sweep_segments.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:21k
开发平台:

MultiPlatform

  1. #include <LEDA/prio.h>
  2. #include <LEDA/sortseq.h>
  3. #include <LEDA/segment.h>
  4. #include <LEDA/window.h>
  5. #include <math.h>
  6. /*
  7. #include <LEDA/graph.h>
  8. */
  9. #define EPS  0.00001
  10. #define EPS2 0.0000000001
  11. window* Wp;
  12. static bool trace = false;
  13. static bool intera = false;
  14. static color seg_color = blue;
  15. static color node_color = red;
  16. class SWEEP_POINT;
  17. class SWEEP_SEGMENT;
  18. typedef SWEEP_POINT* SWEEP_point;
  19. typedef SWEEP_SEGMENT* SWEEP_segment;
  20. enum SWEEP_point_type {Cross=0,Rightend=1,Leftend=2}; 
  21. class SWEEP_POINT
  22. {
  23.   friend class SWEEP_SEGMENT;
  24.   SWEEP_segment seg;
  25.   int     kind;
  26.   double    x,y;
  27.   public:
  28.   SWEEP_POINT(double a,double b)   { x=a; y=b; seg=0; kind=Cross;}
  29.   SWEEP_POINT(point p)         { x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;}
  30.   friend double    get_x(SWEEP_point p);
  31.   friend double    get_y(SWEEP_point p);
  32.   friend int       get_kind(SWEEP_point p);
  33.   friend SWEEP_segment get_seg(SWEEP_point p);
  34.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  35.   LEDA_MEMORY(SWEEP_POINT);
  36. };
  37.   inline double    get_x(SWEEP_point p)       { return p->x; }
  38.   inline double    get_y(SWEEP_point p)       { return p->y; }
  39.   inline int       get_kind(SWEEP_point p)    { return p->kind; }
  40.   inline SWEEP_segment get_seg(SWEEP_point p) { return p->seg; }   
  41. #if defined(__GNUC__)
  42. // if I declare compare static g++ does not use it but instantiates 
  43. // the default error compare template
  44. inline
  45. #else
  46. static
  47. #endif
  48. int compare(const SWEEP_point& p1, const SWEEP_point& p2)
  49. { if (p1==p2) return 0;
  50.   double diffx = get_x(p1) - get_x(p2);
  51.   if (fabs(diffx) > EPS2 ) return (diffx > 0.0) ? 1 : -1;
  52.   int  diffk = get_kind(p1)-get_kind(p2);
  53.   if (diffk != 0) return diffk;
  54.   double diffy = get_y(p1) - get_y(p2);
  55.   if (fabs(diffy) > EPS2 ) return (diffy > 0.0) ? 1 : -1;
  56.   return 0;
  57. }
  58. void Print(SWEEP_point& p) { cout << string("(%f,%f)",get_x(p), get_y(p)); }
  59. class SWEEP_SEGMENT
  60. {
  61.   SWEEP_point startpoint;
  62.   SWEEP_point endpoint;
  63.   double  slope;
  64.   double  yshift;
  65.   //node  left_node;
  66.   int   orient;
  67.   int   color;
  68.   int   name;
  69.   public:
  70.   SWEEP_SEGMENT(SWEEP_point, SWEEP_point,int,int);     
  71.  ~SWEEP_SEGMENT() { delete startpoint; delete endpoint; }     
  72.   friend SWEEP_point get_startpoint(SWEEP_segment seg);
  73.   friend SWEEP_point get_endpoint(SWEEP_segment seg);
  74.   friend double get_slope(SWEEP_segment seg);
  75.   friend double get_yshift(SWEEP_segment seg);
  76.   friend int  get_orient(SWEEP_segment seg);
  77.   friend int  get_color(SWEEP_segment seg);
  78.   friend int  get_name(SWEEP_segment seg);
  79. /*
  80.   friend node get_left_node(SWEEP_segment seg)         { return seg->left_node;}
  81.   friend void set_left_node(SWEEP_segment seg, node v) { seg->left_node = v; }
  82. */
  83.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  84.   LEDA_MEMORY(SWEEP_SEGMENT);
  85. };
  86. inline SWEEP_point get_startpoint(SWEEP_segment seg) { return seg->startpoint; }
  87. inline SWEEP_point get_endpoint(SWEEP_segment seg)   { return seg->endpoint; }
  88. inline double get_slope(SWEEP_segment seg)           { return seg->slope; }
  89. inline double get_yshift(SWEEP_segment seg)          { return seg->yshift; }
  90. inline int  get_orient(SWEEP_segment seg)            { return seg->orient; }
  91. inline int  get_color(SWEEP_segment seg)             { return seg->color; }
  92. inline int  get_name(SWEEP_segment seg)              { return seg->name; }
  93.   SWEEP_SEGMENT::SWEEP_SEGMENT(SWEEP_point p1,SWEEP_point p2,int c, int n)    
  94.   {
  95.     //left_node  = nil;
  96.     color      = c;
  97.     name       = n;
  98.     if (compare(p1,p2) < 0)
  99.      { startpoint = p1; 
  100.        endpoint = p2; 
  101.        orient = 0;
  102.       }
  103.     else
  104.      { startpoint = p2; 
  105.        endpoint = p1; 
  106.        orient = 1;
  107.       }
  108.     startpoint->kind = Leftend; 
  109.     endpoint->kind = Rightend; 
  110.     startpoint->seg = this; 
  111.     endpoint->seg = this;
  112.     if (endpoint->x != startpoint->x)
  113.     {
  114.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  115.       yshift = startpoint->y - slope * startpoint->x;
  116.       startpoint->x -= EPS;
  117.       startpoint->y -= EPS * slope;
  118.       endpoint->x += EPS;
  119.       endpoint->y += EPS * slope;
  120.     }
  121.     else //vertical segment
  122.     { startpoint->y -= EPS;
  123.       endpoint->y   += EPS;
  124.      }
  125.   }
  126. void Print(SWEEP_segment& s) { cout << string("S%d",get_name(s)); }
  127. static double x_sweep;
  128. static double y_sweep;
  129. int compare(const SWEEP_segment& s1,const SWEEP_segment& s2)
  130. {
  131.   double sl1 = get_slope(s1);
  132.   double sl2 = get_slope(s2);
  133.   double ys1 = get_yshift(s1);
  134.   double ys2 = get_yshift(s2);
  135.   double y1 = sl1*x_sweep+ys1;
  136.   double y2 = sl2*x_sweep+ys2;
  137.   double diff = y1-y2;
  138.   if (fabs(diff) > EPS2) return (diff > 0.0) ? 1 : -1;
  139.   if (sl1 == sl2) 
  140.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  141.     if (y1 <= y_sweep+EPS2)
  142.         return compare(sl1,sl2);
  143.     else
  144.         return compare(sl2,sl1);
  145. }
  146. static priority_queue<seq_item,SWEEP_point> X_structure;
  147. static sortseq<SWEEP_segment,pq_item> Y_structure;
  148. bool intersection(SWEEP_segment seg1,SWEEP_segment seg2, SWEEP_point& inter)
  149. {
  150.   if (seg1->slope == seg2->slope)
  151.     return false;
  152.   else
  153.   {
  154.     //x-coordinate  of the intersection
  155.     double Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  156.  
  157.     if (Cross_x <= x_sweep) return false;
  158.     double s1 = seg1->startpoint->x;
  159.     double s2 = seg2->startpoint->x;
  160.     double e1 = seg1->endpoint->x;
  161.     double e2 = seg2->endpoint->x;
  162.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  163.     //y-coordinate of the intersection
  164.     double Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  165.     inter =  new SWEEP_POINT(Cross_x,Cross_y);
  166.     return true;
  167.   }
  168. }
  169. void message(string s, int line=1)
  170. { s += "                                                            ";
  171.   double d = 20/Wp->scale();
  172.   if (s.length() > 150) s = s.head(150);
  173.   Wp->draw_text(Wp->xmin()+d, Wp->ymax()-d*(0.5+line),s);
  174.  }
  175.  
  176. void draw_segment(SWEEP_segment seg)
  177. { double x1 = get_x(get_startpoint(seg));
  178.   double y1 = get_y(get_startpoint(seg));
  179.   double x2 = get_x(get_endpoint(seg));
  180.   double y2 = get_y(get_endpoint(seg));
  181.   double d = 10/Wp->scale();
  182.   Wp->draw_text(x1-d,y1,string("%d",get_name(seg)));
  183.   Wp->draw_segment(x1,y1,x2,y2,seg_color);
  184. }
  185.  
  186. void draw_sweep_line(double xpos) 
  187. {
  188.   Wp->set_mode(xor_mode);
  189.   Wp->draw_segment(xpos,-1150,xpos,Wp->ymax()-5*20/Wp->scale());
  190.   Wp->set_mode(src_mode);
  191. }
  192. void move_sweep_line(double x, double xpos) 
  193.   if (x == xpos) return;
  194.   double delta = 1/Wp->scale(); 
  195.   double y = Wp->ymax()-100*delta;
  196.   Wp->set_mode(xor_mode);
  197.   while (x < xpos)
  198.   { Wp->draw_segment(x+delta,-1150,x+delta,y);
  199.     Wp->draw_segment(x,-1150,x,y);
  200.     x += delta;
  201.    }
  202.   
  203.   Wp->draw_segment(x,-1150,x,y);
  204.   Wp->draw_segment(xpos,-1150,xpos,y);
  205.   Wp->set_mode(src_mode);
  206. }
  207. void draw_Ystructure()
  208. {
  209.   seq_item sit;
  210.   string s = "Y_structure: ";
  211.   forall_items(sit,Y_structure) 
  212.     s+=string("%d ",get_name(Y_structure.key(sit)));
  213.   message(s,3);
  214. }
  215. void draw_Xstructure()
  216. {
  217.   string s = "X_structure: ";
  218.   priority_queue<seq_item,SWEEP_point> Q = X_structure;
  219.   while (!Q.empty())
  220.   { pq_item it = Q.find_min(); 
  221.     SWEEP_point p = X_structure.inf(it);
  222.     seq_item sit  = X_structure.key(it);
  223.     Q.del_min();
  224.      SWEEP_segment seg = get_seg(p);
  225.      switch (get_kind(p)) {
  226.      case Leftend:  s += string("L(%d) ",get_name(seg));
  227.                     break;
  228.      case Rightend: s += string("R(%d) ",get_name(seg)) ;
  229.                     break;
  230.      default:       s += string("X(%d) ",get_name(Y_structure.key(sit))); 
  231.                     break;
  232.      }
  233.   }
  234.   message(s,2);
  235. }
  236. pq_item Xinsert(seq_item i, SWEEP_point p) 
  237.  if (trace)
  238.  {
  239.   SWEEP_segment s ;
  240.   if (i!=nil) s = Y_structure.key(i);
  241.   else s = get_seg(p);
  242.     
  243.      switch (get_kind(p)) {
  244.      case Leftend:  message(string("Xinsert: L(%d) ",get_name(s)),4);
  245.                     break;
  246.      case Rightend: message(string("Xinsert: R(%d) ",get_name(s)),4) ;
  247.                     break;
  248.      default:       message(string("Xinsert: X(%d) ",get_name(s)),4); 
  249.                     break;
  250.       }
  251.   Wp->set_mode(xor_mode);
  252.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  253.   Wp->set_mode(src_mode);
  254.  }
  255.   return X_structure.insert(i,p);
  256. }
  257. SWEEP_point Xdelete(pq_item i) 
  258. {
  259.  if (trace)
  260.  {SWEEP_point p = X_structure.inf(i);
  261.   seq_item sit = X_structure.key(i);
  262.   SWEEP_segment s ;
  263.   if (sit!=nil) s = Y_structure.key(sit);
  264.   else s = get_seg(p);
  265.     
  266.      switch (get_kind(p)) {
  267.      case Leftend:  message(string("Xdelete: L(%d) ",get_name(s)),4);
  268.                     break;
  269.      case Rightend: message(string("Xdelete: R(%d) ",get_name(s)),4) ;
  270.                     break;
  271.      default:       message(string("Xdelete: X(%d) ",get_name(s)),4); 
  272.                     break;
  273.       }
  274.   Wp->set_mode(xor_mode);
  275.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  276.   Wp->set_mode(src_mode);
  277.  }
  278.   SWEEP_point p = X_structure.inf(i);
  279.   X_structure.del_item(i);
  280.   return p;
  281. }
  282. /*
  283. node New_Node(GRAPH<point,int>& G,double x, double y )
  284. { return G.new_node(point(x,y)); }
  285. void New_Edge(GRAPH<point,int>& G,node v, node w, SWEEP_segment l )
  286. { if (get_orient(l)==0)
  287.        G.new_edge(v,w,get_color(l));
  288.   else G.new_edge(w,v,get_color(l));
  289. }
  290. */
  291. void process_vertical_segment(/*GRAPH<point,int>& SUB, */ SWEEP_segment l)
  292.   SWEEP_point p = 
  293.               new SWEEP_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  294.   SWEEP_point q = 
  295.               new SWEEP_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  296.   SWEEP_point r = new SWEEP_POINT(get_x(p)+1,get_y(p));
  297.   SWEEP_point s = new SWEEP_POINT(get_x(q)+1,get_y(q));
  298.   SWEEP_segment bot = new SWEEP_SEGMENT(p,r,0,0);
  299.   SWEEP_segment top = new SWEEP_SEGMENT(q,s,0,0);
  300.   seq_item bot_it = Y_structure.insert(bot,nil);
  301.   seq_item top_it = Y_structure.insert(top,nil);
  302.   seq_item sit;
  303.   //node u,v,w;
  304.   SWEEP_segment seg;
  305.   
  306.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  307.   { seg = Y_structure.key(sit);
  308.     double cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  309.     Wp->draw_filled_node(get_x(p),cross_y,node_color);
  310. /*
  311.     v = get_left_node(seg);
  312.     if (v==nil)
  313.     { w = New_Node(SUB,get_x(p),cross_y);
  314.       set_left_node(seg,w);
  315.      }
  316.     else
  317.     { double vx = SUB[v].xcoord();
  318.       if ( vx < get_x(p)-EPS2) 
  319.       { w = New_Node(SUB,get_x(p),cross_y);
  320.         New_Edge(SUB,v,w,seg);
  321.         set_left_node(seg,w);
  322.        }
  323.       else w = v;
  324.      }
  325.     u = get_left_node(l);
  326.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  327.     set_left_node(l,w);
  328. */
  329.    }
  330.     
  331.   delete l;
  332.   delete bot;
  333.   delete top;
  334.   Y_structure.del_item(bot_it);
  335.   Y_structure.del_item(top_it);
  336.  }
  337. void plane_sweep(list<segment>& L1, list<segment>& L2 
  338.                  /*, GRAPH<point,int>& SUB */)
  339. {
  340.   SWEEP_point    p,inter;
  341.   SWEEP_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  342.   pq_item  pqit,pxmin;
  343.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  344.   int count=1;
  345.   Wp->clear();
  346.  
  347.   //initialization of the X-structure
  348.   segment s;
  349.   forall(s,L1) 
  350.    { SWEEP_point p = new SWEEP_POINT(s.start());
  351.      SWEEP_point q = new SWEEP_POINT(s.end());
  352.      seg = new SWEEP_SEGMENT(p,q,0,count++);
  353.      draw_segment(seg);
  354.      Xinsert(nil,get_startpoint(seg));
  355. /*
  356. Print(seg);
  357. Print(get_startpoint(seg));
  358. newline;
  359. */
  360.    }
  361.   count = -1;
  362.   forall(s,L2) 
  363.    { SWEEP_point p = new SWEEP_POINT(s.start());
  364.      SWEEP_point q = new SWEEP_POINT(s.end());
  365.      seg = new SWEEP_SEGMENT(p,q,1,count--);
  366.      draw_segment(seg);
  367.      Xinsert(nil,get_startpoint(seg));
  368. /*
  369. Print(seg);
  370. Print(get_startpoint(seg));
  371. newline;
  372. */
  373.    }
  374.   count = 0;
  375.   x_sweep = Wp->xmin();
  376.   y_sweep = Wp->ymin();
  377.   if (trace)
  378.   { draw_Xstructure();
  379.     draw_Ystructure();
  380.    }
  381.   draw_sweep_line(x_sweep);
  382.   while(!X_structure.empty())
  383.   {
  384.     if (trace)  
  385.        trace = (Wp->read_mouse() != 3);
  386.     else
  387.        trace = Wp->get_button();
  388.     pxmin = X_structure.find_min();
  389.     p = X_structure.inf(pxmin);
  390.     move_sweep_line(x_sweep,get_x(p));
  391.     sitmin = X_structure.key(pxmin);
  392.     Xdelete(pxmin);
  393.     if (get_kind(p) == Leftend)
  394.     //left endpoint
  395.     { 
  396.       l = get_seg(p); 
  397.       x_sweep = get_x(p);
  398.       y_sweep = get_y(p);
  399.       if (trace)
  400.       message(string("LEFT  point   x = %4f seg = %4d",
  401.               get_x(p),get_name(l)),1);
  402.       if (get_x(p) == get_x(get_endpoint(l)))
  403.         process_vertical_segment(/*SUB,*/ l);
  404.       else
  405.       {
  406.       sit = Y_structure.lookup(l);
  407.       if (sit!=nil)  error_handler(0,"plane sweep: sorry, overlapping segments");
  408.       sit = Y_structure.insert(l,nil);
  409.       Xinsert(sit,get_endpoint(l));
  410.       sitpred = Y_structure.pred(sit);
  411.       sitsucc = Y_structure.succ(sit);
  412.       if (sitpred != nil) 
  413.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  414.           delete Xdelete(pqit);
  415.         lpred = Y_structure.key(sitpred);
  416.         Y_structure.change_inf(sitpred,nil);
  417.         if (intersection(lpred,l,inter))
  418.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  419.       }
  420.       if (sitsucc != nil)
  421.       { lsucc = Y_structure.key(sitsucc);
  422.         if (intersection(lsucc,l,inter))
  423.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  424.       }
  425.      } /* else if vertical */
  426.     }
  427.     else if (get_kind(p) == Rightend)
  428.          //right endpoint
  429.          { 
  430.            x_sweep = get_x(p);
  431.            y_sweep = get_y(p);
  432.            if (trace)
  433.            message(string("RIGHT point   x = %4f seg = %4d",
  434.                    get_x(p),get_name(get_seg(p))),1);
  435.            sit = sitmin;
  436.  
  437.            sitpred = Y_structure.pred(sit);
  438.            sitsucc = Y_structure.succ(sit);
  439.            SWEEP_segment SEG =Y_structure.key(sit);
  440.            Y_structure.del_item(sit);
  441.            delete SEG;
  442.            if((sitpred != nil)&&(sitsucc != nil))
  443.            {
  444.              lpred = Y_structure.key(sitpred);
  445.              lsucc = Y_structure.key(sitsucc);
  446.              if (intersection(lsucc,lpred,inter))
  447.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  448.            }
  449.          }
  450.          else /*point of intersection*/
  451.          { 
  452.            //node w = New_Node(SUB,get_x(p),get_y(p));
  453.            count++;
  454.            /* Let L = list of all lines intersecting in p 
  455.  
  456.               we compute sit     = L.head();
  457.               and        sitpred = L.tail();
  458.               by scanning the Y_structure in both directions 
  459.               starting at sitmin;
  460.            */
  461.            /* search for sitpred upwards from sitmin: */
  462.            Y_structure.change_inf(sitmin,nil);
  463.            sitpred = Y_structure.succ(sitmin);
  464.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  465.            { SWEEP_point q = X_structure.inf(pqit);
  466.              if (compare(p,q) != 0) break; 
  467.              X_structure.del_item(pqit);
  468.              Y_structure.change_inf(sitpred,nil);
  469.              sitpred = Y_structure.succ(sitpred);
  470.             }
  471.            /* search for sit downwards from sitmin: */
  472.            sit = sitmin;
  473.            seq_item sit1;
  474.            
  475.            while ((sit1=Y_structure.pred(sit)) != nil)
  476.            { pqit = Y_structure.inf(sit1);
  477.              if (pqit == nil) break;
  478.              SWEEP_point q = X_structure.inf(pqit);
  479.              if (compare(p,q) != 0) break; 
  480.              X_structure.del_item(pqit);
  481.              Y_structure.change_inf(sit1,nil);
  482.              sit = sit1;
  483.             }
  484. /*
  485.            if (trace)
  486.            { string line;
  487.              line += string("sit = %d  ", get_name(Y_structure.key(sit)));
  488.              line += string("sitpred = %d",get_name(Y_structure.key(sitpred)));
  489.              message(line,5);
  490.             }
  491. */
  492. /*
  493.            // insert edges to p for all segments in sit, ..., sitpred into SUB
  494.            // and set left node to w 
  495.            lsit = Y_structure.key(sitpred);
  496.            node v = get_left_node(lsit);
  497.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  498.            set_left_node(lsit,w);
  499.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  500.            { lsit = Y_structure.key(sit1);
  501.              v = get_left_node(lsit);
  502.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  503.              set_left_node(lsit,w);
  504.             }
  505. */
  506.            lsit = Y_structure.key(sit);
  507.            lpred=Y_structure.key(sitpred);
  508.            sitpredpred = Y_structure.pred(sit);
  509.            sitsucc=Y_structure.succ(sitpred);
  510.            message(string("INTERSECTION  # = %4d  x = %5f  seg = %4d ",
  511.                         count, float(get_x(p)),get_name(lsit)),1);
  512.            draw_sweep_line(get_x(p));
  513.            Wp->draw_filled_node(get_x(p),get_y(p),node_color);
  514.            draw_sweep_line(get_x(p));
  515.            if (sitpredpred != nil)
  516.             { 
  517.               lpredpred=Y_structure.key(sitpredpred);
  518.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  519.                delete Xdelete(pqit);
  520.      
  521.               Y_structure.change_inf(sitpredpred,nil);
  522.               if (intersection(lpred,lpredpred,inter))
  523.                 Y_structure.change_inf(sitpredpred,
  524.                                        Xinsert(sitpredpred,inter));
  525.              }
  526.            if (sitsucc != nil)
  527.             {
  528.               lsucc=Y_structure.key(sitsucc);
  529.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  530.                 delete Xdelete(pqit);
  531.                  
  532.               Y_structure.change_inf(sitpred,nil);
  533.               if (intersection(lsucc,lsit,inter))
  534.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  535.              }
  536. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  537.            x_sweep = get_x(p);
  538.            y_sweep = get_y(p);
  539.            Y_structure.reverse_items(sit,sitpred);
  540.            delete p;
  541.          } // intersection
  542.    if (trace) 
  543.     { draw_Xstructure();
  544.       draw_Ystructure();
  545.      }
  546.   }
  547.   message("END OF SWEEP",1);
  548.   if (intera) Wp->read_mouse();             //wait for mouse click
  549.     draw_sweep_line(x_sweep);
  550.     X_structure.clear();
  551. } // plane_sweep
  552. void interactive(window& W)
  553. {
  554.   intera= true;
  555.   int grid_width = 0;
  556.   int line_width = 1;
  557.   int node_width = 4;
  558.   int N = 80;
  559.   panel P("PLANE SWEEP DEMO");
  560.   P.bool_item("TRACE",trace);
  561.   P.int_item("GRID",grid_width,0,80,20);
  562.   P.int_item("SEGMENTS", N);
  563.   P.int_item("line width",line_width,1,5);
  564.   P.int_item("node width",node_width,1,10);
  565.   P.button("MOUSE");
  566.   P.button("RANDOM");
  567.   P.button("QUIT");
  568.   for(;;)
  569.   { int input = P.open(W);
  570.   
  571.     if (input == 2) break;
  572.   
  573.     W.init(-1200,1200,-1200, grid_width);
  574.     W.set_text_mode(opaque);
  575.     W.set_node_width(node_width);
  576.     W.set_line_width(line_width);
  577.   
  578.     list<segment> seglist1,seglist2;
  579.   
  580.     if (input==1)  // random 
  581.      { double ymax = W.ymax()-4*20/W.scale()-100;
  582.        int xmin = int(W.xmin())+100;
  583.        int xmax = int(W.xmax())-100;
  584.        for(int i=0; i<N; i++)
  585.        { double x1 = rand_int(xmin,-100);
  586.          double y1 = rand_int(-1000,int(ymax));
  587.          double x2 = rand_int(100,xmax);
  588.          double y2 = rand_int(-1000,int(ymax));
  589.          segment s(x1,y1,x2,y2);
  590.          W << s;
  591.          seglist1.append(s);
  592.         }
  593.       }
  594.     else // input == 0 (mouse)
  595.       { segment s;
  596.         while (W >> s)
  597.         { W << s;
  598.           seglist1.append(s);
  599.          }
  600.        }
  601.   
  602.   
  603.     plane_sweep(seglist1,seglist2);
  604.   
  605.   //GRAPH<point,int> SUB;
  606.   //plane_sweep(seglist1,seglist2,SUB);
  607.   
  608.  } // for(;;)
  609. }
  610. void demo(window& W, int N)
  611. {
  612.   trace = false;
  613.   W.init(-1200,1200,-1200);
  614.   for(;;)
  615.   {
  616.   W.clear();
  617.   W.set_text_mode(opaque);
  618.   W.set_node_width(3);
  619.   list<segment> seglist1,seglist2;
  620.      double ymax = W.ymax()-4*20/W.scale()-100;
  621.      for(int i=0; i<N; i++)
  622.      { double x1 = rand_int(-1100,-100);
  623.        double y1 = rand_int(-1000,int(ymax));
  624.        double x2 = rand_int(100,1100);
  625.        double y2 = rand_int(-1000,int(ymax));
  626.        segment s(x1,y1,x2,y2);
  627.        W << s;
  628.        seglist1.append(s);
  629.       }
  630.   plane_sweep(seglist1,seglist2);
  631. /*
  632.   GRAPH<point,int> SUB;
  633.   edge e;
  634.   plane_sweep(seglist1,seglist2,SUB);
  635.  
  636.   W.clear();
  637.   forall_edges(e,SUB) W <<  segment(SUB[source(e)],SUB[target(e)]);
  638. */
  639.   wait(2);
  640.   }
  641. }
  642. /*
  643. #include <LEDA/stream.h>
  644. */
  645. main(int argc, char** argv)
  646. {
  647.   int N = 0;
  648.   panel P0("PLANE SWEEP DEMO");
  649.   P0.text_item("This program computes the intersections in a set of");
  650.   P0.text_item("straight line segments using a plane sweep algorithm.");
  651.   P0.text_item("You can define the set of line segments interactively");
  652.   P0.text_item("using the left mouse button (input is terminated with");
  653.   P0.text_item("the right button) or create a random set of segments.");
  654.   P0.text_item("In TRACE mode the current contents of the event queue");
  655.   P0.text_item("(X-structure) and of the sweep line (Y-structure) are");
  656.   P0.text_item("displayed and the sweep line stops at each event point.");
  657.   P0.button("continue");
  658.    
  659.   if (argc == 1)
  660.     P0.open();
  661.   else
  662.     N = atoi(argv[1]);
  663.   window W;
  664.   Wp = &W;
  665.   if (N==0) 
  666.       interactive(W);
  667.   else
  668.      demo(W,N);
  669.   return 0;
  670. }