xmsstamper  1.0
XmBathymetryIntersector.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 <cfloat>
17 
18 // 4. External library headers
19 #include <boost/make_shared.hpp>
20 
21 // 5. Shared code headers
22 #include <xmscore/math/math.h>
23 #include <xmscore/misc/XmError.h>
24 #include <xmscore/misc/DynBitset.h>
25 #include <xmscore/misc/xmstype.h>
33 #include <xmscore/misc/XmConst.h>
34 
35 // 6. Non-shared code headers
36 
37 //----- Forward declarations ---------------------------------------------------
38 
39 //----- External globals -------------------------------------------------------
40 
41 //----- Namespace declaration --------------------------------------------------
42 
43 namespace xms
44 {
45 //----- Constants / Enumerations -----------------------------------------------
46 
47 //----- Classes / Structs ------------------------------------------------------
48 
52 {
53 public:
54  XmBathymetryIntersectorImpl(BSHP<TrTin> a_tin, BSHP<TrTin> a_stamp);
56 
57  virtual void IntersectCenterLine(XmStamperIo& a_io) override;
58  virtual void DecomposeCenterLine(XmStamperIo& a_io, std::vector<XmStamperIo>& a_vIo) override;
59  virtual void IntersectXsects(XmStamper3dPts& a_pts) override;
60  virtual void IntersectEndCaps(XmStamperIo& a_io, XmStamper3dPts& a_pts) override;
61 
62  void ClassifyPoints(VecPt3d& a_pts, VecInt& a_ptLocation);
63  void CreateIntersector();
64  void Intersect3dPts(VecPt3d& a_pts);
65  void IntersectXsectSide(VecPt3d& a_cl, VecPt3d2d& a_side);
66  void IntersectSlopedAbutment(XmStamperIo& a_io, XmStamper3dPts& a_pts, bool a_first);
67  void IntersectGuideBank(XmStamperIo& a_io, XmStamper3dPts& a_pts, bool a_first);
68 
69  BSHP<TrTin> m_tin;
70  BSHP<TrTin> m_stamp;
73  BSHP<GmMultiPolyIntersector>
76  double m_xyTol;
77 };
78 
83 //------------------------------------------------------------------------------
88 //------------------------------------------------------------------------------
89 XmBathymetryIntersectorImpl::XmBathymetryIntersectorImpl(BSHP<TrTin> a_tin, BSHP<TrTin> a_stamp)
90 : m_tin(a_tin)
91 , m_stamp(a_stamp)
92 , m_xyTol(1e-9)
93 {
94  if (m_tin)
95  {
96  Pt3d pMin, pMax;
97  m_tin->GetExtents(pMin, pMax);
98  double len = Mdist(pMin.x, pMin.y, pMax.x, pMax.y);
99  m_xyTol = len * 1e-9;
100  }
101 } // XmBathymetryIntersectorImpl::XmBathymetryIntersectorImpl
102 //------------------------------------------------------------------------------
104 //------------------------------------------------------------------------------
105 XmBathymetryIntersectorImpl::~XmBathymetryIntersectorImpl()
106 {
107 } // XmBathymetryIntersectorImpl::~XmBathymetryIntersectorImpl
108 //------------------------------------------------------------------------------
113 //------------------------------------------------------------------------------
115 {
116  // get the bounds of the center line
117  if (!m_intersect)
119  if (!m_intersect)
120  return;
121  // intersect the center line in 2d with the tin
122  VecPt3d& pts(m_tin->Points());
123  VecInt& tris(m_tin->Triangles());
124  VecInt triIds;
125  VecDbl tVals;
126  VecPt3d &line(a_io.m_centerLine), line1;
127  std::vector<XmStampCrossSection> vXs, ioXs(a_io.m_cs);
128  if (ioXs.size() != line.size())
129  ioXs.resize(line.size());
130  for (size_t i = 1; i < line.size(); ++i)
131  {
132  Pt3d &p0(line[i - 1]), &p1(line[i]);
133  line1.push_back(p0);
134  vXs.push_back(ioXs[i - 1]);
135  m_intersect->TraverseLineSegment(p0.x, p0.y, p1.x, p1.y, triIds, tVals);
136  for (size_t j = 0; j < triIds.size(); ++j)
137  {
138  if (triIds[j] < 0)
139  continue;
140  // get the triangle id for the triangle in the TIN
141  int idx = m_triIds[triIds[j] - 1];
142  // do a 3d intersection with the segment and the triangle
143  int idx0(tris[idx]), idx1(tris[idx + 1]), idx2(tris[idx + 2]);
144  Pt3d iPt;
145  int rval = gmIntersectTriangleAndLineSegment(p0, p1, pts[idx0], pts[idx1], pts[idx2], iPt);
146  if (1 == rval)
147  {
148  if (!gmEqualPointsXY(p0, iPt, m_xyTol) && !gmEqualPointsXY(p1, iPt, m_xyTol) &&
149  !gmEqualPointsXY(line1.back(), iPt, m_xyTol))
150  {
151  line1.push_back(iPt);
152  vXs.push_back(XmStampCrossSection());
153  }
154  }
155  }
156  }
157  if (line.size() > 1)
158  {
159  line1.push_back(line.back());
160  vXs.push_back(ioXs.back());
161  }
162  line.swap(line1);
163  a_io.m_cs.swap(vXs);
164 } // XmBathymetryIntersectorImpl::IntersectCenterLine
165 //------------------------------------------------------------------------------
173 //------------------------------------------------------------------------------
175  std::vector<XmStamperIo>& a_vIo)
176 {
177  a_vIo.resize(0);
178  VecInt ptLoc;
179  // classify the points of the center line as 1,0,-1,-2 (above, on, below, out)
180  ClassifyPoints(a_io.m_centerLine, ptLoc);
181 
182  // check if all the points are above or below
183  bool allAbove(1);
184  for (auto& i : ptLoc)
185  {
186  if (i != 1 || i != -2)
187  allAbove = false;
188  }
189  // if this is a cut and all points are above then abort
190  if (allAbove && a_io.m_stampingType == 0)
191  return;
192 
193  bool allBelow(1);
194  for (auto& i : ptLoc)
195  {
196  if (i != -1 || i != -2)
197  allBelow = false;
198  }
199  // if this is a fill and all points are below then abort
200  if (allBelow && a_io.m_stampingType == 1)
201  return;
202 
203  // decompose the center line
204 
205  bool done(false);
206  size_t start(0);
207  size_t lastIdx(a_io.m_centerLine.size() - 1);
208  ;
209  while (!done)
210  {
211  VecPt3d& cl(a_io.m_centerLine);
212 
213  // find the intersection
214  size_t idx(0);
215  for (size_t i = start + 1; idx == 0 && i < ptLoc.size(); ++i)
216  {
217  if (ptLoc[i] == 0)
218  idx = i;
219  }
220  if (0 == idx)
221  idx = lastIdx;
222  // check the location of the segment connected to the intersection relative
223  // to the TIN
224  Pt3d &p0(cl[start]), &p1(cl[idx]), pt;
225  if (idx == lastIdx)
226  pt = p0 - ((p0 - p1) * 10 * m_xyTol);
227  else
228  pt = p1 - ((p1 - p0) * 10 * m_xyTol);
229  VecPt3d vPt(1, pt);
230  VecInt vPtLoc;
231  ClassifyPoints(vPt, vPtLoc);
232 
233  if ( // location is above and we are doing a cut
234  (vPtLoc[0] == 1 && a_io.m_stampingType == 0)
235  // location is below and we are doing a fill
236  || (vPtLoc[0] == -1 && a_io.m_stampingType == 1))
237  { // skip this section of the center line
238  }
239  else
240  { // start and the beginning of the center line
241  XmStamperIo io = a_io;
242  io.m_centerLine.resize(idx - start + 1);
243  io.m_cs.resize(idx - start + 1);
244  if (start != 0)
245  a_io.m_firstEndCap = XmStamperEndCap(); // remove the first end cap
246  if (idx != lastIdx)
247  io.m_lastEndCap = XmStamperEndCap(); // remove the last end cap
248  for (size_t j = 0, i = start; i <= idx; ++i, ++j)
249  {
250  io.m_centerLine[j] = a_io.m_centerLine[i];
251  io.m_cs[j] = a_io.m_cs[i];
252  }
253  a_vIo.push_back(io);
254  }
255  start = idx;
256  if (start == lastIdx)
257  done = true;
258  }
259 
260 } // XmBathymetryIntersectorImpl::DecomposeCenterLine
261 //------------------------------------------------------------------------------
268 //------------------------------------------------------------------------------
270 {
271  a_ptLocation.assign(a_pts.size(), -2);
272  if (!m_intersect)
274  if (!m_intersect)
275  return;
276  VecInt triIds;
277  VecDbl tVals;
278  VecPt3d& pts(m_tin->Points());
279  VecInt& tris(m_tin->Triangles());
280  for (size_t i = 0; i < a_pts.size(); ++i)
281  {
282  Pt3d& p0(a_pts[i]);
283  // get the triangle with the point
284  m_intersect->TraverseLineSegment(p0.x, p0.y, p0.x, p0.y, triIds, tVals);
285  if (!triIds.empty())
286  {
287  // get the triangle id for the triangle in the TIN
288  int idx = m_triIds[triIds.front() - 1];
289  // get the points that make the triangle
290  int idx0(tris[idx]), idx1(tris[idx + 1]), idx2(tris[idx + 2]);
291  // interpolate the z from the triangle
292  Pt3d nrm(0, 0, 1), orig, bary, &pt0(pts[idx0]), &pt1(pts[idx1]), &pt2(pts[idx2]);
293  double coef[6];
294  int dir;
295  gmBaryPrepare(&pt0, &pt1, &pt2, &nrm, &orig, coef, &dir, true);
296  gmCartToBary(&p0, &orig, coef, dir, &bary);
297  double interpZ = pt0.z * bary.x + pt1.z * bary.y + pt2.z * bary.z;
298  if (EQ_TOL(interpZ, p0.z, FLT_EPSILON))
299  a_ptLocation[i] = 0;
300  else if (interpZ > p0.z)
301  a_ptLocation[i] = -1;
302  else
303  a_ptLocation[i] = 1;
304  }
305  }
306 } // XmBathymetryIntersectorImpl::ClassifyPoints
307 //------------------------------------------------------------------------------
312 //------------------------------------------------------------------------------
314 {
315  if (!m_intersect)
317  if (!m_intersect)
318  return;
319 
322 } // XmBathymetryIntersectorImpl::IntersectXsects
323 //------------------------------------------------------------------------------
329 //------------------------------------------------------------------------------
331 {
332  XM_ENSURE_TRUE(!a_io.m_cs.empty());
333  if (!m_intersect)
335  if (!m_intersect)
336  return;
337 
338  int type = a_io.m_firstEndCap.m_type;
339  if (type == 1)
340  IntersectSlopedAbutment(a_io, a_pts, true);
341  else if (type == 0)
342  IntersectGuideBank(a_io, a_pts, true);
343 
344  type = a_io.m_lastEndCap.m_type;
345  if (type == 1)
346  IntersectSlopedAbutment(a_io, a_pts, false);
347  else if (type == 0)
348  IntersectGuideBank(a_io, a_pts, false);
349 } // XmBathymetryIntersectorImpl::IntersectEndCaps
350 //------------------------------------------------------------------------------
354 //------------------------------------------------------------------------------
356 {
357  VecPt3d2d& xs(a_side);
358  if (xs.empty())
359  return;
360  VecPt3d& cl(a_cl);
361  XM_ENSURE_TRUE(xs.size() == cl.size());
362  for (size_t i = 0; i < cl.size(); ++i)
363  {
364  VecPt3d line;
365  line.reserve(xs[i].size() + 1);
366  line.push_back(cl[i]);
367  for (auto& p : xs[i])
368  line.push_back(p);
369  Intersect3dPts(line);
370  line.erase(line.begin());
371  xs[i] = line;
372  }
373 } // XmBathymetryIntersectorImpl::IntersectXsectSide
374 //------------------------------------------------------------------------------
376 //------------------------------------------------------------------------------
378 {
379  if (m_intersect)
380  m_intersect.reset();
381 
382  const VecPt3d& pts(m_tin->Points());
383  VecInt &tris(m_tin->Triangles()), vTri(3, 0);
384 
385  DynBitset ptFlags;
386  ptFlags.resize(pts.size(), true);
387 
388  // classify points
389  BSHP<GmTriSearch> tSearch = GmTriSearch::New();
390  if (m_stamp)
391  {
392  BSHP<VecInt> tPtr(new VecInt());
393  {
394  VecInt& tmp(m_stamp->Triangles());
395  tPtr->reserve(tmp.size());
396  for (const auto& t : tmp)
397  tPtr->push_back((int)t);
398  }
399  tSearch->TrisToSearch(m_stamp->PointsPtr(), tPtr);
400  for (size_t i = 0; i < pts.size(); ++i)
401  {
402  if (XM_NONE == tSearch->TriContainingPt(pts[i]))
403  ptFlags[i] = 0;
404  }
405  }
406 
407  // classify triangles
408  Pt3d pMin, pMax;
409  VecInt tIdxes;
410  int triCount(0);
411  DynBitset triFlags;
412  triFlags.resize(tris.size() / 3, 0);
413  for (size_t i = 0, cnt = 0; i < tris.size(); i += 3, ++cnt)
414  {
415  int ix0(tris[i + 0]), ix1(tris[i + 1]), ix2(tris[i + 2]);
416  if (ptFlags[ix0] || ptFlags[ix1] || ptFlags[ix2])
417  {
418  triFlags[cnt] = 1;
419  ++triCount;
420  }
421  else if (!triFlags[cnt])
422  { // get the triangle bounding box
423  pMin = XM_DBL_HIGHEST;
424  pMax = XM_DBL_LOWEST;
425  gmAddToExtents(pts[ix0], pMin, pMax);
426  gmAddToExtents(pts[ix1], pMin, pMax);
427  gmAddToExtents(pts[ix2], pMin, pMax);
428  tSearch->TriEnvelopesOverlap(pMin, pMax, tIdxes);
429  if (!tIdxes.empty())
430  {
431  triFlags[cnt] = 1;
432  ++triCount;
433  }
434  }
435  }
436 
437  VecInt2d polys(triCount, vTri);
438  m_triIds.resize(triCount);
439  for (size_t i = 0, cnt = 0; i < tris.size(); i += 3)
440  {
441  if (!triFlags[i / 3])
442  continue;
443 
444  // see if the boxes overlap
445  // Pt3d pMin(XM_DBL_HIGHEST), pMax(XM_DBL_LOWEST);
446  // gmAddToExtents(pts[tris[i + 0]], pMin, pMax);
447  // gmAddToExtents(pts[tris[i + 1]], pMin, pMax);
448  // gmAddToExtents(pts[tris[i + 2]], pMin, pMax);
449  // if (!gmBoxesOverlap2d(m_min, m_max, pMin, pMax)) continue;
450 
451  m_triIds[cnt] = (int)i;
452  // polys.push_back(vTri);
453  // polys.back()[0] = tris[i + 0];
454  // polys.back()[1] = tris[i + 1];
455  // polys.back()[2] = tris[i + 2];
456 
457  polys[cnt][0] = tris[i + 0];
458  polys[cnt][1] = tris[i + 1];
459  polys[cnt][2] = tris[i + 2];
460  ++cnt;
461  }
462 
463  BSHP<GmMultiPolyIntersectionSorterTerse> sorterTerse =
464  boost::make_shared<GmMultiPolyIntersectionSorterTerse>();
465  BSHP<GmMultiPolyIntersectionSorter> sorter = BDPC<GmMultiPolyIntersectionSorter>(sorterTerse);
466  m_intersect = GmMultiPolyIntersector::New(pts, polys, sorter);
467 } // XmBathymetryIntersectorImpl::CreateIntersector
468 //------------------------------------------------------------------------------
471 //------------------------------------------------------------------------------
473 {
474  VecPt3d& pts(m_tin->Points());
475  VecInt& tris(m_tin->Triangles());
476  VecInt triIds;
477  VecDbl tVals;
478  VecPt3d &line(a_pts), line1;
479  bool done = false;
480  if (line.size() > 0)
481  line1.push_back(line[0]);
482  for (size_t i = 1; !done && i < line.size(); ++i)
483  {
484  Pt3d &p0(line[i - 1]), &p1(line[i]);
485  m_intersect->TraverseLineSegment(p0.x, p0.y, p1.x, p1.y, triIds, tVals);
486  for (size_t j = 0; !done && j < triIds.size(); ++j)
487  {
488  if (triIds[j] < 0)
489  continue;
490 
491  // get the triangle id for the triangle in the TIN
492  int idx = m_triIds[triIds[j] - 1];
493  // do a 3d intersection with the segment and the triangle
494  int idx0(tris[idx]), idx1(tris[idx + 1]), idx2(tris[idx + 2]);
495  Pt3d iPt;
496  Pt3d &t0(pts[idx0]), &t1(pts[idx1]), &t2(pts[idx2]);
497  int rval = gmIntersectTriangleAndLineSegment(p0, p1, t0, t1, t2, iPt);
498  if (1 == rval)
499  {
500  if (!gmEqualPointsXY(p0, iPt, m_xyTol))
501  line1.push_back(iPt);
502  done = true;
503  }
504  }
505  if (!done)
506  line1.push_back(p1);
507  }
508  line.swap(line1);
509 } // XmBathymetryIntersectorImpl::Intersect3dPts
510 //------------------------------------------------------------------------------
515 //------------------------------------------------------------------------------
517  XmStamper3dPts& a_pts,
518  bool a_first)
519 {
520  int leftShoulder = a_io.m_cs[0].m_idxLeftShoulder;
521  int rightShoulder = a_io.m_cs[0].m_idxRightShoulder;
522  Pt3d clPt(a_io.m_centerLine[0]);
523  VecPt3d *xsLeft(&a_pts.m_xsPts.m_left[0]), *xsRight(&a_pts.m_xsPts.m_right[0]);
524  VecPt3d2d *lPtr(&a_pts.m_first_endcap.m_left), *rPtr(&a_pts.m_first_endcap.m_right);
525  if (!a_first)
526  {
527  leftShoulder = a_io.m_cs.back().m_idxLeftShoulder;
528  rightShoulder = a_io.m_cs.back().m_idxRightShoulder;
529  clPt = a_io.m_centerLine.back();
530  xsLeft = &a_pts.m_xsPts.m_left.back();
531  xsRight = &a_pts.m_xsPts.m_right.back();
532  lPtr = &a_pts.m_last_endcap.m_left;
533  rPtr = &a_pts.m_last_endcap.m_right;
534  }
535 
536  {
537  Pt3d ls(clPt);
538  if (leftShoulder - 1 < (int)xsLeft->size())
539  ls = (*xsLeft)[leftShoulder - 1];
540 
541  VecPt3d cl(lPtr->size(), ls);
542  IntersectXsectSide(cl, *lPtr);
543  }
544  {
545  Pt3d rs(clPt);
546  if (rightShoulder - 1 < (int)xsRight->size())
547  rs = (*xsRight)[rightShoulder - 1];
548 
549  VecPt3d cl(rPtr->size(), rs);
550  IntersectXsectSide(cl, *rPtr);
551  }
552 } // XmBathymetryIntersectorImpl::IntersectSlopedAbutment
553 //------------------------------------------------------------------------------
558 //------------------------------------------------------------------------------
560  XmStamper3dPts& a_pts,
561  bool a_first)
562 {
563  int leftShoulder = a_io.m_cs[0].m_idxLeftShoulder;
564  int rightShoulder = a_io.m_cs[0].m_idxRightShoulder;
565  Pt3d clPt(a_io.m_centerLine[0]);
566  VecPt3d *xsLeft(&a_pts.m_xsPts.m_left[0]), *xsRight(&a_pts.m_xsPts.m_right[0]),
567  *clPtr(&a_pts.m_first_endcap.m_centerLine);
568  VecPt3d2d *lPtr(&a_pts.m_first_endcap.m_left), *rPtr(&a_pts.m_first_endcap.m_right);
569  if (!a_first)
570  {
571  leftShoulder = a_io.m_cs.back().m_idxLeftShoulder;
572  rightShoulder = a_io.m_cs.back().m_idxRightShoulder;
573  clPt = a_io.m_centerLine.back();
574  xsLeft = &a_pts.m_xsPts.m_left.back();
575  xsRight = &a_pts.m_xsPts.m_right.back();
576  clPtr = &a_pts.m_last_endcap.m_centerLine;
577  lPtr = &a_pts.m_last_endcap.m_left;
578  rPtr = &a_pts.m_last_endcap.m_right;
579  }
580 
581  // first cut off the guidebank any where the center line intersects the
582  // bathymetry
583  VecPt3d cl(1, clPt);
584  cl.insert(cl.end(), clPtr->begin(), clPtr->end());
585  Intersect3dPts(cl);
586  if (cl.back() != clPtr->back())
587  {
588  size_t s(0);
589  if (cl.size() > 2)
590  s = cl.size() - 2;
591  clPtr->resize(s);
592  lPtr->resize(s);
593  rPtr->resize(s);
594  }
595  if (clPtr->empty())
596  return;
597 
598  // intersect cross sections
599  VecPt3d vCl(*clPtr);
600  vCl.resize(lPtr->size(), vCl.back());
601  IntersectXsectSide(vCl, *lPtr); // left side
602  IntersectXsectSide(*clPtr, *rPtr); // right side
603 
604 } // XmBathymetryIntersectorImpl::IntersectGuideBank
605 
606 //------------------------------------------------------------------------------
611 //------------------------------------------------------------------------------
612 BSHP<XmBathymetryIntersector> XmBathymetryIntersector::New(BSHP<TrTin> a_tin, BSHP<TrTin> a_stamp)
613 {
614  BSHP<XmBathymetryIntersector> p(new XmBathymetryIntersectorImpl(a_tin, a_stamp));
615  return p;
616 } // XmBathymetryIntersector::New
617 //------------------------------------------------------------------------------
619 //------------------------------------------------------------------------------
620 XmBathymetryIntersector::XmBathymetryIntersector()
621 {
622 } // XmBathymetryIntersector::XmBathymetryIntersector
623 //------------------------------------------------------------------------------
625 //------------------------------------------------------------------------------
626 XmBathymetryIntersector::~XmBathymetryIntersector()
627 {
628 } // XmBathymetryIntersector::~XmBathymetryIntersector
629 
630 } // namespace xms
631 
632 #ifdef CXX_TEST
633 //------------------------------------------------------------------------------
634 // Unit Tests
635 //------------------------------------------------------------------------------
636 using namespace xms;
638 
640 
641 //------------------------------------------------------------------------------
643 //------------------------------------------------------------------------------
645 {
646  BSHP<TrTin> t, s;
647  Pt3d pMin, pMax;
648  BSHP<XmBathymetryIntersector> p = XmBathymetryIntersector::New(t, s);
649  TS_ASSERT(p);
650 } // stXmampInterpCrossSectionTests::testCreateClass
651 //------------------------------------------------------------------------------
653 //------------------------------------------------------------------------------
655 {
656  BSHP<TrTin> tin = trBuildTin(), stTin;
657  VecPt3d& pts(tin->Points());
658  pts[3].z = pts[4].z = pts[7].z = pts[8].z = 10.0;
659  XmStamperIo io;
660  io.m_centerLine = {{7.5, -1, 5}, {7.5, 9, 5}, {15, 6, 5}};
661 
662  XmBathymetryIntersectorImpl b(tin, stTin);
663  b.IntersectCenterLine(io);
664  VecPt3d basePts = {{7.5, -1, 5}, {7.5, 2.5, 5}, {7.5, 9, 5}, {12.5, 7, 5}, {15, 6, 5}};
665  double tol(1e-2);
666  TS_ASSERT_DELTA_VECPT3D(basePts, io.m_centerLine, tol);
667 } // stXmampInterpCrossSectionTests::testIntersectCenterLine
668 //------------------------------------------------------------------------------
670 //------------------------------------------------------------------------------
672 {
673  BSHP<TrTin> tin = trBuildTin(), stTin;
674  VecPt3d& pts(tin->Points());
675  pts[3].z = pts[4].z = pts[7].z = pts[8].z = 10.0;
676 
677  XmStamper3dPts xpts;
678  xpts.m_xsPts.m_centerLine = {{5, 9, 11}};
679  xpts.m_xsPts.m_left.push_back(VecPt3d());
680  xpts.m_xsPts.m_left[0] = {{6, 9, 11}, {7, 9, 11}, {8, 9, 11}, {9, 9, 9}};
681 
682  XmBathymetryIntersectorImpl b(tin, stTin);
683  b.IntersectXsects(xpts);
684  VecPt3d basePts = {{6, 9, 11}, {7, 9, 11}, {8, 9, 11}, {8.5, 9, 10}};
685  double tol(1e-2);
686  TS_ASSERT_DELTA_VECPT3D(basePts, xpts.m_xsPts.m_left[0], tol);
687 } // XmBathymetryIntersectorUnitTests::testIntersectXsects
688 //------------------------------------------------------------------------------
691 //------------------------------------------------------------------------------
693 {
694  BSHP<TrTin> tin = trBuildTin(), stTin;
695  XmBathymetryIntersectorImpl b(tin, stTin);
696  VecPt3d pts = {{0, 0, 0}, {4, 6, 0}, {5, 5, 11}, {6, 6, -1}, {9, 9, 9.9}};
697  VecInt ptLoc;
698  b.ClassifyPoints(pts, ptLoc);
699  VecInt baseLoc = {-2, 0, 1, -2, 1};
700  TS_ASSERT_EQUALS_VEC(baseLoc, ptLoc);
701 
702  {
703  VecPt3d& pts(tin->Points());
704  pts[3].z = pts[4].z = pts[7].z = pts[8].z = 10.0;
705  }
706  b.ClassifyPoints(pts, ptLoc);
707  baseLoc = {-2, -1, 1, -2, -1};
708  TS_ASSERT_EQUALS_VEC(baseLoc, ptLoc);
709 
710 } // XmBathymetryIntersectorUnitTests::testClassifyPoints
711 //------------------------------------------------------------------------------
713 //------------------------------------------------------------------------------
715 {
716  BSHP<TrTin> tin = trBuildTin(), stTin;
717  VecPt3d& pts(tin->Points());
718  pts[1].z = 10;
719 
720  XmStamperIo io;
721  io.m_centerLine = {{5, -1, 5}, {11, 4, 5}};
722  io.m_cs.assign(io.m_centerLine.size(), XmStampCrossSection());
723 
724  XmBathymetryIntersectorImpl b(tin, stTin);
725  b.IntersectCenterLine(io);
726  std::vector<XmStamperIo> vIo;
727  b.DecomposeCenterLine(io, vIo);
728  TS_ASSERT_EQUALS(1, vIo.size());
729  if (vIo.size() == 1)
730  {
731  VecPt3d basePts = {{7.5, 1.083, 5}, {9.199, 2.5, 5}};
732  TS_ASSERT_DELTA_VECPT3D(basePts, vIo[0].m_centerLine, 1e-3);
733  }
734 
735  vIo.clear();
736  io.m_stampingType = 1;
737  b.DecomposeCenterLine(io, vIo);
738  TS_ASSERT_EQUALS(2, vIo.size());
739  if (vIo.size() == 2)
740  {
741  VecPt3d basePts = {{5, -1, 5}, {7.5, 1.083, 5}};
742  TS_ASSERT_DELTA_VECPT3D(basePts, vIo[0].m_centerLine, 1e-3);
743  basePts = {{9.199, 2.5, 5}, {11, 4, 5}};
744  TS_ASSERT_DELTA_VECPT3D(basePts, vIo[1].m_centerLine, 1e-3);
745  }
746 
747  vIo.clear();
748  io.m_stampingType = 1; // fill
749  io.m_centerLine = {{6, 2, -1}, {11, 4, -1}};
750  b.DecomposeCenterLine(io, vIo);
751  TS_ASSERT_EQUALS(0, vIo.size());
752 
753  io.m_stampingType = 0; // cut
754  b.DecomposeCenterLine(io, vIo);
755  TS_ASSERT_EQUALS(1, vIo.size());
756 
757  vIo.clear();
758  io.m_centerLine[0].z = 50; // set elevations above bathymetry
759  io.m_centerLine[1].z = 50;
760  b.DecomposeCenterLine(io, vIo);
761  TS_ASSERT_EQUALS(0, vIo.size());
762 
763 } // XmBathymetryIntersectorUnitTests::testDescomposeCenterLine
764 
765 //------------------------------------------------------------------------------
787 //------------------------------------------------------------------------------
788 BSHP<TrTin> trBuildTin()
789 {
790  BSHP<TrTin> tin = TrTin::New();
791 
792  tin->Points() = {{5, 0, 0}, {10, 0, 0}, {0, 5, 0}, {5, 5, 0}, {10, 5, 0},
793  {15, 5, 0}, {0, 10, 0}, {5, 10, 0}, {10, 10, 0}, {5, 15, 0}};
794  tin->Triangles() = {0, 3, 2, 0, 1, 3, 1, 4, 3, 1, 5, 4, 2, 3, 6,
795  3, 7, 6, 4, 8, 7, 4, 5, 8, 6, 7, 9, 7, 8, 9};
796  tin->BuildTrisAdjToPts();
797  return tin;
798 } // trBuildTin
799 #endif
void testClassifyPoints()
Tests point classification compared to the TIN (on, below, above, outside)
std::vector< int > VecInt
double m_xyTol
xy tolerance for geometry comparisons
BSHP< TrTin > trBuildTin()
Builds a simple TIN with a hole in the middle.
VecPt3d2d m_right
3d locations of cross section points
void testIntersectCenterLine()
Tests Intersecting center line with TIN.
int gmCartToBary(const Pt3d *cart, const Pt3d *orig, double coef[6], int dir, Pt3d *bary)
#define XM_NONE
static BSHP< XmBathymetryIntersector > New(BSHP< TrTin > a_tin, BSHP< TrTin > a_stamp)
Creates a XmStampInterpCrossSection class.
void testCreateClass()
Tests XmBathymetryIntersectorUnitTests.
virtual void IntersectCenterLine(XmStamperIo &a_io) override
Intersects the center line from a feature stamp operation with the bathemetry. This can potentially c...
bool gmEqualPointsXY(double x1, double y1, double x2, double y2, double tolerance)
std::vector< double > VecDbl
#define TS_ASSERT_DELTA_VECPT3D(a, b, delta)
Implementaion of XmBathymetryIntersector.
VecInt m_triIds
the ids of the triangles in the intersector
stXs3dPts m_last_endcap
3d locations of the last end cap
XmStamperEndCap m_firstEndCap
end cap at beginnig of polyline
Definition: XmStamperIo.h:195
static BSHP< GmTriSearch > New()
static boost::shared_ptr< GmMultiPolyIntersector > New(const std::vector< Pt3d > &a_points, const std::vector< std::vector< int > > &a_polys, boost::shared_ptr< GmMultiPolyIntersectionSorter > a_sorter, int a_startingId=1)
int gmIntersectTriangleAndLineSegment(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_t0, const Pt3d &a_t1, const Pt3d &a_t2, Pt3d &a_IntersectPt)
End cap definition for feature stamp.
Definition: XmStamperIo.h:120
BSHP< TrTin > m_stamp
TIN of the stamp.
void ClassifyPoints(VecPt3d &a_pts, VecInt &a_ptLocation)
Intersects the center line from a feature stamp operation with the bathemetry. This can potentially c...
VecPt3d m_centerLine
only used by guidebank
Intersects a feature stamp with a TIN.
void IntersectGuideBank(XmStamperIo &a_io, XmStamper3dPts &a_pts, bool a_first)
Intersects sloped abutment end cap cross section points.
BSHP< GmMultiPolyIntersector > m_intersect
polygon intersector for intersecting objects with the bathemetry TIN
boost::dynamic_bitset< size_t > DynBitset
std::vector< VecInt > VecInt2d
XmStamperEndCap m_lastEndCap
end cap at end of polyline
Definition: XmStamperIo.h:197
virtual void IntersectEndCaps(XmStamperIo &a_io, XmStamper3dPts &a_pts) override
Intersects end cap cross section points. When a cross section intersects the bathemetry it stops at t...
static BSHP< TrTin > New()
void Intersect3dPts(VecPt3d &a_pts)
Intersects a line with a surface.
#define XM_ENSURE_TRUE(...)
void IntersectSlopedAbutment(XmStamperIo &a_io, XmStamper3dPts &a_pts, bool a_first)
Intersects sloped abutment end cap cross section points.
XmBathymetryIntersectorImpl(BSHP< TrTin > a_tin, BSHP< TrTin > a_stamp)
int gmBaryPrepare(const Pt3d *p1, const Pt3d *p2, const Pt3d *p3, const Pt3d *norm, Pt3d *orig, double coef[6], int *dir, bool flag)
stXs3dPts m_first_endcap
3d locations of first end cap
class to hold 3d points generated by the stamping operation
void CreateIntersector()
Creates a multi poly intersector if one does not exist.
int m_type
type of end cap: 0- guidebank, 1- sloped abutment, 2- wing wall
Definition: XmStamperIo.h:129
void IntersectXsectSide(VecPt3d &a_cl, VecPt3d2d &a_side)
Intersects left or right side of a cross section with bathymetry.
bool EQ_TOL(const _T &A, const _U &B, const _V &tolerance)
Stamping inputs/outputs class.
Definition: XmStamperIo.h:171
std::vector< VecPt3d > VecPt3d2d
void testIntersectXsects()
Tests Intersecting cross sections with TIN.
virtual void IntersectXsects(XmStamper3dPts &a_pts) override
Intersects cross section points. When a cross section intersects the bathemetry it stops at that loca...
Cross section definition for stamping.
Definition: XmStamperIo.h:142
void testDescomposeCenterLine()
Splits up a center line based on intersections.
std::vector< XmStampCrossSection > m_cs
cross sections along the polyLine
Definition: XmStamperIo.h:193
double Mdist(_T x1, _U y1, _V x2, _W y2)
VecPt3d2d m_left
3d locations of cross section points
stXs3dPts m_xsPts
3d locations of cross section points
void gmAddToExtents(const Pt3d &a_pt, Pt3d &a_min, Pt3d &a_max)
BSHP< TrTin > m_tin
TIN defining Bathemetry surface.
#define TS_ASSERT_EQUALS_VEC(a, b)
int m_stampingType
Stamping type 0 - Cut, 1 - Fill, 2 - Both.
Definition: XmStamperIo.h:191
virtual void DecomposeCenterLine(XmStamperIo &a_io, std::vector< XmStamperIo > &a_vIo) override
Intersects the center line from a feature stamp operation with the bathemetry. This can potentially c...
std::vector< Pt3d > VecPt3d
VecPt3d m_centerLine
Definition: XmStamperIo.h:189