xmsmesh  1.0
TutMeshing.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
7 //------------------------------------------------------------------------------
8 
9 //----- Included files ---------------------------------------------------------
10 
11 // 1. Precompiled header
12 
13 // 2. My own header
14 
15 // 3. Standard library headers
16 
17 // 4. External library headers
18 
19 // 5. Shared code headers
20 
21 // 6. Non-shared code headers
22 
23 //----- Forward declarations ---------------------------------------------------
24 
25 //----- External globals -------------------------------------------------------
26 
27 //----- Namespace declaration --------------------------------------------------
28 
29 //----- Constants / Enumerations -----------------------------------------------
30 
31 //----- Classes / Structs ------------------------------------------------------
32 
33 //----- Internal functions -----------------------------------------------------
34 
35 //----- Class / Function definitions -------------------------------------------
36 
37 #if CXX_TEST
38 // UNIT TESTS
42 
43 #include <fstream>
44 
55 
56 namespace xms
57 {
58 //------------------------------------------------------------------------------
63 //------------------------------------------------------------------------------
64 bool tutReadMeshIoFromFile(const std::string& a_fname, MeMultiPolyMesherIo& a_io)
65 {
66  a_io = MeMultiPolyMesherIo();
67  std::fstream os(a_fname, std::fstream::in);
68  if (!os.is_open())
69  return false;
70 
71  std::string card;
72  size_t numpts;
73  Pt3d pt;
74  MePolyInput* p(nullptr);
75  while (os.good())
76  {
77  os >> card;
78  if ("END_POLYGON" == card)
79  { // do nothing
80  p = nullptr;
81  }
82  else if ("BEGIN_POLYGON" == card)
83  {
84  a_io.m_polys.push_back(MePolyInput());
85  p = &a_io.m_polys.back();
86  }
87  else if ("OUTSIDE" == card && p)
88  {
89  os >> numpts;
90  p->m_outPoly.reserve(numpts);
91  for (size_t i = 0; i < numpts; ++i)
92  {
93  os >> pt.x >> pt.y;
94  p->m_outPoly.push_back(pt);
95  }
96 
97  VecPt3d& vPoly(p->m_outPoly);
98  double area = gmPolygonArea(&vPoly[0], vPoly.size());
99  if (area > 0.0)
100  {
101  std::reverse(vPoly.begin(), vPoly.end());
102  area = gmPolygonArea(&vPoly[0], vPoly.size());
103  }
104  }
105  else if ("INSIDE" == card && p)
106  {
107  p->m_insidePolys.push_back(VecPt3d());
108  std::vector<Pt3d>& in(p->m_insidePolys.back());
109  os >> numpts;
110  in.reserve(numpts);
111  for (size_t i = 0; i < numpts; ++i)
112  {
113  os >> pt.x >> pt.y;
114  in.push_back(pt);
115  }
116 
117  VecPt3d& vPoly(in);
118  double area = gmPolygonArea(&vPoly[0], vPoly.size());
119  if (area < 0.0)
120  {
121  std::reverse(vPoly.begin(), vPoly.end());
122  area = gmPolygonArea(&vPoly[0], vPoly.size());
123  }
124  }
125  else if ("BIAS" == card && p)
126  {
127  os >> p->m_bias;
128  }
129  else if (("SIZE_FUNCTION" == card || "ELEVATION_FUNCTION" == card) && p)
130  {
131  BSHP<InterpBase> interp;
132  std::string interpType;
133  os >> interpType; // LINEAR or IDW
134  if ("LINEAR" == interpType)
135  {
136  interp = InterpLinear::New();
137  }
138  else if ("IDW" == interpType)
139  {
140  interp = InterpIdw::New();
141  }
142 
143  os >> numpts;
144  BSHP<VecPt3d> vpts(new VecPt3d());
145  VecPt3d& pts(*vpts);
146  for (int i = 0; i < (int)numpts; ++i)
147  {
148  os >> pt.x >> pt.y >> pt.z;
149  pts.push_back(pt);
150  }
151 
152  if (interp)
153  {
154  BSHP<VecInt> tris(new VecInt());
155  TrTriangulatorPoints tri(pts, *tris);
156  tri.Triangulate();
157  interp->SetPtsTris(vpts, tris);
158  if ("SIZE_FUNCTION" == card)
159  p->m_sizeFunction = interp;
160  else
161  p->m_elevFunction = interp;
162  }
163  }
164  else if ("CONST_SIZE_FUNCTION" == card && p)
165  {
166  os >> p->m_constSizeFunction >> p->m_constSizeBias;
167  }
168  else if ("PATCH_CORNERS" == card && p)
169  {
170  p->m_polyCorners.assign(3, -1);
171  os >> p->m_polyCorners[0] >> p->m_polyCorners[1] >> p->m_polyCorners[2];
172  }
173  else if ("CHECK_TOPOLOGY" == card)
174  {
175  a_io.m_checkTopology = true;
176  }
177  else if ("RETURN_CELL_POLYGONS" == card)
178  {
179  a_io.m_returnCellPolygons = true;
180  }
181  else if ("REFINE_POINTS" == card)
182  {
183  os >> numpts;
184  a_io.m_refPts.reserve(numpts);
185  MeRefinePoint rpt(Pt3d(), -1, false);
186  for (int i = 0; i < (int)numpts; ++i)
187  {
188  os >> rpt.m_pt.x >> rpt.m_pt.y >> rpt.m_size >> rpt.m_createMeshPoint;
189  a_io.m_refPts.push_back(rpt);
190  }
191  }
192  else if ("SEED_POINTS" == card)
193  {
194  os >> numpts;
195  VecPt3d& pts = p->m_seedPoints;
196  pts.assign(numpts, Pt3d());
197  for (int i = 0; i < numpts; ++i)
198  {
199  os >> pts[i].x >> pts[i].y;
200  }
201  }
202  else if ("RELAXATION_METHOD" == card)
203  {
204  std::string method;
205  os >> method;
206  p->m_relaxationMethod = method;
207  }
208  card = "";
209  }
210  return true;
211 } // tutReadMeshIoFromFile
212 //------------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
220 bool tutReadPolygons(const std::string& a_fname, VecPt3d2d& a_outside, VecPt3d3d& a_inside)
221 {
222  a_outside.resize(0);
223  a_inside.resize(0);
224 
226  if (!tutReadMeshIoFromFile(a_fname, io))
227  return false;
228  for (size_t i = 0; i < io.m_polys.size(); ++i)
229  {
230  a_outside.push_back(io.m_polys[i].m_outPoly);
231  a_inside.push_back(io.m_polys[i].m_insidePolys);
232  }
233  return true;
234 } // tutReadPolygons
235 //------------------------------------------------------------------------------
239 //------------------------------------------------------------------------------
240 void tutGenerateAndCompare2dm(MeMultiPolyMesherIo& a_io, const std::string& a_fileBase)
241 {
242  const std::string path(std::string(XMS_TEST_PATH) + "Tutorial_Meshing/");
243  std::string outFile;
244  std::string baseFile;
245  ttGetTestFilePaths(path, a_fileBase, ".2dm", baseFile, outFile);
246  {
247  std::fstream os(outFile.c_str(), std::fstream::out);
248  TS_ASSERT(!os.bad());
249  if (os.bad())
250  return;
251  BSHP<MeMultiPolyTo2dm> pm = MeMultiPolyTo2dm::New();
252  pm->Generate2dm(a_io, os, 10);
253  }
254  TS_ASSERT_TXT_FILES_EQUAL(baseFile, outFile);
255 } // tutGenerateAndCompare2dm
256 
257 } // namespace xms
258 
263 //------------------------------------------------------------------------------
266 //------------------------------------------------------------------------------
267 //------------------------------------------------------------------------------
269 //------------------------------------------------------------------------------
272 {
273  // The MePolyInput class defines a single polygon to be meshed and which
274  // consists of one outer polygon and, optionally, inner polygons and some
275  // other options.
276  xms::MePolyInput inputPoly;
277 
278  // Outer polygon points are in clockwise order. Do not repeat the first point.
279  inputPoly.m_outPoly = {
280  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
281  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
282  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
283  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
284  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
285 
286  // The MeMultiPolyMesherIo class holds all the options for generating
287  // UGrids from polygon data
289 
290  // The m_polys vector holds the polygons that will be filled with a UGrid.
291  // This case has only 1 polygon.
292  input.m_polys.push_back(inputPoly);
293 
294  // generate the mesh and check the base line
295  const std::string baseFile = "Example_SimplePolygon";
296  tutGenerateAndCompare2dm(input, baseFile);
297 } // TutMeshingIntermediateTests::test_Example_SimplePolygon
299 //------------------------------------------------------------------------------
301 //------------------------------------------------------------------------------
304 {
305  // The MePolyInput class defines a single polygon to be meshed and which
306  // consists of one outer polygon and, optionally, inner polygons and some
307  // other options.
308  xms::MePolyInput inputPoly;
309 
310  // Outer polygon points are in clockwise order. Do not repeat the first point.
311  inputPoly.m_outPoly = {
312  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
313  {0, 90}, {0, 100}, {0, 110}, {0, 120}, {0, 130}, {0, 140}, {0, 150}, {0, 160},
314  {0, 170}, {0, 180}, {0, 190}, {0, 200}, {10, 200}, {20, 200}, {30, 200}, {40, 200},
315  {50, 200}, {60, 200}, {70, 200}, {80, 200}, {90, 200}, {100, 200}, {110, 200}, {120, 200},
316  {130, 200}, {140, 200}, {150, 200}, {160, 200}, {170, 200}, {180, 200}, {190, 200}, {200, 200},
317  {200, 190}, {200, 180}, {200, 170}, {200, 160}, {200, 150}, {200, 140}, {200, 130}, {200, 120},
318  {200, 110}, {200, 100}, {200, 90}, {200, 80}, {200, 70}, {200, 60}, {200, 50}, {200, 40},
319  {200, 30}, {200, 20}, {200, 10}, {200, 0}, {190, 0}, {180, 0}, {170, 0}, {160, 0},
320  {150, 0}, {140, 0}, {130, 0}, {120, 0}, {110, 0}, {110, 10}, {110, 20}, {110, 30},
321  {110, 40}, {120, 40}, {130, 40}, {140, 40}, {150, 40}, {150, 50}, {150, 60}, {150, 70},
322  {150, 80}, {150, 90}, {150, 100}, {150, 110}, {150, 120}, {150, 130}, {150, 140}, {150, 150},
323  {140, 150}, {130, 150}, {120, 150}, {110, 150}, {100, 150}, {90, 150}, {80, 150}, {70, 150},
324  {60, 150}, {50, 150}, {50, 140}, {50, 130}, {50, 120}, {50, 110}, {50, 100}, {50, 90},
325  {50, 80}, {50, 70}, {50, 60}, {50, 50}, {50, 40}, {60, 40}, {70, 40}, {80, 40},
326  {90, 40}, {90, 30}, {90, 20}, {90, 10}, {90, 0}, {80, 0}, {70, 0}, {60, 0},
327  {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
328 
329  // The MeMultiPolyMesherIo class holds all the options for generating
330  // UGrids from polygon data
332 
333  // The m_polys vector holds the polygons that will be filled with a UGrid.
334  // This case has only 1 polygon.
335  input.m_polys.push_back(inputPoly);
336 
337  // generate the mesh and check the base line
338  const std::string baseFile = "Example_ComplexPolygon";
339  tutGenerateAndCompare2dm(input, baseFile);
340 } // TutMeshingIntermediateTests::test_Example_ComplexPolygon
342 //------------------------------------------------------------------------------
344 //------------------------------------------------------------------------------
347 {
348  // The MePolyInput class defines a single polygon to be meshed and which
349  // consists of one outer polygon and, optionally, inner polygons and some
350  // other options.
351  xms::MePolyInput inputPoly;
352 
353  // Outer polygon points are in clockwise order. Do not repeat the first point.
354  inputPoly.m_outPoly = {
355  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
356  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
357  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
358  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
359  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
360 
361  // Inner polygons are in counter clockwise order. Do not repeat the first
362  // point.
363  inputPoly.m_insidePolys.push_back(xms::VecPt3d());
364  inputPoly.m_insidePolys[0] = {{40, 40}, {50, 40}, {60, 40}, {60, 50},
365  {60, 60}, {50, 60}, {40, 60}, {40, 50}};
366 
367  // The MeMultiPolyMesherIo class holds all the options for generating
368  // UGrids from polygon data
370 
371  // The m_polys vector holds the polygons that will be filled with a UGrid.
372  // This case has only 1 polygon.
373  input.m_polys.push_back(inputPoly);
374 
375  // generate the mesh and check the base line
376  const std::string baseFile = "Example_SimplePolygonWithHole";
377  tutGenerateAndCompare2dm(input, baseFile);
378 } // TutMeshingIntermediateTests::test_Example_SimplePolygonWithHole
380 //------------------------------------------------------------------------------
382 //------------------------------------------------------------------------------
385 {
386  // The MePolyInput class defines a single polygon to be meshed and which
387  // consists of one outer polygon and, optionally, inner polygons and some
388  // other options.
389  xms::MePolyInput inputPoly;
390 
391  // Outer polygon points are in clockwise order. Do not repeat the first point.
392  inputPoly.m_outPoly = {
393  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
394  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
395  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
396  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
397  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
398 
399  // Inner polygons are in counter clockwise order. Do not repeat the first
400  // point.
401  inputPoly.m_insidePolys.push_back(xms::VecPt3d());
402  inputPoly.m_insidePolys[0] = {{50, 0}, {50, 10}, {50, 20}, {50, 10}};
403 
404  // The MeMultiPolyMesherIo class holds all the options for generating
405  // UGrids from polygon data
407 
408  // The m_polys vector holds the polygons that will be filled with a UGrid.
409  // This case has only 1 polygon.
410  input.m_polys.push_back(inputPoly);
411 
412  // generate the mesh and check the base line
413  const std::string baseFile = "Example_Breakline";
414  tutGenerateAndCompare2dm(input, baseFile);
415 } // TutMeshingIntermediateTests::test_Example_Breakline
417 //------------------------------------------------------------------------------
419 //------------------------------------------------------------------------------
422 {
423  // The MePolyInput class defines a single polygon to be meshed and which
424  // consists of one outer polygon and, optionally, inner polygons and some
425  // other options.
426  xms::MePolyInput inputPoly;
427 
428  // Outer polygon points are in clockwise order. Do not repeat the first point.
429  inputPoly.m_outPoly = {
430  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
431  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
432  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
433  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
434  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
435 
436  // The MeMultiPolyMesherIo class holds all the options for generating
437  // UGrids from polygon data
439 
440  // Refine points are specified independent of polygons. The mesher will
441  // determine the polygon that contains the point.
442  input.m_refPts.assign(3, xms::MeRefinePoint(xms::Pt3d(), -1, true));
443 
444  // specify a refine point where the point is at the cell center with
445  // a desired size of 2
446  input.m_refPts[0].m_pt = xms::Pt3d(20, 20, 0);
447  input.m_refPts[0].m_createMeshPoint = false;
448  input.m_refPts[0].m_size = 2.0;
449 
450  // specify a refine point where the point is at a mesh node with a
451  // desired size of 7
452  input.m_refPts[1].m_pt = xms::Pt3d(20, 80, 0);
453  input.m_refPts[1].m_createMeshPoint = true;
454  input.m_refPts[1].m_size = 5.0;
455 
456  // specify a "hard point"
457  input.m_refPts[2].m_pt = xms::Pt3d(80, 20, 0);
458  input.m_refPts[2].m_size = -1;
459 
460  // The m_polys vector holds the polygons that will be filled with a UGrid.
461  // This case has only 1 polygon.
462  input.m_polys.push_back(inputPoly);
463 
464  // generate the mesh and check the base line
465  const std::string baseFile = "Example_RefinePoints";
466  tutGenerateAndCompare2dm(input, baseFile);
467 } // TutMeshingIntermediateTests::test_Example_RefinePoints
469 //------------------------------------------------------------------------------
472 //------------------------------------------------------------------------------
475 {
476  const std::string path(std::string(XMS_TEST_PATH) + "Tutorial_Meshing/");
477  const std::string fname(path + "Example_MultiPolys.txt");
478  xms::VecPt3d3d inside;
479  xms::VecPt3d2d outside;
480  // Read the polygons from a text file to avoid typing out all of the
481  // coordinates
482  xms::tutReadPolygons(fname, outside, inside);
483 
484  // put the polygons into the meshing input class
486  for (size_t i = 0; i < outside.size(); ++i)
487  {
488  input.m_polys.push_back(xms::MePolyInput(outside[i], inside[i]));
489  }
490  // add refine points to the meshing input
491  xms::Pt3d p0(80, 80, 0), p1(125, 125, 0);
492  input.m_refPts.push_back(xms::MeRefinePoint(p0, -1.0, true));
493  input.m_refPts.push_back(xms::MeRefinePoint(p1, 1.0, true));
494 
495  // generate the mesh and check the base line
496  const std::string baseFile = "Example_MultiPolys";
497  tutGenerateAndCompare2dm(input, baseFile);
498 } // TutMeshingIntermediateTests::test_Example_MultiplePolygons
500 //------------------------------------------------------------------------------
502 //------------------------------------------------------------------------------
505 {
506  // The MePolyInput class defines a single polygon to be meshed and which
507  // consists of one outer polygon and, optionally, inner polygons and some
508  // other options.
509  xms::MePolyInput inputPoly;
510 
511  // Outer polygon points are in clockwise order. Do not repeat the first point.
512  inputPoly.m_outPoly = {
513  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
514  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
515  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
516  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
517  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
518 
519  // The MeMultiPolyMesherIo class holds all the options for generating
520  // UGrids from polygon data
522 
523  // The m_polys vector holds the polygons that will be filled with a UGrid.
524  // This case has only 1 polygon.
525  input.m_polys.push_back(inputPoly);
526 
527  // create a size function interpolator
528 
529  // These are the interpolator point locations. The size is specified by the
530  // "z" component of the points.
531  BSHP<xms::VecPt3d> sPts(new xms::VecPt3d());
532  *sPts = {{-10, -10, 10}, {-10, 110, 10}, {110, 110, 10}, {110, -10, 10}, {60, 70, 1}};
533  // These are the interpolator triangles.
534  // Triangles are specified as point indexes in ccw order. You can see the
535  // 4 triangles in the vector below.
536  BSHP<xms::VecInt> sTris(new xms::VecInt());
537  *sTris = {0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0};
538  // create a linear interpolator for the size function
539  BSHP<xms::InterpBase> linear(xms::InterpLinear::New());
540  // sets the points and the triangles for the interpolator
541  linear->SetPtsTris(sPts, sTris);
542  // now set the size function on the mesh generator input class
543  input.m_polys[0].m_sizeFunction = linear;
544 
545  // generate the mesh and check the base line
546  const std::string baseFile = "Example_ScalarPaving";
547  tutGenerateAndCompare2dm(input, baseFile);
548 } // TutMeshingIntermediateTests::test_Example_ScalarPaving
550 //------------------------------------------------------------------------------
552 //------------------------------------------------------------------------------
555 {
556  // The MePolyInput class defines a single polygon to be meshed and which
557  // consists of one outer polygon and, optionally, inner polygons and some
558  // other options.
559  xms::MePolyInput inputPoly;
560 
561  // Outer polygon points are in clockwise order. Do not repeat the first point.
562  inputPoly.m_outPoly = {{0, 0}, {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 60},
563  {0, 70}, {0, 80}, {0, 90}, {0, 100}, {20, 100}, {40, 100},
564  {60, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
565  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0},
566  {85, 0}, {70, 0}, {55, 0}, {40, 0}, {25, 0}, {10, 0}};
567 
568  // Specify the polygon corners. It is assumed that the first point above is
569  // one of the corners so we specify the other 3 corners.
570  inputPoly.m_polyCorners = {9, 13, 23};
571 
572  // The MeMultiPolyMesherIo class holds all the options for generating
573  // UGrids from polygon data
575 
576  // The m_polys vector holds the polygons that will be filled with a UGrid.
577  // This case has only 1 polygon.
578  input.m_polys.push_back(inputPoly);
579 
580  // generate the mesh and check the base line
581  const std::string baseFile = "Example_Patch";
582  tutGenerateAndCompare2dm(input, baseFile);
583 } // TutMeshingIntermediateTests::test_Example_Patch
585 //------------------------------------------------------------------------------
587 //------------------------------------------------------------------------------
590 {
591  // The MePolyInput class defines a single polygon to be meshed and which
592  // consists of one outer polygon and, optionally, inner polygons and some
593  // other options.
594  xms::MePolyInput inputPoly;
595 
596  // Outer polygon points are in clockwise order. Do not repeat the first point.
597  inputPoly.m_outPoly = {
598  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
599  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
600  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
601  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
602  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
603 
604  // specify a constant size function
605  inputPoly.m_constSizeFunction = 1.0;
606  inputPoly.m_constSizeBias = 0.2;
607 
608  // The MeMultiPolyMesherIo class holds all the options for generating
609  // UGrids from polygon data
611 
612  // The m_polys vector holds the polygons that will be filled with a UGrid.
613  // This case has only 1 polygon.
614  input.m_polys.push_back(inputPoly);
615 
616  // generate the mesh and check the base line
617  const std::string baseFile = "Example_ConstantSmooth";
618  tutGenerateAndCompare2dm(input, baseFile);
619 
620  // now make the polygon grow to a bigger size element
621  input.m_polys.front().m_constSizeFunction = 50;
622 
623  const std::string baseFile2 = "Example_ConstantSmooth2";
624  tutGenerateAndCompare2dm(input, baseFile2);
625 } // TutMeshingIntermediateTests::test_Example_ConstantSmooth
627 //------------------------------------------------------------------------------
630 //------------------------------------------------------------------------------
633 {
634  // array of depths
635  xms::VecDbl depths = {0, 5, 10, 20, 25, 5, 0};
636  // array for the computed sizes
637  xms::VecDbl elemSize;
638  // set the value of the min and max element size
639  double minElem(2), maxElem(102);
640  // generate the size array
641  xms::meSizeFunctionFromDepth(depths, elemSize, minElem, maxElem);
642  // verify that the sizes are as expected
643  xms::VecDbl baseElemSize = {2, 22, 42, 82, 102, 22, 2};
644  TS_ASSERT_DELTA_VEC(baseElemSize, elemSize, 1e-9);
645 
646  // now create an interpolator to pass along to a mesher
647 
648  // init the locations of the points used to interpolate
649  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
650  *pts = {{10, 10}, {25, 10}, {10, 25}, {50, 10}, {50, 25}, {50, 50}, {25, 50}};
651  BSHP<xms::VecInt> tris(new xms::VecInt());
652 
653  // convert the sizes to a float array for the interpolator
654  xms::VecFlt sizeFlt(elemSize.size(), 0);
655  int i(0);
656  for (auto& d : elemSize)
657  sizeFlt[i++] = (float)d;
658 
659  // create an IDW interpolator
660  BSHP<xms::InterpBase> interp = xms::InterpIdw::New();
661  interp->SetPtsTris(pts, tris);
662 
663  // now the interpolator could be used with a mesher
664  xms::MePolyInput poly;
665  poly.m_sizeFunction = interp;
666 
667 } // TutMeshingIntermediateTests::test_Example_SizeFuncFromDepth
669 //------------------------------------------------------------------------------
704 //------------------------------------------------------------------------------
707 {
708  // create a grid of points
709  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
710  *pts = {{0, 0}, {10, 0}, {20, 0}, {30, 0}, {0, 10}, {10, 10},
711  {20, 10}, {30, 10}, {0, 20}, {10, 20}, {20, 20}, {30, 20}};
712  // assign all points a size of 100
713  xms::VecFlt sizes(pts->size(), 100);
714  // change the size to 1.0 of the point at 0, 10
715  sizes[4] = 1;
716  // create a TrTin class from the array of points
717  BSHP<xms::VecInt> tris(new xms::VecInt());
718  BSHP<xms::VecInt2d> adjTris(new xms::VecInt2d());
719  xms::TrTriangulatorPoints tr(*pts, *tris, &*adjTris);
720  tr.Triangulate();
721  BSHP<xms::TrTin> tin = xms::TrTin::New();
722  tin->SetGeometry(pts, tris, adjTris);
723 
724  // smooth the size function. The size ratio is set to 0.5. The min element
725  // size is 1.0. The "anchor type" is 0 (meaning min). This means the minimum
726  // size will be honored and the other values smoothed from the min.
727  xms::VecFlt vSmooth;
728  xms::DynBitset ptFlgs;
729  xms::meSmoothSizeFunction(tin, sizes, 0.5, 1.0, 0, ptFlgs, vSmooth);
730  xms::VecFlt baseSmooth = {4.46f, 5.90f, 9.36f, 12.83f, 1.0f, 4.46f,
731  7.93f, 11.39f, 4.46f, 7.93f, 11.39f, 14.86f};
732  // ensure the results are as expected
733  TS_ASSERT_DELTA_VEC(baseSmooth, vSmooth, .1);
734 } // TutMeshingIntermediateTests::test_Example_SmoothSizeFunc
736 //------------------------------------------------------------------------------
739 //------------------------------------------------------------------------------
742 {
743  // The MePolyInput class defines a single polygon to be meshed and which
744  // consists of one outer polygon and, optionally, inner polygons and some
745  // other options.
746  xms::MePolyInput inputPoly;
747 
748  // Outer polygon points are in clockwise order. Do not repeat the first point.
749  inputPoly.m_outPoly = {
750  {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50}, {0, 60}, {0, 70}, {0, 80},
751  {0, 90}, {0, 100}, {10, 100}, {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100},
752  {70, 100}, {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70}, {100, 60},
753  {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10}, {100, 0}, {90, 0}, {80, 0},
754  {70, 0}, {60, 0}, {50, 0}, {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
755 
756  // Inner polygons are in counter clockwise order. Do not repeat the first
757  // point.
758  inputPoly.m_insidePolys.push_back(xms::VecPt3d());
759  inputPoly.m_insidePolys[0] = {{40, 40}, {50, 40}, {60, 40}, {60, 50},
760  {60, 60}, {50, 60}, {40, 60}, {40, 50}};
761  inputPoly.m_relaxationMethod = "spring_relaxation";
762 
763  // The MeMultiPolyMesherIo class holds all the options for generating
764  // UGrids from polygon data
766 
767  // The m_polys vector holds the polygons that will be filled with a UGrid.
768  // This case has only 1 polygon.
769  input.m_polys.push_back(inputPoly);
770 
771  // generate the mesh and check the base line
772  const std::string baseFile = "Example_SpringRelax";
773  tutGenerateAndCompare2dm(input, baseFile);
774 } // TutMeshingIntermediateTests::test_Example_SpringRelax
776 
777 //------------------------------------------------------------------------------
780 //------------------------------------------------------------------------------
783 {
784  // Outer polygon points are in clockwise order
785  xms::VecPt3d polygon = {{0, 0}, {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50},
786  {0, 60}, {0, 70}, {0, 80}, {0, 90}, {0, 100}, {10, 100},
787  {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100}, {70, 100},
788  {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70},
789  {100, 60}, {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10},
790  {100, 0}, {90, 0}, {80, 0}, {70, 0}, {60, 0}, {50, 0},
791  {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
792  // create the redistribution class
793  BSHP<xms::MePolyRedistributePts> redist = xms::MePolyRedistributePts::New();
794  // set the redistribution class to use a constant spacing
795  redist->SetConstantSizeFunc(20.0);
796  // redistribute the points
797  xms::VecPt3d outPts = redist->Redistribute(polygon);
798  {
799  xms::VecPt3d expectedPts = {
800  {0, 0, 0}, {0, 20, 0}, {0, 40, 0}, {0, 60, 0}, {0, 80, 0}, {0, 100, 0},
801  {20, 100, 0}, {40, 100, 0}, {60, 100, 0}, {80, 100, 0}, {100, 100, 0}, {100, 80, 0},
802  {100, 60, 0}, {100, 40, 0}, {100, 20, 0}, {100, 0, 0}, {80, 0, 0}, {60, 0, 0},
803  {40, 0, 0}, {20, 0, 0}, {0, 0, 0}};
804  TS_ASSERT_DELTA_VECPT3D(expectedPts, outPts, 1e-3);
805  }
806 } // TutRedistributionIntermediateTests::test_Example_SimplePolygon_Redistribute
808 //------------------------------------------------------------------------------
810 //------------------------------------------------------------------------------
813 {
814  // Outer polygon points are in clockwise order
815  xms::VecPt3d polygon = {{0, 0}, {0, 10}, {0, 20}, {0, 30}, {0, 40}, {0, 50},
816  {0, 60}, {0, 70}, {0, 80}, {0, 90}, {0, 100}, {10, 100},
817  {20, 100}, {30, 100}, {40, 100}, {50, 100}, {60, 100}, {70, 100},
818  {80, 100}, {90, 100}, {100, 100}, {100, 90}, {100, 80}, {100, 70},
819  {100, 60}, {100, 50}, {100, 40}, {100, 30}, {100, 20}, {100, 10},
820  {100, 0}, {90, 0}, {80, 0}, {70, 0}, {60, 0}, {50, 0},
821  {40, 0}, {30, 0}, {20, 0}, {10, 0}, {0, 0}};
822 
823  // create a size function interpolator
824 
825  // These are the interpolator point locations. The size is specified by the
826  // "z" component of the points.
827  BSHP<xms::VecPt3d> sPts(new xms::VecPt3d());
828  *sPts = {{-10, -10, 10}, {-10, 110, 10}, {110, 110, 1}, {110, -10, 10}, {60, 70, 1}};
829  // These are the interpolator triangles.
830  // Triangles are specified as point indexes in ccw order. You can see the
831  // 4 triangles in the vector below.
832  BSHP<xms::VecInt> sTris(new xms::VecInt());
833  *sTris = {0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0};
834  // create a linear interpolator for the size function
835  BSHP<xms::InterpBase> linear(xms::InterpLinear::New());
836  // sets the points and the triangles for the interpolator
837  linear->SetPtsTris(sPts, sTris);
838  // create the redistribution class
839  BSHP<xms::MePolyRedistributePts> redist = xms::MePolyRedistributePts::New();
840  // set the redistribution class to use a constant spacing
841  redist->SetSizeFunc(linear);
842  // redistribute the points
843  xms::VecPt3d outPts = redist->Redistribute(polygon);
844  {
845  xms::VecPt3d expectedPts = {
846  {0.000, 0.000, 0}, {0.000, 8.794, 0}, {0.000, 17.574, 0}, {0.000, 26.355, 0},
847  {0.000, 35.135, 0}, {0.000, 43.916, 0}, {0.000, 52.697, 0}, {0.000, 61.477, 0},
848  {0.000, 70.258, 0}, {0.000, 79.038, 0}, {0.000, 87.819, 0}, {0.000, 96.599, 0},
849  {5.230, 100.000, 0}, {13.015, 100.000, 0}, {20.214, 100.000, 0}, {26.898, 100.000, 0},
850  {33.102, 100.000, 0}, {38.864, 100.000, 0}, {44.212, 100.000, 0}, {49.181, 100.000, 0},
851  {53.794, 100.000, 0}, {58.079, 100.000, 0}, {62.059, 100.000, 0}, {65.757, 100.000, 0},
852  {69.192, 100.000, 0}, {72.382, 100.000, 0}, {75.348, 100.000, 0}, {78.104, 100.000, 0},
853  {80.666, 100.000, 0}, {83.046, 100.000, 0}, {85.260, 100.000, 0}, {87.319, 100.000, 0},
854  {89.234, 100.000, 0}, {91.015, 100.000, 0}, {92.672, 100.000, 0}, {94.214, 100.000, 0},
855  {95.649, 100.000, 0}, {96.986, 100.000, 0}, {98.230, 100.000, 0}, {99.390, 100.000, 0},
856  {100.000, 99.523, 0}, {100.000, 98.406, 0}, {100.000, 97.223, 0}, {100.000, 95.963, 0},
857  {100.000, 94.609, 0}, {100.000, 93.156, 0}, {100.000, 91.594, 0}, {100.000, 89.915, 0},
858  {100.000, 88.111, 0}, {100.000, 86.172, 0}, {100.000, 84.087, 0}, {100.000, 81.844, 0},
859  {100.000, 79.431, 0}, {100.000, 76.836, 0}, {100.000, 74.044, 0}, {100.000, 71.040, 0},
860  {100.000, 67.806, 0}, {100.000, 64.327, 0}, {100.000, 60.580, 0}, {100.000, 56.547, 0},
861  {100.000, 52.206, 0}, {100.000, 47.530, 0}, {100.000, 42.497, 0}, {100.000, 37.076, 0},
862  {100.000, 31.239, 0}, {100.000, 24.951, 0}, {100.000, 18.178, 0}, {100.000, 10.884, 0},
863  {100.000, 3.028, 0}, {94.462, 0.000, 0}, {85.520, 0.000, 0}, {76.579, 0.000, 0},
864  {67.638, 0.000, 0}, {58.696, 0.000, 0}, {49.755, 0.000, 0}, {40.814, 0.000, 0},
865  {31.873, 0.000, 0}, {22.931, 0.000, 0}, {13.990, 0.000, 0}, {5.049, 0.000, 0},
866  {0.000, 0.000, 0}};
867  TS_ASSERT_DELTA_VECPT3D(expectedPts, outPts, 1e-3);
868  }
869 
870 } // TutMeshingIntermediateTests::test_Example_ScalarPaving
872 //------------------------------------------------------------------------------
874 //------------------------------------------------------------------------------
877 {
878  xms::VecPt3d polyline = {{0, 0, 0}, {5, 5, 0}, {10, 10, 0}, {15, 5, 0},
879  {20, 10, 0}, {21, 10, 0}, {25, 0, 0}};
880  // create the redistribution class
881  BSHP<xms::MePolyRedistributePts> redist = xms::MePolyRedistributePts::New();
882  // set the redistribution class to curvature
883  double featureSize(3.0), meanSpacing(0.5), minimumCurvature(.0001);
884  bool smooth(false);
885  redist->SetUseCurvatureRedistribution(featureSize, meanSpacing, minimumCurvature, smooth);
886  // redistribute the points
887  xms::VecPt3d outPts = redist->Redistribute(polyline);
888  {
889  xms::VecPt3d expectedPts = {
890  {0.000, 0.000, 0}, {9.526, 9.526, 0}, {9.582, 9.582, 0}, {9.639, 9.639, 0},
891  {9.695, 9.695, 0}, {9.751, 9.751, 0}, {9.808, 9.808, 0}, {9.864, 9.864, 0},
892  {9.921, 9.921, 0}, {9.977, 9.977, 0}, {10.034, 9.966, 0}, {10.090, 9.910, 0},
893  {10.146, 9.854, 0}, {10.203, 9.797, 0}, {10.259, 9.741, 0}, {10.316, 9.684, 0},
894  {10.372, 9.628, 0}, {10.429, 9.571, 0}, {10.485, 9.515, 0}, {14.481, 5.519, 0},
895  {14.537, 5.463, 0}, {14.594, 5.406, 0}, {14.650, 5.350, 0}, {14.707, 5.293, 0},
896  {14.763, 5.237, 0}, {14.819, 5.181, 0}, {14.876, 5.124, 0}, {14.932, 5.068, 0},
897  {14.989, 5.011, 0}, {15.045, 5.045, 0}, {15.102, 5.102, 0}, {15.158, 5.158, 0},
898  {15.215, 5.215, 0}, {15.271, 5.271, 0}, {15.327, 5.327, 0}, {15.384, 5.384, 0},
899  {15.440, 5.440, 0}, {15.497, 5.497, 0}, {19.484, 9.484, 0}, {19.518, 9.518, 0},
900  {19.552, 9.552, 0}, {19.587, 9.587, 0}, {19.621, 9.621, 0}, {19.655, 9.655, 0},
901  {19.690, 9.690, 0}, {19.724, 9.724, 0}, {19.759, 9.759, 0}, {19.793, 9.793, 0},
902  {19.827, 9.827, 0}, {19.862, 9.862, 0}, {19.896, 9.896, 0}, {19.930, 9.930, 0},
903  {19.965, 9.965, 0}, {19.999, 9.999, 0}, {20.047, 10.000, 0}, {20.096, 10.000, 0},
904  {20.144, 10.000, 0}, {20.193, 10.000, 0}, {20.242, 10.000, 0}, {20.790, 10.000, 0},
905  {20.838, 10.000, 0}, {20.886, 10.000, 0}, {20.934, 10.000, 0}, {20.982, 10.000, 0},
906  {21.011, 9.972, 0}, {21.029, 9.928, 0}, {21.047, 9.883, 0}, {21.065, 9.839, 0},
907  {21.082, 9.794, 0}, {21.100, 9.749, 0}, {21.118, 9.705, 0}, {21.136, 9.660, 0},
908  {21.154, 9.616, 0}, {21.172, 9.571, 0}, {21.189, 9.527, 0}, {21.207, 9.482, 0},
909  {21.225, 9.437, 0}, {21.243, 9.393, 0}, {21.261, 9.348, 0}, {25.000, 0.000, 0}};
910  TS_ASSERT_DELTA_VECPT3D(expectedPts, outPts, 1e-3);
911  }
912 } // TutRedistributionIntermediateTests::test_Example_Redistribute_Curvature
914 //------------------------------------------------------------------------------
916 //------------------------------------------------------------------------------
919 {
920  xms::VecPt3d polyline = {{0, 0, 0}, {5, 5, 0}, {10, 10, 0}, {15, 5, 0},
921  {20, 10, 0}, {21, 10, 0}, {25, 0, 0}, {0, 0, 0}};
922  // create the redistribution class
923  BSHP<xms::MePolyRedistributePts> redist = xms::MePolyRedistributePts::New();
924  // set the redistribution class to curvature
925  double featureSize(3.0), meanSpacing(0.5), minimumCurvature(.0001);
926  bool smooth(false);
927  redist->SetUseCurvatureRedistribution(featureSize, meanSpacing, minimumCurvature, smooth);
928  // redistribute the points
929  xms::VecPt3d outPts = redist->Redistribute(polyline);
930  {
931  xms::VecPt3d expectedPts = {
932  {0.000, 0.000, 0}, {0.042, 0.042, 0}, {0.084, 0.084, 0}, {0.126, 0.126, 0},
933  {0.168, 0.168, 0}, {0.210, 0.210, 0}, {0.252, 0.252, 0}, {0.294, 0.294, 0},
934  {0.336, 0.336, 0}, {0.378, 0.378, 0}, {0.420, 0.420, 0}, {0.462, 0.462, 0},
935  {0.505, 0.505, 0}, {9.491, 9.491, 0}, {9.546, 9.546, 0}, {9.601, 9.601, 0},
936  {9.655, 9.655, 0}, {9.710, 9.710, 0}, {9.765, 9.765, 0}, {9.820, 9.820, 0},
937  {9.875, 9.875, 0}, {9.930, 9.930, 0}, {9.985, 9.985, 0}, {10.040, 9.960, 0},
938  {10.095, 9.905, 0}, {10.150, 9.850, 0}, {10.205, 9.795, 0}, {10.260, 9.740, 0},
939  {10.315, 9.685, 0}, {10.370, 9.630, 0}, {10.424, 9.576, 0}, {10.479, 9.521, 0},
940  {14.474, 5.526, 0}, {14.529, 5.471, 0}, {14.584, 5.416, 0}, {14.639, 5.361, 0},
941  {14.693, 5.307, 0}, {14.748, 5.252, 0}, {14.803, 5.197, 0}, {14.858, 5.142, 0},
942  {14.913, 5.087, 0}, {14.968, 5.032, 0}, {15.023, 5.023, 0}, {15.078, 5.078, 0},
943  {15.133, 5.133, 0}, {15.188, 5.188, 0}, {15.243, 5.243, 0}, {15.298, 5.298, 0},
944  {15.353, 5.353, 0}, {15.408, 5.408, 0}, {15.462, 5.462, 0}, {15.517, 5.517, 0},
945  {19.495, 9.495, 0}, {19.529, 9.529, 0}, {19.562, 9.562, 0}, {19.596, 9.596, 0},
946  {19.629, 9.629, 0}, {19.662, 9.662, 0}, {19.696, 9.696, 0}, {19.729, 9.729, 0},
947  {19.763, 9.763, 0}, {19.796, 9.796, 0}, {19.830, 9.830, 0}, {19.863, 9.863, 0},
948  {19.897, 9.897, 0}, {19.930, 9.930, 0}, {19.964, 9.964, 0}, {19.997, 9.997, 0},
949  {20.043, 10.000, 0}, {20.090, 10.000, 0}, {20.138, 10.000, 0}, {20.185, 10.000, 0},
950  {20.232, 10.000, 0}, {20.779, 10.000, 0}, {20.826, 10.000, 0}, {20.873, 10.000, 0},
951  {20.919, 10.000, 0}, {20.966, 10.000, 0}, {21.005, 9.988, 0}, {21.022, 9.945, 0},
952  {21.039, 9.901, 0}, {21.057, 9.858, 0}, {21.074, 9.815, 0}, {21.092, 9.771, 0},
953  {21.109, 9.728, 0}, {21.126, 9.684, 0}, {21.144, 9.641, 0}, {21.161, 9.598, 0},
954  {21.178, 9.554, 0}, {21.196, 9.511, 0}, {21.213, 9.467, 0}, {21.230, 9.424, 0},
955  {21.248, 9.381, 0}, {21.265, 9.337, 0}, {24.727, 0.682, 0}, {24.752, 0.621, 0},
956  {24.776, 0.559, 0}, {24.801, 0.498, 0}, {24.826, 0.436, 0}, {24.850, 0.375, 0},
957  {24.875, 0.313, 0}, {24.899, 0.251, 0}, {24.924, 0.190, 0}, {24.949, 0.128, 0},
958  {24.973, 0.067, 0}, {24.998, 0.005, 0}, {24.939, 0.000, 0}, {24.873, 0.000, 0},
959  {24.806, 0.000, 0}, {24.740, 0.000, 0}, {24.674, 0.000, 0}, {24.607, 0.000, 0},
960  {24.541, 0.000, 0}, {24.475, 0.000, 0}, {24.408, 0.000, 0}, {24.342, 0.000, 0},
961  {24.276, 0.000, 0}, {0.713, 0.000, 0}, {0.654, 0.000, 0}, {0.595, 0.000, 0},
962  {0.535, 0.000, 0}, {0.476, 0.000, 0}, {0.416, 0.000, 0}, {0.357, 0.000, 0},
963  {0.297, 0.000, 0}, {0.238, 0.000, 0}, {0.178, 0.000, 0}, {0.119, 0.000, 0},
964  {0.059, 0.000, 0}, {0.000, 0.000, 0}};
965  TS_ASSERT_DELTA_VECPT3D(expectedPts, outPts, 1e-3);
966  }
967 } // TutRedistributionIntermediateTests::test_Example_Redistribute_Polygon_Curvature
969 
970 //------------------------------------------------------------------------------
974 //------------------------------------------------------------------------------
976 #include <xmsgrid/ugrid/XmUGrid.h>
980 
982 {
983  // read a UGrid from a file.
984  const std::string path(std::string(XMS_TEST_PATH) +
985  "Tutorial_Meshing/");
986  const std::string inputFilePath = path + "Example_QuadBlossom_triangleUGridInput.txt";
987  BSHP<xms::XmUGrid> ugrid = xms::XmReadUGridFromAsciiFile(inputFilePath); // read from file.
988  BSHP<xms::MeQuadBlossom> quadBlossom = xms::MeQuadBlossom::New(ugrid);
989 
990  // PreMakeQuads returns the number of boundary edges of the triangular mesh.
991  // An even number of boundary edges insures no triangles in the output UGrid.
992  int nBoundaryEdges = quadBlossom->PreMakeQuads();
993  TS_ASSERT((nBoundaryEdges & 0x1) == 0);
994 
995  // The MeQuadBlossom basic algorithm is O(N^3). Check the estimated minutes. If too large,
996  // Then split the mesh into smaller sub-UGrids, then call MakeQuads on each one.
997  double minutes = xms::MeQuadBlossom::EstimatedRunTimeInMinutes(ugrid->GetPointCount());
998  TS_ASSERT(minutes < 2.0);
999 
1000  bool splitVertices = true;
1001  bool useAngle = false;
1002  BSHP<xms::XmUGrid> quadUGrid = quadBlossom->MakeQuads(splitVertices, useAngle);
1003 
1004  // Test the quad UGrid generated by the Quad Blossom algorithm
1005  const std::string outFile = path + "Example_QuadBlossom_quadUGrid_out.txt";
1006  xms::XmWriteUGridToAsciiFile(quadUGrid, outFile);
1007  const std::string baseFile = path + "Example_QuadBlossom_quadUGrid_base.txt";
1008  TS_ASSERT_TXT_FILES_EQUAL(baseFile, outFile);
1009 
1010  // Use MeBadQuadRemover to remove bad quads from the quad UGrid.
1011  double maxAspect = 0.7;
1012  BSHP<xms::MeBadQuadRemover> badQuadRemover = xms::MeBadQuadRemover::New(quadUGrid);
1013  BSHP<xms::XmUGrid> quadUGridImproved = badQuadRemover->RemoveBadQuads(maxAspect);
1014 
1015  // Test the improved quad UGrid returned from the Bad Quad Remover algorithm
1016  const std::string outFile2 = path + "Example_QuadBlossom_quadUGridImproved_out.txt";
1017  xms::XmWriteUGridToAsciiFile(quadUGridImproved, outFile2);
1018  const std::string baseFile2 = path + "Example_QuadBlossom_quadUGridImproved_base.txt";
1019  TS_ASSERT_TXT_FILES_EQUAL(baseFile2, outFile2);
1020 
1021  // Use MeBadQuadRemover to remove bad quads from the quad UGrid a second time.
1022  maxAspect = 0.7;
1023  badQuadRemover = xms::MeBadQuadRemover::New(quadUGridImproved);
1024  BSHP<xms::XmUGrid> quadUGridImproved2 = badQuadRemover->RemoveBadQuads(maxAspect);
1025 
1026  // Test the improved quad UGrid returned from the Bad Quad Remover algorithm
1027  const std::string outFile3 = path + "Example_QuadBlossom_quadUGridImproved2_out.txt";
1028  xms::XmWriteUGridToAsciiFile(quadUGridImproved2, outFile3);
1029  const std::string baseFile3 = path + "Example_QuadBlossom_quadUGridImproved2_base.txt";
1030  TS_ASSERT_TXT_FILES_EQUAL(baseFile3, outFile3);
1031 } // TutMeshingIntermediateTests::test_Example_QuadBlossom_BadQuadRemover
1033 #endif
void test_Example_SizeFuncFromDepth()
[snip_test_Example_ConstantSmooth]
Definition: TutMeshing.cpp:632
double m_constSizeBias
Optional. Transition factor for constant size function.
std::vector< VecPt3d2d > VecPt3d3d
void test_Example_Redistribute_Polygon_Curvature()
[test_Example_Redistribute_Curvature]
Definition: TutMeshing.cpp:918
std::vector< int > VecInt
std::vector< MePolyInput > m_polys
Required (but some data is optional). Inputs for each polygon.
Utilities related to a VTK unstructured grid (from shared1\UGridUtils.cpp)
void test_Example_SimplePolygon_Redistribute()
[snip_test_Example_SpringRelax]
Definition: TutMeshing.cpp:782
static BSHP< MePolyRedistributePts > New()
Creates an instance of this class.
VecPt3d2d m_insidePolys
Optional. Inner polygons (holes). Counter clockwise. 1st pt != last.
#define TS_ASSERT_DELTA_VECPT3D(a, b, delta)
void test_Example_SimplePolygon()
Defines the test group.
Definition: TutMeshing.cpp:271
void ttGetTestFilePaths(const std::string &a_path, const std::string &a_fileBase, const std::string &a_extension, std::string &a_baseFilePath, std::string &a_outFilePath)
BSHP< InterpBase > m_elevFunction
Optional. Elevation function for interpolating z coordinate of mesh points.
static BSHP< InterpIdw > New()
bool m_createMeshPoint
Should a mesh node/point be created at the refine point.
bool m_checkTopology
Optional. If true, checks polygon input topology for errors.
static double EstimatedRunTimeInMinutes(int a_numPoints)
Get the estimated time to run the Quad Blossom algorithm in minutes.
static BSHP< MeBadQuadRemover > New(BSHP< XmUGrid > a_ugrid)
Create new MeBadQuadRemover.
void test_Example_QuadBlossom_BadQuadRemover()
[test_Example_Redistribute_Polygon_Curvature]
Definition: TutMeshing.cpp:981
static BSHP< MeQuadBlossom > New(BSHP< XmUGrid > a_ugrid)
Create new MeQuadBlossom.
A refine point used in meshing.
double m_constSizeFunction
Optional. Constant value size function.
void test_Example_ConstantSmooth()
[snip_test_Example_Patch]
Definition: TutMeshing.cpp:589
void test_Example_SmoothSizeFunc()
[snip_test_Example_SizeFuncFromDepth]
Definition: TutMeshing.cpp:706
bool tutReadPolygons(const std::string &a_fname, VecPt3d2d &a_outside, VecPt3d3d &a_inside)
helper function to read polygons from a text file
Definition: TutMeshing.cpp:220
void tutGenerateAndCompare2dm(MeMultiPolyMesherIo &a_io, const std::string &a_fileBase)
helper function to generate 2dm file and compare to a baseline
Definition: TutMeshing.cpp:240
void test_Example_SpringRelax()
[snip_test_Example_SmoothSizeFunc]
Definition: TutMeshing.cpp:741
static BSHP< TrTin > New()
BSHP< InterpBase > m_sizeFunction
Optional. Size function for scalar paving.
#define TS_ASSERT_TXT_FILES_EQUAL(a, b)
std::string m_relaxationMethod
void test_Example_Redistribute_Curvature()
[snip_test_Example_Redistribute_SizeFunction]
Definition: TutMeshing.cpp:876
std::vector< MeRefinePoint > m_refPts
Optional. Refine points.
VecPt3d m_outPoly
Required. Outer polygons. Clockwise. 1st pt != last.
void test_Example_Patch()
[snip_test_Example_ScalarPaving]
Definition: TutMeshing.cpp:554
bool m_returnCellPolygons
If true, returns the polygon index of each cell.
void test_Example_Breakline()
[snip_test_Example_SimplePolygonWithHole]
Definition: TutMeshing.cpp:384
Provides the input to meshing multiple polygons and holds the output.
std::vector< VecPt3d > VecPt3d2d
void test_Example_MultiplePolygons()
[snip_test_Example_RefinePoints]
Definition: TutMeshing.cpp:474
static BSHP< InterpLinear > New()
bool tutReadMeshIoFromFile(const std::string &a_fname, MeMultiPolyMesherIo &a_io)
helper function to read MeMultiPolyMesherIo
Definition: TutMeshing.cpp:64
void test_Example_RefinePoints()
[snip_test_Example_Breakline]
Definition: TutMeshing.cpp:421
double gmPolygonArea(const Pt3d *pts, size_t npoints)
void test_Example_Redistribute_SizeFunction()
[snip_test_example_SimplePolygon_Redistribute]
Definition: TutMeshing.cpp:812
static boost::shared_ptr< MeMultiPolyTo2dm > New()
Creates a class.
void test_Example_ComplexPolygon()
[snip_test_Example_SimplePolygon]
Definition: TutMeshing.cpp:303
Meshing inputs for one polygon.
void test_Example_SimplePolygonWithHole()
[snip_test_Example_ComplexPolygon]
Definition: TutMeshing.cpp:346
#define TS_ASSERT_DELTA_VEC(a, b, delta)
std::vector< Pt3d > VecPt3d
void test_Example_ScalarPaving()
[snip_test_Example_MultiPolygon]
Definition: TutMeshing.cpp:504