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

MultiPlatform

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