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

MultiPlatform

  1. #include <LEDA/hash.h>
  2. // global variables
  3. static POINT p_sweep;
  4. static int   N;
  5. // geometric primitives
  6. inline int pair(const SEGMENT& p, const SEGMENT& q)
  7. { return  ID_Number(p) * N + ID_Number(q); }
  8. inline int compare(const SEGMENT& s1, const SEGMENT& s2)
  9.   // Precondition: |p_sweep| is identical to the left endpoint of
  10.   // either |s1| or |s2|. This is true since comparisons are only 
  11.   // executed when inserting or looking up new segments.
  12.   if ( identical(p_sweep,s1.start()) )
  13.   { int s = orientation(s2,p_sweep);
  14.     return (s != 0) ? -s : cmp_slopes(s1,s2);
  15.    }
  16.   if ( identical(p_sweep,s2.start()) )
  17.   { int s = orientation(s1,p_sweep);
  18.     return (s != 0) ? s : cmp_slopes(s1,s2);
  19.    }
  20.   error_handler(1,"internal error in sweep");
  21.   return 0; // never reached
  22. }
  23. static void compute_intersection(sortseq<POINT,seq_item>& X_structure,
  24.                                  sortseq<SEGMENT,seq_item>& Y_structure,
  25.                                  hash<int,seq_item>& inter_dic,
  26.                                  seq_item sit0)
  27. {
  28.   // Given an item |sit0| in the Y-structure compute the point of 
  29.   // intersection with its successor and (if existing) insert it into 
  30.   // the event queue and do all necessary updates.
  31.   seq_item sit1 = Y_structure.succ(sit0);
  32.   SEGMENT  s0   = Y_structure.key(sit0);
  33.   SEGMENT  s1   = Y_structure.key(sit1);
  34.   // |s1| is the successor of |s0| in the Y-structure, hence,
  35.   // |s0| and |s1| intersect right or above of the sweep line
  36.   // iff |(s0.start(),s0.end(),s1.end()| is not a left turn and 
  37.   // |(s1.start(),s1.end(),s0.end()| is not a right turn.
  38.   // In this case we intersect the underlying lines
  39.   
  40.   if (orientation(s0,s1.end()) >= 0 && orientation(s1,s0.end()) <=0 )
  41.   { hash_item it = inter_dic.lookup(pair(s0,s1));
  42.     if (it != nil)
  43.        { Y_structure.change_inf(sit0,inter_dic.inf(it));
  44.          inter_dic.del_item(it);
  45.         }
  46.     else
  47.        { POINT    q;
  48.          s0.intersection_of_lines(s1,q);
  49.          Y_structure.change_inf(sit0, X_structure.insert(q,sit0));
  50.         }
  51.   }
  52. }
  53. void sweep1(const list<SEGMENT>& S, GRAPH<POINT,SEGMENT>& G)
  54. {
  55.   // we use two sorted sequences ...
  56.   sortseq <POINT,seq_item>   X_structure;
  57.   sortseq <SEGMENT,seq_item> Y_structure;
  58.   // two maps ...
  59.   map<SEGMENT,node>    last_node(nil);
  60.   map<SEGMENT,SEGMENT> original;
  61.   hash<int,seq_item>   inter_dic;
  62.   // and a priority queue of segments ordered by their left endpoints
  63.   p_queue<POINT,SEGMENT> seg_queue;
  64.   /* INITIALIZATION
  65.      - clear the output graph.
  66.      - compute an upper bound |Infinity| for the input coordinates 
  67.      - make copies of the input segments such that all segments are 
  68.        oriented from left to right or from bottom to top.
  69.      - insert all endpoints of the new segments into the X-structure
  70.      - exploit the fact that insert operations into the X-structure
  71.        leave previously inserted points unchanged to achieve that
  72.        any pair of endpoints $p$ and $q$ with |p == q| are identical
  73.      - use a map to associate with every segment its original 
  74.      - for every created segment $(p,q)$ insert the pair $(p,(p,q))$ 
  75.        into priority queue |seg_queue|
  76.    */
  77.   G.clear();
  78.   numtype Infinity = 1;
  79.   SEGMENT s;
  80.   forall(s,S) 
  81.   {
  82.     while (fabs(s.xcoord1())>=Infinity || fabs(s.ycoord1())>=Infinity ||
  83.            fabs(s.xcoord2())>=Infinity || fabs(s.ycoord2())>=Infinity)
  84.       Infinity *= 2;
  85.     seq_item it1 = X_structure.insert(s.start(), nil);
  86.     seq_item it2 = X_structure.insert(s.end(), nil);
  87.     if (it1 == it2) continue;  // ignore zero-length segments
  88.     POINT p = X_structure.key(it1);
  89.     POINT q = X_structure.key(it2);
  90.     SEGMENT s1(p,q);
  91.     if (compare(p,q) > 0) s1 = SEGMENT(q,p);
  92.     original[s1] = s;
  93.     seg_queue.insert(s1.start(),s1);
  94.   }
  95.   // insert a lower and an upper sentinel segment to avoid special
  96.   // cases when traversing the Y-structure
  97.   SEGMENT lower_sentinel(-Infinity, -Infinity, Infinity, -Infinity);
  98.   SEGMENT upper_sentinel(-Infinity,  Infinity, Infinity,  Infinity);
  99.   // the sweep begins at the lower left corner
  100.   p_sweep = lower_sentinel.start();
  101.   Y_structure.insert(upper_sentinel,nil);
  102.   Y_structure.insert(lower_sentinel,nil);
  103.   // insert a stopper into |seg_queue| and initialize |next_seg| with
  104.   // the first segment in  the queue
  105.   POINT   p_stop(Infinity,Infinity);
  106.   SEGMENT s_stop(p_stop,p_stop);
  107.   seg_queue.insert(p_stop,s_stop);
  108.   SEGMENT next_seg = seg_queue.inf(seg_queue.find_min());
  109.   N = ID_Number(s_stop);
  110.   // Main Loop
  111.   while (!X_structure.empty()) 
  112.   {
  113.     // move |p_sweep| to next event point and insert a new node
  114.     // into the output graph G
  115.     seq_item event = X_structure.min();
  116.     p_sweep = X_structure.key(event);
  117.     node v = G.new_node(p_sweep);
  118.     // If there is a non-nil item |sit| associated with |event|,
  119.     // |key(sit)| is either an ending or passing segment.
  120.     // We use |sit| as an entry point to compute the bundle of
  121.     // segments ending at or passing through |p_sweep|.
  122.     // In particular, we compute the first (sit_first)| and last
  123.     // (|sit_last|) item of this bundle and the successor (|sit_succ)|)
  124.     // and predecessor (|sit_pred|) items.
  125.     seq_item sit = X_structure.inf(event);
  126.     if (sit == nil)
  127.     { // here we do not know any segments ending or passing through 
  128.       // |p_sweep|. However, |p_sweep| could come to lie on a segment 
  129.       // inserted before. To check this we look up the zero length 
  130.       // segment |(p_sweep,p_sweep)|.
  131.       sit = Y_structure.lookup(SEGMENT(p_sweep,p_sweep));
  132.      }
  133.     seq_item sit_succ  = nil;
  134.     seq_item sit_pred  = nil;
  135.     seq_item sit_first = nil;
  136.     seq_item sit_last  = nil;
  137.     // A value of |nil| for |sit_succ| and |sit_pred| after the 
  138.     // following computation indicates that there are no segments 
  139.     // ending at or passing through |p_sweep|
  140.     if (sit != nil)  // key(sit) is an ending or passing segment
  141.     {
  142.       // first walk up until |sit_succ|
  143.       while (Y_structure.inf(sit) == event) sit = Y_structure.succ(sit);
  144.       sit_succ = Y_structure.succ(sit);
  145.       seq_item xit = Y_structure.inf(sit);
  146.       if (xit != nil) 
  147.       { SEGMENT s1 = Y_structure.key(sit);
  148.         SEGMENT s2 = Y_structure.key(sit_succ);
  149.         inter_dic.insert(pair(s1,s2),xit);
  150.        }
  151.       // walk down until |sit_pred|, construct edges for all segments
  152.       // in the bundle, assign information |nil| to continuing segments,
  153.       // and delete ending segments from the Y_structure
  154.       do { SEGMENT s = Y_structure.key(sit);
  155.            G.new_edge(last_node[s], v, original[s]);
  156.        last_node[s] = v;
  157.            if ( identical(p_sweep,s.end()) )  // ending segment
  158.          { seq_item it = Y_structure.pred(sit);
  159.                Y_structure.del_item(sit);
  160.                sit = it; 
  161.               }
  162.            else                               // passing segment
  163.              { Y_structure.change_inf(sit,nil);
  164.                sit = Y_structure.pred(sit); 
  165.               }
  166.           } while (Y_structure.inf(sit) == event);
  167.        sit_pred  = sit;
  168.        sit_first = Y_structure.succ(sit_pred);
  169.        // reverse the bundle of continuing segments (if existing)
  170.        if (sit_first != sit_succ)
  171.        { sit_last = Y_structure.pred(sit_succ);
  172.          Y_structure.reverse_items(sit_first,sit_last);
  173.         }
  174.     }
  175.     // insert all segments starting at |p_sweep|
  176.     while ( identical(p_sweep,next_seg.start()) )
  177.     {
  178.       // insert |next_seg| into the Y-structure and associate the
  179.       // corresponding item with the right endpoint of |next_seg| in
  180.       // the X-structure (already present)
  181.       sit = Y_structure.locate(next_seg);
  182.       SEGMENT seg0 = Y_structure.key(sit);
  183.       if (compare(next_seg, seg0) != 0)
  184.          { // |next_seg| is not collinear with seg0, insert it
  185.            sit = Y_structure.insert_at(sit, next_seg, nil);
  186.            X_structure.insert(next_seg.end(),sit);
  187.            last_node[next_seg] = v;
  188.            if (sit_succ == nil)  
  189.            { // there are only starting segments, compute |sit_succ| 
  190.              // and |sit_pred| using the first inserted segment
  191.            sit_succ = Y_structure.succ(sit);
  192.            sit_pred = Y_structure.pred(sit);
  193.              sit_first = sit_succ;
  194.             }
  195.          }
  196.       else 
  197.         { // |next_seg| and |seg0| are collinear; if |next_seg| is
  198.           // longer insert |(seg0.end(),next_seg.end())| into |seg_queue|
  199.           POINT p = seg0.end();
  200.           POINT q = next_seg.end();
  201.         if (compare(p,q) < 0) seg_queue.insert(p,SEGMENT(p,q));
  202.          }
  203.       // delete minimum and assign new minimum to |next_seg|
  204.       seg_queue.del_min();
  205.       next_seg = seg_queue.inf(seg_queue.find_min());
  206.      }
  207.     // if |sit_pred| still has the value |nil|, there were no ending, 
  208.     // passing or starting segments, i.e., |p_sweep| is an isolated 
  209.     // point. In this case we are done, otherwise we delete the event 
  210.     // associated with |sit_pred| from the X-structure and compute 
  211.     // possible intersections between new neighbors.
  212.     if (sit_pred != nil) 
  213.     {
  214.       // |sit_pred| is no longer adjacent to its former successor we 
  215.       // change its intersection event to |nil| 
  216.       seq_item xit = Y_structure.inf(sit_pred);
  217.       if (xit != nil) 
  218.       { SEGMENT s1 = Y_structure.key(sit_pred);
  219.         SEGMENT s2 = Y_structure.key(sit_first);
  220.         inter_dic.insert(pair(s1,s2),xit);
  221.         Y_structure.change_inf(sit_pred, nil);
  222.        }
  223.       // compute possible intersections between |sit_pred| and its
  224.       // successor and |sit_succ| and its predecessor
  225.       compute_intersection(X_structure, Y_structure, inter_dic, sit_pred);
  226.       sit = Y_structure.pred(sit_succ);
  227.       if (sit != sit_pred)
  228.   compute_intersection(X_structure, Y_structure, inter_dic, sit);
  229.      }
  230.     // finally we delete the current event from the X-structure
  231.     X_structure.del_item(event);
  232.   }
  233. }