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

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _sweep_old.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. //------------------------------------------------------------------------------
  12. //
  13. // SWEEP_SEGMENTS
  14. //
  15. // a plane sweep algorithm for computing line segment intersections
  16. //
  17. // SWEEP_SEGMENTS(list<segment>& L1, list<segment>& L2, GRAPH<point,int> G);
  18. //
  19. // computes the planar subdivision created by the (directed) straight
  20. // line segments of L1 and L2
  21. // 
  22. // G = (V,E) with
  23. //
  24. // 1. each node v in V contains a point of intersectoin between two segments
  25. //    (from L1 or L2)
  26. //
  27. // 2. each edge e = (v,w) corresponds to a
  28. //
  29. //
  30. //------------------------------------------------------------------------------
  31. #include <LEDA/sweep_segments.h>
  32. #include <LEDA/sortseq.h>
  33. #include <LEDA/p_queue.h>
  34. #include <math.h>
  35. #define EPS  0.00001
  36. #define EPS2 0.0000000001
  37. class S_POINT;
  38. class S_SEGMENT;
  39. typedef S_POINT* S_point;
  40. typedef S_SEGMENT* S_segment;
  41. enum S_point_type {Cross=0,Rightend=1,Leftend=2}; 
  42. class S_POINT
  43. {
  44.   friend class S_SEGMENT;
  45.   S_segment seg;
  46.   int     kind;
  47.   double  x;
  48.   double  y;
  49.   public:
  50.   S_POINT(double a,double b)  
  51.   { 
  52.     x=a; y=b; seg=0; kind=Cross;
  53.    }
  54.   S_POINT(point p)         
  55.   { 
  56.     x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;
  57.    }
  58.   LEDA_MEMORY(S_POINT);
  59.   friend double    get_x(S_point);
  60.   friend double    get_y(S_point);
  61.   friend int       get_kind(S_point);
  62.   friend S_segment get_seg(S_point);
  63.   friend bool intersection(S_segment, S_segment, S_point&);
  64. };
  65. inline double    get_x(S_point p)    { return p->x; }
  66. inline double    get_y(S_point p)    { return p->y; }
  67. inline int       get_kind(S_point p) { return p->kind; }
  68. inline S_segment get_seg(S_point p)  { return p->seg; }   
  69. #if defined(__GNUC__)
  70. inline
  71. #else
  72. static 
  73. #endif
  74. int compare(const S_point& p1, const S_point& p2)
  75. { if (p1==p2) return 0;
  76.   double diffx = get_x(p1) - get_x(p2);
  77.   if (diffx >  EPS2 ) return  1;
  78.   if (diffx < -EPS2 ) return -1;
  79.   int    diffk = get_kind(p1)-get_kind(p2);
  80.   if (diffk != 0) return diffk;
  81.   double diffy = get_y(p1) - get_y(p2);
  82.   if (diffy >  EPS2 ) return  1;
  83.   if (diffy < -EPS2 ) return -1;
  84.   return 0;
  85. }
  86. class S_SEGMENT
  87. {
  88.   S_point startpoint;
  89.   S_point endpoint;
  90.   double  slope;
  91.   double  yshift;
  92.   node  left_node;
  93.   int   orient;
  94.   int   color;
  95.   int   name;
  96.   public:
  97.   S_SEGMENT(S_point, S_point,int,int);     
  98.  ~S_SEGMENT() { delete startpoint; delete endpoint; }     
  99.   LEDA_MEMORY(S_SEGMENT);
  100.   friend S_point get_startpoint(S_segment);
  101.   friend S_point get_endpoint(S_segment);
  102.   friend double get_slope(S_segment);
  103.   friend double get_yshift(S_segment);
  104.   friend int  get_orient(S_segment);
  105.   friend int  get_color(S_segment);
  106.   friend int  get_name(S_segment);
  107.   friend node get_left_node(S_segment);
  108.   friend void set_left_node(S_segment, node);
  109.   friend bool intersection(S_segment, S_segment, S_point&);
  110. };
  111. inline S_point get_startpoint(S_segment seg)     { return seg->startpoint; }
  112. inline S_point get_endpoint(S_segment seg)       { return seg->endpoint; }
  113. inline double get_slope(S_segment seg)           { return seg->slope; }
  114. inline double get_yshift(S_segment seg)          { return seg->yshift; }
  115. inline int  get_orient(S_segment seg)            { return seg->orient; }
  116. inline int  get_color(S_segment seg)             { return seg->color; }
  117. inline int  get_name(S_segment seg)              { return seg->name; }
  118. inline node get_left_node(S_segment seg)         { return seg->left_node; }
  119. inline void set_left_node(S_segment seg, node v) { seg->left_node = v; }
  120. S_SEGMENT::S_SEGMENT(S_point p1,S_point p2,int c, int n)    
  121.   {
  122.     left_node  = nil;
  123.     color      = c;
  124.     name       = n;
  125.     if (compare(p1,p2) < 0)
  126.      { startpoint = p1; 
  127.        endpoint = p2; 
  128.        orient = 0;
  129.       }
  130.     else
  131.      { startpoint = p2; 
  132.        endpoint = p1; 
  133.        orient = 1;
  134.       }
  135.     startpoint->kind = Leftend; 
  136.     endpoint->kind = Rightend; 
  137.     startpoint->seg = this; 
  138.     endpoint->seg = this;
  139.     if (endpoint->x != startpoint->x)
  140.     {
  141.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  142.       yshift = startpoint->y - slope * startpoint->x;
  143.       startpoint->x -= EPS;
  144.       startpoint->y -= EPS * slope;
  145.       endpoint->x += EPS;
  146.       endpoint->y += EPS * slope;
  147.     }
  148.     else //vertical segment
  149.     { startpoint->y -= EPS;
  150.       endpoint->y   += EPS;
  151.      }
  152.   }
  153. static double x_sweep;
  154. static double y_sweep;
  155. #if defined(__GNUC__)
  156. inline
  157. #else
  158. static 
  159. #endif
  160. int compare(const S_segment& s1, const S_segment& s2)
  161. {
  162.   double y1 = get_slope(s1)*x_sweep+get_yshift(s1);
  163.   double y2 = get_slope(s2)*x_sweep+get_yshift(s2);
  164.   double diff = y1-y2;
  165.   if (diff >  EPS2 ) return  1;
  166.   if (diff < -EPS2 ) return -1;
  167.   if (get_slope(s1) == get_slope(s2)) 
  168.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  169.   if (y1 <= y_sweep+EPS2)
  170.         return compare(get_slope(s1),get_slope(s2));
  171.   else
  172.         return compare(get_slope(s2),get_slope(s1));
  173. }
  174. void Print(S_segment& x) 
  175. { S_point s = get_startpoint(x);
  176.   S_point e = get_endpoint(x);
  177.   cout << 
  178.     string("[(%f,%f)----(%f,%f)]",get_x(s),get_y(s), get_x(e),get_y(e));
  179. }
  180. static p_queue<S_point,seq_item>  X_structure;
  181. static sortseq<S_segment,pq_item> Y_structure;
  182. bool intersection(S_segment seg1,S_segment seg2, S_point& inter)
  183. {
  184.   if (seg1->slope == seg2->slope)
  185.     return false;
  186.   else
  187.   { 
  188.     double cx = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  189.  
  190.     if (cx <= x_sweep) return false;
  191.     if (seg1->startpoint->x > cx || seg2->startpoint->x > cx ||
  192.         seg1->endpoint->x < cx || seg2->endpoint->x < cx ) return false;
  193.     inter = new S_POINT(cx,seg1->slope * cx + seg1->yshift);
  194.     return true;
  195.   }
  196. }
  197. static pq_item Xinsert(seq_item i, S_point p) 
  198.   return X_structure.insert(p,i);
  199. }
  200. static S_point Xdelete(pq_item i) 
  201. {
  202.   S_point p = X_structure.prio(i);
  203.   X_structure.del_item(i);
  204.   return p;
  205. }
  206. static node New_Node(GRAPH<point,int>& G,double x, double y )
  207. { return G.new_node(point(x,y)); }
  208. static void New_Edge(GRAPH<point,int>& G,node v, node w, S_segment l )
  209. { if (get_orient(l)==0)
  210.        G.new_edge(v,w,get_color(l));
  211.   else G.new_edge(w,v,get_color(l));
  212. }
  213. void handle_vertical_segment(GRAPH<point,int>& SUB, S_segment l)
  214.   S_point p = new S_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  215.   S_point q = new S_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  216.   S_point r = new S_POINT(get_x(p)+1,get_y(p));
  217.   S_point s = new S_POINT(get_x(q)+1,get_y(q));
  218.   S_segment bot = new S_SEGMENT(p,r,0,0);
  219.   S_segment top = new S_SEGMENT(q,s,0,0);
  220.   seq_item bot_it = Y_structure.insert(bot,nil);
  221.   seq_item top_it = Y_structure.insert(top,nil);
  222.   seq_item sit;
  223.   node u,v,w;
  224.   S_segment seg;
  225.   
  226.   for(sit=Y_structure.succ(bot_it); sit != top_it; sit=Y_structure.succ(sit))
  227.   { seg = Y_structure.key(sit);
  228.     double cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  229.     v = get_left_node(seg);
  230.     if (v==nil)
  231.     { w = New_Node(SUB,get_x(p),cross_y);
  232.       set_left_node(seg,w);
  233.      }
  234.     else
  235.     { double vx = SUB[v].xcoord();
  236.       if ( vx < get_x(p)-EPS2) 
  237.       { w = New_Node(SUB,get_x(p),cross_y);
  238.         New_Edge(SUB,v,w,seg);
  239.         set_left_node(seg,w);
  240.        }
  241.       else w = v;
  242.      }
  243.     u = get_left_node(l);
  244.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  245.     set_left_node(l,w);
  246.    }
  247.   
  248.   delete l;
  249.   delete top;
  250.   delete bot;
  251.     
  252.   Y_structure.del_item(bot_it);
  253.   Y_structure.del_item(top_it);
  254.  }
  255. void SWEEP_SEGMENTS(const list<segment>& S, list<point>& P)
  256. { GRAPH<point,int> G;
  257.   list<segment> S0;
  258.   SWEEP_SEGMENTS(S,S0,G);
  259.   node v;
  260.   forall_nodes(v,G) P.append(G[v]);
  261. }
  262. void SWEEP_SEGMENTS(const list<segment>& L1, 
  263.                     const list<segment>& L2, GRAPH<point,int>& SUB)
  264. {
  265.   S_point    p,inter;
  266.   S_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  267.   pq_item  pqit,pxmin;
  268.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  269.   int count=1;
  270.  
  271.   //initialization of the X-structure
  272.   segment s;
  273.   forall(s,L1) 
  274.    { S_point p = new S_POINT(s.start());
  275.      S_point q = new S_POINT(s.end());
  276.      seg = new S_SEGMENT(p,q,0,count++);
  277.      Xinsert(nil,get_startpoint(seg));
  278.    }
  279.   count = -1;
  280.   forall(s,L2) 
  281.    { S_point p = new S_POINT(s.start());
  282.      S_point q = new S_POINT(s.end());
  283.      seg = new S_SEGMENT(p,q,1,count--);
  284.      Xinsert(nil,get_startpoint(seg));
  285.    }
  286.   count = 0;
  287.   x_sweep = -MAXINT;
  288.   y_sweep = -MAXINT;
  289.   while(!X_structure.empty())
  290.   {
  291.     pxmin = X_structure.find_min();
  292.     p = X_structure.prio(pxmin);
  293.     sitmin = X_structure.inf(pxmin);
  294.     Xdelete(pxmin);
  295.     if (sitmin == nil) //left endpoint
  296.     { 
  297.       l = get_seg(p); 
  298.       x_sweep = get_x(p);
  299.       y_sweep = get_y(p);
  300.       if (get_x(p) == get_x(get_endpoint(l)))
  301.         handle_vertical_segment(SUB,l);
  302.       else
  303.       {
  304. /*
  305.       sit = Y_structure.lookup(l);
  306.       if (sit!=nil)  
  307.            error_handler(1,"plane sweep: sorry, overlapping segments");
  308. */
  309.       sit = Y_structure.insert(l,nil);
  310.       Xinsert(sit,get_endpoint(l));
  311.       sitpred = Y_structure.pred(sit);
  312.       sitsucc = Y_structure.succ(sit);
  313.       if (sitpred != nil) 
  314.       { if ((pqit = Y_structure.inf(sitpred)) != nil)
  315.           delete Xdelete(pqit);
  316.         lpred = Y_structure.key(sitpred);
  317.         Y_structure.change_inf(sitpred,nil);
  318.         if (intersection(lpred,l,inter))
  319.             Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  320.       }
  321.       if (sitsucc != nil)
  322.       { lsucc = Y_structure.key(sitsucc);
  323.         if (intersection(lsucc,l,inter))
  324.            Y_structure.change_inf(sit,Xinsert(sit,inter));
  325.       }
  326.      } /* else if vertical */
  327.     }
  328.     else if (get_kind(p) == Rightend)
  329.          //right endpoint
  330.          { 
  331.            x_sweep = get_x(p);
  332.            y_sweep = get_y(p);
  333.            sit = sitmin;
  334.            sitpred = Y_structure.pred(sit);
  335.            sitsucc = Y_structure.succ(sit);
  336.            S_segment seg = Y_structure.key(sit);
  337.            Y_structure.del_item(sit);
  338.            delete seg;
  339.            if((sitpred != nil)&&(sitsucc != nil))
  340.            {
  341.              lpred = Y_structure.key(sitpred);
  342.              lsucc = Y_structure.key(sitsucc);
  343.              if (intersection(lsucc,lpred,inter))
  344.                 Y_structure.change_inf(sitpred,Xinsert(sitpred,inter));
  345.            }
  346.          }
  347.          else // point of intersection
  348.          { 
  349.            node w = New_Node(SUB,get_x(p),get_y(p));
  350.            count++;
  351.            /* Let L = list of all lines intersecting in p 
  352.  
  353.               we compute sit     = L.head();
  354.               and        sitpred = L.tail();
  355.               by scanning the Y_structure in both directions 
  356.               starting at sitmin;
  357.            */
  358.            /* search for sitpred upwards from sitmin: */
  359.            Y_structure.change_inf(sitmin,nil);
  360.            sitpred = Y_structure.succ(sitmin);
  361.            while ((pqit=Y_structure.inf(sitpred)) != nil)
  362.            { S_point q = X_structure.prio(pqit);
  363.              if (compare(p,q) != 0) break; 
  364.              X_structure.del_item(pqit);
  365.              Y_structure.change_inf(sitpred,nil);
  366.              sitpred = Y_structure.succ(sitpred);
  367.             }
  368.            /* search for sit downwards from sitmin: */
  369.            sit = sitmin;
  370.            seq_item sit1;
  371.            
  372.            while ((sit1=Y_structure.pred(sit)) != nil)
  373.            { pqit = Y_structure.inf(sit1);
  374.              if (pqit == nil) break;
  375.              S_point q = X_structure.prio(pqit);
  376.              if (compare(p,q) != 0) break; 
  377.              X_structure.del_item(pqit);
  378.              Y_structure.change_inf(sit1,nil);
  379.              sit = sit1;
  380.             }
  381.            // insert edges to p for all S_segments in sit, ..., sitpred into SUB
  382.            // and set left node to w 
  383.            lsit = Y_structure.key(sitpred);
  384.            node v = get_left_node(lsit);
  385.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  386.            set_left_node(lsit,w);
  387.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure.succ(sit1))
  388.            { lsit = Y_structure.key(sit1);
  389.              v = get_left_node(lsit);
  390.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  391.              set_left_node(lsit,w);
  392.             }
  393.            lsit = Y_structure.key(sit);
  394.            lpred=Y_structure.key(sitpred);
  395.            sitpredpred = Y_structure.pred(sit);
  396.            sitsucc=Y_structure.succ(sitpred);
  397.            if (sitpredpred != nil)
  398.             { 
  399.               lpredpred=Y_structure.key(sitpredpred);
  400.               if ((pqit = Y_structure.inf(sitpredpred)) != nil)
  401.                 delete Xdelete(pqit);
  402.               Y_structure.change_inf(sitpredpred,nil);
  403.               if (intersection(lpred,lpredpred,inter))
  404.                 Y_structure.change_inf(sitpredpred,
  405.                                        Xinsert(sitpredpred,inter));
  406.              }
  407.            if (sitsucc != nil)
  408.             {
  409.               lsucc=Y_structure.key(sitsucc);
  410.               if ((pqit = Y_structure.inf(sitpred)) != nil)
  411.                 delete Xdelete(pqit);
  412.                  
  413.               Y_structure.change_inf(sitpred,nil);
  414.               if (intersection(lsucc,lsit,inter))
  415.                   Y_structure.change_inf(sit,Xinsert(sit,inter));
  416.              }
  417. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  418.            x_sweep = get_x(p);
  419.            y_sweep = get_y(p);
  420.            Y_structure.reverse_items(sit,sitpred);
  421.           delete p;
  422.          } // intersection
  423.   }
  424.   X_structure.clear();
  425. }