69 virtual void SetTin(BSHP<TrTin> a_tin,
double a_tol = -1)
override;
107 BSHP<GmMultiPolyIntersector>
123 TrBreaklineAdderImpl::TrBreaklineAdderImpl()
129 , m_trisAdjToPts(nullptr)
132 , m_multiPolyIntersector()
139 TrBreaklineAdderImpl::~TrBreaklineAdderImpl()
181 double totNumSegs =
static_cast<double>(a_breakline.size() - 1);
182 double segCount(0.0);
184 for (
size_t pt = 1; pt < a_breakline.size(); ++pt)
186 int pt1 = a_breakline[pt - 1];
187 int pt2 = a_breakline[pt];
188 if (!
m_tin->VerticesAreAdjacent(pt1, pt2))
207 size_t totNumSegs(0);
208 for (
size_t i = 0; i < a_breaklines.size(); ++i)
210 totNumSegs += a_breaklines[i].size() - 1;
212 double total =
static_cast<double>(totNumSegs);
213 for (
size_t i = 0; i < a_breaklines.size(); ++i)
215 segCount += a_breaklines[i].size() - 1;
228 switch (a_messageNumber)
231 message =
"One or more breakline segments intersected a boundary and was ignored.";
252 m_tin->GetBoundaryPolys(boundaryPolys);
254 BSHP<GmMultiPolyIntersectionSorter> sorter =
266 m_tin->Points()[a_blpt1].x,
m_tin->Points()[a_blpt1].y,
m_tin->Points()[a_blpt2].x,
267 m_tin->Points()[a_blpt2].y, intersectedPolys, intersectionPts);
268 if (intersectedPolys.empty())
276 for (
size_t i = 0; i < intersectionPts.size(); ++i)
298 "One or more breakline segments intersected a boundary and was ignored.");
304 VecEdge::iterator edge = edges.begin();
306 bool good_tris =
true;
307 bool trisSwappedThisPass =
false;
310 while (!edges.empty() && edge != edges.end())
312 int tri1 =
m_tin->TriangleAdjacentToEdge(edge->pt1, edge->pt2);
313 int tri2 =
m_tin->TriangleAdjacentToEdge(edge->pt2, edge->pt1);
314 if (!
m_tin->SwapEdge(tri1, tri2, good_tris))
320 trisSwappedThisPass =
true;
322 int index =
m_tin->CommonEdgeIndex(tri1, tri2);
324 int newpt1 = (*m_tris)[(tri1 * 3) + index];
326 int newpt2 = (*m_tris)[(tri1 * 3) + index];
327 if ((newpt1 != a_blpt1) && (newpt1 != a_blpt2) && (newpt2 != a_blpt1) &&
328 (newpt2 != a_blpt2) &&
330 (*m_pts)[newpt2], &x, &y, &z1, &z2,
m_xyTol))
340 edge = edges.erase(edge);
344 if (edge == edges.end() && (tri1 != -1 && tri2 != -1))
347 if (!trisSwappedThisPass)
361 edge = edges.begin();
362 trisSwappedThisPass =
false;
364 else if (
m_tin->VerticesAreAdjacent(a_blpt1, a_blpt2))
396 if (intpt1 == -1 || intpt2 == -1)
398 else if (intpt1 == a_blpt2 || intpt2 == a_blpt2)
408 a_edges.push_back(edge);
437 for (
size_t adjTri = 0; adjTri < (*m_trisAdjToPts)[a_blpt1].size() && !found; ++adjTri)
439 int tri = (*m_trisAdjToPts)[a_blpt1][adjTri];
441 int localIdx1 =
m_tin->LocalIndex(tri, a_blpt1);
444 *a_intpt1 =
m_tin->Triangles()[(tri * 3) + localIdx1];
445 *a_intpt2 =
m_tin->Triangles()[(tri * 3) + localIdx2];
452 *a_intpt1 = *a_intpt2 = -1;
483 int tri =
m_tin->TriangleAdjacentToEdge(a_ept2, a_ept1);
486 int localIdx1 =
m_tin->LocalIndex(tri, a_ept2);
487 const int kNumcorners = 3;
490 for (crnrid = localIdx1, count = 1; !found && count <= kNumcorners - 1; count++)
493 int trisIdx = tri * 3;
494 *a_intpt1 = (*m_tris)[trisIdx + crnrid];
495 *a_intpt2 = (*m_tris)[trisIdx + nextid];
503 m_tin->TriangleFromEdge(*a_intpt1, *a_intpt2, adjTri, id1, id2);
506 throw std::runtime_error(
"Void in breakline");
514 *a_intpt1 = *a_intpt2 = -1;
551 TrBreaklineAdder::TrBreaklineAdder()
557 TrBreaklineAdder::~TrBreaklineAdder()
578 #include <boost/assign.hpp> 632 tin->Points() = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 4, 0},
633 {15, 4, 0}, {5, -4, 0}, {15, -4, 0}};
638 int trisB[] = {0, 5, 3, 3, 5, 1, 1, 6, 4, 6, 1, 5, 2, 4, 6, 1, 4, 3};
639 TS_ASSERT_EQUALS(
VecInt(&trisB[0], &trisB[18]), tin->Triangles());
644 VecInt outPoly = {0, 5, 6, 1, 2, 4, 3};
645 adder->AddBreakline(outPoly);
648 int trisA[] = {0, 5, 3, 3, 5, 1, 1, 2, 4, 6, 1, 5, 2, 1, 6, 1, 4, 3};
649 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
733 int trisB[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 5, 6, 10, 9,
734 13, 17, 13, 9, 10, 17, 13, 18, 10, 14, 18, 14, 10, 6, 18, 14, 19, 10, 18,
735 13, 9, 5, 10, 6, 2, 7, 12, 11, 7, 7, 11, 6, 3, 4, 8, 8, 4, 21,
736 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20, 15, 19, 11, 12, 15, 11, 15,
737 12, 16, 20, 16, 21, 16, 20, 15, 21, 16, 8, 12, 8, 16, 11, 19, 14};
738 TS_ASSERT_EQUALS(
VecInt(&trisB[0], &trisB[93]), tin->Triangles());
741 int outPolyA[] = {0, 1, 2, 3, 4, 8, 16, 21, 20, 19, 18, 17, 9};
742 VecInt outPoly(&outPolyA[0], &outPolyA[13]);
743 int inPoly1[] = {10, 5, 13, 14};
744 int inPoly2[] = {6, 11, 15, 7};
746 inPolys.push_back(
VecInt(&inPoly1[0], &inPoly1[4]));
747 inPolys.push_back(
VecInt(&inPoly2[0], &inPoly2[4]));
752 adder->AddBreakline(outPoly);
753 adder->AddBreaklines(inPolys);
756 int trisA[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 5, 6, 10, 9,
757 13, 17, 13, 5, 10, 17, 13, 18, 10, 14, 13, 14, 10, 6, 18, 14, 19, 14, 18,
758 13, 9, 5, 13, 6, 2, 7, 15, 11, 7, 7, 11, 6, 3, 4, 8, 8, 4, 21,
759 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20, 15, 19, 11, 12, 15, 7, 15,
760 12, 16, 20, 16, 21, 16, 20, 15, 21, 16, 8, 12, 8, 16, 11, 19, 14};
762 TS_ASSERT_EQUALS(trisAfter, tin->Triangles());
797 VecInt tris = tin->Triangles();
799 std::string errorMessage = adder->ErrorMessage(0);
802 VecInt breakline = {3, 8};
804 adder->AddBreakline(breakline);
809 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
811 TS_ASSERT_EQUALS(tris, tin->Triangles());
816 adder->AddBreakline(breakline);
821 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
823 TS_ASSERT_EQUALS(tris, tin->Triangles());
826 breakline = {10, 7, 2, 8};
828 adder->AddBreakline(breakline);
833 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
836 int trisA[] = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 7, 6, 3, 7, 2,
837 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
838 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
842 breakline = {0, 4, 11};
844 adder->AddBreakline(breakline);
849 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
852 int trisA[] = {0, 3, 2, 0, 4, 3, 1, 4, 0, 1, 5, 4, 2, 7, 6, 3, 7, 2,
853 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
854 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
858 breakline = {3, 4, 7, 8, 4, 3, 7};
860 adder->AddBreakline(breakline);
863 int trisA[] = {0, 3, 2, 0, 4, 3, 1, 4, 0, 1, 5, 4, 2, 7, 6, 3, 7, 2,
864 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
865 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
870 catch (std::exception&)
872 TS_FAIL(
"exception");
static boost::shared_ptr< TrBreaklineAdder > New()
Create a TrBreaklineAdderImpl object.
BSHP< Observer > m_observer
The observer.
virtual void AddBreakline(const VecInt &a_breakline) override
Add a breakline by swapping. Compare to bkProcessScatBySwapping.
std::vector< std::pair< xmlog::MessageTypeEnum, std::string > > MessageStack
std::vector< int > VecInt
BSHP< TrTin > trBuildTestTin8()
Builds a simple TIN with a hole in the middle and a concavity.
void test2()
Test a more complex case involving two inner polygons and removal of outer triangles. This doesn't remove the triangles - that would be the next step.
void test1()
Test a simple case involving a swap and removal of outer triangle.
Functions dealing with triangles.
void FindIntersectingEdgeFromPoint(int a_blpt1, int a_blpt2, int *a_intpt1, int *a_intpt2, double *a_x, double *a_y, double *a_z1, double *a_z2)
Finds edge opposite of a_blpt1 intersected by breakline segment a_blpt1, a_blpt2. Compare to bkiFindI...
void ProcessSegmentBySwapping(int a_vtx1, int a_vtx2)
Insert breakline segment into triangulation by swapping triangle edges. Compare to bkiProcessScatSegm...
int pt1
Index of point defining the edge.
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 ComputeTolerance()
Computes a tolerance to use based on point extents.
static boost::shared_ptr< GmMultiPolyIntersector > New(const std::vector< Pt3d > &a_points, const std::vector< std::vector< int > > &a_polys, boost::shared_ptr< GmMultiPolyIntersectionSorter > a_sorter, int a_startingId=1)
Creates a new GmMultiPolyIntersectorImpl object.
Adds breaklines to a triangulation.
MessageStack GetAndClearStack()
virtual void SetObserver(BSHP< Observer > a_) override
Set the observer to use for feedback while processing.
std::vector< VecInt > VecInt2d
VecPt3d * m_pts
Pointer to m_tin points for convenience.
Pt3d m_mx
Maximum extent of all points.
Functions dealing with geometry.
static BSHP< TrTin > New()
Create a TrTinImpl object.
bool Triangulate()
Triangulate the points into a tin.
std::string GetAndClearStackStr()
Adds breaklines to a tin.
Pt3d intersection
Point of intersection.
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...
virtual std::string ErrorMessage(int) const override
Returns the error message associated with the given number.
void FindIntersectingEdgeFromEdge(int a_ept1, int a_ept2, int a_blpt1, int a_blpt2, int *a_intpt1, int *a_intpt2, double *a_x, double *a_y, double *a_z1, double *a_z2)
Finds edge of triangle intersected by breakline and returns next edge in a_intpt1 and a_intpt2...
void ProgressStatus(double a_percentComplete)
Pt3d m_mn
Minimum extent of all points.
void GetIntersectingEdges(int a_blpt1, int a_blpt2, VecEdge &a_edges)
Find triangle edges which intersect the breakline. Compare to bkiGetListOfIntersectingScatEdges.
#define XM_ENSURE_TRUE_T_NO_ASSERT(...)
void testCrossingBoundary()
Test a case involving crossing a hole and the outer boundary.
virtual void SetTin(BSHP< TrTin > a_tin, double a_tol=-1) override
Sets the tin that will have breaklines added to it.
#define XM_COUNTOF(array)
BSHP< GmMultiPolyIntersector > m_multiPolyIntersector
Used to check if breakline crosses boundary.
BSHP< TrTin > trBuildTestTin7()
Builds a simple TIN for testing.
static BSHP< GmPtSearch > New(bool a_2dSearch)
Creates an PtSearch class.
static XmLog & Instance(bool a_delete=false, XmLog *a_new=NULL)
int pt2
Index of point defining the edge.
virtual void AddBreaklines(const VecInt2d &a_breakline) override
Add breaklines by swapping. Compare to bkProcessScatBySwapping.
std::vector< edgerecord > VecEdge
Vector of edgerecord.
BSHP< GmPtSearch > m_searcher
Used to check if breakline crosses boundary.
Class for sorting intersections from GmMultiPolyIntersector in a terse way (with no duplicate info)...
VecInt * m_tris
Pointer to m_tin triangles for convenience.
Defines an edge that intersects a breakline.
double m_xyTol
Xy tolerance used with geom functions.
bool GetExtents()
Computes the extents (min, max) of the polygon.
int trIncrementIndex(int i)
Faster than a % operation and we do this a lot.
bool CrossesBoundary(int a_blpt1, int a_blpt2)
Returns true if the line connecting the two points crosses the tin boundary.
BSHP< TrTin > m_tin
The tin.
Class to triangulate simple points.
std::vector< Pt3d > VecPt3d
VecInt2d * m_trisAdjToPts
Pointer to m_tin trisAdjToPts for convenience.