Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r78335 - in trunk: boost/polygon boost/polygon/detail libs/polygon/test
From: sydorchuk.andriy_at_[hidden]
Date: 2012-05-05 10:29:12


Author: asydorchuk
Date: 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
New Revision: 78335
URL: http://svn.boost.org/trac/boost/changeset/78335

Log:
Merging Polygon with Voronoi library.
Adding Boost.Polygon segment concept.
Adding Voronoi tests.
Adding Boost.Polygon segment concept/data/traits tests.
Added:
   trunk/boost/polygon/detail/voronoi_ctypes.hpp (contents, props changed)
   trunk/boost/polygon/detail/voronoi_predicates.hpp (contents, props changed)
   trunk/boost/polygon/detail/voronoi_robust_fpt.hpp (contents, props changed)
   trunk/boost/polygon/detail/voronoi_structures.hpp (contents, props changed)
   trunk/boost/polygon/segment_concept.hpp (contents, props changed)
   trunk/boost/polygon/segment_data.hpp (contents, props changed)
   trunk/boost/polygon/segment_traits.hpp (contents, props changed)
   trunk/boost/polygon/voronoi.hpp (contents, props changed)
   trunk/boost/polygon/voronoi_builder.hpp (contents, props changed)
   trunk/boost/polygon/voronoi_diagram.hpp (contents, props changed)
   trunk/boost/polygon/voronoi_utils.hpp (contents, props changed)
   trunk/libs/polygon/test/polygon_segment_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_builder_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_ctypes_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_predicates_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_robust_fpt_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_structures_test.cpp (contents, props changed)
   trunk/libs/polygon/test/voronoi_test_helper.hpp (contents, props changed)
Removed:
   trunk/boost/polygon/directed_line_segment_concept.hpp
   trunk/boost/polygon/directed_line_segment_data.hpp
   trunk/boost/polygon/directed_line_segment_set_data.hpp
   trunk/boost/polygon/directed_line_segment_traits.hpp
Text files modified:
   trunk/boost/polygon/interval_concept.hpp | 252 +++++++++++++++++++++++----------------
   trunk/boost/polygon/point_3d_concept.hpp | 28 ++--
   trunk/boost/polygon/point_concept.hpp | 199 +++++++++++++++++--------------
   trunk/boost/polygon/polygon.hpp | 7
   trunk/boost/polygon/polygon_90_set_concept.hpp | 17 +-
   trunk/boost/polygon/polygon_traits.hpp | 2
   trunk/boost/polygon/rectangle_concept.hpp | 214 ++++++++++++++++----------------
   trunk/libs/polygon/test/Jamfile.v2 | 14 ++
   trunk/libs/polygon/test/gtl_boost_unit_test.cpp | 17 +-
   9 files changed, 411 insertions(+), 339 deletions(-)

Added: trunk/boost/polygon/detail/voronoi_ctypes.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/detail/voronoi_ctypes.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,713 @@
+// Boost.Polygon library detail/voronoi_ctypes.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_DETAIL_VORONOI_CTYPES
+#define BOOST_POLYGON_DETAIL_VORONOI_CTYPES
+
+#include <cmath>
+#include <cstring>
+
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace polygon {
+namespace detail {
+
+typedef boost::int32_t int32;
+typedef boost::int64_t int64;
+typedef boost::uint32_t uint32;
+typedef boost::uint64_t uint64;
+typedef double fpt64;
+
+// If two floating-point numbers in the same format are ordered (x < y),
+// then they are ordered the same way when their bits are reinterpreted as
+// sign-magnitude integers. Values are considered to be almost equal if
+// their integer bits reinterpretations differ in not more than maxUlps units.
+template <typename _fpt>
+struct ulp_comparison;
+
+template <>
+struct ulp_comparison<fpt64> {
+ enum Result {
+ LESS = -1,
+ EQUAL = 0,
+ MORE = 1
+ };
+
+ Result operator()(fpt64 a, fpt64 b, unsigned int maxUlps) const {
+ uint64 ll_a, ll_b;
+
+ // Reinterpret double bits as 64-bit signed integer.
+ memcpy(&ll_a, &a, sizeof(fpt64));
+ memcpy(&ll_b, &b, sizeof(fpt64));
+
+ // Positive 0.0 is integer zero. Negative 0.0 is 0x8000000000000000.
+ // Map negative zero to an integer zero representation - making it
+ // identical to positive zero - the smallest negative number is
+ // represented by negative one, and downwards from there.
+ if (ll_a < 0x8000000000000000ULL)
+ ll_a = 0x8000000000000000ULL - ll_a;
+ if (ll_b < 0x8000000000000000ULL)
+ ll_b = 0x8000000000000000ULL - ll_b;
+
+ // Compare 64-bit signed integer representations of input values.
+ // Difference in 1 Ulp is equivalent to a relative error of between
+ // 1/4,000,000,000,000,000 and 1/8,000,000,000,000,000.
+ if (ll_a > ll_b)
+ return (ll_a - ll_b <= maxUlps) ? EQUAL : LESS;
+ return (ll_b - ll_a <= maxUlps) ? EQUAL : MORE;
+ }
+};
+
+// Manages exponent of the floating-point value.
+template <typename _fpt>
+struct fpt_exponent_accessor;
+
+template <>
+class fpt_exponent_accessor<fpt64> {
+public:
+ static const int64 kExponentMask;
+ static const int64 kSignedMantissaMask;
+ static const int64 kMinExponent;
+ static const int64 kMaxExponent;
+ static const int64 kMaxSignificantExpDif;
+
+ static int64 set_exponent(fpt64& value, int64 exponent) {
+ int64 bits;
+ memcpy(&bits, &value, sizeof(fpt64));
+ int64 exp = ((bits & kExponentMask) >> 52) - 1023;
+ if (exp == exponent)
+ return exp;
+ bits = (bits & kSignedMantissaMask) | ((exponent + 1023) << 52);
+ memcpy(&value, &bits, sizeof(fpt64));
+ return exp;
+ }
+};
+
+const int64 fpt_exponent_accessor<fpt64>::kExponentMask =
+ 0x7ff0000000000000LL;
+const int64 fpt_exponent_accessor<fpt64>::kSignedMantissaMask =
+ 0x800fffffffffffffLL;
+const int64 fpt_exponent_accessor<fpt64>::kMinExponent = -1023LL;
+const int64 fpt_exponent_accessor<fpt64>::kMaxExponent = 1024LL;
+const int64 fpt_exponent_accessor<fpt64>::kMaxSignificantExpDif = 54;
+
+// Floating point type wrapper. Allows to extend exponent boundaries to the
+// 64 bit integer range. This class does not handle division by zero, subnormal
+// numbers or NaNs.
+template <typename _fpt>
+class extended_exponent_fpt {
+public:
+ typedef _fpt fpt_type;
+ typedef int64 exp_type;
+ typedef fpt_exponent_accessor<fpt_type> fea;
+
+ explicit extended_exponent_fpt(fpt_type value) {
+ if (value == 0.0) {
+ exponent_ = 0;
+ value_ = 0.0;
+ } else {
+ exponent_ = fea::set_exponent(value, 0);
+ value_ = value;
+ }
+ }
+
+ extended_exponent_fpt(fpt_type value, exp_type exponent) {
+ if (value == 0.0) {
+ exponent_ = 0;
+ value_ = 0.0;
+ } else {
+ exponent_ = fea::set_exponent(value, 0) + exponent;
+ value_ = value;
+ }
+ }
+
+ bool is_pos() const {
+ return value_ > 0;
+ }
+
+ bool is_neg() const {
+ return value_ < 0;
+ }
+
+ bool is_zero() const {
+ return value_ == 0;
+ }
+
+ extended_exponent_fpt operator-() const {
+ return extended_exponent_fpt(-value_, exponent_);
+ }
+
+ extended_exponent_fpt operator+(const extended_exponent_fpt& that) const {
+ if (this->value_ == 0.0 ||
+ that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
+ return that;
+ }
+ if (that.value_ == 0.0 ||
+ this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
+ return *this;
+ }
+ if (this->exponent_ >= that.exponent_) {
+ exp_type exp_dif = this->exponent_ - that.exponent_;
+ fpt_type value = this->value_;
+ fea::set_exponent(value, exp_dif);
+ value += that.value_;
+ return extended_exponent_fpt(value, that.exponent_);
+ } else {
+ exp_type exp_dif = that.exponent_ - this->exponent_;
+ fpt_type value = that.value_;
+ fea::set_exponent(value, exp_dif);
+ value += this->value_;
+ return extended_exponent_fpt(value, this->exponent_);
+ }
+ }
+
+ extended_exponent_fpt operator-(const extended_exponent_fpt& that) const {
+ if (this->value_ == 0.0 ||
+ that.exponent_ > this->exponent_ + fea::kMaxSignificantExpDif) {
+ return extended_exponent_fpt(-that.value_, that.exponent_);
+ }
+ if (that.value_ == 0.0 ||
+ this->exponent_ > that.exponent_ + fea::kMaxSignificantExpDif) {
+ return *this;
+ }
+ if (this->exponent_ >= that.exponent_) {
+ exp_type exp_dif = this->exponent_ - that.exponent_;
+ fpt_type value = this->value_;
+ fea::set_exponent(value, exp_dif);
+ value -= that.value_;
+ return extended_exponent_fpt(value, that.exponent_);
+ } else {
+ exp_type exp_dif = that.exponent_ - this->exponent_;
+ fpt_type value = -that.value_;
+ fea::set_exponent(value, exp_dif);
+ value += this->value_;
+ return extended_exponent_fpt(value, this->exponent_);
+ }
+ }
+
+ extended_exponent_fpt operator*(const extended_exponent_fpt& that) const {
+ fpt_type value = this->value_ * that.value_;
+ exp_type exponent = this->exponent_ + that.exponent_;
+ return extended_exponent_fpt(value, exponent);
+ }
+
+ extended_exponent_fpt operator/(const extended_exponent_fpt& that) const {
+ fpt_type value = this->value_ / that.value_;
+ exp_type exponent = this->exponent_ - that.exponent_;
+ return extended_exponent_fpt(value, exponent);
+ }
+
+ extended_exponent_fpt& operator+=(const extended_exponent_fpt& that) {
+ return *this = *this + that;
+ }
+
+ extended_exponent_fpt& operator-=(const extended_exponent_fpt& that) {
+ return *this = *this - that;
+ }
+
+ extended_exponent_fpt& operator*=(const extended_exponent_fpt& that) {
+ return *this = *this * that;
+ }
+
+ extended_exponent_fpt& operator/=(const extended_exponent_fpt& that) {
+ return *this = *this / that;
+ }
+
+ extended_exponent_fpt sqrt() const {
+ fpt_type val = value_;
+ exp_type exp = exponent_;
+ if (exp & 1) {
+ val *= 2.0;
+ --exp;
+ }
+ return extended_exponent_fpt(std::sqrt(val), exp >> 1);
+ }
+
+ fpt_type d() const {
+ fpt_type ret_val = value_;
+ exp_type exp = exponent_;
+ if (ret_val == 0.0)
+ return ret_val;
+ if (exp >= fea::kMaxExponent) {
+ ret_val = 1.0;
+ exp = fea::kMaxExponent;
+ } else if (exp <= fea::kMinExponent) {
+ ret_val = 1.0;
+ exp = fea::kMinExponent;
+ }
+ fea::set_exponent(ret_val, exp);
+ return ret_val;
+ }
+
+private:
+ fpt_type value_;
+ exp_type exponent_;
+};
+typedef extended_exponent_fpt<double> efpt64;
+
+template <typename _fpt>
+extended_exponent_fpt<_fpt> get_sqrt(const extended_exponent_fpt<_fpt>& that) {
+ return that.sqrt();
+}
+
+template <typename _fpt>
+bool is_pos(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_pos();
+}
+
+template <typename _fpt>
+bool is_neg(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_neg();
+}
+
+template <typename _fpt>
+bool is_zero(const extended_exponent_fpt<_fpt>& that) {
+ return that.is_zero();
+}
+
+// Very efficient stack allocated big integer class.
+// Supports next set of arithmetic operations: +, -, *.
+template<size_t N>
+class extended_int {
+public:
+ static const uint64 kUInt64LowMask;
+ static const uint64 kUInt64HighMask;
+
+ extended_int() {}
+
+ extended_int(int32 that) {
+ if (that > 0) {
+ this->chunks_[0] = that;
+ this->count_ = 1;
+ } else if (that < 0) {
+ this->chunks_[0] = -that;
+ this->count_ = -1;
+ } else {
+ this->count_ = 0;
+ }
+ }
+
+ extended_int(int64 that) {
+ if (that > 0) {
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ this->chunks_[1] = that >> 32;
+ this->count_ = this->chunks_[1] ? 2 : 1;
+ } else if (that < 0) {
+ that = -that;
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ this->chunks_[1] = that >> 32;
+ this->count_ = this->chunks_[1] ? -2 : -1;
+ } else {
+ this->count_ = 0;
+ }
+ }
+
+ extended_int(const std::vector<uint32>& chunks, bool plus = true) {
+ this->count_ = static_cast<int32>((std::min)(N, chunks.size()));
+ for (int i = 0; i < this->count_; ++i)
+ this->chunks_[i] = chunks[chunks.size() - i - 1];
+ if (!plus)
+ this->count_ = -this->count_;
+ }
+
+ template <size_t M>
+ extended_int(const extended_int<M>& that) {
+ if (that.size() > N) return;
+ this->count_ = that.count();
+ memcpy(this->chunks_, that.chunks(), that.size() * sizeof(uint32));
+ }
+
+ extended_int& operator=(int32 that) {
+ if (that > 0) {
+ this->chunks_[0] = that;
+ this->count_ = 1;
+ } else if (that < 0) {
+ this->chunks_[0] = -that;
+ this->count_ = -1;
+ } else {
+ this->count_ = 0;
+ }
+ return *this;
+ }
+
+ extended_int& operator=(int64 that) {
+ if (that > 0) {
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ this->chunks_[1] = that >> 32;
+ this->count_ = this->chunks_[1] ? 2 : 1;
+ } else if (that < 0) {
+ that = -that;
+ this->chunks_[0] = static_cast<uint32>(that & kUInt64LowMask);
+ this->chunks_[1] = that >> 32;
+ this->count_ = this->chunks_[1] ? -2 : -1;
+ } else {
+ this->count_ = 0;
+ }
+ return *this;
+ }
+
+ template <size_t M>
+ extended_int& operator=(const extended_int<M>& that) {
+ size_t mx = (std::max)(N, that.size());
+ this->count_ = that.count();
+ memcpy(this->chunks_, that.chunks(), mx * sizeof(uint32));
+ return *this;
+ }
+
+ bool is_pos() const {
+ return this->count_ > 0;
+ }
+
+ bool is_neg() const {
+ return this->count_ < 0;
+ }
+
+ bool is_zero() const {
+ return this->count_ == 0;
+ }
+
+ template <size_t M>
+ bool operator==(const extended_int<M>& that) const {
+ if (this->count_ != that.count())
+ return false;
+ for (size_t i = 0; i < this->size(); ++i)
+ if (this->chunks_[i] != that.chunks()[i])
+ return false;
+ return true;
+ }
+
+ template <size_t M>
+ bool operator!=(const extended_int<M>& that) const {
+ return !(*this == that);
+ }
+
+ template <size_t M>
+ bool operator<(const extended_int<M>& that) const {
+ if (this->count_ != that.count())
+ return this->count_ < that.count();
+ size_t i = this->size();
+ if (!i)
+ return false;
+ do {
+ --i;
+ if (this->chunks_[i] != that.chunks()[i])
+ return (this->chunks_[i] < that.chunks()[i]) ^ (this->count_ < 0);
+ } while (i);
+ return false;
+ }
+
+ template <size_t M>
+ bool operator>(const extended_int<M>& that) const {
+ return that < *this;
+ }
+
+ template <size_t M>
+ bool operator<=(const extended_int<M>& that) const {
+ return !(that < *this);
+ }
+
+ template <size_t M>
+ bool operator>=(const extended_int<M>& that) const {
+ return !(*this < that);
+ }
+
+ extended_int operator-() const {
+ extended_int ret_val = *this;
+ ret_val.neg();
+ return ret_val;
+ }
+
+ void neg() {
+ this->count_ = -this->count_;
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator+(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.add(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void add(const extended_int<N1>& e1, const extended_int<N2>& e2) {
+ if (!e1.count()) {
+ *this = e2;
+ return;
+ }
+ if (!e2.count()) {
+ *this = e1;
+ return;
+ }
+ if ((e1.count() > 0) ^ (e2.count() > 0)) {
+ dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ } else {
+ add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ }
+ if (e1.count() < 0)
+ this->count_ = -this->count_;
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator-(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.dif(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void dif(const extended_int<N1>& e1, const extended_int<N2> &e2) {
+ if (!e1.count()) {
+ *this = e2;
+ this->count_ = -this->count_;
+ return;
+ }
+ if (!e2.count()) {
+ *this = e1;
+ return;
+ }
+ if ((e1.count() > 0) ^ (e2.count() > 0)) {
+ add(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ } else {
+ dif(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ }
+ if (e1.count() < 0)
+ this->count_ = -this->count_;
+ }
+
+ extended_int<N> operator*(int32 that) const {
+ extended_int<N> temp(that);
+ return (*this) * temp;
+ }
+
+ extended_int<N> operator*(int64 that) const {
+ extended_int<N> temp(that);
+ return (*this) * temp;
+ }
+
+ template <size_t M>
+ extended_int<(N>M?N:M)> operator*(const extended_int<M>& that) const {
+ extended_int<(N>M?N:M)> ret_val;
+ ret_val.mul(*this, that);
+ return ret_val;
+ }
+
+ template <size_t N1, size_t N2>
+ void mul(const extended_int<N1>& e1, const extended_int<N2>& e2) {
+ if (!e1.count() || !e2.count()) {
+ this->count_ = 0;
+ return;
+ }
+ mul(e1.chunks(), e1.size(), e2.chunks(), e2.size());
+ if ((e1.count() > 0) ^ (e2.count() > 0))
+ this->count_ = -this->count_;
+ }
+
+ const uint32* chunks() const {
+ return chunks_;
+ }
+
+ int32 count() const {
+ return count_;
+ }
+
+ size_t size() const {
+ return (std::abs)(count_);
+ }
+
+ std::pair<fpt64, int64> p() const {
+ std::pair<fpt64, int64> ret_val(0, 0);
+ size_t sz = this->size();
+ if (!sz) {
+ return ret_val;
+ } else {
+ if (sz == 1) {
+ ret_val.first = static_cast<fpt64>(this->chunks_[0]);
+ } else if (sz == 2) {
+ ret_val.first = static_cast<fpt64>(this->chunks_[1]) *
+ static_cast<fpt64>(0x100000000LL) +
+ static_cast<fpt64>(this->chunks_[0]);
+ } else {
+ for (size_t i = 1; i <= 3; ++i) {
+ ret_val.first *= static_cast<fpt64>(0x100000000LL);
+ ret_val.first += static_cast<fpt64>(this->chunks_[sz - i]);
+ }
+ ret_val.second = (sz - 3) << 5;
+ }
+ }
+ if (this->count_ < 0)
+ ret_val.first = -ret_val.first;
+ return ret_val;
+ }
+
+ fpt64 d() const {
+ std::pair<fpt64, int64> p = this->p();
+ extended_exponent_fpt<fpt64> efpt(p.first, p.second);
+ return efpt.d();
+ }
+
+private:
+ void add(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
+ if (sz1 < sz2) {
+ add(c2, sz2, c1, sz1);
+ return;
+ }
+ this->count_ = sz1;
+ uint64 temp = 0;
+ for (size_t i = 0; i < sz2; ++i) {
+ temp += static_cast<uint64>(c1[i]) + static_cast<uint64>(c2[i]);
+ this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
+ temp >>= 32;
+ }
+ for (size_t i = sz2; i < sz1; ++i) {
+ temp += static_cast<uint64>(c1[i]);
+ this->chunks_[i] = static_cast<uint32>(temp & kUInt64LowMask);
+ temp >>= 32;
+ }
+ if (temp && (this->count_ != N)) {
+ this->chunks_[this->count_] = static_cast<uint32>(temp & kUInt64LowMask);
+ ++this->count_;
+ }
+ }
+
+ void dif(const uint32* c1, size_t sz1,
+ const uint32* c2, size_t sz2, bool rec = false) {
+ if (sz1 < sz2) {
+ dif(c2, sz2, c1, sz1, true);
+ this->count_ = -this->count_;
+ return;
+ } else if ((sz1 == sz2) && !rec) {
+ do {
+ --sz1;
+ if (c1[sz1] < c2[sz1]) {
+ ++sz1;
+ dif(c2, sz1, c1, sz1, true);
+ this->count_ = -this->count_;
+ return;
+ } else if (c1[sz1] > c2[sz1]) {
+ ++sz1;
+ break;
+ }
+ } while (sz1);
+ if (!sz1) {
+ this->count_ = 0;
+ return;
+ }
+ sz2 = sz1;
+ }
+ this->count_ = sz1-1;
+ bool flag = false;
+ for (size_t i = 0; i < sz2; ++i) {
+ this->chunks_[i] = c1[i] - c2[i] - (flag?1:0);
+ flag = (c1[i] < c2[i]) || ((c1[i] == c2[i]) && flag);
+ }
+ for (size_t i = sz2; i < sz1; ++i) {
+ this->chunks_[i] = c1[i] - (flag?1:0);
+ flag = !c1[i] && flag;
+ }
+ if (this->chunks_[this->count_])
+ ++this->count_;
+ }
+
+ void mul(const uint32* c1, size_t sz1, const uint32* c2, size_t sz2) {
+ uint64 cur = 0, nxt, tmp;
+ this->count_ = static_cast<int32>((std::min)(N, sz1 + sz2 - 1));
+ for (size_t shift = 0; shift < static_cast<size_t>(this->count_);
+ ++shift) {
+ nxt = 0;
+ for (size_t first = 0; first <= shift; ++first) {
+ if (first >= sz1)
+ break;
+ size_t second = shift - first;
+ if (second >= sz2)
+ continue;
+ tmp = static_cast<uint64>(c1[first]) * static_cast<uint64>(c2[second]);
+ cur += tmp & kUInt64LowMask;
+ nxt += tmp >> 32;
+ }
+ this->chunks_[shift] = static_cast<uint32>(cur & kUInt64LowMask);
+ cur = nxt + (cur >> 32);
+ }
+ if (cur && (this->count_ != N)) {
+ this->chunks_[this->count_] = static_cast<uint32>(cur & kUInt64LowMask);
+ ++this->count_;
+ }
+ }
+
+ uint32 chunks_[N];
+ int32 count_;
+};
+
+template <size_t N>
+const uint64 extended_int<N>::kUInt64LowMask = 0x00000000ffffffffULL;
+template <size_t N>
+const uint64 extended_int<N>::kUInt64HighMask = 0xffffffff00000000ULL;
+
+template <size_t N>
+bool is_pos(const extended_int<N>& that) {
+ return that.count() > 0;
+}
+
+template <size_t N>
+bool is_neg(const extended_int<N>& that) {
+ return that.count() < 0;
+}
+
+template <size_t N>
+bool is_zero(const extended_int<N>& that) {
+ return !that.count();
+}
+
+struct type_converter_fpt {
+ template <typename T>
+ fpt64 operator()(const T& that) const {
+ return static_cast<fpt64>(that);
+ }
+
+ template <size_t N>
+ fpt64 operator()(const extended_int<N>& that) const {
+ return that.d();
+ }
+
+ fpt64 operator()(const extended_exponent_fpt<fpt64>& that) const {
+ return that.d();
+ }
+};
+
+struct type_converter_efpt {
+ template <size_t N>
+ extended_exponent_fpt<fpt64> operator()(const extended_int<N>& that) const {
+ std::pair<fpt64, int64> p = that.p();
+ return extended_exponent_fpt<fpt64>(p.first, p.second);
+ }
+};
+
+// Voronoi coordinate type traits make it possible to extend algorithm
+// input coordinate range to any user provided integer type and algorithm
+// output coordinate range to any ieee-754 like floating point type.
+template <typename T>
+struct voronoi_ctype_traits;
+
+template <>
+struct voronoi_ctype_traits<int32> {
+ typedef int32 int_type;
+ typedef int64 int_x2_type;
+ typedef uint64 uint_x2_type;
+ typedef extended_int<64> big_int_type;
+ typedef fpt64 fpt_type;
+ typedef extended_exponent_fpt<fpt_type> efpt_type;
+ typedef ulp_comparison<fpt_type> ulp_cmp_type;
+ typedef type_converter_fpt to_fpt_converter_type;
+ typedef type_converter_efpt to_efpt_converter_type;
+};
+} // detail
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_DETAIL_VORONOI_CTYPES

Added: trunk/boost/polygon/detail/voronoi_predicates.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/detail/voronoi_predicates.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,1440 @@
+// Boost.Polygon library detail/voronoi_predicates.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
+#define BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
+
+#include "voronoi_robust_fpt.hpp"
+
+namespace boost {
+namespace polygon {
+namespace detail {
+
+// Predicate utilities. Operates with the coordinate types that could
+// be converted to the 32-bit signed integer without precision loss.
+template <typename CTYPE_TRAITS>
+class voronoi_predicates {
+public:
+ typedef typename CTYPE_TRAITS::int_type int_type;
+ typedef typename CTYPE_TRAITS::int_x2_type int_x2_type;
+ typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type;
+ typedef typename CTYPE_TRAITS::big_int_type big_int_type;
+ typedef typename CTYPE_TRAITS::fpt_type fpt_type;
+ typedef typename CTYPE_TRAITS::efpt_type efpt_type;
+ typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type;
+ typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter;
+ typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter;
+
+ enum {
+ ULPS = 64,
+ ULPSx2 = 128
+ };
+
+ template <typename Point>
+ static bool is_vertical(const Point &point1, const Point &point2) {
+ return point1.x() == point2.x();
+ }
+
+ template <typename Site>
+ static bool is_vertical(const Site &site) {
+ return is_vertical(site.point0(), site.point1());
+ }
+
+ // Compute robust cross_product: a1 * b2 - b1 * a2.
+ // It was mathematically proven that the result is correct
+ // with epsilon relative error equal to 1EPS.
+ static fpt_type robust_cross_product(int_x2_type a1_,
+ int_x2_type b1_,
+ int_x2_type a2_,
+ int_x2_type b2_) {
+ static to_fpt_converter to_fpt;
+ uint_x2_type a1 = static_cast<uint_x2_type>(is_neg(a1_) ? -a1_ : a1_);
+ uint_x2_type b1 = static_cast<uint_x2_type>(is_neg(b1_) ? -b1_ : b1_);
+ uint_x2_type a2 = static_cast<uint_x2_type>(is_neg(a2_) ? -a2_ : a2_);
+ uint_x2_type b2 = static_cast<uint_x2_type>(is_neg(b2_) ? -b2_ : b2_);
+
+ uint_x2_type l = a1 * b2;
+ uint_x2_type r = b1 * a2;
+
+ if (is_neg(a1_) ^ is_neg(b2_)) {
+ if (is_neg(a2_) ^ is_neg(b1_))
+ return (l > r) ? -to_fpt(l - r) : to_fpt(r - l);
+ else
+ return -to_fpt(l + r);
+ } else {
+ if (is_neg(a2_) ^ is_neg(b1_))
+ return to_fpt(l + r);
+ else
+ return (l < r) ? -to_fpt(r - l) : to_fpt(l - r);
+ }
+ }
+
+ typedef struct orientation_test {
+ public:
+ // Represents orientation test result.
+ enum Orientation {
+ RIGHT = -1,
+ COLLINEAR = 0,
+ LEFT = 1
+ };
+
+ // Value is a determinant of two vectors (e.g. x1 * y2 - x2 * y1).
+ // Return orientation based on the sign of the determinant.
+ template <typename T>
+ static Orientation eval(T value) {
+ if (is_zero(value)) return COLLINEAR;
+ return (is_neg(value)) ? RIGHT : LEFT;
+ }
+
+ static Orientation eval(int_x2_type dif_x1_,
+ int_x2_type dif_y1_,
+ int_x2_type dif_x2_,
+ int_x2_type dif_y2_) {
+ return eval(robust_cross_product(dif_x1_, dif_y1_, dif_x2_, dif_y2_));
+ }
+
+ template <typename Point>
+ static Orientation eval(const Point &point1,
+ const Point &point2,
+ const Point &point3) {
+ int_x2_type dx1 = static_cast<int_x2_type>(point1.x()) -
+ static_cast<int_x2_type>(point2.x());
+ int_x2_type dx2 = static_cast<int_x2_type>(point2.x()) -
+ static_cast<int_x2_type>(point3.x());
+ int_x2_type dy1 = static_cast<int_x2_type>(point1.y()) -
+ static_cast<int_x2_type>(point2.y());
+ int_x2_type dy2 = static_cast<int_x2_type>(point2.y()) -
+ static_cast<int_x2_type>(point3.y());
+ return eval(robust_cross_product(dx1, dy1, dx2, dy2));
+ }
+ } ot;
+
+ template <typename Point>
+ class point_comparison_predicate {
+ public:
+ typedef Point point_type;
+
+ bool operator()(const point_type &lhs, const point_type &rhs) const {
+ if (lhs.x() == rhs.x())
+ return lhs.y() < rhs.y();
+ return lhs.x() < rhs.x();
+ }
+ };
+
+ template <typename Site, typename Circle>
+ class event_comparison_predicate {
+ public:
+ typedef Site site_type;
+ typedef Circle circle_type;
+
+ bool operator()(const site_type &lhs, const site_type &rhs) const {
+ if (lhs.x0() != rhs.x0())
+ return lhs.x0() < rhs.x0();
+ if (!lhs.is_segment()) {
+ if (!rhs.is_segment())
+ return lhs.y0() < rhs.y0();
+ if (is_vertical(rhs))
+ return lhs.y0() <= rhs.y0();
+ return true;
+ } else {
+ if (is_vertical(rhs)) {
+ if(is_vertical(lhs))
+ return lhs.y0() < rhs.y0();
+ return false;
+ }
+ if (is_vertical(lhs))
+ return true;
+ if (lhs.y0() != rhs.y0())
+ return lhs.y0() < rhs.y0();
+ return ot::eval(lhs.point1(), lhs.point0(), rhs.point1()) == ot::LEFT;
+ }
+ }
+
+ bool operator()(const site_type &lhs, const circle_type &rhs) const {
+ typename ulp_cmp_type::Result xCmp =
+ ulp_cmp(to_fpt(lhs.x()), to_fpt(rhs.lower_x()), ULPS);
+ if (xCmp != ulp_cmp_type::EQUAL)
+ return xCmp == ulp_cmp_type::LESS;
+ typename ulp_cmp_type::Result yCmp =
+ ulp_cmp(to_fpt(lhs.y()), to_fpt(rhs.lower_y()), ULPS);
+ return yCmp == ulp_cmp_type::LESS;
+ }
+
+ bool operator()(const circle_type &lhs, const site_type &rhs) const {
+ typename ulp_cmp_type::Result xCmp =
+ ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.x()), ULPS);
+ if (xCmp != ulp_cmp_type::EQUAL)
+ return xCmp == ulp_cmp_type::LESS;
+ typename ulp_cmp_type::Result yCmp =
+ ulp_cmp(to_fpt(lhs.lower_y()), to_fpt(rhs.y()), ULPS);
+ return yCmp == ulp_cmp_type::LESS;
+ }
+
+ bool operator()(const circle_type &lhs, const circle_type &rhs) const {
+ typename ulp_cmp_type::Result xCmp =
+ ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.lower_x()), ULPSx2);
+ if (xCmp != ulp_cmp_type::EQUAL)
+ return xCmp == ulp_cmp_type::LESS;
+ typename ulp_cmp_type::Result yCmp =
+ ulp_cmp(to_fpt(lhs.lower_y()), to_fpt(rhs.lower_y()), ULPSx2);
+ return yCmp == ulp_cmp_type::LESS;
+ }
+
+ private:
+ ulp_cmp_type ulp_cmp;
+ to_fpt_converter to_fpt;
+ };
+
+ template <typename Site>
+ class distance_predicate {
+ public:
+ typedef Site site_type;
+
+ // Returns true if a horizontal line going through a 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.
+ bool operator()(const site_type &left_site,
+ const site_type &right_site,
+ const site_type &new_site) const {
+ if (!left_site.is_segment()) {
+ if (!right_site.is_segment()) {
+ return pp(left_site, right_site, new_site);
+ } else {
+ return ps(left_site, right_site, new_site, false);
+ }
+ } else {
+ if (!right_site.is_segment()) {
+ return ps(right_site, left_site, new_site, true);
+ } else {
+ return ss(left_site, right_site, new_site);
+ }
+ }
+ }
+
+ private:
+ // Represents the result of the epsilon robust predicate. If the
+ // result is undefined some further processing is usually required.
+ enum kPredicateResult {
+ LESS = -1,
+ UNDEFINED = 0,
+ MORE = 1
+ };
+
+ typedef typename Site::point_type point_type;
+
+ // Robust predicate, avoids using high-precision libraries.
+ // Returns true if a horizontal line going through the new point site
+ // intersects right arc at first, else returns false. If horizontal line
+ // goes through intersection point of the given two arcs returns false.
+ bool pp(const site_type &left_site,
+ const site_type &right_site,
+ const site_type &new_site) const {
+ const point_type &left_point = left_site.point0();
+ const point_type &right_point = right_site.point0();
+ const point_type &new_point = new_site.point0();
+ if (left_point.x() > right_point.x()) {
+ if (new_point.y() <= left_point.y())
+ return false;
+ } else if (left_point.x() < right_point.x()) {
+ if (new_point.y() >= right_point.y())
+ return true;
+ } else {
+ return static_cast<int_x2_type>(left_point.y()) +
+ static_cast<int_x2_type>(right_point.y()) <
+ static_cast<int_x2_type>(new_point.y()) * 2;
+ }
+
+ fpt_type dist1 = find_distance_to_point_arc(left_site, new_point);
+ fpt_type dist2 = find_distance_to_point_arc(right_site, new_point);
+
+ // The undefined ulp range is equal to 3EPS + 3EPS <= 6ULP.
+ return dist1 < dist2;
+ }
+
+ bool ps(const site_type &left_site, const site_type &right_site,
+ const site_type &new_site, bool reverse_order) const {
+ kPredicateResult fast_res = fast_ps(
+ left_site, right_site, new_site, reverse_order);
+ if (fast_res != UNDEFINED)
+ return (fast_res == LESS);
+
+ fpt_type dist1 = find_distance_to_point_arc(
+ left_site, new_site.point0());
+ fpt_type dist2 = find_distance_to_segment_arc(
+ right_site, new_site.point0());
+
+ // The undefined ulp range is equal to 3EPS + 7EPS <= 10ULP.
+ return reverse_order ^ (dist1 < dist2);
+ }
+
+ bool ss(const site_type &left_site,
+ const site_type &right_site,
+ const site_type &new_site) const {
+ // Handle temporary segment sites.
+ if (left_site.point0() == right_site.point0() &&
+ left_site.point1() == right_site.point1()) {
+ return ot::eval(left_site.point0(),
+ left_site.point1(),
+ new_site.point0()) == ot::LEFT;
+ }
+
+ fpt_type dist1 = find_distance_to_segment_arc(
+ left_site, new_site.point0());
+ fpt_type dist2 = find_distance_to_segment_arc(
+ right_site, new_site.point0());
+
+ // The undefined ulp range is equal to 7EPS + 7EPS <= 14ULP.
+ return dist1 < dist2;
+ }
+
+ fpt_type find_distance_to_point_arc(
+ const site_type &site, const point_type &point) const {
+ fpt_type dx = to_fpt(site.x()) - to_fpt(point.x());
+ fpt_type dy = to_fpt(site.y()) - to_fpt(point.y());
+ // The relative error is at most 3EPS.
+ return (dx * dx + dy * dy) / (to_fpt(2.0) * dx);
+ }
+
+ fpt_type find_distance_to_segment_arc(
+ const site_type &site, const point_type &point) const {
+ if (is_vertical(site)) {
+ return (to_fpt(site.x()) - to_fpt(point.x())) * to_fpt(0.5);
+ } else {
+ const point_type &segment0 = site.point0(true);
+ const point_type &segment1 = site.point1(true);
+ fpt_type a1 = to_fpt(segment1.x()) - to_fpt(segment0.x());
+ fpt_type b1 = to_fpt(segment1.y()) - to_fpt(segment0.y());
+ fpt_type k = get_sqrt(a1 * a1 + b1 * b1);
+ // Avoid subtraction while computing k.
+ if (!is_neg(b1)) {
+ k = to_fpt(1.0) / (b1 + k);
+ } else {
+ k = (k - b1) / (a1 * a1);
+ }
+ // The relative error is at most 7EPS.
+ return k * robust_cross_product(
+ static_cast<int_x2_type>(segment1.x()) - static_cast<int_x2_type>(segment0.x()),
+ static_cast<int_x2_type>(segment1.y()) - static_cast<int_x2_type>(segment0.y()),
+ static_cast<int_x2_type>(point.x()) - static_cast<int_x2_type>(segment0.x()),
+ static_cast<int_x2_type>(point.y()) - static_cast<int_x2_type>(segment0.y()));
+ }
+ }
+
+ kPredicateResult fast_ps(
+ const site_type &left_site, const site_type &right_site,
+ const site_type &new_site, bool reverse_order) const {
+ const point_type &site_point = left_site.point0();
+ const point_type &segment_start = right_site.point0(true);
+ const point_type &segment_end = right_site.point1(true);
+ const point_type &new_point = new_site.point0();
+
+ if (ot::eval(segment_start, segment_end, new_point) != ot::RIGHT)
+ return (!right_site.is_inverse()) ? LESS : MORE;
+
+ fpt_type dif_x = to_fpt(new_point.x()) - to_fpt(site_point.x());
+ fpt_type dif_y = to_fpt(new_point.y()) - to_fpt(site_point.y());
+ fpt_type a = to_fpt(segment_end.x()) - to_fpt(segment_start.x());
+ fpt_type b = to_fpt(segment_end.y()) - to_fpt(segment_start.y());
+
+ if (is_vertical(right_site)) {
+ if (new_point.y() < site_point.y() && !reverse_order)
+ return MORE;
+ else if (new_point.y() > site_point.y() && reverse_order)
+ return LESS;
+ return UNDEFINED;
+ } else {
+ typename ot::Orientation orientation = ot::eval(
+ static_cast<int_x2_type>(segment_end.x()) - static_cast<int_x2_type>(segment_start.x()),
+ static_cast<int_x2_type>(segment_end.y()) - static_cast<int_x2_type>(segment_start.y()),
+ static_cast<int_x2_type>(new_point.x()) - static_cast<int_x2_type>(site_point.x()),
+ static_cast<int_x2_type>(new_point.y()) - static_cast<int_x2_type>(site_point.y()));
+ if (orientation == ot::LEFT) {
+ if (!right_site.is_inverse())
+ return reverse_order ? LESS : UNDEFINED;
+ return reverse_order ? UNDEFINED : MORE;
+ }
+ }
+
+ fpt_type fast_left_expr = a * (dif_y + dif_x) * (dif_y - dif_x);
+ fpt_type fast_right_expr = (to_fpt(2.0) * b) * dif_x * dif_y;
+ typename ulp_cmp_type::Result expr_cmp =
+ ulp_cmp(fast_left_expr, fast_right_expr, 4);
+ if (expr_cmp != ulp_cmp_type::EQUAL) {
+ if ((expr_cmp == ulp_cmp_type::MORE) ^ reverse_order)
+ return reverse_order ? LESS : MORE;
+ return UNDEFINED;
+ }
+ return UNDEFINED;
+ }
+
+ private:
+ ulp_cmp_type ulp_cmp;
+ to_fpt_converter to_fpt;
+ };
+
+ template <typename Node>
+ class node_comparison_predicate {
+ public:
+ typedef Node node_type;
+ typedef typename Node::site_type site_type;
+ typedef typename site_type::coordinate_type coordinate_type;
+ typedef distance_predicate<site_type> distance_predicate_type;
+
+ // Compares nodes in the balanced binary search tree. Nodes are
+ // compared based on the y coordinates of the arcs intersection points.
+ // Nodes with less y coordinate of the intersection point go first.
+ // Comparison is only called during the new site events processing.
+ // That's why one of the nodes will always lie on the sweepline and may
+ // be represented as a straight horizontal line.
+ bool operator() (const node_type &node1,
+ const node_type &node2) const {
+ // Get x coordinate of the rightmost site from both nodes.
+ const site_type &site1 = get_comparison_site(node1);
+ const site_type &site2 = get_comparison_site(node2);
+
+ if (site1.x() < site2.x()) {
+ // The second node contains a new site.
+ return predicate_(node1.left_site(), node1.right_site(), site2);
+ } else if (site1.x() > site2.x()) {
+ // The first node contains a new site.
+ return !predicate_(node2.left_site(), node2.right_site(), site1);
+ } else {
+ // This checks were evaluated experimentally.
+ if (site1.index() == site2.index()) {
+ // Both nodes are new (inserted during same site event processing).
+ return get_comparison_y(node1) < get_comparison_y(node2);
+ } else if (site1.index() < site2.index()) {
+ std::pair<coordinate_type, int> y1 = get_comparison_y(node1, false);
+ std::pair<coordinate_type, int> y2 = get_comparison_y(node2, true);
+ if (y1.first != y2.first) return y1.first < y2.first;
+ return (!site1.is_segment()) ? (y1.second < 0) : false;
+ } else {
+ std::pair<coordinate_type, int> y1 = get_comparison_y(node1, true);
+ std::pair<coordinate_type, int> y2 = get_comparison_y(node2, false);
+ if (y1.first != y2.first) return y1.first < y2.first;
+ return (!site2.is_segment()) ? (y2.second > 0) : true;
+ }
+ }
+ }
+
+ private:
+ // Get the newer site.
+ const site_type &get_comparison_site(const node_type &node) const {
+ if (node.left_site().index() > node.right_site().index()) {
+ return node.left_site();
+ }
+ return node.right_site();
+ }
+
+ // Get comparison pair: y coordinate and direction of the newer site.
+ std::pair<coordinate_type, int> get_comparison_y(
+ const node_type &node, bool is_new_node = true) const {
+ if (node.left_site().index() == node.right_site().index()) {
+ return std::make_pair(node.left_site().y(), 0);
+ }
+ if (node.left_site().index() > node.right_site().index()) {
+ if (!is_new_node &&
+ node.left_site().is_segment() &&
+ is_vertical(node.left_site())) {
+ return std::make_pair(node.left_site().y1(), 1);
+ }
+ return std::make_pair(node.left_site().y(), 1);
+ }
+ return std::make_pair(node.right_site().y(), -1);
+ }
+
+ distance_predicate_type predicate_;
+ };
+
+ template <typename Site>
+ class circle_existence_predicate {
+ public:
+ typedef typename Site::point_type point_type;
+ typedef Site site_type;
+
+ bool ppp(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3) const {
+ return ot::eval(site1.point0(), site2.point0(), site3.point0()) ==
+ ot::RIGHT;
+ }
+
+ bool pps(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int segment_index) const {
+ if (segment_index != 2) {
+ typename ot::Orientation orient1 = ot::eval(site1.point0(),
+ site2.point0(), site3.point0(true));
+ typename ot::Orientation orient2 = ot::eval(site1.point0(),
+ site2.point0(), site3.point1(true));
+ if (segment_index == 1 && site1.x0() >= site2.x0()) {
+ if (orient1 != ot::RIGHT)
+ return false;
+ } else if (segment_index == 3 && site2.x0() >= site1.x0()) {
+ if (orient2 != ot::RIGHT)
+ return false;
+ } else if (orient1 != ot::RIGHT && orient2 != ot::RIGHT) {
+ return false;
+ }
+ } else {
+ if (site3.point0(true) == site1.point0() &&
+ site3.point1(true) == site2.point0())
+ return false;
+ }
+ return true;
+ }
+
+ bool pss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int point_index) const {
+ if (site2.point0() == site3.point0() &&
+ site2.point1() == site3.point1()) {
+ return false;
+ }
+ if (point_index == 2) {
+ if (!site2.is_inverse() && site3.is_inverse())
+ return false;
+ if (site2.is_inverse() == site3.is_inverse() &&
+ ot::eval(site2.point0(true),
+ site1.point0(),
+ site3.point1(true)) != ot::RIGHT)
+ return false;
+ }
+ return true;
+ }
+
+ bool sss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3) const {
+ if (site1.point0() == site2.point0() && site1.point1() == site2.point1())
+ return false;
+ if (site2.point0() == site3.point0() && site2.point1() == site3.point1())
+ return false;
+ return true;
+ }
+ };
+
+ template <typename Site, typename Circle>
+ class mp_circle_formation_functor {
+ public:
+ typedef typename Site::point_type point_type;
+ typedef Site site_type;
+ typedef Circle circle_type;
+ typedef robust_sqrt_expr<big_int_type, efpt_type, to_efpt_converter>
+ robust_sqrt_expr_type;
+
+ void ppp(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ circle_type &circle,
+ bool recompute_c_x = true,
+ bool recompute_c_y = true,
+ bool recompute_lower_x = true) {
+ big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2];
+ dif_x[0] = static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(site2.x());
+ dif_x[1] = static_cast<int_x2_type>(site2.x()) -
+ static_cast<int_x2_type>(site3.x());
+ dif_x[2] = static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(site3.x());
+ dif_y[0] = static_cast<int_x2_type>(site1.y()) -
+ static_cast<int_x2_type>(site2.y());
+ dif_y[1] = static_cast<int_x2_type>(site2.y()) -
+ static_cast<int_x2_type>(site3.y());
+ dif_y[2] = static_cast<int_x2_type>(site1.y()) -
+ static_cast<int_x2_type>(site3.y());
+ sum_x[0] = static_cast<int_x2_type>(site1.x()) +
+ static_cast<int_x2_type>(site2.x());
+ sum_x[1] = static_cast<int_x2_type>(site2.x()) +
+ static_cast<int_x2_type>(site3.x());
+ sum_y[0] = static_cast<int_x2_type>(site1.y()) +
+ static_cast<int_x2_type>(site2.y());
+ sum_y[1] = static_cast<int_x2_type>(site2.y()) +
+ static_cast<int_x2_type>(site3.y());
+ fpt_type inv_denom = to_fpt(0.5) / to_fpt(static_cast<big_int_type>(
+ dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0]));
+ big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0];
+ big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1];
+
+ if (recompute_c_x || recompute_lower_x) {
+ big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0];
+ circle.x(to_fpt(c_x) * inv_denom);
+
+ if (recompute_lower_x) {
+ // Evaluate radius of the circle.
+ big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) *
+ (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) *
+ (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]);
+ fpt_type r = get_sqrt(to_fpt(sqr_r));
+
+ // If c_x >= 0 then lower_x = c_x + r,
+ // else lower_x = (c_x * c_x - r * r) / (c_x - r).
+ // To guarantee epsilon relative error.
+ if (!is_neg(circle.x())) {
+ if (!is_neg(inv_denom)) {
+ circle.lower_x(circle.x() + r * inv_denom);
+ } else {
+ circle.lower_x(circle.x() - r * inv_denom);
+ }
+ } else {
+ big_int_type numer = c_x * c_x - sqr_r;
+ fpt_type lower_x = to_fpt(numer) * inv_denom / (to_fpt(c_x) + r);
+ circle.lower_x(lower_x);
+ }
+ }
+ }
+
+ if (recompute_c_y) {
+ big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1];
+ circle.y(to_fpt(c_y) * inv_denom);
+ }
+ }
+
+ // Recompute parameters of the circle event using high-precision library.
+ void pps(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int segment_index,
+ circle_type &c_event,
+ bool recompute_c_x = true,
+ bool recompute_c_y = true,
+ bool recompute_lower_x = true) {
+ big_int_type cA[4], cB[4];
+ big_int_type line_a = static_cast<int_x2_type>(site3.point1(true).y()) -
+ static_cast<int_x2_type>(site3.point0(true).y());
+ big_int_type line_b = static_cast<int_x2_type>(site3.point0(true).x()) -
+ static_cast<int_x2_type>(site3.point1(true).x());
+ big_int_type segm_len = line_a * line_a + line_b * line_b;
+ big_int_type vec_x = static_cast<int_x2_type>(site2.y()) -
+ static_cast<int_x2_type>(site1.y());
+ big_int_type vec_y = static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(site2.x());
+ big_int_type sum_x = static_cast<int_x2_type>(site1.x()) +
+ static_cast<int_x2_type>(site2.x());
+ big_int_type sum_y = static_cast<int_x2_type>(site1.y()) +
+ static_cast<int_x2_type>(site2.y());
+ big_int_type teta = line_a * vec_x + line_b * vec_y;
+ big_int_type denom = vec_x * line_b - vec_y * line_a;
+
+ big_int_type dif0 = static_cast<int_x2_type>(site3.point1().y()) -
+ static_cast<int_x2_type>(site1.y());
+ big_int_type dif1 = static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(site3.point1().x());
+ big_int_type A = line_a * dif1 - line_b * dif0;
+ dif0 = static_cast<int_x2_type>(site3.point1().y()) -
+ static_cast<int_x2_type>(site2.y());
+ dif1 = static_cast<int_x2_type>(site2.x()) -
+ static_cast<int_x2_type>(site3.point1().x());
+ big_int_type B = line_a * dif1 - line_b * dif0;
+ big_int_type sum_AB = A + B;
+
+ if (is_zero(denom)) {
+ big_int_type numer = teta * teta - sum_AB * sum_AB;
+ big_int_type denom = teta * sum_AB;
+ cA[0] = denom * sum_x * 2 + numer * vec_x;
+ cB[0] = segm_len;
+ cA[1] = denom * sum_AB * 2 + numer * teta;
+ cB[1] = 1;
+ cA[2] = denom * sum_y * 2 + numer * vec_y;
+ fpt_type inv_denom = to_fpt(1.0) / to_fpt(denom);
+ if (recompute_c_x)
+ c_event.x(to_fpt(0.25) * to_fpt(cA[0]) * inv_denom);
+ if (recompute_c_y)
+ c_event.y(to_fpt(0.25) * to_fpt(cA[2]) * inv_denom);
+ if (recompute_lower_x) {
+ c_event.lower_x(to_fpt(0.25) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
+ inv_denom / get_sqrt(to_fpt(segm_len)));
+ }
+ return;
+ }
+
+ big_int_type det = (teta * teta + denom * denom) * A * B * 4;
+ fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom);
+ inv_denom_sqr *= inv_denom_sqr;
+
+ if (recompute_c_x || recompute_lower_x) {
+ cA[0] = sum_x * denom * denom + teta * sum_AB * vec_x;
+ cB[0] = 1;
+ cA[1] = (segment_index == 2) ? -vec_x : vec_x;
+ cB[1] = det;
+ if (recompute_c_x) {
+ c_event.x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
+ inv_denom_sqr);
+ }
+ }
+
+ if (recompute_c_y || recompute_lower_x) {
+ cA[2] = sum_y * denom * denom + teta * sum_AB * vec_y;
+ cB[2] = 1;
+ cA[3] = (segment_index == 2) ? -vec_y : vec_y;
+ cB[3] = det;
+ if (recompute_c_y) {
+ c_event.y(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(&cA[2], &cB[2])) *
+ inv_denom_sqr);
+ }
+ }
+
+ if (recompute_lower_x) {
+ cB[0] = cB[0] * segm_len;
+ cB[1] = cB[1] * segm_len;
+ cA[2] = sum_AB * (denom * denom + teta * teta);
+ cB[2] = 1;
+ cA[3] = (segment_index == 2) ? -teta : teta;
+ cB[3] = det;
+ c_event.lower_x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval4(cA, cB)) *
+ inv_denom_sqr / get_sqrt(to_fpt(segm_len)));
+ }
+ }
+
+ // Recompute parameters of the circle event using high-precision library.
+ void pss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int point_index,
+ circle_type &c_event,
+ bool recompute_c_x = true,
+ bool recompute_c_y = true,
+ bool recompute_lower_x = true) {
+ big_int_type a[2], b[2], c[2], cA[4], cB[4];
+ const point_type &segm_start1 = site2.point1(true);
+ const point_type &segm_end1 = site2.point0(true);
+ const point_type &segm_start2 = site3.point0(true);
+ const point_type &segm_end2 = site3.point1(true);
+ a[0] = static_cast<int_x2_type>(segm_end1.x()) -
+ static_cast<int_x2_type>(segm_start1.x());
+ b[0] = static_cast<int_x2_type>(segm_end1.y()) -
+ static_cast<int_x2_type>(segm_start1.y());
+ a[1] = static_cast<int_x2_type>(segm_end2.x()) -
+ static_cast<int_x2_type>(segm_start2.x());
+ b[1] = static_cast<int_x2_type>(segm_end2.y()) -
+ static_cast<int_x2_type>(segm_start2.y());
+ big_int_type orientation = a[1] * b[0] - a[0] * b[1];
+ if (is_zero(orientation)) {
+ fpt_type denom = to_fpt(2.0) * to_fpt(
+ static_cast<big_int_type>(a[0] * a[0] + b[0] * b[0]));
+ c[0] = b[0] * (static_cast<int_x2_type>(segm_start2.x()) -
+ static_cast<int_x2_type>(segm_start1.x())) -
+ a[0] * (static_cast<int_x2_type>(segm_start2.y()) -
+ static_cast<int_x2_type>(segm_start1.y()));
+ big_int_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) -
+ static_cast<int_x2_type>(segm_start1.y())) -
+ b[0] * (static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(segm_start1.x()));
+ big_int_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) -
+ static_cast<int_x2_type>(segm_start2.x())) -
+ a[0] * (static_cast<int_x2_type>(site1.y()) -
+ static_cast<int_x2_type>(segm_start2.y()));
+ cB[0] = dx * dy;
+ cB[1] = 1;
+
+ if (recompute_c_y) {
+ cA[0] = b[0] * ((point_index == 2) ? 2 : -2);
+ cA[1] = a[0] * a[0] * (static_cast<int_x2_type>(segm_start1.y()) +
+ static_cast<int_x2_type>(segm_start2.y())) -
+ a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
+ static_cast<int_x2_type>(segm_start2.x()) -
+ static_cast<int_x2_type>(site1.x()) * 2) +
+ b[0] * b[0] * (static_cast<int_x2_type>(site1.y()) * 2);
+ fpt_type c_y = to_fpt(sqrt_expr_.eval2(cA, cB));
+ c_event.y(c_y / denom);
+ }
+
+ if (recompute_c_x || recompute_lower_x) {
+ cA[0] = a[0] * ((point_index == 2) ? 2 : -2);
+ cA[1] = b[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
+ static_cast<int_x2_type>(segm_start2.x())) -
+ a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.y()) +
+ static_cast<int_x2_type>(segm_start2.y()) -
+ static_cast<int_x2_type>(site1.y()) * 2) +
+ a[0] * a[0] * (static_cast<int_x2_type>(site1.x()) * 2);
+
+ if (recompute_c_x) {
+ fpt_type c_x = to_fpt(sqrt_expr_.eval2(cA, cB));
+ c_event.x(c_x / denom);
+ }
+
+ if (recompute_lower_x) {
+ cA[2] = is_neg(c[0]) ? -c[0] : c[0];
+ cB[2] = a[0] * a[0] + b[0] * b[0];
+ fpt_type lower_x = to_fpt(sqrt_expr_.eval3(cA, cB));
+ c_event.lower_x(lower_x / denom);
+ }
+ }
+ return;
+ }
+ c[0] = b[0] * segm_end1.x() - a[0] * segm_end1.y();
+ c[1] = a[1] * segm_end2.y() - b[1] * segm_end2.x();
+ big_int_type ix = a[0] * c[1] + a[1] * c[0];
+ big_int_type iy = b[0] * c[1] + b[1] * c[0];
+ big_int_type dx = ix - orientation * site1.x();
+ big_int_type dy = iy - orientation * site1.y();
+ if (is_zero(dx) && is_zero(dy)) {
+ fpt_type denom = to_fpt(orientation);
+ fpt_type c_x = to_fpt(ix) / denom;
+ fpt_type c_y = to_fpt(iy) / denom;
+ c_event = circle_type(c_x, c_y, c_x);
+ return;
+ }
+
+ big_int_type sign = ((point_index == 2) ? 1 : -1) *
+ (is_neg(orientation) ? 1 : -1);
+ cA[0] = a[1] * -dx + b[1] * -dy;
+ cA[1] = a[0] * -dx + b[0] * -dy;
+ cA[2] = sign;
+ cA[3] = 0;
+ cB[0] = a[0] * a[0] + b[0] * b[0];
+ cB[1] = a[1] * a[1] + b[1] * b[1];
+ cB[2] = a[0] * a[1] + b[0] * b[1];
+ cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2;
+ fpt_type temp = to_fpt(
+ sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
+ fpt_type denom = temp * to_fpt(orientation);
+
+ if (recompute_c_y) {
+ cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]);
+ cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]);
+ cA[2] = iy * sign;
+ fpt_type cy = to_fpt(
+ sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
+ c_event.y(cy / denom);
+ }
+
+ if (recompute_c_x || recompute_lower_x) {
+ cA[0] = a[1] * (dx * dx + dy * dy) - ix * (dx * a[1] + dy * b[1]);
+ cA[1] = a[0] * (dx * dx + dy * dy) - ix * (dx * a[0] + dy * b[0]);
+ cA[2] = ix * sign;
+
+ if (recompute_c_x) {
+ fpt_type cx = to_fpt(
+ sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
+ c_event.x(cx / denom);
+ }
+
+ if (recompute_lower_x) {
+ cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1);
+ fpt_type lower_x = to_fpt(
+ sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
+ c_event.lower_x(lower_x / denom);
+ }
+ }
+ }
+
+ // Recompute parameters of the circle event using high-precision library.
+ void sss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ circle_type &c_event,
+ bool recompute_c_x = true,
+ bool recompute_c_y = true,
+ bool recompute_lower_x = true) {
+ big_int_type a[3], b[3], c[3], cA[4], cB[4];
+ // cA - corresponds to the cross product.
+ // cB - corresponds to the squared length.
+ a[0] = static_cast<int_x2_type>(site1.x1(true)) -
+ static_cast<int_x2_type>(site1.x0(true));
+ a[1] = static_cast<int_x2_type>(site2.x1(true)) -
+ static_cast<int_x2_type>(site2.x0(true));
+ a[2] = static_cast<int_x2_type>(site3.x1(true)) -
+ static_cast<int_x2_type>(site3.x0(true));
+
+ b[0] = static_cast<int_x2_type>(site1.y1(true)) -
+ static_cast<int_x2_type>(site1.y0(true));
+ b[1] = static_cast<int_x2_type>(site2.y1(true)) -
+ static_cast<int_x2_type>(site2.y0(true));
+ b[2] = static_cast<int_x2_type>(site3.y1(true)) -
+ static_cast<int_x2_type>(site3.y0(true));
+
+ c[0] = static_cast<int_x2_type>(site1.x0(true)) *
+ static_cast<int_x2_type>(site1.y1(true)) -
+ static_cast<int_x2_type>(site1.y0(true)) *
+ static_cast<int_x2_type>(site1.x1(true));
+ c[1] = static_cast<int_x2_type>(site2.x0(true)) *
+ static_cast<int_x2_type>(site2.y1(true)) -
+ static_cast<int_x2_type>(site2.y0(true)) *
+ static_cast<int_x2_type>(site2.x1(true));
+ c[2] = static_cast<int_x2_type>(site3.x0(true)) *
+ static_cast<int_x2_type>(site3.y1(true)) -
+ static_cast<int_x2_type>(site3.y0(true)) *
+ static_cast<int_x2_type>(site3.x1(true));
+
+ for (int i = 0; i < 3; ++i)
+ cB[i] = a[i] * a[i] + b[i] * b[i];
+
+ for (int i = 0; i < 3; ++i) {
+ int j = (i+1) % 3;
+ int k = (i+2) % 3;
+ cA[i] = a[j] * b[k] - a[k] * b[j];
+ }
+ fpt_type denom = to_fpt(sqrt_expr_.eval3(cA, cB));
+
+ if (recompute_c_y) {
+ for (int i = 0; i < 3; ++i) {
+ int j = (i+1) % 3;
+ int k = (i+2) % 3;
+ cA[i] = b[j] * c[k] - b[k] * c[j];
+ }
+ fpt_type c_y = to_fpt(sqrt_expr_.eval3(cA, cB));
+ c_event.y(c_y / denom);
+ }
+
+ if (recompute_c_x || recompute_lower_x) {
+ cA[3] = 0;
+ for (int i = 0; i < 3; ++i) {
+ int j = (i+1) % 3;
+ int k = (i+2) % 3;
+ cA[i] = a[j] * c[k] - a[k] * c[j];
+ if (recompute_lower_x) {
+ cA[3] = cA[3] + cA[i] * b[i];
+ }
+ }
+
+ if (recompute_c_x) {
+ fpt_type c_x = to_fpt(sqrt_expr_.eval3(cA, cB));
+ c_event.x(c_x / denom);
+ }
+
+ if (recompute_lower_x) {
+ cB[3] = 1;
+ fpt_type lower_x = to_fpt(sqrt_expr_.eval4(cA, cB));
+ c_event.lower_x(lower_x / denom);
+ }
+ }
+ }
+
+ private:
+ // Evaluates A[3] + A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
+ // A[2] * sqrt(B[3] * (sqrt(B[0] * B[1]) + B[2])).
+ template <typename _int, typename _fpt>
+ _fpt sqrt_expr_evaluator_pss4(_int *A, _int *B) {
+ _int cA[4], cB[4];
+ if (is_zero(A[3])) {
+ _fpt lh = sqrt_expr_.eval2(A, B);
+ cA[0] = 1;
+ cB[0] = B[0] * B[1];
+ cA[1] = B[2];
+ cB[1] = 1;
+ _fpt rh = sqrt_expr_.eval1(A+2, B+3) *
+ get_sqrt(sqrt_expr_.eval2(cA, cB));
+ if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
+ return lh + rh;
+ cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
+ A[2] * A[2] * B[3] * B[2];
+ cB[0] = 1;
+ cA[1] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
+ cB[1] = B[0] * B[1];
+ _fpt numer = sqrt_expr_.eval2(cA, cB);
+ return numer / (lh - rh);
+ }
+ cA[0] = 1;
+ cB[0] = B[0] * B[1];
+ cA[1] = B[2];
+ cB[1] = 1;
+ _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB));
+ cA[0] = A[0];
+ cB[0] = B[0];
+ cA[1] = A[1];
+ cB[1] = B[1];
+ cA[2] = A[3];
+ cB[2] = 1;
+ _fpt lh = sqrt_expr_.eval3(cA, cB);
+ if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
+ return lh + rh;
+ cA[0] = A[3] * A[0] * 2;
+ cA[1] = A[3] * A[1] * 2;
+ cA[2] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] +
+ A[3] * A[3] - A[2] * A[2] * B[2] * B[3];
+ cA[3] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
+ cB[3] = B[0] * B[1];
+ _fpt numer = sqrt_expr_evaluator_pss3<_int, _fpt>(cA, cB);
+ return numer / (lh - rh);
+ }
+
+ template <typename _int, typename _fpt>
+ // Evaluates A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
+ // A[2] + A[3] * sqrt(B[0] * B[1]).
+ // B[3] = B[0] * B[1].
+ _fpt sqrt_expr_evaluator_pss3(_int *A, _int *B) {
+ _int cA[2], cB[2];
+ _fpt lh = sqrt_expr_.eval2(A, B);
+ _fpt rh = sqrt_expr_.eval2(A+2, B+2);
+ if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
+ return lh + rh;
+ cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
+ A[2] * A[2] - A[3] * A[3] * B[0] * B[1];
+ cB[0] = 1;
+ cA[1] = (A[0] * A[1] - A[2] * A[3]) * 2;
+ cB[1] = B[3];
+ _fpt numer = sqrt_expr_.eval2(cA, cB);
+ return numer / (lh - rh);
+ }
+
+ robust_sqrt_expr_type sqrt_expr_;
+ to_fpt_converter to_fpt;
+ };
+
+ template <typename Site, typename Circle>
+ class lazy_circle_formation_functor {
+ public:
+ typedef robust_fpt<fpt_type> robust_fpt_type;
+ typedef robust_dif<robust_fpt_type> robust_dif_type;
+ typedef typename Site::point_type point_type;
+ typedef Site site_type;
+ typedef Circle circle_type;
+ typedef mp_circle_formation_functor<site_type, circle_type>
+ exact_circle_formation_functor_type;
+
+ void ppp(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ circle_type &c_event) {
+ fpt_type dif_x1 = to_fpt(site1.x()) - to_fpt(site2.x());
+ fpt_type dif_x2 = to_fpt(site2.x()) - to_fpt(site3.x());
+ fpt_type dif_y1 = to_fpt(site1.y()) - to_fpt(site2.y());
+ fpt_type dif_y2 = to_fpt(site2.y()) - to_fpt(site3.y());
+ fpt_type orientation = robust_cross_product(
+ static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()),
+ static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site3.x()),
+ static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(site2.y()),
+ static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site3.y()));
+ robust_fpt_type inv_orientation(to_fpt(0.5) / orientation, to_fpt(2.0));
+ fpt_type sum_x1 = to_fpt(site1.x()) + to_fpt(site2.x());
+ fpt_type sum_x2 = to_fpt(site2.x()) + to_fpt(site3.x());
+ fpt_type sum_y1 = to_fpt(site1.y()) + to_fpt(site2.y());
+ fpt_type sum_y2 = to_fpt(site2.y()) + to_fpt(site3.y());
+ fpt_type dif_x3 = to_fpt(site1.x()) - to_fpt(site3.x());
+ fpt_type dif_y3 = to_fpt(site1.y()) - to_fpt(site3.y());
+ robust_dif_type c_x, c_y;
+ c_x += robust_fpt_type(dif_x1 * sum_x1 * dif_y2, to_fpt(2.0));
+ c_x += robust_fpt_type(dif_y1 * sum_y1 * dif_y2, to_fpt(2.0));
+ c_x -= robust_fpt_type(dif_x2 * sum_x2 * dif_y1, to_fpt(2.0));
+ c_x -= robust_fpt_type(dif_y2 * sum_y2 * dif_y1, to_fpt(2.0));
+ c_y += robust_fpt_type(dif_x2 * sum_x2 * dif_x1, to_fpt(2.0));
+ c_y += robust_fpt_type(dif_y2 * sum_y2 * dif_x1, to_fpt(2.0));
+ c_y -= robust_fpt_type(dif_x1 * sum_x1 * dif_x2, to_fpt(2.0));
+ c_y -= robust_fpt_type(dif_y1 * sum_y1 * dif_x2, to_fpt(2.0));
+ robust_dif_type lower_x(c_x);
+ lower_x -= robust_fpt_type(get_sqrt(
+ (dif_x1 * dif_x1 + dif_y1 * dif_y1) *
+ (dif_x2 * dif_x2 + dif_y2 * dif_y2) *
+ (dif_x3 * dif_x3 + dif_y3 * dif_y3)), to_fpt(5.0));
+ c_event = circle_type(
+ c_x.dif().fpv() * inv_orientation.fpv(),
+ c_y.dif().fpv() * inv_orientation.fpv(),
+ lower_x.dif().fpv() * inv_orientation.fpv());
+ bool recompute_c_x = c_x.dif().ulp() > ULPS;
+ bool recompute_c_y = c_y.dif().ulp() > ULPS;
+ bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
+ if (recompute_c_x || recompute_c_y || recompute_lower_x) {
+ exact_circle_formation_functor_.ppp(
+ site1, site2, site3, c_event,
+ recompute_c_x, recompute_c_y, recompute_lower_x);
+ }
+ }
+
+ void pps(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int segment_index,
+ circle_type &c_event) {
+ fpt_type line_a = to_fpt(site3.point1(true).y()) -
+ to_fpt(site3.point0(true).y());
+ fpt_type line_b = to_fpt(site3.point0(true).x()) -
+ to_fpt(site3.point1(true).x());
+ fpt_type vec_x = to_fpt(site2.y()) - to_fpt(site1.y());
+ fpt_type vec_y = to_fpt(site1.x()) - to_fpt(site2.x());
+ robust_fpt_type teta(robust_cross_product(
+ static_cast<int_x2_type>(site3.point1(true).y()) - static_cast<int_x2_type>(site3.point0(true).y()),
+ static_cast<int_x2_type>(site3.point0(true).x()) - static_cast<int_x2_type>(site3.point1(true).x()),
+ static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site1.x()),
+ static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
+ robust_fpt_type A(robust_cross_product(
+ static_cast<int_x2_type>(site3.point1(true).y()) - static_cast<int_x2_type>(site3.point0(true).y()),
+ static_cast<int_x2_type>(site3.point0(true).x()) - static_cast<int_x2_type>(site3.point1(true).x()),
+ static_cast<int_x2_type>(site3.point1().y()) - static_cast<int_x2_type>(site1.y()),
+ static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site3.point1().x())), to_fpt(1.0));
+ robust_fpt_type B(robust_cross_product(
+ static_cast<int_x2_type>(site3.point1(true).y()) - static_cast<int_x2_type>(site3.point0(true).y()),
+ static_cast<int_x2_type>(site3.point0(true).x()) - static_cast<int_x2_type>(site3.point1(true).x()),
+ static_cast<int_x2_type>(site3.point1().y()) - static_cast<int_x2_type>(site2.y()),
+ static_cast<int_x2_type>(site2.x()) - static_cast<int_x2_type>(site3.point1().x())), to_fpt(1.0));
+ robust_fpt_type denom(robust_cross_product(
+ static_cast<int_x2_type>(site2.y()) - static_cast<int_x2_type>(site1.y()),
+ static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(site2.x()),
+ static_cast<int_x2_type>(site3.point1(true).y()) - static_cast<int_x2_type>(site3.point0(true).y()),
+ static_cast<int_x2_type>(site3.point0(true).x()) - static_cast<int_x2_type>(site3.point1(true).x())), to_fpt(1.0));
+ robust_fpt_type inv_segm_len(to_fpt(1.0) /
+ get_sqrt(line_a * line_a + line_b * line_b), to_fpt(3.0));
+ robust_dif_type t;
+ if (ot::eval(denom) == ot::COLLINEAR) {
+ t += teta / (robust_fpt_type(to_fpt(8.0)) * A);
+ t -= A / (robust_fpt_type(to_fpt(2.0)) * teta);
+ } else {
+ robust_fpt_type det = ((teta * teta + denom * denom) * A * B).sqrt();
+ if (segment_index == 2) {
+ t -= det / (denom * denom);
+ } else {
+ t += det / (denom * denom);
+ }
+ t += teta * (A + B) / (robust_fpt_type(to_fpt(2.0)) * denom * denom);
+ }
+ robust_dif_type c_x, c_y;
+ c_x += robust_fpt_type(to_fpt(0.5) * (to_fpt(site1.x()) +
+ to_fpt(site2.x())));
+ c_x += robust_fpt_type(vec_x) * t;
+ c_y += robust_fpt_type(to_fpt(0.5) * (to_fpt(site1.y()) +
+ to_fpt(site2.y())));
+ c_y += robust_fpt_type(vec_y) * t;
+ robust_dif_type r, lower_x(c_x);
+ r -= robust_fpt_type(line_a) * robust_fpt_type(site3.x0());
+ r -= robust_fpt_type(line_b) * robust_fpt_type(site3.y0());
+ r += robust_fpt_type(line_a) * c_x;
+ r += robust_fpt_type(line_b) * c_y;
+ if (r.pos().fpv() < r.neg().fpv())
+ r = -r;
+ lower_x += r * inv_segm_len;
+ c_event = circle_type(
+ c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
+ bool recompute_c_x = c_x.dif().ulp() > ULPS;
+ bool recompute_c_y = c_y.dif().ulp() > ULPS;
+ bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
+ if (recompute_c_x || recompute_c_y || recompute_lower_x) {
+ exact_circle_formation_functor_.pps(
+ site1, site2, site3, segment_index, c_event,
+ recompute_c_x, recompute_c_y, recompute_lower_x);
+ }
+ }
+
+ void pss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ int point_index,
+ circle_type &c_event) {
+ const point_type &segm_start1 = site2.point1(true);
+ const point_type &segm_end1 = site2.point0(true);
+ const point_type &segm_start2 = site3.point0(true);
+ const point_type &segm_end2 = site3.point1(true);
+ fpt_type a1 = to_fpt(segm_end1.x()) - to_fpt(segm_start1.x());
+ fpt_type b1 = to_fpt(segm_end1.y()) - to_fpt(segm_start1.y());
+ fpt_type a2 = to_fpt(segm_end2.x()) - to_fpt(segm_start2.x());
+ fpt_type b2 = to_fpt(segm_end2.y()) - to_fpt(segm_start2.y());
+ bool recompute_c_x, recompute_c_y, recompute_lower_x;
+ robust_fpt_type orientation(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()),
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
+ if (ot::eval(orientation) == ot::COLLINEAR) {
+ robust_fpt_type a(a1 * a1 + b1 * b1, to_fpt(2.0));
+ robust_fpt_type c(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_start2.x()) - static_cast<int_x2_type>(segm_start1.x())), to_fpt(1.0));
+ robust_fpt_type det(
+ robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start1.y())) *
+ robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(site1.y()) - static_cast<int_x2_type>(segm_start2.y()),
+ static_cast<int_x2_type>(site1.x()) - static_cast<int_x2_type>(segm_start2.x())),
+ to_fpt(3.0));
+ robust_dif_type t;
+ t -= robust_fpt_type(a1) * robust_fpt_type((
+ to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())) * to_fpt(0.5) -
+ to_fpt(site1.x()));
+ t -= robust_fpt_type(b1) * robust_fpt_type((
+ to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())) * to_fpt(0.5) -
+ to_fpt(site1.y()));
+ if (point_index == 2) {
+ t += det.sqrt();
+ } else {
+ t -= det.sqrt();
+ }
+ t /= a;
+ robust_dif_type c_x, c_y;
+ c_x += robust_fpt_type(to_fpt(0.5) * (
+ to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())));
+ c_x += robust_fpt_type(a1) * t;
+ c_y += robust_fpt_type(to_fpt(0.5) * (
+ to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())));
+ c_y += robust_fpt_type(b1) * t;
+ robust_dif_type lower_x(c_x);
+ if (is_neg(c)) {
+ lower_x -= robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
+ } else {
+ lower_x += robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
+ }
+ recompute_c_x = c_x.dif().ulp() > ULPS;
+ recompute_c_y = c_y.dif().ulp() > ULPS;
+ recompute_lower_x = lower_x.dif().ulp() > ULPS;
+ c_event =
+ circle_type(c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
+ } else {
+ robust_fpt_type sqr_sum1(get_sqrt(a1 * a1 + b1 * b1), to_fpt(2.0));
+ robust_fpt_type sqr_sum2(get_sqrt(a2 * a2 + b2 * b2), to_fpt(2.0));
+ robust_fpt_type a(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_start2.y()) - static_cast<int_x2_type>(segm_end2.y()),
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
+ if (!is_neg(a)) {
+ a += sqr_sum1 * sqr_sum2;
+ } else {
+ a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a);
+ }
+ robust_fpt_type or1(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(site1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
+ robust_fpt_type or2(robust_cross_product(
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()),
+ static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()),
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(site1.x()),
+ static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
+ robust_fpt_type det = robust_fpt_type(to_fpt(2.0)) * a * or1 * or2;
+ robust_fpt_type c1(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end1.y()),
+ static_cast<int_x2_type>(segm_end1.x())), to_fpt(1.0));
+ robust_fpt_type c2(robust_cross_product(
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()),
+ static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()),
+ static_cast<int_x2_type>(segm_end2.x()),
+ static_cast<int_x2_type>(segm_end2.y())), to_fpt(1.0));
+ robust_fpt_type inv_orientation = robust_fpt_type(to_fpt(1.0)) / orientation;
+ robust_dif_type t, b, ix, iy;
+ ix += robust_fpt_type(a2) * c1 * inv_orientation;
+ ix += robust_fpt_type(a1) * c2 * inv_orientation;
+ iy += robust_fpt_type(b1) * c2 * inv_orientation;
+ iy += robust_fpt_type(b2) * c1 * inv_orientation;
+
+ b += ix * (robust_fpt_type(a1) * sqr_sum2);
+ b += ix * (robust_fpt_type(a2) * sqr_sum1);
+ b += iy * (robust_fpt_type(b1) * sqr_sum2);
+ b += iy * (robust_fpt_type(b2) * sqr_sum1);
+ b -= sqr_sum1 * robust_fpt_type(robust_cross_product(
+ static_cast<int_x2_type>(segm_end2.x()) - static_cast<int_x2_type>(segm_start2.x()),
+ static_cast<int_x2_type>(segm_end2.y()) - static_cast<int_x2_type>(segm_start2.y()),
+ static_cast<int_x2_type>(-site1.y()),
+ static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
+ b -= sqr_sum2 * robust_fpt_type(robust_cross_product(
+ static_cast<int_x2_type>(segm_end1.x()) - static_cast<int_x2_type>(segm_start1.x()),
+ static_cast<int_x2_type>(segm_end1.y()) - static_cast<int_x2_type>(segm_start1.y()),
+ static_cast<int_x2_type>(-site1.y()),
+ static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
+ t -= b;
+ if (point_index == 2) {
+ t += det.sqrt();
+ } else {
+ t -= det.sqrt();
+ }
+ t /= (a * a);
+ robust_dif_type c_x(ix), c_y(iy);
+ c_x += t * (robust_fpt_type(a1) * sqr_sum2);
+ c_x += t * (robust_fpt_type(a2) * sqr_sum1);
+ c_y += t * (robust_fpt_type(b1) * sqr_sum2);
+ c_y += t * (robust_fpt_type(b2) * sqr_sum1);
+ if (t.pos().fpv() < t.neg().fpv()) {
+ t = -t;
+ }
+ robust_dif_type lower_x(c_x);
+ if (is_neg(orientation)) {
+ lower_x -= t * orientation;
+ } else {
+ lower_x += t * orientation;
+ }
+ recompute_c_x = c_x.dif().ulp() > ULPS;
+ recompute_c_y = c_y.dif().ulp() > ULPS;
+ recompute_lower_x = lower_x.dif().ulp() > ULPS;
+ c_event = circle_type(
+ c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
+ }
+ if (recompute_c_x || recompute_c_y || recompute_lower_x) {
+ exact_circle_formation_functor_.pss(
+ site1, site2, site3, point_index, c_event,
+ recompute_c_x, recompute_c_y, recompute_lower_x);
+ }
+ }
+
+ void sss(const site_type &site1,
+ const site_type &site2,
+ const site_type &site3,
+ circle_type &c_event) {
+ robust_fpt_type a1(to_fpt(site1.x1(true)) - to_fpt(site1.x0(true)));
+ robust_fpt_type b1(to_fpt(site1.y1(true)) - to_fpt(site1.y0(true)));
+ robust_fpt_type c1(robust_cross_product(
+ site1.x0(true), site1.y0(true),
+ site1.x1(true), site1.y1(true)), to_fpt(1.0));
+
+ robust_fpt_type a2(to_fpt(site2.x1(true)) - to_fpt(site2.x0(true)));
+ robust_fpt_type b2(to_fpt(site2.y1(true)) - to_fpt(site2.y0(true)));
+ robust_fpt_type c2(robust_cross_product(
+ site2.x0(true), site2.y0(true),
+ site2.x1(true), site2.y1(true)), to_fpt(1.0));
+
+ robust_fpt_type a3(to_fpt(site3.x1(true)) - to_fpt(site3.x0(true)));
+ robust_fpt_type b3(to_fpt(site3.y1(true)) - to_fpt(site3.y0(true)));
+ robust_fpt_type c3(robust_cross_product(
+ site3.x0(true), site3.y0(true),
+ site3.x1(true), site3.y1(true)), to_fpt(1.0));
+
+ robust_fpt_type len1 = (a1 * a1 + b1 * b1).sqrt();
+ robust_fpt_type len2 = (a2 * a2 + b2 * b2).sqrt();
+ robust_fpt_type len3 = (a3 * a3 + b3 * b3).sqrt();
+ robust_fpt_type cross_12(robust_cross_product(
+ static_cast<int_x2_type>(site1.x1(true)) - static_cast<int_x2_type>(site1.x0(true)),
+ static_cast<int_x2_type>(site1.y1(true)) - static_cast<int_x2_type>(site1.y0(true)),
+ static_cast<int_x2_type>(site2.x1(true)) - static_cast<int_x2_type>(site2.x0(true)),
+ static_cast<int_x2_type>(site2.y1(true)) - static_cast<int_x2_type>(site2.y0(true))), to_fpt(1.0));
+ robust_fpt_type cross_23(robust_cross_product(
+ static_cast<int_x2_type>(site2.x1(true)) - static_cast<int_x2_type>(site2.x0(true)),
+ static_cast<int_x2_type>(site2.y1(true)) - static_cast<int_x2_type>(site2.y0(true)),
+ static_cast<int_x2_type>(site3.x1(true)) - static_cast<int_x2_type>(site3.x0(true)),
+ static_cast<int_x2_type>(site3.y1(true)) - static_cast<int_x2_type>(site3.y0(true))), to_fpt(1.0));
+ robust_fpt_type cross_31(robust_cross_product(
+ static_cast<int_x2_type>(site3.x1(true)) - static_cast<int_x2_type>(site3.x0(true)),
+ static_cast<int_x2_type>(site3.y1(true)) - static_cast<int_x2_type>(site3.y0(true)),
+ static_cast<int_x2_type>(site1.x1(true)) - static_cast<int_x2_type>(site1.x0(true)),
+ static_cast<int_x2_type>(site1.y1(true)) - static_cast<int_x2_type>(site1.y0(true))), to_fpt(1.0));
+ robust_dif_type denom, c_x, c_y, r;
+
+ // denom = cross_12 * len3 + cross_23 * len1 + cross_31 * len2.
+ denom += cross_12 * len3;
+ denom += cross_23 * len1;
+ denom += cross_31 * len2;
+
+ // denom * r = (b2 * c_x - a2 * c_y - c2 * denom) / len2.
+ r -= cross_12 * c3;
+ r -= cross_23 * c1;
+ r -= cross_31 * c2;
+
+ 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;
+ robust_dif_type lower_x(c_x + r);
+ bool recompute_c_x = c_x.dif().ulp() > ULPS;
+ bool recompute_c_y = c_y.dif().ulp() > ULPS;
+ bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
+ bool recompute_denom = denom.dif().ulp() > ULPS;
+ c_event = circle_type(
+ c_x.dif().fpv() / denom.dif().fpv(),
+ c_y.dif().fpv() / denom.dif().fpv(),
+ lower_x.dif().fpv() / denom.dif().fpv());
+ if (recompute_c_x || recompute_c_y ||
+ recompute_lower_x || recompute_denom) {
+ exact_circle_formation_functor_.sss(
+ site1, site2, site3, c_event,
+ recompute_c_x, recompute_c_y, recompute_lower_x);
+ }
+ }
+
+ private:
+ exact_circle_formation_functor_type exact_circle_formation_functor_;
+ to_fpt_converter to_fpt;
+ };
+
+ template <typename Site,
+ typename Circle,
+ typename CEP = circle_existence_predicate<Site>,
+ typename CFF = lazy_circle_formation_functor<Site, Circle> >
+ class circle_formation_predicate {
+ public:
+ typedef Site site_type;
+ typedef Circle circle_type;
+ typedef CEP circle_existence_predicate_type;
+ typedef CFF circle_formation_functor_type;
+
+ // Create a circle event from the given three sites.
+ // Returns true if the circle event exists, else false.
+ // If exists circle event is saved into the c_event variable.
+ bool operator()(const site_type &site1, const site_type &site2,
+ const site_type &site3, circle_type &circle) {
+ if (!site1.is_segment()) {
+ if (!site2.is_segment()) {
+ if (!site3.is_segment()) {
+ // (point, point, point) sites.
+ if (!circle_existence_predicate_.ppp(site1, site2, site3))
+ return false;
+ circle_formation_functor_.ppp(site1, site2, site3, circle);
+ } else {
+ // (point, point, segment) sites.
+ if (!circle_existence_predicate_.pps(site1, site2, site3, 3))
+ return false;
+ circle_formation_functor_.pps(site1, site2, site3, 3, circle);
+ }
+ } else {
+ if (!site3.is_segment()) {
+ // (point, segment, point) sites.
+ if (!circle_existence_predicate_.pps(site1, site3, site2, 2))
+ return false;
+ circle_formation_functor_.pps(site1, site3, site2, 2, circle);
+ } else {
+ // (point, segment, segment) sites.
+ if (!circle_existence_predicate_.pss(site1, site2, site3, 1))
+ return false;
+ circle_formation_functor_.pss(site1, site2, site3, 1, circle);
+ }
+ }
+ } else {
+ if (!site2.is_segment()) {
+ if (!site3.is_segment()) {
+ // (segment, point, point) sites.
+ if (!circle_existence_predicate_.pps(site2, site3, site1, 1))
+ return false;
+ circle_formation_functor_.pps(site2, site3, site1, 1, circle);
+ } else {
+ // (segment, point, segment) sites.
+ if (!circle_existence_predicate_.pss(site2, site1, site3, 2))
+ return false;
+ circle_formation_functor_.pss(site2, site1, site3, 2, circle);
+ }
+ } else {
+ if (!site3.is_segment()) {
+ // (segment, segment, point) sites.
+ if (!circle_existence_predicate_.pss(site3, site1, site2, 3))
+ return false;
+ circle_formation_functor_.pss(site3, site1, site2, 3, circle);
+ } else {
+ // (segment, segment, segment) sites.
+ if (!circle_existence_predicate_.sss(site1, site2, site3))
+ return false;
+ circle_formation_functor_.sss(site1, site2, site3, circle);
+ }
+ }
+ }
+ return true;
+ }
+
+ private:
+ circle_existence_predicate_type circle_existence_predicate_;
+ circle_formation_functor_type circle_formation_functor_;
+ };
+};
+} // detail
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_DETAIL_VORONOI_PREDICATES

Added: trunk/boost/polygon/detail/voronoi_robust_fpt.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/detail/voronoi_robust_fpt.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,515 @@
+// Boost.Polygon library detail/voronoi_robust_fpt.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
+#define BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT
+
+#include <cmath>
+
+// Geometry predicates with floating-point variables usually require
+// high-precision predicates to retrieve the correct result.
+// Epsilon robust predicates give the result within some epsilon relative
+// error, but are a lot faster than high-precision predicates.
+// To make algorithm robust and efficient epsilon robust predicates are
+// used at the first step. In case of the undefined result high-precision
+// arithmetic is used to produce required robustness. This approach
+// requires exact computation of epsilon intervals within which epsilon
+// robust predicates have undefined value.
+// There are two ways to measure an error of floating-point calculations:
+// relative error and ULPs (units in the last place).
+// Let EPS be machine epsilon, then next inequalities have place:
+// 1 EPS <= 1 ULP <= 2 EPS (1), 0.5 ULP <= 1 EPS <= 1 ULP (2).
+// ULPs are good for measuring rounding errors and comparing values.
+// Relative errors are good for computation of general relative
+// error of formulas or expressions. So to calculate epsilon
+// interval within which epsilon robust predicates have undefined result
+// next schema is used:
+// 1) Compute rounding errors of initial variables using ULPs;
+// 2) Transform ULPs to epsilons using upper bound of the (1);
+// 3) Compute relative error of the formula using epsilon arithmetic;
+// 4) Transform epsilon to ULPs using upper bound of the (2);
+// In case two values are inside undefined ULP range use high-precision
+// arithmetic to produce the correct result, else output the result.
+// Look at almost_equal function to see how two floating-point variables
+// are checked to fit in the ULP range.
+// If A has relative error of r(A) and B has relative error of r(B) then:
+// 1) r(A + B) <= max(r(A), r(B)), for A * B >= 0;
+// 2) r(A - B) <= B*r(A)+A*r(B)/(A-B), for A * B >= 0;
+// 2) r(A * B) <= r(A) + r(B);
+// 3) r(A / B) <= r(A) + r(B);
+// In addition rounding error should be added, that is always equal to
+// 0.5 ULP or at most 1 epsilon. As you might see from the above formulas
+// subtraction relative error may be extremely large, that's why
+// epsilon robust comparator class is used to store floating point values
+// and compute subtraction as the final step of the evaluation.
+// For further information about relative errors and ULPs try this link:
+// http://docs.sun.com/source/806-3568/ncg_goldberg.html
+
+namespace boost {
+namespace polygon {
+namespace detail {
+
+template <typename T>
+T get_sqrt(const T& that) {
+ return (std::sqrt)(that);
+}
+
+template <typename T>
+bool is_pos(const T& that) {
+ return that > 0;
+}
+
+template <typename T>
+bool is_neg(const T& that) {
+ return that < 0;
+}
+
+template <typename T>
+bool is_zero(const T& that) {
+ return that == 0;
+}
+
+template <typename _fpt>
+class robust_fpt {
+public:
+ typedef _fpt floating_point_type;
+ typedef _fpt relative_error_type;
+
+ // Rounding error is at most 1 EPS.
+ static const relative_error_type ROUNDING_ERROR;
+
+ robust_fpt() : fpv_(0.0), re_(0.0) {}
+ robust_fpt(floating_point_type fpv) :
+ fpv_(fpv), re_(0.0) {}
+ robust_fpt(floating_point_type fpv, relative_error_type error) :
+ fpv_(fpv), re_(error) {}
+
+ floating_point_type fpv() const { return fpv_; }
+ relative_error_type re() const { return re_; }
+ relative_error_type ulp() const { return re_; }
+
+ robust_fpt& operator=(const robust_fpt &that) {
+ this->fpv_ = that.fpv_;
+ this->re_ = that.re_;
+ return *this;
+ }
+
+ bool has_pos_value() const {
+ return is_pos(fpv_);
+ }
+
+ bool has_neg_value() const {
+ return is_neg(fpv_);
+ }
+
+ bool has_zero_value() const {
+ return is_zero(fpv_);
+ }
+
+ robust_fpt operator-() const {
+ return robust_fpt(-fpv_, re_);
+ }
+
+ robust_fpt& operator+=(const robust_fpt &that) {
+ floating_point_type fpv = this->fpv_ + that.fpv_;
+ if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
+ this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp))
+ temp = -temp;
+ this->re_ = temp + ROUNDING_ERROR;
+ }
+ this->fpv_ = fpv;
+ return *this;
+ }
+
+ robust_fpt& operator-=(const robust_fpt &that) {
+ floating_point_type fpv = this->fpv_ - that.fpv_;
+ if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
+ this->re_ = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp))
+ temp = -temp;
+ this->re_ = temp + ROUNDING_ERROR;
+ }
+ this->fpv_ = fpv;
+ return *this;
+ }
+
+ robust_fpt& operator*=(const robust_fpt &that) {
+ this->re_ += that.re_ + ROUNDING_ERROR;
+ this->fpv_ *= that.fpv_;
+ return *this;
+ }
+
+ robust_fpt& operator/=(const robust_fpt &that) {
+ this->re_ += that.re_ + ROUNDING_ERROR;
+ this->fpv_ /= that.fpv_;
+ return *this;
+ }
+
+ robust_fpt operator+(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ + that.fpv_;
+ relative_error_type re;
+ if ((!is_neg(this->fpv_) && !is_neg(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_pos(that.fpv_)))
+ re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ - that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp))
+ temp = -temp;
+ re = temp + ROUNDING_ERROR;
+ }
+ return robust_fpt(fpv, re);
+ }
+
+ robust_fpt operator-(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ - that.fpv_;
+ relative_error_type re;
+ if ((!is_neg(this->fpv_) && !is_pos(that.fpv_)) ||
+ (!is_pos(this->fpv_) && !is_neg(that.fpv_)))
+ re = (std::max)(this->re_, that.re_) + ROUNDING_ERROR;
+ else {
+ floating_point_type temp =
+ (this->fpv_ * this->re_ + that.fpv_ * that.re_) / fpv;
+ if (is_neg(temp))
+ temp = -temp;
+ re = temp + ROUNDING_ERROR;
+ }
+ return robust_fpt(fpv, re);
+ }
+
+ robust_fpt operator*(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ * that.fpv_;
+ relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
+ return robust_fpt(fpv, re);
+ }
+
+ robust_fpt operator/(const robust_fpt &that) const {
+ floating_point_type fpv = this->fpv_ / that.fpv_;
+ relative_error_type re = this->re_ + that.re_ + ROUNDING_ERROR;
+ return robust_fpt(fpv, re);
+ }
+
+ robust_fpt sqrt() const {
+ return robust_fpt(get_sqrt(fpv_),
+ re_ * static_cast<relative_error_type>(0.5) +
+ ROUNDING_ERROR);
+ }
+
+private:
+ floating_point_type fpv_;
+ relative_error_type re_;
+};
+
+template <typename T>
+const typename robust_fpt<T>::relative_error_type
+ robust_fpt<T>::ROUNDING_ERROR = 1;
+
+template <typename T>
+robust_fpt<T> get_sqrt(const robust_fpt<T>& that) {
+ return that.sqrt();
+}
+
+template <typename T>
+bool is_pos(const robust_fpt<T>& that) {
+ return that.has_pos_value();
+}
+
+template <typename T>
+bool is_neg(const robust_fpt<T>& that) {
+ return that.has_neg_value();
+}
+
+template <typename T>
+bool is_zero(const robust_fpt<T>& that) {
+ return that.has_zero_value();
+}
+
+// robust_dif consists of two not negative values: value1 and value2.
+// The resulting expression is equal to the value1 - value2.
+// Subtraction of a positive value is equivalent to the addition to value2
+// and subtraction of a negative value is equivalent to the addition to
+// value1. The structure implicitly avoids difference computation.
+template <typename T>
+class robust_dif {
+public:
+ robust_dif() :
+ positive_sum_(0),
+ negative_sum_(0) {}
+
+ robust_dif(const T &value) :
+ positive_sum_((value>0)?value:0),
+ negative_sum_((value<0)?-value:0) {}
+
+ robust_dif(const T &pos, const T &neg) :
+ positive_sum_(pos),
+ negative_sum_(neg) {}
+
+ T dif() const {
+ return positive_sum_ - negative_sum_;
+ }
+
+ T pos() const {
+ return positive_sum_;
+ }
+
+ T neg() const {
+ return negative_sum_;
+ }
+
+ robust_dif<T> operator-() const {
+ return robust_dif(negative_sum_, positive_sum_);
+ }
+
+ robust_dif<T> &operator+=(const T &val) {
+ if (!is_neg(val))
+ positive_sum_ += val;
+ else
+ negative_sum_ -= val;
+ return *this;
+ }
+
+ robust_dif<T> &operator+=(const robust_dif<T> &that) {
+ positive_sum_ += that.positive_sum_;
+ negative_sum_ += that.negative_sum_;
+ return *this;
+ }
+
+ robust_dif<T> &operator-=(const T &val) {
+ if (!is_neg(val))
+ negative_sum_ += val;
+ else
+ positive_sum_ -= val;
+ return *this;
+ }
+
+ robust_dif<T> &operator-=(const robust_dif<T> &that) {
+ positive_sum_ += that.negative_sum_;
+ negative_sum_ += that.positive_sum_;
+ return *this;
+ }
+
+ robust_dif<T> &operator*=(const T &val) {
+ if (!is_neg(val)) {
+ positive_sum_ *= val;
+ negative_sum_ *= val;
+ } else {
+ positive_sum_ *= -val;
+ negative_sum_ *= -val;
+ swap();
+ }
+ return *this;
+ }
+
+ robust_dif<T> &operator*=(const robust_dif<T> &that) {
+ T positive_sum = this->positive_sum_ * that.positive_sum_ +
+ this->negative_sum_ * that.negative_sum_;
+ T negative_sum = this->positive_sum_ * that.negative_sum_ +
+ this->negative_sum_ * that.positive_sum_;
+ positive_sum_ = positive_sum;
+ negative_sum_ = negative_sum;
+ return *this;
+ }
+
+ robust_dif<T> &operator/=(const T &val) {
+ if (!is_neg(val)) {
+ positive_sum_ /= val;
+ negative_sum_ /= val;
+ } else {
+ positive_sum_ /= -val;
+ negative_sum_ /= -val;
+ swap();
+ }
+ return *this;
+ }
+
+private:
+ void swap() {
+ (std::swap)(positive_sum_, negative_sum_);
+ }
+
+ T positive_sum_;
+ T negative_sum_;
+};
+
+template<typename T>
+robust_dif<T> operator+(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ return robust_dif<T>(lhs.pos() + rhs.pos(), lhs.neg() + rhs.neg());
+}
+
+template<typename T>
+robust_dif<T> operator+(const robust_dif<T>& lhs, const T& rhs) {
+ if (!is_neg(rhs)) {
+ return robust_dif<T>(lhs.pos() + rhs, lhs.neg());
+ } else {
+ return robust_dif<T>(lhs.pos(), lhs.neg() - rhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator+(const T& lhs, const robust_dif<T>& rhs) {
+ if (!is_neg(lhs)) {
+ return robust_dif<T>(lhs + rhs.pos(), rhs.neg());
+ } else {
+ return robust_dif<T>(rhs.pos(), rhs.neg() - lhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator-(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ return robust_dif<T>(lhs.pos() + rhs.neg(), lhs.neg() + rhs.pos());
+}
+
+template<typename T>
+robust_dif<T> operator-(const robust_dif<T>& lhs, const T& rhs) {
+ if (!is_neg(rhs)) {
+ return robust_dif<T>(lhs.pos(), lhs.neg() + rhs);
+ } else {
+ return robust_dif<T>(lhs.pos() - rhs, lhs.neg());
+ }
+}
+
+template<typename T>
+robust_dif<T> operator-(const T& lhs, const robust_dif<T>& rhs) {
+ if (!is_neg(lhs)) {
+ return robust_dif<T>(lhs + rhs.neg(), rhs.pos());
+ } else {
+ return robust_dif<T>(rhs.neg(), rhs.pos() - lhs);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator*(const robust_dif<T>& lhs,
+ const robust_dif<T>& rhs) {
+ T res_pos = lhs.pos() * rhs.pos() + lhs.neg() * rhs.neg();
+ T res_neg = lhs.pos() * rhs.neg() + lhs.neg() * rhs.pos();
+ return robust_dif<T>(res_pos, res_neg);
+}
+
+template<typename T>
+robust_dif<T> operator*(const robust_dif<T>& lhs, const T& val) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(lhs.pos() * val, lhs.neg() * val);
+ } else {
+ return robust_dif<T>(-lhs.neg() * val, -lhs.pos() * val);
+ }
+}
+
+template<typename T>
+robust_dif<T> operator*(const T& val, const robust_dif<T>& rhs) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(val * rhs.pos(), val * rhs.neg());
+ } else {
+ return robust_dif<T>(-val * rhs.neg(), -val * rhs.pos());
+ }
+}
+
+template<typename T>
+robust_dif<T> operator/(const robust_dif<T>& lhs, const T& val) {
+ if (!is_neg(val)) {
+ return robust_dif<T>(lhs.pos() / val, lhs.neg() / val);
+ } else {
+ return robust_dif<T>(-lhs.neg() / val, -lhs.pos() / val);
+ }
+}
+
+// Used to compute expressions that operate with sqrts with predefined
+// relative error. Evaluates expressions of the next type:
+// sum(i = 1 .. n)(A[i] * sqrt(B[i])), 1 <= n <= 4.
+template <typename _int, typename _fpt, typename _converter>
+class robust_sqrt_expr {
+public:
+ static const unsigned int EVAL1_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL2_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL3_MAX_RELATIVE_ERROR;
+ static const unsigned int EVAL4_MAX_RELATIVE_ERROR;
+
+ // Evaluates expression (re = 4 EPS):
+ // A[0] * sqrt(B[0]).
+ _fpt eval1(_int *A, _int *B) {
+ _fpt a = convert(A[0]);
+ _fpt b = convert(B[0]);
+ return a * get_sqrt(b);
+ }
+
+ // Evaluates expression (re = 7 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]).
+ _fpt eval2(_int *A, _int *B) {
+ _fpt a = eval1(A, B);
+ _fpt b = eval1(A + 1, B + 1);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ return convert(A[0] * A[0] * B[0] - A[1] * A[1] * B[1]) / (a - b);
+ }
+
+ // Evaluates expression (re = 16 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) + A[2] * sqrt(B[2]).
+ _fpt eval3(_int *A, _int *B) {
+ _fpt a = eval2(A, B);
+ _fpt b = eval1(A + 2, B + 2);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ tA[3] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] - A[2] * A[2] * B[2];
+ tB[3] = 1;
+ tA[4] = A[0] * A[1] * 2;
+ tB[4] = B[0] * B[1];
+ return eval2(tA + 3, tB + 3) / (a - b);
+ }
+
+
+ // Evaluates expression (re = 25 EPS):
+ // A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
+ // A[2] * sqrt(B[2]) + A[3] * sqrt(B[3]).
+ _fpt eval4(_int *A, _int *B) {
+ _fpt a = eval2(A, B);
+ _fpt b = eval2(A + 2, B + 2);
+ if ((!is_neg(a) && !is_neg(b)) ||
+ (!is_pos(a) && !is_pos(b)))
+ return a + b;
+ tA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
+ A[2] * A[2] * B[2] - A[3] * A[3] * B[3];
+ tB[0] = 1;
+ tA[1] = A[0] * A[1] * 2;
+ tB[1] = B[0] * B[1];
+ tA[2] = A[2] * A[3] * -2;
+ tB[2] = B[2] * B[3];
+ return eval3(tA, tB) / (a - b);
+ }
+
+private:
+ _int tA[5];
+ _int tB[5];
+ _converter convert;
+};
+
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL1_MAX_RELATIVE_ERROR = 4;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL2_MAX_RELATIVE_ERROR = 7;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL3_MAX_RELATIVE_ERROR = 16;
+template <typename _int, typename _fpt, typename _converter>
+const unsigned int robust_sqrt_expr<_int, _fpt, _converter>::EVAL4_MAX_RELATIVE_ERROR = 25;
+} // detail
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_DETAIL_VORONOI_ROBUST_FPT

Added: trunk/boost/polygon/detail/voronoi_structures.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/detail/voronoi_structures.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,451 @@
+// Boost.Polygon library detail/voronoi_structures.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
+#define BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES
+
+#include <list>
+#include <queue>
+#include <vector>
+
+namespace boost {
+namespace polygon {
+namespace detail {
+
+// Cartesian 2D point data structure.
+template <typename T>
+class point_2d {
+public:
+ typedef T coordinate_type;
+
+ point_2d() {}
+
+ point_2d(coordinate_type x, coordinate_type y) :
+ x_(x),
+ y_(y) {}
+
+ bool operator==(const point_2d &that) const {
+ return (this->x_ == that.x()) && (this->y_ == that.y());
+ }
+
+ bool operator!=(const point_2d &that) const {
+ return (this->x_ != that.x()) || (this->y_ != that.y());
+ }
+
+ coordinate_type x() const {
+ return x_;
+ }
+
+ coordinate_type y() const {
+ return y_;
+ }
+
+ point_2d& x(coordinate_type x) {
+ x_ = x;
+ return *this;
+ }
+
+ point_2d& y(coordinate_type y) {
+ y_ = y;
+ return *this;
+ }
+
+private:
+ coordinate_type x_;
+ coordinate_type y_;
+};
+
+// Site event type.
+// Occurs when the sweepline sweeps over one of the initial sites:
+// 1) point site;
+// 2) start-point of the segment site;
+// 3) endpoint of the segment site.
+// Implicit segment direction is defined: the start-point of
+// the segment compares less than its endpoint.
+// Each input segment is divided onto two site events:
+// 1) One going from the start-point to the endpoint
+// (is_inverse_ = false);
+// 2) Another going from the endpoint to the start-point
+// (is_inverse_ = true).
+// In beach line data structure segment sites of the first
+// type precede sites of the second type for the same segment.
+// Variables:
+// point0_ - point site or segment's start-point;
+// point1_ - segment's endpoint if site is a segment;
+// index_ - the last bit encodes if the site is inverse;
+// the last-1 bit encodes initial site direction;
+// other bits encode site event index among the other site events.
+// Note: for all the sites is_inverse_ flag is equal to false by default.
+template <typename T>
+class site_event {
+public:
+ typedef T coordinate_type;
+ typedef point_2d<T> point_type;
+
+ site_event() :
+ point0_(0, 0),
+ point1_(0, 0),
+ site_index_(0) {}
+
+ site_event(coordinate_type x, coordinate_type y) :
+ point0_(x, y),
+ point1_(x, y),
+ site_index_(0) {}
+
+ site_event(const point_type &point) :
+ point0_(point),
+ point1_(point),
+ site_index_(0) {}
+
+ site_event(coordinate_type x1, coordinate_type y1,
+ coordinate_type x2, coordinate_type y2):
+ point0_(x1, y1),
+ point1_(x2, y2),
+ site_index_(0) {}
+
+ site_event(const point_type &point1, const point_type &point2) :
+ point0_(point1),
+ point1_(point2),
+ site_index_(0) {}
+
+ bool operator==(const site_event &that) const {
+ return (this->point0_ == that.point0_) &&
+ (this->point1_ == that.point1_) &&
+ (this->site_index_ == that.site_index_);
+ }
+
+ bool operator!=(const site_event &that) const {
+ return (this->point0_ != that.point0_) ||
+ (this->point1_ != that.point1_) ||
+ (this->site_index_ != that.site_index_);
+ }
+
+ coordinate_type x(bool oriented = false) const {
+ return x0(oriented);
+ }
+
+ coordinate_type y(bool oriented = false) const {
+ return y0(oriented);
+ }
+
+ coordinate_type x0(bool oriented = false) const {
+ if (!oriented)
+ return point0_.x();
+ return is_inverse() ? point1_.x() : point0_.x();
+ }
+
+ coordinate_type y0(bool oriented = false) const {
+ if (!oriented)
+ return point0_.y();
+ return is_inverse() ? point1_.y() : point0_.y();
+ }
+
+ coordinate_type x1(bool oriented = false) const {
+ if (!oriented)
+ return point1_.x();
+ return is_inverse() ? point0_.x() : point1_.x();
+ }
+
+ coordinate_type y1(bool oriented = false) const {
+ if (!oriented)
+ return point1_.y();
+ return is_inverse() ? point0_.y() : point1_.y();
+ }
+
+ const point_type &point0(bool oriented = false) const {
+ if (!oriented)
+ return point0_;
+ return is_inverse() ? point1_ : point0_;
+ }
+
+ const point_type &point1(bool oriented = false) const {
+ if (!oriented)
+ return point1_;
+ return is_inverse() ? point0_ : point1_;
+ }
+
+ site_event& index(int index) {
+ site_index_ = (index << 2) + (site_index_ & 3);
+ return *this;
+ }
+
+ site_event& inverse() {
+ site_index_ ^= IS_INVERSE;
+ return *this;
+ }
+
+ site_event& change_initial_direction() {
+ site_index_ ^= HAS_INITIAL_DIRECTION;
+ return *this;
+ }
+
+ size_t index() const {
+ return site_index_ >> 2;
+ }
+
+ bool is_point() const {
+ return point0_.x() == point1_.x() && point0_.y() == point1_.y();
+ }
+
+ bool is_segment() const {
+ return point0_.x() != point1_.x() || point0_.y() != point1_.y();
+ }
+
+ bool is_inverse() const {
+ return (site_index_ & IS_INVERSE) ? true : false;
+ }
+
+ bool is_initial() const {
+ return (site_index_ & HAS_INITIAL_DIRECTION) ? false : true;
+ }
+
+ bool has_initial_direction() const {
+ return is_inverse() ^ is_initial();
+ }
+
+private:
+ enum kBits {
+ IS_INVERSE = 1,
+ HAS_INITIAL_DIRECTION = 2
+ };
+
+ point_type point0_;
+ point_type point1_;
+ unsigned int site_index_;
+};
+
+// Circle event type.
+// Occurs when the sweepline sweeps over the rightmost point of the Voronoi
+// circle (with the center at the intersection point of the bisectors).
+// Circle event is made of the two consecutive nodes in the beach line data
+// structure. In case another node was inserted during algorithm execution
+// between the given two nodes circle event becomes inactive.
+// Variables:
+// center_x_ - center x-coordinate;
+// center_y_ - center y-coordinate;
+// lower_x_ - leftmost x-coordinate;
+// is_active_ - states whether circle event is still active.
+// NOTE: lower_y coordinate is always equal to center_y.
+template <typename T>
+class circle_event {
+public:
+ typedef T coordinate_type;
+
+ circle_event() : is_active_(true) {}
+
+ 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),
+ is_active_(true) {}
+
+ coordinate_type x() const {
+ return center_x_;
+ }
+
+ circle_event& x(coordinate_type center_x) {
+ center_x_ = center_x;
+ return *this;
+ }
+
+ coordinate_type y() const {
+ return center_y_;
+ }
+
+ circle_event& y(coordinate_type center_y) {
+ center_y_ = center_y;
+ return *this;
+ }
+
+ coordinate_type lower_x() const {
+ return lower_x_;
+ }
+
+ circle_event& lower_x(coordinate_type lower_x) {
+ lower_x_ = lower_x;
+ return *this;
+ }
+
+ coordinate_type lower_y() const {
+ return center_y_;
+ }
+
+ bool is_active() const {
+ return is_active_;
+ }
+
+ circle_event& deactivate() {
+ is_active_ = false;
+ return *this;
+ }
+
+private:
+ coordinate_type center_x_;
+ coordinate_type center_y_;
+ coordinate_type lower_x_;
+ bool is_active_;
+};
+
+// Event queue data structure, holds circle events.
+// During algorithm run, some of the circle events disappear (become
+// inactive). Priority queue data structure doesn't support
+// iterators (there is no direct ability to modify its elements).
+// Instead list is used to store all the circle events and priority queue
+// of the iterators to the list elements is used to keep the correct circle
+// events ordering.
+template <typename T, typename Predicate>
+class ordered_queue {
+public:
+ ordered_queue() {}
+
+ bool empty() const {
+ return c_.empty();
+ }
+
+ const T &top() const {
+ return *c_.top();
+ }
+
+ void pop() {
+ list_iterator_type it = c_.top();
+ c_.pop();
+ c_list_.erase(it);
+ }
+
+ T &push(const T &e) {
+ c_list_.push_front(e);
+ c_.push(c_list_.begin());
+ return c_list_.front();
+ }
+
+ void clear() {
+ while (!c_.empty())
+ c_.pop();
+ c_list_.clear();
+ }
+
+private:
+ typedef typename std::list<T>::iterator list_iterator_type;
+
+ struct comparison {
+ bool operator() (const list_iterator_type &it1,
+ const list_iterator_type &it2) const {
+ return cmp_(*it1, *it2);
+ }
+ Predicate cmp_;
+ };
+
+ std::priority_queue< list_iterator_type,
+ std::vector<list_iterator_type>,
+ comparison > c_;
+ std::list<T> c_list_;
+
+ //Disallow copy constructor and operator=
+ ordered_queue(const ordered_queue&);
+ void operator=(const ordered_queue&);
+};
+
+// Represents a bisector node made by two arcs that correspond to the left
+// and right sites. Arc is defined as a curve with points equidistant from
+// the site and from the sweepline. If the site is a point then arc is
+// a parabola, otherwise it's a line segment. A segment site event will
+// produce different bisectors based on its direction.
+// In general case two sites will create two opposite bisectors. That's
+// why the order of the sites is important to define the unique bisector.
+// The one site is considered to be newer than the other one if it was
+// processed by the algorithm later (has greater index).
+template <typename Site>
+class beach_line_node_key {
+public:
+ typedef Site site_type;
+
+ // Constructs degenerate bisector, used to search an arc that is above
+ // the given site. The input to the constructor is the new site point.
+ explicit beach_line_node_key(const site_type &new_site) :
+ left_site_(new_site),
+ right_site_(new_site) {}
+
+ // Constructs a new bisector. The input to the constructor is the two
+ // sites that create the bisector. The order of sites is important.
+ beach_line_node_key(const site_type &left_site,
+ const site_type &right_site) :
+ left_site_(left_site),
+ right_site_(right_site) {}
+
+ const site_type &left_site() const {
+ return left_site_;
+ }
+
+ site_type &left_site() {
+ return left_site_;
+ }
+
+ beach_line_node_key& left_site(const site_type &site) {
+ left_site_ = site;
+ return *this;
+ }
+
+ const site_type &right_site() const {
+ return right_site_;
+ }
+
+ site_type &right_site() {
+ return right_site_;
+ }
+
+ beach_line_node_key& right_site(const site_type &site) {
+ right_site_ = site;
+ return *this;
+ }
+
+private:
+ site_type left_site_;
+ site_type right_site_;
+};
+
+// Represents edge data structure from the Voronoi output, that is
+// associated as a value with beach line bisector in the beach
+// line. Contains pointer to the circle event in the circle event
+// queue if the edge corresponds to the right bisector of the circle event.
+template <typename Edge, typename Circle>
+class beach_line_node_data {
+public:
+ explicit beach_line_node_data(Edge *new_edge) :
+ circle_event_(NULL),
+ edge_(new_edge) {}
+
+ Circle *circle_event() const {
+ return circle_event_;
+ }
+
+ beach_line_node_data& circle_event(Circle *circle_event) {
+ circle_event_ = circle_event;
+ return *this;
+ }
+
+ Edge *edge() const {
+ return edge_;
+ }
+
+ beach_line_node_data& edge(Edge *new_edge) {
+ edge_ = new_edge;
+ return *this;
+ }
+
+private:
+ Circle *circle_event_;
+ Edge *edge_;
+};
+} // detail
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_DETAIL_VORONOI_STRUCTURES

Deleted: trunk/boost/polygon/directed_line_segment_concept.hpp
==============================================================================
--- trunk/boost/polygon/directed_line_segment_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
+++ (empty file)
@@ -1,453 +0,0 @@
-/*
- Copyright 2008 Intel Corporation
-
- Use, modification and distribution are subject to the Boost Software License,
- Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
-*/
-#ifndef BOOST_POLYGON_DIRECTED_LINE_SEGMENT_CONCEPT_HPP
-#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_CONCEPT_HPP
-#include "isotropy.hpp"
-#include "directed_line_segment_data.hpp"
-#include "directed_line_segment_traits.hpp"
-#include "rectangle_concept.hpp"
-#include "detail/polygon_arbitrary_formation.hpp"
-
-namespace boost { namespace polygon{
- struct directed_line_segment_concept {};
-
- template <typename T>
- struct is_directed_line_segment_concept { typedef gtl_no type; };
- template <>
- struct is_directed_line_segment_concept<directed_line_segment_concept> { typedef gtl_yes type; };
-
- template <typename T>
- struct is_mutable_directed_line_segment_concept { typedef gtl_no type; };
- template <>
- struct is_mutable_directed_line_segment_concept<directed_line_segment_concept> { typedef gtl_yes type; };
-
- template <typename T, typename CT>
- struct directed_line_segment_distance_type_by_concept { typedef void type; };
- template <typename T>
- struct directed_line_segment_distance_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename directed_line_segment_traits<T>::coordinate_type>::coordinate_distance type; };
-
- template <typename T>
- struct directed_line_segment_distance_type {
- typedef typename directed_line_segment_distance_type_by_concept<
- T, typename is_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type type;
- };
-
- template <typename T, typename CT>
- struct directed_line_segment_point_type_by_concept { typedef void type; };
- template <typename T>
- struct directed_line_segment_point_type_by_concept<T, gtl_yes> {
- typedef typename directed_line_segment_traits<T>::point_type type; };
-
- template <typename T>
- struct directed_line_segment_point_type {
- typedef typename directed_line_segment_point_type_by_concept<
- T, typename is_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type type;
- };
-
- template <typename T, typename CT>
- struct directed_line_segment_coordinate_type_by_concept { typedef void type; };
- template <typename T>
- struct directed_line_segment_coordinate_type_by_concept<T, gtl_yes> {
- typedef typename directed_line_segment_traits<T>::coordinate_type type; };
-
- template <typename T>
- struct directed_line_segment_coordinate_type {
- typedef typename directed_line_segment_coordinate_type_by_concept<
- T, typename is_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type type;
- };
-
- template <typename T>
- typename directed_line_segment_point_type<T>::type
- get(const T& segment, direction_1d dir,
- typename enable_if<typename gtl_if<typename is_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type>::type * = 0
- ) {
- return directed_line_segment_traits<T>::get(segment, dir);
- }
-
- template <typename T, typename point_type>
- void
- set(T& segment, direction_1d dir, point_type value,
- typename enable_if<typename is_mutable_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
- directed_line_segment_mutable_traits<T>::set(segment, dir, value);
- }
-
- template <typename T, typename T2, typename T3>
- T
- construct(T2 low_value, T3 high_value,
- typename enable_if<typename is_mutable_directed_line_segment_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
- return directed_line_segment_mutable_traits<T>::construct(low_value, high_value);
- }
-
- template <typename T, typename T2>
- T
- copy_construct(const T2& segment,
- typename enable_if< typename gtl_and<typename is_mutable_directed_line_segment_concept<typename geometry_concept<T>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
- return construct<T>
- (get(segment, LOW ),
- get(segment, HIGH));
- }
-
- template <typename T1, typename T2>
- T1 &
- assign(T1& lvalue, const T2& rvalue,
- typename enable_if< typename gtl_and< typename is_mutable_directed_line_segment_concept<typename geometry_concept<T1>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0) {
- lvalue = copy_construct<T1>(rvalue);
- return lvalue;
- }
-
- template <typename T, typename T2>
- bool
- equivalence(const T& segment1, const T2& segment2,
- typename enable_if< typename gtl_and< typename is_directed_line_segment_concept<typename geometry_concept<T>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
- return get(segment1, LOW) ==
- get(segment2, LOW) &&
- get(segment1, HIGH) ==
- get(segment2, HIGH);
- }
-
- struct y_dls_on_above_or_below : gtl_yes {};
-
- //-1 for below, 0 for on and 1 for above
- template <typename segment_type>
- typename enable_if< typename gtl_and< y_dls_on_above_or_below, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type >::type, bool>::type
- on_above_or_below(const segment_type& segment,
- typename directed_line_segment_traits<segment_type>::point_type value) {
- typedef polygon_arbitrary_formation<typename directed_line_segment_traits<segment_type>::coordinate_type> paf;
- typename paf::Point pt, l, h;
- assign(pt, value);
- assign(l, low(segment));
- assign(h, high(segment));
- return paf::on_above_or_below(pt, typename paf::half_edge(l, h));
- }
-
- struct y_dls_contains : gtl_yes {};
-
- template <typename segment_type>
- typename enable_if< typename gtl_and< y_dls_contains, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type >::type, bool>::type
- contains(const segment_type& segment,
- typename directed_line_segment_traits<segment_type>::point_type value,
- bool consider_touch = true ) {
- if(on_above_or_below(segment, value) == 0) {
- rectangle_data<typename directed_line_segment_traits<segment_type>::coordinate_type> rect;
- set_points(rect, low(segment), high(segment));
- if(area(rect) == 0.0) {
- if(!consider_touch) {
- return !equivalence(value, low(segment)) && !equivalence(value, high(segment));
- }
- }
- return contains(rect, value, consider_touch);
- }
- return false;
- }
-
- template <typename segment_type, typename segment_type_2>
- bool
- contains(const segment_type& segment,
- const segment_type_2& value, bool consider_touch = true,
- typename enable_if< typename gtl_and< typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type>::type * = 0
- ) {
- return contains(segment, get(value, LOW), consider_touch) &&
- contains(segment, get(value, HIGH), consider_touch);
- }
-
- // get the low point
- template <typename segment_type>
- typename directed_line_segment_point_type<segment_type>::type
- low(const segment_type& segment,
- typename enable_if< typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type * = 0
- ) { return get(segment, LOW); }
-
- // get the high point
- template <typename segment_type>
- typename directed_line_segment_point_type<segment_type>::type
- high(const segment_type& segment,
- typename enable_if< typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type * = 0
- ) { return get(segment, HIGH); }
-
- // get the center point
- template <typename segment_type>
- typename directed_line_segment_point_type<segment_type>::type
- center(const segment_type& segment,
- typename enable_if< typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type * = 0
- ) {
- return construct<typename directed_line_segment_traits<segment_type>::point_type>((x(high(segment)) + x(low(segment)))/2,
- (y(high(segment)) + y(low(segment)))/2);
-
- }
-
- struct y_dls_low : gtl_yes {};
-
- // set the low point to v
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_low, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, void>::type
- low(segment_type& segment,
- typename directed_line_segment_traits<segment_type>::point_type v) { set(segment, LOW, v); }
-
- struct y_dls_high : gtl_yes {};
-
- // set the high coordinate to v
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_high, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, void>::type
- high(segment_type& segment,
- typename directed_line_segment_traits<segment_type>::point_type v) { set(segment, HIGH, v); }
-
- template <typename segment_type>
- typename directed_line_segment_distance_type<segment_type>::type
- length(const segment_type& segment,
- typename enable_if< typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type * = 0
- ) { return euclidean_distance(low(segment), high(segment)); }
-
- struct y_dls_flip : gtl_yes {};
-
- struct y_dls_scale_up : gtl_yes {};
-
- // scale segment by factor
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_scale_up, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- scale_up(segment_type& segment,
- typename coordinate_traits<typename directed_line_segment_traits<segment_type>::coordinate_type>::unsigned_area_type factor) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, scale_up(l, factor));
- high(segment, scale_up(h, factor));
- return segment;
- }
-
- struct y_dls_scale_down : gtl_yes {};
-
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_scale_down, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- scale_down(segment_type& segment,
- typename coordinate_traits<typename directed_line_segment_traits<segment_type>::coordinate_type>::unsigned_area_type factor) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, scale_down(l, factor));
- high(segment, scale_down(h, factor));
- return segment;
- }
-
- struct y_dls_scale : gtl_yes {};
-
- template <typename segment_type, typename scaling_type>
- typename enable_if<typename gtl_and<y_dls_scale, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- scale(segment_type& segment, scaling_type factor) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, scale(l, factor));
- high(segment, scale(h, factor));
- return segment;
- }
-
-
- struct y_dls_transform : gtl_yes {};
-
- template <typename segment_type, typename transform_type>
- typename enable_if<typename gtl_and<y_dls_transform, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- transform(segment_type& segment, const transform_type& val) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, transform(l, val));
- high(segment, transform(h, val));
- return segment;
- }
- // move segment by delta
- template <typename segment_type>
- segment_type&
- move(segment_type& segment, orientation_2d orient,
- typename directed_line_segment_coordinate_type<segment_type>::type displacement,
- typename enable_if<typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type * = 0
- ) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, move(l, orient, displacement));
- high(segment, move(h, orient, displacement));
- return segment;
- }
-
- struct y_dls_convolve : gtl_yes {};
-
- // convolve this with b
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_convolve, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- convolve(segment_type& segment,
- const typename directed_line_segment_traits<segment_type>::point_type& b) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, convolve(l, b));
- high(segment, convolve(h, b));
- return segment;
- }
-
- struct y_dls_deconvolve : gtl_yes {};
-
- // deconvolve this with b
- template <typename segment_type>
- typename enable_if<typename gtl_and<y_dls_deconvolve, typename is_mutable_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type, segment_type>::type &
- deconvolve(segment_type& segment,
- const typename directed_line_segment_traits<segment_type>::point_type& b) {
- typename directed_line_segment_point_type<segment_type>::type l = low(segment), h = high(segment);
- low(segment, deconvolve(l, b));
- high(segment, deconvolve(h, b));
- return segment;
- }
-
- struct y_dls_e_dist1 : gtl_yes {};
-
- // distance from a point to a segment
- template <typename segment_type>
- typename enable_if< typename gtl_and<y_dls_e_dist1, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type>::type,
- typename directed_line_segment_distance_type<segment_type>::type>::type
- euclidean_distance(const segment_type& segment,
- typename directed_line_segment_traits<segment_type>::point_type position) {
- typedef typename directed_line_segment_distance_type<segment_type>::type Unit;
- Unit x1 = x(low(segment));
- Unit y1 = y(low(segment));
- Unit x2 = x(high(segment));
- Unit y2 = y(high(segment));
- Unit X = x(position);
- Unit Y = y(position);
- Unit A = X - x1;
- Unit B = Y - y1;
- Unit C = x2 - x1;
- Unit D = y2 - y1;
- Unit length_sq = C * C + D * D;
- Unit param = (A * C + B * D)/length_sq;
- if(param > 1.0) {
- return euclidean_distance(high(segment), position);
- } else if(param < 0.0) {
- return euclidean_distance(low(segment), position);
- }
- Unit denom = sqrt(length_sq);
- if(denom == 0.0)
- return 0.0;
- Unit result = (A * D - C * B) / denom;
- if(result < 0.0)
- result *= -1;
- return result;
- }
-
- struct y_dls_e_dist2 : gtl_yes {};
-
- // distance between two segments
- template <typename segment_type, typename segment_type_2>
- typename enable_if<
- typename gtl_and_3<y_dls_e_dist2, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type,
- typename directed_line_segment_distance_type<segment_type>::type>::type
- euclidean_distance(const segment_type& segment,
- const segment_type_2& b) {
- typename directed_line_segment_distance_type<segment_type>::type result1 = euclidean_distance(segment, low(b)),
- result2 = euclidean_distance(segment, high(b));
- if(result2 < result1) result1 = result2;
- return result1;
- }
-
- struct y_dls_e_intersects : gtl_yes {};
-
- // check if Interval b intersects `this` Interval
- template <typename segment_type, typename segment_type_2>
- typename enable_if< typename gtl_and_3<y_dls_e_intersects,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type
- >::type, bool> ::type
- intersects(const segment_type& segment, const segment_type_2& b, bool consider_touch = true) {
- if(consider_touch) {
- if(low(segment) == low(b) || low(segment) == high(b) || high(segment) == low(b) || high(segment) == high(b))
- return true;
- }
- typedef polygon_arbitrary_formation<typename directed_line_segment_traits<segment_type>::coordinate_type> paf;
- typename paf::Point l, h, l2, h2;
- assign(l, low(segment));
- assign(h, high(segment));
- assign(l2, low(b));
- assign(h2, high(b));
- return paf::intersects(typename paf::half_edge(l, h), typename paf::half_edge(l2, h2));
- }
-
- struct y_dls_e_bintersect : gtl_yes {};
-
- // check if Interval b partially overlaps `this` Interval
- template <typename segment_type, typename segment_type_2>
- typename enable_if<
- typename gtl_and_3<y_dls_e_bintersect, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type,
- bool>::type
- boundaries_intersect(const segment_type& segment, const segment_type_2& b,
- bool consider_touch = true) {
- return (contains(segment, low(b), consider_touch) ||
- contains(segment, high(b), consider_touch)) &&
- (contains(b, low(segment), consider_touch) ||
- contains(b, high(segment), consider_touch));
- }
-
- struct y_dls_abuts1 : gtl_yes {};
-
- // check if they are end to end
- template <typename segment_type, typename segment_type_2>
- typename enable_if< typename gtl_and_3<y_dls_abuts1, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type,
- bool>::type
- abuts(const segment_type& segment, const segment_type_2& b, direction_1d dir) {
- return dir.to_int() ? equivalence(low(b) , high(segment)) : equivalence(low(segment) , high(b));
- }
-
- struct y_dls_abuts2 : gtl_yes {};
-
- // check if they are end to end
- template <typename segment_type, typename segment_type_2>
- typename enable_if<
- typename gtl_and_3<y_dls_abuts2, typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type,
- bool>::type
- abuts(const segment_type& segment, const segment_type_2& b) {
- return abuts(segment, b, HIGH) || abuts(segment, b, LOW);
- }
-
- struct y_dls_intersect : gtl_yes {};
-
- // set point to the intersection of segment and b
- template <typename point_type, typename segment_type, typename segment_type_2>
- typename enable_if< typename gtl_and_4<y_dls_intersect, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type>::type>::type,
- typename is_directed_line_segment_concept<typename geometry_concept<segment_type_2>::type>::type>::type,
- bool>::type
- intersection(point_type& intersection, const segment_type& segment, const segment_type_2& b,
- bool projected = false, bool round_closest = false) {
- typedef polygon_arbitrary_formation<typename directed_line_segment_traits<segment_type>::coordinate_type> paf;
- typename paf::Point pt;
- typename paf::Point l, h, l2, h2;
- assign(l, low(segment));
- assign(h, high(segment));
- assign(l2, low(b));
- assign(h2, high(b));
- typename paf::half_edge he1(l, h), he2(l2, h2);
- typename paf::compute_intersection_pack pack;
- if(pack.compute_intersection(pt, he1, he2, projected, round_closest)) {
- assign(intersection, pt);
- return true;
- }
- return false;
- }
-
- template <class T>
- template <class T2>
- directed_line_segment_data<T>& directed_line_segment_data<T>::operator=(const T2& rvalue) {
- assign(*this, rvalue);
- return *this;
- }
-
- template <typename T>
- struct geometry_concept<directed_line_segment_data<T> > {
- typedef directed_line_segment_concept type;
- };
-}
-}
-#endif

Deleted: trunk/boost/polygon/directed_line_segment_data.hpp
==============================================================================
--- trunk/boost/polygon/directed_line_segment_data.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
+++ (empty file)
@@ -1,69 +0,0 @@
-/*
- Copyright 2008 Intel Corporation
-
- Use, modification and distribution are subject to the Boost Software License,
- Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
-*/
-#ifndef BOOST_POLYGON_DIRECTED_LINE_SEGMENT_DATA_HPP
-#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_DATA_HPP
-#include "isotropy.hpp"
-#include "point_data.hpp"
-namespace boost { namespace polygon{
- template <typename T>
- class directed_line_segment_data {
- public:
- typedef T coordinate_type;
- typedef point_data<T> point_type;
- inline directed_line_segment_data()
-#ifndef BOOST_POLYGON_MSVC
- :points_()
-#endif
- {}
- inline directed_line_segment_data(point_type low, point_type high)
-#ifndef BOOST_POLYGON_MSVC
- :points_()
-#endif
- {
- points_[LOW] = low; points_[HIGH] = high;
- }
- inline directed_line_segment_data(const directed_line_segment_data& that)
-#ifndef BOOST_POLYGON_MSVC
- :points_()
-#endif
- {
- (*this) = that;
- }
- inline directed_line_segment_data& operator=(const directed_line_segment_data& that) {
- points_[0] = that.points_[0]; points_[1] = that.points_[1]; return *this;
- }
- template <typename T2>
- inline directed_line_segment_data& operator=(const T2& rvalue);
- inline point_type get(direction_1d dir) const {
- return points_[dir.to_int()];
- }
- inline point_type low() const { return points_[0]; }
- inline point_type high() const { return points_[1]; }
- inline bool operator==(const directed_line_segment_data& that) const {
- return low() == that.low() && high() == that.high(); }
- inline bool operator!=(const directed_line_segment_data& that) const {
- return low() != that.low() || high() != that.high(); }
- inline bool operator<(const directed_line_segment_data& that) const {
- if(points_[0] < that.points_[0]) return true;
- if(points_[0] > that.points_[0]) return false;
- if(points_[1] < that.points_[1]) return true;
- return false;
- }
- inline bool operator<=(const directed_line_segment_data& that) const { return !(that < *this); }
- inline bool operator>(const directed_line_segment_data& that) const { return that < *this; }
- inline bool operator>=(const directed_line_segment_data& that) const { return !((*this) < that); }
- inline void set(direction_1d dir, point_type value) {
- points_[dir.to_int()] = value;
- }
-private:
- point_type points_[2];
-};
-
-}
-}
-#endif

Deleted: trunk/boost/polygon/directed_line_segment_set_data.hpp
==============================================================================
--- trunk/boost/polygon/directed_line_segment_set_data.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
+++ (empty file)
@@ -1,270 +0,0 @@
-/*
- Copyright 2008 Intel Corporation
-
- Use, modification and distribution are subject to the Boost Software License,
- Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
-*/
-#ifndef BOOST_POLYGON_DIRECTED_LINE_SEGMENT_SET_DATA_HPP
-#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_SET_DATA_HPP
-
-namespace boost { namespace polygon{
- template <typename T>
- class directed_line_segment_set_data {
- public:
- typedef T coordinate_type;
- typedef point_data<T> point_type;
- typedef directed_line_segment_data<T> directed_line_segment_type;
- typedef std::vector<directed_line_segment_type> value_type;
- typedef typename std::vector<directed_line_segment_type>::const_iterator iterator_type;
-
- inline directed_line_segment_set_data() : data_(), dirty_(false), unsorted_(false) {}
- inline directed_line_segment_set_data(const directed_line_segment_set_data& that):
- data_(that.data_), dirty_(that.dirty_), unsorted_(that.unsorted_) {}
- inline directed_line_segment_set_data& operator=(const directed_line_segment_set_data& that) {
- if(this == &that) return *this;
- data_ = that.data_;
- dirty_ = that.dirty_;
- unsorted_ = that.unsorted_;
- return *this;
- }
- template <typename T2>
- inline directed_line_segment_set_data& operator=(const T2& rvalue) {
- data_.clear();
- bool unsorted = !sorted(rvalue);
- bool dirty = !dirty(rvalue);
- insert(begin(rvalue), end(rvalue));
- unsorted_ = unsorted;
- dirty_ = dirty;
- return *this;
- }
-
- inline bool operator==(const directed_line_segment_set_data& that) const {
- clean();
- that.clean();
- sort();
- that.sort();
- return data_ == that.data_;
- }
- inline bool operator!=(const directed_line_segment_set_data& that) const {
- return !(*this == that);
- }
-
- template <typename iT>
- inline void insert(iT begin_segments, iT end_segments) {
- data_.clear();
- for(; begin_segments != end_segments; ++begin_segments) {
- insert(*begin_segments);
- }
- }
-
- template <typename ST>
- inline void insert(ST segment) {
- unsorted_ = true;
- dirty_ = true;
- directed_line_segment_type tmp_seg;
- assign(tmp_seg, segment);
- data_.push_back(tmp_seg);
- }
-
- inline void clear() { data_.clear(); unsorted_ = false; dirty_ = false; }
-
- inline iterator_type begin() const {
- return data_.begin();
- }
-
- inline iterator_type end() const {
- return data_.end();
- }
-
- const value_type& value() const {
- return data_;
- }
-
- template <typename output_container>
- inline void get(output_container& output) const {
- for(std::size_t i = 0; i < size(); ++i) {
- output.push_back(typename output_container::value_type());
- assign(output.back(), data_[i]);
- }
- }
-
- inline bool empty() const { return data_.empty(); }
-
- inline std::size_t size() const { clean(); return data_.size(); }
-
- inline std::size_t capacity() const { return data_.capacity(); }
-
- inline void reserve(std::size_t size) { return data_.reserve(size); }
-
- inline bool sorted() const { return !unsorted_; }
-
- inline bool dirty() const { return dirty_; }
-
- void clean() const {
- typedef T Unit;
- typedef typename scanline_base<Unit>::Point Point;
- typedef typename scanline_base<Unit>::half_edge half_edge;
- typedef int segment_id;
- std::vector<std::pair<half_edge, segment_id> > half_edges;
- std::vector<std::pair<half_edge, segment_id> > half_edges_out;
- segment_id id = 0;
- half_edges.reserve(data_.size());
- for(iterator_type itr = begin(); itr != end(); ++itr) {
- Point l = (*itr).low();
- Point h = (*itr).high();
- half_edges.push_back(std::make_pair(half_edge(l, h), id++));
- }
- half_edges_out.reserve(half_edges.size());
- //apparently no need to pre-sort data when calling validate_scan
- line_intersection<Unit>::validate_scan(half_edges_out, half_edges.begin(), half_edges.end());
- value_type result;
- result.reserve(half_edges_out.size());
- for(std::size_t i = 0; i < half_edges_out.size(); ++i) {
- id = half_edges_out[i].second;
- Point l = half_edges_out[i].first.first;
- Point h = half_edges_out[i].first.second;
- directed_line_segment_type orig_seg = data_[id];
- if(orig_seg.high() < orig_seg.low())
- std::swap(l, h);
- result.push_back(directed_line_segment_type(l, h));
- }
- std::swap(result, data_);
- dirty_ = false;
- unsorted_ = true;
- };
-
- void sort() const{
- if(unsorted_) {
- polygon_sort(data_.begin(), data_.end());
- unsorted_ = false;
- }
- }
-
- template <typename input_iterator_type>
- void set(input_iterator_type input_begin, input_iterator_type input_end) {
- clear();
- reserve(std::distance(input_begin,input_end));
- insert(input_begin, input_end);
- dirty_ = true;
- unsorted_ = true;
- }
-
- void set(const value_type& value) {
- data_ = value;
- dirty_ = true;
- unsorted_ = true;
- }
-
- template <typename rectangle_type>
- bool extents(rectangle_type& rect) {
- if(empty()) return false;
- bool first_iteration = true;
- for(iterator_type itr = begin();
- itr != end(); ++itr) {
- rectangle_type edge_box;
- set_points(edge_box, (*itr).low(), (*itr).high());
- if(first_iteration)
- rect = edge_box;
- else
- encompass(rect, edge_box);
- first_iteration = false;
- }
- return true;
- }
-
- template <typename transform_type>
- inline directed_line_segment_set_data&
- transform(const transform_type& tr) {
- for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
- point_type l = (*itr).low();
- point_type h = (*itr).high();
- ::boost::polygon::transform(l, tr);
- ::boost::polygon::transform(h, tr);
- (*itr).low(l);
- (*itr).high(h);
- }
- unsorted_ = true;
- return *this;
- }
-
- inline directed_line_segment_set_data&
- scale_up(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
- for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
- point_type l = (*itr).low();
- point_type h = (*itr).high();
- ::boost::polygon::scale_up(l, factor);
- ::boost::polygon::scale_up(h, factor);
- (*itr).low(l);
- (*itr).high(h);
- }
- return *this;
- }
-
- inline directed_line_segment_set_data&
- scale_down(typename coordinate_traits<coordinate_type>::unsigned_area_type factor) {
- for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
- point_type l = (*itr).low();
- point_type h = (*itr).high();
- ::boost::polygon::scale_down(l, factor);
- ::boost::polygon::scale_down(h, factor);
- (*itr).low(l);
- (*itr).high(h);
- }
- return *this;
- }
-
- template <typename scaling_type>
- inline directed_line_segment_set_data& scale(const scaling_type& scaling) {
- for(typename value_type::iterator itr = data_.begin(); itr != data_.end(); ++itr) {
- point_type l = (*itr).low();
- point_type h = (*itr).high();
- ::boost::polygon::scale(l, scaling);
- ::boost::polygon::scale(h, scaling);
- (*itr).low(l);
- (*itr).high(h);
- }
- return *this;
- }
-
- template <typename cT>
- std::size_t get_intersection_points(cT& output_points) const {
- typedef T Unit;
- typedef typename scanline_base<Unit>::Point Point;
- typedef typename scanline_base<Unit>::half_edge half_edge;
- typedef int segment_id;
- std::vector<std::pair<half_edge, segment_id> > half_edges;
- std::vector<std::pair<half_edge, segment_id> > half_edges_out;
- segment_id id = 0;
- half_edges.reserve(data_.size());
- for(iterator_type itr = begin(); itr != end(); ++itr) {
- Point l = (*itr).low();
- Point h = (*itr).high();
- half_edges.push_back(std::make_pair(half_edge(l, h), id++));
- }
- half_edges_out.reserve(half_edges.size());
- std::vector<std::set<Point> > intersection_points(half_edges.size(), std::set<Point>());
- line_intersection<Unit>::validate_scan_divide_and_conquer(intersection_points, half_edges.begin(), half_edges.end());
- std::vector<Point> tmp_points;
- for(std::size_t i = 0; i < intersection_points.size(); ++i) {
- typename std::set<Point>::iterator itr2 = intersection_points[i].begin();
- for(; itr2 != intersection_points[i].end(); ++itr2)
- if(data_[i].low() != *itr2 && data_[i].high() != *itr2)
- tmp_points.push_back(*itr2);
- }
- polygon_sort(tmp_points.begin(), tmp_points.end());
- typename std::vector<Point>::iterator new_end = std::unique(tmp_points.begin(), tmp_points.end());
- output_points.insert(output_points.end(), tmp_points.begin(), new_end);
- return std::distance(tmp_points.begin(), new_end);
- };
-
-
-private:
- mutable value_type data_;
- mutable bool dirty_;
- mutable bool unsorted_;
-};
-
-}
-}
-#endif

Deleted: trunk/boost/polygon/directed_line_segment_traits.hpp
==============================================================================
--- trunk/boost/polygon/directed_line_segment_traits.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
+++ (empty file)
@@ -1,42 +0,0 @@
-/*
- Copyright 2008 Intel Corporation
-
- Use, modification and distribution are subject to the Boost Software License,
- Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
-*/
-#ifndef BOOST_POLYGON_DIRECTED_LINE_SEGMENT_TRAITS_HPP
-#define BOOST_POLYGON_DIRECTED_LINE_SEGMENT_TRAITS_HPP
-namespace boost { namespace polygon{
- template <typename T>
- struct directed_line_segment_traits {
- typedef typename T::coordinate_type coordinate_type;
- typedef typename T::point_type point_type;
-
- static inline point_type get(const T& segment, direction_1d dir) {
- return segment.get(dir);
- }
- };
-
- template <typename T>
- struct directed_line_segment_mutable_traits {
- template <typename Point1>
- static inline void set(T& segment, direction_1d dir, const Point1& value) {
- typename directed_line_segment_traits<T>::point_type p1;
- assign(p1, value);
- segment.set(dir, value);
- }
-
- template <typename Point1, typename Point2>
- static inline T construct(const Point1& low_value,
- const Point2& high_value) {
- typename directed_line_segment_traits<T>::point_type p1, p2;
- assign(p1, low_value);
- assign(p2, high_value);
- return T(p1, p2);
- }
- };
-}
-}
-#endif
-

Modified: trunk/boost/polygon/interval_concept.hpp
==============================================================================
--- trunk/boost/polygon/interval_concept.hpp (original)
+++ trunk/boost/polygon/interval_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -47,65 +47,79 @@
             T, typename is_interval_concept<typename geometry_concept<T>::type>::type>::type type;
   };
 
+ struct y_i_get : gtl_yes {};
 
   template <typename T>
- typename interval_coordinate_type<T>::type
- get(const T& interval, direction_1d dir,
- typename enable_if<typename gtl_if<typename is_interval_concept<typename geometry_concept<T>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<
+ y_i_get,
+ typename is_interval_concept<typename geometry_concept<T>::type>::type>::type,
+ typename interval_coordinate_type<T>::type>::type
+ get(const T& interval, direction_1d dir) {
     return interval_traits<T>::get(interval, dir);
   }
 
+ struct y_i_set : gtl_yes {};
+
   template <typename T, typename coordinate_type>
- void
- set(T& interval, direction_1d dir, coordinate_type value,
- typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<
+ y_i_set,
+ typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type,
+ void>::type
+ set(T& interval, direction_1d dir, coordinate_type value) {
     //this may need to be refined
     interval_mutable_traits<T>::set(interval, dir, value);
     if(high(interval) < low(interval))
       interval_mutable_traits<T>::set(interval, dir.backward(), value);
   }
+
+ struct y_i_construct : gtl_yes {};
   
   template <typename T, typename T2, typename T3>
- T
- construct(T2 low_value, T3 high_value,
- typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<
+ y_i_construct,
+ typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type>::type,
+ T>::type
+ construct(T2 low_value, T3 high_value) {
     if(low_value > high_value) std::swap(low_value, high_value);
     return interval_mutable_traits<T>::construct(low_value, high_value);
   }
+
+ struct y_i_copy_construct : gtl_yes {};
   
   template <typename T, typename T2>
- T
- copy_construct(const T2& interval,
- typename enable_if< typename gtl_and<typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type,
- typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
- return construct<T>
- (get(interval, LOW ),
- get(interval, HIGH));
+ typename enable_if< typename gtl_and_3<
+ y_i_copy_construct,
+ typename is_mutable_interval_concept<typename geometry_concept<T>::type>::type,
+ typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
+ T>::type
+ copy_construct(const T2& interval) {
+ return construct<T>(get(interval, LOW ), get(interval, HIGH));
   }
 
+ struct y_i_assign : gtl_yes {};
+
   template <typename T1, typename T2>
- T1 &
- assign(T1& lvalue, const T2& rvalue,
- typename enable_if< typename gtl_and< typename is_mutable_interval_concept<typename geometry_concept<T1>::type>::type,
- typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0) {
+ typename enable_if< typename gtl_and_3<
+ y_i_assign,
+ typename is_mutable_interval_concept<typename geometry_concept<T1>::type>::type,
+ typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
+ T1>::type &
+ assign(T1& lvalue, const T2& rvalue) {
     lvalue = copy_construct<T1>(rvalue);
     return lvalue;
   }
 
+ struct y_i_equivalence : gtl_yes {};
+
   template <typename T, typename T2>
- bool
- equivalence(const T& interval1, const T2& interval2,
- typename enable_if< typename gtl_and< typename is_interval_concept<typename geometry_concept<T>::type>::type,
- typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
- return get(interval1, LOW) ==
- get(interval2, LOW) &&
- get(interval1, HIGH) ==
- get(interval2, HIGH);
+ typename enable_if< typename gtl_and_3<
+ y_i_equivalence,
+ typename is_interval_concept<typename geometry_concept<T>::type>::type,
+ typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
+ bool>::type
+ equivalence(const T& interval1, const T2& interval2) {
+ return get(interval1, LOW) == get(interval2, LOW) &&
+ get(interval1, HIGH) == get(interval2, HIGH);
   }
   
   struct y_i_contains : gtl_yes {};
@@ -113,7 +127,7 @@
   template <typename interval_type>
   typename enable_if< typename gtl_and< y_i_contains, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type >::type, bool>::type
   contains(const interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type value,
+ typename interval_coordinate_type<interval_type>::type value,
            bool consider_touch = true ) {
     if(consider_touch) {
       return value <= high(interval) && value >= low(interval);
@@ -121,63 +135,85 @@
       return value < high(interval) && value > low(interval);
     }
   }
-
+
+ struct y_i_contains2 : gtl_yes {};
+
   template <typename interval_type, typename interval_type_2>
- bool
+ typename enable_if< typename gtl_and_3<
+ y_i_contains2,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
+ typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
+ bool>::type
   contains(const interval_type& interval,
- const interval_type_2& value, bool consider_touch = true,
- typename enable_if< typename gtl_and< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type,
- typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type>::type * = 0
- ) {
+ const interval_type_2& value,
+ bool consider_touch = true) {
     return contains(interval, get(value, LOW), consider_touch) &&
       contains(interval, get(value, HIGH), consider_touch);
   }
-
+
+ struct y_i_low : gtl_yes {};
+
   // get the low coordinate
   template <typename interval_type>
- typename interval_traits<interval_type>::coordinate_type
- low(const interval_type& interval,
- typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
- ) { return get(interval, LOW); }
+ typename enable_if< typename gtl_and<
+ y_i_low,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ typename interval_coordinate_type<interval_type>::type>::type
+ low(const interval_type& interval) { return get(interval, LOW); }
+
+ struct y_i_high : gtl_yes {};
 
   // get the high coordinate
   template <typename interval_type>
- typename interval_traits<interval_type>::coordinate_type
- high(const interval_type& interval,
- typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
- ) { return get(interval, HIGH); }
+ typename enable_if< typename gtl_and<
+ y_i_high,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ typename interval_coordinate_type<interval_type>::type>::type
+ high(const interval_type& interval) { return get(interval, HIGH); }
+
+ struct y_i_center : gtl_yes {};
 
   // get the center coordinate
   template <typename interval_type>
- typename interval_traits<interval_type>::coordinate_type
- center(const interval_type& interval,
- typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
- ) { return (high(interval) + low(interval))/2; }
+ typename enable_if< typename gtl_and<
+ y_i_center,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ typename interval_coordinate_type<interval_type>::type>::type
+ center(const interval_type& interval) { return (high(interval) + low(interval))/2; }
 
 
- struct y_i_low : gtl_yes {};
+ struct y_i_low2 : gtl_yes {};
 
   // set the low coordinate to v
   template <typename interval_type>
- typename enable_if<typename gtl_and<y_i_low, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, void>::type
+ typename enable_if<typename gtl_and<
+ y_i_low2,
+ typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ void>::type
   low(interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type v) { set(interval, LOW, v); }
+ typename interval_coordinate_type<interval_type>::type v) { set(interval, LOW, v); }
   
- struct y_i_high : gtl_yes {};
+ struct y_i_high2 : gtl_yes {};
 
   // set the high coordinate to v
   template <typename interval_type>
- typename enable_if<typename gtl_and<y_i_high, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, void>::type
+ typename enable_if<typename gtl_and<
+ y_i_high2,
+ typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ void>::type
   high(interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type v) { set(interval, HIGH, v); }
-
+ typename interval_coordinate_type<interval_type>::type v) { set(interval, HIGH, v); }
+
+ struct y_i_delta : gtl_yes {};
+
   // get the magnitude of the interval
   template <typename interval_type>
- typename interval_difference_type<interval_type>::type
- delta(const interval_type& interval,
- typename enable_if< typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
- ) {
- typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference diffT;
+ typename enable_if< typename gtl_and<
+ y_i_delta,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ typename interval_difference_type<interval_type>::type >::type
+ delta(const interval_type& interval) {
+ typedef typename coordinate_traits<typename interval_coordinate_type<interval_type>::type>::coordinate_difference diffT;
     return (diffT)high(interval) - (diffT)low(interval); }
 
   struct y_i_flip : gtl_yes {};
@@ -186,8 +222,8 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_flip, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   flip(interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type axis = 0) {
- typename interval_traits<interval_type>::coordinate_type newLow, newHigh;
+ typename interval_coordinate_type<interval_type>::type axis = 0) {
+ typename interval_coordinate_type<interval_type>::type newLow, newHigh;
     newLow = 2 * axis - high(interval);
     newHigh = 2 * axis - low(interval);
     low(interval, newLow);
@@ -201,8 +237,8 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_scale_up, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   scale_up(interval_type& interval,
- typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::unsigned_area_type factor) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typename coordinate_traits<typename interval_coordinate_type<interval_type>::type>::unsigned_area_type factor) {
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newHigh = high(interval) * (Unit)factor;
     low(interval, low(interval) * (Unit)factor);
     high(interval, (newHigh));
@@ -214,8 +250,8 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_scale_down, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   scale_down(interval_type& interval,
- typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::unsigned_area_type factor) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typename coordinate_traits<typename interval_coordinate_type<interval_type>::type>::unsigned_area_type factor) {
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     typedef typename coordinate_traits<Unit>::coordinate_distance dt;
     Unit newHigh = scaling_policy<Unit>::round((dt)(high(interval)) / (dt)factor);
     low(interval, scaling_policy<Unit>::round((dt)(low(interval)) / (dt)factor));
@@ -228,21 +264,23 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_scale, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   scale(interval_type& interval, double factor) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newHigh = scaling_policy<Unit>::round((double)(high(interval)) * factor);
     low(interval, scaling_policy<Unit>::round((double)low(interval)* factor));
     high(interval, (newHigh));
     return interval;
   }
-
+
+ struct y_i_move : gtl_yes {};
+
   // move interval by delta
   template <typename interval_type>
- interval_type&
- move(interval_type& interval,
- typename interval_difference_type<interval_type>::type displacement,
- typename enable_if<typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type * = 0
- ) {
- typedef typename interval_traits<interval_type>::coordinate_type ctype;
+ typename enable_if< typename gtl_and<
+ y_i_move,
+ typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ interval_type>::type &
+ move(interval_type& interval, typename interval_difference_type<interval_type>::type displacement) {
+ typedef typename interval_coordinate_type<interval_type>::type ctype;
     typedef typename coordinate_traits<ctype>::coordinate_difference Unit;
     Unit len = delta(interval);
     low(interval, static_cast<ctype>(static_cast<Unit>(low(interval)) + displacement));
@@ -256,8 +294,8 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_convolve, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   convolve(interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typename interval_coordinate_type<interval_type>::type b) {
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) + b;
     Unit newHigh = high(interval) + b;
     low(interval, newLow);
@@ -271,8 +309,8 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_deconvolve, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type &
   deconvolve(interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typename interval_coordinate_type<interval_type>::type b) {
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) - b;
     Unit newHigh = high(interval) - b;
     low(interval, newLow);
@@ -291,7 +329,7 @@
     interval_type>::type &
   convolve(interval_type& interval,
            const interval_type_2& b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) + low(b);
     Unit newHigh = high(interval) + high(b);
     low(interval, newLow);
@@ -310,7 +348,7 @@
     interval_type>::type &
   deconvolve(interval_type& interval,
              const interval_type_2& b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) - low(b);
     Unit newHigh = high(interval) - high(b);
     low(interval, newLow);
@@ -329,7 +367,7 @@
     interval_type>::type &
   reflected_convolve(interval_type& interval,
                      const interval_type_2& b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) - high(b);
     Unit newHigh = high(interval) - low(b);
     low(interval, newLow);
@@ -348,7 +386,7 @@
     interval_type>::type &
   reflected_deconvolve(interval_type& interval,
                        const interval_type_2& b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit newLow = low(interval) + high(b);
     Unit newHigh = high(interval) + low(b);
     low(interval, newLow);
@@ -363,8 +401,8 @@
   typename enable_if< typename gtl_and<y_i_e_dist1, typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        typename interval_difference_type<interval_type>::type>::type
   euclidean_distance(const interval_type& interval,
- typename interval_traits<interval_type>::coordinate_type position) {
- typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference Unit;
+ typename interval_coordinate_type<interval_type>::type position) {
+ typedef typename coordinate_traits<typename interval_difference_type<interval_type>::type>::coordinate_difference Unit;
     Unit dist[3] = {0, (Unit)low(interval) - (Unit)position, (Unit)position - (Unit)high(interval)};
     return dist[ (dist[1] > 0) + ((dist[2] > 0) << 1) ];
   }
@@ -379,7 +417,7 @@
     typename interval_difference_type<interval_type>::type>::type
   euclidean_distance(const interval_type& interval,
                      const interval_type_2& b) {
- typedef typename coordinate_traits<typename interval_traits<interval_type>::coordinate_type>::coordinate_difference Unit;
+ typedef typename coordinate_traits<typename interval_difference_type<interval_type>::type>::coordinate_difference Unit;
     Unit dist[3] = {0, (Unit)low(interval) - (Unit)high(b), (Unit)low(b) - (Unit)high(interval)};
     return dist[ (dist[1] > 0) + ((dist[2] > 0) << 1) ];
   }
@@ -446,7 +484,7 @@
                                          typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
                        bool>::type
   intersect(interval_type& interval, const interval_type_2& b, bool consider_touch = true) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit lowVal = (std::max)(low(interval), low(b));
     Unit highVal = (std::min)(high(interval), high(b));
     bool valid = consider_touch ?
@@ -468,7 +506,7 @@
                       typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
     interval_type>::type &
   generalized_intersect(interval_type& interval, const interval_type_2& b) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit coords[4] = {low(interval), high(interval), low(b), high(b)};
     //consider implementing faster sorting of small fixed length range
     polygon_sort(coords, coords+4);
@@ -483,7 +521,7 @@
   template <typename interval_type>
   typename enable_if< typename gtl_and<y_i_bloat, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        interval_type>::type &
- bloat(interval_type& interval, typename interval_traits<interval_type>::coordinate_type bloating) {
+ bloat(interval_type& interval, typename interval_coordinate_type<interval_type>::type bloating) {
     low(interval, low(interval)-bloating);
     high(interval, high(interval)+bloating);
     return interval;
@@ -495,7 +533,7 @@
   template <typename interval_type>
   typename enable_if< typename gtl_and<y_i_bloat2, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        interval_type>::type &
- bloat(interval_type& interval, direction_1d dir, typename interval_traits<interval_type>::coordinate_type bloating) {
+ bloat(interval_type& interval, direction_1d dir, typename interval_coordinate_type<interval_type>::type bloating) {
     set(interval, dir, get(interval, dir) + dir.get_sign() * bloating);
     return interval;
   }
@@ -506,7 +544,7 @@
   template <typename interval_type>
   typename enable_if< typename gtl_and<y_i_shrink, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        interval_type>::type &
- shrink(interval_type& interval, typename interval_traits<interval_type>::coordinate_type shrinking) {
+ shrink(interval_type& interval, typename interval_coordinate_type<interval_type>::type shrinking) {
     return bloat(interval, -shrinking);
   }
 
@@ -516,31 +554,33 @@
   template <typename interval_type>
   typename enable_if< typename gtl_and<y_i_shrink2, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        interval_type>::type &
- shrink(interval_type& interval, direction_1d dir, typename interval_traits<interval_type>::coordinate_type shrinking) {
+ shrink(interval_type& interval, direction_1d dir, typename interval_coordinate_type<interval_type>::type shrinking) {
     return bloat(interval, dir, -shrinking);
   }
 
+ struct y_i_encompass : gtl_yes {};
+
   // Enlarge `this` Interval to encompass the specified Interval
   template <typename interval_type, typename interval_type_2>
- bool
- encompass(interval_type& interval, const interval_type_2& b,
- typename enable_if<
- typename gtl_and< typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
- typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and_3<
+ y_i_encompass,
+ typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type,
+ typename is_interval_concept<typename geometry_concept<interval_type_2>::type>::type>::type,
+ bool>::type
+ encompass(interval_type& interval, const interval_type_2& b) {
     bool retval = !contains(interval, b, true);
     low(interval, (std::min)(low(interval), low(b)));
     high(interval, (std::max)(high(interval), high(b)));
     return retval;
   }
 
- struct y_i_encompass : gtl_yes {};
+ struct y_i_encompass2 : gtl_yes {};
 
   // Enlarge `this` Interval to encompass the specified Interval
   template <typename interval_type>
- typename enable_if< typename gtl_and<y_i_encompass, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_i_encompass2, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
                        bool>::type
- encompass(interval_type& interval, typename interval_traits<interval_type>::coordinate_type b) {
+ encompass(interval_type& interval, typename interval_coordinate_type<interval_type>::type b) {
     bool retval = !contains(interval, b, true);
     low(interval, (std::min)(low(interval), b));
     high(interval, (std::max)(high(interval), b));
@@ -553,7 +593,7 @@
   template <typename interval_type>
   typename enable_if<typename gtl_and<y_i_get_half, typename is_mutable_interval_concept<typename geometry_concept<interval_type>::type>::type>::type, interval_type>::type
   get_half(const interval_type& interval, direction_1d d1d) {
- typedef typename interval_traits<interval_type>::coordinate_type Unit;
+ typedef typename interval_coordinate_type<interval_type>::type Unit;
     Unit c = (get(interval, LOW) + get(interval, HIGH)) / 2;
     return construct<interval_type>((d1d == LOW) ? get(interval, LOW) : c,
                                     (d1d == LOW) ? c : get(interval, HIGH));

Modified: trunk/boost/polygon/point_3d_concept.hpp
==============================================================================
--- trunk/boost/polygon/point_3d_concept.hpp (original)
+++ trunk/boost/polygon/point_3d_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -39,7 +39,7 @@
   struct point_3d_difference_type_by_concept { typedef void type; };
   template <typename T>
   struct point_3d_difference_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename point_3d_traits<T>::coordinate_type>::coordinate_difference type; };
+ typedef typename coordinate_traits<typename point_3d_coordinate_type<T>::type>::coordinate_difference type; };
 
   template <typename T>
   struct point_3d_difference_type {
@@ -51,7 +51,7 @@
   struct point_3d_distance_type_by_concept { typedef void type; };
   template <typename T>
   struct point_3d_distance_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename point_3d_traits<T>::coordinate_type>::coordinate_distance type; };
+ typedef typename coordinate_traits<typename point_3d_coordinate_type<T>::type>::coordinate_distance type; };
 
   template <typename T>
   struct point_3d_distance_type {
@@ -62,7 +62,7 @@
   struct y_p3d_get : gtl_yes {};
 
   template <typename T>
- typename enable_if< typename gtl_and<y_p3d_get, typename gtl_if<typename is_point_3d_concept<typename geometry_concept<T>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_p3d_get, typename is_point_3d_concept<typename geometry_concept<T>::type>::type>::type,
                        typename point_3d_coordinate_type<T>::type >::type
   get(const T& point, orientation_3d orient) { return point_3d_traits<T>::get(point, orient); }
   
@@ -103,7 +103,7 @@
 
   template <typename point_type>
   typename enable_if< typename gtl_and<y_p3d_z, typename is_point_3d_concept<typename geometry_concept<point_type>::type>::type>::type,
- typename point_3d_traits<point_type>::coordinate_type >::type
+ typename point_3d_coordinate_type<point_type>::type >::type
   z(const point_type& point) { return get(point, PROXIMAL); }
 
   struct y_p3d_x : gtl_yes {};
@@ -142,7 +142,7 @@
                                           typename is_point_3d_concept<typename geometry_concept<point_type_2>::type>::type>::type,
                        typename point_3d_difference_type<point_type_1>::type>::type
   euclidean_distance(const point_type_1& point1, const point_type_2& point2, orientation_3d orient) {
- typedef typename coordinate_traits<typename point_3d_traits<point_type_1>::coordinate_type>::coordinate_difference return_type;
+ typedef typename coordinate_traits<typename point_3d_coordinate_type<point_type_1>::type>::coordinate_difference return_type;
     return_type return_value =
       (return_type)get(point1, orient) - (return_type)get(point2, orient);
     return return_value < 0 ? -return_value : return_value;
@@ -167,7 +167,7 @@
     typename gtl_same_type<point_3d_concept, typename geometry_concept<point_type_2>::type>::type>::type,
                        typename point_3d_distance_type<point_type_1>::type>::type
   euclidean_distance(const point_type_1& point1, const point_type_2& point2) {
- typedef typename coordinate_traits<typename point_3d_traits<point_type_1>::coordinate_type>::coordinate_distance return_value;
+ typedef typename coordinate_traits<typename point_3d_coordinate_type<point_type_1>::type>::coordinate_distance return_value;
     return_value pdist = (return_value)euclidean_distance(point1, point2, PROXIMAL);
     pdist *= pdist;
     return sqrt((double)(distance_squared(point1, point2) + pdist));
@@ -207,10 +207,10 @@
   typename enable_if< typename gtl_and<y_p3d_scale_up, typename is_mutable_point_3d_concept<typename geometry_concept<point_type>::type>::type>::type,
                        point_type>::type &
   scale_up(point_type& point,
- typename coordinate_traits<typename point_3d_traits<point_type>::coordinate_type>::unsigned_area_type factor) {
- x(point, x(point) * (typename point_3d_traits<point_type>::coordinate_type)factor);
- y(point, y(point) * (typename point_3d_traits<point_type>::coordinate_type)factor);
- z(point, z(point) * (typename point_3d_traits<point_type>::coordinate_type)factor);
+ typename coordinate_traits<typename point_3d_coordinate_type<point_type>::type>::unsigned_area_type factor) {
+ x(point, x(point) * (typename point_3d_coordinate_type<point_type>::type)factor);
+ y(point, y(point) * (typename point_3d_coordinate_type<point_type>::type)factor);
+ z(point, z(point) * (typename point_3d_coordinate_type<point_type>::type)factor);
     return point;
   }
 
@@ -220,8 +220,8 @@
   typename enable_if< typename gtl_and<y_p3d_scale_down, typename is_mutable_point_3d_concept<typename geometry_concept<point_type>::type>::type>::type,
                        point_type>::type &
   scale_down(point_type& point,
- typename coordinate_traits<typename point_3d_traits<point_type>::coordinate_type>::unsigned_area_type factor) {
- typedef typename point_3d_traits<point_type>::coordinate_type Unit;
+ typename coordinate_traits<typename point_3d_coordinate_type<point_type>::type>::unsigned_area_type factor) {
+ typedef typename point_3d_coordinate_type<point_type>::type Unit;
     typedef typename coordinate_traits<Unit>::coordinate_distance dt;
     x(point, scaling_policy<Unit>::round((dt)(x(point)) / (dt)factor));
     y(point, scaling_policy<Unit>::round((dt)(y(point)) / (dt)factor));
@@ -236,7 +236,7 @@
                        point_type>::type &
   scale(point_type& point,
         const scaling_type& scaling) {
- typedef typename point_3d_traits<point_type>::coordinate_type Unit;
+ typedef typename point_3d_coordinate_type<point_type>::type Unit;
     Unit x_(x(point)), y_(y(point)), z_(z(point));
     scaling.scale(x_, y_, z_);
     x(point, x_);
@@ -251,7 +251,7 @@
   typename enable_if< typename gtl_and<y_p3d_transform, typename is_mutable_point_3d_concept<typename geometry_concept<point_type>::type>::type>::type,
                        point_type>::type &
   transform(point_type& point, const transformation_type& transformation) {
- typedef typename point_3d_traits<point_type>::coordinate_type Unit;
+ typedef typename point_3d_coordinate_type<point_type>::type Unit;
     Unit x_(x(point)), y_(y(point)), z_(z(point));
     transformation.transform(x_, y_, z_);
     x(point, x_);

Modified: trunk/boost/polygon/point_concept.hpp
==============================================================================
--- trunk/boost/polygon/point_concept.hpp (original)
+++ trunk/boost/polygon/point_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -42,7 +42,7 @@
   struct point_difference_type_by_concept { typedef void type; };
   template <typename T>
   struct point_difference_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename point_traits<T>::coordinate_type>::coordinate_difference type; };
+ typedef typename coordinate_traits<typename point_coordinate_type<T>::type>::coordinate_difference type; };
 
   template <typename T>
   struct point_difference_type {
@@ -54,7 +54,7 @@
   struct point_distance_type_by_concept { typedef void type; };
   template <typename T>
   struct point_distance_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename point_traits<T>::coordinate_type>::coordinate_distance type; };
+ typedef typename coordinate_traits<typename point_coordinate_type<T>::type>::coordinate_distance type; };
 
   template <typename T>
   struct point_distance_type {
@@ -62,36 +62,42 @@
             T, typename is_point_concept<typename geometry_concept<T>::type>::type>::type type;
   };
 
+ struct y_pt_get : gtl_yes {};
+
   template <typename T>
- typename point_coordinate_type<T>::type
- get(const T& point, orientation_2d orient,
- typename enable_if< typename gtl_if<typename is_point_concept<typename geometry_concept<T>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<y_pt_get, typename is_point_concept<typename geometry_concept<T>::type>::type>::type,
+ typename point_coordinate_type<T>::type >::type
+ get(const T& point, orientation_2d orient) {
     return point_traits<T>::get(point, orient);
   }
-
+
+ struct y_pt_set : gtl_yes {};
+
   template <typename T, typename coordinate_type>
- void
- set(T& point, orientation_2d orient, coordinate_type value,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<y_pt_set, typename is_mutable_point_concept<typename geometry_concept<T>::type>::type>::type,
+ void>::type
+ set(T& point, orientation_2d orient, coordinate_type value) {
     point_mutable_traits<T>::set(point, orient, value);
   }
-
+
+ struct y_pt_construct : gtl_yes {};
+
   template <typename T, typename coordinate_type1, typename coordinate_type2>
- T
- construct(coordinate_type1 x_value, coordinate_type2 y_value,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<T>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<y_pt_construct, typename is_mutable_point_concept<typename geometry_concept<T>::type>::type>::type,
+ T>::type
+ construct(coordinate_type1 x_value, coordinate_type2 y_value) {
     return point_mutable_traits<T>::construct(x_value, y_value);
   }
 
+ struct y_pt_assign : gtl_yes {};
+
   template <typename T1, typename T2>
- T1&
- assign(T1& lvalue, const T2& rvalue,
- typename enable_if< typename gtl_and< typename is_mutable_point_concept<typename geometry_concept<T1>::type>::type,
- typename is_point_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if<typename gtl_and_3<
+ y_pt_assign,
+ typename is_mutable_point_concept<typename geometry_concept<T1>::type>::type,
+ typename is_point_concept<typename geometry_concept<T2>::type>::type>::type,
+ T1>::type &
+ assign(T1& lvalue, const T2& rvalue) {
     set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL));
     set(lvalue, VERTICAL, get(rvalue, VERTICAL));
     return lvalue;
@@ -101,7 +107,7 @@
 
   template <typename point_type>
   typename enable_if< typename gtl_and<y_p_x, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
- typename point_traits<point_type>::coordinate_type >::type
+ typename point_coordinate_type<point_type>::type >::type
   x(const point_type& point) {
     return get(point, HORIZONTAL);
   }
@@ -110,7 +116,7 @@
 
   template <typename point_type>
   typename enable_if< typename gtl_and<y_p_y, typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
- typename point_traits<point_type>::coordinate_type >::type
+ typename point_coordinate_type<point_type>::type >::type
   y(const point_type& point) {
     return get(point, VERTICAL);
   }
@@ -133,57 +139,66 @@
     set(point, VERTICAL, value);
   }
 
+ struct y_pt_equiv : gtl_yes {};
+
   template <typename T, typename T2>
- bool
- equivalence(const T& point1, const T2& point2,
- typename enable_if< typename gtl_and<typename gtl_same_type<point_concept, typename geometry_concept<T>::type>::type,
- typename is_point_concept<typename geometry_concept<T2>::type>::type>::type>::type * = 0
- ) {
- typename point_traits<T>::coordinate_type x1 = x(point1);
- typename point_traits<T2>::coordinate_type x2 = get(point2, HORIZONTAL);
- typename point_traits<T>::coordinate_type y1 = get(point1, VERTICAL);
- typename point_traits<T2>::coordinate_type y2 = y(point2);
+ typename enable_if<typename gtl_and_3<y_pt_equiv,
+ typename gtl_same_type<point_concept, typename geometry_concept<T>::type>::type,
+ typename is_point_concept<typename geometry_concept<T2>::type>::type>::type,
+ bool>::type
+ equivalence(const T& point1, const T2& point2) {
+ typename point_coordinate_type<T>::type x1 = x(point1);
+ typename point_coordinate_type<T2>::type x2 = get(point2, HORIZONTAL);
+ typename point_coordinate_type<T>::type y1 = get(point1, VERTICAL);
+ typename point_coordinate_type<T2>::type y2 = y(point2);
     return x1 == x2 && y1 == y2;
   }
 
+ struct y_pt_man_dist : gtl_yes {};
+
   template <typename point_type_1, typename point_type_2>
- typename point_difference_type<point_type_1>::type
- manhattan_distance(const point_type_1& point1, const point_type_2& point2,
- typename enable_if< typename gtl_and<typename gtl_same_type<point_concept, typename geometry_concept<point_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type>::type * = 0) {
+ typename enable_if< typename gtl_and_3<
+ y_pt_man_dist,
+ typename gtl_same_type<point_concept, typename geometry_concept<point_type_1>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
+ typename point_difference_type<point_type_1>::type>::type
+ manhattan_distance(const point_type_1& point1, const point_type_2& point2) {
     return euclidean_distance(point1, point2, HORIZONTAL) + euclidean_distance(point1, point2, VERTICAL);
   }
   
- struct y_i_ed1 : gtl_yes {};
+ struct y_pt_ed1 : gtl_yes {};
 
   template <typename point_type_1, typename point_type_2>
- typename enable_if< typename gtl_and_3<y_i_ed1, typename is_point_concept<typename geometry_concept<point_type_1>::type>::type,
+ typename enable_if< typename gtl_and_3<y_pt_ed1, typename is_point_concept<typename geometry_concept<point_type_1>::type>::type,
   typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
   typename point_difference_type<point_type_1>::type>::type
   euclidean_distance(const point_type_1& point1, const point_type_2& point2, orientation_2d orient) {
- typename coordinate_traits<typename point_traits<point_type_1>::coordinate_type>::coordinate_difference return_value =
+ typename coordinate_traits<typename point_coordinate_type<point_type_1>::type>::coordinate_difference return_value =
       get(point1, orient) - get(point2, orient);
- return return_value < 0 ? (typename coordinate_traits<typename point_traits<point_type_1>::coordinate_type>::coordinate_difference)-return_value : return_value;
+ return return_value < 0 ? (typename coordinate_traits<typename point_coordinate_type<point_type_1>::type>::coordinate_difference)-return_value : return_value;
   }
   
- struct y_i_ed2 : gtl_yes {};
+ struct y_pt_ed2 : gtl_yes {};
 
   template <typename point_type_1, typename point_type_2>
- typename enable_if< typename gtl_and_3<y_i_ed2, typename gtl_same_type<point_concept, typename geometry_concept<point_type_1>::type>::type,
+ typename enable_if< typename gtl_and_3<y_pt_ed2, typename gtl_same_type<point_concept, typename geometry_concept<point_type_1>::type>::type,
   typename gtl_same_type<point_concept, typename geometry_concept<point_type_2>::type>::type>::type,
   typename point_distance_type<point_type_1>::type>::type
   euclidean_distance(const point_type_1& point1, const point_type_2& point2) {
- typedef typename point_traits<point_type_1>::coordinate_type Unit;
+ typedef typename point_coordinate_type<point_type_1>::type Unit;
     return sqrt((double)(distance_squared(point1, point2)));
   }
+
+ struct y_pt_eds : gtl_yes {};
   
   template <typename point_type_1, typename point_type_2>
- typename point_difference_type<point_type_1>::type
- distance_squared(const point_type_1& point1, const point_type_2& point2,
- typename enable_if< typename gtl_and<typename is_point_concept<typename geometry_concept<point_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type_1>::coordinate_type Unit;
+ typename enable_if< typename gtl_and_3<
+ y_pt_eds,
+ typename is_point_concept<typename geometry_concept<point_type_1>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
+ typename point_difference_type<point_type_1>::type>::type
+ distance_squared(const point_type_1& point1, const point_type_2& point2) {
+ typedef typename point_coordinate_type<point_type_1>::type Unit;
     typename coordinate_traits<Unit>::coordinate_difference dx = euclidean_distance(point1, point2, HORIZONTAL);
     typename coordinate_traits<Unit>::coordinate_difference dy = euclidean_distance(point1, point2, VERTICAL);
     dx *= dx;
@@ -191,58 +206,66 @@
     return dx + dy;
   }
 
+ struct y_pt_convolve : gtl_yes {};
+
   template <typename point_type_1, typename point_type_2>
- point_type_1 &
- convolve(point_type_1& lvalue, const point_type_2& rvalue,
- typename enable_if< typename gtl_and<typename is_mutable_point_concept<typename geometry_concept<point_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and_3<
+ y_pt_convolve,
+ typename is_mutable_point_concept<typename geometry_concept<point_type_1>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
+ point_type_1>::type &
+ convolve(point_type_1& lvalue, const point_type_2& rvalue) {
     x(lvalue, x(lvalue) + x(rvalue));
     y(lvalue, y(lvalue) + y(rvalue));
     return lvalue;
   }
-
+
+ struct y_pt_deconvolve : gtl_yes {};
+
   template <typename point_type_1, typename point_type_2>
- point_type_1 &
- deconvolve(point_type_1& lvalue, const point_type_2& rvalue,
- typename enable_if< typename gtl_and<typename is_mutable_point_concept<typename geometry_concept<point_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and_3<
+ y_pt_deconvolve,
+ typename is_mutable_point_concept<typename geometry_concept<point_type_1>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
+ point_type_1>::type &
+ deconvolve(point_type_1& lvalue, const point_type_2& rvalue) {
     x(lvalue, x(lvalue) - x(rvalue));
     y(lvalue, y(lvalue) - y(rvalue));
     return lvalue;
   }
+
+ struct y_pt_scale_up : gtl_yes {};
   
   template <typename point_type, typename coord_type>
- point_type &
- scale_up(point_type& point, coord_type factor,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type>::coordinate_type Unit;
+ typename enable_if< typename gtl_and<y_pt_scale_up, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ point_type>::type &
+ scale_up(point_type& point, coord_type factor) {
+ typedef typename point_coordinate_type<point_type>::type Unit;
     x(point, x(point) * (Unit)factor);
     y(point, y(point) * (Unit)factor);
     return point;
   }
 
+ struct y_pt_scale_down : gtl_yes {};
+
   template <typename point_type, typename coord_type>
- point_type &
- scale_down(point_type& point, coord_type factor,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type>::coordinate_type Unit;
+ typename enable_if< typename gtl_and<y_pt_scale_down, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ point_type>::type &
+ scale_down(point_type& point, coord_type factor) {
+ typedef typename point_coordinate_type<point_type>::type Unit;
     typedef typename coordinate_traits<Unit>::coordinate_distance dt;
     x(point, scaling_policy<Unit>::round((dt)((dt)(x(point)) / (dt)factor)));
     y(point, scaling_policy<Unit>::round((dt)((dt)(y(point)) / (dt)factor)));
     return point;
   }
 
+ struct y_pt_scale : gtl_yes {};
+
   template <typename point_type, typename scaling_type>
- point_type &
- scale(point_type& point,
- const scaling_type& scaling,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type>::coordinate_type Unit;
+ typename enable_if< typename gtl_and<y_pt_scale, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ point_type>::type &
+ scale(point_type& point, const scaling_type& scaling) {
+ typedef typename point_coordinate_type<point_type>::type Unit;
     Unit x_(x(point)), y_(y(point));
     scaling.scale(x_, y_);
     x(point, x_);
@@ -250,12 +273,13 @@
     return point;
   }
 
+ struct y_pt_transform : gtl_yes {};
+
   template <typename point_type, typename transformation_type>
- point_type &
- transform(point_type& point, const transformation_type& transformation,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type>::coordinate_type Unit;
+ typename enable_if< typename gtl_and<y_pt_transform, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ point_type>::type &
+ transform(point_type& point, const transformation_type& transformation) {
+ typedef typename point_coordinate_type<point_type>::type Unit;
     Unit x_(x(point)), y_(y(point));
     transformation.transform(x_, y_);
     x(point, x_);
@@ -266,16 +290,11 @@
   struct y_pt_move : gtl_yes {};
 
   template <typename point_type>
- typename enable_if<
- typename gtl_and< y_pt_move,
- typename is_mutable_point_concept<
- typename geometry_concept<point_type>::type>::type>::type,
- point_type>::type &
+ typename enable_if< typename gtl_and<y_pt_move, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ point_type>::type &
   move(point_type& point, orientation_2d orient,
- typename point_traits<point_type>::coordinate_type displacement,
- typename enable_if<typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type>::type * = 0
- ) {
- typedef typename point_traits<point_type>::coordinate_type Unit;
+ typename point_coordinate_type<point_type>::type displacement) {
+ typedef typename point_coordinate_type<point_type>::type Unit;
     Unit v(get(point, orient));
     set(point, orient, v + displacement);
     return point;

Modified: trunk/boost/polygon/polygon.hpp
==============================================================================
--- trunk/boost/polygon/polygon.hpp (original)
+++ trunk/boost/polygon/polygon.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -88,8 +88,9 @@
 
 #include "polygon_set_concept.hpp"
 
-#include "directed_line_segment_data.hpp"
-#include "directed_line_segment_traits.hpp"
-#include "directed_line_segment_concept.hpp"
+//segment
+#include "segment_data.hpp"
+#include "segment_traits.hpp"
+#include "segment_concept.hpp"
 
 #endif

Modified: trunk/boost/polygon/polygon_90_set_concept.hpp
==============================================================================
--- trunk/boost/polygon/polygon_90_set_concept.hpp (original)
+++ trunk/boost/polygon/polygon_90_set_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -460,24 +460,27 @@
     return polygon_set;
   }
 
+ struct y_p_s_move : gtl_yes {};
+
   //move
   template <typename polygon_set_type>
- polygon_set_type&
+ typename enable_if< typename gtl_and<y_p_s_move, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
+ polygon_set_type>::type &
   move(polygon_set_type& polygon_set,
- orientation_2d orient, typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement,
- typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type * = 0) {
+ orientation_2d orient, typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement) {
     if(orient == HORIZONTAL)
       return move(polygon_set, displacement, 0);
     else
       return move(polygon_set, 0, displacement);
   }
 
+ struct y_p_s_move2 : gtl_yes {};
+
   template <typename polygon_set_type>
- polygon_set_type&
+ typename enable_if< typename gtl_and<y_p_s_move2, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
+ polygon_set_type>::type &
   move(polygon_set_type& polygon_set, typename polygon_90_set_traits<polygon_set_type>::coordinate_type x_displacement,
- typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement,
- typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type * = 0
- ) {
+ typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement) {
     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
     polygon_90_set_data<Unit> ps;
     assign(ps, polygon_set);

Modified: trunk/boost/polygon/polygon_traits.hpp
==============================================================================
--- trunk/boost/polygon/polygon_traits.hpp (original)
+++ trunk/boost/polygon/polygon_traits.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -756,8 +756,6 @@
   void snap_point_vector_to_45(std::vector<point_data<Unit> >& pts) {
     typedef point_data<Unit> Point;
     if(pts.size() < 3) { pts.clear(); return; }
- Point firstPt = pts.front();
- Point prevPt = firstPt;
     typename std::vector<point_data<Unit> >::iterator endLocation = std::unique(pts.begin(), pts.end());
     if(endLocation != pts.end()){
       pts.resize(endLocation - pts.begin());

Modified: trunk/boost/polygon/rectangle_concept.hpp
==============================================================================
--- trunk/boost/polygon/rectangle_concept.hpp (original)
+++ trunk/boost/polygon/rectangle_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -63,7 +63,7 @@
   struct rectangle_difference_type_by_concept { typedef void type; };
   template <typename T>
   struct rectangle_difference_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename rectangle_traits<T>::coordinate_type>::coordinate_difference type; };
+ typedef typename coordinate_traits<typename rectangle_traits<T>::coordinate_type>::coordinate_difference type; };
 
   template <typename T>
   struct rectangle_difference_type {
@@ -75,7 +75,7 @@
   struct rectangle_distance_type_by_concept { typedef void type; };
   template <typename T>
   struct rectangle_distance_type_by_concept<T, gtl_yes> {
- typedef typename coordinate_traits<typename rectangle_traits<T>::coordinate_type>::coordinate_distance type; };
+ typedef typename coordinate_traits<typename rectangle_coordinate_type<T>::type>::coordinate_distance type; };
 
   template <typename T>
   struct rectangle_distance_type {
@@ -83,19 +83,20 @@
       T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type;
   };
 
+ struct y_r_get_interval : gtl_yes {};
+
   template <typename T>
- typename rectangle_interval_type<T>::type
- get(const T& rectangle, orientation_2d orient,
- typename enable_if< typename gtl_if<typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type>::type * = 0
- ) {
- return rectangle_traits<T>::get(rectangle, orient);
+ typename enable_if< typename gtl_and<y_r_get_interval, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
+ typename rectangle_interval_type<T>::type>::type
+ get(const T& rectangle, orientation_2d orient) {
+ return rectangle_traits<T>::get(rectangle, orient);
   }
 
   struct y_r_h : gtl_yes {};
 
   template <typename T>
- typename enable_if< typename gtl_and<y_r_h, typename gtl_if<typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type>::type,
- typename rectangle_traits<T>::interval_type>::type
+ typename enable_if< typename gtl_and<y_r_h, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
+ typename rectangle_interval_type<T>::type>::type
   horizontal(const T& rectangle) {
     return rectangle_traits<T>::get(rectangle, HORIZONTAL);
   }
@@ -103,8 +104,8 @@
   struct y_r_v : gtl_yes {};
 
   template <typename T>
- typename enable_if< typename gtl_and<y_r_v, typename gtl_if<typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type>::type,
- typename rectangle_traits<T>::interval_type>::type
+ typename enable_if< typename gtl_and<y_r_v, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
+ typename rectangle_interval_type<T>::type>::type
   vertical(const T& rectangle) {
     return rectangle_traits<T>::get(rectangle, VERTICAL);
   }
@@ -210,7 +211,7 @@
   struct y_r_get : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_get, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_get, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_coordinate_type<rectangle_type>::type>::type
   get(const rectangle_type& rectangle, orientation_2d orient, direction_1d dir) {
     return get(rectangle_traits<rectangle_type>::get(rectangle, orient), dir);
@@ -221,8 +222,8 @@
   template <typename rectangle_type>
   typename enable_if<typename gtl_and<y_r_set3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
   set(rectangle_type& rectangle, orientation_2d orient, direction_1d dir,
- typename rectangle_traits<rectangle_type>::coordinate_type value) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orient);
+ typename rectangle_coordinate_type<rectangle_type>::type value) {
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
     set(ivl, dir, value);
     set(rectangle, orient, ivl);
   }
@@ -230,7 +231,7 @@
   struct y_r_xl : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_xl, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_xl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_coordinate_type<rectangle_type>::type>::type
   xl(const rectangle_type& rectangle) {
     return get(rectangle, HORIZONTAL, LOW);
@@ -240,14 +241,14 @@
 
   template <typename rectangle_type>
   typename enable_if<typename gtl_and<y_r_xl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
- xl(rectangle_type& rectangle, typename rectangle_traits<rectangle_type>::coordinate_type value) {
+ xl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
     return set(rectangle, HORIZONTAL, LOW, value);
   }
 
   struct y_r_xh : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_xh, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_xh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_coordinate_type<rectangle_type>::type>::type
   xh(const rectangle_type& rectangle) {
     return get(rectangle, HORIZONTAL, HIGH);
@@ -257,14 +258,14 @@
 
   template <typename rectangle_type>
   typename enable_if<typename gtl_and<y_r_xh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
- xh(rectangle_type& rectangle, typename rectangle_traits<rectangle_type>::coordinate_type value) {
+ xh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
     return set(rectangle, HORIZONTAL, HIGH, value);
   }
 
   struct y_r_yl : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_yl, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_yl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_coordinate_type<rectangle_type>::type>::type
   yl(const rectangle_type& rectangle) {
     return get(rectangle, VERTICAL, LOW);
@@ -274,14 +275,14 @@
 
   template <typename rectangle_type>
   typename enable_if<typename gtl_and<y_r_yl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
- yl(rectangle_type& rectangle, typename rectangle_traits<rectangle_type>::coordinate_type value) {
+ yl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
     return set(rectangle, VERTICAL, LOW, value);
   }
 
   struct y_r_yh : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_yh, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_yh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_coordinate_type<rectangle_type>::type>::type
   yh(const rectangle_type& rectangle) {
     return get(rectangle, VERTICAL, HIGH);
@@ -291,44 +292,44 @@
 
   template <typename rectangle_type>
   typename enable_if<typename gtl_and<y_r_yh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
- yh(rectangle_type& rectangle, typename rectangle_traits<rectangle_type>::coordinate_type value) {
+ yh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
     return set(rectangle, VERTICAL, HIGH, value);
   }
 
   struct y_r_ll : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if<typename gtl_and<y_r_ll, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> >::type
+ typename enable_if<typename gtl_and<y_r_ll, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
   ll(const rectangle_type& rectangle) {
- return point_data<typename rectangle_traits<rectangle_type>::coordinate_type> (xl(rectangle), yl(rectangle));
+ return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yl(rectangle));
   }
 
   struct y_r_lr : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if<typename gtl_and<y_r_lr, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> >::type
+ typename enable_if<typename gtl_and<y_r_lr, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
   lr(const rectangle_type& rectangle) {
- return point_data<typename rectangle_traits<rectangle_type>::coordinate_type> (xh(rectangle), yl(rectangle));
+ return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yl(rectangle));
   }
 
   struct y_r_ul : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if<typename gtl_and<y_r_ul, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> >::type
+ typename enable_if<typename gtl_and<y_r_ul, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
   ul(const rectangle_type& rectangle) {
- return point_data<typename rectangle_traits<rectangle_type>::coordinate_type> (xl(rectangle), yh(rectangle));
+ return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yh(rectangle));
   }
 
   struct y_r_ur : gtl_yes {};
 
   template <typename rectangle_type>
- typename enable_if<typename gtl_and<y_r_ur, typename gtl_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> >::type
+ typename enable_if<typename gtl_and<y_r_ur, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
   ur(const rectangle_type& rectangle) {
- return point_data<typename rectangle_traits<rectangle_type>::coordinate_type> (xh(rectangle), yh(rectangle));
+ return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yh(rectangle));
   }
 
   struct y_r_contains : gtl_yes {};
@@ -365,24 +366,25 @@
                        rectangle_type>::type &
   set_points(rectangle_type& rectangle, const point_type_1& p1,
              const point_type_2& p2) {
- typedef typename rectangle_traits<rectangle_type>::coordinate_type Unit;
+ typedef typename rectangle_coordinate_type<rectangle_type>::type Unit;
     Unit x1(x(p1));
     Unit x2(x(p2));
     Unit y1(y(p1));
     Unit y2(y(p2));
- horizontal(rectangle, construct<typename rectangle_traits<rectangle_type>::interval_type>(x1, x2));
- vertical(rectangle, construct<typename rectangle_traits<rectangle_type>::interval_type>(y1, y2));
+ horizontal(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(x1, x2));
+ vertical(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(y1, y2));
     return rectangle;
   }
-
+
+ struct y_r_move : gtl_yes {};
+
   // move rectangle by delta in orient
   template <typename rectangle_type>
- rectangle_type&
+ typename enable_if< typename gtl_and<y_r_move, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ rectangle_type>::type &
   move(rectangle_type& rectangle, orientation_2d orient,
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::coordinate_difference delta,
- typename enable_if<typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type * = 0
- ) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orient);
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference delta) {
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
     move(ivl, delta);
     set(rectangle, orient, ivl);
     return rectangle;
@@ -399,7 +401,7 @@
     rectangle_type_1>::type &
   convolve(rectangle_type_1& rectangle,
            const rectangle_type_2& convolution_rectangle) {
- typename rectangle_traits<rectangle_type_1>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
     horizontal(rectangle, convolve(ivl, horizontal(convolution_rectangle)));
     ivl = vertical(rectangle);
     vertical(rectangle, convolve(ivl, vertical(convolution_rectangle)));
@@ -415,7 +417,7 @@
     typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
                        rectangle_type_1>::type &
   deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
- typename rectangle_traits<rectangle_type_1>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
     horizontal(rectangle, deconvolve(ivl, horizontal(convolution_rectangle)));
     ivl = vertical(rectangle);
     vertical(rectangle, deconvolve(ivl, vertical(convolution_rectangle)));
@@ -431,7 +433,7 @@
                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
     rectangle_type_1>::type &
   reflected_convolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
- typename rectangle_traits<rectangle_type_1>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
     horizontal(rectangle, reflected_convolve(ivl, horizontal(convolution_rectangle)));
     ivl = vertical(rectangle);
     vertical(rectangle, reflected_convolve(ivl, vertical(convolution_rectangle)));
@@ -448,7 +450,7 @@
                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
     rectangle_type_1>::type &
   reflected_deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
- typename rectangle_traits<rectangle_type_1>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
     horizontal(rectangle, reflected_deconvolve(ivl, horizontal(convolution_rectangle)));
     ivl = vertical(rectangle);
     vertical(rectangle, reflected_deconvolve(ivl, vertical(convolution_rectangle)));
@@ -463,7 +465,7 @@
                                          typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
                        rectangle_type>::type &
   convolve(rectangle_type& rectangle, const point_type& convolution_point) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle);
     horizontal(rectangle, convolve(ivl, x(convolution_point)));
     ivl = vertical(rectangle);
     vertical(rectangle, convolve(ivl, y(convolution_point)));
@@ -478,7 +480,7 @@
     typename gtl_and_3<y_r_deconvolve2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
                       typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, rectangle_type>::type &
   deconvolve(rectangle_type& rectangle, const point_type& convolution_point) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = horizontal(rectangle);
+ typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle);
     horizontal(rectangle, deconvolve(ivl, x(convolution_point)));
     ivl = vertical(rectangle);
     vertical(rectangle, deconvolve(ivl, y(convolution_point)));
@@ -489,7 +491,7 @@
 
   // get the magnitude of the interval range depending on orient
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_delta, typename gtl_if<typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_delta, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_difference_type<rectangle_type>::type>::type
   delta(const rectangle_type& rectangle, orientation_2d orient) {
     return delta(get(rectangle, orient));
@@ -500,9 +502,9 @@
   // get the area of the rectangle
   template <typename rectangle_type>
   typename enable_if< typename gtl_and<y_r_area, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::manhattan_area_type>::type
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type>::type
   area(const rectangle_type& rectangle) {
- typedef typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::manhattan_area_type area_type;
+ typedef typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type area_type;
     return (area_type)delta(rectangle, HORIZONTAL) * (area_type)delta(rectangle, VERTICAL);
   }
 
@@ -521,18 +523,19 @@
 
   // get the half perimeter of the rectangle
   template <typename rectangle_type>
- typename enable_if< typename gtl_and<y_r_half_p, typename gtl_if<typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type>::type,
+ typename enable_if< typename gtl_and<y_r_half_p, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                        typename rectangle_difference_type<rectangle_type>::type>::type
   half_perimeter(const rectangle_type& rectangle) {
     return delta(rectangle, HORIZONTAL) + delta(rectangle, VERTICAL);
   }
-
+
+ struct y_r_perimeter : gtl_yes {};
+
   // get the perimeter of the rectangle
   template <typename rectangle_type>
- typename rectangle_difference_type<rectangle_type>::type
- perimeter(const rectangle_type& rectangle,
- typename enable_if< typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and<y_r_perimeter, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
+ typename rectangle_difference_type<rectangle_type>::type>::type
+ perimeter(const rectangle_type& rectangle) {
     return 2 * half_perimeter(rectangle);
   }
 
@@ -623,7 +626,7 @@
     bool>::type
   intersect(rectangle_type& rectangle, const interval_type& b,
             orientation_2d orient, bool consider_touch = true) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orient);
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
     if(intersect(ivl, b, consider_touch)) {
       set(rectangle, orient, ivl);
       return true;
@@ -656,7 +659,7 @@
     typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
                        rectangle_type_1>::type &
   generalized_intersect(rectangle_type_1& rectangle, const rectangle_type_2& b) {
- typename rectangle_traits<rectangle_type_1>::interval_type ivl = get(rectangle, HORIZONTAL);
+ typename rectangle_interval_type<rectangle_type_1>::type ivl = get(rectangle, HORIZONTAL);
     generalized_intersect(ivl, horizontal(b));
     horizontal(rectangle, ivl);
     ivl = vertical(rectangle);
@@ -672,8 +675,8 @@
   typename enable_if<typename gtl_and<y_r_bloat, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   bloat(rectangle_type& rectangle, orientation_2d orient,
- typename rectangle_traits<rectangle_type>::coordinate_type bloating) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orient);
+ typename rectangle_coordinate_type<rectangle_type>::type bloating) {
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
     bloat(ivl, bloating);
     set(rectangle, orient, ivl);
     return rectangle;
@@ -686,7 +689,7 @@
   typename enable_if<typename gtl_and<y_r_bloat2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   bloat(rectangle_type& rectangle,
- typename rectangle_traits<rectangle_type>::coordinate_type bloating) {
+ typename rectangle_coordinate_type<rectangle_type>::type bloating) {
     bloat(rectangle, HORIZONTAL, bloating);
     return bloat(rectangle, VERTICAL, bloating);
   }
@@ -698,8 +701,8 @@
   typename enable_if<typename gtl_and<y_r_bloat3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   bloat(rectangle_type& rectangle, direction_2d dir,
- typename rectangle_traits<rectangle_type>::coordinate_type bloating) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orientation_2d(dir));
+ typename rectangle_coordinate_type<rectangle_type>::type bloating) {
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orientation_2d(dir));
     bloat(ivl, direction_1d(dir), bloating);
     set(rectangle, orientation_2d(dir), ivl);
     return rectangle;
@@ -712,7 +715,7 @@
   typename enable_if<typename gtl_and<y_r_shrink, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   shrink(rectangle_type& rectangle, orientation_2d orient,
- typename rectangle_traits<rectangle_type>::coordinate_type shrinking) {
+ typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
     return bloat(rectangle, orient, -shrinking);
   }
 
@@ -723,7 +726,7 @@
   typename enable_if<typename gtl_and<y_r_shrink2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   shrink(rectangle_type& rectangle,
- typename rectangle_traits<rectangle_type>::coordinate_type shrinking) {
+ typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
     return bloat(rectangle, -shrinking);
   }
 
@@ -734,7 +737,7 @@
   typename enable_if<typename gtl_and<y_r_shrink3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                       rectangle_type>::type &
   shrink(rectangle_type& rectangle, direction_2d dir,
- typename rectangle_traits<rectangle_type>::coordinate_type shrinking) {
+ typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
     return bloat(rectangle, dir, -shrinking);
   }
 
@@ -742,13 +745,13 @@
 
   // encompass interval on orient
   template <typename rectangle_type, typename interval_type>
- typename enable_if<
- typename gtl_and_3<y_r_encompass, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
- typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
- bool>::type
- encompass(rectangle_type& rectangle, const interval_type& b,
- orientation_2d orient) {
- typename rectangle_traits<rectangle_type>::interval_type ivl = get(rectangle, orient);
+ typename enable_if<typename gtl_and_3<
+ y_r_encompass,
+ typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
+ typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
+ bool>::type
+ encompass(rectangle_type& rectangle, const interval_type& b, orientation_2d orient) {
+ typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
     if(encompass(ivl, b)) {
       set(rectangle, orient, ivl);
       return true;
@@ -760,12 +763,12 @@
 
   // enlarge rectangle to encompass the Rectangle b
   template <typename rectangle_type_1, typename rectangle_type_2>
- bool
- encompass(rectangle_type_1& rectangle, const rectangle_type_2& b,
- typename enable_if< typename gtl_and_3<y_r_encompass2,
- typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
- typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type >::type>::type * = 0
- ) {
+ typename enable_if< typename gtl_and_3<
+ y_r_encompass2,
+ typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
+ typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type >::type,
+ bool>::type
+ encompass(rectangle_type_1& rectangle, const rectangle_type_2& b) {
     //note that operator | is intentional because both should be called regardless
     return encompass(rectangle, horizontal(b), HORIZONTAL) |
       encompass(rectangle, vertical(b), VERTICAL);
@@ -775,16 +778,13 @@
 
   // enlarge rectangle to encompass the point b
   template <typename rectangle_type_1, typename point_type>
- typename enable_if<
- typename gtl_and_3<y_r_encompass3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
- bool>::type
- encompass(rectangle_type_1& rectangle, const point_type& b,
- typename enable_if<
- typename gtl_and< typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type>::type * = 0
- ) {
- typename rectangle_traits<rectangle_type_1>::interval_type hivl, vivl;
+ typename enable_if<typename gtl_and_3<
+ y_r_encompass3,
+ typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
+ bool>::type
+ encompass(rectangle_type_1& rectangle, const point_type& b) {
+ typename rectangle_interval_type<rectangle_type_1>::type hivl, vivl;
     hivl = horizontal(rectangle);
     vivl = vertical(rectangle);
     //note that operator | is intentional because both should be called regardless
@@ -818,7 +818,7 @@
                       typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
     bool>::type
   get_corner(point_type& corner_point, const rectangle_type& rectangle, direction_2d direction_facing, direction_1d direction_turning) {
- typedef typename rectangle_traits<rectangle_type>::coordinate_type Unit;
+ typedef typename rectangle_coordinate_type<rectangle_type>::type Unit;
     Unit u1 = get(rectangle, direction_facing);
     Unit u2 = get(rectangle, direction_facing.turn(direction_turning));
     if(orientation_2d(direction_facing).to_int()) std::swap(u1, u2);
@@ -844,8 +844,8 @@
                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
                        bool>::type
   join_with(rectangle_type_1& rectangle, const rectangle_type_2& b) {
- typedef typename rectangle_traits<rectangle_type_1>::interval_type Interval1;
- typedef typename rectangle_traits<rectangle_type_2>::interval_type Interval2;
+ typedef typename rectangle_interval_type<rectangle_type_1>::type Interval1;
+ typedef typename rectangle_interval_type<rectangle_type_2>::type Interval2;
     Interval1 hi1 = get(rectangle, HORIZONTAL);
     Interval1 vi1 = get(rectangle, VERTICAL);
     Interval2 hi2 = get(b, HORIZONTAL), vi2 = get(b, VERTICAL);
@@ -887,12 +887,12 @@
   struct y_r_sed : gtl_yes {};
 
   template <typename rectangle_type, typename point_type>
- typename enable_if< typename gtl_if< typename gtl_and_3<y_r_sed,
+ typename enable_if< typename gtl_and_3<y_r_sed,
     typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
- typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type>::type,
+ typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
                        typename rectangle_difference_type<rectangle_type>::type>::type
   square_euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) {
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::coordinate_difference xdist, ydist;
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
     return (xdist * xdist) + (ydist * ydist);
@@ -906,7 +906,7 @@
                                        typename is_rectangle_concept< typename geometry_concept<rectangle_type_2>::type>::type>::type,
     typename rectangle_difference_type<rectangle_type>::type>::type
   square_euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::coordinate_difference xdist, ydist;
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
     return (xdist * xdist) + (ydist * ydist);
@@ -942,7 +942,7 @@
                                        typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
     typename rectangle_difference_type<rectangle_type>::type>::type
   manhattan_distance(rectangle_type& lvalue, const point_type& rvalue) {
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::coordinate_difference xdist, ydist;
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
     return xdist + ydist;
@@ -956,7 +956,7 @@
                                        typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
     typename rectangle_difference_type<rectangle_type>::type>::type
   manhattan_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::coordinate_difference xdist, ydist;
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
     return xdist + ydist;
@@ -968,7 +968,7 @@
   typename enable_if<typename gtl_and<y_r_scale_up, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                      rectangle_type>::type &
   scale_up(rectangle_type& rectangle,
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::unsigned_area_type factor) {
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) {
     horizontal(rectangle, scale_up(horizontal(rectangle), factor));
     vertical(rectangle, scale_up(vertical(rectangle), factor));
     return rectangle;
@@ -980,7 +980,7 @@
   typename enable_if<typename gtl_and<y_r_scale_down, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                      rectangle_type>::type &
   scale_down(rectangle_type& rectangle,
- typename coordinate_traits<typename rectangle_traits<rectangle_type>::coordinate_type>::unsigned_area_type factor) {
+ typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) {
     horizontal(rectangle, scale_down(horizontal(rectangle), factor));
     vertical(rectangle, scale_down(vertical(rectangle), factor));
     return rectangle;
@@ -992,8 +992,8 @@
   typename enable_if<typename gtl_and<y_r_scale, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                      rectangle_type>::type &
   scale(rectangle_type& rectangle, const scaling_type& scaling) {
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> llp(xl(rectangle), yl(rectangle));
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> urp(xl(rectangle), yl(rectangle));
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle));
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xl(rectangle), yl(rectangle));
     scale(llp, scaling);
     scale(urp, scaling);
     set_points(rectangle, llp, urp);
@@ -1006,8 +1006,8 @@
   typename enable_if<typename gtl_and<y_r_transform, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
                      rectangle_type>::type &
   transform(rectangle_type& rectangle, const transformation_type& transformation) {
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> llp(xl(rectangle), yl(rectangle));
- point_data<typename rectangle_traits<rectangle_type>::coordinate_type> urp(xh(rectangle), yh(rectangle));
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle));
+ point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xh(rectangle), yh(rectangle));
     transform(llp, transformation);
     transform(urp, transformation);
     set_points(rectangle, llp, urp);
@@ -1026,7 +1026,7 @@
       bool>::type
     operator () (const rectangle_type_1& a,
                  const rectangle_type_2& b) const {
- typedef typename rectangle_traits<rectangle_type_1>::coordinate_type Unit;
+ typedef typename rectangle_coordinate_type<rectangle_type_1>::type Unit;
       Unit vl1 = get(get(a, orient_), LOW);
       Unit vl2 = get(get(b, orient_), LOW);
       if(vl1 > vl2) return false;

Added: trunk/boost/polygon/segment_concept.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/segment_concept.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,735 @@
+/*
+ Copyright 2008 Intel Corporation
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+#ifndef BOOST_POLYGON_SEGMENT_CONCEPT_HPP
+#define BOOST_POLYGON_SEGMENT_CONCEPT_HPP
+#include "isotropy.hpp"
+#include "segment_data.hpp"
+#include "segment_traits.hpp"
+#include "rectangle_concept.hpp"
+#include "detail/polygon_arbitrary_formation.hpp"
+
+namespace boost { namespace polygon{
+ struct segment_concept {};
+
+ template <typename Segment>
+ struct is_segment_concept { typedef gtl_no type; };
+
+ template <>
+ struct is_segment_concept<segment_concept> {
+ typedef gtl_yes type;
+ };
+
+ template <typename Segment>
+ struct is_mutable_segment_concept { typedef gtl_no type; };
+
+ template <>
+ struct is_mutable_segment_concept<segment_concept> {
+ typedef gtl_yes type;
+ };
+
+ template <typename Segment, typename CT>
+ struct segment_distance_type_by_concept {
+ typedef void type;
+ };
+
+ template <typename Segment>
+ struct segment_distance_type_by_concept<Segment, gtl_yes> {
+ typedef typename coordinate_traits<
+ typename segment_traits<Segment>::coordinate_type
+ >::coordinate_distance type;
+ };
+
+ template <typename Segment>
+ struct segment_distance_type {
+ typedef typename segment_distance_type_by_concept<
+ Segment,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type type;
+ };
+
+ template <typename Segment, typename CT>
+ struct segment_point_type_by_concept { typedef void type; };
+
+ template <typename Segment>
+ struct segment_point_type_by_concept<Segment, gtl_yes> {
+ typedef typename segment_traits<Segment>::point_type type;
+ };
+
+ template <typename Segment>
+ struct segment_point_type {
+ typedef typename segment_point_type_by_concept<
+ Segment,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type type;
+ };
+
+ template <typename Segment, typename CT>
+ struct segment_coordinate_type_by_concept {
+ typedef void type;
+ };
+
+ template <typename Segment>
+ struct segment_coordinate_type_by_concept<Segment, gtl_yes> {
+ typedef typename segment_traits<Segment>::coordinate_type type;
+ };
+
+ template <typename Segment>
+ struct segment_coordinate_type {
+ typedef typename segment_coordinate_type_by_concept<
+ Segment,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type type;
+ };
+
+ struct y_s_get : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_get,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ typename segment_point_type<Segment>::type
+ >::type
+ get(const Segment& segment, direction_1d dir) {
+ return segment_traits<Segment>::get(segment, dir);
+ }
+
+ struct y_s_set : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_set,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ void
+ >::type
+ set(Segment& segment, direction_1d dir, const Point& point) {
+ segment_mutable_traits<Segment>::set(segment, dir, point);
+ }
+
+ struct y_s_construct : gtl_yes {};
+
+ template <typename Segment, typename Point1, typename Point2>
+ typename enable_if<
+ typename gtl_and_4<
+ y_s_construct,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point1>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point2>::type
+ >::type
+ >::type,
+ Segment
+ >::type
+ construct(const Point1& low, const Point2& high) {
+ return segment_mutable_traits<Segment>::construct(low, high);
+ }
+
+ struct y_s_copy_construct : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_copy_construct,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ Segment1
+ >::type
+ copy_construct(const Segment2& segment) {
+ return construct<Segment1>(get(segment, LOW), get(segment, HIGH));
+ }
+
+ struct y_s_assign : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_assign,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ Segment1
+ >::type &
+ assign(Segment1& segment1, const Segment2& segment2) {
+ return segment1 = copy_construct<Segment1>(segment2);
+ }
+
+ struct y_s_equivalence : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_equivalence,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ equivalence(const Segment1& segment1, const Segment2& segment2) {
+ return get(segment1, LOW) == get(segment2, LOW) &&
+ get(segment1, HIGH) == get(segment2, HIGH);
+ }
+
+ struct y_s_low : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_low,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ typename segment_point_type<Segment>::type
+ >::type
+ low(const Segment& segment) {
+ return get(segment, LOW);
+ }
+
+ struct y_s_high : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_high,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ typename segment_point_type<Segment>::type
+ >::type
+ high(const Segment& segment) {
+ return get(segment, HIGH);
+ }
+
+ struct y_s_center : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_center,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ typename segment_point_type<Segment>::type
+ >::type
+ center(const Segment& segment) {
+ return construct<typename segment_point_type<Segment>::type>(
+ (x(high(segment)) + x(low(segment)))/2,
+ (y(high(segment)) + y(low(segment)))/2);
+ }
+
+ struct y_s_low2 : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_low2,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ void
+ >::type
+ low(Segment& segment, const Point& point) {
+ set(segment, LOW, point);
+ }
+
+ struct y_s_high2 : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_high2,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ void
+ >::type
+ high(Segment& segment, const Point& point) {
+ set(segment, HIGH, point);
+ }
+
+ struct y_s_on_above_or_below : gtl_yes {};
+
+ // -1 for below, 0 for on and 1 for above
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_on_above_or_below,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ int
+ >::type
+ on_above_or_below(const Segment& segment, const Point& point) {
+ typedef polygon_arbitrary_formation<
+ typename segment_coordinate_type<Segment>::type
+ > paf;
+ typename paf::Point pt, l, h;
+ assign(pt, point);
+ assign(l, low(segment));
+ assign(h, high(segment));
+ return paf::on_above_or_below(pt, typename paf::half_edge(l, h));
+ }
+
+ struct y_s_contains : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_contains,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ contains(const Segment& segment, const Point& point, bool consider_touch = true ) {
+ if (!on_above_or_below(segment, point)) {
+ rectangle_data<typename segment_coordinate_type<Segment>::type> rect;
+ set_points(rect, low(segment), high(segment));
+ if (area(rect) == 0.0) {
+ if (!consider_touch) {
+ return !equivalence(point, low(segment)) &&
+ !equivalence(point, high(segment));
+ }
+ }
+ return contains(rect, point, consider_touch);
+ }
+ return false;
+ }
+
+ struct y_s_contains2 : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_contains2,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ contains(const Segment1& segment1, const Segment2& segment2, bool consider_touch = true) {
+ return contains(segment1, get(segment2, LOW), consider_touch) &&
+ contains(segment1, get(segment2, HIGH), consider_touch);
+ }
+
+ struct y_s_length : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_length,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ typename segment_distance_type<Segment>::type
+ >::type
+ length(const Segment& segment) {
+ return euclidean_distance(low(segment), high(segment));
+ }
+
+ struct y_s_scale_up : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_scale_up,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ scale_up(Segment& segment,
+ typename coordinate_traits<
+ typename segment_coordinate_type<Segment>::type
+ >::unsigned_area_type factor) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, scale_up(l, factor));
+ high(segment, scale_up(h, factor));
+ return segment;
+ }
+
+ struct y_s_scale_down : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_scale_down,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ scale_down(Segment& segment,
+ typename coordinate_traits<
+ typename segment_coordinate_type<Segment>::type
+ >::unsigned_area_type factor) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, scale_down(l, factor));
+ high(segment, scale_down(h, factor));
+ return segment;
+ }
+
+ struct y_s_scale : gtl_yes {};
+
+ template <typename Segment, typename Scale>
+ typename enable_if<
+ typename gtl_and<
+ y_s_scale,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ scale(Segment& segment, const Scale& sc) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, scale(l, sc));
+ high(segment, scale(h, sc));
+ return segment;
+ }
+
+ struct y_s_transform : gtl_yes {};
+
+ template <typename Segment, typename Transform>
+ typename enable_if<
+ typename gtl_and<
+ y_s_transform,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ transform(Segment& segment, const Transform& tr) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, transform(l, tr));
+ high(segment, transform(h, tr));
+ return segment;
+ }
+
+ struct y_s_move : gtl_yes {};
+
+ template <typename Segment>
+ typename enable_if<
+ typename gtl_and<
+ y_s_move,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ move(Segment& segment, orientation_2d orient,
+ typename segment_coordinate_type<Segment>::type displacement) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, move(l, orient, displacement));
+ high(segment, move(h, orient, displacement));
+ return segment;
+ }
+
+ struct y_s_convolve : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_convolve,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ convolve(Segment& segment, const Point& point) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, convolve(l, point));
+ high(segment, convolve(h, point));
+ return segment;
+ }
+
+ struct y_s_deconvolve : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_deconvolve,
+ typename is_mutable_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ Segment
+ >::type &
+ deconvolve(Segment& segment, const Point& point) {
+ typename segment_point_type<Segment>::type l = low(segment), h = high(segment);
+ low(segment, deconvolve(l, point));
+ high(segment, deconvolve(h, point));
+ return segment;
+ }
+
+ struct y_s_abuts1 : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_abuts1,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ abuts(const Segment1& segment1, const Segment2& segment2, direction_1d dir) {
+ return dir.to_int() ? equivalence(low(segment2) , high(segment1)) :
+ equivalence(low(segment1) , high(segment2));
+ }
+
+ struct y_s_abuts2 : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_abuts2,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ abuts(const Segment1& segment1, const Segment2& segment2) {
+ return abuts(segment1, segment2, HIGH) || abuts(segment1, segment2, LOW);
+ }
+
+ struct y_s_e_intersects : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_e_intersects,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ intersects(const Segment1& segment1, const Segment2& segment2,
+ bool consider_touch = true) {
+ if (consider_touch) {
+ if (low(segment1) == low(segment2) || low(segment1) == high(segment2) ||
+ high(segment1) == low(segment2) || high(segment1) == high(segment2))
+ return true;
+ }
+ typedef polygon_arbitrary_formation<
+ typename segment_coordinate_type<Segment1>::type
+ > paf;
+ typename paf::Point l1, h1, l2, h2;
+ assign(l1, low(segment1));
+ assign(h1, high(segment1));
+ assign(l2, low(segment2));
+ assign(h2, high(segment2));
+ return paf::intersects(typename paf::half_edge(l1, h1),
+ typename paf::half_edge(l2, h2));
+ }
+
+ struct y_s_intersect : gtl_yes {};
+
+ // Set point to the intersection of segment and b
+ template <typename Point, typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_4<
+ y_s_intersect,
+ typename is_mutable_point_concept<
+ typename geometry_concept<Point>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ bool
+ >::type
+ intersection(Point& intersection,
+ const Segment1& segment1,
+ const Segment2& segment2,
+ bool projected = false,
+ bool round_closest = false) {
+ typedef polygon_arbitrary_formation<
+ typename segment_coordinate_type<Segment1>::type
+ > paf;
+ typename paf::Point pt;
+ typename paf::Point l1, h1, l2, h2;
+ assign(l1, low(segment1));
+ assign(h1, high(segment1));
+ assign(l2, low(segment2));
+ assign(h2, high(segment2));
+ typename paf::half_edge he1(l1, h1), he2(l2, h2);
+ typename paf::compute_intersection_pack pack;
+ if (pack.compute_intersection(pt, he1, he2, projected, round_closest)) {
+ assign(intersection, pt);
+ return true;
+ }
+ return false;
+ }
+
+ struct y_s_e_dist : gtl_yes {};
+
+ template <typename Segment, typename Point>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_e_dist,
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type,
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ typename segment_distance_type<Segment>::type
+ >::type
+ euclidean_distance(const Segment& segment, const Point& point) {
+ typedef typename segment_distance_type<Segment>::type Unit;
+ Unit x1 = x(low(segment));
+ Unit y1 = y(low(segment));
+ Unit x2 = x(high(segment));
+ Unit y2 = y(high(segment));
+ Unit X = x(point);
+ Unit Y = y(point);
+ Unit A = X - x1;
+ Unit B = Y - y1;
+ Unit C = x2 - x1;
+ Unit D = y2 - y1;
+ Unit param = (A * C + B * D);
+ Unit length_sq = C * C + D * D;
+ if (param > length_sq) {
+ return euclidean_distance(high(segment), point);
+ } else if (param < 0.0) {
+ return euclidean_distance(low(segment), point);
+ }
+ if (length_sq == 0.0)
+ return 0.0;
+ Unit denom = sqrt(length_sq);
+ Unit result = (A * D - C * B) / denom;
+ return (result < 0.0) ? -result : result;
+ }
+
+ struct y_s_e_dist2 : gtl_yes {};
+
+ template <typename Segment1, typename Segment2>
+ typename enable_if<
+ typename gtl_and_3<
+ y_s_e_dist2,
+ typename is_segment_concept<
+ typename geometry_concept<Segment1>::type
+ >::type,
+ typename is_segment_concept<
+ typename geometry_concept<Segment2>::type
+ >::type
+ >::type,
+ typename segment_distance_type<Segment1>::type
+ >::type
+ euclidean_distance(const Segment1& segment1, const Segment2& segment2) {
+ if (intersects(segment1, segment2))
+ return 0.0;
+ typename segment_distance_type<Segment1>::type
+ result1 = euclidean_distance(segment1, low(segment2)),
+ result2 = euclidean_distance(segment1, high(segment2)),
+ result3 = euclidean_distance(segment2, low(segment1)),
+ result4 = euclidean_distance(segment2, high(segment1));
+ typename segment_distance_type<Segment1>::type
+ subres1 = (result1 < result2) ? result1 : result2,
+ subres2 = (result3 < result4) ? result3 : result4;
+ return (subres1 < subres2) ? subres1 : subres2;
+ }
+
+ template <class T>
+ template <class Segment>
+ segment_data<T>& segment_data<T>::operator=(const Segment& rvalue) {
+ assign(*this, rvalue);
+ return *this;
+ }
+
+ template <typename T>
+ struct geometry_concept<segment_data<T> > {
+ typedef segment_concept type;
+ };
+}
+}
+#endif

Added: trunk/boost/polygon/segment_data.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/segment_data.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,106 @@
+/*
+ Copyright 2008 Intel Corporation
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+#ifndef BOOST_POLYGON_SEGMENT_DATA_HPP
+#define BOOST_POLYGON_SEGMENT_DATA_HPP
+
+#include "isotropy.hpp"
+
+namespace boost { namespace polygon{
+ template <typename T>
+ class segment_data {
+ public:
+ typedef T coordinate_type;
+ typedef point_data<T> point_type;
+
+ inline segment_data()
+#ifndef BOOST_POLYGON_MSVC
+ :points_()
+#endif
+ {}
+
+ inline segment_data(const point_type& low, const point_type& high)
+#ifndef BOOST_POLYGON_MSVC
+ :points_()
+#endif
+ {
+ points_[LOW] = low; points_[HIGH] = high;
+ }
+
+ inline segment_data(const segment_data& that)
+#ifndef BOOST_POLYGON_MSVC
+ :points_()
+#endif
+ {
+ (*this) = that;
+ }
+
+ inline segment_data& operator=(const segment_data& that) {
+ points_[0] = that.points_[0];
+ points_[1] = that.points_[1];
+ return *this;
+ }
+
+ template <typename Segment>
+ inline segment_data& operator=(const Segment& that);
+
+ inline point_type get(direction_1d dir) const {
+ return points_[dir.to_int()];
+ }
+
+ inline void set(direction_1d dir, const point_type& point) {
+ points_[dir.to_int()] = point;
+ }
+
+ inline point_type low() const { return points_[0]; }
+
+ inline segment_data& low(const point_type& point) {
+ points_[0] = point;
+ return *this;
+ }
+
+ inline point_type high() const {return points_[1]; }
+
+ inline segment_data& high(const point_type& point) {
+ points_[1] = point;
+ return *this;
+ }
+
+ inline bool operator==(const segment_data& that) const {
+ return low() == that.low() && high() == that.high();
+ }
+
+ inline bool operator!=(const segment_data& that) const {
+ return low() != that.low() || high() != that.high();
+ }
+
+ inline bool operator<(const segment_data& that) const {
+ if (points_[0] < that.points_[0])
+ return true;
+ if (points_[0] > that.points_[0])
+ return false;
+ return points_[1] < that.points_[1];
+ }
+
+ inline bool operator<=(const segment_data& that) const {
+ return !(that < *this);
+ }
+
+ inline bool operator>(const segment_data& that) const {
+ return that < *this;
+ }
+
+ inline bool operator>=(const segment_data& that) const {
+ return !((*this) < that);
+ }
+
+ private:
+ point_type points_[2];
+};
+}
+}
+#endif

Added: trunk/boost/polygon/segment_traits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/segment_traits.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,35 @@
+/*
+ Copyright 2008 Intel Corporation
+
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+#ifndef BOOST_POLYGON_SEGMENT_TRAITS_HPP
+#define BOOST_POLYGON_SEGMENT_TRAITS_HPP
+namespace boost { namespace polygon{
+ template <typename Segment>
+ struct segment_traits {
+ typedef typename Segment::coordinate_type coordinate_type;
+ typedef typename Segment::point_type point_type;
+
+ static inline point_type get(const Segment& segment, direction_1d dir) {
+ return segment.get(dir);
+ }
+ };
+
+ template <typename Segment>
+ struct segment_mutable_traits {
+ typedef typename segment_traits<Segment>::point_type point_type;
+
+ static inline void set(Segment& segment, direction_1d dir, const point_type& point) {
+ segment.set(dir, point);
+ }
+
+ static inline Segment construct(const point_type& low, const point_type& high) {
+ return Segment(low, high);
+ }
+ };
+}
+}
+#endif

Added: trunk/boost/polygon/voronoi.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/voronoi.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,164 @@
+// Boost.Polygon library voronoi.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_VORONOI
+#define BOOST_POLYGON_VORONOI
+
+#include "polygon.hpp"
+#include "voronoi_builder.hpp"
+#include "voronoi_diagram.hpp"
+
+// Public methods to compute Voronoi diagram.
+// PC - container of input points (should supports forward iterator).
+// SC - container of input segments (should supports forward iterator).
+// output - Voronoi output data structure to hold Voronoi diagram.
+// Segment class should provide low(), high() methods to access its endpoints.
+// The assumption is made that input doesn't contain segments that intersect
+// or points lying on the segments. Also coordinates of the points and of the
+// endpoints of the segments should belong to the signed integer range
+// [-2^31, 2^31-1]. To use wider input coordinate range use voronoi_builder
+// structure with user provided coordinate type traits.
+// Complexity - O(N*logN), memory usage - O(N),
+// where N is the total number of points and segments.
+namespace boost {
+namespace polygon {
+
+template <typename Point, typename VB>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_point_concept<
+ typename geometry_concept<Point>::type
+ >::type
+ >::type,
+ void
+>::type
+insert(const Point &point, VB *vb) {
+ vb->insert_point(x(point), y(point));
+}
+
+
+template <typename PointIterator, typename VB>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_point_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<PointIterator>::value_type
+ >::type
+ >::type
+ >::type,
+ void
+>::type
+insert(PointIterator first, const PointIterator last, VB *vb) {
+ for (PointIterator it = first; it != last; ++it) {
+ insert(*it, vb);
+ }
+}
+
+template <typename Segment, typename VB>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_segment_concept<
+ typename geometry_concept<Segment>::type
+ >::type
+ >::type,
+ void
+>::type
+insert(const Segment &segment, VB *vb) {
+ vb->insert_segment(x(low(segment)), y(low(segment)), x(high(segment)), y(high(segment)));
+}
+
+template <typename SegmentIterator, typename VB>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_segment_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<SegmentIterator>::value_type
+ >::type
+ >::type
+ >::type,
+ void
+>::type
+insert(SegmentIterator first, SegmentIterator last, VB *vb) {
+ for (SegmentIterator it = first; it != last; ++it) {
+ insert(*it, vb);
+ }
+}
+
+template <typename PointIterator, typename VD>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_point_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<PointIterator>::value_type
+ >::type
+ >::type
+ >::type,
+ void
+>::type
+construct_voronoi(PointIterator first, PointIterator last, VD *vd) {
+ default_voronoi_builder builder;
+ insert(first, last, &builder);
+ builder.construct(vd);
+}
+
+template <typename SegmentIterator, typename VD>
+static inline
+typename enable_if<
+ typename gtl_if<
+ typename is_segment_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<SegmentIterator>::value_type
+ >::type
+ >::type
+ >::type,
+ void
+>::type
+construct_voronoi(SegmentIterator first, SegmentIterator last, VD *vd) {
+ default_voronoi_builder builder;
+ insert(first, last, &builder);
+ builder.construct(vd);
+}
+
+template <typename PointIterator, typename SegmentIterator, typename VD>
+static inline
+typename enable_if<
+ typename gtl_and<
+ typename gtl_if<
+ typename is_point_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<PointIterator>::value_type
+ >::type
+ >::type
+ >::type,
+ typename gtl_if<
+ typename is_segment_concept<
+ typename geometry_concept<
+ typename std::iterator_traits<SegmentIterator>::value_type
+ >::type
+ >::type
+ >::type
+ >::type,
+ void
+>::type
+construct_voronoi(PointIterator p_first, PointIterator p_last,
+ SegmentIterator s_first, SegmentIterator s_last, VD *vd) {
+ default_voronoi_builder builder;
+ insert(p_first, p_last, &builder);
+ insert(s_first, s_last, &builder);
+ builder.construct(vd);
+}
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_VORONOI

Added: trunk/boost/polygon/voronoi_builder.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/voronoi_builder.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,506 @@
+// Boost.Polygon library voronoi_builder.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_VORONOI_BUILDER
+#define BOOST_POLYGON_VORONOI_BUILDER
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include "detail/voronoi_ctypes.hpp"
+#include "detail/voronoi_predicates.hpp"
+#include "detail/voronoi_structures.hpp"
+
+namespace boost {
+namespace polygon {
+// GENERAL INFO:
+// The sweepline algorithm implementation to compute Voronoi diagram of
+// points and non-intersecting segments (except endpoints).
+// Complexity - O(N*logN), memory usage - O(N), where N is the total number
+// of input geometries. Input geometries should have integer coordinate type.
+//
+// IMPLEMENTATION DETAILS:
+// Each input point creates one site event. Each input segment creates three
+// site events: two for its endpoints and one for the segment itself (this is
+// made to simplify output construction). All the site events are constructed
+// and sorted at the algorithm initialization step. Priority queue is used to
+// dynamically hold circle events. At each step of the algorithm execution the
+// leftmost event is retrieved by comparing the current site event and the
+// topmost element from the circle event queue. STL map (red-black tree)
+// container was chosen to hold state of the beach line. The keys of the map
+// correspond to the neighboring sites that form a bisector and values to the
+// corresponding Voronoi edge in the output data structure.
+template <typename T,
+ typename CTT = detail::voronoi_ctype_traits<T>,
+ typename VP = detail::voronoi_predicates<CTT> >
+class voronoi_builder {
+public:
+ typedef typename CTT::int_type int_type;
+ typedef typename CTT::fpt_type fpt_type;
+
+ voronoi_builder() {}
+
+ // Each point creates a single site event.
+ void insert_point(const int_type& x, const int_type& y) {
+ site_events_.push_back(site_event_type(x, y));
+ }
+
+ // Each segment creates three site events that correspond to:
+ // 1) the start point of the segment;
+ // 2) the end point of the segment;
+ // 3) the segment itself defined by its start point.
+ void insert_segment(const int_type& x1, const int_type& y1,
+ const int_type& x2, const int_type& y2) {
+ point_type p1(x1, y1);
+ point_type p2(x2, y2);
+ site_events_.push_back(site_event_type(p1));
+ site_events_.push_back(site_event_type(p2));
+ if (point_comparison_(p1, p2)) {
+ site_events_.push_back(site_event_type(p1, p2));
+ } else {
+ site_events_.push_back(site_event_type(p2, p1));
+ }
+ }
+
+ // Run sweepline algorithm and fill output data structure.
+ template <typename OUTPUT>
+ void construct(OUTPUT *output) {
+ // Init structures.
+ output->builder()->reserve(site_events_.size());
+ init_sites_queue();
+ if (!circle_events_.empty())
+ circle_events_.clear();
+ while (!end_points_.empty())
+ end_points_.pop();
+ init_beach_line(output);
+
+ // The algorithm stops when there are no events to process.
+ event_comparison_predicate event_comparison;
+ while (!circle_events_.empty() ||
+ !(site_event_iterator_ == site_events_.end())) {
+ if (circle_events_.empty()) {
+ process_site_event(output);
+ } else if (site_event_iterator_ == site_events_.end()) {
+ process_circle_event(output);
+ } else {
+ if (event_comparison(*site_event_iterator_,
+ circle_events_.top().first)) {
+ process_site_event(output);
+ } else {
+ process_circle_event(output);
+ }
+ }
+ while (!circle_events_.empty() &&
+ !circle_events_.top().first.is_active()) {
+ circle_events_.pop();
+ }
+ }
+ beach_line_.clear();
+
+ // Finish construction.
+ output->builder()->build();
+ }
+
+ void clear() {
+ site_events_.clear();
+ if (!beach_line_.empty())
+ beach_line_.clear();
+ if (!circle_events_.empty())
+ circle_events_.clear();
+ while (!end_points_.empty())
+ end_points_.pop();
+ }
+
+private:
+ typedef detail::point_2d<int_type> point_type;
+ typedef detail::site_event<int_type> site_event_type;
+ typedef typename std::vector<site_event_type>::const_iterator
+ site_event_iterator_type;
+ typedef detail::circle_event<fpt_type> circle_event_type;
+ typedef typename VP::template point_comparison_predicate<point_type>
+ point_comparison_predicate;
+ typedef typename VP::
+ template event_comparison_predicate<site_event_type, circle_event_type>
+ event_comparison_predicate;
+ typedef typename VP::
+ template circle_formation_predicate<site_event_type, circle_event_type>
+ circle_formation_predicate_type;
+ typedef void edge_type;
+ typedef detail::beach_line_node_key<site_event_type> key_type;
+ typedef detail::beach_line_node_data<edge_type, circle_event_type>
+ value_type;
+ typedef typename VP::template node_comparison_predicate<key_type>
+ node_comparer_type;
+ typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
+ typedef typename beach_line_type::iterator beach_line_iterator;
+ typedef std::pair<circle_event_type, beach_line_iterator> event_type;
+ typedef struct {
+ bool operator()(const event_type &lhs, const event_type &rhs) const {
+ return predicate(rhs.first, lhs.first);
+ }
+ event_comparison_predicate predicate;
+ } event_comparison_type;
+ typedef detail::ordered_queue<event_type, event_comparison_type>
+ circle_event_queue_type;
+ typedef std::pair<point_type, beach_line_iterator> end_point_type;
+
+ void init_sites_queue() {
+ // Sort site events.
+ sort(site_events_.begin(), site_events_.end(),
+ event_comparison_predicate());
+
+ // Remove duplicates.
+ site_events_.erase(unique(
+ site_events_.begin(), site_events_.end()), site_events_.end());
+
+ // Index sites.
+ for (size_t cur = 0; cur < site_events_.size(); ++cur)
+ site_events_[cur].index(cur);
+
+ // Init site iterator.
+ site_event_iterator_ = site_events_.begin();
+ }
+
+ template <typename OUTPUT>
+ void init_beach_line(OUTPUT *output) {
+ if (!beach_line_.empty())
+ beach_line_.clear();
+ if (site_events_.empty())
+ return;
+ if (site_events_.size() == 1) {
+ // Handle single site event case.
+ output->builder()->process_single_site(site_events_[0]);
+ ++site_event_iterator_;
+ } else {
+ int skip = 0;
+
+ while(site_event_iterator_ != site_events_.end() &&
+ VP::is_vertical(site_event_iterator_->point0(),
+ site_events_.begin()->point0()) &&
+ VP::is_vertical(*site_event_iterator_)) {
+ ++site_event_iterator_;
+ ++skip;
+ }
+
+ if (skip == 1) {
+ // Init beach line with the first two sites.
+ init_beach_line_default(output);
+ } else {
+ // Init beach line with collinear vertical sites.
+ init_beach_line_collinear_sites(output);
+ }
+ }
+ }
+
+ // Init beach line with the two first sites.
+ // The first site is always a point.
+ template <typename OUTPUT>
+ void init_beach_line_default(OUTPUT *output) {
+ // Get the first and the second site event.
+ site_event_iterator_type it_first = site_events_.begin();
+ site_event_iterator_type it_second = site_events_.begin();
+ ++it_second;
+ insert_new_arc(
+ *it_first, *it_first, *it_second, beach_line_.end(), output);
+ // The second site was already processed. Move the iterator.
+ ++site_event_iterator_;
+ }
+
+ // Init beach line with collinear sites.
+ template <typename OUTPUT>
+ void init_beach_line_collinear_sites(OUTPUT *output) {
+ site_event_iterator_type it_first = site_events_.begin();
+ site_event_iterator_type it_second = site_events_.begin();
+ ++it_second;
+ while (it_second != site_event_iterator_) {
+ // Create a new beach line node.
+ key_type new_node(*it_first, *it_second);
+
+ // Update the output.
+ edge_type *edge =
+ output->builder()->insert_new_edge(*it_first, *it_second).first;
+
+ // Insert a new bisector into the beach line.
+ beach_line_.insert(beach_line_.end(),
+ std::pair<key_type, value_type>(new_node, value_type(edge)));
+
+ // Update iterators.
+ ++it_first;
+ ++it_second;
+ }
+ }
+
+ void deactivate_circle_event(value_type &value) {
+ if (value.circle_event()) {
+ value.circle_event()->deactivate();
+ value.circle_event(NULL);
+ }
+ }
+
+ template <typename OUTPUT>
+ void process_site_event(OUTPUT *output) {
+ // Get next site event to process.
+ site_event_type site_event = *site_event_iterator_;
+
+ // Move site iterator.
+ site_event_iterator_type last = site_event_iterator_ + 1;
+
+ // If a new site is an end point of some segment,
+ // remove temporary nodes from the beach line data structure.
+ if (!site_event.is_segment()) {
+ while (!end_points_.empty() &&
+ end_points_.top().first == site_event.point0()) {
+ beach_line_iterator b_it = end_points_.top().second;
+ end_points_.pop();
+ beach_line_.erase(b_it);
+ }
+ } else {
+ while (last != site_events_.end() &&
+ last->is_segment() && last->point0() == site_event.point0())
+ ++last;
+ }
+
+ // Find the node in the binary search tree with left arc
+ // lying above the new site point.
+ key_type new_key(*site_event_iterator_);
+ beach_line_iterator right_it = beach_line_.lower_bound(new_key);
+
+ for (; site_event_iterator_ != last; ++site_event_iterator_) {
+ site_event = *site_event_iterator_;
+ beach_line_iterator left_it = right_it;
+
+ // Do further processing depending on the above node position.
+ // For any two neighboring nodes the second site of the first node
+ // is the same as the first site of the second node.
+ if (right_it == beach_line_.end()) {
+ // The above arc corresponds to the second arc of the last node.
+ // Move the iterator to the last node.
+ --left_it;
+
+ // Get the second site of the last node
+ const site_event_type &site_arc = left_it->first.right_site();
+
+ // Insert new nodes into the beach line. Update the output.
+ right_it = insert_new_arc(
+ site_arc, site_arc, site_event, right_it, output);
+
+ // Add a candidate circle to the circle event queue.
+ // There could be only one new circle event formed by
+ // a new bisector and the one on the left.
+ activate_circle_event(left_it->first.left_site(),
+ left_it->first.right_site(),
+ site_event, right_it);
+ } else if (right_it == beach_line_.begin()) {
+ // The above arc corresponds to the first site of the first node.
+ const site_event_type &site_arc = right_it->first.left_site();
+
+ // Insert new nodes into the beach line. Update the output.
+ left_it = insert_new_arc(
+ site_arc, site_arc, site_event, right_it, output);
+
+ // If the site event is a segment, update its direction.
+ if (site_event.is_segment()) {
+ site_event.inverse();
+ }
+
+ // Add a candidate circle to the circle event queue.
+ // There could be only one new circle event formed by
+ // a new bisector and the one on the right.
+ activate_circle_event(site_event, right_it->first.left_site(),
+ right_it->first.right_site(), right_it);
+ right_it = left_it;
+ } else {
+ // The above arc corresponds neither to the first,
+ // nor to the last site in the beach line.
+ const site_event_type &site_arc2 = right_it->first.left_site();
+ const site_event_type &site3 = right_it->first.right_site();
+
+ // Remove the candidate circle from the event queue.
+ deactivate_circle_event(right_it->second);
+ --left_it;
+ const site_event_type &site_arc1 = left_it->first.right_site();
+ const site_event_type &site1 = left_it->first.left_site();
+
+ // Insert new nodes into the beach line. Update the output.
+ beach_line_iterator new_node_it =
+ insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
+
+ // Add candidate circles to the circle event queue.
+ // There could be up to two circle events formed by
+ // a new bisector and the one on the left or right.
+ activate_circle_event(site1, site_arc1, site_event, new_node_it);
+
+ // If the site event is a segment, update its direction.
+ if (site_event.is_segment()) {
+ site_event.inverse();
+ }
+ activate_circle_event(site_event, site_arc2, site3, right_it);
+ right_it = new_node_it;
+ }
+ }
+ }
+
+ // In general case circle event is made of the three consecutive sites
+ // that form two bisectors in the beach line data structure.
+ // Let circle event sites be A, B, C, two bisectors that define
+ // circle event are (A, B), (B, C). During circle event processing
+ // we remove (A, B), (B, C) and insert (A, C). As beach line comparison
+ // works correctly only if one of the nodes is a new one we remove
+ // (B, C) bisector and change (A, B) bisector to the (A, C). That's
+ // why we use const_cast there and take all the responsibility that
+ // map data structure keeps correct ordering.
+ template <typename OUTPUT>
+ void process_circle_event(OUTPUT *output) {
+ // Get the topmost circle event.
+ const event_type &e = circle_events_.top();
+ const circle_event_type &circle_event = e.first;
+ beach_line_iterator it_first = e.second;
+ beach_line_iterator it_last = it_first;
+
+ // Get the C site.
+ site_event_type site3 = it_first->first.right_site();
+
+ // Get the half-edge corresponding to the second bisector - (B, C).
+ edge_type *bisector2 = it_first->second.edge();
+
+ // Get the half-edge corresponding to the first bisector - (A, B).
+ --it_first;
+ edge_type *bisector1 = it_first->second.edge();
+
+ // Get the A site.
+ site_event_type site1 = it_first->first.left_site();
+
+ if (!site1.is_segment() && site3.is_segment() &&
+ site3.point1(true) == site1.point0()) {
+ site3.inverse();
+ }
+
+ // Change the (A, B) bisector node to the (A, C) bisector node.
+ const_cast<key_type &>(it_first->first).right_site(site3);
+
+ // Insert the new bisector into the beach line.
+ it_first->second.edge(output->builder()->insert_new_edge(
+ site1, site3, circle_event, bisector1, bisector2).first);
+
+ // Remove the (B, C) bisector node from the beach line.
+ beach_line_.erase(it_last);
+ it_last = it_first;
+
+ // Pop the topmost circle event from the event queue.
+ circle_events_.pop();
+
+ // Check new triplets formed by the neighboring arcs
+ // to the left for potential circle events.
+ if (it_first != beach_line_.begin()) {
+ deactivate_circle_event(it_first->second);
+ --it_first;
+ const site_event_type &site_l1 = it_first->first.left_site();
+ activate_circle_event(site_l1, site1, site3, it_last);
+ }
+
+ // Check the new triplet formed by the neighboring arcs
+ // to the right for potential circle events.
+ ++it_last;
+ if (it_last != beach_line_.end()) {
+ deactivate_circle_event(it_last->second);
+ const site_event_type &site_r1 = it_last->first.right_site();
+ activate_circle_event(site1, site3, site_r1, it_last);
+ }
+ }
+
+ // Insert new nodes into the beach line. Update the output.
+ template <typename OUTPUT>
+ beach_line_iterator insert_new_arc(
+ const site_event_type &site_arc1, const site_event_type &site_arc2,
+ const site_event_type &site_event, beach_line_iterator position,
+ OUTPUT *output) {
+ // Create two new bisectors with opposite directions.
+ key_type new_left_node(site_arc1, site_event);
+ key_type new_right_node(site_event, site_arc2);
+
+ // Set correct orientation for the first site of the second node.
+ if (site_event.is_segment()) {
+ new_right_node.left_site().inverse();
+ }
+
+ // Update the output.
+ std::pair<edge_type*, edge_type*> edges =
+ output->builder()->insert_new_edge(site_arc2, site_event);
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(
+ new_right_node, value_type(edges.second)));
+
+ if (site_event.is_segment()) {
+ // Update the beach line with temporary bisector, that will
+ // disappear after processing site event corresponding to the
+ // second endpoint of the segment site.
+ key_type new_node(site_event, site_event);
+ new_node.right_site().inverse();
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(new_node, value_type(NULL)));
+
+ // Update the data structure that holds temporary bisectors.
+ end_points_.push(std::make_pair(site_event.point1(), position));
+ }
+
+ position = beach_line_.insert(position,
+ typename beach_line_type::value_type(
+ new_left_node, value_type(edges.first)));
+
+ return position;
+ }
+
+ // Add a new circle event to the event queue.
+ // bisector_node corresponds to the (site2, site3) bisector.
+ void activate_circle_event(const site_event_type &site1,
+ const site_event_type &site2,
+ const site_event_type &site3,
+ beach_line_iterator bisector_node) {
+ circle_event_type c_event;
+ // Check if the three input sites create a circle event.
+ if (circle_formation_predicate_(site1, site2, site3, c_event)) {
+ // Add the new circle event to the circle events queue.
+ // Update bisector's circle event iterator to point to the
+ // new circle event in the circle event queue.
+ event_type &e = circle_events_.push(
+ std::pair<circle_event_type, beach_line_iterator>(
+ c_event, bisector_node));
+ bisector_node->second.circle_event(&e.first);
+ }
+ }
+
+private:
+ point_comparison_predicate point_comparison_;
+ struct end_point_comparison {
+ bool operator() (const end_point_type &end1,
+ const end_point_type &end2) const {
+ return point_comparison(end2.first, end1.first);
+ }
+ point_comparison_predicate point_comparison;
+ };
+
+ std::vector<site_event_type> site_events_;
+ site_event_iterator_type site_event_iterator_;
+ std::priority_queue< end_point_type, std::vector<end_point_type>,
+ end_point_comparison > end_points_;
+ circle_event_queue_type circle_events_;
+ beach_line_type beach_line_;
+ circle_formation_predicate_type circle_formation_predicate_;
+
+ //Disallow copy constructor and operator=
+ voronoi_builder(const voronoi_builder&);
+ void operator=(const voronoi_builder&);
+};
+
+typedef voronoi_builder<detail::int32> default_voronoi_builder;
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_VORONOI_BUILDER

Added: trunk/boost/polygon/voronoi_diagram.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/voronoi_diagram.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,650 @@
+// Boost.Polygon library voronoi_diagram.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_VORONOI_DIAGRAM
+#define BOOST_POLYGON_VORONOI_DIAGRAM
+
+#include <vector>
+
+#include "detail/voronoi_ctypes.hpp"
+#include "detail/voronoi_structures.hpp"
+
+namespace boost {
+namespace polygon {
+
+// Forward declarations.
+template <typename T>
+class voronoi_edge;
+
+// Represents Voronoi cell.
+// Data members:
+// 1) pointer to the incident edge;
+// 2) site inside cell;
+// 3) data associated with a cell.
+// Cell may contain point or segment site inside.
+template <typename T>
+class voronoi_cell {
+public:
+ typedef T coordinate_type;
+ typedef detail::point_2d<coordinate_type> point_type;
+ typedef voronoi_edge<coordinate_type> voronoi_edge_type;
+
+ voronoi_cell(const point_type &p1, voronoi_edge_type *edge) :
+ point0_(p1),
+ point1_(p1),
+ incident_edge_(edge),
+ data_(NULL) {}
+
+ voronoi_cell(const point_type &p1,
+ const point_type &p2,
+ voronoi_edge_type *edge) :
+ point0_(p1),
+ point1_(p2),
+ incident_edge_(edge),
+ data_(NULL) {}
+
+ // Returns true if the cell contains point site, false else.
+ bool contains_point() const { return point0_ == point1_; }
+
+ // Returns true if the cell contains segment site, false else.
+ bool contains_segment() const { return point0_ != point1_; }
+
+ // Degenerate cells don't have any incident edges.
+ bool is_degenerate() const { return incident_edge_ == NULL; }
+
+ // Returns site point in case cell contains point site,
+ // the first endpoint of the segment site else.
+ const point_type &point0() const { return point0_; }
+
+ // Returns site point in case cell contains point site,
+ // the second endpoint of the segment site else.
+ const point_type &point1() const { return point1_; }
+
+ voronoi_edge_type *incident_edge() { return incident_edge_; }
+ const voronoi_edge_type *incident_edge() const { return incident_edge_; }
+ void incident_edge(voronoi_edge_type *e) { incident_edge_ = e; }
+
+#ifndef NO_VORONOI_CELL_DATA
+ void *data() const { return data_; }
+ void data(void *d) const { data_ = d; }
+#endif
+
+private:
+ point_type point0_;
+ point_type point1_;
+ voronoi_edge_type *incident_edge_;
+#ifndef NO_VORONOI_CELL_DATA
+ mutable void *data_;
+#endif
+};
+
+// Represents Voronoi vertex.
+// Data members:
+// 1) vertex point itself;
+// 2) pointer to the incident edge;
+// 3) data associated with vertex.
+template <typename T>
+class voronoi_vertex {
+public:
+ typedef T coordinate_type;
+ typedef detail::point_2d<T> point_type;
+ typedef voronoi_edge<coordinate_type> voronoi_edge_type;
+
+ voronoi_vertex(const point_type &vertex, voronoi_edge_type *edge) :
+ vertex_(vertex),
+ incident_edge_(edge),
+ data_(NULL) {}
+
+ const point_type &vertex() const { return vertex_; }
+
+ bool is_degenerate() const { return incident_edge_ == NULL; }
+
+ voronoi_edge_type *incident_edge() { return incident_edge_; }
+ const voronoi_edge_type *incident_edge() const { return incident_edge_; }
+ void incident_edge(voronoi_edge_type *e) { incident_edge_ = e; }
+
+#ifndef NO_VORONOI_VERTEX_DATA
+ void *data() const { return data_; }
+ void data(void *d) const { data_ = d; }
+#endif
+
+private:
+ point_type vertex_;
+ voronoi_edge_type *incident_edge_;
+#ifndef NO_VORONOI_VERTEX_DATA
+ mutable void *data_;
+#endif
+};
+
+// Half-edge data structure. Represents Voronoi edge.
+// Data members:
+// 1) pointer to the corresponding cell;
+// 2) pointer to the vertex that is the starting
+// point of the half-edge;
+// 3) pointer to the twin edge;
+// 4) pointer to the CCW next edge;
+// 5) pointer to the CCW prev edge;
+// 6) pointer to data associated with edge.
+template <typename T>
+class voronoi_edge {
+public:
+ typedef T coordinate_type;
+ typedef voronoi_cell<coordinate_type> voronoi_cell_type;
+ typedef voronoi_vertex<coordinate_type> voronoi_vertex_type;
+ typedef voronoi_edge<coordinate_type> voronoi_edge_type;
+
+ voronoi_edge() :
+ cell_(NULL),
+ vertex_(NULL),
+ twin_(NULL),
+ next_(NULL),
+ prev_(NULL),
+ data_(NULL) {}
+
+ voronoi_cell_type *cell() { return cell_; }
+ const voronoi_cell_type *cell() const { return cell_; }
+ void cell(voronoi_cell_type *c) { cell_ = c; }
+
+ voronoi_vertex_type *vertex0() { return vertex_; }
+ const voronoi_vertex_type *vertex0() const { return vertex_; }
+ void vertex0(voronoi_vertex_type *v) { vertex_ = v; }
+
+ voronoi_vertex_type *vertex1() { return twin_->vertex0(); }
+ const voronoi_vertex_type *vertex1() const { return twin_->vertex0(); }
+ void vertex1(voronoi_vertex_type *v) { twin_->vertex0(v); }
+
+ voronoi_edge_type *twin() { return twin_; }
+ const voronoi_edge_type *twin() const { return twin_; }
+ void twin(voronoi_edge_type *e) { twin_ = e; }
+
+ voronoi_edge_type *next() { return next_; }
+ const voronoi_edge_type *next() const { return next_; }
+ void next(voronoi_edge_type *e) { next_ = e; }
+
+ voronoi_edge_type *prev() { return prev_; }
+ const voronoi_edge_type *prev() const { return prev_; }
+ void prev(voronoi_edge_type *e) { prev_ = e; }
+
+#ifndef NO_VORONOI_EDGE_DATA
+ void *data() const { return data_; }
+ void data(void *d) const { data_ = d; }
+#endif
+
+ // Returns a pointer to the rotation next edge
+ // over the starting point of the half-edge.
+ voronoi_edge_type *rot_next() {
+ return (vertex_) ? prev_->twin() : NULL;
+ }
+ const voronoi_edge_type *rot_next() const {
+ return (vertex_) ? prev_->twin() : NULL;
+ }
+
+ // Returns a pointer to the rotation prev edge
+ // over the starting point of the half-edge.
+ voronoi_edge_type *rot_prev() {
+ return (vertex_) ? twin_->next() : NULL;
+ }
+ const voronoi_edge_type *rot_prev() const {
+ return (vertex_) ? twin_->next() : NULL;
+ }
+
+ // Returns true if the edge is finite (segment, parabolic arc).
+ // Returns false if the edge is infinite (ray, line).
+ bool is_finite() const { return vertex0() && vertex1(); }
+
+ // Returns true if the edge is linear (segment, ray, line).
+ // Returns false if the edge is curved (parabolic arc).
+ bool is_linear() const {
+ if (!is_primary())
+ return true;
+ return !(cell()->contains_segment() ^ twin()->cell()->contains_segment());
+ }
+
+ // Returns true if the edge is curved (parabolic arc).
+ // Returns false if the edge is linear (segment, ray, line).
+ bool is_curved() const {
+ if (!is_primary())
+ return false;
+ return (cell()->contains_segment() ^ twin()->cell()->contains_segment());
+ }
+
+ // Returns false if edge goes through the endpoint of the segment.
+ // Returns true else.
+ bool is_primary() const {
+ bool flag1 = cell_->contains_segment();
+ bool flag2 = twin_->cell()->contains_segment();
+ if (flag1 && !flag2) {
+ return cell_->point0() != twin_->cell()->point0() &&
+ cell_->point1() != twin_->cell()->point0();
+ }
+ if (!flag1 && flag2) {
+ return twin_->cell()->point0() != cell_->point0() &&
+ twin_->cell()->point1() != cell_->point0();
+ }
+ return true;
+ }
+
+private:
+ voronoi_cell_type *cell_;
+ voronoi_vertex_type *vertex_;
+ voronoi_edge_type *twin_;
+ voronoi_edge_type *next_;
+ voronoi_edge_type *prev_;
+#ifndef NO_VORONOI_EDGE_DATA
+ mutable void *data_;
+#endif
+};
+
+template <typename T>
+struct voronoi_diagram_traits {
+ typedef T coordinate_type;
+ typedef struct {
+ template <typename CT>
+ coordinate_type operator()(const CT& value) {
+ return static_cast<coordinate_type>(value);
+ }
+ } ctype_converter_type;
+ typedef detail::point_2d<coordinate_type> point_type;
+ typedef voronoi_cell<coordinate_type> cell_type;
+ typedef voronoi_vertex<coordinate_type> vertex_type;
+ typedef voronoi_edge<coordinate_type> edge_type;
+ typedef class {
+ public:
+ enum { ULPS = 128 };
+ bool operator()(const point_type &v1, const point_type &v2) const {
+ return (ulp_cmp(v1.x(), v2.x(), ULPS) ==
+ detail::ulp_comparison<T>::EQUAL) &&
+ (ulp_cmp(v1.y(), v2.y(), ULPS) ==
+ detail::ulp_comparison<T>::EQUAL);
+ }
+ private:
+ typename detail::ulp_comparison<T> ulp_cmp;
+ } vertex_equality_predicate_type;
+};
+
+// Voronoi output data structure.
+// CCW ordering is used on the faces perimeter and around the vertices.
+template <typename T, typename TRAITS = voronoi_diagram_traits<T> >
+class voronoi_diagram {
+public:
+ typedef typename TRAITS::coordinate_type coordinate_type;
+ typedef typename TRAITS::point_type point_type;
+ typedef typename TRAITS::cell_type cell_type;
+ typedef typename TRAITS::vertex_type vertex_type;
+ typedef typename TRAITS::edge_type edge_type;
+
+ typedef std::vector<cell_type> cell_container_type;
+ typedef typename cell_container_type::iterator cell_iterator;
+ typedef typename cell_container_type::const_iterator const_cell_iterator;
+
+ typedef std::vector<vertex_type> vertex_container_type;
+ typedef typename vertex_container_type::iterator vertex_iterator;
+ typedef typename vertex_container_type::const_iterator const_vertex_iterator;
+
+ typedef std::vector<edge_type> edge_container_type;
+ typedef typename edge_container_type::iterator edge_iterator;
+ typedef typename edge_container_type::const_iterator const_edge_iterator;
+
+ // This builder class is mainly used to hide from the user methods that
+ // construct the Voronoi diagram.
+ class voronoi_diagram_builder {
+ public:
+ void vd(voronoi_diagram *vd) {
+ vd_ = vd;
+ }
+
+ bool done() {
+ return vd_ == NULL;
+ }
+
+ void reserve(int num_sites) {
+ vd_->reserve(num_sites);
+ }
+
+ template <typename SEvent>
+ void process_single_site(const SEvent &site) {
+ vd_->process_single_site(site);
+ }
+
+ template <typename SEvent>
+ std::pair<void*, void*> insert_new_edge(
+ const SEvent &site1, const SEvent &site2) {
+ return vd_->insert_new_edge(site1, site2);
+ }
+
+ template <typename SEvent, typename CEvent>
+ std::pair<void *, void *> insert_new_edge(
+ const SEvent &site1, const SEvent &site3, const CEvent &circle,
+ void *data12, void *data23) {
+ return vd_->insert_new_edge(site1, site3, circle, data12, data23);
+ }
+
+ void build() {
+ vd_->build();
+ vd_ = NULL;
+ }
+
+ private:
+ voronoi_diagram *vd_;
+ };
+
+ voronoi_diagram() {
+ builder_.vd(&(*this));
+ }
+
+ void clear() {
+ cells_.clear();
+ vertices_.clear();
+ edges_.clear();
+ builder_.vd(&(*this));
+ }
+
+ const cell_container_type &cells() const {
+ return cells_;
+ }
+
+ const vertex_container_type &vertices() const {
+ return vertices_;
+ }
+
+ const edge_container_type &edges() const {
+ return edges_;
+ }
+
+ unsigned int num_cells() const {
+ return cells_.size();
+ }
+
+ unsigned int num_edges() const {
+ return edges_.size() >> 1;
+ }
+
+ unsigned int num_vertices() const {
+ return vertices_.size();
+ }
+
+ voronoi_diagram_builder *builder() {
+ if (builder_.done()) {
+ return NULL;
+ } else {
+ return &builder_;
+ }
+ }
+
+private:
+ typedef typename TRAITS::ctype_converter_type ctype_converter_type;
+ typedef typename TRAITS::vertex_equality_predicate_type
+ vertex_equality_predicate_type;
+
+ friend class voronoi_diagram_builder;
+
+ void reserve(int num_sites) {
+ cells_.reserve(num_sites);
+ vertices_.reserve(num_sites << 1);
+ edges_.reserve((num_sites << 2) + (num_sites << 1));
+ }
+
+ // Update the Voronoi output in case of a single point input.
+ template <typename SEvent>
+ void process_single_site(const SEvent &site) {
+ // Update cell records.
+ point_type p = prepare_point(site.point0());
+ cells_.push_back(cell_type(p, NULL));
+ }
+
+ // Insert a new half-edge into the output data structure.
+ // Takes as input left and right sites that form a new bisector.
+ // Returns a pair of pointers to a new half-edges.
+ template <typename SEvent>
+ std::pair<void*, void*> insert_new_edge(
+ const SEvent &site1, const SEvent &site2) {
+ // Get sites' indexes.
+ int site_index1 = site1.index();
+ int site_index2 = site2.index();
+
+ // Create a new half-edge that belongs to the first site.
+ edges_.push_back(edge_type());
+ edge_type &edge1 = edges_.back();
+
+ // Create a new half-edge that belongs to the second site.
+ edges_.push_back(edge_type());
+ edge_type &edge2 = edges_.back();
+
+ // Add the initial cell during the first edge insertion.
+ if (cells_.empty()) {
+ process_single_site(site1);
+ }
+
+ // The second site represents a new site during site event
+ // processing. Add a new cell to the cell records.
+ cells_.push_back(cell_type(prepare_point(site2.point0()),
+ prepare_point(site2.point1()),
+ NULL));
+
+ // Set up pointers to cells.
+ edge1.cell(&cells_[site_index1]);
+ edge2.cell(&cells_[site_index2]);
+
+ // Set up twin pointers.
+ edge1.twin(&edge2);
+ edge2.twin(&edge1);
+
+ // Return a pointer to the new half-edge.
+ return std::make_pair(&edge1, &edge2);
+ }
+
+ // Insert a new half-edge into the output data structure with the
+ // start at the point where two previously added half-edges intersect.
+ // Takes as input two sites that create a new bisector, circle event
+ // that corresponds to the intersection point of the two old half-edges,
+ // pointers to those half-edges. Half-edges' direction goes out of the
+ // new Voronoi vertex point. Returns a pair of pointers to a new half-edges.
+ template <typename SEvent, typename CEvent>
+ std::pair<void *, void *> insert_new_edge(
+ const SEvent &site1, const SEvent &site3, const CEvent &circle,
+ void *data12, void *data23) {
+ edge_type *edge12 = static_cast<edge_type*>(data12);
+ edge_type *edge23 = static_cast<edge_type*>(data23);
+
+ // Add a new Voronoi vertex.
+ vertices_.push_back(vertex_type(prepare_point(circle), NULL));
+ vertex_type &new_vertex = vertices_.back();
+
+ // Update vertex pointers of the old edges.
+ edge12->vertex0(&new_vertex);
+ edge23->vertex0(&new_vertex);
+
+ // Add a new half-edge.
+ edges_.push_back(edge_type());
+ edge_type &new_edge1 = edges_.back();
+ new_edge1.cell(&cells_[site1.index()]);
+
+ // Add a new half-edge.
+ edges_.push_back(edge_type());
+ edge_type &new_edge2 = edges_.back();
+ new_edge2.cell(&cells_[site3.index()]);
+
+ // Update twin pointers.
+ new_edge1.twin(&new_edge2);
+ new_edge2.twin(&new_edge1);
+
+ // Update vertex pointer.
+ new_edge2.vertex0(&new_vertex);
+
+ // Update Voronoi prev/next pointers.
+ edge12->prev(&new_edge1);
+ new_edge1.next(edge12);
+ edge12->twin()->next(edge23);
+ edge23->prev(edge12->twin());
+ edge23->twin()->next(&new_edge2);
+ new_edge2.prev(edge23->twin());
+
+ // Return a pointer to the new half-edge.
+ return std::make_pair(&new_edge1, &new_edge2);
+ }
+
+ void build() {
+ // Remove degenerate edges.
+ edge_iterator last_edge = edges_.begin();
+ for (edge_iterator it = edges_.begin(); it != edges_.end(); it += 2) {
+ const vertex_type *v1 = it->vertex0();
+ const vertex_type *v2 = it->vertex1();
+ if (v1 && v2 && vertex_equality_predicate_(v1->vertex(), v2->vertex())) {
+ remove_edge(&(*it));
+ } else {
+ if (it != last_edge) {
+ edge_type *e1 = &(*last_edge = *it);
+ edge_type *e2 = &(*(last_edge + 1) = *(it + 1));
+ e1->twin(e2);
+ e2->twin(e1);
+ if (e1->prev()) {
+ e1->prev()->next(e1);
+ e2->next()->prev(e2);
+ }
+ if (e2->prev()) {
+ e1->next()->prev(e1);
+ e2->prev()->next(e2);
+ }
+ }
+ last_edge += 2;
+ }
+ }
+ edges_.erase(last_edge, edges_.end());
+
+ // Set up incident edge pointers for cells and vertices.
+ for (edge_iterator it = edges_.begin(); it != edges_.end(); ++it) {
+ it->cell()->incident_edge(&(*it));
+ if (it->vertex0()) {
+ it->vertex0()->incident_edge(&(*it));
+ }
+ }
+
+ // Remove degenerate vertices.
+ vertex_iterator last_vertex = vertices_.begin();
+ for (vertex_iterator it = vertices_.begin(); it != vertices_.end(); ++it) {
+ if (it->incident_edge()) {
+ if (it != last_vertex) {
+ *last_vertex = *it;
+ vertex_type *v = &(*last_vertex);
+ edge_type *e = v->incident_edge();
+ do {
+ e->vertex0(v);
+ e = e->rot_next();
+ } while (e != v->incident_edge());
+ }
+ ++last_vertex;
+ }
+ }
+ vertices_.erase(last_vertex, vertices_.end());
+
+ // Set up next/prev pointers for infinite edges.
+ if (vertices_.empty()) {
+ if (!edges_.empty()) {
+ // Update prev/next pointers for the line edges.
+ edge_iterator edge_it = edges_.begin();
+ edge_type *edge1 = &(*edge_it);
+ edge1->next(edge1);
+ edge1->prev(edge1);
+ ++edge_it;
+ edge1 = &(*edge_it);
+ ++edge_it;
+
+ while (edge_it != edges_.end()) {
+ edge_type *edge2 = &(*edge_it);
+ ++edge_it;
+
+ edge1->next(edge2);
+ edge1->prev(edge2);
+ edge2->next(edge1);
+ edge2->prev(edge1);
+
+ edge1 = &(*edge_it);
+ ++edge_it;
+ }
+
+ edge1->next(edge1);
+ edge1->prev(edge1);
+ }
+ } else {
+ // Update prev/next pointers for the ray edges.
+ for (cell_iterator cell_it = cells_.begin();
+ cell_it != cells_.end(); ++cell_it) {
+ if (cell_it->is_degenerate())
+ continue;
+ // Move to the previous edge while
+ // it is possible in the CW direction.
+ edge_type *left_edge = cell_it->incident_edge();
+ while (left_edge->prev() != NULL) {
+ left_edge = left_edge->prev();
+ // Terminate if this is not a boundary cell.
+ if (left_edge == cell_it->incident_edge())
+ break;
+ }
+
+ if (left_edge->prev() != NULL)
+ continue;
+
+ edge_type *right_edge = cell_it->incident_edge();
+ while (right_edge->next() != NULL)
+ right_edge = right_edge->next();
+ left_edge->prev(right_edge);
+ right_edge->next(left_edge);
+ }
+ }
+ }
+
+ template <typename P>
+ point_type prepare_point(const P& p) {
+ coordinate_type nx = convert_(p.x());
+ coordinate_type ny = convert_(p.y());
+ return point_type(nx, ny);
+ }
+
+ // Remove degenerate edge.
+ void remove_edge(edge_type *edge) {
+ // Update the endpoints of the incident edges to the second vertex.
+ vertex_type *vertex = edge->vertex0();
+ edge_type *updated_edge = edge->twin()->rot_next();
+ while (updated_edge != edge->twin()) {
+ updated_edge->vertex0(vertex);
+ updated_edge = updated_edge->rot_next();
+ }
+
+ edge_type *edge1 = edge;
+ edge_type *edge2 = edge->twin();
+
+ edge_type *edge1_rot_prev = edge1->rot_prev();
+ edge_type *edge1_rot_next = edge1->rot_next();
+
+ edge_type *edge2_rot_prev = edge2->rot_prev();
+ edge_type *edge2_rot_next = edge2->rot_next();
+
+ // Update prev/next pointers for the incident edges.
+ edge1_rot_next->twin()->next(edge2_rot_prev);
+ edge2_rot_prev->prev(edge1_rot_next->twin());
+ edge1_rot_prev->prev(edge2_rot_next->twin());
+ edge2_rot_next->twin()->next(edge1_rot_prev);
+ }
+
+ cell_container_type cells_;
+ vertex_container_type vertices_;
+ edge_container_type edges_;
+
+ voronoi_diagram_builder builder_;
+ ctype_converter_type convert_;
+ vertex_equality_predicate_type vertex_equality_predicate_;
+
+ // Disallow copy constructor and operator=
+ voronoi_diagram(const voronoi_diagram&);
+ void operator=(const voronoi_diagram&);
+};
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_VORONOI_DIAGRAM

Added: trunk/boost/polygon/voronoi_utils.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/polygon/voronoi_utils.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,479 @@
+// Boost.Polygon library voronoi_utils.hpp header file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_POLYGON_VORONOI_UTILS
+#define BOOST_POLYGON_VORONOI_UTILS
+
+#include <cmath>
+#include <stack>
+#include <vector>
+
+#include "voronoi_diagram.hpp"
+
+namespace boost {
+namespace polygon {
+
+// Bounding rectangle data structure. Contains coordinates
+// of the bottom left and upper right corners of rectangle.
+template <typename T>
+class bounding_rectangle {
+public:
+ typedef T coordinate_type;
+
+ bounding_rectangle() : x_min_(1), x_max_(0) {}
+
+ bounding_rectangle(coordinate_type x1, coordinate_type y1,
+ coordinate_type x2, coordinate_type y2) {
+ x_min_ = (std::min)(x1, x2);
+ y_min_ = (std::min)(y1, y2);
+ x_max_ = (std::max)(x1, x2);
+ y_max_ = (std::max)(y1, y2);
+ }
+
+ // Update bounding rectangle.
+ void update(coordinate_type x, coordinate_type y) {
+ if (x_min_ > x_max_) {
+ x_min_ = x_max_ = x;
+ y_min_ = y_max_ = y;
+ } else {
+ x_min_ = (std::min)(x_min_, x);
+ y_min_ = (std::min)(y_min_, y);
+ x_max_ = (std::max)(x_max_, x);
+ y_max_ = (std::max)(y_max_, y);
+ }
+ }
+
+ bool is_empty() const {
+ return x_min_ > x_max_;
+ }
+
+ void clear() {
+ x_min_ = 1;
+ x_max_ = 0;
+ }
+
+ bool contains(coordinate_type x, coordinate_type y) const {
+ return x > x_min_ && x < x_max_ && y > y_min_ && y < y_max_;
+ }
+
+ // Return the x-coordinate of the bottom left point of the rectangle.
+ coordinate_type x_min() const {
+ return x_min_;
+ }
+
+ // Return the y-coordinate of the bottom left point of the rectangle.
+ coordinate_type y_min() const {
+ return y_min_;
+ }
+
+ // Return the x-coordinate of the upper right point of the rectangle.
+ coordinate_type x_max() const {
+ return x_max_;
+ }
+
+ // Return the y-coordinate of the upper right point of the rectangle.
+ coordinate_type y_max() const {
+ return y_max_;
+ }
+
+private:
+ coordinate_type x_min_;
+ coordinate_type y_min_;
+ coordinate_type x_max_;
+ coordinate_type y_max_;
+};
+
+template <typename fpt>
+struct voronoi_utils_traits {
+ typedef fpt coordinate_type;
+ typedef detail::point_2d<coordinate_type> point_type;
+ typedef std::vector<point_type> point_set_type;
+ typedef bounding_rectangle<coordinate_type> brect_type;
+ typedef struct {
+ template <typename CT>
+ coordinate_type operator()(const CT& value) const {
+ return static_cast<coordinate_type>(value);
+ }
+ } ctype_converter_type;
+};
+
+// Voronoi output post-processing tools.
+template <typename T, typename TRAITS = voronoi_utils_traits<T> >
+class voronoi_utils {
+public:
+ typedef typename TRAITS::coordinate_type coordinate_type;
+ typedef typename TRAITS::point_type point_type;
+ typedef typename TRAITS::point_set_type point_set_type;
+ typedef typename TRAITS::brect_type brect_type;
+
+ // Get scaled by a factor bounding rectangle.
+ template <typename CT>
+ static brect_type scale(const bounding_rectangle<CT> &brect,
+ coordinate_type factor) {
+ coordinate_type x_len = to_fpt(brect.x_max()) - to_fpt(brect.x_min());
+ coordinate_type y_len = to_fpt(brect.y_max()) - to_fpt(brect.y_min());
+ coordinate_type x_mid = to_fpt(brect.x_max()) + to_fpt(brect.x_min());
+ coordinate_type y_mid = to_fpt(brect.y_max()) + to_fpt(brect.y_min());
+ x_mid *= to_fpt(0.5);
+ y_mid *= to_fpt(0.5);
+ coordinate_type offset = (std::max)(x_len, y_len) * factor * to_fpt(0.5);
+ brect_type new_brect(x_mid - offset, y_mid - offset,
+ x_mid + offset, y_mid + offset);
+ return new_brect;
+ }
+
+ // Discretizes finite Voronoi edge.
+ // Discretization absolute error is defined by max_error value.
+ template <typename CT>
+ static void discretize(const voronoi_edge<CT> &edge,
+ coordinate_type max_error, point_set_type &discretization) {
+ // Don't process infinite edges.
+ if (!edge.is_finite())
+ return;
+
+ // Retrieve the cell to the left of the current edge.
+ const typename voronoi_edge<CT>::voronoi_cell_type *cell1 = edge.cell();
+ // Retrieve the cell to the right of the current edge.
+ const typename voronoi_edge<CT>::voronoi_cell_type *cell2 =
+ edge.twin()->cell();
+
+ discretization.push_back(get_point(edge.vertex0()->vertex()));
+ discretization.push_back(get_point(edge.vertex1()->vertex()));
+ if (edge.is_curved()) {
+ bool flag = cell1->contains_segment();
+ // point1 - site point;
+ point_type point1 = flag ?
+ get_point(cell2->point0()) : get_point(cell1->point0());
+ // point2 - start-point of the segment site;
+ point_type point2 = flag ?
+ get_point(cell1->point0()) : get_point(cell2->point0());
+ // point3 - endpoint of the segment site;
+ point_type point3 = flag ?
+ get_point(cell1->point1()) : get_point(cell2->point1());
+ fill_intermediate_points(
+ point1, point2, point3, max_error, discretization);
+ }
+ }
+
+ // Clip a linear Voronoi edge with a given rectangle.
+ template <typename CT>
+ static void clip(const voronoi_edge<CT> &edge,
+ const brect_type &brect, point_set_type &clipped_edge) {
+ // Don't process curved edges.
+ if (edge.is_curved())
+ return;
+
+ if (edge.is_finite()) {
+ clip(edge.vertex0()->vertex(), edge.vertex1()->vertex(),
+ brect, clipped_edge);
+ } else {
+ const typename voronoi_edge<CT>::voronoi_cell_type *cell1 = edge.cell();
+ const typename voronoi_edge<CT>::voronoi_cell_type *cell2 =
+ edge.twin()->cell();
+ point_type point1 = get_point(cell1->point0());
+ point_type point2 = get_point(cell2->point0());
+ if (point1 == point2) {
+ if (cell1->contains_segment())
+ point1 = get_point(cell1->point1());
+ else
+ point2 = get_point(cell2->point1());
+ }
+
+ if (edge.vertex0()) {
+ // Ray edge.
+ point_type origin = get_point(edge.vertex0()->vertex());
+ point_type direction(point1.y() - point2.y(), point2.x() - point1.x());
+ if (brect.contains(origin.x(), origin.y()))
+ clipped_edge.push_back(origin);
+ intersect(origin, direction, RAY, brect, clipped_edge);
+ } else if (edge.vertex1()) {
+ // Ray edge.
+ point_type origin = get_point(edge.vertex1()->vertex());
+ point_type direction(point2.y() - point1.y(), point1.x() - point2.x());
+ if (brect.contains(origin.x(), origin.y()))
+ clipped_edge.push_back(origin);
+ intersect(origin, direction, RAY, brect, clipped_edge);
+ // Keep correct ordering.
+ (std::reverse)(clipped_edge.begin(), clipped_edge.end());
+ } else if (cell1->contains_point() && cell2->contains_point()) {
+ // Primary line edge.
+ point_type origin((point1.x() + point2.x()) * 0.5, (point1.y() + point2.y()) * 0.5);
+ point_type direction(point1.y() - point2.y(), point2.x() - point1.x());
+ intersect(origin, direction, LINE, brect, clipped_edge);
+ } else {
+ point_type origin = cell1->contains_point() ? point1 : point2;
+ point_type direction(point1.y() - point2.y(), point2.x() - point1.x());
+ intersect(origin, direction, LINE, brect, clipped_edge);
+ }
+ }
+ }
+
+ // Clip an edge with the given rectangle.
+ template <typename PointType>
+ static void clip(const PointType &p1, const PointType &p2,
+ const brect_type &brect, point_set_type &clipped_edge) {
+ point_type start = get_point(p1);
+ point_type end = get_point(p2);
+ point_type direction(end.x() - start.x(), end.y() - start.y());
+ if (brect.contains(start.x(), start.y()))
+ clipped_edge.push_back(start);
+ if (p1 != p2)
+ intersect(start, direction, SEGMENT, brect, clipped_edge);
+ if (brect.contains(end.x(), end.y()))
+ clipped_edge.push_back(end);
+ }
+
+private:
+ typedef typename TRAITS::ctype_converter_type ctype_converter_type;
+
+ voronoi_utils();
+
+ // There are three different types of linear primitive:
+ // 1) SEGMENT - has two finite endpoints;
+ // 2) RAY - has one finite and one infinite endpoint;
+ // 3) LINE - has two infinite endpoints.
+ enum EdgeType {
+ SEGMENT = 0,
+ RAY = 1,
+ LINE = 2
+ };
+
+ template <typename P>
+ static point_type get_point(const P &point) {
+ coordinate_type x = to_fpt(point.x());
+ coordinate_type y = to_fpt(point.y());
+ return point_type(x, y);
+ }
+
+ static void intersect(
+ const point_type &origin, const point_type &direction,
+ EdgeType edge_type, const brect_type &brect,
+ point_set_type &clipped_edge) {
+ // Find the center of the rectangle.
+ coordinate_type center_x = (brect.x_min() + brect.x_max()) * to_fpt(0.5);
+ coordinate_type center_y = (brect.y_min() + brect.y_max()) * to_fpt(0.5);
+
+ // Find the half-diagonal vector of the rectangle.
+ coordinate_type len_x = brect.x_max() - center_x;
+ coordinate_type len_y = brect.y_max() - center_y;
+
+ // Find the vector between the origin and the center of the
+ // rectangle.
+ coordinate_type diff_x = origin.x() - center_x;
+ coordinate_type diff_y = origin.y() - center_y;
+
+ // Find the vector perpendicular to the direction vector.
+ coordinate_type perp_x = direction.y();
+ coordinate_type perp_y = -direction.x();
+
+ // Projection of the vector between the origin and the center of
+ // the rectangle on the line perpendicular to the direction vector.
+ coordinate_type lexpr = magnitude(perp_x * diff_x + perp_y * diff_y);
+
+ // Maximum projection among any of the half-diagonals of the
+ // rectangle on the line perpendicular to the direction vector.
+ coordinate_type rexpr =
+ magnitude(perp_x * len_x) + magnitude(perp_y * len_y);
+
+ // Intersection check. Compare projections.
+ if (lexpr > rexpr)
+ return;
+
+ // Intersection parameters. If fT[i]_used is true than:
+ // origin + fT[i] * direction = intersection point, i = 0 .. 1.
+ // For different edge types next fT values are acceptable:
+ // Segment: [0; 1];
+ // Ray: [0; infinity];
+ // Line: [-infinity; infinity].
+ bool fT0_used = false;
+ bool fT1_used = false;
+ coordinate_type fT0 = 0;
+ coordinate_type fT1 = 0;
+
+ // Check for the intersections with the lines
+ // going through the sides of the bounding rectangle.
+ clip_line(+direction.x(), -diff_x - len_x, fT0_used, fT1_used, fT0, fT1);
+ clip_line(-direction.x(), +diff_x - len_x, fT0_used, fT1_used, fT0, fT1);
+ clip_line(+direction.y(), -diff_y - len_y, fT0_used, fT1_used, fT0, fT1);
+ clip_line(-direction.y(), +diff_y - len_y, fT0_used, fT1_used, fT0, fT1);
+
+ // Update intersections vector.
+ if (fT0_used && check_extent(fT0, edge_type))
+ clipped_edge.push_back(point_type(
+ origin.x() + fT0 * direction.x(), origin.y() + fT0 * direction.y()));
+ if (fT1_used && fT0 != fT1 && check_extent(fT1, edge_type))
+ clipped_edge.push_back(point_type(
+ origin.x() + fT1 * direction.x(), origin.y() + fT1 * direction.y()));
+ }
+
+ // Find intermediate points of the parabola.
+ // Parabola is a locus of points equidistant from the point and segment
+ // sites. intermediate_points should contain two initial endpoints
+ // of the edge (Voronoi vertices). Intermediate points are inserted
+ // between the given two endpoints.
+ // Max_dist is the maximum distance allowed between parabola and line
+ // segments that discretize it.
+ static void fill_intermediate_points(
+ point_type point_site, point_type segment_site_start,
+ point_type segment_site_end, coordinate_type max_dist,
+ point_set_type &intermediate_points) {
+ // Apply the linear transformation to move start point of the
+ // segment to the point with coordinates (0, 0) and the direction
+ // of the segment to coincide the positive direction of the x-axis.
+ coordinate_type segm_vec_x =
+ segment_site_end.x() - segment_site_start.x();
+ coordinate_type segm_vec_y =
+ segment_site_end.y() - segment_site_start.y();
+ coordinate_type sqr_segment_length =
+ segm_vec_x * segm_vec_x + segm_vec_y * segm_vec_y;
+
+ // Compute x-coordinates of the endpoints of the edge
+ // in the transformed space.
+ coordinate_type projection_start = sqr_segment_length *
+ get_point_projection(
+ intermediate_points[0], segment_site_start, segment_site_end);
+ coordinate_type projection_end = sqr_segment_length *
+ get_point_projection(
+ intermediate_points[1], segment_site_start, segment_site_end);
+
+ // Compute parabola parameters in the transformed space.
+ // Parabola has next representation:
+ // f(x) = ((x-rot_x)^2 + rot_y^2) / (2.0*rot_y).
+ coordinate_type point_vec_x = point_site.x() - segment_site_start.x();
+ coordinate_type point_vec_y = point_site.y() - segment_site_start.y();
+ coordinate_type rot_x =
+ segm_vec_x * point_vec_x + segm_vec_y * point_vec_y;
+ coordinate_type rot_y =
+ segm_vec_x * point_vec_y - segm_vec_y * point_vec_x;
+
+ // Save the last point.
+ point_type last_point = intermediate_points[1];
+ intermediate_points.pop_back();
+
+ // Use stack to avoid recursion.
+ std::stack<coordinate_type> point_stack;
+ point_stack.push(projection_end);
+ coordinate_type cur_x = projection_start;
+ coordinate_type cur_y = parabola_y(cur_x, rot_x, rot_y);
+
+ // Adjust max_dist parameter in the transformed space.
+ max_dist *= max_dist * sqr_segment_length;
+
+ while (!point_stack.empty()) {
+ coordinate_type new_x = point_stack.top();
+ coordinate_type new_y = parabola_y(new_x, rot_x, rot_y);
+
+ // Compute coordinates of the point of the parabola that is
+ // furthest from the current line segment.
+ coordinate_type mid_x =
+ (new_y - cur_y) / (new_x - cur_x) * rot_y + rot_x;
+ coordinate_type mid_y = parabola_y(mid_x, rot_x, rot_y);
+
+ // Compute maximum distance between the given parabolic arc
+ // and line segment that discretize it.
+ coordinate_type dist = (new_y - cur_y) * (mid_x - cur_x) -
+ (new_x - cur_x) * (mid_y - cur_y);
+ dist = dist * dist / ((new_y - cur_y) * (new_y - cur_y) +
+ (new_x - cur_x) * (new_x - cur_x));
+ if (dist <= max_dist) {
+ // Distance between parabola and line segment is
+ // not greater than max_dist.
+ point_stack.pop();
+ coordinate_type inter_x = (segm_vec_x * new_x - segm_vec_y * new_y) /
+ sqr_segment_length + segment_site_start.x();
+ coordinate_type inter_y = (segm_vec_x * new_y + segm_vec_y * new_x) /
+ sqr_segment_length + segment_site_start.y();
+ intermediate_points.push_back(point_type(inter_x, inter_y));
+ cur_x = new_x;
+ cur_y = new_y;
+ } else {
+ point_stack.push(mid_x);
+ }
+ }
+
+ // Update last point.
+ intermediate_points.back() = last_point;
+ }
+
+ // Compute y(x) = ((x - a) * (x - a) + b * b) / (2 * b).
+ static coordinate_type parabola_y(
+ coordinate_type x, coordinate_type a, coordinate_type b) {
+ return ((x - a) * (x - a) + b * b) / (to_fpt(2.0) * b);
+ }
+
+ // Check whether extent is compatible with the edge type.
+ static bool check_extent(coordinate_type extent, EdgeType etype) {
+ switch (etype) {
+ case SEGMENT: return extent >= to_fpt(0.0) && extent <= to_fpt(1.0);
+ case RAY: return extent >= to_fpt(0.0);
+ case LINE: return true;
+ }
+ return true;
+ }
+
+ // Compute the absolute value.
+ static inline coordinate_type magnitude(coordinate_type value) {
+ return (value >= to_fpt(0.0)) ? value : -value;
+ }
+
+ // Find fT min and max values: fT = numer / denom.
+ static void clip_line(
+ coordinate_type denom, coordinate_type numer,
+ bool &fT0_used, bool &fT1_used,
+ coordinate_type &fT0, coordinate_type &fT1) {
+ if (denom > to_fpt(0.0)) {
+ if (fT1_used && numer > denom * fT1)
+ return;
+ if (!fT0_used || numer > denom * fT0) {
+ fT0_used = true;
+ fT0 = numer / denom;
+ }
+ } else if (denom < to_fpt(0.0)) {
+ if (fT0_used && numer > denom * fT0)
+ return;
+ if (!fT1_used || numer > denom * fT1) {
+ fT1_used = true;
+ fT1 = numer / denom;
+ }
+ }
+ }
+
+ // Get normalized length of the distance between:
+ // 1) point projection onto the segment;
+ // 2) start point of the segment.
+ // Return this length divided by the segment length.
+ // This is made to avoid sqrt computation during transformation from
+ // the initial space to the transformed one and vice versa.
+ // Assumption is made that projection of the point lies
+ // between the start-point and endpoint of the segment.
+ static coordinate_type get_point_projection(
+ const point_type &point,
+ const point_type &segment_start,
+ const point_type &segment_end) {
+ coordinate_type segment_vec_x = segment_end.x() - segment_start.x();
+ coordinate_type segment_vec_y = segment_end.y() - segment_start.y();
+ coordinate_type point_vec_x = point.x() - segment_start.x();
+ coordinate_type point_vec_y = point.y() - segment_start.y();
+ coordinate_type sqr_segment_length =
+ segment_vec_x * segment_vec_x + segment_vec_y * segment_vec_y;
+ coordinate_type vec_dot =
+ segment_vec_x * point_vec_x + segment_vec_y * point_vec_y;
+ return vec_dot / sqr_segment_length;
+ }
+
+ template <typename CT>
+ static coordinate_type to_fpt(const CT& value) {
+ static ctype_converter_type converter;
+ return converter(value);
+ }
+};
+} // polygon
+} // boost
+
+#endif // BOOST_POLYGON_VORONOI_UTILS

Modified: trunk/libs/polygon/test/Jamfile.v2
==============================================================================
--- trunk/libs/polygon/test/Jamfile.v2 (original)
+++ trunk/libs/polygon/test/Jamfile.v2 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -13,10 +13,22 @@
     requirements
         <include>.
         <toolset>msvc:<asynch-exceptions>on
+ <library>/boost/test//boost_unit_test_framework
     ;
 
 test-suite polygon-unit
     :
- [ run gtl_boost_unit_test.cpp ]
+ [ run polygon_segment_test.cpp ]
+ [ run gtl_boost_unit_test.cpp ]
     ;
 
+test-suite voronoi-unit
+ :
+ [ run voronoi_builder_test.cpp ]
+ [ run voronoi_ctypes_test.cpp ]
+ [ run voronoi_predicates_test.cpp ]
+ [ run voronoi_robust_fpt_test.cpp ]
+ [ run voronoi_structures_test.cpp ]
+ ;
+
+

Modified: trunk/libs/polygon/test/gtl_boost_unit_test.cpp
==============================================================================
--- trunk/libs/polygon/test/gtl_boost_unit_test.cpp (original)
+++ trunk/libs/polygon/test/gtl_boost_unit_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -194,7 +194,7 @@
     return o << r.get(HORIZONTAL) << ' ' << r.get(VERTICAL);
   }
   template <class T>
- std::ostream& operator << (std::ostream& o, const directed_line_segment_data<T>& r)
+ std::ostream& operator << (std::ostream& o, const segment_data<T>& r)
   {
     return o << r.get(LOW) << ' ' << r.get(HIGH);
   }
@@ -3649,15 +3649,15 @@
   {
     using namespace gtl;
     typedef point_data<int> Point;
- typedef directed_line_segment_data<int> Dls;
+ typedef segment_data<int> Segment;
     Point pt1(0, 0);
     Point pt2(10, 10);
     Point pt3(20, 20);
     Point pt4(20, 0);
- Dls dls1(pt1, pt2);
- Dls dls2(pt1, pt3);
- Dls dls3(pt1, pt4);
- Dls dls4(pt2, pt1);
+ Segment dls1(pt1, pt2);
+ Segment dls2(pt1, pt3);
+ Segment dls3(pt1, pt4);
+ Segment dls4(pt2, pt1);
     bool b1 = equivalence(dls1, dls1);
     bool b2 = equivalence(dls1, dls2);
     bool b3 = equivalence(dls1, dls3);
@@ -3704,10 +3704,9 @@
     std::cout << euclidean_distance(dls1, Point(5, 6)) << std::endl;
     std::cout << euclidean_distance(dls1, Point(5, 3)) << std::endl;
     std::cout << euclidean_distance(dls1, dls3) << std::endl;
- std::cout << euclidean_distance(dls1, directed_line_segment_data<int>(Point(2, 0), Point(3, 0))) << std::endl;
+ std::cout << euclidean_distance(dls1, segment_data<int>(Point(2, 0), Point(3, 0))) << std::endl;
     assert_s(intersects(dls1, dls3), "intersects1");
- assert_s(!intersects(dls1, directed_line_segment_data<int>(Point(2, 0), Point(3, 0))), "intersects2");
- assert_s(boundaries_intersect(dls1, dls2), "bi");
+ assert_s(!intersects(dls1, segment_data<int>(Point(2, 0), Point(3, 0))), "intersects2");
     assert_s(abuts(dls1, dls2), "abuts");
     Point p;
     bool ir = intersection(p, dls1, dls2);

Added: trunk/libs/polygon/test/polygon_segment_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/polygon_segment_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,367 @@
+// Boost.Polygon library polygon_segment_test.cpp file
+
+// Copyright Andrii Sydorchuk 2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#define BOOST_TEST_MODULE POLYGON_SEGMENT_TEST
+#include <boost/mpl/list.hpp>
+#include <boost/test/test_case_template.hpp>
+
+#include "boost/polygon/polygon.hpp"
+using namespace boost::polygon;
+
+typedef boost::mpl::list<int> test_types;
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_data_test, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef segment_data<T> segment_type;
+ point_type point1(1, 2);
+ point_type point2(3, 4);
+ segment_type segment1(point1, point2);
+ segment_type segment2 = segment1;
+
+ BOOST_CHECK(segment1.low() == point1);
+ BOOST_CHECK(segment1.high() == point2);
+ BOOST_CHECK(segment1.get(LOW) == point1);
+ BOOST_CHECK(segment1.get(HIGH) == point2);
+ BOOST_CHECK(segment1 == segment2);
+ BOOST_CHECK(!(segment1 != segment2));
+ BOOST_CHECK(!(segment1 < segment2));
+ BOOST_CHECK(!(segment1 > segment1));
+ BOOST_CHECK(segment1 <= segment2);
+ BOOST_CHECK(segment1 >= segment2);
+
+ segment1.low(point2);
+ segment1.high(point1);
+ BOOST_CHECK(segment1.low() == point2);
+ BOOST_CHECK(segment1.high() == point1);
+ BOOST_CHECK(!(segment1 == segment2));
+ BOOST_CHECK(segment1 != segment2);
+
+ segment2.set(LOW, point2);
+ segment2.set(HIGH, point1);
+ BOOST_CHECK(segment1 == segment2);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_traits_test, T, test_types) {
+ typedef point_data<T> point_type ;
+ typedef segment_data<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(3, 4);
+ segment_type segment = segment_mutable_traits<segment_type>::construct(point1, point2);
+
+ BOOST_CHECK(segment_traits<segment_type>::get(segment, LOW) == point1);
+ BOOST_CHECK(segment_traits<segment_type>::get(segment, HIGH) == point2);
+
+ segment_mutable_traits<segment_type>::set(segment, LOW, point2);
+ segment_mutable_traits<segment_type>::set(segment, HIGH, point1);
+
+ BOOST_CHECK(segment_traits<segment_type>::get(segment, LOW) == point2);
+ BOOST_CHECK(segment_traits<segment_type>::get(segment, HIGH) == point1);
+}
+
+template <typename T>
+struct Segment {
+ point_data<T> p0;
+ point_data<T> p1;
+};
+
+namespace boost {
+namespace polygon {
+ template <typename T>
+ struct geometry_concept< Segment<T> > { typedef segment_concept type; };
+
+ template <typename T>
+ struct segment_traits< Segment<T> > {
+ typedef T coordinate_type;
+ typedef point_data<T> point_type;
+
+ static point_type get(const Segment<T>& segment, direction_1d dir) {
+ return dir.to_int() ? segment.p1 : segment.p0;
+ }
+ };
+
+ template <typename T>
+ struct segment_mutable_traits< Segment<T> > {
+ typedef point_data<T> point_type;
+
+ static inline void set(Segment<T>& segment, direction_1d dir, const point_type& point) {
+ if (dir.to_int()) {
+ segment.p1 = point;
+ } else {
+ segment.p0 = point;
+ }
+ }
+
+ static inline Segment<T> construct(const point_type& point1, const point_type& point2) {
+ Segment<T> segment;
+ segment.p0 = point1;
+ segment.p1 = point2;
+ return segment;
+ }
+ };
+}
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test1, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(3, 4);
+ point_type point3(2, 3);
+ segment_type segment1 = construct<segment_type>(point1, point2);
+ BOOST_CHECK(segment1.p0 == point1);
+ BOOST_CHECK(segment1.p1 == point2);
+ BOOST_CHECK(get(segment1, LOW) == point1);
+ BOOST_CHECK(low(segment1) == point1);
+ BOOST_CHECK(get(segment1, HIGH) == point2);
+ BOOST_CHECK(high(segment1) == point2);
+ BOOST_CHECK(center(segment1) == point3);
+
+ set(segment1, LOW, point2);
+ set(segment1, HIGH, point1);
+ BOOST_CHECK(segment1.p0 == point2);
+ BOOST_CHECK(segment1.p1 == point1);
+ BOOST_CHECK(get(segment1, LOW) == point2);
+ BOOST_CHECK(get(segment1, HIGH) == point1);
+ low(segment1, point1);
+ high(segment1, point2);
+ BOOST_CHECK(segment1.p0 == point1);
+ BOOST_CHECK(segment1.p1 == point2);
+
+ segment_data<T> segment2 = copy_construct< segment_data<T> >(segment1);
+ BOOST_CHECK(segment1.p0 == segment2.low());
+ BOOST_CHECK(segment1.p1 == segment2.high());
+ BOOST_CHECK(equivalence(segment1, segment2));
+
+ segment_data<T> segment3 = construct< segment_data<T> >(point2, point1);
+ assign(segment1, segment3);
+ BOOST_CHECK(segment1.p0 == point2);
+ BOOST_CHECK(segment1.p1 == point1);
+ BOOST_CHECK(!equivalence(segment1, segment2));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test2, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(2, 4);
+ point_type point3(0, 0);
+ point_type point4(5, 10);
+ point_type point5(1, 3);
+ point_type point6(2, 3);
+ point_type point7(100, 201);
+ point_type point8(100, 200);
+ point_type point9(100, 199);
+ segment_type segment = construct<segment_type>(point1, point2);
+
+ BOOST_CHECK(on_above_or_below(segment, point1) == 0);
+ BOOST_CHECK(on_above_or_below(segment, point2) == 0);
+ BOOST_CHECK(on_above_or_below(segment, point3) == 0);
+ BOOST_CHECK(on_above_or_below(segment, point4) == 0);
+ BOOST_CHECK(on_above_or_below(segment, point5) == 1);
+ BOOST_CHECK(on_above_or_below(segment, point6) == -1);
+ BOOST_CHECK(on_above_or_below(segment, point7) == 1);
+ BOOST_CHECK(on_above_or_below(segment, point8) == 0);
+ BOOST_CHECK(on_above_or_below(segment, point9) == -1);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test3, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(3, 6);
+ point_type point3(2, 4);
+ point_type point4(4, 8);
+ point_type point5(0, 0);
+ segment_type segment = construct<segment_type>(point1, point2);
+
+ BOOST_CHECK(contains(segment, point1, true));
+ BOOST_CHECK(contains(segment, point2, true));
+ BOOST_CHECK(!contains(segment, point1, false));
+ BOOST_CHECK(!contains(segment, point2, false));
+ BOOST_CHECK(contains(segment, point3, false));
+ BOOST_CHECK(!contains(segment, point4, true));
+ BOOST_CHECK(!contains(segment, point5, true));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test4, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(0, 0);
+ point_type point2(10, 0);
+ point_type point3(5, 0);
+ point_type point4(-1, 0);
+ point_type point5(11, 0);
+ segment_type segment = construct<segment_type>(point1, point2);
+
+ BOOST_CHECK(contains(segment, point1, true));
+ BOOST_CHECK(contains(segment, point2, true));
+ BOOST_CHECK(!contains(segment, point1, false));
+ BOOST_CHECK(!contains(segment, point2, false));
+ BOOST_CHECK(contains(segment, point3, false));
+ BOOST_CHECK(!contains(segment, point4, true));
+ BOOST_CHECK(!contains(segment, point5, true));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test5, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(0, 0);
+ point_type point2(1, 2);
+ point_type point3(2, 4);
+ point_type point4(3, 6);
+ point_type point5(4, 8);
+ point_type point6(5, 10);
+ segment_type segment1 = construct<segment_type>(point2, point5);
+ segment_type segment2 = construct<segment_type>(point3, point4);
+ segment_type segment3 = construct<segment_type>(point1, point3);
+ segment_type segment4 = construct<segment_type>(point4, point6);
+
+ BOOST_CHECK(contains(segment1, segment2, false));
+ BOOST_CHECK(!contains(segment2, segment1, true));
+ BOOST_CHECK(!contains(segment1, segment3, true));
+ BOOST_CHECK(!contains(segment1, segment4, true));
+ BOOST_CHECK(contains(segment1, segment1, true));
+ BOOST_CHECK(!contains(segment1, segment1, false));
+}
+
+template<typename T>
+struct Transformer {
+ void scale(T& x, T& y) const {
+ x *= 2;
+ y *= 2;
+ }
+
+ void transform(T& x, T& y) const {
+ T tmp = x;
+ x = y;
+ y = tmp;
+ }
+};
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test6, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(4, 6);
+ segment_type segment1 = construct<segment_type>(point1, point2);
+
+ scale_up(segment1, 3);
+ BOOST_CHECK(low(segment1) == point_type(3, 6));
+ BOOST_CHECK(high(segment1) == point_type(12, 18));
+
+ scale_down(segment1, 3);
+ BOOST_CHECK(low(segment1) == point1);
+ BOOST_CHECK(high(segment1) == point2);
+ BOOST_CHECK(length(segment1) == 5);
+
+ move(segment1, HORIZONTAL, 1);
+ move(segment1, VERTICAL, 2);
+ BOOST_CHECK(low(segment1) == point_type(2, 4));
+ BOOST_CHECK(high(segment1) == point_type(5, 8));
+ BOOST_CHECK(length(segment1) == 5);
+
+ convolve(segment1, point_type(1, 2));
+ BOOST_CHECK(low(segment1) == point_type(3, 6));
+ BOOST_CHECK(high(segment1) == point_type(6, 10));
+
+ deconvolve(segment1, point_type(2, 4));
+ BOOST_CHECK(low(segment1) == point1);
+ BOOST_CHECK(high(segment1) == point2);
+
+ scale(segment1, Transformer<T>());
+ BOOST_CHECK(low(segment1) == point_type(2, 4));
+ BOOST_CHECK(high(segment1) == point_type(8, 12));
+ transform(segment1, Transformer<T>());
+ BOOST_CHECK(low(segment1) == point_type(4, 2));
+ BOOST_CHECK(high(segment1) == point_type(12, 8));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test7, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ segment_type segment1 = construct<segment_type>(point_type(0, 0), point_type(1, 2));
+ segment_type segment2 = construct<segment_type>(point_type(1, 2), point_type(2, 4));
+ segment_type segment3 = construct<segment_type>(point_type(2, 4), point_type(0, 4));
+ segment_type segment4 = construct<segment_type>(point_type(0, 4), point_type(0, 0));
+
+ BOOST_CHECK(abuts(segment1, segment2, HIGH));
+ BOOST_CHECK(abuts(segment2, segment3, HIGH));
+ BOOST_CHECK(abuts(segment3, segment4, HIGH));
+ BOOST_CHECK(abuts(segment4, segment1, HIGH));
+
+ BOOST_CHECK(!abuts(segment1, segment2, LOW));
+ BOOST_CHECK(!abuts(segment2, segment3, LOW));
+ BOOST_CHECK(!abuts(segment3, segment4, LOW));
+ BOOST_CHECK(!abuts(segment4, segment1, LOW));
+
+ BOOST_CHECK(abuts(segment2, segment1));
+ BOOST_CHECK(abuts(segment3, segment2));
+ BOOST_CHECK(abuts(segment4, segment3));
+ BOOST_CHECK(abuts(segment1, segment4));
+
+ BOOST_CHECK(!abuts(segment1, segment3));
+ BOOST_CHECK(!abuts(segment2, segment4));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test8, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point;
+ segment_type segment1 = construct<segment_type>(point_type(0, 0), point_type(2, 2));
+ segment_type segment2 = construct<segment_type>(point_type(1, 1), point_type(3, 3));
+
+ BOOST_CHECK(!intersection(point, segment1, segment2));
+ BOOST_CHECK(intersects(segment1, segment2));
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test9, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ point_type point1(1, 2);
+ point_type point2(7, 10);
+ segment_type segment1 = construct<segment_type>(point1, point2);
+
+ BOOST_CHECK(euclidean_distance(segment1, point1) == 0.0);
+ BOOST_CHECK(euclidean_distance(segment1, point2) == 0.0);
+ BOOST_CHECK(euclidean_distance(segment1, point_type(10, 14)) == 5.0);
+ BOOST_CHECK(euclidean_distance(segment1, point_type(-3, -1)) == 5.0);
+ BOOST_CHECK(euclidean_distance(segment1, point_type(0, 9)) == 5.0);
+ BOOST_CHECK(euclidean_distance(segment1, point_type(8, 3)) == 5.0);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_concept_test10, T, test_types) {
+ typedef point_data<T> point_type;
+ typedef Segment<T> segment_type;
+
+ segment_type segment1 = construct<segment_type>(point_type(0, 0), point_type(3, 4));
+ segment_type segment2 = construct<segment_type>(point_type(2, 0), point_type(0, 2));
+ segment_type segment3 = construct<segment_type>(point_type(1, -7), point_type(10, 5));
+ segment_type segment4 = construct<segment_type>(point_type(7, 7), point_type(10, 11));
+ segment_type segment5 = construct<segment_type>(point_type(1, 1), point_type(-1, 3));
+ segment_type segment6 = construct<segment_type>(point_type(0, 0), point_type(1, 1));
+
+ BOOST_CHECK(intersects(segment1, segment2, false));
+ BOOST_CHECK(euclidean_distance(segment1, segment2) == 0.0);
+ BOOST_CHECK(!intersects(segment1, segment3, true));
+ BOOST_CHECK(euclidean_distance(segment1, segment3) == 5.0);
+ BOOST_CHECK(!intersects(segment1, segment4, true));
+ BOOST_CHECK(euclidean_distance(segment1, segment4) == 5.0);
+ BOOST_CHECK(intersects(segment2, segment5, false));
+ BOOST_CHECK(intersects(segment2, segment6, false));
+}

Added: trunk/libs/polygon/test/voronoi_builder_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_builder_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,608 @@
+// Boost.Polygon library voronoi_builder_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ctime>
+
+#define BOOST_TEST_MODULE voronoi_builder_test
+#include <boost/mpl/list.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/test/test_case_template.hpp>
+
+#include <boost/polygon/polygon.hpp>
+#include <boost/polygon/voronoi.hpp>
+using namespace boost::polygon;
+#include "voronoi_test_helper.hpp"
+
+typedef boost::mpl::list<int> test_types;
+typedef voronoi_diagram<double> vd_type;
+typedef vd_type::coordinate_type coordinate_type;
+typedef vd_type::edge_type voronoi_edge_type;
+typedef vd_type::const_cell_iterator const_cell_iterator;
+typedef vd_type::const_vertex_iterator const_vertex_iterator;
+
+#define CHECK_EQUAL_POINTS(p1, p2) \
+ BOOST_CHECK(p1.x() == static_cast<T>(p2.x())); \
+ BOOST_CHECK(p1.y() == static_cast<T>(p2.y()))
+
+#define CHECK_OUTPUT_SIZE(output, cells, vertices, edges) \
+ BOOST_CHECK(output.num_cells() == cells); \
+ BOOST_CHECK(output.num_vertices() == vertices); \
+ BOOST_CHECK(output.num_edges() == edges)
+
+#define VERIFY_OUTPUT(output) \
+ BOOST_CHECK(voronoi_test_helper::verify_output(output, \
+ voronoi_test_helper::HALF_EDGE_ORIENTATION)); \
+ BOOST_CHECK(voronoi_test_helper::verify_output(output, \
+ voronoi_test_helper::CELL_CONVEXITY)); \
+ BOOST_CHECK(voronoi_test_helper::verify_output(output, \
+ voronoi_test_helper::INCIDENT_EDGES_CCW_ORDER)); \
+ BOOST_CHECK(voronoi_test_helper::verify_output(output, \
+ voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS))
+
+#define VERIFY_NO_HALF_EDGE_INTERSECTIONS(output) \
+ BOOST_CHECK(voronoi_test_helper::verify_output(output, \
+ voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS))
+
+// Sites: (0, 0).
+BOOST_AUTO_TEST_CASE_TEMPLATE(single_site_test, T, test_types) {
+ std::vector< point_data<T> > points;
+ points.push_back(point_data<T>(0, 0));
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+
+ BOOST_CHECK(test_output.cells().size() == 1);
+ CHECK_OUTPUT_SIZE(test_output, 1, 0, 0);
+
+ const_cell_iterator it = test_output.cells().begin();
+ BOOST_CHECK(it->incident_edge() == NULL);
+}
+
+// Sites: (0, 0), (0, 1).
+BOOST_AUTO_TEST_CASE_TEMPLATE(collinear_sites_test1, T, test_types) {
+ std::vector< point_data<T> > points;
+ points.push_back(point_data<T>(0, 0));
+ points.push_back(point_data<T>(0, 1));
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+ CHECK_OUTPUT_SIZE(test_output, 2, 0, 1);
+
+ const_cell_iterator cell_it = test_output.cells().begin();
+ cell_it++;
+
+ const voronoi_edge_type *edge1_1 = cell_it->incident_edge();
+ const voronoi_edge_type *edge1_2 = edge1_1->twin();
+
+ BOOST_CHECK_EQUAL(edge1_1->twin() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge1_2->twin() == edge1_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->next() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge1_1->prev() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge1_1->rot_next() == NULL, true);
+ BOOST_CHECK_EQUAL(edge1_1->rot_prev() == NULL, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge1_2->prev() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge1_2->rot_next() == NULL, true);
+ BOOST_CHECK_EQUAL(edge1_2->rot_prev() == NULL, true);
+}
+
+// Sites: (0, 0), (1, 1), (2, 2).
+BOOST_AUTO_TEST_CASE_TEMPLATE(collinear_sites_test2, T, test_types) {
+ std::vector< point_data<T> > points;
+ points.push_back(point_data<T>(0, 0));
+ points.push_back(point_data<T>(1, 1));
+ points.push_back(point_data<T>(2, 2));
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+ CHECK_OUTPUT_SIZE(test_output, 3, 0, 2);
+
+ const_cell_iterator cell_it = test_output.cells().begin();
+ const voronoi_edge_type *edge1_1 = cell_it->incident_edge();
+ const voronoi_edge_type *edge1_2 = edge1_1->twin();
+ cell_it++;
+ cell_it++;
+ const voronoi_edge_type *edge2_2 = cell_it->incident_edge();
+ const voronoi_edge_type *edge2_1 = edge2_2->twin();
+
+ BOOST_CHECK_EQUAL(edge1_1->twin() == edge1_2 && edge1_2->twin() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_1->twin() == edge2_2 && edge2_2->twin() == edge2_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->next() == edge1_1 && edge1_1->prev() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge1_1->rot_next() == NULL && edge1_1->rot_prev() == NULL, true);
+ BOOST_CHECK_EQUAL(edge1_2->rot_next() == NULL && edge1_2->rot_prev() == NULL, true);
+ BOOST_CHECK_EQUAL(edge2_1->rot_next() == NULL && edge2_1->rot_prev() == NULL, true);
+ BOOST_CHECK_EQUAL(edge2_2->next() == edge2_2 && edge2_2->prev() == edge2_2, true);
+ BOOST_CHECK_EQUAL(edge2_2->rot_next() == NULL && edge2_2->rot_prev() == NULL, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_1->next() == edge1_2 && edge2_1->prev() == edge1_2, true);
+}
+
+// Sites: (0, 0), (0, 4), (2, 1).
+BOOST_AUTO_TEST_CASE_TEMPLATE(triangle_test1, T, test_types) {
+ point_data<T> point1(0, 0);
+ point_data<T> point2(0, 4);
+ point_data<T> point3(2, 1);
+ std::vector< point_data<T> > points;
+ points.push_back(point1);
+ points.push_back(point2);
+ points.push_back(point3);
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+ CHECK_OUTPUT_SIZE(test_output, 3, 1, 3);
+
+ const_vertex_iterator it = test_output.vertices().begin();
+ BOOST_CHECK_EQUAL(it->vertex().x() == static_cast<coordinate_type>(0.25) &&
+ it->vertex().y() == static_cast<coordinate_type>(2.0), true);
+
+ const voronoi_edge_type *edge1_1 = it->incident_edge();
+ const voronoi_edge_type *edge1_2 = edge1_1->twin();
+ CHECK_EQUAL_POINTS(edge1_1->cell()->point0(), point2);
+ CHECK_EQUAL_POINTS(edge1_2->cell()->point0(), point3);
+
+ const voronoi_edge_type *edge2_1 = edge1_1->rot_prev();
+ const voronoi_edge_type *edge2_2 = edge2_1->twin();
+ CHECK_EQUAL_POINTS(edge2_1->cell()->point0(), point3);
+ CHECK_EQUAL_POINTS(edge2_2->cell()->point0(), point1);
+
+ const voronoi_edge_type *edge3_1 = edge2_1->rot_prev();
+ const voronoi_edge_type *edge3_2 = edge3_1->twin();
+ CHECK_EQUAL_POINTS(edge3_1->cell()->point0(), point1);
+ CHECK_EQUAL_POINTS(edge3_2->cell()->point0(), point2);
+
+ BOOST_CHECK_EQUAL(edge1_2->twin() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->twin() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->twin() == edge3_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2, true);
+ BOOST_CHECK_EQUAL(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->rot_next() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_1->rot_next() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_1->rot_next() == edge1_1, true);
+}
+
+// Sites: (0, 1), (2, 0), (2, 4).
+BOOST_AUTO_TEST_CASE_TEMPLATE(triangle_test2, T, test_types) {
+ point_data<T> point1(0, 1);
+ point_data<T> point2(2, 0);
+ point_data<T> point3(2, 4);
+ std::vector< point_data<T> > points;
+ points.push_back(point1);
+ points.push_back(point2);
+ points.push_back(point3);
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+ CHECK_OUTPUT_SIZE(test_output, 3, 1, 3);
+
+ const_vertex_iterator it = test_output.vertices().begin();
+ BOOST_CHECK_EQUAL(it->vertex().x() == static_cast<coordinate_type>(1.75) &&
+ it->vertex().y() == static_cast<coordinate_type>(2.0), true);
+
+ const voronoi_edge_type *edge1_1 = it->incident_edge();
+ const voronoi_edge_type *edge1_2 = edge1_1->twin();
+ CHECK_EQUAL_POINTS(edge1_1->cell()->point0(), point3);
+ CHECK_EQUAL_POINTS(edge1_2->cell()->point0(), point2);
+
+ const voronoi_edge_type *edge2_1 = edge1_1->rot_prev();
+ const voronoi_edge_type *edge2_2 = edge2_1->twin();
+ CHECK_EQUAL_POINTS(edge2_1->cell()->point0(), point2);
+ CHECK_EQUAL_POINTS(edge2_2->cell()->point0(), point1);
+
+ const voronoi_edge_type *edge3_1 = edge2_1->rot_prev();
+ const voronoi_edge_type *edge3_2 = edge3_1->twin();
+ CHECK_EQUAL_POINTS(edge3_1->cell()->point0(), point1);
+ CHECK_EQUAL_POINTS(edge3_2->cell()->point0(), point3);
+
+ BOOST_CHECK_EQUAL(edge1_2->twin() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->twin() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->twin() == edge3_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2, true);
+ BOOST_CHECK_EQUAL(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->rot_next() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_1->rot_next() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_1->rot_next() == edge1_1, true);
+}
+
+// Sites: (0, 0), (0, 1), (1, 0), (1, 1).
+BOOST_AUTO_TEST_CASE_TEMPLATE(square_test1, T, test_types) {
+ point_data<T> point1(0, 0);
+ point_data<T> point2(0, 1);
+ point_data<T> point3(1, 0);
+ point_data<T> point4(1, 1);
+ std::vector< point_data<T> > points;
+ points.push_back(point1);
+ points.push_back(point2);
+ points.push_back(point3);
+ points.push_back(point4);
+ vd_type test_output;
+ construct_voronoi(points.begin(), points.end(), &test_output);
+ VERIFY_OUTPUT(test_output);
+ CHECK_OUTPUT_SIZE(test_output, 4, 1, 4);
+
+ // Check voronoi vertex.
+ const_vertex_iterator it = test_output.vertices().begin();
+ BOOST_CHECK_EQUAL(it->vertex().x() == static_cast<coordinate_type>(0.5) &&
+ it->vertex().y() == static_cast<coordinate_type>(0.5), true);
+
+ // Check voronoi edges.
+ const voronoi_edge_type *edge1_1 = it->incident_edge();
+ const voronoi_edge_type *edge1_2 = edge1_1->twin();
+ CHECK_EQUAL_POINTS(edge1_1->cell()->point0(), points[3]);
+ CHECK_EQUAL_POINTS(edge1_2->cell()->point0(), points[2]);
+
+ const voronoi_edge_type *edge2_1 = edge1_1->rot_prev();
+ const voronoi_edge_type *edge2_2 = edge2_1->twin();
+ CHECK_EQUAL_POINTS(edge2_1->cell()->point0(), points[2]);
+ CHECK_EQUAL_POINTS(edge2_2->cell()->point0(), points[0]);
+
+ const voronoi_edge_type *edge3_1 = edge2_1->rot_prev();
+ const voronoi_edge_type *edge3_2 = edge3_1->twin();
+ CHECK_EQUAL_POINTS(edge3_1->cell()->point0(), points[0]);
+ CHECK_EQUAL_POINTS(edge3_2->cell()->point0(), points[1]);
+
+ const voronoi_edge_type *edge4_1 = edge3_1->rot_prev();
+ const voronoi_edge_type *edge4_2 = edge4_1->twin();
+ CHECK_EQUAL_POINTS(edge4_1->cell()->point0(), points[1]);
+ CHECK_EQUAL_POINTS(edge4_2->cell()->point0(), points[3]);
+
+ BOOST_CHECK_EQUAL(edge1_2->twin() == edge1_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->twin() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->twin() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge4_2->twin() == edge4_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->prev() == edge4_2 && edge1_1->next() == edge4_2, true);
+ BOOST_CHECK_EQUAL(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2, true);
+ BOOST_CHECK_EQUAL(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2, true);
+ BOOST_CHECK_EQUAL(edge4_1->prev() == edge3_2 && edge4_1->next() == edge3_2, true);
+
+ BOOST_CHECK_EQUAL(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_2->next() == edge4_1 && edge3_2->prev() == edge4_1, true);
+ BOOST_CHECK_EQUAL(edge4_2->next() == edge1_1 && edge4_2->prev() == edge1_1, true);
+
+ BOOST_CHECK_EQUAL(edge1_1->rot_next() == edge4_1, true);
+ BOOST_CHECK_EQUAL(edge4_1->rot_next() == edge3_1, true);
+ BOOST_CHECK_EQUAL(edge3_1->rot_next() == edge2_1, true);
+ BOOST_CHECK_EQUAL(edge2_1->rot_next() == edge1_1, true);
+}
+
+#ifdef NDEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(grid_test, T, test_types) {
+ vd_type test_output_small, test_output_large;
+ std::vector< point_data<T> > point_vec_small, point_vec_large;
+ int grid_size[] = {10, 33, 101};
+ int max_value[] = {10, 33, 101};
+ int array_length = sizeof(grid_size) / sizeof(int);
+ for (int k = 0; k < array_length; k++) {
+ test_output_small.clear();
+ test_output_large.clear();
+ point_vec_small.clear();
+ point_vec_large.clear();
+ int koef = std::numeric_limits<int>::max() / max_value[k];
+ for (int i = 0; i < grid_size[k]; i++)
+ for (int j = 0; j < grid_size[k]; j++) {
+ point_vec_small.push_back(point_data<T>(i, j));
+ point_vec_large.push_back(point_data<T>(koef * i, koef * j));
+ }
+ construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small);
+ construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large);
+ VERIFY_OUTPUT(test_output_small);
+ VERIFY_OUTPUT(test_output_large);
+ unsigned int num_cells = grid_size[k] * grid_size[k];
+ unsigned int num_vertices = num_cells - 2 * grid_size[k] + 1;
+ unsigned int num_edges = 2 * num_cells - 2 * grid_size[k];
+ CHECK_OUTPUT_SIZE(test_output_small, num_cells, num_vertices, num_edges);
+ CHECK_OUTPUT_SIZE(test_output_large, num_cells, num_vertices, num_edges);
+ }
+}
+#endif
+
+#ifdef NDEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(random_test, T, test_types) {
+ boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
+ vd_type test_output_small, test_output_large;
+ std::vector< point_data<T> > point_vec_small, point_vec_large;
+ int num_points[] = {10, 100, 1000, 10000};
+ int num_runs[] = {1000, 100, 10, 1};
+ int mod_koef[] = {10, 100, 100, 1000};
+ int max_value[] = {5, 50, 50, 5000};
+ int array_length = sizeof(num_points) / sizeof(int);
+ for (int k = 0; k < array_length; k++) {
+ int koef = std::numeric_limits<int>::max() / max_value[k];
+ for (int i = 0; i < num_runs[k]; i++) {
+ test_output_small.clear();
+ test_output_large.clear();
+ point_vec_small.clear();
+ point_vec_large.clear();
+ for (int j = 0; j < num_points[k]; j++) {
+ T x = gen() % mod_koef[k] - mod_koef[k] / 2;
+ T y = gen() % mod_koef[k] - mod_koef[k] / 2;
+ point_vec_small.push_back(point_data<T>(x, y));
+ point_vec_large.push_back(point_data<T>(koef * x, koef * y));
+ }
+ construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small);
+ construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large);
+ VERIFY_OUTPUT(test_output_small);
+ VERIFY_OUTPUT(test_output_large);
+ BOOST_CHECK_EQUAL(test_output_small.num_cells(), test_output_large.num_cells());
+ BOOST_CHECK_EQUAL(test_output_small.num_vertices(), test_output_large.num_vertices());
+ BOOST_CHECK_EQUAL(test_output_small.num_edges(), test_output_large.num_edges());
+ }
+ }
+}
+#endif
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_sites_test1, T, test_types) {
+ vd_type test_output;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(0, 0);
+ point_data<T> point2(1, 1);
+ segments.push_back(segment_data<T>(point1, point2));
+ construct_voronoi(segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 3, 0, 2);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_sites_test2, T, test_types) {
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(0, 0);
+ point_data<T> point2(4, 4);
+ point_data<T> point3(3, 1);
+ point_data<T> point4(1, 3);
+ segments.push_back(segment_data<T>(point1, point2));
+ points.push_back(point3);
+ points.push_back(point4);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 5, 4, 8);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_sites_test3, T, test_types) {
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(4, 0);
+ point_data<T> point2(0, 4);
+ point_data<T> point3(3, 3);
+ point_data<T> point4(1, 1);
+ segments.push_back(segment_data<T>(point1, point2));
+ points.push_back(point3);
+ points.push_back(point4);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 5, 4, 8);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_sites_test4, T, test_types) {
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(4, 0);
+ point_data<T> point2(0, 4);
+ point_data<T> point3(3, 2);
+ point_data<T> point4(2, 3);
+ segments.push_back(segment_data<T>(point1, point2));
+ points.push_back(point3);
+ points.push_back(point4);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 5, 3, 7);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_site_test5, T, test_types) {
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(0, 0);
+ point_data<T> point2(0, 8);
+ point_data<T> point3(-2, -2);
+ point_data<T> point4(-2, 4);
+ point_data<T> point5(-2, 10);
+ segments.push_back(segment_data<T>(point1, point2));
+ points.push_back(point3);
+ points.push_back(point4);
+ points.push_back(point5);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 6, 4, 9);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_site_test6, T, test_types) {
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(-1, 1);
+ point_data<T> point2(1, 0);
+ point_data<T> point3(1, 2);
+ segments.push_back(segment_data<T>(point2, point3));
+ points.push_back(point1);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 4, 2, 5);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_site_test7, T, test_types) {
+ vd_type test_output;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(0, 0);
+ point_data<T> point2(4, 0);
+ point_data<T> point3(0, 4);
+ point_data<T> point4(4, 4);
+ segments.push_back(segment_data<T>(point1, point2));
+ segments.push_back(segment_data<T>(point2, point3));
+ segments.push_back(segment_data<T>(point3, point4));
+ construct_voronoi(segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 7, 6, 12);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_site_test8, T, test_types) {
+ vd_type test_output;
+ std::vector< segment_data<T> > segments;
+ point_data<T> point1(0, 0);
+ point_data<T> point2(4, 0);
+ point_data<T> point3(4, 4);
+ point_data<T> point4(0, 4);
+ segments.push_back(segment_data<T>(point1, point2));
+ segments.push_back(segment_data<T>(point2, point3));
+ segments.push_back(segment_data<T>(point3, point4));
+ segments.push_back(segment_data<T>(point4, point1));
+ construct_voronoi(segments.begin(), segments.end(), &test_output);
+ CHECK_OUTPUT_SIZE(test_output, 8, 5, 12);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+}
+
+#ifdef NDEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_grid_test, T, test_types) {
+ vd_type test_output_small, test_output_large;
+ std::vector< segment_data<T> > segments_small, segments_large;
+ int grid_size[] = {10, 27, 53};
+ int max_value[] = {100, 330, 1000};
+ int array_length = sizeof(grid_size) / sizeof(int);
+ for (int k = 0; k < array_length; k++) {
+ test_output_small.clear();
+ test_output_large.clear();
+ segments_small.clear();
+ segments_large.clear();
+ int cur_sz = grid_size[k];
+ int koef = std::numeric_limits<int>::max() / max_value[k];
+ for (int i = 0; i < cur_sz + 1; i++)
+ for (int j = 0; j < cur_sz; j++) {
+ point_data<T> point1_1(10 * i, 10 * j);
+ point_data<T> point1_2(koef * 10 * i, koef * 10 * j);
+ point_data<T> point2_1(10 * i, 10 * j + 10);
+ point_data<T> point2_2(koef * 10 * i, koef * (10 * j + 10));
+ segments_small.push_back(segment_data<T>(point1_1, point2_1));
+ segments_large.push_back(segment_data<T>(point1_2, point2_2));
+ point_data<T> point3_1(10 * j, 10 * i);
+ point_data<T> point3_2(koef * 10 * j, koef * 10 * i);
+ point_data<T> point4_1(10 * j + 10, 10 * i);
+ point_data<T> point4_2(koef * (10 * j + 10), koef * 10 * i);
+ segments_small.push_back(segment_data<T>(point3_1, point4_1));
+ segments_large.push_back(segment_data<T>(point3_2, point4_2));
+ }
+ construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small);
+ construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large);
+ BOOST_CHECK_EQUAL(test_output_small.num_cells(), test_output_large.num_cells());
+ BOOST_CHECK_EQUAL(test_output_small.num_vertices(), test_output_large.num_vertices());
+ BOOST_CHECK_EQUAL(test_output_small.num_edges(), test_output_large.num_edges());
+ }
+}
+#endif
+
+#ifdef NDEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_random_test1, T, test_types) {
+ boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
+ vd_type test_output;
+ std::vector< point_data<T> > points;
+ std::vector< segment_data<T> > segments;
+ int num_runs = 1000;
+ int num_segments = 10;
+ points.push_back(point_data<T>(-100, -100));
+ points.push_back(point_data<T>(-100, 100));
+ points.push_back(point_data<T>(100, -100));
+ points.push_back(point_data<T>(100, 100));
+ for (int i = 0; i < num_runs; i++) {
+ test_output.clear();
+ segments.clear();
+ for (int j = 0; j < num_segments; j++) {
+ T x1 = 0, y1 = 0, x2 = 0, y2 = 0;
+ while (x1 == x2 && y1 == y2) {
+ x1 = (gen() % 100) - 50;
+ y1 = (gen() % 100) - 50;
+ x2 = (gen() % 100) - 50;
+ y2 = (gen() % 100) - 50;
+ }
+ point_data<T> point1(x1, y1);
+ point_data<T> point2(x2, y2);
+ segments.push_back(segment_data<T>(point1, point2));
+ }
+ voronoi_test_helper::clean_segment_set(segments);
+ construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
+ }
+}
+#endif
+
+#ifdef NDEBUG
+BOOST_AUTO_TEST_CASE_TEMPLATE(segment_random_test2, T, test_types) {
+ boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
+ vd_type test_output_small, test_output_large;
+ std::vector< segment_data<T> > segments_small, segments_large;
+ int num_segments[] = {5, 25, 125, 625};
+ int num_runs[] = {1000, 100, 10, 1};
+ int mod_koef1[] = {10, 100, 200, 300};
+ int mod_koef2[] = {10, 20, 50, 100};
+ int max_value[] = {10, 60, 125, 200};
+ int array_length = sizeof(num_segments) / sizeof(int);
+ for (int k = 0; k < array_length; k++) {
+ int koef = std::numeric_limits<int>::max() / max_value[k];
+ for (int i = 0; i < num_runs[k]; i++) {
+ test_output_small.clear();
+ test_output_large.clear();
+ segments_small.clear();
+ segments_large.clear();
+ for (int j = 0; j < num_segments[k]; j++) {
+ T x1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2;
+ T y1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2;
+ T dx = 0, dy = 0;
+ while (dx == 0 && dy == 0) {
+ dx = (gen() % mod_koef2[k]) - mod_koef2[k] / 2;
+ dy = (gen() % mod_koef2[k]) - mod_koef2[k] / 2;
+ }
+ T x2 = x1 + dx;
+ T y2 = y1 + dy;
+ point_data<T> point1_small(x1, y1);
+ point_data<T> point2_small(x2, y2);
+ segments_small.push_back(segment_data<T>(point1_small, point2_small));
+ }
+ voronoi_test_helper::clean_segment_set(segments_small);
+ for (typename std::vector< segment_data<T> >::iterator it = segments_small.begin();
+ it != segments_small.end(); ++it) {
+ T x1 = it->low().x() * koef;
+ T y1 = it->low().y() * koef;
+ T x2 = it->high().x() * koef;
+ T y2 = it->high().y() * koef;
+ point_data<T> point1_large(x1, y1);
+ point_data<T> point2_large(x2, y2);
+ segments_large.push_back(segment_data<T>(point1_large, point2_large));
+ }
+ construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small);
+ construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small);
+ VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large);
+ BOOST_CHECK_EQUAL(test_output_small.num_cells(), test_output_large.num_cells());
+ BOOST_CHECK_EQUAL(test_output_small.num_vertices(), test_output_large.num_vertices());
+ BOOST_CHECK_EQUAL(test_output_small.num_edges(), test_output_large.num_edges());
+ }
+ }
+}
+#endif

Added: trunk/libs/polygon/test/voronoi_ctypes_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_ctypes_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,314 @@
+// Boost.Polygon library voronoi_ctypes_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ctime>
+
+#define BOOST_TEST_MODULE voronoi_ctypes_test
+#include <boost/mpl/list.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/test/test_case_template.hpp>
+
+#include <boost/polygon/detail/voronoi_ctypes.hpp>
+using namespace boost::polygon::detail;
+
+type_converter_fpt to_fpt;
+
+BOOST_AUTO_TEST_CASE(ulp_comparison_test1) {
+ ulp_comparison<double> ulp_cmp;
+ uint64 a = 22;
+ uint64 b = 27;
+ fpt64 da, db;
+ memcpy(&da, &a, sizeof(uint64));
+ memcpy(&db, &b, sizeof(uint64));
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 1), ulp_cmp.LESS);
+ BOOST_CHECK_EQUAL(ulp_cmp(db, da, 1), ulp_cmp.MORE);
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 4), ulp_cmp.LESS);
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 5), ulp_cmp.EQUAL);
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 6), ulp_cmp.EQUAL);
+}
+
+BOOST_AUTO_TEST_CASE(ulp_comparison_test2) {
+ ulp_comparison<fpt64> ulp_cmp;
+ uint64 a = 0ULL;
+ uint64 b = 0x8000000000000002ULL;
+ fpt64 da, db;
+ memcpy(&da, &a, sizeof(uint64));
+ memcpy(&db, &b, sizeof(uint64));
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 1), ulp_cmp.MORE);
+ BOOST_CHECK_EQUAL(ulp_cmp(db, da, 1), ulp_cmp.LESS);
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 2), ulp_cmp.EQUAL);
+ BOOST_CHECK_EQUAL(ulp_cmp(da, db, 3), ulp_cmp.EQUAL);
+}
+
+BOOST_AUTO_TEST_CASE(fpt_exponent_accessor_test) {
+ typedef fpt_exponent_accessor<fpt64> fpt_ea;
+ fpt64 value = 15;
+ BOOST_CHECK_EQUAL(fpt_ea::set_exponent(value, 0), 3);
+ BOOST_CHECK_EQUAL(value, 1.875);
+ value = 0.0625;
+ BOOST_CHECK_EQUAL(fpt_ea::set_exponent(value, 0), -4);
+ BOOST_CHECK_EQUAL(value, 1.0);
+ value = -1.5;
+ BOOST_CHECK_EQUAL(fpt_ea::set_exponent(value, 4), 0);
+ BOOST_CHECK_EQUAL(value, -24.0);
+ value = 0.0;
+ BOOST_CHECK_EQUAL(fpt_ea::set_exponent(value, 4), fpt_ea::kMinExponent);
+ BOOST_CHECK_EQUAL(value, 16.0);
+ value = std::pow(2.0, 2000);
+ BOOST_CHECK_EQUAL(fpt_ea::set_exponent(value, 4), fpt_ea::kMaxExponent);
+ BOOST_CHECK_EQUAL(value, 16.0);
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test1) {
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ fpt64 b = 0.0;
+ efpt64 eeb(b);
+ for (int i = 0; i < 1000; ++i) {
+ fpt64 a = to_fpt(static_cast<int64>(gen()));
+ efpt64 eea(a);
+ efpt64 neg = -eea;
+ efpt64 sum = eea + eeb;
+ efpt64 dif = eea - eeb;
+ efpt64 mul = eea * eeb;
+ BOOST_CHECK_EQUAL(to_fpt(neg), -a);
+ BOOST_CHECK_EQUAL(to_fpt(sum), a + b);
+ BOOST_CHECK_EQUAL(to_fpt(dif), a - b);
+ BOOST_CHECK_EQUAL(to_fpt(mul), a * b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test2) {
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ fpt64 a = 0.0;
+ efpt64 eea(a);
+ for (int i = 0; i < 1000; ++i) {
+ fpt64 b = to_fpt(static_cast<int64>(gen()));
+ if (b == 0.0)
+ continue;
+ efpt64 eeb(b);
+ efpt64 neg = -eea;
+ efpt64 sum = eea + eeb;
+ efpt64 dif = eea - eeb;
+ efpt64 mul = eea * eeb;
+ efpt64 div = eea / eeb;
+ BOOST_CHECK_EQUAL(to_fpt(neg), -a);
+ BOOST_CHECK_EQUAL(to_fpt(sum), a + b);
+ BOOST_CHECK_EQUAL(to_fpt(dif), a - b);
+ BOOST_CHECK_EQUAL(to_fpt(mul), a * b);
+ BOOST_CHECK_EQUAL(to_fpt(div), a / b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test3) {
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ for (int i = 0; i < 1000; ++i) {
+ fpt64 a = to_fpt(static_cast<int64>(gen()));
+ fpt64 b = to_fpt(static_cast<int64>(gen()));
+ if (b == 0.0)
+ continue;
+ efpt64 eea(a);
+ efpt64 eeb(b);
+ efpt64 neg = -eea;
+ efpt64 sum = eea + eeb;
+ efpt64 dif = eea - eeb;
+ efpt64 mul = eea * eeb;
+ efpt64 div = eea / eeb;
+ BOOST_CHECK_EQUAL(to_fpt(neg), -a);
+ BOOST_CHECK_EQUAL(to_fpt(sum), a + b);
+ BOOST_CHECK_EQUAL(to_fpt(dif), a - b);
+ BOOST_CHECK_EQUAL(to_fpt(mul), a * b);
+ BOOST_CHECK_EQUAL(to_fpt(div), a / b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test4) {
+ for (int exp = 0; exp < 64; ++exp)
+ for (int i = 1; i < 100; ++i) {
+ fpt64 a = i;
+ fpt64 b = to_fpt(1LL << exp);
+ efpt64 eea(a);
+ efpt64 eeb(b);
+ efpt64 neg = -eea;
+ efpt64 sum = eea + eeb;
+ efpt64 dif = eea - eeb;
+ efpt64 mul = eea * eeb;
+ efpt64 div = eea / eeb;
+ BOOST_CHECK_EQUAL(to_fpt(neg), -a);
+ BOOST_CHECK_EQUAL(to_fpt(sum), a + b);
+ BOOST_CHECK_EQUAL(to_fpt(dif), a - b);
+ BOOST_CHECK_EQUAL(to_fpt(mul), a * b);
+ BOOST_CHECK_EQUAL(to_fpt(div), a / b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test5) {
+ for (int i = 0; i < 100; ++i) {
+ efpt64 a(to_fpt(i * i));
+ efpt64 b = a.sqrt();
+ BOOST_CHECK_EQUAL(to_fpt(b), to_fpt(i));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_exponent_fpt_test6) {
+ for (int i = -10; i <= 10; ++i) {
+ efpt64 a(to_fpt(i));
+ BOOST_CHECK_EQUAL(is_pos(a), i > 0);
+ BOOST_CHECK_EQUAL(is_neg(a), i < 0);
+ BOOST_CHECK_EQUAL(is_zero(a), !i);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test1) {
+ typedef extended_int<1> eint32;
+ eint32 e1(0), e2(32), e3(-32);
+ BOOST_CHECK_EQUAL(e1.count(), 0);
+ BOOST_CHECK_EQUAL(e1.size(), 0U);
+ BOOST_CHECK_EQUAL(e2.count(), 1);
+ BOOST_CHECK_EQUAL(e2.chunks()[0], 32U);
+ BOOST_CHECK_EQUAL(e2.size(), 1U);
+ BOOST_CHECK_EQUAL(e3.count(), -1);
+ BOOST_CHECK_EQUAL(e3.chunks()[0], 32U);
+ BOOST_CHECK_EQUAL(e3.size(), 1U);
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test2) {
+ typedef extended_int<2> eint64;
+ int64 val64 = 0x7fffffffffffffffLL;
+ eint64 e1(0), e2(32), e3(-32), e4(val64), e5(-val64);
+ BOOST_CHECK_EQUAL(e1.count(), 0);
+ BOOST_CHECK_EQUAL(e2.count(), 1);
+ BOOST_CHECK_EQUAL(e2.chunks()[0], 32U);
+ BOOST_CHECK_EQUAL(e3.count(), -1);
+ BOOST_CHECK_EQUAL(e3.chunks()[0], 32U);
+ BOOST_CHECK_EQUAL(e4.count(), 2);
+ BOOST_CHECK_EQUAL(e4.chunks()[0], 0xffffffff);
+ BOOST_CHECK_EQUAL(e4.chunks()[1], val64 >> 32);
+ BOOST_CHECK_EQUAL(e5.count(), -2);
+ BOOST_CHECK_EQUAL(e5.chunks()[0], 0xffffffff);
+ BOOST_CHECK_EQUAL(e5.chunks()[1], val64 >> 32);
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test3) {
+ typedef extended_int<2> eint64;
+ std::vector<uint32> chunks;
+ chunks.push_back(1);
+ chunks.push_back(2);
+ eint64 e1(chunks, true), e2(chunks, false);
+ BOOST_CHECK_EQUAL(e1.count(), 2);
+ BOOST_CHECK_EQUAL(e1.chunks()[0], 2U);
+ BOOST_CHECK_EQUAL(e1.chunks()[1], 1U);
+ BOOST_CHECK_EQUAL(e2.count(), -2);
+ BOOST_CHECK_EQUAL(e2.chunks()[0], 2U);
+ BOOST_CHECK_EQUAL(e2.chunks()[1], 1U);
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test4) {
+ typedef extended_int<2> eint64;
+ std::vector<uint32> chunks;
+ chunks.push_back(1);
+ chunks.push_back(2);
+ eint64 e1(chunks, true), e2(chunks, false);
+ BOOST_CHECK_EQUAL(e1 == e2, false);
+ BOOST_CHECK_EQUAL(e1 == -e2, true);
+ BOOST_CHECK_EQUAL(e1 != e2, true);
+ BOOST_CHECK_EQUAL(e1 != -e2, false);
+ BOOST_CHECK_EQUAL(e1 < e2, false);
+ BOOST_CHECK_EQUAL(e1 < -e2, false);
+ BOOST_CHECK_EQUAL(e1 <= e2, false);
+ BOOST_CHECK_EQUAL(e1 <= -e2, true);
+ BOOST_CHECK_EQUAL(e1 > e2, true);
+ BOOST_CHECK_EQUAL(e1 > -e2, false);
+ BOOST_CHECK_EQUAL(e1 >= e2, true);
+ BOOST_CHECK_EQUAL(e1 >= -e2, true);
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test5) {
+ typedef extended_int<2> eint64;
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ for (int i = 0; i < 1000; ++i) {
+ int64 i1 = static_cast<int64>(gen());
+ int64 i2 = static_cast<int64>(gen());
+ eint64 e1(i1), e2(i2);
+ BOOST_CHECK_EQUAL(e1 == e2, i1 == i2);
+ BOOST_CHECK_EQUAL(e1 != e2, i1 != i2);
+ BOOST_CHECK_EQUAL(e1 > e2, i1 > i2);
+ BOOST_CHECK_EQUAL(e1 >= e2, i1 >= i2);
+ BOOST_CHECK_EQUAL(e1 < e2, i1 < i2);
+ BOOST_CHECK_EQUAL(e1 <= e2, i1 <= i2);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test6) {
+ typedef extended_int<1> eint32;
+ eint32 e1(32);
+ eint32 e2 = -e1;
+ BOOST_CHECK_EQUAL(e2.count(), -1);
+ BOOST_CHECK_EQUAL(e2.size(), 1U);
+ BOOST_CHECK_EQUAL(e2.chunks()[0], 32U);
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test7) {
+ typedef extended_int<2> eint64;
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ for (int i = 0; i < 1000; ++i) {
+ int64 i1 = static_cast<int64>(gen()) >> 2;
+ int64 i2 = static_cast<int64>(gen()) >> 2;
+ eint64 e1(i1), e2(i2), e3(i1 + i2), e4(i1 - i2);
+ BOOST_CHECK(e1 + e2 == e3);
+ BOOST_CHECK(e1 - e2 == e4);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test8) {
+ typedef extended_int<2> eint64;
+ boost::mt19937 gen(static_cast<uint32>(time(NULL)));
+ for (int i = 0; i < 1000; ++i) {
+ int64 i1 = static_cast<int32>(gen());
+ int64 i2 = static_cast<int32>(gen());
+ eint64 e1(i1), e2(i2), e3(i1 * i2);
+ BOOST_CHECK(e1 * e2 == e3);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(exnteded_int_test9) {
+ typedef extended_int<1> eint32;
+ for (int i = -10; i <= 10; ++i) {
+ for (int j = -10; j <= 10; ++j) {
+ eint32 e1(i), e2(j), e3(i+j), e4(i-j), e5(i*j);
+ BOOST_CHECK(e1 + e2 == e3);
+ BOOST_CHECK(e1 - e2 == e4);
+ BOOST_CHECK(e1 * e2 == e5);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extended_int_test10) {
+ typedef extended_int<2> eint64;
+ boost::mt19937_64 gen(static_cast<uint32>(time(NULL)));
+ for (int i = 0; i < 100; ++i) {
+ int64 i1 = static_cast<int64>(gen()) >> 20;
+ int64 i2 = i1 >> 32;
+ eint64 e1(i1), e2(i2);
+ BOOST_CHECK(to_fpt(e1) == static_cast<fpt64>(i1));
+ BOOST_CHECK(to_fpt(e2) == static_cast<fpt64>(i2));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(extened_int_test11) {
+ typedef extended_int<1> eint32;
+ typedef extended_int<64> eint2048;
+ eint32 two(2), one(1);
+ eint2048 value(1);
+ for (int i = 0; i < 1024; ++i)
+ value = value * two;
+ BOOST_CHECK_EQUAL(value.count(), 33);
+ for (size_t i = 1; i < value.size(); ++i)
+ BOOST_CHECK_EQUAL(value.chunks()[i-1], 0U);
+ BOOST_CHECK_EQUAL(value.chunks()[32], 1U);
+}

Added: trunk/libs/polygon/test/voronoi_predicates_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_predicates_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,459 @@
+// Boost.Polygon library voronoi_predicates_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <map>
+
+#define BOOST_TEST_MODULE voronoi_predicates_test
+#include <boost/test/test_case_template.hpp>
+
+#include <boost/polygon/detail/voronoi_ctypes.hpp>
+#include <boost/polygon/detail/voronoi_predicates.hpp>
+#include <boost/polygon/detail/voronoi_structures.hpp>
+using namespace boost::polygon::detail;
+
+ulp_comparison<double> ulp_cmp;
+
+typedef voronoi_predicates< voronoi_ctype_traits<int> > VP;
+typedef point_2d<int> point_type;
+typedef site_event<int> site_type;
+typedef circle_event<double> circle_type;
+VP::event_comparison_predicate<site_type, circle_type> event_comparison;
+
+typedef beach_line_node_key<site_type> key_type;
+typedef VP::distance_predicate<site_type> distance_predicate_type;
+typedef VP::node_comparison_predicate<key_type> node_comparison_type;
+typedef std::map<key_type, int, node_comparison_type> beach_line_type;
+typedef beach_line_type::iterator bieach_line_iterator;
+distance_predicate_type distance_predicate;
+node_comparison_type node_comparison;
+
+typedef VP::circle_existence_predicate<site_type> CEP_type;
+typedef VP::mp_circle_formation_functor<site_type, circle_type> MP_CFF_type;
+typedef VP::lazy_circle_formation_functor<site_type, circle_type> lazy_CFF_type;
+VP::circle_formation_predicate<site_type, circle_type, CEP_type, MP_CFF_type> mp_predicate;
+VP::circle_formation_predicate<site_type, circle_type, CEP_type, lazy_CFF_type> lazy_predicate;
+
+#define CHECK_ORIENTATION(P1, P2, P3, R1, R2) \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P1, P2, P3) == R1, true); \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P1, P3, P2) == R2, true); \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P2, P1, P3) == R2, true); \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P2, P3, P1) == R1, true); \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P3, P1, P2) == R1, true); \
+ BOOST_CHECK_EQUAL(VP::ot::eval(P3, P2, P1) == R2, true)
+
+#define CHECK_EVENT_COMPARISON(A, B, R1, R2) \
+ BOOST_CHECK_EQUAL(event_comparison(A, B), R1); \
+ BOOST_CHECK_EQUAL(event_comparison(B, A), R2)
+
+#define CHECK_DISTANCE_PREDICATE(S1, S2, S3, RES) \
+ BOOST_CHECK_EQUAL(distance_predicate(S1, S2, S3), RES)
+
+#define CHECK_NODE_COMPARISON(node, nodes, res, sz) \
+ for (int i = 0; i < sz; ++i) { \
+ BOOST_CHECK_EQUAL(node_comparison(node, nodes[i]), res[i]); \
+ BOOST_CHECK_EQUAL(node_comparison(nodes[i], node), !res[i]); \
+ }
+
+#define CHECK_CIRCLE(circle, c_x, c_y, l_x) \
+ BOOST_CHECK_EQUAL(ulp_cmp(c1.x(), c_x, 10), ulp_comparison<double>::EQUAL); \
+ BOOST_CHECK_EQUAL(ulp_cmp(c1.y(), c_y, 10), ulp_comparison<double>::EQUAL); \
+ BOOST_CHECK_EQUAL(ulp_cmp(c1.lower_x(), l_x, 10), ulp_comparison<double>::EQUAL)
+
+#define CHECK_CIRCLE_EXISTENCE(s1, s2, s3, RES) \
+ { circle_type c1; \
+ BOOST_CHECK_EQUAL(lazy_predicate(s1, s2, s3, c1), RES); }
+
+#define CHECK_CIRCLE_FORMATION_PREDICATE(s1, s2, s3, c_x, c_y, l_x) \
+ { circle_type c1, c2; \
+ BOOST_CHECK_EQUAL(mp_predicate(s1, s2, s3, c1), true); \
+ BOOST_CHECK_EQUAL(lazy_predicate(s1, s2, s3, c2), true); \
+ CHECK_CIRCLE(c1, c_x, c_y, l_x); \
+ CHECK_CIRCLE(c2, c_x, c_y, l_x); }
+
+BOOST_AUTO_TEST_CASE(orientation_test) {
+ int min_int = std::numeric_limits<int>::min();
+ int max_int = std::numeric_limits<int>::max();
+ point_type point1(min_int, min_int);
+ point_type point2(0, 0);
+ point_type point3(max_int, max_int);
+ point_type point4(min_int, max_int);
+ point_type point5(max_int-1, max_int);
+ CHECK_ORIENTATION(point1, point2, point3, VP::ot::COLLINEAR, VP::ot::COLLINEAR);
+ CHECK_ORIENTATION(point1, point4, point3, VP::ot::RIGHT, VP::ot::LEFT);
+ CHECK_ORIENTATION(point1, point5, point3, VP::ot::RIGHT, VP::ot::LEFT);
+}
+
+BOOST_AUTO_TEST_CASE(event_comparison_test1) {
+ site_type site(1, 2);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 2), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(1, 3), true, false);
+ CHECK_EVENT_COMPARISON(site, site_type(1, 2), false, false);
+}
+
+BOOST_AUTO_TEST_CASE(event_comparison_test2) {
+ site_type site(0, 0, 0, 2);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 2), true, false);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 0), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, -2, 0, -1), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, -2, 1, 1), true, false);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 0, 1, 1), true, false);
+}
+
+BOOST_AUTO_TEST_CASE(event_comparison_test3) {
+ site_type site(0, 0, 10, 10);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 0), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, -1), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 1), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 1, 0, 10), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, -10, 0, -1), false, true);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 0, 10, 9), true, false);
+ CHECK_EVENT_COMPARISON(site, site_type(0, 0, 9, 10), false, true);
+}
+
+BOOST_AUTO_TEST_CASE(event_comparison_test4) {
+ circle_type circle(1, 2, 3);
+ CHECK_EVENT_COMPARISON(circle, circle_type(1, 2, 3), false, false);
+ CHECK_EVENT_COMPARISON(circle, circle_type(1, 3, 3), true, false);
+ CHECK_EVENT_COMPARISON(circle, circle_type(1, 2, 4), true, false);
+ CHECK_EVENT_COMPARISON(circle, circle_type(0, 2, 2), false, true);
+ CHECK_EVENT_COMPARISON(circle, circle_type(-1, 2, 3), false, false);
+}
+
+BOOST_AUTO_TEST_CASE(event_comparison_test5) {
+ circle_type circle(1, 2, 3);
+ CHECK_EVENT_COMPARISON(circle, site_type(0, 100), false, true);
+ CHECK_EVENT_COMPARISON(circle, site_type(3, 0), false, true);
+ CHECK_EVENT_COMPARISON(circle, site_type(3, 2), false, false);
+ CHECK_EVENT_COMPARISON(circle, site_type(3, 3), true, false);
+ CHECK_EVENT_COMPARISON(circle, site_type(4, 2), true, false);
+}
+
+BOOST_AUTO_TEST_CASE(distance_predicate_test1) {
+ site_type site1(-5, 0);
+ site_type site2(-8, 9);
+ site_type site3(-2, 1);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 5), false);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, 5), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 4), false);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, 4), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 6), true);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, 6), true);
+}
+
+BOOST_AUTO_TEST_CASE(distance_predicate_test2) {
+ site_type site1(-4, 0, -4, 20);
+ site_type site2(-2, 10);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 11), false);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 9), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 11), true);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 9), true);
+}
+
+BOOST_AUTO_TEST_CASE(disntace_predicate_test3) {
+ site_type site1(-5, 5, 2, -2);
+ site1.inverse();
+ site_type site2(-2, 4);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, -1), false);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, -1), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 1), false);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 1), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 4), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 4), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 5), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 5), false);
+}
+
+BOOST_AUTO_TEST_CASE(distance_predicate_test4) {
+ site_type site1(-5, 5, 2, -2);
+ site_type site2(-2, -4);
+ site_type site3(-4, 1);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, 1), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, 1), true);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site_type(0, 1), true);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, 1), true);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, -2), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, -2), false);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site_type(0, -2), true);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, -2), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, -8), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, -8), false);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site_type(0, -8), true);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, -8), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(0, -9), true);
+ CHECK_DISTANCE_PREDICATE(site2, site1, site_type(0, -9), false);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site_type(0, -9), true);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site_type(0, -9), false);
+}
+
+BOOST_AUTO_TEST_CASE(disntace_predicate_test5) {
+ site_type site1(-5, 5, 2, -2);
+ site_type site2 = site1;
+ site2.inverse();
+ site_type site3(-2, 4);
+ site_type site4(-2, -4);
+ site_type site5(-4, 1);
+ CHECK_DISTANCE_PREDICATE(site3, site2, site_type(0, 1), false);
+ CHECK_DISTANCE_PREDICATE(site3, site2, site_type(0, 4), false);
+ CHECK_DISTANCE_PREDICATE(site3, site2, site_type(0, 5), false);
+ CHECK_DISTANCE_PREDICATE(site3, site2, site_type(0, 7), true);
+ CHECK_DISTANCE_PREDICATE(site4, site1, site_type(0, -2), false);
+ CHECK_DISTANCE_PREDICATE(site5, site1, site_type(0, -2), false);
+ CHECK_DISTANCE_PREDICATE(site4, site1, site_type(0, -8), false);
+ CHECK_DISTANCE_PREDICATE(site5, site1, site_type(0, -8), false);
+ CHECK_DISTANCE_PREDICATE(site4, site1, site_type(0, -9), false);
+ CHECK_DISTANCE_PREDICATE(site5, site1, site_type(0, -9), false);
+ CHECK_DISTANCE_PREDICATE(site4, site1, site_type(0, -18), false);
+ CHECK_DISTANCE_PREDICATE(site5, site1, site_type(0, -18), false);
+ CHECK_DISTANCE_PREDICATE(site4, site1, site_type(0, -1), true);
+ CHECK_DISTANCE_PREDICATE(site5, site1, site_type(0, -1), true);
+}
+
+BOOST_AUTO_TEST_CASE(distance_predicate_test6) {
+ site_type site1(-5, 0, 2, 7);
+ site_type site2 = site1;
+ site2.inverse();
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(2, 7), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(1, 5), false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(-1, 5), true);
+}
+
+BOOST_AUTO_TEST_CASE(distance_predicate_test7) {
+ site_type site1(-5, 5, 2, -2);
+ site1.inverse();
+ site_type site2(-5, 5, 0, 6);
+ site_type site3(-2, 4, 0, 4);
+ site_type site4(0, 2);
+ site_type site5(0, 5);
+ site_type site6(0, 6);
+ site_type site7(0, 8);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site4, false);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site5, true);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site6, true);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site7, true);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site4, false);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site5, true);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site6, true);
+ CHECK_DISTANCE_PREDICATE(site1, site3, site7, true);
+ site3.inverse();
+ CHECK_DISTANCE_PREDICATE(site3, site1, site4, false);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site5, false);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site6, false);
+ CHECK_DISTANCE_PREDICATE(site3, site1, site7, true);
+}
+
+BOOST_AUTO_TEST_CASE(distatnce_predicate_test8) {
+ site_type site1(-5, 3, -2, 2);
+ site1.inverse();
+ site_type site2(-5, 5, -2, 2);
+ CHECK_DISTANCE_PREDICATE(site1, site2, site_type(-4, 2), false);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test1) {
+ beach_line_type beach_line;
+ site_type site1(0, 0);
+ site1.index(0);
+ site_type site2(0, 2);
+ site2.index(1);
+ site_type site3(1, 0);
+ site3.index(2);
+ beach_line[key_type(site1, site2)] = 2;
+ beach_line[key_type(site1, site3)] = 0;
+ beach_line[key_type(site3, site1)] = 1;
+ int cur_index = 0;
+ for (bieach_line_iterator it = beach_line.begin();
+ it != beach_line.end(); ++it, ++cur_index) {
+ BOOST_CHECK_EQUAL(it->second, cur_index);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test2) {
+ beach_line_type beach_line;
+ site_type site1(0, 1);
+ site1.index(0);
+ site_type site2(2, 0);
+ site2.index(1);
+ site_type site3(2, 4);
+ site3.index(2);
+ beach_line[key_type(site1, site2)] = 0;
+ beach_line[key_type(site2, site1)] = 1;
+ beach_line[key_type(site1, site3)] = 2;
+ beach_line[key_type(site3, site1)] = 3;
+ int cur_index = 0;
+ for (bieach_line_iterator it = beach_line.begin();
+ it != beach_line.end(); ++it, ++cur_index) {
+ BOOST_CHECK_EQUAL(it->second, cur_index);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test3) {
+ key_type node(site_type(1, 0).index(1), site_type(0, 2).index(0));
+ key_type nodes[] = {
+ key_type(site_type(2, -10).index(2)),
+ key_type(site_type(2, -1).index(2)),
+ key_type(site_type(2, 0).index(2)),
+ key_type(site_type(2, 1).index(2)),
+ key_type(site_type(2, 2).index(2)),
+ key_type(site_type(2, 3).index(2)),
+ };
+ bool res[] = {false, false, false, false, true, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 6);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test4) {
+ key_type node(site_type(0, 1).index(0), site_type(1, 0).index(1));
+ key_type nodes[] = {
+ key_type(site_type(2, -3).index(2)),
+ key_type(site_type(2, -2).index(2)),
+ key_type(site_type(2, -1).index(2)),
+ key_type(site_type(2, 0).index(2)),
+ key_type(site_type(2, 1).index(2)),
+ key_type(site_type(2, 3).index(2)),
+ };
+ bool res[] = {false, true, true, true, true, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 6);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test5) {
+ key_type node(site_type(0, 0).index(0), site_type(1, 2).index(1));
+ key_type nodes[] = {
+ key_type(site_type(2, -10).index(2)),
+ key_type(site_type(2, 0).index(2)),
+ key_type(site_type(2, 1).index(2)),
+ key_type(site_type(2, 2).index(2)),
+ key_type(site_type(2, 5).index(2)),
+ key_type(site_type(2, 20).index(2)),
+ };
+ bool res[] = {false, false, true, true, true, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 6);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test6) {
+ key_type node(site_type(1, 1).index(1), site_type(0, 0).index(0));
+ key_type nodes [] = {
+ key_type(site_type(2, -3).index(2)),
+ key_type(site_type(2, -2).index(2)),
+ key_type(site_type(2, 0).index(2)),
+ key_type(site_type(2, 1).index(2)),
+ key_type(site_type(2, 2).index(2)),
+ key_type(site_type(2, 3).index(2)),
+ key_type(site_type(2, 5).index(2)),
+ };
+ bool res[] = {false, false, false, false, false, false, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 7);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test7) {
+ key_type node(site_type(0, 0).index(0), site_type(0, 2).index(1));
+ key_type nodes[] = {
+ key_type(site_type(1, 0).index(2)),
+ key_type(site_type(1, 1).index(2)),
+ key_type(site_type(1, 2).index(2)),
+ };
+ bool res[] = {false, false, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 3);
+}
+
+BOOST_AUTO_TEST_CASE(node_comparison_test8) {
+ key_type node(site_type(0, 0).index(0), site_type(1, 1).index(2));
+ key_type nodes[] = {
+ key_type(site_type(1, 0).index(1)),
+ key_type(site_type(1, 1).index(2)),
+ key_type(site_type(1, 2).index(3)),
+ key_type(site_type(1, 1).index(2), site_type(0, 0).index(0)),
+ };
+ bool res[] = {false, true, true, true};
+ CHECK_NODE_COMPARISON(node, nodes, res, 4);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test1) {
+ site_type site1(0, 0);
+ site_type site2(-8, 0);
+ site_type site3(0, 6);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, -4.0, 3.0, 1.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test2) {
+ int min_int = std::numeric_limits<int>::min();
+ int max_int = std::numeric_limits<int>::max();
+ site_type site1(min_int, min_int);
+ site_type site2(min_int, max_int);
+ site_type site3(max_int-1, max_int-1);
+ site_type site4(max_int, max_int);
+ CHECK_CIRCLE_EXISTENCE(site1, site2, site4, true);
+ CHECK_CIRCLE_EXISTENCE(site1, site3, site4, false);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test3) {
+ site_type site1(-4, 0);
+ site_type site2(0, 4);
+ site_type site3(site1.point0(), site2.point0());
+ CHECK_CIRCLE_EXISTENCE(site1, site3, site2, false);
+ site_type site4(-2, 0);
+ site_type site5(0, 2);
+ CHECK_CIRCLE_EXISTENCE(site3, site4, site5, false);
+ CHECK_CIRCLE_EXISTENCE(site4, site5, site3, false);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test4) {
+ site_type site1(-4, 0, -4, 20);
+ site_type site2(-2, 10);
+ site_type site3(4, 10);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 1.0, 6.0, 6.0);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 14.0, 6.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test5) {
+ site_type site1(1, 0, 7, 0);
+ site1.inverse();
+ site_type site2(-2, 4, 10, 4);
+ site_type site3(6, 2);
+ site_type site4(1, 0);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site3, site1, site2, 4.0, 2.0, 6.0);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site4, site2, site1, 1.0, 2.0, 3.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test6) {
+ site_type site1(-1, 2, 8, -10);
+ site1.inverse();
+ site_type site2(-1, 0, 8, 12);
+ site_type site3(1, 1);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 6.0, 1.0, 11.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test7) {
+ site_type site1(1, 0, 6, 0);
+ site1.inverse();
+ site_type site2(-6, 4, 0, 12);
+ site_type site3(1, 0);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 5.0, 6.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test8) {
+ site_type site1(1, 0, 5, 0);
+ site1.inverse();
+ site_type site2(0, 12, 8, 6);
+ site_type site3(1, 0);
+ CHECK_CIRCLE_FORMATION_PREDICATE(site3, site2, site1, 1.0, 5.0, 6.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test9) {
+ site_type site1(0, 0, 4, 0);
+ site_type site2(0, 0, 0, 4);
+ site_type site3(0, 4, 4, 4);
+ site1.inverse();
+ CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 2.0, 2.0, 4.0);
+}
+
+BOOST_AUTO_TEST_CASE(circle_formation_predicate_test10) {
+ site_type site1(1, 0, 41, 30);
+ site_type site2(-39, 30, 1, 60);
+ site_type site3(1, 60, 41, 30);
+ site1.inverse();
+ CHECK_CIRCLE_FORMATION_PREDICATE(site1, site2, site3, 1.0, 30.0, 25.0);
+}

Added: trunk/libs/polygon/test/voronoi_robust_fpt_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_robust_fpt_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,342 @@
+// Boost.Polygon library voronoi_robust_fpt_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cmath>
+#include <ctime>
+
+#define BOOST_TEST_MODULE voronoi_robust_fpt_test
+#include <boost/mpl/list.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/test/test_case_template.hpp>
+
+#include <boost/polygon/detail/voronoi_ctypes.hpp>
+#include <boost/polygon/detail/voronoi_robust_fpt.hpp>
+using namespace boost::polygon::detail;
+
+typedef robust_fpt<double> rfpt_type;
+typedef type_converter_fpt to_fpt_type;
+typedef type_converter_efpt to_efpt_type;
+type_converter_fpt to_fpt;
+
+BOOST_AUTO_TEST_CASE(robust_fpt_constructors_test1) {
+ rfpt_type a = rfpt_type();
+ BOOST_CHECK_EQUAL(a.fpv(), 0.0);
+ BOOST_CHECK_EQUAL(a.re(), 0.0);
+ BOOST_CHECK_EQUAL(a.ulp(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_constructors_test2) {
+ rfpt_type a(10.0, 1.0);
+ BOOST_CHECK_EQUAL(a.fpv(), 10.0);
+ BOOST_CHECK_EQUAL(a.re(), 1.0);
+ BOOST_CHECK_EQUAL(a.ulp(), 1.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_constructors_test3) {
+ rfpt_type a(10.0);
+ BOOST_CHECK_EQUAL(a.fpv(), 10.0);
+ BOOST_CHECK_EQUAL(a.re(), 0.0);
+ BOOST_CHECK_EQUAL(a.ulp(), 0.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_constructors_test4) {
+ rfpt_type a(10.0, 3.0);
+ BOOST_CHECK_EQUAL(a.fpv(), 10.0);
+ BOOST_CHECK_EQUAL(a.re(), 3.0);
+ BOOST_CHECK_EQUAL(a.ulp(), 3.0);
+
+ rfpt_type b(10.0, 2.75);
+ BOOST_CHECK_EQUAL(b.fpv(), 10.0);
+ BOOST_CHECK_EQUAL(b.re(), 2.75);
+ BOOST_CHECK_EQUAL(b.ulp(), 2.75);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_sum_test1) {
+ rfpt_type a(2.0, 5.0);
+ rfpt_type b(3.0, 4.0);
+ rfpt_type c = a + b;
+ BOOST_CHECK_EQUAL(c.fpv(), 5.0);
+ BOOST_CHECK_EQUAL(c.re(), 6.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 6.0);
+
+ c += b;
+ BOOST_CHECK_EQUAL(c.fpv(), 8.0);
+ BOOST_CHECK_EQUAL(c.re(), 7.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 7.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_sum_test2) {
+ rfpt_type a(3.0, 2.0);
+ rfpt_type b(-2.0, 3.0);
+ rfpt_type c = a + b;
+ BOOST_CHECK_EQUAL(c.fpv(), 1.0);
+ BOOST_CHECK_EQUAL(c.re(), 13.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 13.0);
+
+ c += b;
+ BOOST_CHECK_EQUAL(c.fpv(), -1.0);
+ BOOST_CHECK_EQUAL(c.re(), 20.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 20.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_dif_test1) {
+ rfpt_type a(2.0, 5.0);
+ rfpt_type b(-3.0, 4.0);
+ rfpt_type c = a - b;
+ BOOST_CHECK_EQUAL(c.fpv(), 5.0);
+ BOOST_CHECK_EQUAL(c.re(), 6.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 6.0);
+
+ c -= b;
+ BOOST_CHECK_EQUAL(c.fpv(), 8.0);
+ BOOST_CHECK_EQUAL(c.re(), 7.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 7.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_dif_test2) {
+ rfpt_type a(3.0, 2.0);
+ rfpt_type b(2.0, 3.0);
+ rfpt_type c = a - b;
+ BOOST_CHECK_EQUAL(c.fpv(), 1.0);
+ BOOST_CHECK_EQUAL(c.re(), 13.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 13.0);
+
+ c -= b;
+ BOOST_CHECK_EQUAL(c.fpv(), -1.0);
+ BOOST_CHECK_EQUAL(c.re(), 20.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 20.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_mult_test3) {
+ rfpt_type a(2.0, 3.0);
+ rfpt_type b(4.0, 1.0);
+ rfpt_type c = a * b;
+ BOOST_CHECK_EQUAL(c.fpv(), 8.0);
+ BOOST_CHECK_EQUAL(c.re(), 5.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 5.0);
+
+ c *= b;
+ BOOST_CHECK_EQUAL(c.fpv(), 32.0);
+ BOOST_CHECK_EQUAL(c.re(), 7.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 7.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_fpt_div_test1) {
+ rfpt_type a(2.0, 3.0);
+ rfpt_type b(4.0, 1.0);
+ rfpt_type c = a / b;
+ BOOST_CHECK_EQUAL(c.fpv(), 0.5);
+ BOOST_CHECK_EQUAL(c.re(), 5.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 5.0);
+
+ c /= b;
+ BOOST_CHECK_EQUAL(c.fpv(), 0.125);
+ BOOST_CHECK_EQUAL(c.re(), 7.0);
+ BOOST_CHECK_EQUAL(c.ulp(), 7.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_dif_constructors_test) {
+ robust_dif<int> rd1;
+ BOOST_CHECK_EQUAL(rd1.pos(), 0);
+ BOOST_CHECK_EQUAL(rd1.neg(), 0);
+ BOOST_CHECK_EQUAL(rd1.dif(), 0);
+
+ robust_dif<int> rd2(1);
+ BOOST_CHECK_EQUAL(rd2.pos(), 1);
+ BOOST_CHECK_EQUAL(rd2.neg(), 0);
+ BOOST_CHECK_EQUAL(rd2.dif(), 1);
+
+ robust_dif<int> rd3(-1);
+ BOOST_CHECK_EQUAL(rd3.pos(), 0);
+ BOOST_CHECK_EQUAL(rd3.neg(), 1);
+ BOOST_CHECK_EQUAL(rd3.dif(), -1);
+
+ robust_dif<int> rd4(1, 2);
+ BOOST_CHECK_EQUAL(rd4.pos(), 1);
+ BOOST_CHECK_EQUAL(rd4.neg(), 2);
+ BOOST_CHECK_EQUAL(rd4.dif(), -1);
+}
+
+BOOST_AUTO_TEST_CASE(robust_dif_operators_test1) {
+ robust_dif<int> a(5, 2), b(1, 10);
+ int dif_a = a.dif();
+ int dif_b = b.dif();
+ robust_dif<int> sum = a + b;
+ robust_dif<int> dif = a - b;
+ robust_dif<int> mult = a * b;
+ robust_dif<int> umin = -a;
+ BOOST_CHECK_EQUAL(sum.dif(), dif_a + dif_b);
+ BOOST_CHECK_EQUAL(dif.dif(), dif_a - dif_b);
+ BOOST_CHECK_EQUAL(mult.dif(), dif_a * dif_b);
+ BOOST_CHECK_EQUAL(umin.dif(), -dif_a);
+}
+
+BOOST_AUTO_TEST_CASE(robust_dif_operators_test2) {
+ robust_dif<int> a(5, 2);
+ for (int b = -3; b <= 3; b += 6) {
+ int dif_a = a.dif();
+ int dif_b = b;
+ robust_dif<int> sum = a + b;
+ robust_dif<int> dif = a - b;
+ robust_dif<int> mult = a * b;
+ robust_dif<int> div = a / b;
+ BOOST_CHECK_EQUAL(sum.dif(), dif_a + dif_b);
+ BOOST_CHECK_EQUAL(dif.dif(), dif_a - dif_b);
+ BOOST_CHECK_EQUAL(mult.dif(), dif_a * dif_b);
+ BOOST_CHECK_EQUAL(div.dif(), dif_a / dif_b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(robust_dif_operators_test3) {
+ robust_dif<int> b(5, 2);
+ for (int a = -3; a <= 3; a += 6) {
+ int dif_a = a;
+ int dif_b = b.dif();
+ robust_dif<int> sum = a + b;
+ robust_dif<int> dif = a - b;
+ robust_dif<int> mult = a * b;
+ BOOST_CHECK_EQUAL(sum.dif(), dif_a + dif_b);
+ BOOST_CHECK_EQUAL(dif.dif(), dif_a - dif_b);
+ BOOST_CHECK_EQUAL(mult.dif(), dif_a * dif_b);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(robust_dif_operators_test4) {
+ std::vector< robust_dif<int> > a4(4, robust_dif<int>(5, 2));
+ std::vector< robust_dif<int> > b4(4, robust_dif<int>(1, 2));
+ std::vector< robust_dif<int> > c4 = a4;
+ c4[0] += b4[0];
+ c4[1] -= b4[1];
+ c4[2] *= b4[2];
+ BOOST_CHECK_EQUAL(c4[0].dif(), a4[0].dif() + b4[0].dif());
+ BOOST_CHECK_EQUAL(c4[1].dif(), a4[1].dif() - b4[1].dif());
+ BOOST_CHECK_EQUAL(c4[2].dif(), a4[2].dif() * b4[2].dif());
+ a4[0] += b4[0].dif();
+ a4[1] -= b4[1].dif();
+ a4[2] *= b4[2].dif();
+ a4[3] /= b4[3].dif();
+ BOOST_CHECK_EQUAL(c4[0].dif(), a4[0].dif());
+ BOOST_CHECK_EQUAL(c4[1].dif(), a4[1].dif());
+ BOOST_CHECK_EQUAL(c4[2].dif(), a4[2].dif());
+ BOOST_CHECK_EQUAL(c4[3].dif() / b4[3].dif(), a4[3].dif());
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test1) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[1] = {10};
+ int32 B[1] = {100};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval1(A, B), 100.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test2) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[2] = {10, 30};
+ int32 B[2] = {400, 100};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval2(A, B), 500.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test3) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[2] = {10, -30};
+ int32 B[2] = {400, 100};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval2(A, B), -100.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test4) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[3] = {10, 30, 20};
+ int32 B[3] = {4, 1, 9};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval3(A, B), 110.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test5) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[3] = {10, 30, -20};
+ int32 B[3] = {4, 1, 9};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval3(A, B), -10.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test6) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[4] = {10, 30, 20, 5};
+ int32 B[4] = {4, 1, 9, 16};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval4(A, B), 130.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test7) {
+ robust_sqrt_expr<int32, fpt64, to_fpt_type> sqrt_expr;
+ int32 A[4] = {10, 30, -20, -5};
+ int32 B[4] = {4, 1, 9, 16};
+ BOOST_CHECK_EQUAL(sqrt_expr.eval4(A, B), -30.0);
+}
+
+BOOST_AUTO_TEST_CASE(robust_sqrt_expr_test8) {
+ typedef extended_int<16> eint512;
+ robust_sqrt_expr<eint512, efpt64, to_efpt_type> sqrt_expr;
+ int32 A[4] = {1000, 3000, -2000, -500};
+ int32 B[4] = {400, 100, 900, 1600};
+ eint512 AA[4], BB[4];
+ for (size_t i = 0; i < 4; ++i) {
+ AA[i] = A[i];
+ BB[i] = B[i];
+ }
+ BOOST_CHECK_EQUAL(to_fpt(sqrt_expr.eval4(AA, BB)), -30000.0);
+}
+
+template <typename _int, typename _fpt>
+class sqrt_expr_tester {
+public:
+ static const size_t MX_SQRTS = 4;
+
+ bool run() {
+ static boost::mt19937 gen(static_cast<uint32>(time(NULL)));
+ bool ret_val = true;
+ for (size_t i = 0; i < MX_SQRTS; ++i) {
+ a[i] = gen() & 1048575;
+ int64 temp = gen() & 1048575;
+ b[i] = temp * temp;
+ }
+ uint32 mask = (1 << MX_SQRTS);
+ for (size_t i = 0; i < mask; i++) {
+ fpt64 expected_val = 0.0;
+ for (size_t j = 0; j < MX_SQRTS; j++) {
+ if (i & (1 << j)) {
+ A[j] = a[j];
+ B[j] = b[j];
+ expected_val += static_cast<fpt64>(a[j]) *
+ sqrt(static_cast<fpt64>(b[j]));
+ } else {
+ A[j] = -a[j];
+ B[j] = b[j];
+ expected_val -= static_cast<fpt64>(a[j]) *
+ sqrt(static_cast<fpt64>(b[j]));
+ }
+ }
+ fpt64 received_val = to_fpt(sqrt_expr_.eval4(A, B));
+ ret_val &= ulp_cmp(expected_val, received_val, 25) ==
+ ulp_comparison<fpt64>::EQUAL;
+ }
+ return ret_val;
+ }
+
+private:
+ robust_sqrt_expr<_int, _fpt, to_efpt_type> sqrt_expr_;
+ ulp_comparison<fpt64> ulp_cmp;
+ _int A[MX_SQRTS];
+ _int B[MX_SQRTS];
+ int64 a[MX_SQRTS];
+ int64 b[MX_SQRTS];
+};
+
+BOOST_AUTO_TEST_CASE(mpz_sqrt_evaluator_test) {
+ typedef extended_int<16> eint512;
+ sqrt_expr_tester<eint512, efpt64> tester;
+ for (int i = 0; i < 2000; ++i)
+ BOOST_CHECK(tester.run());
+}

Added: trunk/libs/polygon/test/voronoi_structures_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_structures_test.cpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,133 @@
+// Boost.Polygon library voronoi_structures_test.cpp file
+
+// Copyright Andrii Sydorchuk 2010-2012.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#define BOOST_TEST_MODULE voronoi_structures_test
+
+#include <boost/test/test_case_template.hpp>
+#include <boost/polygon/detail/voronoi_structures.hpp>
+using namespace boost::polygon::detail;
+
+typedef point_2d<int> point_type;
+typedef site_event<int> site_type;
+typedef circle_event<int> circle_type;
+typedef ordered_queue<int, std::greater<int> > ordered_queue_type;
+typedef beach_line_node_key<int> node_key_type;
+typedef beach_line_node_data<int, int> node_data_type;
+
+BOOST_AUTO_TEST_CASE(point_2d_test1) {
+ point_type p(1, 2);
+ BOOST_CHECK_EQUAL(p.x(), 1);
+ BOOST_CHECK_EQUAL(p.y(), 2);
+ p.x(3);
+ BOOST_CHECK_EQUAL(p.x(), 3);
+ p.y(4);
+ BOOST_CHECK_EQUAL(p.y(), 4);
+}
+
+BOOST_AUTO_TEST_CASE(site_event_test2) {
+ site_type s(1, 2);
+ BOOST_CHECK(s.x0() == s.x1() && s.x1() == 1);
+ BOOST_CHECK(s.y0() == s.y1() && s.y1() == 2);
+ BOOST_CHECK(s.index() == 0);
+ BOOST_CHECK(!s.is_segment());
+ BOOST_CHECK(!s.is_inverse());
+ s.index(1);
+ BOOST_CHECK(s.index() == 1);
+ BOOST_CHECK(!s.is_inverse());
+}
+
+BOOST_AUTO_TEST_CASE(site_event_test3) {
+ site_type s(1, 2, 3, 4);
+ BOOST_CHECK(s.x0(true) == 1 && s.x0() == 1);
+ BOOST_CHECK(s.y0(true) == 2 && s.y0() == 2);
+ BOOST_CHECK(s.x1(true) == 3 && s.x1() == 3);
+ BOOST_CHECK(s.y1(true) == 4 && s.y1() == 4);
+ BOOST_CHECK(s.index() == 0);
+ BOOST_CHECK(s.is_segment());
+ BOOST_CHECK(!s.is_inverse());
+ s.inverse();
+ BOOST_CHECK(s.x1(true) == 1 && s.x0() == 1);
+ BOOST_CHECK(s.y1(true) == 2 && s.y0() == 2);
+ BOOST_CHECK(s.x0(true) == 3 && s.x1() == 3);
+ BOOST_CHECK(s.y0(true) == 4 && s.y1() == 4);
+ BOOST_CHECK(s.is_inverse());
+}
+
+BOOST_AUTO_TEST_CASE(site_event_test4) {
+ site_type s(1, 2, 3, 4);
+ s.index(27);
+ BOOST_CHECK(s.is_initial());
+ BOOST_CHECK(s.has_initial_direction());
+ BOOST_CHECK(s.index() == 27);
+ s.inverse();
+ BOOST_CHECK(!s.has_initial_direction());
+ BOOST_CHECK(s.is_initial());
+ BOOST_CHECK(s.index() == 27);
+ s.change_initial_direction();
+ BOOST_CHECK(s.has_initial_direction());
+ BOOST_CHECK(!s.is_initial());
+ BOOST_CHECK(s.index() == 27);
+}
+
+BOOST_AUTO_TEST_CASE(circle_event_test) {
+ circle_type c(0, 1, 2);
+ BOOST_CHECK_EQUAL(c.x(), 0);
+ BOOST_CHECK_EQUAL(c.y(), 1);
+ BOOST_CHECK_EQUAL(c.lower_x(), 2);
+ BOOST_CHECK_EQUAL(c.lower_y(), 1);
+ BOOST_CHECK(c.is_active());
+ c.x(3);
+ c.y(4);
+ c.lower_x(5);
+ BOOST_CHECK_EQUAL(c.x(), 3);
+ BOOST_CHECK_EQUAL(c.y(), 4);
+ BOOST_CHECK_EQUAL(c.lower_x(), 5);
+ BOOST_CHECK_EQUAL(c.lower_y(), 4);
+ c.deactivate();
+ BOOST_CHECK(!c.is_active());
+}
+
+BOOST_AUTO_TEST_CASE(ordered_queue_test) {
+ ordered_queue_type q;
+ BOOST_CHECK(q.empty());
+ std::vector<int*> vi;
+ for (int i = 0; i < 20; ++i)
+ vi.push_back(&q.push(i));
+ for (int i = 0; i < 20; ++i)
+ *vi[i] <<= 1;
+ BOOST_CHECK(!q.empty());
+ for (int i = 0; i < 20; ++i, q.pop())
+ BOOST_CHECK_EQUAL(q.top(), i << 1);
+ BOOST_CHECK(q.empty());
+}
+
+BOOST_AUTO_TEST_CASE(beach_line_node_key_test) {
+ node_key_type key(1);
+ BOOST_CHECK_EQUAL(key.left_site(), 1);
+ BOOST_CHECK_EQUAL(key.right_site(), 1);
+ key.left_site(2);
+ BOOST_CHECK_EQUAL(key.left_site(), 2);
+ BOOST_CHECK_EQUAL(key.right_site(), 1);
+ key.right_site(3);
+ BOOST_CHECK_EQUAL(key.left_site(), 2);
+ BOOST_CHECK_EQUAL(key.right_site(), 3);
+}
+
+BOOST_AUTO_TEST_CASE(beach_line_node_data_test) {
+ node_data_type node_data(NULL);
+ BOOST_CHECK_EQUAL(node_data.edge() == NULL, true);
+ BOOST_CHECK_EQUAL(node_data.circle_event() == NULL, true);
+ int data = 4;
+ node_data.circle_event(&data);
+ BOOST_CHECK_EQUAL(node_data.edge() == NULL, true);
+ BOOST_CHECK_EQUAL(node_data.circle_event() == &data, true);
+ node_data.edge(&data);
+ BOOST_CHECK_EQUAL(node_data.edge() == &data, true);
+ BOOST_CHECK_EQUAL(node_data.circle_event() == &data, true);
+}

Added: trunk/libs/polygon/test/voronoi_test_helper.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/polygon/test/voronoi_test_helper.hpp 2012-05-05 10:29:08 EDT (Sat, 05 May 2012)
@@ -0,0 +1,272 @@
+// Boost.Polygon library voronoi_test_helper.hpp file
+
+// Copyright Andrii Sydorchuk 2010-2011.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef VORONOI_TEST_HELPER
+#define VORONOI_TEST_HELPER
+
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <map>
+#include <vector>
+
+#include <boost/polygon/polygon.hpp>
+using namespace boost::polygon;
+
+namespace voronoi_test_helper {
+
+enum kOrientation {
+ RIGHT = -1,
+ COLLINEAR = 0,
+ LEFT = 1
+};
+
+template <typename Point2D>
+kOrientation get_orientation(const Point2D &point1,
+ const Point2D &point2,
+ const Point2D &point3) {
+ typename Point2D::coordinate_type a = (point2.x() - point1.x()) * (point3.y() - point2.y());
+ typename Point2D::coordinate_type b = (point2.y() - point1.y()) * (point3.x() - point2.x());
+ if (a == b)
+ return COLLINEAR;
+ return (a < b) ? RIGHT : LEFT;
+}
+
+template <typename Output>
+bool verify_half_edge_orientation(const Output &output) {
+ typedef typename Output::point_type point_type;
+ typename Output::const_edge_iterator edge_it;
+ for (edge_it = output.edges().begin();
+ edge_it != output.edges().end(); edge_it++) {
+ if (edge_it->is_finite()) {
+ const point_type &site_point = edge_it->cell()->point0();
+ const point_type &start_point = edge_it->vertex0()->vertex();
+ const point_type &end_point = edge_it->vertex1()->vertex();
+ if (get_orientation(start_point, end_point, site_point) != LEFT)
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename Output>
+bool verify_cell_convexity(const Output &output) {
+ typedef typename Output::point_type point_type;
+ typename Output::const_cell_iterator cell_it;
+ for (cell_it = output.cells().begin();
+ cell_it != output.cells().end(); cell_it++) {
+ const typename Output::edge_type *edge = cell_it->incident_edge();
+ if (edge)
+ do {
+ if (edge->next()->prev() != edge)
+ return false;
+ if (edge->cell() != &(*cell_it))
+ return false;
+ if (edge->vertex0() != NULL &&
+ edge->vertex1() != NULL &&
+ edge->vertex1() == edge->next()->vertex0() &&
+ edge->next()->vertex1() != NULL) {
+ const point_type &vertex1 = edge->vertex0()->vertex();
+ const point_type &vertex2 = edge->vertex1()->vertex();
+ const point_type &vertex3 = edge->next()->vertex1()->vertex();
+ if (get_orientation(vertex1, vertex2, vertex3) != LEFT)
+ return false;
+ }
+ edge = edge->next();
+ } while(edge != cell_it->incident_edge());
+ }
+ return true;
+}
+
+template <typename Output>
+bool verify_incident_edges_ccw_order(const Output &output) {
+ typedef typename Output::point_type point_type;
+ typedef typename Output::edge_type voronoi_edge_type;
+ typename Output::const_vertex_iterator vertex_it;
+ for (vertex_it = output.vertices().begin();
+ vertex_it != output.vertices().end(); vertex_it++) {
+ if (vertex_it->is_degenerate())
+ continue;
+ const voronoi_edge_type *edge = vertex_it->incident_edge();
+ do {
+ const voronoi_edge_type *edge_next1 = edge->rot_next();
+ const voronoi_edge_type *edge_next2 = edge_next1->rot_next();
+ const point_type &site1 = edge->cell()->point0();
+ const point_type &site2 = edge_next1->cell()->point0();
+ const point_type &site3 = edge_next2->cell()->point0();
+
+ if (get_orientation(site1, site2, site3) != LEFT)
+ return false;
+
+ edge = edge->rot_next();
+ } while (edge != vertex_it->incident_edge());
+ }
+ return true;
+}
+
+template <typename P>
+struct cmp {
+ bool operator()(const P& p1, const P& p2) const {
+ if (p1.x() != p2.x())
+ return p1.x() < p2.x();
+ return p1.y() < p2.y();
+ }
+};
+
+template <typename Output>
+bool verfiy_no_line_edge_intersections(const Output &output) {
+ // Create map from edges with first point less than the second one.
+ // Key is the first point of the edge, value is a vector of second points
+ // with the same first point.
+ typedef typename Output::point_type point_type;
+ cmp<point_type> comparator;
+ std::map< point_type, std::vector<point_type>, cmp<point_type> > edge_map;
+ typename Output::const_edge_iterator edge_it;
+ for (edge_it = output.edges().begin();
+ edge_it != output.edges().end(); edge_it++) {
+ if (edge_it->is_finite()) {
+ const point_type &vertex0 = edge_it->vertex0()->vertex();
+ const point_type &vertex1 = edge_it->vertex1()->vertex();
+ if (comparator(vertex0, vertex1))
+ edge_map[vertex0].push_back(vertex1);
+ }
+ }
+ return !intersection_check(edge_map);
+}
+
+template <typename Point2D>
+bool intersection_check(const std::map< Point2D, std::vector<Point2D>, cmp<Point2D> > &edge_map) {
+ // Iterate over map of edges and check if there are any intersections.
+ // All the edges are stored by the low x value. That's why we iterate
+ // left to right checking for intersections between all pairs of edges
+ // that overlap in the x dimension.
+ // Complexity. Approximately N*sqrt(N). Worst case N^2.
+ typedef Point2D point_type;
+ typedef typename point_type::coordinate_type coordinate_type;
+ typedef typename std::map< point_type, std::vector<point_type>, cmp<Point2D> >::const_iterator
+ edge_map_iterator;
+ typedef typename std::vector<point_type>::size_type size_type;
+ edge_map_iterator edge_map_it1, edge_map_it2, edge_map_it_bound;
+ for (edge_map_it1 = edge_map.begin();
+ edge_map_it1 != edge_map.end(); edge_map_it1++) {
+ const point_type &point1 = edge_map_it1->first;
+ for (size_type i = 0; i < edge_map_it1->second.size(); i++) {
+ const point_type &point2 = edge_map_it1->second[i];
+ coordinate_type min_y1 = std::min(point1.y(), point2.y());
+ coordinate_type max_y1 = std::max(point1.y(), point2.y());
+
+ // Find the first edge with greater or equal first point.
+ edge_map_it_bound = edge_map.lower_bound(point2);
+
+ edge_map_it2 = edge_map_it1;
+ edge_map_it2++;
+ for (; edge_map_it2 != edge_map_it_bound; edge_map_it2++) {
+ const point_type &point3 = edge_map_it2->first;
+ for (size_type j = 0; j < edge_map_it2->second.size(); j++) {
+ const point_type &point4 = edge_map_it2->second[j];
+ coordinate_type min_y2 = std::min(point3.y(), point4.y());
+ coordinate_type max_y2 = std::max(point3.y(), point4.y());
+
+ // In most cases it is enought to make
+ // simple intersection check in the y dimension.
+ if (!(max_y1 > min_y2 && max_y2 > min_y1))
+ continue;
+
+ // Intersection check.
+ if (get_orientation(point1, point2, point3) *
+ get_orientation(point1, point2, point4) == RIGHT &&
+ get_orientation(point3, point4, point1) *
+ get_orientation(point3, point4, point2) == RIGHT)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+enum kVerification {
+ HALF_EDGE_ORIENTATION = 1,
+ CELL_CONVEXITY = 2,
+ INCIDENT_EDGES_CCW_ORDER = 4,
+ NO_HALF_EDGE_INTERSECTIONS = 8,
+ FAST_VERIFICATION = 7,
+ COMPLETE_VERIFICATION = 15
+};
+
+template <typename Output>
+bool verify_output(const Output &output, kVerification mask) {
+ bool result = true;
+ if (mask & HALF_EDGE_ORIENTATION)
+ result &= verify_half_edge_orientation(output);
+ if (mask & CELL_CONVEXITY)
+ result &= verify_cell_convexity(output);
+ if (mask & INCIDENT_EDGES_CCW_ORDER)
+ result &= verify_incident_edges_ccw_order(output);
+ if (mask & NO_HALF_EDGE_INTERSECTIONS)
+ result &= verfiy_no_line_edge_intersections(output);
+ return result;
+}
+
+template <typename PointIterator>
+void save_points(PointIterator first, PointIterator last, const char *file_name) {
+ std::ofstream ofs(file_name);
+ ofs << std::distance(first, last) << std::endl;
+ for (PointIterator it = first; it != last; ++it) {
+ ofs << it->x() << " " << it->y() << std::endl;
+ }
+ ofs.close();
+}
+
+template <typename SegmentIterator>
+void save_segments(SegmentIterator first, SegmentIterator last, const char *file_name) {
+ std::ofstream ofs(file_name);
+ ofs << std::distance(first, last) << std::endl;
+ for (SegmentIterator it = first; it != last; ++it) {
+ ofs << it->low().x() << " " << it->low().y() << " ";
+ ofs << it->high().x() << " " << it->high().y() << std::endl;
+ }
+ ofs.close();
+}
+
+template <typename T>
+void clean_segment_set(std::vector< segment_data<T> > &data) {
+ typedef T Unit;
+ typedef typename scanline_base<Unit>::Point Point;
+ typedef typename scanline_base<Unit>::half_edge half_edge;
+ typedef int segment_id;
+ std::vector<std::pair<half_edge, segment_id> > half_edges;
+ std::vector<std::pair<half_edge, segment_id> > half_edges_out;
+ segment_id id = 0;
+ half_edges.reserve(data.size());
+ for (typename std::vector< segment_data<T> >::iterator it = data.begin(); it != data.end(); ++it) {
+ Point l = it->low();
+ Point h = it->high();
+ half_edges.push_back(std::make_pair(half_edge(l, h), id++));
+ }
+ half_edges_out.reserve(half_edges.size());
+ //apparently no need to pre-sort data when calling validate_scan
+ line_intersection<Unit>::validate_scan(half_edges_out, half_edges.begin(), half_edges.end());
+ std::vector< segment_data<T> > result;
+ result.reserve(half_edges_out.size());
+ for (std::size_t i = 0; i < half_edges_out.size(); ++i) {
+ id = half_edges_out[i].second;
+ Point l = half_edges_out[i].first.first;
+ Point h = half_edges_out[i].first.second;
+ segment_data<T> orig_seg = data[id];
+ if (orig_seg.high() < orig_seg.low())
+ std::swap(l, h);
+ result.push_back(segment_data<T>(l, h));
+ }
+ std::swap(result, data);
+}
+
+} // voronoi_test_helper
+
+#endif


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