23 #include <boost/bind.hpp>
24 #include <boost/archive/text_iarchive.hpp>
25 #include <boost/archive/text_oarchive.hpp>
26 #include <boost/serialization/export.hpp>
27 #include <boost/serialization/vector.hpp>
28 #include <boost/unordered_set.hpp>
59 friend class boost::serialization::access;
66 virtual void SetPoints(BSHP<VecPt3d> a_pts)
override;
71 BSHP<VecInt2d> a_trisAdjToPts)
override;
82 virtual BSHP<VecPt3d>
PointsPtr()
override;
95 int& a_idx2)
const override;
97 virtual int LocalIndex(
int a_tri,
int a_pt)
const override;
98 virtual int GlobalIndex(
int a_triIdx,
int a_localVtxIdx)
const override;
110 virtual void ExportTinFile(std::ostream& a_os)
const override;
113 virtual bool SwapEdge(
int a_triA,
int a_triB,
bool a_checkAngle =
true)
override;
117 virtual void Clear()
override;
120 virtual std::string
ToString()
const override;
121 virtual void FromString(
const std::string&)
override;
122 template <
typename Archive>
123 void serialize(Archive& archive,
const unsigned int version);
279 return (
int)(*m_pts).size();
287 return (
int)(*m_tris).size() / 3;
303 int& a_localPt2)
const
305 a_localPt1 = a_localPt2 = 0;
308 VecInt::const_iterator adj = (*m_trisAdjToPts)[a_pt1].begin();
309 for (; adj != (*m_trisAdjToPts)[a_pt1].end(); ++adj)
312 a_localPt2 = trIncrementIndex(a_localPt1);
313 if ((*
m_tris)[(*adj * 3) + a_localPt2] == a_pt2)
333 int localIdx1, localIdx2;
336 VecInt::const_iterator adj = (*m_trisAdjToPts)[a_pt1].begin();
338 for (; adj != (*m_trisAdjToPts)[a_pt1].end(); ++adj)
341 localIdx2 = trDecrementIndex(localIdx1);
342 if ((*
m_tris)[(*adj * 3) + localIdx2] == a_pt2)
348 return (found ? *adj :
XM_NONE);
361 for (
int i = 0; i < 3; ++i)
363 if ((*
m_tris)[t + i] == a_pt)
378 for (
size_t i = 0; i < (*m_trisAdjToPts)[a_pt1].size(); ++i)
380 int trisIdx = (*m_trisAdjToPts)[a_pt1][i] * 3;
384 for (
int j = 0; j < 3; ++j)
386 if ((*
m_tris)[trisIdx + j] == a_pt2)
420 int a1, a2, a3, b1, b2, b3;
421 int top, btm, lft, rgt;
422 Pt3d toppt, btmpt, lftpt, rgtpt;
425 b2 = trDecrementIndex(b3);
426 b1 = trIncrementIndex(b3);
428 a1 = trIncrementIndex(a3);
429 a2 = trIncrementIndex(a1);
434 toppt = (*m_pts)[top];
435 lftpt = (*m_pts)[lft];
436 rgtpt = (*m_pts)[rgt];
437 btmpt = (*m_pts)[btm];
440 double area1 = trArea(toppt, lftpt, btmpt);
441 double area2 = trArea(btmpt, rgtpt, toppt);
443 if (area1 > 0.0 && area2 > 0.0)
448 double ang1 = gmAngleBetweenEdges(rgtpt, btmpt, toppt);
449 double ang2 = gmAngleBetweenEdges(btmpt, toppt, rgtpt);
450 double ang3 = gmAngleBetweenEdges(toppt, btmpt, lftpt);
451 double ang4 = gmAngleBetweenEdges(lftpt, toppt, btmpt);
452 const static double min_ang = 0.01 * (
XM_PI / 180.0);
453 const static double max_ang = 179.99 * (
XM_PI / 180.0);
454 if (ang1 < min_ang || ang1 > max_ang || ang2 < min_ang || ang2 > max_ang || ang3 < min_ang ||
455 ang3 > max_ang || ang4 < min_ang || ang4 > max_ang)
469 (*m_tris)[(a_triA * 3) + a3] = top;
470 (*m_tris)[(a_triB * 3) + b3] = btm;
473 if (!gmCounterClockwiseTri((*
m_pts)[(*m_tris)[a_triA * 3]],
474 (*m_pts)[(*m_tris)[(a_triA * 3) + 1]],
475 (*
m_pts)[(*m_tris)[(a_triA * 3) + 2]]) ||
476 !gmCounterClockwiseTri((*
m_pts)[(*
m_tris)[a_triB * 3]],
480 std::stringstream msg;
481 msg <<
"Swapping triangles: " << a_triA <<
" and " << a_triB
482 <<
" created invalid triangles (ordered cw instead of ccw).";
520 int tri2id0 = 0, tri2id1 = 0, tri2id2 = 0;
525 tri2id1 = trDecrementIndex(tri2id2);
531 tri2id0 = trIncrementIndex(tri2id2);
536 if (a_propagate || (!a_propagate && adjTri !=
XM_NONE && a_flags[adjTri]))
541 if (a_propagate || (!a_propagate && adjTri !=
XM_NONE && a_flags[adjTri]))
602 if (adjtri == a_adjTri)
605 edge = trIncrementIndex(edge);
632 int t = a_triIdx * 3;
633 int edgePt1 = (*m_tris)[t + a_edgeIdx];
634 int edgePt2 = (*m_tris)[t + trIncrementIndex(a_edgeIdx)];
653 centroid += (*m_pts)[(*m_tris)[t + 1]];
654 centroid += (*m_pts)[(*m_tris)[t + 2]];
655 return (centroid / (
double)3);
668 #if 0 // FirstBoundaryPoint has been commented out because it wasn't used
677 int TrTinImpl::FirstBoundaryPoint ()
const
682 int firstTri, tri, localIndex, prevtri(XM_NONE);
683 for (
int p = 0; p < nPoints; ++p)
685 firstTri = tri = (*m_trisAdjToPts)[p][0];
690 }
while (tri != firstTri && tri != XM_NONE);
691 if (tri == XM_NONE) {
715 firstTri = tri = (*m_trisAdjToPts)[a_point][0];
720 localIndex = trDecrementIndex(
LocalIndex(tri, a_point));
723 }
while (tri != firstTri && tri !=
XM_NONE);
750 firstTri = tri = (*m_trisAdjToPts)[a_point][0];
758 }
while (tri != firstTri && tri !=
XM_NONE);
763 bpoint =
GlobalIndex(prevtri, trIncrementIndex(localIndex));
783 size_t numTri =
m_tris->size() / 3;
785 for (
size_t tri = 0; tri < numTri; ++tri, t += 3)
787 for (
int i = 0; i < 3; ++i)
791 setPoints.insert(tris[t + i]);
792 setPoints.insert(tris[t + trIncrementIndex(i)]);
797 a_boundaryPoints.clear();
798 std::copy(setPoints.begin(), setPoints.end(), std::back_inserter(a_boundaryPoints));
814 boost::unordered_set<int> pointSet(points.begin(), points.end());
818 while (!pointSet.empty())
822 auto it = std::min_element(pointSet.begin(), pointSet.end());
827 a_polys.push_back(
VecInt());
828 a_polys.back().push_back(first);
831 while (next != first)
833 a_polys.back().push_back(next);
834 it = pointSet.find(next);
835 if (it == pointSet.end())
838 "Unable to get boundary polygon from meshed points. Check the input polygon.");
845 a_polys.back().push_back(a_polys.back().front());
856 if (!(*m_pts).empty())
861 for (
size_t i = 0; i < pts.size(); ++i)
863 gmAddToExtents(pts[i], a_mn, a_mx);
880 a_os <<
"VERT " << pts.size() <<
"\n";
881 for (
size_t i = 0; i < pts.size(); ++i)
883 a_os <<
STRstd(pts[i].x) <<
"\t" <<
STRstd(pts[i].y) <<
"\t" <<
STRstd(pts[i].z) <<
"\n";
889 for (
size_t i = 0; i < tris.size(); i += 3)
891 a_os << (tris[i] + 1) <<
"\t" << (tris[i + 1] + 1) <<
"\t" << (tris[i + 2] + 1) <<
"\n";
906 (*m_trisAdjToPts)[a_pt].push_back(a_tri);
916 VecInt::iterator adjTri = (*m_trisAdjToPts)[a_pt].begin();
917 for (; adjTri != (*m_trisAdjToPts)[a_pt].end(); ++adjTri)
919 if (*adjTri == a_tri)
921 (*m_trisAdjToPts)[a_pt].erase(adjTri);
935 return (*
m_tris)[(a_triIdx * 3) + a_localPt];
949 int index = (int)(&a_triPt - &*(*m_tris).begin());
964 int index = (int)(&a_point - &*(*m_pts).begin());
979 int index = (int)(&a_adj - &*(*m_trisAdjToPts).begin());
992 for (SetInt::iterator it = a_trisToDelete.begin(); it != a_trisToDelete.end(); ++it)
1002 (*m_tris).erase(std::remove_if((*m_tris).begin(), (*m_tris).end(),
1008 for (VecInt2d::iterator itPoint = (*m_trisAdjToPts).begin(); itPoint != (*m_trisAdjToPts).end();
1011 for (VecInt::iterator itTri = itPoint->begin(); itTri != itPoint->end();)
1013 if (a_trisToDelete.find(*itTri) != a_trisToDelete.end())
1015 itTri = itPoint->erase(itTri);
1026 VecInt oldToNewIdxs(oldNumTris);
1027 std::iota(oldToNewIdxs.begin(), oldToNewIdxs.end(), 0);
1028 SetInt::iterator it = a_trisToDelete.begin();
1030 for (
int i = 0; i < oldNumTris; ++i)
1032 if (it != a_trisToDelete.end() && i >= *it)
1039 oldToNewIdxs[i] -= offset;
1042 for (VecInt2d::iterator itPoint = (*m_trisAdjToPts).begin(); itPoint != (*m_trisAdjToPts).end();
1045 for (VecInt::iterator itAdj = itPoint->begin(); itAdj != itPoint->end(); ++itAdj)
1047 *itAdj = oldToNewIdxs[*itAdj];
1061 m_toDelete.insert(a_points.begin(), a_points.end());
1065 (*m_pts).erase(std::remove_if((*m_pts).begin(), (*m_pts).end(),
1070 SetInt trianglesToDelete;
1071 if (!(*m_trisAdjToPts).empty() && !(*m_tris).empty())
1073 SetInt::const_iterator it = a_points.begin();
1074 for (; it != a_points.end(); ++it)
1080 if (!(*m_trisAdjToPts).empty())
1085 .erase(std::remove_if((*m_trisAdjToPts).begin(), (*m_trisAdjToPts).end(),
1087 (*m_trisAdjToPts).end());
1092 if (!(*m_trisAdjToPts).empty() && !(*m_tris).empty())
1095 trRenumberOnDelete(a_points, (*
m_tris));
1105 bool modified =
false;
1107 VecInt flags(nTri,
false);
1115 meshaltered =
false;
1116 for (
int tri = 0; tri < nTri; ++tri)
1121 for (
int i = 0; i <= 2; i++)
1125 if (adjtri !=
XM_NONE && flags[adjtri])
1133 id = trIncrementIndex(
id);
1139 }
while (meshaltered);
1168 std::stringstream ss;
1170 boost::archive::text_oarchive oa(ss);
1181 std::stringstream ss(a_text);
1183 boost::archive::text_iarchive ia(ss);
1192 template <
typename Archive>
1196 archive& boost::serialization::base_object<TrTin>(*this);
1216 size_t numTri = tris.size() / 3;
1218 for (
size_t tri = 0; tri < numTri; ++tri)
1220 trisAdjToPts[tris[t++]].push_back((
int)tri);
1221 trisAdjToPts[tris[t++]].push_back((
int)tri);
1222 trisAdjToPts[tris[t++]].push_back((
int)tri);
1249 return BDPC<TrTin>(BSHP<TrTinImpl>(
new TrTinImpl()));
1276 void trRenumberOnDelete(
const SetInt& a_deleting,
VecInt& a_vec)
1278 for (SetInt::reverse_iterator itDeleting = a_deleting.rbegin(); itDeleting != a_deleting.rend();
1281 int pt = *itDeleting;
1282 for (VecInt::iterator itTriPt = a_vec.begin(); itTriPt != a_vec.end(); ++itTriPt)
1308 using namespace xms;
1315 static VecPt3d iArrayToVecPt3d(
double* a_array,
int a_size)
1318 for (
int i = 0; i < a_size; i += 2)
1320 v[i / 2].x = a_array[i];
1321 v[i / 2].y = a_array[i + 1];
1355 tin->Points() = {{5, 0, 0}, {10, 0, 0}, {0, 5, 0}, {5, 5, 0}, {10, 5, 0},
1356 {15, 5, 0}, {0, 10, 0}, {5, 10, 0}, {10, 10, 0}, {5, 15, 0}};
1357 tin->Triangles() = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 3, 6,
1358 3, 7, 6, 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 8, 9};
1359 tin->BuildTrisAdjToPts();
1391 tin->Points() = {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {2.5, 2.5, 0},
1392 {0, 5, 0}, {5, 5, 0}, {0, 10, 0}};
1393 int tris[] = {0, 1, 3, 1, 2, 5, 0, 3, 4, 1, 5, 3, 4, 3, 5, 4, 5, 6};
1394 tin->Triangles().assign(&tris[0], &tris[
XM_COUNTOF(tris)]);
1395 tin->BuildTrisAdjToPts();
1424 const double kYMax = 40;
1425 const double kXMax = 80;
1426 for (
int y = 0; y <= kYMax; y += 10)
1428 for (
int x = 0; x <= kXMax; x += 10)
1430 tin->Points().push_back(
Pt3d(x, y, 0.0));
1467 double meshPtsA[] = {0, -10, 10, -10, 20, -10, 30, -10, 40, -10, 5, -5, 15, -5, 25,
1468 -5, 35, -5, 0, 0, 10, 0, 20, 0, 30, 0, 5, 5, 15, 5,
1469 25, 5, 35, 5, 0, 10, 10, 10, 20, 10, 30, 10, 40, 10};
1471 tin->Points() = iArrayToVecPt3d(meshPtsA,
XM_COUNTOF(meshPtsA));
1503 tin->Points() = {{5, 0, 0}, {10, 0, 0}, {0, 5, 0}, {5, 5, 0}, {10, 5, 0}, {15, 5, 0},
1504 {0, 10, 0}, {5, 10, 0}, {10, 10, 0}, {5, 15, 0}, {10, 15, 0}, {15, 15, 0}};
1505 tin->Triangles() = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 3, 6, 3, 7, 6,
1506 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 8, 9, 8, 10, 9, 8, 11, 10};
1507 tin->BuildTrisAdjToPts();
1538 BSHP<VecPt3d> pts(
new VecPt3d());
1539 BSHP<VecInt> tris(
new VecInt());
1540 BSHP<VecInt2d> trisAdjToPts(
new VecInt2d());
1543 *pts = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 10, 0}, {15, 10, 0}};
1544 *tris = {3, 0, 1, 1, 2, 4, 1, 4, 3};
1545 *trisAdjToPts = {{0}, {0, 1, 2}, {1}, {0, 2}, {1, 2}};
1548 tin->SetGeometry(pts, tris, trisAdjToPts);
1555 rv = tin->TriangleFromEdge(1, 3, tri, idx1, idx2);
1556 TS_ASSERT_EQUALS(rv,
true);
1557 TS_ASSERT_EQUALS(tri, 0);
1558 TS_ASSERT_EQUALS(idx1, 2);
1559 TS_ASSERT_EQUALS(idx2, 0);
1560 rv = tin->TriangleFromEdge(3, 1, tri, idx1, idx2);
1561 TS_ASSERT_EQUALS(rv,
true);
1562 TS_ASSERT_EQUALS(tri, 2);
1563 TS_ASSERT_EQUALS(idx1, 2);
1564 TS_ASSERT_EQUALS(idx2, 0);
1565 rv = tin->TriangleFromEdge(1, 0, tri, idx1, idx2);
1566 TS_ASSERT_EQUALS(rv,
false);
1570 tri = tin->TriangleAdjacentToEdge(1, 3);
1571 TS_ASSERT_EQUALS(tri, 2);
1572 tri = tin->TriangleAdjacentToEdge(3, 1);
1573 TS_ASSERT_EQUALS(tri, 0);
1574 tri = tin->TriangleAdjacentToEdge(1, 0);
1575 TS_ASSERT_EQUALS(tri, 0);
1579 TS_ASSERT_EQUALS(tin->LocalIndex(0, 0), 1);
1580 TS_ASSERT_EQUALS(tin->LocalIndex(0, 1), 2);
1581 TS_ASSERT_EQUALS(tin->LocalIndex(0, 3), 0);
1582 TS_ASSERT_EQUALS(tin->LocalIndex(0, 4),
XM_NONE);
1586 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 0), 3);
1587 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 1), 0);
1588 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 2), 1);
1589 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 0), 1);
1590 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 1), 2);
1591 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 2), 4);
1592 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 0), 1);
1593 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 1), 4);
1594 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 2), 3);
1597 TS_ASSERT_EQUALS(tin->GlobalIndex(3, 2),
XM_NONE);
1598 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 3),
XM_NONE);
1603 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(0, 1),
true);
1604 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(1, 0),
true);
1605 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(0, 2),
false);
1609 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(0, 2), 2);
1610 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(2, 0), 2);
1611 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(1, 2), 2);
1612 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(2, 1), 0);
1613 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(0, 1),
XM_NONE);
1617 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 0),
XM_NONE);
1618 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 1),
XM_NONE);
1619 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 2), 2);
1620 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 0),
XM_NONE);
1621 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 1),
XM_NONE);
1622 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 2), 2);
1623 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 0), 1);
1624 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 1),
XM_NONE);
1625 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 2), 0);
1629 const double kDelta = 1e-5;
1636 TS_ASSERT_DELTA(tin->TriangleArea(0), 50.0, kDelta);
1637 TS_ASSERT_DELTA(tin->TriangleArea(1), 50.0, kDelta);
1638 TS_ASSERT_DELTA(tin->TriangleArea(2), 50.0, kDelta);
1642 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(0), 3);
1643 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(3), 4);
1644 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(4), 2);
1645 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(2), 1);
1646 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(1), 0);
1650 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(0), 1);
1651 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(1), 2);
1652 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(2), 4);
1653 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(4), 3);
1654 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(3), 0);
1662 TS_ASSERT_EQUALS(tin->GetExtents(mn, mx),
true);
1664 TS_ASSERT_DELTA_PT3D(mx,
Pt3d(20, 10, 0), kDelta);
1670 rv = tin->SwapEdge(0, 2);
1671 TS_ASSERT_EQUALS(rv,
true);
1672 TS_ASSERT_EQUALS(tin->Triangles()[0], 3);
1673 TS_ASSERT_EQUALS(tin->Triangles()[1], 0);
1674 TS_ASSERT_EQUALS(tin->Triangles()[2], 4);
1675 TS_ASSERT_EQUALS(tin->Triangles()[3], 1);
1676 TS_ASSERT_EQUALS(tin->Triangles()[4], 2);
1677 TS_ASSERT_EQUALS(tin->Triangles()[5], 4);
1678 TS_ASSERT_EQUALS(tin->Triangles()[6], 1);
1679 TS_ASSERT_EQUALS(tin->Triangles()[7], 4);
1680 TS_ASSERT_EQUALS(tin->Triangles()[8], 0);
1681 const VecInt2d& trisAdjToPtsRef = tin->TrisAdjToPts();
1682 TS_ASSERT_EQUALS((
VecInt{0, 2}), trisAdjToPtsRef[0]);
1683 TS_ASSERT_EQUALS((
VecInt{1, 2}), trisAdjToPtsRef[1]);
1684 TS_ASSERT_EQUALS((
VecInt{1}), trisAdjToPtsRef[2]);
1685 TS_ASSERT_EQUALS((
VecInt{0}), trisAdjToPtsRef[3]);
1686 TS_ASSERT_EQUALS((
VecInt{1, 2, 0}), trisAdjToPtsRef[4]);
1695 tin->TrisAdjToPts().clear();
1696 tin->BuildTrisAdjToPts();
1697 TS_ASSERT_EQUALS(*trisAdjToPts, tin->TrisAdjToPts());
1702 TS_ASSERT_EQUALS(tin->Points().empty(),
true);
1703 TS_ASSERT_EQUALS(tin->Triangles().empty(),
true);
1704 TS_ASSERT_EQUALS(tin->TrisAdjToPts().empty(),
true);
1755 BSHP<VecPt3d> pts(
new VecPt3d());
1756 BSHP<VecInt> tris(
new VecInt());
1757 BSHP<VecInt2d> trisAdjToPts(
new VecInt2d());
1760 *pts = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {0, 10, 0}, {10, 10, 0},
1761 {20, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}};
1762 *tris = {0, 1, 3, 1, 6, 3, 1, 4, 6, 4, 7, 6, 1, 2, 4, 2, 7, 4, 2, 5, 7, 5, 8, 7};
1763 *trisAdjToPts = {{0}, {0, 1, 2, 4}, {4, 5, 6}, {0, 1}, {2, 4, 5, 3},
1764 {6, 7}, {1, 2, 3}, {3, 5, 6, 7}, {7}};
1767 tin->SetGeometry(pts, tris, trisAdjToPts);
1771 tin->GetBoundaryPoints(boundaryPoints);
1772 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 5, 6, 7, 8}), boundaryPoints);
1775 TS_ASSERT(tin->OptimizeTriangulation());
1776 VecInt trisAfter = {0, 1, 3, 1, 6, 3, 1, 4, 6, 4, 7, 6, 1, 2, 4, 2, 7, 4, 2, 5, 7, 5, 8, 7};
1780 tin->GetBoundaryPoints(boundaryPoints);
1781 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 5, 6, 7, 8}), boundaryPoints);
1809 VecInt& tris = tin->Triangles();
1810 VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
1813 tin->Points() = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 10, 0},
1814 {15, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}};
1821 int trisB[] = {0, 1, 3, 5, 3, 6, 3, 5, 0, 1, 4, 3, 4, 2, 7, 2, 4, 1, 7, 6, 4, 4, 6, 3};
1822 VecInt trisBefore(&trisB[0], &trisB[24]);
1823 TS_ASSERT_EQUALS(trisBefore, tris);
1825 VecInt2d trisAdjToPtsBefore = {{0, 2}, {0, 3, 5}, {4, 5}, {0, 1, 2, 3, 7},
1826 {3, 4, 5, 6, 7}, {1, 2}, {1, 6, 7}, {4, 6}};
1828 TS_ASSERT_EQUALS(trisAdjToPtsBefore, trisAdjToPts);
1831 bool rv = tin->SwapEdge(3, 7);
1832 TS_ASSERT_EQUALS(rv,
true);
1835 int trisA[] = {0, 1, 3, 5, 3, 6, 3, 5, 0, 1, 6, 3, 4, 2, 7, 2, 4, 1, 7, 6, 4, 4, 6, 1};
1836 VecInt trisAfter(&trisA[0], &trisA[24]);
1837 TS_ASSERT_EQUALS(trisAfter, tris);
1839 VecInt2d trisAdjToPtsAfter = {{0, 2}, {0, 3, 5, 7}, {4, 5}, {0, 1, 2, 3},
1840 {4, 5, 6, 7}, {1, 2}, {1, 6, 7, 3}, {4, 6}};
1841 TS_ASSERT_EQUALS(trisAdjToPtsAfter, trisAdjToPts);
1845 tin->GetBoundaryPoints(boundaryPoints);
1846 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 5, 6, 7}), boundaryPoints);
1849 #if 0 // FirstBoundaryPoint has been commented out because it wasn't used
1853 void TrTinTests::testFirstBoundaryPoint ()
1860 TS_ASSERT_EQUALS(tin->FirstBoundaryPoint(), 0);
1883 tin->Points() = {{5,10,0},{15,10,0},{0,0,0},{10,0,0},
1884 {20,0,0},{0,20,0},{10,20,0},{20,20,0}};
1886 &tin->TrisAdjToPts());
1888 TS_ASSERT_EQUALS(tin->FirstBoundaryPoint(), 2);
1917 SetInt toDelete = {20, 24};
1918 tin->DeletePoints(toDelete);
1924 tin->GetBoundaryPoints(pts);
1925 int ptsA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20,
1926 22, 23, 24, 25, 26, 27, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42};
1928 TS_ASSERT_EQUALS(expectedPts, pts);
1932 tin->GetBoundaryPolys(boundaries);
1935 {0, 9, 18, 25, 34, 35, 36, 37, 38, 39, 40, 41, 42, 33, 24, 17, 8, 7, 6, 5, 4, 3, 2, 1, 0},
1936 {10, 11, 20, 27, 26, 19, 10},
1937 {15, 16, 23, 31, 22, 15}};
1946 TS_ASSERT_EQUALS(tin->NumTriangles(), 64);
1947 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
1949 const VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
1952 TS_ASSERT_EQUALS((
VecInt{7, 19, 20, 21, 23, 29}), trisAdjToPts[20]);
1953 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 7, 12, 29}), trisAdjToPts[10]);
1954 TS_ASSERT_EQUALS((
VecInt{7, 8, 10, 12, 21}), trisAdjToPts[11]);
1955 TS_ASSERT_EQUALS((
VecInt{10, 13, 20, 21, 22, 27, 30}), trisAdjToPts[21]);
1956 TS_ASSERT_EQUALS((
VecInt{18, 20, 22, 23, 25, 28}), trisAdjToPts[29]);
1957 TS_ASSERT_EQUALS((
VecInt{14, 16, 17, 18, 19, 23}), trisAdjToPts[28]);
1958 TS_ASSERT_EQUALS((
VecInt{3, 14, 15, 19, 29}), trisAdjToPts[19]);
1961 SetInt toDelete = {7, 19, 20, 21, 23, 29};
1962 tin->DeleteTriangles(toDelete);
1964 TS_ASSERT_EQUALS(tin->NumTriangles(), 58);
1965 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
1969 for (
size_t i = 0; i < trisAdjToPts.size(); ++i)
1971 for (
size_t j = 0; j < trisAdjToPts[i].size(); ++j)
1973 if (trisAdjToPts[i][j] > mx)
1974 mx = trisAdjToPts[i][j];
1977 TS_ASSERT_EQUALS(mx, 57);
1994 TS_ASSERT(tin->TrisAdjToPts()[20].empty());
1995 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 11}), trisAdjToPts[10]);
1996 TS_ASSERT_EQUALS((
VecInt{7, 9, 11}), trisAdjToPts[11]);
1997 TS_ASSERT_EQUALS((
VecInt{9, 12, 18, 22, 24}), trisAdjToPts[21]);
1998 TS_ASSERT_EQUALS((
VecInt{17, 18, 20, 23}), trisAdjToPts[29]);
1999 TS_ASSERT_EQUALS((
VecInt{13, 15, 16, 17}), trisAdjToPts[28]);
2000 TS_ASSERT_EQUALS((
VecInt{3, 13, 14}), trisAdjToPts[19]);
2008 TS_ASSERT_EQUALS(tin->NumTriangles(), 64);
2009 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
2011 SetInt toDelete = {20, 24};
2012 tin->DeletePoints(toDelete);
2014 TS_ASSERT_EQUALS(tin->NumTriangles(), 53);
2015 TS_ASSERT_EQUALS(tin->NumPoints(), 43);
2033 const VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
2035 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 11}), trisAdjToPts[10]);
2036 TS_ASSERT_EQUALS((
VecInt{7, 9, 11}), trisAdjToPts[11]);
2037 TS_ASSERT_EQUALS((
VecInt{9, 12, 18, 22, 24}), trisAdjToPts[20]);
2038 TS_ASSERT_EQUALS((
VecInt{17, 18, 20, 23}), trisAdjToPts[27]);
2039 TS_ASSERT_EQUALS((
VecInt{13, 15, 16, 17}), trisAdjToPts[26]);
2040 TS_ASSERT_EQUALS((
VecInt{3, 13, 14}), trisAdjToPts[19]);
2042 TS_ASSERT_EQUALS((
VecInt{28, 30, 32, 33}), trisAdjToPts[15]);
2043 TS_ASSERT_EQUALS((
VecInt{32, 35, 36, 46}), trisAdjToPts[16]);
2044 TS_ASSERT_EQUALS((
VecInt{45, 46, 48}), trisAdjToPts[23]);
2045 TS_ASSERT_EQUALS((
VecInt{39, 40, 43, 48}), trisAdjToPts[31]);
2046 TS_ASSERT_EQUALS((
VecInt{26, 28, 29, 39}), trisAdjToPts[22]);
bool CheckAndSwap(int a_triA, int a_triB, bool a_propagate, const VecInt &a_flags)
Swap edges if triangles combine to form convex quad. Compare to trCheckAndSwap.
virtual int AdjacentTriangle(int a_triIdx, int a_edgeIdx) const override
Returns the triangle adjacent to a_triIdx across a_edgeIdx (0-2). Compare to trAdjacentTriangle. Example: a_edgeIdx 2 returns triangle adjacent to edge c.
void testBoundaries()
Tests TrTin::GetBoundaryPoints and TrTin::GetBoundaryPolys.
virtual bool TriangleFromEdge(int a_pt1, int a_pt2, int &a_tri, int &a_idx1, int &a_idx2) const override
Finds the triangle with the edge defined by a_pt1 and a_pt2 and the local index of those points...
virtual ~TrTinImpl()
destructor
bool PointIndexFound(const Pt3d &a_point) const
Predicate used in remove_if to get the index of the current item in the vector.
BSHP< TrTin > trBuildTestTin8()
Builds a simple TIN with a hole in the middle and a concavity.
virtual ~TrTin()
destructor
static const double XM_DBL_LOWEST
virtual int NextBoundaryPoint(int a_point) const override
Returns the next point CW from point on the boundary. CCW if in an inside hole. Compare to trNextBoun...
BOOST_CLASS_EXPORT(xms::TrTinImpl)
Cause boost.
#define XM_ENSURE_TRUE_VOID(...)
BSHP< VecPt3d > m_pts
tin points
Functions dealing with triangles.
virtual int LocalIndex(int a_tri, int a_pt) const override
Returns index (0-2) of point within triangle given global index. Compare to trIndex.
void InsertAdjacentTriangle(int a_pt, int a_tri)
Adds a_tri as an adjacent triangle to a_pt and updates m_trisAdjToPts.
bool TriIndexFound(const int &a_triPt) const
Predicate used in remove_if to get the index of the current item in the vector.
virtual std::string ToString() const override
Use boost archive to get the TrTin as text.
virtual void SetTriangles(BSHP< VecInt > a_tris) override
Sets the tin triangles.
virtual bool GetExtents(Pt3d &a_mn, Pt3d &a_mx) const override
Computes the extents (min, max) of the tin.
BSHP< TrTin > trBuildTestTin()
Builds a simple TIN with a hole in the middle.
void stShrinkCapacity(std::vector< T > &v)
#define XM_ENSURE_TRUE_NO_ASSERT(...)
virtual int GlobalIndex(int a_triIdx, int a_localVtxIdx) const override
Returns index into m_pts of a_localPt which is 0-2.
std::vector< int > VecInt
virtual void SetTrianglesAdjacentToPoints(BSHP< VecInt2d > a_trisAdjToPts) override
Sets the adjacency info of triangles adjacent to points.
BSHP< VecInt > m_tris
triangles, 0-based indices to m_pts, grouped by 3s
virtual void Clear() override
Delete the memory.
virtual void BuildTrisAdjToPts() override
Build array of triangles adjacent to points.
BSHP< TrTin > trBuildTestTin6()
Builds a simple TIN for testing.
virtual void GetBoundaryPolys(VecInt2d &a_polys) const override
Gets exterior boundary and all interior voids as polygons of 0-based point indices. First point is not repeated as the last point.
Functions dealing with geometry.
static BSHP< TrTin > New()
Create a TrTinImpl object.
virtual BSHP< VecPt3d > PointsPtr() override
Return the pointer to tin points.
bool Triangulate()
Triangulate the points into a tin.
Class to encapsulate a tin made simply of arrays of points, triangles and adjacency information...
bool AdjacentIndexFound(const VecInt &a_point) const
Predicate used in remove_if to get the index of the current item in the vector.
void DeleteAdjacentTriangle(int a_pt, int a_tri)
Removes a_tri from a_pt's adjacent triangles. Compare to vrDeleteAdjacentTrianglePtr.
virtual VecInt2d & TrisAdjToPts() override
Returns triangles adjacent to points (0-based).
#define XM_ENSURE_TRUE(...)
virtual int NumPoints() const override
Return the number of points.
virtual void DeleteTriangles(const SetInt &a_trisToDelete) override
Deletes the triangles specified in a_trisToDelete and updates and renumbers triangle adjacency info...
virtual double TriangleArea(int a_tri) const override
Calculate and return the area of a triangle.
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
std::vector< Pt3d > VecPt3d
virtual void FromString(const std::string &) override
Use boost archive to turn the text into a TrTin.
virtual void GetBoundaryPoints(VecInt &a_boundaryPoints) const override
Gives the 0-based indices of all points on any boundary, in no particular order.
std::string STRstd(double a_value, int a_n, int width, int flags)
virtual void DeletePoints(const SetInt &a_points) override
Deletes the points and any attached triangles, updates adjacency and renumbers things.
virtual bool SwapEdge(int a_triA, int a_triB, bool a_checkAngle=true) override
Swap edges if triangles combine to form convex quad. Compare to trSwapEdge.
virtual int PreviousBoundaryPoint(int a_point) const override
Returns the next point CCW from point on the boundary. CW if in an inside hole. Compare to trPrevious...
boost::unordered_set< int > m_toDelete
Used only when deleting stuff.
void BuildTrisAdjToPtsConst() const
A const function used only internally and needed to modify m_trisAdjToPts which is mutable...
virtual VecInt & Triangles() override
Return 0-based indices of triangle points (grouped by 3s).
virtual VecPt3d & Points() override
Return the tin points.
#define XM_COUNTOF(array)
virtual Pt3d TriangleCentroid(int a_tri) const override
Calculate and return the centroid of a triangle.
BSHP< TrTin > trBuildTestTin7()
Builds a simple TIN for testing.
void testDeletePoints()
Tests TrTin::DeletePoints.
virtual void SetPoints(BSHP< VecPt3d > a_pts) override
Sets the tin points.
void serialize(Archive &archive, const unsigned int version)
Boost serialize function.
virtual int CommonEdgeIndex(int a_tri, int a_adjTri) const override
Return index of common edge between triangle and neighbor. Edge index is 0-2 based on a_tri...
bool PointIsInCircumcircle(int a_tri1, int a_tri2, int id)
Returns true if a_localPt of a_tri2 is inside a_tri1's circumcircle.
virtual bool VerticesAreAdjacent(int a_pt1, int a_pt2) const override
Return true if vertices form the edge of a triangle. Compare to vrVerticesAreAdjacent.
BSHP< VecInt2d > m_trisAdjToPts
triangles adjacent to points. 1st dim = size of m_pts
std::vector< VecInt > VecInt2d
virtual bool OptimizeTriangulation() override
Swaps triangle edges until they are a Delauney triangulation.
virtual BSHP< VecInt > TrianglesPtr() override
Return the pointer to tin triangles.
BSHP< TrTin > trBuildTestTin2()
Builds a simple TIN for testing.
void test1()
Tests a bunch of the TrTin methods.
virtual void SetGeometry(BSHP< VecPt3d > a_pts, BSHP< VecInt > a_tris, BSHP< VecInt2d > a_trisAdjToPts) override
Set all the tin geometry at once (points, triangles, adjacency).
virtual void ExportTinFile(std::ostream &a_os) const override
Export in the .tin file format. Useful for debugging.
virtual int TriangleAdjacentToEdge(int a_pt1, int a_pt2) const override
Returns the triangle adjacent to the edge defined by a_pt1 and a_pt2. Compare to trTriangleAdjacentTo...
void testOptimizeTriangulation()
virtual int NumTriangles() const override
Return the number of triangles.
void testDeleteTriangles()
Tests TrTin::DeleteTriangles.
Class to triangulate simple points.
static const double XM_DBL_HIGHEST