Tin.cpp
Go to the documentation of this file.
1 /*!
2 \file terralib/mnt/core/Tin.cpp
3 
4 \brief This file contains a class to define a TIN.
5 
6 */
7 
8 #include "Tin.h"
9 #include "Utils.h"
10 
11 #include "boost/algorithm/string/predicate.hpp"
12 
13 #include "../../common/Exception.h"
14 #include "../../common/progress/TaskProgress.h"
15 #include "../../core/translator/Translator.h"
16 
17 #include "../../dataaccess/utils/Utils.h"
18 
19 #include "../../datatype/Property.h"
20 #include "../../datatype/SimpleProperty.h"
21 #include "../../datatype/StringProperty.h"
22 
23 #include "../../geometry/GeometryProperty.h"
24 #include "../../geometry/Line.h"
25 #include "../../geometry/MultiPolygon.h"
26 
27 #include "../../memory/DataSet.h"
28 #include "../../memory/DataSetItem.h"
29 
30 #include "../../raster/Grid.h"
31 #include "../../raster/Utils.h"
32 
33 #include "../../vp/Utils.h"
34 
35 #include <iostream>
36 #include <limits>
37 #include <cmath>
38 
39 bool te::mnt::TinLine::operator== (const TinLine &rhs) const
40 {
41  if ((this->m_nodefrom != rhs.m_nodefrom) ||
42  (this->m_nodeto != rhs.m_nodeto) ||
43  (this->m_leftpoly != rhs.m_leftpoly) ||
44  (this->m_rightpoly != rhs.m_rightpoly)
45  )
46  return false;
47  else
48  return true;
49 }
50 
51 bool te::mnt::TinLine::operator > (const TinLine &rhs) const
52 {
53  if ((this->m_nodefrom <= rhs.m_nodefrom) ||
54  (this->m_nodeto <= rhs.m_nodeto) ||
55  (this->m_leftpoly <= rhs.m_leftpoly) ||
56  (this->m_rightpoly <= rhs.m_rightpoly)
57  )
58  return false;
59  else
60  return true;
61 }
62 
63 bool te::mnt::TinLine::operator < (const TinLine &rhs) const
64 {
65  if ((this->m_nodefrom >= rhs.m_nodefrom) ||
66  (this->m_nodeto >= rhs.m_nodeto) ||
67  (this->m_leftpoly >= rhs.m_leftpoly) ||
68  (this->m_rightpoly >= rhs.m_rightpoly)
69  )
70  return false;
71  else
72  return true;
73 }
74 
75 bool te::mnt::TinLine::ExchangePolygon(int32_t oldPolyId, int32_t newPolyId)
76 {
77  if (m_rightpoly == oldPolyId)
78  m_rightpoly = newPolyId;
79  else if (m_leftpoly == oldPolyId)
80  m_leftpoly = newPolyId;
81  else
82  return false;
83 
84  return true;
85 }
86 
87 bool te::mnt::TinLine::ExchangeNode(int32_t oldNodeId, int32_t newNodeId)
88 {
89  if (m_nodefrom == oldNodeId)
90  m_nodefrom = newNodeId;
91  else if (m_nodeto == oldNodeId)
92  m_nodeto = newNodeId;
93  else
94  return false;
95 
96  return true;
97 }
98 
100 {
101  int32_t aux;
102 
103  aux = m_rightpoly;
105  m_leftpoly = aux;
106  return true;
107 }
108 
110 {
111  int32_t aux;
112 
113  aux = m_nodefrom;
115  m_nodeto = aux;
116 
117  return true;
118 }
119 
121 {
122  SwapNode();
123  SwapPolygon();
124  return true;
125 }
126 
128 {
129  if ((this->m_point.getX() == rhs.m_point.getX()) &&
130  (this->m_point.getY() == rhs.m_point.getY()))
131  return true;
132  else
133  return false;
134 }
135 
136 bool te::mnt::TinNode::operator> (const TinNode &rhs) const
137 {
138  if ((this->m_point.getX() > rhs.m_point.getX()) &&
139  (this->m_point.getY() > rhs.m_point.getY()))
140  return true;
141  else
142  return false;
143 }
144 
145 bool te::mnt::TinNode::operator< (const TinNode &rhs) const
146 {
147  if ((this->m_point.getX() < rhs.m_point.getX()) &&
148  (this->m_point.getY() < rhs.m_point.getY()))
149  return true;
150  else
151  return false;
152 }
153 
154 bool te::mnt::TinNode::setEdge(int32_t edge)
155 {
156  if (std::find(m_edge.begin(), m_edge.end(), edge) == m_edge.end()) {
157  m_edge.push_back(edge);
158  return true;
159  }
160  return false;
161 }
162 
164 {
165  std::vector<int32_t>::iterator it = std::find(m_edge.begin(), m_edge.end(), edge);
166  if (it != m_edge.end())
167  {
168  m_edge.erase(it);
169  return true;
170  }
171  return false;
172 }
173 
175 {
176 }
177 void te::mnt::Tin::setSRID(int srid)
178 {
179  m_srid = srid;
180 }
181 
183 {
184  if (m_env.getWidth())
185  m_env.Union(env);
186  else
187  m_env = env;
188 }
189 
191 {
192  int32_t v = -1;
193  int i;
194 
195  if (m_lline == 0)
196  return -1;
197 
198  for (i = static_cast<int32_t>(m_lline - 1); i >= 0; i--)
199  {
200  if ((v = m_line[static_cast<unsigned int>(i)].getNodeFrom()) != -1)
201  break;
202  }
203  if (v == -1)
204  return -1;
205 
206  double tol = m_env.getWidth() / 1000000.;
207  double px = ptr1.getX();
208  double py = ptr1.getY();
209 
210  for (;;)
211  {
212  //1. Set the segment line r whose endpoints point p and the vertice v
213  te::gm::Point ptr2 = m_node[static_cast<unsigned int>(v)].getNPoint();
214 
215  //2. Set the edge assist aaux as null
216  int32_t aaux = -1;
217 
218  //3. Be m be the number of edges opposite to v . Set the set A = { a1, . , Am } the opposite edges to v ,
219  std::vector<int32_t> aam;
220  if (!NodeOppositeLines(v, aam))
221  return -1;
222 
223  //4 . Set the vertice assist Vaux as the vertice v ,
224  int32_t vaux = static_cast<int32_t>(v);
225 
226  //5. n is the number of neighboring vertices to v. Defines the set V = {v1,...,vn} of all neighboring vertices to v,
227  std::vector<int32_t> vvn;
228  if (!NodeNodes(v, vvn))
229  return -1;
230 
231  int32_t vi;
232  for (;;)
233  {
234  //6. For each vertice vi (i Î {1, .,n}) of V, do:
235  size_t iiv;
236  for (iiv = 0; iiv < vvn.size(); iiv++)
237  {
238  vi = vvn[iiv];
239  if ((fabs(px - m_node[static_cast<unsigned int>(vi)].getX()) < tol) && (fabs(py - m_node[static_cast<unsigned int>(vi)].getY()) < tol))
240  { //6.1. If vi is equla p, the triangle that contains p is one of the triangles that sharing vi.
241  // choose eiher of trianglesand finish the algorithm.
242  return NodeTriangle(vi);
243  }
244 
245  //6.2. If vi is not equal vaux and is on r, do:
246  if (vaux != -1)
247  {
248  if ((vi == vaux) ||
249  ((fabs(m_node[static_cast<unsigned int>(vaux)].getX() - m_node[static_cast<unsigned int>(vi)].getX()) < tol) &&
250  (fabs(m_node[static_cast<unsigned int>(vaux)].getY() - m_node[static_cast<unsigned int>(vi)].getY()) < tol)))
251  continue;
252  }
253  te::gm::Point ptvi = m_node[static_cast<unsigned int>(vi)].getNPoint();
254 
255  double dist = pointToSegmentDistance(ptr1, ptr2, ptvi, nullptr);
256 
257  if (dist < tol)
258  { //6.2.1. Define v as vi,
259  v = vi;
260  //6.2.2. Return to 2.;
261  break;
262  }
263  }
264  if (iiv != vvn.size())
265  break;
266 
267  //7. For each edge ai (i Î {1, .,m}) of A, do:
268  size_t iia;
269  for (iia = 0; iia < aam.size(); iia++)
270  {
271  int32_t ai = aam[iia];
272  if (ai != aaux)
273  { //7.1. If ai is different aaux
274  te::gm::Point lfr = m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(ai)].getNodeFrom())].getNPoint();
275  te::gm::Point lto = m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(ai)].getNodeTo())].getNPoint();
276  if (segIntersect(ptr1, ptr2, lfr, lto))
277  { // and intersects r, do:
278  int32_t t;
279  int32_t taux = m_line[static_cast<unsigned int>(ai)].getLeftPolygon();
280  if (vaux != -1)
281  { // 7.1.1. If vaux is not NULL, do:
282  // 7.1.1.1. Defines the t triangle that sharing ai
283  // with the taux triangle that contains the vaux vertex ,
284  if (OppositeNode(taux, ai) == vaux)
285  t = m_line[static_cast<unsigned int>(ai)].getRightPolygon();
286  else
287  t = m_line[static_cast<unsigned int>(ai)].getLeftPolygon();
288  }
289  else if (aaux != -1)
290  { // 7.1.2. Else, aaux is not NULL, do:
291  // 7.1.2.1. Defines the t triangle that sharing ai with
292  // the taux triangle that constins aaux.
293  int32_t lidsaux[3];
294  t = m_line[static_cast<unsigned int>(ai)].getLeftPolygon();
295  if (t == -1)
296  return -1;
297  if (!m_triang[static_cast<unsigned int>(t)].LinesId(lidsaux))
298  return -1;
299 
300  for (unsigned int j = 0; j < 3; j++)
301  {
302  if (lidsaux[j] == aaux)
303  {
304  t = m_line[static_cast<unsigned int>(ai)].getRightPolygon();
305  break;
306  }
307  }
308  }
309  else
310  {
311  return -1;
312  }
313 
314  //7.1.3. If the t traingle contains the p point, finish the algorihm.
315  if (ContainsPoint(t, ptr1))
316  return t;
317 
318  //7.1.4. Redefines the set A={a1, a2}.
319  aam.clear();
320  int32_t lids[3];
321  if (t == -1)
322  return -1;
323  if (!m_triang[static_cast<unsigned int>(t)].LinesId(lids))
324  return -1;
325 
326  for (unsigned int j = 0; j < 3; j++)
327  { // The edges a1 e a2 are different edges of ai of t triangle,
328  if (lids[j] != ai)
329  {
330  if (std::find(aam.begin(), aam.end(), lids[j]) == aam.end())
331  aam.push_back(lids[j]);
332  }
333  }
334 
335  //7.1.5. Redefines the set V={v1}.
336  vvn.clear();
337  // The v1 vertice is the t triangle vertice that is not in any border of ai,
338  int32_t v1 = OppositeNode(t, ai);
339  if (v1 >= 0)
340  {
341  if ((fabs(ptr2.getX() - m_node[static_cast<unsigned int>(v1)].getX()) < tol) && (fabs(ptr2.getY() - m_node[static_cast<unsigned int>(v1)].getY()) < tol))
342  {
343  break;
344  }
345  }
346  vvn.push_back(v1);
347 
348  //7.1.6. Defines aaux as ai,
349  aaux = ai;
350  //7.1.7. Defines vaux auxiliar vertice as null
351  vaux = -1;
352  //7.1.8. Returns to 6.;
353  break;
354  }
355  }
356  }
357  if (vvn.empty())
358  {
359  for (i = i - 1; i >= 0; i--)
360  {
361  if (m_line[static_cast<unsigned int>(i)].getNodeFrom() != -1)
362  {
363  v = m_line[static_cast<unsigned int>(i)].getNodeFrom();
364  break;
365  }
366  }
367  if (v == -1)
368  return -1;
369  break;
370  }
371  if (iia != aam.size())
372  continue;
373  //8. If no more edges in A, then:
374  //8.1. Be k the triangles number that sharing v. Defines the set T={t1, ., tk} of all triangles that sharing v,
375  std::vector<int32_t> ttk;
376  if (!NodeTriangles(v, ttk))
377  return -1;
378 
379  //8.2. For each ti triangle (i Î {1, .,k}) of T, do:
380  for (size_t iit = 0; iit < ttk.size(); iit++)
381  {
382  int32_t ti = ttk[iit];
383 
384  //8.2.1. If ti triangle contains p point, finish the algorithm.
385  if (ContainsPoint(ti, ptr1))
386  return ti;
387  }
388  for (i = i - 1; i >= 0; i--)
389  {
390  if ((v = m_line[static_cast<unsigned int>(i)].getNodeFrom()) != -1)
391  break;
392  }
393  if (v == -1)
394  return -1;
395  break;
396  }
397  }
398 }
399 
400 bool te::mnt::Tin::TrianglePoints(int32_t triangId, te::gm::Point *vertex)
401 {
402  int32_t linesid[3];
403  if (triangId == -1)
404  return false;
405 
406  if (!m_triang[static_cast<unsigned int>(triangId)].LinesId(linesid))
407  return false;
408  if (m_line[static_cast<unsigned int>(linesid[0])].getNodeTo() == m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())
409  {
410  vertex[0].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getX());
411  vertex[0].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getY());
412  vertex[0].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getZ());
413  vertex[1].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getX());
414  vertex[1].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getY());
415  vertex[1].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getZ());
416  vertex[2].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getX());
417  vertex[2].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getY());
418  vertex[2].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getZ());
419  }
420  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeTo() == m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())
421  {
422  vertex[0].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getX());
423  vertex[0].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getY());
424  vertex[0].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getZ());
425  vertex[1].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getX());
426  vertex[1].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getY());
427  vertex[1].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getZ());
428  vertex[2].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getX());
429  vertex[2].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getY());
430  vertex[2].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getZ());
431  }
432  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom() == m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())
433  {
434  vertex[0].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getX());
435  vertex[0].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getY());
436  vertex[0].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getZ());
437  vertex[1].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getX());
438  vertex[1].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getY());
439  vertex[1].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getZ());
440  vertex[2].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getX());
441  vertex[2].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getY());
442  vertex[2].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())].getZ());
443  }
444  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom() == m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())
445  {
446  vertex[0].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getX());
447  vertex[0].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getY());
448  vertex[0].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeTo())].getZ());
449  vertex[1].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getX());
450  vertex[1].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getY());
451  vertex[1].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom())].getZ());
452  vertex[2].setX(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getX());
453  vertex[2].setY(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getY());
454  vertex[2].setZ(m_node[static_cast<unsigned int>(m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())].getZ());
455  }
456  else
457  return false;
458  return true;
459 }
460 
461 bool te::mnt::Tin::ContainsPoint(int32_t triangId, te::gm::Point &pt)
462 {
463  double totalArea, triangleArea;
467 
468  TrianglePoints(triangId, vert);
469 
470  // Calculate the base triangle area
471  triangleArea = fabs(((vert[1].getX() - vert[0].getX()) * (vert[2].getY() - vert[0].getY())) -
472  ((vert[2].getX() - vert[0].getX()) * (vert[1].getY() - vert[0].getY())));
473  triangleArea *= 1.00001;
474  totalArea = fabs(((vert[0].getX() - pt.getX()) * (vert[1].getY() - pt.getY())) -
475  ((vert[1].getX() - pt.getX()) * (vert[0].getY() - pt.getY())));
476  if (totalArea > triangleArea)
477  return false;
478 
479  totalArea += fabs(((vert[1].getX() - pt.getX()) * (vert[2].getY() - pt.getY())) -
480  ((vert[2].getX() - pt.getX()) * (vert[1].getY() - pt.getY())));
481  if (totalArea > triangleArea)
482  return false;
483 
484  totalArea += fabs(((vert[0].getX() - pt.getX()) * (vert[2].getY() - pt.getY())) -
485  ((vert[2].getX() - pt.getX()) * (vert[0].getY() - pt.getY())));
486  if (totalArea > triangleArea)
487  return false;
488 
489  return true;
490 }
491 
492 bool te::mnt::Tin::NodeOppositeLines(int32_t v, std::vector<int32_t> &linids)
493 {
494  int32_t td, te, taux, ti;
495  int32_t ai,
496  ao,
497  lids[3];
498  int32_t aaux;
499  unsigned short j;
500  std::vector<int32_t> a;
501 
502  // Find one line that contains node
503  a = FindLine(v);
504  if (!a.size())
505  return false;
506 
507  for (size_t i = 0; i < a.size(); i++)
508  {
509  if (a[i] == -1) continue;
510  // 1. Defines td as triangle that is right of
511  // edge a and te as triangle is left of a,
512  td = m_line[static_cast<unsigned int>(a[i])].getRightPolygon();
513  te = m_line[static_cast<unsigned int>(a[i])].getLeftPolygon();
514 
515  // 2. Defines ai as edge a and ti as traingle td,
516  ai = a[i];
517  ti = td;
518 
519  // 3. If the triangle ti is not null, insert the edge ao of ti
520  // that is not directly connected to v in set A,
521  if (ti != -1)
522  {
523  ao = OppositeEdge(ti, v);
524  if (ao == -1)
525  //return false;
526  continue;
527  if (std::find(linids.begin(), linids.end(), ao) == linids.end())
528  linids.push_back(ao); // A = lines
529  else
530  continue;
531  }
532 
533  // 4. While ti is different of triangle te,
534  while (ti != te)
535  {
536  // 4.1. If the triangle ti is null (is in border triangulation) do:
537  if (ti == -1)
538  {
539  // 4.1.1. Defines ti as triangle te,
540  ti = te;
541  // 4.1.2. Defines te as null,
542  te = -1;
543  // 4.1.3. Defines ai as edge a,
544  ai = a[i];
545  // 4.1.4. If triangle ti is not null, insert edge ao
546  // of ti is not directly connected to v in set A,
547  if (ti != -1)
548  {
549  ao = OppositeEdge(ti, v);
550  if (ao == -1)
551  //return false;
552  break;
553  if (std::find(linids.begin(), linids.end(), ao) == linids.end())
554  linids.push_back(ao); // A = lines
555  else
556  break;
557  }
558 
559  // 4.1.5. Returns to 4.
560  continue;
561  }
562 
563  // 4.2. Defines edge aaux of ti triangle that conects the v vertice and is different of ai
564  if (!m_triang[static_cast<unsigned int>(ti)].LinesId(lids))
565  //return false;
566  break;
567 
568  for (j = 0; j < 3; j++)
569  {
570  if (lids[j] == ai)
571  continue;
572  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() == v) ||
573  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() == v))
574  break;
575  }
576  if (j == 3){
577  //return false;
578  break;
579  }
580 
581  aaux = lids[j];
582 
583  // 4.3. Defines taux as the triangle that sharing the aaux edge with ti
584  if (m_line[static_cast<unsigned int>(aaux)].getRightPolygon() == ti)
585  taux = m_line[static_cast<unsigned int>(aaux)].getLeftPolygon();
586  else if (m_line[static_cast<unsigned int>(aaux)].getLeftPolygon() == ti)
587  taux = m_line[static_cast<unsigned int>(aaux)].getRightPolygon();
588  else{
589  // return false;
590  break;
591  }
592 
593  // 4.4. Defines ti as taux triangle and ai as aaux edge
594  ti = taux;
595  ai = aaux;
596 
597  // 4.5. If ti triangle isn't NULL, insert ao edge of ti that isn't directly connected to v in A set
598  if (ti != -1)
599  {
600  ao = OppositeEdge(ti, v);
601  if (ao == -1)
602  //return false;
603  break;
604  if (std::find(linids.begin(), linids.end(), ao) == linids.end())
605  linids.push_back(ao); // A = lines
606  else
607  break;
608  }
609 
610  // 4.6. Returns to 4.
611  }
612  }
613  if (!linids.size())
614  return false;
615 
616  return true;
617 }
618 
619 int32_t te::mnt::Tin::OppositeEdge(int32_t triangId, int32_t nodeId)
620 {
621  int32_t lids[3];
622  unsigned short j;
623 
624  if (!m_triang[static_cast<unsigned int>(triangId)].LinesId(lids))
625  return -1;
626 
627  for (j = 0; j < 3; j++)
628  {
629  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() != nodeId) &&
630  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() != nodeId))
631  break;
632  }
633  if (j == 3)
634  {
635  return -1;
636  }
637 
638  return lids[j];
639 }
640 
641 std::vector<int32_t> te::mnt::Tin::FindLine(int32_t nid)
642 {
643  std::vector<int32_t> linid = m_node[static_cast<unsigned int>(nid)].getEdge();
644 
645  // Test to make sure there is no wrong index
646  for (unsigned int i = 0; i < linid.size(); i++)
647  {
648  if ((m_line[static_cast<unsigned int>(linid[i])].getNodeTo() != nid) &&
649  (m_line[static_cast<unsigned int>(linid[i])].getNodeFrom() != nid))
650  linid.erase(linid.begin()+i);
651  }
652  if (linid.size())
653  return linid;
654 
655  static int32_t oldtri = 1;
656  int32_t j, k, lids[3];
657  unsigned short m;
658  unsigned int i;
659 
660  if ((oldtri < 0) || (oldtri >= m_ltriang))
661  oldtri = 0;
662  if (oldtri == 0)
663  {
664  for (i = 0; i < static_cast<unsigned int>(m_ltriang); i++)
665  {
666  if (!m_triang[i].LinesId(lids))
667  return linid;
668  for (m = 0; m < 3; m++)
669  {
670  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == nid) ||
671  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == nid))
672  {
673  oldtri = static_cast<int32_t>(i);
674  if (m_node[static_cast<unsigned int>(nid)].setEdge(lids[m]))
675  linid.push_back(lids[m]);
676  }
677  }
678  }
679  return linid;
680  }
681 
682  j = oldtri;
683  k = oldtri + 1;
684  while ((j > 0) || (k < m_ltriang))
685  {
686  if (j > 0)
687  {
688  if (!m_triang[static_cast<unsigned int>(j)].LinesId(lids))
689  return linid;
690  for (m = 0; m < 3; m++)
691  {
692  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == nid) ||
693  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == nid))
694  {
695  oldtri = j;
696  if (m_node[static_cast<unsigned int>(nid)].setEdge(lids[m]))
697  linid.push_back(lids[m]);
698  }
699  }
700  j--;
701  }
702  if (k < m_ltriang)
703  {
704  if (!m_triang[static_cast<unsigned int>(k)].LinesId(lids))
705  return linid;
706  for (m = 0; m < 3; m++)
707  {
708  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == nid) ||
709  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == nid))
710  {
711  oldtri = k;
712  if (m_node[static_cast<unsigned int>(nid)].setEdge(lids[m]))
713  linid.push_back(lids[m]);
714  }
715  }
716  k++;
717  }
718  }
719  oldtri = 1;
720  return linid;
721 
722 }
723 
724 int32_t te::mnt::Tin::FindLine(int32_t fnid, int32_t snid)
725 {
726  static int32_t oldtri = 1;
727  int32_t i, j, k, lids[3];
728  short m;
729 
730  if ((oldtri < 0) || (oldtri >= m_ltriang))
731  oldtri = 0;
732  if (oldtri == 0)
733  {
734  for (i = 0; i < m_ltriang; i++)
735  {
736  if (!m_triang[static_cast<unsigned int>(i)].LinesId(lids))
737  return -1;
738 
739  for (m = 0; m < 3; m++)
740  {
741  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == fnid) &&
742  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == snid))
743  {
744  oldtri = i;
745  return lids[m];
746  }
747  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == fnid) &&
748  (m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == snid))
749  {
750  oldtri = i;
751  return lids[m];
752  }
753  }
754  }
755  return -1;
756  }
757  j = oldtri;
758  k = oldtri + 1;
759  while ((j > 0) || (k < m_ltriang))
760  {
761  if (j > 0)
762  {
763  if (!m_triang[static_cast<unsigned int>(j)].LinesId(lids))
764  return -1;
765 
766  for (m = 0; m < 3; m++)
767  {
768  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == fnid) &&
769  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == snid))
770  {
771  oldtri = j;
772  return lids[m];
773  }
774  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == fnid) &&
775  (m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == snid))
776  {
777  oldtri = j;
778  return lids[m];
779  }
780  }
781  j--;
782  }
783  if (k < m_ltriang)
784  {
785  if (!m_triang[static_cast<unsigned int>(k)].LinesId(lids))
786  return -1;
787 
788  for (m = 0; m < 3; m++)
789  {
790  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == fnid) &&
791  (m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == snid))
792  {
793  oldtri = k;
794  return lids[m];
795  }
796  if ((m_line[static_cast<unsigned int>(lids[m])].getNodeTo() == fnid) &&
797  (m_line[static_cast<unsigned int>(lids[m])].getNodeFrom() == snid))
798  {
799  oldtri = k;
800  return lids[m];
801  }
802  }
803  k++;
804  }
805  }
806  oldtri = 1;
807  return -1;
808 }
809 
810 bool te::mnt::Tin::NodeLines(int32_t v, std::vector<int32_t> &linids)
811 {
812  int32_t td, te, ti, taux = 0;
813  int32_t ai,
814  lids[3];
815  int32_t aaux;
816  unsigned short j;
817  std::vector<int32_t> a;
818 
819  // Find one line that contains node
820  a = FindLine(v);
821  if (!a.size())
822  return false;
823 
824  for (size_t i = 0; i < a.size(); i++)
825  {
826  // 1. Defines td as the triangle that is on the right edge a
827  // and te as the triangle that is on the left of a,
828  td = m_line[static_cast<unsigned int>(a[i])].getRightPolygon();
829  te = m_line[static_cast<unsigned int>(a[i])].getLeftPolygon();
830 
831  // 2. Defines ai as edge a and ti as triangle td,
832  ai = a[i];
833  ti = td;
834 
835  // 3. Inserts edge ai in set A,
836  if (std::find(linids.begin(), linids.end(), ai) == linids.end())
837  linids.push_back(ai); // A = linids
838  else
839  continue;
840 
841  // 4. while ti is different of triangle te,
842  while (ti != te)
843  {
844  // 4.1. If triangle ti is null (is on border of triangulation) do:
845  if (ti == -1)
846  {
847  // 4.1.1. Defines ti as triangle te,
848  ti = te;
849  // 4.1.2. Defines te as null,
850  te = -1;
851  // 4.1.3. Defines ai as edge a,
852  ai = a[i];
853  // 4.1.4. Returns to 4.
854  continue;
855  }
856 
857  // 4.2. Defines edge aaux of traingle ti that conects
858  // vertice v and is different of ai,
859  if (!m_triang[static_cast<unsigned int>(ti)].LinesId(lids))
860  break;
861  for (j = 0; j < 3; j++)
862  {
863  if (lids[j] == ai)
864  continue;
865  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() == v) ||
866  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() == v))
867  break;
868  }
869  if (j == 3){
870  break;
871  }
872 
873  aaux = lids[j];
874 
875  // 4.3. Defines taux as triangle that sharing edge aaux with ti,
876  if (m_line[static_cast<unsigned int>(aaux)].getRightPolygon() == ti)
877  taux = m_line[static_cast<unsigned int>(aaux)].getLeftPolygon();
878  else if (m_line[static_cast<unsigned int>(aaux)].getLeftPolygon() == ti)
879  taux = m_line[static_cast<unsigned int>(aaux)].getRightPolygon();
880  else{
881  break;
882  }
883 
884  // 4.4. Defines ti as triangle taux and ai as edge aaux,
885  ti = taux;
886  ai = aaux;
887 
888  // 4.5. 3. Inserta edge ai in set A,
889  if (std::find(linids.begin(), linids.end(), ai) == linids.end())
890  linids.push_back(ai); // A = linids
891  else
892  break;
893 
894  // 4.6. Returns to 4.
895  }
896  }
897  if (!linids.size())
898  return false;
899 
900  return true;
901 }
902 
903 int32_t te::mnt::Tin::NodeId(int32_t triangId, short vertex)
904 {
905  int32_t nodeids[3];
906  if (!NodesId(triangId, nodeids))
907  return -1;
908  if (vertex == -1)
909  return -1;
910  return nodeids[static_cast<unsigned int>(vertex)];
911 }
912 
913 bool te::mnt::Tin::NodesId(int32_t triangId, int32_t *nodeIds)
914 {
915  if (triangId == -1)
916  return false;
917  int32_t linesid[3];
918 
919  if (!m_triang[static_cast<unsigned int>(triangId)].LinesId(linesid))
920  return false;
921  if (m_line[static_cast<unsigned int>(linesid[0])].getNodeTo() == m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())
922  {
923  nodeIds[0] = m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom();
924  nodeIds[1] = m_line[static_cast<unsigned int>(linesid[0])].getNodeTo();
925  nodeIds[2] = m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom();
926  }
927  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeTo() == m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())
928  {
929  nodeIds[0] = m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom();
930  nodeIds[1] = m_line[static_cast<unsigned int>(linesid[0])].getNodeTo();
931  nodeIds[2] = m_line[static_cast<unsigned int>(linesid[1])].getNodeTo();
932  }
933  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom() == m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom())
934  {
935  nodeIds[0] = m_line[static_cast<unsigned int>(linesid[0])].getNodeTo();
936  nodeIds[1] = m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom();
937  nodeIds[2] = m_line[static_cast<unsigned int>(linesid[1])].getNodeTo();
938  }
939  else if (m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom() == m_line[static_cast<unsigned int>(linesid[1])].getNodeTo())
940  {
941  nodeIds[0] = m_line[static_cast<unsigned int>(linesid[0])].getNodeTo();
942  nodeIds[1] = m_line[static_cast<unsigned int>(linesid[0])].getNodeFrom();
943  nodeIds[2] = m_line[static_cast<unsigned int>(linesid[1])].getNodeFrom();
944  }
945  else
946  return false;
947  return true;
948 }
949 
950 bool te::mnt::Tin::NeighborsId(int32_t triangId, int32_t *neighsId)
951 {
952  if (triangId == -1)
953  return false;
954 
955  int32_t linesid[3];
956  unsigned short i;
957 
958  if (!m_triang[static_cast<unsigned int>(triangId)].LinesId(linesid))
959  return false;
960  for (i = 0; i < 3; i++)
961  {
962  if (linesid[i] < 0 || linesid[i] > static_cast<int32_t>(m_linesize))
963  return false;
964  if (m_line[static_cast<unsigned int>(linesid[i])].getLeftPolygon() == triangId)
965  neighsId[i] = m_line[static_cast<unsigned int>(linesid[i])].getRightPolygon();
966  else if (m_line[static_cast<unsigned int>(linesid[i])].getRightPolygon() == triangId)
967  neighsId[i] = m_line[static_cast<unsigned int>(linesid[i])].getLeftPolygon();
968  else
969  return false;
970  }
971 
972  return true;
973 }
974 
975 int32_t te::mnt::Tin::OppositeNode(int32_t triangId, int32_t linId)
976 {
977  int32_t nodtoid, nodfrid;
978  int32_t nodeids[3];
979 
980  nodtoid = m_line[static_cast<unsigned int>(linId)].getNodeTo();
981  nodfrid = m_line[static_cast<unsigned int>(linId)].getNodeFrom();
982  if (!NodesId(triangId, nodeids))
983  return -1;
984  unsigned short i;
985  for (i = 0; i < 3; i++)
986  {
987  if ((nodtoid == nodeids[i]) ||
988  (nodfrid == nodeids[i]))
989  continue;
990  break;
991  }
992  if (i == 3){
993  return 0;
994  }
995 
996  return nodeids[i];
997 }
998 
999 int32_t te::mnt::Tin::NextNode(int32_t nodeId)
1000 {
1001  if (nodeId == -1)
1002  return -1;
1003  int32_t j;
1004 
1005  if (m_node[static_cast<unsigned int>(nodeId + 1)].getType() != Deletednode)
1006  return nodeId + 1;
1007 
1008  // Search next non-deleted point
1009  for (j = 2; nodeId + j < m_lnode; j++)
1010  if (m_node[static_cast<unsigned int>(nodeId + j)].getType() != Deletednode)
1011  break;
1012  if (nodeId + j > m_lnode)
1013  return -1;
1014 
1015  return nodeId + j;
1016 }
1017 
1018 int32_t te::mnt::Tin::PreviousNode(int32_t nodeId)
1019 {
1020  if (nodeId <= 0)
1021  return -1;
1022 
1023  int32_t j;
1024 
1025  if (m_node[static_cast<unsigned int>(nodeId - 1)].getType() != Deletednode)
1026  return nodeId - 1;
1027 
1028  // Search next non-deleted point
1029  for (j = 2; nodeId - j >= 0; j++)
1030  if (m_node[static_cast<unsigned int>(nodeId - j)].getType() != Deletednode)
1031  break;
1032  if (nodeId - j < 0)
1033  return -1;
1034 
1035  return nodeId - j;
1036 }
1037 
1038 bool te::mnt::Tin::NodeNodes(int32_t v, std::vector<int32_t>& nodids)
1039 {
1040  int32_t td, te, ti,
1041  nodeid, taux = 0;
1042  int32_t ai,
1043  lids[3];
1044  int32_t aaux;
1045  unsigned short j;
1046  std::vector<int32_t> a;
1047 
1048  // Find one line that contains node
1049  a = FindLine(v);
1050  if (!a.size())
1051  return false;
1052 
1053  for (size_t i = 0; i < a.size(); i++)
1054  {
1055  // 1. Defines td as triangle that is right of
1056  // edge a and te as triangle is left of a,
1057  td = m_line[static_cast<unsigned int>(a[i])].getRightPolygon();
1058  te = m_line[static_cast<unsigned int>(a[i])].getLeftPolygon();
1059 
1060  // 2. Defines ai as edge a and ti as traingle td,
1061  ai = a[i];
1062  ti = td;
1063 
1064  // 3. Inserts the vertice is different of v conected to edge ai
1065  // in set V,
1066  nodeid = m_line[static_cast<unsigned int>(ai)].getNodeFrom();
1067  if (nodeid > 0)
1068  {
1069  if (nodeid == v)
1070  nodeid = m_line[static_cast<unsigned int>(ai)].getNodeTo();
1071  if (std::find(nodids.begin(), nodids.end(), nodeid) == nodids.end())
1072  nodids.push_back(nodeid); // V = nodids
1073  else
1074  continue;
1075  }
1076 
1077  // 4. While ti is different of triangle te,
1078  while (ti != te)
1079  {
1080  // 4.1. If the triangle ti is null (is in border triangulation) do:
1081  if (ti == -1)
1082  {
1083  // 4.1.1. Defines ti as triangle te,
1084  ti = te;
1085  // 4.1.2.Defines te as null,
1086  te = -1;
1087  // 4.1.3. Defines ai as edge a,
1088  ai = a[i];
1089  // 4.1.4. Returns to 4.
1090  break;
1091  }
1092 
1093  // 4.2. Defines edge aaux of triangle ti that connects
1094  // to vertice v and is different of ai,
1095  m_triang[static_cast<unsigned int>(ti)].LinesId(lids);
1096  for (j = 0; j < 3; j++)
1097  {
1098  if (lids[j] == ai)
1099  continue;
1100  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() == v) ||
1101  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() == v))
1102  break;
1103  }
1104  if (j == 3){
1105  break;
1106  }
1107 
1108  aaux = lids[j];
1109 
1110  // 4.3. Defines taux as triangle that sharing edge a with ti
1111  if (m_line[static_cast<unsigned int>(aaux)].getRightPolygon() == ti)
1112  taux = m_line[static_cast<unsigned int>(aaux)].getLeftPolygon();
1113  else if (m_line[static_cast<unsigned int>(aaux)].getLeftPolygon() == ti)
1114  taux = m_line[static_cast<unsigned int>(aaux)].getRightPolygon();
1115  else{
1116  break;
1117  }
1118 
1119  // 4.4. Defines ti as triangle taux and ai as edge aaux,
1120  ti = taux;
1121  ai = aaux;
1122 
1123  // 4.5. Inserts the vertice is different of v connected to edge ai in set V,
1124  nodeid = m_line[static_cast<unsigned int>(ai)].getNodeFrom();
1125  if (nodeid > 0)
1126  {
1127  if (nodeid == v)
1128  nodeid = m_line[static_cast<unsigned int>(ai)].getNodeTo();
1129  if (std::find(nodids.begin(), nodids.end(), nodeid) == nodids.end())
1130  nodids.push_back(nodeid);
1131  else
1132  break;
1133  }
1134  // 4.6. Returns to 4.
1135  }
1136  }
1137  return true;
1138 }
1139 
1140 int32_t te::mnt::Tin::NodeTriangle(int32_t v)
1141 {
1142  // Find one line that contains node
1143  std::vector<int32_t> a = FindLine(v);
1144  if (!a.size())
1145  return -1;
1146  for (size_t i = 0; i < a.size(); i++)
1147  {
1148  if (a[i] == -1)
1149  continue;
1150  int32_t td = m_line[static_cast<unsigned int>(a[i])].getRightPolygon();
1151  if (td == -1)
1152  return m_line[static_cast<unsigned int>(a[i])].getLeftPolygon();
1153  else
1154  return td;
1155  }
1156  return -1;
1157 }
1158 
1159 bool te::mnt::Tin::NodeTriangles(int32_t v, std::vector<int32_t> &triangles)
1160 {
1161  int32_t td, te, ai, ti, taux = 0,
1162  lids[3];
1163  int32_t aaux;
1164  short j;
1165  std::vector<int32_t> a;
1166  // Find one line that contains node
1167  a = FindLine(v);
1168  if (!a.size())
1169  return false;
1170 
1171  for (size_t i = 0; i < a.size(); i++)
1172  {
1173  if (a[i] == -1)
1174  continue;
1175  // 1. Defines td as triangle that is right of
1176  // edge a and te as troiangle that is left of a,
1177  td = m_line[static_cast<unsigned int>(a[i])].getRightPolygon();
1178  te = m_line[static_cast<unsigned int>(a[i])].getLeftPolygon();
1179 
1180  // 2. Defines ai as a edge and ti as td triangle,
1181  ai = a[i];
1182  ti = td;
1183 
1184  // 3. Insert triangle ti in set C if it is not null,
1185  if (ti != -1)
1186  {
1187  if (std::find(triangles.begin(), triangles.end(), ti) == triangles.end())
1188  triangles.push_back(ti); // C = triangles
1189  else
1190  continue;
1191  }
1192 
1193  // 4. while ti is different of triangle te,
1194  while (ti != te)
1195  {
1196  // 4.1. If triangle ti is null (is on border) do:
1197  if (ti == -1)
1198  {
1199  // 4.1.1. Defines ti as te,
1200  ti = te;
1201  // 4.1.2. Defines te as null,
1202  te = -1;
1203  // 4.1.3. Defines ai as edge a,
1204  ai = a[i];
1205  // 4.1.4. Insert the trinagle ti in set C if
1206  // it is not null,
1207  if (ti != -1)
1208  {
1209  if (std::find(triangles.begin(), triangles.end(), ti) == triangles.end())
1210  triangles.push_back(ti); // C = triangles
1211  else
1212  break;
1213  }
1214 
1215  // 4.1.5. returns to 4.
1216  continue;
1217  }
1218 
1219  // 4.2. Defines the edge aaux of triangle ti that conects the vertice v
1220  // and is different of ai,
1221  m_triang[static_cast<unsigned int>(ti)].LinesId(lids);
1222  for (j = 0; j < 3; j++)
1223  {
1224  if (lids[j] == ai)
1225  continue;
1226  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() == v) ||
1227  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() == v))
1228  break;
1229  }
1230  if (j == 3){
1231  break;
1232  }
1233 
1234  aaux = lids[j];
1235 
1236  // 4.3. Defines taux as triangle that sharing the
1237  // edge aaux with ti,
1238  if (m_line[static_cast<unsigned int>(aaux)].getRightPolygon() == ti)
1239  taux = m_line[static_cast<unsigned int>(aaux)].getLeftPolygon();
1240  else if (m_line[static_cast<unsigned int>(aaux)].getLeftPolygon() == ti)
1241  taux = m_line[static_cast<unsigned int>(aaux)].getRightPolygon();
1242  else{
1243  break;
1244  }
1245 
1246  // 4.4. Defines ti as triangle taux and ai as
1247  // edge aaux,
1248  ti = taux;
1249  ai = aaux;
1250 
1251  // 4.5. Inserts the triangle ti in set C if it is not null,
1252  if (ti != -1)
1253  {
1254  if (std::find(triangles.begin(), triangles.end(), ti) == triangles.end())
1255  triangles.push_back(ti); // C = triangles
1256  else
1257  break;
1258  }
1259 
1260  // 4.6. Returns to 4.
1261  }
1262  }
1263 
1264  return true;
1265 }
1266 
1268 {
1269  if (m_nodesize < nSize)
1270  {
1271  while (m_nodesize < nSize)
1272  {
1273  m_node.push_back(TinNode());
1274  m_nodesize = m_node.size();
1275  }
1276 
1277  m_triangsize = 2 * (m_nodesize)-5; // ntri = 2n-5
1278 
1279  while (m_triang.size() < m_triangsize)
1280  {
1281  m_triang.push_back(TinTriang());
1282  }
1283 
1284  m_linesize = 3 * m_nodesize; // nlin = (n-1)*3
1285 
1286  while (m_line.size() < m_linesize)
1287  {
1288  m_line.push_back(TinLine());
1289  }
1290  }
1291 
1292  return true;
1293 }
1294 
1295 
1297 {
1298  te::da::DataSetType* dsType = new te::da::DataSetType(outDsetName);
1299 
1300  //Primary key
1302  fidProperty->setAutoNumber(true);
1303  dsType->add(fidProperty);
1304 
1306  dsType->add(pkProperty);
1307 
1308  te::da::PrimaryKey* pk = new te::da::PrimaryKey(outDsetName + "_pk", dsType);
1309  pk->add(pkProperty);
1310  dsType->setPrimaryKey(pk);
1311 
1313  dsType->add(prop1);
1315  dsType->add(prop2);
1317  dsType->add(prop3);
1319  dsType->add(prop4);
1321  dsType->add(prop5);
1323  dsType->add(prop6);
1325  dsType->add(prop7);
1327  dsType->add(prop8);
1329  dsType->add(prop9);
1331  dsType->add(prop10);
1333  dsType->add(prop11);
1335  dsType->add(prop12);
1336  te::gm::GeometryProperty* geometry = new te::gm::GeometryProperty("geometry", 0, te::gm::MultiPolygonZType, true);
1337  geometry->setSRID(m_srid);
1338  dsType->add(geometry);
1339 
1340  return dsType;
1341 }
1342 
1343 
1344 bool te::mnt::Tin::SaveTin(te::da::DataSourcePtr &outDsrc, std::string &outDsetName)
1345 {
1346  te::common::TaskProgress task("Saving TIN...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_triangsize));
1347 
1348  std::unique_ptr<te::da::DataSetType> outDSType(GetDataSetType(outDsetName));
1349  std::unique_ptr<te::mem::DataSet> outDSet(new te::mem::DataSet(outDSType.get()));
1350 
1354  int32_t tEdges[3];
1355  int32_t nids[3];
1356  int32_t left[3];
1357  int32_t right[3];
1358  Ntype type[3];
1359  double value[3];
1360 
1361  for (unsigned int tri = 0; tri < m_triangsize; tri++)
1362  {
1363  if (!task.isActive())
1364  return false;
1365  task.pulse();
1366 
1367  if (!m_triang[tri].LinesId(tEdges))
1368  continue;
1369  TrianglePoints(static_cast<int32_t>(tri), vert);
1370  if (!NodesId(static_cast<int32_t>(tri), nids))
1371  continue;
1372  for (size_t e = 0; e < 3; e++)
1373  {
1374  value[e] = vert[e].getZ();
1375  left[e] = m_line[static_cast<unsigned int>(tEdges[e])].getLeftPolygon();
1376  right[e] = m_line[static_cast<unsigned int>(tEdges[e])].getRightPolygon();
1377  type[e] = m_node[static_cast<unsigned int>(nids[e])].getType();
1378  }
1379 
1380  te::mem::DataSetItem* dataSetItem = new te::mem::DataSetItem(outDSet.get());
1381  std::unique_ptr<te::gm::Polygon> p(new te::gm::Polygon(0, te::gm::PolygonZType));
1382  std::unique_ptr<te::gm::LinearRing> s(new te::gm::LinearRing(4, te::gm::LineStringZType));
1383  s->setPointN(0, vert[0]);
1384  s->setPointN(1, vert[1]);
1385  s->setPointN(2, vert[2]);
1386  s->setPointN(3, vert[0]);
1387  p->push_back(s.release());
1388  p->setSRID(m_srid);
1389 
1390  dataSetItem->setInt32(0, static_cast<int32_t>(tri)); //FID
1391  dataSetItem->setInt32(1, static_cast<int32_t>(tri)); //tri_id
1392  if (value[0] != m_nodatavalue)
1393  dataSetItem->setDouble("val1", value[0]);
1394  if (value[1] != m_nodatavalue)
1395  dataSetItem->setDouble("val2", value[1]);
1396  if (value[2] != m_nodatavalue)
1397  dataSetItem->setDouble("val3", value[2]);
1398  dataSetItem->setInt32("type1", type[0]);
1399  dataSetItem->setInt32("type2", type[1]);
1400  dataSetItem->setInt32("type3", type[2]);
1401  dataSetItem->setInt32("right1", right[0]);
1402  dataSetItem->setInt32("right2", right[1]);
1403  dataSetItem->setInt32("right3", right[2]);
1404  dataSetItem->setInt32("left1", left[0]);
1405  dataSetItem->setInt32("left2", left[1]);
1406  dataSetItem->setInt32("left3", left[2]);
1407  dataSetItem->setGeometry("geometry", static_cast<te::gm::Geometry*>(p->clone()));
1408 
1409  outDSet->add(dataSetItem);
1410 
1411  }
1412 
1413  te::vp::Save(outDsrc.get(), outDSet.get(), outDSType.get());
1414 
1415  return true;
1416 }
1417 
1418 bool fncomp(te::mnt::TinNode lhs, te::mnt::TinNode rhs) { return lhs<rhs; }
1419 
1420 struct nodecomp {
1421  bool operator() (const te::mnt::TinNode& lhs, const te::mnt::TinNode& rhs) const
1422  {
1423  return lhs<rhs;
1424  }
1425 };
1426 
1427 bool te::mnt::Tin::BuildTriangle(int32_t id, te::gm::LinearRing* lr, double *val, int32_t *right, int32_t *left, te::mnt::Ntype *type, \
1428  double zmin, double zmax, bool &first, KD_TREE &nodetree, te::sam::rtree::Index<std::size_t>& linetree)
1429 {
1430  int32_t no[3];
1431  int32_t lid[3];
1432 
1433  te::gm::Envelope e;
1434  std::vector<KD_NODE*> reportsnode;
1435  std::vector<std::size_t> reportline;
1436 
1437  for (std::size_t j = 0; j < 3; ++j) //for 3 points of triangle
1438  {
1439  TinNode nd;
1440  std::unique_ptr<te::gm::Point> p = lr->getPointN(j);
1441  val[j] = val[j] > zmax || val[j] < zmin || val[j] > std::numeric_limits< double >::max() ? m_nodatavalue : val[j];
1442 
1443  if (val[j] != m_nodatavalue)
1444  {
1445  if (val[j] < m_min)
1446  m_min = val[j];
1447  if (val[j] > m_max)
1448  m_max = val[j];
1449  }
1450  nd.Init(p->getX(), p->getY(), val[j], type[j]);
1451 
1452  te::gm::Envelope ept(*p->getMBR());
1453  nodetree.search(ept, reportsnode);
1454  size_t kn = 0;
1455  for (kn = 0; kn < reportsnode.size(); kn++) //Node already exists, gets its id
1456  {
1457  te::gm::Coord2D ind = reportsnode[kn]->getKey();
1458  if (ind.getX() == p->getX() && ind.getY() == p->getY())
1459  {
1460  no[j] = reportsnode[kn]->getData();
1461  break;
1462  }
1463  }
1464  if (kn == reportsnode.size()) //Node doesn't exist. Create new it.
1465  {
1466  no[j] = static_cast<int32_t>(m_node.size());
1467  m_node.push_back(nd);
1468  te::gm::Coord2D coord(p->getX(), p->getY());
1469  nodetree.insert(coord, no[j]);
1470  }
1471  reportsnode.clear();
1472 
1473  if (m_fbnode == 0 && nd.getType() == Breaklinefirst)
1474  m_fbnode = no[j];
1475  } //nodes
1476 
1477  if (first)
1478  {
1479  m_env = *lr->getMBR();
1480  first = false;
1481  }
1482  else
1483  m_env.Union(*lr->getMBR());
1484 
1485  TinLine tl[3];
1486  tl[0] = TinLine(no[0], no[1], left[0], right[0], Normalline);
1487  tl[1] = TinLine(no[1], no[2], left[1], right[1], Normalline);
1488  tl[2] = TinLine(no[2], no[0], left[2], right[2], Normalline);
1489  lid[0] = lid[1] = lid[2] = -1;
1490 
1491  for (unsigned int j = 0; j < 3; j++)
1492  {
1493  double x0 = m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].getX();
1494  double y0 = m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].getY();
1495  double x1 = m_node[static_cast<unsigned int>(tl[j].getNodeTo())].getX();
1496  double y1 = m_node[static_cast<unsigned int>(tl[j].getNodeTo())].getY();
1497  te::gm::Envelope e1(std::min(x0, x1), std::min(y0, y1), std::max(x0, x1), std::max(y0, y1));
1498  reportline.clear();
1499  linetree.search(e1, reportline);
1500  size_t kl = 0;
1501  for (kl = 0; kl < reportline.size(); kl++)
1502  {
1503  int32_t nd0 = m_line[reportline[kl]].getNodeFrom();
1504  int32_t nd1 = m_line[reportline[kl]].getNodeTo();
1505  if ((nd0 == tl[j].getNodeFrom() && nd1 == tl[j].getNodeTo()) || (nd1 == tl[j].getNodeFrom() && nd0 == tl[j].getNodeTo()))
1506  {
1507  lid[j] = static_cast<int32_t>(reportline[kl]);
1508  m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].setEdge(static_cast<int32_t>(reportline[kl]));
1509  m_node[static_cast<unsigned int>(tl[j].getNodeTo())].setEdge(static_cast<int32_t>(reportline[kl]));
1510  break;
1511  }
1512  }
1513  if (kl == reportline.size())
1514  {
1515  lid[j] = static_cast<int32_t>(m_line.size());
1516  m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].setEdge(static_cast<int32_t>(m_line.size()));
1517  m_node[static_cast<unsigned int>(tl[j].getNodeTo())].setEdge(static_cast<int32_t>(m_line.size()));
1518  double x0 = m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].getX();
1519  double y0 = m_node[static_cast<unsigned int>(tl[j].getNodeFrom())].getY();
1520  double x1 = m_node[static_cast<unsigned int>(tl[j].getNodeTo())].getX();
1521  double y1 = m_node[static_cast<unsigned int>(tl[j].getNodeTo())].getY();
1522  te::gm::Envelope e1(std::min(x0, x1), std::min(y0, y1), std::max(x0, x1), std::max(y0, y1));
1523  linetree.insert(e1, m_line.size());
1524  m_line.push_back(tl[j]);
1525  }
1526  reportline.clear();
1527  }
1528 
1529  while (id >= static_cast<int32_t>(m_triang.size()))
1530  m_triang.push_back(TinTriang());
1531  m_triang[static_cast<unsigned int>(id)].setEdges(lid[0], lid[1], lid[2]);
1532 
1533  return true;
1534 }
1535 
1536 /*!
1537 \brief Method used to load a triangular network (TIN) generated by QGIS
1538 \return TRUE if the TIN is loaded with no errors or FALSE otherwise
1539 */
1540 bool te::mnt::Tin::LoadTinQGIS(te::da::DataSourcePtr &inDsrc, std::string &inDsetName, double zmin, double zmax)
1541 {
1542  double val[3];
1543  int32_t id = 0;
1544  te::mnt::Ntype type[3] = { Normalnode, Normalnode, Normalnode };
1545  int32_t right[3];
1546  int32_t left[3];
1547 
1548  te::gm::Envelope e;
1549  KD_TREE nodetree(e);
1550 
1551  std::unique_ptr<te::da::DataSet> inDset = inDsrc->getDataSet(inDsetName);
1552  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
1553  std::unique_ptr<te::da::DataSetType> dsType = inDsrc.get()->getDataSetType(inDsetName);
1554  std::unique_ptr<te::gm::GeometryProperty>geomProp(te::da::GetFirstGeomProperty(dsType.get()));
1555 
1556  try
1557  {
1558  std::vector<KD_NODE*> reportsnode;
1560  std::vector<std::size_t> reportline;
1561 
1562  inDset->moveBeforeFirst();
1563  std::vector<te::gm::Polygon *> vp;
1564  bool first = true;
1565 
1566  while (inDset->moveNext())
1567  {
1568  std::unique_ptr<te::gm::Geometry> gin = inDset->getGeometry(geo_pos);
1569  if (!gin.get()->is3D())
1570  throw te::common::Exception(TE_TR("Data without 3D information!"));
1571 
1572  if ((gin->getGeomTypeId())%1000 == te::gm::MultiPolygonType)
1573  {
1574  te::gm::MultiPolygon *mg = dynamic_cast<te::gm::MultiPolygon*>(gin.get()->clone());
1575  if (!mg)
1576  throw te::common::Exception(TE_TR("Isn't possible to read data!"));
1577 
1578  std::size_t np = mg->getNumGeometries();
1579  for (std::size_t i = 0; i < np; i++)
1580  vp.push_back(dynamic_cast<te::gm::Polygon*>(mg->getGeometryN(i)));
1581  }
1582  if ((gin->getGeomTypeId()) % 1000 == te::gm::PolygonType)
1583  {
1584  te::gm::Polygon *pol = dynamic_cast<te::gm::Polygon*>(gin.get()->clone());
1585  if (!pol)
1586  throw te::common::Exception(TE_TR("Isn't possible to read data!"));
1587  vp.push_back(pol);
1588  }
1589  for (std::size_t i = 0; i < vp.size(); ++i)
1590  {
1591  te::gm::Polygon *pol = vp[i];
1592  te::gm::Curve* c = pol->getRingN(0);
1593  te::gm::LinearRing* lr = dynamic_cast<te::gm::LinearRing*>(c);
1594  right[0] = right[1] = right[2] = id;
1595  left[0] = left[1] = left[2] = -1;
1596  val[0] = lr->getZ(0);
1597  val[1] = lr->getZ(1);
1598  val[2] = lr->getZ(2);
1599  if (BuildTriangle(id, lr, val, right, left, type, zmin, zmax, first, nodetree, linetree))
1600  id++;
1601 
1602  } // for vp
1603  vp.clear();
1604  } //while (inDset->moveNext())
1605  } //try
1606  catch (te::common::Exception& ex)
1607  {
1608  std::cerr << "LoadTin: " << ex.what() << '\n';
1609  geomProp.release();
1610  dsType.release();
1611  inDset.release();
1612  throw (ex);
1613  }
1614  geomProp.release();
1615  dsType.release();
1616  inDset.release();
1617  return true;
1618 }
1619 
1620 /*!
1621 \brief Method used to load a triangular network (TIN)
1622 \return TRUE if the TIN is loaded with no errors or FALSE otherwise
1623 */
1624 bool te::mnt::Tin::LoadTin(te::da::DataSourcePtr &inDsrc, std::string &inDsetName, double zmin, double zmax)
1625 {
1626 
1627  double val[3];
1628  te::mnt::Ntype type[3];
1629  int32_t right[3];
1630  int32_t left[3];
1631  int32_t id;
1632 
1633  std::unique_ptr<te::da::DataSet> inDset = inDsrc->getDataSet(inDsetName);
1634  std::string geo_attr("tri_id");
1635  const std::size_t np = inDset->getNumProperties();
1636  m_triangsize = inDset->size();
1637 
1638 
1639  // Open tin nodes file for nodes data load
1640  m_fbnode = 0;
1641 
1642  std::vector<std::string>pnames;
1643  std::vector<int> ptypes;
1644  bool isTeTIN = false;
1645  for (std::size_t i = 0; i != np; ++i)
1646  {
1647  if (boost::iequals(inDset->getPropertyName(i), geo_attr))
1648  isTeTIN = true;
1649  pnames.push_back(inDset->getPropertyName(i));
1650  ptypes.push_back(inDset->getPropertyDataType(i));
1651  }
1652 
1653  if (!isTeTIN)
1654  {
1655  try
1656  {
1657  LoadTinQGIS(inDsrc, inDsetName, zmin, zmax);
1658  }
1659  catch (te::common::Exception& e)
1660  {
1661  throw (e);
1662  }
1663 
1664  m_nodesize = m_node.size();
1665  m_lnode = static_cast<int32_t>(m_nodesize);
1666  m_linesize = m_line.size();
1667  m_lline = static_cast<int32_t>(m_linesize);
1668  m_triangsize = m_triang.size();
1669  m_ltriang = static_cast<int32_t>(m_triangsize);
1670 
1671  return true;
1672  }
1673 
1674  te::gm::Envelope e;
1675  KD_TREE nodetree(e);
1677 
1678  te::common::TaskProgress task("Loading TIN...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_triangsize));
1679 
1680  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
1681 
1682  inDset->moveBeforeFirst();
1683 
1684  bool first = true;
1685 
1686  while (inDset->moveNext())
1687  {
1688  if (!task.isActive())
1689  return false;
1690  task.pulse();
1691 
1692  id = inDset->getInt32(1);
1693  if (inDset->isNull("val1"))
1694  val[0] = m_nodatavalue;
1695  else
1696  val[0] = inDset->getDouble("val1");
1697  if (inDset->isNull("val2"))
1698  val[1] = m_nodatavalue;
1699  else
1700  val[1] = inDset->getDouble("val2");
1701  if (inDset->isNull("val3"))
1702  val[2] = m_nodatavalue;
1703  else
1704  val[2] = inDset->getDouble("val3");
1705 
1706  type[0] = static_cast<Ntype>(inDset->getInt32("type1"));
1707  type[1] = static_cast<Ntype>(inDset->getInt32("type2"));
1708  type[2] = static_cast<Ntype>(inDset->getInt32("type3"));
1709  right[0] = inDset->getInt32("right1");
1710  right[1] = inDset->getInt32("right2");
1711  right[2] = inDset->getInt32("right3");
1712  left[0] = inDset->getInt32("left1");
1713  left[1] = inDset->getInt32("left2");
1714  left[2] = inDset->getInt32("left3");
1715 
1716  std::unique_ptr<te::gm::Geometry> gin = inDset->getGeometry(geo_pos);
1717  te::gm::Polygon *g = dynamic_cast<te::gm::Polygon*>(gin.get());
1718  if (!g)
1719  {
1720  te::gm::GeometryCollection *mg = dynamic_cast<te::gm::GeometryCollection*>(gin.get());
1721  g = dynamic_cast<te::gm::Polygon*>(mg->getGeometryN(0));
1722  if (!g)
1723  return false;
1724  }
1725  te::gm::Curve* c = g->getRingN(0);
1726  te::gm::LinearRing* lr = dynamic_cast<te::gm::LinearRing*>(c);
1727 
1728  BuildTriangle(id, lr, val, right, left, type, zmin, zmax, first, nodetree, linetree);
1729 
1730  } //while (inDset->moveNext())
1731 
1732  m_nodesize = m_node.size();
1733  m_lnode = static_cast<int32_t>(m_nodesize);
1734  m_linesize = m_line.size();
1735  m_lline = static_cast<int32_t>(m_linesize);
1736  m_triangsize = m_triang.size();
1737  m_ltriang = static_cast<int32_t>(m_triangsize);
1738 
1739  return true;
1740 }
1741 
1742 
1744 {
1745  // Calculate first derivatives on triangles
1746  if (!TriangleFirstDeriv())
1747  return false;
1748 
1749  //Calculate first derivatives on nodes
1750  if (!NodeFirstDeriv())
1751  return false;
1752 
1753  // Calculate second derivatives on triangles
1754  if (!TriangleSecondDeriv())
1755  return false;
1756 
1757  // Calculate second derivatives on nodes
1758  if (!NodeSecondDeriv())
1759  return false;
1760 
1761  if (m_fbnode > 0)
1762  {
1763  // If there are breaklines
1764  // Calculate first derivatives on breaklines nodes
1765  if (!BreakNodeFirstDeriv())
1766  return false;
1767 
1768  // Calculate second derivatives on triangles that touch breaklines
1769  if (!BreakTriangleSecondDeriv())
1770  return false;
1771 
1772  // Calculate second derivatives on breaklines nodes
1773  if (!BreakNodeSecondDeriv())
1774  return false;
1775  }
1776 
1777  return true;
1778 }
1779 
1781 {
1785  double nvector[3];
1786  double m1, m2;
1787  int32_t nodesid[3];
1788  short j;
1789  size_t i;
1790  double tol = .01;
1791 
1792  // Create and Initialize first derivatives vector
1793  if (m_tfderiv.size())
1794  {
1795  m_tfderiv.clear();
1796  }
1797 
1798  for (i = 0; i < m_triangsize + 1; i++)
1799  {
1801  pt.setX(m_nodatavalue);
1802  pt.setY(0.);
1803  pt.setZ(0.);
1804  m_tfderiv.push_back(pt);
1805  }
1806 
1807  te::common::TaskProgress task("Creating triangle first derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_ltriang));
1808 
1809  for (i = 0; i <static_cast<unsigned int>(m_ltriang); i++)
1810  {
1811  if (!task.isActive())
1812  return false;
1813  task.pulse();
1814  if (!NodesId(static_cast<int32_t>(i), nodesid))
1815  {
1816  m_tfderiv[i].setY(m_nodatavalue);
1817  continue;
1818  }
1819 
1820  for (j = 0; j < 3; j++)
1821  {
1822  p3da[j].setX(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getX());
1823  p3da[j].setY(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getY());
1824  p3da[j].setZ(m_node[static_cast<unsigned int>(nodesid[j])].getZ());
1825  }
1826 
1827  // Special cases
1828  if ((p3da[0].getZ() >= m_nodatavalue) || (p3da[1].getZ() >= m_nodatavalue) ||
1829  (p3da[2].getZ() >= m_nodatavalue))
1830  {
1831  // Triangle with DUMMY Value
1832  m_tfderiv[i].setY(m_nodatavalue);
1833  continue;
1834  }
1835 
1836  m1 = m2 = m_nodatavalue;
1837 
1838  if ((p3da[1].getY() - p3da[0].getY()) != 0.0)
1839  m1 = (p3da[1].getX() - p3da[0].getX()) / (p3da[1].getY() - p3da[0].getY());
1840 
1841  if ((p3da[2].getY() - p3da[0].getY()) != 0.0)
1842  m2 = (p3da[2].getX() - p3da[0].getX()) / (p3da[2].getY() - p3da[0].getY());
1843 
1844  if (fabs(m1 - m2) < tol)
1845  {
1846  // Triangle with DUMMY Value
1847  m_tfderiv[i].setY(m_nodatavalue);
1848  continue;
1849  }
1850 
1851  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
1852  {
1853  // Triangle parallel to XY plane
1854  m_tfderiv[i].setX(0.);
1855  continue;
1856  }
1857 
1858  // Calculate vector normal to triangle
1859  triangleNormalVector(p3da, nvector);
1860  m_tfderiv[i].setX(-nvector[0] / nvector[2]);
1861  m_tfderiv[i].setY(-nvector[1] / nvector[2]);
1862  }
1863 
1864  return true;
1865 }
1866 
1868 {
1872  double nvector[3];
1873  double dxy, dyx;
1874  double m1, m2;
1875  double tol = .01;
1876  int32_t nodesid[3];
1877 
1878  // Create and Initialize second derivatives vector
1879  if (!m_nfderiv.size())
1880  return false;
1881  if (m_tsderiv.size())
1882  {
1883  m_tsderiv.clear();
1884  }
1885 
1886  te::common::TaskProgress task("Creating triangle second derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_ltriang));
1887  size_t i;
1888  for (i = 0; i < m_triangsize + 1; i++)
1889  {
1890  m_tsderiv.push_back(TinNode());
1891 
1893  pt.setX(m_nodatavalue);
1894  pt.setY(m_nodatavalue);
1895  pt.setZ(0.);
1896 
1897  m_tsderiv[i].setNPoint(pt);
1898  }
1899 
1900  for (i = 0; i < static_cast<unsigned int>(m_ltriang); i++)
1901  {
1902  if (!task.isActive())
1903  return false;
1904  task.pulse();
1905  if (!NodesId(static_cast<int32_t>(i), nodesid))
1906  {
1907  m_tsderiv[i].setZ(m_nodatavalue);
1908  continue;
1909  }
1910 
1911  // Special case
1912  if ((m_nfderiv[static_cast<unsigned int>(nodesid[0])].getX() >= m_nodatavalue) ||
1913  (m_nfderiv[static_cast<unsigned int>(nodesid[1])].getX() >= m_nodatavalue) ||
1914  (m_nfderiv[static_cast<unsigned int>(nodesid[2])].getX() >= m_nodatavalue) ||
1915  (m_node[static_cast<unsigned int>(nodesid[0])].getZ() >= m_nodatavalue) ||
1916  (m_node[static_cast<unsigned int>(nodesid[1])].getZ() >= m_nodatavalue) ||
1917  (m_node[static_cast<unsigned int>(nodesid[2])].getZ() >= m_nodatavalue))
1918  {
1919  // Triangle with DUMMY Value
1920  m_tsderiv[i].setZ(m_nodatavalue);
1921  continue;
1922  }
1923 
1924  m1 = m2 = m_nodatavalue;
1925 
1926  if ((m_nfderiv[static_cast<unsigned int>(nodesid[1])].getY() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getY()) != 0.0)
1927  m1 = (m_nfderiv[static_cast<unsigned int>(nodesid[1])].getX() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getX()) /
1928  (m_nfderiv[static_cast<unsigned int>(nodesid[1])].getY() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getY());
1929 
1930  if ((m_nfderiv[static_cast<unsigned int>(nodesid[2])].getY() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getY()) != 0.0)
1931  m2 = (m_nfderiv[static_cast<unsigned int>(nodesid[2])].getX() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getX()) /
1932  (m_nfderiv[static_cast<unsigned int>(nodesid[2])].getY() - m_nfderiv[static_cast<unsigned int>(nodesid[0])].getY());
1933 
1934  if (fabs(m1 - m2) < tol)
1935  {
1936  // Triangle with DUMMY Value
1937  m_tsderiv[i].setZ(m_nodatavalue);
1938  continue;
1939  }
1940 
1941  // Calculate using dx
1942  for (unsigned short j = 0; j < 3; j++)
1943  {
1944  p3da[j].setX(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getX());
1945  p3da[j].setY(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getY());
1946  p3da[j].setZ(m_nfderiv[static_cast<unsigned int>(nodesid[j])].getX());
1947  }
1948 
1949  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
1950  {
1951  m_tsderiv[i].setX(0.);
1952  dxy = 0.;
1953  }
1954  else
1955  {
1956  triangleNormalVector(p3da, nvector);
1957  m_tsderiv[i].setX(-nvector[0] / nvector[2]);
1958  dxy = (-nvector[1] / nvector[2]);
1959  }
1960 
1961  // Calculate using dy
1962  for (unsigned int j = 0; j < 3; j++)
1963  p3da[j].setZ(m_nfderiv[static_cast<unsigned int>(nodesid[j])].getY());
1964 
1965  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
1966  {
1967  m_tsderiv[i].setY(0.);
1968  dyx = 0.;
1969  }
1970  else
1971  {
1972  triangleNormalVector(p3da, nvector);
1973  m_tsderiv[i].setY(-nvector[1] / nvector[2]);
1974  dyx = (-nvector[0] / nvector[2]);
1975  }
1976  m_tsderiv[i].setZ((dxy + dyx) / 2.);
1977  }
1978 
1979  return true;
1980 }
1981 
1982 
1984 {
1985  int32_t clstnids[CLNODES];
1986  size_t i;
1987 
1988  // Create and Initialize first derivatives vector
1989  if (m_nfderiv.size())
1990  {
1991  m_nfderiv.clear();
1992  }
1993  for (i = 0; i < m_nodesize + 1; i++)
1994  {
1996  pt.setX(0.);
1997  pt.setY(0.);
1998  pt.setZ(0.);
1999  m_nfderiv.push_back(pt);
2000  }
2001 
2002  te::common::TaskProgress task("Creating node first derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_node.size()));
2003 
2004  // To each node
2005  for (i = 0; i < m_node.size(); i++)
2006  {
2007  if (!task.isActive())
2008  return false;
2009  task.pulse();
2010  // Special cases
2011  if (m_node[i].getZ() >= m_nodatavalue)
2012  continue;
2013  if (m_node[i].getType() == Deletednode)
2014  // If deleted node
2015  continue;
2016 
2017  // Look for closest points of the node
2018  if (!NodeClosestPoints(static_cast<int32_t>(i), clstnids))
2019  continue;
2020  m_nfderiv[i] = CalcNodeFirstDeriv(static_cast<int32_t>(i), clstnids);
2021  }
2022 
2023 
2024  return true;
2025 }
2026 
2028 {
2029  size_t i;
2030  int32_t clstnids[CLNODES];
2031  TinNode sderiv;
2032 
2033  if (!m_tsderiv.size())
2034  return false;
2035  // Create and Initialize second derivatives vector
2036  if (m_nsderiv.size())
2037  {
2038  m_nsderiv.clear();
2039  }
2040 
2041  for (i = 0; i < m_nodesize + 1; i++)
2042  {
2043  m_nsderiv.push_back(TinNode());
2044  m_nsderiv[i].Init(0., 0., 0.);
2045  }
2046 
2047  te::common::TaskProgress task("Creating node second derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_node.size()));
2048  for (i = 0; i < m_node.size(); i++)
2049  {
2050  if (!task.isActive())
2051  return false;
2052  task.pulse();
2053  // Special cases
2054  if (m_node[i].getZ() >= m_nodatavalue)
2055  // Node with DUMMY value
2056  continue;
2057  if (m_node[i].getType() == Deletednode)
2058  // Deleted node
2059  continue;
2060 
2061  // Look for closest point of the node
2062  if (!NodeClosestPoints(static_cast<int32_t>(i), clstnids))
2063  continue;
2064  sderiv = CalcNodeSecondDeriv(static_cast<int32_t>(i), clstnids);
2065  m_nsderiv[i].setX(sderiv.getX());
2066  m_nsderiv[i].setY(sderiv.getY());
2067  m_nsderiv[i].setZ(sderiv.getZ());
2068  }
2069 
2070  return true;
2071 }
2072 
2073 bool te::mnt::Tin::NodeClosestPoints(int32_t nid, int32_t *clstNids, bool useBrNode)
2074 {
2075  int32_t lineid;
2076  size_t j, k;
2077  double dist, distv[CLNODES];
2078  int32_t nodeid;
2079 
2080  // Find one line that contains node
2081  std::vector<int32_t> lineids = FindLine(nid);
2082  if (!lineids.size())
2083  return false;
2084 
2085  for (j = 0; j < CLNODES; j++)
2086  {
2087  distv[j] = m_nodatavalue;
2088  clstNids[j] = -1;
2089  }
2090 
2091  for (size_t i = 0; i < lineids.size(); i++)
2092  {
2093  if (lineids[i] == -1)
2094  continue;
2095 
2096  lineid = lineids[i];
2097 
2098  if (m_line[static_cast<unsigned int>(lineid)].getNodeFrom() == nid)
2099  nodeid = m_line[static_cast<unsigned int>(lineid)].getNodeTo();
2100  else if (m_line[static_cast<unsigned int>(lineid)].getNodeTo() == nid)
2101  nodeid = m_line[static_cast<unsigned int>(lineid)].getNodeFrom();
2102  else
2103  continue;
2104 
2105  if ((m_node[static_cast<unsigned int>(nodeid)].getZ() < m_nodatavalue) && ((useBrNode) ||
2106  ((useBrNode) && (nodeid < m_fbnode))))
2107  {
2108  dist = (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) *
2109  (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) +
2110  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY()) *
2111  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY());
2112  for (j = 0; j < CLNODES; j++)
2113  {
2114  if (dist < distv[j])
2115  {
2116  for (k = CLNODES - 1; k > j; k--)
2117  {
2118  distv[k] = distv[k - 1];
2119  clstNids[k] = clstNids[k - 1];
2120  }
2121  distv[j] = dist;
2122  clstNids[j] = nodeid;
2123  break;
2124  }
2125  }
2126  }
2127  }
2128 
2129  return true;
2130 }
2131 
2132 te::gm::Point te::mnt::Tin::CalcNodeFirstDeriv(int32_t nodeId, int32_t clstNodes[CLNODES])
2133 {
2134  size_t j, k;
2139  double nvector[3], tnx, tny, tnz;
2140  double m1, m2;
2141  double tol = .01;
2142 
2143  p3da[0].setX(m_node[static_cast<unsigned int>(nodeId)].getNPoint().getX());
2144  p3da[0].setY(m_node[static_cast<unsigned int>(nodeId)].getNPoint().getY());
2145  p3da[0].setZ(m_node[static_cast<unsigned int>(nodeId)].getZ());
2146 
2147  tnx = 0.;
2148  tny = 0.;
2149  tnz = 0.;
2150  for (j = 0; j < CLNODES; j++)
2151  {
2152  if (clstNodes[j] == -1)
2153  break;
2154  p3da[1].setX(m_node[static_cast<unsigned int>(clstNodes[j])].getNPoint().getX());
2155  p3da[1].setY(m_node[static_cast<unsigned int>(clstNodes[j])].getNPoint().getY());
2156  p3da[1].setZ(m_node[static_cast<unsigned int>(clstNodes[j])].getZ());
2157  for (k = j + 1; k < CLNODES; k++)
2158  {
2159  if (clstNodes[k] == -1)
2160  break;
2161  p3da[2].setX(m_node[static_cast<unsigned int>(clstNodes[k])].getNPoint().getX());
2162  p3da[2].setY(m_node[static_cast<unsigned int>(clstNodes[k])].getNPoint().getY());
2163  p3da[2].setZ(m_node[static_cast<unsigned int>(clstNodes[k])].getZ());
2164 
2165  // Special cases
2166  m1 = m2 = m_nodatavalue;
2167 
2168  if ((p3da[1].getY() - p3da[0].getY()) != 0.0)
2169  m1 = (p3da[1].getX() - p3da[0].getX()) / (p3da[1].getY() - p3da[0].getY());
2170 
2171  if ((p3da[2].getY() - p3da[0].getY()) != 0.0)
2172  m2 = (p3da[2].getX() - p3da[0].getX()) / (p3da[2].getY() - p3da[0].getY());
2173 
2174  if (fabs(m1 - m2) < tol)
2175  continue;
2176 
2177  if ((p3da[0].getZ() >= m_nodatavalue) || (p3da[1].getZ() >= m_nodatavalue) ||
2178  (p3da[2].getZ() >= m_nodatavalue))
2179  continue;
2180 
2181  if ((p3da[0].getZ() == p3da[1].getZ()) &&
2182  (p3da[0].getZ() == p3da[2].getZ()))
2183  continue;
2184 
2185  triangleNormalVector(p3da, nvector);
2186  tnx += nvector[0];
2187  tny += nvector[1];
2188  tnz += nvector[2];
2189  }
2190 
2191  }
2192  // Calculate node first derivatives
2193  if (tnz != 0.)
2194  {
2195  deriv.setX(-tnx / tnz);
2196  deriv.setY(-tny / tnz);
2197  }
2198  else
2199  {
2200  deriv.setX(0.);
2201  deriv.setY(0.);
2202  }
2203  return deriv;
2204 }
2205 
2207  int32_t clstNIds[CLNODES])
2208 {
2212  double tnxx, tnxy, tnxz, tnyx, tnyy, tnyz,
2213  nvector[3], m1, m2;
2214  double tol = .01;
2215  unsigned int j, k;
2216  TinNode sderiv;
2217 
2218  p3da[0].setX(m_node[static_cast<unsigned int>(nodeId)].getNPoint().getX());
2219  p3da[0].setY(m_node[static_cast<unsigned int>(nodeId)].getNPoint().getY());
2220  p3da[0].setZ(m_nfderiv[static_cast<unsigned int>(nodeId)].getX());
2221 
2222  tnxx = 0.;
2223  tnxy = 0.;
2224  tnxz = 0.;
2225  tnyx = 0.;
2226  tnyy = 0.;
2227  tnyz = 0.;
2228 
2229  for (j = 0; j < static_cast<unsigned int>(CLNODES); j++)
2230  {
2231  if (clstNIds[j] == -1)
2232  break;
2233  p3da[1].setX(m_node[static_cast<unsigned int>(clstNIds[j])].getNPoint().getX());
2234  p3da[1].setY(m_node[static_cast<unsigned int>(clstNIds[j])].getNPoint().getY());
2235  p3da[1].setZ(m_nfderiv[static_cast<unsigned int>(clstNIds[j])].getX());
2236  for (k = j + 1; k < CLNODES; k++)
2237  {
2238  if (clstNIds[k] == -1)
2239  break;
2240  p3da[2].setX(m_node[static_cast<unsigned int>(clstNIds[k])].getNPoint().getX());
2241  p3da[2].setY(m_node[static_cast<unsigned int>(clstNIds[k])].getNPoint().getY());
2242  p3da[2].setZ(m_nfderiv[static_cast<unsigned int>(clstNIds[k])].getX());
2243 
2244  m1 = m2 = m_nodatavalue;
2245 
2246  if ((p3da[1].getY() - p3da[0].getY()) != 0.0)
2247  m1 = (p3da[1].getX() - p3da[0].getX()) / (p3da[1].getY() - p3da[0].getY());
2248 
2249  if ((p3da[2].getY() - p3da[0].getY()) != 0.0)
2250  m2 = (p3da[2].getX() - p3da[0].getX()) / (p3da[2].getY() - p3da[0].getY());
2251 
2252  if (fabs(m1 - m2) < tol) continue;
2253 
2254  if ((p3da[0].getZ() >= m_nodatavalue) ||
2255  (p3da[1].getZ() >= m_nodatavalue) ||
2256  (p3da[2].getZ() >= m_nodatavalue))
2257  // Triangle with DUMMY Value
2258  continue;
2259  if ((p3da[0].getZ() == p3da[1].getZ()) &&
2260  (p3da[0].getZ() == p3da[2].getZ()))
2261  // Triangle parallel to XY plane
2262  continue;
2263 
2264  triangleNormalVector(p3da, nvector);
2265  tnxx += nvector[0];
2266  tnxy += nvector[1];
2267  tnxz += nvector[2];
2268  }
2269  }
2270  p3da[0].setZ(m_nfderiv[static_cast<unsigned int>(nodeId)].getY());
2271  for (j = 0; j < CLNODES; j++)
2272  {
2273  if (clstNIds[j] == -1)
2274  break;
2275  p3da[1].setX(m_node[static_cast<unsigned int>(clstNIds[j])].getNPoint().getX());
2276  p3da[1].setY(m_node[static_cast<unsigned int>(clstNIds[j])].getNPoint().getY());
2277  p3da[1].setZ(m_nfderiv[static_cast<unsigned int>(clstNIds[j])].getY());
2278  for (k = j + 1; k < CLNODES; k++)
2279  {
2280  if (clstNIds[k] == -1)
2281  break;
2282  p3da[2].setX(m_node[static_cast<unsigned int>(clstNIds[k])].getNPoint().getX());
2283  p3da[2].setY(m_node[static_cast<unsigned int>(clstNIds[k])].getNPoint().getY());
2284  p3da[2].setZ(m_nfderiv[static_cast<unsigned int>(clstNIds[k])].getY());
2285 
2286  m1 = m2 = m_nodatavalue;
2287 
2288  if ((p3da[1].getY() - p3da[0].getY()) != 0.0)
2289  m1 = (p3da[1].getX() - p3da[0].getX()) / (p3da[1].getY() - p3da[0].getY());
2290 
2291  if ((p3da[2].getY() - p3da[0].getY()) != 0.0)
2292  m2 = (p3da[2].getX() - p3da[0].getX()) / (p3da[2].getY() - p3da[0].getY());
2293 
2294  if (fabs(m1 - m2) < tol)
2295  continue;
2296 
2297  if ((p3da[0].getZ() >= m_nodatavalue) ||
2298  (p3da[1].getZ() >= m_nodatavalue) ||
2299  (p3da[2].getZ() >= m_nodatavalue))
2300  continue;
2301  if ((p3da[0].getZ() == p3da[1].getZ()) &&
2302  (p3da[0].getZ() == p3da[2].getZ()))
2303  continue;
2304 
2305  triangleNormalVector(p3da, nvector);
2306  tnyx += nvector[0];
2307  tnyy += nvector[1];
2308  tnyz += nvector[2];
2309  }
2310  }
2311  // Calculate node second derivatives
2312  if (tnxz != 0.)
2313  {
2314  sderiv.setX(-tnxx / tnxz);
2315  tnxy = -tnxy / tnxz;
2316  }
2317  else
2318  tnxy = 0.;
2319  if (tnyz != 0.)
2320  {
2321  sderiv.setY(-tnyy / tnyz);
2322  tnyx = -tnyx / tnyz;
2323  }
2324  else
2325  tnyx = 0.;
2326 
2327  sderiv.setZ((tnxy + tnyx) / 2.);
2328 
2329  return sderiv;
2330 }
2331 
2332 
2333 bool ::te::mnt::Tin::BreakNodeFirstDeriv()
2334 {
2335  size_t i, bnodesize,
2336  node1, node2;
2337  int32_t rclstnids[CLNODES], lclstnids[CLNODES];
2338  double deltax, deltay,
2339  sintheta, costheta, modxy,
2340  dzds, dzdt, dzdx, dzdy;
2341  te::gm::Point rderiv(0, te::gm::PointZType);
2342  te::gm::Point lderiv(0, te::gm::PointZType);
2343 
2344  if (!m_tfderiv.size())
2345  return false;
2346  // Create and Initialize first derivatives vector
2347  bnodesize = static_cast<unsigned int>(m_lnode - m_fbnode);
2348  if (m_nbrfderiv.size())
2349  {
2350  m_nbrfderiv.clear();
2351  }
2352 
2353  for (i = 0; i < bnodesize + 1; i++)
2354  {
2355  m_nbrfderiv.push_back(m_nfderiv[i + static_cast<unsigned long>(m_fbnode)]);
2356  m_nblfderiv.push_back(m_nfderiv[i + static_cast<unsigned long>(m_fbnode)]);
2357  }
2358 
2359  te::common::TaskProgress task("Creating breaknode first derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_node.size()));
2360 
2361  // To each break node
2362  for (i = static_cast<unsigned int>(m_fbnode); i < m_node.size() - 1; i++)
2363  {
2364  if (!task.isActive())
2365  return false;
2366  task.pulse();
2367  // Special cases
2368  if ((m_node[i].getZ() >= m_nodatavalue) ||
2369  (m_node[i].getType() == Deletednode) ||
2370  (m_node[i].getType() > Breaklinenormal))
2371  continue;
2372 
2373  // Look for triangles that sharing the node
2374  BreakNodeClosestPoints(static_cast<int32_t>(i), rclstnids, lclstnids);
2375  rderiv = CalcNodeFirstDeriv(static_cast<int32_t>(i), rclstnids);
2376  lderiv = CalcNodeFirstDeriv(static_cast<int32_t>(i), lclstnids);
2377 
2378  node1 = static_cast<unsigned int>(NextNode(static_cast<int32_t>(i)));
2379  node2 = static_cast<unsigned int>(PreviousNode(static_cast<int32_t>(i)));
2380 
2381  deltax = m_node[node1].getX() - m_node[node2].getX();
2382  deltay = m_node[node1].getY() - m_node[node2].getY();
2383  modxy = sqrt(deltax*deltax + deltay*deltay);
2384  costheta = deltax / modxy;
2385  sintheta = deltay / modxy;
2386 
2387  if (m_nfderiv[i].getX() >= m_nodatavalue)
2388  dzds = 0.;
2389  else
2390  dzds = costheta*m_nfderiv[i].getX() -
2391  sintheta*m_nfderiv[i].getY();
2392 
2393  if (rderiv.getX() >= m_nodatavalue)
2394  dzdt = 0.;
2395  else
2396  dzdt = sintheta*rderiv.getX() +
2397  costheta*rderiv.getY();
2398  dzdx = costheta*dzds + sintheta*dzdt;
2399  dzdy = -sintheta*dzds + costheta*dzdt;
2400  m_nbrfderiv[i - static_cast<unsigned long>(m_fbnode)].setX(dzdx);
2401  m_nbrfderiv[i - static_cast<unsigned long>(m_fbnode)].setY(dzdy);
2402 
2403  if (lderiv.getX() >= m_nodatavalue)
2404  dzdt = 0.;
2405  else
2406  dzdt = sintheta*lderiv.getX() +
2407  costheta*lderiv.getY();
2408  dzdx = costheta*dzds + sintheta*dzdt;
2409  dzdy = -sintheta*dzds + costheta*dzdt;
2410  m_nblfderiv[i - static_cast<unsigned long>(m_fbnode)].setX(dzdx);
2411  m_nblfderiv[i - static_cast<unsigned long>(m_fbnode)].setY(dzdy);
2412  }
2413 
2414  return true;
2415 }
2416 
2418 {
2419  size_t i;
2420  std::vector<int32_t> rightri, leftri;
2421 
2422  // Create and Initialize second derivatives vector
2423  if ((!m_nbrfderiv.size()) || (!m_nblfderiv.size()))
2424  return false;
2425  if (!m_tsderiv.size())
2426  return false;
2427 
2428  te::common::TaskProgress task("Creating breaknode second derivatives...", te::common::TaskProgress::UNDEFINED, static_cast<int>(m_node.size()));
2429  // To each break node except first and last
2430  for (i = static_cast<unsigned int>(m_fbnode); i < m_node.size() - 1; i++)
2431  {
2432  if (!task.isActive())
2433  return false;
2434  task.pulse();
2435  if (m_node[i].getZ() >- m_nodatavalue)
2436  continue;
2437 
2438  // If first or last point of a breakline
2439  if ((m_node[i].getType() == Breaklinefirst) ||
2440  (m_node[i].getType() == Breaklinelast) ||
2441  (m_node[i].getType() == Deletednode))
2442  continue;
2443 
2444  // Look for triangles that sharing the node
2445  NodeTriangles(static_cast<int32_t>(i), rightri, leftri);
2446 
2447  // Calculate second derivative of node using right side triangles
2448  CalcTriangleSecondDeriv(rightri, m_nbrfderiv);
2449 
2450  // Calculate second derivative of node using left side triangles
2451  CalcTriangleSecondDeriv(leftri, m_nblfderiv);
2452 
2453  rightri.clear();
2454  leftri.clear();
2455  }
2456 
2457  return true;
2458 }
2459 
2460 bool te::mnt::Tin::NodeTriangles(int32_t nodeid, std::vector<int32_t> &rightri, std::vector<int32_t> &leftri)
2461 {
2462  int32_t rtri, ltri;
2463  int32_t lids[3], linid;
2464  short k;
2465 
2466  lids[0] = lids[1] = lids[2] = -1;
2467 
2468  // Find one line that contains node
2469  std::vector<int32_t> fline = FindLine(nodeid);
2470  if (!fline.size())
2471  return false;
2472 
2473  for (size_t i = 0; i < fline.size(); i++)
2474  {
2475  linid = fline[i];
2476 
2477  ltri = m_line[static_cast<unsigned int>(linid)].getLeftPolygon();
2478  rtri = m_line[static_cast<unsigned int>(linid)].getRightPolygon();
2479  if (rtri == -1)
2480  {
2481  rtri = ltri;
2482  ltri = -1;
2483  }
2484 
2485  // While right side triangle different from left side<br>
2486  while (rtri != ltri)
2487  {
2488  if (m_line[static_cast<unsigned int>(linid)].getNodeTo() == nodeid)
2489  {
2490  rightri.push_back(m_line[static_cast<unsigned int>(linid)].getRightPolygon());
2491  }
2492  else if (m_line[static_cast<unsigned int>(linid)].getNodeFrom() == nodeid)
2493  {
2494  leftri.push_back(m_line[static_cast<unsigned int>(linid)].getLeftPolygon());
2495  }
2496 
2497  // Find line that contains node in the right triangle
2498  if (rtri >= 0)
2499  if (!m_triang[static_cast<unsigned int>(rtri)].LinesId(lids))
2500  break;
2501 
2502  for (k = 0; k < 3; k++)
2503  {
2504  if (lids[k] == linid || lids[k] == -1)
2505  continue;
2506  if ((m_line[static_cast<unsigned int>(lids[k])].getNodeFrom() == nodeid) ||
2507  (m_line[static_cast<unsigned int>(lids[k])].getNodeTo() == nodeid))
2508  break;
2509  }
2510  if (k == 3){
2511  break;
2512  }
2513 
2514  // Make right triangle equal to the triangle at the
2515  // other side
2516  linid = lids[k];
2517  if (m_line[static_cast<unsigned int>(linid)].getRightPolygon() == rtri)
2518  rtri = m_line[static_cast<unsigned int>(linid)].getLeftPolygon();
2519  else if (m_line[static_cast<unsigned int>(linid)].getLeftPolygon() == rtri)
2520  rtri = m_line[static_cast<unsigned int>(linid)].getRightPolygon();
2521  else
2522  break;
2523  if (rtri == -1)
2524  {
2525  rtri = ltri;
2526  ltri = -1;
2527  linid = fline[i];
2528  }
2529  }
2530  // Insert left side triangle in triangle list
2531  if (ltri != -1)
2532  {
2533  if (m_line[static_cast<unsigned int>(linid)].getNodeTo() == nodeid)
2534  {
2535  rightri.push_back(m_line[static_cast<unsigned int>(linid)].getRightPolygon());
2536  }
2537  if (m_line[static_cast<unsigned int>(linid)].getNodeFrom() == nodeid)
2538  {
2539  leftri.push_back(m_line[static_cast<unsigned int>(linid)].getLeftPolygon());
2540  }
2541  }
2542  }
2543 
2544  return true;
2545 }
2546 
2547 bool te::mnt::Tin::BreakNodeClosestPoints(int32_t nid, int32_t *rClstNids, int32_t *lClstNids)
2548 {
2549  int32_t ltri, rtri;
2550  int32_t lids[3],
2551  flin;
2552  double dist, rdistv[CLNODES], ldistv[CLNODES];
2553  int32_t nodeid;
2554 
2555  lids[0] = lids[1] = lids[2] = -1;
2556  // Find one line that contains node
2557  std::vector<int32_t>lineid = FindLine(nid);
2558  if (!lineid.size())
2559  return false;
2560 
2561  for (size_t i = 0; i < lineid.size(); i++)
2562  {
2563  flin = lineid[i];
2564 
2565  for (unsigned int j = 0; j < CLNODES; j++)
2566  {
2567  rdistv[j] = m_nodatavalue;
2568  rClstNids[j] = -1;
2569 
2570  ldistv[j] = m_nodatavalue;
2571  lClstNids[j] = -1;
2572  }
2573 
2574  // Find right and left triangle
2575  rtri = m_line[static_cast<unsigned int>(lineid[i])].getRightPolygon();
2576  ltri = m_line[static_cast<unsigned int>(lineid[i])].getLeftPolygon();
2577  if (rtri == -1)
2578  {
2579  rtri = ltri;
2580  ltri = -1;
2581  }
2582  while (rtri != ltri)
2583  {
2584  if (rtri >= 0)
2585  if (!m_triang[static_cast<unsigned int>(rtri)].LinesId(lids))
2586  break;
2587 
2588  unsigned int j;
2589  for (j = 0; j < 3; j++)
2590  {
2591  // Find line that contains node
2592  if (lids[j] == lineid[i] || lids[j] == -1)
2593  continue;
2594  if ((m_line[static_cast<unsigned int>(lids[j])].getNodeFrom() == nid) ||
2595  (m_line[static_cast<unsigned int>(lids[j])].getNodeTo() == nid))
2596  break;
2597  }
2598  if (j == 3){
2599  break;
2600  }
2601 
2602  lineid[i] = lids[j];
2603  if (m_line[static_cast<unsigned int>(lineid[i])].getNodeFrom() == nid)
2604  {
2605  nodeid = m_line[static_cast<unsigned int>(lineid[i])].getNodeTo();
2606  if (nodeid < m_fbnode)
2607  { //Node is a breakline node at right side of it
2608  dist = (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) *
2609  (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) +
2610  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY()) *
2611  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY());
2612  for (j = 0; j < CLNODES; j++)
2613  {
2614  if (dist < rdistv[j])
2615  {
2616  for (unsigned int k = static_cast<unsigned int>(CLNODES - 1); k > j; k--)
2617  {
2618  rdistv[k] = rdistv[k - 1];
2619  rClstNids[k] = rClstNids[k - 1];
2620  }
2621  rdistv[j] = dist;
2622  rClstNids[j] = nodeid;
2623  break;
2624  }
2625  }
2626  }
2627  }
2628  else
2629  {
2630  nodeid = m_line[static_cast<unsigned int>(lineid[i])].getNodeFrom();
2631  if (nodeid < m_fbnode)
2632  { //Node is a breakline node at left side of it
2633  dist = (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) *
2634  (m_node[static_cast<unsigned int>(nid)].getX() - m_node[static_cast<unsigned int>(nodeid)].getX()) +
2635  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY()) *
2636  (m_node[static_cast<unsigned int>(nid)].getY() - m_node[static_cast<unsigned int>(nodeid)].getY());
2637  for (j = 0; j < CLNODES; j++)
2638  {
2639  if (dist < ldistv[j])
2640  {
2641  for (unsigned int k = static_cast<unsigned int>(CLNODES - 1); k > j; k--)
2642  {
2643  ldistv[k] = ldistv[k - 1];
2644  lClstNids[k] = lClstNids[k - 1];
2645  }
2646  ldistv[j] = dist;
2647  lClstNids[j] = nodeid;
2648  break;
2649  }
2650  }
2651  }
2652  }
2653 
2654  // Find new right triangle
2655  if (m_line[static_cast<unsigned int>(lineid[i])].getRightPolygon() == rtri)
2656  rtri = m_line[static_cast<unsigned int>(lineid[i])].getLeftPolygon();
2657  else if (m_line[static_cast<unsigned int>(lineid[i])].getLeftPolygon() == rtri)
2658  rtri = m_line[static_cast<unsigned int>(lineid[i])].getRightPolygon();
2659  else
2660  break;
2661  if ((rtri == -1) && (ltri != -1))
2662  {
2663  rtri = ltri;
2664  ltri = -1;
2665  lineid[i] = flin;
2666  }
2667  }
2668  }
2669  return true;
2670 }
2671 
2672 bool te::mnt::Tin::CalcTriangleSecondDeriv(std::vector<int32_t> &triangles, std::vector<te::gm::Point> &fderiv)
2673 {
2674  int32_t triid, nodesid[3];
2678  double nvector[3];
2679  double dxy, dyx;
2680  double m1, m2;
2681  double tol = .01;
2682 
2683  for (size_t i = 0; i < triangles.size(); i++)
2684  {
2685  if (triangles[i] == -1)
2686  continue;
2687  triid = triangles[i];
2688  if (!NodesId(triid, nodesid))
2689  continue;
2690 
2691  // Special case
2692  if ((m_node[static_cast<unsigned int>(nodesid[0])].getZ() >= m_nodatavalue) ||
2693  (m_node[static_cast<unsigned int>(nodesid[1])].getZ() >= m_nodatavalue) ||
2694  (m_node[static_cast<unsigned int>(nodesid[2])].getZ() >= m_nodatavalue))
2695  {
2696  // Triangle with DUMMY Value
2697  m_tsderiv[static_cast<unsigned int>(triid)].setX(m_nodatavalue);
2698  m_tsderiv[static_cast<unsigned int>(triid)].setY(m_nodatavalue);
2699  m_tsderiv[static_cast<unsigned int>(triid)].setZ(m_nodatavalue);
2700  continue;
2701  }
2702  m1 = m2 = m_nodatavalue;
2703  if ((m_node[static_cast<unsigned int>(nodesid[1])].getY() - m_node[static_cast<unsigned int>(nodesid[0])].getY()) != 0.0)
2704  m1 = (m_node[static_cast<unsigned int>(nodesid[1])].getX() - m_node[static_cast<unsigned int>(nodesid[0])].getX()) /
2705  (m_node[static_cast<unsigned int>(nodesid[1])].getY() - m_node[static_cast<unsigned int>(nodesid[0])].getY());
2706  if ((m_node[static_cast<unsigned int>(nodesid[2])].getY() - m_node[static_cast<unsigned int>(nodesid[0])].getY()) != 0.0)
2707  m2 = (m_node[static_cast<unsigned int>(nodesid[2])].getX() - m_node[static_cast<unsigned int>(nodesid[0])].getX()) /
2708  (m_node[static_cast<unsigned int>(nodesid[2])].getY() - m_node[static_cast<unsigned int>(nodesid[0])].getY());
2709 
2710  if (fabs(m1 - m2) < tol)
2711  {
2712  // Triangle with DUMMY Value
2713  m_tsderiv[static_cast<unsigned int>(triid)].setX(m_nodatavalue);
2714  m_tsderiv[static_cast<unsigned int>(triid)].setY(m_nodatavalue);
2715  m_tsderiv[static_cast<unsigned int>(triid)].setZ(m_nodatavalue);
2716  continue;
2717  }
2718 
2719  // Calculate using dx
2720  for (unsigned int j = 0; j < 3; j++)
2721  {
2722  p3da[j].setX(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getX());
2723  p3da[j].setY(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getY());
2724  if (m_node[static_cast<unsigned int>(nodesid[j])].getType() > Last && m_node[static_cast<unsigned int>(nodesid[j])].getType() < Sample)
2725  // If breakline node
2726  p3da[j].setZ(fderiv[static_cast<unsigned int>(nodesid[j] - m_fbnode)].getX());
2727  else
2728  p3da[j].setZ(m_nfderiv[static_cast<unsigned int>(nodesid[j])].getX());
2729  }
2730 
2731  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
2732  {
2733  m_tsderiv[static_cast<unsigned int>(triid)].setX(0.);
2734  dxy = 0.;
2735  }
2736  else
2737  {
2738  triangleNormalVector(p3da, nvector);
2739  m_tsderiv[static_cast<unsigned int>(triid)].setX(-nvector[0] / nvector[2]);
2740  dxy = (-nvector[1] / nvector[2]);
2741  }
2742 
2743  // Calculate using dy
2744  for (unsigned int j = 0; j < 3; j++)
2745  if (m_node[static_cast<unsigned int>(nodesid[j])].getType() > Last && m_node[static_cast<unsigned int>(nodesid[j])].getType() < Sample)
2746  // If breakline node
2747  p3da[j].setZ(fderiv[static_cast<unsigned int>(nodesid[j] - m_fbnode)].getY());
2748  else
2749  p3da[j].setZ(m_nfderiv[static_cast<unsigned int>(nodesid[j])].getY());
2750 
2751  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
2752  {
2753  m_tsderiv[static_cast<unsigned int>(triid)].setY(0.);
2754  dyx = 0.;
2755  }
2756  else
2757  {
2758  triangleNormalVector(p3da, nvector);
2759  m_tsderiv[static_cast<unsigned int>(triid)].setY(-nvector[1] / nvector[2]);
2760  dyx = (-nvector[0] / nvector[2]);
2761  }
2762  m_tsderiv[static_cast<unsigned int>(triid)].setZ((dxy + dyx) / 2.);
2763  }
2764 
2765  return true;
2766 }
2767 
2769 {
2770  int32_t bnodesize,
2771  node1, node2,
2772  rclstnids[CLNODES], lclstnids[CLNODES];
2773  TinNode rsderiv, lsderiv;
2774  double deltax, deltay, modxy,
2775  costheta, sintheta,
2776  cos2theta, sin2theta, sincostheta,
2777  dzdss, dzdtt, dzdst,
2778  dzdxx, dzdyy, dzdxy;
2779 
2780  if (!m_tsderiv.size())
2781  return false;
2782 
2783  // Create and Initialize second derivatives vector
2784  bnodesize = m_lnode - m_fbnode;
2785  if (m_nbrsderiv.size())
2786  {
2787  m_nbrsderiv.clear();
2788  }
2789 
2790  size_t i;
2791  for (i = 0; i < static_cast<unsigned int>(bnodesize + 1); i++)
2792  {
2793  m_nbrsderiv.push_back(m_nsderiv[i + static_cast<unsigned int>(m_fbnode)]);
2794  m_nblsderiv.push_back(m_nsderiv[i + static_cast<unsigned int>(m_fbnode)]);
2795  }
2796 
2797  // To each break node
2798  for (i = static_cast<unsigned int>(m_fbnode); i < m_node.size() - 1; i++)
2799  {
2800  // Special cases
2801  if ((m_node[i].getZ() >= m_nodatavalue) ||
2802  (m_node[i].getType() == Deletednode) ||
2803  (m_node[i].getType() > Breaklinenormal))
2804  continue;
2805 
2806  // Look for triangles that sharing the node
2807  BreakNodeClosestPoints(static_cast<int32_t>(i), rclstnids, lclstnids);
2808  rsderiv = CalcNodeSecondDeriv(static_cast<int32_t>(i), rclstnids);
2809  lsderiv = CalcNodeSecondDeriv(static_cast<int32_t>(i), lclstnids);
2810 
2811  node1 = NextNode(static_cast<int32_t>(i));
2812  node2 = PreviousNode(static_cast<int32_t>(i));
2813 
2814  deltax = m_node[static_cast<unsigned int>(node1)].getX() - m_node[static_cast<unsigned int>(node2)].getX();
2815  deltay = m_node[static_cast<unsigned int>(node1)].getY() - m_node[static_cast<unsigned int>(node2)].getY();
2816  modxy = sqrt(deltax*deltax + deltay*deltay);
2817  costheta = deltax / modxy;
2818  sintheta = deltay / modxy;
2819  cos2theta = costheta*costheta;
2820  sin2theta = sintheta*sintheta;
2821  sincostheta = sintheta*costheta;
2822 
2823  dzdss = cos2theta*m_nsderiv[i].getX() -
2824  2 * sincostheta*m_nsderiv[i].getZ() +
2825  sin2theta*m_nsderiv[i].getY();
2826 
2827  dzdtt = sin2theta*rsderiv.getX() +
2828  2 * sincostheta*rsderiv.getZ() +
2829  cos2theta*rsderiv.getY();
2830  dzdst = sincostheta*rsderiv.getX() +
2831  (cos2theta - sin2theta)*rsderiv.getZ() -
2832  sincostheta*rsderiv.getY();
2833 
2834  dzdxx = cos2theta*dzdss +
2835  2 * sincostheta*dzdst +
2836  sin2theta*dzdtt;
2837  dzdyy = sin2theta*dzdss -
2838  2 * sincostheta*dzdst +
2839  cos2theta*dzdtt;
2840  dzdxy = -sincostheta*dzdss +
2841  (cos2theta - sin2theta)*dzdst +
2842  sincostheta*dzdtt;
2843 
2844  m_nbrsderiv[i - static_cast<unsigned long>(m_fbnode)].setX(dzdxx);
2845  m_nbrsderiv[i - static_cast<unsigned long>(m_fbnode)].setY(dzdyy);
2846  m_nbrsderiv[i - static_cast<unsigned long>(m_fbnode)].setZ(dzdxy);
2847 
2848  dzdtt = sin2theta*lsderiv.getX() +
2849  2 * sincostheta*lsderiv.getZ() +
2850  cos2theta*lsderiv.getY();
2851  dzdst = sincostheta*lsderiv.getX() +
2852  (cos2theta - sin2theta)*lsderiv.getZ() -
2853  sincostheta*lsderiv.getY();
2854 
2855  dzdxx = cos2theta*dzdss +
2856  2 * sincostheta*dzdst +
2857  sin2theta*dzdtt;
2858  dzdyy = sin2theta*dzdss -
2859  2 * sincostheta*dzdst +
2860  cos2theta*dzdtt;
2861  dzdxy = -sincostheta*dzdss +
2862  (cos2theta - sin2theta)*dzdst +
2863  sincostheta*dzdtt;
2864 
2865  m_nblsderiv[i - static_cast<unsigned long>(m_fbnode)].setX(dzdxx);
2866  m_nblsderiv[i - static_cast<unsigned long>(m_fbnode)].setY(dzdyy);
2867  m_nblsderiv[i - static_cast<unsigned long>(m_fbnode)].setZ(dzdxy);
2868  }
2869 
2870  return true;
2871 }
2872 
2874 {
2875  int32_t triangid;
2876 
2877  for (triangid = 0; triangid < m_ltriang; triangid++)
2878  {
2879  CheckLines(triangid);
2880  }
2881 
2882  return true;
2883 }
2884 
2885 
2886 bool te::mnt::Tin::CheckLines(int32_t trid)
2887 {
2888  int32_t lids[3], nids[3];
2889  double a, b, c, d, s;
2890  short i;
2891 
2892  if (trid > m_ltriang)
2893  return false;
2894 
2895  if (!m_triang[static_cast<unsigned int>(trid)].LinesId(lids))
2896  return false;
2897 
2898  if (!NodesId(trid, nids))
2899  return false;
2900 
2901  a = m_node[static_cast<unsigned int>(nids[1])].getX() - m_node[static_cast<unsigned int>(nids[0])].getX();
2902  b = m_node[static_cast<unsigned int>(nids[1])].getY() - m_node[static_cast<unsigned int>(nids[0])].getY();
2903  c = m_node[static_cast<unsigned int>(nids[2])].getX() - m_node[static_cast<unsigned int>(nids[0])].getX();
2904  d = m_node[static_cast<unsigned int>(nids[2])].getY() - m_node[static_cast<unsigned int>(nids[0])].getY();
2905  s = a*d - b*c;
2906 
2907  // To all triangle lines
2908  for (i = 0; i < 3; i++)
2909  {
2910  // Make sure that triangle is inside
2911  if (s > 0.)
2912  {
2913  if (((m_line[static_cast<unsigned int>(lids[i])].getNodeFrom() == nids[i]) &&
2914  (m_line[static_cast<unsigned int>(lids[i])].getRightPolygon() == trid)) ||
2915  ((m_line[static_cast<unsigned int>(lids[i])].getNodeTo() == nids[i]) &&
2916  (m_line[static_cast<unsigned int>(lids[i])].getLeftPolygon() == trid)))
2917  m_line[static_cast<unsigned int>(lids[i])].SwapPolygon();
2918  }
2919  else
2920  {
2921  if (((m_line[static_cast<unsigned int>(lids[i])].getNodeTo() == nids[i]) &&
2922  (m_line[static_cast<unsigned int>(lids[i])].getRightPolygon() == trid)) ||
2923  ((m_line[static_cast<unsigned int>(lids[i])].getNodeFrom() == nids[i]) &&
2924  (m_line[static_cast<unsigned int>(lids[i])].getLeftPolygon() == trid)))
2925  m_line[static_cast<unsigned int>(lids[i])].SwapPolygon();
2926  }
2927  }
2928 
2929  return true;
2930 }
2931 
2932 
2934 {
2935  double u, v, ap, bp, cp, dp, x0, y0,
2936  p00, p01, p02, p03, p04, p05,
2937  p10, p11, p12, p13, p14,
2938  p20, p21, p22, p23,
2939  p30, p31, p32,
2940  p40, p41, p50,
2941  p0, p1, p2, p3, p4,
2942  coef[27];
2943 
2944  DefineAkimaCoeficients(triid, coef);
2945 
2946  // Polynomial coefficients
2947  p00 = coef[0]; p01 = coef[1]; p02 = coef[2]; p03 = coef[3]; p04 = coef[4]; p05 = coef[5];
2948  p10 = coef[6]; p11 = coef[7]; p12 = coef[8]; p13 = coef[9]; p14 = coef[10];
2949  p20 = coef[11]; p21 = coef[12]; p22 = coef[13]; p23 = coef[14];
2950  p30 = coef[15]; p31 = coef[16]; p32 = coef[17];
2951  p40 = coef[18]; p41 = coef[19];
2952  p50 = coef[20];
2953 
2954  // Coefficients of conversion from XY to UV coordinates
2955  ap = coef[21]; bp = coef[22]; cp = coef[23]; dp = coef[24];
2956  x0 = coef[25]; y0 = coef[26];
2957 
2958  // Converts point from XY to UV
2959  u = ap*(pt1.getX() - x0) +
2960  bp*(pt1.getY() - y0);
2961  v = cp*(pt1.getX() - x0) +
2962  dp*(pt1.getY() - y0);
2963 
2964  // Evaluates the polynomial
2965  p0 = p00 + v*(p01 + v*(p02 + v*(p03 + v*(p04 + v*p05))));
2966  p1 = p10 + v*(p11 + v*(p12 + v*(p13 + v*p14)));
2967  p2 = p20 + v*(p21 + v*(p22 + v*p23));
2968  p3 = p30 + v*(p31 + v*p32);
2969  p4 = p40 + v*p41;
2970 
2971  pt1.setZ((p0 + u*(p1 + u*(p2 + u*(p3 + u*(p4 + u*p50))))));
2972 
2973  // Converts point from XY to UV
2974  u = ap*(pt2.getX() - x0) +
2975  bp*(pt2.getY() - y0);
2976  v = cp*(pt2.getX() - x0) +
2977  dp*(pt2.getY() - y0);
2978 
2979  // Evaluates the polynomial
2980  p0 = p00 + v*(p01 + v*(p02 + v*(p03 + v*(p04 + v*p05))));
2981  p1 = p10 + v*(p11 + v*(p12 + v*(p13 + v*p14)));
2982  p2 = p20 + v*(p21 + v*(p22 + v*p23));
2983  p3 = p30 + v*(p31 + v*p32);
2984  p4 = p40 + v*p41;
2985 
2986  pt2.setZ((p0 + u*(p1 + u*(p2 + u*(p3 + u*(p4 + u*p50))))));
2987 
2988  return true;
2989 }
2990 
2991 bool te::mnt::Tin::DefineAkimaCoeficients(int32_t triid, double *coef)
2992 {
2993  int32_t nodesid[3];
2997 
2998  if (!NodesId(triid, nodesid))
2999  return false;
3000  for (unsigned int j = 0; j < 3; j++)
3001  {
3002  p3d[j].setX(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getX());
3003  p3d[j].setY(m_node[static_cast<unsigned int>(nodesid[j])].getNPoint().getY());
3004  p3d[j].setZ(m_node[static_cast<unsigned int>(nodesid[j])].getZ());
3005  }
3006 
3007  DefineAkimaCoeficients(triid, nodesid, p3d, coef);
3008 
3009  return true;
3010 }
3011 
3012 bool te::mnt::Tin::DefineAkimaCoeficients(int32_t triid, int32_t *nodesid, te::gm::Point *p3d, double *coef)
3013 {
3014  double a, b, c, d,
3015  aa, bb, cc, dd,
3016  ad, bc, det,
3017  ap, bp, cp, dp,
3018  lu, lv,
3019  theta, phi, thxu, thphi,
3020  cstheta, lusntheta, lvsntheta,
3021  e, f, g, h,
3022  p00, p01, p02, p03, p04, p05,
3023  p10, p11, p12, p13, p14,
3024  p20, p21, p22, p23,
3025  p30, p31, p32,
3026  p40, p41, p50,
3027  h1, h2, h3, g1, g2,
3028  fg, eh, ee, gg,
3029  zu[3], zv[3], zuu[3], zvv[3], zuv[3];
3030  short bside;
3031  int32_t lids[3], nodid;
3032  std::vector<te::gm::Point>* fderiv;
3033  std::vector<TinNode> *sderiv;
3034 
3035  // Coeficients of conversion from UV to XY coordinates
3036  a = p3d[1].getX() - p3d[0].getX();
3037  b = p3d[2].getX() - p3d[0].getX();
3038  c = p3d[1].getY() - p3d[0].getY();
3039  d = p3d[2].getY() - p3d[0].getY();
3040 
3041  aa = a * a;
3042  bb = b * b;
3043  cc = c * c;
3044  dd = d * d;
3045 
3046  // Coeficients of conversion from XY to UV coordinates
3047  ad = a * d;
3048  bc = b * c;
3049  det = ad - bc;
3050  ap = d / det;
3051  bp = -b / det;
3052  cp = -c / det;
3053  dp = a / det;
3054 
3055  bside = 0;
3056  if (m_fbnode > 0)
3057  {
3058  // If there are breaklines
3059  if (!m_triang[static_cast<unsigned int>(triid)].LinesId(lids))
3060  return false;
3061 
3062  for (unsigned int i = 0; i < 3; i++)
3063  {
3064  if ((m_line[static_cast<unsigned int>(lids[i])].getNodeTo() >= m_fbnode) &&
3065  (m_line[static_cast<unsigned int>(lids[i])].getNodeFrom() >= m_fbnode))
3066  {
3067  if (m_line[static_cast<unsigned int>(lids[i])].getRightPolygon() == triid)
3068  // Triangle at the right side of a breakline
3069  bside = 1;
3070  else if (m_line[static_cast<unsigned int>(lids[i])].getLeftPolygon() == triid)
3071  // Triangle at the left side of a breakline
3072  bside = 2;
3073  else
3074  return false;
3075  break;
3076  }
3077  if (m_line[static_cast<unsigned int>(lids[i])].getNodeTo() >= m_fbnode)
3078  {
3079  // Triangle at the right side of a breakline
3080  bside = 1;
3081  break;
3082  }
3083  if (m_line[static_cast<unsigned int>(lids[i])].getNodeFrom() >= m_fbnode)
3084  {
3085  // Triangle at the left side of a breakline
3086  bside = 2;
3087  break;
3088  }
3089  }
3090  }
3091 
3092  // Conversion of derivatives from XY to UV coordinates
3093  for (unsigned int i = 0; i < 3; i++)
3094  {
3095  if ((m_fbnode == 0) ||
3096  ((m_fbnode > 0) && (nodesid[i] < m_fbnode)))
3097  {
3098  nodid = nodesid[i];
3099  fderiv = &m_nfderiv;
3100  sderiv = &m_nsderiv;
3101  }
3102  else if (bside == 1)
3103  {
3104  nodid = nodesid[i] - m_fbnode;
3105  fderiv = &m_nbrfderiv;
3106  sderiv = &m_nbrsderiv;
3107  }
3108  else if (bside == 2)
3109  {
3110  nodid = nodesid[i] - m_fbnode;
3111  fderiv = &m_nblfderiv;
3112  sderiv = &m_nbrsderiv;
3113  }
3114  else{
3115  return false;
3116  }
3117 
3118  if ((*fderiv)[static_cast<unsigned int>(nodid)].getY() >= m_nodatavalue)
3119  {
3120  zu[i] = 0.; zv[i] = 0.;
3121  }
3122  else
3123  {
3124  zu[i] = a * (*fderiv)[static_cast<unsigned int>(nodid)].getX() +
3125  c * (*fderiv)[static_cast<unsigned int>(nodid)].getY();
3126  zv[i] = b * (*fderiv)[static_cast<unsigned int>(nodid)].getX() +
3127  d * (*fderiv)[static_cast<unsigned int>(nodid)].getY();
3128  }
3129  if ((*sderiv)[static_cast<unsigned int>(nodid)].getZ() >= m_nodatavalue)
3130  {
3131  zuu[i] = 0.;
3132  zuv[i] = 0.;
3133  zvv[i] = 0.;
3134  }
3135  else
3136  {
3137  zuu[i] = aa * (*sderiv)[static_cast<unsigned int>(nodid)].getX() +
3138  2.*a*c * static_cast<double>((*sderiv)[static_cast<unsigned int>(nodid)].getZ()) +
3139  cc * (*sderiv)[static_cast<unsigned int>(nodid)].getY();
3140  zuv[i] = a*b * (*sderiv)[static_cast<unsigned int>(nodid)].getX() +
3141  (ad + bc) * static_cast<double>((*sderiv)[static_cast<unsigned int>(nodid)].getZ()) +
3142  c*d * (*sderiv)[static_cast<unsigned int>(nodid)].getY();
3143  zvv[i] = bb * (*sderiv)[static_cast<unsigned int>(nodid)].getX() +
3144  2.*b*d * static_cast<double>((*sderiv)[static_cast<unsigned int>(nodid)].getZ()) +
3145  dd * (*sderiv)[static_cast<unsigned int>(nodid)].getY();
3146  }
3147  }
3148 
3149  // Calculate U and V side sizes
3150  lu = sqrt(aa + cc);
3151  lv = sqrt(bb + dd);
3152 
3153  // Calculate angle between U and V axis and its cosine
3154  thxu = atan2(c, a);
3155  theta = atan2(d, b) - thxu;
3156  cstheta = cos(theta);
3157  lusntheta = lu * sin(theta);
3158  lvsntheta = lv * sin(theta);
3159 
3160  // Calculate angle between U and S axis and its cosine
3161  phi = atan2(d - c, b - a) - thxu;
3162  thphi = theta - phi;
3163 
3164  // Coeficients of conversion from ST to UV coordinates when
3165  // S axis is paralel to v2v3 side
3166  e = sin(thphi) / lusntheta;
3167  f = -cos(thphi) / lusntheta;
3168  g = sin(phi) / lvsntheta;
3169  h = cos(phi) / lvsntheta;
3170 
3171  // Definition of the polynomial coefficients
3172  // Using (u,v) = (0,0) -> v1
3173  p00 = p3d[0].getZ();
3174  p10 = zu[0];
3175  p01 = zv[0];
3176  p11 = zuv[0];
3177  p20 = zuu[0] / 2.;
3178  p02 = zvv[0] / 2.;
3179 
3180  // Using (u,v) = (1,0) -> v2 and z(u,v), zu and zuu
3181  h1 = p3d[1].getZ() - p00 - p10 - p20;
3182  h2 = zu[1] - p10 - zuu[0];
3183  h3 = zuu[1] - zuu[0];
3184  p30 = 10.*h1 - 4.*h2 + h3 / 2.;
3185  p40 = -15.*h1 + 7.*h2 - h3;
3186  p50 = 6.*h1 - 3.*h2 + h3 / 2.;
3187 
3188  // Using (u,v) = (0,1) -> v3 and z(u,v), zu and zuu
3189  h1 = p3d[2].getZ() - p00 - p01 - p02;
3190  h2 = zv[2] - p01 - zvv[0];
3191  h3 = zvv[2] - zvv[0];
3192  p03 = 10.*h1 - 4.*h2 + h3 / 2.;
3193  p04 = -15.*h1 + 7.*h2 - h3;
3194  p05 = 6.*h1 - 3.*h2 + h3 / 2.;
3195 
3196  p41 = 5. * lv * cstheta * p50 / lu;
3197  p14 = 5. * lu * cstheta * p05 / lv;
3198 
3199  // Using (u,v) = (1,0) -> v2 and z(u,v) and zuv
3200  h1 = zv[1] - p01 - p11 - p41;
3201  h2 = zuv[1] - p11 - 4.*p41;
3202  p21 = 3.*h1 - h2;
3203  p31 = -2.*h1 + h2;
3204 
3205  // Using (u,v) = (1,0) -> v3 and z(u,v) and zuv
3206  h1 = zu[2] - p10 - p11 - p14;
3207  h2 = zuv[2] - p11 - 4.*p14;
3208  p12 = 3.*h1 - h2;
3209  p13 = -2.*h1 + h2;
3210 
3211  // Using continuity restriction and zvv at v2 and zuu at v3
3212  fg = f * g;
3213  eh = e * h;
3214  ee = e * e;
3215  gg = g * g;
3216 
3217  g1 = ee*g*(3.*fg + 2.*eh);
3218  g2 = e*gg*(2.*fg + 3.*eh);
3219 
3220  h1 = -5.*ee*ee*f*p50 -
3221  ee*e*(fg + eh)*p41 -
3222  gg*g*(fg + 4 * eh) -
3223  5.*gg*gg*h*p05;
3224 
3225  h2 = zvv[1] / 2. - p02 - p12;
3226  h3 = zuu[2] / 2. - p20 - p21;
3227 
3228  p22 = (g1*h2 + g2*h3 - h1) / (g1 + g2);
3229  p32 = h2 - p22;
3230  p23 = h3 - p22;
3231 
3232  // Polynomial coefficients
3233  coef[0] = p00; coef[1] = p01; coef[2] = p02; coef[3] = p03; coef[4] = p04; coef[5] = p05;
3234  coef[6] = p10; coef[7] = p11; coef[8] = p12; coef[9] = p13; coef[10] = p14;
3235  coef[11] = p20; coef[12] = p21; coef[13] = p22; coef[14] = p23;
3236  coef[15] = p30; coef[16] = p31; coef[17] = p32;
3237  coef[18] = p40; coef[19] = p41;
3238  coef[20] = p50;
3239 
3240  // Coefficients of conversion from XY to UV coordinates
3241  coef[21] = ap; coef[22] = bp; coef[23] = cp; coef[24] = dp;
3242  coef[25] = p3d[0].getX(); coef[26] = p3d[0].getY();
3243 
3244  return true;
3245 }
3246 
3247 
3248 /*!
3249 \brief Method that fills the grid locations, inside a triangle, with a zvalue
3250 \param triid is the triangle identification number
3251 \param flin and llin are the first and the last lines (rows) of the grid
3252 \param fcol and lcol are the first and the last columns of the grid
3253 \param zvalue is the z value to be stored in the grid inside the triangle region
3254 \return true always
3255 */
3256 bool te::mnt::Tin::FillGridValue(int32_t triid, int32_t flin, int32_t llin, int32_t fcol, int32_t lcol, double zvalue)
3257 {
3258  int32_t nlin, ncol;
3260  te::gm::Coord2D cg;
3261 
3262  for (nlin = flin; nlin <= llin; nlin++)
3263  {
3264  for (ncol = fcol; ncol <= lcol; ncol++)
3265  {
3266  cg = m_rst->getGrid()->gridToGeo(ncol, nlin);
3267  pg.setX(cg.getX());
3268  pg.setY(cg.getY());
3269  if (!(ContainsPoint(triid, pg)))
3270  continue;
3271  m_rst->setValue(static_cast<unsigned int>(ncol), static_cast<unsigned int>(nlin), zvalue);
3272  }
3273  }
3274 
3275  return true;
3276 }
3277 
3278 
3279 bool te::mnt::Tin::DefineInterLinesColumns(int32_t *nodesid, int32_t &flin, int32_t &llin, int32_t &fcol, int32_t &lcol)
3280 {
3281  te::gm::Coord2D cg;
3282 
3283  te::gm::Point llpt(std::numeric_limits< double >::max(), std::numeric_limits< double >::max());
3284  te::gm::Point urpt(-std::numeric_limits< double >::max(), -std::numeric_limits< double >::max());
3285  for (size_t j = 0; j < 3; j++)
3286  {
3287  llpt = Min(llpt, m_node[static_cast<unsigned int>(nodesid[j])].getNPoint());
3288  urpt = Max(urpt, m_node[static_cast<unsigned int>(nodesid[j])].getNPoint());
3289  }
3290 
3291  // Calculate lines and coluns intercepted
3292  cg = m_rst->getGrid()->geoToGrid(llpt.getX(), llpt.getY());
3293  fcol = te::rst::Round(cg.getX());
3294  llin = te::rst::Round(cg.getY());
3295  cg = m_rst->getGrid()->geoToGrid(urpt.getX(), urpt.getY());
3296  lcol = te::rst::Round(cg.getX());
3297  flin = te::rst::Round(cg.getY());
3298 
3299  if ((static_cast<int32_t>(m_rst->getNumberOfColumns()) <= fcol) || (lcol < 0) ||
3300  (static_cast<int32_t>(m_rst->getNumberOfRows()) <= flin) || (llin < 0))
3301  return false;
3302 
3303  if (fcol < 0)
3304  fcol = 0;
3305  if (flin < 0)
3306  flin = 0;
3307  if (static_cast<int32_t>(m_rst->getNumberOfColumns()) <= lcol)
3308  lcol = static_cast<int32_t>(m_rst->getNumberOfColumns()) - 1;
3309  if (static_cast<int32_t>(m_rst->getNumberOfRows()) <= llin)
3310  llin = static_cast<int32_t>(m_rst->getNumberOfRows()) - 1;
3311 
3312  return true;
3313 }
3314 
static te::dt::TimeDuration td(20, 30, 50, 11)
void insert(const kdKey &key, const kdDataItem &item)
It inserts the data with a given key in tree.
void setAutoNumber(bool a)
It tells if the property is an autonumber or not.
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
int32_t m_nodeto
last node number
Definition: Tin.h:176
bool ExchangePolygon(int32_t oldPolyId, int32_t newPolyId)
Method for exchange polygons in the triangulation.
Definition: Tin.cpp:75
int32_t getRightPolygon()
Definition: Tin.h:125
bool CheckTopology()
Method that check the topology in a triangulation.
Definition: Tin.cpp:2873
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
bool setEdge(int32_t edge)
Definition: Tin.cpp:154
int32_t FindTriangle(te::gm::Point &ptr1)
Method that finds a triangle containing a given point.
Definition: Tin.cpp:190
Geometric property.
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
bool TrianglePoints(int32_t triangId, te::gm::Point *vertex)
Method that reads the vertex (points) of a given triangle.
Definition: Tin.cpp:400
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
bool TriangleSecondDeriv()
Method that calculates the second derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1867
void setDouble(std::size_t i, double value)
It sets the value of the i-th property.
bool ContainsPoint(int32_t triangId, te::gm::Point &pt)
Method that verifies if a triangle contains a given point.
Definition: Tin.cpp:461
An atomic property like an integer or double.
bool FillGridValue(int32_t triid, int32_t flin, int32_t llin, int32_t fcol, int32_t lcol, double zvalue)
Method that fills the grid locations, inside a triangle, with a zvalue.
Definition: Tin.cpp:3256
bool operator==(const TinLine &rhs) const
Definition: Tin.cpp:39
int32_t PreviousNode(int32_t nodeId)
Method that finds out which is the previous node.
Definition: Tin.cpp:1018
bool NodeSecondDeriv()
Method that calculates the second derivative at all triangulation nodes.
Definition: Tin.cpp:2027
int32_t getNodeFrom()
Definition: Tin.h:100
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
boost::shared_ptr< DataSource > DataSourcePtr
bool operator<(const TinNode &rhs) const
Definition: Tin.cpp:145
bool NodeDerivatives()
Method that calculates the first and second derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1743
A class that represents an R-tree.
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
double getX()
Definition: Tin.h:219
A class that models the description of a dataset.
Definition: DataSetType.h:72
Curve is an abstract class that represents 1-dimensional geometric objects stored as a sequence of co...
Definition: Curve.h:58
virtual const char * what() const
It outputs the exception message.
TEMNTEXPORT te::gm::Point Max(te::gm::Point &p1, te::gm::Point &p2)
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 ExchangeNode(int32_t oldNodeId, int32_t newNodeId)
Method for exchange nodes in the triangulation.
Definition: Tin.cpp:87
bool NodeFirstDeriv()
Method that calculates the first derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1983
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
void setZ(double zvalue)
Definition: Tin.h:210
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
bool removeEdge(int32_t edge)
Definition: Tin.cpp:163
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
double getY() const
It returns the y-coordinate.
Definition: Coord2D.h:108
bool LoadTinQGIS(te::da::DataSourcePtr &inDsrc, std::string &inDsetName, double zmin, double zmax)
Method used to load a triangular network (TIN) generated by QGIS.
Definition: Tin.cpp:1540
TEMNTEXPORT double pointToSegmentDistance(te::gm::Point &fseg, te::gm::Point &lseg, te::gm::Point &pt, te::gm::Point *pti)
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
bool SwapPolygon()
Method for swap two adjacent polygons.
Definition: Tin.cpp:99
bool operator>(const TinLine &rhs) const
Definition: Tin.cpp:51
bool SwapNode()
Method for swap two nodes.
Definition: Tin.cpp:109
bool CalcTriangleSecondDeriv(std::vector< int32_t > &triangles, std::vector< te::gm::Point > &fderiv)
Method that calculates the second derivatives in a node of a given triangle.
Definition: Tin.cpp:2672
te::gm::Point * pt2
bool isActive() const
Verify if the task is active.
bool NodeClosestPoints(int32_t nid, int32_t *clstNids, bool useBrNode=true)
Method that searches the closest points of a specific node.
Definition: Tin.cpp:2073
bool operator==(const TinNode &rhs) const
Definition: Tin.cpp:127
void setSRID(int srid)
Definition: Tin.cpp:177
bool DefineInterLinesColumns(int32_t *nodesid, int32_t &flin, int32_t &llin, int32_t &fcol, int32_t &lcol)
Method that calculates the lines and the columns intercepted by a triangle.
Definition: Tin.cpp:3279
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
bool BuildTriangle(int32_t id, te::gm::LinearRing *lr, double *val, int32_t *right, int32_t *left, te::mnt::Ntype *type, double zmin, double zmax, bool &first, KD_TREE &nodetree, te::sam::rtree::Index< std::size_t > &linetree)
Definition: Tin.cpp:1427
void setInt32(std::size_t i, boost::int32_t value)
It sets the value of the i-th property.
TEVPEXPORT void Save(te::da::DataSource *source, te::da::DataSet *result, te::da::DataSetType *outDsType, const bool &enableProgress=true)
int b
Definition: TsRtree.cpp:32
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
bool SwapNodePolygon()
Method for swap two nodes and two adjacent polygons.
Definition: Tin.cpp:120
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
int32_t getNodeTo()
Definition: Tin.h:106
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.
An Envelope defines a 2D rectangular region.
bool NodeOppositeLines(int32_t v, std::vector< int32_t > &linids)
Method that find the oposite lines of a specific node.
Definition: Tin.cpp:492
bool NeighborsId(int32_t triangId, int32_t *neighsId)
Definition: Tin.cpp:950
te::gm::Point * pt1
void Init(te::gm::Point &npoint, Ntype ntype=Normalnode)
Set node coordinates and height.
Definition: Tin.h:242
int32_t m_leftpoly
left polygon number
Definition: Tin.h:177
URI C++ Library.
Definition: Attributes.h:37
int32_t m_rightpoly
right polygon number
Definition: Tin.h:178
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
TERASTEREXPORT int Round(double val)
Round a double value to a integer value.
int32_t getLeftPolygon()
Definition: Tin.h:119
void setEnvelope(te::gm::Envelope &env)
Definition: Tin.cpp:182
const int32_t CLNODES
Definition: Tin.h:27
te::gm::Polygon * p
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
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
bool BreakNodeSecondDeriv()
Method that calculates the second derivative at all triangulation break nodes.
Definition: Tin.cpp:2768
Utility functions for the data access module.
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
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
te::da::DataSetType * GetDataSetType(std::string &outDsetName)
Definition: Tin.cpp:1296
int32_t OppositeEdge(int32_t triangId, int32_t nodeId)
Method that reads the identification number of the opposite edge of a given node. ...
Definition: Tin.cpp:619
bool BreakTriangleSecondDeriv()
Method that calculates the second derivatives in the nodes of a given break triangle.
Definition: Tin.cpp:2417
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
void add(Constraint *c)
It adds a new constraint.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
bool operator>(const TinNode &rhs) const
Definition: Tin.cpp:136
void setX(double xvalue)
Definition: Tin.h:216
bool TriangleFirstDeriv()
Method that calculates the first derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1780
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
double getX() const
It returns the x-coordinate.
Definition: Coord2D.h:102
bool SaveTin(te::da::DataSourcePtr &outDsrc, std::string &outDsetName)
Definition: Tin.cpp:1344
double getY()
Definition: Tin.h:225
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
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
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
te::gm::Point CalcNodeFirstDeriv(int32_t nodeId, int32_t clstNodes[CLNODES])
Method that calculates the first derivative in a given node.
Definition: Tin.cpp:2132
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
bool NodeNodes(int32_t v, std::vector< int32_t > &nodids)
Method that includes a node in the tin node list.
Definition: Tin.cpp:1038
int32_t NodeTriangle(int32_t v)
Method that search a node in a triangulation.
Definition: Tin.cpp:1140
bool NodeTriangles(int32_t v, std::vector< int32_t > &triangles)
Method that includes a node in a triangle list.
Definition: Tin.cpp:1159
TEMNTEXPORT short segIntersect(te::gm::Point &pfr, te::gm::Point &pto, te::gm::Point &lfr, te::gm::Point &lto)
Function for check segment intersection.
TinNode CalcNodeSecondDeriv(int32_t nodeId, int32_t clstNIds[CLNODES])
Method that calculates the second derivative in a given node.
Definition: Tin.cpp:2206
void setY(double yvalue)
Definition: Tin.h:222
bool LoadTin(te::da::DataSourcePtr &inDsrc, std::string &inDsetName, double zmin=std::numeric_limits< double >::min(), double zmax=std::numeric_limits< double >::max())
Method used to load a triangular network (TIN)
Definition: Tin.cpp:1624
const double & getZ(std::size_t i) const
It returns the n-th z coordinate value.
TEDATAACCESSEXPORT DataSetType * GetDataSetType(const std::string &name, const std::string &datasourceId)
TEMNTEXPORT te::gm::Point Min(te::gm::Point &p1, te::gm::Point &p2)
Ltype getType()
Definition: Tin.h:154
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
te::gm::Point m_point
Node point.
Definition: Tin.h:262
bool operator<(const TinLine &rhs) const
Definition: Tin.cpp:63
void search(const te::gm::Envelope &e, std::vector< KdTreeNode * > &report) const
Range search query.
It is a collection of other geometric objects.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
int32_t m_nodefrom
initial node number
Definition: Tin.h:175
TEMNTEXPORT bool triangleNormalVector(te::gm::Point *, double *)
Function that defines the triangle normal vector.
double getZ()
Definition: Tin.h:213
bool ReallocateVectors(size_t nSize)
Method that reallocates Vectors.
Definition: Tin.cpp:1267
bool DefineAkimaCoeficients(int32_t triid, double *coef)
Method that defines the coefficients of the Akima polynomium fitted in a given triangle.
Definition: Tin.cpp:2991
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
bool fncomp(te::mnt::TinNode lhs, te::mnt::TinNode rhs)
Definition: Tin.cpp:1418
This file contains a class to define a TIN. Adapted from SPRING.
void setPrimaryKey(PrimaryKey *pk)
It sets the primary key constraint.
bool BreakNodeClosestPoints(int32_t nid, int32_t *rClstNids, int32_t *lClstNids)
Method that searches the Break node closest points.
Definition: Tin.cpp:2547
Curve * getRingN(std::size_t i) const
It returns the n-th ring for this curve polygon as a curve.
Definition: CurvePolygon.h:193
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
bool CheckLines(int32_t trid)
Method that check the lines in a triangulation.
Definition: Tin.cpp:2886
std::vector< int32_t > FindLine(int32_t nid)
Method that find a line containing a specific node.
Definition: Tin.cpp:641