sweep0.tmp
资源名称:leda.tar.gz [点击查看]
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:9k
源码类别:
数值算法/人工智能
开发平台:
MultiPlatform
- // global variables
- static POINT p_sweep;
- // geometric primitives
- inline int compare(const SEGMENT& s1, const SEGMENT& s2)
- {
- // Precondition: |p_sweep| is identical to the left endpoint of
- // either |s1| or |s2|. This is true since comparisons are only
- // executed when inserting or looking up new segments.
- if ( identical(p_sweep,s1.start()) )
- { int s = orientation(s2,p_sweep);
- return (s != 0) ? -s : cmp_slopes(s1,s2);
- }
- if ( identical(p_sweep,s2.start()) )
- { int s = orientation(s1,p_sweep);
- return (s != 0) ? s : cmp_slopes(s1,s2);
- }
- error_handler(1,"internal error in sweep");
- return 0; // never reached
- }
- static void compute_intersection(sortseq<POINT,seq_item>& X_structure,
- sortseq<SEGMENT,seq_item>& Y_structure,
- seq_item sit0)
- {
- // Given an item |sit0| in the Y-structure compute the point of
- // intersection with its successor and (if existing) insert it into
- // the event queue and do all necessary updates.
- seq_item sit1 = Y_structure.succ(sit0);
- SEGMENT s0 = Y_structure.key(sit0);
- SEGMENT s1 = Y_structure.key(sit1);
- POINT q;
- // |s1| is the successor of |s0| in the Y-structure, hence,
- // |s0| and |s1| intersect right or above of the sweep line
- // iff |(s0.start(),s0.end(),s1.end()| is not a left turn and
- // |(s1.start(),s1.end(),s0.end()| is not a right turn.
- // In this case we intersect the underlying lines
- if (orientation(s0,s1.end()) >= 0 && orientation(s1,s0.end()) <=0 )
- { s0.intersection_of_lines(s1,q);
- Y_structure.change_inf(sit0, X_structure.insert(q,sit0));
- }
- }
- void sweep(const list<SEGMENT>& S, GRAPH<POINT,SEGMENT>& G)
- {
- // we use two sorted sequences ...
- sortseq <POINT,seq_item> X_structure;
- sortseq <SEGMENT,seq_item> Y_structure;
- // two maps ...
- map<SEGMENT,node> last_node(nil);
- map<SEGMENT,SEGMENT> original;
- // and a priority queue of segments ordered by their left endpoints
- p_queue<POINT,SEGMENT> seg_queue;
- /* INITIALIZATION
- - clear the output graph.
- - compute an upper bound |Infinity| for the input coordinates
- - make copies of the input segments such that all segments are
- oriented from left to right or from bottom to top.
- - insert all endpoints of the new segments into the X-structure
- - exploit the fact that insert operations into the X-structure
- leave previously inserted points unchanged to achieve that
- any pair of endpoints $p$ and $q$ with |p == q| are identical
- - use a map to associate with every segment its original
- - for every created segment $(p,q)$ insert the pair $(p,(p,q))$
- into priority queue |seg_queue|
- */
- G.clear();
- numtype Infinity = 1;
- SEGMENT s,s1;
- forall(s,S)
- {
- while (fabs(s.xcoord1())>=Infinity || fabs(s.ycoord1())>=Infinity ||
- fabs(s.xcoord2())>=Infinity || fabs(s.ycoord2())>=Infinity)
- Infinity *= 2;
- seq_item it1 = X_structure.insert(s.start(), nil);
- seq_item it2 = X_structure.insert(s.end(), nil);
- if (it1 == it2) continue; // ignore zero-length segments
- POINT p = X_structure.key(it1);
- POINT q = X_structure.key(it2);
- s1 = (compare(p,q) < 0) ? SEGMENT(p,q) : SEGMENT(q,p);
- original[s1] = s;
- seg_queue.insert(s1.start(),s1);
- }
- // insert a lower and an upper sentinel segment to avoid special
- // cases when traversing the Y-structure
- SEGMENT lower_sentinel(-Infinity, -Infinity, Infinity, -Infinity);
- SEGMENT upper_sentinel(-Infinity, Infinity, Infinity, Infinity);
- // the sweep begins at the lower left corner
- p_sweep = lower_sentinel.start();
- Y_structure.insert(upper_sentinel,nil);
- Y_structure.insert(lower_sentinel,nil);
- // insert a stopper into |seg_queue| and initialize |next_seg| with
- // the first segment in the queue
- POINT pstop(Infinity,Infinity);
- seg_queue.insert(pstop,SEGMENT(pstop,pstop));
- SEGMENT next_seg = seg_queue.inf(seg_queue.find_min());
- // Main Loop
- while (!X_structure.empty())
- {
- // move |p_sweep| to next event point and insert a new node
- // into the output graph G
- seq_item event = X_structure.min();
- p_sweep = X_structure.key(event);
- node v = G.new_node(p_sweep);
- // If there is a non-nil item |sit| associated with |event|,
- // |key(sit)| is either an ending or passing segment.
- // We use |sit| as an entry point to compute the bundle of
- // segments ending at or passing through |p_sweep|.
- // In particular, we compute the first (sit_first)| and last
- // (|sit_last|) item of this bundle and the successor (|sit_succ)|)
- // and predecessor (|sit_pred|) items.
- seq_item sit = X_structure.inf(event);
- if (sit == nil)
- { // here we do not know any segments ending or passing through
- // |p_sweep|. However, |p_sweep| could come to lie on a segment
- // inserted before. To check this we look up the zero length
- // segment |(p_sweep,p_sweep)|.
- sit = Y_structure.lookup(SEGMENT(p_sweep,p_sweep));
- }
- seq_item sit_succ = nil;
- seq_item sit_pred = nil;
- // A value of |nil| for |sit_succ| and |sit_pred| after the
- // following computation indicates that there are no segments
- // ending at or passing through |p_sweep|
- if (sit != nil) // key(sit) is an ending or passing segment
- {
- // first walk up until |sit_succ|
- while (Y_structure.inf(sit) == event) sit = Y_structure.succ(sit);
- sit_succ = Y_structure.succ(sit);
- // walk down until |sit_pred|, construct edges for all segments
- // in the bundle, assign information |nil| to continuing segments,
- // and delete ending segments from the Y_structure
- do { SEGMENT s = Y_structure.key(sit);
- G.new_edge(last_node[s], v, original[s]);
- last_node[s] = v;
- if ( identical(p_sweep,s.end()) ) // ending segment
- { seq_item it = Y_structure.pred(sit);
- Y_structure.del_item(sit);
- sit = it;
- }
- else // passing segment
- { Y_structure.change_inf(sit,nil);
- sit = Y_structure.pred(sit);
- }
- } while (Y_structure.inf(sit) == event);
- sit_pred = sit;
- // reverse the bundle of continuing segments (if existing)
- seq_item sit_first = Y_structure.succ(sit_pred);
- if (sit_first != sit_succ)
- { seq_item sit_last = Y_structure.pred(sit_succ);
- Y_structure.reverse_items(sit_first,sit_last);
- }
- }
- // insert all segments starting at |p_sweep|
- while ( identical(p_sweep,next_seg.start()) )
- {
- // insert |next_seg| into the Y-structure and associate the
- // corresponding item with the right endpoint of |next_seg| in
- // the X-structure (already present)
- sit = Y_structure.locate(next_seg);
- SEGMENT seg0 = Y_structure.key(sit);
- if (compare(next_seg, seg0) != 0)
- { // |next_seg| is not collinear with seg0, insert it
- sit = Y_structure.insert_at(sit, next_seg, nil);
- X_structure.insert(next_seg.end(),sit);
- last_node[next_seg] = v;
- if (sit_succ == nil)
- { // there are only starting segments, compute |sit_succ|
- // and |sit_pred| using the first inserted segment
- sit_succ = Y_structure.succ(sit);
- sit_pred = Y_structure.pred(sit);
- }
- }
- else
- { // |next_seg| and |seg0| are collinear; if |next_seg| is
- // longer insert |(seg0.end(),next_seg.end())| into |seg_queue|
- POINT p = seg0.end();
- POINT q = next_seg.end();
- if (compare(p,q) < 0) seg_queue.insert(p,SEGMENT(p,q));
- }
- // delete minimum and assign new minimum to |next_seg|
- seg_queue.del_min();
- next_seg = seg_queue.inf(seg_queue.find_min());
- }
- // if |sit_pred| still has the value |nil|, there were no ending,
- // passing or starting segments, i.e., |p_sweep| is an isolated
- // point. In this case we are done, otherwise we delete the event
- // associated with |sit_pred| from the X-structure and compute
- // possible intersections between new neighbors.
- if (sit_pred != nil)
- {
- // |sit_pred| is no longer adjacent to its former successor we
- // change its intersection event to |nil|
- Y_structure.change_inf(sit_pred, nil);
- // compute possible intersections between |sit_pred| and its
- // successor and |sit_succ| and its predecessor
- compute_intersection(X_structure, Y_structure, sit_pred);
- sit = Y_structure.pred(sit_succ);
- if (sit != sit_pred)
- compute_intersection(X_structure, Y_structure, sit);
- }
- // finally we delete the current event from the X-structure
- X_structure.del_item(event);
- }
- }