RobustPredicates.cs 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. // -----------------------------------------------------------------------
  2. // <copyright file="RobustPredicates.cs">
  3. // Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
  4. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  5. // </copyright>
  6. // -----------------------------------------------------------------------
  7. namespace UnityEngine.U2D.Animation.TriangleNet
  8. {
  9. using System;
  10. using Animation.TriangleNet.Geometry;
  11. using Animation.TriangleNet.Tools;
  12. /// <summary>
  13. /// Adaptive exact arithmetic geometric predicates.
  14. /// </summary>
  15. /// <remarks>
  16. /// The adaptive exact arithmetic geometric predicates implemented herein are described in
  17. /// detail in the paper "Adaptive Precision Floating-Point Arithmetic and Fast Robust
  18. /// Geometric Predicates." by Jonathan Richard Shewchuk, see
  19. /// http://www.cs.cmu.edu/~quake/robust.html
  20. ///
  21. /// The macros of the original C code were automatically expanded using the Visual Studio
  22. /// command prompt with the command "CL /P /C EXACT.C", see
  23. /// http://msdn.microsoft.com/en-us/library/8z9z0bx6.aspx
  24. /// </remarks>
  25. internal class RobustPredicates : IPredicates
  26. {
  27. #region Default predicates instance (Singleton)
  28. private static readonly object creationLock = new object();
  29. private static RobustPredicates _default;
  30. /// <summary>
  31. /// Gets the default configuration instance.
  32. /// </summary>
  33. internal static RobustPredicates Default
  34. {
  35. get
  36. {
  37. if (_default == null)
  38. {
  39. lock (creationLock)
  40. {
  41. if (_default == null)
  42. {
  43. _default = new RobustPredicates();
  44. }
  45. }
  46. }
  47. return _default;
  48. }
  49. }
  50. #endregion
  51. #region Static initialization
  52. private static double epsilon, splitter, resulterrbound;
  53. private static double ccwerrboundA, ccwerrboundB, ccwerrboundC;
  54. private static double iccerrboundA, iccerrboundB, iccerrboundC;
  55. //private static double o3derrboundA, o3derrboundB, o3derrboundC;
  56. /// <summary>
  57. /// Initialize the variables used for exact arithmetic.
  58. /// </summary>
  59. /// <remarks>
  60. /// 'epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in
  61. /// floating-point arithmetic. 'epsilon' bounds the relative roundoff
  62. /// error. It is used for floating-point error analysis.
  63. ///
  64. /// 'splitter' is used to split floating-point numbers into two half-
  65. /// length significands for exact multiplication.
  66. ///
  67. /// I imagine that a highly optimizing compiler might be too smart for its
  68. /// own good, and somehow cause this routine to fail, if it pretends that
  69. /// floating-point arithmetic is too much like double arithmetic.
  70. ///
  71. /// Don't change this routine unless you fully understand it.
  72. /// </remarks>
  73. static RobustPredicates()
  74. {
  75. double half;
  76. double check, lastcheck;
  77. bool every_other;
  78. every_other = true;
  79. half = 0.5;
  80. epsilon = 1.0;
  81. splitter = 1.0;
  82. check = 1.0;
  83. // Repeatedly divide 'epsilon' by two until it is too small to add to
  84. // one without causing roundoff. (Also check if the sum is equal to
  85. // the previous sum, for machines that round up instead of using exact
  86. // rounding. Not that these routines will work on such machines.)
  87. do
  88. {
  89. lastcheck = check;
  90. epsilon *= half;
  91. if (every_other)
  92. {
  93. splitter *= 2.0;
  94. }
  95. every_other = !every_other;
  96. check = 1.0 + epsilon;
  97. }
  98. while ((check != 1.0) && (check != lastcheck));
  99. splitter += 1.0;
  100. // Error bounds for orientation and incircle tests.
  101. resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
  102. ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
  103. ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
  104. ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
  105. iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
  106. iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
  107. iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
  108. //o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
  109. //o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
  110. //o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
  111. }
  112. #endregion
  113. public RobustPredicates()
  114. {
  115. AllocateWorkspace();
  116. }
  117. /// <summary>
  118. /// Check, if the three points appear in counterclockwise order. The result is
  119. /// also a rough approximation of twice the signed area of the triangle defined
  120. /// by the three points.
  121. /// </summary>
  122. /// <param name="pa">Point a.</param>
  123. /// <param name="pb">Point b.</param>
  124. /// <param name="pc">Point c.</param>
  125. /// <returns>Return a positive value if the points pa, pb, and pc occur in
  126. /// counterclockwise order; a negative value if they occur in clockwise order;
  127. /// and zero if they are collinear.</returns>
  128. public double CounterClockwise(Point pa, Point pb, Point pc)
  129. {
  130. double detleft, detright, det;
  131. double detsum, errbound;
  132. Statistic.CounterClockwiseCount++;
  133. detleft = (pa.x - pc.x) * (pb.y - pc.y);
  134. detright = (pa.y - pc.y) * (pb.x - pc.x);
  135. det = detleft - detright;
  136. if (Behavior.NoExact)
  137. {
  138. return det;
  139. }
  140. if (detleft > 0.0)
  141. {
  142. if (detright <= 0.0)
  143. {
  144. return det;
  145. }
  146. else
  147. {
  148. detsum = detleft + detright;
  149. }
  150. }
  151. else if (detleft < 0.0)
  152. {
  153. if (detright >= 0.0)
  154. {
  155. return det;
  156. }
  157. else
  158. {
  159. detsum = -detleft - detright;
  160. }
  161. }
  162. else
  163. {
  164. return det;
  165. }
  166. errbound = ccwerrboundA * detsum;
  167. if ((det >= errbound) || (-det >= errbound))
  168. {
  169. return det;
  170. }
  171. Statistic.CounterClockwiseAdaptCount++;
  172. return CounterClockwiseAdapt(pa, pb, pc, detsum);
  173. }
  174. /// <summary>
  175. /// Check if the point pd lies inside the circle passing through pa, pb, and pc. The
  176. /// points pa, pb, and pc must be in counterclockwise order, or the sign of the result
  177. /// will be reversed.
  178. /// </summary>
  179. /// <param name="pa">Point a.</param>
  180. /// <param name="pb">Point b.</param>
  181. /// <param name="pc">Point c.</param>
  182. /// <param name="pd">Point d.</param>
  183. /// <returns>Return a positive value if the point pd lies inside the circle passing through
  184. /// pa, pb, and pc; a negative value if it lies outside; and zero if the four points
  185. /// are cocircular.</returns>
  186. public double InCircle(Point pa, Point pb, Point pc, Point pd)
  187. {
  188. double adx, bdx, cdx, ady, bdy, cdy;
  189. double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
  190. double alift, blift, clift;
  191. double det;
  192. double permanent, errbound;
  193. Statistic.InCircleCount++;
  194. adx = pa.x - pd.x;
  195. bdx = pb.x - pd.x;
  196. cdx = pc.x - pd.x;
  197. ady = pa.y - pd.y;
  198. bdy = pb.y - pd.y;
  199. cdy = pc.y - pd.y;
  200. bdxcdy = bdx * cdy;
  201. cdxbdy = cdx * bdy;
  202. alift = adx * adx + ady * ady;
  203. cdxady = cdx * ady;
  204. adxcdy = adx * cdy;
  205. blift = bdx * bdx + bdy * bdy;
  206. adxbdy = adx * bdy;
  207. bdxady = bdx * ady;
  208. clift = cdx * cdx + cdy * cdy;
  209. det = alift * (bdxcdy - cdxbdy)
  210. + blift * (cdxady - adxcdy)
  211. + clift * (adxbdy - bdxady);
  212. if (Behavior.NoExact)
  213. {
  214. return det;
  215. }
  216. permanent = (Math.Abs(bdxcdy) + Math.Abs(cdxbdy)) * alift
  217. + (Math.Abs(cdxady) + Math.Abs(adxcdy)) * blift
  218. + (Math.Abs(adxbdy) + Math.Abs(bdxady)) * clift;
  219. errbound = iccerrboundA * permanent;
  220. if ((det > errbound) || (-det > errbound))
  221. {
  222. return det;
  223. }
  224. Statistic.InCircleAdaptCount++;
  225. return InCircleAdapt(pa, pb, pc, pd, permanent);
  226. }
  227. /// <summary>
  228. /// Return a positive value if the point pd is incompatible with the circle
  229. /// or plane passing through pa, pb, and pc (meaning that pd is inside the
  230. /// circle or below the plane); a negative value if it is compatible; and
  231. /// zero if the four points are cocircular/coplanar. The points pa, pb, and
  232. /// pc must be in counterclockwise order, or the sign of the result will be
  233. /// reversed.
  234. /// </summary>
  235. /// <param name="pa">Point a.</param>
  236. /// <param name="pb">Point b.</param>
  237. /// <param name="pc">Point c.</param>
  238. /// <param name="pd">Point d.</param>
  239. /// <returns>Return a positive value if the point pd lies inside the circle passing through
  240. /// pa, pb, and pc; a negative value if it lies outside; and zero if the four points
  241. /// are cocircular.</returns>
  242. public double NonRegular(Point pa, Point pb, Point pc, Point pd)
  243. {
  244. return InCircle(pa, pb, pc, pd);
  245. }
  246. /// <summary>
  247. /// Find the circumcenter of a triangle.
  248. /// </summary>
  249. /// <param name="org">Triangle point.</param>
  250. /// <param name="dest">Triangle point.</param>
  251. /// <param name="apex">Triangle point.</param>
  252. /// <param name="xi">Relative coordinate of new location.</param>
  253. /// <param name="eta">Relative coordinate of new location.</param>
  254. /// <param name="offconstant">Off-center constant.</param>
  255. /// <returns>Coordinates of the circumcenter (or off-center)</returns>
  256. public Point FindCircumcenter(Point org, Point dest, Point apex,
  257. ref double xi, ref double eta, double offconstant)
  258. {
  259. double xdo, ydo, xao, yao;
  260. double dodist, aodist, dadist;
  261. double denominator;
  262. double dx, dy, dxoff, dyoff;
  263. Statistic.CircumcenterCount++;
  264. // Compute the circumcenter of the triangle.
  265. xdo = dest.x - org.x;
  266. ydo = dest.y - org.y;
  267. xao = apex.x - org.x;
  268. yao = apex.y - org.y;
  269. dodist = xdo * xdo + ydo * ydo;
  270. aodist = xao * xao + yao * yao;
  271. dadist = (dest.x - apex.x) * (dest.x - apex.x) +
  272. (dest.y - apex.y) * (dest.y - apex.y);
  273. if (Behavior.NoExact)
  274. {
  275. denominator = 0.5 / (xdo * yao - xao * ydo);
  276. }
  277. else
  278. {
  279. // Use the counterclockwise() routine to ensure a positive (and
  280. // reasonably accurate) result, avoiding any possibility of
  281. // division by zero.
  282. denominator = 0.5 / CounterClockwise(dest, apex, org);
  283. // Don't count the above as an orientation test.
  284. Statistic.CounterClockwiseCount--;
  285. }
  286. dx = (yao * dodist - ydo * aodist) * denominator;
  287. dy = (xdo * aodist - xao * dodist) * denominator;
  288. // Find the (squared) length of the triangle's shortest edge. This
  289. // serves as a conservative estimate of the insertion radius of the
  290. // circumcenter's parent. The estimate is used to ensure that
  291. // the algorithm terminates even if very small angles appear in
  292. // the input PSLG.
  293. if ((dodist < aodist) && (dodist < dadist))
  294. {
  295. if (offconstant > 0.0)
  296. {
  297. // Find the position of the off-center, as described by Alper Ungor.
  298. dxoff = 0.5 * xdo - offconstant * ydo;
  299. dyoff = 0.5 * ydo + offconstant * xdo;
  300. // If the off-center is closer to the origin than the
  301. // circumcenter, use the off-center instead.
  302. if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
  303. {
  304. dx = dxoff;
  305. dy = dyoff;
  306. }
  307. }
  308. }
  309. else if (aodist < dadist)
  310. {
  311. if (offconstant > 0.0)
  312. {
  313. dxoff = 0.5 * xao + offconstant * yao;
  314. dyoff = 0.5 * yao - offconstant * xao;
  315. // If the off-center is closer to the origin than the
  316. // circumcenter, use the off-center instead.
  317. if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
  318. {
  319. dx = dxoff;
  320. dy = dyoff;
  321. }
  322. }
  323. }
  324. else
  325. {
  326. if (offconstant > 0.0)
  327. {
  328. dxoff = 0.5 * (apex.x - dest.x) - offconstant * (apex.y - dest.y);
  329. dyoff = 0.5 * (apex.y - dest.y) + offconstant * (apex.x - dest.x);
  330. // If the off-center is closer to the destination than the
  331. // circumcenter, use the off-center instead.
  332. if (dxoff * dxoff + dyoff * dyoff <
  333. (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo))
  334. {
  335. dx = xdo + dxoff;
  336. dy = ydo + dyoff;
  337. }
  338. }
  339. }
  340. // To interpolate vertex attributes for the new vertex inserted at
  341. // the circumcenter, define a coordinate system with a xi-axis,
  342. // directed from the triangle's origin to its destination, and
  343. // an eta-axis, directed from its origin to its apex.
  344. // Calculate the xi and eta coordinates of the circumcenter.
  345. xi = (yao * dx - xao * dy) * (2.0 * denominator);
  346. eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
  347. return new Point(org.x + dx, org.y + dy);
  348. }
  349. /// <summary>
  350. /// Find the circumcenter of a triangle.
  351. /// </summary>
  352. /// <param name="org">Triangle point.</param>
  353. /// <param name="dest">Triangle point.</param>
  354. /// <param name="apex">Triangle point.</param>
  355. /// <param name="xi">Relative coordinate of new location.</param>
  356. /// <param name="eta">Relative coordinate of new location.</param>
  357. /// <returns>Coordinates of the circumcenter</returns>
  358. /// <remarks>
  359. /// The result is returned both in terms of x-y coordinates and xi-eta
  360. /// (barycentric) coordinates. The xi-eta coordinate system is defined in
  361. /// terms of the triangle: the origin of the triangle is the origin of the
  362. /// coordinate system; the destination of the triangle is one unit along the
  363. /// xi axis; and the apex of the triangle is one unit along the eta axis.
  364. /// This procedure also returns the square of the length of the triangle's
  365. /// shortest edge.
  366. /// </remarks>
  367. public Point FindCircumcenter(Point org, Point dest, Point apex,
  368. ref double xi, ref double eta)
  369. {
  370. double xdo, ydo, xao, yao;
  371. double dodist, aodist;
  372. double denominator;
  373. double dx, dy;
  374. Statistic.CircumcenterCount++;
  375. // Compute the circumcenter of the triangle.
  376. xdo = dest.x - org.x;
  377. ydo = dest.y - org.y;
  378. xao = apex.x - org.x;
  379. yao = apex.y - org.y;
  380. dodist = xdo * xdo + ydo * ydo;
  381. aodist = xao * xao + yao * yao;
  382. if (Behavior.NoExact)
  383. {
  384. denominator = 0.5 / (xdo * yao - xao * ydo);
  385. }
  386. else
  387. {
  388. // Use the counterclockwise() routine to ensure a positive (and
  389. // reasonably accurate) result, avoiding any possibility of
  390. // division by zero.
  391. denominator = 0.5 / CounterClockwise(dest, apex, org);
  392. // Don't count the above as an orientation test.
  393. Statistic.CounterClockwiseCount--;
  394. }
  395. dx = (yao * dodist - ydo * aodist) * denominator;
  396. dy = (xdo * aodist - xao * dodist) * denominator;
  397. // To interpolate vertex attributes for the new vertex inserted at
  398. // the circumcenter, define a coordinate system with a xi-axis,
  399. // directed from the triangle's origin to its destination, and
  400. // an eta-axis, directed from its origin to its apex.
  401. // Calculate the xi and eta coordinates of the circumcenter.
  402. xi = (yao * dx - xao * dy) * (2.0 * denominator);
  403. eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
  404. return new Point(org.x + dx, org.y + dy);
  405. }
  406. #region Exact arithmetics
  407. /// <summary>
  408. /// Sum two expansions, eliminating zero components from the output expansion.
  409. /// </summary>
  410. /// <param name="elen"></param>
  411. /// <param name="e"></param>
  412. /// <param name="flen"></param>
  413. /// <param name="f"></param>
  414. /// <param name="h"></param>
  415. /// <returns></returns>
  416. /// <remarks>
  417. /// Sets h = e + f. See the Robust Predicates paper for details.
  418. ///
  419. /// If round-to-even is used (as with IEEE 754), maintains the strongly nonoverlapping
  420. /// property. (That is, if e is strongly nonoverlapping, h will be also.) Does NOT
  421. /// maintain the nonoverlapping or nonadjacent properties.
  422. /// </remarks>
  423. private int FastExpansionSumZeroElim(int elen, double[] e, int flen, double[] f, double[] h)
  424. {
  425. double Q;
  426. double Qnew;
  427. double hh;
  428. double bvirt;
  429. double avirt, bround, around;
  430. int eindex, findex, hindex;
  431. double enow, fnow;
  432. enow = e[0];
  433. fnow = f[0];
  434. eindex = findex = 0;
  435. if ((fnow > enow) == (fnow > -enow))
  436. {
  437. Q = enow;
  438. enow = e[++eindex];
  439. }
  440. else
  441. {
  442. Q = fnow;
  443. fnow = f[++findex];
  444. }
  445. hindex = 0;
  446. if ((eindex < elen) && (findex < flen))
  447. {
  448. if ((fnow > enow) == (fnow > -enow))
  449. {
  450. Qnew = (double)(enow + Q); bvirt = Qnew - enow; hh = Q - bvirt;
  451. enow = e[++eindex];
  452. }
  453. else
  454. {
  455. Qnew = (double)(fnow + Q); bvirt = Qnew - fnow; hh = Q - bvirt;
  456. fnow = f[++findex];
  457. }
  458. Q = Qnew;
  459. if (hh != 0.0)
  460. {
  461. h[hindex++] = hh;
  462. }
  463. while ((eindex < elen) && (findex < flen))
  464. {
  465. if ((fnow > enow) == (fnow > -enow))
  466. {
  467. Qnew = (double)(Q + enow);
  468. bvirt = (double)(Qnew - Q);
  469. avirt = Qnew - bvirt;
  470. bround = enow - bvirt;
  471. around = Q - avirt;
  472. hh = around + bround;
  473. enow = e[++eindex];
  474. }
  475. else
  476. {
  477. Qnew = (double)(Q + fnow);
  478. bvirt = (double)(Qnew - Q);
  479. avirt = Qnew - bvirt;
  480. bround = fnow - bvirt;
  481. around = Q - avirt;
  482. hh = around + bround;
  483. fnow = f[++findex];
  484. }
  485. Q = Qnew;
  486. if (hh != 0.0)
  487. {
  488. h[hindex++] = hh;
  489. }
  490. }
  491. }
  492. while (eindex < elen)
  493. {
  494. Qnew = (double)(Q + enow);
  495. bvirt = (double)(Qnew - Q);
  496. avirt = Qnew - bvirt;
  497. bround = enow - bvirt;
  498. around = Q - avirt;
  499. hh = around + bround;
  500. enow = e[++eindex];
  501. Q = Qnew;
  502. if (hh != 0.0)
  503. {
  504. h[hindex++] = hh;
  505. }
  506. }
  507. while (findex < flen)
  508. {
  509. Qnew = (double)(Q + fnow);
  510. bvirt = (double)(Qnew - Q);
  511. avirt = Qnew - bvirt;
  512. bround = fnow - bvirt;
  513. around = Q - avirt;
  514. hh = around + bround;
  515. fnow = f[++findex];
  516. Q = Qnew;
  517. if (hh != 0.0)
  518. {
  519. h[hindex++] = hh;
  520. }
  521. }
  522. if ((Q != 0.0) || (hindex == 0))
  523. {
  524. h[hindex++] = Q;
  525. }
  526. return hindex;
  527. }
  528. /// <summary>
  529. /// Multiply an expansion by a scalar, eliminating zero components from the output expansion.
  530. /// </summary>
  531. /// <param name="elen"></param>
  532. /// <param name="e"></param>
  533. /// <param name="b"></param>
  534. /// <param name="h"></param>
  535. /// <returns></returns>
  536. /// <remarks>
  537. /// Sets h = be. See my Robust Predicates paper for details.
  538. ///
  539. /// Maintains the nonoverlapping property. If round-to-even is used (as with IEEE 754),
  540. /// maintains the strongly nonoverlapping and nonadjacent properties as well. (That is,
  541. /// if e has one of these properties, so will h.)
  542. /// </remarks>
  543. private int ScaleExpansionZeroElim(int elen, double[] e, double b, double[] h)
  544. {
  545. double Q, sum;
  546. double hh;
  547. double product1;
  548. double product0;
  549. int eindex, hindex;
  550. double enow;
  551. double bvirt;
  552. double avirt, bround, around;
  553. double c;
  554. double abig;
  555. double ahi, alo, bhi, blo;
  556. double err1, err2, err3;
  557. c = (double)(splitter * b); abig = (double)(c - b); bhi = c - abig; blo = b - bhi;
  558. Q = (double)(e[0] * b); c = (double)(splitter * e[0]); abig = (double)(c - e[0]); ahi = c - abig; alo = e[0] - ahi; err1 = Q - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); hh = (alo * blo) - err3;
  559. hindex = 0;
  560. if (hh != 0)
  561. {
  562. h[hindex++] = hh;
  563. }
  564. for (eindex = 1; eindex < elen; eindex++)
  565. {
  566. enow = e[eindex];
  567. product1 = (double)(enow * b); c = (double)(splitter * enow); abig = (double)(c - enow); ahi = c - abig; alo = enow - ahi; err1 = product1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); product0 = (alo * blo) - err3;
  568. sum = (double)(Q + product0); bvirt = (double)(sum - Q); avirt = sum - bvirt; bround = product0 - bvirt; around = Q - avirt; hh = around + bround;
  569. if (hh != 0)
  570. {
  571. h[hindex++] = hh;
  572. }
  573. Q = (double)(product1 + sum); bvirt = Q - product1; hh = sum - bvirt;
  574. if (hh != 0)
  575. {
  576. h[hindex++] = hh;
  577. }
  578. }
  579. if ((Q != 0.0) || (hindex == 0))
  580. {
  581. h[hindex++] = Q;
  582. }
  583. return hindex;
  584. }
  585. /// <summary>
  586. /// Produce a one-word estimate of an expansion's value.
  587. /// </summary>
  588. /// <param name="elen"></param>
  589. /// <param name="e"></param>
  590. /// <returns></returns>
  591. private double Estimate(int elen, double[] e)
  592. {
  593. double Q;
  594. int eindex;
  595. Q = e[0];
  596. for (eindex = 1; eindex < elen; eindex++)
  597. {
  598. Q += e[eindex];
  599. }
  600. return Q;
  601. }
  602. /// <summary>
  603. /// Return a positive value if the points pa, pb, and pc occur in counterclockwise
  604. /// order; a negative value if they occur in clockwise order; and zero if they are
  605. /// collinear. The result is also a rough approximation of twice the signed area of
  606. /// the triangle defined by the three points.
  607. /// </summary>
  608. /// <param name="pa"></param>
  609. /// <param name="pb"></param>
  610. /// <param name="pc"></param>
  611. /// <param name="detsum"></param>
  612. /// <returns></returns>
  613. /// <remarks>
  614. /// Uses exact arithmetic if necessary to ensure a correct answer. The result returned
  615. /// is the determinant of a matrix. This determinant is computed adaptively, in the
  616. /// sense that exact arithmetic is used only to the degree it is needed to ensure that
  617. /// the returned value has the correct sign. Hence, this function is usually quite fast,
  618. /// but will run more slowly when the input points are collinear or nearly so.
  619. /// </remarks>
  620. private double CounterClockwiseAdapt(Point pa, Point pb, Point pc, double detsum)
  621. {
  622. double acx, acy, bcx, bcy;
  623. double acxtail, acytail, bcxtail, bcytail;
  624. double detleft, detright;
  625. double detlefttail, detrighttail;
  626. double det, errbound;
  627. // Edited to work around index out of range exceptions (changed array length from 4 to 5).
  628. // See unsafe indexing in FastExpansionSumZeroElim.
  629. double[] B = new double[5], u = new double[5];
  630. double[] C1 = new double[8], C2 = new double[12], D = new double[16];
  631. double B3;
  632. int C1length, C2length, Dlength;
  633. double u3;
  634. double s1, t1;
  635. double s0, t0;
  636. double bvirt;
  637. double avirt, bround, around;
  638. double c;
  639. double abig;
  640. double ahi, alo, bhi, blo;
  641. double err1, err2, err3;
  642. double _i, _j;
  643. double _0;
  644. acx = (double)(pa.x - pc.x);
  645. bcx = (double)(pb.x - pc.x);
  646. acy = (double)(pa.y - pc.y);
  647. bcy = (double)(pb.y - pc.y);
  648. detleft = (double)(acx * bcy); c = (double)(splitter * acx); abig = (double)(c - acx); ahi = c - abig; alo = acx - ahi; c = (double)(splitter * bcy); abig = (double)(c - bcy); bhi = c - abig; blo = bcy - bhi; err1 = detleft - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); detlefttail = (alo * blo) - err3;
  649. detright = (double)(acy * bcx); c = (double)(splitter * acy); abig = (double)(c - acy); ahi = c - abig; alo = acy - ahi; c = (double)(splitter * bcx); abig = (double)(c - bcx); bhi = c - abig; blo = bcx - bhi; err1 = detright - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); detrighttail = (alo * blo) - err3;
  650. _i = (double)(detlefttail - detrighttail); bvirt = (double)(detlefttail - _i); avirt = _i + bvirt; bround = bvirt - detrighttail; around = detlefttail - avirt; B[0] = around + bround; _j = (double)(detleft + _i); bvirt = (double)(_j - detleft); avirt = _j - bvirt; bround = _i - bvirt; around = detleft - avirt; _0 = around + bround; _i = (double)(_0 - detright); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - detright; around = _0 - avirt; B[1] = around + bround; B3 = (double)(_j + _i); bvirt = (double)(B3 - _j); avirt = B3 - bvirt; bround = _i - bvirt; around = _j - avirt; B[2] = around + bround;
  651. B[3] = B3;
  652. det = Estimate(4, B);
  653. errbound = ccwerrboundB * detsum;
  654. if ((det >= errbound) || (-det >= errbound))
  655. {
  656. return det;
  657. }
  658. bvirt = (double)(pa.x - acx); avirt = acx + bvirt; bround = bvirt - pc.x; around = pa.x - avirt; acxtail = around + bround;
  659. bvirt = (double)(pb.x - bcx); avirt = bcx + bvirt; bround = bvirt - pc.x; around = pb.x - avirt; bcxtail = around + bround;
  660. bvirt = (double)(pa.y - acy); avirt = acy + bvirt; bround = bvirt - pc.y; around = pa.y - avirt; acytail = around + bround;
  661. bvirt = (double)(pb.y - bcy); avirt = bcy + bvirt; bround = bvirt - pc.y; around = pb.y - avirt; bcytail = around + bround;
  662. if ((acxtail == 0.0) && (acytail == 0.0)
  663. && (bcxtail == 0.0) && (bcytail == 0.0))
  664. {
  665. return det;
  666. }
  667. errbound = ccwerrboundC * detsum + resulterrbound * ((det) >= 0.0 ? (det) : -(det));
  668. det += (acx * bcytail + bcy * acxtail)
  669. - (acy * bcxtail + bcx * acytail);
  670. if ((det >= errbound) || (-det >= errbound))
  671. {
  672. return det;
  673. }
  674. s1 = (double)(acxtail * bcy); c = (double)(splitter * acxtail); abig = (double)(c - acxtail); ahi = c - abig; alo = acxtail - ahi; c = (double)(splitter * bcy); abig = (double)(c - bcy); bhi = c - abig; blo = bcy - bhi; err1 = s1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); s0 = (alo * blo) - err3;
  675. t1 = (double)(acytail * bcx); c = (double)(splitter * acytail); abig = (double)(c - acytail); ahi = c - abig; alo = acytail - ahi; c = (double)(splitter * bcx); abig = (double)(c - bcx); bhi = c - abig; blo = bcx - bhi; err1 = t1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); t0 = (alo * blo) - err3;
  676. _i = (double)(s0 - t0); bvirt = (double)(s0 - _i); avirt = _i + bvirt; bround = bvirt - t0; around = s0 - avirt; u[0] = around + bround; _j = (double)(s1 + _i); bvirt = (double)(_j - s1); avirt = _j - bvirt; bround = _i - bvirt; around = s1 - avirt; _0 = around + bround; _i = (double)(_0 - t1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - t1; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  677. u[3] = u3;
  678. C1length = FastExpansionSumZeroElim(4, B, 4, u, C1);
  679. s1 = (double)(acx * bcytail); c = (double)(splitter * acx); abig = (double)(c - acx); ahi = c - abig; alo = acx - ahi; c = (double)(splitter * bcytail); abig = (double)(c - bcytail); bhi = c - abig; blo = bcytail - bhi; err1 = s1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); s0 = (alo * blo) - err3;
  680. t1 = (double)(acy * bcxtail); c = (double)(splitter * acy); abig = (double)(c - acy); ahi = c - abig; alo = acy - ahi; c = (double)(splitter * bcxtail); abig = (double)(c - bcxtail); bhi = c - abig; blo = bcxtail - bhi; err1 = t1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); t0 = (alo * blo) - err3;
  681. _i = (double)(s0 - t0); bvirt = (double)(s0 - _i); avirt = _i + bvirt; bround = bvirt - t0; around = s0 - avirt; u[0] = around + bround; _j = (double)(s1 + _i); bvirt = (double)(_j - s1); avirt = _j - bvirt; bround = _i - bvirt; around = s1 - avirt; _0 = around + bround; _i = (double)(_0 - t1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - t1; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  682. u[3] = u3;
  683. C2length = FastExpansionSumZeroElim(C1length, C1, 4, u, C2);
  684. s1 = (double)(acxtail * bcytail); c = (double)(splitter * acxtail); abig = (double)(c - acxtail); ahi = c - abig; alo = acxtail - ahi; c = (double)(splitter * bcytail); abig = (double)(c - bcytail); bhi = c - abig; blo = bcytail - bhi; err1 = s1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); s0 = (alo * blo) - err3;
  685. t1 = (double)(acytail * bcxtail); c = (double)(splitter * acytail); abig = (double)(c - acytail); ahi = c - abig; alo = acytail - ahi; c = (double)(splitter * bcxtail); abig = (double)(c - bcxtail); bhi = c - abig; blo = bcxtail - bhi; err1 = t1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); t0 = (alo * blo) - err3;
  686. _i = (double)(s0 - t0); bvirt = (double)(s0 - _i); avirt = _i + bvirt; bround = bvirt - t0; around = s0 - avirt; u[0] = around + bround; _j = (double)(s1 + _i); bvirt = (double)(_j - s1); avirt = _j - bvirt; bround = _i - bvirt; around = s1 - avirt; _0 = around + bround; _i = (double)(_0 - t1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - t1; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  687. u[3] = u3;
  688. Dlength = FastExpansionSumZeroElim(C2length, C2, 4, u, D);
  689. return (D[Dlength - 1]);
  690. }
  691. /// <summary>
  692. /// Return a positive value if the point pd lies inside the circle passing through
  693. /// pa, pb, and pc; a negative value if it lies outside; and zero if the four points
  694. /// are cocircular. The points pa, pb, and pc must be in counterclockwise order, or
  695. /// the sign of the result will be reversed.
  696. /// </summary>
  697. /// <param name="pa"></param>
  698. /// <param name="pb"></param>
  699. /// <param name="pc"></param>
  700. /// <param name="pd"></param>
  701. /// <param name="permanent"></param>
  702. /// <returns></returns>
  703. /// <remarks>
  704. /// Uses exact arithmetic if necessary to ensure a correct answer. The result returned
  705. /// is the determinant of a matrix. This determinant is computed adaptively, in the
  706. /// sense that exact arithmetic is used only to the degree it is needed to ensure that
  707. /// the returned value has the correct sign. Hence, this function is usually quite fast,
  708. /// but will run more slowly when the input points are cocircular or nearly so.
  709. /// </remarks>
  710. private double InCircleAdapt(Point pa, Point pb, Point pc, Point pd, double permanent)
  711. {
  712. double adx, bdx, cdx, ady, bdy, cdy;
  713. double det, errbound;
  714. double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
  715. double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
  716. double[] bc = new double[4], ca = new double[4], ab = new double[4];
  717. double bc3, ca3, ab3;
  718. int axbclen, axxbclen, aybclen, ayybclen, alen;
  719. int bxcalen, bxxcalen, bycalen, byycalen, blen;
  720. int cxablen, cxxablen, cyablen, cyyablen, clen;
  721. int ablen;
  722. double[] finnow, finother, finswap;
  723. int finlength;
  724. double adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
  725. double adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
  726. double adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
  727. double[] aa = new double[4], bb = new double[4], cc = new double[4];
  728. double aa3, bb3, cc3;
  729. double ti1, tj1;
  730. double ti0, tj0;
  731. // Edited to work around index out of range exceptions (changed array length from 4 to 5).
  732. // See unsafe indexing in FastExpansionSumZeroElim.
  733. double[] u = new double[5], v = new double[5];
  734. double u3, v3;
  735. int temp8len, temp16alen, temp16blen, temp16clen;
  736. int temp32alen, temp32blen, temp48len, temp64len;
  737. double[] axtbb = new double[8], axtcc = new double[8], aytbb = new double[8], aytcc = new double[8];
  738. int axtbblen, axtcclen, aytbblen, aytcclen;
  739. double[] bxtaa = new double[8], bxtcc = new double[8], bytaa = new double[8], bytcc = new double[8];
  740. int bxtaalen, bxtcclen, bytaalen, bytcclen;
  741. double[] cxtaa = new double[8], cxtbb = new double[8], cytaa = new double[8], cytbb = new double[8];
  742. int cxtaalen, cxtbblen, cytaalen, cytbblen;
  743. double[] axtbc = new double[8], aytbc = new double[8], bxtca = new double[8], bytca = new double[8], cxtab = new double[8], cytab = new double[8];
  744. int axtbclen = 0, aytbclen = 0, bxtcalen = 0, bytcalen = 0, cxtablen = 0, cytablen = 0;
  745. double[] axtbct = new double[16], aytbct = new double[16], bxtcat = new double[16], bytcat = new double[16], cxtabt = new double[16], cytabt = new double[16];
  746. int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
  747. double[] axtbctt = new double[8], aytbctt = new double[8], bxtcatt = new double[8];
  748. double[] bytcatt = new double[8], cxtabtt = new double[8], cytabtt = new double[8];
  749. int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
  750. double[] abt = new double[8], bct = new double[8], cat = new double[8];
  751. int abtlen, bctlen, catlen;
  752. double[] abtt = new double[4], bctt = new double[4], catt = new double[4];
  753. int abttlen, bcttlen, cattlen;
  754. double abtt3, bctt3, catt3;
  755. double negate;
  756. double bvirt;
  757. double avirt, bround, around;
  758. double c;
  759. double abig;
  760. double ahi, alo, bhi, blo;
  761. double err1, err2, err3;
  762. double _i, _j;
  763. double _0;
  764. adx = (double)(pa.x - pd.x);
  765. bdx = (double)(pb.x - pd.x);
  766. cdx = (double)(pc.x - pd.x);
  767. ady = (double)(pa.y - pd.y);
  768. bdy = (double)(pb.y - pd.y);
  769. cdy = (double)(pc.y - pd.y);
  770. adx = (double)(pa.x - pd.x);
  771. bdx = (double)(pb.x - pd.x);
  772. cdx = (double)(pc.x - pd.x);
  773. ady = (double)(pa.y - pd.y);
  774. bdy = (double)(pb.y - pd.y);
  775. cdy = (double)(pc.y - pd.y);
  776. bdxcdy1 = (double)(bdx * cdy); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; c = (double)(splitter * cdy); abig = (double)(c - cdy); bhi = c - abig; blo = cdy - bhi; err1 = bdxcdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); bdxcdy0 = (alo * blo) - err3;
  777. cdxbdy1 = (double)(cdx * bdy); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; c = (double)(splitter * bdy); abig = (double)(c - bdy); bhi = c - abig; blo = bdy - bhi; err1 = cdxbdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); cdxbdy0 = (alo * blo) - err3;
  778. _i = (double)(bdxcdy0 - cdxbdy0); bvirt = (double)(bdxcdy0 - _i); avirt = _i + bvirt; bround = bvirt - cdxbdy0; around = bdxcdy0 - avirt; bc[0] = around + bround; _j = (double)(bdxcdy1 + _i); bvirt = (double)(_j - bdxcdy1); avirt = _j - bvirt; bround = _i - bvirt; around = bdxcdy1 - avirt; _0 = around + bround; _i = (double)(_0 - cdxbdy1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - cdxbdy1; around = _0 - avirt; bc[1] = around + bround; bc3 = (double)(_j + _i); bvirt = (double)(bc3 - _j); avirt = bc3 - bvirt; bround = _i - bvirt; around = _j - avirt; bc[2] = around + bround;
  779. bc[3] = bc3;
  780. axbclen = ScaleExpansionZeroElim(4, bc, adx, axbc);
  781. axxbclen = ScaleExpansionZeroElim(axbclen, axbc, adx, axxbc);
  782. aybclen = ScaleExpansionZeroElim(4, bc, ady, aybc);
  783. ayybclen = ScaleExpansionZeroElim(aybclen, aybc, ady, ayybc);
  784. alen = FastExpansionSumZeroElim(axxbclen, axxbc, ayybclen, ayybc, adet);
  785. cdxady1 = (double)(cdx * ady); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; c = (double)(splitter * ady); abig = (double)(c - ady); bhi = c - abig; blo = ady - bhi; err1 = cdxady1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); cdxady0 = (alo * blo) - err3;
  786. adxcdy1 = (double)(adx * cdy); c = (double)(splitter * adx); abig = (double)(c - adx); ahi = c - abig; alo = adx - ahi; c = (double)(splitter * cdy); abig = (double)(c - cdy); bhi = c - abig; blo = cdy - bhi; err1 = adxcdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); adxcdy0 = (alo * blo) - err3;
  787. _i = (double)(cdxady0 - adxcdy0); bvirt = (double)(cdxady0 - _i); avirt = _i + bvirt; bround = bvirt - adxcdy0; around = cdxady0 - avirt; ca[0] = around + bround; _j = (double)(cdxady1 + _i); bvirt = (double)(_j - cdxady1); avirt = _j - bvirt; bround = _i - bvirt; around = cdxady1 - avirt; _0 = around + bround; _i = (double)(_0 - adxcdy1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - adxcdy1; around = _0 - avirt; ca[1] = around + bround; ca3 = (double)(_j + _i); bvirt = (double)(ca3 - _j); avirt = ca3 - bvirt; bround = _i - bvirt; around = _j - avirt; ca[2] = around + bround;
  788. ca[3] = ca3;
  789. bxcalen = ScaleExpansionZeroElim(4, ca, bdx, bxca);
  790. bxxcalen = ScaleExpansionZeroElim(bxcalen, bxca, bdx, bxxca);
  791. bycalen = ScaleExpansionZeroElim(4, ca, bdy, byca);
  792. byycalen = ScaleExpansionZeroElim(bycalen, byca, bdy, byyca);
  793. blen = FastExpansionSumZeroElim(bxxcalen, bxxca, byycalen, byyca, bdet);
  794. adxbdy1 = (double)(adx * bdy); c = (double)(splitter * adx); abig = (double)(c - adx); ahi = c - abig; alo = adx - ahi; c = (double)(splitter * bdy); abig = (double)(c - bdy); bhi = c - abig; blo = bdy - bhi; err1 = adxbdy1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); adxbdy0 = (alo * blo) - err3;
  795. bdxady1 = (double)(bdx * ady); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; c = (double)(splitter * ady); abig = (double)(c - ady); bhi = c - abig; blo = ady - bhi; err1 = bdxady1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); bdxady0 = (alo * blo) - err3;
  796. _i = (double)(adxbdy0 - bdxady0); bvirt = (double)(adxbdy0 - _i); avirt = _i + bvirt; bround = bvirt - bdxady0; around = adxbdy0 - avirt; ab[0] = around + bround; _j = (double)(adxbdy1 + _i); bvirt = (double)(_j - adxbdy1); avirt = _j - bvirt; bround = _i - bvirt; around = adxbdy1 - avirt; _0 = around + bround; _i = (double)(_0 - bdxady1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - bdxady1; around = _0 - avirt; ab[1] = around + bround; ab3 = (double)(_j + _i); bvirt = (double)(ab3 - _j); avirt = ab3 - bvirt; bround = _i - bvirt; around = _j - avirt; ab[2] = around + bround;
  797. ab[3] = ab3;
  798. cxablen = ScaleExpansionZeroElim(4, ab, cdx, cxab);
  799. cxxablen = ScaleExpansionZeroElim(cxablen, cxab, cdx, cxxab);
  800. cyablen = ScaleExpansionZeroElim(4, ab, cdy, cyab);
  801. cyyablen = ScaleExpansionZeroElim(cyablen, cyab, cdy, cyyab);
  802. clen = FastExpansionSumZeroElim(cxxablen, cxxab, cyyablen, cyyab, cdet);
  803. ablen = FastExpansionSumZeroElim(alen, adet, blen, bdet, abdet);
  804. finlength = FastExpansionSumZeroElim(ablen, abdet, clen, cdet, fin1);
  805. det = Estimate(finlength, fin1);
  806. errbound = iccerrboundB * permanent;
  807. if ((det >= errbound) || (-det >= errbound))
  808. {
  809. return det;
  810. }
  811. bvirt = (double)(pa.x - adx); avirt = adx + bvirt; bround = bvirt - pd.x; around = pa.x - avirt; adxtail = around + bround;
  812. bvirt = (double)(pa.y - ady); avirt = ady + bvirt; bround = bvirt - pd.y; around = pa.y - avirt; adytail = around + bround;
  813. bvirt = (double)(pb.x - bdx); avirt = bdx + bvirt; bround = bvirt - pd.x; around = pb.x - avirt; bdxtail = around + bround;
  814. bvirt = (double)(pb.y - bdy); avirt = bdy + bvirt; bround = bvirt - pd.y; around = pb.y - avirt; bdytail = around + bround;
  815. bvirt = (double)(pc.x - cdx); avirt = cdx + bvirt; bround = bvirt - pd.x; around = pc.x - avirt; cdxtail = around + bround;
  816. bvirt = (double)(pc.y - cdy); avirt = cdy + bvirt; bround = bvirt - pd.y; around = pc.y - avirt; cdytail = around + bround;
  817. if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
  818. && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0))
  819. {
  820. return det;
  821. }
  822. errbound = iccerrboundC * permanent + resulterrbound * ((det) >= 0.0 ? (det) : -(det));
  823. det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) - (bdy * cdxtail + cdx * bdytail))
  824. + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
  825. + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) - (cdy * adxtail + adx * cdytail))
  826. + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
  827. + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) - (ady * bdxtail + bdx * adytail))
  828. + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
  829. if ((det >= errbound) || (-det >= errbound))
  830. {
  831. return det;
  832. }
  833. finnow = fin1;
  834. finother = fin2;
  835. if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) || (cdytail != 0.0))
  836. {
  837. adxadx1 = (double)(adx * adx); c = (double)(splitter * adx); abig = (double)(c - adx); ahi = c - abig; alo = adx - ahi; err1 = adxadx1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); adxadx0 = (alo * alo) - err3;
  838. adyady1 = (double)(ady * ady); c = (double)(splitter * ady); abig = (double)(c - ady); ahi = c - abig; alo = ady - ahi; err1 = adyady1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); adyady0 = (alo * alo) - err3;
  839. _i = (double)(adxadx0 + adyady0); bvirt = (double)(_i - adxadx0); avirt = _i - bvirt; bround = adyady0 - bvirt; around = adxadx0 - avirt; aa[0] = around + bround; _j = (double)(adxadx1 + _i); bvirt = (double)(_j - adxadx1); avirt = _j - bvirt; bround = _i - bvirt; around = adxadx1 - avirt; _0 = around + bround; _i = (double)(_0 + adyady1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = adyady1 - bvirt; around = _0 - avirt; aa[1] = around + bround; aa3 = (double)(_j + _i); bvirt = (double)(aa3 - _j); avirt = aa3 - bvirt; bround = _i - bvirt; around = _j - avirt; aa[2] = around + bround;
  840. aa[3] = aa3;
  841. }
  842. if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) || (adytail != 0.0))
  843. {
  844. bdxbdx1 = (double)(bdx * bdx); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; err1 = bdxbdx1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); bdxbdx0 = (alo * alo) - err3;
  845. bdybdy1 = (double)(bdy * bdy); c = (double)(splitter * bdy); abig = (double)(c - bdy); ahi = c - abig; alo = bdy - ahi; err1 = bdybdy1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); bdybdy0 = (alo * alo) - err3;
  846. _i = (double)(bdxbdx0 + bdybdy0); bvirt = (double)(_i - bdxbdx0); avirt = _i - bvirt; bround = bdybdy0 - bvirt; around = bdxbdx0 - avirt; bb[0] = around + bround; _j = (double)(bdxbdx1 + _i); bvirt = (double)(_j - bdxbdx1); avirt = _j - bvirt; bround = _i - bvirt; around = bdxbdx1 - avirt; _0 = around + bround; _i = (double)(_0 + bdybdy1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = bdybdy1 - bvirt; around = _0 - avirt; bb[1] = around + bround; bb3 = (double)(_j + _i); bvirt = (double)(bb3 - _j); avirt = bb3 - bvirt; bround = _i - bvirt; around = _j - avirt; bb[2] = around + bround;
  847. bb[3] = bb3;
  848. }
  849. if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) || (bdytail != 0.0))
  850. {
  851. cdxcdx1 = (double)(cdx * cdx); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; err1 = cdxcdx1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); cdxcdx0 = (alo * alo) - err3;
  852. cdycdy1 = (double)(cdy * cdy); c = (double)(splitter * cdy); abig = (double)(c - cdy); ahi = c - abig; alo = cdy - ahi; err1 = cdycdy1 - (ahi * ahi); err3 = err1 - ((ahi + ahi) * alo); cdycdy0 = (alo * alo) - err3;
  853. _i = (double)(cdxcdx0 + cdycdy0); bvirt = (double)(_i - cdxcdx0); avirt = _i - bvirt; bround = cdycdy0 - bvirt; around = cdxcdx0 - avirt; cc[0] = around + bround; _j = (double)(cdxcdx1 + _i); bvirt = (double)(_j - cdxcdx1); avirt = _j - bvirt; bround = _i - bvirt; around = cdxcdx1 - avirt; _0 = around + bround; _i = (double)(_0 + cdycdy1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = cdycdy1 - bvirt; around = _0 - avirt; cc[1] = around + bround; cc3 = (double)(_j + _i); bvirt = (double)(cc3 - _j); avirt = cc3 - bvirt; bround = _i - bvirt; around = _j - avirt; cc[2] = around + bround;
  854. cc[3] = cc3;
  855. }
  856. if (adxtail != 0.0)
  857. {
  858. axtbclen = ScaleExpansionZeroElim(4, bc, adxtail, axtbc);
  859. temp16alen = ScaleExpansionZeroElim(axtbclen, axtbc, 2.0 * adx, temp16a);
  860. axtcclen = ScaleExpansionZeroElim(4, cc, adxtail, axtcc);
  861. temp16blen = ScaleExpansionZeroElim(axtcclen, axtcc, bdy, temp16b);
  862. axtbblen = ScaleExpansionZeroElim(4, bb, adxtail, axtbb);
  863. temp16clen = ScaleExpansionZeroElim(axtbblen, axtbb, -cdy, temp16c);
  864. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  865. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  866. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  867. finswap = finnow; finnow = finother; finother = finswap;
  868. }
  869. if (adytail != 0.0)
  870. {
  871. aytbclen = ScaleExpansionZeroElim(4, bc, adytail, aytbc);
  872. temp16alen = ScaleExpansionZeroElim(aytbclen, aytbc, 2.0 * ady, temp16a);
  873. aytbblen = ScaleExpansionZeroElim(4, bb, adytail, aytbb);
  874. temp16blen = ScaleExpansionZeroElim(aytbblen, aytbb, cdx, temp16b);
  875. aytcclen = ScaleExpansionZeroElim(4, cc, adytail, aytcc);
  876. temp16clen = ScaleExpansionZeroElim(aytcclen, aytcc, -bdx, temp16c);
  877. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  878. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  879. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  880. finswap = finnow; finnow = finother; finother = finswap;
  881. }
  882. if (bdxtail != 0.0)
  883. {
  884. bxtcalen = ScaleExpansionZeroElim(4, ca, bdxtail, bxtca);
  885. temp16alen = ScaleExpansionZeroElim(bxtcalen, bxtca, 2.0 * bdx, temp16a);
  886. bxtaalen = ScaleExpansionZeroElim(4, aa, bdxtail, bxtaa);
  887. temp16blen = ScaleExpansionZeroElim(bxtaalen, bxtaa, cdy, temp16b);
  888. bxtcclen = ScaleExpansionZeroElim(4, cc, bdxtail, bxtcc);
  889. temp16clen = ScaleExpansionZeroElim(bxtcclen, bxtcc, -ady, temp16c);
  890. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  891. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  892. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  893. finswap = finnow; finnow = finother; finother = finswap;
  894. }
  895. if (bdytail != 0.0)
  896. {
  897. bytcalen = ScaleExpansionZeroElim(4, ca, bdytail, bytca);
  898. temp16alen = ScaleExpansionZeroElim(bytcalen, bytca, 2.0 * bdy, temp16a);
  899. bytcclen = ScaleExpansionZeroElim(4, cc, bdytail, bytcc);
  900. temp16blen = ScaleExpansionZeroElim(bytcclen, bytcc, adx, temp16b);
  901. bytaalen = ScaleExpansionZeroElim(4, aa, bdytail, bytaa);
  902. temp16clen = ScaleExpansionZeroElim(bytaalen, bytaa, -cdx, temp16c);
  903. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  904. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  905. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  906. finswap = finnow; finnow = finother; finother = finswap;
  907. }
  908. if (cdxtail != 0.0)
  909. {
  910. cxtablen = ScaleExpansionZeroElim(4, ab, cdxtail, cxtab);
  911. temp16alen = ScaleExpansionZeroElim(cxtablen, cxtab, 2.0 * cdx, temp16a);
  912. cxtbblen = ScaleExpansionZeroElim(4, bb, cdxtail, cxtbb);
  913. temp16blen = ScaleExpansionZeroElim(cxtbblen, cxtbb, ady, temp16b);
  914. cxtaalen = ScaleExpansionZeroElim(4, aa, cdxtail, cxtaa);
  915. temp16clen = ScaleExpansionZeroElim(cxtaalen, cxtaa, -bdy, temp16c);
  916. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  917. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  918. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  919. finswap = finnow; finnow = finother; finother = finswap;
  920. }
  921. if (cdytail != 0.0)
  922. {
  923. cytablen = ScaleExpansionZeroElim(4, ab, cdytail, cytab);
  924. temp16alen = ScaleExpansionZeroElim(cytablen, cytab, 2.0 * cdy, temp16a);
  925. cytaalen = ScaleExpansionZeroElim(4, aa, cdytail, cytaa);
  926. temp16blen = ScaleExpansionZeroElim(cytaalen, cytaa, bdx, temp16b);
  927. cytbblen = ScaleExpansionZeroElim(4, bb, cdytail, cytbb);
  928. temp16clen = ScaleExpansionZeroElim(cytbblen, cytbb, -adx, temp16c);
  929. temp32alen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32a);
  930. temp48len = FastExpansionSumZeroElim(temp16clen, temp16c, temp32alen, temp32a, temp48);
  931. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  932. finswap = finnow; finnow = finother; finother = finswap;
  933. }
  934. if ((adxtail != 0.0) || (adytail != 0.0))
  935. {
  936. if ((bdxtail != 0.0) || (bdytail != 0.0)
  937. || (cdxtail != 0.0) || (cdytail != 0.0))
  938. {
  939. ti1 = (double)(bdxtail * cdy); c = (double)(splitter * bdxtail); abig = (double)(c - bdxtail); ahi = c - abig; alo = bdxtail - ahi; c = (double)(splitter * cdy); abig = (double)(c - cdy); bhi = c - abig; blo = cdy - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  940. tj1 = (double)(bdx * cdytail); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; c = (double)(splitter * cdytail); abig = (double)(c - cdytail); bhi = c - abig; blo = cdytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  941. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; u[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  942. u[3] = u3;
  943. negate = -bdy;
  944. ti1 = (double)(cdxtail * negate); c = (double)(splitter * cdxtail); abig = (double)(c - cdxtail); ahi = c - abig; alo = cdxtail - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  945. negate = -bdytail;
  946. tj1 = (double)(cdx * negate); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  947. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; v[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; v[1] = around + bround; v3 = (double)(_j + _i); bvirt = (double)(v3 - _j); avirt = v3 - bvirt; bround = _i - bvirt; around = _j - avirt; v[2] = around + bround;
  948. v[3] = v3;
  949. bctlen = FastExpansionSumZeroElim(4, u, 4, v, bct);
  950. ti1 = (double)(bdxtail * cdytail); c = (double)(splitter * bdxtail); abig = (double)(c - bdxtail); ahi = c - abig; alo = bdxtail - ahi; c = (double)(splitter * cdytail); abig = (double)(c - cdytail); bhi = c - abig; blo = cdytail - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  951. tj1 = (double)(cdxtail * bdytail); c = (double)(splitter * cdxtail); abig = (double)(c - cdxtail); ahi = c - abig; alo = cdxtail - ahi; c = (double)(splitter * bdytail); abig = (double)(c - bdytail); bhi = c - abig; blo = bdytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  952. _i = (double)(ti0 - tj0); bvirt = (double)(ti0 - _i); avirt = _i + bvirt; bround = bvirt - tj0; around = ti0 - avirt; bctt[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 - tj1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - tj1; around = _0 - avirt; bctt[1] = around + bround; bctt3 = (double)(_j + _i); bvirt = (double)(bctt3 - _j); avirt = bctt3 - bvirt; bround = _i - bvirt; around = _j - avirt; bctt[2] = around + bround;
  953. bctt[3] = bctt3;
  954. bcttlen = 4;
  955. }
  956. else
  957. {
  958. bct[0] = 0.0;
  959. bctlen = 1;
  960. bctt[0] = 0.0;
  961. bcttlen = 1;
  962. }
  963. if (adxtail != 0.0)
  964. {
  965. temp16alen = ScaleExpansionZeroElim(axtbclen, axtbc, adxtail, temp16a);
  966. axtbctlen = ScaleExpansionZeroElim(bctlen, bct, adxtail, axtbct);
  967. temp32alen = ScaleExpansionZeroElim(axtbctlen, axtbct, 2.0 * adx, temp32a);
  968. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  969. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  970. finswap = finnow; finnow = finother; finother = finswap;
  971. if (bdytail != 0.0)
  972. {
  973. temp8len = ScaleExpansionZeroElim(4, cc, adxtail, temp8);
  974. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a);
  975. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  976. finswap = finnow; finnow = finother; finother = finswap;
  977. }
  978. if (cdytail != 0.0)
  979. {
  980. temp8len = ScaleExpansionZeroElim(4, bb, -adxtail, temp8);
  981. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a);
  982. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  983. finswap = finnow; finnow = finother; finother = finswap;
  984. }
  985. temp32alen = ScaleExpansionZeroElim(axtbctlen, axtbct, adxtail, temp32a);
  986. axtbcttlen = ScaleExpansionZeroElim(bcttlen, bctt, adxtail, axtbctt);
  987. temp16alen = ScaleExpansionZeroElim(axtbcttlen, axtbctt, 2.0 * adx, temp16a);
  988. temp16blen = ScaleExpansionZeroElim(axtbcttlen, axtbctt, adxtail, temp16b);
  989. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  990. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  991. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  992. finswap = finnow; finnow = finother; finother = finswap;
  993. }
  994. if (adytail != 0.0)
  995. {
  996. temp16alen = ScaleExpansionZeroElim(aytbclen, aytbc, adytail, temp16a);
  997. aytbctlen = ScaleExpansionZeroElim(bctlen, bct, adytail, aytbct);
  998. temp32alen = ScaleExpansionZeroElim(aytbctlen, aytbct, 2.0 * ady, temp32a);
  999. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  1000. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  1001. finswap = finnow; finnow = finother; finother = finswap;
  1002. temp32alen = ScaleExpansionZeroElim(aytbctlen, aytbct, adytail, temp32a);
  1003. aytbcttlen = ScaleExpansionZeroElim(bcttlen, bctt, adytail, aytbctt);
  1004. temp16alen = ScaleExpansionZeroElim(aytbcttlen, aytbctt, 2.0 * ady, temp16a);
  1005. temp16blen = ScaleExpansionZeroElim(aytbcttlen, aytbctt, adytail, temp16b);
  1006. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  1007. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  1008. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  1009. finswap = finnow; finnow = finother; finother = finswap;
  1010. }
  1011. }
  1012. if ((bdxtail != 0.0) || (bdytail != 0.0))
  1013. {
  1014. if ((cdxtail != 0.0) || (cdytail != 0.0)
  1015. || (adxtail != 0.0) || (adytail != 0.0))
  1016. {
  1017. ti1 = (double)(cdxtail * ady); c = (double)(splitter * cdxtail); abig = (double)(c - cdxtail); ahi = c - abig; alo = cdxtail - ahi; c = (double)(splitter * ady); abig = (double)(c - ady); bhi = c - abig; blo = ady - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1018. tj1 = (double)(cdx * adytail); c = (double)(splitter * cdx); abig = (double)(c - cdx); ahi = c - abig; alo = cdx - ahi; c = (double)(splitter * adytail); abig = (double)(c - adytail); bhi = c - abig; blo = adytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1019. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; u[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  1020. u[3] = u3;
  1021. negate = -cdy;
  1022. ti1 = (double)(adxtail * negate); c = (double)(splitter * adxtail); abig = (double)(c - adxtail); ahi = c - abig; alo = adxtail - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1023. negate = -cdytail;
  1024. tj1 = (double)(adx * negate); c = (double)(splitter * adx); abig = (double)(c - adx); ahi = c - abig; alo = adx - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1025. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; v[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; v[1] = around + bround; v3 = (double)(_j + _i); bvirt = (double)(v3 - _j); avirt = v3 - bvirt; bround = _i - bvirt; around = _j - avirt; v[2] = around + bround;
  1026. v[3] = v3;
  1027. catlen = FastExpansionSumZeroElim(4, u, 4, v, cat);
  1028. ti1 = (double)(cdxtail * adytail); c = (double)(splitter * cdxtail); abig = (double)(c - cdxtail); ahi = c - abig; alo = cdxtail - ahi; c = (double)(splitter * adytail); abig = (double)(c - adytail); bhi = c - abig; blo = adytail - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1029. tj1 = (double)(adxtail * cdytail); c = (double)(splitter * adxtail); abig = (double)(c - adxtail); ahi = c - abig; alo = adxtail - ahi; c = (double)(splitter * cdytail); abig = (double)(c - cdytail); bhi = c - abig; blo = cdytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1030. _i = (double)(ti0 - tj0); bvirt = (double)(ti0 - _i); avirt = _i + bvirt; bround = bvirt - tj0; around = ti0 - avirt; catt[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 - tj1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - tj1; around = _0 - avirt; catt[1] = around + bround; catt3 = (double)(_j + _i); bvirt = (double)(catt3 - _j); avirt = catt3 - bvirt; bround = _i - bvirt; around = _j - avirt; catt[2] = around + bround;
  1031. catt[3] = catt3;
  1032. cattlen = 4;
  1033. }
  1034. else
  1035. {
  1036. cat[0] = 0.0;
  1037. catlen = 1;
  1038. catt[0] = 0.0;
  1039. cattlen = 1;
  1040. }
  1041. if (bdxtail != 0.0)
  1042. {
  1043. temp16alen = ScaleExpansionZeroElim(bxtcalen, bxtca, bdxtail, temp16a);
  1044. bxtcatlen = ScaleExpansionZeroElim(catlen, cat, bdxtail, bxtcat);
  1045. temp32alen = ScaleExpansionZeroElim(bxtcatlen, bxtcat, 2.0 * bdx, temp32a);
  1046. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  1047. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  1048. finswap = finnow; finnow = finother; finother = finswap;
  1049. if (cdytail != 0.0)
  1050. {
  1051. temp8len = ScaleExpansionZeroElim(4, aa, bdxtail, temp8);
  1052. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, cdytail, temp16a);
  1053. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  1054. finswap = finnow; finnow = finother; finother = finswap;
  1055. }
  1056. if (adytail != 0.0)
  1057. {
  1058. temp8len = ScaleExpansionZeroElim(4, cc, -bdxtail, temp8);
  1059. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a);
  1060. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  1061. finswap = finnow; finnow = finother; finother = finswap;
  1062. }
  1063. temp32alen = ScaleExpansionZeroElim(bxtcatlen, bxtcat, bdxtail, temp32a);
  1064. bxtcattlen = ScaleExpansionZeroElim(cattlen, catt, bdxtail, bxtcatt);
  1065. temp16alen = ScaleExpansionZeroElim(bxtcattlen, bxtcatt, 2.0 * bdx, temp16a);
  1066. temp16blen = ScaleExpansionZeroElim(bxtcattlen, bxtcatt, bdxtail, temp16b);
  1067. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  1068. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  1069. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  1070. finswap = finnow; finnow = finother; finother = finswap;
  1071. }
  1072. if (bdytail != 0.0)
  1073. {
  1074. temp16alen = ScaleExpansionZeroElim(bytcalen, bytca, bdytail, temp16a);
  1075. bytcatlen = ScaleExpansionZeroElim(catlen, cat, bdytail, bytcat);
  1076. temp32alen = ScaleExpansionZeroElim(bytcatlen, bytcat, 2.0 * bdy, temp32a);
  1077. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  1078. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  1079. finswap = finnow; finnow = finother; finother = finswap;
  1080. temp32alen = ScaleExpansionZeroElim(bytcatlen, bytcat, bdytail, temp32a);
  1081. bytcattlen = ScaleExpansionZeroElim(cattlen, catt, bdytail, bytcatt);
  1082. temp16alen = ScaleExpansionZeroElim(bytcattlen, bytcatt, 2.0 * bdy, temp16a);
  1083. temp16blen = ScaleExpansionZeroElim(bytcattlen, bytcatt, bdytail, temp16b);
  1084. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  1085. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  1086. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  1087. finswap = finnow; finnow = finother; finother = finswap;
  1088. }
  1089. }
  1090. if ((cdxtail != 0.0) || (cdytail != 0.0))
  1091. {
  1092. if ((adxtail != 0.0) || (adytail != 0.0)
  1093. || (bdxtail != 0.0) || (bdytail != 0.0))
  1094. {
  1095. ti1 = (double)(adxtail * bdy); c = (double)(splitter * adxtail); abig = (double)(c - adxtail); ahi = c - abig; alo = adxtail - ahi; c = (double)(splitter * bdy); abig = (double)(c - bdy); bhi = c - abig; blo = bdy - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1096. tj1 = (double)(adx * bdytail); c = (double)(splitter * adx); abig = (double)(c - adx); ahi = c - abig; alo = adx - ahi; c = (double)(splitter * bdytail); abig = (double)(c - bdytail); bhi = c - abig; blo = bdytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1097. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; u[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; u[1] = around + bround; u3 = (double)(_j + _i); bvirt = (double)(u3 - _j); avirt = u3 - bvirt; bround = _i - bvirt; around = _j - avirt; u[2] = around + bround;
  1098. u[3] = u3;
  1099. negate = -ady;
  1100. ti1 = (double)(bdxtail * negate); c = (double)(splitter * bdxtail); abig = (double)(c - bdxtail); ahi = c - abig; alo = bdxtail - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1101. negate = -adytail;
  1102. tj1 = (double)(bdx * negate); c = (double)(splitter * bdx); abig = (double)(c - bdx); ahi = c - abig; alo = bdx - ahi; c = (double)(splitter * negate); abig = (double)(c - negate); bhi = c - abig; blo = negate - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1103. _i = (double)(ti0 + tj0); bvirt = (double)(_i - ti0); avirt = _i - bvirt; bround = tj0 - bvirt; around = ti0 - avirt; v[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 + tj1); bvirt = (double)(_i - _0); avirt = _i - bvirt; bround = tj1 - bvirt; around = _0 - avirt; v[1] = around + bround; v3 = (double)(_j + _i); bvirt = (double)(v3 - _j); avirt = v3 - bvirt; bround = _i - bvirt; around = _j - avirt; v[2] = around + bround;
  1104. v[3] = v3;
  1105. abtlen = FastExpansionSumZeroElim(4, u, 4, v, abt);
  1106. ti1 = (double)(adxtail * bdytail); c = (double)(splitter * adxtail); abig = (double)(c - adxtail); ahi = c - abig; alo = adxtail - ahi; c = (double)(splitter * bdytail); abig = (double)(c - bdytail); bhi = c - abig; blo = bdytail - bhi; err1 = ti1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); ti0 = (alo * blo) - err3;
  1107. tj1 = (double)(bdxtail * adytail); c = (double)(splitter * bdxtail); abig = (double)(c - bdxtail); ahi = c - abig; alo = bdxtail - ahi; c = (double)(splitter * adytail); abig = (double)(c - adytail); bhi = c - abig; blo = adytail - bhi; err1 = tj1 - (ahi * bhi); err2 = err1 - (alo * bhi); err3 = err2 - (ahi * blo); tj0 = (alo * blo) - err3;
  1108. _i = (double)(ti0 - tj0); bvirt = (double)(ti0 - _i); avirt = _i + bvirt; bround = bvirt - tj0; around = ti0 - avirt; abtt[0] = around + bround; _j = (double)(ti1 + _i); bvirt = (double)(_j - ti1); avirt = _j - bvirt; bround = _i - bvirt; around = ti1 - avirt; _0 = around + bround; _i = (double)(_0 - tj1); bvirt = (double)(_0 - _i); avirt = _i + bvirt; bround = bvirt - tj1; around = _0 - avirt; abtt[1] = around + bround; abtt3 = (double)(_j + _i); bvirt = (double)(abtt3 - _j); avirt = abtt3 - bvirt; bround = _i - bvirt; around = _j - avirt; abtt[2] = around + bround;
  1109. abtt[3] = abtt3;
  1110. abttlen = 4;
  1111. }
  1112. else
  1113. {
  1114. abt[0] = 0.0;
  1115. abtlen = 1;
  1116. abtt[0] = 0.0;
  1117. abttlen = 1;
  1118. }
  1119. if (cdxtail != 0.0)
  1120. {
  1121. temp16alen = ScaleExpansionZeroElim(cxtablen, cxtab, cdxtail, temp16a);
  1122. cxtabtlen = ScaleExpansionZeroElim(abtlen, abt, cdxtail, cxtabt);
  1123. temp32alen = ScaleExpansionZeroElim(cxtabtlen, cxtabt, 2.0 * cdx, temp32a);
  1124. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  1125. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  1126. finswap = finnow; finnow = finother; finother = finswap;
  1127. if (adytail != 0.0)
  1128. {
  1129. temp8len = ScaleExpansionZeroElim(4, bb, cdxtail, temp8);
  1130. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, adytail, temp16a);
  1131. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  1132. finswap = finnow; finnow = finother; finother = finswap;
  1133. }
  1134. if (bdytail != 0.0)
  1135. {
  1136. temp8len = ScaleExpansionZeroElim(4, aa, -cdxtail, temp8);
  1137. temp16alen = ScaleExpansionZeroElim(temp8len, temp8, bdytail, temp16a);
  1138. finlength = FastExpansionSumZeroElim(finlength, finnow, temp16alen, temp16a, finother);
  1139. finswap = finnow; finnow = finother; finother = finswap;
  1140. }
  1141. temp32alen = ScaleExpansionZeroElim(cxtabtlen, cxtabt, cdxtail, temp32a);
  1142. cxtabttlen = ScaleExpansionZeroElim(abttlen, abtt, cdxtail, cxtabtt);
  1143. temp16alen = ScaleExpansionZeroElim(cxtabttlen, cxtabtt, 2.0 * cdx, temp16a);
  1144. temp16blen = ScaleExpansionZeroElim(cxtabttlen, cxtabtt, cdxtail, temp16b);
  1145. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  1146. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  1147. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  1148. finswap = finnow; finnow = finother; finother = finswap;
  1149. }
  1150. if (cdytail != 0.0)
  1151. {
  1152. temp16alen = ScaleExpansionZeroElim(cytablen, cytab, cdytail, temp16a);
  1153. cytabtlen = ScaleExpansionZeroElim(abtlen, abt, cdytail, cytabt);
  1154. temp32alen = ScaleExpansionZeroElim(cytabtlen, cytabt, 2.0 * cdy, temp32a);
  1155. temp48len = FastExpansionSumZeroElim(temp16alen, temp16a, temp32alen, temp32a, temp48);
  1156. finlength = FastExpansionSumZeroElim(finlength, finnow, temp48len, temp48, finother);
  1157. finswap = finnow; finnow = finother; finother = finswap;
  1158. temp32alen = ScaleExpansionZeroElim(cytabtlen, cytabt, cdytail, temp32a);
  1159. cytabttlen = ScaleExpansionZeroElim(abttlen, abtt, cdytail, cytabtt);
  1160. temp16alen = ScaleExpansionZeroElim(cytabttlen, cytabtt, 2.0 * cdy, temp16a);
  1161. temp16blen = ScaleExpansionZeroElim(cytabttlen, cytabtt, cdytail, temp16b);
  1162. temp32blen = FastExpansionSumZeroElim(temp16alen, temp16a, temp16blen, temp16b, temp32b);
  1163. temp64len = FastExpansionSumZeroElim(temp32alen, temp32a, temp32blen, temp32b, temp64);
  1164. finlength = FastExpansionSumZeroElim(finlength, finnow, temp64len, temp64, finother);
  1165. finswap = finnow; finnow = finother; finother = finswap;
  1166. }
  1167. }
  1168. return finnow[finlength - 1];
  1169. }
  1170. #region Workspace
  1171. // InCircleAdapt workspace:
  1172. double[] fin1, fin2, abdet;
  1173. double[] axbc, axxbc, aybc, ayybc, adet;
  1174. double[] bxca, bxxca, byca, byyca, bdet;
  1175. double[] cxab, cxxab, cyab, cyyab, cdet;
  1176. double[] temp8, temp16a, temp16b, temp16c;
  1177. double[] temp32a, temp32b, temp48, temp64;
  1178. private void AllocateWorkspace()
  1179. {
  1180. fin1 = new double[1152];
  1181. fin2 = new double[1152];
  1182. abdet = new double[64];
  1183. axbc = new double[8];
  1184. axxbc = new double[16];
  1185. aybc = new double[8];
  1186. ayybc = new double[16];
  1187. adet = new double[32];
  1188. bxca = new double[8];
  1189. bxxca = new double[16];
  1190. byca = new double[8];
  1191. byyca = new double[16];
  1192. bdet = new double[32];
  1193. cxab = new double[8];
  1194. cxxab = new double[16];
  1195. cyab = new double[8];
  1196. cyyab = new double[16];
  1197. cdet = new double[32];
  1198. temp8 = new double[8];
  1199. temp16a = new double[16];
  1200. temp16b = new double[16];
  1201. temp16c = new double[16];
  1202. temp32a = new double[32];
  1203. temp32b = new double[32];
  1204. temp48 = new double[48];
  1205. temp64 = new double[64];
  1206. }
  1207. private void ClearWorkspace()
  1208. {
  1209. }
  1210. #endregion
  1211. #endregion
  1212. }
  1213. }