19 #pragma warning(disable : 4512) // boost code: no assignment operator 20 #pragma warning(disable : 4244) // boost code: possible loss of data 21 #pragma warning(disable : 4127) // boost code: conditional expression is constant 22 #pragma warning(disable : 4267) // boost code: size_t to const int 23 #include <boost/geometry/geometry.hpp> 25 #include <boost/unordered_set.hpp> 47 namespace bg = boost::geometry;
51 } // unnamed namespace 58 void SetupInIn(
const std::vector<MePolyOffsetterOutput>& a_offsets,
double a_xyTol);
65 std::vector<std::vector<size_t>>& a_output);
74 std::set<size_t>& a_psetUsed,
75 std::vector<std::vector<size_t>>& a_output);
111 const std::vector<Pt3d>& a_pts)
114 if (a_loop.empty() || a_pts.empty())
117 b.min_corner() = b.max_corner() = a_pts[a_loop[0]];
118 b.min_corner().z = b.max_corner().z = 0;
119 for (
size_t j = 1; j < a_loop.size(); ++j)
121 const Pt3d& p(a_pts[a_loop[j]]);
122 if (b.min_corner().x > p.
x)
123 b.min_corner().x = p.
x;
124 if (b.max_corner().x < p.
x)
125 b.max_corner().x = p.
x;
126 if (b.min_corner().y > p.
y)
127 b.min_corner().y = p.
y;
128 if (b.max_corner().y < p.
y)
129 b.max_corner().y = p.
y;
143 const std::vector<GmBstBox3d>& a_iEnv,
144 const std::vector<GmBstBox3d>& a_jEnv)
146 const Pt3d &iMin(a_iEnv[a_i].min_corner()), &iMax(a_iEnv[a_i].max_corner()),
147 &jMin(a_jEnv[a_j].min_corner()), &jMax(a_jEnv[a_j].max_corner());
148 if (iMax.x > jMin.x && iMin.x < jMax.
x && iMax.y > jMin.y && iMin.y < jMax.
y)
161 const std::vector<GmBstBox3d>& a_envelopes)
163 const Pt3d &iMin(a_envelopes[a_i].min_corner()), &iMax(a_envelopes[a_i].max_corner()),
164 &jMin(a_envelopes[a_j].min_corner()), &jMax(a_envelopes[a_j].max_corner());
165 if (jMin.x >= iMin.x && jMin.y >= iMin.y && jMax.
x <= iMax.x && jMax.
y <= iMax.y)
211 for (
size_t i = 0; i <
m_p->
m_loops.size(); ++i)
253 std::vector<std::vector<size_t>>& a_output)
264 const VecPt3d& a_origOutsidePoly)
286 for (
size_t k = 0; start > 0 && k <
m_out.
m_loops.back().size(); ++k)
295 for (
size_t i = 0; i < a_offsets.size(); ++i)
298 std::vector<GmBstPoly3d> newOutPolys;
300 size_t start = pts.size();
301 pts.insert(pts.end(), o.
m_pts.begin(), o.
m_pts.end());
302 for (
size_t j = 0; j < o.
m_loops.size(); ++j)
305 if (MePolyOffsetter::OUTSIDE_POLY == o.
m_loopTypes[j] ||
308 moveToOut(o, j, start);
309 if (MePolyOffsetter::NEWOUT_POLY == o.
m_loopTypes[j])
313 const std::vector<size_t>& l(o.
m_loops[j]);
314 std::vector<size_t>::const_iterator it(l.begin()), iend(l.end());
315 for (; it != iend; ++it)
317 bg::exterior_ring(bPoly).push_back(pts[*it]);
319 bg::exterior_ring(bPoly).push_back(pts[l[0]]);
320 newOutPolys.push_back(bPoly);
325 for (
size_t j = 0; j < o.
m_loops.size(); ++j)
327 if (MePolyOffsetter::OUTSIDE_POLY == o.
m_loopTypes[j] ||
334 bool moveToOutput(
false);
336 for (
size_t k = 0; !moveToOutput && k < newOutPolys.size(); ++k)
338 if (bg::within(p0, newOutPolys[k]))
343 moveToOut(o, j, start);
348 for (
size_t k = 0; start > 0 && k <
m_loops.back().size(); ++k)
362 std::vector<size_t> idx(m_polyPts.HashPts());
364 UpdateInPolyLoopsFromHash(idx);
366 for (
size_t i = 0; i < m_loops.size(); ++i)
368 m_bPolys.push_back(BoostPoly(i));
378 m_polyPts.XyTol() = a_xyTol;
381 std::vector<Pt3d>& pts(m_polyPts.Pts());
383 pts.insert(pts.end(), o.m_pts.begin(), o.m_pts.end());
384 for (
size_t j = 0; j < o.m_loops.size(); ++j)
386 if (MePolyOffsetter::NEWOUT_POLY == o.m_loopTypes[j])
388 m_out.m_loopTypes.push_back(o.m_loopTypes[j]);
389 m_out.m_loops.push_back(o.m_loops[j]);
392 m_loops.push_back(o.m_loops[j]);
393 m_loopTypes.push_back(o.m_loopTypes[j]);
407 ClassifyDisjointPolys(delPolys);
408 ClassifyPolysInsideOfPolys(delPolys);
409 ClassifyDisjointPolys(delPolys);
413 std::multimap<double, size_t> areaMap;
414 std::vector<GmBstBox3d>& env(m_envelopes);
415 for (
size_t i = 0; i < env.size(); ++i)
417 if (delPolys.find(i) == delPolys.end())
420 double area = (b.max_corner().x - b.min_corner().x) * (b.max_corner().y - b.min_corner().y);
421 areaMap.insert(std::make_pair(area, i));
424 std::multimap<double, size_t>::reverse_iterator rit = areaMap.rbegin();
425 for (; rit != areaMap.rend(); ++rit)
427 m_stack.push_back(rit->second);
442 while (!m_stack.empty())
444 std::list<size_t>::iterator it = m_stack.begin();
445 size_t idx = *it, idx2;
447 bool processed =
false;
448 std::list<size_t>::iterator it2 = it;
450 while (!processed && it2 != m_stack.end())
458 processed = BoostPolyUnion(idx, idx2);
472 m_bOutPolys.push_back(m_bPolys[idx]);
473 m_bOutPolyType.push_back(MePolyOffsetter::INSIDE_POLY);
489 InOutCalcStartingStack();
490 while (!m_stack.empty())
492 std::list<size_t>::iterator it = m_stack.begin();
494 std::vector<size_t> polys(InOutFindIntersectingPolys(idx));
496 bool processed(
false);
497 for (
size_t i = 0; i < polys.size(); ++i)
499 if (BoostPolySubtract(polys[i], idx))
507 m_bOutPolys.push_back(m_bPolys[idx]);
508 m_bOutPolyType.push_back(MePolyOffsetter::INSIDE_POLY);
512 SetIdx::iterator it(m_inOutOpolys.begin()), iend(m_inOutOpolys.end());
513 for (; it != iend; ++it)
515 m_bOutPolys.push_back(m_bPolys[*it]);
516 m_bOutPolyType.push_back(MePolyOffsetter::OUTSIDE_POLY);
528 std::vector<size_t> loop;
529 for (
size_t i = 0; i < m_bOutPolys.size(); ++i)
533 if (m_bOutPolyType[i] == MePolyOffsetter::INSIDE_POLY)
535 for (
size_t j = 1; j < p.outer().size(); ++j)
537 Pt3d& pt(p.outer()[j]);
538 size_t idx = m_polyPts.IdxFromPt3d(pt);
541 std::reverse(loop.begin(), loop.end());
543 if (!p.inners().empty())
545 for (
size_t j = 0; j < p.inners().size(); ++j)
547 std::vector<size_t> iPolyLoop;
549 for (
size_t k = 0; k < iPoly.size() - 1; ++k)
551 size_t idx = m_polyPts.IdxFromPt3d(iPoly[k]);
552 iPolyLoop.push_back(idx);
554 std::reverse(iPolyLoop.begin(), iPolyLoop.end());
555 a_out.
m_loops.push_back(iPolyLoop);
556 a_out.
m_loopTypes.push_back(MePolyOffsetter::NEWOUT_POLY);
562 for (
size_t j = 0; j < p.outer().size() - 1; ++j)
564 Pt3d& pt(p.outer()[j]);
565 size_t idx = m_polyPts.IdxFromPt3d(pt);
572 a_out.
m_pts = m_polyPts.Pts();
585 std::set<size_t>& a_psetUsed,
586 std::vector<std::vector<size_t>>& a_output)
588 std::vector<Pt3d>& pts(m_polyPts.Pts());
589 std::set<size_t>::iterator it(a_oPoly.begin()), itend(a_oPoly.end()), usedEnd(a_psetUsed.end());
590 for (; it != itend; ++it)
593 a_output.push_back(std::vector<size_t>());
594 a_output.back().push_back(*it);
597 for (
size_t i = 0; i < m_loops.size(); ++i)
599 if (a_psetUsed.find(i) != usedEnd)
602 Pt3d& p(pts[m_loops[i].front()]);
603 if (bg::within(p, poly))
605 a_output.back().push_back(i);
606 a_psetUsed.insert(i);
618 std::vector<std::vector<size_t>>& a_output)
621 m_polyPts.Pts() = a_input.
m_pts;
625 std::set<size_t> psetNewOut, psetOut, psetUsed;
627 for (
size_t i = 0; i < m_loopTypes.size(); ++i)
629 if (MePolyOffsetter::NEWOUT_POLY == m_loopTypes[i])
631 psetNewOut.insert(i);
634 else if (MePolyOffsetter::OUTSIDE_POLY == m_loopTypes[i])
641 FillPolysInsideOfPolys(psetNewOut, psetUsed, a_output);
643 FillPolysInsideOfPolys(psetOut, psetUsed, a_output);
653 std::vector<GmBstBox3d>& env(m_envelopes);
655 std::vector<int> overlaps(env.size(), 0);
656 for (
size_t i = 0; i < env.size(); ++i)
658 if (a_delPolys.find(i) != a_delPolys.end())
661 for (
size_t j = 0; j < env.size(); j++)
667 if (a_delPolys.find(j) != a_delPolys.end())
672 overlaps[i] = overlaps[j] = 1;
676 for (
size_t i = 0; i < overlaps.size(); ++i)
679 if (!overlaps[i] && a_delPolys.find(i) == a_delPolys.end())
681 m_out.m_loops.push_back(m_loops[i]);
682 m_out.m_loopTypes.push_back(MePolyOffsetter::INSIDE_POLY);
683 a_delPolys.insert(i);
695 std::vector<GmBstBox3d>& env(m_envelopes);
696 for (
size_t i = 0; i < env.size(); ++i)
698 if (a_delPolys.find(i) != a_delPolys.end())
701 for (
size_t j = 0; j < env.size(); j++)
705 if (a_delPolys.find(j) != a_delPolys.end())
710 if (m_polyPts.PolyInsideOfPoly(m_loops[i], m_loops[j]))
712 m_polyInsideOfPoly.insert(std::make_pair(i, j));
714 bool inNewOut(
false);
715 for (
size_t k = 0; !inNewOut && k < m_out.m_loops.size(); ++k)
717 if (m_out.m_loopTypes[k] == MePolyOffsetter::NEWOUT_POLY)
719 std::vector<size_t> idx(m_out.m_loops[k]);
720 std::reverse(idx.begin(), idx.end());
721 if (m_polyPts.PolyInsideOfPoly(idx, m_loops[j]))
728 a_delPolys.insert(j);
744 std::vector<std::vector<size_t>>& loops(m_loops);
745 for (
size_t i = 0; i < loops.size(); ++i)
747 for (
size_t j = 0; j < loops[i].size(); ++j)
750 loops[i][j] = a_idx[idx];
762 std::vector<size_t> inPolys;
763 for (
size_t i = 0; i < m_loopTypes.size(); ++i)
765 if (MePolyOffsetter::OUTSIDE_POLY == m_loopTypes[i])
766 m_inOutOpolys.insert(i);
767 else if (MePolyOffsetter::INSIDE_POLY == m_loopTypes[i])
768 inPolys.push_back(i);
771 std::multimap<double, size_t> areaMap;
772 for (
size_t i = 0; i < inPolys.size(); ++i)
775 double area = (b.max_corner().x - b.min_corner().x) * (b.max_corner().y - b.min_corner().y);
776 areaMap.insert(std::make_pair(area, inPolys[i]));
778 std::multimap<double, size_t>::reverse_iterator rit = areaMap.rbegin();
779 for (; rit != areaMap.rend(); ++rit)
781 m_stack.push_back(rit->second);
792 std::vector<size_t> outPolys;
794 std::vector<GmBstBox3d>& env(m_envelopes);
795 SetIdx::iterator it(m_inOutOpolys.begin()), iend(m_inOutOpolys.end());
796 for (; it != iend; ++it)
800 if (!m_polyPts.PolyInsideOfPoly(m_bPolys[*it].outer(), m_loops[a_poly]))
802 outPolys.push_back(*it);
818 std::vector<Pt3d>& pts(m_polyPts.Pts());
819 std::vector<size_t>& l(m_loops[a_loopIdx]);
820 if (m_loopTypes.empty() || m_loopTypes[a_loopIdx] == MePolyOffsetter::INSIDE_POLY)
822 std::vector<size_t>::reverse_iterator it(l.rbegin()), iend(l.rend());
823 bg::exterior_ring(poly).push_back(pts[l[0]]);
824 for (; it != iend; ++it)
826 bg::exterior_ring(poly).push_back(pts[*it]);
831 std::vector<size_t>::iterator it(l.begin()), iend(l.end());
832 for (; it != iend; ++it)
834 bg::exterior_ring(poly).push_back(pts[*it]);
836 bg::exterior_ring(poly).push_back(pts[l[0]]);
848 std::vector<GmBstPoly3d> out;
849 GmBstPoly3d &iPoly(m_bPolys[a_i]), &jPoly(m_bPolys[a_j]);
850 std::pair<size_t, size_t> p1(a_i, a_j), p2(a_j, a_i);
851 if (m_polyInsideOfPoly.find(p1) != m_polyInsideOfPoly.end() ||
852 m_polyInsideOfPoly.find(p2) != m_polyInsideOfPoly.end())
854 bg::union_(iPoly, jPoly, out);
857 m_stack.push_back(m_bPolys.size());
858 m_bPolys.push_back(out[0]);
861 std::vector<Pt3d>& pts(m_bPolys.back().outer());
862 std::vector<size_t> loop(pts.size());
863 for (
size_t i = 0; i < loop.size(); ++i)
868 for (
size_t i = 0; i < out[0].inners().size(); ++i)
871 std::vector<Pt3d>& vi(out[0].inners()[i]);
872 std::vector<Pt3d>::reverse_iterator it(vi.rbegin()), iend(vi.rend());
873 for (; it != iend; ++it)
875 bg::exterior_ring(innerPoly).push_back(*it);
877 m_bOutPolys.push_back(innerPoly);
878 m_bOutPolyType.push_back(MePolyOffsetter::NEWOUT_POLY);
892 std::vector<GmBstPoly3d> out;
893 GmBstPoly3d &iPoly(m_bPolys[a_i]), &jPoly(m_bPolys[a_j]);
894 if (!bg::intersects(iPoly, jPoly))
896 bg::difference(iPoly, jPoly, out);
897 m_inOutOpolys.erase(a_i);
898 for (
size_t i = 0; i < out.size(); ++i)
900 m_inOutOpolys.insert(m_bPolys.size());
901 m_bPolys.push_back(out[i]);
902 m_bPolys.back().inners().clear();
903 std::vector<Pt3d>& pts(m_bPolys.back().outer());
904 std::vector<size_t> loop(pts.size());
905 for (
size_t i = 0; i < loop.size(); ++i)
908 m_loopTypes.push_back(MePolyOffsetter::OUTSIDE_POLY);
920 const VecPt3d& a_origOutsidePoly)
922 if (a_origOutsidePoly.empty())
926 std::set<size_t> newOutPolys, polysToDelete;
927 for (
size_t i = 0; i < a_out.
m_loopTypes.size(); ++i)
929 if (MePolyOffsetter::NEWOUT_POLY == a_out.
m_loopTypes[i])
930 newOutPolys.insert(i);
933 if (newOutPolys.empty())
938 for (
size_t i = 0; i < a_origOutsidePoly.size(); ++i)
940 bg::exterior_ring(oPoly).push_back(a_origOutsidePoly[i]);
942 bg::exterior_ring(oPoly).push_back(a_origOutsidePoly[0]);
947 for (
const auto& newOutPolyIdx : newOutPolys)
949 if (polysToDelete.find(newOutPolyIdx) != polysToDelete.end())
952 bool pointOutside(
false);
953 std::vector<size_t>& l1(a_out.
m_loops[newOutPolyIdx]);
954 for (
size_t i = 0; !pointOutside && i < l1.size(); ++i)
957 if (!bg::covered_by(p, oPoly))
961 polysToDelete.insert(newOutPolyIdx);
965 auto rit = polysToDelete.rbegin(), rend = polysToDelete.rend();
966 for (; rit != rend; ++rit)
1015 o.
m_pts = {{1, 1, 0}, {1, 3, 0}, {4, 3, 0}, {4, 1, 0}, {0, 0, 0},
1016 {0, 4, 0}, {8, 4, 0}, {8, 0, 0}, {5, 1, 0}, {7, 1, 0},
1017 {7, 2, 0}, {5, 2, 0}, {5, 3, 0}, {7, 3, 0}, {7, 3.5, 0},
1018 {5, 3.5, 0}, {1.5, 1.5, 0}, {3.5, 1.5, 0}, {3.5, 2.5, 0}, {1.5, 2.5, 0}};
1019 std::vector<size_t> v0 = {0, 1, 2, 3};
1021 std::vector<size_t> v1 = {4, 5, 6, 7};
1023 std::vector<size_t> v2 = {8, 9, 10, 11};
1025 std::vector<size_t> v3 = {12, 13, 14, 15};
1027 std::vector<size_t> v4 = {16, 17, 18, 19};
1029 o.
m_loopTypes.assign(5, MePolyOffsetter::INSIDE_POLY);
1032 std::vector<std::vector<size_t>> output;
1035 TS_ASSERT_EQUALS(2, output.size());
1036 if (2 != output.size())
1038 std::vector<size_t> baseIdx = {0, 4};
1040 baseIdx = {1, 2, 3};
std::vector< GmBstPoly3d > m_bOutPolys
boost::geometry::polygon
boost::geometry::model::box< Pt3d > GmBstBox3d
void ClassifyPolys(const MePolyOffsetterOutput &a_input, std::vector< std::vector< size_t >> &a_output)
calls implementation
void FillOutput(MePolyOffsetterOutput &a_out)
calls implementation
void SetupInOut(const MePolyOffsetterOutput &a_offsets, double a_xyTol)
Setup for InOutDoIntersection.
void SetupInOut(const MePolyOffsetterOutput &a_offsets, double a_xyTol)
calls implementation
void InInTrivialPolyCases()
calls implementation
void InOutDoIntersection()
calls implementation
Does polygon intersection for MePolyCleaner.
MeIntersectPolys()
Constructor.
bool BoostPolySubtract(size_t a_i, size_t a_j)
Performs a subtraction with 2 polygons. Used by InOutDoIntersection.
std::vector< size_t > InOutFindIntersectingPolys(size_t a_poly)
Finds OUTSIDE_POLY polygons that potentially intersect the INSIDE_POLY "a_poly". Used by InOutDoInter...
std::vector< GmBstBox3d > m_envelopes
extents of polygons
static GmBstBox3d iCalcPolyEnvelope(const std::vector< size_t > &a_loop, const std::vector< Pt3d > &a_pts)
Returns the envelop of a polygon.
void FillPolysInsideOfPolys(std::set< size_t > &a_oPoly, std::set< size_t > &a_psetUsed, std::vector< std::vector< size_t >> &a_output)
Finds INSIDE_POLY that are inside of NEWOUT_POLY or OUTSIDE_POLY. Used by MeIntersectPolys::impl::Cla...
void InOutDoIntersection()
A stack is created of INSIDE_POLY polygons. Each of these polygons is checked to see if it intersects...
void InInDoIntersection()
Uses a stack of INSIDE_POLY polygons to intersect the polygons with one another. The stack is sorted ...
void SetupInIn(const std::vector< MePolyOffsetterOutput > &a_offsets, double a_xyTol)
calls implementation
std::vector< int > m_loopTypes
type of polygon (OUTSIDE_POLY, INSIDE_POLY, NEWOUT_POLY)
void SetupInIn(const std::vector< MePolyOffsetterOutput > &a_offsets, double a_xyTol)
Setup for the InInDoIntersection.
void ClassifyDisjointPolys(SetIdx &a_delPolys)
Classifies polygons that are completely disjoint from other polygons based on the envelopes of the po...
std::vector< GmBstPoly3d > m_bPolys
boost::geometry::polygon
void UpdateInPolyLoopsFromHash(const std::vector< size_t > &a_idx)
Updates the indexes that define the polygons after the point locations have been hashed to find dupli...
convenience class for holding output data from the MePolyOffsetter
Intersect polygons that are a result of the paving process.
std::vector< Pt3d > m_pts
locations used by polygons
boost::geometry::model::polygon< Pt3d > GmBstPoly3d
impl * m_p
implementation class
MePolyOffsetterOutput m_out
newpolygons created by this class
std::vector< int > m_bOutPolyType
type of polygon (OUTSIDE_POLY, INSIDE_POLY, NEWOUT_POLY)
void InInTrivialPolyCases()
Looks for polygons that are completely disjoint based on their envelopes. Also finds polygons that ar...
std::list< size_t > m_stack
stack for processing the polygons
~MeIntersectPolys()
Destructor.
void ClassifyPolys(const MePolyOffsetterOutput &a_input, std::vector< std::vector< size_t >> &a_output)
Classifies the polygons. see PolyClassifierImpl::Classify.
MePolyPts m_polyPts
polygon points class
void DeleteBad_NEWOUT_POLY(MePolyOffsetterOutput &a_out, const VecPt3d &a_origOutsidePoly)
calls implementation
void DeleteBad_NEWOUT_POLY(MePolyOffsetterOutput &a_out, const VecPt3d &a_origOutsidePoly)
deletes NEWOUT_POLY polygons that have points outside of OUTSIDE_POLY polygon
GmBstPoly3d BoostPoly(size_t a_loopIdx)
Creates a boost polygon from a vector of point indexes.
void InOutCalcStartingStack()
Sets up the stack for the InOutDoIntersection method. A stack of INSIDE_POLY polygons is created and ...
std::set< size_t > SetIdx
typedef for shorter declaration
boost::unordered_set< std::pair< size_t, size_t > > m_polyInsideOfPoly
index of polygon that is inside of another polygon
void CalcEnvelopes()
Calculates the envelope of all of the polygons.
static bool iEnvelopeInsideOfEnvelope(size_t a_i, size_t a_j, const std::vector< GmBstBox3d > &a_envelopes)
Returns true if envelope a_i is inside of envelope a_j.
SetIdx m_inOutOpolys
outside polygons
std::vector< int > m_loopTypes
type of loop
static bool iEnvelopesOverlap(size_t a_i, size_t a_j, const std::vector< GmBstBox3d > &a_iEnv, const std::vector< GmBstBox3d > &a_jEnv)
Returns true only if the envelopes overlap (not touch)
std::vector< std::vector< size_t > > m_loops
indexes of points that define loops
std::vector< Pt3d > & Pts()
Returns the vector of points.
void InInDoIntersection()
calls implementation
void FillOutput(MePolyOffsetterOutput &a_out)
Fills the output class.
bool BoostPolyUnion(size_t a_i, size_t a_j)
Performs a union operation on 2 polygons. Used by InInDoIntersection.
double & XyTol()
Returns the tolerance.
void ClassifyPolysInsideOfPolys(SetIdx &a_delPolys)
If an INSIDE_POLY is inside of another INSIDE_POLY then it will be deleted. But if it is inside of a ...
Utility class to work with polygon paving.
void testClassify()
tests classifying polygons
void OnSetup()
Setup member variables. Called by SetupInIn and SetupInOut.
std::vector< std::vector< size_t > > m_loops
indexes to points that make polygons
std::vector< Pt3d > VecPt3d