voronoi_predicates.hpp 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533
  1. // Boost.Polygon library detail/voronoi_predicates.hpp header file
  2. // Copyright Andrii Sydorchuk 2010-2012.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for updates, documentation, and revision history.
  7. #ifndef BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
  8. #define BOOST_POLYGON_DETAIL_VORONOI_PREDICATES
  9. #include <utility>
  10. #include "voronoi_robust_fpt.hpp"
  11. namespace boost {
  12. namespace polygon {
  13. namespace detail {
  14. // Predicate utilities. Operates with the coordinate types that could
  15. // be converted to the 32-bit signed integer without precision loss.
  16. template <typename CTYPE_TRAITS>
  17. class voronoi_predicates {
  18. public:
  19. typedef typename CTYPE_TRAITS::int_type int_type;
  20. typedef typename CTYPE_TRAITS::int_x2_type int_x2_type;
  21. typedef typename CTYPE_TRAITS::uint_x2_type uint_x2_type;
  22. typedef typename CTYPE_TRAITS::big_int_type big_int_type;
  23. typedef typename CTYPE_TRAITS::fpt_type fpt_type;
  24. typedef typename CTYPE_TRAITS::efpt_type efpt_type;
  25. typedef typename CTYPE_TRAITS::ulp_cmp_type ulp_cmp_type;
  26. typedef typename CTYPE_TRAITS::to_fpt_converter_type to_fpt_converter;
  27. typedef typename CTYPE_TRAITS::to_efpt_converter_type to_efpt_converter;
  28. enum {
  29. ULPS = 64,
  30. ULPSx2 = 128
  31. };
  32. template <typename Point>
  33. static bool is_vertical(const Point& point1, const Point& point2) {
  34. return point1.x() == point2.x();
  35. }
  36. template <typename Site>
  37. static bool is_vertical(const Site& site) {
  38. return is_vertical(site.point0(), site.point1());
  39. }
  40. // Compute robust cross_product: a1 * b2 - b1 * a2.
  41. // It was mathematically proven that the result is correct
  42. // with epsilon relative error equal to 1EPS.
  43. static fpt_type robust_cross_product(int_x2_type a1_,
  44. int_x2_type b1_,
  45. int_x2_type a2_,
  46. int_x2_type b2_) {
  47. static to_fpt_converter to_fpt;
  48. uint_x2_type a1 = static_cast<uint_x2_type>(is_neg(a1_) ? -a1_ : a1_);
  49. uint_x2_type b1 = static_cast<uint_x2_type>(is_neg(b1_) ? -b1_ : b1_);
  50. uint_x2_type a2 = static_cast<uint_x2_type>(is_neg(a2_) ? -a2_ : a2_);
  51. uint_x2_type b2 = static_cast<uint_x2_type>(is_neg(b2_) ? -b2_ : b2_);
  52. uint_x2_type l = a1 * b2;
  53. uint_x2_type r = b1 * a2;
  54. if (is_neg(a1_) ^ is_neg(b2_)) {
  55. if (is_neg(a2_) ^ is_neg(b1_))
  56. return (l > r) ? -to_fpt(l - r) : to_fpt(r - l);
  57. else
  58. return -to_fpt(l + r);
  59. } else {
  60. if (is_neg(a2_) ^ is_neg(b1_))
  61. return to_fpt(l + r);
  62. else
  63. return (l < r) ? -to_fpt(r - l) : to_fpt(l - r);
  64. }
  65. }
  66. struct orientation_test {
  67. public:
  68. // Represents orientation test result.
  69. enum Orientation {
  70. RIGHT = -1,
  71. COLLINEAR = 0,
  72. LEFT = 1
  73. };
  74. // Value is a determinant of two vectors (e.g. x1 * y2 - x2 * y1).
  75. // Return orientation based on the sign of the determinant.
  76. template <typename T>
  77. static Orientation eval(T value) {
  78. if (is_zero(value)) return COLLINEAR;
  79. return (is_neg(value)) ? RIGHT : LEFT;
  80. }
  81. static Orientation eval(int_x2_type dif_x1_,
  82. int_x2_type dif_y1_,
  83. int_x2_type dif_x2_,
  84. int_x2_type dif_y2_) {
  85. return eval(robust_cross_product(dif_x1_, dif_y1_, dif_x2_, dif_y2_));
  86. }
  87. template <typename Point>
  88. static Orientation eval(const Point& point1,
  89. const Point& point2,
  90. const Point& point3) {
  91. int_x2_type dx1 = static_cast<int_x2_type>(point1.x()) -
  92. static_cast<int_x2_type>(point2.x());
  93. int_x2_type dx2 = static_cast<int_x2_type>(point2.x()) -
  94. static_cast<int_x2_type>(point3.x());
  95. int_x2_type dy1 = static_cast<int_x2_type>(point1.y()) -
  96. static_cast<int_x2_type>(point2.y());
  97. int_x2_type dy2 = static_cast<int_x2_type>(point2.y()) -
  98. static_cast<int_x2_type>(point3.y());
  99. return eval(robust_cross_product(dx1, dy1, dx2, dy2));
  100. }
  101. };
  102. typedef orientation_test ot;
  103. template <typename Point>
  104. class point_comparison_predicate {
  105. public:
  106. typedef Point point_type;
  107. bool operator()(const point_type& lhs, const point_type& rhs) const {
  108. if (lhs.x() == rhs.x())
  109. return lhs.y() < rhs.y();
  110. return lhs.x() < rhs.x();
  111. }
  112. };
  113. template <typename Site, typename Circle>
  114. class event_comparison_predicate {
  115. public:
  116. typedef Site site_type;
  117. typedef Circle circle_type;
  118. bool operator()(const site_type& lhs, const site_type& rhs) const {
  119. if (lhs.x0() != rhs.x0())
  120. return lhs.x0() < rhs.x0();
  121. if (!lhs.is_segment()) {
  122. if (!rhs.is_segment())
  123. return lhs.y0() < rhs.y0();
  124. if (is_vertical(rhs))
  125. return lhs.y0() <= rhs.y0();
  126. return true;
  127. } else {
  128. if (is_vertical(rhs)) {
  129. if (is_vertical(lhs))
  130. return lhs.y0() < rhs.y0();
  131. return false;
  132. }
  133. if (is_vertical(lhs))
  134. return true;
  135. if (lhs.y0() != rhs.y0())
  136. return lhs.y0() < rhs.y0();
  137. return ot::eval(lhs.point1(), lhs.point0(), rhs.point1()) == ot::LEFT;
  138. }
  139. }
  140. bool operator()(const site_type& lhs, const circle_type& rhs) const {
  141. typename ulp_cmp_type::Result xCmp =
  142. ulp_cmp(to_fpt(lhs.x0()), to_fpt(rhs.lower_x()), ULPS);
  143. return xCmp == ulp_cmp_type::LESS;
  144. }
  145. bool operator()(const circle_type& lhs, const site_type& rhs) const {
  146. typename ulp_cmp_type::Result xCmp =
  147. ulp_cmp(to_fpt(lhs.lower_x()), to_fpt(rhs.x0()), ULPS);
  148. return xCmp == ulp_cmp_type::LESS;
  149. }
  150. bool operator()(const circle_type& lhs, const circle_type& rhs) const {
  151. if (lhs.lower_x() != rhs.lower_x()) {
  152. return lhs.lower_x() < rhs.lower_x();
  153. }
  154. return lhs.y() < rhs.y();
  155. }
  156. private:
  157. ulp_cmp_type ulp_cmp;
  158. to_fpt_converter to_fpt;
  159. };
  160. template <typename Site>
  161. class distance_predicate {
  162. public:
  163. typedef Site site_type;
  164. typedef typename site_type::point_type point_type;
  165. // Returns true if a horizontal line going through a new site intersects
  166. // right arc at first, else returns false. If horizontal line goes
  167. // through intersection point of the given two arcs returns false also.
  168. bool operator()(const site_type& left_site,
  169. const site_type& right_site,
  170. const point_type& new_point) const {
  171. if (!left_site.is_segment()) {
  172. if (!right_site.is_segment()) {
  173. return pp(left_site, right_site, new_point);
  174. } else {
  175. return ps(left_site, right_site, new_point, false);
  176. }
  177. } else {
  178. if (!right_site.is_segment()) {
  179. return ps(right_site, left_site, new_point, true);
  180. } else {
  181. return ss(left_site, right_site, new_point);
  182. }
  183. }
  184. }
  185. private:
  186. // Represents the result of the epsilon robust predicate. If the
  187. // result is undefined some further processing is usually required.
  188. enum kPredicateResult {
  189. LESS = -1,
  190. UNDEFINED = 0,
  191. MORE = 1
  192. };
  193. // Robust predicate, avoids using high-precision libraries.
  194. // Returns true if a horizontal line going through the new point site
  195. // intersects right arc at first, else returns false. If horizontal line
  196. // goes through intersection point of the given two arcs returns false.
  197. bool pp(const site_type& left_site,
  198. const site_type& right_site,
  199. const point_type& new_point) const {
  200. const point_type& left_point = left_site.point0();
  201. const point_type& right_point = right_site.point0();
  202. if (left_point.x() > right_point.x()) {
  203. if (new_point.y() <= left_point.y())
  204. return false;
  205. } else if (left_point.x() < right_point.x()) {
  206. if (new_point.y() >= right_point.y())
  207. return true;
  208. } else {
  209. return static_cast<int_x2_type>(left_point.y()) +
  210. static_cast<int_x2_type>(right_point.y()) <
  211. static_cast<int_x2_type>(new_point.y()) * 2;
  212. }
  213. fpt_type dist1 = find_distance_to_point_arc(left_site, new_point);
  214. fpt_type dist2 = find_distance_to_point_arc(right_site, new_point);
  215. // The undefined ulp range is equal to 3EPS + 3EPS <= 6ULP.
  216. return dist1 < dist2;
  217. }
  218. bool ps(const site_type& left_site, const site_type& right_site,
  219. const point_type& new_point, bool reverse_order) const {
  220. kPredicateResult fast_res = fast_ps(
  221. left_site, right_site, new_point, reverse_order);
  222. if (fast_res != UNDEFINED) {
  223. return fast_res == LESS;
  224. }
  225. fpt_type dist1 = find_distance_to_point_arc(left_site, new_point);
  226. fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point);
  227. // The undefined ulp range is equal to 3EPS + 7EPS <= 10ULP.
  228. return reverse_order ^ (dist1 < dist2);
  229. }
  230. bool ss(const site_type& left_site,
  231. const site_type& right_site,
  232. const point_type& new_point) const {
  233. // Handle temporary segment sites.
  234. if (left_site.sorted_index() == right_site.sorted_index()) {
  235. return ot::eval(
  236. left_site.point0(), left_site.point1(), new_point) == ot::LEFT;
  237. }
  238. fpt_type dist1 = find_distance_to_segment_arc(left_site, new_point);
  239. fpt_type dist2 = find_distance_to_segment_arc(right_site, new_point);
  240. // The undefined ulp range is equal to 7EPS + 7EPS <= 14ULP.
  241. return dist1 < dist2;
  242. }
  243. fpt_type find_distance_to_point_arc(
  244. const site_type& site, const point_type& point) const {
  245. fpt_type dx = to_fpt(site.x()) - to_fpt(point.x());
  246. fpt_type dy = to_fpt(site.y()) - to_fpt(point.y());
  247. // The relative error is at most 3EPS.
  248. return (dx * dx + dy * dy) / (to_fpt(2.0) * dx);
  249. }
  250. fpt_type find_distance_to_segment_arc(
  251. const site_type& site, const point_type& point) const {
  252. if (is_vertical(site)) {
  253. return (to_fpt(site.x()) - to_fpt(point.x())) * to_fpt(0.5);
  254. } else {
  255. const point_type& segment0 = site.point0();
  256. const point_type& segment1 = site.point1();
  257. fpt_type a1 = to_fpt(segment1.x()) - to_fpt(segment0.x());
  258. fpt_type b1 = to_fpt(segment1.y()) - to_fpt(segment0.y());
  259. fpt_type k = get_sqrt(a1 * a1 + b1 * b1);
  260. // Avoid subtraction while computing k.
  261. if (!is_neg(b1)) {
  262. k = to_fpt(1.0) / (b1 + k);
  263. } else {
  264. k = (k - b1) / (a1 * a1);
  265. }
  266. // The relative error is at most 7EPS.
  267. return k * robust_cross_product(
  268. static_cast<int_x2_type>(segment1.x()) -
  269. static_cast<int_x2_type>(segment0.x()),
  270. static_cast<int_x2_type>(segment1.y()) -
  271. static_cast<int_x2_type>(segment0.y()),
  272. static_cast<int_x2_type>(point.x()) -
  273. static_cast<int_x2_type>(segment0.x()),
  274. static_cast<int_x2_type>(point.y()) -
  275. static_cast<int_x2_type>(segment0.y()));
  276. }
  277. }
  278. kPredicateResult fast_ps(
  279. const site_type& left_site, const site_type& right_site,
  280. const point_type& new_point, bool reverse_order) const {
  281. const point_type& site_point = left_site.point0();
  282. const point_type& segment_start = right_site.point0();
  283. const point_type& segment_end = right_site.point1();
  284. if (ot::eval(segment_start, segment_end, new_point) != ot::RIGHT)
  285. return (!right_site.is_inverse()) ? LESS : MORE;
  286. fpt_type dif_x = to_fpt(new_point.x()) - to_fpt(site_point.x());
  287. fpt_type dif_y = to_fpt(new_point.y()) - to_fpt(site_point.y());
  288. fpt_type a = to_fpt(segment_end.x()) - to_fpt(segment_start.x());
  289. fpt_type b = to_fpt(segment_end.y()) - to_fpt(segment_start.y());
  290. if (is_vertical(right_site)) {
  291. if (new_point.y() < site_point.y() && !reverse_order)
  292. return MORE;
  293. else if (new_point.y() > site_point.y() && reverse_order)
  294. return LESS;
  295. return UNDEFINED;
  296. } else {
  297. typename ot::Orientation orientation = ot::eval(
  298. static_cast<int_x2_type>(segment_end.x()) -
  299. static_cast<int_x2_type>(segment_start.x()),
  300. static_cast<int_x2_type>(segment_end.y()) -
  301. static_cast<int_x2_type>(segment_start.y()),
  302. static_cast<int_x2_type>(new_point.x()) -
  303. static_cast<int_x2_type>(site_point.x()),
  304. static_cast<int_x2_type>(new_point.y()) -
  305. static_cast<int_x2_type>(site_point.y()));
  306. if (orientation == ot::LEFT) {
  307. if (!right_site.is_inverse())
  308. return reverse_order ? LESS : UNDEFINED;
  309. return reverse_order ? UNDEFINED : MORE;
  310. }
  311. }
  312. fpt_type fast_left_expr = a * (dif_y + dif_x) * (dif_y - dif_x);
  313. fpt_type fast_right_expr = (to_fpt(2.0) * b) * dif_x * dif_y;
  314. typename ulp_cmp_type::Result expr_cmp =
  315. ulp_cmp(fast_left_expr, fast_right_expr, 4);
  316. if (expr_cmp != ulp_cmp_type::EQUAL) {
  317. if ((expr_cmp == ulp_cmp_type::MORE) ^ reverse_order)
  318. return reverse_order ? LESS : MORE;
  319. return UNDEFINED;
  320. }
  321. return UNDEFINED;
  322. }
  323. private:
  324. ulp_cmp_type ulp_cmp;
  325. to_fpt_converter to_fpt;
  326. };
  327. template <typename Node>
  328. class node_comparison_predicate {
  329. public:
  330. typedef Node node_type;
  331. typedef typename Node::site_type site_type;
  332. typedef typename site_type::point_type point_type;
  333. typedef typename point_type::coordinate_type coordinate_type;
  334. typedef point_comparison_predicate<point_type> point_comparison_type;
  335. typedef distance_predicate<site_type> distance_predicate_type;
  336. // Compares nodes in the balanced binary search tree. Nodes are
  337. // compared based on the y coordinates of the arcs intersection points.
  338. // Nodes with less y coordinate of the intersection point go first.
  339. // Comparison is only called during the new site events processing.
  340. // That's why one of the nodes will always lie on the sweepline and may
  341. // be represented as a straight horizontal line.
  342. bool operator() (const node_type& node1,
  343. const node_type& node2) const {
  344. // Get x coordinate of the rightmost site from both nodes.
  345. const site_type& site1 = get_comparison_site(node1);
  346. const site_type& site2 = get_comparison_site(node2);
  347. const point_type& point1 = get_comparison_point(site1);
  348. const point_type& point2 = get_comparison_point(site2);
  349. if (point1.x() < point2.x()) {
  350. // The second node contains a new site.
  351. return distance_predicate_(
  352. node1.left_site(), node1.right_site(), point2);
  353. } else if (point1.x() > point2.x()) {
  354. // The first node contains a new site.
  355. return !distance_predicate_(
  356. node2.left_site(), node2.right_site(), point1);
  357. } else {
  358. // This checks were evaluated experimentally.
  359. if (site1.sorted_index() == site2.sorted_index()) {
  360. // Both nodes are new (inserted during same site event processing).
  361. return get_comparison_y(node1) < get_comparison_y(node2);
  362. } else if (site1.sorted_index() < site2.sorted_index()) {
  363. std::pair<coordinate_type, int> y1 = get_comparison_y(node1, false);
  364. std::pair<coordinate_type, int> y2 = get_comparison_y(node2, true);
  365. if (y1.first != y2.first) return y1.first < y2.first;
  366. return (!site1.is_segment()) ? (y1.second < 0) : false;
  367. } else {
  368. std::pair<coordinate_type, int> y1 = get_comparison_y(node1, true);
  369. std::pair<coordinate_type, int> y2 = get_comparison_y(node2, false);
  370. if (y1.first != y2.first) return y1.first < y2.first;
  371. return (!site2.is_segment()) ? (y2.second > 0) : true;
  372. }
  373. }
  374. }
  375. private:
  376. // Get the newer site.
  377. const site_type& get_comparison_site(const node_type& node) const {
  378. if (node.left_site().sorted_index() > node.right_site().sorted_index()) {
  379. return node.left_site();
  380. }
  381. return node.right_site();
  382. }
  383. const point_type& get_comparison_point(const site_type& site) const {
  384. return point_comparison_(site.point0(), site.point1()) ?
  385. site.point0() : site.point1();
  386. }
  387. // Get comparison pair: y coordinate and direction of the newer site.
  388. std::pair<coordinate_type, int> get_comparison_y(
  389. const node_type& node, bool is_new_node = true) const {
  390. if (node.left_site().sorted_index() ==
  391. node.right_site().sorted_index()) {
  392. return std::make_pair(node.left_site().y0(), 0);
  393. }
  394. if (node.left_site().sorted_index() > node.right_site().sorted_index()) {
  395. if (!is_new_node &&
  396. node.left_site().is_segment() &&
  397. is_vertical(node.left_site())) {
  398. return std::make_pair(node.left_site().y0(), 1);
  399. }
  400. return std::make_pair(node.left_site().y1(), 1);
  401. }
  402. return std::make_pair(node.right_site().y0(), -1);
  403. }
  404. point_comparison_type point_comparison_;
  405. distance_predicate_type distance_predicate_;
  406. };
  407. template <typename Site>
  408. class circle_existence_predicate {
  409. public:
  410. typedef typename Site::point_type point_type;
  411. typedef Site site_type;
  412. bool ppp(const site_type& site1,
  413. const site_type& site2,
  414. const site_type& site3) const {
  415. return ot::eval(site1.point0(),
  416. site2.point0(),
  417. site3.point0()) == ot::RIGHT;
  418. }
  419. bool pps(const site_type& site1,
  420. const site_type& site2,
  421. const site_type& site3,
  422. int segment_index) const {
  423. if (segment_index != 2) {
  424. typename ot::Orientation orient1 = ot::eval(
  425. site1.point0(), site2.point0(), site3.point0());
  426. typename ot::Orientation orient2 = ot::eval(
  427. site1.point0(), site2.point0(), site3.point1());
  428. if (segment_index == 1 && site1.x0() >= site2.x0()) {
  429. if (orient1 != ot::RIGHT)
  430. return false;
  431. } else if (segment_index == 3 && site2.x0() >= site1.x0()) {
  432. if (orient2 != ot::RIGHT)
  433. return false;
  434. } else if (orient1 != ot::RIGHT && orient2 != ot::RIGHT) {
  435. return false;
  436. }
  437. } else {
  438. return (site3.point0() != site1.point0()) ||
  439. (site3.point1() != site2.point0());
  440. }
  441. return true;
  442. }
  443. bool pss(const site_type& site1,
  444. const site_type& site2,
  445. const site_type& site3,
  446. int point_index) const {
  447. if (site2.sorted_index() == site3.sorted_index()) {
  448. return false;
  449. }
  450. if (point_index == 2) {
  451. if (!site2.is_inverse() && site3.is_inverse())
  452. return false;
  453. if (site2.is_inverse() == site3.is_inverse() &&
  454. ot::eval(site2.point0(),
  455. site1.point0(),
  456. site3.point1()) != ot::RIGHT)
  457. return false;
  458. }
  459. return true;
  460. }
  461. bool sss(const site_type& site1,
  462. const site_type& site2,
  463. const site_type& site3) const {
  464. return (site1.sorted_index() != site2.sorted_index()) &&
  465. (site2.sorted_index() != site3.sorted_index());
  466. }
  467. };
  468. template <typename Site, typename Circle>
  469. class mp_circle_formation_functor {
  470. public:
  471. typedef typename Site::point_type point_type;
  472. typedef Site site_type;
  473. typedef Circle circle_type;
  474. typedef robust_sqrt_expr<big_int_type, efpt_type, to_efpt_converter>
  475. robust_sqrt_expr_type;
  476. void ppp(const site_type& site1,
  477. const site_type& site2,
  478. const site_type& site3,
  479. circle_type& circle,
  480. bool recompute_c_x = true,
  481. bool recompute_c_y = true,
  482. bool recompute_lower_x = true) {
  483. big_int_type dif_x[3], dif_y[3], sum_x[2], sum_y[2];
  484. dif_x[0] = static_cast<int_x2_type>(site1.x()) -
  485. static_cast<int_x2_type>(site2.x());
  486. dif_x[1] = static_cast<int_x2_type>(site2.x()) -
  487. static_cast<int_x2_type>(site3.x());
  488. dif_x[2] = static_cast<int_x2_type>(site1.x()) -
  489. static_cast<int_x2_type>(site3.x());
  490. dif_y[0] = static_cast<int_x2_type>(site1.y()) -
  491. static_cast<int_x2_type>(site2.y());
  492. dif_y[1] = static_cast<int_x2_type>(site2.y()) -
  493. static_cast<int_x2_type>(site3.y());
  494. dif_y[2] = static_cast<int_x2_type>(site1.y()) -
  495. static_cast<int_x2_type>(site3.y());
  496. sum_x[0] = static_cast<int_x2_type>(site1.x()) +
  497. static_cast<int_x2_type>(site2.x());
  498. sum_x[1] = static_cast<int_x2_type>(site2.x()) +
  499. static_cast<int_x2_type>(site3.x());
  500. sum_y[0] = static_cast<int_x2_type>(site1.y()) +
  501. static_cast<int_x2_type>(site2.y());
  502. sum_y[1] = static_cast<int_x2_type>(site2.y()) +
  503. static_cast<int_x2_type>(site3.y());
  504. fpt_type inv_denom = to_fpt(0.5) / to_fpt(static_cast<big_int_type>(
  505. dif_x[0] * dif_y[1] - dif_x[1] * dif_y[0]));
  506. big_int_type numer1 = dif_x[0] * sum_x[0] + dif_y[0] * sum_y[0];
  507. big_int_type numer2 = dif_x[1] * sum_x[1] + dif_y[1] * sum_y[1];
  508. if (recompute_c_x || recompute_lower_x) {
  509. big_int_type c_x = numer1 * dif_y[1] - numer2 * dif_y[0];
  510. circle.x(to_fpt(c_x) * inv_denom);
  511. if (recompute_lower_x) {
  512. // Evaluate radius of the circle.
  513. big_int_type sqr_r = (dif_x[0] * dif_x[0] + dif_y[0] * dif_y[0]) *
  514. (dif_x[1] * dif_x[1] + dif_y[1] * dif_y[1]) *
  515. (dif_x[2] * dif_x[2] + dif_y[2] * dif_y[2]);
  516. fpt_type r = get_sqrt(to_fpt(sqr_r));
  517. // If c_x >= 0 then lower_x = c_x + r,
  518. // else lower_x = (c_x * c_x - r * r) / (c_x - r).
  519. // To guarantee epsilon relative error.
  520. if (!is_neg(circle.x())) {
  521. if (!is_neg(inv_denom)) {
  522. circle.lower_x(circle.x() + r * inv_denom);
  523. } else {
  524. circle.lower_x(circle.x() - r * inv_denom);
  525. }
  526. } else {
  527. big_int_type numer = c_x * c_x - sqr_r;
  528. fpt_type lower_x = to_fpt(numer) * inv_denom / (to_fpt(c_x) + r);
  529. circle.lower_x(lower_x);
  530. }
  531. }
  532. }
  533. if (recompute_c_y) {
  534. big_int_type c_y = numer2 * dif_x[0] - numer1 * dif_x[1];
  535. circle.y(to_fpt(c_y) * inv_denom);
  536. }
  537. }
  538. // Recompute parameters of the circle event using high-precision library.
  539. void pps(const site_type& site1,
  540. const site_type& site2,
  541. const site_type& site3,
  542. int segment_index,
  543. circle_type& c_event,
  544. bool recompute_c_x = true,
  545. bool recompute_c_y = true,
  546. bool recompute_lower_x = true) {
  547. big_int_type cA[4], cB[4];
  548. big_int_type line_a = static_cast<int_x2_type>(site3.y1()) -
  549. static_cast<int_x2_type>(site3.y0());
  550. big_int_type line_b = static_cast<int_x2_type>(site3.x0()) -
  551. static_cast<int_x2_type>(site3.x1());
  552. big_int_type segm_len = line_a * line_a + line_b * line_b;
  553. big_int_type vec_x = static_cast<int_x2_type>(site2.y()) -
  554. static_cast<int_x2_type>(site1.y());
  555. big_int_type vec_y = static_cast<int_x2_type>(site1.x()) -
  556. static_cast<int_x2_type>(site2.x());
  557. big_int_type sum_x = static_cast<int_x2_type>(site1.x()) +
  558. static_cast<int_x2_type>(site2.x());
  559. big_int_type sum_y = static_cast<int_x2_type>(site1.y()) +
  560. static_cast<int_x2_type>(site2.y());
  561. big_int_type teta = line_a * vec_x + line_b * vec_y;
  562. big_int_type denom = vec_x * line_b - vec_y * line_a;
  563. big_int_type dif0 = static_cast<int_x2_type>(site3.y1()) -
  564. static_cast<int_x2_type>(site1.y());
  565. big_int_type dif1 = static_cast<int_x2_type>(site1.x()) -
  566. static_cast<int_x2_type>(site3.x1());
  567. big_int_type A = line_a * dif1 - line_b * dif0;
  568. dif0 = static_cast<int_x2_type>(site3.y1()) -
  569. static_cast<int_x2_type>(site2.y());
  570. dif1 = static_cast<int_x2_type>(site2.x()) -
  571. static_cast<int_x2_type>(site3.x1());
  572. big_int_type B = line_a * dif1 - line_b * dif0;
  573. big_int_type sum_AB = A + B;
  574. if (is_zero(denom)) {
  575. big_int_type numer = teta * teta - sum_AB * sum_AB;
  576. denom = teta * sum_AB;
  577. cA[0] = denom * sum_x * 2 + numer * vec_x;
  578. cB[0] = segm_len;
  579. cA[1] = denom * sum_AB * 2 + numer * teta;
  580. cB[1] = 1;
  581. cA[2] = denom * sum_y * 2 + numer * vec_y;
  582. fpt_type inv_denom = to_fpt(1.0) / to_fpt(denom);
  583. if (recompute_c_x)
  584. c_event.x(to_fpt(0.25) * to_fpt(cA[0]) * inv_denom);
  585. if (recompute_c_y)
  586. c_event.y(to_fpt(0.25) * to_fpt(cA[2]) * inv_denom);
  587. if (recompute_lower_x) {
  588. c_event.lower_x(to_fpt(0.25) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
  589. inv_denom / get_sqrt(to_fpt(segm_len)));
  590. }
  591. return;
  592. }
  593. big_int_type det = (teta * teta + denom * denom) * A * B * 4;
  594. fpt_type inv_denom_sqr = to_fpt(1.0) / to_fpt(denom);
  595. inv_denom_sqr *= inv_denom_sqr;
  596. if (recompute_c_x || recompute_lower_x) {
  597. cA[0] = sum_x * denom * denom + teta * sum_AB * vec_x;
  598. cB[0] = 1;
  599. cA[1] = (segment_index == 2) ? -vec_x : vec_x;
  600. cB[1] = det;
  601. if (recompute_c_x) {
  602. c_event.x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(cA, cB)) *
  603. inv_denom_sqr);
  604. }
  605. }
  606. if (recompute_c_y || recompute_lower_x) {
  607. cA[2] = sum_y * denom * denom + teta * sum_AB * vec_y;
  608. cB[2] = 1;
  609. cA[3] = (segment_index == 2) ? -vec_y : vec_y;
  610. cB[3] = det;
  611. if (recompute_c_y) {
  612. c_event.y(to_fpt(0.5) * to_fpt(sqrt_expr_.eval2(&cA[2], &cB[2])) *
  613. inv_denom_sqr);
  614. }
  615. }
  616. if (recompute_lower_x) {
  617. cB[0] = cB[0] * segm_len;
  618. cB[1] = cB[1] * segm_len;
  619. cA[2] = sum_AB * (denom * denom + teta * teta);
  620. cB[2] = 1;
  621. cA[3] = (segment_index == 2) ? -teta : teta;
  622. cB[3] = det;
  623. c_event.lower_x(to_fpt(0.5) * to_fpt(sqrt_expr_.eval4(cA, cB)) *
  624. inv_denom_sqr / get_sqrt(to_fpt(segm_len)));
  625. }
  626. }
  627. // Recompute parameters of the circle event using high-precision library.
  628. void pss(const site_type& site1,
  629. const site_type& site2,
  630. const site_type& site3,
  631. int point_index,
  632. circle_type& c_event,
  633. bool recompute_c_x = true,
  634. bool recompute_c_y = true,
  635. bool recompute_lower_x = true) {
  636. big_int_type a[2], b[2], c[2], cA[4], cB[4];
  637. const point_type& segm_start1 = site2.point1();
  638. const point_type& segm_end1 = site2.point0();
  639. const point_type& segm_start2 = site3.point0();
  640. const point_type& segm_end2 = site3.point1();
  641. a[0] = static_cast<int_x2_type>(segm_end1.x()) -
  642. static_cast<int_x2_type>(segm_start1.x());
  643. b[0] = static_cast<int_x2_type>(segm_end1.y()) -
  644. static_cast<int_x2_type>(segm_start1.y());
  645. a[1] = static_cast<int_x2_type>(segm_end2.x()) -
  646. static_cast<int_x2_type>(segm_start2.x());
  647. b[1] = static_cast<int_x2_type>(segm_end2.y()) -
  648. static_cast<int_x2_type>(segm_start2.y());
  649. big_int_type orientation = a[1] * b[0] - a[0] * b[1];
  650. if (is_zero(orientation)) {
  651. fpt_type denom = to_fpt(2.0) * to_fpt(
  652. static_cast<big_int_type>(a[0] * a[0] + b[0] * b[0]));
  653. c[0] = b[0] * (static_cast<int_x2_type>(segm_start2.x()) -
  654. static_cast<int_x2_type>(segm_start1.x())) -
  655. a[0] * (static_cast<int_x2_type>(segm_start2.y()) -
  656. static_cast<int_x2_type>(segm_start1.y()));
  657. big_int_type dx = a[0] * (static_cast<int_x2_type>(site1.y()) -
  658. static_cast<int_x2_type>(segm_start1.y())) -
  659. b[0] * (static_cast<int_x2_type>(site1.x()) -
  660. static_cast<int_x2_type>(segm_start1.x()));
  661. big_int_type dy = b[0] * (static_cast<int_x2_type>(site1.x()) -
  662. static_cast<int_x2_type>(segm_start2.x())) -
  663. a[0] * (static_cast<int_x2_type>(site1.y()) -
  664. static_cast<int_x2_type>(segm_start2.y()));
  665. cB[0] = dx * dy;
  666. cB[1] = 1;
  667. if (recompute_c_y) {
  668. cA[0] = b[0] * ((point_index == 2) ? 2 : -2);
  669. cA[1] = a[0] * a[0] * (static_cast<int_x2_type>(segm_start1.y()) +
  670. static_cast<int_x2_type>(segm_start2.y())) -
  671. a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
  672. static_cast<int_x2_type>(segm_start2.x()) -
  673. static_cast<int_x2_type>(site1.x()) * 2) +
  674. b[0] * b[0] * (static_cast<int_x2_type>(site1.y()) * 2);
  675. fpt_type c_y = to_fpt(sqrt_expr_.eval2(cA, cB));
  676. c_event.y(c_y / denom);
  677. }
  678. if (recompute_c_x || recompute_lower_x) {
  679. cA[0] = a[0] * ((point_index == 2) ? 2 : -2);
  680. cA[1] = b[0] * b[0] * (static_cast<int_x2_type>(segm_start1.x()) +
  681. static_cast<int_x2_type>(segm_start2.x())) -
  682. a[0] * b[0] * (static_cast<int_x2_type>(segm_start1.y()) +
  683. static_cast<int_x2_type>(segm_start2.y()) -
  684. static_cast<int_x2_type>(site1.y()) * 2) +
  685. a[0] * a[0] * (static_cast<int_x2_type>(site1.x()) * 2);
  686. if (recompute_c_x) {
  687. fpt_type c_x = to_fpt(sqrt_expr_.eval2(cA, cB));
  688. c_event.x(c_x / denom);
  689. }
  690. if (recompute_lower_x) {
  691. cA[2] = is_neg(c[0]) ? -c[0] : c[0];
  692. cB[2] = a[0] * a[0] + b[0] * b[0];
  693. fpt_type lower_x = to_fpt(sqrt_expr_.eval3(cA, cB));
  694. c_event.lower_x(lower_x / denom);
  695. }
  696. }
  697. return;
  698. }
  699. c[0] = b[0] * segm_end1.x() - a[0] * segm_end1.y();
  700. c[1] = a[1] * segm_end2.y() - b[1] * segm_end2.x();
  701. big_int_type ix = a[0] * c[1] + a[1] * c[0];
  702. big_int_type iy = b[0] * c[1] + b[1] * c[0];
  703. big_int_type dx = ix - orientation * site1.x();
  704. big_int_type dy = iy - orientation * site1.y();
  705. if (is_zero(dx) && is_zero(dy)) {
  706. fpt_type denom = to_fpt(orientation);
  707. fpt_type c_x = to_fpt(ix) / denom;
  708. fpt_type c_y = to_fpt(iy) / denom;
  709. c_event = circle_type(c_x, c_y, c_x);
  710. return;
  711. }
  712. big_int_type sign = ((point_index == 2) ? 1 : -1) *
  713. (is_neg(orientation) ? 1 : -1);
  714. cA[0] = a[1] * -dx + b[1] * -dy;
  715. cA[1] = a[0] * -dx + b[0] * -dy;
  716. cA[2] = sign;
  717. cA[3] = 0;
  718. cB[0] = a[0] * a[0] + b[0] * b[0];
  719. cB[1] = a[1] * a[1] + b[1] * b[1];
  720. cB[2] = a[0] * a[1] + b[0] * b[1];
  721. cB[3] = (a[0] * dy - b[0] * dx) * (a[1] * dy - b[1] * dx) * -2;
  722. fpt_type temp = to_fpt(
  723. sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
  724. fpt_type denom = temp * to_fpt(orientation);
  725. if (recompute_c_y) {
  726. cA[0] = b[1] * (dx * dx + dy * dy) - iy * (dx * a[1] + dy * b[1]);
  727. cA[1] = b[0] * (dx * dx + dy * dy) - iy * (dx * a[0] + dy * b[0]);
  728. cA[2] = iy * sign;
  729. fpt_type cy = to_fpt(
  730. sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
  731. c_event.y(cy / denom);
  732. }
  733. if (recompute_c_x || recompute_lower_x) {
  734. cA[0] = a[1] * (dx * dx + dy * dy) - ix * (dx * a[1] + dy * b[1]);
  735. cA[1] = a[0] * (dx * dx + dy * dy) - ix * (dx * a[0] + dy * b[0]);
  736. cA[2] = ix * sign;
  737. if (recompute_c_x) {
  738. fpt_type cx = to_fpt(
  739. sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
  740. c_event.x(cx / denom);
  741. }
  742. if (recompute_lower_x) {
  743. cA[3] = orientation * (dx * dx + dy * dy) * (is_neg(temp) ? -1 : 1);
  744. fpt_type lower_x = to_fpt(
  745. sqrt_expr_evaluator_pss4<big_int_type, efpt_type>(cA, cB));
  746. c_event.lower_x(lower_x / denom);
  747. }
  748. }
  749. }
  750. // Recompute parameters of the circle event using high-precision library.
  751. void sss(const site_type& site1,
  752. const site_type& site2,
  753. const site_type& site3,
  754. circle_type& c_event,
  755. bool recompute_c_x = true,
  756. bool recompute_c_y = true,
  757. bool recompute_lower_x = true) {
  758. big_int_type a[3], b[3], c[3], cA[4], cB[4];
  759. // cA - corresponds to the cross product.
  760. // cB - corresponds to the squared length.
  761. a[0] = static_cast<int_x2_type>(site1.x1()) -
  762. static_cast<int_x2_type>(site1.x0());
  763. a[1] = static_cast<int_x2_type>(site2.x1()) -
  764. static_cast<int_x2_type>(site2.x0());
  765. a[2] = static_cast<int_x2_type>(site3.x1()) -
  766. static_cast<int_x2_type>(site3.x0());
  767. b[0] = static_cast<int_x2_type>(site1.y1()) -
  768. static_cast<int_x2_type>(site1.y0());
  769. b[1] = static_cast<int_x2_type>(site2.y1()) -
  770. static_cast<int_x2_type>(site2.y0());
  771. b[2] = static_cast<int_x2_type>(site3.y1()) -
  772. static_cast<int_x2_type>(site3.y0());
  773. c[0] = static_cast<int_x2_type>(site1.x0()) *
  774. static_cast<int_x2_type>(site1.y1()) -
  775. static_cast<int_x2_type>(site1.y0()) *
  776. static_cast<int_x2_type>(site1.x1());
  777. c[1] = static_cast<int_x2_type>(site2.x0()) *
  778. static_cast<int_x2_type>(site2.y1()) -
  779. static_cast<int_x2_type>(site2.y0()) *
  780. static_cast<int_x2_type>(site2.x1());
  781. c[2] = static_cast<int_x2_type>(site3.x0()) *
  782. static_cast<int_x2_type>(site3.y1()) -
  783. static_cast<int_x2_type>(site3.y0()) *
  784. static_cast<int_x2_type>(site3.x1());
  785. for (int i = 0; i < 3; ++i)
  786. cB[i] = a[i] * a[i] + b[i] * b[i];
  787. for (int i = 0; i < 3; ++i) {
  788. int j = (i+1) % 3;
  789. int k = (i+2) % 3;
  790. cA[i] = a[j] * b[k] - a[k] * b[j];
  791. }
  792. fpt_type denom = to_fpt(sqrt_expr_.eval3(cA, cB));
  793. if (recompute_c_y) {
  794. for (int i = 0; i < 3; ++i) {
  795. int j = (i+1) % 3;
  796. int k = (i+2) % 3;
  797. cA[i] = b[j] * c[k] - b[k] * c[j];
  798. }
  799. fpt_type c_y = to_fpt(sqrt_expr_.eval3(cA, cB));
  800. c_event.y(c_y / denom);
  801. }
  802. if (recompute_c_x || recompute_lower_x) {
  803. cA[3] = 0;
  804. for (int i = 0; i < 3; ++i) {
  805. int j = (i+1) % 3;
  806. int k = (i+2) % 3;
  807. cA[i] = a[j] * c[k] - a[k] * c[j];
  808. if (recompute_lower_x) {
  809. cA[3] = cA[3] + cA[i] * b[i];
  810. }
  811. }
  812. if (recompute_c_x) {
  813. fpt_type c_x = to_fpt(sqrt_expr_.eval3(cA, cB));
  814. c_event.x(c_x / denom);
  815. }
  816. if (recompute_lower_x) {
  817. cB[3] = 1;
  818. fpt_type lower_x = to_fpt(sqrt_expr_.eval4(cA, cB));
  819. c_event.lower_x(lower_x / denom);
  820. }
  821. }
  822. }
  823. private:
  824. // Evaluates A[3] + A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
  825. // A[2] * sqrt(B[3] * (sqrt(B[0] * B[1]) + B[2])).
  826. template <typename _int, typename _fpt>
  827. _fpt sqrt_expr_evaluator_pss4(_int *A, _int *B) {
  828. _int cA[4], cB[4];
  829. if (is_zero(A[3])) {
  830. _fpt lh = sqrt_expr_.eval2(A, B);
  831. cA[0] = 1;
  832. cB[0] = B[0] * B[1];
  833. cA[1] = B[2];
  834. cB[1] = 1;
  835. _fpt rh = sqrt_expr_.eval1(A+2, B+3) *
  836. get_sqrt(sqrt_expr_.eval2(cA, cB));
  837. if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
  838. return lh + rh;
  839. cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
  840. A[2] * A[2] * B[3] * B[2];
  841. cB[0] = 1;
  842. cA[1] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
  843. cB[1] = B[0] * B[1];
  844. _fpt numer = sqrt_expr_.eval2(cA, cB);
  845. return numer / (lh - rh);
  846. }
  847. cA[0] = 1;
  848. cB[0] = B[0] * B[1];
  849. cA[1] = B[2];
  850. cB[1] = 1;
  851. _fpt rh = sqrt_expr_.eval1(A+2, B+3) * get_sqrt(sqrt_expr_.eval2(cA, cB));
  852. cA[0] = A[0];
  853. cB[0] = B[0];
  854. cA[1] = A[1];
  855. cB[1] = B[1];
  856. cA[2] = A[3];
  857. cB[2] = 1;
  858. _fpt lh = sqrt_expr_.eval3(cA, cB);
  859. if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
  860. return lh + rh;
  861. cA[0] = A[3] * A[0] * 2;
  862. cA[1] = A[3] * A[1] * 2;
  863. cA[2] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] +
  864. A[3] * A[3] - A[2] * A[2] * B[2] * B[3];
  865. cA[3] = A[0] * A[1] * 2 - A[2] * A[2] * B[3];
  866. cB[3] = B[0] * B[1];
  867. _fpt numer = sqrt_expr_evaluator_pss3<_int, _fpt>(cA, cB);
  868. return numer / (lh - rh);
  869. }
  870. template <typename _int, typename _fpt>
  871. // Evaluates A[0] * sqrt(B[0]) + A[1] * sqrt(B[1]) +
  872. // A[2] + A[3] * sqrt(B[0] * B[1]).
  873. // B[3] = B[0] * B[1].
  874. _fpt sqrt_expr_evaluator_pss3(_int *A, _int *B) {
  875. _int cA[2], cB[2];
  876. _fpt lh = sqrt_expr_.eval2(A, B);
  877. _fpt rh = sqrt_expr_.eval2(A+2, B+2);
  878. if ((!is_neg(lh) && !is_neg(rh)) || (!is_pos(lh) && !is_pos(rh)))
  879. return lh + rh;
  880. cA[0] = A[0] * A[0] * B[0] + A[1] * A[1] * B[1] -
  881. A[2] * A[2] - A[3] * A[3] * B[0] * B[1];
  882. cB[0] = 1;
  883. cA[1] = (A[0] * A[1] - A[2] * A[3]) * 2;
  884. cB[1] = B[3];
  885. _fpt numer = sqrt_expr_.eval2(cA, cB);
  886. return numer / (lh - rh);
  887. }
  888. robust_sqrt_expr_type sqrt_expr_;
  889. to_fpt_converter to_fpt;
  890. };
  891. template <typename Site, typename Circle>
  892. class lazy_circle_formation_functor {
  893. public:
  894. typedef robust_fpt<fpt_type> robust_fpt_type;
  895. typedef robust_dif<robust_fpt_type> robust_dif_type;
  896. typedef typename Site::point_type point_type;
  897. typedef Site site_type;
  898. typedef Circle circle_type;
  899. typedef mp_circle_formation_functor<site_type, circle_type>
  900. exact_circle_formation_functor_type;
  901. void ppp(const site_type& site1,
  902. const site_type& site2,
  903. const site_type& site3,
  904. circle_type& c_event) {
  905. fpt_type dif_x1 = to_fpt(site1.x()) - to_fpt(site2.x());
  906. fpt_type dif_x2 = to_fpt(site2.x()) - to_fpt(site3.x());
  907. fpt_type dif_y1 = to_fpt(site1.y()) - to_fpt(site2.y());
  908. fpt_type dif_y2 = to_fpt(site2.y()) - to_fpt(site3.y());
  909. fpt_type orientation = robust_cross_product(
  910. static_cast<int_x2_type>(site1.x()) -
  911. static_cast<int_x2_type>(site2.x()),
  912. static_cast<int_x2_type>(site2.x()) -
  913. static_cast<int_x2_type>(site3.x()),
  914. static_cast<int_x2_type>(site1.y()) -
  915. static_cast<int_x2_type>(site2.y()),
  916. static_cast<int_x2_type>(site2.y()) -
  917. static_cast<int_x2_type>(site3.y()));
  918. robust_fpt_type inv_orientation(to_fpt(0.5) / orientation, to_fpt(2.0));
  919. fpt_type sum_x1 = to_fpt(site1.x()) + to_fpt(site2.x());
  920. fpt_type sum_x2 = to_fpt(site2.x()) + to_fpt(site3.x());
  921. fpt_type sum_y1 = to_fpt(site1.y()) + to_fpt(site2.y());
  922. fpt_type sum_y2 = to_fpt(site2.y()) + to_fpt(site3.y());
  923. fpt_type dif_x3 = to_fpt(site1.x()) - to_fpt(site3.x());
  924. fpt_type dif_y3 = to_fpt(site1.y()) - to_fpt(site3.y());
  925. robust_dif_type c_x, c_y;
  926. c_x += robust_fpt_type(dif_x1 * sum_x1 * dif_y2, to_fpt(2.0));
  927. c_x += robust_fpt_type(dif_y1 * sum_y1 * dif_y2, to_fpt(2.0));
  928. c_x -= robust_fpt_type(dif_x2 * sum_x2 * dif_y1, to_fpt(2.0));
  929. c_x -= robust_fpt_type(dif_y2 * sum_y2 * dif_y1, to_fpt(2.0));
  930. c_y += robust_fpt_type(dif_x2 * sum_x2 * dif_x1, to_fpt(2.0));
  931. c_y += robust_fpt_type(dif_y2 * sum_y2 * dif_x1, to_fpt(2.0));
  932. c_y -= robust_fpt_type(dif_x1 * sum_x1 * dif_x2, to_fpt(2.0));
  933. c_y -= robust_fpt_type(dif_y1 * sum_y1 * dif_x2, to_fpt(2.0));
  934. robust_dif_type lower_x(c_x);
  935. lower_x -= robust_fpt_type(get_sqrt(
  936. (dif_x1 * dif_x1 + dif_y1 * dif_y1) *
  937. (dif_x2 * dif_x2 + dif_y2 * dif_y2) *
  938. (dif_x3 * dif_x3 + dif_y3 * dif_y3)), to_fpt(5.0));
  939. c_event = circle_type(
  940. c_x.dif().fpv() * inv_orientation.fpv(),
  941. c_y.dif().fpv() * inv_orientation.fpv(),
  942. lower_x.dif().fpv() * inv_orientation.fpv());
  943. bool recompute_c_x = c_x.dif().ulp() > ULPS;
  944. bool recompute_c_y = c_y.dif().ulp() > ULPS;
  945. bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
  946. if (recompute_c_x || recompute_c_y || recompute_lower_x) {
  947. exact_circle_formation_functor_.ppp(
  948. site1, site2, site3, c_event,
  949. recompute_c_x, recompute_c_y, recompute_lower_x);
  950. }
  951. }
  952. void pps(const site_type& site1,
  953. const site_type& site2,
  954. const site_type& site3,
  955. int segment_index,
  956. circle_type& c_event) {
  957. fpt_type line_a = to_fpt(site3.y1()) - to_fpt(site3.y0());
  958. fpt_type line_b = to_fpt(site3.x0()) - to_fpt(site3.x1());
  959. fpt_type vec_x = to_fpt(site2.y()) - to_fpt(site1.y());
  960. fpt_type vec_y = to_fpt(site1.x()) - to_fpt(site2.x());
  961. robust_fpt_type teta(robust_cross_product(
  962. static_cast<int_x2_type>(site3.y1()) -
  963. static_cast<int_x2_type>(site3.y0()),
  964. static_cast<int_x2_type>(site3.x0()) -
  965. static_cast<int_x2_type>(site3.x1()),
  966. static_cast<int_x2_type>(site2.x()) -
  967. static_cast<int_x2_type>(site1.x()),
  968. static_cast<int_x2_type>(site2.y()) -
  969. static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
  970. robust_fpt_type A(robust_cross_product(
  971. static_cast<int_x2_type>(site3.y0()) -
  972. static_cast<int_x2_type>(site3.y1()),
  973. static_cast<int_x2_type>(site3.x0()) -
  974. static_cast<int_x2_type>(site3.x1()),
  975. static_cast<int_x2_type>(site3.y1()) -
  976. static_cast<int_x2_type>(site1.y()),
  977. static_cast<int_x2_type>(site3.x1()) -
  978. static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
  979. robust_fpt_type B(robust_cross_product(
  980. static_cast<int_x2_type>(site3.y0()) -
  981. static_cast<int_x2_type>(site3.y1()),
  982. static_cast<int_x2_type>(site3.x0()) -
  983. static_cast<int_x2_type>(site3.x1()),
  984. static_cast<int_x2_type>(site3.y1()) -
  985. static_cast<int_x2_type>(site2.y()),
  986. static_cast<int_x2_type>(site3.x1()) -
  987. static_cast<int_x2_type>(site2.x())), to_fpt(1.0));
  988. robust_fpt_type denom(robust_cross_product(
  989. static_cast<int_x2_type>(site1.y()) -
  990. static_cast<int_x2_type>(site2.y()),
  991. static_cast<int_x2_type>(site1.x()) -
  992. static_cast<int_x2_type>(site2.x()),
  993. static_cast<int_x2_type>(site3.y1()) -
  994. static_cast<int_x2_type>(site3.y0()),
  995. static_cast<int_x2_type>(site3.x1()) -
  996. static_cast<int_x2_type>(site3.x0())), to_fpt(1.0));
  997. robust_fpt_type inv_segm_len(to_fpt(1.0) /
  998. get_sqrt(line_a * line_a + line_b * line_b), to_fpt(3.0));
  999. robust_dif_type t;
  1000. if (ot::eval(denom) == ot::COLLINEAR) {
  1001. t += teta / (robust_fpt_type(to_fpt(8.0)) * A);
  1002. t -= A / (robust_fpt_type(to_fpt(2.0)) * teta);
  1003. } else {
  1004. robust_fpt_type det = ((teta * teta + denom * denom) * A * B).sqrt();
  1005. if (segment_index == 2) {
  1006. t -= det / (denom * denom);
  1007. } else {
  1008. t += det / (denom * denom);
  1009. }
  1010. t += teta * (A + B) / (robust_fpt_type(to_fpt(2.0)) * denom * denom);
  1011. }
  1012. robust_dif_type c_x, c_y;
  1013. c_x += robust_fpt_type(to_fpt(0.5) *
  1014. (to_fpt(site1.x()) + to_fpt(site2.x())));
  1015. c_x += robust_fpt_type(vec_x) * t;
  1016. c_y += robust_fpt_type(to_fpt(0.5) *
  1017. (to_fpt(site1.y()) + to_fpt(site2.y())));
  1018. c_y += robust_fpt_type(vec_y) * t;
  1019. robust_dif_type r, lower_x(c_x);
  1020. r -= robust_fpt_type(line_a) * robust_fpt_type(site3.x0());
  1021. r -= robust_fpt_type(line_b) * robust_fpt_type(site3.y0());
  1022. r += robust_fpt_type(line_a) * c_x;
  1023. r += robust_fpt_type(line_b) * c_y;
  1024. if (r.pos().fpv() < r.neg().fpv())
  1025. r = -r;
  1026. lower_x += r * inv_segm_len;
  1027. c_event = circle_type(
  1028. c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
  1029. bool recompute_c_x = c_x.dif().ulp() > ULPS;
  1030. bool recompute_c_y = c_y.dif().ulp() > ULPS;
  1031. bool recompute_lower_x = lower_x.dif().ulp() > ULPS;
  1032. if (recompute_c_x || recompute_c_y || recompute_lower_x) {
  1033. exact_circle_formation_functor_.pps(
  1034. site1, site2, site3, segment_index, c_event,
  1035. recompute_c_x, recompute_c_y, recompute_lower_x);
  1036. }
  1037. }
  1038. void pss(const site_type& site1,
  1039. const site_type& site2,
  1040. const site_type& site3,
  1041. int point_index,
  1042. circle_type& c_event) {
  1043. const point_type& segm_start1 = site2.point1();
  1044. const point_type& segm_end1 = site2.point0();
  1045. const point_type& segm_start2 = site3.point0();
  1046. const point_type& segm_end2 = site3.point1();
  1047. fpt_type a1 = to_fpt(segm_end1.x()) - to_fpt(segm_start1.x());
  1048. fpt_type b1 = to_fpt(segm_end1.y()) - to_fpt(segm_start1.y());
  1049. fpt_type a2 = to_fpt(segm_end2.x()) - to_fpt(segm_start2.x());
  1050. fpt_type b2 = to_fpt(segm_end2.y()) - to_fpt(segm_start2.y());
  1051. bool recompute_c_x, recompute_c_y, recompute_lower_x;
  1052. robust_fpt_type orientation(robust_cross_product(
  1053. static_cast<int_x2_type>(segm_end1.y()) -
  1054. static_cast<int_x2_type>(segm_start1.y()),
  1055. static_cast<int_x2_type>(segm_end1.x()) -
  1056. static_cast<int_x2_type>(segm_start1.x()),
  1057. static_cast<int_x2_type>(segm_end2.y()) -
  1058. static_cast<int_x2_type>(segm_start2.y()),
  1059. static_cast<int_x2_type>(segm_end2.x()) -
  1060. static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
  1061. if (ot::eval(orientation) == ot::COLLINEAR) {
  1062. robust_fpt_type a(a1 * a1 + b1 * b1, to_fpt(2.0));
  1063. robust_fpt_type c(robust_cross_product(
  1064. static_cast<int_x2_type>(segm_end1.y()) -
  1065. static_cast<int_x2_type>(segm_start1.y()),
  1066. static_cast<int_x2_type>(segm_end1.x()) -
  1067. static_cast<int_x2_type>(segm_start1.x()),
  1068. static_cast<int_x2_type>(segm_start2.y()) -
  1069. static_cast<int_x2_type>(segm_start1.y()),
  1070. static_cast<int_x2_type>(segm_start2.x()) -
  1071. static_cast<int_x2_type>(segm_start1.x())), to_fpt(1.0));
  1072. robust_fpt_type det(
  1073. robust_cross_product(
  1074. static_cast<int_x2_type>(segm_end1.x()) -
  1075. static_cast<int_x2_type>(segm_start1.x()),
  1076. static_cast<int_x2_type>(segm_end1.y()) -
  1077. static_cast<int_x2_type>(segm_start1.y()),
  1078. static_cast<int_x2_type>(site1.x()) -
  1079. static_cast<int_x2_type>(segm_start1.x()),
  1080. static_cast<int_x2_type>(site1.y()) -
  1081. static_cast<int_x2_type>(segm_start1.y())) *
  1082. robust_cross_product(
  1083. static_cast<int_x2_type>(segm_end1.y()) -
  1084. static_cast<int_x2_type>(segm_start1.y()),
  1085. static_cast<int_x2_type>(segm_end1.x()) -
  1086. static_cast<int_x2_type>(segm_start1.x()),
  1087. static_cast<int_x2_type>(site1.y()) -
  1088. static_cast<int_x2_type>(segm_start2.y()),
  1089. static_cast<int_x2_type>(site1.x()) -
  1090. static_cast<int_x2_type>(segm_start2.x())),
  1091. to_fpt(3.0));
  1092. robust_dif_type t;
  1093. t -= robust_fpt_type(a1) * robust_fpt_type((
  1094. to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())) * to_fpt(0.5) -
  1095. to_fpt(site1.x()));
  1096. t -= robust_fpt_type(b1) * robust_fpt_type((
  1097. to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())) * to_fpt(0.5) -
  1098. to_fpt(site1.y()));
  1099. if (point_index == 2) {
  1100. t += det.sqrt();
  1101. } else {
  1102. t -= det.sqrt();
  1103. }
  1104. t /= a;
  1105. robust_dif_type c_x, c_y;
  1106. c_x += robust_fpt_type(to_fpt(0.5) * (
  1107. to_fpt(segm_start1.x()) + to_fpt(segm_start2.x())));
  1108. c_x += robust_fpt_type(a1) * t;
  1109. c_y += robust_fpt_type(to_fpt(0.5) * (
  1110. to_fpt(segm_start1.y()) + to_fpt(segm_start2.y())));
  1111. c_y += robust_fpt_type(b1) * t;
  1112. robust_dif_type lower_x(c_x);
  1113. if (is_neg(c)) {
  1114. lower_x -= robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
  1115. } else {
  1116. lower_x += robust_fpt_type(to_fpt(0.5)) * c / a.sqrt();
  1117. }
  1118. recompute_c_x = c_x.dif().ulp() > ULPS;
  1119. recompute_c_y = c_y.dif().ulp() > ULPS;
  1120. recompute_lower_x = lower_x.dif().ulp() > ULPS;
  1121. c_event =
  1122. circle_type(c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
  1123. } else {
  1124. robust_fpt_type sqr_sum1(get_sqrt(a1 * a1 + b1 * b1), to_fpt(2.0));
  1125. robust_fpt_type sqr_sum2(get_sqrt(a2 * a2 + b2 * b2), to_fpt(2.0));
  1126. robust_fpt_type a(robust_cross_product(
  1127. static_cast<int_x2_type>(segm_end1.x()) -
  1128. static_cast<int_x2_type>(segm_start1.x()),
  1129. static_cast<int_x2_type>(segm_end1.y()) -
  1130. static_cast<int_x2_type>(segm_start1.y()),
  1131. static_cast<int_x2_type>(segm_start2.y()) -
  1132. static_cast<int_x2_type>(segm_end2.y()),
  1133. static_cast<int_x2_type>(segm_end2.x()) -
  1134. static_cast<int_x2_type>(segm_start2.x())), to_fpt(1.0));
  1135. if (!is_neg(a)) {
  1136. a += sqr_sum1 * sqr_sum2;
  1137. } else {
  1138. a = (orientation * orientation) / (sqr_sum1 * sqr_sum2 - a);
  1139. }
  1140. robust_fpt_type or1(robust_cross_product(
  1141. static_cast<int_x2_type>(segm_end1.y()) -
  1142. static_cast<int_x2_type>(segm_start1.y()),
  1143. static_cast<int_x2_type>(segm_end1.x()) -
  1144. static_cast<int_x2_type>(segm_start1.x()),
  1145. static_cast<int_x2_type>(segm_end1.y()) -
  1146. static_cast<int_x2_type>(site1.y()),
  1147. static_cast<int_x2_type>(segm_end1.x()) -
  1148. static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
  1149. robust_fpt_type or2(robust_cross_product(
  1150. static_cast<int_x2_type>(segm_end2.x()) -
  1151. static_cast<int_x2_type>(segm_start2.x()),
  1152. static_cast<int_x2_type>(segm_end2.y()) -
  1153. static_cast<int_x2_type>(segm_start2.y()),
  1154. static_cast<int_x2_type>(segm_end2.x()) -
  1155. static_cast<int_x2_type>(site1.x()),
  1156. static_cast<int_x2_type>(segm_end2.y()) -
  1157. static_cast<int_x2_type>(site1.y())), to_fpt(1.0));
  1158. robust_fpt_type det = robust_fpt_type(to_fpt(2.0)) * a * or1 * or2;
  1159. robust_fpt_type c1(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_end1.y()),
  1165. static_cast<int_x2_type>(segm_end1.x())), to_fpt(1.0));
  1166. robust_fpt_type c2(robust_cross_product(
  1167. static_cast<int_x2_type>(segm_end2.x()) -
  1168. static_cast<int_x2_type>(segm_start2.x()),
  1169. static_cast<int_x2_type>(segm_end2.y()) -
  1170. static_cast<int_x2_type>(segm_start2.y()),
  1171. static_cast<int_x2_type>(segm_end2.x()),
  1172. static_cast<int_x2_type>(segm_end2.y())), to_fpt(1.0));
  1173. robust_fpt_type inv_orientation =
  1174. robust_fpt_type(to_fpt(1.0)) / orientation;
  1175. robust_dif_type t, b, ix, iy;
  1176. ix += robust_fpt_type(a2) * c1 * inv_orientation;
  1177. ix += robust_fpt_type(a1) * c2 * inv_orientation;
  1178. iy += robust_fpt_type(b1) * c2 * inv_orientation;
  1179. iy += robust_fpt_type(b2) * c1 * inv_orientation;
  1180. b += ix * (robust_fpt_type(a1) * sqr_sum2);
  1181. b += ix * (robust_fpt_type(a2) * sqr_sum1);
  1182. b += iy * (robust_fpt_type(b1) * sqr_sum2);
  1183. b += iy * (robust_fpt_type(b2) * sqr_sum1);
  1184. b -= sqr_sum1 * robust_fpt_type(robust_cross_product(
  1185. static_cast<int_x2_type>(segm_end2.x()) -
  1186. static_cast<int_x2_type>(segm_start2.x()),
  1187. static_cast<int_x2_type>(segm_end2.y()) -
  1188. static_cast<int_x2_type>(segm_start2.y()),
  1189. static_cast<int_x2_type>(-site1.y()),
  1190. static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
  1191. b -= sqr_sum2 * robust_fpt_type(robust_cross_product(
  1192. static_cast<int_x2_type>(segm_end1.x()) -
  1193. static_cast<int_x2_type>(segm_start1.x()),
  1194. static_cast<int_x2_type>(segm_end1.y()) -
  1195. static_cast<int_x2_type>(segm_start1.y()),
  1196. static_cast<int_x2_type>(-site1.y()),
  1197. static_cast<int_x2_type>(site1.x())), to_fpt(1.0));
  1198. t -= b;
  1199. if (point_index == 2) {
  1200. t += det.sqrt();
  1201. } else {
  1202. t -= det.sqrt();
  1203. }
  1204. t /= (a * a);
  1205. robust_dif_type c_x(ix), c_y(iy);
  1206. c_x += t * (robust_fpt_type(a1) * sqr_sum2);
  1207. c_x += t * (robust_fpt_type(a2) * sqr_sum1);
  1208. c_y += t * (robust_fpt_type(b1) * sqr_sum2);
  1209. c_y += t * (robust_fpt_type(b2) * sqr_sum1);
  1210. if (t.pos().fpv() < t.neg().fpv()) {
  1211. t = -t;
  1212. }
  1213. robust_dif_type lower_x(c_x);
  1214. if (is_neg(orientation)) {
  1215. lower_x -= t * orientation;
  1216. } else {
  1217. lower_x += t * orientation;
  1218. }
  1219. recompute_c_x = c_x.dif().ulp() > ULPS;
  1220. recompute_c_y = c_y.dif().ulp() > ULPS;
  1221. recompute_lower_x = lower_x.dif().ulp() > ULPS;
  1222. c_event = circle_type(
  1223. c_x.dif().fpv(), c_y.dif().fpv(), lower_x.dif().fpv());
  1224. }
  1225. if (recompute_c_x || recompute_c_y || recompute_lower_x) {
  1226. exact_circle_formation_functor_.pss(
  1227. site1, site2, site3, point_index, c_event,
  1228. recompute_c_x, recompute_c_y, recompute_lower_x);
  1229. }
  1230. }
  1231. void sss(const site_type& site1,
  1232. const site_type& site2,
  1233. const site_type& site3,
  1234. circle_type& c_event) {
  1235. robust_fpt_type a1(to_fpt(site1.x1()) - to_fpt(site1.x0()));
  1236. robust_fpt_type b1(to_fpt(site1.y1()) - to_fpt(site1.y0()));
  1237. robust_fpt_type c1(robust_cross_product(
  1238. site1.x0(), site1.y0(),
  1239. site1.x1(), site1.y1()), to_fpt(1.0));
  1240. robust_fpt_type a2(to_fpt(site2.x1()) - to_fpt(site2.x0()));
  1241. robust_fpt_type b2(to_fpt(site2.y1()) - to_fpt(site2.y0()));
  1242. robust_fpt_type c2(robust_cross_product(
  1243. site2.x0(), site2.y0(),
  1244. site2.x1(), site2.y1()), to_fpt(1.0));
  1245. robust_fpt_type a3(to_fpt(site3.x1()) - to_fpt(site3.x0()));
  1246. robust_fpt_type b3(to_fpt(site3.y1()) - to_fpt(site3.y0()));
  1247. robust_fpt_type c3(robust_cross_product(
  1248. site3.x0(), site3.y0(),
  1249. site3.x1(), site3.y1()), to_fpt(1.0));
  1250. robust_fpt_type len1 = (a1 * a1 + b1 * b1).sqrt();
  1251. robust_fpt_type len2 = (a2 * a2 + b2 * b2).sqrt();
  1252. robust_fpt_type len3 = (a3 * a3 + b3 * b3).sqrt();
  1253. robust_fpt_type cross_12(robust_cross_product(
  1254. static_cast<int_x2_type>(site1.x1()) -
  1255. static_cast<int_x2_type>(site1.x0()),
  1256. static_cast<int_x2_type>(site1.y1()) -
  1257. static_cast<int_x2_type>(site1.y0()),
  1258. static_cast<int_x2_type>(site2.x1()) -
  1259. static_cast<int_x2_type>(site2.x0()),
  1260. static_cast<int_x2_type>(site2.y1()) -
  1261. static_cast<int_x2_type>(site2.y0())), to_fpt(1.0));
  1262. robust_fpt_type cross_23(robust_cross_product(
  1263. static_cast<int_x2_type>(site2.x1()) -
  1264. static_cast<int_x2_type>(site2.x0()),
  1265. static_cast<int_x2_type>(site2.y1()) -
  1266. static_cast<int_x2_type>(site2.y0()),
  1267. static_cast<int_x2_type>(site3.x1()) -
  1268. static_cast<int_x2_type>(site3.x0()),
  1269. static_cast<int_x2_type>(site3.y1()) -
  1270. static_cast<int_x2_type>(site3.y0())), to_fpt(1.0));
  1271. robust_fpt_type cross_31(robust_cross_product(
  1272. static_cast<int_x2_type>(site3.x1()) -
  1273. static_cast<int_x2_type>(site3.x0()),
  1274. static_cast<int_x2_type>(site3.y1()) -
  1275. static_cast<int_x2_type>(site3.y0()),
  1276. static_cast<int_x2_type>(site1.x1()) -
  1277. static_cast<int_x2_type>(site1.x0()),
  1278. static_cast<int_x2_type>(site1.y1()) -
  1279. static_cast<int_x2_type>(site1.y0())), to_fpt(1.0));
  1280. // denom = cross_12 * len3 + cross_23 * len1 + cross_31 * len2.
  1281. robust_dif_type denom;
  1282. denom += cross_12 * len3;
  1283. denom += cross_23 * len1;
  1284. denom += cross_31 * len2;
  1285. // denom * r = (b2 * c_x - a2 * c_y - c2 * denom) / len2.
  1286. robust_dif_type r;
  1287. r -= cross_12 * c3;
  1288. r -= cross_23 * c1;
  1289. r -= cross_31 * c2;
  1290. robust_dif_type c_x;
  1291. c_x += a1 * c2 * len3;
  1292. c_x -= a2 * c1 * len3;
  1293. c_x += a2 * c3 * len1;
  1294. c_x -= a3 * c2 * len1;
  1295. c_x += a3 * c1 * len2;
  1296. c_x -= a1 * c3 * len2;
  1297. robust_dif_type c_y;
  1298. c_y += b1 * c2 * len3;
  1299. c_y -= b2 * c1 * len3;
  1300. c_y += b2 * c3 * len1;
  1301. c_y -= b3 * c2 * len1;
  1302. c_y += b3 * c1 * len2;
  1303. c_y -= b1 * c3 * len2;
  1304. robust_dif_type lower_x = c_x + r;
  1305. robust_fpt_type denom_dif = denom.dif();
  1306. robust_fpt_type c_x_dif = c_x.dif() / denom_dif;
  1307. robust_fpt_type c_y_dif = c_y.dif() / denom_dif;
  1308. robust_fpt_type lower_x_dif = lower_x.dif() / denom_dif;
  1309. bool recompute_c_x = c_x_dif.ulp() > ULPS;
  1310. bool recompute_c_y = c_y_dif.ulp() > ULPS;
  1311. bool recompute_lower_x = lower_x_dif.ulp() > ULPS;
  1312. c_event = circle_type(c_x_dif.fpv(), c_y_dif.fpv(), lower_x_dif.fpv());
  1313. if (recompute_c_x || recompute_c_y || recompute_lower_x) {
  1314. exact_circle_formation_functor_.sss(
  1315. site1, site2, site3, c_event,
  1316. recompute_c_x, recompute_c_y, recompute_lower_x);
  1317. }
  1318. }
  1319. private:
  1320. exact_circle_formation_functor_type exact_circle_formation_functor_;
  1321. to_fpt_converter to_fpt;
  1322. };
  1323. template <typename Site,
  1324. typename Circle,
  1325. typename CEP = circle_existence_predicate<Site>,
  1326. typename CFF = lazy_circle_formation_functor<Site, Circle> >
  1327. class circle_formation_predicate {
  1328. public:
  1329. typedef Site site_type;
  1330. typedef Circle circle_type;
  1331. typedef CEP circle_existence_predicate_type;
  1332. typedef CFF circle_formation_functor_type;
  1333. // Create a circle event from the given three sites.
  1334. // Returns true if the circle event exists, else false.
  1335. // If exists circle event is saved into the c_event variable.
  1336. bool operator()(const site_type& site1, const site_type& site2,
  1337. const site_type& site3, circle_type& circle) {
  1338. if (!site1.is_segment()) {
  1339. if (!site2.is_segment()) {
  1340. if (!site3.is_segment()) {
  1341. // (point, point, point) sites.
  1342. if (!circle_existence_predicate_.ppp(site1, site2, site3))
  1343. return false;
  1344. circle_formation_functor_.ppp(site1, site2, site3, circle);
  1345. } else {
  1346. // (point, point, segment) sites.
  1347. if (!circle_existence_predicate_.pps(site1, site2, site3, 3))
  1348. return false;
  1349. circle_formation_functor_.pps(site1, site2, site3, 3, circle);
  1350. }
  1351. } else {
  1352. if (!site3.is_segment()) {
  1353. // (point, segment, point) sites.
  1354. if (!circle_existence_predicate_.pps(site1, site3, site2, 2))
  1355. return false;
  1356. circle_formation_functor_.pps(site1, site3, site2, 2, circle);
  1357. } else {
  1358. // (point, segment, segment) sites.
  1359. if (!circle_existence_predicate_.pss(site1, site2, site3, 1))
  1360. return false;
  1361. circle_formation_functor_.pss(site1, site2, site3, 1, circle);
  1362. }
  1363. }
  1364. } else {
  1365. if (!site2.is_segment()) {
  1366. if (!site3.is_segment()) {
  1367. // (segment, point, point) sites.
  1368. if (!circle_existence_predicate_.pps(site2, site3, site1, 1))
  1369. return false;
  1370. circle_formation_functor_.pps(site2, site3, site1, 1, circle);
  1371. } else {
  1372. // (segment, point, segment) sites.
  1373. if (!circle_existence_predicate_.pss(site2, site1, site3, 2))
  1374. return false;
  1375. circle_formation_functor_.pss(site2, site1, site3, 2, circle);
  1376. }
  1377. } else {
  1378. if (!site3.is_segment()) {
  1379. // (segment, segment, point) sites.
  1380. if (!circle_existence_predicate_.pss(site3, site1, site2, 3))
  1381. return false;
  1382. circle_formation_functor_.pss(site3, site1, site2, 3, circle);
  1383. } else {
  1384. // (segment, segment, segment) sites.
  1385. if (!circle_existence_predicate_.sss(site1, site2, site3))
  1386. return false;
  1387. circle_formation_functor_.sss(site1, site2, site3, circle);
  1388. }
  1389. }
  1390. }
  1391. if (lies_outside_vertical_segment(circle, site1) ||
  1392. lies_outside_vertical_segment(circle, site2) ||
  1393. lies_outside_vertical_segment(circle, site3)) {
  1394. return false;
  1395. }
  1396. return true;
  1397. }
  1398. private:
  1399. bool lies_outside_vertical_segment(
  1400. const circle_type& c, const site_type& s) {
  1401. if (!s.is_segment() || !is_vertical(s)) {
  1402. return false;
  1403. }
  1404. fpt_type y0 = to_fpt(s.is_inverse() ? s.y1() : s.y0());
  1405. fpt_type y1 = to_fpt(s.is_inverse() ? s.y0() : s.y1());
  1406. return ulp_cmp(c.y(), y0, ULPS) == ulp_cmp_type::LESS ||
  1407. ulp_cmp(c.y(), y1, ULPS) == ulp_cmp_type::MORE;
  1408. }
  1409. private:
  1410. to_fpt_converter to_fpt;
  1411. ulp_cmp_type ulp_cmp;
  1412. circle_existence_predicate_type circle_existence_predicate_;
  1413. circle_formation_functor_type circle_formation_functor_;
  1414. };
  1415. };
  1416. } // detail
  1417. } // polygon
  1418. } // boost
  1419. #endif // BOOST_POLYGON_DETAIL_VORONOI_PREDICATES