home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / prog / graphics / sweep_se.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  20.2 KB  |  942 lines

  1. #include <LEDA/prio.h>
  2. #include <LEDA/sortseq.h>
  3. #include <LEDA/graph.h>
  4. #include <LEDA/plane.h>
  5. #include <LEDA/window.h>
  6.  
  7. #define EPS  0.00001
  8. #define EPS2 0.0000000001
  9.  
  10. declare2(GRAPH,point,int)
  11.  
  12. declare(list,seq_item)
  13.  
  14.  
  15. window* Wp;
  16.  
  17. static int trace = 0;
  18. static int intera = 0;
  19. static color seg_color = blue;
  20. static color node_color = red;
  21.  
  22.  
  23. class SWEEP_POINT;
  24. class SWEEP_SEGMENT;
  25. typedef SWEEP_POINT* SWEEP_point;
  26. typedef SWEEP_SEGMENT* SWEEP_segment;
  27.  
  28. enum SWEEP_point_type {Cross=0,Rightend=1,Leftend=2}; 
  29.  
  30.  
  31. class SWEEP_POINT
  32. {
  33.   friend class SWEEP_SEGMENT;
  34.  
  35.   SWEEP_segment seg;
  36.   int     kind;
  37.   real    x,y;
  38.  
  39.   public:
  40.  
  41.   SWEEP_POINT(real a,real b)   { x=a; y=b; seg=0; kind=Cross;}
  42.  
  43.   SWEEP_POINT(point p)         { x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;}
  44.  
  45.   friend real    get_x(SWEEP_point p)      { return p->x; }
  46.   friend real    get_y(SWEEP_point p)      { return p->y; }
  47.   friend int     get_kind(SWEEP_point p)   { return p->kind; }
  48.   friend SWEEP_segment get_seg(SWEEP_point p)    { return p->seg; }   
  49.  
  50.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  51.  
  52.   OPERATOR_NEW(4);
  53.   OPERATOR_DEL(4);
  54.  
  55. };
  56.  
  57.  
  58. int compare(SWEEP_point& p1,SWEEP_point& p2)
  59. { if (p1==p2) return 0;
  60.  
  61.   real diffx = get_x(p1) - get_x(p2);
  62.   if (fabs(diffx) > EPS2 ) return (diffx > 0.0) ? 1 : -1;
  63.  
  64.   int  diffk = get_kind(p1)-get_kind(p2);
  65.   if (diffk != 0) return diffk;
  66.  
  67.   real diffy = get_y(p1) - get_y(p2);
  68.   if (fabs(diffy) > EPS2 ) return (diffy > 0.0) ? 1 : -1;
  69.  
  70.   return 0;
  71.  
  72. }
  73.  
  74. void Print(SWEEP_point& p) { cout << form("(%f,%f)",~get_x(p), ~get_y(p)); }
  75.  
  76. declare(list,SWEEP_point);
  77.  
  78.  
  79.  
  80. class SWEEP_SEGMENT
  81. {
  82.   SWEEP_point startpoint;
  83.   SWEEP_point endpoint;
  84.   real  slope;
  85.   real  yshift;
  86.   node  left_node;
  87.   int   orient;
  88.   int   color;
  89.   int   name;
  90.  
  91.   public:
  92.  
  93.   SWEEP_SEGMENT(SWEEP_point, SWEEP_point,int,int);     
  94.  ~SWEEP_SEGMENT() { delete startpoint; delete endpoint; }     
  95.  
  96.   friend SWEEP_point get_startpoint(SWEEP_segment seg)       { return seg->startpoint; }
  97.   friend SWEEP_point get_endpoint(SWEEP_segment seg)         { return seg->endpoint; }
  98.   friend real get_slope(SWEEP_segment seg)             { return seg->slope; }
  99.   friend real get_yshift(SWEEP_segment seg)            { return seg->yshift; }
  100.   friend int  get_orient(SWEEP_segment seg)            { return seg->orient; }
  101.   friend int  get_color(SWEEP_segment seg)             { return seg->color; }
  102.   friend int  get_name(SWEEP_segment seg)              { return seg->name; }
  103.   friend node get_left_node(SWEEP_segment seg)         { return seg->left_node; }
  104.   friend void set_left_node(SWEEP_segment seg, node v) { seg->left_node = v; }
  105.  
  106.   friend bool intersection(SWEEP_segment, SWEEP_segment, SWEEP_point&);
  107.  
  108.   OPERATOR_NEW(8);
  109.   OPERATOR_DEL(8);
  110.  
  111. };
  112.  
  113.  
  114.   SWEEP_SEGMENT::SWEEP_SEGMENT(SWEEP_point p1,SWEEP_point p2,int c, int n)    
  115.   {
  116.     left_node  = nil;
  117.     color      = c;
  118.     name       = n;
  119.  
  120.     if (compare(p1,p2) < 0)
  121.      { startpoint = p1; 
  122.        endpoint = p2; 
  123.        orient = 0;
  124.       }
  125.     else
  126.      { startpoint = p2; 
  127.        endpoint = p1; 
  128.        orient = 1;
  129.       }
  130.  
  131.     startpoint->kind = Leftend; 
  132.     endpoint->kind = Rightend; 
  133.     startpoint->seg = this; 
  134.     endpoint->seg = this;
  135.  
  136.     if (endpoint->x != startpoint->x)
  137.     {
  138.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  139.       yshift = startpoint->y - slope * startpoint->x;
  140.  
  141.       startpoint->x -= EPS;
  142.       startpoint->y -= EPS * slope;
  143.       endpoint->x += EPS;
  144.       endpoint->y += EPS * slope;
  145.     }
  146.     else //vertical segment
  147.     { startpoint->y -= EPS;
  148.       endpoint->y   += EPS;
  149.      }
  150.   }
  151.  
  152. void Print(SWEEP_segment& s) { cout << form("S%d",get_name(s)); }
  153.  
  154. static real x_sweep;
  155. static real y_sweep;
  156.  
  157.  
  158. int compare(SWEEP_segment& s1,SWEEP_segment& s2)
  159. {
  160.   real sl1 = get_slope(s1);
  161.   real sl2 = get_slope(s2);
  162.   real ys1 = get_yshift(s1);
  163.   real ys2 = get_yshift(s2);
  164.  
  165.   real y1 = sl1*x_sweep+ys1;
  166.   real y2 = sl2*x_sweep+ys2;
  167.  
  168.   real diff = y1-y2;
  169.  
  170.   if (fabs(diff) > EPS2) return (diff > 0.0) ? 1 : -1;
  171.  
  172.   if (sl1 == sl2) 
  173.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  174.  
  175.     if (y1 <= y_sweep+EPS2)
  176.         return compare(sl1,sl2);
  177.     else
  178.         return compare(sl2,sl1);
  179.  
  180. }
  181.  
  182.  
  183.  
  184.  
  185. declare2(priority_queue,seq_item,SWEEP_point);
  186. static priority_queue(seq_item,SWEEP_point) X_structure;
  187.  
  188. declare2(sortseq,SWEEP_segment,pq_item);
  189. static sortseq(SWEEP_segment,pq_item) Y_structure;
  190.  
  191.  
  192. bool intersection(SWEEP_segment seg1,SWEEP_segment seg2, SWEEP_point& inter)
  193. {
  194.   if (seg1->slope == seg2->slope)
  195.     return false;
  196.   else
  197.   {
  198.     //x-coordinate  of the intersection
  199.     real Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  200.  
  201.     if (Cross_x <= x_sweep) return false;
  202.  
  203.     real s1 = seg1->startpoint->x;
  204.     real s2 = seg2->startpoint->x;
  205.     real e1 = seg1->endpoint->x;
  206.     real e2 = seg2->endpoint->x;
  207.  
  208.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  209.  
  210.     //y-coordinate of the intersection
  211.     real Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  212.     inter =  new SWEEP_POINT(Cross_x,Cross_y);
  213.  
  214.     return true;
  215.   }
  216. }
  217.  
  218. void message(string s, int line=1)
  219. { s += "                                                            ";
  220.   double d = 20/Wp->scale();
  221.   if (s.length() > 150) s = s.head(150);
  222.   Wp->draw_text(Wp->xmin()+d, Wp->ymax()-d*(0.5+line),s);
  223.  }
  224.  
  225.  
  226. void draw_segment(SWEEP_segment seg)
  227. { real x1 = get_x(get_startpoint(seg));
  228.   real y1 = get_y(get_startpoint(seg));
  229.   real x2 = get_x(get_endpoint(seg));
  230.   real y2 = get_y(get_endpoint(seg));
  231.  
  232.   real d = 10/Wp->scale();
  233.  
  234.   Wp->draw_text(x1-d,y1,form("%d",get_name(seg)));
  235.  
  236.   Wp->draw_segment(x1,y1,x2,y2,seg_color);
  237. }
  238.  
  239.  
  240. declare(list,SWEEP_segment);
  241.  
  242. void draw_sweep_line(real xpos) 
  243. {
  244.  
  245.   Wp->set_mode(xor_mode);
  246.  
  247.  if (trace) 
  248.     Wp->draw_segment(xpos,-1150,xpos,Wp->ymax()-5*20/Wp->scale());
  249.  else 
  250.     Wp->draw_segment(xpos,-1150,xpos,Wp->ymax()-2*20/Wp->scale());
  251.  
  252.   Wp->set_mode(src_mode);
  253. }
  254.  
  255. void move_sweep_line(real x, real xpos) 
  256.   if (x == xpos) return;
  257.   
  258.   real delta = 1/Wp->scale(); 
  259.  
  260.   Wp->set_mode(xor_mode);
  261.  
  262.   while (x < xpos)
  263.   { draw_sweep_line(x+delta);
  264.     draw_sweep_line(x);
  265.     x += delta;
  266.    }
  267.   
  268.   draw_sweep_line(x);
  269.  
  270.   draw_sweep_line(xpos);
  271.  
  272.   Wp->set_mode(src_mode);
  273. }
  274.  
  275. void draw_Ystructure()
  276. {
  277.   seq_item sit;
  278.   string s = "Y_structure: ";
  279.  
  280.   forall_seq_items(sit,Y_structure) 
  281.     s+=form("%d ",get_name(Y_structure.key(sit)));
  282.  
  283.   message(s,3);
  284.  
  285. }
  286.  
  287. void draw_Xstructure()
  288. {
  289.   string s = "X_structure: ";
  290.  
  291.   priority_queue(seq_item,SWEEP_point) Q = X_structure;
  292.  
  293.   while (!Q.empty())
  294.   { pq_item it = Q.find_min(); 
  295.  
  296.     SWEEP_point p = X_structure.inf(it);
  297.     seq_item sit  = X_structure.key(it);
  298.  
  299.     Q.del_min();
  300.  
  301.      SWEEP_segment seg = get_seg(p);
  302.  
  303.      switch (get_kind(p)) {
  304.  
  305.      case Leftend:  s += form("L(%d) ",get_name(seg));
  306.                     break;
  307.  
  308.      case Rightend: s += form("R(%d) ",get_name(seg)) ;
  309.                     break;
  310.  
  311.      default:       s += form("X(%d) ",get_name(Y_structure.key(sit))); 
  312.                     break;
  313.  
  314.      }
  315.  
  316.   }
  317.  
  318.   message(s,2);
  319.  
  320. }
  321.  
  322. pq_item Xinsert(seq_item i, SWEEP_point p) 
  323.  
  324.  if (trace)
  325.  {
  326.   SWEEP_segment s ;
  327.   if (i!=nil) s = Y_structure.key(i);
  328.  
  329.   else s = get_seg(p);
  330.     
  331.      switch (get_kind(p)) {
  332.  
  333.      case Leftend:  message(form("Xinsert: L(%d) ",get_name(s)),4);
  334.                     break;
  335.  
  336.      case Rightend: message(form("Xinsert: R(%d) ",get_name(s)),4) ;
  337.                     break;
  338.  
  339.      default:       message(form("Xinsert: X(%d) ",get_name(s)),4); 
  340.                     break;
  341.       }
  342.  
  343.   Wp->set_mode(xor_mode);
  344.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  345.   Wp->set_mode(src_mode);
  346.  }
  347.   return X_structure.insert(i,p);
  348. }
  349.  
  350. SWEEP_point Xdelete(pq_item i) 
  351. {
  352.  if (trace)
  353.  {SWEEP_point p = X_structure.inf(i);
  354.  
  355.   seq_item sit = X_structure.key(i);
  356.  
  357.   SWEEP_segment s ;
  358.  
  359.   if (sit!=nil) s = Y_structure.key(sit);
  360.   else s = get_seg(p);
  361.     
  362.      switch (get_kind(p)) {
  363.  
  364.      case Leftend:  message(form("Xdelete: L(%d) ",get_name(s)),4);
  365.                     break;
  366.  
  367.      case Rightend: message(form("Xdelete: R(%d) ",get_name(s)),4) ;
  368.                     break;
  369.  
  370.      default:       message(form("Xdelete: X(%d) ",get_name(s)),4); 
  371.                     break;
  372.       }
  373.  
  374.   Wp->set_mode(xor_mode);
  375.   Wp->draw_filled_node(get_x(p),get_y(p),green);
  376.   Wp->set_mode(src_mode);
  377.  }
  378.  
  379.   SWEEP_point p = X_structure.inf(i);
  380.  
  381.   X_structure.del_item(i);
  382.  
  383.   return p;
  384. }
  385.  
  386.  
  387. node New_Node(GRAPH(point,int)& G,real x, real y )
  388. { return G.new_node(point(x,y)); }
  389.  
  390. void New_Edge(GRAPH(point,int)& G,node v, node w, SWEEP_segment l )
  391. { if (get_orient(l)==0)
  392.        G.new_edge(v,w,get_color(l));
  393.   else G.new_edge(w,v,get_color(l));
  394. }
  395.  
  396.  
  397. void process_vertical_segment(GRAPH(point,int)& SUB, SWEEP_segment l)
  398.   SWEEP_point p = 
  399.               new SWEEP_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  400.   SWEEP_point q = 
  401.               new SWEEP_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  402.  
  403.   SWEEP_point r = new SWEEP_POINT(get_x(p)+1,get_y(p));
  404.   SWEEP_point s = new SWEEP_POINT(get_x(q)+1,get_y(q));
  405.  
  406.   SWEEP_segment bot = new SWEEP_SEGMENT(p,r,0,0);
  407.   SWEEP_segment top = new SWEEP_SEGMENT(q,s,0,0);
  408.  
  409.   seq_item bot_it = Y_structure.insert(bot,nil);
  410.   seq_item top_it = Y_structure.insert(top,nil);
  411.   seq_item sit;
  412.  
  413.   node u,v,w;
  414.   SWEEP_segment seg;
  415.   
  416.  
  417.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  418.   { seg = Y_structure.key(sit);
  419.  
  420.     real cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  421.  
  422.     Wp->draw_filled_node(get_x(p),cross_y,node_color);
  423.  
  424.     v = get_left_node(seg);
  425.     if (v==nil)
  426.     { w = New_Node(SUB,get_x(p),cross_y);
  427.       set_left_node(seg,w);
  428.      }
  429.     else
  430.     { real vx = SUB[v].xcoord();
  431.       if ( vx < get_x(p)-EPS2) 
  432.       { w = New_Node(SUB,get_x(p),cross_y);
  433.         New_Edge(SUB,v,w,seg);
  434.         set_left_node(seg,w);
  435.        }
  436.       else w = v;
  437.      }
  438.  
  439.     u = get_left_node(l);
  440.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  441.     set_left_node(l,w);
  442.  
  443.    }
  444.     
  445.   delete l;
  446.   delete bot;
  447.   delete top;
  448.   Y_structure.del_item(bot_it);
  449.   Y_structure.del_item(top_it);
  450.  
  451.  }
  452.  
  453.  
  454. void plane_sweep(list(segment)& L1, list(segment)& L2, GRAPH(point,int)& SUB)
  455. {
  456.   SWEEP_point    p,inter;
  457.   SWEEP_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  458.  
  459.   pq_item  pqit,pxmin;
  460.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  461.  
  462.  
  463.   int count=1;
  464.  
  465.   Wp->clear();
  466.  
  467.   //initialization of the X-structure
  468.  
  469.   segment s;
  470.  
  471.   forall(s,L1) 
  472.    { SWEEP_point p = new SWEEP_POINT(s.start());
  473.      SWEEP_point q = new SWEEP_POINT(s.end());
  474.      seg = new SWEEP_SEGMENT(p,q,0,count++);
  475.      draw_segment(seg);
  476.      Xinsert(nil,get_startpoint(seg));
  477.    }
  478.  
  479.   count = -1;
  480.  
  481.   forall(s,L2) 
  482.    { SWEEP_point p = new SWEEP_POINT(s.start());
  483.      SWEEP_point q = new SWEEP_POINT(s.end());
  484.      seg = new SWEEP_SEGMENT(p,q,1,count--);
  485.      draw_segment(seg);
  486.      Xinsert(nil,get_startpoint(seg));
  487.    }
  488.  
  489.  
  490.   count = 0;
  491.  
  492.   x_sweep = Wp->xmin();
  493.   y_sweep = Wp->ymin();
  494.  
  495.   if (trace)
  496.   { draw_Xstructure();
  497.     draw_Ystructure();
  498.    }
  499.  
  500.   draw_sweep_line(x_sweep);
  501.  
  502.   while(!X_structure.empty())
  503.   {
  504.     if (trace==1)  trace = Wp->read_mouse();
  505.  
  506.     pxmin = X_structure.find_min();
  507.     p = X_structure.inf(pxmin);
  508.  
  509.     move_sweep_line(x_sweep,get_x(p));
  510.  
  511.     sitmin = X_structure.key(pxmin);
  512.  
  513.     Xdelete(pxmin);
  514.  
  515.  
  516.  
  517.     if (get_kind(p) == Leftend)
  518.  
  519.     //left endpoint
  520.     { 
  521.  
  522.       l = get_seg(p); 
  523.  
  524.       x_sweep = get_x(p);
  525.       y_sweep = get_y(p);
  526.  
  527.       if (trace)
  528.       message(form("LEFT  point   x = %4f seg = %4d",
  529.               ~get_x(p),get_name(l)),1);
  530.  
  531.  
  532.       if (get_x(p) == get_x(get_endpoint(l)))
  533.         process_vertical_segment(SUB,l);
  534.       else
  535.       {
  536.  
  537.       sit = Y_structure.lookup(l);
  538.  
  539.       if (sit!=nil)  error_handler(0,"plane sweep: sorry, overlapping segments");
  540.  
  541.       sit = Y_structure.insert(l,nil);
  542.  
  543.       Xinsert(sit,get_endpoint(l));
  544.  
  545.       sitpred = Y_structure.pred(sit);
  546.       sitsucc = Y_structure.succ(sit);
  547.  
  548.       if (sitpred != nil) 
  549.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  550.           delete Xdelete(pqit);
  551.  
  552.         lpred = Y_structure.key(sitpred);
  553.  
  554.         Y_structure.change_inf(sitpred,nil);
  555.  
  556.         if (intersection(lpred,l,inter))
  557.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  558.       }
  559.  
  560.  
  561.       if (sitsucc != nil)
  562.       { lsucc = Y_structure.key(sitsucc);
  563.         if (intersection(lsucc,l,inter))
  564.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  565.       }
  566.      } /* else if vertical */
  567.  
  568.     }
  569.     else if (get_kind(p) == Rightend)
  570.          //right endpoint
  571.          { 
  572.            x_sweep = get_x(p);
  573.            y_sweep = get_y(p);
  574.  
  575.            if (trace)
  576.            message(form("RIGHT point   x = %4f seg = %4d",
  577.                    ~get_x(p),get_name(get_seg(p))),1);
  578.  
  579.            sit = sitmin;
  580.  
  581.            sitpred = Y_structure.pred(sit);
  582.            sitsucc = Y_structure.succ(sit);
  583.  
  584.            SWEEP_segment SEG =Y_structure.key(sit);
  585.  
  586.            Y_structure.del_item(sit);
  587.  
  588.            delete SEG;
  589.  
  590.            if((sitpred != nil)&&(sitsucc != nil))
  591.            {
  592.              lpred = Y_structure.key(sitpred);
  593.              lsucc = Y_structure.key(sitsucc);
  594.              if (intersection(lsucc,lpred,inter))
  595.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  596.            }
  597.          }
  598.          else /*point of intersection*/
  599.          { 
  600.            node w = New_Node(SUB,get_x(p),get_y(p));
  601.  
  602.            count++;
  603.  
  604.            /* Let L = list of all lines intersecting in p 
  605.  
  606.               we compute sit     = L.head();
  607.               and        sitpred = L.tail();
  608.  
  609.               by scanning the Y_structure in both directions 
  610.               starting at sitmin;
  611.  
  612.            */
  613.  
  614.            /* search for sitpred upwards from sitmin: */
  615.  
  616.            Y_structure.change_inf(sitmin,nil);
  617.  
  618.            sitpred = Y_structure.succ(sitmin);
  619.  
  620.  
  621.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  622.            { SWEEP_point q = X_structure.inf(pqit);
  623.              if (compare(p,q) != 0) break; 
  624.              X_structure.del_item(pqit);
  625.              Y_structure.change_inf(sitpred,nil);
  626.              sitpred = Y_structure.succ(sitpred);
  627.             }
  628.  
  629.  
  630.            /* search for sit downwards from sitmin: */
  631.  
  632.            sit = sitmin;
  633.  
  634.            seq_item sit1;
  635.            
  636.            while ((sit1=Y_structure.pred(sit)) != nil)
  637.            { pqit = Y_structure.inf(sit1);
  638.              if (pqit == nil) break;
  639.              SWEEP_point q = X_structure.inf(pqit);
  640.              if (compare(p,q) != 0) break; 
  641.              X_structure.del_item(pqit);
  642.              Y_structure.change_inf(sit1,nil);
  643.              sit = sit1;
  644.             }
  645.  
  646.  
  647. /*
  648.            if (trace)
  649.            { string line;
  650.              line += form("sit = %d  ", get_name(Y_structure.key(sit)));
  651.              line += form("sitpred = %d",get_name(Y_structure.key(sitpred)));
  652.              message(line,5);
  653.             }
  654. */
  655.  
  656.  
  657.            // insert edges to p for all segments in sit, ..., sitpred into SUB
  658.            // and set left node to w 
  659.  
  660.            lsit = Y_structure.key(sitpred);
  661.  
  662.            node v = get_left_node(lsit);
  663.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  664.            set_left_node(lsit,w);
  665.  
  666.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  667.            { lsit = Y_structure.key(sit1);
  668.  
  669.              v = get_left_node(lsit);
  670.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  671.              set_left_node(lsit,w);
  672.             }
  673.  
  674.            lsit = Y_structure.key(sit);
  675.            lpred=Y_structure.key(sitpred);
  676.            sitpredpred = Y_structure.pred(sit);
  677.            sitsucc=Y_structure.succ(sitpred);
  678.  
  679.            message(form("INTERSECTION  # = %4d  x = %5f  seg = %4d ",
  680.                         count, ~get_x(p),get_name(lsit)),1);
  681.  
  682.            Wp->draw_filled_node(get_x(p),get_y(p),node_color);
  683.  
  684.  
  685.            if (sitpredpred != nil)
  686.             { 
  687.               lpredpred=Y_structure.key(sitpredpred);
  688.  
  689.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  690.                delete Xdelete(pqit);
  691.      
  692.  
  693.               Y_structure.change_inf(sitpredpred,nil);
  694.  
  695.  
  696.               if (intersection(lpred,lpredpred,inter))
  697.                 Y_structure.change_inf(sitpredpred,
  698.                                        Xinsert(sitpredpred,inter));
  699.              }
  700.  
  701.  
  702.            if (sitsucc != nil)
  703.             {
  704.               lsucc=Y_structure.key(sitsucc);
  705.  
  706.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  707.                 delete Xdelete(pqit);
  708.                  
  709.               Y_structure.change_inf(sitpred,nil);
  710.  
  711.               if (intersection(lsucc,lsit,inter))
  712.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  713.              }
  714.  
  715.  
  716. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  717.  
  718.            x_sweep = get_x(p);
  719.            y_sweep = get_y(p);
  720.  
  721.            Y_structure.reverse_items(sit,sitpred);
  722.  
  723.            delete p;
  724.  
  725.          } // intersection
  726.  
  727.    if (trace) 
  728.     { draw_Xstructure();
  729.       draw_Ystructure();
  730.      }
  731.  
  732.   }
  733.  
  734.   message("END OF SWEEP",1);
  735.  
  736.   if (intera) Wp->read_mouse();             //wait for mouse click
  737.  
  738.     draw_sweep_line(x_sweep);
  739.  
  740.     X_structure.clear();
  741.  
  742. } // plane_sweep
  743.  
  744.  
  745.  
  746. void interactive(window& W)
  747. {
  748.   bool random_input;
  749.   int grid_width = 0;
  750.   int line_width = 1;
  751.   int node_width = 4;
  752.   int N = 50;
  753.  
  754.   intera= 1;
  755.  
  756.   panel P("PLANE SWEEP");
  757.  
  758.   P.text_item("This program performs a plane sweep to compute the  "); 
  759.   P.text_item("intersections of a set of straight line segments.   ");
  760.   P.text_item("You can define a sequence of segments with the left ");
  761.   P.text_item("mouse button terminated by pressing the right button");
  762.   P.text_item("or create a random set of segments. In TRACE mode,  ");
  763.   P.text_item("the current states of the event queue (X-structure) ");
  764.   P.text_item("and the sweep line (Y-structure) are displayed, and ");
  765.   P.text_item("the sweep line stops at each event point waiting for");
  766.   P.text_item("a mouse click.                                      ");
  767.   P.text_item("                                                    ");
  768.  
  769.   P.bool_item("TRACE",trace);
  770.   P.choice_item("INPUT", random_input,"mouse","random");
  771.   P.int_item("GRID",grid_width,0,40,10);
  772.   P.int_item("SEGMENTS", N);
  773.   P.text_item("");
  774.   P.int_item("line width",line_width,1,5);
  775.   P.int_item("node width",node_width,1,10);
  776.  
  777.  
  778. for(;;)
  779. {
  780.   P.open();
  781.  
  782.   W.init(-1200,1200,-1200, grid_width);
  783.  
  784.   W.set_text_mode(opaque);
  785.   W.set_node_width(node_width);
  786.   W.set_line_width(line_width);
  787.  
  788.   list(segment) seglist1,seglist2;
  789.  
  790.   if (random_input) 
  791.    { 
  792.      init_random();
  793.  
  794.      double ymax = W.ymax()-4*20/W.scale()-100;
  795.  
  796.      int xmin = int(W.xmin())+100;
  797.      int xmax = int(W.xmax())-100;
  798.  
  799.      while (N--) 
  800.      { real x1 = random(xmin,-100);
  801.        real y1 = random(-1000,int(ymax));
  802.        real x2 = random(100,xmax);
  803.        real y2 = random(-1000,int(ymax));
  804.        segment s(x1,y1,x2,y2);
  805.        W << s;
  806.        seglist1.append(s);
  807.       }
  808.     }
  809.   else // mouse input
  810.     { segment s;
  811.  
  812.       while (W >> s)
  813.       { W << s;
  814.         seglist1.append(s);
  815.        }
  816.  
  817.      }
  818.  
  819.  
  820.   GRAPH(point,int) SUB;
  821.  
  822.   plane_sweep(seglist1,seglist2,SUB);
  823.  
  824. } // for(;;)
  825.  
  826. }
  827.  
  828.  
  829.  
  830. void demo(window& W, int N)
  831. {
  832.   trace = false;
  833.  
  834.   W.init(-1200,1200,-1200);
  835.  
  836.   for(;;)
  837.   {
  838.  
  839.   W.clear();
  840.  
  841.  
  842.   W.set_text_mode(opaque);
  843.   W.set_node_width(3);
  844.  
  845.  
  846.   list(segment) seglist1,seglist2;
  847.  
  848.      init_random();
  849.  
  850.      double ymax = W.ymax()-4*20/W.scale()-100;
  851.  
  852.      for(int i=0; i<N; i++)
  853.      { real x1 = random(-1100,-100);
  854.        real y1 = random(-1000,int(ymax));
  855.        real x2 = random(100,1100);
  856.        real y2 = random(-1000,int(ymax));
  857.        segment s(x1,y1,x2,y2);
  858.        W << s;
  859.        seglist1.append(s);
  860.       }
  861.  
  862.  
  863.   GRAPH(point,int) SUB;
  864.   edge e;
  865.  
  866.   plane_sweep(seglist1,seglist2,SUB);
  867.  
  868.   W.clear();
  869.   forall_edges(e,SUB) W <<  segment(SUB[source(e)],SUB[target(e)]);
  870.  
  871.   sleep(2);
  872.  
  873.   }
  874.  
  875. }
  876.  
  877.  
  878.  
  879. main(int argc, char** argv)
  880. {
  881.   int   position=0, 
  882.         N=0;
  883.  
  884.   float f1=0, 
  885.         f2=0;
  886.  
  887.   float w,h,xpos,ypos;
  888.  
  889.   string_istream arguments(argc-1,argv+1);
  890.  
  891.   arguments >> f1;
  892.   arguments >> f2;
  893.  
  894.   if (f1 == 0 && f2 == 0) 
  895.    { f1 = 0.75;
  896.      f2 = 0.95;
  897.     }
  898.   else 
  899.    if (f2 == 0) 
  900.      f2 = f1;
  901.    else
  902.      { arguments >> position;
  903.        arguments >> N;
  904.       }
  905.  
  906.   w = SCREEN_WIDTH*f1;
  907.   h = SCREEN_HEIGHT*f2;
  908.  
  909.   switch(position) {
  910.  
  911.   case 0: xpos = SCREEN_WIDTH - w;
  912.           ypos = 0;
  913.           break; 
  914.  
  915.   case 1: xpos = 0;
  916.           ypos = 0;
  917.           break; 
  918.  
  919.   case 2: xpos = 0;
  920.           ypos = SCREEN_HEIGHT - h;
  921.           break; 
  922.  
  923.   case 3: xpos = SCREEN_WIDTH - w;
  924.           ypos = SCREEN_HEIGHT - h;
  925.           break; 
  926. }
  927.  
  928.  
  929.   window W(w,h,xpos,ypos);
  930.  
  931.   Wp = &W;
  932.  
  933.   if (N==0) 
  934.      interactive(W);
  935.   else
  936.      demo(W,N);
  937.  
  938. }
  939.