Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:04:55

0001 // Boost.Polygon library detail/voronoi_predicates.hpp header file
0002 
0003 //          Copyright Andrii Sydorchuk 2010-2012.
0004 // Distributed under the Boost Software License, Version 1.0.
0005 //    (See accompanying file LICENSE_1_0.txt or copy at
0006 //          http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 // See http://www.boost.org for updates, documentation, and revision history.
0009 
0010 #ifndef BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
0011 #define BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
0012 
0013 #include <utility>
0014 
0015 #include "voronoi_robust_fpt.hpp"
0016 
0017 namespace boost {
0018 namespace polygon {
0019 namespace detail {
0020 
0021 // Predicate utilities. Operates with the coordinate types that could
0022 // be converted to the 32-bit signed integer without precision loss.
0023 template <typename CTYPE_TRAITS>
0024 class voronoi_predicates {
0025  public:
0026   typedef typename CTYPE_TRAITS::int_type int_type;
0027   typedef typename CTYPE_TRAITS::int_x2_type int_x2_type;
0028   typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type;
0029   typedef typename CTYPE_TRAITS::big_int_type big_int_type;
0030   typedef typename CTYPE_TRAITS::fpt_type fpt_type;
0031   typedef typename CTYPE_TRAITS::efpt_type efpt_type;
0032   typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type;
0033   typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter;
0034   typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter;
0035 
0036   enum {
0037     ULPS = 64,
0038     ULPSx2 = 128
0039   };
0040 
0041   template <typename Point>
0042   static bool is_vertical(const Point& point1, const Point& point2) {
0043     return point1.x() == point2.x();
0044   }
0045 
0046   template <typename Site>
0047   static bool is_vertical(const Site& site) {
0048     return is_vertical(site.point0(), site.point1());
0049   }
0050 
0051   // Compute robust cross_product: a1 * b2 - b1 * a2.
0052   // It was mathematically proven that the result is correct
0053   // with epsilon relative error equal to 1EPS.
0054   static fpt_type robust_cross_product(int_x2_type a1_,
0055                                        int_x2_type b1_,
0056                                        int_x2_type a2_,
0057                                        int_x2_type b2_) {
0058     static to_fpt_converter to_fpt;
0059     uint_x2_type a1 = static_cast<uint_x2_type>(is_neg(a1_) ? -a1_ : a1_);
0060     uint_x2_type b1 = static_cast<uint_x2_type>(is_neg(b1_) ? -b1_ : b1_);
0061     uint_x2_type a2 = static_cast<uint_x2_type>(is_neg(a2_) ? -a2_ : a2_);
0062     uint_x2_type b2 = static_cast<uint_x2_type>(is_neg(b2_) ? -b2_ : b2_);
0063 
0064     uint_x2_type l = a1 * b2;
0065     uint_x2_type r = b1 * a2;
0066 
0067     if (is_neg(a1_) ^ is_neg(b2_)) {
0068       if (is_neg(a2_) ^ is_neg(b1_))
0069         return (l > r) ? -to_fpt(l - r) : to_fpt(r - l);
0070       else
0071         return -to_fpt(l + r);
0072     } else {
0073       if (is_neg(a2_) ^ is_neg(b1_))
0074         return to_fpt(l + r);
0075       else
0076         return (l < r) ? -to_fpt(r - l) : to_fpt(l - r);
0077     }
0078   }
0079 
0080   struct orientation_test {
0081    public:
0082     // Represents orientation test result.
0083     enum Orientation {
0084       RIGHT = -1,
0085       COLLINEAR = 0,
0086       LEFT = 1
0087     };
0088 
0089     // Value is a determinant of two vectors (e.g. x1 * y2 - x2 * y1).
0090     // Return orientation based on the sign of the determinant.
0091     template <typename T>
0092     static Orientation eval(T value) {
0093       if (is_zero(value)) return COLLINEAR;
0094       return (is_neg(value)) ? RIGHT : LEFT;
0095     }
0096 
0097     static Orientation eval(int_x2_type dif_x1_,
0098                             int_x2_type dif_y1_,
0099                             int_x2_type dif_x2_,
0100                             int_x2_type dif_y2_) {
0101       return eval(robust_cross_product(dif_x1_, dif_y1_, dif_x2_, dif_y2_));
0102     }
0103 
0104     template <typename Point>
0105     static Orientation eval(const Point& point1,
0106                             const Point& point2,
0107                             const Point& point3) {
0108       int_x2_type dx1 = static_cast<int_x2_type>(point1.x()) -
0109                         static_cast<int_x2_type>(point2.x());
0110       int_x2_type dx2 = static_cast<int_x2_type>(point2.x()) -
0111                         static_cast<int_x2_type>(point3.x());
0112       int_x2_type dy1 = static_cast<int_x2_type>(point1.y()) -
0113                         static_cast<int_x2_type>(point2.y());
0114       int_x2_type dy2 = static_cast<int_x2_type>(point2.y()) -
0115                         static_cast<int_x2_type>(point3.y());
0116       return eval(robust_cross_product(dx1, dy1, dx2, dy2));
0117     }
0118   };
0119   typedef orientation_test ot;
0120 
0121   template <typename Point>
0122   class point_comparison_predicate {
0123    public:
0124     typedef Point point_type;
0125 
0126     bool operator()(const point_type& lhs, const point_type& rhs) const {
0127       if (lhs.x() == rhs.x())
0128         return lhs.y() < rhs.y();
0129       return lhs.x() < rhs.x();
0130     }
0131   };
0132 
0133   template <typename Site, typename Circle>
0134   class event_comparison_predicate {
0135    public:
0136     typedef Site site_type;
0137     typedef Circle circle_type;
0138 
0139     bool operator()(const site_type& lhs, const site_type& rhs) const {
0140       if (lhs.x0() != rhs.x0())
0141         return lhs.x0() < rhs.x0();
0142       if (!lhs.is_segment()) {
0143         if (!rhs.is_segment())
0144           return lhs.y0() < rhs.y0();
0145         if (is_vertical(rhs))
0146           return lhs.y0() <= rhs.y0();
0147         return true;
0148       } else {
0149         if (is_vertical(rhs)) {
0150           if (is_vertical(lhs))
0151             return lhs.y0() < rhs.y0();
0152           return false;
0153         }
0154         if (is_vertical(lhs))
0155           return true;
0156         if (lhs.y0() != rhs.y0())
0157           return lhs.y0() < rhs.y0();
0158         return ot::eval(lhs.point1(), lhs.point0(), rhs.point1()) == ot::LEFT;
0159       }
0160     }
0161 
0162     bool operator()(const site_type& lhs, const circle_type& rhs) const {
0163       typename ulp_cmp_type::Result xCmp =
0164           ulp_cmp(to_fpt(lhs.x0()), to_fpt(rhs.lower_x()), ULPS);
0165       return xCmp == ulp_cmp_type::LESS;
0166     }
0167 
0168     bool operator()(const circle_type& lhs, const site_type& rhs) const {
0169       typename ulp_cmp_type::Result xCmp =
0170           ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.x0()), ULPS);
0171       return xCmp == ulp_cmp_type::LESS;
0172     }
0173 
0174     bool operator()(const circle_type& lhs, const circle_type& rhs) const {
0175       if (lhs.lower_x() != rhs.lower_x()) {
0176         return lhs.lower_x() < rhs.lower_x();
0177       }
0178       return lhs.y() < rhs.y();
0179     }
0180 
0181    private:
0182     ulp_cmp_type ulp_cmp;
0183     to_fpt_converter to_fpt;
0184   };
0185 
0186   template <typename Site>
0187   class distance_predicate {
0188    public:
0189     typedef Site site_type;
0190     typedef typename site_type::point_type point_type;
0191 
0192     // Returns true if a horizontal line going through a new site intersects
0193     // right arc at first, else returns false. If horizontal line goes
0194     // through intersection point of the given two arcs returns false also.
0195     bool operator()(const site_type& left_site,
0196                     const site_type& right_site,
0197                     const point_type& new_point) const {
0198       if (!left_site.is_segment()) {
0199         if (!right_site.is_segment()) {
0200           return pp(left_site, right_site, new_point);
0201         } else {
0202           return ps(left_site, right_site, new_point, false);
0203         }
0204       } else {
0205         if (!right_site.is_segment()) {
0206           return ps(right_site, left_site, new_point, true);
0207         } else {
0208           return ss(left_site, right_site, new_point);
0209         }
0210       }
0211     }
0212 
0213    private:
0214     // Represents the result of the epsilon robust predicate. If the
0215     // result is undefined some further processing is usually required.
0216     enum kPredicateResult {
0217       LESS = -1,
0218       UNDEFINED = 0,
0219       MORE = 1
0220     };
0221 
0222     // Robust predicate, avoids using high-precision libraries.
0223     // Returns true if a horizontal line going through the new point site
0224     // intersects right arc at first, else returns false. If horizontal line
0225     // goes through intersection point of the given two arcs returns false.
0226     bool pp(const site_type& left_site,
0227             const site_type& right_site,
0228             const point_type& new_point) const {
0229       const point_type& left_point = left_site.point0();
0230       const point_type& right_point = right_site.point0();
0231       if (left_point.x() > right_point.x()) {
0232         if (new_point.y() <= left_point.y())
0233           return false;
0234       } else if (left_point.x() < right_point.x()) {
0235         if (new_point.y() >= right_point.y())
0236           return true;
0237       } else {
0238         return static_cast<int_x2_type>(left_point.y()) +
0239                static_cast<int_x2_type>(right_point.y()) <
0240                static_cast<int_x2_type>(new_point.y()) * 2;
0241       }
0242 
0243       fpt_type dist1 = find_distance_to_point_arc(left_site, new_point);
0244       fpt_type dist2 = find_distance_to_point_arc(right_site, new_point);
0245 
0246       // The undefined ulp range is equal to 3EPS + 3EPS <= 6ULP.
0247       return dist1 < dist2;
0248     }
0249 
0250     bool ps(const site_type& left_site, const site_type& right_site,
0251             const point_type& new_point, bool reverse_order) const {
0252       kPredicateResult fast_res = fast_ps(
0253         left_site, right_site, new_point, reverse_order);
0254       if (fast_res != UNDEFINED) {
0255         return fast_res == LESS;
0256       }
0257 
0258       fpt_type dist1 = find_distance_to_point_arc(left_site, new_point);
0259       fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point);
0260 
0261       // The undefined ulp range is equal to 3EPS + 7EPS <= 10ULP.
0262       return reverse_order ^ (dist1 < dist2);
0263     }
0264 
0265     bool ss(const site_type& left_site,
0266             const site_type& right_site,
0267             const point_type& new_point) const {
0268       // Handle temporary segment sites.
0269       if (left_site.sorted_index() == right_site.sorted_index()) {
0270         return ot::eval(
0271             left_site.point0(), left_site.point1(), new_point) == ot::LEFT;
0272       }
0273 
0274       fpt_type dist1 = find_distance_to_segment_arc(left_site, new_point);
0275       fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point);
0276 
0277       // The undefined ulp range is equal to 7EPS + 7EPS <= 14ULP.
0278       return dist1 < dist2;
0279     }
0280 
0281     fpt_type find_distance_to_point_arc(
0282         const site_type& site, const point_type& point) const {
0283       fpt_type dx = to_fpt(site.x()) - to_fpt(point.x());
0284       fpt_type dy = to_fpt(site.y()) - to_fpt(point.y());
0285       // The relative error is at most 3EPS.
0286       return (dx * dx + dy * dy) / (to_fpt(2.0) * dx);
0287     }
0288 
0289     fpt_type find_distance_to_segment_arc(
0290         const site_type& site, const point_type& point) const {
0291       if (is_vertical(site)) {
0292         return (to_fpt(site.x()) - to_fpt(point.x())) * to_fpt(0.5);
0293       } else {
0294         const point_type& segment0 = site.point0();
0295         const point_type& segment1 = site.point1();
0296         fpt_type a1 = to_fpt(segment1.x()) - to_fpt(segment0.x());
0297         fpt_type b1 = to_fpt(segment1.y()) - to_fpt(segment0.y());
0298         fpt_type k = get_sqrt(a1 * a1 + b1 * b1);
0299         // Avoid subtraction while computing k.
0300         if (!is_neg(b1)) {
0301           k = to_fpt(1.0) / (b1 + k);
0302         } else {
0303           k = (k - b1) / (a1 * a1);
0304         }
0305         // The relative error is at most 7EPS.
0306         return k * robust_cross_product(
0307             static_cast<int_x2_type>(segment1.x()) -
0308             static_cast<int_x2_type>(segment0.x()),
0309             static_cast<int_x2_type>(segment1.y()) -
0310             static_cast<int_x2_type>(segment0.y()),
0311             static_cast<int_x2_type>(point.x()) -
0312             static_cast<int_x2_type>(segment0.x()),
0313             static_cast<int_x2_type>(point.y()) -
0314             static_cast<int_x2_type>(segment0.y()));
0315       }
0316     }
0317 
0318     kPredicateResult fast_ps(
0319         const site_type& left_site, const site_type& right_site,
0320         const point_type& new_point, bool reverse_order) const {
0321       const point_type& site_point = left_site.point0();
0322       const point_type& segment_start = right_site.point0();
0323       const point_type& segment_end = right_site.point1();
0324 
0325       if (ot::eval(segment_start, segment_end, new_point) != ot::RIGHT)
0326         return (!right_site.is_inverse()) ? LESS : MORE;
0327 
0328       fpt_type dif_x = to_fpt(new_point.x()) - to_fpt(site_point.x());
0329       fpt_type dif_y = to_fpt(new_point.y()) - to_fpt(site_point.y());
0330       fpt_type a = to_fpt(segment_end.x()) - to_fpt(segment_start.x());
0331       fpt_type b = to_fpt(segment_end.y()) - to_fpt(segment_start.y());
0332 
0333       if (is_vertical(right_site)) {
0334         if (new_point.y() < site_point.y() && !reverse_order)
0335           return MORE;
0336         else if (new_point.y() > site_point.y() && reverse_order)
0337           return LESS;
0338         return UNDEFINED;
0339       } else {
0340         typename ot::Orientation orientation = ot::eval(
0341             static_cast<int_x2_type>(segment_end.x()) -
0342             static_cast<int_x2_type>(segment_start.x()),
0343             static_cast<int_x2_type>(segment_end.y()) -
0344             static_cast<int_x2_type>(segment_start.y()),
0345             static_cast<int_x2_type>(new_point.x()) -
0346             static_cast<int_x2_type>(site_point.x()),
0347             static_cast<int_x2_type>(new_point.y()) -
0348             static_cast<int_x2_type>(site_point.y()));
0349         if (orientation == ot::LEFT) {
0350           if (!right_site.is_inverse())
0351             return reverse_order ? LESS : UNDEFINED;
0352           return reverse_order ? UNDEFINED : MORE;
0353         }
0354       }
0355 
0356       fpt_type fast_left_expr = a * (dif_y + dif_x) * (dif_y - dif_x);
0357       fpt_type fast_right_expr = (to_fpt(2.0) * b) * dif_x * dif_y;
0358       typename ulp_cmp_type::Result expr_cmp =
0359           ulp_cmp(fast_left_expr, fast_right_expr, 4);
0360       if (expr_cmp != ulp_cmp_type::EQUAL) {
0361         if ((expr_cmp == ulp_cmp_type::MORE) ^ reverse_order)
0362           return reverse_order ? LESS : MORE;
0363         return UNDEFINED;
0364       }
0365       return UNDEFINED;
0366     }
0367 
0368    private:
0369     ulp_cmp_type ulp_cmp;
0370     to_fpt_converter to_fpt;
0371   };
0372 
0373   template <typename Node>
0374   class node_comparison_predicate {
0375    public:
0376     typedef Node node_type;
0377     typedef typename Node::site_type site_type;
0378     typedef typename site_type::point_type point_type;
0379     typedef typename point_type::coordinate_type coordinate_type;
0380     typedef point_comparison_predicate<point_type> point_comparison_type;
0381     typedef distance_predicate<site_type> distance_predicate_type;
0382 
0383     // Compares nodes in the balanced binary search tree. Nodes are
0384     // compared based on the y coordinates of the arcs intersection points.
0385     // Nodes with less y coordinate of the intersection point go first.
0386     // Comparison is only called during the new site events processing.
0387     // That's why one of the nodes will always lie on the sweepline and may
0388     // be represented as a straight horizontal line.
0389     bool operator() (const node_type& node1,
0390                      const node_type& node2) const {
0391       // Get x coordinate of the rightmost site from both nodes.
0392       const site_type& site1 = get_comparison_site(node1);
0393       const site_type& site2 = get_comparison_site(node2);
0394       const point_type& point1 = get_comparison_point(site1);
0395       const point_type& point2 = get_comparison_point(site2);
0396 
0397       if (point1.x() < point2.x()) {
0398         // The second node contains a new site.
0399         return distance_predicate_(
0400             node1.left_site(), node1.right_site(), point2);
0401       } else if (point1.x() > point2.x()) {
0402         // The first node contains a new site.
0403         return !distance_predicate_(
0404             node2.left_site(), node2.right_site(), point1);
0405       } else {
0406         // This checks were evaluated experimentally.
0407         if (site1.sorted_index() == site2.sorted_index()) {
0408           // Both nodes are new (inserted during same site event processing).
0409           return get_comparison_y(node1) < get_comparison_y(node2);
0410         } else if (site1.sorted_index() < site2.sorted_index()) {
0411           std::pair<coordinate_type, int> y1 = get_comparison_y(node1, false);
0412           std::pair<coordinate_type, int> y2 = get_comparison_y(node2, true);
0413           if (y1.first != y2.first) return y1.first < y2.first;
0414           return (!site1.is_segment()) ? (y1.second < 0) : false;
0415         } else {
0416           std::pair<coordinate_type, int> y1 = get_comparison_y(node1, true);
0417           std::pair<coordinate_type, int> y2 = get_comparison_y(node2, false);
0418           if (y1.first != y2.first) return y1.first < y2.first;
0419           return (!site2.is_segment()) ? (y2.second > 0) : true;
0420         }
0421       }
0422     }
0423 
0424    private:
0425     // Get the newer site.
0426     const site_type& get_comparison_site(const node_type& node) const {
0427       if (node.left_site().sorted_index() > node.right_site().sorted_index()) {
0428         return node.left_site();
0429       }
0430       return node.right_site();
0431     }
0432 
0433     const point_type& get_comparison_point(const site_type& site) const {
0434       return point_comparison_(site.point0(), site.point1()) ?
0435           site.point0() : site.point1();
0436     }
0437 
0438     // Get comparison pair: y coordinate and direction of the newer site.
0439     std::pair<coordinate_type, int> get_comparison_y(
0440       const node_type& node, bool is_new_node = true) const {
0441       if (node.left_site().sorted_index() ==
0442           node.right_site().sorted_index()) {
0443         return std::make_pair(node.left_site().y0(), 0);
0444       }
0445       if (node.left_site().sorted_index() > node.right_site().sorted_index()) {
0446         if (!is_new_node &&
0447             node.left_site().is_segment() &&
0448             is_vertical(node.left_site())) {
0449           return std::make_pair(node.left_site().y0(), 1);
0450         }
0451         return std::make_pair(node.left_site().y1(), 1);
0452       }
0453       return std::make_pair(node.right_site().y0(), -1);
0454     }
0455 
0456     point_comparison_type point_comparison_;
0457     distance_predicate_type distance_predicate_;
0458   };
0459 
0460   template <typename Site>
0461   class circle_existence_predicate {
0462    public:
0463     typedef typename Site::point_type point_type;
0464     typedef Site site_type;
0465 
0466     bool ppp(const site_type& site1,
0467              const site_type& site2,
0468              const site_type& site3) const {
0469       return ot::eval(site1.point0(),
0470                       site2.point0(),
0471                       site3.point0()) == ot::RIGHT;
0472     }
0473 
0474     bool pps(const site_type& site1,
0475              const site_type& site2,
0476              const site_type& site3,
0477              int segment_index) const {
0478       if (segment_index != 2) {
0479         typename ot::Orientation orient1 = ot::eval(
0480             site1.point0(), site2.point0(), site3.point0());
0481         typename ot::Orientation orient2 = ot::eval(
0482             site1.point0(), site2.point0(), site3.point1());
0483         if (segment_index == 1 && site1.x0() >= site2.x0()) {
0484           if (orient1 != ot::RIGHT)
0485             return false;
0486         } else if (segment_index == 3 && site2.x0() >= site1.x0()) {
0487           if (orient2 != ot::RIGHT)
0488             return false;
0489         } else if (orient1 != ot::RIGHT && orient2 != ot::RIGHT) {
0490           return false;
0491         }
0492       } else {
0493         return (site3.point0() != site1.point0()) ||
0494                (site3.point1() != site2.point0());
0495       }
0496       return true;
0497     }
0498 
0499     bool pss(const site_type& site1,
0500              const site_type& site2,
0501              const site_type& site3,
0502              int point_index) const {
0503       if (site2.sorted_index() == site3.sorted_index()) {
0504         return false;
0505       }
0506       if (point_index == 2) {
0507         if (!site2.is_inverse() && site3.is_inverse())
0508           return false;
0509         if (site2.is_inverse() == site3.is_inverse() &&
0510             ot::eval(site2.point0(),
0511                      site1.point0(),
0512                      site3.point1()) != ot::RIGHT)
0513           return false;
0514       }
0515       return true;
0516     }
0517 
0518     bool sss(const site_type& site1,
0519              const site_type& site2,
0520              const site_type& site3) const {
0521       return (site1.sorted_index() != site2.sorted_index()) &&
0522              (site2.sorted_index() != site3.sorted_index());
0523     }
0524   };
0525 
0526   template <typename Site, typename Circle>
0527   class mp_circle_formation_functor {
0528    public:
0529     typedef typename Site::point_type point_type;
0530     typedef Site site_type;
0531     typedef Circle circle_type;
0532     typedef robust_sqrt_expr<big_int_type, efpt_type, to_efpt_converter>
0533         robust_sqrt_expr_type;
0534 
0535     void ppp(const site_type& site1,
0536              const site_type& site2,
0537              const site_type& site3,
0538              circle_type& circle,
0539              bool recompute_c_x = true,
0540              bool recompute_c_y = true,
0541              bool recompute_lower_x = true) {
0542       big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2];
0543       dif_x[0] = static_cast<int_x2_type>(site1.x()) -
0544                  static_cast<int_x2_type>(site2.x());
0545       dif_x[1] = static_cast<int_x2_type>(site2.x()) -
0546                  static_cast<int_x2_type>(site3.x());
0547       dif_x[2] = static_cast<int_x2_type>(site1.x()) -
0548                  static_cast<int_x2_type>(site3.x());
0549       dif_y[0] = static_cast<int_x2_type>(site1.y()) -
0550                  static_cast<int_x2_type>(site2.y());
0551       dif_y[1] = static_cast<int_x2_type>(site2.y()) -
0552                  static_cast<int_x2_type>(site3.y());
0553       dif_y[2] = static_cast<int_x2_type>(site1.y()) -
0554                  static_cast<int_x2_type>(site3.y());
0555       sum_x[0] = static_cast<int_x2_type>(site1.x()) +
0556                  static_cast<int_x2_type>(site2.x());
0557       sum_x[1] = static_cast<int_x2_type>(site2.x()) +
0558                  static_cast<int_x2_type>(site3.x());
0559       sum_y[0] = static_cast<int_x2_type>(site1.y()) +
0560                  static_cast<int_x2_type>(site2.y());
0561       sum_y[1] = static_cast<int_x2_type>(site2.y()) +
0562                  static_cast<int_x2_type>(site3.y());
0563       fpt_type inv_denom = to_fpt(0.5) / to_fpt(static_cast<big_int_type>(
0564           dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0]));
0565       big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0];
0566       big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1];
0567 
0568       if (recompute_c_x || recompute_lower_x) {
0569         big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0];
0570         circle.x(to_fpt(c_x) * inv_denom);
0571 
0572         if (recompute_lower_x) {
0573           // Evaluate radius of the circle.
0574           big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) *
0575                                (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) *
0576                                (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]);
0577           fpt_type r = get_sqrt(to_fpt(sqr_r));
0578 
0579           // If c_x >= 0 then lower_x = c_x + r,
0580           // else lower_x = (c_x * c_x - r * r) / (c_x - r).
0581           // To guarantee epsilon relative error.
0582           if (!is_neg(circle.x())) {
0583             if (!is_neg(inv_denom)) {
0584               circle.lower_x(circle.x() + r * inv_denom);
0585             } else {
0586               circle.lower_x(circle.x() - r * inv_denom);
0587             }
0588           } else {
0589             big_int_type numer = c_x * c_x - sqr_r;
0590             fpt_type lower_x = to_fpt(numer) * inv_denom / (to_fpt(c_x) + r);
0591             circle.lower_x(lower_x);
0592           }
0593         }
0594       }
0595 
0596       if (recompute_c_y) {
0597         big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1];
0598         circle.y(to_fpt(c_y) * inv_denom);
0599       }
0600     }
0601 
0602     // Recompute parameters of the circle event using high-precision library.
0603     void pps(const site_type& site1,
0604              const site_type& site2,
0605              const site_type& site3,
0606              int segment_index,
0607              circle_type& c_event,
0608              bool recompute_c_x = true,
0609              bool recompute_c_y = true,
0610              bool recompute_lower_x = true) {
0611       big_int_type cA[4], cB[4];
0612       big_int_type line_a = static_cast<int_x2_type>(site3.y1()) -
0613                             static_cast<int_x2_type>(site3.y0());
0614       big_int_type line_b = static_cast<int_x2_type>(site3.x0()) -
0615                             static_cast<int_x2_type>(site3.x1());
0616       big_int_type segm_len = line_a * line_a + line_b * line_b;
0617       big_int_type vec_x = static_cast<int_x2_type>(site2.y()) -
0618                            static_cast<int_x2_type>(site1.y());
0619       big_int_type vec_y = static_cast<int_x2_type>(site1.x()) -
0620                            static_cast<int_x2_type>(site2.x());
0621       big_int_type sum_x = static_cast<int_x2_type>(site1.x()) +
0622                            static_cast<int_x2_type>(site2.x());
0623       big_int_type sum_y = static_cast<int_x2_type>(site1.y()) +
0624                            static_cast<int_x2_type>(site2.y());
0625       big_int_type teta = line_a * vec_x + line_b * vec_y;
0626       big_int_type denom = vec_x * line_b - vec_y * line_a;
0627 
0628       big_int_type dif0 = static_cast<int_x2_type>(site3.y1()) -
0629                           static_cast<int_x2_type>(site1.y());
0630       big_int_type dif1 = static_cast<int_x2_type>(site1.x()) -
0631                           static_cast<int_x2_type>(site3.x1());
0632       big_int_type A = line_a * dif1 - line_b * dif0;
0633       dif0 = static_cast<int_x2_type>(site3.y1()) -
0634              static_cast<int_x2_type>(site2.y());
0635       dif1 = static_cast<int_x2_type>(site2.x()) -
0636              static_cast<int_x2_type>(site3.x1());
0637       big_int_type B = line_a * dif1 - line_b * dif0;
0638       big_int_type sum_AB = A + B;
0639 
0640       if (is_zero(denom)) {
0641         big_int_type numer = teta * teta - sum_AB * sum_AB;
0642         denom = teta * sum_AB;
0643         cA[0] = denom * sum_x * 2 + numer * vec_x;
0644         cB[0] = segm_len;
0645         cA[1] = denom * sum_AB * 2 + numer * teta;
0646         cB[1] = 1;
0647         cA[2] = denom * sum_y * 2 + numer * vec_y;
0648         fpt_type inv_denom = to_fpt(1.0) / to_fpt(denom);
0649         if (recompute_c_x)
0650           c_event.x(to_fpt(0.25) * to_fpt(cA[0]) * inv_denom);
0651         if (recompute_c_y)
0652           c_event.y(to_fpt(0.25) * to_fpt(cA[2]) * inv_denom);
0653         if (recompute_lower_x) {
0654           c_event.lower_x(to_fpt(0.25) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
0655               inv_denom / get_sqrt(to_fpt(segm_len)));
0656         }
0657         return;
0658       }
0659 
0660       big_int_type det = (teta * teta + denom * denom) * A * B * 4;
0661       fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom);
0662       inv_denom_sqr *= inv_denom_sqr;
0663 
0664       if (recompute_c_x || recompute_lower_x) {
0665         cA[0] = sum_x * denom * denom + teta * sum_AB * vec_x;
0666         cB[0] = 1;
0667         cA[1] = (segment_index == 2) ? -vec_x : vec_x;
0668         cB[1] = det;
0669         if (recompute_c_x) {
0670           c_event.x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
0671               inv_denom_sqr);
0672         }
0673       }
0674 
0675       if (recompute_c_y || recompute_lower_x) {
0676         cA[2] = sum_y * denom * denom + teta * sum_AB * vec_y;
0677         cB[2] = 1;
0678         cA[3] = (segment_index == 2) ? -vec_y : vec_y;
0679         cB[3] = det;
0680         if (recompute_c_y) {
0681           c_event.y(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(&cA[2], &cB[2])) *
0682                     inv_denom_sqr);
0683         }
0684       }
0685 
0686       if (recompute_lower_x) {
0687         cB[0] = cB[0] * segm_len;
0688         cB[1] = cB[1] * segm_len;
0689         cA[2] = sum_AB * (denom * denom + teta * teta);
0690         cB[2] = 1;
0691         cA[3] = (segment_index == 2) ? -teta : teta;
0692         cB[3] = det;
0693         c_event.lower_x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval4(cA, cB)) *
0694             inv_denom_sqr / get_sqrt(to_fpt(segm_len)));
0695       }
0696     }
0697 
0698     // Recompute parameters of the circle event using high-precision library.
0699     void pss(const site_type& site1,
0700              const site_type& site2,
0701              const site_type& site3,
0702              int point_index,
0703              circle_type& c_event,
0704              bool recompute_c_x = true,
0705              bool recompute_c_y = true,
0706              bool recompute_lower_x = true) {
0707       big_int_type a[2], b[2], c[2], cA[4], cB[4];
0708       const point_type& segm_start1 = site2.point1();
0709       const point_type& segm_end1 = site2.point0();
0710       const point_type& segm_start2 = site3.point0();
0711       const point_type& segm_end2 = site3.point1();
0712       a[0] = static_cast<int_x2_type>(segm_end1.x()) -
0713              static_cast<int_x2_type>(segm_start1.x());
0714       b[0] = static_cast<int_x2_type>(segm_end1.y()) -
0715              static_cast<int_x2_type>(segm_start1.y());
0716       a[1] = static_cast<int_x2_type>(segm_end2.x()) -
0717              static_cast<int_x2_type>(segm_start2.x());
0718       b[1] = static_cast<int_x2_type>(segm_end2.y()) -
0719              static_cast<int_x2_type>(segm_start2.y());
0720       big_int_type orientation = a[1] * b[0] - a[0] * b[1];
0721       if (is_zero(orientation)) {
0722         fpt_type denom = to_fpt(2.0) * to_fpt(
0723             static_cast<big_int_type>(a[0] * a[0] + b[0] * b[0]));
0724         c[0] = b[0] * (static_cast<int_x2_type>(segm_start2.x()) -
0725                        static_cast<int_x2_type>(segm_start1.x())) -
0726                a[0] * (static_cast<int_x2_type>(segm_start2.y()) -
0727                        static_cast<int_x2_type>(segm_start1.y()));
0728         big_int_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) -
0729                                   static_cast<int_x2_type>(segm_start1.y())) -
0730                           b[0] * (static_cast<int_x2_type>(site1.x()) -
0731                                   static_cast<int_x2_type>(segm_start1.x()));
0732         big_int_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) -
0733                                   static_cast<int_x2_type>(segm_start2.x())) -
0734                           a[0] * (static_cast<int_x2_type>(site1.y()) -
0735                                   static_cast<int_x2_type>(segm_start2.y()));
0736         cB[0] = dx * dy;
0737         cB[1] = 1;
0738 
0739         if (recompute_c_y) {
0740           cA[0] = b[0] * ((point_index == 2) ? 2 : -2);
0741           cA[1] = a[0] * a[0] * (static_cast<int_x2_type>(segm_start1.y()) +
0742                                  static_cast<int_x2_type>(segm_start2.y())) -
0743                   a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
0744                                  static_cast<int_x2_type>(segm_start2.x()) -
0745                                  static_cast<int_x2_type>(site1.x()) * 2) +
0746                   b[0] * b[0] * (static_cast<int_x2_type>(site1.y()) * 2);
0747           fpt_type c_y = to_fpt(sqrt_expr_.eval2(cA, cB));
0748           c_event.y(c_y / denom);
0749         }
0750 
0751         if (recompute_c_x || recompute_lower_x) {
0752           cA[0] = a[0] * ((point_index == 2) ? 2 : -2);
0753           cA[1] = b[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
0754                                  static_cast<int_x2_type>(segm_start2.x())) -
0755                   a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.y()) +
0756                                  static_cast<int_x2_type>(segm_start2.y()) -
0757                                  static_cast<int_x2_type>(site1.y()) * 2) +
0758                   a[0] * a[0] * (static_cast<int_x2_type>(site1.x()) * 2);
0759 
0760           if (recompute_c_x) {
0761             fpt_type c_x = to_fpt(sqrt_expr_.eval2(cA, cB));
0762             c_event.x(c_x / denom);
0763           }
0764 
0765           if (recompute_lower_x) {
0766             cA[2] = is_neg(c[0]) ? -c[0] : c[0];
0767             cB[2] = a[0] * a[0] + b[0] * b[0];
0768             fpt_type lower_x = to_fpt(sqrt_expr_.eval3(cA, cB));
0769             c_event.lower_x(lower_x / denom);
0770           }
0771         }
0772         return;
0773       }
0774       c[0] = b[0] * segm_end1.x() - a[0] * segm_end1.y();
0775       c[1] = a[1] * segm_end2.y() - b[1] * segm_end2.x();
0776       big_int_type ix = a[0] * c[1] + a[1] * c[0];
0777       big_int_type iy = b[0] * c[1] + b[1] * c[0];
0778       big_int_type dx = ix - orientation * site1.x();
0779       big_int_type dy = iy - orientation * site1.y();
0780       if (is_zero(dx) && is_zero(dy)) {
0781         fpt_type denom = to_fpt(orientation);
0782         fpt_type c_x = to_fpt(ix) / denom;
0783         fpt_type c_y = to_fpt(iy) / denom;
0784         c_event = circle_type(c_x, c_y, c_x);
0785         return;
0786       }
0787 
0788       big_int_type sign = ((point_index == 2) ? 1 : -1) *
0789                           (is_neg(orientation) ? 1 : -1);
0790       cA[0] = a[1] * -dx + b[1] * -dy;
0791       cA[1] = a[0] * -dx + b[0] * -dy;
0792       cA[2] = sign;
0793       cA[3] = 0;
0794       cB[0] = a[0] * a[0] + b[0] * b[0];
0795       cB[1] = a[1] * a[1] + b[1] * b[1];
0796       cB[2] = a[0] * a[1] + b[0] * b[1];
0797       cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2;
0798       fpt_type temp = to_fpt(
0799           sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
0800       fpt_type denom = temp * to_fpt(orientation);
0801 
0802       if (recompute_c_y) {
0803         cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]);
0804         cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]);
0805         cA[2] = iy * sign;
0806         fpt_type cy = to_fpt(
0807             sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
0808         c_event.y(cy / denom);
0809       }
0810 
0811       if (recompute_c_x || recompute_lower_x) {
0812         cA[0] = a[1] * (dx * dx + dy * dy) - ix * (dx * a[1] + dy * b[1]);
0813         cA[1] = a[0] * (dx * dx + dy * dy) - ix * (dx * a[0] + dy * b[0]);
0814         cA[2] = ix * sign;
0815 
0816         if (recompute_c_x) {
0817           fpt_type cx = to_fpt(
0818               sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
0819           c_event.x(cx / denom);
0820         }
0821 
0822         if (recompute_lower_x) {
0823           cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1);
0824           fpt_type lower_x = to_fpt(
0825               sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
0826           c_event.lower_x(lower_x / denom);
0827         }
0828       }
0829     }
0830 
0831     // Recompute parameters of the circle event using high-precision library.
0832     void sss(const site_type& site1,
0833              const site_type& site2,
0834              const site_type& site3,
0835              circle_type& c_event,
0836              bool recompute_c_x = true,
0837              bool recompute_c_y = true,
0838              bool recompute_lower_x = true) {
0839       big_int_type a[3], b[3], c[3], cA[4], cB[4];
0840       // cA - corresponds to the cross product.
0841       // cB - corresponds to the squared length.
0842       a[0] = static_cast<int_x2_type>(site1.x1()) -
0843              static_cast<int_x2_type>(site1.x0());
0844       a[1] = static_cast<int_x2_type>(site2.x1()) -
0845              static_cast<int_x2_type>(site2.x0());
0846       a[2] = static_cast<int_x2_type>(site3.x1()) -
0847              static_cast<int_x2_type>(site3.x0());
0848 
0849       b[0] = static_cast<int_x2_type>(site1.y1()) -
0850              static_cast<int_x2_type>(site1.y0());
0851       b[1] = static_cast<int_x2_type>(site2.y1()) -
0852              static_cast<int_x2_type>(site2.y0());
0853       b[2] = static_cast<int_x2_type>(site3.y1()) -
0854              static_cast<int_x2_type>(site3.y0());
0855 
0856       c[0] = static_cast<int_x2_type>(site1.x0()) *
0857              static_cast<int_x2_type>(site1.y1()) -
0858              static_cast<int_x2_type>(site1.y0()) *
0859              static_cast<int_x2_type>(site1.x1());
0860       c[1] = static_cast<int_x2_type>(site2.x0()) *
0861              static_cast<int_x2_type>(site2.y1()) -
0862              static_cast<int_x2_type>(site2.y0()) *
0863              static_cast<int_x2_type>(site2.x1());
0864       c[2] = static_cast<int_x2_type>(site3.x0()) *
0865              static_cast<int_x2_type>(site3.y1()) -
0866              static_cast<int_x2_type>(site3.y0()) *
0867              static_cast<int_x2_type>(site3.x1());
0868 
0869       for (int i = 0; i < 3; ++i)
0870         cB[i] = a[i] * a[i] + b[i] * b[i];
0871 
0872       for (int i = 0; i < 3; ++i) {
0873         int j = (i+1) % 3;
0874         int k = (i+2) % 3;
0875         cA[i] = a[j] * b[k] - a[k] * b[j];
0876       }
0877       fpt_type denom = to_fpt(sqrt_expr_.eval3(cA, cB));
0878 
0879       if (recompute_c_y) {
0880         for (int i = 0; i < 3; ++i) {
0881           int j = (i+1) % 3;
0882           int k = (i+2) % 3;
0883           cA[i] = b[j] * c[k] - b[k] * c[j];
0884         }
0885         fpt_type c_y = to_fpt(sqrt_expr_.eval3(cA, cB));
0886         c_event.y(c_y / denom);
0887       }
0888 
0889       if (recompute_c_x || recompute_lower_x) {
0890         cA[3] = 0;
0891         for (int i = 0; i < 3; ++i) {
0892           int j = (i+1) % 3;
0893           int k = (i+2) % 3;
0894           cA[i] = a[j] * c[k] - a[k] * c[j];
0895           if (recompute_lower_x) {
0896             cA[3] = cA[3] + cA[i] * b[i];
0897           }
0898         }
0899 
0900         if (recompute_c_x) {
0901           fpt_type c_x = to_fpt(sqrt_expr_.eval3(cA, cB));
0902           c_event.x(c_x / denom);
0903         }
0904 
0905         if (recompute_lower_x) {
0906           cB[3] = 1;
0907           fpt_type lower_x = to_fpt(sqrt_expr_.eval4(cA, cB));
0908           c_event.lower_x(lower_x / denom);
0909         }
0910       }
0911     }
0912 
0913    private:
0914     // Evaluates A[3] + A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
0915     //           A[2] * sqrt(B[3] * (sqrt(B[0] * B[1]) + B[2])).
0916     template <typename _int, typename _fpt>
0917     _fpt sqrt_expr_evaluator_pss4(_int *A, _int *B) {
0918       _int cA[4], cB[4];
0919       if (is_zero(A[3])) {
0920         _fpt lh = sqrt_expr_.eval2(A, B);
0921         cA[0] = 1;
0922         cB[0] = B[0] * B[1];
0923         cA[1] = B[2];
0924         cB[1] = 1;
0925         _fpt rh = sqrt_expr_.eval1(A+2, B+3) *
0926             get_sqrt(sqrt_expr_.eval2(cA, cB));
0927         if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
0928           return lh + rh;
0929         cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
0930                 A[2] * A[2] * B[3] * B[2];
0931         cB[0] = 1;
0932         cA[1] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
0933         cB[1] = B[0] * B[1];
0934         _fpt numer = sqrt_expr_.eval2(cA, cB);
0935         return numer / (lh - rh);
0936       }
0937       cA[0] = 1;
0938       cB[0] = B[0] * B[1];
0939       cA[1] = B[2];
0940       cB[1] = 1;
0941       _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB));
0942       cA[0] = A[0];
0943       cB[0] = B[0];
0944       cA[1] = A[1];
0945       cB[1] = B[1];
0946       cA[2] = A[3];
0947       cB[2] = 1;
0948       _fpt lh = sqrt_expr_.eval3(cA, cB);
0949       if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
0950         return lh + rh;
0951       cA[0] = A[3] * A[0] * 2;
0952       cA[1] = A[3] * A[1] * 2;
0953       cA[2] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] +
0954               A[3] * A[3] - A[2] * A[2] * B[2] * B[3];
0955       cA[3] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
0956       cB[3] = B[0] * B[1];
0957       _fpt numer = sqrt_expr_evaluator_pss3<_int, _fpt>(cA, cB);
0958       return numer / (lh - rh);
0959     }
0960 
0961     template <typename _int, typename _fpt>
0962     // Evaluates A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
0963     //           A[2] + A[3] * sqrt(B[0] * B[1]).
0964     // B[3] = B[0] * B[1].
0965     _fpt sqrt_expr_evaluator_pss3(_int *A, _int *B) {
0966       _int cA[2], cB[2];
0967       _fpt lh = sqrt_expr_.eval2(A, B);
0968       _fpt rh = sqrt_expr_.eval2(A+2, B+2);
0969       if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
0970         return lh + rh;
0971       cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
0972               A[2] * A[2] - A[3] * A[3] * B[0] * B[1];
0973       cB[0] = 1;
0974       cA[1] = (A[0] * A[1] - A[2] * A[3]) * 2;
0975       cB[1] = B[3];
0976       _fpt numer = sqrt_expr_.eval2(cA, cB);
0977       return numer / (lh - rh);
0978     }
0979 
0980     robust_sqrt_expr_type sqrt_expr_;
0981     to_fpt_converter to_fpt;
0982   };
0983 
0984   template <typename Site, typename Circle>
0985   class lazy_circle_formation_functor {
0986    public:
0987     typedef robust_fpt<fpt_type> robust_fpt_type;
0988     typedef robust_dif<robust_fpt_type> robust_dif_type;
0989     typedef typename Site::point_type point_type;
0990     typedef Site site_type;
0991     typedef Circle circle_type;
0992     typedef mp_circle_formation_functor<site_type, circle_type>
0993         exact_circle_formation_functor_type;
0994 
0995     void ppp(const site_type& site1,
0996              const site_type& site2,
0997              const site_type& site3,
0998              circle_type& c_event) {
0999       fpt_type dif_x1 = to_fpt(site1.x()) - to_fpt(site2.x());
1000       fpt_type dif_x2 = to_fpt(site2.x()) - to_fpt(site3.x());
1001       fpt_type dif_y1 = to_fpt(site1.y()) - to_fpt(site2.y());
1002       fpt_type dif_y2 = to_fpt(site2.y()) - to_fpt(site3.y());
1003       fpt_type orientation = robust_cross_product(
1004           static_cast<int_x2_type>(site1.x()) -
1005           static_cast<int_x2_type>(site2.x()),
1006           static_cast<int_x2_type>(site2.x()) -
1007           static_cast<int_x2_type>(site3.x()),
1008           static_cast<int_x2_type>(site1.y()) -
1009           static_cast<int_x2_type>(site2.y()),
1010           static_cast<int_x2_type>(site2.y()) -
1011           static_cast<int_x2_type>(site3.y()));
1012       robust_fpt_type inv_orientation(to_fpt(0.5) / orientation, to_fpt(2.0));
1013       fpt_type sum_x1 = to_fpt(site1.x()) + to_fpt(site2.x());
1014       fpt_type sum_x2 = to_fpt(site2.x()) + to_fpt(site3.x());
1015       fpt_type sum_y1 = to_fpt(site1.y()) + to_fpt(site2.y());
1016       fpt_type sum_y2 = to_fpt(site2.y()) + to_fpt(site3.y());
1017       fpt_type dif_x3 = to_fpt(site1.x()) - to_fpt(site3.x());
1018       fpt_type dif_y3 = to_fpt(site1.y()) - to_fpt(site3.y());
1019       robust_dif_type c_x, c_y;
1020       c_x += robust_fpt_type(dif_x1 * sum_x1 * dif_y2, to_fpt(2.0));
1021       c_x += robust_fpt_type(dif_y1 * sum_y1 * dif_y2, to_fpt(2.0));
1022       c_x -= robust_fpt_type(dif_x2 * sum_x2 * dif_y1, to_fpt(2.0));
1023       c_x -= robust_fpt_type(dif_y2 * sum_y2 * dif_y1, to_fpt(2.0));
1024       c_y += robust_fpt_type(dif_x2 * sum_x2 * dif_x1, to_fpt(2.0));
1025       c_y += robust_fpt_type(dif_y2 * sum_y2 * dif_x1, to_fpt(2.0));
1026       c_y -= robust_fpt_type(dif_x1 * sum_x1 * dif_x2, to_fpt(2.0));
1027       c_y -= robust_fpt_type(dif_y1 * sum_y1 * dif_x2, to_fpt(2.0));
1028       robust_dif_type lower_x(c_x);
1029       lower_x -= robust_fpt_type(get_sqrt(
1030           (dif_x1 * dif_x1 + dif_y1 * dif_y1) *
1031           (dif_x2 * dif_x2 + dif_y2 * dif_y2) *
1032           (dif_x3 * dif_x3 + dif_y3 * dif_y3)), to_fpt(5.0));
1033       c_event = circle_type(
1034           c_x.dif().fpv() * inv_orientation.fpv(),
1035           c_y.dif().fpv() * inv_orientation.fpv(),
1036           lower_x.dif().fpv() * inv_orientation.fpv());
1037       bool recompute_c_x = c_x.dif().ulp() > ULPS;
1038       bool recompute_c_y = c_y.dif().ulp() > ULPS;
1039       bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
1040       if (recompute_c_x || recompute_c_y || recompute_lower_x) {
1041         exact_circle_formation_functor_.ppp(
1042             site1, site2, site3, c_event,
1043             recompute_c_x, recompute_c_y, recompute_lower_x);
1044       }
1045     }
1046 
1047     void pps(const site_type& site1,
1048              const site_type& site2,
1049              const site_type& site3,
1050              int segment_index,
1051              circle_type& c_event) {
1052       fpt_type line_a = to_fpt(site3.y1()) - to_fpt(site3.y0());
1053       fpt_type line_b = to_fpt(site3.x0()) - to_fpt(site3.x1());
1054       fpt_type vec_x = to_fpt(site2.y()) - to_fpt(site1.y());
1055       fpt_type vec_y = to_fpt(site1.x()) - to_fpt(site2.x());
1056       robust_fpt_type teta(robust_cross_product(
1057           static_cast<int_x2_type>(site3.y1()) -
1058           static_cast<int_x2_type>(site3.y0()),
1059           static_cast<int_x2_type>(site3.x0()) -
1060           static_cast<int_x2_type>(site3.x1()),
1061           static_cast<int_x2_type>(site2.x()) -
1062           static_cast<int_x2_type>(site1.x()),
1063           static_cast<int_x2_type>(site2.y()) -
1064           static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
1065       robust_fpt_type A(robust_cross_product(
1066           static_cast<int_x2_type>(site3.y0()) -
1067           static_cast<int_x2_type>(site3.y1()),
1068           static_cast<int_x2_type>(site3.x0()) -
1069           static_cast<int_x2_type>(site3.x1()),
1070           static_cast<int_x2_type>(site3.y1()) -
1071           static_cast<int_x2_type>(site1.y()),
1072           static_cast<int_x2_type>(site3.x1()) -
1073           static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
1074       robust_fpt_type B(robust_cross_product(
1075           static_cast<int_x2_type>(site3.y0()) -
1076           static_cast<int_x2_type>(site3.y1()),
1077           static_cast<int_x2_type>(site3.x0()) -
1078           static_cast<int_x2_type>(site3.x1()),
1079           static_cast<int_x2_type>(site3.y1()) -
1080           static_cast<int_x2_type>(site2.y()),
1081           static_cast<int_x2_type>(site3.x1()) -
1082           static_cast<int_x2_type>(site2.x())), to_fpt(1.0));
1083       robust_fpt_type denom(robust_cross_product(
1084           static_cast<int_x2_type>(site1.y()) -
1085           static_cast<int_x2_type>(site2.y()),
1086           static_cast<int_x2_type>(site1.x()) -
1087           static_cast<int_x2_type>(site2.x()),
1088           static_cast<int_x2_type>(site3.y1()) -
1089           static_cast<int_x2_type>(site3.y0()),
1090           static_cast<int_x2_type>(site3.x1()) -
1091           static_cast<int_x2_type>(site3.x0())), to_fpt(1.0));
1092       robust_fpt_type inv_segm_len(to_fpt(1.0) /
1093           get_sqrt(line_a * line_a + line_b * line_b), to_fpt(3.0));
1094       robust_dif_type t;
1095       if (ot::eval(denom) == ot::COLLINEAR) {
1096         t += teta / (robust_fpt_type(to_fpt(8.0)) * A);
1097         t -= A / (robust_fpt_type(to_fpt(2.0)) * teta);
1098       } else {
1099         robust_fpt_type det = ((teta * teta + denom * denom) * A * B).sqrt();
1100         if (segment_index == 2) {
1101           t -= det / (denom * denom);
1102         } else {
1103           t += det / (denom * denom);
1104         }
1105         t += teta * (A + B) / (robust_fpt_type(to_fpt(2.0)) * denom * denom);
1106       }
1107       robust_dif_type c_x, c_y;
1108       c_x += robust_fpt_type(to_fpt(0.5) *
1109           (to_fpt(site1.x()) + to_fpt(site2.x())));
1110       c_x += robust_fpt_type(vec_x) * t;
1111       c_y += robust_fpt_type(to_fpt(0.5) *
1112           (to_fpt(site1.y()) + to_fpt(site2.y())));
1113       c_y += robust_fpt_type(vec_y) * t;
1114       robust_dif_type r, lower_x(c_x);
1115       r -= robust_fpt_type(line_a) * robust_fpt_type(site3.x0());
1116       r -= robust_fpt_type(line_b) * robust_fpt_type(site3.y0());
1117       r += robust_fpt_type(line_a) * c_x;
1118       r += robust_fpt_type(line_b) * c_y;
1119       if (r.pos().fpv() < r.neg().fpv())
1120         r = -r;
1121       lower_x += r * inv_segm_len;
1122       c_event = circle_type(
1123           c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
1124       bool recompute_c_x = c_x.dif().ulp() > ULPS;
1125       bool recompute_c_y = c_y.dif().ulp() > ULPS;
1126       bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
1127       if (recompute_c_x || recompute_c_y || recompute_lower_x) {
1128         exact_circle_formation_functor_.pps(
1129             site1, site2, site3, segment_index, c_event,
1130             recompute_c_x, recompute_c_y, recompute_lower_x);
1131       }
1132     }
1133 
1134     void pss(const site_type& site1,
1135              const site_type& site2,
1136              const site_type& site3,
1137              int point_index,
1138              circle_type& c_event) {
1139       const point_type& segm_start1 = site2.point1();
1140       const point_type& segm_end1 = site2.point0();
1141       const point_type& segm_start2 = site3.point0();
1142       const point_type& segm_end2 = site3.point1();
1143       fpt_type a1 = to_fpt(segm_end1.x()) - to_fpt(segm_start1.x());
1144       fpt_type b1 = to_fpt(segm_end1.y()) - to_fpt(segm_start1.y());
1145       fpt_type a2 = to_fpt(segm_end2.x()) - to_fpt(segm_start2.x());
1146       fpt_type b2 = to_fpt(segm_end2.y()) - to_fpt(segm_start2.y());
1147       bool recompute_c_x, recompute_c_y, recompute_lower_x;
1148       robust_fpt_type orientation(robust_cross_product(
1149         static_cast<int_x2_type>(segm_end1.y()) -
1150         static_cast<int_x2_type>(segm_start1.y()),
1151         static_cast<int_x2_type>(segm_end1.x()) -
1152         static_cast<int_x2_type>(segm_start1.x()),
1153         static_cast<int_x2_type>(segm_end2.y()) -
1154         static_cast<int_x2_type>(segm_start2.y()),
1155         static_cast<int_x2_type>(segm_end2.x()) -
1156         static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
1157       if (ot::eval(orientation) == ot::COLLINEAR) {
1158         robust_fpt_type a(a1 * a1 + b1 * b1, to_fpt(2.0));
1159         robust_fpt_type c(robust_cross_product(
1160             static_cast<int_x2_type>(segm_end1.y()) -
1161             static_cast<int_x2_type>(segm_start1.y()),
1162             static_cast<int_x2_type>(segm_end1.x()) -
1163             static_cast<int_x2_type>(segm_start1.x()),
1164             static_cast<int_x2_type>(segm_start2.y()) -
1165             static_cast<int_x2_type>(segm_start1.y()),
1166             static_cast<int_x2_type>(segm_start2.x()) -
1167             static_cast<int_x2_type>(segm_start1.x())), to_fpt(1.0));
1168         robust_fpt_type det(
1169             robust_cross_product(
1170                 static_cast<int_x2_type>(segm_end1.x()) -
1171                 static_cast<int_x2_type>(segm_start1.x()),
1172                 static_cast<int_x2_type>(segm_end1.y()) -
1173                 static_cast<int_x2_type>(segm_start1.y()),
1174                 static_cast<int_x2_type>(site1.x()) -
1175                 static_cast<int_x2_type>(segm_start1.x()),
1176                 static_cast<int_x2_type>(site1.y()) -
1177                 static_cast<int_x2_type>(segm_start1.y())) *
1178             robust_cross_product(
1179                 static_cast<int_x2_type>(segm_end1.y()) -
1180                 static_cast<int_x2_type>(segm_start1.y()),
1181                 static_cast<int_x2_type>(segm_end1.x()) -
1182                 static_cast<int_x2_type>(segm_start1.x()),
1183                 static_cast<int_x2_type>(site1.y()) -
1184                 static_cast<int_x2_type>(segm_start2.y()),
1185                 static_cast<int_x2_type>(site1.x()) -
1186                 static_cast<int_x2_type>(segm_start2.x())),
1187             to_fpt(3.0));
1188         robust_dif_type t;
1189         t -= robust_fpt_type(a1) * robust_fpt_type((
1190              to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())) * to_fpt(0.5) -
1191              to_fpt(site1.x()));
1192         t -= robust_fpt_type(b1) * robust_fpt_type((
1193              to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())) * to_fpt(0.5) -
1194              to_fpt(site1.y()));
1195         if (point_index == 2) {
1196           t += det.sqrt();
1197         } else {
1198           t -= det.sqrt();
1199         }
1200         t /= a;
1201         robust_dif_type c_x, c_y;
1202         c_x += robust_fpt_type(to_fpt(0.5) * (
1203             to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())));
1204         c_x += robust_fpt_type(a1) * t;
1205         c_y += robust_fpt_type(to_fpt(0.5) * (
1206             to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())));
1207         c_y += robust_fpt_type(b1) * t;
1208         robust_dif_type lower_x(c_x);
1209         if (is_neg(c)) {
1210           lower_x -= robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
1211         } else {
1212           lower_x += robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
1213         }
1214         recompute_c_x = c_x.dif().ulp() > ULPS;
1215         recompute_c_y = c_y.dif().ulp() > ULPS;
1216         recompute_lower_x = lower_x.dif().ulp() > ULPS;
1217         c_event =
1218             circle_type(c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
1219       } else {
1220         robust_fpt_type sqr_sum1(get_sqrt(a1 * a1 + b1 * b1), to_fpt(2.0));
1221         robust_fpt_type sqr_sum2(get_sqrt(a2 * a2 + b2 * b2), to_fpt(2.0));
1222         robust_fpt_type a(robust_cross_product(
1223           static_cast<int_x2_type>(segm_end1.x()) -
1224           static_cast<int_x2_type>(segm_start1.x()),
1225           static_cast<int_x2_type>(segm_end1.y()) -
1226           static_cast<int_x2_type>(segm_start1.y()),
1227           static_cast<int_x2_type>(segm_start2.y()) -
1228           static_cast<int_x2_type>(segm_end2.y()),
1229           static_cast<int_x2_type>(segm_end2.x()) -
1230           static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
1231         if (!is_neg(a)) {
1232           a += sqr_sum1 * sqr_sum2;
1233         } else {
1234           a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a);
1235         }
1236         robust_fpt_type or1(robust_cross_product(
1237             static_cast<int_x2_type>(segm_end1.y()) -
1238             static_cast<int_x2_type>(segm_start1.y()),
1239             static_cast<int_x2_type>(segm_end1.x()) -
1240             static_cast<int_x2_type>(segm_start1.x()),
1241             static_cast<int_x2_type>(segm_end1.y()) -
1242             static_cast<int_x2_type>(site1.y()),
1243             static_cast<int_x2_type>(segm_end1.x()) -
1244             static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
1245         robust_fpt_type or2(robust_cross_product(
1246             static_cast<int_x2_type>(segm_end2.x()) -
1247             static_cast<int_x2_type>(segm_start2.x()),
1248             static_cast<int_x2_type>(segm_end2.y()) -
1249             static_cast<int_x2_type>(segm_start2.y()),
1250             static_cast<int_x2_type>(segm_end2.x()) -
1251             static_cast<int_x2_type>(site1.x()),
1252             static_cast<int_x2_type>(segm_end2.y()) -
1253             static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
1254         robust_fpt_type det = robust_fpt_type(to_fpt(2.0)) * a * or1 * or2;
1255         robust_fpt_type c1(robust_cross_product(
1256             static_cast<int_x2_type>(segm_end1.y()) -
1257             static_cast<int_x2_type>(segm_start1.y()),
1258             static_cast<int_x2_type>(segm_end1.x()) -
1259             static_cast<int_x2_type>(segm_start1.x()),
1260             static_cast<int_x2_type>(segm_end1.y()),
1261             static_cast<int_x2_type>(segm_end1.x())), to_fpt(1.0));
1262         robust_fpt_type c2(robust_cross_product(
1263             static_cast<int_x2_type>(segm_end2.x()) -
1264             static_cast<int_x2_type>(segm_start2.x()),
1265             static_cast<int_x2_type>(segm_end2.y()) -
1266             static_cast<int_x2_type>(segm_start2.y()),
1267             static_cast<int_x2_type>(segm_end2.x()),
1268             static_cast<int_x2_type>(segm_end2.y())), to_fpt(1.0));
1269         robust_fpt_type inv_orientation =
1270             robust_fpt_type(to_fpt(1.0)) / orientation;
1271         robust_dif_type t, b, ix, iy;
1272         ix += robust_fpt_type(a2) * c1 * inv_orientation;
1273         ix += robust_fpt_type(a1) * c2 * inv_orientation;
1274         iy += robust_fpt_type(b1) * c2 * inv_orientation;
1275         iy += robust_fpt_type(b2) * c1 * inv_orientation;
1276 
1277         b += ix * (robust_fpt_type(a1) * sqr_sum2);
1278         b += ix * (robust_fpt_type(a2) * sqr_sum1);
1279         b += iy * (robust_fpt_type(b1) * sqr_sum2);
1280         b += iy * (robust_fpt_type(b2) * sqr_sum1);
1281         b -= sqr_sum1 * robust_fpt_type(robust_cross_product(
1282             static_cast<int_x2_type>(segm_end2.x()) -
1283             static_cast<int_x2_type>(segm_start2.x()),
1284             static_cast<int_x2_type>(segm_end2.y()) -
1285             static_cast<int_x2_type>(segm_start2.y()),
1286             static_cast<int_x2_type>(-site1.y()),
1287             static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
1288         b -= sqr_sum2 * robust_fpt_type(robust_cross_product(
1289             static_cast<int_x2_type>(segm_end1.x()) -
1290             static_cast<int_x2_type>(segm_start1.x()),
1291             static_cast<int_x2_type>(segm_end1.y()) -
1292             static_cast<int_x2_type>(segm_start1.y()),
1293             static_cast<int_x2_type>(-site1.y()),
1294             static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
1295         t -= b;
1296         if (point_index == 2) {
1297           t += det.sqrt();
1298         } else {
1299           t -= det.sqrt();
1300         }
1301         t /= (a * a);
1302         robust_dif_type c_x(ix), c_y(iy);
1303         c_x += t * (robust_fpt_type(a1) * sqr_sum2);
1304         c_x += t * (robust_fpt_type(a2) * sqr_sum1);
1305         c_y += t * (robust_fpt_type(b1) * sqr_sum2);
1306         c_y += t * (robust_fpt_type(b2) * sqr_sum1);
1307         if (t.pos().fpv() < t.neg().fpv()) {
1308           t = -t;
1309         }
1310         robust_dif_type lower_x(c_x);
1311         if (is_neg(orientation)) {
1312           lower_x -= t * orientation;
1313         } else {
1314           lower_x += t * orientation;
1315         }
1316         recompute_c_x = c_x.dif().ulp() > ULPS;
1317         recompute_c_y = c_y.dif().ulp() > ULPS;
1318         recompute_lower_x = lower_x.dif().ulp() > ULPS;
1319         c_event = circle_type(
1320             c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
1321       }
1322       if (recompute_c_x || recompute_c_y || recompute_lower_x) {
1323           exact_circle_formation_functor_.pss(
1324               site1, site2, site3, point_index, c_event,
1325         recompute_c_x, recompute_c_y, recompute_lower_x);
1326       }
1327     }
1328 
1329     void sss(const site_type& site1,
1330              const site_type& site2,
1331              const site_type& site3,
1332              circle_type& c_event) {
1333       robust_fpt_type a1(to_fpt(site1.x1()) - to_fpt(site1.x0()));
1334       robust_fpt_type b1(to_fpt(site1.y1()) - to_fpt(site1.y0()));
1335       robust_fpt_type c1(robust_cross_product(
1336           site1.x0(), site1.y0(),
1337           site1.x1(), site1.y1()), to_fpt(1.0));
1338 
1339       robust_fpt_type a2(to_fpt(site2.x1()) - to_fpt(site2.x0()));
1340       robust_fpt_type b2(to_fpt(site2.y1()) - to_fpt(site2.y0()));
1341       robust_fpt_type c2(robust_cross_product(
1342           site2.x0(), site2.y0(),
1343           site2.x1(), site2.y1()), to_fpt(1.0));
1344 
1345       robust_fpt_type a3(to_fpt(site3.x1()) - to_fpt(site3.x0()));
1346       robust_fpt_type b3(to_fpt(site3.y1()) - to_fpt(site3.y0()));
1347       robust_fpt_type c3(robust_cross_product(
1348           site3.x0(), site3.y0(),
1349           site3.x1(), site3.y1()), to_fpt(1.0));
1350 
1351       robust_fpt_type len1 = (a1 * a1 + b1 * b1).sqrt();
1352       robust_fpt_type len2 = (a2 * a2 + b2 * b2).sqrt();
1353       robust_fpt_type len3 = (a3 * a3 + b3 * b3).sqrt();
1354       robust_fpt_type cross_12(robust_cross_product(
1355           static_cast<int_x2_type>(site1.x1()) -
1356           static_cast<int_x2_type>(site1.x0()),
1357           static_cast<int_x2_type>(site1.y1()) -
1358           static_cast<int_x2_type>(site1.y0()),
1359           static_cast<int_x2_type>(site2.x1()) -
1360           static_cast<int_x2_type>(site2.x0()),
1361           static_cast<int_x2_type>(site2.y1()) -
1362           static_cast<int_x2_type>(site2.y0())), to_fpt(1.0));
1363       robust_fpt_type cross_23(robust_cross_product(
1364           static_cast<int_x2_type>(site2.x1()) -
1365           static_cast<int_x2_type>(site2.x0()),
1366           static_cast<int_x2_type>(site2.y1()) -
1367           static_cast<int_x2_type>(site2.y0()),
1368           static_cast<int_x2_type>(site3.x1()) -
1369           static_cast<int_x2_type>(site3.x0()),
1370           static_cast<int_x2_type>(site3.y1()) -
1371           static_cast<int_x2_type>(site3.y0())), to_fpt(1.0));
1372       robust_fpt_type cross_31(robust_cross_product(
1373           static_cast<int_x2_type>(site3.x1()) -
1374           static_cast<int_x2_type>(site3.x0()),
1375           static_cast<int_x2_type>(site3.y1()) -
1376           static_cast<int_x2_type>(site3.y0()),
1377           static_cast<int_x2_type>(site1.x1()) -
1378           static_cast<int_x2_type>(site1.x0()),
1379           static_cast<int_x2_type>(site1.y1()) -
1380           static_cast<int_x2_type>(site1.y0())), to_fpt(1.0));
1381 
1382       // denom = cross_12 * len3 + cross_23 * len1 + cross_31 * len2.
1383       robust_dif_type denom;
1384       denom += cross_12 * len3;
1385       denom += cross_23 * len1;
1386       denom += cross_31 * len2;
1387 
1388       // denom * r = (b2 * c_x - a2 * c_y - c2 * denom) / len2.
1389       robust_dif_type r;
1390       r -= cross_12 * c3;
1391       r -= cross_23 * c1;
1392       r -= cross_31 * c2;
1393 
1394       robust_dif_type c_x;
1395       c_x += a1 * c2 * len3;
1396       c_x -= a2 * c1 * len3;
1397       c_x += a2 * c3 * len1;
1398       c_x -= a3 * c2 * len1;
1399       c_x += a3 * c1 * len2;
1400       c_x -= a1 * c3 * len2;
1401 
1402       robust_dif_type c_y;
1403       c_y += b1 * c2 * len3;
1404       c_y -= b2 * c1 * len3;
1405       c_y += b2 * c3 * len1;
1406       c_y -= b3 * c2 * len1;
1407       c_y += b3 * c1 * len2;
1408       c_y -= b1 * c3 * len2;
1409 
1410       robust_dif_type lower_x = c_x + r;
1411 
1412       robust_fpt_type denom_dif = denom.dif();
1413       robust_fpt_type c_x_dif = c_x.dif() / denom_dif;
1414       robust_fpt_type c_y_dif = c_y.dif() / denom_dif;
1415       robust_fpt_type lower_x_dif = lower_x.dif() / denom_dif;
1416 
1417       bool recompute_c_x = c_x_dif.ulp() > ULPS;
1418       bool recompute_c_y = c_y_dif.ulp() > ULPS;
1419       bool recompute_lower_x = lower_x_dif.ulp() > ULPS;
1420       c_event = circle_type(c_x_dif.fpv(), c_y_dif.fpv(), lower_x_dif.fpv());
1421       if (recompute_c_x || recompute_c_y || recompute_lower_x) {
1422         exact_circle_formation_functor_.sss(
1423             site1, site2, site3, c_event,
1424             recompute_c_x, recompute_c_y, recompute_lower_x);
1425       }
1426     }
1427 
1428    private:
1429     exact_circle_formation_functor_type exact_circle_formation_functor_;
1430     to_fpt_converter to_fpt;
1431   };
1432 
1433   template <typename Site,
1434             typename Circle,
1435             typename CEP = circle_existence_predicate<Site>,
1436             typename CFF = lazy_circle_formation_functor<Site, Circle> >
1437   class circle_formation_predicate {
1438    public:
1439     typedef Site site_type;
1440     typedef Circle circle_type;
1441     typedef CEP circle_existence_predicate_type;
1442     typedef CFF circle_formation_functor_type;
1443 
1444     // Create a circle event from the given three sites.
1445     // Returns true if the circle event exists, else false.
1446     // If exists circle event is saved into the c_event variable.
1447     bool operator()(const site_type& site1, const site_type& site2,
1448                     const site_type& site3, circle_type& circle) {
1449       if (!site1.is_segment()) {
1450         if (!site2.is_segment()) {
1451           if (!site3.is_segment()) {
1452             // (point, point, point) sites.
1453             if (!circle_existence_predicate_.ppp(site1, site2, site3))
1454               return false;
1455             circle_formation_functor_.ppp(site1, site2, site3, circle);
1456           } else {
1457             // (point, point, segment) sites.
1458             if (!circle_existence_predicate_.pps(site1, site2, site3, 3))
1459               return false;
1460             circle_formation_functor_.pps(site1, site2, site3, 3, circle);
1461           }
1462         } else {
1463           if (!site3.is_segment()) {
1464             // (point, segment, point) sites.
1465             if (!circle_existence_predicate_.pps(site1, site3, site2, 2))
1466               return false;
1467             circle_formation_functor_.pps(site1, site3, site2, 2, circle);
1468           } else {
1469             // (point, segment, segment) sites.
1470             if (!circle_existence_predicate_.pss(site1, site2, site3, 1))
1471               return false;
1472             circle_formation_functor_.pss(site1, site2, site3, 1, circle);
1473           }
1474         }
1475       } else {
1476         if (!site2.is_segment()) {
1477           if (!site3.is_segment()) {
1478             // (segment, point, point) sites.
1479             if (!circle_existence_predicate_.pps(site2, site3, site1, 1))
1480               return false;
1481             circle_formation_functor_.pps(site2, site3, site1, 1, circle);
1482           } else {
1483             // (segment, point, segment) sites.
1484             if (!circle_existence_predicate_.pss(site2, site1, site3, 2))
1485               return false;
1486             circle_formation_functor_.pss(site2, site1, site3, 2, circle);
1487           }
1488         } else {
1489           if (!site3.is_segment()) {
1490             // (segment, segment, point) sites.
1491             if (!circle_existence_predicate_.pss(site3, site1, site2, 3))
1492               return false;
1493             circle_formation_functor_.pss(site3, site1, site2, 3, circle);
1494           } else {
1495             // (segment, segment, segment) sites.
1496             if (!circle_existence_predicate_.sss(site1, site2, site3))
1497               return false;
1498             circle_formation_functor_.sss(site1, site2, site3, circle);
1499           }
1500         }
1501       }
1502       if (lies_outside_vertical_segment(circle, site1) ||
1503           lies_outside_vertical_segment(circle, site2) ||
1504           lies_outside_vertical_segment(circle, site3)) {
1505         return false;
1506       }
1507       return true;
1508     }
1509 
1510    private:
1511     bool lies_outside_vertical_segment(
1512         const circle_type& c, const site_type& s) {
1513       if (!s.is_segment() || !is_vertical(s)) {
1514         return false;
1515       }
1516       fpt_type y0 = to_fpt(s.is_inverse() ? s.y1() : s.y0());
1517       fpt_type y1 = to_fpt(s.is_inverse() ? s.y0() : s.y1());
1518       return ulp_cmp(c.y(), y0, ULPS) == ulp_cmp_type::LESS ||
1519              ulp_cmp(c.y(), y1, ULPS) == ulp_cmp_type::MORE;
1520     }
1521 
1522    private:
1523     to_fpt_converter to_fpt;
1524     ulp_cmp_type ulp_cmp;
1525     circle_existence_predicate_type circle_existence_predicate_;
1526     circle_formation_functor_type circle_formation_functor_;
1527   };
1528 };
1529 }  // detail
1530 }  // polygon
1531 }  // boost
1532 
1533 #endif  // BOOST_POLYGON_DETAIL_VORONOI_PREDICATES