📄 geometricpredicates.cpp
字号:
/* Sets h = e + f. See the long version of my paper for details. *//* *//* If round-to-even is used (as with IEEE 754), maintains the strongly *//* nonoverlapping property. (That is, if e is strongly nonoverlapping, h *//* will be also.) Does NOT maintain the nonoverlapping or nonadjacent *//* properties. *//* *//*****************************************************************************/static int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h) /* h cannot be e or f. */{ REAL Q; INEXACT REAL Qnew; INEXACT REAL hh; INEXACT REAL bvirt; REAL avirt, bround, around; int eindex, findex, hindex; REAL enow, fnow; enow = e[0]; fnow = f[0]; eindex = findex = 0; if ((fnow > enow) == (fnow > -enow)) { Q = enow; enow = e[++eindex]; } else { Q = fnow; fnow = f[++findex]; } hindex = 0; if ((eindex < elen) && (findex < flen)) { if ((fnow > enow) == (fnow > -enow)) { Fast_Two_Sum(enow, Q, Qnew, hh); enow = e[++eindex]; } else { Fast_Two_Sum(fnow, Q, Qnew, hh); fnow = f[++findex]; } Q = Qnew; if (hh != 0.0) { h[hindex++] = hh; } while ((eindex < elen) && (findex < flen)) { if ((fnow > enow) == (fnow > -enow)) { Two_Sum(Q, enow, Qnew, hh); enow = e[++eindex]; } else { Two_Sum(Q, fnow, Qnew, hh); fnow = f[++findex]; } Q = Qnew; if (hh != 0.0) { h[hindex++] = hh; } } } while (eindex < elen) { Two_Sum(Q, enow, Qnew, hh); enow = e[++eindex]; Q = Qnew; if (hh != 0.0) { h[hindex++] = hh; } } while (findex < flen) { Two_Sum(Q, fnow, Qnew, hh); fnow = f[++findex]; Q = Qnew; if (hh != 0.0) { h[hindex++] = hh; } } if ((Q != 0.0) || (hindex == 0)) { h[hindex++] = Q; } return hindex;}/*****************************************************************************//* *//* scale_expansion_zeroelim() Multiply an expansion by a scalar, *//* eliminating zero components from the *//* output expansion. *//* *//* Sets h = be. See either version of my paper for details. *//* *//* Maintains the nonoverlapping property. If round-to-even is used (as *//* with IEEE 754), maintains the strongly nonoverlapping and nonadjacent *//* properties as well. (That is, if e has one of these properties, so *//* will h.) *//* *//*****************************************************************************/static int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h) /* e and h cannot be the same. */{ INEXACT REAL Q, sum; REAL hh; INEXACT REAL product1; REAL product0; int eindex, hindex; REAL enow; INEXACT REAL bvirt; REAL avirt, bround, around; INEXACT REAL c; INEXACT REAL abig; REAL ahi, alo, bhi, blo; REAL err1, err2, err3; Split(b, bhi, blo); Two_Product_Presplit(e[0], b, bhi, blo, Q, hh); hindex = 0; if (hh != 0) { h[hindex++] = hh; } for (eindex = 1; eindex < elen; eindex++) { enow = e[eindex]; Two_Product_Presplit(enow, b, bhi, blo, product1, product0); Two_Sum(Q, product0, sum, hh); if (hh != 0) { h[hindex++] = hh; } Fast_Two_Sum(product1, sum, Q, hh); if (hh != 0) { h[hindex++] = hh; } } if ((Q != 0.0) || (hindex == 0)) { h[hindex++] = Q; } return hindex;}/*****************************************************************************//* *//* estimate() Produce a one-word estimate of an expansion's value. *//* *//* See either version of my paper for details. *//* *//*****************************************************************************/static REAL estimate(int elen, REAL *e){ REAL Q; int eindex; Q = e[0]; for (eindex = 1; eindex < elen; eindex++) { Q += e[eindex]; } return Q;}/*****************************************************************************//* *//* orient2dfast() Approximate 2D orientation test. Nonrobust. *//* orient2dexact() Exact 2D orientation test. Robust. *//* orient2dslow() Another exact 2D orientation test. Robust. *//* orient2d() Adaptive exact 2D orientation test. Robust. *//* *//* Return a positive value if the points pa, pb, and pc occur *//* in counterclockwise order; a negative value if they occur *//* in clockwise order; and zero if they are collinear. The *//* result is also a rough approximation of twice the signed *//* area of the triangle defined by the three points. *//* *//* Only the first and last routine should be used; the middle two are for *//* timings. *//* *//* The last three use exact arithmetic to ensure a correct answer. The *//* result returned is the determinant of a matrix. In orient2d() only, *//* this determinant is computed adaptively, in the sense that exact *//* arithmetic is used only to the degree it is needed to ensure that the *//* returned value has the correct sign. Hence, orient2d() is usually quite *//* fast, but will run more slowly when the input points are collinear or *//* nearly so. *//* *//*****************************************************************************/static REAL orient2dadapt(REAL *pa, REAL *pb, REAL *pc, REAL detsum){ INEXACT REAL acx, acy, bcx, bcy; REAL acxtail, acytail, bcxtail, bcytail; INEXACT REAL detleft, detright; REAL detlefttail, detrighttail; REAL det, errbound; REAL B[4], C1[8], C2[12], D[16]; INEXACT REAL B3; int C1length, C2length, Dlength; REAL u[4]; INEXACT REAL u3; INEXACT REAL s1, t1; REAL s0, t0; INEXACT REAL bvirt; REAL avirt, bround, around; INEXACT REAL c; INEXACT REAL abig; REAL ahi, alo, bhi, blo; REAL err1, err2, err3; INEXACT REAL _i, _j; REAL _0; acx = (REAL) (pa[0] - pc[0]); bcx = (REAL) (pb[0] - pc[0]); acy = (REAL) (pa[1] - pc[1]); bcy = (REAL) (pb[1] - pc[1]); Two_Product(acx, bcy, detleft, detlefttail); Two_Product(acy, bcx, detright, detrighttail); Two_Two_Diff(detleft, detlefttail, detright, detrighttail, B3, B[2], B[1], B[0]); B[3] = B3; det = estimate(4, B); errbound = ccwerrboundB * detsum; if ((det >= errbound) || (-det >= errbound)) { return det; } Two_Diff_Tail(pa[0], pc[0], acx, acxtail); Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail); Two_Diff_Tail(pa[1], pc[1], acy, acytail); Two_Diff_Tail(pb[1], pc[1], bcy, bcytail); if ((acxtail == 0.0) && (acytail == 0.0) && (bcxtail == 0.0) && (bcytail == 0.0)) { return det; } errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det); det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail); if ((det >= errbound) || (-det >= errbound)) { return det; } Two_Product(acxtail, bcy, s1, s0); Two_Product(acytail, bcx, t1, t0); Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); u[3] = u3; C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1); Two_Product(acx, bcytail, s1, s0); Two_Product(acy, bcxtail, t1, t0); Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); u[3] = u3; C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2); Two_Product(acxtail, bcytail, s1, s0); Two_Product(acytail, bcxtail, t1, t0); Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]); u[3] = u3; Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D); return(D[Dlength - 1]);}REAL orient2d(REAL *pa, REAL *pb, REAL *pc){ REAL detleft, detright, det; REAL detsum, errbound; REAL orient; FPU_ROUND_DOUBLE; detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]); detright = (pa[1] - pc[1]) * (pb[0] - pc[0]); det = detleft - detright; if (detleft > 0.0) { if (detright <= 0.0) { FPU_RESTORE; return det; } else { detsum = detleft + detright; } } else if (detleft < 0.0) { if (detright >= 0.0) { FPU_RESTORE; return det; } else { detsum = -detleft - detright; } } else { FPU_RESTORE; return det; } errbound = ccwerrboundA * detsum; if ((det >= errbound) || (-det >= errbound)) { FPU_RESTORE; return det; } orient = orient2dadapt(pa, pb, pc, detsum); FPU_RESTORE; return orient;}/*****************************************************************************//* *//* orient3dfast() Approximate 3D orientation test. Nonrobust. *//* orient3dexact() Exact 3D orientation test. Robust. *//* orient3dslow() Another exact 3D orientation test. Robust. *//* orient3d() Adaptive exact 3D orientation test. Robust. *//* *//* Return a positive value if the point pd lies below the *//* plane passing through pa, pb, and pc; "below" is defined so *//* that pa, pb, and pc appear in counterclockwise order when *//* viewed from above the plane. Returns a negative value if *//* pd lies above the plane. Returns zero if the points are *//* coplanar. The result is also a rough approximation of six *//* times the signed volume of the tetrahedron defined by the *//* four points. *//* *//* Only the first and last routine should be used; the middle two are for *//* timings. *//* *//* The last three use exact arithmetic to ensure a correct answer. The *//* result returned is the determinant of a matrix. In orient3d() only, *//* this determinant is computed adaptively, in the sense that exact *//* arithmetic is used only to the degree it is needed to ensure that the *//* returned value has the correct sign. Hence, orient3d() is usually quite *//* fast, but will run more slowly when the input points are coplanar or *//* nearly so. *//* *//*****************************************************************************/static REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -