xmsgeom  1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
TrOuterTriangleDeleter.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
7 //------------------------------------------------------------------------------
8 
9 //----- Included files ---------------------------------------------------------
10 
11 // 1. Precompiled header
12 
13 // 2. My own header
15 
16 // 3. Standard library headers
17 
18 // 4. External library headers
19 
20 // 5. Shared code headers
21 #include <xmscore/stl/set.h>
22 #include <xmscore/stl/vector.h>
23 #include <xmscore/misc/Observer.h>
24 #include <xmscore/misc/XmError.h>
25 #include <xmscore/misc/boost_defines.h> // BSHP
28 
29 // 6. Non-shared code headers
30 
31 //----- Forward declarations ---------------------------------------------------
32 
33 //----- External globals -------------------------------------------------------
34 
35 //----- Namespace declaration --------------------------------------------------
36 
37 namespace xms
38 {
39 //----- Constants / Enumerations -----------------------------------------------
40 
41 //----- Classes / Structs ------------------------------------------------------
42 
45 {
46 public:
48  enum BoundaryEnum {
49  BE_UNVISITED = 0,
50  BE_VISITED = 1,
51  BE_OUTSIDE = 2,
52  BE_INSIDE = 4,
53  BE_ONBOUNDARY = 8
54  };
55 
57  virtual ~TrOuterTriangleDeleterImpl();
58 
59 public:
60  virtual void Delete(const VecInt2d& a_polys, BSHP<TrTin> a_tin) override;
63  virtual void SetObserver(BSHP<Observer> a_) override { m_observer = a_; }
64 
65 private:
66  void FlagTrianglesAlongPolygon(const VecInt& a_poly, VecInt& a_flags);
67  void MarkNeighbors(VecInt& a_flags);
68 
69 private:
71  BSHP<TrTin> m_tin;
72  BSHP<Observer> m_observer;
73 }; // class TrOuterTriangleDeleterImpl
74 
75 //----- Internal functions -----------------------------------------------------
76 
77 //----- Class / Function definitions -------------------------------------------
78 
84 //------------------------------------------------------------------------------
86 //------------------------------------------------------------------------------
89 , m_polys()
90 , m_tin()
91 {
92 }
93 //------------------------------------------------------------------------------
95 //------------------------------------------------------------------------------
96 TrOuterTriangleDeleterImpl::~TrOuterTriangleDeleterImpl()
97 {
98 }
99 //------------------------------------------------------------------------------
107 //------------------------------------------------------------------------------
108 void TrOuterTriangleDeleterImpl::Delete(const VecInt2d& a_polys, BSHP<TrTin> a_tin)
109 {
110  m_polys = a_polys;
111  m_tin = a_tin;
112 
113  // Make sure polygons are closed
114  for (int i = 0; i < (int)m_polys.size(); ++i)
115  {
116  if (m_polys[i].front() != m_polys[i].back())
117  {
118  XM_ASSERT(false);
119  m_polys[i].push_back(m_polys[i].front());
120  }
121  }
122 
123  // Flag triangles on border
124  VecInt flags(m_tin->NumTriangles(), BE_UNVISITED);
125  for (size_t i = 0; i < m_polys.size(); ++i)
126  {
128  }
129  if (m_observer)
130  m_observer->ProgressStatus(0.4);
131 
132  // Flag all triangles working out from the ones already flagged
133  MarkNeighbors(flags);
134  if (m_observer)
135  m_observer->ProgressStatus(0.8);
136 
137  // Create the set of triangles to delete
138  SetInt trisToDelete;
139  for (size_t i = 0; i < flags.size(); ++i)
140  {
141  if (flags[i] & BE_OUTSIDE)
142  {
143  trisToDelete.insert((int)i);
144  }
145  }
146 
147  m_tin->DeleteTriangles(trisToDelete);
148  if (m_observer)
149  m_observer->ProgressStatus(1.0);
150 } // TrOuterTriangleDeleterImpl::Delete
151 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
157 {
158  VecInt::const_iterator it0 = a_poly.begin();
159  VecInt::const_iterator it1 = it0;
160  ++it1;
161  int outTri, inTri;
162  for (; it1 != a_poly.end(); ++it0, ++it1)
163  {
164  // outTri = m_tin->TriangleAdjacentToEdge(*it0, *it1);
165  // inTri = m_tin->TriangleAdjacentToEdge(*it1, *it0);
166  inTri = m_tin->TriangleAdjacentToEdge(*it0, *it1);
167  outTri = m_tin->TriangleAdjacentToEdge(*it1, *it0);
168  if (outTri != -1)
169  {
170  // A polygon with an internal arc is a little different. We have adjacent
171  // triangles to 2 edges that will be marked as "inside".
172  if (!(a_flags[outTri] & BE_INSIDE))
173  a_flags[outTri] = BE_OUTSIDE | BE_ONBOUNDARY;
174  }
175  if (inTri != -1)
176  {
177  a_flags[inTri] = BE_INSIDE | BE_ONBOUNDARY;
178  }
179  }
180 
181 } // TrOuterTriangleDeleterImpl::FlagTrianglesAlongPolygon
182 //------------------------------------------------------------------------------
187 //------------------------------------------------------------------------------
189 {
190  XM_ENSURE_TRUE_VOID_NO_ASSERT(!m_tin->Triangles().empty());
191 
192  // Create stack size of num triangles
193  int numTri = m_tin->NumTriangles();
194  VecInt stack(numTri, -1);
195 
196  bool done = false;
197  int lastTri = 0;
198  while (!done)
199  {
200  // find a visited elem with unvisited neighbors
201  int tri = lastTri;
202  bool found = false;
203  while (tri < numTri && tri != -1 && !found)
204  {
205  if (a_flags[tri] & BE_ONBOUNDARY && !(a_flags[tri] & BE_VISITED))
206  {
207  for (int id = 0; id < 3 && !found; ++id)
208  {
209  int adjTri = m_tin->AdjacentTriangle(tri, id);
210  if (adjTri != -1 && a_flags[adjTri] == BE_UNVISITED)
211  {
212  found = true;
213  lastTri = tri + 1;
214  }
215  }
216  }
217  if (!found)
218  {
219  ++tri;
220  }
221  }
222 
223  // all have been flagged, we're done
224  if (!found)
225  {
226  done = true;
227  // AKZ - flag unvisited as out
228  for (size_t i = 0; i < a_flags.size(); ++i)
229  {
230  if (a_flags[i] == BE_UNVISITED)
231  {
232  a_flags[i] = BE_OUTSIDE;
233  }
234  }
235  }
236  else
237  {
238  int size = 0;
239  // push the first tri onto the stack
240  stack[size++] = tri;
241  for (int i = 0; i < size; i++)
242  {
243  int currTri = stack[i];
244  a_flags[currTri] |= BE_VISITED;
245  // find the unflagged adjacents and push onto stack
246  int id = 0;
247  do
248  {
249  int adjTri = m_tin->AdjacentTriangle(currTri, id);
250  if (adjTri != -1 && a_flags[adjTri] == BE_UNVISITED)
251  {
252  // push adjacent onto stack
253  stack[size++] = adjTri;
254  if (a_flags[currTri] & BE_INSIDE)
255  a_flags[adjTri] = BE_INSIDE;
256  else
257  a_flags[adjTri] = BE_OUTSIDE;
258  }
259  id = trIncrementIndex(id);
260  } while (id != 0);
261  }
262  }
263  }
264 
265 } // TrOuterTriangleDeleterImpl::MarkNeighbors
266 
271 //------------------------------------------------------------------------------
274 //------------------------------------------------------------------------------
275 BSHP<TrOuterTriangleDeleter> TrOuterTriangleDeleter::New()
276 {
277  BSHP<TrOuterTriangleDeleter> deleter(new TrOuterTriangleDeleterImpl);
278  return deleter;
279 } // TrOuterTriangleDeleter::New
280 //------------------------------------------------------------------------------
282 //------------------------------------------------------------------------------
283 TrOuterTriangleDeleter::TrOuterTriangleDeleter()
284 {
285 } // TrOuterTriangleDeleter::TrOuterTriangleDeleter
286 //------------------------------------------------------------------------------
288 //------------------------------------------------------------------------------
289 TrOuterTriangleDeleter::~TrOuterTriangleDeleter()
290 {
291 } // TrOuterTriangleDeleter::~TrOuterTriangleDeleter
292 
293 } // namespace xms
294 
295 #if CXX_TEST
296 // UNIT TESTS
299 
301 
304 #include <xmscore/misc/carray.h>
305 
310 //------------------------------------------------------------------------------
313 // Before
314 // 10- 17-----18------19------20------21
315 // | |\ 8 /|\ 11 /|\ 22 / \ 26 /|
316 // | | \ / | \ / | \ / \ //|
317 // | | \ / | \ /30|23\ / 27 \ / /|
318 // 5- |6 13 12|9 14 | 15------16 /|
319 // | | / \ | /|\ | / \ 25 /|28/|
320 // | | / \ | / | \ | / \ / | / |
321 // | |/ 7 \|/ | \|/ 24 \ /29| / |
322 // 0- 9------10 10|3 11------12 | / |
323 // | |\ 13 / \ | / \ 15 / \ |/ |
324 // | | \ / \ | / \ / \ |/ |
325 // | | \ / 5 \|/ 16 \ / 21 \|/ |
326 // -5- | 0 5-------6-------7-------8 18|
327 // | | / \ 4 / \ 14 / \ 19 / \ |
328 // | | / \ / \ / \ / \ |
329 // | |/ 1 \ / 2 \ / 20 \ / 17 \|
330 // -10- 0-------1-------2-------3-------4
331 //
332 // |-------|-------|-------|-------|
333 // 0 10 20 30 40
334 //
335 // After
336 // 10- 17-----18------19------20------21
337 // | |\ 8 /|\ 11 /|\ 22 / \ 26 /
338 // | | \ / | \ / | \ / \ /
339 // | | \ / | \ /30|23\ / 27 \ /
340 // 5- |6 13 12|9 14 | 15------16
341 // | | / \ | /|\ | / \ 25 /|
342 // | | / \ | / | \ | / \ / |
343 // | |/ 7 \|/ | \|/ \ /29|
344 // 0- 9------10 |3 11 12 |
345 // | |\ 13 / | / \ / \ |
346 // | | \ / | / \ / \ |
347 // | | \ / |/ 16 \ / 21 \|
348 // -5- | 0 5-------6-------7-------8
349 // | | / \ 4 / \ 14 / \ 19 / \
350 // | | / \ / \ / \ / \
351 // | |/ 1 \ / 2 \ / 20 \ / 17 \
352 // -10- 0-------1-------2-------3-------4
353 //
354 // |-------|-------|-------|-------|
355 // 0 10 20 30 40
357 //------------------------------------------------------------------------------
359 {
360  BSHP<xms::TrTin> tin = trBuildTestTin7();
361 
362  // Set up polygons
363  xms::VecInt2d polys;
364  int outPoly[] = {0, 9, 17, 18, 19, 20, 21, 16, 8, 4, 3, 2, 1, 0};
365  int inPoly1[] = {10, 5, 6, 14, 10};
366  int inPoly2[] = {11, 7, 12, 15, 11};
367  polys.push_back(xms::VecInt(&outPoly[0], &outPoly[XM_COUNTOF(outPoly)]));
368  polys.push_back(xms::VecInt(&inPoly1[0], &inPoly1[XM_COUNTOF(inPoly1)]));
369  polys.push_back(xms::VecInt(&inPoly2[0], &inPoly2[XM_COUNTOF(inPoly2)]));
370 
371  BSHP<xms::TrOuterTriangleDeleter> deleter = xms::TrOuterTriangleDeleter::New();
372  deleter->Delete(polys, tin);
373 
374  // Verify triangles after
375  int trisA[] = {0, 5, 9, 5, 0, 1, 1, 2, 6, 14, 6, 11, 1, 6, 5, 9, 13, 17, 13,
376  9, 10, 17, 13, 18, 10, 14, 18, 18, 14, 19, 10, 18, 13, 9, 5, 10, 6, 2,
377  7, 7, 11, 6, 3, 4, 8, 3, 8, 7, 7, 2, 3, 12, 7, 8, 19, 15, 20,
378  15, 19, 11, 15, 12, 16, 20, 16, 21, 16, 20, 15, 12, 8, 16, 11, 19, 14};
379  xms::VecInt trisAfter(&trisA[0], &trisA[XM_COUNTOF(trisA)]);
380  TS_ASSERT_EQUALS_VEC(trisAfter, tin->Triangles());
381 
382 } // TrOuterTriangleDeleterUnitTests::test1
383 
384 #endif // CXX_TEST
void FlagTrianglesAlongPolygon(const VecInt &a_poly, VecInt &a_flags)
Flag triangles along polygon as inside or outside the polygon.
BSHP< Observer > m_observer
Observer.
Functions dealing with triangles.
std::vector< int > VecInt
std::set< int > SetInt
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
#define XM_ASSERT(x)
static boost::shared_ptr< TrOuterTriangleDeleter > New()
Creates a TrOuterTriangleDeleterImpl object.
virtual void Delete(const VecInt2d &a_polys, BSHP< TrTin > a_tin) override
Deletes triangles in a_tin that are outside a_polys or inside if the poly is a hole.
#define XM_COUNTOF(array)
BSHP< TrTin > trBuildTestTin7()
Builds a simple TIN for testing.
Definition: TrTin.cpp:1465
void test1()
Tests TrOuterTriangleDeleter.
Used to delete tin triangles that are outside given polygons. The polygons may include holes - polygo...
std::vector< VecInt > VecInt2d
#define TS_ASSERT_EQUALS_VEC(a, b)
virtual void SetObserver(BSHP< Observer > a_) override
Set the observer to use for feedback while processing.
VecInt2d m_polys
Polygons (boundary and holes) of tin.
void MarkNeighbors(VecInt &a_flags)
Flag all triangles as inside or outside the polygon, starting with those already flagged and working ...