22 #include <boost/bind.hpp> 23 #include <boost/archive/text_iarchive.hpp> 24 #include <boost/archive/text_oarchive.hpp> 25 #include <boost/serialization/export.hpp> 26 #include <boost/serialization/vector.hpp> 27 #include <boost/unordered_set.hpp> 58 friend class boost::serialization::access;
65 virtual void SetPoints(BSHP<VecPt3d> a_pts)
override;
70 BSHP<VecInt2d> a_trisAdjToPts)
override;
81 virtual BSHP<VecPt3d>
PointsPtr()
override;
94 int& a_idx2)
const override;
96 virtual int LocalIndex(
int a_tri,
int a_pt)
const override;
97 virtual int GlobalIndex(
int a_triIdx,
int a_localVtxIdx)
const override;
109 virtual void ExportTinFile(std::ostream& a_os)
const override;
112 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);
134 void CheckTriangle(
const int a_tri,
const int a_index,
const double a_ratio,
282 return (
int)(*m_pts).size();
290 return (
int)(*m_tris).size() / 3;
306 int& a_localPt2)
const 308 a_localPt1 = a_localPt2 = 0;
311 VecInt::const_iterator adj = (*m_trisAdjToPts)[a_pt1].begin();
312 for (; adj != (*m_trisAdjToPts)[a_pt1].end(); ++adj)
316 if ((*
m_tris)[(*adj * 3) + a_localPt2] == a_pt2)
336 int localIdx1, localIdx2;
339 VecInt::const_iterator adj = (*m_trisAdjToPts)[a_pt1].begin();
341 for (; adj != (*m_trisAdjToPts)[a_pt1].end(); ++adj)
345 if ((*
m_tris)[(*adj * 3) + localIdx2] == a_pt2)
351 return (found ? *adj :
XM_NONE);
364 for (
int i = 0; i < 3; ++i)
366 if ((*
m_tris)[t + i] == a_pt)
381 for (
size_t i = 0; i < (*m_trisAdjToPts)[a_pt1].size(); ++i)
383 int trisIdx = (*m_trisAdjToPts)[a_pt1][i] * 3;
387 for (
int j = 0; j < 3; ++j)
389 if ((*
m_tris)[trisIdx + j] == a_pt2)
423 int a1, a2, a3, b1, b2, b3;
424 int top, btm, lft, rgt;
425 Pt3d toppt, btmpt, lftpt, rgtpt;
437 toppt = (*m_pts)[top];
438 lftpt = (*m_pts)[lft];
439 rgtpt = (*m_pts)[rgt];
440 btmpt = (*m_pts)[btm];
443 double area1 =
trArea(toppt, lftpt, btmpt);
444 double area2 =
trArea(btmpt, rgtpt, toppt);
446 if (area1 > 0.0 && area2 > 0.0)
455 const static double min_ang = 0.01 * (
XM_PI / 180.0);
456 const static double max_ang = 179.99 * (
XM_PI / 180.0);
457 if (ang1 < min_ang || ang1 > max_ang || ang2 < min_ang || ang2 > max_ang || ang3 < min_ang ||
458 ang3 > max_ang || ang4 < min_ang || ang4 > max_ang)
472 (*m_tris)[(a_triA * 3) + a3] = top;
473 (*m_tris)[(a_triB * 3) + b3] = btm;
477 (*m_pts)[(*m_tris)[(a_triA * 3) + 1]],
478 (*
m_pts)[(*m_tris)[(a_triA * 3) + 2]]) ||
483 std::stringstream msg;
484 msg <<
"Swapping triangles: " << a_triA <<
" and " << a_triB
485 <<
" created invalid triangles (ordered cw instead of ccw).";
523 int tri2id0 = 0, tri2id1 = 0, tri2id2 = 0;
539 if (a_propagate || (!a_propagate && adjTri !=
XM_NONE && a_flags[adjTri]))
544 if (a_propagate || (!a_propagate && adjTri !=
XM_NONE && a_flags[adjTri]))
605 if (adjtri == a_adjTri)
635 int t = a_triIdx * 3;
636 int edgePt1 = (*m_tris)[t + a_edgeIdx];
656 centroid += (*m_pts)[(*m_tris)[t + 1]];
657 centroid += (*m_pts)[(*m_tris)[t + 2]];
658 return (centroid / (
double)3);
671 #if 0 // FirstBoundaryPoint has been commented out because it wasn't used 680 int TrTinImpl::FirstBoundaryPoint ()
const 685 int firstTri, tri, localIndex, prevtri(XM_NONE);
686 for (
int p = 0; p < nPoints; ++p)
688 firstTri = tri = (*m_trisAdjToPts)[p][0];
693 }
while (tri != firstTri && tri != XM_NONE);
694 if (tri == XM_NONE) {
718 firstTri = tri = (*m_trisAdjToPts)[a_point][0];
726 }
while (tri != firstTri && tri !=
XM_NONE);
753 firstTri = tri = (*m_trisAdjToPts)[a_point][0];
761 }
while (tri != firstTri && tri !=
XM_NONE);
786 size_t numTri =
m_tris->size() / 3;
788 for (
size_t tri = 0; tri < numTri; ++tri, t += 3)
790 for (
int i = 0; i < 3; ++i)
794 setPoints.insert(tris[t + i]);
800 a_boundaryPoints.clear();
801 std::copy(setPoints.begin(), setPoints.end(), std::back_inserter(a_boundaryPoints));
817 boost::unordered_set<int> pointSet(points.begin(), points.end());
821 while (!pointSet.empty())
825 auto it = std::min_element(pointSet.begin(), pointSet.end());
830 a_polys.push_back(
VecInt());
831 a_polys.back().push_back(first);
834 while (next != first)
836 a_polys.back().push_back(next);
837 it = pointSet.find(next);
838 if (it == pointSet.end())
841 "Unable to get boundary polygon from meshed points. Check the input polygon.");
848 a_polys.back().push_back(a_polys.back().front());
859 if (!(*m_pts).empty())
862 a_mn = XM_DBL_HIGHEST;
863 a_mx = XM_DBL_LOWEST;
864 for (
size_t i = 0; i < pts.size(); ++i)
883 a_os <<
"VERT " << pts.size() <<
"\n";
884 for (
size_t i = 0; i < pts.size(); ++i)
886 a_os <<
STRstd(pts[i].x) <<
"\t" <<
STRstd(pts[i].y) <<
"\t" <<
STRstd(pts[i].z) <<
"\n";
892 for (
size_t i = 0; i < tris.size(); i += 3)
894 a_os << (tris[i] + 1) <<
"\t" << (tris[i + 1] + 1) <<
"\t" << (tris[i + 2] + 1) <<
"\n";
909 (*m_trisAdjToPts)[a_pt].push_back(a_tri);
919 VecInt::iterator adjTri = (*m_trisAdjToPts)[a_pt].begin();
920 for (; adjTri != (*m_trisAdjToPts)[a_pt].end(); ++adjTri)
922 if (*adjTri == a_tri)
924 (*m_trisAdjToPts)[a_pt].erase(adjTri);
938 return (*
m_tris)[(a_triIdx * 3) + a_localPt];
952 int index = (int)(&a_triPt - &*(*m_tris).begin());
967 int index = (int)(&a_point - &*(*m_pts).begin());
982 int index = (int)(&a_adj - &*(*m_trisAdjToPts).begin());
995 for (SetInt::iterator it = a_trisToDelete.begin(); it != a_trisToDelete.end(); ++it)
1005 (*m_tris).erase(std::remove_if((*m_tris).begin(), (*m_tris).end(),
1011 for (VecInt2d::iterator itPoint = (*m_trisAdjToPts).begin(); itPoint != (*m_trisAdjToPts).end();
1014 for (VecInt::iterator itTri = itPoint->begin(); itTri != itPoint->end();)
1016 if (a_trisToDelete.find(*itTri) != a_trisToDelete.end())
1018 itTri = itPoint->erase(itTri);
1029 VecInt oldToNewIdxs(oldNumTris);
1030 std::iota(oldToNewIdxs.begin(), oldToNewIdxs.end(), 0);
1031 SetInt::iterator it = a_trisToDelete.begin();
1033 for (
int i = 0; i < oldNumTris; ++i)
1035 if (it != a_trisToDelete.end() && i >= *it)
1042 oldToNewIdxs[i] -= offset;
1045 for (VecInt2d::iterator itPoint = (*m_trisAdjToPts).begin(); itPoint != (*m_trisAdjToPts).end();
1048 for (VecInt::iterator itAdj = itPoint->begin(); itAdj != itPoint->end(); ++itAdj)
1050 *itAdj = oldToNewIdxs[*itAdj];
1064 m_toDelete.insert(a_points.begin(), a_points.end());
1068 (*m_pts).erase(std::remove_if((*m_pts).begin(), (*m_pts).end(),
1073 SetInt trianglesToDelete;
1074 if (!(*m_trisAdjToPts).empty() && !(*m_tris).empty())
1076 SetInt::const_iterator it = a_points.begin();
1077 for (; it != a_points.end(); ++it)
1083 if (!(*m_trisAdjToPts).empty())
1088 .erase(std::remove_if((*m_trisAdjToPts).begin(), (*m_trisAdjToPts).end(),
1090 (*m_trisAdjToPts).end());
1095 if (!(*m_trisAdjToPts).empty() && !(*m_tris).empty())
1108 bool modified =
false;
1110 VecInt flags(nTri,
false);
1118 meshaltered =
false;
1119 for (
int tri = 0; tri < nTri; ++tri)
1124 for (
int i = 0; i <= 2; i++)
1128 if (adjtri !=
XM_NONE && flags[adjtri])
1142 }
while (meshaltered);
1182 const double a_ratio,
VecInt &a_flags,
SetInt &a_trisToDelete)
const 1186 a_flags[a_tri] |= a_index;
1196 double lengthRatio = l12 / (l23 + l31);
1197 if (lengthRatio >= a_ratio)
1199 a_trisToDelete.insert(a_tri);
1204 a_flags, a_trisToDelete);
1208 a_flags, a_trisToDelete);
1225 for (
int tri = 0; tri < nTri; ++tri)
1268 std::stringstream ss;
1270 boost::archive::text_oarchive oa(ss);
1281 std::stringstream ss(a_text);
1283 boost::archive::text_iarchive ia(ss);
1292 template <
typename Archive>
1296 archive& boost::serialization::base_object<TrTin>(*this);
1316 size_t numTri = tris.size() / 3;
1318 for (
size_t tri = 0; tri < numTri; ++tri)
1320 trisAdjToPts[tris[t++]].push_back((
int)tri);
1321 trisAdjToPts[tris[t++]].push_back((
int)tri);
1322 trisAdjToPts[tris[t++]].push_back((
int)tri);
1349 return BDPC<TrTin>(BSHP<TrTinImpl>(
new TrTinImpl()));
1378 for (SetInt::reverse_iterator itDeleting = a_deleting.rbegin(); itDeleting != a_deleting.rend();
1381 int pt = *itDeleting;
1382 for (VecInt::iterator itTriPt = a_vec.begin(); itTriPt != a_vec.end(); ++itTriPt)
1408 using namespace xms;
1415 static VecPt3d iArrayToVecPt3d(
double* a_array,
int a_size)
1418 for (
int i = 0; i < a_size; i += 2)
1420 v[i / 2].x = a_array[i];
1421 v[i / 2].y = a_array[i + 1];
1455 tin->Points() = {{5, 0, 0}, {10, 0, 0}, {0, 5, 0}, {5, 5, 0}, {10, 5, 0},
1456 {15, 5, 0}, {0, 10, 0}, {5, 10, 0}, {10, 10, 0}, {5, 15, 0}};
1457 tin->Triangles() = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 3, 6,
1458 3, 7, 6, 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 8, 9};
1459 tin->BuildTrisAdjToPts();
1491 tin->Points() = {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {2.5, 2.5, 0},
1492 {0, 5, 0}, {5, 5, 0}, {0, 10, 0}};
1493 int tris[] = {0, 1, 3, 1, 2, 5, 0, 3, 4, 1, 5, 3, 4, 3, 5, 4, 5, 6};
1494 tin->Triangles().assign(&tris[0], &tris[
XM_COUNTOF(tris)]);
1495 tin->BuildTrisAdjToPts();
1524 const double kYMax = 40;
1525 const double kXMax = 80;
1526 for (
int y = 0; y <= kYMax; y += 10)
1528 for (
int x = 0; x <= kXMax; x += 10)
1530 tin->Points().push_back(
Pt3d(x, y, 0.0));
1567 double meshPtsA[] = {0, -10, 10, -10, 20, -10, 30, -10, 40, -10, 5, -5, 15, -5, 25,
1568 -5, 35, -5, 0, 0, 10, 0, 20, 0, 30, 0, 5, 5, 15, 5,
1569 25, 5, 35, 5, 0, 10, 10, 10, 20, 10, 30, 10, 40, 10};
1571 tin->Points() = iArrayToVecPt3d(meshPtsA,
XM_COUNTOF(meshPtsA));
1603 tin->Points() = {{5, 0, 0}, {10, 0, 0}, {0, 5, 0}, {5, 5, 0}, {10, 5, 0}, {15, 5, 0},
1604 {0, 10, 0}, {5, 10, 0}, {10, 10, 0}, {5, 15, 0}, {10, 15, 0}, {15, 15, 0}};
1605 tin->Triangles() = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 3, 6, 3, 7, 6,
1606 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 8, 9, 8, 10, 9, 8, 11, 10};
1607 tin->BuildTrisAdjToPts();
1639 tin->Points() = {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {2.5, 2.5, 0},
1640 {0, 5, 0}, {5, 5, 0}, {6, 5, 0}, {0, 10, 0}};
1641 int tris[] = {0, 1, 3, 1, 2, 5, 0, 3, 4, 1, 5, 3, 4, 3, 5, 5, 2, 6, 4, 5, 7, 5, 6, 7};
1642 tin->Triangles().assign(&tris[0], &tris[
XM_COUNTOF(tris)]);
1643 tin->BuildTrisAdjToPts();
1674 BSHP<VecPt3d> pts(
new VecPt3d());
1675 BSHP<VecInt> tris(
new VecInt());
1676 BSHP<VecInt2d> trisAdjToPts(
new VecInt2d());
1679 *pts = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 10, 0}, {15, 10, 0}};
1680 *tris = {3, 0, 1, 1, 2, 4, 1, 4, 3};
1681 *trisAdjToPts = {{0}, {0, 1, 2}, {1}, {0, 2}, {1, 2}};
1684 tin->SetGeometry(pts, tris, trisAdjToPts);
1691 rv = tin->TriangleFromEdge(1, 3, tri, idx1, idx2);
1692 TS_ASSERT_EQUALS(rv,
true);
1693 TS_ASSERT_EQUALS(tri, 0);
1694 TS_ASSERT_EQUALS(idx1, 2);
1695 TS_ASSERT_EQUALS(idx2, 0);
1696 rv = tin->TriangleFromEdge(3, 1, tri, idx1, idx2);
1697 TS_ASSERT_EQUALS(rv,
true);
1698 TS_ASSERT_EQUALS(tri, 2);
1699 TS_ASSERT_EQUALS(idx1, 2);
1700 TS_ASSERT_EQUALS(idx2, 0);
1701 rv = tin->TriangleFromEdge(1, 0, tri, idx1, idx2);
1702 TS_ASSERT_EQUALS(rv,
false);
1706 tri = tin->TriangleAdjacentToEdge(1, 3);
1707 TS_ASSERT_EQUALS(tri, 2);
1708 tri = tin->TriangleAdjacentToEdge(3, 1);
1709 TS_ASSERT_EQUALS(tri, 0);
1710 tri = tin->TriangleAdjacentToEdge(1, 0);
1711 TS_ASSERT_EQUALS(tri, 0);
1715 TS_ASSERT_EQUALS(tin->LocalIndex(0, 0), 1);
1716 TS_ASSERT_EQUALS(tin->LocalIndex(0, 1), 2);
1717 TS_ASSERT_EQUALS(tin->LocalIndex(0, 3), 0);
1718 TS_ASSERT_EQUALS(tin->LocalIndex(0, 4),
XM_NONE);
1722 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 0), 3);
1723 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 1), 0);
1724 TS_ASSERT_EQUALS(tin->GlobalIndex(0, 2), 1);
1725 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 0), 1);
1726 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 1), 2);
1727 TS_ASSERT_EQUALS(tin->GlobalIndex(1, 2), 4);
1728 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 0), 1);
1729 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 1), 4);
1730 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 2), 3);
1733 TS_ASSERT_EQUALS(tin->GlobalIndex(3, 2),
XM_NONE);
1734 TS_ASSERT_EQUALS(tin->GlobalIndex(2, 3),
XM_NONE);
1739 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(0, 1),
true);
1740 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(1, 0),
true);
1741 TS_ASSERT_EQUALS(tin->VerticesAreAdjacent(0, 2),
false);
1745 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(0, 2), 2);
1746 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(2, 0), 2);
1747 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(1, 2), 2);
1748 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(2, 1), 0);
1749 TS_ASSERT_EQUALS(tin->CommonEdgeIndex(0, 1),
XM_NONE);
1753 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 0),
XM_NONE);
1754 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 1),
XM_NONE);
1755 TS_ASSERT_EQUALS(tin->AdjacentTriangle(0, 2), 2);
1756 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 0),
XM_NONE);
1757 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 1),
XM_NONE);
1758 TS_ASSERT_EQUALS(tin->AdjacentTriangle(1, 2), 2);
1759 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 0), 1);
1760 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 1),
XM_NONE);
1761 TS_ASSERT_EQUALS(tin->AdjacentTriangle(2, 2), 0);
1765 const double kDelta = 1e-5;
1772 TS_ASSERT_DELTA(tin->TriangleArea(0), 50.0, kDelta);
1773 TS_ASSERT_DELTA(tin->TriangleArea(1), 50.0, kDelta);
1774 TS_ASSERT_DELTA(tin->TriangleArea(2), 50.0, kDelta);
1778 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(0), 3);
1779 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(3), 4);
1780 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(4), 2);
1781 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(2), 1);
1782 TS_ASSERT_EQUALS(tin->NextBoundaryPoint(1), 0);
1786 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(0), 1);
1787 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(1), 2);
1788 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(2), 4);
1789 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(4), 3);
1790 TS_ASSERT_EQUALS(tin->PreviousBoundaryPoint(3), 0);
1798 TS_ASSERT_EQUALS(tin->GetExtents(mn, mx),
true);
1806 rv = tin->SwapEdge(0, 2);
1807 TS_ASSERT_EQUALS(rv,
true);
1808 TS_ASSERT_EQUALS(tin->Triangles()[0], 3);
1809 TS_ASSERT_EQUALS(tin->Triangles()[1], 0);
1810 TS_ASSERT_EQUALS(tin->Triangles()[2], 4);
1811 TS_ASSERT_EQUALS(tin->Triangles()[3], 1);
1812 TS_ASSERT_EQUALS(tin->Triangles()[4], 2);
1813 TS_ASSERT_EQUALS(tin->Triangles()[5], 4);
1814 TS_ASSERT_EQUALS(tin->Triangles()[6], 1);
1815 TS_ASSERT_EQUALS(tin->Triangles()[7], 4);
1816 TS_ASSERT_EQUALS(tin->Triangles()[8], 0);
1817 const VecInt2d& trisAdjToPtsRef = tin->TrisAdjToPts();
1818 TS_ASSERT_EQUALS((
VecInt{0, 2}), trisAdjToPtsRef[0]);
1819 TS_ASSERT_EQUALS((
VecInt{1, 2}), trisAdjToPtsRef[1]);
1820 TS_ASSERT_EQUALS((
VecInt{1}), trisAdjToPtsRef[2]);
1821 TS_ASSERT_EQUALS((
VecInt{0}), trisAdjToPtsRef[3]);
1822 TS_ASSERT_EQUALS((
VecInt{1, 2, 0}), trisAdjToPtsRef[4]);
1831 tin->TrisAdjToPts().clear();
1832 tin->BuildTrisAdjToPts();
1833 TS_ASSERT_EQUALS(*trisAdjToPts, tin->TrisAdjToPts());
1838 TS_ASSERT_EQUALS(tin->Points().empty(),
true);
1839 TS_ASSERT_EQUALS(tin->Triangles().empty(),
true);
1840 TS_ASSERT_EQUALS(tin->TrisAdjToPts().empty(),
true);
1891 BSHP<VecPt3d> pts(
new VecPt3d());
1892 BSHP<VecInt> tris(
new VecInt());
1893 BSHP<VecInt2d> trisAdjToPts(
new VecInt2d());
1896 *pts = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {0, 10, 0}, {10, 10, 0},
1897 {20, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}};
1898 *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};
1899 *trisAdjToPts = {{0}, {0, 1, 2, 4}, {4, 5, 6}, {0, 1}, {2, 4, 5, 3},
1900 {6, 7}, {1, 2, 3}, {3, 5, 6, 7}, {7}};
1903 tin->SetGeometry(pts, tris, trisAdjToPts);
1907 tin->GetBoundaryPoints(boundaryPoints);
1908 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 5, 6, 7, 8}), boundaryPoints);
1911 TS_ASSERT(tin->OptimizeTriangulation());
1912 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};
1916 tin->GetBoundaryPoints(boundaryPoints);
1917 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 5, 6, 7, 8}), boundaryPoints);
1945 VecInt& tris = tin->Triangles();
1946 VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
1949 tin->Points() = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 10, 0},
1950 {15, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}};
1957 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};
1958 VecInt trisBefore(&trisB[0], &trisB[24]);
1959 TS_ASSERT_EQUALS(trisBefore, tris);
1961 VecInt2d trisAdjToPtsBefore = {{0, 2}, {0, 3, 5}, {4, 5}, {0, 1, 2, 3, 7},
1962 {3, 4, 5, 6, 7}, {1, 2}, {1, 6, 7}, {4, 6}};
1964 TS_ASSERT_EQUALS(trisAdjToPtsBefore, trisAdjToPts);
1967 bool rv = tin->SwapEdge(3, 7);
1968 TS_ASSERT_EQUALS(rv,
true);
1971 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};
1972 VecInt trisAfter(&trisA[0], &trisA[24]);
1973 TS_ASSERT_EQUALS(trisAfter, tris);
1975 VecInt2d trisAdjToPtsAfter = {{0, 2}, {0, 3, 5, 7}, {4, 5}, {0, 1, 2, 3},
1976 {4, 5, 6, 7}, {1, 2}, {1, 6, 7, 3}, {4, 6}};
1977 TS_ASSERT_EQUALS(trisAdjToPtsAfter, trisAdjToPts);
1981 tin->GetBoundaryPoints(boundaryPoints);
1982 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 5, 6, 7}), boundaryPoints);
1985 #if 0 // FirstBoundaryPoint has been commented out because it wasn't used 1989 void TrTinTests::testFirstBoundaryPoint ()
1996 TS_ASSERT_EQUALS(tin->FirstBoundaryPoint(), 0);
2019 tin->Points() = {{5,10,0},{15,10,0},{0,0,0},{10,0,0},
2020 {20,0,0},{0,20,0},{10,20,0},{20,20,0}};
2022 &tin->TrisAdjToPts());
2024 TS_ASSERT_EQUALS(tin->FirstBoundaryPoint(), 2);
2053 SetInt toDelete = {20, 24};
2054 tin->DeletePoints(toDelete);
2060 tin->GetBoundaryPoints(pts);
2061 int ptsA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20,
2062 22, 23, 24, 25, 26, 27, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42};
2064 TS_ASSERT_EQUALS(expectedPts, pts);
2068 tin->GetBoundaryPolys(boundaries);
2071 {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},
2072 {10, 11, 20, 27, 26, 19, 10},
2073 {15, 16, 23, 31, 22, 15}};
2082 TS_ASSERT_EQUALS(tin->NumTriangles(), 64);
2083 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
2085 const VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
2088 TS_ASSERT_EQUALS((
VecInt{7, 19, 20, 21, 23, 29}), trisAdjToPts[20]);
2089 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 7, 12, 29}), trisAdjToPts[10]);
2090 TS_ASSERT_EQUALS((
VecInt{7, 8, 10, 12, 21}), trisAdjToPts[11]);
2091 TS_ASSERT_EQUALS((
VecInt{10, 13, 20, 21, 22, 27, 30}), trisAdjToPts[21]);
2092 TS_ASSERT_EQUALS((
VecInt{18, 20, 22, 23, 25, 28}), trisAdjToPts[29]);
2093 TS_ASSERT_EQUALS((
VecInt{14, 16, 17, 18, 19, 23}), trisAdjToPts[28]);
2094 TS_ASSERT_EQUALS((
VecInt{3, 14, 15, 19, 29}), trisAdjToPts[19]);
2097 SetInt toDelete = {7, 19, 20, 21, 23, 29};
2098 tin->DeleteTriangles(toDelete);
2100 TS_ASSERT_EQUALS(tin->NumTriangles(), 58);
2101 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
2105 for (
size_t i = 0; i < trisAdjToPts.size(); ++i)
2107 for (
size_t j = 0; j < trisAdjToPts[i].size(); ++j)
2109 if (trisAdjToPts[i][j] > mx)
2110 mx = trisAdjToPts[i][j];
2113 TS_ASSERT_EQUALS(mx, 57);
2130 TS_ASSERT(tin->TrisAdjToPts()[20].empty());
2131 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 11}), trisAdjToPts[10]);
2132 TS_ASSERT_EQUALS((
VecInt{7, 9, 11}), trisAdjToPts[11]);
2133 TS_ASSERT_EQUALS((
VecInt{9, 12, 18, 22, 24}), trisAdjToPts[21]);
2134 TS_ASSERT_EQUALS((
VecInt{17, 18, 20, 23}), trisAdjToPts[29]);
2135 TS_ASSERT_EQUALS((
VecInt{13, 15, 16, 17}), trisAdjToPts[28]);
2136 TS_ASSERT_EQUALS((
VecInt{3, 13, 14}), trisAdjToPts[19]);
2144 TS_ASSERT_EQUALS(tin->NumTriangles(), 64);
2145 TS_ASSERT_EQUALS(tin->NumPoints(), 45);
2147 SetInt toDelete = {20, 24};
2148 tin->DeletePoints(toDelete);
2150 TS_ASSERT_EQUALS(tin->NumTriangles(), 53);
2151 TS_ASSERT_EQUALS(tin->NumPoints(), 43);
2169 const VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
2171 TS_ASSERT_EQUALS((
VecInt{0, 1, 2, 3, 4, 11}), trisAdjToPts[10]);
2172 TS_ASSERT_EQUALS((
VecInt{7, 9, 11}), trisAdjToPts[11]);
2173 TS_ASSERT_EQUALS((
VecInt{9, 12, 18, 22, 24}), trisAdjToPts[20]);
2174 TS_ASSERT_EQUALS((
VecInt{17, 18, 20, 23}), trisAdjToPts[27]);
2175 TS_ASSERT_EQUALS((
VecInt{13, 15, 16, 17}), trisAdjToPts[26]);
2176 TS_ASSERT_EQUALS((
VecInt{3, 13, 14}), trisAdjToPts[19]);
2178 TS_ASSERT_EQUALS((
VecInt{28, 30, 32, 33}), trisAdjToPts[15]);
2179 TS_ASSERT_EQUALS((
VecInt{32, 35, 36, 46}), trisAdjToPts[16]);
2180 TS_ASSERT_EQUALS((
VecInt{45, 46, 48}), trisAdjToPts[23]);
2181 TS_ASSERT_EQUALS((
VecInt{39, 40, 43, 48}), trisAdjToPts[31]);
2182 TS_ASSERT_EQUALS((
VecInt{26, 28, 29, 39}), trisAdjToPts[22]);
2190 TS_ASSERT_EQUALS(tin->NumTriangles(), 8);
2191 TS_ASSERT_EQUALS(tin->NumPoints(), 8);
2193 tin->RemoveLongThinTrianglesOnPerimeter(0.75);
2195 TS_ASSERT_EQUALS(tin->NumTriangles(), 6);
2196 TS_ASSERT_EQUALS(tin->NumPoints(), 8);
int trDecrementIndex(int i)
Faster than a % operation and we do this a lot.
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...
std::vector< int > VecInt
virtual ~TrTinImpl()
destructor
BSHP< TrTin > trBuildTestTin8()
Builds a simple TIN with a hole in the middle and a concavity.
virtual ~TrTin()
destructor
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...
double gmXyDistance(double x1, double y1, double x2, double y2)
Compute the 2d distance between 2 points.
BOOST_CLASS_EXPORT(xms::TrTinImpl)
Cause boost.
#define XM_ENSURE_TRUE_VOID(...)
std::string STRstd(double a_value, int a_n, int width, int flags)
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.
virtual std::string ToString() const override
Use boost archive to get the TrTin as text.
bool TriIndexFound(const int &a_triPt) const
Predicate used in remove_if to get the index of the current item in the vector.
PtInOutOrOn_enum gmPtInCircumcircle(const Pt3d &pt, Pt3d circumcirclePts[3])
Is a given point inside a circumcircle defined by three points?
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.
#define XM_ENSURE_TRUE_NO_ASSERT(...)
bool AdjacentIndexFound(const VecInt &a_point) const
Predicate used in remove_if to get the index of the current item in the vector.
virtual int GlobalIndex(int a_triIdx, int a_localVtxIdx) const override
Returns index into m_pts of a_localPt which is 0-2.
bool PointIndexFound(const Pt3d &a_point) const
Predicate used in remove_if to get the index of the current item in the vector.
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.
double gmAngleBetweenEdges(const Pt3d &p1, const Pt3d &p2, const Pt3d &p3)
Returns the ccw angle (0-2pi) between p2-p1 and p2-p3.
virtual void BuildTrisAdjToPts() override
Build array of triangles adjacent to points.
void testRemoveLongThinTrianglesOnPerimeter()
Tests TrTin::RemoveLongThinTrianglesOnPerimeter.
BSHP< TrTin > trBuildTestTin6()
Builds a simple TIN for testing.
std::vector< VecInt > VecInt2d
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...
virtual bool RemoveLongThinTrianglesOnPerimeter(const double a_ratio) override
Removes long thin triangles on the boundary of the TIN.
double trArea(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_pt3)
Return the signed planar area of the triangle (CCW Positive).
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(...)
int AdjacentTriangleIndex(const int a_currTri, const int a_adjTri) const
finds the index of adjacent triangle that points to the current triangle
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.
void trRenumberOnDelete(const SetInt &a_deleting, VecInt &a_vec)
Boost serialize function.
void CheckTriangle(const int a_tri, const int a_index, const double a_ratio, VecInt &a_flags, SetInt &a_trisToDelete) const
If triangle is long and thin (index edge is long compared to sum of other two edges) the triangle is ...
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 previous point CCW from point on the boundary. CW if in an inside hole. Compare to trPreviousBoundaryVertex (or trNextBoundaryVertex since order here is CW, not CCW).
boost::unordered_set< int > m_toDelete
Used only when deleting stuff.
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.
void stShrinkCapacity(std::vector< T > &v)
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.
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 gmCounterClockwiseTri(const Pt3d &vtx0, const Pt3d &vtx1, const Pt3d &vtx2)
Returns true if the triangle is wrapped counter clockwise.
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
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).
void BuildTrisAdjToPtsConst() const
A const function used only internally and needed to modify m_trisAdjToPts which is mutable...
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.
int trIncrementIndex(int i)
Faster than a % operation and we do this a lot.
void testDeleteTriangles()
Tests TrTin::DeleteTriangles.
BSHP< TrTin > trBuildTestTin9()
Builds a TIN with long thin triangles for testing.
Class to triangulate simple points.
std::vector< Pt3d > VecPt3d