xmsmesh  1.0
MePolyMesher.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 // 2. My own header
14 
15 // 3. Standard library headers
16 #include <fstream>
17 
18 // 4. External library headers
19 #pragma warning(push)
20 #pragma warning(disable : 4512) // boost code: no assignment operator
21 #include <boost/geometry.hpp>
22 #include <boost/geometry/geometries/point_xy.hpp>
23 #include <boost/unordered_set.hpp>
24 #include <boost/unordered_map.hpp>
25 #pragma warning(pop)
26 
27 // 5. Shared code headers
28 #include <xmscore/math/math.h>
29 #include <xmscore/misc/XmConst.h>
30 #include <xmscore/misc/XmError.h>
31 #include <xmscore/misc/boost_defines.h> // BSHP
32 #include <xmscore/misc/XmLog.h>
33 #include <xmscore/stl/set.h>
48 
49 // 6. Non-shared code headers
50 
51 //----- Forward declarations ---------------------------------------------------
52 
53 //----- External globals -------------------------------------------------------
54 
55 //----- Namespace declaration --------------------------------------------------
56 
57 namespace xms
58 {
59 //----- Constants / Enumerations -----------------------------------------------
60 
61 //----- Classes / Structs ------------------------------------------------------
62 typedef boost::unordered_map<std::pair<double, double>, int> PtHash;
63 
66 {
67 public:
69  enum BoundaryEnum {
70  BE_UNVISITED = 0,
71  BE_VISITED = 1,
72  BE_OUTSIDE = 2,
73  BE_INSIDE = 4,
74  BE_ONBOUNDARY = 8
75  };
76 
78  virtual ~MePolyMesherImpl();
79 
80 public:
81  virtual bool MeshIt(const MeMultiPolyMesherIo& a_input,
82  size_t a_polyIdx,
83  VecPt3d& a_points,
84  VecInt& a_triangles,
85  VecInt& a_cells) override;
86  virtual bool MeshIt(const VecPt3d& a_outPoly,
87  const VecPt3d2d& a_inPolys,
88  double a_bias,
89  VecPt3d& a_points,
90  VecInt& a_triangles);
91 
92  virtual void GetProcessedRefinePts(std::vector<Pt3d>& a_pts) override;
93 
94  void TestWithPoints(const VecInt& a_outPoly,
95  const VecInt2d& a_inPolys,
96  const VecPt3d& a_points,
97  VecInt& a_triangles);
98 
99 private:
100  bool MeshFromInputs(std::vector<Pt3d>& a_points, VecInt& a_triangles, VecInt& a_cells);
101  void SortPoly(VecPt3d& a_outPoly);
102  bool ComputeExtents(Pt3d& a_mn, Pt3d& a_mx);
103  void ComputeTolerance();
104  void GenerateMeshPts();
106  void Triangulate();
107  void FindAllPolyPointIdxs();
108  void FindPolyPointIdxs(const VecPt3d& a_poly, VecInt& a_polyPtIdxs);
109  void AddBreaklines();
111  void AutoFixFourTrianglePts();
112  void Relax();
113  void ExportTinForDebug();
114 
115 private:
120  VecPt3d
122  BSHP<VecPt3d> m_points;
123  BSHP<TrTin> m_tin;
124  BSHP<MePolyRedistributePts>
126  BSHP<MePolyPaverToMeshPts> m_polyPaver;
127  BSHP<MeRefinePtsToPolys>
129  BSHP<MeRelaxer> m_relaxer;
131  double m_bias;
136  double m_xyTol;
137  bool m_testing;
141  BSHP<InterpBase> m_elev;
142  int m_polyId;
146  false;
147 }; // class MePolyMesherImpl
148 
149 //----- Internal functions -----------------------------------------------------
150 
151 //----- Class / Function definitions -------------------------------------------
152 
153 //------------------------------------------------------------------------------
156 //------------------------------------------------------------------------------
157 BSHP<MePolyMesher> MePolyMesher::New()
158 {
159  BSHP<MePolyMesher> polyMesher(new MePolyMesherImpl);
160  return polyMesher;
161 } // MePolyMesher::New
162 //------------------------------------------------------------------------------
164 //------------------------------------------------------------------------------
165 MePolyMesher::MePolyMesher()
166 {
167 } // MePolyMesher::MePolyMesher
168 //------------------------------------------------------------------------------
170 //------------------------------------------------------------------------------
171 MePolyMesher::~MePolyMesher()
172 {
173 } // MePolyMesher::~MePolyMesher
174 
182 //------------------------------------------------------------------------------
184 //------------------------------------------------------------------------------
185 MePolyMesherImpl::MePolyMesherImpl()
186 : MePolyMesher()
187 , m_outPoly()
188 , m_inPolys()
189 , m_points(new VecPt3d())
190 , m_tin(TrTin::New())
191 , m_redist(MePolyRedistributePts::New())
192 , m_polyPaver(MePolyPaverToMeshPts::New())
193 , m_refineToPolys(MeRefinePtsToPolys::New())
194 , m_relaxer(MeRelaxer::New())
195 , m_bias(1.0)
196 , m_outPolyPtIdxs()
197 , m_inPolyPtIdxs()
198 , m_refPtIdxs()
199 , m_xyTol(1e-9)
200 , m_testing(false)
201 , m_polyId(-1)
202 , m_seedPts()
203 {
204 } // MePolyMesherImpl::MePolyMesherImpl
205 //------------------------------------------------------------------------------
207 //------------------------------------------------------------------------------
208 MePolyMesherImpl::~MePolyMesherImpl()
209 {
210 } // MePolyMesherImpl::~MePolyMesherImpl
211 //------------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
221  size_t a_polyIdx,
222  VecPt3d& a_points,
223  VecInt& a_triangles,
224  VecInt& a_cells)
225 {
226  // reinitialize some internal classes
227  m_tin = TrTin::New();
232 
233  // outer polygons
234  const MePolyInput& polyInput = a_input.m_polys[a_polyIdx];
235 
236  if (!polyInput.m_relaxationMethod.empty())
237  {
238  m_relaxer->SetRelaxationMethod(polyInput.m_relaxationMethod);
239  m_relaxer->SetPointSizer(m_redist);
240  }
241 
242  m_polyId = polyInput.m_polyId;
243  m_outPoly = polyInput.m_outPoly;
244  m_seedPts = polyInput.m_seedPoints;
246 
247  // holes inside the outer polygons
248  m_inPolys = polyInput.m_insidePolys;
249  // bias term
250  m_bias = polyInput.m_bias;
251  // refine pts
252  m_refineToPolys->SetRefinePoints(a_input.m_refPts, m_xyTol);
253  m_refineToPolys->RefPtsAsPolys(polyInput.m_polyId, m_outPoly, m_inPolys, m_refPtPolys,
255  // size function
256  if (!polyInput.m_sizeFunction)
257  {
258  VecPt3d2d inPolys(m_inPolys);
259  inPolys.insert(inPolys.end(), m_refPtPolys.begin(), m_refPtPolys.end());
260  m_redist->SetSizeFuncFromPoly(m_outPoly, inPolys, m_bias);
261  }
262  else
263  {
264  m_redist->SetSizeFunc(polyInput.m_sizeFunction);
265  }
266  if (polyInput.m_constSizeFunction != -1.0)
267  {
268  m_redist->SetConstantSizeFunc(polyInput.m_constSizeFunction);
269  if (polyInput.m_constSizeBias != -1.0)
270  m_redist->SetConstantSizeBias(polyInput.m_constSizeBias);
271  }
272  m_polyPaver->SetRedistributor(m_redist);
273 
274  // patch
275  if (!polyInput.m_polyCorners.empty())
276  m_polyCorners = polyInput.m_polyCorners;
277  else
279 
280  m_elev = polyInput.m_elevFunction;
283  return MeshFromInputs(a_points, a_triangles, a_cells);
284 } // MePolyMesherImpl::MeshIt
285 //------------------------------------------------------------------------------
294 //------------------------------------------------------------------------------
295 bool MePolyMesherImpl::MeshIt(const VecPt3d& a_outPoly,
296  const VecPt3d2d& a_inPolys,
297  double a_bias,
298  VecPt3d& a_points,
299  VecInt& a_triangles)
300 {
301  m_outPoly = a_outPoly;
304  m_inPolys = a_inPolys;
305  m_bias = a_bias;
306  VecInt cells;
307  return MeshFromInputs(a_points, a_triangles, cells);
308 } // MePolyMesherImp::MeshIt
309 //------------------------------------------------------------------------------
312 //------------------------------------------------------------------------------
314 {
315  // Find the lower left most point
316  double minX(XM_DBL_HIGHEST), minY(XM_DBL_HIGHEST);
317  size_t minIdx = 0;
318  for (size_t i = 0; i < a_outPoly.size(); ++i)
319  {
320  if (a_outPoly[i].x < minX)
321  {
322  minX = a_outPoly[i].x;
323  minY = a_outPoly[i].y;
324  minIdx = i;
325  }
326  else if (EQ_TOL(a_outPoly[i].x, minX, m_xyTol))
327  {
328  if (a_outPoly[i].y < minY)
329  { // X is same as min. Check y
330  minX = a_outPoly[i].x;
331  minY = a_outPoly[i].y;
332  minIdx = i;
333  }
334  }
335  }
336  std::rotate(a_outPoly.begin(), a_outPoly.begin() + minIdx, a_outPoly.end());
337 } // MePolyMesherImpl::SortPoly
338 //------------------------------------------------------------------------------
342 //------------------------------------------------------------------------------
343 void MePolyMesherImpl::GetProcessedRefinePts(std::vector<Pt3d>& a_pts)
344 {
345  a_pts.resize(0);
346  a_pts = m_refMeshPts;
347  a_pts.insert(a_pts.end(), m_refPtsTooClose.begin(), m_refPtsTooClose.end());
348 } // MePolyMesherImpl::GetProcessedRefinePts
349 //------------------------------------------------------------------------------
356 //------------------------------------------------------------------------------
357 bool MePolyMesherImpl::MeshFromInputs(VecPt3d& a_points, VecInt& a_triangles, VecInt& a_cells)
358 {
359  try
360  {
361  GenerateMeshPts();
362  if (m_cells.empty())
363  { // paving
364  while (m_tin->Triangles().empty())
365  {
367  Triangulate();
370  AddBreaklines();
372  Relax();
373  }
374  // Re-add breaklines and delete outer polys because relaxing can swap edges
375  AddBreaklines();
377  a_triangles.swap(m_tin->Triangles());
378  a_cells.resize(0);
379  }
380  else
381  { // patch
382  a_cells.swap(m_cells);
383  a_triangles.resize(0);
384  }
385  a_points.swap(*m_points);
386  m_tin->Clear();
387  m_polyCorners.clear();
388  if (m_elev)
389  for (Pt3d& p : a_points)
390  p.z = (double)m_elev->InterpToPt(p);
391  }
392  catch (std::exception& e)
393  {
394  std::string msg = e.what();
396  XM_LOG(xmlog::error, msg);
397  return false;
398  }
399  return true;
400 } // MePolyMesherImpl::MeshFromInputs
401 //------------------------------------------------------------------------------
408 //------------------------------------------------------------------------------
410  const VecInt2d& a_inPolys,
411  const VecPt3d& a_points,
412  VecInt& a_triangles)
413 {
414  m_testing = true;
415 
416  // Convert polys from idxs to Pt3d
417  VecPt3d outPoly(a_outPoly.size());
418  for (size_t i = 0; i < a_outPoly.size(); ++i)
419  {
420  outPoly[i] = a_points[a_outPoly[i]];
421  }
422  VecPt3d2d inPolys(a_inPolys.size());
423  for (size_t j = 0; j < a_inPolys.size(); ++j)
424  {
425  inPolys[j].resize(a_inPolys[j].size());
426  for (size_t i = 0; i < a_inPolys[j].size(); ++i)
427  {
428  inPolys[j][i] = a_points[a_inPolys[j][i]];
429  }
430  }
431 
432  *m_points = a_points;
433  VecPt3d points;
434  MeshIt(outPoly, inPolys, 1.0, points, a_triangles);
435 } // MePolyMesherImpl::TestWithPoints
436 //------------------------------------------------------------------------------
441 //------------------------------------------------------------------------------
443 {
444  if (!m_outPoly.empty())
445  {
446  a_mn = XM_DBL_HIGHEST;
447  a_mx = XM_DBL_LOWEST;
448  for (size_t i = 0; i < m_outPoly.size(); ++i)
449  {
450  gmAddToExtents(m_outPoly[i], a_mn, a_mx);
451  }
452  return true;
453  }
454  return false;
455 } // MePolyMesherImpl::ComputeExtents
456 //------------------------------------------------------------------------------
458 //------------------------------------------------------------------------------
460 {
461  if (ComputeExtents(m_min, m_max))
462  {
464  }
465 } // MePolyMesherImpl::ComputeTolerance
466 //------------------------------------------------------------------------------
469 //------------------------------------------------------------------------------
471 {
472  if (m_testing)
473  return;
474  if (!m_polyCorners.empty())
475  {
476  if (!m_seedPts.empty())
477  {
479  "Seed points specified with \"Patch option.\" "
480  "These points will be ignored.");
481  }
482  BSHP<MePolyPatcher> patcher(MePolyPatcher::New());
483  patcher->MeshIt(m_polyId, m_outPoly, m_polyCorners, m_xyTol, *m_points, m_cells);
484  }
485  else
486  {
487  // add the refine point polygons
488  VecPt3d2d inPolys(m_inPolys);
489  inPolys.insert(inPolys.end(), m_refPtPolys.begin(), m_refPtPolys.end());
490 
491  // if the user provided the seed points then we don't need to pave
492  if (!m_seedPts.empty())
493  {
494  // add the outer poly and the inner poly points
495  *m_points = m_seedPts;
496  m_points->insert(m_points->end(), m_outPoly.begin(), m_outPoly.end());
497  for (auto& in : inPolys)
498  m_points->insert(m_points->end(), in.begin(), in.end());
499  }
500  else
501  {
502  // generate mesh points
503  m_polyPaver->PolyToMeshPts(m_outPoly, inPolys, m_bias, m_xyTol, *m_points);
504  }
505 
506  // add the mesh refine points
507  m_points->insert(m_points->end(), m_refMeshPts.begin(), m_refMeshPts.end());
508  }
509 } // MePolyMesherImpl::GenerateMeshPts
510 //------------------------------------------------------------------------------
512 //------------------------------------------------------------------------------
514 {
515  if (m_boundPtsToRemove.empty())
516  return;
517  boost::unordered_set<std::pair<double, double>> ptSet;
518  for (auto& p : m_boundPtsToRemove)
519  {
520  std::pair<double, double> pp(p.x, p.y);
521  ptSet.insert(pp);
522  }
523  auto itEnd = ptSet.end();
524  for (size_t i = m_outPoly.size(); i > 0; --i)
525  {
526  size_t ix = i - 1;
527  std::pair<double, double> pp(m_outPoly[ix].x, m_outPoly[ix].y);
528  auto it = ptSet.find(pp);
529  if (it != itEnd)
530  {
531  m_outPoly.erase(m_outPoly.begin() + ix);
532  }
533  }
534  VecPt3d& pts(*m_points);
535  for (size_t i = pts.size(); i > 0; --i)
536  {
537  size_t ix = i - 1;
538  std::pair<double, double> pp(pts[ix].x, pts[ix].y);
539  auto it = ptSet.find(pp);
540  if (it != itEnd)
541  {
542  pts.erase(pts.begin() + ix);
543  }
544  }
545 } // MePolyMesherImpl::ProcessBoundaryPtsFlaggedToRemove
546 //------------------------------------------------------------------------------
548 //------------------------------------------------------------------------------
550 {
551  m_tin->SetPoints(m_points);
552  TrTriangulatorPoints client(*m_points.get(), m_tin->Triangles(), &m_tin->TrisAdjToPts());
553  bool rv = client.Triangulate();
554  if (!rv)
555  {
556  throw std::runtime_error("Error triangulating mesh points.");
557  }
558 } // MePolyMesherImpl::Triangulate
559 //------------------------------------------------------------------------------
561 //------------------------------------------------------------------------------
563 {
564 #if _DEBUG
565  std::ofstream ofs;
566  ofs.open("C:\\temp\\TrBreaklineAdder.tin");
567  m_tin->ExportTinFile(ofs);
568 #endif
569 } // MePolyMesherImpl::ExportTinForDebug
570 //------------------------------------------------------------------------------
572 //------------------------------------------------------------------------------
574 {
575  BSHP<TrBreaklineAdder> adder = TrBreaklineAdder::New();
576  adder->SetTin(m_tin, m_xyTol);
577 
578  // Close the polys
579  VecInt outPolyPtIdxs = m_outPolyPtIdxs;
580  outPolyPtIdxs.push_back(m_outPolyPtIdxs.front());
581  VecInt2d inPolyPtIdxs = m_inPolyPtIdxs;
582  for (size_t i = 0; i < m_inPolyPtIdxs.size(); ++i)
583  {
584  inPolyPtIdxs[i].push_back(m_inPolyPtIdxs[i].front());
585  }
586 
587  adder->AddBreakline(outPolyPtIdxs);
588  adder->AddBreaklines(inPolyPtIdxs);
589 } // MePolyMesherImpl::AddBreaklines
590 //------------------------------------------------------------------------------
596 //------------------------------------------------------------------------------
598 {
599  // Close the polygons by making the last point the same as the first and
600  // create one 2D array for outer and all inner
601  VecInt2d allPolys;
602  allPolys.push_back(m_outPolyPtIdxs);
603  allPolys.back().push_back(m_outPolyPtIdxs.front());
604  for (size_t i = 0; i < m_inPolyPtIdxs.size(); ++i)
605  {
606  allPolys.push_back(m_inPolyPtIdxs[i]);
607  allPolys.back().push_back(m_inPolyPtIdxs[i].front());
608  }
609 
610  BSHP<TrOuterTriangleDeleter> deleter = TrOuterTriangleDeleter::New();
611  deleter->Delete(allPolys, m_tin);
612 } // MePolyMesherImpl::DeleteTrianglesOutsidePolys
613 //------------------------------------------------------------------------------
616 //------------------------------------------------------------------------------
618 {
620  return;
621  BSHP<TrAutoFixFourTrianglePts> fixer = TrAutoFixFourTrianglePts::New();
622 
623  // can't delete boundary pts or refine points
624  VecInt noDeletePts(m_outPolyPtIdxs);
625  for (size_t i = 0; i < m_inPolys.size(); ++i)
626  {
627  for (auto& ix : m_inPolyPtIdxs[i])
628  noDeletePts.push_back(ix);
629  }
630  for (auto& ix : m_refPtIdxs)
631  noDeletePts.push_back(ix);
632  fixer->SetUndeleteablePtIdxs(noDeletePts);
633 
634  size_t ptsBefore(m_tin->Points().size());
635  fixer->Fix(m_tin);
636  if (ptsBefore != m_tin->Points().size())
638 } // MePolyMesherImpl::AutoFixFourTrianglePts
639 //------------------------------------------------------------------------------
641 //------------------------------------------------------------------------------
643 {
644  // if the user specified the seed points then do not relax
645  if (!m_seedPts.empty())
646  return;
647 
648  // Put polygons into one vector
649  VecInt fixedPoints(m_outPolyPtIdxs.begin(), m_outPolyPtIdxs.end());
650  for (size_t i = 0; i < m_inPolyPtIdxs.size(); ++i)
651  {
652  fixedPoints.insert(fixedPoints.end(), m_inPolyPtIdxs[i].begin(), m_inPolyPtIdxs[i].end());
653  }
654  // add refine points to the fixed
655  fixedPoints.insert(fixedPoints.end(), m_refPtIdxs.begin(), m_refPtIdxs.end());
656  m_relaxer->Relax(fixedPoints, m_tin);
657 } // MePolyMesherImpl::Relax
658 //------------------------------------------------------------------------------
662 //------------------------------------------------------------------------------
664 {
665  m_ptHash.clear();
666  std::pair<std::pair<double, double>, int> pd;
667  size_t nPts(m_points->size());
668  Pt3d* pts(nPts > 0 ? &(*m_points)[0] : NULL);
669  for (size_t i = 0; i < nPts; ++i)
670  {
671  pd.first.first = pts[i].x;
672  pd.first.second = pts[i].y;
673  pd.second = (int)i;
674  m_ptHash.insert(pd);
675  }
677  m_inPolyPtIdxs.resize(m_inPolys.size(), VecInt());
678  for (size_t i = 0; i < m_inPolys.size(); ++i)
679  {
681  }
682  // get the refine point idxs
683  m_refPtIdxs.resize(0);
685  for (size_t i = 0; i < m_refPtPolys.size(); ++i)
686  {
687  VecInt tmp;
689  m_refPtIdxs.insert(m_refPtIdxs.end(), tmp.begin(), tmp.end());
690  }
691 } // MePolyMesherImpl::FindAllPolyPointIdxs
692 //------------------------------------------------------------------------------
696 //------------------------------------------------------------------------------
697 void MePolyMesherImpl::FindPolyPointIdxs(const VecPt3d& a_poly, VecInt& a_polyPtIdxs)
698 {
699  a_polyPtIdxs.resize(0);
700  size_t nPts(a_poly.size());
701  auto itEnd = m_ptHash.end();
702  auto it = m_ptHash.begin();
703  std::pair<double, double> pd;
704  for (size_t i = 0; i < nPts; ++i)
705  {
706  pd.first = a_poly[i].x;
707  pd.second = a_poly[i].y;
708  it = m_ptHash.find(pd);
709  if (it == itEnd)
710  {
711  throw std::runtime_error("Polygon point not in mesh points.");
712  }
713  else
714  a_polyPtIdxs.push_back(it->second);
715  }
716 } // MePolyMesherImpl::FindPolyPointIdxs
717 
718 } // namespace xms
719 
720 #if CXX_TEST
721 // UNIT TESTS
724 
726 
728 
729 //----- Namespace declaration --------------------------------------------------
730 
731 // namespace xms {
732 using namespace xms;
733 
734 namespace
735 {
736 //------------------------------------------------------------------------------
738 //------------------------------------------------------------------------------
739 static VecPt3d iArrayToVecPt3d(int* a_array, int a_size)
740 {
741  VecPt3d v(a_size / 2);
742  for (int i = 0; i < a_size; i += 2)
743  {
744  v[i / 2].x = a_array[i];
745  v[i / 2].y = a_array[i + 1];
746  }
747  return v;
748 } // iArrayToVecPt3d
749 
750 } // namespace
751 
756 //------------------------------------------------------------------------------
760 // Before
761 //
762 // 10- 17-----18------19------20------21
763 // | |\ 8 /|\ 11 /|\ 22 / \ 26 /|
764 // | | \ / | \ / | \ / \ //|
765 // | | \ / | \ /30|23\ / 27 \ / /|
766 // 5- |6 13 12|9 14 | 15------16 /|
767 // | | / \ | /|\ | / \ 25 /|28/|
768 // | | / \ | / | \ | / \ / | / |
769 // | |/ 7 \|/ | \|/ 24 \ /29| / |
770 // 0- 9------10 10|3 11------12 | / |
771 // | |\ 13 / \ | / \ 15 / \ |/ |
772 // | | \ / \ | / \ / \ |/ |
773 // | | \ / 5 \|/ 16 \ / 21 \|/ |
774 // -5- | 0 5-------6-------7-------8 18|
775 // | | / \ 4 / \ 14 / \ 19 / \ |
776 // | | / \ / \ / \ / \ |
777 // | |/ 1 \ / 2 \ / 20 \ / 17 \|
778 // -10- 0-------1-------2-------3-------4
779 //
780 // |-------|-------|-------|-------|
781 // 0 10 20 30 40
782 //
783 // After swapping
784 //
785 // 10- 17-----18------19------20------21
786 // | |\ 8 / \ 11 /|\ 22 / \ 26 /|
787 // | | \ / \ / | \ / \ //|
788 // | | \ / 12 \ /30|23\ / 27 \ / /|
789 // 5- |6 13------14 | 15------16 /|
790 // | | /|\ 9 /|\ | /|\ 25 /|28/|
791 // | | / | \ / | \ | / | \ / | / |
792 // | |/ | \ / | \|/ |24\ /29| / |
793 // 0- 9 13|7 10 10|3 11 15| 12 | / |
794 // | |\ | / \ | / \ | / \ |/ |
795 // | | \ | / \ | / \ | / \ |/ |
796 // | | \|/ 5 \|/ 16 \|/ 21 \|/ |
797 // -5- | 0 5-------6-------7-------8 18|
798 // | | / \ 4 / \ 14 / \ 19 / \ |
799 // | | / \ / \ / \ / \ |
800 // | |/ 1 \ / 2 \ / 20 \ / 17 \|
801 // -10- 0-------1-------2-------3-------4
802 //
803 // |-------|-------|-------|-------|
804 // 0 10 20 30 40
805 //
806 // After removing triangles (*** means a hole)
807 //
808 // 10- 17-----18------19------20------21
809 // | |\ 7 / \ 9 /|\ 17 / \ 21 /
810 // | | \ / \ / | \ / \ /
811 // | | \ / 10 \ /24|18\ / 22 \ /
812 // 5- |6 13------14 | 15------16
813 // | | /|******/|\ | /|\ 20 /|
814 // | | / |*****/ | \ | /*| \ / |
815 // | |/ |****/ | \|/**|19\ /23|
816 // 0- 9 11|**10 8|3 11***| 12 |
817 // | |\ |**/ \ | /****| / \ |
818 // | | \ |*/ \ | /*****| / \ |
819 // | | \|/ 5 \|/******|/ 16 \|
820 // -5- | 0 5-------6-------7-------8
821 // | | / \ 4 / \ 12 / \ 14 / \
822 // | | / \ / \ / \ / \
823 // | |/ 1 \ / 2 \ / 15 \ / 13 \
824 // -10- 0-------1-------2-------3-------4
825 //
826 // |-------|-------|-------|-------|
827 // 0 10 20 30 40
829 //------------------------------------------------------------------------------
831 {
832  // Set up tin
833  int meshPtsA[] = {0, -10, 10, -10, 20, -10, 30, -10, 40, -10, 5, -5, 15, -5, 25,
834  -5, 35, -5, 0, 0, 10, 0, 20, 0, 30, 0, 5, 5, 15, 5,
835  25, 5, 35, 5, 0, 10, 10, 10, 20, 10, 30, 10, 40, 10};
836  VecPt3d points = iArrayToVecPt3d(meshPtsA, 44);
837 
838  // Set up polygons
839  int outPolyA[] = {9, 17, 18, 19, 20, 21, 16, 8, 4, 3, 2, 1, 0};
840  VecInt outPoly(&outPolyA[0], &outPolyA[13]);
841  int inPoly1[] = {14, 13, 5, 10};
842  int inPoly2[] = {7, 15, 11, 6};
843  VecInt2d inPolys;
844  inPolys.push_back(VecInt(&inPoly1[0], &inPoly1[4]));
845  inPolys.push_back(VecInt(&inPoly2[0], &inPoly2[4]));
846 
847  // Create the mesher, set the test points, and mesh it
848 
849  BSHP<MePolyMesher> mesher = MePolyMesher::New();
850  BSHP<MePolyMesherImpl> mesherImp = BDPC<MePolyMesherImpl>(mesher);
851  VecInt triangles;
852  mesherImp->TestWithPoints(outPoly, inPolys, points, triangles);
853 
854  // Verify triangles after
855  int trisA[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 5, 6, 10, 9,
856  13, 17, 17, 13, 18, 14, 10, 6, 18, 14, 19, 14, 18, 13, 9, 5, 13, 6, 2,
857  7, 3, 4, 8, 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20, 15, 19, 11,
858  12, 15, 7, 15, 12, 16, 20, 16, 21, 16, 20, 15, 12, 8, 16, 11, 19, 14};
859  VecInt trisAfter(&trisA[0], &trisA[75]);
860  TS_ASSERT_EQUALS(trisAfter, triangles);
861 
862 } // MePolyMesherUnitTests::test1
863 
864 //} // namespace xms
865 
866 #endif // CXX_TEST
double m_xyTol
xy tolerance used in geometric comparisons
static boost::shared_ptr< TrBreaklineAdder > New()
double m_constSizeBias
Optional. Transition factor for constant size function.
Redistributes the point locations on a polygon based on a size function.
void test1()
Tests the part of MePolyMesher that triangulates, adds breaklines, and removes outer triangles...
#define XM_LOG(A, B)
BSHP< MePolyPaverToMeshPts > m_polyPaver
class for paving from a polygon definition
void SortPoly(VecPt3d &a_outPoly)
Start polygon with lower left most point so results are consistent.
std::vector< int > VecInt
void Relax()
Relaxes the mesh points for better element quality.
std::vector< MePolyInput > m_polys
Required (but some data is optional). Inputs for each polygon.
static BSHP< MeRefinePtsToPolys > New()
Creates a new instance of this class.
Utilities related to a VTK unstructured grid (from shared1\UGridUtils.cpp)
BSHP< InterpBase > m_elev
interpolator to assign elevations to mesh points
static BSHP< MePolyRedistributePts > New()
Creates an instance of this class.
int m_polyId
id of the polygon
VecPt3d2d m_insidePolys
Optional. Inner polygons (holes). Counter clockwise. 1st pt != last.
static BSHP< MePolyPatcher > New()
Creates a new instance of this class.
VecPt3d m_boundPtsToRemove
boundary points to remove after the paving process is complete
Creates polygon from refine point information.
void TestWithPoints(const VecInt &a_outPoly, const VecInt2d &a_inPolys, const VecPt3d &a_points, VecInt &a_triangles)
Used only for testing. Test the class by supplying the polygons and mesh points.
static BSHP< MePolyPaverToMeshPts > New()
Creates a new instance of this class.
Pt3d m_max
max xy bound
boost::unordered_map< std::pair< double, double >, int > PtHash
typdef for a short name
BSHP< InterpBase > m_elevFunction
Optional. Elevation function for interpolating z coordinate of mesh points.
BSHP< TrTin > m_tin
triangles that become mesh elements
Fills a polygon with a mesh (points and cells). Honors the polygon boundary.
Definition: MePolyMesher.h:39
static BSHP< MeRelaxer > New()
Creates a new instance of the class.
Definition: MeRelaxer.cpp:559
VecPt3d2d m_inPolys
inside boundaries or holes in polygon
double m_constSizeFunction
Optional. Constant value size function.
std::vector< VecInt > VecInt2d
void ProcessBoundaryPtsFlaggedToRemove()
Remove boundary points.
double m_bias
factor that affects how quickly the size of elements transitions in the mesh
void meModifyMessageWithPolygonId(int a_polyId, std::string &a_msg)
Prepends the polygon id as part of an error messge.
PtHash m_ptHash
hash for point locations
Pt3d m_min
min xy bound
void FindPolyPointIdxs(const VecPt3d &a_poly, VecInt &a_polyPtIdxs)
See FindAllPolyPointIdxs.
static BSHP< TrTin > New()
BSHP< InterpBase > m_sizeFunction
Optional. Size function for scalar paving.
bool ComputeExtents(Pt3d &a_mn, Pt3d &a_mx)
Computes the extents (min, max) of the polygon.
bool MeshFromInputs(std::vector< Pt3d > &a_points, VecInt &a_triangles, VecInt &a_cells)
Creates the mesh from inputs that have set member variables in the class.
BSHP< MeRelaxer > m_relaxer
class for relaxing the location of mesh nodes
std::string m_relaxationMethod
virtual void GetProcessedRefinePts(std::vector< Pt3d > &a_pts) override
Gets the refine points that were inside the polygon, both points that are included in the meshing pro...
bool m_testing
flag to indicate if we are testing the class
bool m_removeInternalFourTrianglePts
flag to indicate the removal of internal pts connected to 4 triangles will occur
std::vector< MeRefinePoint > m_refPts
Optional. Refine points.
VecPt3d m_outPoly
Required. Outer polygons. Clockwise. 1st pt != last.
VecPt3d m_seedPts
user generated seed points.
virtual bool MeshIt(const MeMultiPolyMesherIo &a_input, size_t a_polyIdx, VecPt3d &a_points, VecInt &a_triangles, VecInt &a_cells) override
Perform MESH_PAVE, MESH_SPAVE, MESH_PATCH meshing on a polygon.
static BSHP< TrAutoFixFourTrianglePts > New()
bool EQ_TOL(const _T &A, const _U &B, const _V &tolerance)
VecPt3d2d m_refPtPolys
refine points
Provides the input to meshing multiple polygons and holds the output.
void DeleteTrianglesOutsidePolys()
Delete triangles outside the polygon boundary or in polygon holes.
static boost::shared_ptr< TrOuterTriangleDeleter > New()
static boost::shared_ptr< MePolyMesher > New()
Creates a polymesher class.
BSHP< MeRefinePtsToPolys > m_refineToPolys
class for creating polygon from refine point information
std::vector< VecPt3d > VecPt3d2d
void GenerateMeshPts()
Creates the points in interior of the input polygon that are used to create cells.
Creates a mesh inside a polygon.
void Triangulate()
Triangulate the mesh points.
Generates mesh node locations by paving a polygon.
VecPt3d m_refPtsTooClose
refine points that can not be honored because of distance constraints
void AutoFixFourTrianglePts()
Delete internal points that are only connected to 4 triangles and retriangulates. ...
void ExportTinForDebug()
Exports the tin for debugging purposes.
VecPt3d m_refMeshPts
refine point that have been made into mesh nodes
void gmAddToExtents(const Pt3d &a_pt, Pt3d &a_min, Pt3d &a_max)
BSHP< MePolyRedistributePts > m_redist
class for performing redistribution of points along a polyline
Meshing inputs for one polygon.
VecPt3d m_outPoly
outer boundary of polygon being meshed
BSHP< VecPt3d > m_points
resulting mesh nodes
void FindAllPolyPointIdxs()
Find the indices of the poly points among m_points. They will most likely be at the front of m_points...
VecInt m_polyCorners
corner indexes used with mesh patch generation
VecPt3d m_points
points of the triangular mesh
void ComputeTolerance()
Computes a tolerance to use based on point extents.
void AddBreaklines()
Add the polys as breaklines in the tin.
VecInt2d m_inPolyPtIdxs
indices to the mesh points that match the inner polygon boundaries
VecInt m_outPolyPtIdxs
indices to the mesh points that match the outer polygon boundary
double gmComputeXyTol(const Pt3d &a_mn, const Pt3d &a_mx)
VecInt m_cells
Cells generated by the Patcher.
Relaxes mesh points.
Definition: MeRelaxer.h:31
VecInt m_refPtIdxs
indices to points mesh point that match refine points
BoundaryEnum
enumeration for boundary processing
std::vector< Pt3d > VecPt3d