sweep0.c
Upload User: gzelex
Upload Date: 2007-01-07
Package Size: 707k
Code Size: 16k
Development Platform:

MultiPlatform

  1. /* This file has been automatically generated from "sweep.w"
  2.    by CTANGLE (Version 3.1 [km2c]) */
  3. #include <LEDA/sortseq.h>
  4. #include <LEDA/graph.h>
  5. #include <LEDA/rat_point.h>
  6. #include <LEDA/rat_segment.h>
  7. #include <LEDA/integer.h>
  8. #include <LEDA/floatf.h>
  9. #include <math.h>
  10. typedef rat_point POINT;
  11. typedef rat_segment SEGMENT;
  12. extern int cmp_points_count;
  13. extern int exact_cmp_points_count;
  14. class MyPointRep;
  15. static MyPointRep *first_myPoint = 0;
  16. struct MyPointRep {
  17.   POINT pt;
  18.   floatf x;
  19.   floatf y;
  20.   floatf w;
  21.   int count;
  22.   MyPointRep *next;
  23.    MyPointRep(const POINT & p) {
  24.     pt = p;
  25.     x = floatf(p.X());
  26.     y = floatf(p.Y());
  27.     w = floatf(p.W());
  28.     count = 0;
  29.     next = first_myPoint;
  30.     first_myPoint = this;
  31.   }
  32.    LEDA_MEMORY(MyPointRep)
  33. };
  34. typedef MyPointRep *myPoint;
  35. struct MySegmentRep {
  36.   myPoint start;
  37.   myPoint end;
  38.   SEGMENT seg;
  39.   floatf dx;
  40.   floatf dy;
  41.   node last_node;
  42.    MySegmentRep(const SEGMENT & s) {
  43.     start = new MyPointRep(s.start());
  44.     end = new MyPointRep(s.end());
  45.     seg = s;
  46.     dx = floatf(s.dx());
  47.     dy = floatf(s.dy());
  48.     last_node = nil;
  49.   }
  50.    MySegmentRep(const myPoint & p) { /* creates the zero-length segment
  51.  * $(p,p)$ */
  52.     start = p;
  53.     end = p;
  54.     seg = SEGMENT(p->pt, p->pt);
  55.     last_node = nil;
  56.   }
  57.   LEDA_MEMORY(MySegmentRep)
  58. };
  59. typedef MySegmentRep *mySegment;
  60. static integer Infinity;
  61. static myPoint p_sweep;
  62. static bool use_filter;
  63. int cmp_points_count = 0;
  64. int exact_cmp_points_count = 0 ;
  65. #if defined(STATISTICS)
  66. int cmp_points_failed;
  67. int cmp_segments_count;
  68. int exact_cmp_segments_count;
  69. #endif
  70. /*
  71. template <class int_type> inline
  72. int cmp_points(const int_type& x1, const int_type& y1, const int_type& w1,
  73.                const int_type& x2, const int_type& y2, const int_type& w2)
  74. {
  75.   int s = Sign(x1*w2-x2*w1);
  76.   return (s != 0) ? s : Sign(y1*w2-y2*w1);
  77.  }
  78. */
  79. inline int cmp_points(const integer & x1, const integer & y1, const integer & w1,
  80.    const integer & x2, const integer & y2, const integer & w2)
  81. {
  82.   cmp_points_count++;
  83.   exact_cmp_points_count++;
  84.   int s1 = sign(x1) * sign(w2);
  85.   int s2 = sign(x2) * sign(w1);
  86.   if (s1 > s2)
  87.     return +1;
  88.   if (s1 < s2)
  89.     return -1;
  90.   int l1 = x1.length() + w2.length();
  91.   int l2 = x2.length() + w1.length();
  92.   if (l1 > l2 + 1)
  93.     return s1;
  94.   if (l2 > l1 + 1)
  95.     return -s1;
  96. /*
  97.   int s = cmp_products(x1,w2,x2,w1);
  98.   return (s != 0) ? s : cmp_products(y1,w2,y2,w1);
  99. */
  100.   int s = compare(x1 * w2, x2 * w1);
  101.   return (s != 0) ? s : compare(y1 * w2, y2 * w1);
  102. }
  103. inline int cmp_points(const floatf & x1, const floatf & y1, const floatf & w1,
  104.    const floatf & x2, const floatf & y2, const floatf & w2)
  105. {
  106.   cmp_points_count++;
  107.   int s = Sign(x1 * w2 - x2 * w1);
  108.   return (s != 0) ? s : Sign(y1 * w2 - y2 * w1);
  109. }
  110. inline int cmp_points(const double &x1, const double &y1, const double &w1,
  111.    const double &x2, const double &y2, const double &w2)
  112. {
  113.   int s = Sign(x1 * w2 - x2 * w1);
  114.   return (s != 0) ? s : Sign(y1 * w2 - y2 * w1);
  115. }
  116. template < class int_type >
  117. int cmp_segments(const int_type & px, const int_type & py, const int_type & pw,
  118.    const int_type & spx, const int_type & spy, const int_type & spw,
  119.    const int_type & sqx, const int_type & sqy, const int_type & sqw,
  120.    const int_type & rx, const int_type & ry, const int_type & rw,
  121.    const int_type & dx, const int_type & dy,
  122.    const int_type & sdx, const int_type & sdy)
  123. {
  124. /*
  125.     We first test whether the underlying lines are identical. The lines are
  126.     identical if the three slopes $dy/dx$, $sdy/sdx$, and $mdy/mdx$ are equal
  127.   */
  128.   int_type T1 = dy * sdx - sdy * dx;
  129.   int sign1 = Sign(T1);
  130.   if (sign1 == 0 || sign1 == NO_IDEA) {
  131.     int_type mdx = sqx * pw - px * sqw;
  132.     int_type mdy = sqy * pw - py * sqw;
  133.     int sign2 = Sign(dy * mdx - mdy * dx);
  134.     if (sign2 == 0 || sign2 == NO_IDEA) {
  135.       int sign3 = Sign(sdy * mdx - mdy * sdx);
  136.       if (sign3 == 0 || sign3 == NO_IDEA)
  137. return (sign1 == 0 && sign2 == 0 && sign3 == 0) ? 0 : NO_IDEA;
  138.     }
  139.   }
  140. /* The underlying lines are different; in particular, at most one of the
  141.       lines is vertical. We first deal with the cases that one of the lines
  142.       is vertical. A segment $(p,q)$ is vertical iff $px*qw-qx*pw$ is equal
  143.       to zero. Since |dx| is an optimal floating point approximation
  144.       of this integer value, a segment is vertical iff its |dx|-value is zero.
  145.     */
  146.   if (dx == 0) { /* |dx| = 0, i.e., |s1| is vertical and |s2|
  147.  * is not vertical; $l cap s2$ is above
  148.  * |p_sweep| iff $(spy/spw + sdy/sdx(rx/rw -
  149.  * spx/spw) -ry/rw) > 0$; in this case we
  150.  * return $-1$ */
  151.     int i = Sign((spy * sdx - spx * sdy) * rw + (sdy * rx - ry * sdx) * spw);
  152.     if (i == NO_IDEA)
  153.       return NO_IDEA;
  154.     return (i <= 0) ? 1 : -1;
  155.   }
  156.   if (sdx == 0) { /* $sdx = 0$, i.e., |s2| is vertical but |s1|
  157.  * is not vertical; we return -1 if $l cap
  158.  * s1$ is below or equal to |p_sweep| iff
  159.  * $(py/pw + dy/dx(rx/rw - px/pw)-ry/rw) leq
  160.  * 0$. */
  161.     int i = Sign((py * dx - px * dy) * rw + (dy * rx - ry * dx) * pw);
  162.     if (i == NO_IDEA)
  163.       return NO_IDEA;
  164.     return (i <= 0) ? -1 : 1;
  165.   }
  166. /* Neither |s1| nor |s2| is vertical. We compare $l cap s1$ and $ l cap s2$.
  167.      We have $$ y(l cap s1) -y(l cap s2) =
  168.      frac{py}{pw} +frac{dy}{dx}(frac{rx}{rw} -frac{px}{pw}) -frac{spy}{spw}
  169.      - frac{sdy}{sdx}(frac{rx}{rw} - frac{spx}{spw}). $$
  170.      If the difference is non-zero then we return its sign. If the difference is
  171.      zero then we return $-1$ iff the common intersection is not above
  172.      |p_sweep| and $s1$ has the smaller slope or the intersection is above
  173.      |p_sweep| and $s1$ has the larger slope.
  174.   */
  175.   int_type T2 = sdx * spw * (py * dx * rw + dy * (rx * pw - px * rw))
  176.   - dx * pw * (spy * sdx * rw + sdy * (rx * spw - spx * rw));
  177.   int sign2 = Sign(T2);
  178.   if (sign2 == NO_IDEA)
  179.     return NO_IDEA;
  180.   if (sign2 != 0)
  181.     return sign2;
  182. /* Now we know that the difference is zero, i.e., |s1| and |s2|
  183.      intersect in a point $I$. We compare slopes:\
  184.      |s1| has larger slope than |s2| iff |T1*dxs*dx > 0|;
  185.      note that orienting the lines from left to right makes all |dx|
  186.      values non-negative , i.e.,
  187.      |s1| has larger slope than |s2| iff |sign(T1) = 1|
  188.    */
  189.   int_type T3 = (py * dx - px * dy) * rw + (dy * rx - ry * dx) * pw;
  190. /* The common intersection $I$ is above |p_sweep| iff $T3*rw*dx*pw > 0$.
  191.      In this case we return |-sign(T1)| and |sign(T1)| otherwise.
  192.      Note that all |dx| and |w| values are non-negative
  193.      i.e., |sign(T3*rw*dx*pw) = sign(T3)|
  194.    */
  195.   int sign3 = Sign(T3);
  196.   if (sign3 == NO_IDEA)
  197.     return NO_IDEA;
  198.   return (sign3 <= 0) ? sign1 : -sign1;
  199. }
  200. inline int compare(const myPoint & a, const myPoint & b)
  201. {
  202. /* floating point filter version for |myPoint|s */
  203.   int c = NO_IDEA;
  204. /* if not explicitely turned off we first use floating point arithmetic */
  205.   if (use_filter)
  206.     c = cmp_points(a->x, a->y, a->w, b->x, b->y, b->w);
  207. /* if the floating point computation is not reliable, i.e., the result
  208.     is |NO_IDEA| we use exact arithmetic (|integer|)
  209.   */
  210.   if (c == NO_IDEA) {
  211.     c = cmp_points(a->pt.X(), a->pt.Y(), a->pt.W(), b->pt.X(), b->pt.Y(), b->pt.W());
  212. #if defined(STATISTICS)
  213.     if (cmp_points(double (a->x), double (a->y), double (a->w),
  214. double (b->x), double (b->y), double (b->w)) !=c)
  215.       cmp_points_failed++;
  216. #endif
  217.   }
  218.   return c;
  219. }
  220. inline int compare(const mySegment & s1, const mySegment & s2)
  221. {
  222.   int c = NO_IDEA;
  223. /* if not explicitely turned off we first try the
  224.      floating point computation
  225.    */
  226. #if defined(STATISTICS)
  227.   cmp_segments_count++;
  228. #endif
  229.   if (use_filter)
  230.     c = cmp_segments(s1->start->x, s1->start->y, s1->start->w,
  231.       s2->start->x, s2->start->y, s2->start->w,
  232.       s2->end->x, s2->end->y, s2->end->w,
  233.       p_sweep->x, p_sweep->y, p_sweep->w,
  234.       s1->dx, s1->dy, s2->dx, s2->dy);
  235. /* If the result is not reliable  we call the exact compare
  236.      for the underlying |SEGMENT|s.
  237.    */
  238.   if (c == NO_IDEA) {
  239.     c = cmp_segments(s1->seg.X1(), s1->seg.Y1(), s1->seg.W1(),
  240.       s2->seg.X1(), s2->seg.Y1(), s2->seg.W1(),
  241.       s2->seg.X2(), s2->seg.Y2(), s2->seg.W2(),
  242.       p_sweep->pt.X(), p_sweep->pt.Y(), p_sweep->pt.W(),
  243.       s1->seg.dx(), s1->seg.dy(), s2->seg.dx(), s2->seg.dy());
  244. #if defined(STATISTICS)
  245.     exact_cmp_segments_count++;
  246. #endif
  247.   }
  248.   return c;
  249. }
  250. int cmp_mySeg(const mySegment & s1, const mySegment & s2)
  251. {
  252.   int c = NO_IDEA;
  253.   if (use_filter) /* floating point compare */
  254.     c = cmp_points(s1->start->x, s1->start->y, s1->start->w,
  255.       s2->start->x, s2->start->y, s2->start->w);
  256.   if (c == NO_IDEA) /* exact compare */
  257.     c = cmp_points(s1->seg.X1(), s1->seg.Y1(), s1->seg.W1(),
  258.       s2->seg.X1(), s2->seg.Y1(), s2->seg.W1());
  259.   return c;
  260. }
  261. void compute_intersection(sortseq <myPoint, seq_item >&X_structure,
  262.    sortseq <mySegment, seq_item >&Y_structure,
  263.    seq_item sit0)
  264. {
  265.   seq_item sit1 = Y_structure.succ(sit0);
  266.   mySegment seg0 = Y_structure.key(sit0);
  267.   mySegment seg1 = Y_structure.key(sit1);
  268. /* |seg1| is the successor of |seg0| in the Y-structure, hence,
  269.      the underlying lines intersect right or above of the sweep line
  270.      iff the slope of |seg0| is larger than the slope of |seg1|.
  271.    */
  272.   if (use_filter) {
  273.     int i = Sign(seg0->dy * seg1->dx - seg1->dy * seg0->dx);
  274.     if (i == -1 || i == 0)
  275.       return; /* $slope(s0)leq slope(s1)$ */
  276.   }
  277.   SEGMENT s0 = seg0->seg;
  278.   SEGMENT s1 = seg1->seg;
  279.   integer w = s0.dy() * s1.dx() - s1.dy() * s0.dx();
  280.   if (sign(w) > 0) { /* $slope(s0) > slope(s1)$ */
  281.     integer c1 = s0.X2() * s0.Y1() - s0.X1() * s0.Y2();
  282.     integer c2 = s1.X2() * s1.Y1() - s1.X1() * s1.Y2();
  283. /* The underlying lines intersect in a point right or above of the
  284.        sweep line. We still have to test whether it lies on both segments.
  285.      */
  286.     integer x = c2 * s0.dx() - c1 * s1.dx();
  287.     integer d0 = x * s0.W2() - s0.X2() * w;
  288.     if (sign(d0) > 0)
  289.       return;
  290.     if (x * s1.W2() > s1.X2() * w)
  291.       return;
  292.     integer y = c2 * s0.dy() - c1 * s1.dy();
  293.     if (sign(d0) == 0 && y * s0.W2() > s0.Y2() * w)
  294.       return;
  295.     myPoint Q = new MyPointRep(POINT(x, y, w));
  296.     seq_item xit = X_structure.insert(Q, sit0);
  297.     X_structure.key(xit)->count++;
  298.     Y_structure.change_inf(sit0, xit);
  299.   }
  300. }
  301. void sweep0(list <SEGMENT > &S, GRAPH <POINT, SEGMENT > &G, bool use_filter)
  302. {
  303.   sortseq <myPoint, seq_item >X_structure;
  304.   sortseq <mySegment, seq_item >Y_structure;
  305. cmp_points_count = 0;
  306. exact_cmp_points_count = 0;
  307. #if defined(STATISTICS)
  308.   cmp_points_failed = 0;
  309.   cmp_segments_count = 0;
  310.   exact_cmp_segments_count = 0;
  311. #endif
  312.   ::use_filter = use_filter;
  313. /* compute an upper bound |Infinity| for the input coordinates */
  314.   Infinity = 1;
  315.   SEGMENT s;
  316.   forall (s, S)
  317.     while (abs(s.X1()) >= Infinity || abs(s.Y1()) >= Infinity ||
  318.       abs(s.X2()) >= Infinity || abs(s.Y2()) >= Infinity)
  319.       Infinity *= 2;
  320.   p_sweep = new MyPointRep(POINT(-Infinity, -Infinity));
  321.   mySegment uppersentinel =
  322.   new MySegmentRep(SEGMENT(-Infinity, Infinity, Infinity, Infinity));
  323.   mySegment lowersentinel =
  324.   new MySegmentRep(SEGMENT(-Infinity, -Infinity, Infinity, -Infinity));
  325.   Y_structure.insert(uppersentinel, nil);
  326.   Y_structure.insert(lowersentinel, nil);
  327.   G.clear();
  328.   list <mySegment > S_Sorted;
  329.   forall (s, S) {
  330. /* |mySegment|s are always oriented from left to right or (if vertical)
  331.      from bottom to top
  332.    */
  333.     if (compare(s.start(),s.end()) > 0) 
  334.       s = SEGMENT(s.end(), s.start());
  335.     mySegment s1 = new MySegmentRep(s);
  336.     S_Sorted.append(s1);
  337.     seq_item it = X_structure.insert(s1->start, nil);
  338.     s1->start = X_structure.key(it);
  339.     s1->start->count++;
  340.   }
  341.   S_Sorted.sort(cmp_mySeg);
  342.   while (!X_structure.empty()) {
  343.     seq_item event = X_structure.min();
  344.     seq_item sit = X_structure.inf(event);
  345.     myPoint p = X_structure.key(event);
  346.     node v = G.new_node(p->pt);
  347.     p_sweep = p;
  348.     seq_item sit_succ = nil;
  349.     seq_item sit_pred = nil;
  350.     if (sit == nil) {
  351.       MySegmentRep s(p); /* create a zero length segment $s = (p,p)$ */
  352.       sit = Y_structure.lookup(&s);
  353.     }
  354.     if (sit != nil) {
  355.       seq_item sit_last = sit;
  356.       while (Y_structure.inf(sit_last) == event)
  357. sit_last = Y_structure.succ(sit_last);
  358.       sit_succ = Y_structure.succ(sit_last);
  359.       sit_pred = Y_structure.pred(sit);
  360.       while (Y_structure.inf(sit_pred) == event)
  361. sit_pred = Y_structure.pred(sit_pred);
  362.       seq_item sit_first = Y_structure.succ(sit_pred);
  363.       seq_item i1 = sit_pred;
  364.       seq_item i2 = sit_first;
  365.       while (i2 != sit_succ) {
  366. mySegment s = Y_structure.key(i2);
  367. G.new_edge(s->last_node, v, s->seg);
  368. s->last_node = v;
  369. if (p == s->end) { /* ending segment */
  370.   Y_structure.del_item(i2);
  371.   delete s;
  372. }
  373. else { /* continuing segment */
  374.   if (i2 != sit_last)
  375.     Y_structure.change_inf(i2, nil);
  376.   i1 = i2;
  377. }
  378. i2 = Y_structure.succ(i1);
  379.       }
  380.       sit_first = Y_structure.succ(sit_pred);
  381.       sit_last = Y_structure.pred(sit_succ);
  382.       seq_item xit = Y_structure.inf(sit_pred);
  383.       if (xit != nil) {
  384. if (--X_structure.key(xit)->count == 0)
  385.   X_structure.del_item(xit);
  386. Y_structure.change_inf(sit_pred, nil);
  387.       }
  388.       if (sit_last != sit_pred) {
  389. xit = Y_structure.inf(sit_last);
  390. if (xit != nil) {
  391.   if (--X_structure.key(xit)->count == 0)
  392.     X_structure.del_item(xit);
  393.   Y_structure.change_inf(sit_last, nil);
  394. }
  395. Y_structure.reverse_items(sit_first, sit_last);
  396.       }
  397.     }
  398.     while (!S_Sorted.empty() && p == S_Sorted.head()->start) {
  399.       mySegment Seg = S_Sorted.pop();
  400. /* first insert the right endpoint of |Seg| into the X-structure */
  401.       seq_item end_it = X_structure.insert(Seg->end, nil);
  402.       Seg->end = X_structure.key(end_it);
  403.       Seg->end->count++;
  404. /* note that the following test uses the fact that two endpoints are equal
  405.      if an only if the corresponding pointer values (|myPoint|s) are equal
  406.    */
  407.       if (Seg->start == Seg->end) { /* Seg has length  zero, nothing to
  408.  * do */
  409. delete Seg;
  410. continue;
  411.       }
  412.       sit = Y_structure.locate(Seg);
  413.       if (compare(Seg, Y_structure.key(sit)) != 0) { /* |Seg| is not
  414.  * collinear with the
  415.  * segment associated
  416.  * with |sit|. We simply
  417.  * insert |Seg| into the
  418.  * Y-structure */
  419. sit = Y_structure.insert_at(sit, Seg, nil);
  420. Seg->last_node = v;
  421.       }
  422.       else { /* |Seg| is collinear with the segment
  423.  * associated with |sit|. If |Seg| is longer
  424.  * then we use |Seg| and otherwise we do
  425.  * nothing. */
  426. mySegment Seg_old = Y_structure.key(sit);
  427. if (compare(Seg->end, Seg_old->end) > 0) { /* |Seg| extends further
  428.  * to the right or above
  429.  * replace |Seg_old| by
  430.  * |Seg|.  */
  431.   Seg_old->seg = Seg->seg;
  432.   Seg_old->end = Seg->end;
  433. }
  434. delete Seg; /* not needed anymore */
  435.       }
  436.       X_structure.change_inf(end_it, sit);
  437.       if (sit_succ == nil) {
  438. sit_succ = Y_structure.succ(sit);
  439. sit_pred = Y_structure.pred(sit);
  440. /* |sit_pred| is no longer adjacent to |sit_succ| we have to
  441.         change its current intersection event to |nil| and delete
  442.         the corresponding item in the X-structure if necessary
  443.       */
  444. seq_item xit = Y_structure.inf(sit_pred);
  445. if (xit != nil) {
  446.   if (--X_structure.key(xit)->count == 0)
  447.     X_structure.del_item(xit);
  448.   Y_structure.change_inf(sit_pred, nil);
  449. }
  450.       }
  451.     }
  452. /* compute possible intersections */
  453.     if (sit_succ != nil) { /* |v| is an isolated vertex otherwise */
  454.       compute_intersection(X_structure, Y_structure, sit_pred);
  455.       sit = Y_structure.pred(sit_succ);
  456.       if (sit != sit_pred)
  457. compute_intersection(X_structure, Y_structure, sit);
  458.     }
  459.     X_structure.del_item(event);
  460.   }
  461.   {
  462.     delete(uppersentinel);
  463.     delete(lowersentinel);
  464.     myPoint p = first_myPoint;
  465.     while (first_myPoint != nil) {
  466.       p = first_myPoint->next;
  467.       delete(first_myPoint);
  468.       first_myPoint = p;
  469.     }
  470. #if defined(STATISTICS)
  471.     if (use_filter) {
  472.       cout << string ("compare points:  %6d / %4d (%5.2f%%)  (%5.2f%% failed)  ",
  473.  cmp_points_count, exact_cmp_points_count,
  474.  (100.0 * exact_cmp_points_count) / cmp_points_count,
  475.  (100.0 * cmp_points_failed) / cmp_points_count);
  476.       newline;
  477.       cout << string ("compare segments: %6d / %4d  (%5.2f%%)",
  478.  cmp_segments_count, exact_cmp_segments_count,
  479.  (100.0 * exact_cmp_segments_count) / cmp_segments_count);
  480.       newline;
  481.     }
  482. #endif
  483.   }
  484. }