19 #pragma warning(disable : 4512) // boost code: no assignment operator 20 #include <boost/geometry/geometry.hpp> 42 typedef std::map<size_t, std::multimap<double, size_t>>
SegMap;
51 namespace bg = boost::geometry;
62 ,
m_pts(
new std::vector<Pt3d>())
85 static size_t iNextSegIdx(
size_t a_i,
const std::vector<size_t>& a_seg)
88 if (next >= a_seg.size())
102 const std::vector<size_t>& a_iSeg,
107 if (a_t >= 0 && a_t <= 1)
109 a_mapSegCross[&a_iSeg][a_i].insert(std::make_pair(a_t, a_j));
121 static void iHashPts(std::vector<size_t>& a_newIdx, BSHP<std::vector<Pt3d>> a_pts,
double a_xyTol)
128 ps->PtsToSearch(a_pts);
130 a_newIdx.resize(a_pts->size(), 0);
131 for (
size_t i = 0; i < a_newIdx.size(); ++i)
135 for (
size_t i = 0; i < a_pts->size(); ++i)
137 ps->PtsWithinDistanceToPtInRtree((
int)i, (*a_pts)[i], a_xyTol, n);
138 for (
size_t j = 0; j < n.size(); ++j)
140 if ((
size_t)n[j] > i)
155 const std::vector<Pt3d>& a_pts)
158 std::vector<GmBstBox3d> envelopes;
159 envelopes.reserve(a_segs.size());
160 for (
size_t i = 0; i < a_segs.size(); ++i)
162 size_t ix0(a_segs[i]);
164 size_t ix1(a_segs[next]);
166 const Pt3d &p0(a_pts[ix0]), &p1(a_pts[ix1]);
167 b.max_corner() = b.min_corner() = p0;
168 b.max_corner().z = b.min_corner().z = 0;
169 if (b.min_corner().x > p1.
x)
170 b.min_corner().x = p1.
x;
171 if (b.max_corner().x < p1.
x)
172 b.max_corner().x = p1.
x;
174 if (b.min_corner().y > p1.
y)
175 b.min_corner().y = p1.
y;
176 if (b.max_corner().y < p1.
y)
177 b.max_corner().y = p1.
y;
179 envelopes.push_back(b);
193 const std::vector<GmBstBox3d>& a_iEnv,
194 const std::vector<GmBstBox3d>& a_jEnv)
196 const Pt3d &iMin(a_iEnv[a_i].min_corner()), &iMax(a_iEnv[a_i].max_corner()),
197 &jMin(a_jEnv[a_j].min_corner()), &jMax(a_jEnv[a_j].max_corner());
198 if (jMin.x > iMax.x || jMin.y > iMax.y || iMin.x > jMax.
x || iMin.y > jMax.
y)
214 double denomX = a_p1.
x - a_p0.
x;
215 double denomY = a_p1.
y - a_p0.
y;
216 if (fabs(denomX) > fabs(denomY))
218 tval = (a_iPt.
x - a_p0.
x) / denomX;
222 tval = (a_iPt.
y - a_p0.
y) / denomY;
250 const std::vector<size_t>& a_iSeg,
251 const std::vector<size_t>& a_jSeg,
252 const std::vector<Pt3d>& a_pts,
257 size_t p00(a_iSeg[a_i]), p01(a_iSeg[nexti]), p10(a_jSeg[a_j]), p11(a_jSeg[nextj]);
258 if (p00 != p10 && p00 != p11 && p01 != p10 && p01 != p11)
261 if ((p00 == p10 || p00 == p11) && (p01 == p10 || p01 == p11))
264 const Pt3d &s1p0(a_pts[p00]), &s1p1(a_pts[p01]);
266 if (p00 == p10 || p01 == p10)
296 std::vector<Pt3d>& a_pts)
302 double dx1 = a_s1p1.
x - a_s1p0.
x;
303 double dy1 = a_s1p1.
y - a_s1p0.
y;
304 double dx2 = a_s2p1.
x - a_s2p0.
x;
305 double dy2 = a_s2p1.
y - a_s2p0.
y;
306 double cross = (dx1 * dy2) - (dy1 * dx2);
312 a_pts.push_back(a_s2p1);
317 a_pts.push_back(a_s1p1);
350 const std::vector<size_t>& a_iSeg,
351 const std::vector<size_t>& a_jSeg,
352 BSHP<std::vector<Pt3d>>& a_shptrPts,
355 BSHP<GmPtSearch> a_ps)
357 std::vector<Pt3d>& spts(*a_shptrPts);
363 Pt3d &s1p0(spts[a_iSeg[a_i]]), &s1p1(spts[a_iSeg[nexti]]);
366 Pt3d &s2p0(spts[a_jSeg[a_j]]), &s2p1(spts[a_jSeg[nextj]]);
368 std::vector<Pt3d> pts;
372 for (
size_t i = 0; i < pts.size(); ++i)
391 if (1 == t2 || 0 == t2)
402 ptIdx = (int)spts.size();
403 spts.push_back(pts[i]);
408 a_ps->AddPtToVectorIfUnique(pts[i], a_xyTol, idx);
431 const std::vector<size_t>& a_polyToTest,
432 const std::vector<Pt3d>& a_pts)
435 for (
size_t i = 0; !out && i < a_polyToTest.size(); ++i)
437 const Pt3d& p(a_pts[a_polyToTest[i]]);
438 if (!bg::covered_by(p, a_poly))
454 std::list<std::vector<size_t>>& a_loops,
457 std::vector<Pt3d>& pts(a_polyPts.
Pts());
459 std::list<std::vector<size_t>>::iterator it, it2;
463 a_polyInsideOfPoly.resize(a_loops.size());
464 for (it = a_loops.begin(); it != a_loops.end(); ++it, ++cnt_it)
468 for (
size_t i = 0; i < it->size(); ++i)
470 bg::exterior_ring(poly).push_back(pts[(*it)[i]]);
472 bg::exterior_ring(poly).push_back(pts[(*it)[0]]);
475 for (it2 = a_loops.begin(); it2 != a_loops.end(); ++it2, ++cnt_it2)
481 a_polyInsideOfPoly[cnt_it2].push_back(cnt_it);
492 static std::vector<double>
iCalcPolyAreas(
const std::list<std::vector<size_t>>& a_loops,
493 const std::vector<Pt3d>& a_pts)
495 std::vector<double> areas;
496 areas.reserve(a_loops.size());
497 std::list<std::vector<size_t>>::const_iterator it(a_loops.begin());
498 for (; it != a_loops.end(); ++it)
500 std::vector<Pt3d> pts(it->size(),
Pt3d());
501 for (
size_t i = 0; i < it->size(); ++i)
502 pts[i] = a_pts[(*it)[i]];
513 if (a_sequence.size() < 3)
516 std::list<size_t>::iterator it(a_sequence.begin());
517 std::list<size_t>::iterator back1(it);
519 std::list<size_t>::iterator back2(back1);
522 std::list<size_t>::iterator itEnd(a_sequence.end());
523 while (it != itEnd && back1 != itEnd && back2 != itEnd)
528 a_sequence.erase(back1, it);
565 return *(
m_p->m_pts);
581 std::vector<size_t> idx;
591 std::vector<size_t> tmpSegs(
HashPts()), retSegs;
593 retSegs.reserve(
Pts().size());
594 if (!tmpSegs.empty())
595 retSegs.push_back(tmpSegs[0]);
596 for (
size_t i = 1; i < tmpSegs.size(); ++i)
598 if (tmpSegs[i - 1] != tmpSegs[i])
599 retSegs.push_back(tmpSegs[i]);
610 for (
size_t i = 0; i < a_segs.size(); ++i)
612 for (
size_t j = i + 1; j < a_segs.size(); ++j)
631 std::list<size_t> sequence;
633 for (
size_t i = 0; i < a_segs.size(); ++i)
635 sequence.push_back(a_segs[i]);
637 SegMap::iterator it =
m_p->m_segCross[&a_segs].find(i);
638 if (it ==
m_p->m_segCross[&a_segs].end())
641 std::multimap<double, size_t>::iterator it1(it->second.begin());
642 for (; it1 != it->second.end(); ++it1)
644 size_t& pIdx(it1->second);
646 if (sequence.back() != pIdx)
647 sequence.push_back(pIdx);
663 const std::vector<size_t>& a_iSeg,
664 const std::vector<size_t>& a_jSeg)
677 std::list<std::vector<size_t>>& a_loops)
679 while (!a_sequence.empty())
683 while (sSize != a_sequence.size())
685 sSize = a_sequence.size();
689 std::map<size_t, std::list<size_t>::iterator> mapPidxItr;
690 std::map<size_t, std::list<size_t>::iterator>::iterator it1;
691 std::list<size_t>::iterator it(a_sequence.begin());
692 bool loopfound =
false;
693 for (; !loopfound && it != a_sequence.end(); ++it)
696 it1 = mapPidxItr.find(ptIdx);
697 if (it1 == mapPidxItr.end())
699 mapPidxItr[ptIdx] = it;
703 a_loops.push_back(std::vector<size_t>(it1->second, it));
704 a_sequence.erase(it1->second, it);
710 a_loops.push_back(std::vector<size_t>(a_sequence.begin(), a_sequence.end()));
726 int cnt(0), out(MePolyOffsetter::OUTSIDE_POLY), in(MePolyOffsetter::INSIDE_POLY);
727 std::list<std::vector<size_t>>::iterator it(a_loops.begin()), next;
728 while (it != a_loops.end())
732 if ((a_pType == out && areas[cnt] > 0) || (a_pType == in && areas[cnt] < 0))
751 std::vector<int>& a_loopType)
753 std::vector<std::vector<size_t>> polyInsideOfPoly(a_loops.size());
757 std::vector<int> validPoly(areas.size(), 1);
758 for (
size_t i = 0; i < areas.size(); ++i)
761 validPoly[i] =
false;
766 std::list<std::vector<size_t>>::iterator it(a_loops.begin()), next;
767 for (; it != a_loops.end(); ++it, ++cnt_it)
769 if (polyInsideOfPoly[cnt_it].empty()) {}
770 else if (!polyInsideOfPoly[cnt_it].empty())
772 if (validPoly[polyInsideOfPoly[cnt_it][0]])
774 validPoly[cnt_it] = validPoly[cnt_it] ? 0 : 1;
785 for (it = a_loops.begin(), cnt_it = 0; it != a_loops.end(); it = next, ++cnt_it)
789 if (!validPoly[cnt_it])
795 int type(MePolyOffsetter::INSIDE_POLY);
796 if (areas[cnt_it] < 0)
797 type = MePolyOffsetter::NEWOUT_POLY;
798 a_loopType.push_back(type);
810 const std::vector<size_t>& a_polyToTest)
812 std::vector<Pt3d>& pts(
Pts());
814 for (
size_t i = 0; i < a_poly.size(); ++i)
816 bg::exterior_ring(poly).push_back(pts[a_poly[i]]);
818 bg::exterior_ring(poly).push_back(pts[a_poly[0]]);
831 const std::vector<size_t>& a_polyToTest)
834 for (
size_t i = 0; i < a_poly.size(); ++i)
836 bg::exterior_ring(poly).push_back(a_poly[i]);
838 std::vector<Pt3d>& pts(
Pts());
853 m_p->m_ps->VectorThatGrowsToSearch(
m_p->m_pts);
856 m_p->m_ps->AddPtToVectorIfUnique(a_pt,
m_p->m_xyTol, idx);
857 return idx > -1 ? (size_t)idx : 0;
std::map< size_t, std::multimap< double, size_t > > SegMap
map for segment intersection indices
boost::geometry::model::box< Pt3d > GmBstBox3d
void ClassifyLoopsFromInPolyAndRemoveInvalid(std::list< std::vector< size_t >> &a_loops, std::vector< int > &a_loopType)
Classifies loops extracted from a pave on an INSIDE_POLY and removes invalid loops. There are more rules when dealing with paving outward from polygons. Sometimes paving outward will create a new "outside" polygon that we then pave inward on the next step in the algorithm. See testCase8. You can also generate "inside" polygons that are inside of other "inside" polygons. These are deleted. Again see testCase8.
bool gmIntersectLineSegmentsWithTol(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2, double *xi, double *yi, double *zi1, double *zi2, double tol)
size_t IdxFromPt3d(const Pt3d &a_pt)
Returns the index of a location by hashing that location with the current list of points...
std::vector< size_t > HashPts()
Hashes the point locations.
#define T_TOL
tolerance used in multipoly intersector
bool PolyInsideOfPoly(const std::vector< size_t > &a_poly, const std::vector< size_t > &a_polyToTest)
Returns true if a_polyToTest is inside of a_poly.
bool gmEqualPointsXY(double x1, double y1, double x2, double y2, double tolerance)
double m_xyTol
tolerance for geometric comparisons
void CalcLoopsForCleanPolyOffset(std::list< size_t > &a_sequence, std::list< std::vector< size_t >> &a_loops)
Calculates new loops from a sequence that has intersections included.
static std::vector< GmBstBox3d > iCalcSegEnvelopes(const std::vector< size_t > &a_segs, const std::vector< Pt3d > &a_pts)
Returns the envelopes of the segments.
std::map< const std::vector< size_t > *, SegMap > MapSegMap
map used to see where segments cross each other
std::list< size_t > SequenceWithIntersects(std::vector< size_t > &a_segs)
Returns a new sequence that includes intersection indexes.
static size_t iNextSegIdx(size_t a_i, const std::vector< size_t > &a_seg)
Get the next index for a segment. The segments are stored as a vector and it forms a closed loop so t...
boost::geometry::model::polygon< Pt3d > GmBstPoly3d
static double iCalcIntersectionT(const Pt3d &a_p0, const Pt3d &a_p1, Pt3d &a_iPt, double a_xyTol)
Computes the T value for the point on the line a_p0, a_p1.
static void iCheckIntersection(size_t a_i, size_t a_j, const std::vector< size_t > &a_iSeg, const std::vector< size_t > &a_jSeg, BSHP< std::vector< Pt3d >> &a_shptrPts, double a_xyTol, MapSegMap &a_mapSegCross, BSHP< GmPtSearch > a_ps)
Sees if 2 segments intersects and if they do then information is added to the a_mapSegCross.
Implementation of MePolyPts.
void IntersectSegs(const std::vector< size_t > &a_segs)
Intersects the segments.
static std::vector< double > iCalcPolyAreas(const std::list< std::vector< size_t >> &a_loops, const std::vector< Pt3d > &a_pts)
Calculates polygon areas.
BSHP< std::vector< Pt3d > > m_pts
point locations
static void iFindPolysInsideOfOtherPolys(std::vector< std::vector< size_t >> &a_polyInsideOfPoly, std::list< std::vector< size_t >> &a_loops, MePolyPts &a_polyPts)
Given a list of polygons, finds the polygons that are inside of other polygons.
BSHP< GmPtSearch > m_ps
spatial index for searching points
static bool iCheckSharedPtIdx(size_t a_i, size_t a_j, const std::vector< size_t > &a_iSeg, const std::vector< size_t > &a_jSeg, const std::vector< Pt3d > &a_pts, double a_xyTol, MapSegMap &a_mapSegCross)
Check segments to see if they share a point index.
static bool iPolyInsideOfPoly(const GmBstPoly3d &a_poly, const std::vector< size_t > &a_polyToTest, const std::vector< Pt3d > &a_pts)
Returns true if a polygon is inside of another polygon.
bool EQ_TOL(const _T &A, const _U &B, const _V &tolerance)
MapSegMap m_segCross
map used to see where segment cross each other
BSHP< impl > m_p
implementation class
static bool iEnvelopesOverlapOrTouch(size_t a_i, size_t a_j, const std::vector< GmBstBox3d > &a_iEnv, const std::vector< GmBstBox3d > &a_jEnv)
Returns true if the envelopes overlap or touch.
static void iAddIntersection(size_t a_i, const std::vector< size_t > &a_iSeg, size_t a_j, double a_t, MapSegMap &a_mapSegCross)
Adds an intersection to a map of intersection information.
static void iRemoveRepeatedSegmentFromSequence(std::list< size_t > &a_sequence)
Removes a repeated segment (2 numbers) from a sequence.
void CheckIntersectTwoSegs(size_t a_i, size_t a_j, const std::vector< size_t > &a_iSeg, const std::vector< size_t > &a_jSeg)
Intersects 2 segments.
static BSHP< GmPtSearch > New(bool a_2dSearch)
double gmPolygonArea(const Pt3d *pts, size_t npoints)
BSHP< std::vector< Pt3d > > PtsSharedPointer()
Returns the vector of points.
std::vector< Pt3d > & Pts()
Returns the vector of points.
std::vector< size_t > SegmentsForCleanPolyOffset()
Returns the segments that will be used in CleanPolyOffset.
void RemoveBackwardLoopsForCleanPolyOffset(std::list< std::vector< size_t >> &a_loops, int a_pType)
Removes loops that are "backwards" for CleanPolyOffset. "backwards" depends on the type of input (OUT...
double & XyTol()
Returns the tolerance.
static void iHashPts(std::vector< size_t > &a_newIdx, BSHP< std::vector< Pt3d >> a_pts, double a_xyTol)
hash the points and fill in a vector with the new index assigned to each point. If there are no dupli...
Utility class to work with polygon paving.
static bool iIntersectTwoSegments(const Pt3d &a_s1p0, const Pt3d &a_s1p1, const Pt3d &a_s2p0, const Pt3d &a_s2p1, double a_xyTol, std::vector< Pt3d > &a_pts)
Intersects 2 segments. Normally there is only 1 intersection between 2 segments but if the lines are ...
bool gmOnLineAndBetweenEndpointsWithTol(const Pt3d &a_pt1, const Pt3d &a_pt2, const double a_x, const double a_y, double a_tol)