xmsmesh  1.0
MePolyCleaner.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 #include <iostream>
17 
18 // 4. External library headers
19 #include <xmscore/misc/XmError.h>
20 
21 // 5. Shared code headers
25 
26 // 6. Non-shared code headers
27 
28 //----- Forward declarations ---------------------------------------------------
29 using namespace xms;
30 
31 //----- External globals -------------------------------------------------------
32 
33 //----- Namespace declaration --------------------------------------------------
34 namespace xms
35 {
36 //----- Constants / Enumerations -----------------------------------------------
37 
38 //----- Classes / Structs ------------------------------------------------------
40 {
41 public:
43 
44  virtual void CleanPolyOffset(const VecPt3d& a_input,
45  int a_pType,
46  double a_tol,
47  MePolyOffsetterOutput& a_out) override;
48  virtual void SetOriginalOutsidePolygon(const VecPt3d& a_origOutsidePoly) override;
49  virtual void IntersectCleanInPolys(const std::vector<MePolyOffsetterOutput>& a_offsets,
50  MePolyOffsetterOutput& a_out,
51  double a_xyTol) override;
52  virtual void IntersectCleanInOutPolys(const MePolyOffsetterOutput& a_offsets,
53  MePolyOffsetterOutput& a_out,
54  double a_xyTol) override;
55 
57  int a_pType,
58  std::list<std::vector<size_t>>& a_loops,
59  std::vector<int>& a_loopType,
60  const VecPt3d& a_pts);
62 };
63 //----- Internal functions -----------------------------------------------------
64 #if 0
65 //------------------------------------------------------------------------------
67 //------------------------------------------------------------------------------
68 static void iDumpOutput(const MePolyOffsetterOutput& a_output)
69 {
70  std::cout << "o1.m_loops.size(): " << a_output.m_loops.size() << std::endl;
71  int i = -1;
72  for (auto loop : a_output.m_loops)
73  {
74  ++i;
75  std::cout << "loop type: " << a_output.m_loopTypes[i] << " loop number: " << i << std::endl;
76  for (auto idx : loop)
77  {
78  std::cout << idx << ", ";
79  }
80  std::cout << std::endl << std::endl;
81 
82  for (auto idx : loop)
83  {
84  std::cout << "m_pts[" << idx << "]: " << "{" << a_output.m_pts[idx].x << ", "
85  << a_output.m_pts[idx].y << "}" << std::endl;
86  }
87  }
88 }
89 #endif
90 
91 //----- Class / Function definitions -------------------------------------------
92 
93 //------------------------------------------------------------------------------
96 //------------------------------------------------------------------------------
97 BSHP<MePolyCleaner> MePolyCleaner::New()
98 {
99  BSHP<MePolyCleaner> ptr(new MePolyCleanerImpl());
100  return ptr;
101 } // PolyOffsetter::New
102 
107 //------------------------------------------------------------------------------
114 //------------------------------------------------------------------------------
115 void MePolyCleanerImpl::CleanPolyOffset(const std::vector<Pt3d>& a_input,
116  int a_pType,
117  double a_tol,
118  MePolyOffsetterOutput& a_out)
119 {
120  MePolyPts polyPts;
121  polyPts.XyTol() = a_tol;
122  polyPts.Pts() = a_input;
123  // create a vector of segments - vector with the indexes to the points in
124  // m_polyPts.m_pts
125  std::vector<size_t> segs(polyPts.SegmentsForCleanPolyOffset());
126 
127  // Intersect the segments
128  polyPts.IntersectSegs(segs);
129 
130  // Generate a list of segments that includes the intersections just
131  // calculated. We use a list because we are going to iteratively remove
132  // elements from the list and we didn't want to force a vector to keep
133  // copying stuff around when we delete items in the list.
134  std::list<size_t> sequence(polyPts.SequenceWithIntersects(segs));
135 
136  // create closed loops (polygons) using the list of segments. One polyline
137  // came into this method "a_input". That line may have intersected itself
138  // and is really multiple polygons. This next method extracts those multiple
139  // polygons
140  std::list<std::vector<size_t>> loops;
141  polyPts.CalcLoopsForCleanPolyOffset(sequence, loops);
142 
143  // clean up the polygons that were extracted
144  std::vector<int> loopType;
145  if (MePolyOffsetter::OUTSIDE_POLY == a_pType || loops.size() < 2)
146  { // when we pave inward or if we only extracted 1 polygon then
147  // we delete any polygons with an area that has
148  // the opposite sign from what we are expecting
149  polyPts.RemoveBackwardLoopsForCleanPolyOffset(loops, a_pType);
150  }
151  else
152  { // There are more rules when dealing with paving outward from polygons.
153  // Sometimes paving outward will create a new "outside" polygon that we
154  // then pave inward on the next step in the algorithm. See testCase8.
155  // You can also generate "inside" polygons that are inside of other
156  // "inside" polygons. These are deleted. Again see testCase8.
157  polyPts.ClassifyLoopsFromInPolyAndRemoveInvalid(loops, loopType);
158  }
159  FillOutputForCleanPolyOffset(a_out, a_pType, loops, loopType, polyPts.Pts());
160 } // MePolyCleanerImpl::CleanPolyOffset
161 //------------------------------------------------------------------------------
164 //------------------------------------------------------------------------------
165 void MePolyCleanerImpl::SetOriginalOutsidePolygon(const std::vector<Pt3d>& a_origOutsidePoly)
166 {
167  m_origOutsidePoly = a_origOutsidePoly;
168 } // MePolyCleanerImpl::SetOriginalOutsidePolygon
169 //------------------------------------------------------------------------------
178 //------------------------------------------------------------------------------
179 void MePolyCleanerImpl::IntersectCleanInPolys(const std::vector<MePolyOffsetterOutput>& a_offsets,
180  MePolyOffsetterOutput& a_out,
181  double a_xyTol)
182 {
183  MeIntersectPolys inPolys;
184  inPolys.SetupInIn(a_offsets, a_xyTol);
185  // compute envelopes for all INSIDE_POLY polygons
186  inPolys.CalcEnvelopes();
187  // do trivial cases of completely disjoint or completely inside
188  inPolys.InInTrivialPolyCases();
189  // intersect segments of potentially overlapping polys
190  inPolys.InInDoIntersection();
191  inPolys.FillOutput(a_out);
192  // make sure that NEWOUT_POLY polygons are inside of OUTSIDE_POLY polygons
194 } // MePolyCleanerImpl::IntersectCleanInPolys
195 //------------------------------------------------------------------------------
202 //------------------------------------------------------------------------------
204  MePolyOffsetterOutput& a_out,
205  double a_xyTol)
206 {
207  MeIntersectPolys inPolys;
208  inPolys.SetupInOut(a_offsets, a_xyTol);
209  inPolys.CalcEnvelopes();
210  inPolys.InOutDoIntersection();
211  inPolys.FillOutput(a_out);
212 } // MePolyCleanerImpl::IntersectCleanInPolys
213 //------------------------------------------------------------------------------
220 //------------------------------------------------------------------------------
222  int a_pType,
223  std::list<std::vector<size_t>>& a_loops,
224  std::vector<int>& a_loopType,
225  const std::vector<Pt3d>& a_pts)
226 {
227  a_out.m_pts = a_pts;
228  a_out.m_loops.resize(0);
229  a_out.m_loops.reserve(a_loops.size());
230  std::list<std::vector<size_t>>::iterator it(a_loops.begin());
231  for (; it != a_loops.end(); ++it)
232  {
233  a_out.m_loops.push_back(std::vector<size_t>(it->begin(), it->end()));
234  }
235  std::vector<int>& lt(a_out.m_loopTypes);
236  if (!a_loopType.empty())
237  lt.swap(a_loopType);
238  else
239  lt.assign(a_loops.size(), a_pType);
240 } // MePolyCleanerImpl::FillOutputForCleanPolyOffset
241 
242 } // namespace xms
243 
244 #ifdef CXX_TEST
245 
248 
250 
251 // namespace xms {
252 using namespace xms;
253 
258 //------------------------------------------------------------------------------
260 //------------------------------------------------------------------------------
262 {
263  BSHP<MePolyCleaner> b = MePolyCleaner::New();
264  TS_ASSERT(b);
265 } // MePolyCleanerUnitTests::testCreateClass
266 //------------------------------------------------------------------------------
268 //------------------------------------------------------------------------------
270 {
271  // x = 0 1
272  //
273  // y=1 1
274  // /|
275  // / |
276  // / |
277  // / |
278  // y=0 0---------2
280  std::vector<Pt3d> input = {{0, 0, 0}, {1, 1, 0}, {1, 0, 0}};
282  p.CleanPolyOffset(input, 0, 1e-9, out);
283  TS_ASSERT_EQUALS(1, out.m_loops.size());
284  if (out.m_loops.size() != 1)
285  return;
286  std::vector<size_t> baseLoop = {0, 1, 2};
287  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
288  TS_ASSERT_EQUALS(0, out.m_loopTypes[0]);
289  TS_ASSERT_EQUALS_VEC(input, out.m_pts);
290 } // MePolyCleanerUnitTests::testCase0
291 //------------------------------------------------------------------------------
293 //------------------------------------------------------------------------------
295 {
296  // x = 0 1
297  //
298  // y=1 1---------2
299  // | |
300  // | |
301  // | |
302  // | |
303  // y=0 0---------3
305  std::vector<Pt3d> input = {{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}};
307  p.CleanPolyOffset(input, 0, 1e-9, out);
308  TS_ASSERT_EQUALS(1, out.m_loops.size());
309  if (out.m_loops.size() != 1)
310  return;
311  std::vector<size_t> baseLoop = {0, 1, 2, 3};
312  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
313  TS_ASSERT_EQUALS(0, out.m_loopTypes[0]);
314  TS_ASSERT_EQUALS_VEC(input, out.m_pts);
315 } // MePolyCleanerUnitTests::testCase1
316 //------------------------------------------------------------------------------
318 //------------------------------------------------------------------------------
320 {
321  // x = 0 1
322  //
323  // y=2 2---------3
324  // \ |
325  // \ |
326  // \ |
327  // y=1 \|1
328  // /|
329  // / |
330  // / |
331  // / |
332  // y=0 0---------4
333 
335  std::vector<Pt3d> input = {{0, 0, 0}, {1, 1, 0}, {0, 2, 0}, {1, 2, 0}, {1, 0, 0}};
337  p.CleanPolyOffset(input, 0, 1e-9, out);
338  TS_ASSERT_EQUALS(2, out.m_loops.size());
339  if (out.m_loops.size() != 2)
340  return;
341  std::vector<Pt3d> base = input;
342  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
343  std::vector<size_t> baseLoop = {1, 2, 3};
344  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
345  baseLoop = {0, 1, 4};
346  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
347  std::vector<int> baseType = {0, 0};
348  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
349 } // MePolyCleanerUnitTests::testCase2
350 //------------------------------------------------------------------------------
352 //------------------------------------------------------------------------------
354 {
355  // x = 0 1
356  //
357  // y=2 0---------1
358  // \ |
359  // \ |
360  // \ |
361  // y=1 \|4
362  // /|
363  // / |
364  // / |
365  // / |
366  // y=0 3---------2
367 
369  std::vector<Pt3d> input = {{0, 2, 0}, {1, 2, 0}, {1, 0, 0}, {0, 0, 0}, {1, 1, 0}};
371  p.CleanPolyOffset(input, 0, 1e-9, out);
372  TS_ASSERT_EQUALS(2, out.m_loops.size());
373  if (out.m_loops.size() != 2)
374  return;
375  std::vector<Pt3d> base = input;
376  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
377  std::vector<size_t> baseLoop = {4, 2, 3};
378  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
379  baseLoop = {0, 1, 4};
380  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
381  std::vector<int> baseType = {0, 0};
382  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
383 } // MePolyCleanerUnitTests::testCase2a
384 //------------------------------------------------------------------------------
386 //------------------------------------------------------------------------------
388 {
389  // x = 0 2
390  //
391  // y=6 2---------3
392  // \ |
393  // \ |
394  // \ |
395  // \ |
396  // \|
397  // |\
398  // | \
399  //y=3 | 1
400  // | /
401  // |/
402  // /|
403  // / |
404  // / |
405  // / |
406  // / |
407  // y=0 0---------4
409  std::vector<Pt3d> input = {{0, 0, 0}, {3, 3, 0}, {0, 6, 0}, {2, 6, 0}, {2, 0, 0}};
411  p.CleanPolyOffset(input, 0, 1e-9, out);
412  TS_ASSERT_EQUALS(2, out.m_loops.size());
413  if (out.m_loops.size() != 2)
414  return;
415  std::vector<Pt3d> base = input;
416  base.push_back(Pt3d(2, 2, 0));
417  base.push_back(Pt3d(2, 4, 0));
418  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
419  std::vector<size_t> baseLoop = {6, 2, 3};
420  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
421  baseLoop = {0, 5, 4};
422  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
423  std::vector<int> baseType = {0, 0};
424  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
425 } // MePolyCleanerUnitTests::testCase3
426 //------------------------------------------------------------------------------
428 //------------------------------------------------------------------------------
430 {
431  // x = 0 2
432  //
433  // y=6 4---------0
434  // \ |
435  // \ |
436  // \ |
437  // \ |
438  // \|
439  // |\
440  // | \
441  //y=3 | 3
442  // | /
443  // |/
444  // /|
445  // / |
446  // / |
447  // / |
448  // / |
449  // y=0 2---------1
451  std::vector<Pt3d> input = {{2, 6, 0}, {2, 0, 0}, {0, 0, 0}, {3, 3, 0}, {0, 6, 0}};
453  p.CleanPolyOffset(input, 0, 1e-9, out);
454  TS_ASSERT_EQUALS(2, out.m_loops.size());
455  if (out.m_loops.size() != 2)
456  return;
457  std::vector<Pt3d> base = input;
458  base.push_back(Pt3d(2, 2, 0));
459  base.push_back(Pt3d(2, 4, 0));
460  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
461  std::vector<size_t> baseLoop = {5, 1, 2};
462  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
463  baseLoop = {0, 6, 4};
464  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
465  std::vector<int> baseType = {0, 0};
466  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
467 } // MePolyCleanerUnitTests::testCase3a
468 //------------------------------------------------------------------------------
470 //------------------------------------------------------------------------------
472 {
473  // x = 0 1
474  //
475  // y=1 3
476  // /|
477  // / |
478  // / |
479  // / |
480  // y=0 (2)1---------0
482  std::vector<Pt3d> input = {{1, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 1, 0}};
484  p.CleanPolyOffset(input, 0, 1e-9, out);
485  TS_ASSERT_EQUALS(1, out.m_loops.size());
486  if (out.m_loops.size() != 1)
487  return;
488  std::vector<Pt3d> base = input;
489  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
490  std::vector<size_t> baseLoop = {0, 1, 3};
491  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
492  std::vector<int> baseType = {0};
493  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
494 } // MePolyCleanerUnitTests::testCase4
495 //------------------------------------------------------------------------------
497 //------------------------------------------------------------------------------
499 {
500  // x = 0 4
501  //
502  // y=6 5----------------0
503  // \ /
504  // \ /
505  // \ /
506  // \ /
507  // \ /
508  // \ /
509  // \ / 1
510  // y=3 4 / \
511  // / \
512  // / \
513  // / \
514  // / \
515  // / \
516  // / \
517  // / \
518  //y=0 3-----------------2
520  std::vector<Pt3d> input = {{4, 6, 0}, {2, 3, 0}, {4, 0, 0}, {0, 0, 0}, {2, 3, 0}, {0, 6, 0}};
522  p.CleanPolyOffset(input, 0, 1e-9, out);
523  TS_ASSERT_EQUALS(2, out.m_loops.size());
524  if (out.m_loops.size() != 2)
525  return;
526  std::vector<Pt3d> base = input;
527  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
528  std::vector<size_t> baseLoop = {1, 2, 3};
529  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
530  baseLoop = {0, 1, 5};
531  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
532  std::vector<int> baseType = {0, 0};
533  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
534 } // MePolyCleanerUnitTests::testCase5
535 //------------------------------------------------------------------------------
537 //------------------------------------------------------------------------------
539 {
540  // x = 0 4
541  //
542  // y=6 1----------------2
543  // \ /
544  // \ /
545  // \ /
546  // \ /
547  // \ /
548  // \ /
549  // \ / 3
550  // y=3 0 / \
551  // / \
552  // / \
553  // / \
554  // / \
555  // / \
556  // / \
557  // / \
558  //y=0 5-----------------4
560  std::vector<Pt3d> input = {{4, 2, 0}, {0, 6, 0}, {4, 6, 0}, {4, 2, 0}, {4, 0, 0}, {0, 0, 0}};
562  p.CleanPolyOffset(input, 0, 1e-9, out);
563  TS_ASSERT_EQUALS(2, out.m_loops.size());
564  if (out.m_loops.size() != 2)
565  return;
566  std::vector<Pt3d> base = input;
567  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
568  std::vector<size_t> baseLoop = {0, 1, 2};
569  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
570  baseLoop = {0, 4, 5};
571  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
572  std::vector<int> baseType = {0, 0};
573  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
574 } // MePolyCleanerUnitTests::testCase5a
575 //------------------------------------------------------------------------------
577 //------------------------------------------------------------------------------
579 {
580  // x = 0 4
581  //
582  // y=6 1----------------2
583  // | |
584  // | |
585  // | |
586  // | |
587  // y=4 4----------------3
588  // |
589  // |
590  // |
591  // |
592  // |
593  // y=2 5-----------------6
594  // | |
595  // | |
596  // | |
597  // | |
598  // y=0 0-----------------7
600  std::vector<Pt3d> input = {{0, 0, 0}, {0, 6, 0}, {4, 6, 0}, {4, 4, 0},
601  {0, 4, 0}, {0, 2, 0}, {4, 2, 0}, {4, 0, 0}};
603  p.CleanPolyOffset(input, 0, 1e-9, out);
604  TS_ASSERT_EQUALS(2, out.m_loops.size());
605  if (out.m_loops.size() != 2)
606  return;
607  std::vector<Pt3d> base = input;
608  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
609  std::vector<size_t> baseLoop = {4, 1, 2, 3};
610  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
611  baseLoop = {0, 5, 6, 7};
612  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
613  std::vector<int> baseType = {0, 0};
614  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
615 } // MePolyCleanerUnitTests::testCase6
616 //------------------------------------------------------------------------------
618 //------------------------------------------------------------------------------
620 {
621  // x = 0 4
622  //
623  // y=6 6----------------7
624  // | |
625  // | |
626  // | |
627  // | |
628  // y=4 1----------------0
629  // |
630  // |
631  // |
632  // |
633  // |
634  // y=2 2-----------------3
635  // | |
636  // | |
637  // | |
638  // | |
639  // y=0 5-----------------4
641  std::vector<Pt3d> input = {{2, 4, 0}, {0, 4, 0}, {0, 2, 0}, {4, 2, 0},
642  {4, 0, 0}, {0, 0, 0}, {0, 6, 0}, {4, 6, 0}};
644  p.CleanPolyOffset(input, 0, 1e-9, out);
645  TS_ASSERT_EQUALS(2, out.m_loops.size());
646  if (out.m_loops.size() != 2)
647  return;
648  std::vector<Pt3d> base = input;
649  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
650  std::vector<size_t> baseLoop = {2, 3, 4, 5};
651  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
652  baseLoop = {0, 1, 6, 7};
653  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
654  std::vector<int> baseType = {0, 0};
655  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
656 } // MePolyCleanerUnitTests::testCase6a
657 //------------------------------------------------------------------------------
659 //------------------------------------------------------------------------------
661 {
662  // x = 0 4
663  //
664  // y=6 7----------------8
665  // | |
666  // | |
667  // | |
668  // | |
669  // y=4 1----------------0
670  // |
671  // |
672  // 6
673  // |
674  // |
675  // y=2 2-----------------3
676  // | |
677  // | |
678  // | |
679  // | |
680  // y=0 5-----------------4
682  std::vector<Pt3d> input = {{4, 4, 0}, {0, 4, 0}, {0, 2, 0}, {4, 2, 0}, {4, 0, 0},
683  {0, 0, 0}, {0, 3, 0}, {0, 6, 0}, {4, 6, 0}};
685  p.CleanPolyOffset(input, 0, 1e-9, out);
686  TS_ASSERT_EQUALS(2, out.m_loops.size());
687  if (out.m_loops.size() != 2)
688  return;
689  std::vector<Pt3d> base = input;
690  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
691  std::vector<size_t> baseLoop = {2, 3, 4, 5};
692  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
693  baseLoop = {0, 1, 7, 8};
694  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
695  std::vector<int> baseType = {0, 0};
696  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
697 } // MePolyCleanerUnitTests::testCase6b
698 //------------------------------------------------------------------------------
700 //------------------------------------------------------------------------------
702 {
703  // x = 0 4
704  //
705  // y=6 9----------------10
706  // | |
707  // | |
708  // | |
709  // | |
710  // y=4 (8)1----------------0
711  // |
712  // |
713  // 7
714  // |
715  // |
716  // y=2 (6)2-----------------3
717  // | |
718  // | |
719  // | |
720  // | |
721  // y=0 5-----------------4
723  std::vector<Pt3d> input = {{4, 4, 0}, {0, 4, 0}, {0, 2, 0}, {4, 2, 0}, {4, 0, 0}, {0, 0, 0},
724  {0, 2, 0}, {0, 3, 0}, {0, 4, 0}, {0, 6, 0}, {4, 6, 0}};
726  p.CleanPolyOffset(input, 0, 1e-9, out);
727  TS_ASSERT_EQUALS(2, out.m_loops.size());
728  if (out.m_loops.size() != 2)
729  return;
730  std::vector<Pt3d> base = input;
731  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
732  std::vector<size_t> baseLoop = {2, 3, 4, 5};
733  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
734  baseLoop = {0, 1, 9, 10};
735  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
736  std::vector<int> baseType = {0, 0};
737  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
738 } // MePolyCleanerUnitTests::testCase6c
739 //------------------------------------------------------------------------------
741 //------------------------------------------------------------------------------
743 {
744  // x = 0 4 8
745  //
746  // y=6 10---------------------------------11
747  // | |
748  // | |
749  // | |
750  // | 1(8) |
751  // y=4 9---------------------------------0
752  // |
753  // |
754  // |
755  // |
756  // |
757  // y=2 6----------------------------------3
758  // | 2(7) |
759  // | |
760  // | |
761  // | |
762  // y=0 5----------------------------------4
764  std::vector<Pt3d> input = {{8, 4, 0}, {4, 4, 0}, {4, 2, 0}, {8, 2, 0}, {8, 0, 0}, {0, 0, 0},
765  {0, 2, 0}, {4, 2, 0}, {4, 4, 0}, {0, 4, 0}, {0, 6, 0}, {8, 6, 0}};
767  p.CleanPolyOffset(input, 0, 1e-9, out);
768  TS_ASSERT_EQUALS(2, out.m_loops.size());
769  if (out.m_loops.size() != 2)
770  return;
771  std::vector<Pt3d> base = input;
772  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
773  std::vector<size_t> baseLoop = {2, 3, 4, 5, 6};
774  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
775  baseLoop = {0, 1, 9, 10, 11};
776  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
777  std::vector<int> baseType = {0, 0};
778  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
779 } // MePolyCleanerUnitTests::testCase7
780 //------------------------------------------------------------------------------
782 //------------------------------------------------------------------------------
784 {
785  // x = 0 4 8
786  //
787  // y=6 10---------------------------------11
788  // | |
789  // | |
790  // 9----------------8 |
791  // | |
792  // y=4 -----------------0
793  // | 1
794  // |
795  // |
796  // |
797  // | 2
798  // y=2 ------------------3
799  // | |
800  // 6----------------7 |
801  // | |
802  // | |
803  // y=0 5----------------------------------4
805  std::vector<Pt3d> input = {{8, 4, 0}, {4, 4, 0}, {4, 2, 0}, {8, 2, 0}, {8, 0, 0}, {0, 0, 0},
806  {0, 1, 0}, {4, 1, 0}, {4, 5, 0}, {0, 5, 0}, {0, 6, 0}, {8, 6, 0}};
808  p.CleanPolyOffset(input, 0, 1e-9, out);
809  TS_ASSERT_EQUALS(2, out.m_loops.size());
810  if (out.m_loops.size() != 2)
811  return;
812  std::vector<Pt3d> base = input;
813  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
814  std::vector<size_t> baseLoop = {2, 3, 4, 5, 6, 7};
815  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
816  baseLoop = {0, 1, 8, 9, 10, 11};
817  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
818  std::vector<int> baseType = {0, 0};
819  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
820 } // MePolyCleanerUnitTests::testCase7a
821 //------------------------------------------------------------------------------
823 //------------------------------------------------------------------------------
825 {
826  // x = 0 4 8
827  //
828  // y=6 10---------------------------------11
829  // | |
830  // | |
831  // 9----------------8 |
832  // | |
833  // y=4 -----------------0
834  // | 1
835  // |
836  // 6----------------| 7
837  // | |
838  // | | 2
839  // y=2 | ------------------3
840  // | |
841  // | |
842  // | |
843  // | |
844  // y=0 5----------------------------------4
846  std::vector<Pt3d> input = {{8, 4, 0}, {4, 4, 0}, {4, 2, 0}, {8, 2, 0}, {8, 0, 0}, {0, 0, 0},
847  {0, 3, 0}, {4, 3, 0}, {4, 5, 0}, {0, 5, 0}, {0, 6, 0}, {8, 6, 0}};
849  p.CleanPolyOffset(input, 0, 1e-9, out);
850  TS_ASSERT_EQUALS(2, out.m_loops.size());
851  if (out.m_loops.size() != 2)
852  return;
853  std::vector<Pt3d> base = input;
854  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
855  std::vector<size_t> baseLoop = {7, 2, 3, 4, 5, 6};
856  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
857  baseLoop = {0, 1, 8, 9, 10, 11};
858  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
859  std::vector<int> baseType = {0, 0};
860  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
861 } // MePolyCleanerUnitTests::testCase7b
862 //------------------------------------------------------------------------------
864 //------------------------------------------------------------------------------
866 {
867  // x = 0 4 8
868  //
869  // y=6 10---------------------------------11
870  // | |
871  // | |
872  // | |
873  // | 1 |
874  // y=4 | -----------------0
875  // | |
876  // 9----------------| 8
877  // |
878  // 6----------------| 7
879  // | |
880  // y=2 | ------------------3
881  // | 2 |
882  // | |
883  // | |
884  // | |
885  // y=0 5----------------------------------4
887  std::vector<Pt3d> input = {{8, 4, 0}, {4, 4, 0}, {4, 2, 0}, {8, 2, 0},
888  {8, 0, 0}, {0, 0, 0}, {0, 2.5, 0}, {4, 2.5, 0},
889  {4, 3.5, 0}, {0, 3.5, 0}, {0, 6, 0}, {8, 6, 0}};
891  p.CleanPolyOffset(input, 0, 1e-9, out);
892  TS_ASSERT_EQUALS(2, out.m_loops.size());
893  if (out.m_loops.size() != 2)
894  return;
895  std::vector<Pt3d> base = input;
896  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
897  std::vector<size_t> baseLoop = {7, 2, 3, 4, 5, 6};
898  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
899  baseLoop = {0, 1, 8, 9, 10, 11};
900  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
901  std::vector<int> baseType = {0, 0};
902  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
903 } // MePolyCleanerUnitTests::testCase7c
904 //------------------------------------------------------------------------------
906 //------------------------------------------------------------------------------
908 {
909  // x = 0 4 8
910  //
911  // y=6 10----------------------------------9
912  // | |
913  // | |
914  // | |
915  // | |
916  // y=4 | 6 3 8
917  // | / \ / \ /
918  // | / \ / \ /
919  // | 5 /\ \/
920  // | \ / \ / \
921  // | \ / \ / \
922  //y=2 | 4 7 2
923  // | |
924  // | |
925  // | |
926  // | |
927  // y=0 0----------------------------------1
929  std::vector<Pt3d> input = {{0, 0, 0}, {8, 0, 0}, {8, 2, 0}, {6, 4, 0}, {4, 2, 0}, {3, 3, 0},
930  {4, 4, 0}, {6, 2, 0}, {8, 4, 0}, {8, 6, 0}, {0, 6, 0}};
932  p.CleanPolyOffset(input, 1, 1e-9, out);
933  TS_ASSERT_EQUALS(2, out.m_loops.size());
934  if (out.m_loops.size() != 2)
935  return;
936  std::vector<Pt3d> base = input;
937  base.push_back(Pt3d(7, 3, 0));
938  base.push_back(Pt3d(5, 3, 0));
939  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
940  std::vector<size_t> baseLoop = {12, 4, 5, 6};
941  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
942  baseLoop = {0, 1, 2, 11, 8, 9, 10};
943  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
944  std::vector<int> baseType = {2, 1};
945  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
946 } // MePolyCleanerUnitTests::testCase8
947 //------------------------------------------------------------------------------
949 //------------------------------------------------------------------------------
951 {
952  // x = 0 4 8
953  //
954  // y=6 1----------------------------------0
955  // | |
956  // | |
957  // | |
958  // | |
959  // y=4 | 8 5 10
960  // | / \ / \ /
961  // | / \ / \ /
962  // | 7 /\ \/
963  // | \ / \ / \
964  // | \ / \ / \
965  //y=2 | 6 9 4
966  // | |
967  // | |
968  // | |
969  // | |
970  // y=0 2----------------------------------3
972  std::vector<Pt3d> input = {{8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {8, 0, 0}, {8, 2, 0}, {6, 4, 0},
973  {4, 2, 0}, {3, 3, 0}, {4, 4, 0}, {6, 2, 0}, {8, 4, 0}};
975  p.CleanPolyOffset(input, 1, 1e-9, out);
976  TS_ASSERT_EQUALS(2, out.m_loops.size());
977  if (out.m_loops.size() != 2)
978  return;
979  std::vector<Pt3d> base = input;
980  base.push_back(Pt3d(7, 3, 0));
981  base.push_back(Pt3d(5, 3, 0));
982  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
983  std::vector<size_t> baseLoop = {12, 6, 7, 8};
984  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
985  baseLoop = {0, 1, 2, 3, 4, 11, 10};
986  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
987  std::vector<int> baseType = {2, 1};
988  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
989 } // MePolyCleanerUnitTests::testCase8a
990 //------------------------------------------------------------------------------
992 //------------------------------------------------------------------------------
994 {
995  // x = 0 4 8
996  //
997  // y=6 7----------------------------------6
998  // | |
999  // | |
1000  // | |
1001  // | |
1002  // y=4 | 3 0 5
1003  // | / \ / \ /
1004  // | / \ / \ /
1005  // | 2 /\ \/
1006  // | \ / \ / \
1007  // | \ / \ / \
1008  //y=2 | 1 4 10
1009  // | |
1010  // | |
1011  // | |
1012  // | |
1013  // y=0 8----------------------------------9
1015  std::vector<Pt3d> input = {{6, 4, 0}, {4, 2, 0}, {3, 3, 0}, {4, 4, 0}, {6, 2, 0}, {8, 4, 0},
1016  {8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {6, 0, 0}, {8, 2, 0}};
1018  p.CleanPolyOffset(input, 1, 1e-9, out);
1019  TS_ASSERT_EQUALS(2, out.m_loops.size());
1020  if (out.m_loops.size() != 2)
1021  return;
1022  std::vector<Pt3d> base = input;
1023  base.push_back(Pt3d(5, 3, 0));
1024  base.push_back(Pt3d(7, 3, 0));
1025  TS_ASSERT_EQUALS_VEC(base, out.m_pts);
1026  std::vector<size_t> baseLoop = {11, 1, 2, 3};
1027  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
1028  baseLoop = {12, 5, 6, 7, 8, 9, 10};
1029  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
1030  std::vector<int> baseType = {2, 1};
1031  TS_ASSERT_EQUALS_VEC(baseType, out.m_loopTypes);
1032 } // MePolyCleanerUnitTests::testCase8b
1033 //------------------------------------------------------------------------------
1035 //------------------------------------------------------------------------------
1037 {
1038  // x = 0 4 8
1039  //
1040  // y=6 7----------------------------------6
1041  // | |
1042  // | |
1043  // | |
1044  // | |
1045  // y=4 | 3 0 5
1046  // | / \ /| /
1047  // | / \ / | /
1048  // | 2 /\ | /
1049  // | \ / \ | /
1050  // | \ / \|/
1051  // y=2 | 1 4(10)
1052  // | \
1053  // | \
1054  // | \
1055  // | \
1056  //y=0 8----------------------------------9
1058  std::vector<Pt3d> input = {{6, 4, 0}, {4, 2, 0}, {3, 3, 0}, {4, 4, 0}, {6, 2, 0}, {8, 4, 0},
1059  {8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {6, 0, 0}, {6, 2, 0}};
1061  p.CleanPolyOffset(input, 1, 1e-9, out);
1062  TS_ASSERT_EQUALS(2, out.m_loops.size());
1063  if (2 != out.m_loops.size())
1064  return;
1065  std::vector<Pt3d> basePts = {{6, 4, 0}, {4, 2, 0}, {3, 3, 0}, {4, 4, 0}, {6, 2, 0}, {8, 4, 0},
1066  {8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {6, 0, 0}, {6, 2, 0}, {5, 3, 0}};
1067  TS_ASSERT_EQUALS_VEC(basePts, out.m_pts);
1068  std::vector<size_t> baseLoop = {11, 1, 2, 3};
1069  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
1070  baseLoop = {4, 5, 6, 7, 8, 9};
1071  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[1]);
1072  std::vector<int> basePolyType = {2, 1};
1073  TS_ASSERT_EQUALS_VEC(basePolyType, out.m_loopTypes);
1074 } // MePolyCleanerUnitTests::testCase8c
1075 //------------------------------------------------------------------------------
1077 //------------------------------------------------------------------------------
1079 {
1080  // x = 0 4 8
1081  //
1082  // y=6 1----------------------------------0
1083  // | |
1084  // | |
1085  // | |
1086  // | |
1087  // y=4 | |
1088  // | |
1089  // | 5 |
1090  // | /\ |
1091  // | / \ |
1092  // | / \ |
1093  // y=2 | 6 / \4 |
1094  // | \ / |
1095  // | \ / |
1096  // | \ / |
1097  // | 7\/ |
1098  // y=0 2----------------3-----------------8
1100  std::vector<Pt3d> input = {{8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {4, 0, 0}, {5, 2, 0},
1101  {3, 4, 0}, {3, 2, 0}, {4, 0, 0}, {8, 0, 0}};
1103  p.CleanPolyOffset(input, 1, 1e-9, out);
1104  TS_ASSERT_EQUALS(1, out.m_loops.size());
1105  if (1 != out.m_loops.size())
1106  return;
1107  std::vector<Pt3d> basePts = {{8, 6, 0}, {0, 6, 0}, {0, 0, 0}, {4, 0, 0}, {5, 2, 0},
1108  {3, 4, 0}, {3, 2, 0}, {4, 0, 0}, {8, 0, 0}};
1109  TS_ASSERT_EQUALS_VEC(basePts, out.m_pts);
1110  std::vector<size_t> baseLoop = {0, 1, 2, 3, 8};
1111  TS_ASSERT_EQUALS_VEC(baseLoop, out.m_loops[0]);
1112  std::vector<int> basePolyType = {1};
1113  TS_ASSERT_EQUALS_VEC(basePolyType, out.m_loopTypes);
1114 } // MePolyCleanerUnitTests::testCase9
1115 //------------------------------------------------------------------------------
1117 //------------------------------------------------------------------------------
1119 {
1120  // x = 0 4 8
1121  //
1122  //
1123  // y=2 3----------2 7--------6
1124  // | | | |
1125  // | | | |
1126  // | | | |
1127  // | | | |
1128  // y=0 0----------1 4--------5
1129  MePolyOffsetterOutput o, o1;
1130  o.m_pts = {{0, 0, 0}, {3, 0, 0}, {3, 2, 0}, {0, 2, 0},
1131  {4, 0, 0}, {6, 0, 0}, {6, 2, 0}, {4, 2, 0}};
1132  std::vector<size_t> v0 = {0, 1, 2, 3};
1133  o.m_loops.push_back(v0);
1134  std::vector<size_t> v1 = {4, 5, 6, 7};
1135  o.m_loops.push_back(v1);
1136  o.m_loopTypes.assign(2, MePolyOffsetter::INSIDE_POLY);
1138  std::vector<MePolyOffsetterOutput> vO(1, o);
1139  p.IntersectCleanInPolys(vO, o1, 1e-9);
1140  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1141  if (2 != o1.m_loops.size())
1142  return;
1144  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[0]);
1145  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[1]);
1147 } // MePolyCleanerUnitTests::testCleanIn0
1148 //------------------------------------------------------------------------------
1150 //------------------------------------------------------------------------------
1152 {
1153  // x = 0 4 8
1154  //
1155  // y=4 3----------------------------------2
1156  // | |
1157  // | |
1158  // | |
1159  // | |
1160  // | |
1161  // y=2 | 7------6 |
1162  // | | | |
1163  // | | | |
1164  // | 4------5 |
1165  // | |
1166  // y=0 0----------------------------------1
1167  MePolyOffsetterOutput o, o1;
1168  o.m_pts = {{0, 0, 0}, {8, 0, 0}, {8, 4, 0}, {0, 4, 0},
1169  {2, 1, 0}, {4, 1, 0}, {4, 2, 0}, {2, 2, 0}};
1170  std::vector<size_t> v0 = {0, 1, 2, 3};
1171  o.m_loops.push_back(v0);
1172  std::vector<size_t> v1 = {4, 5, 6, 7};
1173  o.m_loops.push_back(v1);
1174  o.m_loopTypes.assign(2, MePolyOffsetter::INSIDE_POLY);
1176  std::vector<MePolyOffsetterOutput> vO(1, o);
1177  p.IntersectCleanInPolys(vO, o1, 1e-9);
1178  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1179  if (1 != o1.m_loops.size())
1180  return;
1182  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[0]);
1183  std::vector<int> baseLoopType = {1};
1184  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1185 } // MePolyCleanerUnitTests::testCleanIn1
1186 //------------------------------------------------------------------------------
1188 //------------------------------------------------------------------------------
1190 {
1191  // x = 0 4 8
1192  //
1193  // y=4 7----------------------------------6
1194  // | |
1195  // | |
1196  // | |
1197  // | |
1198  // | |
1199  // y=2 | 3------2 |
1200  // | | | |
1201  // | | | |
1202  // | 0------1 |
1203  // | |
1204  // y=0 4----------------------------------5
1205  MePolyOffsetterOutput o, o1;
1206  o.m_pts = {{2, 1, 0}, {4, 1, 0}, {4, 2, 0}, {2, 2, 0},
1207  {0, 0, 0}, {8, 0, 0}, {8, 4, 0}, {0, 4, 0}};
1208  std::vector<size_t> v0 = {0, 1, 2, 3};
1209  o.m_loops.push_back(v0);
1210  std::vector<size_t> v1 = {4, 5, 6, 7};
1211  o.m_loops.push_back(v1);
1212  o.m_loopTypes.assign(2, MePolyOffsetter::INSIDE_POLY);
1214  std::vector<MePolyOffsetterOutput> vO(1, o);
1215  p.IntersectCleanInPolys(vO, o1, 1e-9);
1216  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1217  if (1 != o1.m_loops.size())
1218  return;
1220  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[0]);
1221  std::vector<int> baseLoopType = {1};
1222  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1223 } // MePolyCleanerUnitTests::testCleanIn1a
1224 //------------------------------------------------------------------------------
1226 //------------------------------------------------------------------------------
1228 {
1229  // x = 0 4 8
1230  //
1231  // y=4 7----------------------------------6
1232  // | |
1233  // | 15------14 |
1234  // | | | |
1235  // | 12------13 |
1236  // | |
1237  // y=2 | 3------2 8------11 |
1238  // | | | | | |
1239  // | | | | | |
1240  // | 0------1 9------10 |
1241  // | |
1242  // y=0 4----------------------------------5
1243  MePolyOffsetterOutput o, o1;
1244  o.m_pts = {{2, 1, 0}, {4, 1, 0}, {4, 2, 0}, {2, 2, 0}, {0, 0, 0}, {8, 0, 0},
1245  {8, 4, 0}, {0, 4, 0}, {5, 1, 0}, {7, 1, 0}, {7, 2, 0}, {5, 2, 0},
1246  {5, 3, 0}, {7, 3, 0}, {7, 3.5, 0}, {5, 3.5, 0}};
1247  std::vector<size_t> v0 = {0, 1, 2, 3};
1248  o.m_loops.push_back(v0);
1249  std::vector<size_t> v1 = {4, 5, 6, 7};
1250  o.m_loops.push_back(v1);
1251  std::vector<size_t> v2 = {8, 9, 10, 11};
1252  o.m_loops.push_back(v2);
1253  std::vector<size_t> v3 = {12, 13, 14, 15};
1254  o.m_loops.push_back(v3);
1255  o.m_loopTypes.assign(4, MePolyOffsetter::INSIDE_POLY);
1257  std::vector<MePolyOffsetterOutput> vO(1, o);
1258  p.IntersectCleanInPolys(vO, o1, 1e-9);
1259  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1260  if (1 != o1.m_loops.size())
1261  return;
1263  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[0]);
1264  std::vector<int> baseLoopType = {1};
1265  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1266 } // MePolyCleanerUnitTests::testCleanIn1b
1267 //------------------------------------------------------------------------------
1269 //------------------------------------------------------------------------------
1271 {
1272  // x = 0 4 8
1273  //
1274  // y=4 5----------------------------------4
1275  // | |
1276  // | |
1277  // | 2-------------------------3
1278  // | |
1279  // | |
1280  // y=2 | | 9------8
1281  // | | | |
1282  // | | | |
1283  // | | 6------7
1284  // | |
1285  // y=0 0--------1
1286  MePolyOffsetterOutput o, o1;
1287  o.m_pts = {{0, 0, 0}, {2, 0, 0}, {2, 3, 0}, {8, 3, 0}, {8, 4, 0},
1288  {0, 4, 0}, {4, 1, 0}, {5, 1, 0}, {5, 2, 0}, {4, 2, 0}};
1289  std::vector<size_t> v0 = {0, 1, 2, 3, 4, 5};
1290  o.m_loops.push_back(v0);
1291  std::vector<size_t> v1 = {6, 7, 8, 9};
1292  o.m_loops.push_back(v1);
1293  o.m_loopTypes.assign(2, MePolyOffsetter::INSIDE_POLY);
1295  std::vector<MePolyOffsetterOutput> vO(1, o);
1296  p.IntersectCleanInPolys(vO, o1, 1e-9);
1297  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1298  if (2 != o1.m_loops.size())
1299  return;
1301  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[0]);
1302  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[1]);
1303  std::vector<int> baseLoopType = {1, 1};
1304  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1305 } // MePolyCleanerUnitTests::testCleanIn2
1306 //------------------------------------------------------------------------------
1308 //------------------------------------------------------------------------------
1310 {
1311  // x = 0 4 8
1312  //
1313  // y=4 5----------------4
1314  // | |
1315  // | |
1316  // | 2-------3(9)---8
1317  // | | | |
1318  // | | | |
1319  // y=2 | | 6------7
1320  // | |
1321  // | |
1322  // | |
1323  // | |
1324  // y=0 0--------1
1325  MePolyOffsetterOutput o, o1;
1326  o.m_pts = {{0, 0, 0}, {2, 0, 0}, {2, 3, 0}, {4, 3, 0}, {4, 4, 0},
1327  {0, 4, 0}, {4, 2, 0}, {5, 2, 0}, {5, 3, 0}, {4, 3, 0}};
1328  std::vector<size_t> v0 = {0, 1, 2, 3, 4, 5};
1329  o.m_loops.push_back(v0);
1330  std::vector<size_t> v1 = {6, 7, 8, 9};
1331  o.m_loops.push_back(v1);
1332  o.m_loopTypes.assign(2, MePolyOffsetter::INSIDE_POLY);
1334  std::vector<MePolyOffsetterOutput> vO(1, o);
1335  p.IntersectCleanInPolys(vO, o1, 1e-9);
1336  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1337  if (2 != o1.m_loops.size())
1338  return;
1340  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[0]);
1341  std::vector<size_t> baseLoop = {6, 7, 8, 3};
1342  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[1]);
1343  std::vector<int> baseLoopType = {1, 1};
1344  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1345 } // MePolyCleanerUnitTests::testCleanIn2a
1346 //------------------------------------------------------------------------------
1348 //------------------------------------------------------------------------------
1350 {
1351  // x = 0 4 8
1352  //
1353  // y=4 5----------------4
1354  // | |
1355  // | (3) |
1356  // | 2-------3(2)
1357  // | |\ \
1358  // | | \ \
1359  //y=2 | | \ \
1360  // | | \ \
1361  // | | \ \
1362  // | | 0-------1
1363  // | |
1364  // y=0 0--------1
1365  MePolyOffsetterOutput o, o1;
1366  o.m_pts = {{0, 0, 0}, {2, 0, 0}, {2, 3, 0}, {4, 3, 0}, {4, 4, 0}, {0, 4, 0}};
1367  std::vector<size_t> v0 = {0, 1, 2, 3, 4, 5};
1368  o.m_loops.push_back(v0);
1369  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1370  std::vector<MePolyOffsetterOutput> vO(1, o);
1371  o.m_pts = {{3.5, 1, 0}, {4.5, 1, 0}, {4, 3, 0}, {2, 3, 0}};
1372  std::vector<size_t> v1 = {0, 1, 2, 3};
1373  o.m_loops[0] = v1;
1374  vO.push_back(o);
1376  p.IntersectCleanInPolys(vO, o1, 1e-9);
1377  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1378  if (2 != o1.m_loops.size())
1379  return;
1380  std::vector<Pt3d> basePts = {{0, 0, 0}, {2, 0, 0}, {2, 3, 0}, {4, 3, 0}, {4, 4, 0},
1381  {0, 4, 0}, {3.5, 1, 0}, {4.5, 1, 0}, {4, 3, 0}, {2, 3, 0}};
1382  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1383  std::vector<size_t> baseLoop = {0, 1, 2, 6, 7, 3, 4, 5};
1384  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1385  std::vector<int> baseLoopType = {1};
1386  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1387 } // MePolyCleanerUnitTests::testCleanIn2b
1388 //------------------------------------------------------------------------------
1390 //------------------------------------------------------------------------------
1392 {
1393  // x = 0 4 8
1394  //
1395  // y=4 3---------------------2
1396  // | |
1397  // | |
1398  // | (7)3---------|------------2(6)
1399  // | | |(8) |
1400  // | | | |
1401  // y=2 | | | |
1402  // | | | |
1403  // | (9)| | |
1404  // 0---------------------1 |
1405  // | |
1406  // y=0 (4)0----------------------1(5)
1407  MePolyOffsetterOutput o, o1;
1408  o.m_pts = {{0, 1, 0}, {5, 1, 0}, {5, 4, 0}, {0, 4, 0}};
1409  std::vector<size_t> v0 = {0, 1, 2, 3};
1410  o.m_loops.push_back(v0);
1411  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1412  std::vector<MePolyOffsetterOutput> vO(1, o);
1413  o.m_pts = {{3, 0, 0}, {8, 0, 0}, {8, 3, 0}, {3, 3, 0}};
1414  vO.push_back(o);
1416  p.IntersectCleanInPolys(vO, o1, 1e-9);
1417  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1418  if (1 != o1.m_loops.size())
1419  return;
1420  std::vector<Pt3d> basePts = {{0, 1, 0}, {5, 1, 0}, {5, 4, 0}, {0, 4, 0}, {3, 0, 0},
1421  {8, 0, 0}, {8, 3, 0}, {3, 3, 0}, {5, 3, 0}, {3, 1, 0}};
1422  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1423  std::vector<size_t> baseLoop = {9, 4, 5, 6, 8, 2, 3, 0};
1424  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1425  std::vector<int> baseLoopType = {1};
1426  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1427 } // MePolyCleanerUnitTests::testCleanIn3
1428 //------------------------------------------------------------------------------
1430 //------------------------------------------------------------------------------
1432 {
1433  // x = 0 4 8
1434  //
1435  // y=4 (4)0---------------------3(7)
1436  // | |
1437  // | (9)|
1438  // | 0---------|------------3
1439  // | | | |
1440  // | | | |
1441  // y=2 | | | |
1442  // | | | |
1443  // | (8)| | |
1444  // (5)1---------------------2(6) |
1445  // | |
1446  // y=0 1----------------------2
1447  MePolyOffsetterOutput o, o1;
1448  o.m_pts = {{3, 3, 0}, {3, 0, 0}, {8, 0, 0}, {8, 3, 0}};
1449  std::vector<size_t> v0 = {0, 1, 2, 3};
1450  o.m_loops.push_back(v0);
1451  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1452  std::vector<MePolyOffsetterOutput> vO(1, o);
1453  o.m_pts = {{0, 4, 0}, {0, 1, 0}, {5, 1, 0}, {5, 4, 0}};
1454  vO.push_back(o);
1456  p.IntersectCleanInPolys(vO, o1, 1e-9);
1457  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1458  if (1 != o1.m_loops.size())
1459  return;
1460  std::vector<Pt3d> basePts = {{3, 3, 0}, {3, 0, 0}, {8, 0, 0}, {8, 3, 0}, {0, 4, 0},
1461  {0, 1, 0}, {5, 1, 0}, {5, 4, 0}, {3, 1, 0}, {5, 3, 0}};
1462  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1463  std::vector<size_t> baseLoop = {9, 7, 4, 5, 8, 1, 2, 3};
1464  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1465  std::vector<int> baseLoopType = {1};
1466  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1467 } // MePolyCleanerUnitTests::testCleanIn3a
1468 //------------------------------------------------------------------------------
1470 //------------------------------------------------------------------------------
1472 {
1473  // x = 0 4 8
1474  //
1475  // y=4 0---------------------3
1476  // | |
1477  // | |
1478  // | 0---------|------------3
1479  // | | | |
1480  // | | | |
1481  // y=2 | | | |
1482  // | | | |
1483  // | | | |
1484  // | 1---------|------------2
1485  // | |
1486  // y=0 1---------------------2
1487  MePolyOffsetterOutput o, o1;
1488  o.m_pts = {{3, 3, 0}, {3, 1, 0}, {8, 1, 0}, {8, 3, 0}};
1489  std::vector<size_t> v0 = {0, 1, 2, 3};
1490  o.m_loops.push_back(v0);
1491  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1492  std::vector<MePolyOffsetterOutput> vO(1, o);
1493  o.m_pts = {{0, 4, 0}, {0, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1494  vO.push_back(o);
1496  p.IntersectCleanInPolys(vO, o1, 1e-9);
1497  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1498  if (1 != o1.m_loops.size())
1499  return;
1500  std::vector<Pt3d> basePts = {{3, 3, 0}, {3, 1, 0}, {8, 1, 0}, {8, 3, 0}, {0, 4, 0},
1501  {0, 0, 0}, {5, 0, 0}, {5, 4, 0}, {5, 1, 0}, {5, 3, 0}};
1502  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1503  std::vector<size_t> baseLoop = {9, 7, 4, 5, 6, 8, 2, 3};
1504  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1505  std::vector<int> baseLoopType = {1};
1506  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1507 } // MePolyCleanerUnitTests::testCleanIn4
1508 //------------------------------------------------------------------------------
1510 //------------------------------------------------------------------------------
1512 {
1513  // x = 0 4 8
1514  //
1515  // y=4 (4)0---------------------3(7)
1516  // | |
1517  // | |
1518  // | 0---------|------------3
1519  // | | | |
1520  // | | | |
1521  // y=2 | | | |
1522  // | | | |
1523  // | | | |
1524  // | | | |
1525  // | | |(6) |
1526  // y=0 (5)1-----------1---------2------------2
1527  MePolyOffsetterOutput o, o1;
1528  o.m_pts = {{3, 3, 0}, {3, 0, 0}, {8, 0, 0}, {8, 3, 0}};
1529  std::vector<size_t> v0 = {0, 1, 2, 3};
1530  o.m_loops.push_back(v0);
1531  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1532  std::vector<MePolyOffsetterOutput> vO(1, o);
1533  o.m_pts = {{0, 4, 0}, {0, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1534  vO.push_back(o);
1536  p.IntersectCleanInPolys(vO, o1, 1e-9);
1537  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1538  if (1 != o1.m_loops.size())
1539  return;
1540  std::vector<Pt3d> basePts = {{3, 3, 0}, {3, 0, 0}, {8, 0, 0}, {8, 3, 0}, {0, 4, 0},
1541  {0, 0, 0}, {5, 0, 0}, {5, 4, 0}, {5, 3, 0}};
1542  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1543  std::vector<size_t> baseLoop = {8, 7, 4, 5, 1, 6, 2, 3};
1544  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1545  std::vector<int> baseLoopType = {1};
1546  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1547 } // MePolyCleanerUnitTests::testCleanIn4a
1548 //------------------------------------------------------------------------------
1550 //------------------------------------------------------------------------------
1552 {
1553  // x = 0 4 8
1554  //
1555  // y=4 (4)0-----------0---------3(7)---------3
1556  // | | | |
1557  // | | | |
1558  // | | | |
1559  // | | | |
1560  // | | | |
1561  // y=2 | | | |
1562  // | | | |
1563  // | | | |
1564  // | | | |
1565  // | | |(6) |
1566  // y=0 (5)1-----------1---------2------------2
1567  MePolyOffsetterOutput o, o1;
1568  o.m_pts = {{3, 4, 0}, {3, 0, 0}, {8, 0, 0}, {8, 4, 0}};
1569  std::vector<size_t> v0 = {0, 1, 2, 3};
1570  o.m_loops.push_back(v0);
1571  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1572  std::vector<MePolyOffsetterOutput> vO(1, o);
1573  o.m_pts = {{0, 4, 0}, {0, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1574  vO.push_back(o);
1576  p.IntersectCleanInPolys(vO, o1, 1e-9);
1577  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1578  if (1 != o1.m_loops.size())
1579  return;
1580  std::vector<Pt3d> basePts = {{3, 4, 0}, {3, 0, 0}, {8, 0, 0}, {8, 4, 0},
1581  {0, 4, 0}, {0, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1582  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1583  std::vector<size_t> baseLoop = {7, 0, 4, 5, 1, 6, 2, 3};
1584  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1585  std::vector<int> baseLoopType = {1};
1586  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1587 } // MePolyCleanerUnitTests::testCleanIn4b
1588 //------------------------------------------------------------------------------
1590 //------------------------------------------------------------------------------
1592 {
1593  // x = 0 4 8
1594  //
1595  // y=4 (4)0---------------------3(7)
1596  // | |
1597  // | |(9)
1598  // 0---------------------|------------3
1599  // | | |
1600  // | | |
1601  // y=2 | | |
1602  // | |(8) |
1603  // 1---------------------|------------2
1604  // | |
1605  // | |
1606  // y=0 (5)1---------------------2(6)
1607  MePolyOffsetterOutput o, o1;
1608  o.m_pts = {{0, 3, 0}, {0, 1, 0}, {8, 1, 0}, {8, 3, 0}};
1609  std::vector<size_t> v0 = {0, 1, 2, 3};
1610  o.m_loops.push_back(v0);
1611  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1612  std::vector<MePolyOffsetterOutput> vO(1, o);
1613  o.m_pts = {{0, 4, 0}, {0, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1614  vO.push_back(o);
1616  p.IntersectCleanInPolys(vO, o1, 1e-9);
1617  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1618  if (1 != o1.m_loops.size())
1619  return;
1620  std::vector<Pt3d> basePts = {{0, 3, 0}, {0, 1, 0}, {8, 1, 0}, {8, 3, 0}, {0, 4, 0},
1621  {0, 0, 0}, {5, 0, 0}, {5, 4, 0}, {5, 1, 0}, {5, 3, 0}};
1622  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1623  std::vector<size_t> baseLoop = {9, 7, 4, 0, 1, 5, 6, 8, 2, 3};
1624  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1625  std::vector<int> baseLoopType = {1};
1626  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1627 } // MePolyCleanerUnitTests::testCleanIn4c
1628 //------------------------------------------------------------------------------
1630 //------------------------------------------------------------------------------
1632 {
1633  // x = 0 4 8
1634  //
1635  // y=4 1(5)
1636  // /|
1637  // / |
1638  // / |
1639  // / |
1640  // (7)/ |
1641  // y=2 0----------------3
1642  // | / |
1643  // | / |
1644  // | / |
1645  // |/ |
1646  // y=0 1----------------2
1647  // 2(6) 0(4)
1648  MePolyOffsetterOutput o, o1;
1649  o.m_pts = {{0, 2, 0}, {0, 0, 0}, {4, 0, 0}, {4, 2, 0}};
1650  std::vector<size_t> v0 = {0, 1, 2, 3};
1651  o.m_loops.push_back(v0);
1652  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1653  std::vector<MePolyOffsetterOutput> vO(1, o);
1654  o.m_pts = {{4, 0, 0}, {4, 4, 0}, {0, 0, 0}};
1655  o.m_loops[0].pop_back();
1656  vO.push_back(o);
1658  p.IntersectCleanInPolys(vO, o1, 1e-9);
1659  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1660  if (1 != o1.m_loops.size())
1661  return;
1662  std::vector<Pt3d> basePts = {{0, 2, 0}, {0, 0, 0}, {4, 0, 0}, {4, 2, 0},
1663  {4, 0, 0}, {4, 4, 0}, {0, 0, 0}, {2, 2, 0}};
1664  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1665  std::vector<size_t> baseLoop = {1, 2, 3, 5, 7, 0};
1666  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1667  std::vector<int> baseLoopType = {1};
1668  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1669 } // MePolyCleanerUnitTests::testCleanIn4d
1670 //------------------------------------------------------------------------------
1672 //------------------------------------------------------------------------------
1674 {
1675  // x = 0 4 8
1676  //
1677  // y=4 0----------------------3
1678  // | |
1679  // | |
1680  // 0 | |
1681  // | \ | |
1682  // | \ | |
1683  // y=2 | |\ |
1684  // | | \ |
1685  // | | \ |
1686  // | 1----------------------2
1687  // | \
1688 //y=0 1-----------------2
1689  MePolyOffsetterOutput o, o1;
1690  o.m_pts = {{3, 4, 0}, {3, 1, 0}, {8, 1, 0}, {8, 4, 0}};
1691  std::vector<size_t> v0 = {0, 1, 2, 3};
1692  o.m_loops.push_back(v0);
1693  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1694  std::vector<MePolyOffsetterOutput> vO(1, o);
1695  o.m_pts = {{2, 3, 0}, {2, 0, 0}, {5, 0, 0}};
1696  o.m_loops[0].pop_back();
1697  vO.push_back(o);
1699  p.IntersectCleanInPolys(vO, o1, 1e-9);
1700  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1701  if (1 != o1.m_loops.size())
1702  return;
1703  std::vector<Pt3d> basePts = {{3, 4, 0}, {3, 1, 0}, {8, 1, 0}, {8, 4, 0}, {2, 3, 0},
1704  {2, 0, 0}, {5, 0, 0}, {3, 2, 0}, {4, 1, 0}};
1705  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1706  std::vector<size_t> baseLoop = {8, 2, 3, 0, 7, 4, 5, 6};
1707  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1708  std::vector<int> baseLoopType = {1};
1709  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1710 } // MePolyCleanerUnitTests::testCleanIn5
1711 //------------------------------------------------------------------------------
1713 //------------------------------------------------------------------------------
1715 {
1716  // x = 0 4 8
1717  //
1718  // y=8
1719  // (4) (8)
1720  // 0----------------------4
1721  // | /
1722  // | 0----------------------3
1723  // | | / (10) |
1724  // y=4 | | |
1725  // | / |(11) |
1726  // | / | |
1727  // | 3(7) | |
1728  // | \ | |
1729  // | \ | |
1730  // y=2 | |\(12) |
1731  // | | \ |
1732  // | | \ (9) |
1733  // | 1----------------------2
1734  // | \
1735  //y=0 1------------------------2
1736  // (5) (6)
1737  MePolyOffsetterOutput o, o1;
1738  o.m_pts = {{3, 5, 0}, {3, 1, 0}, {8, 1, 0}, {8, 5, 0}};
1739  std::vector<size_t> v0 = {0, 1, 2, 3};
1740  o.m_loops.push_back(v0);
1741  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1742  std::vector<MePolyOffsetterOutput> vO(1, o);
1743  o.m_pts = {{0, 6, 0}, {0, 0, 0}, {5, 0, 0}, {2, 3, 0}, {5, 6, 0}};
1744  o.m_loops[0] = {0, 1, 2, 3, 4};
1745  vO.push_back(o);
1747  p.IntersectCleanInPolys(vO, o1, 1e-9);
1748  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1749  if (2 != o1.m_loops.size())
1750  return;
1751  std::vector<Pt3d> basePts = {{3, 5, 0}, {3, 1, 0}, {8, 1, 0}, {8, 5, 0}, {0, 6, 0},
1752  {0, 0, 0}, {5, 0, 0}, {2, 3, 0}, {5, 6, 0}, {4, 1, 0},
1753  {4, 5, 0}, {3, 4, 0}, {3, 2, 0}};
1754  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1755  std::vector<size_t> baseLoop = {12, 7, 11};
1756  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1757  baseLoop = {10, 8, 4, 5, 6, 9, 2, 3};
1758  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[1]);
1759  std::vector<int> baseLoopType = {2, 1};
1760  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1761 } // MePolyCleanerUnitTests::testCleanIn6
1762 //------------------------------------------------------------------------------
1764 //------------------------------------------------------------------------------
1766 {
1767  // x = 0 4 8
1768  //
1769  // y=8
1770  //
1771  // 3(7)
1772  // (15)/ \ (8)
1773  // 0----------------3
1774  // | / \ |
1775  // y=4 |/ \|
1776  // / |(14) (9)| \
1777 // / | | \
1778 // (4)0 | | 2(6)
1779  // \ | | /
1780  // \ | | /
1781  // y=2 \|(13) (10)|/
1782  // |\ /|
1783  // | \ (12) (11)/ |
1784  // 1----------------2
1785  // \ /
1786  // y=0 1(5)
1787  MePolyOffsetterOutput o, o1;
1788  o.m_pts = {{1, 5, 0}, {1, 1, 0}, {5, 1, 0}, {5, 5, 0}};
1789  std::vector<size_t> v0 = {0, 1, 2, 3};
1790  o.m_loops.push_back(v0);
1791  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1792  std::vector<MePolyOffsetterOutput> vO(1, o);
1793  o.m_pts = {{0, 3, 0}, {3, 0, 0}, {6, 3, 0}, {3, 6, 0}};
1794  vO.push_back(o);
1796  p.IntersectCleanInPolys(vO, o1, 1e-9);
1797  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1798  if (1 != o1.m_loops.size())
1799  return;
1800  std::vector<Pt3d> basePts = {{1, 5, 0}, {1, 1, 0}, {5, 1, 0}, {5, 5, 0}, {0, 3, 0}, {3, 0, 0},
1801  {6, 3, 0}, {3, 6, 0}, {4, 5, 0}, {5, 4, 0}, {5, 2, 0}, {4, 1, 0},
1802  {2, 1, 0}, {1, 2, 0}, {1, 4, 0}, {2, 5, 0}};
1803  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1804  std::vector<size_t> baseLoop = {15, 0, 14, 4, 13, 1, 12, 5, 11, 2, 10, 6, 9, 3, 8, 7};
1805  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1806  std::vector<int> baseLoopType = {1};
1807  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1808 } // MePolyCleanerUnitTests::testCleanIn7
1809 //------------------------------------------------------------------------------
1811 //------------------------------------------------------------------------------
1813 {
1814  // x = 0 4 8
1815  //
1816  // y=4 0--------------3
1817  // | |
1818  // (12)| (9) (5) |(13)
1819  // (10)2-------|---1 1----|------------0(4)
1820  // | | | | | |
1821  // | | | | | |
1822  // y=2 | | | | | |
1823  // | | | | | |
1824  // | (15)| | | |(14) |
1825  // (11)3-------|---0 2----|------------3(7)
1826  // | (8) (6) |
1827  // y=0 1--------------2
1828  MePolyOffsetterOutput o, o1;
1829  o.m_pts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0}};
1830  std::vector<size_t> v0{0, 1, 2, 3};
1831  o.m_loops.push_back(v0);
1832  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1833  std::vector<MePolyOffsetterOutput> vO(1, o);
1834  o.m_pts = {{8, 3, 0}, {4, 3, 0}, {4, 1, 0}, {8, 1, 0}};
1835  vO.push_back(o);
1836  o.m_pts = {{3, 1, 0}, {3, 3, 0}, {0, 3, 0}, {0, 1, 0}};
1837  vO.push_back(o);
1839  p.IntersectCleanInPolys(vO, o1, 1e-9);
1840  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1841  if (1 != o1.m_loops.size())
1842  return;
1843  std::vector<Pt3d> basePts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0}, {8, 3, 0}, {4, 3, 0},
1844  {4, 1, 0}, {8, 1, 0}, {3, 1, 0}, {3, 3, 0}, {0, 3, 0}, {0, 1, 0},
1845  {2, 3, 0}, {5, 3, 0}, {5, 1, 0}, {2, 1, 0}};
1846  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1847  std::vector<size_t> baseLoop = {15, 1, 2, 14, 7, 4, 13, 3, 0, 12, 10, 11};
1848  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1849  std::vector<int> baseLoopType = {1};
1850  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1851 } // MePolyCleanerUnitTests::testCleanIn8
1852 
1853 //------------------------------------------------------------------------------
1855 //------------------------------------------------------------------------------
1857 {
1858  // x = 0 2 4 6 8
1859  //
1860  // y=6
1861  //
1862  //
1863  // (5)1-----------------0(4)
1864  // | |
1865  // |(14) |
1866  // y=4 2--------------------------1 |
1867  // | | | |
1868  // | | (11) | |
1869  // | 2(10) | 0 | |
1870  // | |\ | /| | |
1871  // | | \(17) |(16) / | | |
1872  // y=2 3--------------------------0 |
1873  // (15)| \ | / | |
1874  // | (9)\ |/ | |
1875  // 0---------1 | |
1876  // (8) / | | |
1877  // y=0 (12)1---2--------2--------3(7)
1878  // (6) (13)
1879  MePolyOffsetterOutput o, o1;
1880  o.m_pts = {{6, 2, 0}, {6, 4, 0}, {0, 4, 0}, {0, 2, 0}};
1881  std::vector<size_t> v0 = {0, 1, 2, 3};
1882  o.m_loops.push_back(v0);
1883  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1884  std::vector<MePolyOffsetterOutput> vO(1, o);
1885  o.m_pts = {{7, 5, 0}, {3, 5, 0}, {3, 0, 0}, {7, 0, 0}};
1886  vO.push_back(o);
1887  o.m_pts = {{1, 1, 0}, {3, 1, 0}, {1, 3, 0}};
1888  o.m_loops[0].pop_back();
1889  vO.push_back(o);
1890  o.m_pts = {{5, 3, 0}, {2, 0, 0}, {5, 0, 0}};
1891  vO.push_back(o);
1893  p.IntersectCleanInPolys(vO, o1, 1e-9);
1894 
1895 #if BOOST_VERSION > 106100
1896  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1897 
1898  if (2 != o1.m_loops.size())
1899  {
1900  // iDumpOutput(o1);
1901  return;
1902  }
1903  std::vector<Pt3d> basePts = {{6, 2, 0}, {6, 4, 0}, {0, 4, 0}, {0, 2, 0}, {7, 5, 0}, {3, 5, 0},
1904  {3, 0, 0}, {7, 0, 0}, {1, 1, 0}, {3, 1, 0}, {1, 3, 0}, {5, 3, 0},
1905  {2, 0, 0}, {5, 0, 0}, {3, 4, 0}, {1, 2, 0}, {3, 2, 0}, {2, 2, 0}};
1906  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1907  std::vector<size_t> loop0 = {17, 16, 9};
1908  TS_ASSERT_EQUALS_VEC(loop0, o1.m_loops[0])
1909  std::vector<size_t> loop1 = {15, 8, 9, 12, 6, 13, 7, 4, 5, 14, 2, 3};
1910  TS_ASSERT_EQUALS_VEC(loop1, o1.m_loops[1])
1911  std::vector<int> baseLoopTypes = {2, 1};
1912  TS_ASSERT_EQUALS_VEC(baseLoopTypes, o1.m_loopTypes);
1913 #else
1914  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1915  if (1 != o1.m_loops.size())
1916  return;
1917  std::vector<Pt3d> basePts = {{6, 2, 0}, {6, 4, 0}, {0, 4, 0}, {0, 2, 0}, {7, 5, 0}, {3, 5, 0},
1918  {3, 0, 0}, {7, 0, 0}, {1, 1, 0}, {3, 1, 0}, {1, 3, 0}, {5, 3, 0},
1919  {2, 0, 0}, {5, 0, 0}, {3, 4, 0}, {3, 2, 0}, {2, 2, 0}, {1, 2, 0}};
1920  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1921  std::vector<size_t> baseLoop = {17, 8, 9, 16, 15, 9, 12, 6, 13, 7, 4, 5, 14, 2, 3};
1922  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1923  std::vector<int> baseLoopType = {1};
1924  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1925 #endif
1926 } // MePolyCleanerUnitTests::testCleanIn9
1927 //------------------------------------------------------------------------------
1929 //------------------------------------------------------------------------------
1931 {
1932  // x = 0 2 4 6 8
1933  //
1934  // y=6
1935  //
1936  //
1937  // 1-------------------------------0
1938  // | |
1939  // | |
1940  // y=4 | |
1941  // | |
1942  // | |
1943  // | 2(8) |
1944  // | |\ |
1945  // | | \(10) |
1946  // y=2 2-------------3 |
1947  // (9)| \ | |
1948  // | \ | |
1949  // 0---------1(7) |
1950  // (6) | |
1951  // y=0 4-----------------5
1952  //
1953  MePolyOffsetterOutput o, o1;
1954  o.m_pts = {{7, 7, 0}, {0, 7, 0}, {0, 2, 0}, {3, 2, 0}, {3, 0, 0}, {7, 0, 0}};
1955  std::vector<size_t> v0 = {0, 1, 2, 3, 4, 5};
1956  o.m_loops.push_back(v0);
1957  o.m_loopTypes.assign(1, MePolyOffsetter::INSIDE_POLY);
1958  std::vector<MePolyOffsetterOutput> vO(1, o);
1959  o.m_pts = {{1, 1, 0}, {3, 1, 0}, {1, 3, 0}};
1960  o.m_loops[0] = {0, 1, 2};
1961  vO.push_back(o);
1963  p.IntersectCleanInPolys(vO, o1, 1e-9);
1964 
1965 #if BOOST_VERSION > 106100
1966  TS_ASSERT_EQUALS(2, o1.m_loops.size());
1967  if (2 != o1.m_loops.size())
1968  {
1969  // iDumpOutput(o1);
1970  return;
1971  }
1972  std::vector<Pt3d> basePts = {{7, 7, 0}, {0, 7, 0}, {0, 2, 0}, {3, 2, 0}, {3, 0, 0}, {7, 0, 0},
1973  {1, 1, 0}, {3, 1, 0}, {1, 3, 0}, {1, 2, 0}, {2, 2, 0}};
1974  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1975  std::vector<size_t> loop0 = {10, 3, 7};
1976  TS_ASSERT_EQUALS_VEC(loop0, o1.m_loops[0]);
1977  std::vector<size_t> loop1 = {7, 4, 5, 0, 1, 2, 9, 6};
1978  TS_ASSERT_EQUALS_VEC(loop1, o1.m_loops[1]);
1979  std::vector<int> baseLoopType = {2, 1};
1980  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1981 #else
1982  TS_ASSERT_EQUALS(1, o1.m_loops.size());
1983  if (1 != o1.m_loops.size())
1984  return;
1985  std::vector<Pt3d> basePts = {{7, 7, 0}, {0, 7, 0}, {0, 2, 0}, {3, 2, 0}, {3, 0, 0}, {7, 0, 0},
1986  {1, 1, 0}, {3, 1, 0}, {1, 3, 0}, {2, 2, 0}, {1, 2, 0}};
1987  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
1988  std::vector<size_t> baseLoop = {10, 6, 7, 9, 3, 4, 5, 0, 1, 2};
1989  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
1990  std::vector<int> baseLoopType = {1};
1991  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
1992 #endif
1993 } // MePolyCleanerUnitTests::testCleanIn10
1994 //------------------------------------------------------------------------------
1996 //------------------------------------------------------------------------------
1998 {
1999  // x = 0 4 8
2000  //
2001  // y=4 7----------------------------------6
2002  // | |
2003  // | 15------14 |
2004  // | 1-----------2 | | |
2005  // | | | 12------13 |
2006  // | | 19---18 | |
2007  // y=2 | | | | | 8------11 |
2008  // | | 16---17 | | | |
2009  // | | | | | |
2010  // | 0-----------3 9------10 |
2011  // | |
2012  // y=0 4----------------------------------5
2013  //
2014  // Poly 0,1,2,3 is a NEWOUT_POLY all the others are INSIDE_POLY
2015  //
2016  MePolyOffsetterOutput o, o1;
2017  o.m_pts = {{1, 1, 0}, {1, 3, 0}, {4, 3, 0}, {4, 1, 0}, {0, 0, 0},
2018  {8, 0, 0}, {8, 4, 0}, {0, 4, 0}, {5, 1, 0}, {7, 1, 0},
2019  {7, 2, 0}, {5, 2, 0}, {5, 3, 0}, {7, 3, 0}, {7, 3.5, 0},
2020  {5, 3.5, 0}, {1.5, 1.5, 0}, {3.5, 1.5, 0}, {3.5, 2.5, 0}, {1.5, 2.5, 0}};
2021  std::vector<size_t> v0{0, 1, 2, 3};
2022  o.m_loops.push_back(v0);
2023  std::vector<size_t> v1{4, 5, 6, 7};
2024  o.m_loops.push_back(v1);
2025  std::vector<size_t> v2{8, 9, 10, 11};
2026  o.m_loops.push_back(v2);
2027  std::vector<size_t> v3{12, 13, 14, 15};
2028  o.m_loops.push_back(v3);
2029  std::vector<size_t> v4{16, 17, 18, 19};
2030  o.m_loops.push_back(v4);
2031  o.m_loopTypes.assign(5, MePolyOffsetter::INSIDE_POLY);
2032  o.m_loopTypes[0] = MePolyOffsetter::NEWOUT_POLY;
2034  std::vector<MePolyOffsetterOutput> vO(1, o);
2035  p.IntersectCleanInPolys(vO, o1, 1e-9);
2036  TS_ASSERT_EQUALS(3, o1.m_loops.size());
2037  if (3 != o1.m_loops.size())
2038  return;
2040  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[0]);
2041  TS_ASSERT_EQUALS_VEC(o.m_loops[4], o1.m_loops[1]);
2042  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[2]);
2043  std::vector<int> baseLoopType = {2, 1, 1};
2044  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
2045 } // MePolyCleanerUnitTests::testCleanIn11
2046 //------------------------------------------------------------------------------
2048 //------------------------------------------------------------------------------
2050 {
2051  // x = 0 4 8
2052  //
2053  // y=4 7----------------6
2054  // | |
2055  // | IN |
2056  // 4----------------5
2057  //
2058  //
2059  // y=2 1----------------2
2060  // | |
2061  // | |
2062  // | OUT |
2063  // | |
2064  // y=0 0----------------3
2065  //
2066  MePolyOffsetterOutput o, o1;
2067  o.m_pts = {{0, 0, 0}, {0, 2, 0}, {4, 2, 0}, {4, 0, 0},
2068  {0, 3, 0}, {0, 4, 0}, {4, 4, 0}, {4, 3, 0}};
2069  std::vector<size_t> v0 = {0, 1, 2, 3};
2070  o.m_loops.push_back(v0);
2071  std::vector<size_t> v1 = {4, 5, 6, 7};
2072  o.m_loops.push_back(v1);
2073  o.m_loopTypes = {MePolyOffsetter::OUTSIDE_POLY, MePolyOffsetter::INSIDE_POLY};
2075  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2076  TS_ASSERT_EQUALS(2, o1.m_loops.size());
2077  if (2 != o1.m_loops.size())
2078  return;
2080  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[0]);
2081  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[1]);
2082  std::vector<int> baseLoops = {MePolyOffsetter::INSIDE_POLY, MePolyOffsetter::OUTSIDE_POLY};
2083  TS_ASSERT_EQUALS_VEC(baseLoops, o1.m_loopTypes);
2084 } // MePolyCleanerUnitTests::testCleanInOut0
2085 //------------------------------------------------------------------------------
2087 //------------------------------------------------------------------------------
2089 {
2090  // x = 0 4 8
2091  //
2092  // y=4 1----------------------------------2
2093  // | |
2094  // | |
2095  // | 4---------------------------3
2096  // | |
2097  // | |
2098  // y=2 | | 6-------9
2099  // | | | |
2100  // | | | |
2101  // | OUT | | IN |
2102  // | | | |
2103  // y=0 0------5 7-------8
2104  //
2105  MePolyOffsetterOutput o, o1;
2106  o.m_pts = {{0, 0, 0}, {0, 4, 0}, {8, 4, 0}, {8, 3, 0}, {2, 3, 0},
2107  {2, 0, 0}, {4, 2, 0}, {4, 0, 0}, {6, 0, 0}, {6, 2, 0}};
2108  std::vector<size_t> v0{0, 1, 2, 3, 4, 5};
2109  o.m_loops.push_back(v0);
2110  std::vector<size_t> v1{6, 7, 8, 9};
2111  o.m_loops.push_back(v1);
2112  o.m_loopTypes = {MePolyOffsetter::OUTSIDE_POLY, MePolyOffsetter::INSIDE_POLY};
2114  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2115  TS_ASSERT_EQUALS(2, o1.m_loops.size());
2116  if (2 != o1.m_loops.size())
2117  return;
2119  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[0]);
2120  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[1]);
2121  std::vector<int> baseLoops = {MePolyOffsetter::INSIDE_POLY, MePolyOffsetter::OUTSIDE_POLY};
2122  TS_ASSERT_EQUALS_VEC(baseLoops, o1.m_loopTypes);
2123 } // MePolyCleanerUnitTests::testCleanInOut0a
2124 //------------------------------------------------------------------------------
2126 //------------------------------------------------------------------------------
2128 {
2129  // x = 0 4 8
2130  //
2131  // y=4 1----------------------------------2
2132  // | |
2133  // | |
2134  // | |
2135  // | |
2136  // | |
2137  // y=2 | 7-------6 |
2138  // | | | |
2139  // | | IN | |
2140  // | 4-------5 |
2141  // | OUT |
2142  // y=0 0----------------------------------3
2143  //
2144  MePolyOffsetterOutput o, o1;
2145  o.m_pts = {{0, 0, 0}, {0, 4, 0}, {8, 4, 0}, {8, 0, 0},
2146  {2, 1, 0}, {4, 1, 0}, {4, 2, 0}, {2, 2, 0}};
2147  std::vector<size_t> v0{0, 1, 2, 3};
2148  o.m_loops.push_back(v0);
2149  std::vector<size_t> v1{4, 5, 6, 7};
2150  o.m_loops.push_back(v1);
2151  o.m_loopTypes = {MePolyOffsetter::OUTSIDE_POLY, MePolyOffsetter::INSIDE_POLY};
2153  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2154  TS_ASSERT_EQUALS(2, o1.m_loops.size());
2155  if (2 != o1.m_loops.size())
2156  return;
2158  TS_ASSERT_EQUALS_VEC(o.m_loops[1], o1.m_loops[0]);
2159  TS_ASSERT_EQUALS_VEC(o.m_loops[0], o1.m_loops[1]);
2160  std::vector<int> baseLoops = {MePolyOffsetter::INSIDE_POLY, MePolyOffsetter::OUTSIDE_POLY};
2161  TS_ASSERT_EQUALS_VEC(baseLoops, o1.m_loopTypes);
2162 } // MePolyCleanerUnitTests::testCleanInOut0b
2163 //------------------------------------------------------------------------------
2165 //------------------------------------------------------------------------------
2167 {
2168  // x = 0 4 8
2169  //
2170  // y=4 0--------------1
2171  // | |
2172  // (12)| |(13)
2173  // 10-------|---9 5----|------------4
2174  // | | | | | |
2175  // | | | | | |
2176  // y=2 | | | | | |
2177  // | | | | | |
2178  // | (15)| | | |(14) |
2179  // 11-------|---8 6----|------------7
2180  // | |
2181  // y=0 3--------------2
2182  MePolyOffsetterOutput o, o1;
2183  o.m_pts = {{2, 4, 0}, {5, 4, 0}, {5, 0, 0}, {2, 0, 0}, {8, 3, 0}, {4, 3, 0},
2184  {4, 1, 0}, {8, 1, 0}, {3, 1, 0}, {3, 3, 0}, {0, 3, 0}, {0, 1, 0}};
2185  std::vector<size_t> v0 = {0, 1, 2, 3};
2186  o.m_loops.push_back(v0);
2187  std::vector<size_t> v1 = {4, 5, 6, 7};
2188  o.m_loops.push_back(v1);
2189  std::vector<size_t> v2 = {8, 9, 10, 11};
2190  o.m_loops.push_back(v2);
2191 
2192  o.m_loopTypes.assign(3, MePolyOffsetter::INSIDE_POLY);
2193  o.m_loopTypes[0] = MePolyOffsetter::OUTSIDE_POLY;
2195  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2196  TS_ASSERT_EQUALS(1, o1.m_loops.size());
2197  if (1 != o1.m_loops.size())
2198  return;
2199  std::vector<Pt3d> basePts = {{2, 4, 0}, {5, 4, 0}, {5, 0, 0}, {2, 0, 0}, {8, 3, 0}, {4, 3, 0},
2200  {4, 1, 0}, {8, 1, 0}, {3, 1, 0}, {3, 3, 0}, {0, 3, 0}, {0, 1, 0},
2201  {2, 3, 0}, {5, 3, 0}, {5, 1, 0}, {2, 1, 0}};
2202  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
2203  std::vector<size_t> baseLoop{12, 0, 1, 13, 5, 6, 14, 2, 3, 15, 8, 9};
2204  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
2205  std::vector<int> baseLoopType = {MePolyOffsetter::OUTSIDE_POLY};
2206  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
2207 } // MePolyCleanerUnitTests::testCleanInOut1
2208 //------------------------------------------------------------------------------
2210 //------------------------------------------------------------------------------
2212 {
2213  // x = 0 4 8
2214  //
2215  // y=4 0--------------3
2216  // | |
2217  // (15)| |(13)
2218  // 10-------|---11 7----|------------4
2219  // | | | | | |
2220  // | | | | | |
2221  // y=2 | | | | | |
2222  // | | | | | |
2223  // | (14)| | | |(12) |
2224  // 9-------|---8 6----|------------5
2225  // | |
2226  // y=0 1--------------2
2227  MePolyOffsetterOutput o, o1;
2228  o.m_pts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0}, {8, 3, 0}, {8, 1, 0},
2229  {4, 1, 0}, {4, 3, 0}, {3, 1, 0}, {0, 1, 0}, {0, 3, 0}, {3, 3, 0}};
2230  std::vector<size_t> v0 = {0, 1, 2, 3};
2231  o.m_loops.push_back(v0);
2232  std::vector<size_t> v1 = {4, 5, 6, 7};
2233  o.m_loops.push_back(v1);
2234  std::vector<size_t> v2 = {8, 9, 10, 11};
2235  o.m_loops.push_back(v2);
2236 
2237  o.m_loopTypes.assign(3, MePolyOffsetter::OUTSIDE_POLY);
2238  o.m_loopTypes[0] = MePolyOffsetter::INSIDE_POLY;
2240  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2241  TS_ASSERT_EQUALS(2, o1.m_loops.size());
2242  if (2 != o1.m_loops.size())
2243  return;
2244  std::vector<Pt3d> basePts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0}, {8, 3, 0}, {8, 1, 0},
2245  {4, 1, 0}, {4, 3, 0}, {3, 1, 0}, {0, 1, 0}, {0, 3, 0}, {3, 3, 0},
2246  {5, 1, 0}, {5, 3, 0}, {2, 1, 0}, {2, 3, 0}};
2247  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
2248  std::vector<size_t> baseLoop{12, 13, 4, 5};
2249  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
2250  baseLoop = {14, 9, 10, 15};
2251  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[1]);
2252  std::vector<int> baseLoopType(2, MePolyOffsetter::OUTSIDE_POLY);
2253  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
2254 } // MePolyCleanerUnitTests::testCleanInOut1a
2255 //------------------------------------------------------------------------------
2257 //------------------------------------------------------------------------------
2259 {
2260  // x = 0 4 8
2261  //
2262  // y=4 0--------------3
2263  // | |
2264  // (9)| |(11)
2265  // 7-------|--------------|------------4
2266  // | | | |
2267  // | | | |
2268  // y=2 | | | |
2269  // | | | |
2270  // | (8)| |(10) |
2271  // 6-------|--------------|------------5
2272  // | |
2273  // y=0 1--------------2
2274  MePolyOffsetterOutput o, o1;
2275  o.m_pts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0},
2276  {8, 3, 0}, {8, 1, 0}, {0, 1, 0}, {0, 3, 0}};
2277  std::vector<size_t> v0 = {0, 1, 2, 3};
2278  o.m_loops.push_back(v0);
2279  std::vector<size_t> v1 = {4, 5, 6, 7};
2280  o.m_loops.push_back(v1);
2281 
2282  o.m_loopTypes.assign(2, MePolyOffsetter::OUTSIDE_POLY);
2283  o.m_loopTypes[0] = MePolyOffsetter::INSIDE_POLY;
2285  p.IntersectCleanInOutPolys(o, o1, 1e-9);
2286  TS_ASSERT_EQUALS(2, o1.m_loops.size());
2287  if (2 != o1.m_loops.size())
2288  return;
2289  std::vector<Pt3d> basePts = {{2, 4, 0}, {2, 0, 0}, {5, 0, 0}, {5, 4, 0}, {8, 3, 0}, {8, 1, 0},
2290  {0, 1, 0}, {0, 3, 0}, {2, 1, 0}, {2, 3, 0}, {5, 1, 0}, {5, 3, 0}};
2291  TS_ASSERT_EQUALS_VEC(basePts, o1.m_pts);
2292  std::vector<size_t> baseLoop{8, 6, 7, 9};
2293  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[0]);
2294  baseLoop = {10, 11, 4, 5};
2295  TS_ASSERT_EQUALS_VEC(baseLoop, o1.m_loops[1]);
2296  std::vector<int> baseLoopType(2, MePolyOffsetter::OUTSIDE_POLY);
2297  TS_ASSERT_EQUALS_VEC(baseLoopType, o1.m_loopTypes);
2298 } // MePolyCleanerUnitTests::testCleanInOut1b
2299 
2300 //} // namespace xms
2301 #endif // CXX_TEST
virtual void CleanPolyOffset(const VecPt3d &a_input, int a_pType, double a_tol, MePolyOffsetterOutput &a_out) override
Takes an input polyline (forming a closed loop) and intersects it with itself and fills the output wi...
void testCase5a()
tests the figure below
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
void FillOutput(MePolyOffsetterOutput &a_out)
calls implementation
void testCase1()
simple square SANITY CHECK
void SetupInOut(const MePolyOffsetterOutput &a_offsets, double a_xyTol)
calls implementation
void InInTrivialPolyCases()
calls implementation
void testCase7c()
tests the figure below
void InOutDoIntersection()
calls implementation
void testCleanIn7()
tests the figure below
void testCleanIn4a()
tests the figure below
void testCleanIn2b()
tests the figure below
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
void testCleanInOut1a()
tests the figure below
VecPt3d m_origOutsidePoly
the original outside polygon for this step of the paving process
void testCase6b()
tests the figure below
void testCleanInOut1b()
tests the figure below
void testCase5()
tests the figure below
std::list< size_t > SequenceWithIntersects(std::vector< size_t > &a_segs)
Returns a new sequence that includes intersection indexes.
Definition: MePolyPts.cpp:629
void testCleanIn4b()
tests the figure below
void testCleanIn1b()
tests the figure below
void SetupInIn(const std::vector< MePolyOffsetterOutput > &a_offsets, double a_xyTol)
calls implementation
void testCase2a()
tests the figure below
void testCleanIn4d()
tests the figure below
virtual void SetOriginalOutsidePolygon(const VecPt3d &a_origOutsidePoly) override
Sets the original outside polygon for this pave operation.
convenience class for holding output data from the MePolyOffsetter
void testCase8a()
tests the figure below
void testCase8c()
tests the figure below
Intersect polygons that are a result of the paving process.
std::vector< Pt3d > m_pts
locations used by polygons
void testCase6a()
tests the figure below
void FillOutputForCleanPolyOffset(MePolyOffsetterOutput &a_out, int a_pType, std::list< std::vector< size_t >> &a_loops, std::vector< int > &a_loopType, const VecPt3d &a_pts)
Fills the output variable for CleanPolyOffset method.
void testCase8()
tests the figure below
void testCase8b()
tests the figure below
void IntersectSegs(const std::vector< size_t > &a_segs)
Intersects the segments.
Definition: MePolyPts.cpp:607
void testCase7()
tests the figure below
void testCleanIn9()
tests the figure below
virtual void IntersectCleanInOutPolys(const MePolyOffsetterOutput &a_offsets, MePolyOffsetterOutput &a_out, double a_xyTol) override
Takes a PolyOffsetOutput and intersects and cleans all INSIDE_POLY polygons with OUTSIDE_POLY polygon...
void testCleanIn4c()
tests the figure below
void testCleanIn6()
tests the figure below
void testCase2()
tests the figure below
void DeleteBad_NEWOUT_POLY(MePolyOffsetterOutput &a_out, const VecPt3d &a_origOutsidePoly)
calls implementation
void testCleanIn2a()
tests the figure below
Intersects and cleans polygons generated from MePolyOffsetter.
void testCleanIn11()
tests the figure below
void testCleanIn4()
tests the figure below
void testCleanIn1a()
tests the figure below
void testCleanIn0()
tests the figure below
void testCase6c()
tests the figure below
void CalcEnvelopes()
Calculates the envelope of all of the polygons.
static BSHP< MePolyCleaner > New()
Creates a new instance of this class.
void testCleanInOut1()
tests the figure below
void testCase0()
simple triangle SANITY CHECK
void testCase4()
triangle with duplicate point
void testCleanIn3a()
tests the figure below
void testCase3a()
tests the figure below
void testCase9()
tests the figure below
cleans the output produced by MePolyOffsetter
Definition: MePolyCleaner.h:26
void testCase3()
tests the figure below
void testCleanInOut0a()
tests the figure below
std::vector< int > m_loopTypes
type of loop
void testCleanInOut0b()
tests the figure below
virtual void IntersectCleanInPolys(const std::vector< MePolyOffsetterOutput > &a_offsets, MePolyOffsetterOutput &a_out, double a_xyTol) override
Takes a vector of PolyOffsetOutput and intersects and cleans all INSIDE_POLY polygons ...
void testCleanIn8()
tests the figure below
void testCleanIn5()
tests the figure below
void testCase7a()
tests the figure below
std::vector< std::vector< size_t > > m_loops
indexes of points that define loops
void testCleanIn3()
tests the figure below
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 InInDoIntersection()
calls implementation
void testCreateClass()
tests creating the class
void testCleanIn10()
tests the figure below
void testCleanIn1()
tests the figure below
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
#define TS_ASSERT_EQUALS_VEC(a, b)
void testCleanInOut0()
tests the figure below
double & XyTol()
Returns the tolerance.
Definition: MePolyPts.cpp:555
void testCase6()
tests the figure below
void testCase7b()
tests the figure below
Utility class to work with polygon paving.
Definition: MePolyPts.h:28
void testCleanIn2()
tests the figure below
std::vector< Pt3d > VecPt3d