voronoi_predicates.hpp 61 KB

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