home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / plane / _sweep_s.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  13.2 KB  |  586 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _sweep_segments.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. //------------------------------------------------------------------------------
  16. //
  17. // SWEEP_SEGMENTS
  18. //
  19. // a plane sweep algorithm for computing line segment intersections
  20. //
  21. // SWEEP_SEGMENTS(list(segment)& L1, list(segment)& L2, GRAPH(point,int) G);
  22. //
  23. // computes the planar subdivision created by the (directed) straight
  24. // line segments of L1 and L2
  25. // 
  26. // G = (V,E) with
  27. //
  28. // 1. each node v in V contains a point of intersectoin between two segments
  29. //    (from L1 or L2)
  30. //
  31. // 2. each edge e = (v,w) corresponds to a
  32. //
  33. //
  34. //------------------------------------------------------------------------------
  35.  
  36.  
  37. #include <LEDA/plane.h>
  38. #include <LEDA/plane_alg.h>
  39.  
  40. #include <LEDA/sortseq.h>
  41. #include <LEDA/prio.h>
  42.  
  43. #include <math.h>
  44.  
  45. #define EPS  0.00001
  46. #define EPS2 0.0000000001
  47.  
  48. class S_POINT;
  49. class S_SEGMENT;
  50. typedef S_POINT* S_point;
  51. typedef S_SEGMENT* S_segment;
  52.  
  53. enum S_point_type {Cross=0,Rightend=1,Leftend=2}; 
  54.  
  55. static class S_POINT
  56. {
  57.   friend class S_SEGMENT;
  58.  
  59.   S_segment seg;
  60.   int     kind;
  61.   real  x;
  62.   real  y;
  63.  
  64. //size = 4 words
  65.  
  66.   public:
  67.  
  68.   S_POINT(real a,real b)  
  69.   { 
  70.     x=a; y=b; seg=0; kind=Cross;
  71.    }
  72.  
  73.  
  74.  
  75.   S_POINT(point p)         
  76.   { 
  77.     x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;
  78.    }
  79.  
  80.  
  81. OPERATOR_NEW(4)
  82. OPERATOR_DEL(4)
  83.  
  84.   friend real    get_x(S_point p)      { return p->x; }
  85.   friend real    get_y(S_point p)      { return p->y; }
  86.   friend int     get_kind(S_point p)   { return p->kind; }
  87.   friend S_segment get_seg(S_point p)    { return p->seg; }   
  88.  
  89.   friend bool intersection(S_segment, S_segment, S_point&);
  90. };
  91.  
  92. static int compare(S_point& p1,S_point& p2)
  93. { if (p1==p2) return 0;
  94.  
  95.   real diffx = get_x(p1) - get_x(p2);
  96.   if (fabs(diffx) > EPS2 ) return (diffx > 0.0) ? 1 : -1;
  97.  
  98.   int    diffk = get_kind(p1)-get_kind(p2);
  99.   if (diffk != 0) return diffk;
  100.  
  101.   real diffy = get_y(p1) - get_y(p2);
  102.   if (fabs(diffy) > EPS2 ) return (diffy > 0.0) ? 1 : -1;
  103.  
  104.   return 0;
  105.  
  106. }
  107.  
  108.  
  109. static class S_SEGMENT
  110. {
  111.   S_point startpoint;
  112.   S_point endpoint;
  113.   real  slope;
  114.   real  yshift;
  115.   node  left_node;
  116.   int   orient;
  117.   int   color;
  118.   int   name;
  119.  
  120.  
  121. // size = 8 words
  122.  
  123.   public:
  124.  
  125.   S_SEGMENT(S_point, S_point,int,int);     
  126.  
  127.  ~S_SEGMENT() { delete startpoint; delete endpoint; }     
  128.  
  129. OPERATOR_NEW(8)
  130. OPERATOR_DEL(8)
  131.  
  132.  
  133.   friend S_point get_startpoint(S_segment seg)       { return seg->startpoint; }
  134.   friend S_point get_endpoint(S_segment seg)         { return seg->endpoint; }
  135.   friend real get_slope(S_segment seg)             { return seg->slope; }
  136.   friend real get_yshift(S_segment seg)            { return seg->yshift; }
  137.   friend int  get_orient(S_segment seg)            { return seg->orient; }
  138.   friend int  get_color(S_segment seg)             { return seg->color; }
  139.   friend int  get_name(S_segment seg)              { return seg->name; }
  140.   friend node get_left_node(S_segment seg)         { return seg->left_node; }
  141.   friend void set_left_node(S_segment seg, node v) { seg->left_node = v; }
  142.  
  143.   friend bool intersection(S_segment, S_segment, S_point&);
  144. };
  145.  
  146.  
  147. S_SEGMENT::S_SEGMENT(S_point p1,S_point p2,int c, int n)    
  148.   {
  149.     left_node  = nil;
  150.     color      = c;
  151.     name       = n;
  152.  
  153.     if (compare(p1,p2) < 0)
  154.      { startpoint = p1; 
  155.        endpoint = p2; 
  156.        orient = 0;
  157.       }
  158.     else
  159.      { startpoint = p2; 
  160.        endpoint = p1; 
  161.        orient = 1;
  162.       }
  163.  
  164.     startpoint->kind = Leftend; 
  165.     endpoint->kind = Rightend; 
  166.     startpoint->seg = this; 
  167.     endpoint->seg = this;
  168.  
  169.     if (endpoint->x != startpoint->x)
  170.     {
  171.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  172.       yshift = startpoint->y - slope * startpoint->x;
  173.  
  174.       startpoint->x -= EPS;
  175.       startpoint->y -= EPS * slope;
  176.       endpoint->x += EPS;
  177.       endpoint->y += EPS * slope;
  178.     }
  179.     else //vertical segment
  180.     { startpoint->y -= EPS;
  181.       endpoint->y   += EPS;
  182.      }
  183.   }
  184.  
  185.  
  186. real x_sweep;
  187. real y_sweep;
  188.  
  189.  
  190. static int compare(S_segment& s1,S_segment& s2)
  191. {
  192.   real y1 = get_slope(s1)*x_sweep+get_yshift(s1);
  193.   real y2 = get_slope(s2)*x_sweep+get_yshift(s2);
  194.  
  195.   real diff = y1-y2;
  196.  
  197.   if (fabs(diff) > EPS2) return (diff > 0.0) ? 1 : -1;
  198.  
  199.   if (get_slope(s1) == get_slope(s2)) 
  200.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  201.  
  202.   if (y1 <= y_sweep+EPS2)
  203.         return compare(get_slope(s1),get_slope(s2));
  204.   else
  205.         return compare(get_slope(s2),get_slope(s1));
  206.  
  207. }
  208.  
  209.  
  210. void Print(S_segment& x) 
  211. { S_point s = get_startpoint(x);
  212.   S_point e = get_endpoint(x);
  213.   cout << 
  214.     string("[(%f,%f)----(%f,%f)]",~get_x(s),~get_y(s), ~get_x(e),~get_y(e));
  215. }
  216.  
  217.  
  218. declare2(priority_queue,seq_item,S_point);
  219. priority_queue(seq_item,S_point) X_structure;
  220.  
  221. declare2(sortseq,S_segment,pq_item);
  222. sortseq(S_segment,pq_item) Y_structure;
  223.  
  224.  
  225. bool intersection(S_segment seg1,S_segment seg2, S_point& inter)
  226. {
  227.   if (seg1->slope == seg2->slope)
  228.     return false;
  229.   else
  230.   {
  231.     //x-coordinate  of the intersection
  232.     real Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  233.  
  234.     if (Cross_x <= x_sweep) return false;
  235.  
  236.     real s1 = seg1->startpoint->x;
  237.     real s2 = seg2->startpoint->x;
  238.     real e1 = seg1->endpoint->x;
  239.     real e2 = seg2->endpoint->x;
  240.  
  241.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  242.  
  243.     //y-coordinate of the intersection
  244.     real Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  245.     inter =  new S_POINT(Cross_x,Cross_y);
  246.  
  247.     return true;
  248.   }
  249. }
  250.  
  251.  
  252. static pq_item Xinsert(seq_item i, S_point p) 
  253.   return X_structure.insert(i,p);
  254. }
  255.  
  256. static S_point Xdelete(pq_item i) 
  257. {
  258.   S_point p = X_structure.inf(i);
  259.   X_structure.del_item(i);
  260.   return p;
  261. }
  262.  
  263.  
  264. static node New_Node(GRAPH(point,int)& G,real x, real y )
  265. { return G.new_node(point(x,y)); }
  266.  
  267. static void New_Edge(GRAPH(point,int)& G,node v, node w, S_segment l )
  268. { if (get_orient(l)==0)
  269.        G.new_edge(v,w,get_color(l));
  270.   else G.new_edge(w,v,get_color(l));
  271. }
  272.  
  273.  
  274. void handle_vertical_segment(GRAPH(point,int)& SUB, S_segment l)
  275.   S_point p = new S_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  276.   S_point q = new S_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  277.  
  278.   S_point r = new S_POINT(get_x(p)+1,get_y(p));
  279.   S_point s = new S_POINT(get_x(q)+1,get_y(q));
  280.  
  281.   S_segment bot = new S_SEGMENT(p,r,0,0);
  282.   S_segment top = new S_SEGMENT(q,s,0,0);
  283.  
  284.   seq_item bot_it = Y_structure.insert(bot,nil);
  285.   seq_item top_it = Y_structure.insert(top,nil);
  286.   seq_item sit;
  287.  
  288.   node u,v,w;
  289.   S_segment seg;
  290.   
  291.  
  292.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  293.   { seg = Y_structure.key(sit);
  294.  
  295.     real cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  296.  
  297.     v = get_left_node(seg);
  298.     if (v==nil)
  299.     { w = New_Node(SUB,get_x(p),cross_y);
  300.       set_left_node(seg,w);
  301.      }
  302.     else
  303.     { real vx = SUB[v].xcoord();
  304.       if ( vx < get_x(p)-EPS2) 
  305.       { w = New_Node(SUB,get_x(p),cross_y);
  306.         New_Edge(SUB,v,w,seg);
  307.         set_left_node(seg,w);
  308.        }
  309.       else w = v;
  310.      }
  311.  
  312.     u = get_left_node(l);
  313.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  314.     set_left_node(l,w);
  315.  
  316.    }
  317.   
  318.   delete l;
  319.   delete top;
  320.   delete bot;
  321.     
  322.   Y_structure.del_item(bot_it);
  323.   Y_structure.del_item(top_it);
  324.  
  325.  }
  326.  
  327.  
  328. void SWEEP_SEGMENTS(list(segment)& S, list(point)& P)
  329. { GRAPH(point,int) G;
  330.   list(segment) S0;
  331.  
  332.   SWEEP_SEGMENTS(S,S0,G);
  333.  
  334.   node v;
  335.   forall_nodes(v,G) P.append(G[v]);
  336.  
  337. }
  338.  
  339. void SWEEP_SEGMENTS(list(segment)& L1, list(segment)& L2, GRAPH(point,int)& SUB)
  340. {
  341.   S_point    p,inter;
  342.   S_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  343.   pq_item  pqit,pxmin;
  344.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  345.  
  346.  
  347.   int count=1;
  348.  
  349.   //initialization of the X-structure
  350.  
  351.   segment s;
  352.  
  353.   forall(s,L1) 
  354.    { S_point p = new S_POINT(s.start());
  355.      S_point q = new S_POINT(s.end());
  356.      seg = new S_SEGMENT(p,q,0,count++);
  357.      Xinsert(nil,get_startpoint(seg));
  358.    }
  359.  
  360.   count = -1;
  361.  
  362.   forall(s,L2) 
  363.    { S_point p = new S_POINT(s.start());
  364.      S_point q = new S_POINT(s.end());
  365.      seg = new S_SEGMENT(p,q,1,count--);
  366.      Xinsert(nil,get_startpoint(seg));
  367.    }
  368.  
  369.  
  370.   count = 0;
  371.  
  372.   x_sweep = -Infinity;
  373.   y_sweep = -Infinity;
  374.  
  375.  
  376.   while(!X_structure.empty())
  377.   {
  378.     pxmin = X_structure.find_min();
  379.     p = X_structure.inf(pxmin);
  380.  
  381.     sitmin = X_structure.key(pxmin);
  382.  
  383.     Xdelete(pxmin);
  384.  
  385.  
  386.  
  387.     if (get_kind(p) == Leftend)
  388.  
  389.     //left endpoint
  390.     { 
  391.  
  392.       l = get_seg(p); 
  393.  
  394.       x_sweep = get_x(p);
  395.       y_sweep = get_y(p);
  396.  
  397.  
  398.       if (get_x(p) == get_x(get_endpoint(l)))
  399.         handle_vertical_segment(SUB,l);
  400.       else
  401.       {
  402.  
  403. /*
  404.       sit = Y_structure.lookup(l);
  405.       if (sit!=nil)  
  406.            error_handler(1,"plane sweep: sorry, overlapping segments");
  407. */
  408.  
  409.  
  410.       sit = Y_structure.insert(l,nil);
  411.  
  412.       Xinsert(sit,get_endpoint(l));
  413.  
  414.       sitpred = Y_structure.pred(sit);
  415.       sitsucc = Y_structure.succ(sit);
  416.  
  417.       if (sitpred != nil) 
  418.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  419.           delete Xdelete(pqit);
  420.  
  421.         lpred = Y_structure.key(sitpred);
  422.  
  423.         Y_structure.change_inf(sitpred,nil);
  424.  
  425.         if (intersection(lpred,l,inter))
  426.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  427.       }
  428.  
  429.  
  430.       if (sitsucc != nil)
  431.       { lsucc = Y_structure.key(sitsucc);
  432.         if (intersection(lsucc,l,inter))
  433.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  434.       }
  435.      } /* else if vertical */
  436.  
  437.     }
  438.     else if (get_kind(p) == Rightend)
  439.          //right endpoint
  440.          { 
  441.            x_sweep = get_x(p);
  442.            y_sweep = get_y(p);
  443.  
  444.            sit = sitmin;
  445.  
  446.            sitpred = Y_structure.pred(sit);
  447.            sitsucc = Y_structure.succ(sit);
  448.  
  449.            S_segment seg = Y_structure.key(sit);
  450.  
  451.            Y_structure.del_item(sit);
  452.  
  453.            delete seg;
  454.  
  455.            if((sitpred != nil)&&(sitsucc != nil))
  456.            {
  457.              lpred = Y_structure.key(sitpred);
  458.              lsucc = Y_structure.key(sitsucc);
  459.              if (intersection(lsucc,lpred,inter))
  460.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  461.            }
  462.          }
  463.          else
  464.          /*point of intersection*/
  465.          { 
  466.            node w = New_Node(SUB,get_x(p),get_y(p));
  467.  
  468.            count++;
  469.  
  470.            /* Let L = list of all lines intersecting in p 
  471.  
  472.               we compute sit     = L.head();
  473.               and        sitpred = L.tail();
  474.  
  475.               by scanning the Y_structure in both directions 
  476.               starting at sitmin;
  477.  
  478.            */
  479.  
  480.            /* search for sitpred upwards from sitmin: */
  481.  
  482.            Y_structure.change_inf(sitmin,nil);
  483.  
  484.            sitpred = Y_structure.succ(sitmin);
  485.  
  486.  
  487.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  488.            { S_point q = X_structure.inf(pqit);
  489.              if (compare(p,q) != 0) break; 
  490.              X_structure.del_item(pqit);
  491.              Y_structure.change_inf(sitpred,nil);
  492.              sitpred = Y_structure.succ(sitpred);
  493.             }
  494.  
  495.  
  496.            /* search for sit downwards from sitmin: */
  497.  
  498.            sit = sitmin;
  499.  
  500.            seq_item sit1;
  501.            
  502.            while ((sit1=Y_structure.pred(sit)) != nil)
  503.            { pqit = Y_structure.inf(sit1);
  504.              if (pqit == nil) break;
  505.              S_point q = X_structure.inf(pqit);
  506.              if (compare(p,q) != 0) break; 
  507.              X_structure.del_item(pqit);
  508.              Y_structure.change_inf(sit1,nil);
  509.              sit = sit1;
  510.             }
  511.  
  512.  
  513.  
  514.            // insert edges to p for all S_segments in sit, ..., sitpred into SUB
  515.            // and set left node to w 
  516.  
  517.            lsit = Y_structure.key(sitpred);
  518.  
  519.            node v = get_left_node(lsit);
  520.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  521.            set_left_node(lsit,w);
  522.  
  523.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  524.            { lsit = Y_structure.key(sit1);
  525.  
  526.              v = get_left_node(lsit);
  527.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  528.              set_left_node(lsit,w);
  529.             }
  530.  
  531.            lsit = Y_structure.key(sit);
  532.            lpred=Y_structure.key(sitpred);
  533.            sitpredpred = Y_structure.pred(sit);
  534.            sitsucc=Y_structure.succ(sitpred);
  535.  
  536.  
  537.            if (sitpredpred != nil)
  538.             { 
  539.               lpredpred=Y_structure.key(sitpredpred);
  540.  
  541.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  542.                 delete Xdelete(pqit);
  543.  
  544.               Y_structure.change_inf(sitpredpred,nil);
  545.  
  546.  
  547.               if (intersection(lpred,lpredpred,inter))
  548.                 Y_structure.change_inf(sitpredpred,
  549.                                        Xinsert(sitpredpred,inter));
  550.              }
  551.  
  552.  
  553.            if (sitsucc != nil)
  554.             {
  555.               lsucc=Y_structure.key(sitsucc);
  556.  
  557.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  558.                 delete Xdelete(pqit);
  559.                  
  560.               Y_structure.change_inf(sitpred,nil);
  561.  
  562.               if (intersection(lsucc,lsit,inter))
  563.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  564.              }
  565.  
  566.  
  567. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  568.  
  569.            x_sweep = get_x(p);
  570.            y_sweep = get_y(p);
  571.  
  572.            Y_structure.reverse_items(sit,sitpred);
  573.  
  574.           delete p;
  575.  
  576.          } // intersection
  577.  
  578.   }
  579.  
  580.   X_structure.clear();
  581.  
  582. }
  583.