xmsmesh  1.0
MeRefinePtsToPolys.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 <map>
17 #include <sstream>
18 
19 // 4. External library headers
20 
21 // 5. Shared code headers
22 #include <xmscore/math/math.h>
23 #include <xmscore/points/pt.h>
28 #include <xmscore/misc/XmLog.h>
29 
30 // 6. Non-shared code headers
31 
32 //----- Forward declarations ---------------------------------------------------
33 
34 //----- External globals -------------------------------------------------------
35 
36 //----- Namespace declaration --------------------------------------------------
37 namespace xms
38 {
39 //----- Constants / Enumerations -----------------------------------------------
40 
41 //----- Classes / Structs ------------------------------------------------------
42 
43 //----- Internal functions -----------------------------------------------------
44 
45 //----- Class / Function definitions -------------------------------------------
47 {
48 public:
50  : m_TwoTimesSqrtThree(3.4641016151377545870548926830117)
51  , m_SqrtThree(1.7320508075688772935274463415059)
52  , m_SqrtThreeOverTwo(0.86602540378443864676372317075294)
53  , m_xyTol(1e-9)
54  , m_polyId(-1)
55  {
56  }
57 
58  //------------------------------------------------------------------------------
62  //------------------------------------------------------------------------------
63  virtual void SetRefinePoints(const std::vector<MeRefinePoint>& a_pts, double a_tol) override
64  {
65  m_pts = a_pts;
66  m_xyTol = a_tol;
67  }
68 
69  virtual void RefPtsAsPolys(int a_polyId,
70  const std::vector<Pt3d>& a_outPoly,
71  const std::vector<std::vector<Pt3d>>& a_inPolys,
72  std::vector<std::vector<Pt3d>>& a_newInPolys,
73  std::vector<Pt3d>& a_refMeshPts,
74  std::vector<Pt3d>& a_refPtsTooClose) override;
75 
76  void FindPtsInsidePolygon(const std::vector<Pt3d>& a_outPoly,
77  const std::vector<std::vector<Pt3d>>& a_inPolys,
78  std::vector<Pt3d>& a_refPtsTooClose);
79  void CheckRefPtsTooCloseToOtherRefPts(std::multimap<double, size_t>& a_mapSizeIdx,
80  std::vector<Pt3d>& a_refPtsTooClose);
81  void CreateNewInsidePolygons(std::vector<std::vector<Pt3d>>& a_newInPolys,
82  std::vector<Pt3d>& a_refMeshPts,
83  std::vector<Pt3d>& a_refPtsProcessed);
84  std::vector<Pt3d> TriPolyAtPoint(const Pt3d& a_pt, double a_size);
85  std::vector<Pt3d> HexPolyAtPoint(const Pt3d& a_pt, double a_size);
86 
88  double m_SqrtThree;
90  double m_xyTol;
91  std::vector<MeRefinePoint> m_pts;
92  std::vector<size_t> m_ptsInsidePoly;
93  int m_polyId;
95 };
96 //------------------------------------------------------------------------------
99 //------------------------------------------------------------------------------
100 BSHP<MeRefinePtsToPolys> MeRefinePtsToPolys::New()
101 {
102  BSHP<MeRefinePtsToPolys> ret(new MeRefinePtsToPolysImpl);
103  return ret;
104 } // MeRefinePtsToPolys::New
105 //------------------------------------------------------------------------------
107 //------------------------------------------------------------------------------
108 MeRefinePtsToPolys::MeRefinePtsToPolys()
109 {
110 }
111 //------------------------------------------------------------------------------
113 //------------------------------------------------------------------------------
114 MeRefinePtsToPolys::~MeRefinePtsToPolys()
115 {
116 }
117 
122 //------------------------------------------------------------------------------
133 //------------------------------------------------------------------------------
135  const std::vector<Pt3d>& a_outPoly,
136  const std::vector<std::vector<Pt3d>>& a_inPolys,
137  std::vector<std::vector<Pt3d>>& a_newInPolys,
138  std::vector<Pt3d>& a_refMeshPts,
139  std::vector<Pt3d>& a_refPtsProcessed)
140 {
141  m_polyId = a_polyId;
142  m_ptsInsidePoly.resize(0);
143  a_newInPolys.resize(0);
144  a_refMeshPts.resize(0);
145  a_refPtsProcessed.resize(0);
146  FindPtsInsidePolygon(a_outPoly, a_inPolys, a_refPtsProcessed);
147  CreateNewInsidePolygons(a_newInPolys, a_refMeshPts, a_refPtsProcessed);
148 } // MeRefinePtsToPolysImpl::RefPtsAsPolys
149 //------------------------------------------------------------------------------
157 //------------------------------------------------------------------------------
158 void MeRefinePtsToPolysImpl::FindPtsInsidePolygon(const std::vector<Pt3d>& a_outPoly,
159  const std::vector<std::vector<Pt3d>>& a_inPolys,
160  std::vector<Pt3d>& a_refPtsProcessed)
161 {
162  BSHP<GmPolygon> gmPoly = GmPolygon::New();
163  gmPoly->Setup(a_outPoly, a_inPolys);
164  std::multimap<double, size_t> mapSizeIdx;
165  for (size_t i = 0; i < m_pts.size(); ++i)
166  {
167  if (gmPoly->Within(m_pts[i].m_pt))
168  {
169  // see if this point is far enough away from the boundary of the
170  // polygon. If not then push a message that this point was too close
171  // to the polygon boundary.
172  double dist = gmPoly->MinDistanceToBoundary(m_pts[i].m_pt);
173  if (dist < m_pts[i].m_size)
174  {
175  std::stringstream ss, loc;
176  loc << "(" << m_pts[i].m_pt.x << ", " << m_pts[i].m_pt.y << ")";
177  ss << "Refine point at location: " << loc.str()
178  << " is too close to the polygon boundary with specified size: " << m_pts[i].m_size
179  << ". The point was not inserted by the meshing process. Specify a "
180  "size smaller than "
181  << dist << " for the point to be included by the meshing process.";
182  std::string msg = ss.str();
184  XM_LOG(xmlog::error, msg);
185  a_refPtsProcessed.push_back(m_pts[i].m_pt);
186  }
187  else
188  mapSizeIdx.insert(std::make_pair(m_pts[i].m_size, i));
189  }
190  }
191  // now check points that are too close to other points
192  CheckRefPtsTooCloseToOtherRefPts(mapSizeIdx, a_refPtsProcessed);
193 } // MeRefinePtsToPolysImpl::FindPtsInsidePolygon
194 //------------------------------------------------------------------------------
203 //------------------------------------------------------------------------------
205  std::multimap<double, size_t>& a_mapSizeIdx,
206  std::vector<Pt3d>& a_refPtsProcessed)
207 {
208  std::vector<int> removePt(a_mapSizeIdx.size(), 0);
209  std::multimap<double, size_t>::iterator it(a_mapSizeIdx.begin()), itEnd(a_mapSizeIdx.end());
210  for (size_t i = 0; it != itEnd; ++i, ++it)
211  {
212  if (removePt[i])
213  continue;
214 
215  size_t iIdx(it->second);
216  double iSize(m_pts[iIdx].m_size);
217  const Pt3d& pi(m_pts[iIdx].m_pt);
218  m_ptsInsidePoly.push_back(iIdx);
219 
220  std::multimap<double, size_t>::iterator it2(it);
221  ++it2;
222  for (size_t j = i; it2 != itEnd; ++j, ++it2)
223  {
224  size_t jIdx(it2->second);
225  const Pt3d& pj(m_pts[jIdx].m_pt);
226  double jSize(m_pts[jIdx].m_size);
227  double dist(Mdist(pi.x, pi.y, pj.x, pj.y));
228  double totalSize(iSize + jSize);
229  if (dist < totalSize)
230  {
231  double target = dist - iSize;
232  removePt[j] = true;
233  std::stringstream ss, loc;
234  loc << "(" << pj.x << ", " << pj.y << ")";
235  ss << "Refine point at location: " << loc.str() << " with specified size: " << jSize
236  << " is too close to another refine point. The point was not "
237  "inserted by the meshing process. Specify a size smaller than "
238  << target << " for the point to be included by the meshing process.";
239  std::string msg = ss.str();
241  XM_LOG(xmlog::error, msg);
242  a_refPtsProcessed.push_back(pj);
243  }
244  }
245  }
246 } // MeRefinePtsToPolysImpl::CheckRefPtsTooCloseToOtherRefPts
247 //------------------------------------------------------------------------------
256 //------------------------------------------------------------------------------
257 void MeRefinePtsToPolysImpl::CreateNewInsidePolygons(std::vector<std::vector<Pt3d>>& a_newInPolys,
258  std::vector<Pt3d>& a_refMeshPts,
259  std::vector<Pt3d>& a_refPtsProcessed)
260 {
261  for (size_t i = 0; i < m_ptsInsidePoly.size(); ++i)
262  {
263  size_t idx = m_ptsInsidePoly[i];
264  std::vector<Pt3d> p;
265  if (m_pts[idx].m_size > m_xyTol)
266  {
267  if (m_pts[idx].m_createMeshPoint)
268  {
269  p = HexPolyAtPoint(m_pts[idx].m_pt, m_pts[idx].m_size);
270  a_refMeshPts.push_back(m_pts[idx].m_pt);
271  }
272  else
273  {
274  p = TriPolyAtPoint(m_pts[idx].m_pt, m_pts[idx].m_size);
275  a_refPtsProcessed.push_back(m_pts[idx].m_pt);
276  }
277  a_newInPolys.push_back(p);
278  }
279  else if (m_pts[idx].m_createMeshPoint)
280  a_refMeshPts.push_back(m_pts[idx].m_pt);
281  }
282 } // MeRefinePtsToPolysImpl::CreateNewInsidePolygons
283 //------------------------------------------------------------------------------
289 //------------------------------------------------------------------------------
290 std::vector<Pt3d> MeRefinePtsToPolysImpl::TriPolyAtPoint(const Pt3d& a_pt, double a_size)
291 {
292  // Equilateral triangle with edge length "l"
293  //
294  // * (x, y + l / sqrt(3))
295  // / \
296 // / \
297 // / \
298 // / \
299 // / \
300 // / \
301 // / \
302 // / \
303 // / \
304 // / * \
305 // / (x,y) \
306 // / \
307 // / \
308 // / \
309 //(x-l/2, y-l/2*sqrt(3)) *-----------------------------* (x+l/2, y-l/2*sqrt(3))
310  //
311  // |------------ l --------------|
312 
313  double sizeOver2(a_size / 2);
314  double sizeOver2TimesSqrt3(a_size / m_TwoTimesSqrtThree);
315  double sizeOverSqrt3(a_size / m_SqrtThree);
316  std::vector<Pt3d> rval(3, a_pt);
317  rval[0].x -= sizeOver2;
318  rval[0].y -= sizeOver2TimesSqrt3;
319  rval[1].x += sizeOver2;
320  rval[1].y -= sizeOver2TimesSqrt3;
321  rval[2].y += sizeOverSqrt3;
322  return rval;
323 } // MeRefinePtsToPolysImpl::TriPolyAtPoint
324 //------------------------------------------------------------------------------
330 //------------------------------------------------------------------------------
331 std::vector<Pt3d> MeRefinePtsToPolysImpl::HexPolyAtPoint(const Pt3d& a_pt, double a_size)
332 {
333  // Hexagon with element edge length equal to "l"
334  // the center is at (x, y)
335  //
336  //
337  // (x-l/2,y+l*sqrt(3)/2)
338  // *-----------*(x+l/2,y+l*sqrt(3)/2)
339  // / \ / \
340 // / \ / \
341 // / \ / \
342 // / \ / \
343 // / \ / \
344 // (x-l/2,y)*-----------*-----------* (x+l/2,y)
345  // \ / \ /
346  // \ / \ /
347  // \ / \ /
348  // \ / \ /
349  // \ / \ /
350  // *-----------*(x+l/2,y-l*sqrt(3)/2)
351  // (x-l/2,y-l*sqrt(3)/2)
352  //
353  // squence to define inner poly that will have the inside pt
354  // 0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,1
355  //
356  double sizeOver2(a_size / 2);
357  double sizeTimesSqrtThreeOverTwo(a_size * m_SqrtThreeOverTwo);
358  std::vector<Pt3d> pts(6, a_pt);
359  pts[0].x += a_size;
360  pts[1].x += sizeOver2;
361  pts[1].y += sizeTimesSqrtThreeOverTwo;
362  pts[2].x -= sizeOver2;
363  pts[2].y += sizeTimesSqrtThreeOverTwo;
364  pts[3].x -= a_size;
365  pts[4].x -= sizeOver2;
366  pts[4].y -= sizeTimesSqrtThreeOverTwo;
367  pts[5].x += sizeOver2;
368  pts[5].y -= sizeTimesSqrtThreeOverTwo;
369  return pts;
370  // int sequence[] = {0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,1};
371  // std::vector<Pt3d> rval(18, a_pt);
372  // for (size_t i=0; i<rval.size(); ++i) rval[i] = pts[sequence[i]];
373  // return rval;
374 } // MeRefinePtsToPolysImpl::HexPolyAtPoint
375 
376 } // namespace xms
377 
378 #ifdef CXX_TEST
379 
382 
385 
386 // namespace xms {
387 using namespace xms;
388 
393 //------------------------------------------------------------------------------
395 //------------------------------------------------------------------------------
397 {
398  BSHP<MeRefinePtsToPolys> b = MeRefinePtsToPolys::New();
399  TS_ASSERT(b);
400 } // MeRefinePtsToPolysUnitTests::testCreateClass
401 //------------------------------------------------------------------------------
403 //------------------------------------------------------------------------------
405 {
407  Pt3d pt(1, 1, 0);
408  std::vector<Pt3d> pts = p.TriPolyAtPoint(pt, 1);
409  std::vector<Pt3d> basePts = {{.5, .7113, 0}, {1.5, .7113, 0}, {1, 1.5773, 0}};
410  TS_ASSERT_DELTA_VECPT3D(basePts, pts, 1e-3);
411 } // MeRefinePtsToPolysUnitTests::testTriPolyAtPoint
412 //------------------------------------------------------------------------------
414 //------------------------------------------------------------------------------
416 {
418  Pt3d pt(1, 1, 0);
419  std::vector<Pt3d> pts = p.HexPolyAtPoint(pt, 1);
420  std::vector<Pt3d> hexPts = {{2, 1, 0}, {1.5, 1.866, 0}, {.5, 1.866, 0},
421  {0, 1, 0}, {.5, .1339, 0}, {1.5, .1339, 0}};
422  TS_ASSERT_DELTA_VECPT3D(hexPts, pts, 1e-3);
423  // int seq[] = {0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,1};
424  // std::vector<Pt3d> basePts(18);
425  // for (size_t i=0; i<basePts.size(); ++i) basePts[i] = hexPts[seq[i]];
426  // TS_ASSERT_DELTA_VECPT3D(basePts, pts, 1e-3);
427 } // MeRefinePtsToPolysUnitTests::testHexPolyAtPoint
428 //------------------------------------------------------------------------------
430 //------------------------------------------------------------------------------
432 {
434  double tol(1e-9);
435  std::vector<MeRefinePoint> refPts = {{{4, 4, 0}, 1, 1}, {{8, 8, 0}, 1, 0}};
436  p.SetRefinePoints(refPts, tol);
437  std::vector<Pt3d> outPoly = {{0, 0, 0}, {0, 10, 0}, {10, 10, 0}, {10, 0, 0}};
438  std::vector<Pt3d> refMeshPts, tooClose;
439  std::vector<std::vector<Pt3d>> inPolys, newInPolys;
440  p.RefPtsAsPolys(-1, outPoly, inPolys, newInPolys, refMeshPts, tooClose);
441  TS_ASSERT_EQUALS(1, refMeshPts.size());
442  TS_ASSERT_EQUALS(2, newInPolys.size());
443  if (2 != newInPolys.size())
444  return;
445 
446  std::vector<Pt3d> hexPts = {{5, 4, 0}, {4.5, 4.866, 0}, {3.5, 4.866, 0},
447  {3, 4, 0}, {3.5, 3.1339, 0}, {4.5, 3.1339, 0}};
448  TS_ASSERT_DELTA_VECPT3D(hexPts, newInPolys[0], 1e-3);
449  // int seq[] = {0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,1};
450  std::vector<Pt3d> basePts(18);
451  // for (size_t i=0; i<basePts.size(); ++i) basePts[i] = hexPts[seq[i]];
452  // TS_ASSERT_DELTA_VECPT3D(basePts, newInPolys[0], 1e-3);
453 
454  basePts = {{7.5, 7.71132, 0}, {8.5, 7.71132, 0}, {8, 8.57735, 0}};
455  TS_ASSERT_DELTA_VECPT3D(basePts, newInPolys[1], 1e-3);
456 } // MeRefinePtsToPolysUnitTests::testRefPtsAsPolys
457 //------------------------------------------------------------------------------
459 //------------------------------------------------------------------------------
461 {
464  double tol(1e-9);
465  std::vector<MeRefinePoint> refPts = {{{.5, 4, 0}, 1, 1}, {{9.001, 8, 0}, 1, 0}};
466  p.SetRefinePoints(refPts, tol);
467  std::vector<Pt3d> outPoly = {{0, 0, 0}, {0, 10, 0}, {10, 10, 0}, {10, 0, 0}};
468  std::vector<Pt3d> refMeshPts, tooClose;
469  std::vector<std::vector<Pt3d>> inPolys, newInPolys;
470  p.RefPtsAsPolys(-1, outPoly, inPolys, newInPolys, refMeshPts, tooClose);
471  TS_ASSERT_EQUALS(0, newInPolys.size());
472  TS_ASSERT_EQUALS(2, XmLog::Instance().ErrCount());
474  "---Refine point at location: (0.5, 4) is too close to the polygon boundary "
475  "with specified size: 1. The point was not inserted by the meshing "
476  "process. Specify a size smaller than 0.5 for the point to be included "
477  "by the meshing process.\n\n"
478  "---Refine point at location: (9.001, 8) is too close to the polygon "
479  "boundary with specified size: 1. The point was not inserted by the "
480  "meshing process. Specify a size smaller than 0.999 for the point to be "
481  "included by the meshing process.\n\n");
482 } // MeRefinePtsToPolysUnitTests::testRefinePtsTooCloseToBoundary
483 
484 //} // namespace xms
485 #endif // CXX_TEST
#define XM_LOG(A, B)
Creates polygons from refine point input.
void CheckRefPtsTooCloseToOtherRefPts(std::multimap< double, size_t > &a_mapSizeIdx, std::vector< Pt3d > &a_refPtsTooClose)
Checks on refine points that are inside of the polygon to make sure that they are not too close to on...
static BSHP< MeRefinePtsToPolys > New()
Creates a new instance of this class.
Utilities related to a VTK unstructured grid (from shared1\UGridUtils.cpp)
void testRefinePtsTooCloseToBoundary()
test refine points that are too close to the polygon boundary
void testTriPolyAtPoint()
tests creating a triangle polygon at the refined point
#define TS_ASSERT_DELTA_VECPT3D(a, b, delta)
void testRefPtsAsPolys()
tests multiple refine points to polygons
Creates polygon from refine point information.
virtual void SetRefinePoints(const std::vector< MeRefinePoint > &a_pts, double a_tol) override
Sets the refine points.
double m_SqrtThreeOverTwo
precalculated constant
void testCreateClass()
tests creating the class
static BSHP< GmPolygon > New()
std::vector< Pt3d > HexPolyAtPoint(const Pt3d &a_pt, double a_size)
Creates a hexagon polygon that surrounds a refine point. The refine point itself WILL be included in ...
void meModifyMessageWithPolygonId(int a_polyId, std::string &a_msg)
Prepends the polygon id as part of an error messge.
std::string GetAndClearStackStr()
double m_TwoTimesSqrtThree
precalculated constant
#define TS_ASSERT_STACKED_ERRORS(expected)
double m_SqrtThree
precalculated constant
void FindPtsInsidePolygon(const std::vector< Pt3d > &a_outPoly, const std::vector< std::vector< Pt3d >> &a_inPolys, std::vector< Pt3d > &a_refPtsTooClose)
Finds the refine points that are inside of the polygon.
int m_polyId
id of the polygon
std::vector< Pt3d > TriPolyAtPoint(const Pt3d &a_pt, double a_size)
Creates a triangle polygon that surrounds a refine point. The refine point itself will NOT be include...
std::vector< MeRefinePoint > m_pts
the refine points
double Mdist(_T x1, _U y1, _V x2, _W y2)
static XmLog & Instance(bool a_delete=false, XmLog *a_new=NULL)
double m_xyTol
tolerance used for geometric comparison
void CreateNewInsidePolygons(std::vector< std::vector< Pt3d >> &a_newInPolys, std::vector< Pt3d > &a_refMeshPts, std::vector< Pt3d > &a_refPtsProcessed)
Creates new inside polygons from the refine points and appends these polygons to the current vector o...
virtual void RefPtsAsPolys(int a_polyId, const std::vector< Pt3d > &a_outPoly, const std::vector< std::vector< Pt3d >> &a_inPolys, std::vector< std::vector< Pt3d >> &a_newInPolys, std::vector< Pt3d > &a_refMeshPts, std::vector< Pt3d > &a_refPtsTooClose) override
Creates new inside polygons from refine points that are inside of the polygon being considered...
std::vector< size_t > m_ptsInsidePoly
void testHexPolyAtPoint()
test creating a hex polygon at the refine point