xmsmesh  1.0
MePolyPts.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 // 2. My own header
14 
15 // 3. Standard library headers
16 
17 // 4. External library headers
18 #pragma warning(push)
19 #pragma warning(disable : 4512) // boost code: no assignment operator
20 #include <boost/geometry/geometry.hpp>
21 #pragma warning(pop)
22 
23 // 5. Shared code headers
24 #include <xmscore/math/math.h>
25 #include <xmsinterp/geometry/GmBoostTypes.h> // GmBstPoly3d, XmBstRing
30 #include <xmscore/misc/XmError.h>
31 
32 // 6. Non-shared code headers
33 
34 //----- Forward declarations ---------------------------------------------------
35 
36 //----- External globals -------------------------------------------------------
37 
38 //----- Namespace declaration --------------------------------------------------
39 namespace xms
40 {
42 typedef std::map<size_t, std::multimap<double, size_t>> SegMap;
44 typedef std::map<const std::vector<size_t>*, SegMap> MapSegMap;
45 
46 //----- Constants / Enumerations -----------------------------------------------
47 
48 //----- Classes / Structs ------------------------------------------------------
49 namespace
50 {
51 namespace bg = boost::geometry;
52 
53 #define T_TOL 1e-13
54 
55 } // unnamed namespace
58 {
59 public:
60  impl()
61  : m_xyTol(1e-9)
62  , m_pts(new std::vector<Pt3d>())
63  {
64  }
65  ~impl() {}
66 
67  double m_xyTol;
68  BSHP<std::vector<Pt3d>> m_pts;
70  BSHP<GmPtSearch> m_ps;
71 };
72 
73 //----- Internal functions -----------------------------------------------------
74 
75 //----- Class / Function definitions -------------------------------------------
76 
77 //------------------------------------------------------------------------------
84 //------------------------------------------------------------------------------
85 static size_t iNextSegIdx(size_t a_i, const std::vector<size_t>& a_seg)
86 {
87  size_t next(a_i + 1);
88  if (next >= a_seg.size())
89  next = 0;
90  return next;
91 } // iNextSegIdx
92 //------------------------------------------------------------------------------
100 //------------------------------------------------------------------------------
101 static void iAddIntersection(size_t a_i,
102  const std::vector<size_t>& a_iSeg,
103  size_t a_j,
104  double a_t,
105  MapSegMap& a_mapSegCross)
106 {
107  if (a_t >= 0 && a_t <= 1)
108  {
109  a_mapSegCross[&a_iSeg][a_i].insert(std::make_pair(a_t, a_j));
110  }
111 } // iAddIntersection
112 //------------------------------------------------------------------------------
120 //------------------------------------------------------------------------------
121 static void iHashPts(std::vector<size_t>& a_newIdx, BSHP<std::vector<Pt3d>> a_pts, double a_xyTol)
122 {
123  a_newIdx.resize(0);
124  if (a_pts->empty())
125  return;
126 
127  BSHP<GmPtSearch> ps = GmPtSearch::New(true);
128  ps->PtsToSearch(a_pts);
129 
130  a_newIdx.resize(a_pts->size(), 0);
131  for (size_t i = 0; i < a_newIdx.size(); ++i)
132  a_newIdx[i] = i;
133 
134  std::vector<int> n;
135  for (size_t i = 0; i < a_pts->size(); ++i)
136  {
137  ps->PtsWithinDistanceToPtInRtree((int)i, (*a_pts)[i], a_xyTol, n);
138  for (size_t j = 0; j < n.size(); ++j)
139  {
140  if ((size_t)n[j] > i)
141  {
142  a_newIdx[n[j]] = i;
143  }
144  }
145  }
146 } // iHashPts
147 //------------------------------------------------------------------------------
153 //------------------------------------------------------------------------------
154 static std::vector<GmBstBox3d> iCalcSegEnvelopes(const std::vector<size_t>& a_segs,
155  const std::vector<Pt3d>& a_pts)
156 {
157  GmBstBox3d b;
158  std::vector<GmBstBox3d> envelopes;
159  envelopes.reserve(a_segs.size());
160  for (size_t i = 0; i < a_segs.size(); ++i)
161  {
162  size_t ix0(a_segs[i]);
163  size_t next(iNextSegIdx(i, a_segs));
164  size_t ix1(a_segs[next]);
165 
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;
173 
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;
178 
179  envelopes.push_back(b);
180  }
181  return envelopes;
182 } // iCalcSegEnvelopes
183 //------------------------------------------------------------------------------
190 //------------------------------------------------------------------------------
191 static bool iEnvelopesOverlapOrTouch(size_t a_i,
192  size_t a_j,
193  const std::vector<GmBstBox3d>& a_iEnv,
194  const std::vector<GmBstBox3d>& a_jEnv)
195 {
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)
199  return false;
200  return true;
201 } // iEnvelopesOverlapOrTouch
202 //------------------------------------------------------------------------------
210 //------------------------------------------------------------------------------
211 static double iCalcIntersectionT(const Pt3d& a_p0, const Pt3d& a_p1, Pt3d& a_iPt, double a_xyTol)
212 {
213  double tval(-1);
214  double denomX = a_p1.x - a_p0.x;
215  double denomY = a_p1.y - a_p0.y;
216  if (fabs(denomX) > fabs(denomY))
217  {
218  tval = (a_iPt.x - a_p0.x) / denomX;
219  }
220  else
221  {
222  tval = (a_iPt.y - a_p0.y) / denomY;
223  }
224  if (gmEqualPointsXY(a_p0, a_iPt, a_xyTol) || (tval < 0 && EQ_TOL(tval, 0, T_TOL)))
225  {
226  a_iPt = a_p0;
227  tval = 0;
228  }
229  if (gmEqualPointsXY(a_p1, a_iPt, a_xyTol) || (tval > 1 && EQ_TOL(tval, 1, T_TOL)))
230  {
231  a_iPt = a_p1;
232  tval = 1;
233  }
234  return tval;
235 } // iCalcIntersectionT
236 //------------------------------------------------------------------------------
247 //------------------------------------------------------------------------------
248 static bool iCheckSharedPtIdx(size_t a_i,
249  size_t a_j,
250  const std::vector<size_t>& a_iSeg,
251  const std::vector<size_t>& a_jSeg,
252  const std::vector<Pt3d>& a_pts,
253  double a_xyTol,
254  MapSegMap& a_mapSegCross)
255 {
256  size_t nexti(iNextSegIdx(a_i, a_iSeg)), nextj(iNextSegIdx(a_j, a_jSeg));
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)
259  return false;
260  // check if this is the same segment (can happen after hashing points)
261  if ((p00 == p10 || p00 == p11) && (p01 == p10 || p01 == p11))
262  return true;
263 
264  const Pt3d &s1p0(a_pts[p00]), &s1p1(a_pts[p01]);
265  size_t idx(0);
266  if (p00 == p10 || p01 == p10)
267  idx = p11;
268  else
269  idx = p10;
270 
271  Pt3d p = a_pts[idx];
272  if (gmOnLineAndBetweenEndpointsWithTol(s1p0, s1p1, p.x, p.y, a_xyTol))
273  {
274  double t = iCalcIntersectionT(s1p0, s1p1, p, a_xyTol);
275  iAddIntersection(a_i, a_iSeg, idx, t, a_mapSegCross);
276  }
277  return true;
278 } // iCheckSharedPtIdx
279 //------------------------------------------------------------------------------
290 //------------------------------------------------------------------------------
291 static bool iIntersectTwoSegments(const Pt3d& a_s1p0,
292  const Pt3d& a_s1p1,
293  const Pt3d& a_s2p0,
294  const Pt3d& a_s2p1,
295  double a_xyTol,
296  std::vector<Pt3d>& a_pts)
297 {
298  bool rval(false);
299  a_pts.resize(0);
300 
301  // check parallel
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);
307  if (EQ_TOL(0.0, cross, T_TOL))
308  { // if we are parallel then we just want to
309  // check if p1 and seg2 is on seg1
310  if (gmOnLineAndBetweenEndpointsWithTol(a_s1p0, a_s1p1, a_s2p1.x, a_s2p1.y, a_xyTol))
311  {
312  a_pts.push_back(a_s2p1);
313  rval = true;
314  }
315  if (gmOnLineAndBetweenEndpointsWithTol(a_s2p0, a_s2p1, a_s1p1.x, a_s1p1.y, a_xyTol))
316  {
317  a_pts.push_back(a_s1p1);
318  rval = true;
319  }
320  }
321  else
322  {
323  double z2;
324  Pt3d pt;
325  if (gmIntersectLineSegmentsWithTol(a_s1p0, a_s1p1, a_s2p0, a_s2p1, &pt.x, &pt.y, &pt.z, &z2,
326  a_xyTol))
327  {
328  a_pts.push_back(pt);
329  rval = true;
330  }
331  }
332  return rval;
333 } // iIntersectTwoSegments
334 //------------------------------------------------------------------------------
347 //------------------------------------------------------------------------------
348 static void iCheckIntersection(size_t a_i,
349  size_t a_j,
350  const std::vector<size_t>& a_iSeg,
351  const std::vector<size_t>& a_jSeg,
352  BSHP<std::vector<Pt3d>>& a_shptrPts,
353  double a_xyTol,
354  MapSegMap& a_mapSegCross,
355  BSHP<GmPtSearch> a_ps)
356 {
357  std::vector<Pt3d>& spts(*a_shptrPts);
358  if (iCheckSharedPtIdx(a_i, a_j, a_iSeg, a_jSeg, spts, a_xyTol, a_mapSegCross))
359  return;
360 
361  // first segment
362  size_t nexti = iNextSegIdx(a_i, a_iSeg);
363  Pt3d &s1p0(spts[a_iSeg[a_i]]), &s1p1(spts[a_iSeg[nexti]]);
364  // second segment
365  size_t nextj = iNextSegIdx(a_j, a_jSeg);
366  Pt3d &s2p0(spts[a_jSeg[a_j]]), &s2p1(spts[a_jSeg[nextj]]);
367 
368  std::vector<Pt3d> pts;
369  bool intersect = iIntersectTwoSegments(s1p0, s1p1, s2p0, s2p1, a_xyTol, pts);
370  if (intersect)
371  {
372  for (size_t i = 0; i < pts.size(); ++i)
373  {
374  // calculate the "t" value for the intersection on the first segment
375  double t = iCalcIntersectionT(s1p0, s1p1, pts[i], a_xyTol);
376  double t2 = iCalcIntersectionT(s2p0, s2p1, pts[i], a_xyTol);
377  // if t = 1 then we want this intersection to go on the second segment
378  // with the t value on the second segment so that intersections on that
380  if (1 == t)
381  {
382  t = iCalcIntersectionT(s2p0, s2p1, pts[i], a_xyTol);
383  iAddIntersection(a_j, a_jSeg, a_iSeg[nexti], t, a_mapSegCross);
384  }
385  // > 0 is here because at some point in our looping we will consider
386  // the same location for both t = 0 and 1 if an endpoint of a segment
387  // touches another segment. To keep from adding it twice we only add
388  // when t > 0. See testCase2 as an example.
389  else if (t > 0)
390  {
391  if (1 == t2 || 0 == t2)
392  {
393  if (1 == t2)
394  iAddIntersection(a_i, a_iSeg, a_jSeg[nextj], t, a_mapSegCross);
395  // ignore 0 because we will hit this point when t2 is 1
396  }
397  else
398  {
399  size_t ptIdx;
400  if (!a_ps)
401  {
402  ptIdx = (int)spts.size();
403  spts.push_back(pts[i]);
404  }
405  else
406  {
407  int idx;
408  a_ps->AddPtToVectorIfUnique(pts[i], a_xyTol, idx);
409  ptIdx = (size_t)idx;
410  }
411  iAddIntersection(a_i, a_iSeg, ptIdx, t, a_mapSegCross);
412  iAddIntersection(a_j, a_jSeg, ptIdx, t2, a_mapSegCross);
413  }
414  }
415  if (t < 0 || t > 1)
416  {
417  XM_ASSERT(0);
418  }
419  }
420  }
421 } // iCheckIntersection
422 //------------------------------------------------------------------------------
429 //------------------------------------------------------------------------------
430 static bool iPolyInsideOfPoly(const GmBstPoly3d& a_poly,
431  const std::vector<size_t>& a_polyToTest,
432  const std::vector<Pt3d>& a_pts)
433 {
434  bool out = false;
435  for (size_t i = 0; !out && i < a_polyToTest.size(); ++i)
436  {
437  const Pt3d& p(a_pts[a_polyToTest[i]]);
438  if (!bg::covered_by(p, a_poly))
439  out = true;
440  }
441  if (out)
442  return false;
443  return true;
444 } // iPolyInsideOfPoly
445 //------------------------------------------------------------------------------
452 //------------------------------------------------------------------------------
453 static void iFindPolysInsideOfOtherPolys(std::vector<std::vector<size_t>>& a_polyInsideOfPoly,
454  std::list<std::vector<size_t>>& a_loops,
455  MePolyPts& a_polyPts)
456 {
457  std::vector<Pt3d>& pts(a_polyPts.Pts());
458  // create set of point indices that make up polygons
459  std::list<std::vector<size_t>>::iterator it, it2;
460 
461  // determine which polygons are inside of other polygons
462  size_t cnt_it(0);
463  a_polyInsideOfPoly.resize(a_loops.size());
464  for (it = a_loops.begin(); it != a_loops.end(); ++it, ++cnt_it)
465  {
466  // create polygon for iterator it
467  GmBstPoly3d poly;
468  for (size_t i = 0; i < it->size(); ++i)
469  {
470  bg::exterior_ring(poly).push_back(pts[(*it)[i]]);
471  }
472  bg::exterior_ring(poly).push_back(pts[(*it)[0]]);
473 
474  size_t cnt_it2(0);
475  for (it2 = a_loops.begin(); it2 != a_loops.end(); ++it2, ++cnt_it2)
476  {
477  if (it == it2)
478  continue;
479  if (iPolyInsideOfPoly(poly, *it2, pts))
480  {
481  a_polyInsideOfPoly[cnt_it2].push_back(cnt_it);
482  }
483  }
484  }
485 } // iFindPolysInsideOfOtherPolys
486 //------------------------------------------------------------------------------
491 //------------------------------------------------------------------------------
492 static std::vector<double> iCalcPolyAreas(const std::list<std::vector<size_t>>& a_loops,
493  const std::vector<Pt3d>& a_pts)
494 {
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)
499  {
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]];
503  areas.push_back(gmPolygonArea(&pts[0], (int)pts.size()));
504  }
505  return areas;
506 } // iCalcPolyAreas
507 //------------------------------------------------------------------------------
510 //------------------------------------------------------------------------------
511 static void iRemoveRepeatedSegmentFromSequence(std::list<size_t>& a_sequence)
512 {
513  if (a_sequence.size() < 3)
514  return;
515 
516  std::list<size_t>::iterator it(a_sequence.begin());
517  std::list<size_t>::iterator back1(it);
518  ++it;
519  std::list<size_t>::iterator back2(back1);
520  ++back1;
521  ++it;
522  std::list<size_t>::iterator itEnd(a_sequence.end());
523  while (it != itEnd && back1 != itEnd && back2 != itEnd)
524  {
525  if (*it == *back2)
526  { // remove it and back1
527  ++it;
528  a_sequence.erase(back1, it);
529  return;
530  }
531  else
532  {
533  ++back2;
534  ++back1;
535  ++it;
536  }
537  }
538 } // iRemoveRepeatedSegmentFromSequence
539 
544 //------------------------------------------------------------------------------
546 //------------------------------------------------------------------------------
548 : m_p(new MePolyPts::impl())
549 {
550 } // MpPolyPts::MpPolyPts
551 //------------------------------------------------------------------------------
554 //------------------------------------------------------------------------------
556 {
557  return m_p->m_xyTol;
558 } // MpPolyPts::XyTol
559 //------------------------------------------------------------------------------
562 //------------------------------------------------------------------------------
563 std::vector<Pt3d>& MePolyPts::Pts()
564 {
565  return *(m_p->m_pts);
566 } // MpPolyPts::Pts
567 //------------------------------------------------------------------------------
570 //------------------------------------------------------------------------------
571 BSHP<std::vector<Pt3d>> MePolyPts::PtsSharedPointer()
572 {
573  return m_p->m_pts;
574 } // MpPolyPts::PtsSharedPointer
575 //------------------------------------------------------------------------------
578 //------------------------------------------------------------------------------
579 std::vector<size_t> MePolyPts::HashPts()
580 {
581  std::vector<size_t> idx;
582  iHashPts(idx, PtsSharedPointer(), XyTol());
583  return idx;
584 } // MePolyPts::HashPts
585 //------------------------------------------------------------------------------
588 //------------------------------------------------------------------------------
590 {
591  std::vector<size_t> tmpSegs(HashPts()), retSegs;
592  // remove any consecutive indices in a_segs
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)
597  {
598  if (tmpSegs[i - 1] != tmpSegs[i])
599  retSegs.push_back(tmpSegs[i]);
600  }
601  return retSegs;
602 } // MpPolyPts::SegmentsForCleanPolyOffset
603 //------------------------------------------------------------------------------
606 //------------------------------------------------------------------------------
607 void MePolyPts::IntersectSegs(const std::vector<size_t>& a_segs)
608 {
609  std::vector<GmBstBox3d> envelopes(iCalcSegEnvelopes(a_segs, Pts()));
610  for (size_t i = 0; i < a_segs.size(); ++i)
611  {
612  for (size_t j = i + 1; j < a_segs.size(); ++j)
613  {
614  // this wouldn't work with the tests with boost 1.55
615  // if (bg::overlaps(m_envelopes[i], m_envelopes[j]))
616  // if (bg::covered_by(m_envelopes[i], m_envelopes[j]))
617  if (iEnvelopesOverlapOrTouch(i, j, envelopes, envelopes))
618  { // see if the segments intersect
619  CheckIntersectTwoSegs(i, j, a_segs, a_segs);
620  }
621  }
622  }
623 } // MpPolyPts::IntersectSegs
624 //------------------------------------------------------------------------------
628 //------------------------------------------------------------------------------
629 std::list<size_t> MePolyPts::SequenceWithIntersects(std::vector<size_t>& a_segs)
630 {
631  std::list<size_t> sequence;
632 
633  for (size_t i = 0; i < a_segs.size(); ++i)
634  {
635  sequence.push_back(a_segs[i]);
636 
637  SegMap::iterator it = m_p->m_segCross[&a_segs].find(i);
638  if (it == m_p->m_segCross[&a_segs].end())
639  continue;
640 
641  std::multimap<double, size_t>::iterator it1(it->second.begin());
642  for (; it1 != it->second.end(); ++it1)
643  {
644  size_t& pIdx(it1->second);
645  // don't add the same point twice (happens in testCase6c)
646  if (sequence.back() != pIdx)
647  sequence.push_back(pIdx);
648  }
649  }
650  return sequence;
651 } // MpPolyPts::SequenceWithIntersects
652 //------------------------------------------------------------------------------
660 //------------------------------------------------------------------------------
662  size_t a_j,
663  const std::vector<size_t>& a_iSeg,
664  const std::vector<size_t>& a_jSeg)
665 {
666  iCheckIntersection(a_i, a_j, a_iSeg, a_jSeg, m_p->m_pts, XyTol(), m_p->m_segCross, m_p->m_ps);
667 } // MpPolyPts::CheckIntersectTwoSegs
668 //------------------------------------------------------------------------------
675 //------------------------------------------------------------------------------
676 void MePolyPts::CalcLoopsForCleanPolyOffset(std::list<size_t>& a_sequence,
677  std::list<std::vector<size_t>>& a_loops)
678 {
679  while (!a_sequence.empty())
680  {
681  // keep doing this until we don't find any more
682  size_t sSize(0);
683  while (sSize != a_sequence.size())
684  {
685  sSize = a_sequence.size();
687  }
688 
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)
694  {
695  size_t& ptIdx(*it);
696  it1 = mapPidxItr.find(ptIdx);
697  if (it1 == mapPidxItr.end())
698  {
699  mapPidxItr[ptIdx] = it;
700  }
701  else
702  {
703  a_loops.push_back(std::vector<size_t>(it1->second, it));
704  a_sequence.erase(it1->second, it);
705  loopfound = true;
706  }
707  }
708  if (!loopfound)
709  {
710  a_loops.push_back(std::vector<size_t>(a_sequence.begin(), a_sequence.end()));
711  a_sequence.clear();
712  }
713  }
714 } // MpPolyPts::CalcLoopsForCleanPolyOffset
715 //------------------------------------------------------------------------------
721 //------------------------------------------------------------------------------
722 void MePolyPts::RemoveBackwardLoopsForCleanPolyOffset(std::list<std::vector<size_t>>& a_loops,
723  int a_pType)
724 {
725  std::vector<double> areas(iCalcPolyAreas(a_loops, Pts()));
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())
729  {
730  next = it;
731  ++next;
732  if ((a_pType == out && areas[cnt] > 0) || (a_pType == in && areas[cnt] < 0))
733  {
734  a_loops.erase(it);
735  }
736  it = next;
737  cnt++;
738  }
739 } // MpPolyPts::RemoveBackwardLoopsForCleanPolyOffset
740 //------------------------------------------------------------------------------
749 //------------------------------------------------------------------------------
750 void MePolyPts::ClassifyLoopsFromInPolyAndRemoveInvalid(std::list<std::vector<size_t>>& a_loops,
751  std::vector<int>& a_loopType)
752 {
753  std::vector<std::vector<size_t>> polyInsideOfPoly(a_loops.size());
754  iFindPolysInsideOfOtherPolys(polyInsideOfPoly, a_loops, *this);
755 
756  std::vector<double> areas(iCalcPolyAreas(a_loops, Pts()));
757  std::vector<int> validPoly(areas.size(), 1);
758  for (size_t i = 0; i < areas.size(); ++i)
759  {
760  if (areas[i] < 0)
761  validPoly[i] = false;
762  }
763  // if a polygon is not inside of another polygon then just check its area
764  // to see if we should remove it
765  size_t cnt_it(0);
766  std::list<std::vector<size_t>>::iterator it(a_loops.begin()), next;
767  for (; it != a_loops.end(); ++it, ++cnt_it)
768  {
769  if (polyInsideOfPoly[cnt_it].empty()) {}
770  else if (!polyInsideOfPoly[cnt_it].empty())
771  {
772  if (validPoly[polyInsideOfPoly[cnt_it][0]])
773  {
774  validPoly[cnt_it] = validPoly[cnt_it] ? 0 : 1;
775  }
776  }
777  // else
778  //{
779  // XM_ASSERT(false);
780  // XM_LOG(xmlog::debug, "Implement section in "
781  // "PolyCleanerImp::ClassifyLoopsFromInsidePoly");
782  //}
783  }
784 
785  for (it = a_loops.begin(), cnt_it = 0; it != a_loops.end(); it = next, ++cnt_it)
786  {
787  next = it;
788  ++next;
789  if (!validPoly[cnt_it])
790  {
791  a_loops.erase(it);
792  }
793  else
794  {
795  int type(MePolyOffsetter::INSIDE_POLY); // INSIDE_POLY
796  if (areas[cnt_it] < 0)
797  type = MePolyOffsetter::NEWOUT_POLY; // OUTSIDE_POLY
798  a_loopType.push_back(type);
799  }
800  }
801 } // MpPolyPts::ClassifyLoopsFromInPolyAndRemoveInvalid
802 //------------------------------------------------------------------------------
808 //------------------------------------------------------------------------------
809 bool MePolyPts::PolyInsideOfPoly(const std::vector<size_t>& a_poly,
810  const std::vector<size_t>& a_polyToTest)
811 {
812  std::vector<Pt3d>& pts(Pts());
813  GmBstPoly3d poly;
814  for (size_t i = 0; i < a_poly.size(); ++i)
815  {
816  bg::exterior_ring(poly).push_back(pts[a_poly[i]]);
817  }
818  bg::exterior_ring(poly).push_back(pts[a_poly[0]]);
819 
820  return iPolyInsideOfPoly(poly, a_polyToTest, pts);
821 } // MePolyPts::PolyInsideOfPoly
822 //------------------------------------------------------------------------------
829 //------------------------------------------------------------------------------
830 bool MePolyPts::PolyInsideOfPoly(const std::vector<Pt3d>& a_poly,
831  const std::vector<size_t>& a_polyToTest)
832 {
833  GmBstPoly3d poly;
834  for (size_t i = 0; i < a_poly.size(); ++i)
835  {
836  bg::exterior_ring(poly).push_back(a_poly[i]);
837  }
838  std::vector<Pt3d>& pts(Pts());
839  return iPolyInsideOfPoly(poly, a_polyToTest, pts);
840 } // MePolyPts::PolyInsideOfPoly
841 //------------------------------------------------------------------------------
847 //------------------------------------------------------------------------------
848 size_t MePolyPts::IdxFromPt3d(const Pt3d& a_pt)
849 {
850  if (!m_p->m_ps)
851  {
852  m_p->m_ps = GmPtSearch::New(true);
853  m_p->m_ps->VectorThatGrowsToSearch(m_p->m_pts);
854  }
855  int idx(0);
856  m_p->m_ps->AddPtToVectorIfUnique(a_pt, m_p->m_xyTol, idx);
857  return idx > -1 ? (size_t)idx : 0;
858 } // MePolyPts::IdxFromPt3d
859 
860 } // namespace xms
std::map< size_t, std::multimap< double, size_t > > SegMap
map for segment intersection indices
Definition: MePolyPts.cpp:42
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.
Definition: MePolyPts.cpp:750
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...
Definition: MePolyPts.cpp:848
std::vector< size_t > HashPts()
Hashes the point locations.
Definition: MePolyPts.cpp:579
#define T_TOL
tolerance used in multipoly intersector
Definition: MePolyPts.cpp:53
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.
Definition: MePolyPts.cpp:809
bool gmEqualPointsXY(double x1, double y1, double x2, double y2, double tolerance)
double m_xyTol
tolerance for geometric comparisons
Definition: MePolyPts.cpp:67
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.
Definition: MePolyPts.cpp:676
static std::vector< GmBstBox3d > iCalcSegEnvelopes(const std::vector< size_t > &a_segs, const std::vector< Pt3d > &a_pts)
Returns the envelopes of the segments.
Definition: MePolyPts.cpp:154
std::map< const std::vector< size_t > *, SegMap > MapSegMap
map used to see where segments cross each other
Definition: MePolyPts.cpp:44
std::list< size_t > SequenceWithIntersects(std::vector< size_t > &a_segs)
Returns a new sequence that includes intersection indexes.
Definition: MePolyPts.cpp:629
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...
Definition: MePolyPts.cpp:85
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.
Definition: MePolyPts.cpp:211
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.
Definition: MePolyPts.cpp:348
Implementation of MePolyPts.
Definition: MePolyPts.cpp:57
void IntersectSegs(const std::vector< size_t > &a_segs)
Intersects the segments.
Definition: MePolyPts.cpp:607
static std::vector< double > iCalcPolyAreas(const std::list< std::vector< size_t >> &a_loops, const std::vector< Pt3d > &a_pts)
Calculates polygon areas.
Definition: MePolyPts.cpp:492
BSHP< std::vector< Pt3d > > m_pts
point locations
Definition: MePolyPts.cpp:68
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.
Definition: MePolyPts.cpp:453
BSHP< GmPtSearch > m_ps
spatial index for searching points
Definition: MePolyPts.cpp:70
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.
Definition: MePolyPts.cpp:248
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.
Definition: MePolyPts.cpp:430
bool EQ_TOL(const _T &A, const _U &B, const _V &tolerance)
MapSegMap m_segCross
map used to see where segment cross each other
Definition: MePolyPts.cpp:69
#define XM_ASSERT(x)
BSHP< impl > m_p
implementation class
Definition: MePolyPts.h:57
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.
Definition: MePolyPts.cpp:191
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.
Definition: MePolyPts.cpp:101
static void iRemoveRepeatedSegmentFromSequence(std::list< size_t > &a_sequence)
Removes a repeated segment (2 numbers) from a sequence.
Definition: MePolyPts.cpp:511
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.
Definition: MePolyPts.cpp:661
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.
Definition: MePolyPts.cpp:571
MePolyPts()
constructor
Definition: MePolyPts.cpp:547
std::vector< Pt3d > & Pts()
Returns the vector of points.
Definition: MePolyPts.cpp:563
std::vector< size_t > SegmentsForCleanPolyOffset()
Returns the segments that will be used in CleanPolyOffset.
Definition: MePolyPts.cpp:589
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...
Definition: MePolyPts.cpp:722
double & XyTol()
Returns the tolerance.
Definition: MePolyPts.cpp:555
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...
Definition: MePolyPts.cpp:121
Utility class to work with polygon paving.
Definition: MePolyPts.h:28
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 ...
Definition: MePolyPts.cpp:291
bool gmOnLineAndBetweenEndpointsWithTol(const Pt3d &a_pt1, const Pt3d &a_pt2, const double a_x, const double a_y, double a_tol)