xmsgrid  1.0
TrAutoFixFourTrianglePts.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 <map>
17 
18 // 4. External library headers
19 
20 // 5. Shared code headers
21 #include <xmscore/math/math.h>
22 #include <xmscore/misc/XmError.h>
23 #include <xmscore/misc/Observer.h>
25 
26 // 6. Non-shared code headers
27 
28 //----- Forward declarations ---------------------------------------------------
29 
30 //----- External globals -------------------------------------------------------
31 
32 //----- Namespace declaration --------------------------------------------------
33 
34 namespace xms
35 {
36 //----- Constants / Enumerations -----------------------------------------------
37 
38 //----- Classes / Structs ------------------------------------------------------
39 
42 {
43 public:
46 
47 public:
48  virtual void Fix(BSHP<TrTin> a_tin) override;
51  virtual void SetObserver(BSHP<Observer> a_) override { m_observer = a_; }
54  virtual void SetUndeleteablePtIdxs(VecInt& a_ptIdx) override
55  {
56  m_noDelete.clear();
57  m_noDelete.insert(a_ptIdx.begin(), a_ptIdx.end());
58  }
59 
60  void FillAdjTrisIfNeeded();
61  void GetPtsAndTrisToDelete();
62  std::pair<int, int> EdgeOppositePt(int a_ptIdx, int a_tri, VecInt& a_tris);
63  void MakeTwoNewTriangles(VecPt3d& a_pts, std::map<int, int> a_edges, int a_tris[2][3]);
64  void ReplaceTriangle(int& a_tIdx, int a_newTri[3], VecInt& a_tris);
65  void RenumberPts();
66  void RenumberTris();
67  void RemovePts();
68  void RemoveTris();
69  void ClearAdjTrisIfCreated();
70 
71 private:
72 private:
73  BSHP<TrTin> m_tin;
74  BSHP<Observer> m_observer;
79 }; // class TrOuterTriangleDeleterImpl
80 
81 //----- Internal functions -----------------------------------------------------
82 
83 //----- Class / Function definitions -------------------------------------------
84 
90 //------------------------------------------------------------------------------
92 //------------------------------------------------------------------------------
95 , m_tin()
96 , m_observer()
97 , m_removeAdjTris(false)
98 , m_ptsToDelete()
99 , m_trisToDelete()
100 {
101 } // TrAutoFixFourTrianglePtsImpl::TrAutoFixFourTrianglePtsImpl
102 //------------------------------------------------------------------------------
104 //------------------------------------------------------------------------------
105 TrAutoFixFourTrianglePtsImpl::~TrAutoFixFourTrianglePtsImpl()
106 {
107 }
108 //------------------------------------------------------------------------------
112 //------------------------------------------------------------------------------
113 void TrAutoFixFourTrianglePtsImpl::Fix(BSHP<TrTin> a_tin)
114 {
115  m_tin = a_tin;
118  RenumberPts();
119  RenumberTris();
120  RemovePts();
121  RemoveTris();
123 } // TrOuterTriangleDeleterImpl::Fix
124 //------------------------------------------------------------------------------
126 //------------------------------------------------------------------------------
128 {
129  VecInt2d& adjTris(m_tin->TrisAdjToPts());
130  if (adjTris.empty())
131  {
132  m_tin->BuildTrisAdjToPts();
133  m_removeAdjTris = true;
134  }
135 } // TrAutoFixFourTrianglePtsImpl::FillAdjTrisIfNeeded
136 //------------------------------------------------------------------------------
138 //------------------------------------------------------------------------------
140 {
141  VecInt2d& adjTris(m_tin->TrisAdjToPts());
142  VecInt& tris(m_tin->Triangles());
143  VecPt3d& pts(m_tin->Points());
144  int npts = static_cast<int>(adjTris.size());
145  auto itEnd = m_noDelete.end();
146  for (int i = 0; i < npts; ++i)
147  {
148  auto it = m_noDelete.find(i);
149  if (4 == adjTris[i].size() && it == itEnd)
150  {
151  m_ptsToDelete.insert(i);
152  m_trisToDelete.insert(adjTris[i][2]);
153  m_trisToDelete.insert(adjTris[i][3]);
154  std::map<int, int> mapii;
155  for (int t = 0; t < 4; ++t)
156  {
157  mapii.insert(EdgeOppositePt(i, adjTris[i][t], tris));
158  }
159  int newTris[2][3];
160  MakeTwoNewTriangles(pts, mapii, newTris);
161  ReplaceTriangle(adjTris[i][0], newTris[0], tris);
162  ReplaceTriangle(adjTris[i][1], newTris[1], tris);
163  }
164  }
165 } // TrAutoFixFourTrianglePtsImpl::RemovePts
166 //------------------------------------------------------------------------------
173 //------------------------------------------------------------------------------
174 std::pair<int, int> TrAutoFixFourTrianglePtsImpl::EdgeOppositePt(int a_ptIdx,
175  int a_tri,
176  VecInt& a_tris)
177 {
178  int tIdx = a_tri * 3;
179  int* tPts = &a_tris[tIdx];
180  std::pair<int, int> rval(tPts[0], tPts[1]);
181  if (tPts[0] == a_ptIdx)
182  {
183  rval.first = tPts[1];
184  rval.second = tPts[2];
185  }
186  else if (tPts[1] == a_ptIdx)
187  {
188  rval.first = tPts[2];
189  rval.second = tPts[0];
190  }
191  return rval;
192 } // TrAutoFixFourTrianglePtsImpl::EdgeOppositePt
193 //------------------------------------------------------------------------------
200 //------------------------------------------------------------------------------
202  std::map<int, int> a_edges,
203  int a_tris[2][3])
204 {
205  int bound[4];
206  auto e = a_edges.begin();
207  for (int t = 0; t < 4; ++t)
208  {
209  bound[t] = e->first;
210  e = a_edges.find(e->second);
211  }
212  // is 0,2 closer or 1,3 closer
213  Pt3d &p0(a_pts[bound[0]]), &p1(a_pts[bound[1]]), &p2(a_pts[bound[2]]), &p3(a_pts[bound[3]]);
214  double d2_02 = MdistSq(p0.x, p0.y, p2.x, p2.y);
215  double d2_13 = MdistSq(p1.x, p1.y, p3.x, p3.y);
216  if (d2_02 < d2_13)
217  {
218  a_tris[0][0] = bound[0];
219  a_tris[0][1] = bound[1];
220  a_tris[0][2] = bound[2];
221  a_tris[1][0] = bound[0];
222  a_tris[1][1] = bound[2];
223  a_tris[1][2] = bound[3];
224  }
225  else
226  {
227  a_tris[0][0] = bound[0];
228  a_tris[0][1] = bound[1];
229  a_tris[0][2] = bound[3];
230  a_tris[1][0] = bound[1];
231  a_tris[1][1] = bound[2];
232  a_tris[1][2] = bound[3];
233  }
234 } // TrAutoFixFourTrianglePtsImpl::MakeTwoNewTriangles
235 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
241 void TrAutoFixFourTrianglePtsImpl::ReplaceTriangle(int& a_tIdx, int a_newTri[3], VecInt& a_tris)
242 {
243  int tIdx = a_tIdx * 3;
244  for (int i = 0; i < 3; ++i)
245  a_tris[tIdx + i] = a_newTri[i];
246 } // TrAutoFixFourTrianglePtsImpl::ReplaceTriangle
247 //------------------------------------------------------------------------------
249 //------------------------------------------------------------------------------
251 {
252  VecInt& tris(m_tin->Triangles());
253  VecPt3d& pts(m_tin->Points());
254 
255  VecInt oldToNewPt(pts.size());
256  auto it = m_ptsToDelete.begin();
257  auto itEnd = m_ptsToDelete.end();
258  int cnt(0), npts(static_cast<int>(pts.size()));
259  for (int i = 0; i < npts; ++i)
260  {
261  if (it != itEnd && i == *it)
262  {
263  cnt++;
264  it++;
265  }
266  oldToNewPt[i] = i - cnt;
267  }
268 
269  for (auto& t : tris)
270  t = oldToNewPt[t];
271 } // TrAutoFixFourTrianglePtsImpl::RenumberPts
272 //------------------------------------------------------------------------------
274 //------------------------------------------------------------------------------
276 {
277  if (m_removeAdjTris)
278  return;
279 
280  int ntri = static_cast<int>(m_tin->Triangles().size() / 3);
281  VecInt oldToNewTris(ntri);
282  auto it = m_trisToDelete.begin();
283  auto itEnd = m_trisToDelete.end();
284  int cnt(0);
285  for (int i = 0; i < ntri; ++i)
286  {
287  if (it != itEnd && i == *it)
288  {
289  cnt++;
290  it++;
291  }
292  oldToNewTris[i] = i - cnt;
293  }
294 
295  VecInt2d& adjTris(m_tin->TrisAdjToPts());
296  for (auto& v : adjTris)
297  for (auto& t : v)
298  t = oldToNewTris[t];
299 } // TrAutoFixFourTrianglePtsImpl::RenumberTris
300 //------------------------------------------------------------------------------
302 //------------------------------------------------------------------------------
304 {
305  VecPt3d& pts(m_tin->Points());
306  auto it = m_ptsToDelete.rbegin();
307  auto itEnd = m_ptsToDelete.rend();
308  for (; it != itEnd; ++it)
309  pts.erase(pts.begin() + *it);
310 } // TrAutoFixFourTrianglePtsImpl::RemovePts
311 //------------------------------------------------------------------------------
313 //------------------------------------------------------------------------------
315 {
316  SetInt delTris;
317  for (auto& t : m_trisToDelete)
318  {
319  int tIdx = t * 3;
320  delTris.insert(tIdx + 0);
321  delTris.insert(tIdx + 1);
322  delTris.insert(tIdx + 2);
323  }
324 
325  VecInt& tris(m_tin->Triangles());
326  auto it = delTris.rbegin();
327  auto itEnd = delTris.rend();
328  for (; it != itEnd; ++it)
329  tris.erase(tris.begin() + *it);
330 } // TrAutoFixFourTrianglePtsImpl::RemoveTris
331 //------------------------------------------------------------------------------
333 //------------------------------------------------------------------------------
335 {
336  VecInt2d& adjTris(m_tin->TrisAdjToPts());
337  adjTris.clear();
338  if (m_removeAdjTris)
339  return;
340  m_tin->BuildTrisAdjToPts();
341 } // TrAutoFixFourTrianglePtsImpl::ClearAdjTrisIfCreated
342 
347 //------------------------------------------------------------------------------
350 //------------------------------------------------------------------------------
351 BSHP<TrAutoFixFourTrianglePts> TrAutoFixFourTrianglePts::New()
352 {
353  BSHP<TrAutoFixFourTrianglePts> fixer(new TrAutoFixFourTrianglePtsImpl);
354  return fixer;
355 } // TrAutoFixFourTrianglePts::New
356 //------------------------------------------------------------------------------
358 //------------------------------------------------------------------------------
359 TrAutoFixFourTrianglePts::TrAutoFixFourTrianglePts()
360 {
361 }
362 TrAutoFixFourTrianglePts::~TrAutoFixFourTrianglePts()
363 {
364 }
365 
366 } // namespace xms
367 
368 #if CXX_TEST
369 // UNIT TESTS
372 
373 using namespace xms;
375 
378 
383 //------------------------------------------------------------------------------
385 //------------------------------------------------------------------------------
387 {
388  BSHP<VecPt3d> pts(new VecPt3d());
389  *pts = {{0, 0}, {10, 0}, {0, 10}, {10, 10}, {5, 5}};
390  BSHP<TrTin> tin = TrTin::New();
391  tin->SetPoints(pts);
392  TrTriangulatorPoints client(*pts, tin->Triangles(), &tin->TrisAdjToPts());
393  client.Triangulate();
394 
396  p.Fix(tin);
397 
398  TS_ASSERT_EQUALS(4, tin->Points().size());
399 
400 } // TrOuterTriangleDeleterTests::test1
401 
402 #endif // CXX_TEST
std::vector< int > VecInt
std::pair< int, int > EdgeOppositePt(int a_ptIdx, int a_tri, VecInt &a_tris)
Finds and removes the points connected to 4 triangles.
void RenumberTris()
Renumbers the triangle indexes in the adjacent triangles.
SetInt m_trisToDelete
triangles that will be deleted
virtual void SetObserver(BSHP< Observer > a_) override
Set the observer to use for feedback while processing.
void RemoveTris()
Removes triangles from the triangles vector in the TIN.
std::vector< VecInt > VecInt2d
static BSHP< TrTin > New()
Create a TrTinImpl object.
Definition: TrTin.cpp:1347
SetInt m_noDelete
indexes of points that can&#39;t be deleted
bool Triangulate()
Triangulate the points into a tin.
double MdistSq(_T x1, _U y1, _V x2, _W y2)
void FillAdjTrisIfNeeded()
Makes sure the adjacent triangles exist in the TIN.
SetInt m_ptsToDelete
points in the TIN that will be deleted
void MakeTwoNewTriangles(VecPt3d &a_pts, std::map< int, int > a_edges, int a_tris[2][3])
Makes 2 new triangles from the 4 edges passed into this method.
std::set< int > SetInt
static BSHP< TrAutoFixFourTrianglePts > New()
Creates a TrAutoFixFourTrianglePtsImpl object.
XMS Namespace.
Definition: geoms.cpp:34
void ReplaceTriangle(int &a_tIdx, int a_newTri[3], VecInt &a_tris)
Makes 2 new triangles from the 4 edges passed into this method.
virtual void Fix(BSHP< TrTin > a_tin) override
Removes any points in the tin that are connected to only 4 triangles. These points usually cause poor...
void GetPtsAndTrisToDelete()
Finds and removes the points connected to 4 triangles.
Used to delete points that are connected to 4 triangles and then retriangulate the void...
void test1()
Tests TrAutoFixFourTrianglePts.
void ClearAdjTrisIfCreated()
Clears the adjacent triangles if this class created them.
void RemovePts()
Removes points from the points vector of the TIN.
virtual void SetUndeleteablePtIdxs(VecInt &a_ptIdx) override
Set the indexes of points that can not be deleted.
void RenumberPts()
Renumbers the point indexes in the triangles.
bool m_removeAdjTris
flag to remove adjacent tris when done
Class to triangulate simple points.
std::vector< Pt3d > VecPt3d