xmsmesh  1.0
MeMeshUtils.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
15 
16 // 3. Standard library headers
17 #include <map>
18 #include <sstream>
19 
20 // 4. External library headers
21 
22 // 5. Shared code headers
23 #include <xmscore/math/math.h>
24 #include <xmscore/misc/XmError.h>
25 #include <xmscore/misc/DynBitset.h>
27 
28 // 6. Non-shared code headers
29 
30 //----- Forward declarations ---------------------------------------------------
31 
32 //----- External globals -------------------------------------------------------
33 
34 //----- Namespace declaration --------------------------------------------------
35 namespace xms
36 {
37 //----- Constants / Enumerations -----------------------------------------------
38 
39 //----- Classes / Structs ------------------------------------------------------
40 
41 //------------------------------------------------------------------------------
43 //------------------------------------------------------------------------------
44 class SmoothIo
45 {
46 public:
47  SmoothIo()
48  : m_tin()
49  , m_sizes(nullptr)
50  , m_anchorType(0)
51  , m_ptsFlag()
52  , m_smoothSize(nullptr)
53  , m_checkMinSize(false)
54  , m_sizeRatio(0)
55  , m_minSize(0)
56  , m_scaleFactor(0)
57  , m_percentGrowth(0)
59  , m_maxSize(0)
60  {
61  }
62 
63  bool CalcMaxSize(double a_length, float a_smoothVal, double& a_maxSize);
64  double CalcMinSize(double a_length, float a_smoothVal, double a_calcMaxSize);
65 
66  BSHP<TrTin> m_tin;
67  const VecFlt* m_sizes;
71 
72  // used with size function smoothing
74  double m_sizeRatio;
75  double m_minSize;
76  double m_scaleFactor;
77  double m_percentGrowth;
79 
80  double m_maxSize;
81 };
82 
83 //----- Internal functions -----------------------------------------------------
84 //------------------------------------------------------------------------------
90 //------------------------------------------------------------------------------
91 bool SmoothIo::CalcMaxSize(double a_length, float a_smoothVal, double& a_maxSize)
92 {
93  if (m_checkMinSize)
94  {
95  double sizeOneAway = a_length / (m_scaleFactor * a_smoothVal);
96  double negLogCheck = sizeOneAway * (m_percentGrowth - 1.0) + 1.0;
97  XM_ENSURE_TRUE(negLogCheck > 0.0, false);
98  double numElems = log(negLogCheck) / m_logPercentGrowth;
99  a_maxSize = pow(m_percentGrowth, numElems) * a_smoothVal;
100  }
101  else
102  {
103  a_maxSize = (double)a_smoothVal + a_length * m_maxSize;
104  }
105  return true;
106 } // SmoothIo::CalcMaxSize
107 //------------------------------------------------------------------------------
113 //------------------------------------------------------------------------------
114 double SmoothIo::CalcMinSize(double a_length, float a_smoothVal, double a_calcMaxSize)
115 {
116  double minSize(0);
117  if (m_checkMinSize)
118  {
119  minSize = a_smoothVal - (a_calcMaxSize - a_smoothVal);
120  }
121  else
122  {
123  minSize = (double)a_smoothVal - a_length * m_maxSize;
124  }
125  return minSize;
126 } // SmoothIo::CalcMaxSize
127 //------------------------------------------------------------------------------
132 //------------------------------------------------------------------------------
133 static void meiDoSmooth(SmoothIo& a_)
134 {
135  if (a_.m_ptsFlag.empty())
136  a_.m_ptsFlag.resize(a_.m_tin->NumPoints(), true);
137  XM_ENSURE_TRUE(a_.m_ptsFlag.size() == (size_t)a_.m_tin->NumPoints());
138 
139  DynBitset ptsFlag(a_.m_tin->NumPoints(), false);
140 
141  VecFlt& smoothSize(*a_.m_smoothSize);
142  const VecFlt& sz(*a_.m_sizes);
143  // set the smoothed size equal to the incoming size
144  smoothSize = sz;
145  // sort points based on size
146  std::multimap<float, int> mapSizeIdx;
147  std::vector<std::multimap<float, int>::iterator> vecIt;
148  float val(1.0);
149  // if we are anchoring to the max size then make the map key the negative
150  // of the size
151  if (1 == a_.m_anchorType)
152  val = -1.0;
153  for (int i = 0; i < (int)sz.size(); ++i)
154  {
155  vecIt.push_back(mapSizeIdx.insert(std::make_pair(val * sz[i], i)));
156  }
157 
158  // get references to the Tin
159  const VecPt3d& pts(a_.m_tin->Points());
160  const VecInt2d& trisAdjToPts(a_.m_tin->TrisAdjToPts());
161  const VecInt& tris(a_.m_tin->Triangles());
162 
163  // iterate through the points
164  auto it = mapSizeIdx.begin();
165  auto endIt = mapSizeIdx.end();
166  for (; it != endIt; ++it)
167  {
168  int i = it->second; // index of the point
169  if (!a_.m_ptsFlag[i])
170  continue;
171  if (a_.m_checkMinSize && (double)smoothSize[i] < a_.m_minSize)
172  {
173  smoothSize[i] = (float)a_.m_minSize;
174  }
175  const VecInt adjTris(trisAdjToPts[i]); // triangles adjacent to the point
176  for (const auto& t : adjTris)
177  {
178  int tIdx = t * 3;
179  int triPts[3];
180  // points in the adjacent triangle
181  triPts[0] = tris[tIdx];
182  triPts[1] = tris[tIdx + 1];
183  triPts[2] = tris[tIdx + 2];
184  for (int t1 = 0; t1 < 3; ++t1)
185  {
186  int ix = triPts[t1]; // index of triangle point
187  // make sure this is not the vertex in the "i" loop
188  if (ix == i)
189  continue;
190  // make sure we have not already adjusted this point
191  if (ptsFlag[ix])
192  continue;
193 
194  const Pt3d &p0(pts[i]), &p1(pts[ix]);
195  // calculate what the min or max size can be based on how close
196  // the elements are
197  double length = Mdist(p0.x, p0.y, p1.x, p1.y);
198  double maxSize(0);
199  XM_ENSURE_TRUE(a_.CalcMaxSize(length, smoothSize[i], maxSize));
200 
201  switch (a_.m_anchorType)
202  {
203  case 0: // anchor to the min size
204  {
205  if (a_.m_checkMinSize)
206  XM_ENSURE_TRUE(maxSize > a_.m_minSize);
207  XM_ENSURE_TRUE(maxSize >= (double)smoothSize[i]);
208  if (maxSize < (double)smoothSize[ix])
209  {
210  smoothSize[ix] = (float)maxSize;
211  ptsFlag.set(ix, true);
212  }
213  else if (a_.m_checkMinSize && (double)smoothSize[ix] < a_.m_minSize)
214  {
215  smoothSize[ix] = (float)a_.m_minSize;
216  ptsFlag.set(ix, true);
217  }
218  }
219  break;
220  case 1: // anchor to the max size
221  {
222  double minSize = a_.CalcMinSize(length, smoothSize[i], maxSize);
223  // double minSize = smoothSize[i] - (maxSize - smoothSize[i]);
224  XM_ENSURE_TRUE(minSize < smoothSize[i]);
225  if (minSize > (double)smoothSize[ix])
226  {
227  smoothSize[ix] = (float)minSize;
228  ptsFlag.set(ix, true);
229  }
230  else if (a_.m_checkMinSize && (double)smoothSize[ix] < a_.m_minSize)
231  {
232  smoothSize[ix] = (float)a_.m_minSize;
233  ptsFlag.set(ix, true);
234  }
235  }
236  break;
237  default:
238  XM_ASSERT(0);
239  break;
240  }
241  // resort the point if it changed size
242  if (ptsFlag[ix])
243  {
244  ptsFlag.set(ix, false);
245  mapSizeIdx.erase(vecIt[ix]);
246  vecIt[ix] = mapSizeIdx.insert(std::make_pair(val * smoothSize[ix], ix));
247  }
248  }
249  }
250  }
251 } // meiDoSmooth
252 
253 //------------------------------------------------------------------------------
263 //------------------------------------------------------------------------------
264 void meSizeFunctionFromDepth(const VecDbl& a_depths,
265  VecDbl& a_size,
266  double a_minSize,
267  double a_maxSize)
268 {
269  XM_ENSURE_TRUE(a_minSize > 0);
270  XM_ENSURE_TRUE(a_maxSize > a_minSize);
271  double minD = *std::min_element(a_depths.begin(), a_depths.end());
272  double maxD = *std::max_element(a_depths.begin(), a_depths.end());
273  double dDiff = maxD - minD;
274  XM_ENSURE_TRUE(dDiff > 0);
275  double sDiff = a_maxSize - a_minSize;
276  XM_ENSURE_TRUE(sDiff > 0);
277 
278  a_size.assign(a_depths.size(), a_minSize);
279  int i(0);
280  for (auto& d : a_size)
281  {
282  d += ((a_depths[i++] - minD) / dDiff) * sDiff;
283  }
284 } // meSizeFunctionFromDepth
285 //------------------------------------------------------------------------------
299 //------------------------------------------------------------------------------
300 void meSmoothSizeFunction(BSHP<TrTin> a_tin,
301  const VecFlt& a_sizes,
302  double a_sizeRatio,
303  double a_minSize,
304  int a_anchorType,
305  const DynBitset& a_ptsFlag,
306  VecFlt& a_smoothSize)
307 {
308  a_smoothSize.resize(0);
309 
310  // error checking
311  XM_ENSURE_TRUE(!a_sizes.empty());
312  XM_ENSURE_TRUE(a_sizeRatio > 0.0);
313  XM_ENSURE_TRUE(a_minSize > 0.0);
314  double percentGrowth = sqrt(1.0 / a_sizeRatio);
315  XM_ENSURE_TRUE(percentGrowth > 0.0);
316  double logPercentGrowth = log(percentGrowth);
317  double scaleFactor = (percentGrowth - 1.0) / logPercentGrowth;
318  XM_ENSURE_TRUE(scaleFactor != 0.0);
319 
320  SmoothIo io;
321  io.m_tin = a_tin;
322  io.m_sizes = &a_sizes;
323  io.m_anchorType = a_anchorType;
324  io.m_ptsFlag = a_ptsFlag;
325  io.m_smoothSize = &a_smoothSize;
326 
327  io.m_checkMinSize = true;
328  io.m_sizeRatio = a_sizeRatio;
329  io.m_minSize = a_minSize;
330  io.m_percentGrowth = percentGrowth;
331  io.m_logPercentGrowth = logPercentGrowth;
332  io.m_scaleFactor = scaleFactor;
333  meiDoSmooth(io);
334 } // meSmoothSizeFunction
335 //------------------------------------------------------------------------------
348 //------------------------------------------------------------------------------
349 void meSmoothElevBySlope(BSHP<TrTin> a_tin,
350  const VecFlt& a_elevs,
351  double a_maxSlope,
352  int a_anchorType,
353  const DynBitset& a_ptsFlag,
354  VecFlt& a_smoothElevs)
355 {
356  a_smoothElevs.resize(0);
357 
358  // error checking
359  XM_ENSURE_TRUE(!a_elevs.empty());
360  XM_ENSURE_TRUE(a_maxSlope > 0.0);
361 
362  SmoothIo io;
363  io.m_tin = a_tin;
364  io.m_sizes = &a_elevs;
365  io.m_anchorType = a_anchorType;
366  io.m_ptsFlag = a_ptsFlag;
367  io.m_smoothSize = &a_smoothElevs;
368 
369  io.m_maxSize = a_maxSlope;
370 
371  meiDoSmooth(io);
372 } // meSmoothSizeFunction
373 //------------------------------------------------------------------------------
377 //------------------------------------------------------------------------------
378 void meModifyMessageWithPolygonId(int a_polyId, std::string& a_msg)
379 {
380  if (a_polyId > -1)
381  {
382  std::stringstream ss;
383  ss << "Error meshing polygon id: " << a_polyId << ". ";
384  a_msg = ss.str() + a_msg;
385  }
386 } // meModifyMessageWithPolygonId
387 
388 } // namespace xms
389 
390 #if CXX_TEST
391 
393 
396 
401 //------------------------------------------------------------------------------
403 //------------------------------------------------------------------------------
405 {
406  // array of depths
407  xms::VecDbl depths = {0, 5, 10, 20, 25, 5, 0};
408  // array for the computed sizes
409  xms::VecDbl elemSize;
410  // set the value of the min and max element size
411  double minElem(2), maxElem(102);
412  // generate the size array
413  xms::meSizeFunctionFromDepth(depths, elemSize, minElem, maxElem);
414  // verify that the sizes are as expected
415  xms::VecDbl baseElemSize = {2, 22, 42, 82, 102, 22, 2};
416  TS_ASSERT_DELTA_VEC(baseElemSize, elemSize, 1e-9);
417 } // MeMeshUtilsUnitTests::testSizeFuncFromDepth
418 //------------------------------------------------------------------------------
449 //------------------------------------------------------------------------------
452 {
453  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
454  *pts = {{0, 0}, {10, 0}, {20, 0}, {30, 0}, {0, 10}, {10, 10},
455  {20, 10}, {30, 10}, {0, 20}, {10, 20}, {20, 20}, {30, 20}};
456  xms::VecFlt sizes(pts->size(), 100);
457  sizes[4] = 1;
458  BSHP<xms::VecInt> tris(new xms::VecInt());
459  BSHP<xms::VecInt2d> adjTris(new xms::VecInt2d());
460  xms::TrTriangulatorPoints tr(*pts, *tris, &*adjTris);
461  tr.Triangulate();
462  BSHP<xms::TrTin> tin = xms::TrTin::New();
463  tin->SetGeometry(pts, tris, adjTris);
464 
465  xms::VecFlt vSmooth;
466  xms::DynBitset ptFlags;
467  xms::meSmoothSizeFunction(tin, sizes, 0.5, 1.0, 0, ptFlags, vSmooth);
468  xms::VecFlt baseSmooth = {4.46f, 5.90f, 9.36f, 12.83f, 1.0f, 4.46f,
469  7.93f, 11.39f, 4.46f, 7.93f, 11.39f, 14.86f};
470  TS_ASSERT_DELTA_VEC(baseSmooth, vSmooth, .1);
471 } // MeMeshUtilsUnitTests::testSmoothSizeFunc
473 //------------------------------------------------------------------------------
504 //------------------------------------------------------------------------------
507 {
508  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
509  *pts = {{0, 0}, {10, 0}, {20, 0}, {30, 0}, {0, 10}, {10, 10},
510  {20, 10}, {30, 10}, {0, 20}, {10, 20}, {20, 20}, {30, 20}};
511  xms::VecFlt sizes(pts->size(), 1);
512  sizes[4] = 100;
513  BSHP<xms::VecInt> tris(new xms::VecInt());
514  BSHP<xms::VecInt2d> adjTris(new xms::VecInt2d());
515  xms::TrTriangulatorPoints tr(*pts, *tris, &*adjTris);
516  tr.Triangulate();
517  BSHP<xms::TrTin> tin = xms::TrTin::New();
518  tin->SetGeometry(pts, tris, adjTris);
519 
520  xms::VecFlt vSmooth;
521  xms::DynBitset ptFlags;
522  xms::meSmoothSizeFunction(tin, sizes, 0.5, 1.0, 1, ptFlags, vSmooth);
523  xms::VecFlt baseSmooth = {96.53f, 95.10f, 91.63f, 88.17f, 100.0f, 96.53f,
524  93.07f, 89.60f, 96.53f, 93.07f, 89.60f, 86.14f};
525  TS_ASSERT_DELTA_VEC(baseSmooth, vSmooth, .1);
526 } // MeMeshUtilsUnitTests::testSmoothSizeFunc1
528 
529 //------------------------------------------------------------------------------
560 //------------------------------------------------------------------------------
563 {
564  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
565  *pts = {{0, 0}, {10, 0}, {20, 0}, {30, 0}, {0, 10}, {10, 10},
566  {20, 10}, {30, 10}, {0, 20}, {10, 20}, {20, 20}, {30, 20}};
567  xms::VecFlt sizes(pts->size(), 100);
568  sizes[4] = 1;
569  BSHP<xms::VecInt> tris(new xms::VecInt());
570  BSHP<xms::VecInt2d> adjTris(new xms::VecInt2d());
571  xms::TrTriangulatorPoints tr(*pts, *tris, &*adjTris);
572  tr.Triangulate();
573  BSHP<xms::TrTin> tin = xms::TrTin::New();
574  tin->SetGeometry(pts, tris, adjTris);
575 
576  xms::VecFlt vSmooth;
577  xms::DynBitset ptsFlag;
578  xms::meSmoothElevBySlope(tin, sizes, 0.5, 0, ptsFlag, vSmooth);
579  xms::VecFlt baseSmooth = {6.00f, 8.07f, 13.07f, 18.07f, 1.0f, 6.00f,
580  11.00f, 16.00f, 6.00f, 11.00f, 16.00f, 21.00f};
581  TS_ASSERT_DELTA_VEC(baseSmooth, vSmooth, .1);
582 } // MeMeshUtilsUnitTests::testSmoothSizeFunc2
584 //------------------------------------------------------------------------------
615 //------------------------------------------------------------------------------
618 {
619  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
620  *pts = {{0, 0}, {10, 0}, {20, 0}, {30, 0}, {0, 10}, {10, 10},
621  {20, 10}, {30, 10}, {0, 20}, {10, 20}, {20, 20}, {30, 20}};
622  xms::VecFlt sizes(pts->size(), 1);
623  sizes[4] = 100;
624  BSHP<xms::VecInt> tris(new xms::VecInt());
625  BSHP<xms::VecInt2d> adjTris(new xms::VecInt2d());
626  xms::TrTriangulatorPoints tr(*pts, *tris, &*adjTris);
627  tr.Triangulate();
628  BSHP<xms::TrTin> tin = xms::TrTin::New();
629  tin->SetGeometry(pts, tris, adjTris);
630 
631  xms::VecFlt vSmooth;
632  xms::DynBitset ptsFlag;
633  xms::meSmoothElevBySlope(tin, sizes, 0.5, 1, ptsFlag, vSmooth);
634  xms::VecFlt baseSmooth = {95.00f, 92.92f, 87.92f, 82.92f, 100.0f, 95.00f,
635  90.00f, 85.00f, 95.00f, 90.00f, 85.00f, 80.00f};
636  TS_ASSERT_DELTA_VEC(baseSmooth, vSmooth, .1);
637 } // MeMeshUtilsUnitTests::testSmoothSizeFunc3
639 
640 #endif
double m_minSize
min size
Definition: MeMeshUtils.cpp:75
std::vector< int > VecInt
Utilities related to a VTK unstructured grid (from shared1\UGridUtils.cpp)
Helper class for size function smoothing.
Definition: MeMeshUtils.cpp:44
std::vector< double > VecDbl
std::vector< float > VecFlt
static void meiDoSmooth(SmoothIo &a_)
Smooths a size function. Ensures that the size function transitions over a sufficient distance so tha...
void meSizeFunctionFromDepth(const VecDbl &a_depths, VecDbl &a_size, double a_minSize, double a_maxSize)
Creates a size at each point based on the depth at the point and the min and max sizes the equation i...
void meSmoothSizeFunction(BSHP< TrTin > a_tin, const VecFlt &a_sizes, double a_sizeRatio, double a_minSize, int a_anchorType, const DynBitset &a_ptsFlag, VecFlt &a_smoothSize)
Smooths a size function. Ensures that the size function transitions over a sufficient distance so tha...
double m_maxSize
max size used with elevation smoothing
Definition: MeMeshUtils.cpp:80
bool CalcMaxSize(double a_length, float a_smoothVal, double &a_maxSize)
Calculates a max size for use in meiDoSmooth.
Definition: MeMeshUtils.cpp:91
void testSizeFuncFromDepth()
Tests creating a size function from depth.
boost::dynamic_bitset< size_t > DynBitset
void testSmoothSizeFunc1()
[snip_MeMeshUtilsTests::testSmoothSizeFunc]
std::vector< VecInt > VecInt2d
void testSmoothSizeFunc3()
[snip_MeMeshUtilsTests::testSmoothSizeFunc2]
void meModifyMessageWithPolygonId(int a_polyId, std::string &a_msg)
Prepends the polygon id as part of an error messge.
static BSHP< TrTin > New()
void testSmoothSizeFunc()
Tests size function smoothing.
bool m_checkMinSize
flag to indicate that the min size should be checked
Definition: MeMeshUtils.cpp:73
#define XM_ENSURE_TRUE(...)
double m_sizeRatio
size ratio value
Definition: MeMeshUtils.cpp:74
BSHP< TrTin > m_tin
geometry defining connections between points
Definition: MeMeshUtils.cpp:66
#define XM_ASSERT(x)
void testSmoothSizeFunc2()
[snip_MeMeshUtilsTests::testSmoothSizeFunc1]
double m_logPercentGrowth
growth factor
Definition: MeMeshUtils.cpp:78
int m_anchorType
anchor to min or max value
Definition: MeMeshUtils.cpp:68
double Mdist(_T x1, _U y1, _V x2, _W y2)
VecFlt * m_smoothSize
the output smoothed sizes
Definition: MeMeshUtils.cpp:70
double m_scaleFactor
scaling factor
Definition: MeMeshUtils.cpp:76
const VecFlt * m_sizes
array of size values
Definition: MeMeshUtils.cpp:67
double m_percentGrowth
growth factor
Definition: MeMeshUtils.cpp:77
void meSmoothElevBySlope(BSHP< TrTin > a_tin, const VecFlt &a_elevs, double a_maxSlope, int a_anchorType, const DynBitset &a_ptsFlag, VecFlt &a_smoothElevs)
Smooths a elevations based on max specified slope (a_maxSlope) preserving either the min or max based...
double CalcMinSize(double a_length, float a_smoothVal, double a_calcMaxSize)
Calculates a max size for use in meiDoSmooth.
DynBitset m_ptsFlag
flags indicating whether a point should be processed
Definition: MeMeshUtils.cpp:69
#define TS_ASSERT_DELTA_VEC(a, b, delta)
std::vector< Pt3d > VecPt3d