22 #pragma warning(disable : 4512) // boost code: no assignment operator
23 #include <boost/geometry.hpp>
24 #include <boost/geometry/geometries/polygon.hpp>
25 #include <boost/geometry/index/rtree.hpp>
26 #include <boost/unordered_map.hpp>
27 #include <boost/iterator/counting_iterator.hpp>
49 namespace bg = boost::geometry;
50 namespace bgi = bg::index;
53 typedef bgi::quadratic<16> qRtree;
68 explicit idx_tri(
const Pt3d* a_pts,
const int* a_tris,
double a_tol)
88 b.max_corner() = b.min_corner() = p0;
89 if (b.min_corner().x > p1.
x)
90 b.min_corner().
x = p1.
x;
91 if (b.min_corner().x > p2.
x)
92 b.min_corner().x = p2.
x;
93 if (b.max_corner().x < p1.
x)
94 b.max_corner().x = p1.
x;
95 if (b.max_corner().x < p2.
x)
96 b.max_corner().x = p2.
x;
98 if (b.min_corner().y > p1.
y)
99 b.min_corner().y = p1.
y;
100 if (b.min_corner().y > p2.
y)
101 b.min_corner().y = p2.
y;
102 if (b.max_corner().y < p1.
y)
103 b.max_corner().y = p1.
y;
104 if (b.max_corner().y < p2.
y)
105 b.max_corner().y = p2.
y;
106 b.min_corner() -=
m_tol;
107 b.max_corner() +=
m_tol;
130 virtual void TrisToSearch(
BSHP<std::vector<Pt3d>> a_pts,
BSHP<std::vector<int>> a_tris)
override;
141 std::vector<int>& a_tris)
override;
144 std::vector<int>& a_idxs,
145 std::vector<double>& a_wts)
override;
148 std::vector<int>& a_idxs,
149 std::vector<double>& a_wts)
override;
151 virtual std::string
ToString()
const override;
171 boost::unordered_map<size_t, BarycentricVals>
m_cache;
188 Pt3d a(a_pt1.
x, a_pt1.
y, 0.0);
189 Pt3d b(a_pt2.
x, a_pt2.
y, 0.0);
190 Pt3d c(a_pt3.
x, a_pt3.
y, 0.0);
192 gmBaryPrepare(&a, &b, &c, &norm, &a_b.
orig, a_b.
coef, &a_b.
dir,
true);
203 Pt3d p(a_p.
x, a_p.
y, 0.0);
204 gmCartToBary(&p, &a_b.
orig, a_b.
coef, a_b.
dir, &weights);
242 , m_pts(new std::vector<
Pt3d>())
243 , m_tris(new std::vector<int>())
285 for (
size_t i = 0; i <
m_pts->size(); ++i)
287 Pt3d& pt = (*m_pts)[i];
302 tol = sqrt(tol) / 1e9;
305 size_t nTri =
m_tris->size() / 3;
307 m_rTree =
new bgi::rtree<size_t, qRtree, idx_tri>(
308 boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(nTri), rtree, getter);
321 for (
size_t i = 0; i <
m_tris->size(); i += 3)
323 if (!a_activity.test((*
m_tris)[i]) || !a_activity.test((*
m_tris)[i + 1]) ||
324 !a_activity.test((*
m_tris)[i + 2]))
336 if (a_activity.empty())
347 for (
size_t i = 0; i < a_activity.size(); ++i)
390 Pt3d p(a_pt.
x, a_pt.
y, 0);
391 std::vector<value> vals;
392 m_rTree->query(bgi::intersects(p), std::back_inserter(vals));
393 for (
size_t i = 0; i < vals.size(); ++i)
395 idx = (int)(vals[i] * 3);
396 a_tris.push_back(idx);
408 bx.max_corner() = a_pMax;
409 bx.max_corner().
z = 0;
410 bx.min_corner() = a_pMin;
411 bx.min_corner().
z = 0;
414 std::vector<value> vals;
416 m_rTree->query(bgi::intersects(bx), std::back_inserter(vals));
417 for (
size_t i = 0; i < vals.size(); ++i)
419 idx = (int)(vals[i] * 3);
420 a_tris.push_back(idx);
456 a_wts.push_back(weights.
x);
457 a_wts.push_back(weights.
y);
458 a_wts.push_back(weights.
z);
459 a_idxs.assign(ix, ix + 3);
475 std::stringstream ss;
494 a_ptIdxes[0] = a_ptIdxes[1] = a_ptIdxes[2] = -1;
495 if (a_triIdx < 0 || a_triIdx + 2 >= (
int)
m_tris->size())
497 std::stringstream msg;
498 msg <<
"Index out of range. File: " << __FILE__ <<
", Line:" << __LINE__;
502 a_ptIdxes[0] = (*m_tris)[a_triIdx + 0];
503 a_ptIdxes[1] = (*m_tris)[a_triIdx + 1];
504 a_ptIdxes[2] = (*m_tris)[a_triIdx + 2];
520 Pt3d p(a_pt.
x, a_pt.
y, 0);
521 std::vector<value> vals;
522 m_rTree->query(bgi::intersects(p), std::back_inserter(vals));
527 for (
size_t i = 0; i < vals.size(); ++i)
533 ix[0] = (*m_tris)[idx];
534 ix[1] = (*m_tris)[idx + 1];
535 ix[2] = (*m_tris)[idx + 2];
538 for (
size_t j = 0; j < 3; ++j)
540 bg::exterior_ring(poly).push_back((*
m_pts)[ix[j]]);
542 bg::exterior_ring(poly).push_back((*
m_pts)[ix[0]]);
543 if (bg::covered_by(a_pt, poly))
547 iGetBarycentricCoords(p, b, weights);
552 for (
size_t i = 0; i < vals.size(); ++i)
558 ix[0] = (*m_tris)[idx];
559 ix[1] = (*m_tris)[idx + 1];
560 ix[2] = (*m_tris)[idx + 2];
563 iGetBarycentricCoords(p, b, weights);
588 iCartToBary((*
m_pts)[a_ix[0]], (*
m_pts)[a_ix[1]], (*
m_pts)[a_ix[2]], a_b);
604 r.resize(
m_pts->size(), 0);
605 for (
size_t i = 0; i <
m_tris->size(); i += 3)
609 r[(*m_tris)[i + 0]] = 1;
610 r[(*m_tris)[i + 1]] = 1;
611 r[(*m_tris)[i + 2]] = 1;
623 pts->PtsToSearch(
m_pts);
661 BSHP<std::vector<Pt3d>> p(
new std::vector<Pt3d>());
662 *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
663 BSHP<std::vector<int>> t(
new std::vector<int>());
664 *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
665 tris->TrisToSearch(p, t);
667 std::vector<int> idxs, baseIdx;
668 std::vector<double> wt, baseWt;
670 TS_ASSERT(tris->InterpWeights(pt, idxs, wt));
672 baseWt = {.5, .3, .2};
677 TS_ASSERT(tris->InterpWeightsTriangleIdx({.25, .75, 0}, triangleIdx, idxs, wt));
678 TS_ASSERT_EQUALS(3, triangleIdx);
681 baseWt = {.25, .25, .5};
684 TS_ASSERT(!tris->InterpWeightsTriangleIdx({0, 1.25, 0}, triangleIdx, idxs, wt));
685 TS_ASSERT_EQUALS(XM_NONE, triangleIdx);
694 BSHP<GmTriSearch> tris = GmTriSearch::New();
695 BSHP<std::vector<Pt3d>> p(
new std::vector<Pt3d>());
696 *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
697 BSHP<std::vector<int>> t(
new std::vector<int>());
698 *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
699 tris->TrisToSearch(p, t);
703 tris->SetPtActivity(act_wrongSize);
706 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
711 tris->SetPtActivity(act);
713 TS_ASSERT_EQUALS(
XM_NONE, tris->TriContainingPt(pt));
720 BSHP<GmTriSearch> tris = GmTriSearch::New();
721 BSHP<std::vector<Pt3d>> p(
new std::vector<Pt3d>());
722 *p = {{0, 0, 0}, {1, 1, 1}, {1, 0, 2}, {0, 1, 2}, {.5, 1.5, 1}};
723 BSHP<std::vector<int>> t(
new std::vector<int>());
724 *t = {0, 2, 1, 0, 1, 3, 3, 1, 4};
725 tris->TrisToSearch(p, t);
729 tris->SetTriActivity(act_wrongSize);
731 Pt3d pt(.5, .2, 0), pt2(.5, .5, 0);
732 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
734 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
739 tris->SetTriActivity(act);
741 TS_ASSERT_EQUALS(
XM_NONE, tris->TriContainingPt(pt));
742 TS_ASSERT_EQUALS(3, tris->TriContainingPt(pt2));
746 tris->SetTriActivity(act);
747 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
748 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
755 Pt3d pt(-31.459823375717541, 29.927133417260336, 0);
757 BSHP<std::vector<Pt3d>> p(
new std::vector<Pt3d>());
758 *p = {{-20.150000000000002, 46.579999999999998, 7},
759 {-41.100000000000001, 30.370000000000001, 8},
760 {-19.550000000000001, 29.379999999999999, 9}};
761 BSHP<std::vector<int>> t(
new std::vector<int>());
773 BSHP<std::vector<Pt3d>> p(
new std::vector<Pt3d>());
774 *p = {{0, 0, 7}, {1, 0, 8}, {1, 1, 9}};
775 BSHP<std::vector<int>> t(
new std::vector<int>());
787 BSHP<VecInt> tPtr(
new VecInt());
788 tPtr->reserve(t->Triangles().size());
789 for (
const auto& tt : t->Triangles())
790 tPtr->push_back((
int)tt);
793 Pt3d pMin(9, 4, 0), pMax(15, 10, 0);
796 std::sort(tIdxes.begin(), tIdxes.end());
797 VecInt baseIdxes = {3, 6, 9, 18, 21, 27};
provides indexing for the spatial index
virtual void TriEnvelopsContainingPt(const Pt3d &a_pt, std::vector< int > &a_tris) override
Find all triangle whose envelop contains the point.
DynBitset PointActivityFromTriActivity()
Gets the activity of the points from the triangles.
virtual void TrisToSearch(BSHP< std::vector< Pt3d >> a_pts, BSHP< std::vector< int >> a_tris) override
Adds the triangles to the class.
void testPtActivity()
tests setting the point activity
#define BARYTOL
This is an odd duck tolerance.
Structure for Barycentric coordinate calculations.
virtual ~GmTriSearchImpl()
Destructor.
BSHP< std::vector< Pt3d > > m_pts
point locations
virtual void TriEnvelopesOverlap(const Pt3d &a_pMin, const Pt3d &a_pMax, std::vector< int > &a_tris) override
Find all triangle whose envelop contains the point.
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.
int FindTriangle(const Pt3d &a_pt, int ix[3], Pt3d &weights)
Find the triangle containing the location a_pt.
const GmBstBox3d result_type
#define XM_ENSURE_TRUE_NO_ASSERT(...)
DynBitset m_triActivity
activity of the triangles
An intersection point of a line with a polygon.
Spatial index for searching triangles.
result_type operator()(size_t i) const
calculates triangle extents based on a triangle index
void testCreateClass()
tests creating the class
std::vector< int > VecInt
const Pt3d * m_pts
point locations
void VecToStream(std::stringstream &a_ss, const T &a_v, std::string a_label)
void testInterpWeights()
tests calculation of interpolation weights from triangles
double coef[6]
barycentric coefficients
boost::unordered_map< size_t, BarycentricVals > m_cache
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
std::vector< double > VecDbl
idx_tri(const Pt3d *a_pts, const int *a_tris, double a_tol)
boost::dynamic_bitset< size_t > DynBitset
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
static const float XM_FLT_HIGHEST
void GetTriBarycentricVals(int a_idx, int a_ix[3], BarycentricVals &a_b)
Gets the barycentric values for a triangle.
Pt3d m_min
mininum extents of all points
static BSHP< GmPtSearch > New(bool a_2dSearch)
Creates an PtSearch class.
GmTriSearchImpl()
Constructor.
virtual void SetTriActivity(DynBitset &a_activity) override
Modifies the activity bitset of the class.
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
virtual void SetPtActivity(DynBitset &a_activity) override
Modifies the activity bitset of the class.
GmTriSearch()
Constructor.
bool ActiveTri(int a_idx)
Tests if a triangle is active. If any of the points of the tri are not active then the tri is not act...
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
int dir
direction based on the xyz's of the points making the triangle
virtual ~GmTriSearch()
Destructor.
void testSmsCase1()
A particular test case from SMS that was included.
virtual DynBitset GetPtActivity() override
Activity of the points based on the triangle activity.
void testTriActivity()
tests setting the triangle activity
void testTouch()
tests a point that touches a triangle
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.
static const float XM_FLT_LOWEST
void CreateRTree()
Creates the RTree of the triangles.