xmsgrid  1.0
GmTriSearch.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
8 //------------------------------------------------------------------------------
9 
10 //----- Included files ---------------------------------------------------------
11 
12 // 1. Precompiled header
13 
14 // 2. My header
16 
17 // 3. Standard Library Headers
18 
19 // 4. External Library Headers
20 #pragma warning(push)
21 #pragma warning(disable : 4512) // boost code: no assignment operator
22 #include <boost/geometry.hpp>
23 #include <boost/geometry/geometries/polygon.hpp>
24 #include <boost/geometry/index/rtree.hpp>
25 #include <boost/unordered_map.hpp>
26 #include <boost/iterator/counting_iterator.hpp>
27 #pragma warning(pop)
28 
29 // 5. Shared Headers
30 #include <xmscore/math/math.h>
31 #include <xmscore/stl/utility.h>
33 #include <xmsgrid/geometry/geoms.h>
35 #include <xmscore/misc/xmstype.h>
36 #include <xmscore/misc/XmError.h>
37 #include <xmscore/misc/XmConst.h>
38 
39 // 6. Non-shared Headers
40 
41 //----- Forward declarations ---------------------------------------------------
42 
43 //----- External globals -------------------------------------------------------
44 
45 //----- Namespace declaration --------------------------------------------------
46 namespace xms
47 {
48 namespace bg = boost::geometry;
49 namespace bgi = bg::index;
50 
51 typedef size_t value;
52 typedef bgi::quadratic<16> qRtree;
53 
54 //----- Constants / Enumerations -----------------------------------------------
55 
56 //----- Classes / Structs ------------------------------------------------------
57 
58 class GmTriSearchImpl;
59 
60 #define BARYTOL 1e-6
61 
62 class idx_tri
64 {
65 public:
66  typedef const GmBstBox3d result_type;
67  explicit idx_tri(const Pt3d* a_pts, const int* a_tris, double a_tol)
72  : m_pts(a_pts)
73  , m_tris(a_tris)
74  , m_tol(a_tol)
75  {
76  }
80  result_type operator()(size_t i) const
81  {
82  i *= 3;
83  const Pt3d& p0(m_pts[m_tris[i]]);
84  const Pt3d& p1(m_pts[m_tris[i + 1]]);
85  const Pt3d& p2(m_pts[m_tris[i + 2]]);
86  GmBstBox3d b;
87  b.max_corner() = b.min_corner() = p0;
88  if (b.min_corner().x > p1.x)
89  b.min_corner().x = p1.x;
90  if (b.min_corner().x > p2.x)
91  b.min_corner().x = p2.x;
92  if (b.max_corner().x < p1.x)
93  b.max_corner().x = p1.x;
94  if (b.max_corner().x < p2.x)
95  b.max_corner().x = p2.x;
96 
97  if (b.min_corner().y > p1.y)
98  b.min_corner().y = p1.y;
99  if (b.min_corner().y > p2.y)
100  b.min_corner().y = p2.y;
101  if (b.max_corner().y < p1.y)
102  b.max_corner().y = p1.y;
103  if (b.max_corner().y < p2.y)
104  b.max_corner().y = p2.y;
105  b.min_corner() -= m_tol;
106  b.max_corner() += m_tol;
107  return b;
108  }
109  const Pt3d* m_pts;
110  const int* m_tris;
111  double m_tol;
112 };
113 
116 {
118  double coef[6];
119  int dir;
120 };
121 
125 {
126 public:
127  GmTriSearchImpl();
128  virtual ~GmTriSearchImpl();
129  virtual void TrisToSearch(BSHP<std::vector<Pt3d>> a_pts, BSHP<std::vector<int>> a_tris) override;
130  virtual void SetPtActivity(DynBitset& a_activity) override;
131  virtual void SetTriActivity(DynBitset& a_activity) override;
134  virtual DynBitset GetPtActivity() const override { return PointActivityFromTriActivity(); }
135  virtual DynBitset GetTriActivity() const override;
136  bool ActiveTri(int a_idx) const;
137  virtual int TriContainingPt(const Pt3d& a_pt) override;
138  virtual void TriEnvelopsContainingPt(const Pt3d& a_pt, std::vector<int>& a_tris) override;
139  virtual void TriEnvelopesOverlap(const Pt3d& a_pMin,
140  const Pt3d& a_pMax,
141  std::vector<int>& a_tris) override;
142 
143  virtual bool InterpWeights(const Pt3d& a_pt,
144  std::vector<int>& a_idxs,
145  std::vector<double>& a_wts) override;
146  virtual bool InterpWeightsTriangleIdx(const Pt3d& a_pt,
147  int& a_triangleIdx,
148  std::vector<int>& a_idxs,
149  std::vector<double>& a_wts) override;
150  virtual const BSHP<VecPt3d> GetPoints() const override;
151  virtual const BSHP<VecInt> GetTriangles() const override;
152 
153  virtual std::string ToString() const override;
154 
155  void CreateRTree();
156 
157  void PointIdxesFromTriIdx(int a_triIdx, int a_ptIdxes[3]);
158  int FindTriangle(const Pt3d& a_pt, int ix[3], Pt3d& weights);
159  void GetTriBarycentricVals(int a_idx, int a_ix[3], BarycentricVals& a_b);
160 
162  BSHP<GmPtSearch> CreatePtSearch();
163 
166 
167  BSHP<std::vector<Pt3d>> m_pts;
168  BSHP<std::vector<int>> m_tris;
170 
173  boost::unordered_map<size_t, BarycentricVals> m_cache;
175  bgi::rtree<value, qRtree, idx_tri>* m_rTree;
176 };
177 
178 //----- Internal functions -----------------------------------------------------
179 
180 //------------------------------------------------------------------------------
187 //------------------------------------------------------------------------------
188 void iCartToBary(const Pt3d& a_pt1, const Pt3d& a_pt2, const Pt3d& a_pt3, BarycentricVals& a_b)
189 {
190  Pt3d a(a_pt1.x, a_pt1.y, 0.0);
191  Pt3d b(a_pt2.x, a_pt2.y, 0.0);
192  Pt3d c(a_pt3.x, a_pt3.y, 0.0);
193  Pt3d norm(0, 0, 1);
194  gmBaryPrepare(&a, &b, &c, &norm, &a_b.orig, a_b.coef, &a_b.dir, true);
195 } // iCartToBary
196 //------------------------------------------------------------------------------
202 //------------------------------------------------------------------------------
203 void iGetBarycentricCoords(const Pt3d& a_p, BarycentricVals& a_b, Pt3d& weights)
204 {
205  Pt3d p(a_p.x, a_p.y, 0.0);
206  gmCartToBary(&p, &a_b.orig, a_b.coef, a_b.dir, &weights);
207 } // iGetBarycentricCoords
208 
209 //----- Class / Function definitions -------------------------------------------
210 
211 //------------------------------------------------------------------------------
214 //------------------------------------------------------------------------------
215 BSHP<GmTriSearch> GmTriSearch::New()
216 {
217  BSHP<GmTriSearch> ptr(new GmTriSearchImpl());
218  return ptr;
219 } // TriSearch::New
220 //------------------------------------------------------------------------------
222 //------------------------------------------------------------------------------
224 {
225 } // TriSearch::TriSearch
226 //------------------------------------------------------------------------------
228 //------------------------------------------------------------------------------
230 {
231 } // TriSearch::~TriSearch
232 
238 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
242 : m_min(XM_FLT_HIGHEST)
243 , m_max(XM_FLT_LOWEST)
244 , m_pts(new std::vector<Pt3d>())
245 , m_tris(new std::vector<int>())
246 , m_triActivity()
247 , m_rTree(nullptr)
248 {
249 } // GmTriSearchImpl::GmTriSearchImpl
250 //------------------------------------------------------------------------------
252 //------------------------------------------------------------------------------
254 {
255  if (m_rTree)
256  delete (m_rTree);
257 } // GmTriSearchImpl::~GmTriSearchImpl
258 //------------------------------------------------------------------------------
265 //------------------------------------------------------------------------------
266 void GmTriSearchImpl::TrisToSearch(BSHP<std::vector<Pt3d>> a_pts, BSHP<std::vector<int>> a_tris)
267 {
268  // remove existing rtree and cache
269  if (m_rTree)
270  delete (m_rTree);
271  m_cache.clear();
272 
273  m_pts = a_pts;
274  m_tris = a_tris;
275  CreateRTree();
276 } // GmTriSearchImpl::TrisToSearch
277 //------------------------------------------------------------------------------
279 //------------------------------------------------------------------------------
281 {
282  if (m_pts->empty() || m_tris->empty())
283  return;
284 
285  m_min = XM_FLT_HIGHEST;
286  m_max = XM_FLT_LOWEST;
287  for (size_t i = 0; i < m_pts->size(); ++i)
288  {
289  Pt3d& pt = (*m_pts)[i];
290  if (pt.x < m_min.x)
291  m_min.x = pt.x;
292  if (pt.y < m_min.y)
293  m_min.y = pt.y;
294  if (pt.z < m_min.z)
295  m_min.z = pt.z;
296  if (pt.x > m_max.x)
297  m_max.x = pt.x;
298  if (pt.y > m_max.y)
299  m_max.y = pt.y;
300  if (pt.z > m_max.z)
301  m_max.z = pt.z;
302  }
303  double tol = sqr(m_max.x - m_min.x) + sqr(m_max.y - m_min.y);
304  tol = sqrt(tol) / 1e9;
305 
306  qRtree rtree;
307  size_t nTri = m_tris->size() / 3;
308  idx_tri getter(&(*m_pts)[0], &(*m_tris)[0], tol);
309  m_rTree = new bgi::rtree<size_t, qRtree, idx_tri>(
310  boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(nTri), rtree, getter);
311 } // GmTriSearchImpl::CreateRTree
312 //------------------------------------------------------------------------------
315 //------------------------------------------------------------------------------
317 {
318  XM_ENSURE_TRUE_NO_ASSERT(a_activity.size() == m_pts->size());
319 
320  // set triangle activity from point activity
321  m_triActivity.clear();
322  m_triActivity.resize(m_tris->size(), 1);
323  for (size_t i = 0; i < m_tris->size(); i += 3)
324  {
325  if (!a_activity.test((*m_tris)[i]) || !a_activity.test((*m_tris)[i + 1]) ||
326  !a_activity.test((*m_tris)[i + 2]))
327  {
328  m_triActivity[i] = m_triActivity[i + 1] = m_triActivity[i + 2] = 0;
329  }
330  }
331 } // GmTriSearchImpl::SetPtActivity
332 //------------------------------------------------------------------------------
335 //------------------------------------------------------------------------------
337 {
338  if (a_activity.empty())
339  {
340  m_triActivity = a_activity;
341  return;
342  }
343 
344  XM_ENSURE_TRUE_NO_ASSERT(a_activity.size() == m_tris->size() / 3);
345 
346  m_triActivity.reset();
347  m_triActivity.resize(m_tris->size(), 1);
348  size_t idx;
349  for (size_t i = 0; i < a_activity.size(); ++i)
350  {
351  idx = i * 3;
352  m_triActivity[idx + 0] = a_activity[i];
353  m_triActivity[idx + 1] = a_activity[i];
354  m_triActivity[idx + 2] = a_activity[i];
355  }
356 } // GmTriSearchImpl::SetTriActivity
357 //------------------------------------------------------------------------------
360 //------------------------------------------------------------------------------
362 {
363  DynBitset rval;
364  if (m_triActivity.empty() || m_tris->empty())
365  return rval;
366  rval.resize(m_tris->size() / 3, 1);
367  for (size_t i = 0; i < rval.size(); ++i)
368  {
369  size_t idx = i * 3;
370  rval[i] = m_triActivity[idx];
371  }
372  return rval;
373 } // GmTriSearchImpl::GetTriActivity
374 //------------------------------------------------------------------------------
379 //------------------------------------------------------------------------------
380 bool GmTriSearchImpl::ActiveTri(int a_idx) const
381 {
382  if (m_triActivity.empty())
383  return true;
384  if (!m_triActivity.test(a_idx))
385  return false;
386  return true;
387 } // GmTriSearchImpl::ActiveTri
388 //------------------------------------------------------------------------------
393 //------------------------------------------------------------------------------
395 {
396  int ix[3];
397  Pt3d weights;
398  return FindTriangle(a_pt, ix, weights);
399 } // GmTriSearchImpl::TriContainingPt
400 //------------------------------------------------------------------------------
404 //------------------------------------------------------------------------------
406 {
407  int idx;
408  a_tris.resize(0);
409  Pt3d p(a_pt.x, a_pt.y, 0);
410  std::vector<value> vals;
411  m_rTree->query(bgi::intersects(p), std::back_inserter(vals));
412  for (size_t i = 0; i < vals.size(); ++i)
413  {
414  idx = (int)(vals[i] * 3);
415  a_tris.push_back(idx);
416  }
417 } // GmTriSearchImpl::TriEnvelopsContainingPt
418 //------------------------------------------------------------------------------
425 //------------------------------------------------------------------------------
426 void GmTriSearchImpl::TriEnvelopesOverlap(const Pt3d& a_pMin, const Pt3d& a_pMax, VecInt& a_tris)
427 {
428  GmBstBox3d bx;
429  bx.max_corner() = a_pMax;
430  bx.max_corner().z = 0;
431  bx.min_corner() = a_pMin;
432  bx.min_corner().z = 0;
433  int idx;
434  a_tris.resize(0);
435  std::vector<value> vals;
436  // m_rTree->query(bgi::overlaps(bx), std::back_inserter(vals));
437  m_rTree->query(bgi::intersects(bx), std::back_inserter(vals));
438  for (size_t i = 0; i < vals.size(); ++i)
439  {
440  idx = (int)(vals[i] * 3);
441  a_tris.push_back(idx);
442  }
443 } // GmTriSearchImpl::TriContainingPt
444 //------------------------------------------------------------------------------
451 //------------------------------------------------------------------------------
452 bool GmTriSearchImpl::InterpWeights(const Pt3d& a_pt, VecInt& a_idxs, VecDbl& a_wts)
453 {
454  int triangleIdx;
455  bool result = InterpWeightsTriangleIdx(a_pt, triangleIdx, a_idxs, a_wts);
456  return result;
457 } // GmTriSearchImpl::InterpWeights
458 //------------------------------------------------------------------------------
467 //------------------------------------------------------------------------------
468 bool GmTriSearchImpl::InterpWeightsTriangleIdx(const Pt3d& a_pt, int& a_triangleIdx,
469  VecInt& a_idxs, VecDbl& a_wts)
470 {
471  int ix[3];
472  Pt3d weights;
473  a_triangleIdx = FindTriangle(a_pt, ix, weights);
474  if (a_triangleIdx != XM_NONE)
475  {
476  a_wts.resize(0);
477  a_wts.push_back(weights.x);
478  a_wts.push_back(weights.y);
479  a_wts.push_back(weights.z);
480  a_idxs.assign(ix, ix + 3);
481  return true;
482  }
483  else
484  {
485  a_idxs.clear();
486  a_wts.clear();
487  }
488  return false;
489 } // GmTriSearchImpl::InterpWeightsTriangleIdx
490 //------------------------------------------------------------------------------
493 //------------------------------------------------------------------------------
494 const BSHP<VecPt3d> GmTriSearchImpl::GetPoints() const
495 {
496  return m_pts;
497 } // GmTriSearchImpl::GetPoints
498 //------------------------------------------------------------------------------
501 //------------------------------------------------------------------------------
502 const BSHP<VecInt> GmTriSearchImpl::GetTriangles() const
503 {
504  return m_tris;
505 } // GmTriSearchImpl::GetTriangles
506 //------------------------------------------------------------------------------
509 //------------------------------------------------------------------------------
510 std::string GmTriSearchImpl::ToString() const
511 {
512  std::stringstream ss;
513  ss << m_min << "=min" << m_max << "=max"
514  << "\n";
515 
516  if (m_pts)
517  VecToStream(ss, *m_pts, "pts");
518  if (m_tris)
519  VecToStream(ss, *m_tris, "tris");
520  VecToStream(ss, m_triActivity, "triActivity");
521  return ss.str();
522 } // GmTriSearchImpl::ToString
523 //------------------------------------------------------------------------------
528 //------------------------------------------------------------------------------
529 void GmTriSearchImpl::PointIdxesFromTriIdx(int a_triIdx, int a_ptIdxes[3])
530 {
531  a_ptIdxes[0] = a_ptIdxes[1] = a_ptIdxes[2] = -1;
532  if (a_triIdx < 0 || a_triIdx + 2 >= (int)m_tris->size())
533  {
534  std::stringstream msg;
535  msg << "Index out of range. File: " << __FILE__ << ", Line:" << __LINE__;
536  XM_LOG(xmlog::debug, msg.str());
537  return;
538  }
539  a_ptIdxes[0] = (*m_tris)[a_triIdx + 0];
540  a_ptIdxes[1] = (*m_tris)[a_triIdx + 1];
541  a_ptIdxes[2] = (*m_tris)[a_triIdx + 2];
542 } // GmTriSearchImpl::PointIdxesFromTriIdx
543 //------------------------------------------------------------------------------
549 //------------------------------------------------------------------------------
550 int GmTriSearchImpl::FindTriangle(const Pt3d& a_pt, int ix[3], Pt3d& weights)
551 {
552  if (!m_tris || m_tris->empty() || !m_pts || m_pts->empty())
553  {
554  XM_LOG(xmlog::error, "Unable to find triangle; no points or triangles exist.");
555  return XM_NONE;
556  }
557  Pt3d p(a_pt.x, a_pt.y, 0);
558  std::vector<value> vals;
559  m_rTree->query(bgi::intersects(p), std::back_inserter(vals));
560  if (vals.empty())
561  return XM_NONE;
562 
563  size_t idx;
564  for (size_t i = 0; i < vals.size(); ++i)
565  {
566  idx = vals[i] * 3;
567  // if any point is inactive then skip this triangle
568  if (!ActiveTri((int)idx))
569  continue;
570  ix[0] = (*m_tris)[idx];
571  ix[1] = (*m_tris)[idx + 1];
572  ix[2] = (*m_tris)[idx + 2];
573 
574  GmBstPoly3d poly;
575  for (size_t j = 0; j < 3; ++j)
576  {
577  bg::exterior_ring(poly).push_back((*m_pts)[ix[j]]);
578  }
579  bg::exterior_ring(poly).push_back((*m_pts)[ix[0]]);
580  if (bg::covered_by(a_pt, poly))
581  {
582  BarycentricVals b;
583  GetTriBarycentricVals((int)idx, ix, b);
584  iGetBarycentricCoords(p, b, weights);
585  return (int)idx;
586  }
587  }
588  // additional checks with some tolerancing
589  for (size_t i = 0; i < vals.size(); ++i)
590  {
591  idx = vals[i] * 3;
592  // if any point is inactive then skip this triangle
593  if (!ActiveTri((int)idx))
594  continue;
595  ix[0] = (*m_tris)[idx];
596  ix[1] = (*m_tris)[idx + 1];
597  ix[2] = (*m_tris)[idx + 2];
598  BarycentricVals b;
599  GetTriBarycentricVals((int)idx, ix, b);
600  iGetBarycentricCoords(p, b, weights);
601  // if (GTEQ_TOL(weights.x, 0, BARYTOL) && GTEQ_TOL(weights.y, 0, BARYTOL) &&
602  // GTEQ_TOL(weights.z, 0, BARYTOL)) {
603  if (weights.x >= -BARYTOL && weights.y >= -BARYTOL && weights.z >= -BARYTOL)
604  {
605  return (int)idx;
606  }
607  }
608 
609  return XM_NONE;
610 } // GmTriSearchImpl::FindTriangle
611 //------------------------------------------------------------------------------
616 //------------------------------------------------------------------------------
617 void GmTriSearchImpl::GetTriBarycentricVals(int a_idx, int a_ix[3], BarycentricVals& a_b)
618 {
619  if (m_cache.find(a_idx) != m_cache.end())
620  {
621  a_b = m_cache[a_idx];
622  }
623  else
624  {
625  iCartToBary((*m_pts)[a_ix[0]], (*m_pts)[a_ix[1]], (*m_pts)[a_ix[2]], a_b);
626  m_cache[a_idx] = a_b;
627  }
628 } // GmTriSearchImpl::GetTriBarycentricVals
629 //------------------------------------------------------------------------------
632 //------------------------------------------------------------------------------
634 {
635  DynBitset r;
636  if (m_triActivity.empty())
637  return r;
638 
639  // all points inactive, if any triangle attached to point is active then
640  // the point will be active
641  r.resize(m_pts->size(), 0);
642  for (size_t i = 0; i < m_tris->size(); i += 3)
643  {
644  if (ActiveTri((int)i))
645  {
646  r[(*m_tris)[i + 0]] = 1;
647  r[(*m_tris)[i + 1]] = 1;
648  r[(*m_tris)[i + 2]] = 1;
649  }
650  }
651  return r;
652 } // GmTriSearchImpl::PointActivityFromTriActivity
653 //------------------------------------------------------------------------------
656 //------------------------------------------------------------------------------
658 {
659  BSHP<GmPtSearch> pts = GmPtSearch::New(true);
660  pts->PtsToSearch(m_pts);
662  pts->SetActivity(b);
663  return pts;
664 } // GmTriSearchImpl::CreatePtSearch
665 
666 } // namespace xms
667 
668 #ifdef CXX_TEST
669 
672 
674 
677 
678 using namespace xms;
679 
684 //------------------------------------------------------------------------------
686 //------------------------------------------------------------------------------
688 {
689  boost::shared_ptr<GmTriSearch> pts = GmTriSearch::New();
690  TS_ASSERT(pts);
691 }
692 //------------------------------------------------------------------------------
694 //------------------------------------------------------------------------------
696 {
697  boost::shared_ptr<GmTriSearch> tris = GmTriSearch::New();
698  BSHP<std::vector<Pt3d>> p(new std::vector<Pt3d>());
699  *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
700  BSHP<std::vector<int>> t(new std::vector<int>());
701  *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
702  tris->TrisToSearch(p, t);
703 
704  std::vector<int> idxs, baseIdx;
705  std::vector<double> wt, baseWt;
706  Pt3d pt(.5, .2, 0);
707  TS_ASSERT(tris->InterpWeights(pt, idxs, wt));
708  baseIdx = {0, 2, 1};
709  baseWt = {.5, .3, .2};
710  TS_ASSERT_EQUALS_VEC(baseIdx, idxs);
711  TS_ASSERT_DELTA_VEC(baseWt, wt, 1e-7);
712 
713  int triangleIdx;
714  TS_ASSERT(tris->InterpWeightsTriangleIdx({.25, .75, 0}, triangleIdx, idxs, wt));
715  TS_ASSERT_EQUALS(3, triangleIdx);
716  baseIdx = {0, 1, 3};
717  TS_ASSERT_EQUALS_VEC(baseIdx, idxs);
718  baseWt = {.25, .25, .5};
719  TS_ASSERT_DELTA_VEC(baseWt, wt, 1e-7);
720 
721  TS_ASSERT(!tris->InterpWeightsTriangleIdx({0, 1.25, 0}, triangleIdx, idxs, wt));
722  TS_ASSERT_EQUALS(XM_NONE, triangleIdx);
723  TS_ASSERT_EQUALS_VEC(VecInt(), idxs);
724  TS_ASSERT_DELTA_VEC(VecDbl(), wt, 1e-7);
725 } // TriSearchUnitTests::testInterpWeights
726 //------------------------------------------------------------------------------
728 //------------------------------------------------------------------------------
730 {
731  BSHP<GmTriSearch> tris = GmTriSearch::New();
732  BSHP<std::vector<Pt3d>> p(new std::vector<Pt3d>());
733  *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
734  BSHP<std::vector<int>> t(new std::vector<int>());
735  *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
736  tris->TrisToSearch(p, t);
737 
738  DynBitset act_wrongSize(6);
739  // won't do anything
740  tris->SetPtActivity(act_wrongSize);
741 
742  Pt3d pt(.5, .2, 0);
743  TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
744 
745  DynBitset act(5);
746  act.flip();
747  act.set(1, false);
748  tris->SetPtActivity(act);
749 
750  TS_ASSERT_EQUALS(XM_NONE, tris->TriContainingPt(pt));
751 } // TriSearchUnitTests::testPtActivity
752 //------------------------------------------------------------------------------
754 //------------------------------------------------------------------------------
756 {
757  BSHP<GmTriSearch> tris = GmTriSearch::New();
758  BSHP<std::vector<Pt3d>> p(new std::vector<Pt3d>());
759  *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
760  BSHP<std::vector<int>> t(new std::vector<int>());
761  *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
762  tris->TrisToSearch(p, t);
763 
764  DynBitset act_wrongSize(4);
765  // won't do anything
766  tris->SetTriActivity(act_wrongSize);
767 
768  Pt3d pt(.5, .2, 0), pt2(.5, .5, 0);
769  TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
770  // pt2 is right on the boundary between first two triangles
771  TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
772 
773  DynBitset act(3);
774  act.flip();
775  act.set(0, false);
776  tris->SetTriActivity(act);
777 
778  TS_ASSERT_EQUALS(XM_NONE, tris->TriContainingPt(pt));
779  TS_ASSERT_EQUALS(3, tris->TriContainingPt(pt2));
780 
781  // setting to empty activity turns on everything
782  act.clear();
783  tris->SetTriActivity(act);
784  TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
785  TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
786 } // TriSearchUnitTests::testPtActivity
787 //------------------------------------------------------------------------------
789 //------------------------------------------------------------------------------
791 {
792  Pt3d pt(-31.459823375717541, 29.927133417260336, 0);
793  GmTriSearchImpl tris;
794  BSHP<std::vector<Pt3d>> p(new std::vector<Pt3d>());
795  *p = {{-20.150000000000002, 46.579999999999998, 7},
796  {-41.100000000000001, 30.370000000000001, 8},
797  {-19.550000000000001, 29.379999999999999, 9}};
798  BSHP<std::vector<int>> t(new std::vector<int>());
799  *t = {2, 0, 1};
800  tris.TrisToSearch(p, t);
801  TS_ASSERT_EQUALS(0, tris.TriContainingPt(pt));
802 } // TriSearchUnitTests::testCase1
803 //------------------------------------------------------------------------------
805 //------------------------------------------------------------------------------
807 {
808  Pt3d pt(.5, .5, 0);
809  GmTriSearchImpl tris;
810  BSHP<std::vector<Pt3d>> p(new std::vector<Pt3d>());
811  *p = {{0, 0, 7}, {1, 0, 8}, {1, 1, 9}};
812  BSHP<std::vector<int>> t(new std::vector<int>());
813  *t = {2, 0, 1};
814  tris.TrisToSearch(p, t);
815  TS_ASSERT_EQUALS(0, tris.TriContainingPt(pt));
816 } // TriSearchUnitTests::testTouch
817 //------------------------------------------------------------------------------
819 //------------------------------------------------------------------------------
821 {
822  BSHP<TrTin> t = trBuildTestTin();
823  GmTriSearchImpl ts;
824  BSHP<VecInt> tPtr(new VecInt());
825  tPtr->reserve(t->Triangles().size());
826  for (const auto& tt : t->Triangles())
827  tPtr->push_back((int)tt);
828  ts.TrisToSearch(t->PointsPtr(), tPtr);
829 
830  Pt3d pMin(9, 4, 0), pMax(15, 10, 0);
831  VecInt tIdxes;
832  ts.TriEnvelopesOverlap(pMin, pMax, tIdxes);
833  std::sort(tIdxes.begin(), tIdxes.end());
834  VecInt baseIdxes = {3, 6, 9, 18, 21, 27};
835  TS_ASSERT_EQUALS_VEC(baseIdxes, tIdxes);
836 } // TriSearchUnitTests::testTriEnvelopesOverlap
837 
838 #endif // CXX_TEST
provides indexing for the spatial index
Definition: GmTriSearch.cpp:63
#define XM_LOG(A, B)
std::vector< int > VecInt
virtual void TriEnvelopsContainingPt(const Pt3d &a_pt, std::vector< int > &a_tris) override
Find all triangles whose envelope contains the point.
virtual DynBitset GetPtActivity() const override
Activity of the points based on the triangle activity.
virtual void TrisToSearch(BSHP< std::vector< Pt3d >> a_pts, BSHP< std::vector< int >> a_tris) override
Adds the triangles to the class.
#define XM_NONE
void testPtActivity()
tests setting the point activity
#define BARYTOL
This is an odd duck tolerance.
Definition: GmTriSearch.cpp:60
Structure for Barycentric coordinate calculations.
virtual ~GmTriSearchImpl()
Destructor.
std::vector< double > VecDbl
BSHP< std::vector< Pt3d > > m_pts
point locations
size_t value
value
Definition: GmPtSearch.cpp:87
virtual void TriEnvelopesOverlap(const Pt3d &a_pMin, const Pt3d &a_pMax, std::vector< int > &a_tris) override
Find all triangles whose envelope overlaps the envelope defined by a_pMin and a_pMax.
boost::geometry types
BSHP< std::vector< int > > m_tris
triangles that reference point indexes
static BSHP< GmTriSearch > New()
Creates an TriSearch class.
BSHP< TrTin > trBuildTestTin()
Builds a simple TIN with a hole in the middle.
Definition: TrTin.cpp:1451
int FindTriangle(const Pt3d &a_pt, int ix[3], Pt3d &weights)
Find the triangle containing the location a_pt.
const GmBstBox3d result_type
Definition: GmTriSearch.cpp:66
#define XM_ENSURE_TRUE_NO_ASSERT(...)
DynBitset m_triActivity
activity of the triangles
An intersection point of a line with a polygon.
bgi::quadratic< 8 > qRtree
qRtree
Definition: GmPtSearch.cpp:89
void VecToStream(std::stringstream &a_ss, const T &a_v, std::string a_label)
Spatial index for searching triangles.
Definition: GmTriSearch.h:29
void testCreateClass()
tests creating the class
const Pt3d * m_pts
point locations
void testInterpWeights()
tests calculation of interpolation weights from triangles
boost::dynamic_bitset< size_t > DynBitset
double coef[6]
barycentric coefficients
boost::unordered_map< size_t, BarycentricVals > m_cache
virtual DynBitset GetTriActivity() const override
Gets the activity bitset of the triangles.
Functions dealing with geometry.
void testTriEnvelopesOverlap()
tests overlaping triangles
Pt3d m_max
maximum extents of all points
double m_tol
tolerance used to expand extents of triangle
const int * m_tris
triangles referencing point indexes
idx_tri(const Pt3d *a_pts, const int *a_tris, double a_tol)
Definition: GmTriSearch.cpp:71
virtual bool InterpWeightsTriangleIdx(const Pt3d &a_pt, int &a_triangleIdx, std::vector< int > &a_idxs, std::vector< double > &a_wts) override
Use the stored triangles to get interpolation weights for a point. Returns false if the point is outs...
Pt3d orig
original point location
_T sqr(const _T x)
virtual const BSHP< VecPt3d > GetPoints() const override
Returns the points.
result_type operator()(size_t i) const
calculates triangle extents based on a triangle index
Definition: GmTriSearch.cpp:80
#define BSHP
boost::geometry::model::polygon< Pt3d > GmBstPoly3d
Boost polygon 3d.
Definition: GmBoostTypes.h:39
void GetTriBarycentricVals(int a_idx, int a_ix[3], BarycentricVals &a_b)
Gets the barycentric values for a triangle.
void iCartToBary(const Pt3d &a_pt1, const Pt3d &a_pt2, const Pt3d &a_pt3, BarycentricVals &a_b)
Converts from Cartesian coordinates to Barycentric coordinates (local triangle coords).
boost::geometry::model::box< Pt3d > GmBstBox3d
Boost box 3d.
Definition: GmBoostTypes.h:41
bool ActiveTri(int a_idx) const
Tests if a triangle is active. If any of the points of the tri are not active then the tri is not act...
XMS Namespace.
Definition: geoms.cpp:34
DynBitset PointActivityFromTriActivity() const
Gets the activity of the points from the triangles.
Pt3d m_min
mininum extents of all points
void iGetBarycentricCoords(const Pt3d &a_p, BarycentricVals &a_b, Pt3d &weights)
Calculates weights at the 3 points of a triangle given the location "a_p" and the Barycentric coords ...
static BSHP< GmPtSearch > New(bool a_2dSearch)
Creates an PtSearch class.
Definition: GmPtSearch.cpp:235
GmTriSearchImpl()
Constructor.
virtual const BSHP< VecInt > GetTriangles() const override
Returns the triangles.
virtual void SetTriActivity(DynBitset &a_activity) override
Modifies the activity bitset of the triangles.
virtual bool InterpWeights(const Pt3d &a_pt, std::vector< int > &a_idxs, std::vector< double > &a_wts) override
Use the stored triangles to get interpolation weights for a point. Returns false if the point is outs...
BSHP< GmPtSearch > CreatePtSearch()
creates the rtree of the points
int gmCartToBary(const Pt3d *cart, const Pt3d *orig, double coef[6], int dir, Pt3d *bary)
Compute Barycentric coords for point. Use gmBaryPrepare to get the coefficients and direction...
Definition: geoms.cpp:275
virtual void SetPtActivity(DynBitset &a_activity) override
Modifies the activity bitset of the points.
GmTriSearch()
Constructor.
int gmBaryPrepare(const Pt3d *p1, const Pt3d *p2, const Pt3d *p3, const Pt3d *norm, Pt3d *orig, double coef[6], int *dir, bool flag)
For a tri - compute dir & coefs to compute Barycentric coords.
Definition: geoms.cpp:315
virtual int TriContainingPt(const Pt3d &a_pt) override
Find the triangle containing the point.
bgi::rtree< value, qRtree, idx_tri > * m_rTree
spatial index of the triangle extents
#define TS_ASSERT_EQUALS_VEC(a, b)
int dir
direction based on the xyz&#39;s of the points making the triangle
virtual ~GmTriSearch()
Destructor.
void testSmsCase1()
A particular test case from SMS that was included.
void testTriActivity()
tests setting the triangle activity
void testTouch()
tests a point that touches a triangle
#define TS_ASSERT_DELTA_VEC(a, b, delta)
virtual std::string ToString() const override
Write the internals to a string.
Implementation of GmTriSearch.
void PointIdxesFromTriIdx(int a_triIdx, int a_ptIdxes[3])
Fills in the point indices based on the triangle index.
void CreateRTree()
Creates the RTree of the triangles.