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

MultiPlatform

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