22 #include <boost/format.hpp> 23 #include <boost/unordered_map.hpp> 59 std::string& a_errors)
const override;
76 const Pt3d& two2)
const;
81 boost::unordered_map<std::pair<double, double>,
int>
m_ptHash;
95 SegmentLocation(
int a_poly = 0,
int a_polySeg = 0,
int a_inPoly = 0,
int a_inPolySeg = 0)
117 void iWriteInterpDataToDebugFile(std::fstream& a_os, BSHP<InterpBase> a_interp)
119 BSHP<VecPt3d> ptsPtr = a_interp->GetPts();
120 BSHP<InterpIdw> idw = BDPC<InterpIdw>(a_interp);
121 BSHP<InterpLinear> linear = BDPC<InterpLinear>(a_interp);
129 a_os << pts.size() <<
"\n";
130 for (
const auto& p : pts)
139 std::ifstream f(
"c:\\temp\\xmsmesh_write_inputs.dbg");
143 os.open(
"C:\\temp\\xmsmesh_inputs.txt", std::fstream::out);
146 for (
size_t i = 0; i < a_io.
m_polys.size(); ++i)
149 os <<
"BEGIN_POLYGON\nOUTSIDE " << poly.m_outPoly.size() <<
"\n";
150 for (
auto& p : poly.m_outPoly)
152 for (
auto& v : poly.m_insidePolys)
154 os <<
"INSIDE " << v.size() <<
"\n";
158 os <<
"BIAS " <<
STRstd(poly.m_bias) <<
"\n";
159 if (poly.m_sizeFunction)
161 os <<
"SIZE_FUNCTION\n";
162 iWriteInterpDataToDebugFile(os, poly.m_sizeFunction);
164 if (poly.m_elevFunction)
166 os <<
"ELEVATION_FUNCTION\n";
167 iWriteInterpDataToDebugFile(os, poly.m_elevFunction);
169 if (poly.m_constSizeFunction != -1)
171 os <<
"CONST_SIZE_FUNCTION " <<
STRstd(poly.m_constSizeFunction) <<
"\n";
173 if (!poly.m_polyCorners.empty())
175 os <<
"PATCH_CORNERS ";
176 for (
size_t j = 0; j < poly.m_polyCorners.size(); ++j)
177 os << poly.m_polyCorners[j] <<
" ";
180 if (poly.m_relaxationMethod !=
"")
182 os <<
"RELAXATION_METHOD " << poly.m_relaxationMethod <<
"\n";
184 os <<
"END_POLYGON\n";
188 os <<
"CHECK_TOPOLOGY\n";
192 os <<
"RETURN_CELL_POLYGONS\n";
196 os <<
"REFINE_POINTS " << a_io.
m_refPts.size() <<
"\n";
200 << p.m_createMeshPoint <<
"\n";
232 iWriteInputsToDebugFile(a_io);
241 std::stringstream ss;
242 ss <<
"Meshing polygon 1 of " << a_io.
m_polys.size();
245 VecPt3d pts, refinePts, tmpPts;
246 VecInt tris, cells, cellPolygons;
247 for (
size_t i = 0; i < a_io.
m_polys.size(); ++i)
251 if (pm->MeshIt(a_io, i, pts, tris, cells))
253 pm->GetProcessedRefinePts(tmpPts);
254 refinePts.insert(refinePts.end(), tmpPts.begin(), tmpPts.end());
266 ss <<
"Meshing polygon " << i + 2 <<
" of " << a_io.
m_polys.size();
267 prog.UpdateMessage(ss.str());
268 prog.ProgressStatus((
double)i / a_io.
m_polys.size());
291 for (
size_t i = 0; i < a_io.
m_polys.size(); ++i)
294 auto &first = polyInput.
m_outPoly.front();
313 for (
size_t i = 0; i < a_io.
m_polys.size(); ++i)
342 errors +=
"Error: Per polygon input is empty. No polygons to mesh.\n";
346 for (
size_t i = 0; i < a_io.
m_polys.size(); ++i)
351 std::stringstream ss;
362 std::stringstream ss;
363 ss <<
"Error: Outer polygon " <<
id <<
" is empty.\n";
372 std::stringstream ss;
373 ss <<
"Error: Inner polygon " << j <<
" of outer polygon " <<
id <<
" is empty.\n";
381 std::stringstream ss;
382 ss <<
"Error: Polygon patch corners for polygon " <<
id <<
" is size " 383 << polyInput.
m_polyCorners.size() <<
". It must be size 0 or 3.\n";
412 std::string& a_errors)
const 416 std::vector<const Pt3d*> segments;
417 std::vector<SegmentLocation> segmentLocs;
418 for (
int i = 0; i < (int)a_io.
m_polys.size(); ++i)
423 segments.push_back(
nullptr);
431 for (
int j = 0; j < (int)outerPoly.size(); ++j)
433 segments.push_back(&outerPoly[j]);
437 segments.push_back(&outerPoly[0]);
445 segments.push_back(
nullptr);
449 for (
int k = 0; k < (int)inputPoly.
m_insidePolys.size(); ++k)
454 segments.push_back(
nullptr);
460 for (
int m = 0; m < (int)innerPoly.size(); ++m)
462 segments.push_back(&innerPoly[m]);
466 segments.push_back(&innerPoly[0]);
473 double xi, yi, zi1, zi2, tol(
gmXyTol());
474 size_t size = segments.size();
477 for (
size_t i = 1; i < segments.size(); ++i)
480 if (segments[i] ==
nullptr)
485 const Pt3d* one1 = segments[i - 1];
486 const Pt3d* one2 = segments[i];
494 for (
size_t j = i + 1; j < size; ++j)
497 if (segments[j] ==
nullptr)
502 const Pt3d* two1 = segments[j - 1];
503 const Pt3d* two2 = segments[j];
513 std::stringstream ss;
523 s = (boost::format(
"Error: Input polygon segments intersect." 524 " The segment defined by points %d and %d" 525 " of outer polygon %d" 526 " intersects with the segment defined by points %d and %d" 527 " of outer polygon %d.\n") %
534 s = (boost::format(
"Error: Input polygon segments intersect." 535 " The segment defined by points %d and %d" 536 " of outer polygon %d" 537 " intersects with the segment defined by points %d and %d" 538 " of inner polygon %d of outer polygon %d.\n") %
548 s = (boost::format(
"Error: Input polygon segments intersect." 549 " The segment defined by points %d and %d" 550 " of inner polygon %d of outer polygon %d" 551 " intersects with the segment defined by points %d and %d" 552 " of outer polygon %d.\n") %
559 s = (boost::format(
"Error: Input polygon segments intersect." 560 " The segment defined by points %d and %d" 561 " of inner polygon %d of outer polygon %d" 562 " intersects with the segment defined by points %d and %d" 563 " of inner polygon %d of outer polygon %d.\n") %
588 const Pt3d& a_two2)
const 593 if (twoMn.
x > a_oneMx.
x)
597 if (twoMx.
x < a_oneMn.
x)
601 if (twoMn.
y > a_oneMx.
y)
605 if (twoMx.
y < a_oneMn.
y)
619 const VecInt& a_triangles,
625 const int VTK_TRI(5);
630 if (!a_triangles.empty())
632 cellCount = (int)a_triangles.size() / 3;
633 cells.reserve(cellCount * 5);
634 for (
size_t i = 0; i < a_triangles.size(); i += 3)
636 cells.push_back(VTK_TRI);
638 cells.push_back(a_triangles[i + 0]);
639 cells.push_back(a_triangles[i + 1]);
640 cells.push_back(a_triangles[i + 2]);
646 while (i < cells.size())
650 int npts = cells[i++];
656 if ((*m_pts).empty())
658 std::pair<std::pair<double, double>,
int> pd;
659 for (
size_t i = 0; i < a_points.size(); ++i)
661 pd.first.first = a_points[i].x;
662 pd.first.second = a_points[i].y;
667 m_pts->swap(a_points);
673 int oldNumPts = (int)(*m_pts).size();
699 std::pair<std::pair<double, double>,
int> pd;
701 for (
size_t i = 0; i < a_points.size(); ++i)
703 pd.first.first = a_points[i].x;
704 pd.first.second = a_points[i].y;
705 pd.second = (int)
m_pts->size();
710 m_pts->push_back(a_points[i]);
714 a_oldDups.push_back(it->second);
715 a_newDups.push_back((
int)i);
737 VecInt newPtsIdx(a_numNewPts, -1);
738 if (a_newDups.empty())
740 std::iota(newPtsIdx.begin(), newPtsIdx.end(), a_oldNumPts);
745 for (
size_t i = 0; i < a_newDups.size(); ++i)
747 newPtsIdx[a_newDups[i]] = a_oldDups[i];
751 int cnt(a_oldNumPts);
752 for (
size_t i = 0; i < newPtsIdx.size(); ++i)
754 if (newPtsIdx[i] < 0)
763 for (
size_t i = 1; i < a_cells.size(); ++i)
765 int nPts = a_cells[i];
766 for (
int j = 1; j <= nPts; ++j)
768 a_cells[i + j] = newPtsIdx[a_cells[i + j]];
790 SetPt3d setPts(a_usedPts.begin(), a_usedPts.end());
791 SetPt3d::iterator itEnd = setPts.end();
793 for (
size_t i = 0; i < a_io.
m_refPts.size(); ++i)
795 if (setPts.find(a_io.
m_refPts[i].m_pt) == itEnd)
797 std::stringstream ss;
798 ss <<
"(" << a_io.
m_refPts[i].m_pt.x <<
", " << a_io.
m_refPts[i].m_pt.y <<
")";
799 strLoc.push_back(ss.str());
805 "The following refine points were not included by the meshing process " 806 "because the points are located outside of all polygons.";
807 for (
size_t i = 0; i < strLoc.size(); ++i)
809 msg +=
"\n" + strLoc[i];
874 poly.
m_outPoly = {{0, 0, 0}, {100, 0, 0}, {100, 10, 0}, {0, -10, 0}};
882 bool rv = mesher->MeshIt(input);
884 TS_ASSERT_EQUALS(rv,
false);
886 std::string expected =
887 "---Error: Input polygon segments intersect. The segment defined by points 0 and 1 of outer " 888 "polygon 0 intersects with the segment defined by points 2 and 3 of outer polygon 0.\n" 891 TS_ASSERT_EQUALS(expected, errors);
912 poly.
m_outPoly = {{0, 0, 0}, {100, 0, 0}, {100, 100, 0}, {0, 100, 0}};
913 poly.
m_insidePolys.push_back({{10, 50}, {90, 50}, {90, 90}, {10, 10}});
921 bool rv = mesher->MeshIt(input);
923 TS_ASSERT_EQUALS(rv,
false);
925 std::string expected =
926 "---Error: Input polygon segments intersect. The segment defined by points 0 and 1 of inner " 927 "polygon 0 of outer polygon 0 intersects with the segment defined by points 2 and 3 of inner " 928 "polygon 0 of outer polygon 0.\n" 931 TS_ASSERT_EQUALS(expected, errors);
951 poly.
m_outPoly = {{0, 0, 0}, {100, 0, 0}, {100, 100, 0}, {0, 100, 0}};
952 poly.
m_insidePolys.push_back({{90, 10}, {110, 10}, {110, 20}, {90, 20}});
960 bool rv = mesher->MeshIt(input);
962 TS_ASSERT_EQUALS(rv,
false);
964 std::string expected =
965 "---Error: Input polygon segments intersect. The segment defined by points 1 and 2 of outer " 966 "polygon 0 intersects with the segment defined by points 0 and 1 of inner polygon 0 of outer " 968 "Error: Input polygon segments intersect. The segment defined by points 1 and 2 of outer " 969 "polygon 0 intersects with the segment defined by points 2 and 3 of inner polygon 0 of outer " 973 TS_ASSERT_EQUALS(expected, errors);
995 poly.
m_outPoly = {{0, 0, 0}, {0, 100, 0}, {100, 100, 0}, {100, 0, 0}};
997 poly.
m_outPoly = {{10, 10, 0}, {10, 110, 0}, {110, 110, 0}, {110, 10, 0}};
1005 bool rv = mesher->MeshIt(input);
1007 TS_ASSERT_EQUALS(rv,
false);
1009 std::string expected =
1010 "---Error: Input polygon segments intersect. The segment defined by points 1 and 2 of outer " 1011 "polygon 0 intersects with the segment defined by points 0 and 1 of outer polygon 1.\n" 1012 "Error: Input polygon segments intersect. The segment defined by points 2 and 3 of outer " 1013 "polygon 0 intersects with the segment defined by points 3 and 0 of outer polygon 1.\n" 1016 TS_ASSERT_EQUALS(expected, errors);
1038 poly.
m_outPoly = {{0, 0, 0}, {100, 0, 0}, {100, 100, 0}, {0, 100, 0}};
1039 poly.
m_insidePolys.push_back({{10, 10}, {60, 10}, {60, 60}, {10, 60}});
1040 poly.
m_insidePolys.push_back({{40, 40}, {90, 40}, {90, 90}, {40, 90}});
1041 input.
m_polys.push_back(poly);
1048 bool rv = mesher->MeshIt(input);
1050 TS_ASSERT_EQUALS(rv,
false);
1052 std::string expected =
1053 "---Error: Input polygon segments intersect. The segment defined by points 1 and 2 of inner " 1054 "polygon 0 of outer polygon 0 intersects with the segment defined by points 0 and 1 of inner " 1055 "polygon 1 of outer polygon 0.\n" 1056 "Error: Input polygon segments intersect. The segment defined by points 2 and 3 of inner " 1057 "polygon 0 of outer polygon 0 intersects with the segment defined by points 3 and 0 of inner " 1058 "polygon 1 of outer polygon 0.\n" 1061 TS_ASSERT_EQUALS(expected, errors);
void testCheckForIntersections5()
Tests checking for bad input: 2 inner polys overlap.
bool gmIntersectLineSegmentsWithTol(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2, double *xi, double *yi, double *zi1, double *zi2, double tol)
int m_poly
Index of polygon in MeMultiPolyMesherIo::m_polys.
Creates a mesh from multiple polygons that will honor polygon boundaries.
std::vector< int > VecInt
void AddUniquePoints(const VecPt3d &a_points, VecInt &a_oldDups, VecInt &a_newDups)
Adds new mesh points that aren't in old mesh, to old mesh.
virtual void CheckForIntersections(const MeMultiPolyMesherIo &a_io, std::string &a_errors) const override
Checks input to see if anything intersects. Will not catch polys entirely inside or outside of where ...
std::vector< MePolyInput > m_polys
Required (but some data is optional). Inputs for each polygon.
int m_polySeg
Index of segment in MePolyInput::m_outPoly.
boost::unordered_map< std::pair< double, double >, int > m_ptHash
hashes points
void testCheckForIntersections3()
Tests checking for bad input: inner poly intersects outer poly.
bool ExtentsOverlap(const Pt3d &oneMn, const Pt3d &oneMx, const Pt3d &two1, const Pt3d &two2) const
Given extents of one segment, and another segment, return true if the extents of the two segments ove...
std::string STRstd(double a_value, int a_n, int width, int flags)
bool gmEqualPointsXY(double x1, double y1, double x2, double y2, double tolerance)
std::vector< std::string > VecStr
MeMultiPolyMesherImpl()
Constructor.
bool m_checkTopology
Optional. If true, checks polygon input topology for errors.
int m_cellCount
Number of cells.
void RenumberNewMesh(int a_oldNumPts, size_t a_numNewPts, const VecInt &a_oldDups, const VecInt &a_newDups, VecInt &a_cells) const
Renumber points referred to in the new mesh to remove duplicate points and to start new mesh numberin...
void AppendNewCells(const VecInt &a_cells)
Append the new cells to the existing cells.
Struct defining the location of a polygon line segment in the list of polygons in MeMultiPolyMesherIo...
void testCreateClass()
tests creating the class
VecInt m_cellPolygons
Polygon index of each cell.
int m_inPoly
Index of inner polygon in MePolyInput::m_insidePolys.
void EnsureProperPolygonInputs(MeMultiPolyMesherIo &a_io)
Remove last point of polygon if it is the same as the first point and make sure the polygon points ar...
bool ValidateInput(const MeMultiPolyMesherIo &a_io)
Make sure the input makes sense.
void testCheckForIntersections1()
Tests checking for bad input: self-intersecting outer poly.
void AppendMesh(VecPt3d &a_points, const VecInt &a_triangles, VecInt &a_cells)
Adds new points and triangles to existing mesh, hashing points and renumbering.
std::string GetAndClearStackStr()
#define XM_ENSURE_TRUE(...)
std::vector< MeRefinePoint > m_refPts
Optional. Refine points.
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
VecPt3d m_points
The points of the resulting mesh.
bool m_returnCellPolygons
If true, returns the polygon index of each cell.
void ReportUnusedRefinePts(const MeMultiPolyMesherIo &a_io, const VecPt3d &a_usedPts)
Reports refine points that were not used.
Provides the input to meshing multiple polygons and holds the output.
int m_inPolySeg
Index of segment on inner polygon.
static boost::shared_ptr< MePolyMesher > New()
Creates a polymesher class.
SegmentLocation(int a_poly=0, int a_polySeg=0, int a_inPoly=0, int a_inPolySeg=0)
Constructor.
BSHP< VecPt3d > m_pts
Mesh points. BSHP because of PtSearch::VectorThatGrowsToSearch.
double gmPolygonArea(const Pt3d *pts, size_t npoints)
static XmLog & Instance(bool a_delete=false, XmLog *a_new=NULL)
static boost::shared_ptr< MeMultiPolyMesher > New()
Creates a class.
void gmAddToExtents(const Pt3d &a_pt, Pt3d &a_min, Pt3d &a_max)
VecInt m_cells
Mesh cells as a stream.
void testCheckForIntersections2()
Tests checking for bad input: self-intersecting inner poly.
virtual bool MeshIt(MeMultiPolyMesherIo &a_io) override
Creates a triangle mesh from the input polygons. The polygons can not overlap.
double gmXyTol(bool a_set, double a_value)
VecInt m_cells
The cells of the resulting mesh, as a stream.
void testCheckForIntersections4()
Tests checking for bad input: 2 outer polys overlap.
std::vector< Pt3d > VecPt3d