TINGeneration.cpp
Go to the documentation of this file.
1 /*!
2 \file terralib/mnt/core/TINGeneration.cpp
3 
4 \brief This file contains a class to generate TIN.
5 
6 */
7 
8 #include "TINGeneration.h"
9 #include "Utils.h"
10 
11 //.. /..
12 #include "../../common/progress/TaskProgress.h"
13 #include "../../dataaccess/utils/Utils.h"
14 
15 #include "../../geometry/Envelope.h"
16 #include "../../geometry/Geometry.h"
17 #include "../../geometry/LineString.h"
18 #include "../../geometry/Point.h"
19 #include "../../geometry/TIN.h"
20 #include "../../geometry/Triangle.h"
21 
22 #include "../../sam.h"
23 
24 #include <limits>
25 
26 
28 {
29  m_srid = 0;
30  m_tolerance = 0.;
31  m_maxdist = 0.;
32  m_minedgesize = 0.;
34  m_inDsetName_point = "";
35  m_atrZ_sample = "";
36  m_atrZ_point = "";
37 }
38 
40 
42  std::string inDsetName,
43  std::unique_ptr<te::da::DataSetType> inDsetType, InputType type)
44 {
45  if (type == Isolines)
46  {
47  m_inDsrc_sample = inDsrc;
48  m_inDsetName_sample = inDsetName;
49  m_inDsetType_sample = std::move(inDsetType);
50  }
51  else
52  {
53  m_inDsrc_point = inDsrc;
54  m_inDsetName_point = inDsetName;
55  m_inDsetType_point = std::move(inDsetType);
56  }
57 }
58 
59 void te::mnt::TINGeneration::setBreakLine(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::unique_ptr<te::da::DataSetType> inDsetType, double tol)
60 {
61  m_inDsrc_break = inDsrc;
62  m_inDsetName_break = inDsetName;
63  m_inDsetType_break = std::move(inDsetType);
64  m_tolerance_break = tol;
65 }
66 
68 {
69  m_outDsrc = outDsrc;
70  m_outDsetName = dsname;
71 }
72 
73 void te::mnt::TINGeneration::setParams(const double& tolerance,
74  const double &maxdist,
75  const double &minedgesize,
76  const std::string &atrz_iso,
77  const std::string &atrz_pt)
78 {
79  setTolerance(tolerance);
80  setMaxdist(maxdist);
81  setMinedgesize(minedgesize);
82  m_atrZ_sample = atrz_iso;
83  m_atrZ_point = atrz_pt;
84 }
85 
87 {
91  std::string geostype;
92 
93  // Get samples
94  size_t nsamples;
95  te::gm::Envelope env;
96 
97  nsamples = ReadPoints(m_inDsetName_point, m_inDsrc_point, m_atrZ_point, m_tolerance, mpt, geostype, env);
98  setEnvelope(env);
99 
100  nsamples += ReadSamples(m_inDsetName_sample, m_inDsrc_sample, m_atrZ_sample, m_tolerance, m_maxdist, AccumulatedDistance, mptiso, isolines_simp, geostype, env);
101  setEnvelope(env);
102 
103  // Initialize triangulation process
104  CreateInitialTriangles(nsamples);
105  // Insert points in initial triangulation
106  InsertNodes(mpt, isolines_simp);
107  // Modify initial triangulation generating Delaunay
108  if (!CreateDelaunay())
109  return false;
110  // Modify Delaunay triangulation to a achieve convex hull
111  if (!ModifyBoundTriangles())
112  return false;
113 
114  //Test isolines
115  if (m_method == 0) //Delanay
116  {
117  if (isolines_simp.getNumGeometries())
119  }
120  else //Smaller Angle
122 
123  if (m_inDsrc_break.get())
124  {
126  }
127 
128  // Save triangulation to datasource
129  SaveTin();
130 
131  return true;
132 }
133 
135 {
137 }
138 
140 {
141  m_nodesize = nsamples + 6;
142  m_triangsize = 2 * (nsamples + 6) - 5; // ntri = 2n-5
143  m_linesize = (3 * (nsamples + 5)); // nlin = (n-1)*3
144  m_ltriang = 0;
145  m_lnode = -1;
146  m_lline = 0;
147 
148  size_t i;
149  for (i = 0; i < m_nodesize; i++)
150  {
151  TinNode tn;
152  m_node.push_back(tn);
153  }
154 
155  for (i = 0; i < m_triangsize; i++)
156  {
157  TinTriang tt;
158  m_triang.push_back(tt);
159  }
160 
161  for (i = 0; i < m_linesize; i++)
162  {
163  TinLine tl;
164  m_line.push_back(tl);
165  }
166 
167  int32_t nodelist[4], linlist[5];
168 
169  // Create the two initial triangles of the Tin
170  size_t t1 = (size_t)m_ltriang++;
171  size_t t2 = (size_t)m_ltriang++;
172  if (t1 > m_triangsize)
173  return false;
174  if (t2 > m_triangsize)
175  return false;
176 
177  // Create and insert initial nodes of the Tin
178  std::vector<te::gm::Point> pointaux;
179 
182  pointaux.push_back(pt1);
183 
186  pointaux.push_back(pt2);
187 
190  pointaux.push_back(pt3);
191 
193  pt4.setZ(m_nodatavalue);
194  pointaux.push_back(pt4);
195 
196  int32_t node;
197  for (i = 0; i < 4; i++)
198  {
199  node = ++m_lnode;
200  nodelist[i] = node;
201  if (nodelist[i] >(int32_t)m_nodesize)
202  return false;
203  m_node[(unsigned int)nodelist[i]].Init(pointaux[i]);
204  m_node[(unsigned int)nodelist[i]].setType(Box);
205  }
206 
207  // Create and insert initial lines of the Tin
208  int32_t lin;
209  for (i = 0; i < 5; i++)
210  {
211  lin = m_lline++;
212  linlist[i] = lin;
213  if (linlist[i] >(int32_t)m_linesize){
214  return false;
215  }
216 
217  if (i < 4)
218  {
219  m_line[(unsigned int)linlist[i]].Nodes(nodelist[i], nodelist[((i + 1) % 4)]);
220  m_node[(unsigned int)nodelist[i]].setEdge(linlist[i]);
221  m_node[(unsigned int)nodelist[((i + 1) % 4)]].setEdge(linlist[i]);
222  }
223 
224  if (i < 2)
225  {
226  m_line[(unsigned int)linlist[i]].Polygons(-1, (int32_t)t1);
227  }
228  else if (i < 4)
229  {
230  m_line[(unsigned int)linlist[i]].Polygons(-1, (int32_t)t2);
231  }
232  else
233  {
234  m_line[(unsigned int)linlist[i]].Nodes(nodelist[2], nodelist[0]);
235  m_node[(unsigned int)nodelist[2]].setEdge(linlist[i]);
236  m_node[(unsigned int)nodelist[0]].setEdge(linlist[i]);
237  m_line[(unsigned int)linlist[i]].Polygons((int32_t)t2, (int32_t)t1);
238  }
239  }
240 
241  // Update triangles edges
242  m_triang[t1].setEdges(linlist[0], linlist[1], linlist[4]);
243 
244  m_triang[t2].setEdges(linlist[4], linlist[2], linlist[3]);
245 
246  m_node[(unsigned int)nodelist[0]].setEdge(linlist[0]);
247  m_node[(unsigned int)nodelist[1]].setEdge(linlist[1]);
248  m_node[(unsigned int)nodelist[2]].setEdge(linlist[2]);
249  m_node[(unsigned int)nodelist[3]].setEdge(linlist[3]);
250 
251  return true;
252 }
253 
254 
256 {
257  te::common::TaskProgress task("Inserting Nodes...", te::common::TaskProgress::UNDEFINED, (int)m_nodesize-6);
258 
259  int32_t node = 0;
260  // Create nodes and insert on triangulation
261  for (size_t id = 0; id < mpt.getNumGeometries(); ++id)
262  {
263  te::gm::Point* pto3d = dynamic_cast<te::gm::Point*>(mpt.getGeometryN(id));
264  node = ++m_lnode;
265  if (node > (int32_t)m_nodesize)
266  return false;
267  m_node[(unsigned int)node].Init(*pto3d, Sample);
268  InsertNode(node, 1);
269  if (!task.isActive())
270  return false;
271  task.pulse();
272  }
273 
274  bool nflag;
275 
279  KD_TREE nodetree(e);
280  std::vector<KD_NODE*> reportsnode;
281 
282  size_t mlsize = mls.getNumGeometries();
283  for (unsigned int id = 0; id < mlsize; ++id)
284  {
285  te::gm::LineString* gout = dynamic_cast<te::gm::LineString*>(mls.getGeometryN(id));
286  nflag = true;
287 
288  size_t gnp = gout->getNPoints();
289  for (size_t j = 0; j < gnp; ++j)
290  {
291  std::unique_ptr<te::gm::Point> p = gout->getPointN(j);
292  te::gm::Point pz(p->getX(), p->getY(), 0, te::gm::PointZType);
293  pz.setZ(p->getZ());
294 
295  // Test if new point is equal to inserted
296  te::gm::Envelope ept(*p->getMBR());
297  nodetree.search(ept, reportsnode);
298  if (reportsnode.size())
299  {
300  reportsnode.clear();
301  continue;
302  }
303 
304  // for each point, create and insert node
305  node = ++m_lnode;
306  if (node > (int32_t)m_nodesize)
307  return false;
308 
309  m_node[(unsigned int)node].Init(pz);
310 
311  te::gm::Coord2D coord(p->getX(), p->getY());
312  nodetree.insert(coord, node);
313 
314  // Set node type
315  if (nflag)
316  {
317  m_node[(unsigned int)node].setType(First);
318  InsertNode(node, 1);
319  if (m_node[(unsigned int)node].getType() == Deletednode)
320  nflag = true;
321  else
322  nflag = false;
323  }
324  else
325  {
326  m_node[(unsigned int)node].setType(Normalnode);
327  InsertNode(node, 1);
328  } //nflag
329  if (!task.isActive())
330  return false;
331  task.pulse();
332  } //for (std::size_t j = 0; j < gout->getNPoints(); ++j)
333 
334  if (m_node[(unsigned int)node].getType() == Normalnode)
335  m_node[(unsigned int)node].setType(Last);
336  else if (m_node[(unsigned int)node].getType() == First)
337  m_node[(unsigned int)node].setType(Sample);
338  else if ((m_node[(unsigned int)node].getType() != Sample) && (m_node[(unsigned int)node].getType() != Last))
339  return false;
340  } //for (unsigned int id = 0; id < mls.getNumGeometries(); ++id)
341 
342  m_fbnode = 0;
343  nodetree.clear();
344 
345  return true;
346 }
347 
348 bool te::mnt::TINGeneration::InsertNode(int32_t nodeId, int type)
349 {
350  double tol = m_minedgesize;
351 
352  // Get Point to be inserted from vector
353  te::gm::Point pt(m_node[(unsigned int)nodeId].getNPoint());
354 
355  if (!m_env.contains(*pt.getMBR()))
356  return false;
357 
358  double zvalue = pt.getZ();
359 
360  // Find the triangle that owns the point pt
361  double px = pt.getX();
362  double py = pt.getY();
363 
364  int32_t triangid = FindTriangle(pt);
365 
366  if (triangid == -1)
367  return false;
368 
372  TrianglePoints(triangid, vert);
373  int32_t nids[3];
374 
375  // Verify if point is too close to one triangle vertex
376  for (unsigned short j = 0; j < 3; j++)
377  {
378  if ((fabs(px - vert[j].getX()) < tol) && (fabs(py - vert[j].getY()) < tol))
379  {
380  NodesId(triangid, nids);
381  NodeExchange(nids[j], nodeId);
382  DeleteNode(nids[j]);
383  return false;
384  }
385  }
386 
387  int32_t linesid[3];
388  int32_t neighids[3];
389  m_triang[(unsigned int)triangid].LinesId(linesid);
390  if (!NeighborsId(triangid, neighids))
391  return false;
392 
393  // Test if the point is on an edge
394  short nedge = -1;
395  double dmin = std::numeric_limits< float >::max();
398  for (unsigned int j = 0; j < 3; j++)
399  {
400  if ((pt.getX() > vert[j].getX()) &&
401  (pt.getX() > vert[(j + 1) % 3].getX()))
402  continue;
403  if ((pt.getX() < vert[j].getX()) &&
404  (pt.getX() < vert[(j + 1) % 3].getX()))
405  continue;
406  if ((pt.getY() > vert[j].getY()) &&
407  (pt.getY() > vert[(j + 1) % 3].getY()))
408  continue;
409  if ((pt.getY() < vert[j].getY()) &&
410  (pt.getY() < vert[(j + 1) % 3].getY()))
411  continue;
412 
413  double daux = pointToSegmentDistance(vert[j], vert[(j + 1) % 3], pt, &paux);
414  if ((daux < tol) && (daux < dmin))
415  {
416  // On edge j
417  nedge = (short)j;
418  dmin = daux;
419  paux.setZ(zvalue);
420  pmin = paux;
421  }
422  }
423 
424  int32_t ntri1, ntri2;
425  if (nedge == -1)
426  {
427  int32_t testLines[6];
428  TwoNewTriangles(triangid, nodeId, testLines); //If not, split triang
429  for (int j = 0; j < 6; j++)
430  {
431  if (testLines[j] == -1)
432  break;
433  if (TestDelaunay(testLines[j]))
434  j = -1;
435  }
436  ntri1 = m_ltriang - 1;
437  ntri2 = m_ltriang - 2;
438  if (type == 0)
439  TestDelaunay(triangid, ntri1, ntri2);
440  else
441  {
442  if (!NeighborsId(triangid, neighids))
443  return false;
444  TestDelaunay(triangid, 0);
445  TestDelaunay(triangid, 1);
446  TestDelaunay(triangid, 2);
447 
448  TestDelaunay(neighids[0], 0);
449  TestDelaunay(neighids[0], 1);
450  TestDelaunay(neighids[0], 2);
451  TestDelaunay(neighids[1], 0);
452  TestDelaunay(neighids[1], 1);
453  TestDelaunay(neighids[1], 2);
454  TestDelaunay(neighids[2], 0);
455  TestDelaunay(neighids[2], 1);
456  TestDelaunay(neighids[2], 2);
457  TestDelaunay(ntri1, 0);
458  TestDelaunay(ntri1, 1);
459  TestDelaunay(ntri1, 2);
460  TestDelaunay(ntri2, 0);
461  TestDelaunay(ntri2, 1);
462  TestDelaunay(ntri2, 2);
463  }
464  }
465  else
466  {
467  m_node[(unsigned int)nodeId].setNPoint(pmin);
468 
469  for (unsigned int j = 0; j < 3; j++)
470  {
471  if (neighids[j] == -1)
472  continue;
473  int32_t oppNode = OppositeNode(neighids[j], linesid[j]);
474  if (oppNode == -1)
475  continue;
476  if ((fabs(px - m_node[(unsigned int)oppNode].getX()) < tol) && (fabs(py - m_node[(unsigned int)oppNode].getY()) < tol))
477  {
478  NodesId(triangid, nids);
479  NodeExchange(nids[j], nodeId);
480  DeleteNode(nids[j]);
481  return false;
482  }
483  }
484 
485  // Duplicate triangle and its neighbor on the same edge
486  int32_t testLines[5];
487  int32_t linid = DuplicateTriangle(triangid, nedge, nodeId, testLines);
488  if (neighids[(unsigned int)nedge] != -1)
489  {
490  int32_t ngtriang = neighids[(unsigned int)nedge];
491  if (ngtriang > (int32_t)m_triangsize)
492  return false;
493  int32_t testLines2[2];
494  DupNeighTriangle(ngtriang, linid, nedge, nodeId, testLines2);
495  for (int j = 0; j < 2; j++)
496  {
497  if (testLines2[(unsigned int)j] == -1)
498  break;
499  if (TestDelaunay(testLines2[(unsigned int)j]))
500  j = -1;
501  }
502 
503  // Test Delaunay restriction with neighbour 1
504  ntri1 = m_ltriang - 1;
505  ntri2 = m_ltriang - 2;
506  if (type == 0)
507  TestDelaunay(triangid, ngtriang, ntri1, ntri2);
508  else
509  {
510  if (!NeighborsId(triangid, neighids))
511  return false;
512  TestDelaunay(triangid, 0);
513  TestDelaunay(triangid, 1);
514  TestDelaunay(triangid, 2);
515  TestDelaunay(ngtriang, 0);
516  TestDelaunay(ngtriang, 1);
517  TestDelaunay(ngtriang, 2);
518 
519  TestDelaunay(neighids[0], 0);
520  TestDelaunay(neighids[0], 1);
521  TestDelaunay(neighids[0], 2);
522  TestDelaunay(neighids[1], 0);
523  TestDelaunay(neighids[1], 1);
524  TestDelaunay(neighids[1], 2);
525  TestDelaunay(neighids[2], 0);
526  TestDelaunay(neighids[2], 1);
527  TestDelaunay(neighids[2], 2);
528  TestDelaunay(ntri1, 0);
529  TestDelaunay(ntri1, 1);
530  TestDelaunay(ntri1, 2);
531  TestDelaunay(ntri2, 0);
532  TestDelaunay(ntri2, 1);
533  TestDelaunay(ntri2, 2);
534  }
535  }
536  else
537  {
538  for (int j = 0; j < 5; j++)
539  {
540  if (testLines[(unsigned int)j] == -1)
541  break;
542  if (TestDelaunay(testLines[(unsigned int)j]))
543  j = -1;
544  }
545  if (!NeighborsId(triangid, neighids))
546  return false;
547  ntri1 = m_ltriang - 1;
548  TestDelaunay(triangid, 0);
549  TestDelaunay(triangid, 1);
550  TestDelaunay(triangid, 2);
551  TestDelaunay(neighids[0], 0);
552  TestDelaunay(neighids[0], 1);
553  TestDelaunay(neighids[0], 2);
554  TestDelaunay(neighids[1], 0);
555  TestDelaunay(neighids[1], 1);
556  TestDelaunay(neighids[1], 2);
557  TestDelaunay(neighids[2], 0);
558  TestDelaunay(neighids[2], 1);
559  TestDelaunay(neighids[2], 2);
560  TestDelaunay(ntri1, 0);
561  TestDelaunay(ntri1, 1);
562  TestDelaunay(ntri1, 2);
563  }
564  }
565 
566  return true;
567 }
568 
570 {
571  int32_t nidaux;
572 
573  switch (m_node[(unsigned int)node].getType())
574  {
575  case Normalnode: // Isoline normal point
576  case Sample: // Sample point
577  case Box:
578  case Deletednode:
579  break;
580  case First: // Isoline first point
581  {
582  nidaux = NextNode(node);
583 
584  if (m_node[(unsigned int)nidaux].getType() == Normalnode)
585  m_node[(unsigned int)nidaux].setType(First);
586  else if (m_node[(unsigned int)nidaux].getType() == Last)
587  m_node[(unsigned int)nidaux].setType(Sample);
588  else
589  return false;
590  break;
591  }
592  case Last: // Isoline last point
593  {
594  nidaux = PreviousNode(node);
595 
596  if (m_node[(unsigned int)nidaux].getType() == Normalnode)
597  m_node[(unsigned int)nidaux].setType(Last);
598  else if (m_node[(unsigned int)nidaux].getType() == First)
599  m_node[(unsigned int)nidaux].setType(Sample);
600  else
601  return false;
602  break;
603  }
604  case Breaklinenormal: // Breakline normal point
605  {
606  nidaux = NextNode(node);
607 
608  if (nidaux == m_lnode)
609  break;
610 
611  if (m_node[(unsigned int)nidaux].getType() == Breaklinenormal)
612  m_node[(unsigned int)nidaux].setType(Breaklinefirst);
613  else if (m_node[(unsigned int)nidaux].getType() == Breaklinelast)
614  m_node[(unsigned int)nidaux].setType(Sample);
615  else
616  return false;
617  nidaux = PreviousNode(node);
618 
619  if (m_node[(unsigned int)nidaux].getType() == Breaklinenormal)
620  m_node[(unsigned int)nidaux].setType(Breaklinelast);
621  else if (m_node[(unsigned int)nidaux].getType() == Breaklinefirst)
622  m_node[(unsigned int)nidaux].setType(Sample);
623  break;
624  }
625  case Breaklinefirst: // Breakline first point
626  {
627  nidaux = NextNode(node);
628 
629  if (nidaux == m_lnode)
630  {
631  m_node[(unsigned int)nidaux].setType(Breaklinefirst);
632  break;
633  }
634  if (m_node[(unsigned int)nidaux].getType() == Breaklinenormal)
635  m_node[(unsigned int)nidaux].setType(Breaklinefirst);
636  else if (m_node[(unsigned int)nidaux].getType() == Breaklinelast)
637  m_node[(unsigned int)nidaux].setType(Sample);
638  else
639  return false;
640  break;
641  }
642  case Breaklinelast: // Breakline last point
643  {
644  nidaux = PreviousNode(node);
645 
646  if (m_node[(unsigned int)nidaux].getType() == Breaklinenormal)
647  m_node[(unsigned int)nidaux].setType(Breaklinelast);
648  else if (m_node[(unsigned int)nidaux].getType() == Breaklinefirst)
649  m_node[(unsigned int)nidaux].setType(Sample);
650  else
651  {
652  return false;
653  }
654  break;
655  }
656  }
657  m_node[(unsigned int)node].setType(Deletednode);
658 
659  return true;
660 }
661 
662 
663 bool te::mnt::TINGeneration::NodeExchange(int32_t oldNode, int32_t newNode)
664 {
665  std::vector<int32_t> lids;
666  int32_t linid = 0;
667 
668  if (!NodeLines(oldNode, lids))
669  return false;
670  for (size_t i = 0; i < lids.size(); i++)
671  {
672  linid = lids[i];
673  m_line[(unsigned int)linid].ExchangeNode(oldNode, newNode);
674  m_node[(unsigned int)oldNode].removeEdge(linid);
675  m_node[(unsigned int)newNode].setEdge(linid);
676  }
677  m_node[(unsigned int)newNode].setX(m_node[(unsigned int)oldNode].getX());
678  m_node[(unsigned int)newNode].setY(m_node[(unsigned int)oldNode].getY());
679  m_node[(unsigned int)newNode].setZ(m_node[(unsigned int)oldNode].getZ());
680  return true;
681 }
682 
683 
684 bool te::mnt::TINGeneration::TwoNewTriangles(int32_t t, int32_t nodeId, int32_t* testLines)
685 {
686  //1. Creates the vertex vn with data of sample s,
687  int32_t vn = nodeId;
688 
689  //2. Creates 2 nwes triangles t1 and t2,
690  int32_t t1 = m_ltriang++;
691  if (t1 > (int32_t)m_triangsize)
692  return false;
693 
694  int32_t t2 = m_ltriang++;
695  if (t2 > (int32_t)m_triangsize)
696  return false;
697 
698  //3. Creates a new edge an0 that connects vertex vn and v0 and
699  // has t and t1 as the triangles that shared the edge.
700  int32_t an0 = m_lline++;
701  m_line[(unsigned int)an0].Nodes(vn, NodeId(t, 0)); //v0 is the vertex 0 of t
702  m_node[(unsigned int)vn].setEdge(an0);
703  m_node[(unsigned int)NodeId(t, 0)].setEdge(an0);
704  m_line[(unsigned int)an0].Polygons(t, t1);
705 
706  //4. Create a new edge an1 that connects the vertex vn and v1 and
707  // has t1 and t2 as triangles thats shares the edge.
708  int32_t an1 = m_lline++;
709  m_line[(unsigned int)an1].Nodes(vn, NodeId(t, 1)); //v1 is the vertex 1 of t
710  m_node[(unsigned int)vn].setEdge(an1);
711  m_node[(unsigned int)NodeId(t, 1)].setEdge(an1);
712  m_line[(unsigned int)an1].Polygons(t1, t2);
713 
714  //5. Creates a new wdge an2 that connects the vertex vn and v2 and
715  // has t2 and t as triangles that shares the edge.
716  int32_t an2 = m_lline++;
717  m_line[(unsigned int)an2].Nodes(vn, NodeId(t, 2)); //v2 is the vertex 2 of t
718  m_node[(unsigned int)vn].setEdge(an2);
719  m_node[(unsigned int)NodeId(t, 2)].setEdge(an2);
720  m_line[(unsigned int)an2].Polygons(t2, t);
721 
722  //6. Swap triangle t for t1 on edge a0,
723  int32_t a0 = ExchangePolygon(t, t1, 0); // returns edge 0 of t
724 
725  //7. Defines the edges of t1 as an0, a0 and an1,
726  m_triang[(unsigned int)t1].setEdges(an0, a0, an1);
727 
728  //8. Swap the triangle t for t2 in edge a1,
729  int32_t a1 = ExchangePolygon(t, t2, 1); // returns edge 1 of t
730 
731  //9. Defines edges of t2 as an1, a1 and an2,
732  m_triang[(unsigned int)t2].setEdges(an1, a1, an2);
733 
734  //10. Defines edges of t as an2, a2 and an0,
735  int32_t a2 = m_triang[(unsigned int)t].LineAtEdge(2);
736  m_triang[(unsigned int)t].setEdges(an2, a2, an0);
737 
738  //Define lines to be tested
739  testLines[0] = a0;
740  testLines[1] = a1;
741  testLines[2] = a2;
742  testLines[3] = an0;
743  testLines[4] = an1;
744  testLines[5] = an2;
745 
746  return true;
747 }
748 
749 
750 int32_t te::mnt::TINGeneration::DuplicateTriangle(int32_t t, short n, int32_t v, int32_t* testLines)
751 {
752  // Is to triangle containing whose nth edge is an edge
753  // next the sample s(n � {0,1,2}). Then edge connects vn and vj vertices,
754  // aj edge connects the vertices vj and vk and ak edge connects
755  // vk and vn vertices, and j is the rest of division of n+ 1 for 3
756  // and k the rest of division n+2 by 3 .
757 
758  int32_t lineids[3];
759  m_triang[(unsigned int)t].LinesId(lineids);
760 
761  int32_t an = lineids[n];
762  int32_t aj = lineids[(n + 1) % 3];
763  int32_t ak = lineids[(n + 2) % 3];
764  int32_t vn = NodeId(t, n);
765 
766  testLines[0] = aj;
767  testLines[1] = ak;
768 
769  // 1. Create the vertice v with data of sample s,
770  // 2. Definen the triangle tv that shares edge an with t,
771  int32_t tv;
772  if (m_line[(unsigned int)an].getLeftPolygon() == t)
773  tv = m_line[(unsigned int)an].getRightPolygon();
774  else if (m_line[(unsigned int)an].getRightPolygon() == t)
775  tv = m_line[(unsigned int)an].getLeftPolygon();
776  else{
777  return -1;
778  }
779 
780  // 3. Defines vertice vop of triangleo t that is not connected to an,
781  int32_t vop = NodeId(t, (n + 2) % 3);
782 
783  // 4. Create new triangle t1,
784  int32_t t1 = m_ltriang++;
785  if (t1 > (int32_t)m_triangsize)
786  return -1;
787 
788  // 5. Create new edge an0 that connects the vertice v and vn and
789  // has t1 and tv as triangles that shares the edge.
790  int32_t an0 = m_lline++;
791  if (an0 > (int32_t)m_linesize)
792  return -1;
793 
794  m_line[(unsigned int)an0].Nodes(v, vn);
795  m_node[(unsigned int)v].setEdge(an0);
796  m_node[(unsigned int)vn].setEdge(an0);
797  m_line[(unsigned int)an0].Polygons(t1, tv);
798 
799  testLines[2] = an;
800  testLines[3] = an0;
801 
802  // 6. Create a new edge an1 that connects the vertices v and vop and
803  // has t and t1 as triangles that shares the edge.
804  int32_t an1 = m_lline++;
805  if (an1 > (int32_t)m_linesize)
806  return -1;
807 
808  m_line[(unsigned int)an1].Nodes(v, vop);
809  m_node[(unsigned int)v].setEdge(an1);
810  m_node[(unsigned int)vop].setEdge(an1);
811  m_line[(unsigned int)an1].Polygons(t, t1);
812 
813  testLines[4] = an1;
814 
815  // 7. Modifies the edge an to connect vertice v instead of vn,
816  m_node[(unsigned int)vn].removeEdge(an);
817  m_node[(unsigned int)v].setEdge(an);
818  m_line[(unsigned int)an].ExchangeNode(vn, v);
819 
820  // 8. Defines the edges of t as an, aj and an1,
821  m_triang[(unsigned int)t].setEdges(an, aj, an1);
822 
823  // 9. Modifies edge ak to shares triangle t1 instead of t,
824  m_line[(unsigned int)ak].ExchangePolygon(t, t1);
825 
826  // 10. Defines edges of t1 as an0, an1 and ak,
827  m_triang[(unsigned int)t1].setEdges(an0, an1, ak);
828 
829  return an0;
830 }
831 
832 bool te::mnt::TINGeneration::DupNeighTriangle(int32_t tv, int32_t an0, short, int32_t v, int32_t *testLines)
833 {
834  // 11.1. Create new triangle t2,
835  int32_t t2 = m_ltriang++;
836  if (t2 > (int32_t)m_triangsize)
837  return false;
838  // 11.2. Defines edge av of triangle tv that contains vertex vn
839  // (obs: there is only an edge because the other was modified),
840  int32_t vn = m_line[(unsigned int)an0].getNodeTo(); //Due to assembly, dangerous
841  int32_t lineids[3];
842  m_triang[(unsigned int)tv].LinesId(lineids);
843  unsigned short i;
844  for (i = 0; i < 3; i++)
845  {
846  if (lineids[i] >(int32_t)m_linesize)
847  return false;
848  if ((m_line[(unsigned int)lineids[i]].getNodeFrom() == vn) ||
849  (m_line[(unsigned int)lineids[i]].getNodeTo() == vn))
850  break;
851  }
852  if (i == 3){
853  return false;
854  }
855  int32_t av = lineids[i];
856 
857  testLines[0] = av;
858 
859  // 11.3. Defines the other edge tv as av1 and av2.
860  int32_t av1 = lineids[(i + 1) % 3];
861  int32_t av2 = lineids[(i + 2) % 3];
862 
863  testLines[1] = av1;
864 
865  // 11.4. Defines the vertex vvo connect to vn by edge av,
866  int32_t vvo;
867  if (m_line[(unsigned int)av].getNodeFrom() == vn)
868  vvo = m_line[(unsigned int)av].getNodeTo();
869  else
870  vvo = m_line[(unsigned int)av].getNodeFrom();
871 
872  // 11.5. Create new wdge an2 that connects vertex v and vvo and
873  // there are t and t2 as triangles that shares the edge.
874  int32_t an2 = m_lline++;
875  if (an2 > (int32_t)m_linesize)
876  return false;
877  m_line[(unsigned int)an2].Nodes(v, vvo);
878  m_line[(unsigned int)an2].Polygons(tv, t2);
879 
880  // 11.6. Swap the triangle tv by t2 in edge av,
881  m_line[(unsigned int)av].ExchangePolygon(tv, t2);
882 
883  // 11.7. Swap the triangle tv by t2 in edge an0,
884  m_line[(unsigned int)an0].ExchangePolygon(tv, t2);
885 
886  // 11.8. Defines edges of tv as an2, av1 and av2.
887  m_triang[(unsigned int)tv].setEdges(an2, av1, av2);
888 
889  // 11.9. Defines edges of t2 as an0, av and an2,
890  m_triang[(unsigned int)t2].setEdges(an0, av, an2);
891 
892  return true;
893 }
894 
895 bool te::mnt::TINGeneration::TestDelaunay(int32_t tri1Id, int32_t tri2Id, int32_t tri3Id)
896 {
897  if (tri1Id == -1)
898  return false;
899 
900  int32_t nids[3];
901  unsigned short j;
902 
903  if (!NeighborsId(tri1Id, nids))
904  return false;
905  for (j = 0; j < 3; j++)
906  if ((nids[j] != tri2Id) && (nids[j] != tri3Id))
907  break;
908  if (j == 3)
909  return false;
910  if (IsNeighborOnIsoOrBreakline(tri1Id, j) == false)
911  TestDelaunay(tri1Id, (short)j);
912 
913  if (!NeighborsId(tri2Id, nids))
914  return false;
915  for (j = 0; j < 3; j++)
916  if ((nids[j] != tri1Id) && (nids[j] != tri3Id))
917  break;
918  if (j == 3)
919  return false;
920  if (IsNeighborOnIsoOrBreakline(tri2Id, j) == false)
921  TestDelaunay(tri2Id, (short)j);
922 
923  if (!NeighborsId(tri3Id, nids))
924  return false;
925  for (j = 0; j < 3; j++)
926  if ((nids[j] != tri1Id) && (nids[j] != tri2Id))
927  break;
928  if (j == 3)
929  return false;
930  if (IsNeighborOnIsoOrBreakline(tri3Id, j) == false)
931  TestDelaunay(tri3Id, (short)j);
932 
933  return true;
934 }
935 
936 
937 bool te::mnt::TINGeneration::TestDelaunay(int32_t tri1Id, int32_t tri2Id, int32_t tri3Id, int32_t tri4Id)
938 {
939  if (tri1Id == -1)
940  return false;
941 
942  int32_t nids[3];
943  unsigned short j;
944 
945  if (!NeighborsId(tri1Id, nids))
946  return false;
947  for (j = 0; j < 3; j++)
948  if ((nids[j] != tri2Id) && (nids[j] != tri3Id) && (nids[j] != tri4Id))
949  break;
950  if (j == 3)
951  return false;
952  if (IsNeighborOnIsoOrBreakline(tri1Id, j) == false)
953  TestDelaunay(tri1Id, (short)j);
954 
955  if (!NeighborsId(tri2Id, nids))
956  return false;
957  for (j = 0; j < 3; j++)
958  if ((nids[j] != tri1Id) && (nids[j] != tri3Id) && (nids[j] != tri4Id))
959  break;
960  if (j == 3)
961  return false;
962  if (IsNeighborOnIsoOrBreakline(tri2Id, j) == false)
963  TestDelaunay(tri2Id, (short)j);
964 
965  if (!NeighborsId(tri3Id, nids))
966  return false;
967  for (j = 0; j < 3; j++)
968  if ((nids[j] != tri1Id) && (nids[j] != tri2Id) && (nids[j] != tri4Id))
969  break;
970  if (j == 3)
971  return false;
972  if (IsNeighborOnIsoOrBreakline(tri3Id, j) == false)
973  TestDelaunay(tri3Id, (short)j);
974 
975  if (!NeighborsId(tri4Id, nids))
976  return false;
977  for (j = 0; j < 3; j++)
978  if ((nids[j] != tri1Id) && (nids[j] != tri2Id) && (nids[j] != tri3Id))
979  break;
980  if (j == 3)
981  return false;
982  if (IsNeighborOnIsoOrBreakline(tri4Id, j) == false)
983  TestDelaunay(tri4Id, (short)j);
984 
985  return true;
986 }
987 
988 
990 {
991  if (linId == -1)
992  return false;
993  int32_t tv = m_line[(unsigned int)linId].getLeftPolygon();
994  if (tv == -1)
995  return false;
996 
997  int32_t linids[3];
998  if (!m_triang[(unsigned int)tv].LinesId(linids))
999  return false;
1000 
1001  unsigned short j;
1002  for (j = 0; j < 3; j++)
1003  if (linids[j] == linId)
1004  break;
1005  if (j != 3)
1006  return TestDelaunay(tv, (short)j);
1007  else
1008  return false;
1009 }
1010 
1011 
1012 bool te::mnt::TINGeneration::TestDelaunay(int32_t triId, short nviz)
1013 {
1014  if (triId == -1)
1015  return false;
1016  double xc, yc, xaux, yaux, raio2, dist2,
1017  xo, yo;
1018  int32_t nodid, neighids[3];
1022  unsigned short i;
1023  double minx = std::numeric_limits< float >::max(),
1024  miny = std::numeric_limits< float >::max();
1025 
1026  // Retrieve neighbour triangle (tviz) pointer
1027  if (!NeighborsId(triId, neighids))
1028  return false;
1029  if (neighids[nviz] == -1)
1030  return false;
1031 
1032  // Retrieve line of triangle common to neighbor triangle
1033  int32_t linid = m_triang[(unsigned int)triId].LineAtEdge((unsigned short)nviz);
1034  if (linid == -1 || linid > (int32_t)m_linesize)
1035  return false;
1036 
1037  // Define base triangle (tri) center point
1038  TrianglePoints(triId, vert);
1039 
1040  // Find opposite point to base triangle (tri) inside neighbour (tviz)
1041  nodid = OppositeNode(neighids[nviz], linid);
1042  if (nodid == -1)
1043  return false;
1044  if (nodid > (int32_t) m_nodesize)
1045  return false;
1046  for (i = 0; i < 3; i++)
1047  {
1048  if (vert[i].getX() < minx)
1049  minx = vert[i].getX();
1050  if (vert[i].getY() < miny)
1051  miny = vert[i].getY();
1052  }
1053  if ((minx < std::numeric_limits< float >::max()) && (miny < std::numeric_limits< float >::max()))
1054  {
1055  for (i = 0; i < 3; i++)
1056  {
1057  vert[i].setX(vert[i].getX() - minx);
1058  vert[i].setY(vert[i].getY() - miny);
1059  }
1060  xo = m_node[(unsigned int)nodid].getNPoint().getX() - minx;
1061  yo = m_node[(unsigned int)nodid].getNPoint().getY() - miny;
1062  }
1063  else
1064  {
1065  xo = m_node[(unsigned int)nodid].getNPoint().getX();
1066  yo = m_node[(unsigned int)nodid].getNPoint().getY();
1067  }
1068 
1069  if (findCenter(vert, &xc, &yc) == false)
1070  {
1071  return false;
1072  }
1073 
1074  // Calculate base triangle (tri) radius
1075  xaux = xc - vert[0].getX();
1076  yaux = yc - vert[0].getY();
1077  raio2 = xaux * xaux + yaux * yaux;
1078 
1079  // Calculate distance from opposite point (tviz) to center point (tri)
1080  xaux = xc - xo;
1081  yaux = yc - yo;
1082  dist2 = xaux * xaux + yaux * yaux;
1083  float fr = (float)sqrt(raio2);
1084  float fd = (float)sqrt(dist2);
1085 
1086  if (fr <= fd){
1087  return false;
1088  }
1089 
1090  // If not, change edge between tri and ntri
1091  return UpdateTriangles(triId, neighids[nviz], linid);
1092 }
1093 
1094 
1095 bool te::mnt::TINGeneration::UpdateTriangles(int32_t t, int32_t tv, int32_t ai)
1096 {
1097  //Be the triangle t whose ith edge there is the edge
1098  //that you want to change (i � { 0,1,2 } ). The edge ai connects the
1099  //vertices vi and vj , the aj edge connects the vertices vj and vk and
1100  //ak edge connects vk vertices and vi , and j is the rest of the division
1101  //of i+1 for 3 and k the rest of the i+2 division by 3.
1102 
1103  if (tv == -1)
1104  return false;
1105 
1106  int32_t tEdges[3];
1107  if (!m_triang[(unsigned int)t].LinesId(tEdges))
1108  return false;
1109 
1110  int32_t nodeIds[3];
1111  if (!NodesId(t, nodeIds))
1112  return false;
1113 
1114  unsigned short i;
1115  for (i = 0; i < 3; i++)
1116  if (tEdges[i] == ai)
1117  break;
1118 
1119  if (i == 3) return false;
1120 
1121  int32_t aj = tEdges[(i + 1) % 3];
1122  int32_t ak = tEdges[(i + 2) % 3];
1123 
1124  int32_t vi = nodeIds[i];
1125  int32_t vj = nodeIds[(i + 1) % 3];
1126  int32_t vk = nodeIds[(i + 2) % 3];
1127 
1128  // Be the triangle tv that sharing the edge ai with t. The vertice of
1129  // tv that is not connected by edge ai is the vertice vn. Others
1130  // edges of triangle tv are am that connects edge vi and vn and the
1131  // edge an connects vertices vn and vj.
1132 
1133  int32_t vn = OppositeNode(tv, ai);
1134  if (tv == -1)
1135  return false;
1136 
1137  int32_t tvEdges[3];
1138  if (!m_triang[(unsigned int)tv].LinesId(tvEdges))
1139  return false;
1140 
1141  int32_t an = 0;
1142  unsigned short j;
1143  for (j = 0; j < 3; j++)
1144  {
1145  if (tvEdges[j] == ai)
1146  continue;
1147 
1148  if (m_line[(unsigned int)tvEdges[j]].getNodeFrom() == vn)
1149  {
1150  if (m_line[(unsigned int)tvEdges[j]].getNodeTo() == vi)
1151  {}
1152  else if (m_line[(unsigned int)tvEdges[j]].getNodeTo() == vj)
1153  an = tvEdges[j];
1154  else{
1155  return false;
1156  }
1157  }
1158  else if (m_line[(unsigned int)tvEdges[j]].getNodeTo() == vn)
1159  {
1160  if (m_line[(unsigned int)tvEdges[j]].getNodeFrom() == vi)
1161  {}
1162  else if (m_line[(unsigned int)tvEdges[j]].getNodeFrom() == vj)
1163  an = tvEdges[j];
1164  else{
1165  return false;
1166  }
1167  }
1168  }
1169 
1170  // 1. If the line segment formed by connecting vertice vk of
1171  // triangle t to vertice vn of tv intersects the edge ai, do:
1172  te::gm::Point ptvk = m_node[(unsigned int)vk].getNPoint();
1173  te::gm::Point ptvn = m_node[(unsigned int)vn].getNPoint();
1174  te::gm::Point ptvi = m_node[(unsigned int)vi].getNPoint();
1175  te::gm::Point ptvj = m_node[(unsigned int)vj].getNPoint();
1176 
1177  if (!segIntersect(ptvi, ptvj, ptvk, ptvn))
1178  return false;
1179 
1180  // 1.1. Swap in edge ai the vertice vi by vertice vk and the
1181  // vertice vj pelo vertice vn.
1182  if (m_line[(unsigned int)ai].getNodeTo() == vi)
1183  {
1184  m_node[(unsigned int)vi].removeEdge(ai);
1185  m_node[(unsigned int)vk].setEdge(ai);
1186  m_node[(unsigned int)vn].setEdge(ai);
1187  m_line[(unsigned int)ai].setNodeTo(vk);
1188  m_line[(unsigned int)ai].setNodeFrom(vn); // this is vj
1189  }
1190  else if (m_line[(unsigned int)ai].getNodeTo() == vj)
1191  {
1192  m_node[(unsigned int)vj].removeEdge(ai);
1193  m_node[(unsigned int)vn].setEdge(ai);
1194  m_node[(unsigned int)vk].setEdge(ai);
1195  m_line[(unsigned int)ai].setNodeTo(vn);
1196  m_line[(unsigned int)ai].setNodeFrom(vk); // this is vi
1197  }
1198 
1199  std::vector<int32_t>::iterator it;
1200  it = std::find(m_node[(unsigned int)vi].m_edge.begin(), m_node[(unsigned int)vi].m_edge.end(), ai);
1201  if (it != m_node[(unsigned int)vi].m_edge.end())
1202  {
1203  m_node[(unsigned int)vi].m_edge.erase(it);
1204  m_node[(unsigned int)vi].setEdge(ak);
1205  }
1206 
1207  it = std::find(m_node[(unsigned int)vj].m_edge.begin(), m_node[(unsigned int)vj].m_edge.end(), ai);
1208  if (it != m_node[(unsigned int)vj].m_edge.end())
1209  {
1210  m_node[(unsigned int)vj].m_edge.erase(it);
1211  m_node[(unsigned int)vj].setEdge(aj);
1212  }
1213 
1214  // 1.2. Swap in edge an the triangle tv by triangle t.
1215  if (m_line[(unsigned int)an].getRightPolygon() == tv)
1216  m_line[(unsigned int)an].setRightPolygon(t);
1217  else
1218  m_line[(unsigned int)an].setLeftPolygon(t);
1219 
1220  // 1.3. Swap in edge ak the triangle t by triangle tv.
1221  if (m_line[(unsigned int)ak].getRightPolygon() == t)
1222  m_line[(unsigned int)ak].setRightPolygon(tv);
1223  else
1224  m_line[(unsigned int)ak].setLeftPolygon(tv);
1225 
1226  // 1.4. Swap in triangle t the edge ai by edge an and the
1227  // edge ak by edge ai.
1228  for (i = 0; i < 3; i++)
1229  if (tEdges[i] == ai)
1230  break;
1231  if (i < 3) tEdges[i] = an;
1232  tEdges[(i + 2) % 3] = ai;
1233  m_triang[(unsigned int)t].setEdges((int32_t)tEdges[0], (int32_t)tEdges[1], (int32_t)tEdges[2]);
1234 
1235  // 1.5. Swap in triangle tv the edge aiby edge ak
1236  for (i = 0; i < 3; i++)
1237  if (tvEdges[i] == ai)
1238  break;
1239  if (i < 3) tvEdges[i] = ak;
1240 
1241  // and the edge an by edge ai.
1242  for (i = 0; i < 3; i++)
1243  if (tvEdges[i] == an)
1244  break;
1245  if (i < 3) tvEdges[i] = ai;
1246 
1247  m_triang[(unsigned int)tv].setEdges((int32_t)tvEdges[0], (int32_t)tvEdges[1], (int32_t)tvEdges[2]);
1248 
1249  return true;
1250 }
1251 
1252 int32_t te::mnt::TINGeneration::ExchangePolygon(int32_t triangId, int32_t newPolyId, unsigned short edge)
1253 {
1254  int32_t linId;
1255 
1256  linId = m_triang[(unsigned int)triangId].LineAtEdge(edge);
1257  if (linId == -1)
1258  return false;
1259  if (linId > (int32_t)m_linesize)
1260  return false;
1261  m_line[(unsigned int)linId].ExchangePolygon(triangId, newPolyId);
1262 
1263  return linId;
1264 }
1265 
1266 
1268 {
1269  int32_t nid0, nid1;
1270 
1271  if ((m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getType() == Sample) ||
1272  (m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getType() == Sample))
1273  // If sample point
1274  return false;
1275 
1276  if ((m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getType() > Last) ||
1277  (m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getType() > Last))
1278  // If breakline point
1279  return false;
1280 
1281  nid0 = m_line[(unsigned int)linid].getNodeFrom();
1282  if (nid0 > m_line[(unsigned int)linid].getNodeTo())
1283  {
1284  nid0 = m_line[(unsigned int)linid].getNodeTo();
1285  nid1 = m_line[(unsigned int)linid].getNodeFrom();
1286  }
1287  else
1288  nid1 = m_line[(unsigned int)linid].getNodeTo();
1289 
1290  if (m_node[(unsigned int)nid0].getType() == Last)
1291  // If first point is last point of line
1292  return false;
1293 
1294  if (m_node[(unsigned int)nid1].getType() == First)
1295  // If last point is first point of line
1296  return false;
1297 
1298  // Search next non-deleted point
1299  if (NextNode(nid0) != nid1)
1300  return false;
1301 
1302  return true;
1303 }
1304 
1305 
1307 {
1308  int32_t nid0, nid1;
1309 
1310  if ((m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getType() == Sample) ||
1311  (m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getType() == Sample))
1312  // If sample point
1313  return false;
1314 
1315  if ((m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getType() < Breaklinenormal) ||
1316  (m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getType() < Breaklinenormal))
1317  // If breakline point
1318  return false;
1319 
1320  nid0 = m_line[(unsigned int)linid].getNodeFrom();
1321  if (nid0 > m_line[(unsigned int)linid].getNodeTo())
1322  {
1323  nid0 = m_line[(unsigned int)linid].getNodeTo();
1324  nid1 = m_line[(unsigned int)linid].getNodeFrom();
1325  }
1326  else
1327  nid1 = m_line[(unsigned int)linid].getNodeTo();
1328 
1329  if (m_node[(unsigned int)nid0].getType() == Breaklinelast)
1330  // If first point is last point of line
1331  return false;
1332 
1333  if (m_node[(unsigned int)nid1].getType() == Breaklinefirst)
1334  // If last point is first point of line
1335  return false;
1336 
1337  // Search next non-deleted point
1338  if (NextNode(nid0) != nid1)
1339  return false;
1340 
1341  return true;
1342 }
1343 
1344 
1345 
1346 bool te::mnt::TINGeneration::IsNeighborOnIsoOrBreakline(int32_t triId, unsigned short nviz)
1347 {
1348  int32_t linid;
1349 
1350  // Retrieve line of triangle common to neighbor triangle
1351  linid = m_triang[(unsigned int)triId].LineAtEdge(nviz);
1352  if (IsIsolineSegment(linid))
1353  return true;
1354  if (IsBreaklineSegment(linid))
1355  return true;
1356  return false;
1357 }
1358 
1360 {
1361  int32_t triangid, contr = 0, npoly = -1;
1362 
1363  te::common::TaskProgress task("Creating Delaunay...", te::common::TaskProgress::UNDEFINED, (int)m_ltriang);
1364 
1365  for (triangid = 0; triangid < m_ltriang; triangid++)
1366  {
1367  if (!task.isActive())
1368  return false;
1369  task.pulse();
1370 
1371  if (triangid > npoly)
1372  npoly = triangid;
1373  else
1374  return false;
1375 
1376  if (!GenerateDelaunay(npoly, npoly, contr))
1377  {
1378  return false;
1379  }
1380  }
1381 
1382  return true;
1383 }
1384 
1385 
1386 bool te::mnt::TINGeneration::GenerateDelaunay(int32_t nt, int32_t ntbase, int32_t contr)
1387 {
1388  int32_t aux, neighids[3];
1389  short j;
1390 
1391  contr++;
1392  if (contr > m_ltriang)
1393  {
1394  return false;
1395  }
1396 
1397  for (j = 0; j < 3; j++)
1398  {
1399  NeighborsId(nt, neighids);
1400  aux = neighids[(unsigned int)j];
1401  if (aux == nt)
1402  continue;
1403 
1404  // Test with each neighbor, if it exists
1405  if (aux == -1)
1406  continue;
1407  if (TestDelaunay(nt, j))
1408  {
1409  // If changed,
1410  if (ntbase > aux)
1411  // Se numero menor que base
1412  GenerateDelaunay(aux, ntbase, contr);
1413 
1414  //Return current neighbor
1415  j = -1;
1416  }
1417  }
1418 
1419  return true;
1420 }
1421 
1422 
1424 {
1425  std::vector<int32_t> lids;
1426  int32_t nid, linid;
1427  int32_t rtri, ltri;
1428  int32_t nids[4] = { 0, 0, 0, 0 }, tnids[3] = { 0, 0, 0 };
1429  int32_t trids[4] = {0, 0, 0, 0};
1430  unsigned short j, modified;
1431 
1432  int i = 0;
1433  for (nid = 1; nid < (int32_t)m_node.size(); nid++)
1434  {
1435  if (m_node[(unsigned int)nid].getType() != Box &&
1436  m_node[(unsigned int)nid].getType() != Deletednode &&
1437  m_node[(unsigned int)nid].getType() != Sample)
1438  continue;
1439  if (m_node[(unsigned int)nid].getZ() < m_nodatavalue)
1440  // If not fake sample point
1441  continue;
1442  nids[i++] = nid;
1443  if (i == 4)
1444  break;
1445  }
1446 
1447  modified = 0;
1448  for (i = 0; i < 4; i++)
1449  {
1450  if (!NodeLines(nids[(unsigned int)i], lids))
1451  continue;
1452  for (size_t ii = 0; ii < lids.size(); ii++)
1453  {
1454  linid = lids[ii];
1455  rtri = m_line[(unsigned int)linid].getRightPolygon();
1456  ltri = m_line[(unsigned int)linid].getLeftPolygon();
1457  if ((rtri != -1) && (ltri != -1))
1458  {
1459  NeighborsId(rtri, tnids);
1460  for (j = 0; j < 3; j++)
1461  if (tnids[j] == -1)
1462  break;
1463  if (j != 3)
1464  continue;
1465  if (UpdateTriangles(rtri, ltri, linid))
1466  modified = 1;
1467  }
1468  else
1469  {
1470  if (((m_line[(unsigned int)linid].getNodeFrom() == nids[(unsigned int)i]) &&
1471  ((m_line[(unsigned int)linid].getNodeTo() == nids[(unsigned int)(i + 1) % 4]) ||
1472  (m_line[(unsigned int)linid].getNodeTo() == nids[(unsigned int)(i + 2) % 4]) ||
1473  (m_line[(unsigned int)linid].getNodeTo() == nids[(unsigned int)(i + 3) % 4]))) ||
1474  ((m_line[(unsigned int)linid].getNodeTo() == nids[(unsigned int)i]) &&
1475  ((m_line[(unsigned int)linid].getNodeFrom() == nids[(unsigned int)(i + 1) % 4]) ||
1476  (m_line[(unsigned int)linid].getNodeFrom() == nids[(unsigned int)(i + 2) % 4]) ||
1477  (m_line[(unsigned int)linid].getNodeFrom() == nids[(unsigned int)(i + 3) % 4]))))
1478  {
1479  if (rtri == -1)
1480  trids[(unsigned int)i] = ltri;
1481  else
1482  trids[(unsigned int)i] = rtri;
1483  }
1484  }
1485  }
1486  lids.clear();
1487  if ((i == 3) && (modified))
1488  {
1489  i = -1;
1490  modified = 0;
1491  }
1492  }
1493  for (i = 0; i < 4; i++)
1494  {
1495  m_triang[(unsigned int)trids[(unsigned int)i]].LinesId(tnids);
1496  for (j = 0; j < 3; j++)
1497  {
1498  rtri = m_line[(unsigned int)tnids[j]].getRightPolygon();
1499  ltri = m_line[(unsigned int)tnids[j]].getLeftPolygon();
1500  if ((rtri != -1) && (ltri != -1))
1501  UpdateTriangles(rtri, ltri, tnids[j]);
1502  }
1503  }
1504  return true;
1505 }
1506 
1507 
1509 {
1510  int iter = 0;
1511  for (;;)
1512  if (!TestIsolines(++iter))
1513  break;
1514 
1515  return true;
1516 }
1517 
1518 
1520 {
1521  int32_t linid1 = 0, lidaux, oldline,
1522  ntri,
1523  tnodid, vnodid;
1524  int32_t nid0, nid1, node, nidaux, nidaux1;
1525  int32_t vlins[3] = {-1, -1, -1};
1526  unsigned int i;
1527  std::vector<int32_t> lids;
1530  bool modified = false;
1531  std::vector<te::mnt::TinNode> p3dl;
1532  te::mnt::TinNode ptaux;
1533  std::vector<int32_t> snode;
1534 
1535  for (nid0 = 0; nid0 < m_lnode; nid0++)
1536  snode.push_back(0);
1537 
1538  std::string msg("Testing Isolines(");
1539  std::stringstream ss;
1540  ss << iter;
1541  msg += ss.str() + ")...";
1543 
1544  for (i = 0; i < m_linesize; i++)
1545  {
1546  if (!task.isActive())
1547  return false;
1548  task.pulse();
1549 
1550  if (m_line[i].getNodeFrom() == -1)
1551  continue;
1552  nid0 = m_line[i].getNodeFrom();
1553  if (nid0 > m_line[i].getNodeTo())
1554  {
1555  nid0 = m_line[i].getNodeTo();
1556  nid1 = m_line[i].getNodeFrom();
1557  }
1558  else
1559  nid1 = m_line[i].getNodeTo();
1560  if ((m_node[(unsigned int)nid0].getType() == Deletednode) || (m_node[(unsigned int)nid0].getType() > First))
1561  {
1562  //If deleted, last or sample point
1563  snode[(unsigned int)nid0] = 1;
1564  continue;
1565  }
1566  node = NextNode(nid0);
1567  if (node == nid1)
1568  snode[(unsigned int)nid0] = 1;
1569  }
1570 
1571  modified = false;
1572  for (nid0 = 0; nid0 < m_lnode; nid0++)
1573  {
1574  if ((m_node[(unsigned int)nid0].getType() == Deletednode) ||
1575  (m_node[(unsigned int)nid0].getType() > First))
1576  // If deleted, last or sample point
1577  continue;
1578 
1579  if (snode[(unsigned int)nid0] == 1)
1580  continue;
1581 
1582  // Find next non-deleted node
1583  nid1 = NextNode(nid0);
1584  if (nid1 == -1)
1585  continue;
1586  if ((m_node[(unsigned int)nid1].getType() != Normalnode) &&
1587  (m_node[(unsigned int)nid1].getType() != Last))
1588  {
1589  continue;
1590  }
1591 
1592  // Find triangle edge that intersects isoline segment
1593  NodeOppositeLines(nid0, lids);
1594  te::gm::Point pt0(m_node[(unsigned int)nid0].getNPoint());
1595  te::gm::Point pt1(m_node[(unsigned int)nid1].getNPoint());
1596  lidaux = -1;
1597  for (size_t ii = 0; ii < lids.size(); ii++)
1598  {
1599  linid1 = lids[ii];
1600  te::gm::Point ptl0(m_node[(unsigned int)m_line[(unsigned int)linid1].getNodeTo()].getNPoint());
1601  te::gm::Point ptl1(m_node[(unsigned int)m_line[(unsigned int)linid1].getNodeFrom()].getNPoint());
1602  if (segInterPoint(pt0, pt1, ptl0, ptl1, &ptf))
1603  {
1604  lids.clear();
1605  // Save first edge of triangulation that intersects isoline segment
1606  lidaux = linid1;
1607  break;
1608  }
1609  }
1610  if (lidaux == -1)
1611  {
1612  lids.clear();
1613  continue;
1614  }
1615 
1616  // Find triangle at opposite side of node, compared to one line
1617  ntri = -1;
1618  for (i = 0; i < 3; i++)
1619  {
1620  if (NodeId(m_line[(unsigned int)lidaux].getRightPolygon(), (short)i) == nid0)
1621  {
1622  ntri = m_line[(unsigned int)lidaux].getLeftPolygon();
1623  break;
1624  }
1625  if (NodeId(m_line[(unsigned int)lidaux].getLeftPolygon(), (short)i) == nid0)
1626  {
1627  ntri = m_line[(unsigned int)lidaux].getRightPolygon();
1628  break;
1629  }
1630  }
1631  if (ntri == -1)
1632  return false;
1633 
1634  tnodid = OppositeNode(m_line[(unsigned int)lidaux].getRightPolygon(), lidaux);
1635  vnodid = OppositeNode(m_line[(unsigned int)lidaux].getLeftPolygon(), lidaux);
1636  node = m_line[(unsigned int)lidaux].getNodeFrom();
1637  if (node > m_line[(unsigned int)lidaux].getNodeTo())
1638  {
1639  node = m_line[(unsigned int)lidaux].getNodeTo();
1640  nidaux = m_line[(unsigned int)lidaux].getNodeFrom();
1641  }
1642  else
1643  nidaux = m_line[(unsigned int)lidaux].getNodeTo();
1644  nidaux1 = NextNode(node);
1645 
1646  if ((tnodid == nid1) || (vnodid == nid1))
1647  {
1648  if (((m_node[(unsigned int)node].getType() != First) && (m_node[(unsigned int)node].getType() != Normalnode)) ||
1649  (nidaux1 != nidaux))
1650  {
1651  if (UpdateTriangles(m_line[(unsigned int)lidaux].getLeftPolygon(), m_line[(unsigned int)lidaux].getRightPolygon(), lidaux))
1652  {
1653  modified = true;
1654  continue;
1655  }
1656  }
1657  }
1658 
1659  ptaux.setNPoint(ptf);
1660  ptaux.setZ(m_node[(unsigned int)nid0].getZ());
1661  ptaux.setType(First);
1662  p3dl.push_back(ptaux);
1663 
1664  nidaux = nid0;
1665  oldline = lidaux;
1666  while (nidaux != nid1)
1667  {
1668  // Test if reached final isoline node
1669  m_triang[(unsigned int)ntri].LinesId(vlins);
1670  for (i = 0; i < 3; i++)
1671  {
1672  if (vlins[i] == oldline)
1673  continue;
1674  if ((m_line[(unsigned int)vlins[i]].getNodeTo() == nid1) ||
1675  (m_line[(unsigned int)vlins[i]].getNodeFrom() == nid1))
1676  {
1677  nidaux = nid1;
1678  break;
1679  }
1680  }
1681  if (nidaux == nid1)
1682  break;
1683 
1684  // Find intersection point between triangle edge and isoline segment
1685  for (i = 0; i < 3; i++)
1686  {
1687  if (vlins[i] == oldline)
1688  // If previous edge
1689  continue;
1690  linid1 = vlins[i];
1691  if (linid1 >= 0)
1692  {
1693  if ((m_line[static_cast<size_t>(linid1)].getNodeTo() == nid0) ||
1694  (m_line[static_cast<size_t>(linid1)].getNodeFrom() == nid0))
1695  continue;
1696  te::gm::Point ptl0(m_node[(unsigned int)m_line[(unsigned int)linid1].getNodeTo()].getNPoint());
1697  te::gm::Point ptl1(m_node[(unsigned int)m_line[(unsigned int)linid1].getNodeFrom()].getNPoint());
1698  if (segInterPoint(pt0, pt1, ptl0, ptl1, &pt))
1699  break;
1700  }
1701  }
1702  if (i == 3)
1703  {
1704  break;
1705  }
1706 
1707  // Insert intersected point to point list
1708  ptaux.setX(pt.getX());
1709  ptaux.setY(pt.getY());
1710  ptaux.setZ(m_node[(unsigned int)nid0].getZ());
1711  ptaux.setType(Normalnode);
1712  p3dl.push_back(ptaux);
1713 
1714  nidaux = m_line[(unsigned int)linid1].getNodeTo();
1715  oldline = linid1;
1716  if (m_line[(unsigned int)linid1].getLeftPolygon() == ntri)
1717  ntri = m_line[(unsigned int)linid1].getRightPolygon();
1718  else
1719  ntri = m_line[(unsigned int)linid1].getLeftPolygon();
1720 
1721  modified = true;
1722  }
1723 
1724  te::mnt::TinNode ptaux1 = p3dl.back();
1725  if (ptaux1.getType() == Normalnode)
1726  ptaux1.setType(Last);
1727  else if (ptaux1.getType() == First)
1728  ptaux1.setType(Sample);
1729 
1730  if (m_node[(unsigned int)nid0].getType() == First)
1731  m_node[(unsigned int)nid0].setType(Sample);
1732  else
1733  m_node[(unsigned int)nid0].setType(Last);
1734  if (m_node[(unsigned int)nid1].getType() == Normalnode)
1735  m_node[(unsigned int)nid1].setType(First);
1736  else
1737  m_node[(unsigned int)nid1].setType(Sample);
1738  }
1739 
1740  size_t npts = p3dl.size();
1741  if (npts == 0)
1742  {
1743  return modified;
1744  }
1745 
1746  if ((npts + m_lnode + 6) > m_nodesize)
1747  ReallocateVectors(npts + m_lnode + 6);
1748 
1749  for (size_t ii = 0; ii < p3dl.size(); ii++)
1750  {
1751  ptaux = p3dl[ii];
1752  node = ++m_lnode;
1753  if (node > (int32_t)m_nodesize)
1754  return false;
1755 
1756  m_node[(unsigned int)node].Init(ptaux.getNPoint(), ptaux.getType());
1757  InsertNode(node, 0);
1758  }
1759 
1760  return modified;
1761 }
1762 
1764 {
1765  int32_t triangid, neighids[3];
1766  short j;
1767 
1768  te::common::TaskProgress task("Creating Minimum Angle...", te::common::TaskProgress::UNDEFINED, (int)m_ltriang);
1769 
1770  for (triangid = 0; triangid < m_ltriang; triangid++)
1771  {
1772  if (!task.isActive())
1773  return false;
1774  task.pulse();
1775 
1776  NeighborsId(triangid, neighids);
1777  for (j = 0; j < 3; j++)
1778  {
1779  if (TestAngleBetweenNormals(triangid, j))
1780  {
1781  if (neighids[j] < triangid)
1782  {
1783  triangid = neighids[j] - 1;
1784  j = 3;
1785  }
1786  else
1787  {
1788  j = -1;
1789  }
1790  }
1791  }
1792  }
1793 
1794  return true;
1795 }
1796 
1798 {
1799  double nvector1[3], nvector2[3], cos1, cos2;
1800  int32_t nodid1, nodid2, linid, neighids[3], i;
1804 
1808 
1809  if (triId == -1)
1810  return false;
1811 
1812  // Retrieve neighbour triangle (tviz) pointer
1813  NeighborsId(triId, neighids);
1814  if (neighids[nviz] == -1)
1815  return false;
1816 
1817  // Retrieve line of triangle common to neighbor triangle
1818  linid = m_triang[(unsigned int)triId].LineAtEdge((unsigned short)nviz);
1819  if (linid > (int32_t)m_linesize)
1820  return false;
1821  nodid1 = m_line[(unsigned int)linid].getNodeTo();
1822  if (nodid1 > m_line[(unsigned int)linid].getNodeFrom())
1823  {
1824  nodid1 = m_line[(unsigned int)linid].getNodeFrom();
1825  nodid2 = m_line[(unsigned int)linid].getNodeTo();
1826  }
1827  else
1828  nodid2 = m_line[(unsigned int)linid].getNodeFrom();
1829  if ((m_node[(unsigned int)nodid1].getZ() >= m_nodatavalue) || (m_node[(unsigned int)nodid2].getZ() >= m_nodatavalue))
1830  return false;
1831 
1832  TrianglePoints(triId, vert1);
1833  TrianglePoints(neighids[nviz], vert2);
1834  for (i = 0; i < 3; i++)
1835  if ((vert1[i].getZ() >= m_nodatavalue) || (vert2[i].getZ() >= m_nodatavalue))
1836  return false;
1837 
1838  // Define base triangle (tri) normal vector
1839  triangleNormalVector(vert1, nvector1);
1840  normalizeVector(nvector1);
1841 
1842  // Define opposite triangle (nviz) normal vector
1843  triangleNormalVector(vert2, nvector2);
1844  normalizeVector(nvector2);
1845 
1846  // Calculate cosine between triangles
1847  cos1 = nvector1[0] * nvector2[0] + nvector1[1] * nvector2[1] + nvector1[2] * nvector2[2];
1848 
1849  // Find opposite point to common edge on base triangle
1850  nodid1 = OppositeNode(triId, linid);
1851 
1852  // Find opposite point to common edge on neighbor triangle
1853  nodid2 = OppositeNode(neighids[nviz], linid);
1854 
1855  // Fill in first possible triangle points
1856  vert1[0].setX(m_node[(unsigned int)nodid1].getX());
1857  vert1[0].setY(m_node[(unsigned int)nodid1].getY());
1858  vert1[0].setZ(m_node[(unsigned int)nodid1].getZ());
1859  vert1[1].setX(m_node[(unsigned int)nodid2].getX());
1860  vert1[1].setY(m_node[(unsigned int)nodid2].getY());
1861  vert1[1].setZ(m_node[(unsigned int)nodid2].getZ());
1862  vert1[2].setX(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getX());
1863  vert1[2].setY(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getY());
1864  vert1[2].setZ(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getZ());
1865 
1866  // Fill in second possible triangle points
1867  vert2[0].setX(m_node[(unsigned int)nodid1].getX());
1868  vert2[0].setY(m_node[(unsigned int)nodid1].getY());
1869  vert2[0].setZ(m_node[(unsigned int)nodid1].getZ());
1870  vert2[1].setX(m_node[(unsigned int)nodid2].getX());
1871  vert2[1].setY(m_node[(unsigned int)nodid2].getY());
1872  vert2[1].setZ(m_node[(unsigned int)nodid2].getZ());
1873  vert2[2].setX(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getX());
1874  vert2[2].setY(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getY());
1875  vert2[2].setZ(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getZ());
1876 
1877  // Define first possible triangle normal vector
1878  triangleNormalVector(vert1, nvector1);
1879  normalizeVector(nvector1);
1880 
1881  // Define second possible triangle normal vector
1882  triangleNormalVector(vert2, nvector2);
1883  normalizeVector(nvector2);
1884 
1885  // Calculate cosine between triangles
1886  cos2 = nvector1[0] * nvector2[0] + nvector1[1] * nvector2[1] + nvector1[2] * nvector2[2];
1887 
1888  // If new triangles normal vector angle difference smaller than old triangle's
1889  if (cos2 > cos1)
1890  return UpdateTriangles(triId, neighids[nviz], linid);
1891 
1892  return false;
1893 }
1894 
1895 
1897 {
1898 
1899  if (m_inDsetName_break.empty())
1900  return 0;
1901 
1902  std::unique_ptr<te::da::DataSet> inDset;
1903  size_t nbreak = mpt.getNumGeometries();
1904 
1905  inDset = m_inDsrc_break->getDataSet(m_inDsetName_break);
1906 
1907  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
1908 
1909  inDset->moveBeforeFirst();
1910 
1911  while (inDset->moveNext())
1912  {
1913  std::unique_ptr<te::gm::Geometry> gin = inDset->getGeometry(geo_pos);
1914  geostype = gin.get()->getGeometryType();
1915 
1916  if (geostype == "LineString")
1917  {
1918  te::gm::LineString *l = dynamic_cast<te::gm::LineString*>(gin.get());
1919 
1921  breaklines.add(dynamic_cast<te::gm::Geometry*>(ls));
1922  nbreak += ls->size();
1923  }
1924  if (geostype == "MultiLineString")
1925  {
1926  te::gm::MultiLineString *g = dynamic_cast<te::gm::MultiLineString*>(gin.get());
1927  std::size_t np = g->getNumGeometries();
1928  for (std::size_t i = 0; i < np; ++i)
1929  {
1930  te::gm::LineString *l = dynamic_cast<te::gm::LineString*>(g->getGeometryN(i));
1932 
1933  for (std::size_t il = 0; il < l->size(); il++)
1934  lz->setPoint(il, l->getX(il), l->getY(il));
1935  l->setSRID(breaklines.getSRID());
1937  if (ls->size())
1938  {
1939  breaklines.add(dynamic_cast<te::gm::Geometry*>(ls));
1940  nbreak += ls->size();
1941  }
1942  }
1943  }
1944  }
1945 
1946  std::unique_ptr<te::gm::Envelope> env = inDset->getExtent(geo_pos);
1947  env->init((env->getLowerLeftX() - m_tolerance_break), (env->getLowerLeftY() - m_tolerance_break), (env->getUpperRightX() + m_tolerance_break), (env->getUpperRightY() + m_tolerance_break));
1948 
1949  setEnvelope(*env);
1950 
1951  return nbreak;
1952 }
1953 
1955 {
1956  if (!m_nsderiv.size())
1957  // Calculate derivatives
1958  if (!NodeDerivatives())
1959  return false;
1960 
1961  std::vector<te::gm::Point> p3dl;
1962  std::vector<bool> fixed;
1963 
1964  te::common::TaskProgress task("Inserting BreakLines...", te::common::TaskProgress::UNDEFINED, (int)breaklines.getNumGeometries());
1965 
1966  // To all breaklines
1967  for (unsigned int id = 0; id < breaklines.getNumGeometries(); ++id)
1968  {
1969  if (!task.isActive())
1970  return false;
1971  task.pulse();
1972 
1973  te::gm::LineString* gout = dynamic_cast<te::gm::LineString*>(breaklines.getGeometryN(id));
1974  if ((gout->getNPoints() < 2))
1975  {
1976  continue;
1977  }
1978  for (std::size_t j = 0; j < gout->getNPoints()-1; ++j)
1979  {
1980  std::unique_ptr<te::gm::Point> pf = gout->getPointN(j);
1981  std::unique_ptr<te::gm::Point> pn = gout->getPointN(j + 1);
1983  pfz.setX(pf->getX());
1984  pfz.setY(pf->getY());
1985  pfz.setZ(0.);
1986 
1988  pnz.setX(pn->getX());
1989  pnz.setY(pn->getY());
1990  pnz.setZ(0.);
1991 
1992  // Fill list of points intersecting triangle edges
1993  if (!FindInterPoints(pfz, pnz, p3dl, fixed))
1994  {
1995  return false;
1996  }
1997  }
1998 
1999  // Mark last point of a line
2001  p3d.setX(std::numeric_limits< float >::max());
2002  p3d.setY(std::numeric_limits< float >::max());
2003  p3d.setZ(std::numeric_limits< float >::max());
2004  p3dl.push_back(p3d);
2005  fixed.push_back(false);
2006  }
2007 
2008  RegeneratewithNewPoints(p3dl, fixed);
2009 
2010  return true;
2011 }
2012 
2014 {
2017  std::string geostype;
2018  ReadBreakLines(mpt, breaklines, geostype);
2019 
2020  InsertBreakNodes(breaklines);
2021  return true;
2022 }
2023 
2024 
2025 bool te::mnt::TINGeneration::FindInterPoints(te::gm::Point &pf, te::gm::Point &pn, std::vector<te::gm::Point> &p3d, std::vector<bool> &fixed)
2026 {
2027  int32_t ftri, ltri, nids[3], lids[3],
2028  ledge, ntri;
2029  double tol = m_minedgesize;
2030  double dist, mindist;
2031  size_t i, k;
2032  bool fixedf = false;
2033  bool fixedn = false;
2034 
2035  // Search triangle containing first point
2036  ftri = FindTriangle(pf);
2037 
2038  // Search triangle containing last point
2039  ltri = FindTriangle(pn);
2040  if (ftri == ltri)
2041  {
2042  // If first triangle equal to last
2043  m_triang[(unsigned int)ftri].LinesId(lids);
2044  for (i = 0; i < 3; i++)
2045  if ((m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeFrom()].getZ() >= m_nodatavalue) ||
2046  (m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeTo()].getZ() >= m_nodatavalue))
2047  {
2048  pf.setZ(m_nodatavalue);
2049  pn.setZ(m_nodatavalue);
2050  break;
2051  }
2052 
2053  // Calculate zvalue of first and last points
2054  if (i == 3)
2055  {
2056  for (k = 0; k < 3; k++)
2057  if (OnIsolineSegment(lids[(unsigned int)k], pf, fixedf))
2058  // If on isoline segment
2059  break;
2060 
2061  for (k = 0; k < 3; k++)
2062  if (OnIsolineSegment(lids[(unsigned int)k], pn, fixedn))
2063  // If on isoline segment
2064  break;
2065 
2066  // Calculate zvalue of first and last points using quintic surface
2067  if (!fixedf && !fixedn)
2068  CalcZvalueAkima(ftri, pf, pn);
2069  else if (!fixedf)
2070  CalcZvalueAkima(ftri, pf, pf);
2071  else if (!fixedn)
2072  CalcZvalueAkima(ftri, pn, pn);
2073  }
2074 
2075  // Insert points in list
2076  p3d.push_back(pf);
2077  fixed.push_back(fixedf);
2078  p3d.push_back(pn);
2079  fixed.push_back(fixedn);
2080 
2081  return true;
2082  }
2083 
2084  // Search intersecting edge and point between first triangle
2085  // edges and the segment from first to last point.
2086  m_triang[(unsigned int)ftri].LinesId(lids);
2087  NeighborsId(ftri, nids);
2089  pt.setX(std::numeric_limits< float >::max());
2090  pt.setY(0.);
2091  pt.setZ(0.);
2093  int auxj = -1, j, minj;
2094  for (j = 0; j < 3; j++)
2095  {
2096  te::gm::Point pt1 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeFrom()].getNPoint();
2097  te::gm::Point pt2 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getNPoint();
2098  if (segInterPoint(pf, pn, pt1, pt2, &pt))
2099  {
2100  if (Equal(pt, pt2, m_tolerance) || Equal(pt, pt1, m_tolerance))
2101  {
2102  auxj = j;
2103  minpt = pt;
2104  }
2105  else
2106  break;
2107  }
2108  }
2109  if ((j == 3) && (auxj != -1))
2110  {
2111  j = auxj;
2112  pt = minpt;
2113  }
2114  if (j == 3)
2115  {
2116  minj = -1;
2117  mindist = std::numeric_limits< float >::max();
2118  for (j = 0; j < 3; j++)
2119  {
2120  te::gm::Point pt1 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeFrom()].getNPoint();
2121  te::gm::Point pt2 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getNPoint();
2122  dist = pointToSegmentDistance(pt1, pt2, pf, nullptr);
2123  if (dist < tol)
2124  {
2125  if (dist < mindist)
2126  {
2127  minj = j;
2128  mindist = dist;
2129  minpt.setX(pf.getX());
2130  minpt.setY(pf.getY());
2131  }
2132  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2133  {
2134  pt.setX(pf.getX());
2135  pt.setY(pf.getY());
2136  break;
2137  }
2138  }
2139  dist = pointToSegmentDistance(pt1, pt2, pn, nullptr);
2140  if (dist < tol)
2141  {
2142  if (dist < mindist)
2143  {
2144  minj = j;
2145  mindist = dist;
2146  minpt.setX(pn.getX());
2147  minpt.setY(pn.getY());
2148  }
2149  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2150  {
2151  pt.setX(pn.getX());
2152  pt.setY(pn.getY());
2153  break;
2154  }
2155  }
2156  dist = pointToSegmentDistance(pf, pn, pt1, nullptr);
2157  if (dist < tol)
2158  {
2159  if (dist < mindist)
2160  {
2161  minj = j;
2162  mindist = dist;
2163  minpt.setX(pt1.getX());
2164  minpt.setY(pt1.getY());
2165  }
2166  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2167  {
2168  pt.setX(pt1.getX());
2169  pt.setY(pt1.getY());
2170  break;
2171  }
2172  }
2173  dist = pointToSegmentDistance(pf, pn, pt2, nullptr);
2174  if (dist < tol)
2175  {
2176  if (dist < mindist)
2177  {
2178  minj = j;
2179  mindist = dist;
2180  minpt.setX(pt2.getX());
2181  minpt.setY(pt2.getY());
2182  }
2183  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2184  {
2185  pt.setX(pt2.getX());
2186  pt.setY(pt2.getY());
2187  break;
2188  }
2189  }
2190  }
2191  if (minj != -1)
2192  {
2193  j = minj;
2194  pt.setX(minpt.getX());
2195  pt.setY(minpt.getY());
2196  }
2197  }
2198  if (j == 3)
2199  {
2200  return false;
2201  }
2202 
2203  te::gm::Point p3t1(pf);
2204  te::gm::Point p3t2(pt);
2205  bool fixed1 = false;
2206  bool fixed2 = false;
2207  for (i = 0; i < 3; i++)
2208  if ((m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeFrom()].getZ() >= m_nodatavalue) ||
2209  (m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeTo()].getZ() >= m_nodatavalue))
2210  {
2211  p3t1.setZ(m_nodatavalue);
2212  p3t2.setZ(m_nodatavalue);
2213  break;
2214  }
2215  // Calculate zvalue of first and intersected points
2216  if (i == 3)
2217  {
2218  for (k = 0; k < 3; k++)
2219  if (OnIsolineSegment(lids[(unsigned int)k], p3t1, fixed1))
2220  // If on isoline segment
2221  break;
2222 
2223  for (k = 0; k < 3; k++)
2224  if (OnIsolineSegment(lids[(unsigned int)k], p3t2, fixed2))
2225  // If on isoline segment
2226  break;
2227 
2228  // Calculate zvalue of first and last points using quintic surface
2229  if (!fixed1 && !fixed2)
2230  CalcZvalueAkima(ftri, p3t1, p3t2);
2231  else if (!fixed1)
2232  CalcZvalueAkima(ftri, p3t1, p3t1);
2233  else if (!fixed2)
2234  CalcZvalueAkima(ftri, p3t2, p3t2);
2235  }
2236 
2237  // Insert points in list
2238  p3d.push_back(p3t1);
2239  fixed.push_back(fixed1);
2240  p3d.push_back(p3t2);
2241  fixed.push_back(fixed2);
2242 
2243  k = 0;
2244 
2245  while (nids[j] != ltri)
2246  {
2247  ledge = lids[j];
2248  ntri = nids[j];
2249  m_triang[(unsigned int)ntri].LinesId(lids);
2250  NeighborsId(ntri, nids);
2251 
2252  // Search intersecting edge and point in triangle
2253  pt.setX(m_nodatavalue);
2254  auxj = -1;
2255  for (j = 0; j < 3; j++)
2256  {
2257  if (lids[j] == ledge)
2258  continue;
2259  te::gm::Point pt1 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeFrom()].getNPoint();
2260  te::gm::Point pt2 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getNPoint();
2261  if (segInterPoint(pf, pn, pt1, pt2, &pt))
2262  {
2263  if (Equal(pt,pt2, m_tolerance) || Equal(pt,pt1, m_tolerance))
2264  {
2265  auxj = j;
2266  minpt = pt;
2267  }
2268  else
2269  break;
2270  }
2271  }
2272  if ((j == 3) && (auxj != -1))
2273  {
2274  j = auxj;
2275  pt = minpt;
2276  }
2277  if (j == 3)
2278  {
2279  minj = -1;
2280  mindist = std::numeric_limits< float >::max();
2281  for (j = 0; j < 3; j++)
2282  {
2283  if (lids[j] == ledge)
2284  continue;
2285  te::gm::Point pt1 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeFrom()].getNPoint();
2286  te::gm::Point pt2 = m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getNPoint();
2287  dist = pointToSegmentDistance(pt1, pt2, pf, nullptr);
2288  if (dist < tol)
2289  {
2290  if (dist < mindist)
2291  {
2292  minj = j;
2293  mindist = dist;
2294  minpt.setX(pf.getX());
2295  minpt.setY(pf.getY());
2296  }
2297  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2298  {
2299  pt.setX(pf.getX());
2300  pt.setY(pf.getY());
2301  break;
2302  }
2303  }
2304  dist = pointToSegmentDistance(pt1, pt2, pn, nullptr);
2305  if (dist < tol)
2306  {
2307  if (dist < mindist)
2308  {
2309  minj = j;
2310  mindist = dist;
2311  minpt.setX(pn.getX());
2312  minpt.setY(pn.getY());
2313  }
2314  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2315  {
2316  pt.setX(pn.getX());
2317  pt.setY(pn.getY());
2318  break;
2319  }
2320  }
2321  dist = pointToSegmentDistance(pf, pn, pt1, nullptr);
2322  if (dist < tol)
2323  {
2324  if (dist < mindist)
2325  {
2326  minj = j;
2327  mindist = dist;
2328  minpt.setX(pt1.getX());
2329  minpt.setY(pt1.getY());
2330  }
2331  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2332  {
2333  pt.setX(pt1.getX());
2334  pt.setY(pt1.getY());
2335  break;
2336  }
2337  }
2338  dist = pointToSegmentDistance(pf, pn, pt2, nullptr);
2339  if (dist < tol)
2340  {
2341  if (dist < mindist)
2342  {
2343  minj = j;
2344  mindist = dist;
2345  minpt.setX(pt2.getX());
2346  minpt.setY(pt2.getY());
2347  }
2348  if (onSameSide(te::gm::Coord2D(pf.getX(), pf.getY()), te::gm::Coord2D(pn.getX(), pn.getY()), te::gm::Coord2D(pt1.getX(), pt1.getY()), te::gm::Coord2D(pt2.getX(), pt2.getY())) != 1)
2349  {
2350  pt.setX(pt2.getX());
2351  pt.setY(pt2.getY());
2352  break;
2353  }
2354  }
2355  }
2356  if (minj != -1)
2357  {
2358  j = minj;
2359  pt.setX(minpt.getX());
2360  pt.setY(minpt.getY());
2361  }
2362  if (j == 3)
2363  {
2364  return false;
2365  }
2366  }
2367 
2368  if (k == 0)
2369  {
2370  // Search next intersecting point
2371  p3t1.setX(pt.getX());
2372  p3t1.setY(pt.getY());
2373  if (IsIsolineSegment(lids[j]))
2374  {
2375  fixed1 = true;
2376  p3t1.setZ(m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getZ());
2377  }
2378  else
2379  fixed1 = false;
2380  k++;
2381  }
2382  else
2383  {
2384  if (IsIsolineSegment(lids[j]))
2385  {
2386  fixed2 = true;
2387  p3t2.setZ(m_node[(unsigned int)m_line[(unsigned int)lids[j]].getNodeTo()].getZ());
2388  }
2389  else
2390  fixed2 = false;
2391  p3t2.setX(pt.getX());
2392  p3t2.setY(pt.getY());
2393  for (i = 0; i < 3; i++)
2394  if ((m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeFrom()].getZ() >= m_nodatavalue) ||
2395  (m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeTo()].getZ() >= m_nodatavalue))
2396  {
2397  p3t1.setZ(m_nodatavalue);
2398  p3t2.setZ(m_nodatavalue);
2399  break;
2400  }
2401 
2402  // Calculate zvalue of intersected point using quintic surface
2403  if (i == 3)
2404  {
2405  // Calculate zvalue of first and last points using quintic surface
2406  if (!fixed1 && !fixed2)
2407  CalcZvalueAkima(ntri, p3t1, p3t2);
2408  else if (!fixed1)
2409  CalcZvalueAkima(ntri, p3t1, p3t1);
2410  else if (!fixed2)
2411  CalcZvalueAkima(ntri, p3t2, p3t2);
2412  }
2413  p3d.push_back(p3t1);
2414  fixed.push_back(fixed1);
2415  p3d.push_back(p3t2);
2416  fixed.push_back(fixed2);
2417  k = 0;
2418  }
2419  }
2420  m_triang[(unsigned int)ltri].LinesId(lids);
2421  if (k == 0)
2422  {
2423  p3t1.setX(pn.getX());
2424  p3t1.setY(pn.getY());
2425  for (i = 0; i < 3; i++)
2426  if ((m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeFrom()].getZ() >= m_nodatavalue) ||
2427  (m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeTo()].getZ() >= m_nodatavalue))
2428  {
2429  p3t1.setZ(m_nodatavalue);
2430  break;
2431  }
2432 
2433  // Calculate zvalue of last point using quintic surface
2434  if (i == 3)
2435  {
2436  for (k = 0; k < 3; k++)
2437  if (OnIsolineSegment(lids[k], p3t1, fixed1))
2438  // If on isoline segment
2439  break;
2440 
2441  // Calculate zvalue of first and last points using quintic surface
2442  if (!fixed1)
2443  CalcZvalueAkima(ltri, p3t1, p3t1);
2444  }
2445  p3d.push_back(p3t1);
2446  fixed.push_back(fixed1);
2447  }
2448  else
2449  {
2450  p3t2.setX(pn.getX());
2451  p3t2.setY(pn.getY());
2452  for (i = 0; i < 3; i++)
2453  if ((m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeFrom()].getZ() >= m_nodatavalue) ||
2454  (m_node[(unsigned int)m_line[(unsigned int)lids[i]].getNodeTo()].getZ() >= m_nodatavalue))
2455  {
2456  p3t1.setZ(m_nodatavalue);
2457  p3t2.setZ(m_nodatavalue);
2458  break;
2459  }
2460 
2461  if (i == 3)
2462  {
2463  for (k = 0; k < 3; k++)
2464  if (OnIsolineSegment(lids[k], p3t1, fixed1))
2465  // If on isoline segment
2466  break;
2467 
2468  for (k = 0; k < 3; k++)
2469  if (OnIsolineSegment(lids[k], p3t2, fixed2))
2470  // If on isoline segment
2471  break;
2472 
2473  // Calculate zvalue of first and last points using quintic surface
2474  if (!fixed2)
2475  CalcZvalueAkima(ltri, p3t1, p3t2);
2476  }
2477  p3d.push_back(p3t1);
2478  fixed.push_back(fixed1);
2479  p3d.push_back(p3t2);
2480  fixed.push_back(fixed2);
2481  }
2482 
2483  return true;
2484 }
2485 
2486 bool te::mnt::TINGeneration::OnIsolineSegment(int32_t linid, te::gm::Point &pt, bool &fixed)
2487 {
2488  te::gm::Point pt1 = m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getNPoint();
2489  te::gm::Point pt2 = m_node[(unsigned int)m_line[(unsigned int)linid].getNodeTo()].getNPoint();
2490 
2491  fixed = false;
2492  if (onSegment(pt, pt1, pt2, m_minedgesize))
2493  if (IsIsolineSegment(linid))
2494  {
2495  // If on isoline segment
2496  pt.setZ(m_node[(unsigned int)m_line[(unsigned int)linid].getNodeFrom()].getZ());
2497  fixed = true; // Fixed Zvalue point
2498  return true;
2499  }
2500 
2501  return false;
2502 }
2503 
2505 {
2506  int32_t i, tri,
2507  nrtri,
2508  bline, nline, lline,
2509  lids[3],
2510  node1, node2;
2511  short j;
2512 
2513  // To all breakline nodes
2514  for (i = m_fbnode; i < (int32_t)m_node.size() - 1; i++)
2515  {
2516  if ((m_node[(unsigned int)i].getType() > Breaklinefirst) ||
2517  (m_node[(unsigned int)i].getType() == Deletednode))
2518  // If node is last or sample point
2519  continue;
2520 
2521  node1 = NextNode(i);
2522  if (node1 == -1) continue;
2523 
2524  if (m_node[(unsigned int)node1].getType() == Breaklinelast)
2525  // If next node is last of a breakline
2526  continue;
2527 
2528  // Search line from node to node+1
2529  bline = FindLine(i, node1);
2530  if (bline == -1)
2531  {
2532  if (m_node[(unsigned int)i].getType() == Breaklinefirst)
2533  m_node[(unsigned int)i].setType(Sample);
2534  else
2535  m_node[(unsigned int)i].setType(Breaklinelast);
2536  m_node[(unsigned int)node1].setType(Breaklinefirst);
2537  continue;
2538  }
2539 
2540  // Search line from node+1 to node+2
2541  node2 = NextNode(node1);
2542  if (node2 == -1) continue;
2543  nline = FindLine(node1, node2);
2544  if (nline == -1)
2545  {
2546  m_node[(unsigned int)node1].setType(Breaklinelast);
2547  if (m_node[(unsigned int)node2].getType() == Breaklinelast)
2548  m_node[(unsigned int)node2].setType(Sample);
2549  else
2550  m_node[(unsigned int)node2].setType(Breaklinefirst);
2551  continue;
2552  }
2553 
2554  // Make sure line pointing to next node
2555  if (m_line[(unsigned int)bline].getNodeTo() == i)
2556  m_line[(unsigned int)bline].SwapNodePolygon();
2557 
2558  tri = m_line[(unsigned int)bline].getRightPolygon();
2559  lline = bline;
2560 
2561  // Search lines at right side
2562  while ((lline != nline) && (tri != -1))
2563  {
2564  m_triang[(unsigned int)tri].LinesId(lids);
2565  for (j = 0; j < 3; j++)
2566  {
2567  if (lids[j] == lline)
2568  continue;
2569  if (m_line[(unsigned int)lids[j]].getNodeTo() == node1)
2570  break;
2571  if (m_line[(unsigned int)lids[j]].getNodeFrom() == node1)
2572  {
2573  // Make line pointing to next node
2574  m_line[(unsigned int)lids[j]].SwapNodePolygon();
2575  break;
2576  }
2577  }
2578  if (j == 3)
2579  return false;
2580  lline = lids[j];
2581  nrtri = m_line[(unsigned int)lline].getRightPolygon();
2582  if (nrtri == tri)
2583  m_line[(unsigned int)lline].SwapPolygon();
2584  tri = m_line[(unsigned int)lline].getRightPolygon();
2585  }
2586 
2587  tri = m_line[(unsigned int)bline].getLeftPolygon();
2588  lline = bline;
2589 
2590  // Search lines at left side
2591  while ((lline != nline) && (tri != -1))
2592  {
2593  m_triang[(unsigned int)tri].LinesId(lids);
2594  for (j = 0; j < 3; j++)
2595  {
2596  if (lids[j] == lline)
2597  continue;
2598  if (m_line[(unsigned int)lids[j]].getNodeFrom() == node1)
2599  break;
2600  if (m_line[(unsigned int)lids[j]].getNodeTo() == node1)
2601  {
2602  // Make line pointing to opposite node of next node
2603  m_line[(unsigned int)lids[j]].SwapNodePolygon();
2604  break;
2605  }
2606  }
2607  if (j == 3)
2608  return false;
2609  lline = lids[j];
2610  nrtri = m_line[(unsigned int)lline].getRightPolygon();
2611  if (nrtri == tri)
2612  m_line[(unsigned int)lline].SwapPolygon();
2613  tri = m_line[(unsigned int)lline].getRightPolygon();
2614  }
2615  }
2616 
2617  return true;
2618 }
2619 
2621 {
2622  int32_t triangid, contr = 0, npoly = -1;
2623 
2624  te::common::TaskProgress task("Regeneration Delaunay...", te::common::TaskProgress::UNDEFINED, (int)m_ltriang);
2625 
2626  for (triangid = 0; triangid < m_ltriang; triangid++)
2627  {
2628  if (!task.isActive())
2629  return false;
2630  task.pulse();
2631 
2632  if (triangid > npoly)
2633  npoly = triangid;
2634  else
2635  {
2636  return false;
2637  }
2638  if (!ReGenerateDelaunay(npoly, npoly, contr) )
2639  {
2640  return false;
2641  }
2642  }
2643 
2644  return false;
2645 }
2646 
2647 bool te::mnt::TINGeneration::ReGenerateDelaunay(int32_t nt, int32_t ntbase, int32_t contr)
2648 {
2649  int32_t aux, neighids[3];
2650  short j;
2651 
2652  contr++;
2653  if (contr > m_ltriang)
2654  {
2655  return false;
2656  }
2657 
2658  for (j = 0; j < 3; j++)
2659  {
2660  NeighborsId(nt, neighids);
2661  aux = neighids[(unsigned int)j];
2662  if (aux == nt)
2663  continue;
2664 
2665  // Test with each neighbor, if it exists
2666  if (aux == -1)
2667  continue;
2668  if (IsNeighborOnIsoOrBreakline(nt, (unsigned short)j))
2669  continue;
2670  if (TestDelaunay(nt, j))
2671  {
2672  // If changed,
2673  if (ntbase > aux)
2674  // If smaller number that base
2675  ReGenerateDelaunay(aux, ntbase, contr);
2676 
2677  // Returns to current neighbor
2678  j = -1;
2679  }
2680  }
2681  return true;
2682 }
2683 
2685 {
2686  if (!m_nsderiv.size())
2687  // Calculate derivatives
2688  if (!NodeDerivatives())
2689  return false;
2690 
2697  int32_t neighs[3];
2698  std::vector<int32_t> used_tri;
2699  std::vector<te::gm::Point> p3dl;
2700  std::vector<bool> fixed;
2701 
2702  for (int32_t tri = 0; tri < (int32_t)m_triangsize; tri++)
2703  {
2704  if (std::find(used_tri.begin(), used_tri.end(), tri) != used_tri.end())
2705  continue;
2706 
2707  used_tri.push_back(tri);
2708  TrianglePoints(tri, vert);
2709  if (vert[0].getZ() == vert[1].getZ() && vert[0].getZ() == vert[2].getZ())
2710  {
2711  NeighborsId(tri, neighs);
2712  for (int n = 0; n < 3; n++)
2713  {
2715  TrianglePoints(neighs[n], vertn);
2716 
2717  if (vertn[0].getZ() == vertn[1].getZ() && vertn[0].getZ() == vertn[2].getZ())
2718  {
2719  if (std::find(used_tri.begin(), used_tri.end(), neighs[n]) != used_tri.end())
2720  continue;
2721 
2722  used_tri.push_back(neighs[n]);
2723 
2724  if (n == 0) // first edge
2725  {
2726  pc.setX((vert[0].getX() + vert[1].getX()) / 2.);
2727  pc.setY((vert[0].getY() + vert[1].getY()) / 2.);
2728  }
2729  if (n == 1) //second edge
2730  {
2731  pc.setX((vert[1].getX() + vert[2].getX()) / 2.);
2732  pc.setY((vert[1].getY() + vert[2].getY()) / 2.);
2733  }
2734  if (n == 2) //third edge
2735  {
2736  pc.setX((vert[2].getX() + vert[0].getX()) / 2.);
2737  pc.setY((vert[2].getY() + vert[0].getY()) / 2.);
2738  }
2739 
2740  CalcZvalueAkima(tri, pc, pc);
2741  p3dl.push_back(pc);
2742  fixed.push_back(false);
2743  break;
2744  }
2745  }
2746  }
2747  }
2748 
2749  RegeneratewithNewPoints(p3dl, fixed);
2750 
2751  return true;
2752 }
2753 
2754 te::gm::Geometry* te::mnt::TINGeneration::neigh_union(te::gm::Geometry* tri_union, int32_t tri, std::vector<int32_t> &used_tri, std::map<int32_t, te::gm::Polygon> &pol_tri)
2755 {
2759  int32_t neighs[3];
2760 
2761  NeighborsId(tri, neighs);
2762  for (int n = 0; n < 3; n++)
2763  {
2764  int trii = neighs[n];
2765  if (std::find(used_tri.begin(), used_tri.end(), trii) != used_tri.end())
2766  continue;
2767 
2768  used_tri.push_back(trii);
2769 
2770  TrianglePoints(trii, vert);
2771  if (vert[0].getZ() == vert[1].getZ() && vert[0].getZ() == vert[2].getZ())
2772  {
2773  used_tri.push_back(trii);
2774  te::gm::Polygon tri_n(1, te::gm::PolygonZType, m_srid, nullptr);
2776  for (std::size_t i = 0; i < 4; ++i)
2777  {
2778  r.setX(i, vert[i%3].getX());
2779  r.setY(i, vert[i%3].getY());
2780  r.setZ(i, vert[i%3].getZ());
2781  }
2782  tri_n.setRingN(0, dynamic_cast<te::gm::Curve*>(r.clone()));
2783 
2784  pol_tri.insert(std::pair<int32_t, te::gm::Polygon>(trii, tri_n));
2785 
2786  tri_union = tri_union->Union(dynamic_cast<te::gm::Geometry*>(&tri_n));
2787  tri_union = neigh_union(tri_union, trii, used_tri, pol_tri);
2788  }
2789  }
2790  return tri_union;
2791 }
2792 
2793 
2794 bool te::mnt::TINGeneration::RegeneratewithNewPoints(std::vector<te::gm::Point> &p3dl, std::vector<bool> &fixed)
2795 {
2796  point3dListFilter(p3dl, fixed, m_tolerance);
2797  size_t blnode = p3dl.size();
2798 
2799  size_t newtnodesize = blnode + m_lnode + 6;
2800  ReallocateVectors(newtnodesize);
2801 
2802  m_fbnode = m_lnode;
2803  bool frsflag = true;
2804  int32_t nidaux, node;
2805  for (size_t pp = 0; pp < p3dl.size(); pp++)
2806  {
2807  te::gm::Point p3d = p3dl[pp];
2808  if (p3d.getX() >= m_nodatavalue)
2809  {
2810  // If last point of a line, change type of previous node
2811  frsflag = true;
2812  nidaux = PreviousNode(m_lnode);
2813 
2814  if (m_node[(unsigned int)nidaux].getType() == Breaklinenormal)
2815  m_node[(unsigned int)nidaux].setType(Sample);
2816  else if (m_node[(unsigned int)nidaux].getType() == Last)
2817  m_node[(unsigned int)nidaux].setType(Breaklinelast);
2818  else
2819  return false;
2820  continue;
2821  }
2822  node = ++m_lnode;
2823  if (node > (int32_t)m_nodesize)
2824  return false;
2825  m_node[(unsigned int)node].setNPoint(p3d);
2826  if (frsflag)
2827  {
2828  // If first point of a line, set node type
2829  frsflag = false;
2830  m_node[(unsigned int)node].setType(Breaklinenormal);
2831  }
2832  else
2833  m_node[(unsigned int)node].setType(Last);
2834  InsertNode(node, 0);
2835 
2836  }
2837 
2838  //Check triangulation topology
2839  if (!CheckTopology())
2840  return false;
2841 
2842  //Order breaklines
2843  OrderLines();
2844  ReCreateDelaunay();
2845  if (m_nsderiv.size())
2846  {
2847  m_nsderiv.clear();
2848  }
2849 
2850  return true;
2851 
2852 }
2853 
2855 {
2856  //Search ONBOXVERTEX vertex
2857  for (int32_t vii = 0; vii < (int32_t)m_node.size(); ++vii)
2858  {
2859  if ((m_node[(unsigned int)vii].getType() == Box)/* || (m_node[(unsigned int)vii].getType() == Deletednode)*/)
2860  {//if node has Box type
2861  //Search adjacent edges to the vertex
2862  std::vector <int32_t> lids;
2863  NodeLines(vii, lids);
2864 
2865  for (size_t li = 0; li < lids.size(); li++)
2866  { //Swaps vertex reference in the edges (from and/or to) for NULL
2867  int32_t lii = lids[li];
2868  int32_t from = m_line[(unsigned int)lii].getNodeFrom();
2869  int32_t to = m_line[(unsigned int)lii].getNodeTo();
2870 
2871  if (from == vii)
2872  {
2873  m_node[(unsigned int)from].removeEdge(lii);
2874  m_line[(unsigned int)lii].setNodeFrom(-1);
2875  m_line[(unsigned int)lii].setType(Deletedline);
2876  }
2877  if (to == vii)
2878  {
2879  m_node[(unsigned int)to].removeEdge(lii);
2880  m_line[(unsigned int)lii].setNodeTo(-1);
2881  m_line[(unsigned int)lii].setType(Deletedline);
2882  }
2883 
2884  //Swaps edge reference in the triangles for NULL
2885  long tleft = m_line[(unsigned int)lii].getLeftPolygon();
2886  long tright = m_line[(unsigned int)lii].getRightPolygon();
2887 
2888  //Check if triangle edges are equal eii
2889  int32_t edge[3];
2890  edge[0]= edge[1] = edge[2] = -1;
2891  if (tleft != -1)
2892  {
2893  //left triangle
2894  m_triang[(unsigned int)tleft].LinesId(edge);
2895  if (edge[0] == lii)
2896  m_triang[(unsigned int)tleft].setEdges(-1, edge[1], edge[2]);
2897  if (edge[1] == lii)
2898  m_triang[(unsigned int)tleft].setEdges(edge[0], -1, edge[2]);
2899  if (edge[2] == lii)
2900  m_triang[(unsigned int)tleft].setEdges(edge[0], edge[1], -1);
2901 
2902  }
2903  if (tright != -1)
2904  { //right triangle
2905  m_triang[(unsigned int)tright].LinesId(edge);
2906  if (edge[0] == lii)
2907  m_triang[(unsigned int)tright].setEdges(-1, edge[1], edge[2]);
2908  if (edge[1] == lii)
2909  m_triang[(unsigned int)tright].setEdges(edge[0], -1, edge[2]);
2910  if (edge[2] == lii)
2911  m_triang[(unsigned int)tright].setEdges(edge[0], edge[1], -1);
2912  }
2913 
2914  std::vector <int32_t> edgesadj;
2915  //Checks if vertex from and to have reference to this edge in onEdge
2916  //If, there is the reference, changes it to another adjacent edge.
2917  if (from != -1)
2918  {
2919  std::vector<int32_t> edge1 = m_node[(unsigned int)from].getEdge();
2920  for (size_t i_e = 0; i_e < edge1.size(); i_e++)
2921  {
2922  if (edge1[i_e] == lii)//vertex from
2923  {
2924  NodeLines(from, edgesadj);
2925  for (size_t iAdj = 0; iAdj < edgesadj.size(); iAdj++)
2926  {
2927  if (edgesadj[iAdj] != -1 && edgesadj[iAdj] != lii)
2928  {
2929  m_node[(unsigned int)from].setEdge(edgesadj[iAdj]);
2930  break;
2931  }
2932  }
2933  }
2934  }
2935  }
2936 
2937  if (to != -1)
2938  {
2939  std::vector<int32_t> edge1 = m_node[(unsigned int)to].getEdge();
2940  for (size_t i_e = 0; i_e < edge1.size(); i_e++)
2941  {
2942  if (edge1[i_e] == lii)//vertex to
2943  {
2944  NodeLines(to, edgesadj);
2945  for (size_t iAdj = 0; iAdj < edgesadj.size(); iAdj++)
2946  {
2947  if (edgesadj[iAdj] != -1 && edgesadj[iAdj] != lii)
2948  {
2949  m_node[(unsigned int)to].setEdge(edgesadj[iAdj]);
2950  break;
2951  }
2952  }
2953  }
2954  }
2955  }
2956  }
2957  }
2958  }
2959 
2960  //Search triangles with NULL reference
2961  for (int32_t tit = 0; tit < (int32_t)m_triang.size(); ++tit)
2962  {
2963  int32_t edge[3];
2964  m_triang[(unsigned int)tit].LinesId(edge);
2965  if (edge[0] == -1 || edge[1] == -1 || edge[2] == -1)
2966  {//if triangle has NULL edge
2967  //For each triangle to be removed:
2968  //Changes triangle reference in the edges (left and right) to -1
2969  if (edge[0] != -1)
2970  {
2971  int32_t left = m_line[(unsigned int)edge[0]].getLeftPolygon();
2972  int32_t right = m_line[(unsigned int)edge[0]].getRightPolygon();
2973 
2974  if (left == tit)
2975  m_line[(unsigned int)edge[0]].setLeftPolygon(-1);
2976  if (right == tit)
2977  m_line[(unsigned int)edge[0]].setRightPolygon(-1);
2978  }
2979 
2980  if (edge[1] != -1)
2981  {
2982  long left = m_line[(unsigned int)edge[1]].getLeftPolygon();
2983  long right = m_line[(unsigned int)edge[1]].getRightPolygon();
2984 
2985  if (left == tit)
2986  m_line[(unsigned int)edge[1]].setLeftPolygon(-1);
2987  if (right == tit)
2988  m_line[(unsigned int)edge[1]].setRightPolygon(-1);
2989  }
2990  if (edge[2] != -1)
2991  {
2992  long left = m_line[(unsigned int)edge[2]].getLeftPolygon();
2993  long right = m_line[(unsigned int)edge[2]].getRightPolygon();
2994 
2995  if (left == tit)
2996  m_line[(unsigned int)edge[2]].setLeftPolygon(-1);
2997  if (right == tit)
2998  m_line[(unsigned int)edge[2]].setRightPolygon(-1);
2999  }
3000  }
3001  }
3002 
3003  return true;
3004 }
3005 
void insert(const kdKey &key, const kdDataItem &item)
It inserts the data with a given key in tree.
void setZ(std::size_t i, const double &z)
It sets the n-th z coordinate value.
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
int m_srid
Attribute with spatial reference information.
Definition: Tin.h:596
bool CreateMinAngleTriangulation()
Method used to create a Triangulation using the Minimum Angle Method.
bool CheckTopology()
Method that check the topology in a triangulation.
Definition: Tin.cpp:2873
int32_t FindTriangle(te::gm::Point &ptr1)
Method that finds a triangle containing a given point.
Definition: Tin.cpp:190
size_t m_triangsize
Triangulation triangles vector size.
Definition: Tin.h:601
bool IsolinesConstrained()
Method that define the Constrained Isolines.
bool FindInterPoints(te::gm::Point &pf, te::gm::Point &pn, std::vector< te::gm::Point > &p3d, std::vector< bool > &fixed)
Method fint the point that intersects two triangles containing points pf and pn.
bool TrianglePoints(int32_t triangId, te::gm::Point *vertex)
Method that reads the vertex (points) of a given triangle.
Definition: Tin.cpp:400
void setTolerance(double tolerance)
Definition: TINGeneration.h:93
void setX(std::size_t i, const double &x)
It sets the n-th x coordinate value.
InputType
Input types.
int32_t PreviousNode(int32_t nodeId)
Method that finds out which is the previous node.
Definition: Tin.cpp:1018
bool NodesId(int32_t triangId, int32_t *nodeIds)
Method that reads the identification number of the nodes of a given triangle.
Definition: Tin.cpp:913
void setNPoint(te::gm::Point npoint)
Definition: Tin.h:228
boost::shared_ptr< DataSource > DataSourcePtr
bool NodeDerivatives()
Method that calculates the first and second derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1743
bool CalcZvalueAkima(int32_t triid, te::gm::Point &pt1, te::gm::Point &pt2)
Method that evaluates Z values for pt1 and pt2 using the Akima polynomium fitted in a triangle...
Definition: Tin.cpp:2933
TEMNTEXPORT bool normalizeVector(double *)
Function that normalize a vector by its size.
TEMNTEXPORT bool Equal(te::gm::Point &p1, te::gm::Point &p2, double &tol)
te::gm::Envelope m_env
Attribute used to restrict the area to generate the samples.
Definition: Tin.h:598
bool DupNeighTriangle(int32_t tv, int32_t an0, short, int32_t v, int32_t *testLines)
Method used to duplicate a neighbour triangle in a TIN (Triangular Irregular Network) ...
int32_t DuplicateTriangle(int32_t t, short n, int32_t v, int32_t *testLines)
Method used to duplicate a triangle in a TIN (Triangular Irregular Network)
bool NodeLines(int32_t v, std::vector< int32_t > &linids)
Method that includes a node in the tin line list.
Definition: Tin.cpp:810
bool NodeExchange(int32_t oldNode, int32_t newNode)
Method used to exchange two nodes in a TIN (Triangular Irregular Network)
size_t m_nodesize
Triangulation nodes vector size.
Definition: Tin.h:602
bool DeleteNode(int32_t node)
Method used to delete a node in a TIN (Triangular Irregular Network)
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
int32_t m_lline
Triangulation last line number.
Definition: Tin.h:620
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
bool InsertNode(int32_t nodeid, int type)
Method used to insert a node in a TIN (Triangular Irregular Network)
void setZ(double zvalue)
Definition: Tin.h:210
bool UpdateTriangles(int32_t t, int32_t tv, int32_t ai)
Method used to Update Triangles of a given triangulation.
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
te::da::DataSourcePtr m_outDsrc
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
bool ReGenerateDelaunay(int32_t nt, int32_t ntbase, int32_t contr)
Method that regenerates a Delaunay triangulation.
int32_t ExchangePolygon(int32_t triangId, int32_t newPolyId, unsigned short edge)
Method that exchanges polygon.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void setOutput(te::da::DataSourcePtr outDsrc, std::string dsname)
It sets the Datasource that is being used to save TIN.
te::gm::Geometry * neigh_union(te::gm::Geometry *tri_union, int32_t tri, std::vector< int32_t > &used_tri_all, std::map< int32_t, te::gm::Polygon > &pol_tri)
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
std::vector< TinLine > m_line
Triangulation lines vector.
Definition: Tin.h:604
TEMNTEXPORT double pointToSegmentDistance(te::gm::Point &fseg, te::gm::Point &lseg, te::gm::Point &pt, te::gm::Point *pti)
bool IsIsolineSegment(int32_t linid)
Method that veryfies if the Isoline is a segment.
std::string m_inDsetName_point
bool InsertNodes(const te::gm::MultiPoint &mpt, const te::gm::MultiLineString &mls)
virtual Geometry * Union(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns a geometric object that represents the point set union with another geometry.
double m_tolerance
Triangulation lines simplification tolerance.
int32_t m_fbnode
First break node number.
Definition: Tin.h:617
bool TestAngleBetweenNormals(int32_t triId, short nviz)
Method used to test the angle between two normals.
bool TestDelaunay(int32_t tri1Id, int32_t tri2Id, int32_t tri3Id)
Method used to test if the triangulation follows the Delaunay rule.
te::gm::Point * pt2
bool isActive() const
Verify if the task is active.
bool IsNeighborOnIsoOrBreakline(int32_t triId, unsigned short nviz)
std::vector< TinTriang > m_triang
Triangulation triangles vector.
Definition: Tin.h:605
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
std::unique_ptr< te::da::DataSetType > m_inDsetType_sample
void setBreakLine(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::unique_ptr< te::da::DataSetType > inDsetType, double tol)
It sets the BreakLine Datasource that is being used to generate TIN.
std::unique_ptr< te::da::DataSetType > m_inDsetType_point
bool ReCreateDelaunay()
Method that recreates a Delaunay triangulation.
size_t m_linesize
Triangulation lines vector size.
Definition: Tin.h:600
TINGeneration()
Default constructor.
te::dt::AbstractData * clone() const
It clones the linear ring.
int32_t OppositeNode(int32_t triangId, int32_t linId)
Method that reads the identification number of the opposite node of a given edge. ...
Definition: Tin.cpp:975
double m_nodatavalue
Definition: Tin.h:622
TEMNTEXPORT size_t ReadPoints(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, te::gm::MultiPoint &mpt, std::string &geostype, te::gm::Envelope &env)
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
double m_tolerance_break
Triangulation breaklines simplification tolerance.
std::vector< TinNode > m_nsderiv
Definition: Tin.h:613
const double & getY() const
It returns the Point y-coordinate value.
Definition: Point.h:152
A point with x and y coordinate values.
Definition: Point.h:50
const Envelope * getMBR() const _NOEXCEPT_OP(true)
It returns the minimum bounding rectangle for the geometry in an internal representation.
bool CreateInitialTriangles(size_t nsamples)
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
An Envelope defines a 2D rectangular region.
bool contains(const Envelope &rhs) const
It returns true if this envelope "spatially contains" the rhs envelope.
std::string m_inDsetName_sample
TEMNTEXPORT te::gm::LineString * pointListSimplify(te::gm::LineString *ls, double snap, double maxdist, double Zvalue)
bool NodeOppositeLines(int32_t v, std::vector< int32_t > &linids)
Method that find the oposite lines of a specific node.
Definition: Tin.cpp:492
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
bool NeighborsId(int32_t triangId, int32_t *neighsId)
Definition: Tin.cpp:950
te::gm::Point * pt1
te::da::DataSourcePtr m_inDsrc_point
TEMNTEXPORT bool point3dListFilter(std::vector< te::gm::Point > &p3dl, std::vector< bool > &fixed, double tol)
Function that filters the points that are closer considering a given tolerance.
This file contains a class to generate TIN. Adapted from SPRING.
void setEnvelope(te::gm::Envelope &env)
Definition: Tin.cpp:182
te::gm::Polygon * p
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
A class that represents a two dimensional K-d Tree (2-d Tree).
Ntype getType()
Definition: Tin.h:237
bool InsertBreakNodes(te::gm::MultiLineString &breaklines)
Utility functions for the data access module.
std::unique_ptr< te::da::DataSetType > m_inDsetType_break
int32_t NextNode(int32_t nodeId)
Method that finds out which is the next node.
Definition: Tin.cpp:999
const double & getZ() const
It returns the Point z-coordinate value, if it has one or DoubleNotANumber otherwise.
Definition: Point.h:166
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
bool TestIsolines(int iter)
Method that test the Isolines.
TEMNTEXPORT size_t ReadSamples(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, double max, Simplify alg, te::gm::MultiPoint &mpt, te::gm::MultiLineString &isolines, std::string &geostype, te::gm::Envelope &env, int srid=0)
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
void setMaxdist(double maxdist)
Definition: TINGeneration.h:96
MultiLineString is a MultiCurve whose elements are LineStrings.
void setX(double xvalue)
Definition: Tin.h:216
int m_method
Triangulation method Delanay or Smaller Angle.
bool CreateDelaunay()
Method that creates a Delaunay triangulation.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
bool SaveTin(te::da::DataSourcePtr &outDsrc, std::string &outDsetName)
Definition: Tin.cpp:1344
bool run()
Generate TIN \ return true or false.
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
te::sam::kdtree::Index< KD_NODE > KD_TREE
Definition: GAP.h:28
std::vector< TinNode > m_node
Triangulation nodes vector.
Definition: Tin.h:606
int32_t NodeId(int32_t triangId, short vertex)
Method that reads the identification number of the nodes of a given triangle.
Definition: Tin.cpp:903
A class that represents an Kd-tree node.
Definition: kdtree/Node.h:61
void clear()
It clears all tree nodes.
size_t ReadBreakLines(te::gm::MultiPoint &mpt, te::gm::MultiLineString &isolines, std::string &geostype)
TEMNTEXPORT int onSameSide(te::gm::Coord2D pt1, te::gm::Coord2D pt2, te::gm::Coord2D fseg, te::gm::Coord2D lseg)
void add(Geometry *g)
It adds the geometry into the collection.
te::sam::kdtree::Node< te::gm::Coord2D, std::pair< int32_t, int32_t >, std::pair< int32_t, int32_t > > KD_NODE
Definition: GAP.h:27
te::gm::Point * pt3
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
bool OrderLines()
Method that order lines.
te::da::DataSourcePtr m_inDsrc_break
bool GenerateDelaunay(int32_t nt, int32_t ntbase, int32_t contr)
Method that generates a Delaunay triangulation.
void setSRID(int srid)
It sets the Spatial Reference System ID of the linestring.
TEMNTEXPORT short segIntersect(te::gm::Point &pfr, te::gm::Point &pto, te::gm::Point &lfr, te::gm::Point &lto)
Function for check segment intersection.
bool IsBreaklineSegment(int32_t linid)
Method that veryfies if the Breakline is a segment.
bool TestFlatTriangles()
Method that test if has flat triangles and regenerate them.
void setY(double yvalue)
Definition: Tin.h:222
bool RegeneratewithNewPoints(std::vector< te::gm::Point > &p3dl, std::vector< bool > &fixed)
te::da::DataSourcePtr m_inDsrc_sample
double m_maxdist
Triangulation lines simplification maximum distance.
bool TwoNewTriangles(int32_t t, int32_t nodeId, int32_t *testLines)
Method used to create two new triangles in a TIN (Triangular Irregular Network)
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:159
void setY(std::size_t i, const double &y)
It sets the n-th y coordinate value.
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::unique_ptr< te::da::DataSetType > inDsetType, InputType type)
It sets the Datasource that is being used to generate TIN.
TEMNTEXPORT bool segInterPoint(te::gm::Point &pfr, te::gm::Point &pto, te::gm::Point &lfr, te::gm::Point &lto, te::gm::Point *pt)
Function for determines the point of two segment intersections.
bool ModifyBoundTriangles()
Method that modifies the bounds of Triangles.
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
TEMNTEXPORT bool onSegment(te::gm::Point &pt, te::gm::Point &fseg, te::gm::Point &lseg, double tol)
Function that checks if a point pt is on a segment.
std::string m_inDsetName_break
int32_t m_ltriang
Triangulation last triangle number.
Definition: Tin.h:619
TEMNTEXPORT bool triangleNormalVector(te::gm::Point *, double *)
Function that defines the triangle normal vector.
void setMinedgesize(double minedgesize)
Definition: TINGeneration.h:99
bool OnIsolineSegment(int32_t linid, te::gm::Point &pt3d, bool &fixed)
Method that checks if a point 3D is on the isoline segment.
void setType(Ntype ntype)
Definition: Tin.h:234
te::gm::Point & getNPoint()
Definition: Tin.h:231
bool ReallocateVectors(size_t nSize)
Method that reallocates Vectors.
Definition: Tin.cpp:1267
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
TEMNTEXPORT short findCenter(te::gm::Point *vert, double *pcx, double *pcy)
Function that finds the center of the vertices of a triangle.
void setParams(const double &tolerance, const double &maxdist, const double &minedgesize, const std::string &atrz_iso, const std::string &atrz_pt)
It sets the parameters to generate TIN.
int32_t m_lnode
Triangulation last node number.
Definition: Tin.h:618
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
void setRingN(std::size_t i, Curve *r)
It sets the informed position ring to the new one.
double m_minedgesize
Triangulation edges minimum size.
std::vector< int32_t > FindLine(int32_t nid)
Method that find a line containing a specific node.
Definition: Tin.cpp:641