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> 48 namespace bg = boost::geometry;
49 namespace bgi = bg::index;
52 typedef bgi::quadratic<16>
qRtree;
67 explicit idx_tri(
const Pt3d* a_pts,
const int* a_tris,
double a_tol)
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;
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;
129 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;
150 virtual const BSHP<VecPt3d>
GetPoints()
const override;
151 virtual const BSHP<VecInt>
GetTriangles()
const override;
153 virtual std::string
ToString()
const override;
173 boost::unordered_map<size_t, BarycentricVals>
m_cache;
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);
205 Pt3d p(a_p.
x, a_p.
y, 0.0);
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>())
285 m_min = XM_FLT_HIGHEST;
286 m_max = XM_FLT_LOWEST;
287 for (
size_t i = 0; i <
m_pts->size(); ++i)
289 Pt3d& pt = (*m_pts)[i];
304 tol = sqrt(tol) / 1e9;
307 size_t nTri =
m_tris->size() / 3;
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);
323 for (
size_t i = 0; i <
m_tris->size(); i += 3)
325 if (!a_activity.test((*
m_tris)[i]) || !a_activity.test((*
m_tris)[i + 1]) ||
326 !a_activity.test((*
m_tris)[i + 2]))
338 if (a_activity.empty())
349 for (
size_t i = 0; i < a_activity.size(); ++i)
366 rval.resize(
m_tris->size() / 3, 1);
367 for (
size_t i = 0; i < rval.size(); ++i)
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)
414 idx = (int)(vals[i] * 3);
415 a_tris.push_back(idx);
429 bx.max_corner() = a_pMax;
430 bx.max_corner().
z = 0;
431 bx.min_corner() = a_pMin;
432 bx.min_corner().
z = 0;
435 std::vector<value> vals;
437 m_rTree->query(bgi::intersects(bx), std::back_inserter(vals));
438 for (
size_t i = 0; i < vals.size(); ++i)
440 idx = (int)(vals[i] * 3);
441 a_tris.push_back(idx);
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);
512 std::stringstream ss;
531 a_ptIdxes[0] = a_ptIdxes[1] = a_ptIdxes[2] = -1;
532 if (a_triIdx < 0 || a_triIdx + 2 >= (
int)
m_tris->size())
534 std::stringstream msg;
535 msg <<
"Index out of range. File: " << __FILE__ <<
", Line:" << __LINE__;
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];
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));
564 for (
size_t i = 0; i < vals.size(); ++i)
570 ix[0] = (*m_tris)[idx];
571 ix[1] = (*m_tris)[idx + 1];
572 ix[2] = (*m_tris)[idx + 2];
575 for (
size_t j = 0; j < 3; ++j)
577 bg::exterior_ring(poly).push_back((*
m_pts)[
ix[j]]);
579 bg::exterior_ring(poly).push_back((*
m_pts)[
ix[0]]);
580 if (bg::covered_by(a_pt, poly))
589 for (
size_t i = 0; i < vals.size(); ++i)
595 ix[0] = (*m_tris)[idx];
596 ix[1] = (*m_tris)[idx + 1];
597 ix[2] = (*m_tris)[idx + 2];
641 r.resize(
m_pts->size(), 0);
642 for (
size_t i = 0; i <
m_tris->size(); i += 3)
646 r[(*m_tris)[i + 0]] = 1;
647 r[(*m_tris)[i + 1]] = 1;
648 r[(*m_tris)[i + 2]] = 1;
660 pts->PtsToSearch(
m_pts);
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);
704 std::vector<int> idxs, baseIdx;
705 std::vector<double> wt, baseWt;
707 TS_ASSERT(tris->InterpWeights(pt, idxs, wt));
709 baseWt = {.5, .3, .2};
714 TS_ASSERT(tris->InterpWeightsTriangleIdx({.25, .75, 0}, triangleIdx, idxs, wt));
715 TS_ASSERT_EQUALS(3, triangleIdx);
718 baseWt = {.25, .25, .5};
721 TS_ASSERT(!tris->InterpWeightsTriangleIdx({0, 1.25, 0}, triangleIdx, idxs, wt));
722 TS_ASSERT_EQUALS(
XM_NONE, triangleIdx);
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);
740 tris->SetPtActivity(act_wrongSize);
743 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
748 tris->SetPtActivity(act);
750 TS_ASSERT_EQUALS(
XM_NONE, tris->TriContainingPt(pt));
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);
766 tris->SetTriActivity(act_wrongSize);
768 Pt3d pt(.5, .2, 0), pt2(.5, .5, 0);
769 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
771 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
776 tris->SetTriActivity(act);
778 TS_ASSERT_EQUALS(
XM_NONE, tris->TriContainingPt(pt));
779 TS_ASSERT_EQUALS(3, tris->TriContainingPt(pt2));
783 tris->SetTriActivity(act);
784 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt));
785 TS_ASSERT_EQUALS(0, tris->TriContainingPt(pt2));
792 Pt3d pt(-31.459823375717541, 29.927133417260336, 0);
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>());
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>());
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);
830 Pt3d pMin(9, 4, 0), pMax(15, 10, 0);
833 std::sort(tIdxes.begin(), tIdxes.end());
834 VecInt baseIdxes = {3, 6, 9, 18, 21, 27};
provides indexing for the spatial index
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.
void testPtActivity()
tests setting the point activity
#define BARYTOL
This is an odd duck tolerance.
Structure for Barycentric coordinate calculations.
virtual ~GmTriSearchImpl()
Destructor.
std::vector< double > VecDbl
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 triangles whose envelope overlaps the envelope defined by a_pMin and a_pMax.
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.
bgi::quadratic< 8 > qRtree
qRtree
void VecToStream(std::stringstream &a_ss, const T &a_v, std::string a_label)
Spatial index for searching triangles.
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)
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
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
boost::geometry::model::polygon< Pt3d > GmBstPoly3d
Boost polygon 3d.
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.
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...
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.
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...
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.
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.
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.
void CreateRTree()
Creates the RTree of the triangles.