|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r66595 - sandbox/SOC/2010/sweepline/boost/sweepline/detail
From: sydorchuk.andriy_at_[hidden]
Date: 2010-11-15 16:28:30
Author: asydorchuk
Date: 2010-11-15 16:28:29 EST (Mon, 15 Nov 2010)
New Revision: 66595
URL: http://svn.boost.org/trac/boost/changeset/66595
Log:
Changed pps, pss, sss circle event creation function.
Made simplification step epsilon robust for segment input data sets.
Changed output simplification to be epsilon robust.
Text files modified:
sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp | 470 +++++++++++++++++++++++++--------------
1 files changed, 303 insertions(+), 167 deletions(-)
Modified: sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp
==============================================================================
--- sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp (original)
+++ sandbox/SOC/2010/sweepline/boost/sweepline/detail/voronoi_formation.hpp 2010-11-15 16:28:29 EST (Mon, 15 Nov 2010)
@@ -259,24 +259,44 @@
circle_event() : is_active_(true) {}
- circle_event(coordinate_type c_x, coordinate_type c_y,
- coordinate_type lower_x) :
+ circle_event(coordinate_type c_x, coordinate_type c_y, coordinate_type lower_x) :
center_x_(c_x),
center_y_(c_y),
lower_x_(lower_x),
+ denom_(1),
is_active_(true) {}
- circle_event(coordinate_type c_x_pos, coordinate_type c_x_neg,
- coordinate_type c_y_pos, coordinate_type c_y_neg,
- coordinate_type lower_x_pos, coordinate_type lower_x_neg) :
- center_x_(c_x_pos, c_x_neg),
- center_y_(c_y_pos, c_y_neg),
- lower_x_(lower_x_pos, lower_x_neg),
+ circle_event(const epsilon_robust_comparator<T> &c_x,
+ const epsilon_robust_comparator<T> &c_y,
+ const epsilon_robust_comparator<T> &lower_x) :
+ center_x_(c_x),
+ center_y_(c_y),
+ lower_x_(lower_x),
+ denom_(1),
is_active_(true) {}
+ circle_event(const epsilon_robust_comparator<T> &c_x,
+ const epsilon_robust_comparator<T> &c_y,
+ const epsilon_robust_comparator<T> &lower_x,
+ const epsilon_robust_comparator<T> &denom) :
+ center_x_(c_x),
+ center_y_(c_y),
+ lower_x_(lower_x),
+ denom_(denom),
+ is_active_(true) {
+ if (denom_.abs()) {
+ center_x_.swap();
+ center_y_.swap();
+ lower_x_.swap();
+ }
+ }
+
bool operator==(const circle_event &c_event) const {
- return (center_y_.compare(c_event.center_y_) == UNDEFINED &&
- lower_x_.compare(c_event.lower_x_) == UNDEFINED);
+ epsilon_robust_comparator<T> &lhs1 = center_y_ * c_event.denom_;
+ epsilon_robust_comparator<T> &rhs1 = denom_ * c_event.center_y_;
+ epsilon_robust_comparator<T> &lhs2 = lower_x_ * c_event.denom_;
+ epsilon_robust_comparator<T> &rhs2 = denom_ * c_event.lower_x_;
+ return (lhs1.compare(rhs1) == UNDEFINED && lhs2.compare(rhs2) == UNDEFINED);
}
bool operator!=(const circle_event &c_event) const {
@@ -284,15 +304,14 @@
}
bool operator<(const circle_event &c_event) const {
- double dif1 = lower_x();
- double dif2 = c_event.lower_x();
- if (dif1 != dif2)
- return dif1 < dif2;
- return center_y_.get_dif() < c_event.get_erc_y().get_dif();
- /*kPredicateResult pres = lower_x_.compare(c_event.lower_x_, 64);
+ epsilon_robust_comparator<T> &lhs1 = lower_x_ * c_event.denom_;
+ epsilon_robust_comparator<T> &rhs1 = denom_ * c_event.lower_x_;
+ kPredicateResult pres = lhs1.compare(rhs1, 64);
if (pres != UNDEFINED)
return (pres == LESS);
- return (center_y_.compare(c_event.center_y_, 32) == LESS);*/
+ epsilon_robust_comparator<T> &lhs2 = center_y_ * c_event.denom_;
+ epsilon_robust_comparator<T> &rhs2 = denom_ * c_event.center_y_;
+ return (lhs2.compare(rhs2, 64) == LESS);
}
bool operator<=(const circle_event &c_event) const {
@@ -312,22 +331,22 @@
// If circle point is equal to site point return 0.
// If circle point is greater than site point return 1.
kPredicateResult compare(const site_event<coordinate_type> &s_event) const {
- kPredicateResult pres = lower_x_.compare(s_event.x());
+ kPredicateResult pres = lower_x_.compare(denom_ * s_event.x(), 64);
if (pres != UNDEFINED)
return pres;
- return center_y_.compare(s_event.y());
+ return center_y_.compare(denom_ * s_event.y(), 64);
}
coordinate_type x() const {
- return center_x_.get_dif();
+ return center_x_.dif() / denom_.dif();
}
coordinate_type y() const {
- return center_y_.get_dif();
+ return center_y_.dif() / denom_.dif();
}
coordinate_type lower_x() const {
- return lower_x_.get_dif();
+ return lower_x_.dif() / denom_.dif();
}
Point2D get_center() const {
@@ -342,6 +361,10 @@
return center_y_;
}
+ const epsilon_robust_comparator<T> &get_erc_denom() const {
+ return denom_;
+ }
+
void set_bisector(beach_line_iterator iterator) {
bisector_node_ = iterator;
}
@@ -362,6 +385,7 @@
epsilon_robust_comparator<T> center_x_;
epsilon_robust_comparator<T> center_y_;
epsilon_robust_comparator<T> lower_x_;
+ epsilon_robust_comparator<T> denom_;
beach_line_iterator bisector_node_;
bool is_active_;
};
@@ -616,18 +640,70 @@
positive_sum_(pos),
negative_sum_(neg) {}
- T get_dif() const {
+ T dif() const {
return positive_sum_ - negative_sum_;
}
- T get_positive_sum() const {
+ T pos() const {
return positive_sum_;
}
- T get_negative_sum() const {
+ T neg() const {
return negative_sum_;
}
+ void swap() {
+ (std::swap)(positive_sum_, negative_sum_);
+ }
+
+ bool abs() {
+ if (positive_sum_ < negative_sum_) {
+ swap();
+ return true;
+ }
+ return false;
+ }
+
+ epsilon_robust_comparator<T>& operator+=(const T& val) {
+ avoid_cancellation(val, positive_sum_, negative_sum_);
+ return *this;
+ }
+
+ epsilon_robust_comparator<T>& operator+=(const epsilon_robust_comparator<T>& erc) {
+ positive_sum_ += erc.positive_sum_;
+ negative_sum_ += erc.negative_sum_;
+ return *this;
+ }
+
+ epsilon_robust_comparator<T>& operator-=(const T& val) {
+ avoid_cancellation(val, negative_sum_, positive_sum_);
+ return *this;
+ }
+
+ epsilon_robust_comparator<T>& operator-=(const epsilon_robust_comparator<T>& erc) {
+ positive_sum_ += erc.negative_sum_;
+ negative_sum_ += erc.positive_sum_;
+ return *this;
+ }
+
+ epsilon_robust_comparator<T>& operator*=(const T& val) {
+ positive_sum_ *= fabs(val);
+ negative_sum_ *= fabs(val);
+ if (val < 0) {
+ swap();
+ }
+ return *this;
+ }
+
+ epsilon_robust_comparator<T>& operator/=(const T& val) {
+ positive_sum_ /= fabs(val);
+ negative_sum_ /= fabs(val);
+ if (val < 0) {
+ swap();
+ }
+ return *this;
+ }
+
kPredicateResult compare(T value, int ulp = 0) const {
T lhs = positive_sum_ - ((value < 0) ? value : 0);
T rhs = negative_sum_ + ((value > 0) ? value : 0);
@@ -637,8 +713,8 @@
}
kPredicateResult compare(const epsilon_robust_comparator &rc, int ulp = 0) const {
- T lhs = positive_sum_ + rc.get_negative_sum();
- T rhs = negative_sum_ + rc.get_positive_sum();
+ T lhs = positive_sum_ + rc.neg();
+ T rhs = negative_sum_ + rc.pos();
if (almost_equal(lhs, rhs, ulp))
return UNDEFINED;
return (lhs < rhs) ? LESS : MORE;
@@ -649,6 +725,42 @@
T negative_sum_;
};
+ template<typename T>
+ epsilon_robust_comparator<T> operator+(const epsilon_robust_comparator<T>& lhs,
+ const epsilon_robust_comparator<T>& rhs) {
+ return epsilon_robust_comparator<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg());
+ }
+
+ template<typename T>
+ epsilon_robust_comparator<T> operator-(const epsilon_robust_comparator<T>& lhs,
+ const epsilon_robust_comparator<T>& rhs) {
+ return epsilon_robust_comparator<T>(lhs.pos() - rhs.neg(), lhs.neg() + rhs.pos());
+ }
+
+ template<typename T>
+ epsilon_robust_comparator<T> operator*(const epsilon_robust_comparator<T>& lhs,
+ const epsilon_robust_comparator<T>& rhs) {
+ double res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
+ double res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
+ return epsilon_robust_comparator<T>(res_pos, res_neg);
+ }
+
+ template<typename T>
+ epsilon_robust_comparator<T> operator*(const epsilon_robust_comparator<T>& lhs,
+ const T& val) {
+ if (val >= 0)
+ return epsilon_robust_comparator<T>(lhs.pos() * val, lhs.neg() * val);
+ return epsilon_robust_comparator<T>(-lhs.neg() * val, -lhs.pos() * val);
+ }
+
+ template<typename T>
+ epsilon_robust_comparator<T> operator*(const T& val,
+ const epsilon_robust_comparator<T>& rhs) {
+ if (val >= 0)
+ return epsilon_robust_comparator<T>(val * rhs.pos(), val * rhs.neg());
+ return epsilon_robust_comparator<T>(-val * rhs.neg(), -val * rhs.pos());
+ }
+
// Returns true if horizontal line going through new site intersects
// right arc at first, else returns false. If horizontal line goes
// through intersection point of the given two arcs returns false also.
@@ -1028,43 +1140,35 @@
const site_event<T> &site2,
const site_event<T> &site3,
circle_event<T> &c_event) {
- double dif_x1 = static_cast<double>(site1.x()) - static_cast<double>(site2.x());
- double dif_x2 = static_cast<double>(site2.x()) - static_cast<double>(site3.x());
- double dif_y1 = static_cast<double>(site1.y()) - static_cast<double>(site2.y());
- double dif_y2 = static_cast<double>(site2.y()) - static_cast<double>(site3.y());
+ double dif_x1 = site1.x() - site2.x();
+ double dif_x2 = site2.x() - site3.x();
+ double dif_y1 = site1.y() - site2.y();
+ double dif_y2 = site2.y() - site3.y();
double orientation = robust_cross_product(dif_x1, dif_y1, dif_x2, dif_y2);
if (orientation_test(orientation) != RIGHT_ORIENTATION)
return false;
double inv_orientation = 0.5 / orientation;
- double sum_x1 = static_cast<double>(site1.x()) + static_cast<double>(site2.x());
- double sum_x2 = static_cast<double>(site2.x()) + static_cast<double>(site3.x());
- double sum_y1 = static_cast<double>(site1.y()) + static_cast<double>(site2.y());
- double sum_y2 = static_cast<double>(site2.y()) + static_cast<double>(site3.y());
- double dif_x3 = static_cast<double>(site1.x()) - static_cast<double>(site3.x());
- double dif_y3 = static_cast<double>(site1.y()) - static_cast<double>(site3.y());
- double c_x_pos, c_x_neg, c_y_pos, c_y_neg;
- c_x_pos = c_x_neg = c_y_pos = c_y_neg = 0;
- detail::avoid_cancellation(dif_x1 * sum_x1 * dif_y2, c_x_pos, c_x_neg);
- detail::avoid_cancellation(dif_y1 * sum_y1 * dif_y2, c_x_pos, c_x_neg);
- detail::avoid_cancellation(dif_x2 * sum_x2 * dif_y1, c_x_neg, c_x_pos);
- detail::avoid_cancellation(dif_y2 * sum_y2 * dif_y1, c_x_neg, c_x_pos);
- detail::avoid_cancellation(dif_x2 * sum_x2 * dif_x1, c_y_pos, c_y_neg);
- detail::avoid_cancellation(dif_y2 * sum_y2 * dif_x1, c_y_pos, c_y_neg);
- detail::avoid_cancellation(dif_x1 * sum_x1 * dif_x2, c_y_neg, c_y_pos);
- detail::avoid_cancellation(dif_y1 * sum_y1 * dif_x2, c_y_neg, c_y_pos);
- if (orientation < 0) {
- (std::swap)(c_x_pos, c_x_neg);
- (std::swap)(c_y_pos, c_y_neg);
- inv_orientation = -inv_orientation;
- }
- c_x_pos *= inv_orientation;
- c_x_neg *= inv_orientation;
- c_y_pos *= inv_orientation;
- c_y_neg *= inv_orientation;
- double radius = sqrt(get_sqr_distance(dif_x1, dif_y1) * get_sqr_distance(dif_x2, dif_y2) *
- get_sqr_distance(dif_x3, dif_y3)) * fabs(inv_orientation);
- c_event = circle_event<double>(c_x_pos, c_x_neg, c_y_pos, c_y_neg,
- c_x_pos + radius, c_x_neg);
+ double sum_x1 = site1.x() + site2.x();
+ double sum_x2 = site2.x() + site3.x();
+ double sum_y1 = site1.y() + site2.y();
+ double sum_y2 = site2.y() + site3.y();
+ double dif_x3 = site1.x() - site3.x();
+ double dif_y3 = site1.y() - site3.y();
+ epsilon_robust_comparator<T> c_x, c_y;
+ c_x += dif_x1 * sum_x1 * dif_y2;
+ c_x += dif_y1 * sum_y1 * dif_y2;
+ c_x -= dif_x2 * sum_x2 * dif_y1;
+ c_x -= dif_y2 * sum_y2 * dif_y1;
+ c_y += dif_x2 * sum_x2 * dif_x1;
+ c_y += dif_y2 * sum_y2 * dif_x1;
+ c_y -= dif_x1 * sum_x1 * dif_x2;
+ c_y -= dif_y1 * sum_y1 * dif_x2;
+ c_x *= inv_orientation;
+ c_y *= inv_orientation;
+ epsilon_robust_comparator<T> lower_x(c_x);
+ lower_x += sqrt(get_sqr_distance(dif_x1, dif_y1) * get_sqr_distance(dif_x2, dif_y2) *
+ get_sqr_distance(dif_x3, dif_y3)) * fabs(inv_orientation);
+ c_event = circle_event<double>(c_x, c_y, lower_x);
return true;
}
@@ -1083,10 +1187,8 @@
site2.get_point0()) != RIGHT_ORIENTATION)
return false;
} else {
- if (orientation_test(site1.get_point0(), site3.get_point0(),
- site2.get_point0()) != RIGHT_ORIENTATION &&
- detail::orientation_test(site1.get_point0(), site3.get_point1(),
- site2.get_point0()) != RIGHT_ORIENTATION)
+ if (site3.get_point0(true) == site1.get_point0() &&
+ site3.get_point1(true) == site2.get_point0())
return false;
}
@@ -1102,44 +1204,33 @@
site3.get_point1().y() - site2.y(),
site2.x() - site3.get_point1().x());
double denom = robust_cross_product(vec_x, vec_y, line_a, line_b);
- double t_pos, t_neg;
- t_pos = t_neg = 0;
+ double inv_segm_len = 1.0 / sqrt(get_sqr_distance(line_a, line_b));
+ epsilon_robust_comparator<double> t;
if (orientation_test(denom) == COLINEAR) {
- avoid_cancellation(teta / (4.0 * (A + B)), t_pos, t_neg);
- avoid_cancellation(A * B / (teta * (A + B)), t_neg, t_pos);
+ t += teta / (4.0 * (A + B));
+ t -= A * B / (teta * (A + B));
} else {
double det = sqrt((teta * teta + denom * denom) * A * B);
if (segment_index == 2) {
- t_neg += det / (denom * denom);
+ t -= det / (denom * denom);
} else {
- t_pos += det / (denom * denom);
+ t += det / (denom * denom);
}
- avoid_cancellation(teta * (A + B) / (2.0 * denom * denom), t_pos, t_neg);
+ t += teta * (A + B) / (2.0 * denom * denom);
}
- double c_x_pos, c_x_neg, c_y_pos, c_y_neg, lower_x_pos, lower_x_neg;
- c_x_pos = c_x_neg = c_y_pos = c_y_neg = lower_x_pos = lower_x_neg = 0;
- avoid_cancellation(0.5 * (site1.x() + site2.x()), c_x_pos, c_x_neg);
- avoid_cancellation(t_pos * vec_x, c_x_pos, c_x_neg);
- avoid_cancellation(t_neg * vec_x, c_x_neg, c_x_pos);
- avoid_cancellation(0.5 * (site1.y() + site2.y()), c_y_pos, c_y_neg);
- avoid_cancellation(t_pos * vec_y, c_y_pos, c_y_neg);
- avoid_cancellation(t_neg * vec_y, c_y_neg, c_y_pos);
-
- double inv_segm_len = 1.0 / sqrt(get_sqr_distance(line_a, line_b));
- double radius_pos, radius_neg;
- radius_pos = radius_neg = 0;
- avoid_cancellation(line_a * site3.get_point0().x(), radius_neg, radius_pos);
- avoid_cancellation(line_b * site3.get_point0().y(), radius_neg, radius_pos);
- avoid_cancellation(line_a * c_x_pos, radius_pos, radius_neg);
- avoid_cancellation(line_a * c_x_neg, radius_neg, radius_pos);
- avoid_cancellation(line_b * c_y_pos, radius_pos, radius_neg);
- avoid_cancellation(line_b * c_y_neg, radius_neg, radius_pos);
- if (radius_pos < radius_neg) {
- (std::swap)(radius_pos, radius_neg);
- }
- c_event = circle_event<double>(c_x_pos, c_x_neg, c_y_pos, c_y_neg,
- c_x_pos + inv_segm_len * radius_pos,
- c_x_neg + inv_segm_len * radius_neg);
+ epsilon_robust_comparator<double> c_x, c_y;
+ c_x += 0.5 * (site1.x() + site2.x());
+ c_x += t * vec_x;
+ c_y += 0.5 * (site1.y() + site2.y());
+ c_y += t * vec_y;
+ epsilon_robust_comparator<double> r, lower_x(c_x);
+ r -= line_a * site3.x0();
+ r -= line_b * site3.y0();
+ r += line_a * c_x;
+ r += line_b * c_y;
+ r.abs();
+ lower_x += r * inv_segm_len;
+ c_event = circle_event<double>(c_x, c_y, lower_x);
return true;
}
@@ -1177,57 +1268,83 @@
}
}
- double a1 = static_cast<double>(segm_end1.x() - segm_start1.x());
- double b1 = static_cast<double>(segm_end1.y() - segm_start1.y());
- double a2 = static_cast<double>(segm_end2.x() - segm_start2.x());
- double b2 = static_cast<double>(segm_end2.y() - segm_start2.y());
-
- kOrientation segm_orient = orientation_test(
- static_cast<long long>(a1), static_cast<long long>(b1),
- static_cast<long long>(a2), static_cast<long long>(b2));
-
- if (segm_orient == COLINEAR) {
+ double a1 = segm_end1.x() - segm_start1.x();
+ double b1 = segm_end1.y() - segm_start1.y();
+ double a2 = segm_end2.x() - segm_start2.x();
+ double b2 = segm_end2.y() - segm_start2.y();
+ double orientation = robust_cross_product(b1, a1, b2, a2);
+ if (orientation_test(orientation) == COLINEAR) {
double a = a1 * a1 + b1 * b1;
- double b = a1 * ((static_cast<double>(segm_start1.x()) +
- static_cast<double>(segm_start2.x())) * 0.5 -
- static_cast<double>(site1.x())) +
- b1 * ((static_cast<double>(segm_start1.y()) +
- static_cast<double>(segm_start2.y())) * 0.5 -
- static_cast<double>(site1.y()));
double c = robust_cross_product(b1, a1, segm_start2.y() - segm_start1.y(),
segm_start2.x() - segm_start1.x());
double det = robust_cross_product(a1, b1, site1.x() - segm_start1.x(),
site1.y() - segm_start1.y()) *
robust_cross_product(b1, a1, site1.y() - segm_start2.y(),
site1.x() - segm_start2.x());
- double t = ((point_index == 2) ? (-b + sqrt(det)) : (-b - sqrt(det))) / a;
- double c_x = 0.5 * (static_cast<double>(segm_start1.x() + segm_start2.x())) + a1 * t;
- double c_y = 0.5 * (static_cast<double>(segm_start1.y() + segm_start2.y())) + b1 * t;
- double radius = 0.5 * fabs(c) / sqrt(a);
- c_event = circle_event<double>(c_x, c_y, c_x + radius);
+ epsilon_robust_comparator<double> t;
+ t -= a1 * ((segm_start1.x() + segm_start2.x()) * 0.5 - site1.x());
+ t -= b1 * ((segm_start1.y() + segm_start2.y()) * 0.5 - site1.y());
+ if (point_index == 2) {
+ t += sqrt(det);
+ } else {
+ t -= sqrt(det);
+ }
+ t /= a;
+ epsilon_robust_comparator<double> c_x, c_y;
+ c_x += 0.5 * (segm_start1.x() + segm_start2.x());
+ c_x += a1 * t;
+ c_y += 0.5 * (segm_start1.y() + segm_start2.y());
+ c_y += b1 * t;
+ epsilon_robust_comparator<double> lower_x(c_x);
+ lower_x += 0.5 * fabs(c) / sqrt(a);
+ c_event = circle_event<double>(c_x, c_y, lower_x);
return true;
} else {
- double c1 = robust_cross_product(b1, a1, segm_end1.y(), segm_end1.x());
- double c2 = robust_cross_product(a2, b2, segm_end2.x(), segm_end2.y());
- double denom = robust_cross_product(b1, a1, b2, a2);
- double intersection_x = (c1 * a2 + a1 * c2) / denom;
- double intersection_y = (b1 * c2 + b2 * c1) / denom;
double sqr_sum1 = sqrt(a1 * a1 + b1 * b1);
double sqr_sum2 = sqrt(a2 * a2 + b2 * b2);
- double vec_x = a1 * sqr_sum2 + a2 * sqr_sum1;
- double vec_y = b1 * sqr_sum2 + b2 * sqr_sum1;
- double dx = intersection_x - site1.get_point0().x();
- double dy = intersection_y - site1.get_point0().y();
- double a = robust_cross_product(a1, b1, -b2, a2) + sqr_sum1 * sqr_sum2;
- double b = dx * vec_x + dy * vec_y;
- double det = fabs(-2.0 * a * (b1 * dx - a1 * dy) * (b2 * dx - a2 * dy));
- double t = ((point_index == 2) ? (-b + sqrt(det)) : (-b - sqrt(det))) / (a * a);
- double c_x = intersection_x + vec_x * t;
- double c_y = intersection_y + vec_y * t;
- double radius = fabs(denom * t);
- c_event = circle_event<double>(c_x, c_y, c_x + radius);
- return true;
+ double a = robust_cross_product(a1, b1, -b2, a2);
+ if (a >= 0) {
+ a += sqr_sum1 * sqr_sum2;
+ } else {
+ a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a);
+ }
+ double or1 = robust_cross_product(b1, a1, segm_end1.y() - site1.y(),
+ segm_end1.x() - site1.x());
+ double or2 = robust_cross_product(a2, b2, segm_end2.x() - site1.x(),
+ segm_end2.y() - site1.y());
+ double det = 2.0 * a * or1 * or2;
+ double c1 = robust_cross_product(b1, a1, segm_end1.y(), segm_end1.x());
+ double c2 = robust_cross_product(a2, b2, segm_end2.x(), segm_end2.y());
+ double inv_orientation = 1.0 / orientation;
+ epsilon_robust_comparator<double> t, b, ix, iy;
+ ix += c1 * a2 * inv_orientation;
+ ix += a1 * c2 * inv_orientation;
+ iy += b1 * c2 * inv_orientation;
+ iy += b2 * c1 * inv_orientation;
+ b += ix * (a1 * sqr_sum2);
+ b += ix * (a2 * sqr_sum1);
+ b += iy * (b1 * sqr_sum2);
+ b += iy * (b2 * sqr_sum1);
+ b -= sqr_sum1 * robust_cross_product(a2, b2, -site1.y(), site1.x());
+ b -= sqr_sum2 * robust_cross_product(a1, b1, -site1.y(), site1.x());
+ t -= b;
+ if (point_index == 2) {
+ t += sqrt(det);
+ } else {
+ t -= sqrt(det);
+ }
+ t /= (a * a);
+ epsilon_robust_comparator<double> c_x(ix), c_y(iy);
+ c_x += t * (a1 * sqr_sum2);
+ c_x += t * (a2 * sqr_sum1);
+ c_y += t * (b1 * sqr_sum2);
+ c_y += t * (b2 * sqr_sum1);
+ t.abs();
+ epsilon_robust_comparator<double> lower_x(c_x);
+ lower_x += t * fabs(orientation);
+ c_event = circle_event<double>(c_x, c_y, lower_x);
}
+ return true;
}
// Create circle event from three segment sites.
@@ -1240,32 +1357,42 @@
site2.get_site_index() == site3.get_site_index()) {
return false;
}
- double a1 = static_cast<double>(site1.x1(true) - site1.x0(true));
- double b1 = static_cast<double>(site1.y1(true) - site1.y0(true));
- double c1 = b1 * static_cast<double>(site1.x0(true)) -
- a1 * static_cast<double>(site1.y0(true));
- double a2 = static_cast<double>(site2.x1(true) - site2.x0(true));
- double b2 = static_cast<double>(site2.y1(true) - site2.y0(true));
- double c2 = b2 * static_cast<double>(site2.x0(true)) -
- a2 * static_cast<double>(site2.y0(true));
- double a3 = static_cast<double>(site3.x1(true) - site3.x0(true));
- double b3 = static_cast<double>(site3.y1(true) - site3.y0(true));
- double c3 = b3 * static_cast<double>(site3.x0(true)) -
- a3 * static_cast<double>(site3.y0(true));
- double sqr_sum1 = sqrt(a1 * a1 + b1 * b1);
- double sqr_sum2 = sqrt(a2 * a2 + b2 * b2);
- double sqr_sum3 = sqrt(a3 * a3 + b3 * b3);
- double vec_a1 = -a1 * sqr_sum2 + a2 * sqr_sum1;
- double vec_b1 = -b1 * sqr_sum2 + b2 * sqr_sum1;
- double vec_c1 = -c1 * sqr_sum2 + c2 * sqr_sum1;
- double vec_a2 = -a2 * sqr_sum3 + a3 * sqr_sum2;
- double vec_b2 = -b2 * sqr_sum3 + b3 * sqr_sum2;
- double vec_c2 = -c2 * sqr_sum3 + c3 * sqr_sum2;
- double det = vec_a1 * vec_b2 - vec_b1 * vec_a2;
- double c_x = (vec_a1 * vec_c2 - vec_c1 * vec_a2) / det;
- double c_y = (vec_b1 * vec_c2 - vec_c1 * vec_b2) / det;
- double radius = fabs(-b2 * c_x + a2 * c_y + c2) / sqr_sum2;
- c_event = circle_event<double>(c_x, c_y, c_x + radius);
+ double a1 = site1.x1(true) - site1.x0(true);
+ double b1 = site1.y1(true) - site1.y0(true);
+ double c1 = robust_cross_product(b1, a1, site1.y0(true), site1.x0(true));
+ double a2 = site2.x1(true) - site2.x0(true);
+ double b2 = site2.y1(true) - site2.y0(true);
+ double c2 = robust_cross_product(b2, a2, site2.y0(true), site2.x0(true));
+ double a3 = site3.x1(true) - site3.x0(true);
+ double b3 = site3.y1(true) - site3.y0(true);
+ double c3 = robust_cross_product(b3, a3, site3.y0(true), site3.x0(true));
+ double len1 = sqrt(a1 * a1 + b1 * b1);
+ double len2 = sqrt(a2 * a2 + b2 * b2);
+ double len3 = sqrt(a3 * a3 + b3 * b3);
+ double cross_12 = robust_cross_product(a1, b1, a2, b2);
+ double cross_23 = robust_cross_product(a2, b2, a3, b3);
+ double cross_31 = robust_cross_product(a3, b3, a1, b1);
+ epsilon_robust_comparator<double> det, c_x, c_y, r;
+ det += cross_12 * len3;
+ det += cross_23 * len1;
+ det += cross_31 * len2;
+ c_x += a1 * c2 * len3;
+ c_x -= a2 * c1 * len3;
+ c_x += a2 * c3 * len1;
+ c_x -= a3 * c2 * len1;
+ c_x += a3 * c1 * len2;
+ c_x -= a1 * c3 * len2;
+ c_y += b1 * c2 * len3;
+ c_y -= b2 * c1 * len3;
+ c_y += b2 * c3 * len1;
+ c_y -= b3 * c2 * len1;
+ c_y += b3 * c1 * len2;
+ c_y -= b1 * c3 * len2;
+ r += b2 * c_x;
+ r -= a2 * c_y;
+ r -= c2 * det;
+ r /= len2;
+ c_event = circle_event<double>(c_x, c_y, c_x + r, det);
return true;
}
@@ -1505,17 +1632,20 @@
voronoi_edge<coordinate_type> *incident_edge;
epsilon_robust_comparator<T> center_x;
epsilon_robust_comparator<T> center_y;
+ epsilon_robust_comparator<T> denom;
Point2D vertex;
int num_incident_edges;
typename std::list< voronoi_vertex<coordinate_type> >::iterator voronoi_record_it;
voronoi_vertex(const epsilon_robust_comparator<T> &c_x,
const epsilon_robust_comparator<T> &c_y,
+ const epsilon_robust_comparator<T> &den,
voronoi_edge<coordinate_type>* edge) :
incident_edge(edge),
center_x(c_x),
center_y(c_y),
- vertex(c_x.get_dif(), c_y.get_dif()),
+ denom(den),
+ vertex(c_x.dif() / den.dif(), c_y.dif() / den.dif()),
num_incident_edges(0) {}
};
@@ -1691,7 +1821,7 @@
// Add new voronoi vertex with point at center of the circle.
vertex_records_.push_back(voronoi_vertex_type(
- circle.get_erc_x(), circle.get_erc_y(), edge12));
+ circle.get_erc_x(), circle.get_erc_y(), circle.get_erc_denom(), edge12));
voronoi_vertex_type &new_vertex = vertex_records_.back();
new_vertex.num_incident_edges = 3;
new_vertex.voronoi_record_it = vertex_records_.end();
@@ -1805,11 +1935,17 @@
edge_it1 = edge_it;
std::advance(edge_it, 2);
- if (edge_it1->start_point && edge_it1->end_point &&
- edge_it1->start_point->center_x.compare(
- edge_it1->end_point->center_x, 128) == UNDEFINED &&
- edge_it1->start_point->center_y.compare(
- edge_it1->end_point->center_y, 128) == UNDEFINED) {
+ if (!edge_it1->start_point || !edge_it1->end_point)
+ continue;
+
+ const voronoi_vertex_type *p1 = edge_it1->start_point;
+ const voronoi_vertex_type *p2 = edge_it1->end_point;
+ epsilon_robust_comparator<T> lhs1 = p1->center_x * p2->denom;
+ epsilon_robust_comparator<T> rhs1 = p1->denom * p2->center_x;
+ epsilon_robust_comparator<T> lhs2 = p1->center_y * p2->denom;
+ epsilon_robust_comparator<T> rhs2 = p1->denom * p2->center_y;
+
+ if (lhs1.compare(rhs1, 64) == UNDEFINED && lhs2.compare(rhs2, 64) == UNDEFINED) {
// Decrease number of cell incident edges.
edge_it1->cell->num_incident_edges--;
edge_it1->twin->cell->num_incident_edges--;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk