19 #pragma warning(disable : 4512) // boost code: no assignment operator 20 #include <boost/geometry.hpp> 21 #include <boost/geometry/geometries/register/point.hpp> 22 #include <boost/geometry/index/rtree.hpp> 23 #include <boost/iterator/counting_iterator.hpp> 51 bPt(
double a_x,
double a_y,
double a_z)
57 bPt(
const xms::Pt3d& a_)
63 bPt& operator=(
const xms::Pt3d a_)
81 namespace bg = boost::geometry;
82 namespace bgi = bg::index;
85 typedef bg::model::box<bPt>
box;
111 template <
typename value>
142 explicit idx_pt(BSHP<std::vector<Pt3d>> a_,
bool a_2d)
155 return bPt(
m_[i].x,
m_[i].y,
m_2d ? 0 :
m_[i].z);
157 return bPt((*
m_v)[i].x, (*
m_v)[i].y,
m_2d ? 0 : (*
m_v)[i].z);
162 BSHP<std::vector<Pt3d>>
m_v;
181 bool a_quad_oct_Search,
182 std::vector<int>& a_nearest)
const override;
187 bool a_quad_oct_Search,
188 std::vector<int>& a_nearest)
const override;
190 virtual bool PtInRTree(
const Pt3d& a_pt,
const double a_tol)
override;
195 std::vector<int>& a_nearest)
const override;
199 bool a_quad_oct_Search,
200 std::vector<int>& a_nearest,
212 virtual std::string
ToString()
const override;
243 GmPtSearch::GmPtSearch()
249 GmPtSearch::~GmPtSearch()
261 : m_2dSearch(a_2dSearch)
262 , m_min(XM_FLT_HIGHEST)
263 , m_max(XM_FLT_LOWEST)
271 GmPtSearchImpl::~GmPtSearchImpl()
288 m_rTree =
new bgi::rtree<size_t, qRtree, idx_pt>(
289 boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(
m_bshpPt3d->size()),
301 for (
size_t i = 0; i < a_nPts; ++i)
333 m_rTree =
new bgi::rtree<size_t, qRtree, idx_pt>(boost::counting_iterator<size_t>(0),
334 boost::counting_iterator<size_t>(a_->size()),
355 a_ptIdx = *std::min_element(n.begin(), n.end());
389 bool a_quad_oct_Search,
390 std::vector<int>& a_nearest)
const 398 NearestPtsToPt(a_pt, a_numPtsToFind, a_quad_oct_Search, a_nearest, fs);
417 bool a_quad_oct_Search,
418 std::vector<int>& a_nearest,
421 std::vector<value> nearest;
429 if (!a_quad_oct_Search)
432 m_rTree->query(bgi::satisfies(*a_fsat) && bgi::nearest(tmpPt, a_numPtsToFind),
433 std::back_inserter(nearest));
435 m_rTree->query(bgi::nearest(tmpPt, a_numPtsToFind), std::back_inserter(nearest));
436 a_nearest.reserve(nearest.size());
437 for (
size_t i = 0; i < nearest.size(); ++i)
439 a_nearest.push_back((
int)nearest[i]);
447 std::vector<box> boxes;
449 for (
size_t i = 0; i < boxes.size(); ++i)
451 std::vector<value> foundPts;
453 bgi::covered_by(boxes[i]) && bgi::satisfies(*fPtr) && bgi::nearest(tmpPt, a_numPtsToFind),
454 std::back_inserter(foundPts));
455 a_nearest.reserve(a_nearest.size() + foundPts.size());
456 for (
size_t j = 0; j < foundPts.size(); ++j)
458 a_nearest.push_back((
int)foundPts[j]);
459 fPtr->m_bits.set(foundPts[j]);
463 std::sort(a_nearest.begin(), a_nearest.end());
481 bool a_quad_oct_Search,
482 std::vector<int>& a_nearest)
const 487 fsat.m_bits.set(a_ptIdx);
488 NearestPtsToPt(a_pt, a_numPtsToFind, a_quad_oct_Search, a_nearest, &fsat);
518 std::vector<int>& a_nearest)
const 524 fsat.m_bits.set(a_ptIdx);
526 Pt3d bMin(a_pt - a_distance), bMax(a_pt + a_distance);
533 box aBox(bMin, bMax);
535 std::vector<value> nearest;
538 m_rTree->query(bgi::satisfies(fsat) && bgi::covered_by(aBox), std::back_inserter(nearest));
539 a_nearest.reserve(nearest.size());
540 for (
size_t i = 0; i < nearest.size(); ++i)
542 a_nearest.push_back((
int)nearest[i]);
553 if (a_activity.size() ==
m_rTree->size())
575 std::stringstream ss;
595 box bound(bmin, bmax);
597 bound.min_corner().z = pt.
z;
606 aBox.max_corner().x = pt.
x;
607 aBox.min_corner().y = pt.
y;
608 a_boxes.push_back(aBox);
611 aBox.min_corner() = pt;
613 aBox.min_corner().
z = -1;
614 a_boxes.push_back(aBox);
617 aBox.max_corner() = pt;
620 aBox.max_corner().z = 1;
621 a_boxes.push_back(aBox);
624 aBox.min_corner().x = pt.
x;
625 aBox.max_corner().y = pt.
y;
626 a_boxes.push_back(aBox);
630 for (
int i = 0; i < 4; ++i)
632 a_boxes.push_back(a_boxes[i]);
633 a_boxes.back().max_corner().z = pt.
z;
634 a_boxes.back().min_corner().z =
m_min.
z;
644 #include <boost/assign.hpp> 656 void iGetPoints2(std::vector<Pt3d>& a_pts, std::vector<float>& a_scalar, std::vector<Pt3d>& a_iPts)
658 a_pts = {{-75.0, -16.0, 0.0}, {-60.0, 32.0, 0.0}, {-34.0, 50.0, 0.0}, {-34.0, 27.0, 0.0},
659 {-8.0, 40.0, 0.0}, {16.0, 38.0, 0.0}, {-25.0, 14.0, 43.64}, {10.0, 18.0, 44.16},
660 {27.0, 26.0, 0.0}, {63.0, 35.0, 0.0}, {-32.0, 0.0, 59.04}, {-7.0, 7.0, 90.2},
661 {26.0, 6.0, 67.2}, {75.0, 7.0, 0.0}, {-37.0, -15.0, 9.24}, {-7.0, -13.0, 71.0},
662 {2.0, -3.0, 98.4}, {31.0, -15.0, 25.56}, {60.0, -13.0, 0.0}, {-50.0, -30.0, 0.0},
663 {-30.0, -28.0, 0.0}, {43.0, -22.0, 0.0}, {-32.0, -50.0, 0.0}, {27.0, -37.0, 0.0},
666 a_scalar.resize(a_pts.size());
667 for (
size_t i = 0; i < a_pts.size(); ++i)
668 a_scalar[i] = (
float)a_pts[i].z;
669 a_iPts = {{-90, 60, 0}, {90, 60, 0}, {-90, -60, 0}, {90, -60, 0}, {60, -33, 0}};
673 #define _TS_ASSERT_POINTS_FOUND(a_file, a_line, a_required, a_optional, a_found) \ 674 iAssertPointsFound(a_file, a_line, a_required, a_optional, a_found) 675 #define TS_ASSERT_POINTS_FOUND(a_required, a_optional, a_found) \ 677 _TS_ASSERT_POINTS_FOUND(__FILE__, __LINE__, a_required, a_optional, a_found) 688 const std::vector<int>& a_required,
689 const std::vector<int>& a_optional,
690 const std::vector<int>& a_found)
693 std::vector<bool> handled(a_found.size(),
false);
694 for (
size_t i = 0; i < a_required.size(); ++i)
696 int idx = a_required[i];
697 auto it = std::find(a_found.begin(), a_found.end(), idx);
698 bool found = it != a_found.end();
701 handled[it - a_found.begin()] = found;
705 std::stringstream ss;
706 ss <<
"Result failed to include " << idx;
707 _TS_FAIL(a_file, a_line, ss.str().c_str());
712 for (
size_t i = 0; i < handled.size(); ++i)
716 int idx = a_found[i];
717 bool found = std::find(a_optional.begin(), a_optional.end(), idx) != a_optional.end();
720 std::stringstream ss;
721 ss <<
"Failed to find " << idx <<
" in optional points";
722 _TS_FAIL(a_file, a_line, ss.str().c_str());
744 static void iSetupPts(std::vector<Pt3d>& pts,
bool a_2d)
748 for (
int i = 1; i < 11; ++i)
750 for (
int j = 1; j < 11; ++j)
752 pts.push_back(
Pt3d(i, j, 0));
754 pts.push_back(
Pt3d(-i, j, 0));
755 pts.push_back(
Pt3d(i, -j, 0));
757 pts.push_back(
Pt3d(-i, -j, 0));
762 std::vector<Pt3d> pts1(pts);
763 for (
size_t i = 0; i < pts1.size(); ++i)
764 pts1[i].z = .1 * (
double)(i + 1);
765 pts.insert(pts.end(), pts1.begin(), pts1.end());
766 for (
size_t i = 0; i < pts1.size(); ++i)
767 pts1[i].z = -.1 * (
double)(i + 1);
768 pts.insert(pts.end(), pts1.begin(), pts1.end());
775 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
779 iPts->PtsToSearch(pts);
780 TS_ASSERT_EQUALS(
true, iPts->Is2D());
783 std::vector<int> foundPts, requiredPts, optionalPts;
784 iPts->NearestPtsToPt(aPt, 8,
false, foundPts);
785 requiredPts = {0, 1, 2, 3, 4, 6, 40, 41};
786 std::sort(foundPts.begin(), foundPts.end());
787 TS_ASSERT_EQUALS(8, foundPts.size());
790 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
791 requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 40, 41, 42, 43, 61, 63};
792 std::sort(foundPts.begin(), foundPts.end());
793 TS_ASSERT_EQUALS(16, foundPts.size());
798 iPts->NearestPtsToPt(aPt, 8,
false, foundPts);
799 requiredPts = {61, 65, 69, 73, 121, 125, 129, 133};
800 std::sort(foundPts.begin(), foundPts.end());
801 TS_ASSERT_EQUALS(8, foundPts.size());
804 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
805 requiredPts = {1, 5, 9, 61, 65, 69, 73, 77, 121, 125, 129, 133, 137, 181, 185, 189};
806 std::sort(foundPts.begin(), foundPts.end());
807 TS_ASSERT_EQUALS(16, foundPts.size());
812 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
813 requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 40, 41, 61, 63, 65, 67};
814 std::sort(foundPts.begin(), foundPts.end());
815 TS_ASSERT_EQUALS(16, foundPts.size());
818 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
819 requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 40, 41, 61, 63, 65, 67};
820 std::sort(foundPts.begin(), foundPts.end());
821 TS_ASSERT_EQUALS(16, foundPts.size());
829 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
830 std::vector<Pt3d> ipts;
831 std::vector<float> scalar, s, vBase;
835 iPts->PtsToSearch(pts);
837 std::vector<int> foundPts, requiredPts, optionalPts;
838 iPts->NearestPtsToPt(ipts[0], 16,
false, foundPts);
839 requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 14, 15, 16, 19, 20};
840 std::sort(foundPts.begin(), foundPts.end());
841 TS_ASSERT_EQUALS(16, foundPts.size());
849 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
853 iPts->PtsToSearch(pts);
856 std::vector<int> foundPts, requiredPts, optionalPts;
857 iPts->NearestPtsToPt(aPt, 16,
false, foundPts);
858 requiredPts = {0, 1, 2, 3, 300, 301, 302, 303, 600, 601, 602, 603};
859 optionalPts = {4, 5, 6, 7, 40, 41};
860 TS_ASSERT_EQUALS(16, foundPts.size());
870 pts.push_back(
Pt3d(1, 0, 0));
871 pts.push_back(
Pt3d(2, 0, 0));
872 pts.push_back(
Pt3d(-1, 0, 0));
873 pts.push_back(
Pt3d(-2, 0, 0));
874 pts.push_back(
Pt3d(0, 1, 0));
875 pts.push_back(
Pt3d(0, 2, 0));
876 pts.push_back(
Pt3d(0, -1, 0));
877 pts.push_back(
Pt3d(0, -2, 0));
878 pts.push_back(
Pt3d(0, 0, 1));
879 pts.push_back(
Pt3d(0, 0, 2));
880 pts.push_back(
Pt3d(0, 0, -1));
881 pts.push_back(
Pt3d(0, 0, -2));
885 pts.push_back(
Pt3d(1, 1, 2));
886 pts.push_back(
Pt3d(2, 1, 2));
887 pts.push_back(
Pt3d(1, 2, 2));
888 pts.push_back(
Pt3d(1, 1, 3));
890 pts.push_back(
Pt3d(-1, 1, 2));
891 pts.push_back(
Pt3d(-2, 1, 2));
892 pts.push_back(
Pt3d(-1, 2, 2));
893 pts.push_back(
Pt3d(-1, 1, 3));
895 pts.push_back(
Pt3d(1, -1, 2));
896 pts.push_back(
Pt3d(2, -1, 2));
897 pts.push_back(
Pt3d(1, -2, 2));
898 pts.push_back(
Pt3d(1, -1, 3));
900 pts.push_back(
Pt3d(-1, -1, 2));
901 pts.push_back(
Pt3d(-2, -1, 2));
902 pts.push_back(
Pt3d(-1, -2, 2));
903 pts.push_back(
Pt3d(-1, -1, 3));
906 pts.push_back(
Pt3d(1, 1, -2));
907 pts.push_back(
Pt3d(2, 1, -2));
908 pts.push_back(
Pt3d(1, 2, -2));
909 pts.push_back(
Pt3d(1, 1, -3));
911 pts.push_back(
Pt3d(-1, 1, -2));
912 pts.push_back(
Pt3d(-2, 1, -2));
913 pts.push_back(
Pt3d(-1, 2, -2));
914 pts.push_back(
Pt3d(-1, 1, -3));
916 pts.push_back(
Pt3d(1, -1, -2));
917 pts.push_back(
Pt3d(2, -1, -2));
918 pts.push_back(
Pt3d(1, -2, -2));
919 pts.push_back(
Pt3d(1, -1, -3));
921 pts.push_back(
Pt3d(-1, -1, -2));
922 pts.push_back(
Pt3d(-2, -1, -2));
923 pts.push_back(
Pt3d(-1, -2, -2));
924 pts.push_back(
Pt3d(-1, -1, -3));
932 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
936 iPts->PtsToSearch(pts);
939 std::vector<int> foundPts;
940 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
941 std::vector<int> requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22,
942 23, 24, 28, 29, 30, 31, 32, 36, 37, 38, 39, 40, 41, 42, 43};
943 std::vector<int> optionalPts = {33, 34};
944 std::sort(foundPts.begin(), foundPts.end());
945 TS_ASSERT_EQUALS(32, foundPts.size());
948 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
949 std::sort(foundPts.begin(), foundPts.end());
950 TS_ASSERT_EQUALS(32, foundPts.size());
958 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
962 iPts->PtsToSearch(pts);
966 iPts->SetActivity(activity_wrongSize);
969 std::vector<int> foundPts, requiredPts, optionalPts;
970 iPts->NearestPtsToPt(aPt, 8,
false, foundPts);
971 requiredPts = {0, 1, 2, 3, 4, 6, 40, 41};
972 std::sort(foundPts.begin(), foundPts.end());
973 TS_ASSERT_EQUALS(8, foundPts.size());
980 iPts->SetActivity(act);
981 iPts->NearestPtsToPt(aPt, 8,
false, foundPts);
982 requiredPts = {0, 1, 3, 4, 6, 41, 42};
983 optionalPts = {7, 43};
984 std::sort(foundPts.begin(), foundPts.end());
985 TS_ASSERT_EQUALS(8, foundPts.size());
993 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
997 iPts->PtsToSearch(pts);
1001 iPts->SetActivity(activity_wrongSize);
1004 std::vector<int> foundPts;
1005 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
1006 std::vector<int> requiredPts = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22,
1007 23, 24, 28, 29, 30, 31, 32, 36, 37, 38, 39, 40, 41, 42, 43};
1008 std::vector<int> optionalPts = {33, 34};
1009 std::sort(foundPts.begin(), foundPts.end());
1010 TS_ASSERT_EQUALS(32, foundPts.size());
1017 iPts->SetActivity(act);
1018 iPts->NearestPtsToPt(aPt, 4,
true, foundPts);
1019 requiredPts = {0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 20, 21, 22,
1020 23, 24, 28, 29, 30, 31, 32, 36, 37, 38, 39, 41, 42, 43};
1021 optionalPts = {13, 14, 25, 33, 34};
1022 std::sort(foundPts.begin(), foundPts.end());
1023 TS_ASSERT_EQUALS(31, foundPts.size());
1031 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
1032 *pts = {{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {1, 1, 0}, {1, -1, 0}};
1039 std::vector<int> base;
1041 base = {0, 2, 3, 4};
1053 BSHP<std::vector<Pt3d>> pts(
new std::vector<Pt3d>());
1054 *pts = {{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {1, 1, 0}, {1, -1, 0}};
1063 TS_ASSERT_EQUALS(0, ptIdx);
1065 TS_ASSERT_EQUALS(5, ptIdx);
virtual bool PtInRTree(const Pt3d &a_pt, const double a_tol) override
Checks if the point is in the Rtree within tolerance.
Spatial index for searching points.
bg::model::box< bPt > box
box
DynBitset m_activity
point activity
void iGetPoints2(std::vector< Pt3d > &a_pts, std::vector< float > &a_scalar, std::vector< Pt3d > &a_iPts)
Get GMS tutorial data.
bool m_2dSearch
flag specifying 2d searching only
BOOST_GEOMETRY_REGISTER_POINT_3D(bPt, double, cs::cartesian, x, y, z)
result_type operator()(size_t i) const
operator to return the point location based on an index
static void iSetupPts(std::vector< Pt3d > &pts, bool a_2d)
helper function for testing
virtual bool Is2D() const override
Returns true if class only searches in 2D.
void testTest3d()
testing in 3d
const bPt result_type
created to follow boost examples
virtual void PtsToSearch(BSHP< std::vector< Pt3d >> a_pts) override
Adds the point locations to the class.
GmPtSearchImpl(bool a_2dSearch)
Constructor.
bgi::quadratic< 8 > qRtree
qRtree
void VecToStream(std::stringstream &a_ss, const T &a_v, std::string a_label)
virtual bool AddPtToVectorIfUnique(const Pt3d &a_, double a_tol, int &a_ptIdx) override
Adds the point to the R-tree if the point location is unique based on the passed in tolerance...
fSatisfies(size_t a_nVals)
Constructor.
boost::dynamic_bitset< size_t > DynBitset
Pt3d m_min
minimum extents of points
static void iSetupPtsOctant(std::vector< Pt3d > &pts)
helper function for testing
void testActivity2d()
testing searching with activity
#define TS_ASSERT_POINTS_FOUND(a_required, a_optional, a_found)
macro for testing
BSHP< std::vector< Pt3d > > m_v
vector of point locations
DynBitset m_bits
bitset that is the size of the points
void testCreateClass()
tests creating the class
const Pt3d * m_
array of point locations
virtual void NearestPtsToPtInRtree(int a_ptIdx, const Pt3d &a_pt, int a_numPtsToFind, bool a_quad_oct_Search, std::vector< int > &a_nearest) const override
Finds the nearest points to the input a_pt with an option to search quadrants/octants. Similar to NearestPtsToPt but this method will always pass the fSatisfies class to the RTree. This method is used to find the nearest points to a point that is included in the RTree.
virtual DynBitset GetActivity() override
Returns the point activity.
bool operator()(value const &a_) const
Determines if a point can be returned. If the bit is not set yet.
void testTest2dTutData()
testing tutorial data from GMS in 2d
virtual void PtsWithinDistanceToPtInRtree(int a_ptIdx, const Pt3d &a_pt, double a_dist, std::vector< int > &a_nearest) const override
Finds the nearest points to the input a_pt with an option to search quadrants/octants. Similar to NearestPtsToPt but this method will always pass the fSatisfies class to the RTree. This method is used to find the nearest points to a point that is included in the RTree.
virtual void NearestPtsToPt(const Pt3d &a_pt, int a_numPtsToFind, bool a_quad_oct_Search, std::vector< int > &a_nearest) const override
Finds the nearest points to the input a_pt with an option to search quadrants/octants.
class for indexing the points
virtual void VectorThatGrowsToSearch(BSHP< std::vector< Pt3d >> a_) override
Adds the point locations to the class.
void UpdateMinMax(const Pt3d *a_pts, size_t a_npts)
Updates the m_min, m_max variables.
a class used with the boost::geometry::index::satisfies function
void CreateOctants(const Pt3d &a_pt, std::vector< box > &a_boxes) const
Creates octants (or quadrants for 2d) to be used in the rtree query.
void testTest3dOct()
testing octant searching in 3d
bool m_2d
flag specifying 2d searching only
idx_pt(const Pt3d *a_, bool a_2d)
constructor
static BSHP< GmPtSearch > New(bool a_2dSearch)
Creates an PtSearch class.
idx_pt(BSHP< std::vector< Pt3d >> a_, bool a_2d)
constructor
Pt3d m_max
maximum extents of points
void testVectorThatGrows()
testing VectorThatGrows functionality
bgi::rtree< value, qRtree, idx_pt > * m_rTree
spatial index for searching the points
virtual void SetActivity(DynBitset &a_activity) override
Sets activity on the points in the Rtree so that points can be ignored when interpolating.
virtual const BSHP< VecPt3d > GetPointsPtr() const override
Returns shared point to the point locations in the RTree.
Implementation of GmPtSearch. Generic class for searching location data. Uses a boost R-tree to query...
BSHP< VecPt3d > m_bshpPt3d
Vector of point locations.
void testActivity3d()
testing searching with activity
void testPtsWithinDist()
testing Point within a distance to a specified point
void testTest2d()
testing in 2d
void iAssertPointsFound(const char *a_file, int a_line, const std::vector< int > &a_required, const std::vector< int > &a_optional, const std::vector< int > &a_found)
helper function for testing
virtual std::string ToString() const override
Write the internals to a string.