57 typedef std::vector<edgerecord> VecEdge;
69 virtual void SetTin(BSHP<TrTin> a_tin,
double a_tol = -1)
override;
109 BSHP<GmMultiPolyIntersector>
125 TrBreaklineAdderImpl::TrBreaklineAdderImpl()
133 , m_trisAdjToPts(nullptr)
136 , m_multiPolyIntersector()
143 TrBreaklineAdderImpl::~TrBreaklineAdderImpl()
185 bool progressStarted =
false;
190 m_observer->BeginOperationString(
"Adding Breaklines");
191 progressStarted =
true;
197 for (
size_t pt = 1; pt < a_breakline.size(); ++pt)
199 int pt1 = a_breakline[pt - 1];
200 int pt2 = a_breakline[pt];
201 if (!
m_tin->VerticesAreAdjacent(pt1, pt2))
230 m_observer->BeginOperationString(
"Adding Breaklines");
233 for (
size_t i = 0; i < a_breaklines.size(); ++i)
239 for (
size_t i = 0; i < a_breaklines.size(); ++i)
260 switch (a_messageNumber)
263 message =
"One or more breakline segments intersected a boundary and was ignored.";
284 m_tin->GetBoundaryPolys(boundaryPolys);
286 BSHP<GmMultiPolyIntersectionSorter> sorter =
289 m_multiPolyIntersector->SetQuery(GMMPIQ_INTERSECTS);
298 m_tin->Points()[a_blpt1].x,
m_tin->Points()[a_blpt1].y,
m_tin->Points()[a_blpt2].x,
299 m_tin->Points()[a_blpt2].y, intersectedPolys, intersectionPts);
300 if (intersectedPolys.empty())
308 for (
size_t i = 0; i < intersectionPts.size(); ++i)
330 "One or more breakline segments intersected a boundary and was ignored.");
336 VecEdge::iterator edge = edges.begin();
338 bool good_tris =
true;
339 bool trisSwappedThisPass =
false;
342 while (!edges.empty() && edge != edges.end())
344 int tri1 =
m_tin->TriangleAdjacentToEdge(edge->pt1, edge->pt2);
345 int tri2 =
m_tin->TriangleAdjacentToEdge(edge->pt2, edge->pt1);
346 if (!
m_tin->SwapEdge(tri1, tri2, good_tris))
352 trisSwappedThisPass =
true;
354 int index =
m_tin->CommonEdgeIndex(tri1, tri2);
356 int newpt1 = (*m_tris)[(tri1 * 3) + index];
357 index = trIncrementIndex(index);
358 int newpt2 = (*m_tris)[(tri1 * 3) + index];
359 if ((newpt1 != a_blpt1) && (newpt1 != a_blpt2) && (newpt2 != a_blpt1) &&
360 (newpt2 != a_blpt2) &&
361 gmIntersectLineSegmentsWithTol((*
m_pts)[a_blpt1], (*m_pts)[a_blpt2], (*m_pts)[newpt1],
362 (*m_pts)[newpt2], &x, &y, &z1, &z2,
m_xyTol))
372 edge = edges.erase(edge);
376 if (edge == edges.end() && (tri1 != -1 && tri2 != -1))
379 if (!trisSwappedThisPass)
393 edge = edges.begin();
394 trisSwappedThisPass =
false;
396 else if (
m_tin->VerticesAreAdjacent(a_blpt1, a_blpt2))
428 if (intpt1 == -1 || intpt2 == -1)
430 else if (intpt1 == a_blpt2 || intpt2 == a_blpt2)
440 a_edges.push_back(edge);
469 for (
size_t adjTri = 0; adjTri < (*m_trisAdjToPts)[a_blpt1].size() && !found; ++adjTri)
471 int tri = (*m_trisAdjToPts)[a_blpt1][adjTri];
473 int localIdx1 =
m_tin->LocalIndex(tri, a_blpt1);
474 localIdx1 = trIncrementIndex(localIdx1);
475 int localIdx2 = trIncrementIndex(localIdx1);
476 *a_intpt1 =
m_tin->Triangles()[(tri * 3) + localIdx1];
477 *a_intpt2 =
m_tin->Triangles()[(tri * 3) + localIdx2];
479 gmIntersectLineSegmentsWithTol((*
m_pts)[a_blpt1], (*
m_pts)[a_blpt2], (*
m_pts)[*a_intpt1],
484 *a_intpt1 = *a_intpt2 = -1;
515 int tri =
m_tin->TriangleAdjacentToEdge(a_ept2, a_ept1);
518 int localIdx1 =
m_tin->LocalIndex(tri, a_ept2);
519 const int kNumcorners = 3;
522 for (crnrid = localIdx1, count = 1; !found && count <= kNumcorners - 1; count++)
524 int nextid = trIncrementIndex(crnrid);
525 int trisIdx = tri * 3;
526 *a_intpt1 = (*m_tris)[trisIdx + crnrid];
527 *a_intpt2 = (*m_tris)[trisIdx + nextid];
529 gmIntersectLineSegmentsWithTol((*
m_pts)[a_blpt1], (*
m_pts)[a_blpt2], (*
m_pts)[*a_intpt1],
535 m_tin->TriangleFromEdge(*a_intpt1, *a_intpt2, adjTri, id1, id2);
538 throw std::runtime_error(
"Void in breakline");
546 *a_intpt1 = *a_intpt2 = -1;
583 TrBreaklineAdder::TrBreaklineAdder()
589 TrBreaklineAdder::~TrBreaklineAdder()
610 #include <boost/assign.hpp>
664 tin->Points() = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {5, 4, 0},
665 {15, 4, 0}, {5, -4, 0}, {15, -4, 0}};
670 int trisB[] = {0, 5, 3, 3, 5, 1, 1, 6, 4, 6, 1, 5, 2, 4, 6, 1, 4, 3};
671 TS_ASSERT_EQUALS(
VecInt(&trisB[0], &trisB[18]), tin->Triangles());
676 VecInt outPoly = {0, 5, 6, 1, 2, 4, 3};
677 adder->AddBreakline(outPoly);
680 int trisA[] = {0, 5, 3, 3, 5, 1, 1, 2, 4, 6, 1, 5, 2, 1, 6, 1, 4, 3};
681 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
765 int trisB[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 5, 6, 10, 9,
766 13, 17, 13, 9, 10, 17, 13, 18, 10, 14, 18, 14, 10, 6, 18, 14, 19, 10, 18,
767 13, 9, 5, 10, 6, 2, 7, 12, 11, 7, 7, 11, 6, 3, 4, 8, 8, 4, 21,
768 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20, 15, 19, 11, 12, 15, 11, 15,
769 12, 16, 20, 16, 21, 16, 20, 15, 21, 16, 8, 12, 8, 16, 11, 19, 14};
770 TS_ASSERT_EQUALS(
VecInt(&trisB[0], &trisB[93]), tin->Triangles());
773 int outPolyA[] = {0, 1, 2, 3, 4, 8, 16, 21, 20, 19, 18, 17, 9};
774 VecInt outPoly(&outPolyA[0], &outPolyA[13]);
775 int inPoly1[] = {10, 5, 13, 14};
776 int inPoly2[] = {6, 11, 15, 7};
778 inPolys.push_back(
VecInt(&inPoly1[0], &inPoly1[4]));
779 inPolys.push_back(
VecInt(&inPoly2[0], &inPoly2[4]));
784 adder->AddBreakline(outPoly);
785 adder->AddBreaklines(inPolys);
788 int trisA[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 5, 6, 10, 9,
789 13, 17, 13, 5, 10, 17, 13, 18, 10, 14, 13, 14, 10, 6, 18, 14, 19, 14, 18,
790 13, 9, 5, 13, 6, 2, 7, 15, 11, 7, 7, 11, 6, 3, 4, 8, 8, 4, 21,
791 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20, 15, 19, 11, 12, 15, 7, 15,
792 12, 16, 20, 16, 21, 16, 20, 15, 21, 16, 8, 12, 8, 16, 11, 19, 14};
794 TS_ASSERT_EQUALS(trisAfter, tin->Triangles());
829 VecInt tris = tin->Triangles();
831 std::string errorMessage = adder->ErrorMessage(0);
834 VecInt breakline = {3, 8};
836 adder->AddBreakline(breakline);
841 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
843 TS_ASSERT_EQUALS(tris, tin->Triangles());
848 adder->AddBreakline(breakline);
853 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
855 TS_ASSERT_EQUALS(tris, tin->Triangles());
858 breakline = {10, 7, 2, 8};
860 adder->AddBreakline(breakline);
865 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
868 int trisA[] = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 7, 6, 3, 7, 2,
869 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
870 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
874 breakline = {0, 4, 11};
876 adder->AddBreakline(breakline);
881 TS_ASSERT_EQUALS(messages[0].second, errorMessage);
884 int trisA[] = {0, 3, 2, 0, 4, 3, 1, 4, 0, 1, 5, 4, 2, 7, 6, 3, 7, 2,
885 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
886 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
890 breakline = {3, 4, 7, 8, 4, 3, 7};
892 adder->AddBreakline(breakline);
895 int trisA[] = {0, 3, 2, 0, 4, 3, 1, 4, 0, 1, 5, 4, 2, 7, 6, 3, 7, 2,
896 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 10, 9, 8, 10, 7, 8, 11, 10};
897 TS_ASSERT_EQUALS(
VecInt(&trisA[0], &trisA[
XM_COUNTOF(trisA)]), tin->Triangles());
902 catch (std::exception&)
904 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.
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.
size_t m_totNumSegs
Total num segments. For progress.
std::vector< std::pair< xmlog::MessageTypeEnum, std::string > > MessageStack
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.
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()
std::vector< int > VecInt
virtual void SetObserver(BSHP< Observer > a_) override
Set the observer to use for feedback while processing.
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.
std::vector< Pt3d > VecPt3d
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...
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.
std::vector< VecInt > VecInt2d
virtual void AddBreaklines(const VecInt2d &a_breakline) override
Add breaklines by swapping. Compare to bkProcessScatBySwapping.
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.
size_t m_segCount
Current segment. For progress.
bool GetExtents()
Computes the extents (min, max) of the polygon.
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.
VecInt2d * m_trisAdjToPts
Pointer to m_tin trisAdjToPts for convenience.