49 bool isRightTurn(
Turn_enum turn,
bool includeCollinear)
67 if (a_pt.x < a_bMin.x || a_pt.y < a_bMin.y || a_pt.x > a_bMax.x || a_pt.y > a_bMax.y)
84 if (a_b1Max.x < a_b2Min.x)
86 if (a_b1Min.x > a_b2Max.x)
88 if (a_b1Max.y < a_b2Min.y)
90 if (a_b1Min.y > a_b2Max.y)
135 double x1(p1->x), y1(p1->y), z1(p1->z);
136 double x2(p2->x), y2(p2->y), z2(p2->z);
137 double x3(p3->x), y3(p3->y), z3(p3->z);
138 *a = (y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2));
139 *b = (z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2));
140 *c = (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2));
141 double mag(sqrt((*a) * (*a) + (*b) * (*b) + (*c) * (*c)));
145 *d = -(*a) * x1 - (*b) * y1 - (*c) * z1;
156 double zmin = XM_DBL_HIGHEST;
157 double zmax = XM_DBL_LOWEST;
158 for (
size_t i = 0; i < a_points.size(); ++i)
160 double z = a_points[i].z;
161 zmin = std::min(zmin, z);
162 zmax = std::max(zmax, z);
164 return (zmin + zmax) / 2.0;
182 double delta = sqrt(r2) - sqrt(
sqr(pt.x - xc) +
sqr(pt.y - yc));
204 return (
sqr(pt1.x - pt2.x) +
sqr(pt1.y - pt2.y));
227 double det11, det12, det13, det21, det22, det23;
230 det11 = pt1->x - pt2->x;
231 det12 = pt1->y - pt2->y;
232 det13 = det11 * (pt1->x + pt2->x) / 2.0 + det12 * (pt1->y + pt2->y) / 2.0;
234 det21 = pt3->x - pt2->x;
235 det22 = pt3->y - pt2->y;
236 det23 = det21 * (pt3->x + pt2->x) / 2.0 + det22 * (pt3->y + pt2->y) / 2.0;
238 determinate = det11 * det22 - det12 * det21;
240 if (fabs(determinate) < tol)
260 *xc = (det13 * det22 - det23 * det12) / determinate;
261 *yc = (det11 * det23 - det21 * det13) / determinate;
262 *r2 =
sqr(pt1->x - *xc) +
sqr(pt1->y - *yc);
278 x = cart->x - orig->x;
279 y = cart->y - orig->y;
280 z = cart->z - orig->z;
285 bary->x = coef[0] * y + coef[1] * z + coef[2];
286 bary->y = coef[3] * y + coef[4] * z + coef[5];
287 bary->z = 1.0 - bary->x - bary->y;
290 bary->x = coef[0] * z + coef[1] * x + coef[2];
291 bary->y = coef[3] * z + coef[4] * x + coef[5];
292 bary->z = 1.0 - bary->x - bary->y;
295 bary->x = coef[0] * x + coef[1] * y + coef[2];
296 bary->y = coef[3] * x + coef[4] * y + coef[5];
297 bary->z = 1.0 - bary->x - bary->y;
324 double x1, x2, x3, y1, y2, y3, z1, z2, z3, sizeinv;
329 if (x1 > y1 && x1 > z1)
338 orig->x =
Mmin(p1->x,
Mmin(p2->x, p3->x));
339 orig->y =
Mmin(p1->y,
Mmin(p2->y, p3->y));
340 orig->z =
Mmin(p1->z,
Mmin(p2->z, p3->z));
343 x1 = p1->x - orig->x;
344 y1 = p1->y - orig->y;
345 z1 = p1->z - orig->z;
346 x2 = p2->x - orig->x;
347 y2 = p2->y - orig->y;
348 z2 = p2->z - orig->z;
349 x3 = p3->x - orig->x;
350 y3 = p3->y - orig->y;
351 z3 = p3->z - orig->z;
355 sizeinv = 1.0 / ((y2 - y3) * (z1 - z3) - (z2 - z3) * (y1 - y3));
356 coef[0] = (z3 - z2) * sizeinv;
357 coef[1] = (y2 - y3) * sizeinv;
358 coef[2] = (y3 * z2 - z3 * y2) * sizeinv;
359 coef[3] = (z1 - z3) * sizeinv;
360 coef[4] = (y3 - y1) * sizeinv;
361 coef[5] = (y1 * z3 - z1 * y3) * sizeinv;
364 sizeinv = 1.0 / ((z2 - z3) * (x1 - x3) - (x2 - x3) * (z1 - z3));
365 coef[0] = (x3 - x2) * sizeinv;
366 coef[1] = (z2 - z3) * sizeinv;
367 coef[2] = (z3 * x2 - x3 * z2) * sizeinv;
368 coef[3] = (x1 - x3) * sizeinv;
369 coef[4] = (z3 - z1) * sizeinv;
370 coef[5] = (z1 * x3 - x1 * z3) * sizeinv;
373 sizeinv = 1.0 / ((x2 - x3) * (y1 - y3) - (y2 - y3) * (x1 - x3));
374 coef[0] = (y3 - y2) * sizeinv;
375 coef[1] = (x2 - x3) * sizeinv;
376 coef[2] = (x3 * y2 - y3 * x2) * sizeinv;
377 coef[3] = (y1 - y3) * sizeinv;
378 coef[4] = (x3 - x1) * sizeinv;
379 coef[5] = (x1 * y3 - y1 * x3) * sizeinv;
430 double minx1, minx2, miny1, miny2, maxx1, maxx2, maxy1, maxy2;
431 double dx1, dy1, dz1, dx2, dy2, dz2, lambda, mu, cross;
434 minx1 = std::min(one1.x, one2.x);
435 maxx2 = std::max(two1.x, two2.x);
436 if (
GT_TOL(minx1, maxx2, tol))
440 maxx1 = std::max(one1.x, one2.x);
441 minx2 = std::min(two1.x, two2.x);
442 if (
LT_TOL(maxx1, minx2, tol))
446 miny1 = std::min(one1.y, one2.y);
447 maxy2 = std::max(two1.y, two2.y);
448 if (
GT_TOL(miny1, maxy2, tol))
452 maxy1 = std::max(one1.y, one2.y);
453 miny2 = std::min(two1.y, two2.y);
454 if (
LT_TOL(maxy1, miny2, tol))
459 dx1 = one2.x - one1.x;
460 dy1 = one2.y - one1.y;
461 dz1 = one2.z - one1.z;
462 dx2 = two2.x - two1.x;
463 dy2 = two2.y - two1.y;
464 dz2 = two2.z - two1.z;
466 cross = (dx1 * dy2) -
471 if (
EQ_TOL(cross, 0.0, tol))
474 lambda = (dy2 * (two1.x - one1.x) + dx2 * (one1.y - two1.y)) / cross;
483 bool checkDistance(
false);
487 checkDistance =
true;
489 else if (lambda > 1.0)
492 checkDistance =
true;
499 if (fabs(dx2) > fabs(dy2))
500 mu = (one1.x + lambda * dx1 - two1.x) / dx2;
502 mu = (one1.y + lambda * dy1 - two1.y) / dy2;
509 checkDistance =
true;
514 checkDistance =
true;
518 Pt3d lambdapos = one1 +
Pt3d(lambda * dx1, lambda * dy1, lambda * dz1);
519 Pt3d mupos = two1 +
Pt3d(mu * dx2, mu * dy2, mu * dz2);
566 double triarea1 =
trArea(vtx0, vtx1, vtx2);
567 return (triarea1 > 0.0);
579 double gmCross2D(
const double& dx1,
const double& dy1,
const double& dx2,
const double& dy2)
581 return (dx1 * dy2) - (dx2 * dy1);
592 return (a_A.x - a_origin.x) * (a_B.y - a_origin.y) - (a_A.y - a_origin.y) * (a_B.x - a_origin.x);
607 magn = sqrt(
sqr(dxn) +
sqr(dyn));
608 magp = sqrt(
sqr(dxp) +
sqr(dyp));
629 double theangle, cosign;
631 if (a_magn == 0.0 || a_magp == 0.0)
633 cosign = (dxn * dxp + dyn * dyp) / (a_magn * a_magp);
638 theangle = acos(cosign);
641 if ((dxn * dxp) + (dyn * dyp) < 0.0)
644 else if (
gmCross2D(dxp, dyp, dxn, dyn) < 0.0)
645 theangle = 2 *
XM_PI - theangle;
657 double dxp, dyp, dxn, dyn;
674 double dxp, dyp, dxn, dyn;
699 double x1, y1, x2, y2, m, cosine_dev;
700 x1 = a_p1.x - a_p0.x;
701 y1 = a_p1.y - a_p0.y;
702 x2 = a_p2.x - a_p1.x;
703 y2 = a_p2.y - a_p1.y;
704 m = sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2);
707 cosine_dev =
Mmin((x1 * x2 + y1 * y2) / (m), 1.0);
708 cosine_dev =
Mmax(cosine_dev, -1.0);
709 return acos(cosine_dev);
739 double dx = p2.x - p1.x;
740 double dy = p2.y - p1.y;
741 double mag = sqrt(
sqr(dx) +
sqr(dy));
747 double a = -dy / mag;
749 double c = -a * p2.x - b * p2.y;
751 double d = a * x + b * y + c;
752 return fabs(d) <= tol;
773 if ((
Mmin(a_pt1.x, a_pt2.x) - a_tol <= a_x &&
Mmax(a_pt1.x, a_pt2.x) + a_tol >= a_x) &&
774 (
Mmin(a_pt1.y, a_pt2.y) - a_tol <= a_y &&
Mmax(a_pt1.y, a_pt2.y) + a_tol >= a_y))
789 a_min.x = std::min(a_pt.x, a_min.x);
790 a_min.y = std::min(a_pt.y, a_min.y);
791 a_min.z = std::min(a_pt.z, a_min.z);
792 a_max.x = std::max(a_pt.x, a_max.x);
793 a_max.y = std::max(a_pt.y, a_max.y);
794 a_max.z = std::max(a_pt.z, a_max.z);
804 a_min.x = std::min(a_pt.x, a_min.x);
805 a_min.y = std::min(a_pt.y, a_min.y);
806 a_max.x = std::max(a_pt.x, a_max.x);
807 a_max.y = std::max(a_pt.y, a_max.y);
817 a_min.x = std::min(a_pt.x, a_min.x);
818 a_min.y = std::min(a_pt.y, a_min.y);
819 a_max.x = std::max(a_pt.x, a_max.x);
820 a_max.y = std::max(a_pt.y, a_max.y);
834 return sqrt(
sqr(x1 - x2) +
sqr(y1 - y2));
844 return sqrt(
sqr(pt1.x - pt2.x) +
sqr(pt1.y - pt2.y));
866 double dx32 = a_v3.x - a_v2.x;
867 double dy32 = a_v3.y - a_v2.y;
868 double dx12 = a_v1.x - a_v2.x;
869 double dy12 = a_v1.y - a_v2.y;
870 double d32 = sqrt(dx32 * dx32 + dy32 * dy32);
871 double d12 = sqrt(dx12 * dx12 + dy12 * dy12);
872 double mag = d12 * d32;
873 double sint = (dx32 * dy12 - dx12 * dy32) / mag;
878 else if (sint < -a_angtol)
884 double cost = (dx12 * dx32 + dy12 * dy32) / mag;
898 size_t size = a_points.size();
899 for (
size_t i = 0; i < size; ++i)
900 centroid += a_points[i];
901 return (centroid / (
double)size);
914 double xMax = XM_DBL_LOWEST, yMax = XM_DBL_LOWEST, xMin = XM_DBL_HIGHEST, yMin = XM_DBL_HIGHEST;
916 for (i = 0; i < pts.size(); ++i)
920 xMax = (x > xMax) ? x : xMax;
921 yMax = (y > yMax) ? y : yMax;
922 xMin = (x < xMin) ? x : xMin;
923 yMin = (y < yMin) ? y : yMin;
925 double xOffset = (xMax + xMin) / 2.0;
926 double yOffset = (yMax + yMin) / 2.0;
928 double signedArea = 0.0;
929 for (i = 0; i < pts.size() - 1; ++i)
931 double x0 = pts[i].x - xOffset;
932 double y0 = pts[i].y - yOffset;
933 double x1 = pts[i + 1].x - xOffset;
934 double y1 = pts[i + 1].y - yOffset;
935 double a = x0 * y1 - x1 * y0;
937 centroid.x += (x0 + x1) * a;
938 centroid.y += (y0 + y1) * a;
941 double x0 = pts[i].x - xOffset;
942 double y0 = pts[i].y - yOffset;
943 double x1 = pts[0].x - xOffset;
944 double y1 = pts[0].y - yOffset;
945 double a = x0 * y1 - x1 * y0;
947 centroid.x += (x0 + x1) * a;
948 centroid.y += (y0 + y1) * a;
950 centroid.x /= (6.0 * signedArea);
951 centroid.y /= (6.0 * signedArea);
952 centroid.x += xOffset;
953 centroid.y += yOffset;
969 double min = std::min(one1.x, one2.x);
970 double max = std::max(two1.x, two2.x);
972 if (
GT_TOL(min, max, tol))
974 max = std::max(one1.x, one2.x);
975 min = std::min(two1.x, two2.x);
976 if (
LT_TOL(max, min, tol))
978 min = std::min(one1.y, one2.y);
979 max = std::max(two1.y, two2.y);
980 if (
GT_TOL(min, max, tol))
982 max = std::max(one1.y, one2.y);
983 min = std::min(two1.y, two2.y);
984 if (
LT_TOL(max, min, tol))
987 Pt2d d1(one2 - one1), d2(two2 - two1);
991 double cross = (d2.x * d1.y) - (d2.y * d1.x);
995 double s = ((d1.x * (two1.y - one1.y)) + (d1.y * (one1.x - two1.x))) / cross;
999 double t = ((d2.x * (one1.y - two1.y)) + (d2.y * (two1.x - one1.x))) / cross;
1014 const Pt3d& a_segment1Point2,
1015 const Pt3d& a_segment2Point1,
1016 const Pt3d& a_segment2Point2)
1020 if ((a_segment1Point1 == a_segment2Point1 || a_segment1Point1 == a_segment2Point2) &&
1021 (a_segment1Point2 == a_segment2Point1 || a_segment1Point2 == a_segment2Point2))
1035 double result1 =
gmCross2D(a_segment2Point1, a_segment1Point1, a_segment2Point2);
1036 double result2 =
gmCross2D(a_segment2Point1, a_segment1Point2, a_segment2Point2);
1037 double result3 =
gmCross2D(a_segment1Point1, a_segment2Point1, a_segment1Point2);
1038 double result4 =
gmCross2D(a_segment2Point1, a_segment2Point2, a_segment1Point2);
1040 return (result1 * result2 < 0 && result3 * result4 < 0);
1056 template <
typename T>
1063 if (a_verts && a_num)
1065 int nmleft = 0, nmrght = 0;
1066 double dy2 = fabs(a_verts[0].y - a_y);
1068 for (
size_t i = 0; i < a_num; i++)
1074 dy2 = fabs(a_verts[i2].y - a_y);
1081 if (((a_verts[i].x >= a_x) && (a_verts[i2].x <= a_x)) ||
1082 ((a_verts[i].x <= a_x) && (a_verts[i2].x >= a_x)))
1090 diff = a_verts[i].x - a_x;
1091 if (fabs(diff) <= a_tol)
1093 else if (a_verts[i].y < a_verts[i2].y)
1103 else if (dy2 <= a_tol)
1108 diff = a_verts[i2].x - a_x;
1109 if (fabs(diff) <= a_tol)
1111 else if (a_verts[i2].y < a_verts[i].y)
1120 else if (((a_verts[i].y < a_y) && (a_verts[i2].y > a_y)) ||
1121 ((a_verts[i].y > a_y) && (a_verts[i2].y < a_y)))
1125 double val = a_verts[i].x + (a_verts[i2].x - a_verts[i].x) * (a_y - a_verts[i].y) /
1126 (a_verts[i2].y - a_verts[i].y);
1128 if (fabs(diff) <= a_tol)
1136 nmleft = nmleft % 2;
1137 nmrght = nmrght % 2;
1138 if (nmleft != nmrght)
1140 else if (nmleft == 1)
1226 const double a_tol);
1240 const double a_tol);
1254 const double a_tol);
1265 double const kFactor = 1e-9;
1266 double xytol = d * kFactor;
1267 if (xytol < kFactor)
1281 static double xytol = a_value;
1294 static double ztol = a_value;
1310 double dx = fabs(x1 - x2);
1311 double dy = fabs(y1 - y2);
1312 if (dx > tolerance || dy > tolerance)
1314 else if (sqrt(dx * dx + dy * dy) <= tolerance)
1361 if (point1.x == point2.x && point1.y == point2.y)
1384 if ((fabs(x1 - x2) <= tolerance) && (fabs(y1 - y2) <= tolerance) && (fabs(z1 - z2) <= tolerance))
1452 const Pt3d* inpoint,
1458 double dx, dy, a, b, c, mag;
1463 mag = sqrt(
sqr(dx) +
sqr(dy));
1472 c = -a * p1->x - b * p1->y;
1474 d1 = a * x + b * y + c;
1476 d2 = a * inpoint->x + b * inpoint->y + c;
1478 if (
Mfabs(d2) <= tol)
1487 if (
Mfabs(d1) <= tol)
1503 if ((d1 < 0.0) && (d2 < 0.0))
1511 else if ((d1 > 0.0) && (d2 > 0.0))
1568 double x0 = pts[0].x;
1569 double y0 = pts[0].y;
1570 for (
id = 1;
id < npoints;
id++)
1572 x.push_back((pts[
id].x - x0));
1573 y.push_back((pts[
id].y - y0));
1575 for (
id = 0;
id < npoints - 2;
id++)
1577 area += (x[id] * y[
id + 1]);
1578 area -= (y[id] * x[
id + 1]);
1593 for (
int i = 0; i < a_size; i += 2)
1595 v[i / 2].x = a_array[i];
1596 v[i / 2].y = a_array[i + 1];
1608 a_min = a_max =
Pt3d();
1610 a_min = a_max = a_pts.front();
1611 for (
size_t i = 0; i < a_pts.size(); ++i)
1613 if (a_pts[i].x < a_min.x)
1614 a_min.x = a_pts[i].x;
1615 if (a_pts[i].y < a_min.y)
1616 a_min.y = a_pts[i].y;
1617 if (a_pts[i].z < a_min.z)
1618 a_min.z = a_pts[i].z;
1619 if (a_pts[i].x > a_max.x)
1620 a_max.x = a_pts[i].x;
1621 if (a_pts[i].y > a_max.y)
1622 a_max.y = a_pts[i].y;
1623 if (a_pts[i].z > a_max.z)
1624 a_max.z = a_pts[i].z;
1637 int numnodes = (int)a_pts.size();
1643 for (
int i = 0; i < numnodes; i++)
1649 center.x = sumx / numnodes;
1650 center.y = sumy / numnodes;
1654 std::vector<std::pair<float, int> > angleIndex(numnodes);
1655 for (
int i = 0; i < numnodes; i++)
1657 float angle = (float)(atan2(a_pts[i].y - center.y, a_pts[i].x - center.x));
1658 angleIndex[i] = std::pair<float, int>(angle, i);
1661 std::stable_sort(angleIndex.begin(), angleIndex.end());
1664 auto startIter = angleIndex.begin();
1665 while (startIter != angleIndex.end() && startIter->second != a_startindex)
1669 if (startIter == angleIndex.end())
1670 startIter = angleIndex.begin();
1673 a_ccwOrder.resize(numnodes, 0);
1675 for (
auto iter = startIter; iter != angleIndex.end(); ++iter)
1677 a_ccwOrder[j] = iter->second;
1680 for (
auto iter = angleIndex.begin(); iter != startIter; ++iter)
1682 a_ccwOrder[j] = iter->second;
1698 for (
size_t i = 0; i < ccwOrder.size(); ++i)
1700 a_pts[i] = pts[ccwOrder[i]];
1723 a_newpt.x = a_pt1.x;
1724 a_newpt.y = a_pt1.y;
1728 a_newpt.x = a_pt2.x;
1729 a_newpt.y = a_pt2.y;
1733 double dx = a_pt2.x - a_pt1.x;
1734 double dy = a_pt2.y - a_pt1.y;
1735 a_newpt.x = a_pt1.x + dx * t;
1736 a_newpt.y = a_pt1.y + dy * t;
1756 dx = a_pt2.x - a_pt1.x;
1757 dy = a_pt2.y - a_pt1.y;
1759 if ((dx == 0.0 && dy == 0.0) || (sqrt(dx * dx + dy * dy) <= a_tol))
1765 t = ((a_pt.x - a_pt1.x) * dx + (a_pt.y - a_pt1.y) * dy) / (dx * dx + dy * dy);
1783 const Pt3d& a_vertex2,
1784 const Pt3d& a_oppositevertex,
1789 double dx = a_vertex2.x - a_vertex1.x;
1790 double dy = a_vertex2.y - a_vertex1.y;
1791 double mag = sqrt(
sqr(dx) +
sqr(dy));
1798 double a = -dy / mag;
1799 double b = dx / mag;
1800 double c = -a * a_vertex1.x - b * a_vertex1.y;
1802 double d1 = a * a_x + b * a_y + c;
1804 double d2 = a * a_oppositevertex.x + b * a_oppositevertex.y + c;
1805 if (fabs(d1) <= a_tol)
1807 else if ((d1 < 0.0) && (d2 < 0.0))
1809 else if ((d1 > 0.0) && (d2 > 0.0))
1825 a_min.x = a_max.x = a_points.at(0).x;
1826 a_min.y = a_max.y = a_points.at(0).y;
1827 for (
int i = 1; i < (int)a_points.size(); i++)
1842 a_min.x = a_max.x = a_points.at(0).x;
1843 a_min.y = a_max.y = a_points.at(0).y;
1844 a_min.z = a_max.z = 0.0;
1845 for (
int i = 1; i < (int)a_points.size(); i++)
1860 a_min.x = a_max.x = a_points.at(0).x;
1861 a_min.y = a_max.y = a_points.at(0).y;
1862 a_min.z = a_max.z = a_points.at(0).z;
1863 for (
int i = 1; i < (int)a_points.size(); i++)
1877 double deltax, deltay, arad, theangle;
1879 deltax = a_pt1.x - a_pt2.x;
1880 deltay = a_pt1.y - a_pt2.y;
1881 hypot = sqrt(
sqr(deltax) +
sqr(deltay));
1882 arad = deltax / hypot;
1885 else if (arad < -.9999)
1888 theangle = acos(arad);
1890 theangle = 2 *
XM_PI - acos(arad);
1891 return (theangle - (
XM_PI / 2));
1903 double dxn, dyn, dxp, dyp, magn, magp, angletoedge1, theanglebetween;
1906 dxp = a_p1.x - a_p2.x;
1907 dyp = a_p1.y - a_p2.y;
1908 dxn = a_p3.x - a_p2.x;
1909 dyn = a_p3.y - a_p2.y;
1910 angletoedge1 = atan2(dyp, dxp);
1911 magn = sqrt(
sqr(dxn) +
sqr(dyn));
1912 magp = sqrt(
sqr(dxp) +
sqr(dyp));
1913 cosign = (dxn * dxp + dyn * dyp) / (magn * magp);
1914 if (cosign > .99999)
1916 if (cosign < -.99999)
1918 theanglebetween = acos(cosign);
1919 if (theanglebetween == 0.0)
1921 if ((dxn * dxp) + (dyn * dyp) < 0.0)
1922 theanglebetween =
XM_PI;
1924 else if (
gmCross2D(dxp, dyp, dxn, dyn) < 0.0)
1925 theanglebetween = 2 *
XM_PI - theanglebetween;
1926 return angletoedge1 + theanglebetween / 2.0;
1956 *a_mag = sqrt(
sqr(*a_x) +
sqr(*a_y));
1957 *a_dir = (atan(*a_y / *a_x)) * (180 /
XM_PI);
1966 rads = *a_dir * (
XM_PI / 180);
1967 *a_x = cos(rads) * *a_mag;
1968 *a_y = sin(rads) * *a_mag;
1985 vector.x = a_p2.x - a_p1.x;
1986 vector.y = a_p2.y - a_p1.y;
1987 vector.z = a_p2.z - a_p1.z;
2000 double ang = a_angle;
2004 ang *= (180.0 /
XM_PI);
2007 #if BOOST_OS_WINDOWS 2008 while (
LT_TOL(ang, 0.0, DBL_EPSILON) && _finite(ang))
2011 while (
LT_TOL(ang, 0.0, DBL_EPSILON) && std::isfinite(ang))
2016 #if BOOST_OS_WINDOWS 2017 while (
GTEQ_TOL(ang, 360.0, DBL_EPSILON) && _finite(ang))
2020 while (
GTEQ_TOL(ang, 360.0, DBL_EPSILON) && std::isfinite(ang))
2036 a_vec3->x = a_vec1.y * a_vec2.z - a_vec1.z * a_vec2.y;
2037 a_vec3->y = a_vec1.z * a_vec2.x - a_vec1.x * a_vec2.z;
2038 a_vec3->z = a_vec1.x * a_vec2.y - a_vec1.y * a_vec2.x;
2050 return (a_vec1.x * a_vec2.x + a_vec1.y * a_vec2.y + a_vec1.z * a_vec2.z);
2080 Pt3d& a_IntersectPt)
2083 Pt3d dir, n, NullVector(0.0, 0.0, 0.0), u, v, w, w0;
2091 if (n == NullVector)
2097 dir = a_pt2 - a_pt1;
2122 if (r < -FLT_EPSILON || r > 1.0 + FLT_EPSILON)
2128 a_IntersectPt = a_pt1 + dir * r;
2131 double D, uu, uv, vv, wu, wv;
2136 w = a_IntersectPt - a_t0;
2139 D = uv * uv - uu * vv;
2144 s = (uv * wv - vv * wu) / D;
2145 if (s < 0.0 || s > 1.0)
2150 t = (uv * wu - uu * wv) / D;
2151 if (t < 0.0 || (s + t) > 1.0)
2183 double a1, b1, c, mag;
2186 a1 = a_pt2->x - a_pt1->x;
2187 b1 = a_pt2->y - a_pt1->y;
2188 mag = sqrt(a1 * a1 + b1 * b1);
2192 return sqrt(
sqr(a_pt1->x - a_x) +
sqr(a_pt1->y - a_y));
2199 c = -a * a_pt1->x - b * a_pt1->y;
2201 dist = a * a_x + b * a_y + c;
2217 for (
size_t i = 0; i < points.size(); ++i)
2221 std::sort(points.begin(), points.end());
2222 auto end = std::unique(points.begin(), points.end());
2223 size_t size = end - points.begin();
2224 points.resize(size);
2234 for (
auto p = points.begin(); p != points.end(); ++p)
2236 size_t lsize = lower.size();
2237 while (lsize > 1 && isRightTurn(
gmTurn(lower[lsize - 2], lower[lsize - 1], *p), !a_includeOn))
2240 lsize = lower.size();
2242 lower.push_back(*p);
2248 for (
auto p = points.rbegin(); p != points.rend(); ++p)
2250 size_t usize = upper.size();
2251 while (usize > 1 && isRightTurn(
gmTurn(upper[usize - 2], upper[usize - 1], *p), !a_includeOn))
2254 usize = upper.size();
2256 upper.push_back(*p);
2261 a_hull.insert(a_hull.end(), upper.begin(), upper.end());
2272 #include <boost/timer/timer.hpp> 2322 const double xStart = -5;
2323 const double xEnd = 55;
2324 const double yStart = 35;
2325 const double yEnd = -5;
2326 const double kIncrement = 1e-1;
2328 for (
double y = yStart; y >= yEnd; y -= kIncrement)
2330 for (
double x = xStart; x <= xEnd; x += kIncrement)
2350 boost::timer::cpu_times
const elapsed_times(
m_timer.elapsed());
2351 boost::timer::nanosecond_type time = elapsed_times.system + elapsed_times.user;
2354 const double NANO_PER_SEC = 1e9;
2355 double seconds = time / NANO_PER_SEC;
2358 int const kCountTotal = 240000;
2359 TS_ASSERT_EQUALS(
m_count, kCountTotal);
2367 TS_ASSERT(seconds <
MaxTime());
2395 if (outer == 1 && inner == -1)
2399 else if (outer == -1 || inner == 1)
2403 else if (outer == 0 || inner == 0)
2460 std::vector<Pt3d> points{{0, 0, 0}, {10, 0, 0}, {10, 5, 0}, {10, 10, 0}, {0, 10, 0}};
2461 const double kDelta = 1e-5;
2480 std::vector<Pt3d> points{{0, 0, 0}, {10, 0, 0}, {10, 5, 0}, {10, 10, 0}, {0, 10, 0}};
2481 const double kDelta = 1e-5;
2518 using namespace xms;
2523 expectedHull = {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}};
2524 for (
int i = 0; i < 2; ++i)
2526 for (
int j = 0; j < 2; ++j)
2528 inputPoints.push_back(
Pt3d(i, j));
2531 inputPoints.push_back(
Pt3d(.5, .5));
2533 TS_ASSERT_EQUALS(expectedHull, hull);
2536 expectedHull.clear();
2537 inputPoints.clear();
2539 TS_ASSERT_EQUALS(expectedHull, hull);
2546 using namespace xms;
2553 bool expected =
false;
2554 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2562 bool expected =
true;
2563 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2571 bool expected =
true;
2572 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2580 bool expected =
false;
2581 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2589 bool expected =
false;
2590 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2598 bool expected =
false;
2599 TS_ASSERT_EQUALS(expected,
gmLinesCross(point1, point2, point3, point4));
2630 xms::VecPt3d poly{{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {10, 5, 0}, {10, 10, 0}, {0, 10, 0}};
2631 for (
size_t i = 0; i < 2; ++i)
2636 std::reverse(poly.begin(), poly.end());
virtual void Setup()
Setup the polygons.
void testConvexHull()
Test building a convex hull.
double gmMiddleZ(const VecPt3d &a_points)
Returns the z value halfway between the max and min z. Different from the average z (where many point...
For testing point in polygon speed.
bool gmOnLineWithTol(const Pt3d &p1, const Pt3d &p2, const double x, const double y, const double tol)
Determines if a point (x,y) is on the line defined by p1 and p2. Assumes p1 and p2 aren't the same...
double gmZTol(bool a_set, double a_value)
Get or set (set first time) global z tolerance for float operations.
bool gmInsideOfLineWithTol(const Pt3d &a_vertex1, const Pt3d &a_vertex2, const Pt3d &a_oppositevertex, const double a_x, const double a_y, const double a_tol)
Returns TRUE if the Point on the same side of the line (defined by vertex1 and vertex2) as oppositeve...
double gmBisectingAngle(const Pt3d &a_p1, const Pt3d &a_p2, const Pt3d &a_p3)
Returns the angle (0-2pi) which bisects the edges p2-p1 and p2-p3 based on a ccw rotation from edge 1...
std::vector< int > VecInt
template int gmPointInPolygon2D< Pt2d >(const Pt2d *a_verts, const size_t a_num, const double a_x, const double a_y, const double a_tol)
void gmOrderPointsCounterclockwise(const VecPt3d &a_pts, VecInt &a_ccwOrder, int a_startindex)
Orders array of points counter clockwise. Given non-empty array of points. array of point indices ord...
virtual void GetResults()
Get the timer results and do some assertions.
double gmXyDistance(double x1, double y1, double x2, double y2)
Compute the 2d distance between 2 points.
bool gmOnLineAndBetweenEndpointsWithTol(const Pt3d &a_pt1, const Pt3d &a_pt2, const double a_x, const double a_y, double a_tol)
determines if (x,y) is on the line passing through p1 & p2 and between p1 & p2.
Functions dealing with triangles.
virtual double MaxTime()=0
std::vector< double > VecDbl
virtual double MaxTime() override
Maximum time test should take.
bool gmPointInTriangleWithTol(const Pt3d *p1, const Pt3d *p2, const Pt3d *p3, double x, double y, double tol)
Returns true if (x,y) is in the tri formed by p1, p2, p3.
PtInOutOrOn_enum gmPtInCircumcircle(const Pt3d &pt, Pt3d circumcirclePts[3])
Is a given point inside a circumcircle defined by three points?
template int gmPointInPolygon2D< Pt3d >(const Pt3d *a_verts, const size_t a_num, const double a_x, const double a_y, const double a_tol)
virtual void CheckPoint(const xms::Pt3d &a_pt)=0
double gmPerpendicularAngle(const Pt3d &a_pt1, const Pt3d &a_pt2)
Returns the angle in radians perpendicular to the two points.
bool gmEqualPointsXY(double x1, double y1, double x2, double y2, double tolerance)
Returns true if the points are equal to within gmXyTol().
Turn_enum gmTurn(const Pt3d &a_v1, const Pt3d &a_v2, const Pt3d &a_v3, double a_angtol)
Determine if angle a_v1, a_v2, a_v3 is a left turn, a right turn, colinear 180 degrees, or colinear 0 degrees.
double gmAngleBetween2DVectors(double dxp, double dyp, double dxn, double dyn)
Returns the angle (0-2PI) in radians between the edges p and n based on a ccw rotation from p to n...
bool gmIntersectLineSegmentsWithTol(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2, double *xi, double *yi, double *zi1, double *zi2, double tol)
Intersects the plan projection of two line segments.
void gmGetConvexHull(const VecPt3d &a_pts, VecPt3d &a_hull, bool a_includeOn)
Calculate convex hull using Monotone chain aka Andrew's algorithm.
virtual void CheckPoint(const xms::Pt3d &a_pt) override
Determine if a point is in or out.
turns back on same segment
static void SetUpPolyWithHole(xms::VecPt3d &a_outPoly, xms::VecPt3d &a_inPolys)
Used in tests to create a polygon with lots of segments and 2 holes.
void gmEnvelopeOfPts(const VecPt3d &a_pts, Pt3d &a_min, Pt3d &a_max)
Calculates the envelope of a vector of points.
boost::timer::cpu_timer m_timer
Timer.
PtInOutOrOn_enum
point in, out, or on
Pt3d gmCreateVector(const Pt3d &a_p1, const Pt3d &a_p2)
creates a vector from a_p1 to a_p2
bool gmInsideOrOnLineWithTol(const Pt3d *p1, const Pt3d *p2, const Pt3d *inpoint, const double x, const double y, const double tol, double *dist)
Returns true if the (x,y) is on the line segment (p1,p2) or on the same side of the line as "inpoint"...
bool gmColinearWithTol(const Pt3d &p1, const Pt3d &p2, const Pt3d &p3, const double tol)
Returns true if (the three vertices are gmColinear. Result should be insensitive to the order of the ...
double gmPtDistanceAlongSegment(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_pt, const double a_tol)
Finds the distance along a segment for the location closest to a_pt.
double gmAngleBetweenEdges(const Pt3d &p1, const Pt3d &p2, const Pt3d &p3)
Returns the ccw angle (0-2pi) between p2-p1 and p2-p3.
int m_status
Status (in, out, on) of at least one pt.
VecPt3d gmArrayToVecPt3d(double *a_array, int a_size)
Useful in testing to create a VecPt3d from a C array of xy pairs.
void DoTest()
Run the test. This is the main function to call.
double gmPolygonArea(const Pt3d *pts, size_t npoints)
Compute 2d planview projection of area of polygon.
void gmCalculateNormalizedPlaneCoefficients(const Pt3d &p1, const Pt3d &p2, const Pt3d &p3, double *a, double *b, double *c, double *d)
Calculates the plane coefficients for a triangle. Given point references calculate coefficents for pl...
bool gmLinesIntersect(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2)
intersects the plan projection of two line segments (bad func name) segment 1 = one1,one2 = one1 + lambda(one2 - one1) segment 2 = two1,two2 = two1 + mu (two2 - two1)
Functions dealing with geometry.
bool GTEQ_TOL(_T A, _U B, _V tol)
void gmComponentMagnitudes(double *a_x, double *a_y, double *a_mag, double *a_dir, bool a_tomagdir)
converts the magnitude and angle to xy components or vice versa
double gmComputeDeviationInDirection(const Pt3d &a_p0, const Pt3d &a_p1, const Pt3d &a_p2)
Computes the deviation in direction from one seg to next seg 1 is from a_p0 to a_p1 seg 2 is from a_p...
double trArea(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_pt3)
Return the signed planar area of the triangle (CCW Positive).
#define XM_ENSURE_TRUE(...)
void gmCross3D(const Pt3d &a_vec1, const Pt3d &a_vec2, Pt3d *a_vec3)
Perform a cross product of Pt3d's.
double gmComputeXyTol(const Pt3d &a_mn, const Pt3d &a_mx)
Given extents (min, max), compute a tolerance for the xy plane to be used with geometric functions...
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
GmPointInPolyUnitTests()
constructor
Pt3d gmComputeCentroid(const VecPt3d &a_points)
Computes the centroid of points (but not of a polygon). Shouldn't pass an empty vector (no checks are...
double gm2DDistanceToLineWithTol(const Pt3d *a_pt1, const Pt3d *a_pt2, double a_x, double a_y, double a_tol)
return the xy distance from (a_x,a_y) to line through (a_pt1, a_pt2)
double gmXyTol(bool a_set, double a_value)
Get or set (set first time) global xy tolerance for float operations.
double gmConvertAngleToBetween0And360(double a_angle, bool a_InDegrees)
given an angle, this function will return the corresponding angle that matches it in the range of 0 d...
bool gmCircumcircleWithTol(const Pt3d *pt1, const Pt3d *pt2, const Pt3d *pt3, double *xc, double *yc, double *r2, double tol)
Computes center & radius squared for circumcircle of triangle made by the three points.
double gmCross2D(const double &dx1, const double &dy1, const double &dx2, const double &dy2)
Returns the cross product of two 2-d vectors.
void test_gmPointInPolygon2D_Speed()
Test lots of points for timing purposes. Only in release, not debug.
#define XM_DISALLOW_COPY_AND_ASSIGN(TypeName)
bool EQ_TOL(const _T &A, const _U &B, const _V &tolerance)
double gmFindClosestPtOnSegment(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_pt, Pt3d &a_newpt, const double a_tol)
Finds the closest point to another point on a segment.
void test_gmComputePolygonCentroid()
bool gmEqualPointsXYZ(double x1, double y1, double z1, double x2, double y2, double z2, double tolerance)
Returns true if the points are equal to within tolerance.
bool LT_TOL(_T A, _U B, _V tolerance)
int m_count
Number of points checked.
std::vector< xms::Pt3d > m_inPoly
Input polygon.
virtual void CheckPoints()
Check a lot of points to see if they are in the polys.
bool gmLinesCross(const Pt3d &a_segment1Point1, const Pt3d &a_segment1Point2, const Pt3d &a_segment2Point1, const Pt3d &a_segment2Point2)
Determine whether 2 line segments cross. The segments may touch at the end points.
Used for speed tests of various point in poly functions / classes.
int gmIntersectTriangleAndLineSegment(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_t0, const Pt3d &a_t1, const Pt3d &a_t2, Pt3d &a_IntersectPt)
Determine if the line (described by a_pt1 and a_pt2) intersects the triangle (a_t0, a_t1, a_t2).
Turn_enum
direction of turn between 3 points
bool gmPointInOrOnBox2d(const Pt3d &a_bMin, const Pt3d &a_bMax, const Pt3d &a_pt)
finds if a point is in or on a box in 2d
void gmAddToExtents(const Pt3d &a_pt, Pt3d &a_min, Pt3d &a_max)
Compares a_pt to a_min and a_max. If a_pt is less than a_min or greater than a_max, a_min and a_max are updated.
bool gmCounterClockwiseTri(const Pt3d &vtx0, const Pt3d &vtx1, const Pt3d &vtx2)
Returns true if the triangle is wrapped counter clockwise.
double gmDot3D(const Pt3d &a_vec1, const Pt3d &a_vec2)
Perform a dot product of Pt3d's.
void test_gmComputeCentroid()
int gmPointInPolygon2D(const VecPt3d &a_verts, const Pt3d &a_pt)
bool gmBoxesOverlap2d(const Pt3d &a_b1Min, const Pt3d &a_b1Max, const Pt3d &a_b2Min, const Pt3d &a_b2Max)
finds if 2 boxes overlap in 2d
void gmExtents2D(const VecPt3d &a_points, Pt2d &a_min, Pt2d &a_max)
Get the 2D extents of a vector of points.
int gmPointInPolygon2D(const T *a_verts, const size_t a_num, const double a_x, const double a_y, const double a_tol)
Determines whether (a_x, a_y) is inside=1, on=0, or outside=-1 the polygon defined by the given verti...
int gmCartToBary(const Pt3d *cart, const Pt3d *orig, double coef[6], int dir, Pt3d *bary)
Compute Barycentric coords for point. Use gmBaryPrepare to get the coefficients and direction...
int gmBaryPrepare(const Pt3d *p1, const Pt3d *p2, const Pt3d *p3, const Pt3d *norm, Pt3d *orig, double coef[6], int *dir, bool flag)
For a tri - compute dir & coefs to compute Barycentric coords.
template int gmPointInPolygon2D< Pt2i >(const Pt2i *a_verts, const size_t a_num, const double a_x, const double a_y, const double a_tol)
std::vector< xms::Pt3d > m_outPoly
Output polygon.
void gmExtents3D(const VecPt3d &a_points, Pt3d &a_min, Pt3d &a_max)
Get the 3D extents of a vector of points.
Pt3d gmComputePolygonCentroid(const VecPt3d &pts)
Computes the plan view centroid of a non-self-intersecting polygon.
GmPointInPolyTester_gmPointInPolygon2D()
Constructor.
bool GT_TOL(_T A, _U B, _V tolerance)
void testDoLineSegmentsCross()
Test determining if two lines intersect.
double gmXyDistanceSquared(const Pt3d &pt1, const Pt3d &pt2)
Calculate XY distance between two 3D points.
std::vector< Pt3d > VecPt3d