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