src/terralib/mnt/core/Utils.cpp
Go to the documentation of this file.
1 
2 /*!
3 \file terralib/mnt/core/Utils.cpp
4 
5 \brief Utility functions for MNT support.
6 */
7 
8 #include "Utils.h"
9 #include "CalculateGrid.h"
10 #include "SplineGrass.h"
11 
12 #include "../../common/progress/TaskProgress.h"
13 #include "../../dataaccess/datasource/DataSourceTransactor.h"
14 #include "../../dataaccess/utils/Utils.h"
15 #include "../../datatype/SimpleProperty.h"
16 #include "../../geometry/GeometryProperty.h"
17 #include "../../geometry/Point.h"
18 #include "../../memory/DataSet.h"
19 #include "../../memory/DataSetItem.h"
20 #include "../../raster.h"
21 #include "../../vp/Utils.h"
22 
23 //#include <geos.h>
24 #include <geos/geom/Coordinate.h>
25 #include <geos/simplify/DouglasPeuckerLineSimplifier.h>
26 
27 #include <cmath>
28 #include <iostream>
29 #include <limits>
30 #include <stdint.h>
31 
32 
33 size_t te::mnt::ReadPoints(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol,
34  te::gm::MultiPoint &mpt, std::string &geostype, te::gm::Envelope &env)
35 {
36  if (inDsetName.empty())
37  return 0;
38 
39  size_t nsamples = 0;
40 
41  std::unique_ptr<te::da::DataSet> inDset(inDsrc->getDataSet(inDsetName));
42 
43  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
44 
45  te::common::TaskProgress task("Reading Samples...", te::common::TaskProgress::UNDEFINED, (int)inDset->size());
46 
47  inDset->moveBeforeFirst();
48  double value=std::numeric_limits<double>::max();
49  while (inDset->moveNext())
50  {
51  if (!task.isActive())
52  return false;
53  task.pulse();
54 
55  std::unique_ptr<te::gm::Geometry> gin(inDset->getGeometry(geo_pos));
56  geostype = gin.get()->getGeometryType();
57 
58  if (geostype == "MultiPoint")
59  {
60  te::gm::MultiPoint *g = dynamic_cast<te::gm::MultiPoint*>(gin.get());
61  std::size_t np = g->getNumGeometries();
62  if (!atrZ.empty())
63  value = inDset->getDouble(atrZ);
64  for (std::size_t i = 0; i < np; ++i)
65  {
66  te::gm::Point *p = dynamic_cast<te::gm::Point*>(g->getGeometryN(i));
67  if (atrZ.empty())
68  value = p->getZ();
69 
71  pz.setX(p->getX());
72  pz.setY(p->getY());
73  pz.setZ(value);
74 
75  mpt.add(dynamic_cast<te::gm::Geometry*>(pz.clone()));
76  nsamples++;
77  }
78  }
79  else if (geostype == "Point")
80  {
81  te::gm::Point *p = dynamic_cast<te::gm::Point*>(gin.get());
82  if (atrZ.empty())
83  value = p->getZ();
84  else
85  value = inDset->getDouble(atrZ);
86 
88  pz.setX(p->getX());
89  pz.setY(p->getY());
90  pz.setZ(value);
91 
92  mpt.add(dynamic_cast<te::gm::Geometry*>(pz.clone()));
93  nsamples++;
94  }
95  else
96  return 0;
97  }
98 
99  std::unique_ptr<te::gm::Envelope> e(inDset->getExtent(geo_pos));
100  env.init((e->getLowerLeftX() - tol), (e->getLowerLeftY() - tol), (e->getUpperRightX() + tol), (e->getUpperRightY() + tol));
101 
102  return nsamples;
103 }
104 
105 size_t te::mnt::ReadSamples(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, double max, Simplify alg,
106  te::gm::MultiPoint &mpt, te::gm::MultiLineString &isolines, std::string &geostype, te::gm::Envelope &env, int srid)
107 {
108 
109  if (inDsetName.empty())
110  return 0;
111 
112  std::unique_ptr<te::da::DataSet> inDset;
113  size_t nsamples = mpt.getNumGeometries();
114 
115  inDset = inDsrc->getDataSet(inDsetName);
116 
117  const std::size_t npr = inDset->getNumProperties();
118 
119  //Read attributes
120  std::vector<std::string>pnames;
121  std::vector<int> ptypes;
122  for (std::size_t i = 0; i != npr; ++i)
123  {
124  pnames.push_back(inDset->getPropertyName(i));
125  ptypes.push_back(inDset->getPropertyDataType(i));
126  }
127 
128  te::common::TaskProgress task("Reading Isolines...", te::common::TaskProgress::UNDEFINED, (int)inDset->size());
129 
130  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
131 
132  inDset->moveBeforeFirst();
133  double value = std::numeric_limits<double>::max();
134 
135  while (inDset->moveNext())
136  {
137  if (!task.isActive())
138  return false;
139  task.pulse();
140 
141  std::unique_ptr<te::gm::Geometry> gin(inDset->getGeometry(geo_pos));
142  gin->setSRID(srid);
143  geostype = gin.get()->getGeometryType();
144 
145  if (geostype == "LineString")
146  {
147  te::gm::LineString *l = dynamic_cast<te::gm::LineString*>(gin.get());
148  if (atrZ.empty())
149  {
150  if (l->is3D())
151  value = *l->getZ();
152  }
153  else
154  value = inDset->getDouble(atrZ);
155 
156  te::gm::LineString *ls;
157  if (alg == Spline)
159  else if (alg == DouglasPeucker)
160  ls = GEOS_DouglasPeucker(l, tol, value);
161  else if (alg == None)
162  {
163  ls = new te::gm::LineString(l->size(), te::gm::LineStringZType, isolines.getSRID());
164  for (std::size_t il = 0; il < l->size(); il++)
165  ls->setPointZ(il, l->getX(il), l->getY(il), value);
166  }
167  else
168  ls = pointListSimplify(l, tol, max, value);
169 
170  isolines.add(dynamic_cast<te::gm::Geometry*>(ls));
171  for (std::size_t p = 0; p < ls->size(); p++)
172  {
173  mpt.add(ls->getPointN(p).release());
174  }
175  nsamples += ls->size();
176  }
177  if (geostype == "MultiLineString")
178  {
179  te::gm::MultiLineString *g = dynamic_cast<te::gm::MultiLineString*>(gin.get());
180  std::size_t np = g->getNumGeometries();
181  if (!atrZ.empty())
182  value = inDset->getDouble(atrZ);
183  for (std::size_t i = 0; i < np; ++i)
184  {
185  te::gm::LineString *l = dynamic_cast<te::gm::LineString*>(g->getGeometryN(i));
186  std::unique_ptr<te::gm::LineString> lz(new te::gm::LineString(l->size(), te::gm::LineStringZType, isolines.getSRID()));
187  if (atrZ.empty() && l->is3D())
188  value = *l->getZ();
189 
190  for (std::size_t il = 0; il < l->size(); il++)
191  lz->setPointZ(il, l->getX(il), l->getY(il), value);
192  l->setSRID(isolines.getSRID());
193  std::unique_ptr<te::gm::LineString> ls;
194  if (alg == Spline)
196  else if (alg == DouglasPeucker)
197  ls.reset(GEOS_DouglasPeucker(l, tol, value));
198  else if (alg == None)
199  ls.reset(lz.release());
200  else
201  ls.reset(pointListSimplify(l, tol, max, value));
202  if (ls->size())
203  {
204  isolines.add(dynamic_cast<te::gm::Geometry*>(ls.get()));
205  nsamples += ls->size();
206 
207  for (std::size_t p = 0; p < ls->size(); p++)
208  {
209  mpt.add(ls->getPointN(p).release());
210  }
211  ls.release();
212  }
213  }
214  }
215  }
216 
217  std::unique_ptr<te::gm::Envelope> e = inDset->getExtent(geo_pos);
218  env.init((e->getLowerLeftX() - tol), (e->getLowerLeftY() - tol), (e->getUpperRightX() + tol), (e->getUpperRightY() + tol));
219 
220  return nsamples;
221 }
222 
224 {
225  return(Distance(pt1.getX(), pt1.getY(), pt2.getX(), pt2.getY()));
226 }
227 
228 double te::mnt::Distance(const double pt1x, const double pt1y, const double pt2x, const double pt2y)
229 {
230  double dx,
231  dy,
232  dist;
233 
234  dx = pt1x - pt2x;
235  dx = dx * dx;
236  dy = pt1y - pt2y;
237  dy = dy * dy;
238  dist = sqrt(dy + dx);
239  return(dist);
240 }
241 
242 
244 {
245  return te::gm::Point(MAX(p1.getX(), p2.getX()), MAX(p1.getY(), p2.getY()));
246 }
247 
249 {
250  return te::gm::Point(MIN(p1.getX(), p2.getX()), MIN(p1.getY(), p2.getY()));
251 }
252 
253 
254 bool te::mnt::Equal(te::gm::Point &p1, te::gm::Point &p2, double &tol)
255 {
256  return (std::fabs(p1.getX() - p2.getX()) < tol && std::fabs(p1.getY() - p2.getY()) < tol && std::fabs(p1.getZ() - p2.getZ()) < tol);
257 }
258 
259 bool te::mnt::equalFptSpt(te::gm::Point & fpt, te::gm::Point &spt, double scale)
260 {
261  double delta = (double)(scale/* * 0.04 / 1000.*/); // point one percent of map tolerance
262 
263  if ((fpt.getX() == spt.getX()) && (fpt.getY() == spt.getY())) return true;
264  if (fabs(fpt.getX() - spt.getX()) > delta) return false;
265  if (fabs(fpt.getY() - spt.getY()) < delta) return true;
266  return false;
267 }
268 
269 double TePerpendicularDistance(const te::gm::Coord2D& first, const te::gm::Coord2D& last, const te::gm::Coord2D& pin, te::gm::Coord2D &pinter)
270 {
271  double d12, xmin, ymin;
272 
273  double xi = first.getX();
274  double xf = last.getX();
275  double yi = first.getY();
276  double yf = last.getY();
277  double x = pin.getX();
278  double y = pin.getY();
279 
280  double dx = xf - xi;
281  double dy = yf - yi;
282  double a2 = (y - yi) * dx - (x - xi)*dy;
283 
284  if (dx == 0. && dy == 0.)
285  {
286  d12 = sqrt(((x - xi) * (x - xi)) + ((y - yi) * (y - yi)));
287  d12 *= d12;
288  }
289  else
290  d12 = a2 * a2 / (dx * dx + dy * dy);
291 
292  if (dx == 0.)
293  {
294  xmin = xi;
295  ymin = y;
296  }
297  else if (dy == 0.)
298  {
299  xmin = x;
300  ymin = yi;
301  }
302  else
303  {
304  double alfa = dy / dx;
305  xmin = (x + alfa * (y - yi) + alfa * alfa * xi) / (1. + alfa * alfa);
306  ymin = (x - xmin) / alfa + y;
307  }
308 
309  pinter.x = xmin;
310  pinter.y = ymin;
311 
312  return (sqrt(d12));
313 }
314 
315 te::gm::LineString* te::mnt::DouglasPeuckerTA(te::gm::LineString *lineIn, double simpFactor, double Zvalue)
316 {
317  te::gm::LineString *lineOut;
318 
319  if (lineIn->size() <= 3)
320  {
321  lineOut = new te::gm::LineString(*lineIn);
322  return lineOut;
323  }
324 
325  te::gm::LineString lringIn(*lineIn);
326 
327  std::vector<te::gm::Point*> lringOut;
328  lringOut.push_back(lringIn.getPointN(0).release());
329 
330  unsigned int initial = 0;
331  unsigned int final = 2;
332 
333  while (initial < (lringIn.size() - 2))
334  {
335  bool distIsGreater = false;
336 
337  while (!distIsGreater)
338  {
339  for (unsigned i = initial + 1; i < final; i++)
340  {
341  te::gm::Coord2D pInter;
342  if (TePerpendicularDistance(te::gm::Coord2D(lringIn.getX(initial), lringIn.getY(initial)), te::gm::Coord2D(lringIn.getX(final), lringIn.getY(final)),
343  te::gm::Coord2D(lringIn.getX(i), lringIn.getY(i)), pInter) > simpFactor)
344  {//if distance is greater than maximum distance
345  lringOut.push_back(lringIn.getPointN(final - 1).release());
346 
347  initial = final - 1;
348  final = initial + 2;
349 
350  distIsGreater = true;
351 
352  break;
353  }
354  }
355 
356  if (!distIsGreater)
357  {
358  final++;
359 
360  if ((final) >= lringIn.size())
361  {
362  lringOut.push_back(lringIn.getPointN(final - 2).release());
363 
364  initial = final;
365  distIsGreater = true;
366 
367  break;
368  }
369  }
370  else
371  break;
372 
373  if (final >= lringIn.size())
374  {
375  initial = final;
376  distIsGreater = true;
377 
378  break;
379  }
380  }
381  }
382 
383  if (lringOut.size() <= 3)
384  {
385  lineOut = new te::gm::LineString(*lineIn);
386  }
387  else
388  {
389  lineOut = new te::gm::LineString(lringOut.size(), te::gm::LineStringZType);
390  for (std::size_t i = 0; i < lringOut.size(); i++)
391  {
392  lineOut->setPointN(i, *lringOut[i]);
393  lineOut->setZ(i, Zvalue);
394  }
395  }
396 
397  te::common::FreeContents(lringOut);
398 
399  return lineOut;
400 }
401 
403 {
404  std::vector<geos::geom::Coordinate> coordpts;
405  for (std::size_t j = 0; j < ls->size(); ++j)
406  {
407  std::unique_ptr<te::gm::Point> lpt = ls->getPointN(j);
408  geos::geom::Coordinate coo(lpt->getX(), lpt->getY());
409  coordpts.push_back(coo);
410  }
411  geos::simplify::DouglasPeuckerLineSimplifier douglas(coordpts);
412  douglas.setDistanceTolerance(snap);
413  geos::simplify::DouglasPeuckerLineSimplifier::CoordsVectAutoPtr simplified(douglas.simplify());
414 
415  te::gm::LineString* lsout = new te::gm::LineString(simplified->size(), te::gm::LineStringZType);
416 
417  for (std::size_t j = 0; j < simplified->size(); ++j)
418  {
419  geos::geom::Coordinate c1 = simplified.get()->at(j);
420  lsout->setPointZ(j, c1.x, c1.y, Zvalue);
421  }
422 
423  return lsout;
424 }
425 
426 te::gm::LineString* te::mnt::pointListSimplify(te::gm::LineString *ls, double snap, double maxdist, double Zvalue)
427 {
428  size_t npts = ls->getNPoints();
429  size_t npte = npts;
430 
431  te::gm::Coord2D* vxy = ls->getCoordinates();
432 
433  // If line is too short do nothing
434  if (npts <= 3 || snap == 0.)
435  {
436  std::unique_ptr<te::gm::LineString > ptlist(new te::gm::LineString(npts, te::gm::LineStringZType));
437  for (size_t i = 0; i < npts; i++)
438  {
439  ptlist->setPointZ(i, vxy[i].getX(), vxy[i].getY(), Zvalue);
440  }
441  return ptlist.release();
442  }
443 
444  // snap2 = 400 * snap*snap;
445  double snap2 = maxdist*maxdist;
446 
447  size_t npt;
448  bool island = false;
449  // Check for islands before defining number of points to be used
450  if (vxy[0] == vxy[npte - 1])
451  {
452  npt = npte - 1;
453  island = true;
454  }
455  else
456  npt = npte;
457 
458  // initialize variables
459  size_t i = 0;
460  size_t numa = 0;
461  size_t numpf = npt - 1;
462 
463  // define anchor
464  te::gm::Coord2D axy = vxy[numa];
465 
466  // define floating point
467  te::gm::Coord2D pfxy = vxy[numpf];
468 
469  bool retv;
470  double dmax, d,
471  a = 0, b = 0,
472  aa1 = 0;
473  size_t numdmax;
474 
475  while (numa < (npt - 1))
476  {
477  // Compute coeficients of straight line y=ax+b
478  if (pfxy.getX() == axy.getX())
479  retv = true;
480  else
481  {
482  retv = false;
483  a = (pfxy.getY() - axy.getY()) / (pfxy.getX() - axy.getX());
484  b = pfxy.getY() - a * pfxy.getX();
485  aa1 = sqrt(a * a + 1.);
486  }
487 
488  dmax = 0;
489  numdmax = numpf;
490  size_t k;
491 
492  for (k = numa + 1; k < numpf; k++)
493  {
494  // Distance between point and line
495  if (retv)
496  d = fabs(axy.getX() - vxy[k].getX());
497  else
498  d = fabs(vxy[k].getY() - a*vxy[k].getX() - b) / aa1;
499 
500  if (d > dmax)
501  {
502  dmax = d;
503  numdmax = k;
504  }
505  }
506 
507  if (dmax <= snap)
508  {
509  // Store selected point
510  if (i > (npt - 1))
511  {
512  throw;
513  }
514  vxy[i++] = axy;
515 
516  double axbx = pfxy.getX() - axy.getX();
517  double ayby = pfxy.getY() - axy.getY();
518  double dist2 = axbx*axbx + ayby*ayby;
519  if (dist2 > snap2)
520  {
521  for (k = numpf; k > numa + 1; k--)
522  {
523  axbx = vxy[k].getX() - axy.getX();
524  ayby = vxy[k].getY() - axy.getY();
525  dist2 = axbx*axbx + ayby*ayby;
526  if (dist2 < snap2)
527  break;
528  }
529  // Shift anchor
530  numa = k;
531  axy = vxy[k];
532  }
533  else
534  {
535  // Shift anchor
536  numa = numpf;
537  axy = vxy[numpf];
538  }
539  numpf = npt - 1;
540  }
541  else
542  // Shift floating point
543  numpf = numdmax;
544 
545  pfxy = vxy[numpf];
546  }
547 
548  // Store results
549  vxy[i] = vxy[numa];
550  npts = i + 1;
551 
552  if ((Distance(vxy[i], vxy[i - 1]) < snap) || (Distance(vxy[i], vxy[0]) < snap))
553  npts = i;
554 
555  size_t newpts;
556  if (island)
557  newpts = npts + 1;
558  else
559  newpts = npts;
560 
561  std::unique_ptr< te::gm::LineString> ptlist(new te::gm::LineString(newpts, te::gm::LineStringZType, ls->getSRID()));
562 
563  for (i = 0; i < npts; i++)
564  {
565  ptlist->setPointZ(i, vxy[i].getX(), vxy[i].getY(), Zvalue);
566  }
567 
568  if (island)
569  ptlist->setPointZ(npts, vxy[0].getX(), vxy[0].getY(), Zvalue);
570 
571  return ptlist.release();
572 }
573 
574 /*!
575 \brief Function that evaluates the distance between a point and a segment
576 \param fseg is a pointer to the segment first point
577 \param lseg is a pointer to the segment last point
578 \param pt is a pointer to the considered point
579 \param pti is a pointer to the intersection point
580 \return the distance between the point and the segment
581 */
582 double te::mnt::SegmentDistance(double fx, double fy, double lx, double ly, double ptx, double pty, double *pix, double *piy)
583 {
584  double ux = lx - fx;
585  double uy = ly - fy;
586  double vx = ptx - fx;
587  double vy = pty - fy;
588  double uv = (ux*vx + uy*vy);
589  if (uv < 0.)
590  {
591  if (pix && piy)
592  {
593  *pix = lx;
594  *piy = ly;
595  }
596  return (sqrt(vx*vx + vy*vy));
597  }
598  else
599  {
600  ux = fx - lx;
601  uy = fy - ly;
602  vx = ptx - lx;
603  vy = pty - ly;
604  uv = (ux*vx + uy*vy);
605  if (uv < 0.)
606  {
607  if (pix && piy)
608  {
609  *pix = lx;
610  *piy = ly;
611  }
612  return (sqrt(vx*vx + vy*vy));
613  }
614  }
615 
616  double a, b, c, k, dist, aabb;
617 
618  a = ly - fy;
619  b = fx - lx;
620  c = lx*fy - fx*ly;
621  aabb = a*a + b*b;
622 
623  dist = fabs((a*ptx + b*pty + c) / (sqrt(aabb)));
624  if (pix && piy)
625  {
626  k = b*ptx - a*pty;
627  *pix = (b*k - a*c) / aabb;
628  *piy = (-a*k - b*c) / aabb;
629  }
630 
631  return dist;
632 
633 }
634 
636 {
637  double pix, piy;
638  double dist = SegmentDistance(fseg.getX(), fseg.getY(), lseg.getX(), lseg.getY(), pt.getX(), pt.getY(), &pix, &piy);
639  if (pti)
640  {
641  pti->x = pix;
642  pti->y = piy;
643  }
644  return dist;
645 }
646 
648 {
649  double pix, piy;
650  double dist = SegmentDistance(fseg.getX(), fseg.getY(), lseg.getX(), lseg.getY(), pt.getX(), pt.getY(), &pix, &piy);
651  if (pti)
652  {
653  pti->setX(pix);
654  pti->setY(piy);
655  }
656  return dist;
657 }
658 
659 /*!
660 \brief Function that finds the center of the vertices of a triangle
661 \param vert is pointer to the triangle vertices
662 \param pcx and pcy are pointers to coordinates x and y of the vertex center points
663 \return TRUE if the centers are evaluated with no errors or FALSE otherwise
664 */
665 
666 short te::mnt::findCenter(te::gm::Point* vert, double* pcx, double* pcy)
667 {
668  double m1 = 10., m2 = 10.; // normais aos segmentos 1 e 2
669  double xm1, ym1, // coords do ponto medio do segm. 1
670  xm2, ym2, // coords do ponto medio do segm. 2
671  xaux, yaux,
672  px[3], py[3];
673  bool perpvert1 = false, // perpendicular vertical ao segmento 1
674  perpvert2 = false; // perpendicular vertical ao segmento 2
675  short i;
676 
677  for (i = 0; i < 3; i++)
678  {
679  px[i] = vert[i].getX();
680  py[i] = vert[i].getY();
681  }
682 
683  // calcula o coeficiente angular perpendicular a reta 1
684  if ((float)py[0] == (float)py[1])
685  {
686  if ((float)px[0] == (float)px[1])
687  {
688  // pontos sao iguais-> retorna
689  return false;
690  }
691  perpvert1 = true;
692  }
693  else
694  m1 = -(px[1] - px[0]) / (py[1] - py[0]);
695 
696  // calcula o coeficiente angular da perpendicular a reta 2
697  if ((float)py[1] == (float)py[2])
698  {
699  if ((float)px[1] == (float)px[2])
700  {
701  // pontos sao iguais-> retorna
702  return false;
703  }
704  perpvert2 = false;
705  }
706  else
707  m2 = -(px[2] - px[1]) / (py[2] - py[1]);
708 
709  // Caso as retas sejam coincidentes, uma circunferencia
710  // nao eh definida
711  if ((float)m1 == (float)m2)
712  {
713  return false;
714  }
715 
716  // passou pelos testes: os pontos definem uma circunferencia
717  // calculo do ponto medio do segmento ponto0-ponto1 (segmento 1)
718  xm1 = (px[0] + px[1]) / 2.;
719  ym1 = (py[0] + py[1]) / 2.;
720 
721  // calculo do ponto medio do segmento ponto1-ponto2 (segmento 2)
722  xm2 = (px[1] + px[2]) / 2.;
723  ym2 = (py[1] + py[2]) / 2.;
724 
725  // calculo das coordenadas do centro: ponto de interseccao das mediatrizes
726  // dos segmentos ponto0-ponto1 e ponto1-ponto2
727  if (perpvert1 == true)
728  {
729  xaux = xm1;
730  yaux = (ym2 + m2 * (xaux - xm2));
731  }
732  else if (perpvert2 == true)
733  {
734  xaux = xm2;
735  yaux = (ym1 + m1 * (xaux - xm1));
736  }
737  else
738  {
739  xaux = (m1*xm1 - m2*xm2 - ym1 + ym2) / (m1 - m2);
740  yaux = (ym1 + m1 * (xaux - xm1));
741  }
742  *pcx = xaux;
743  *pcy = yaux;
744 
745  return true;
746 }
747 /*!
748 \brief Function for check segment intersection
749 \param pfr, pto, lfr, lto are pointers to Point objects
750 \return point of intersection
751 */
753 {
755 
756  return segInterPoint(pfr, pto, lfr, lto, &pt);
757 }
758 
759 /*!
760 \brief Function for determines the point of two segment intersections
761 \param pfr, pto, lfr, lto and pt are pointers to Point objects
762 \return TRUE if the intersection was calculated with no errors or FALSE otherwise
763 */
764 
766 {
767  // Adapted from TWO-DIMENSIONAL CLIPPING: A VECTOR-BASED APPROACH
768  // Hans J.W. Spoelder, Fons H. Ullings in:
769  //// Graphics Gems I, pp.701,
770 
771  double a, b, c,
772  px, py, lx, ly, lpx, lpy, s;
773 
774  px = pto.getX() - pfr.getX();
775  py = pto.getY() - pfr.getY();
776  lx = lto.getX() - lfr.getX();
777  ly = lto.getY() - lfr.getY();
778  lpx = pfr.getX() - lfr.getX();
779  lpy = pfr.getY() - lfr.getY();
780 
781  a = py * lx - px * ly;
782  b = lpx * ly - lpy * lx;
783  c = lpx * py - lpy * px;
784 
785  if (a == 0) // Linhas paralelas
786  return false;
787  else
788  {
789  if (a > 0)
790  {
791  if ((b < 0) || (b > a) || (c < 0) || (c > a))
792  return false;
793  }
794  else
795  {
796  if ((b > 0) || (b < a) || (c > 0) || (c < a))
797  return false;
798  }
799  if (pt)
800  {
801  s = b / a;
802  pt->setX(pfr.getX() + (px*s));
803  pt->setY(pfr.getY() + (py*s));
804  }
805  }
806  return true;
807 }
808 
809 
810 /*!
811 \brief Function that test the vertex values
812 \param isolin is the isolin value of a given isolin
813 \param p3da is a pointer to a vector with Point3d objects
814 \return TRUE if the vertex values are in the same isolin or FALSE otherwise
815 */
816 bool te::mnt::testVertexValues(double isolin, te::gm::Point *p3da)
817 {
818  double delta = .9999;
819  size_t i;
820 
821  for (i = 0; i < 3; i++)
822  if (p3da[i].getZ() == isolin)
823  p3da[i].setZ(isolin*delta);
824 
825 
826  if ((p3da[0].getZ() == std::numeric_limits<double>::max()) ||
827  (p3da[1].getZ() == std::numeric_limits<double>::max()) ||
828  (p3da[2].getZ() == std::numeric_limits<double>::max()))
829  return false;
830 
831  if ((p3da[0].getZ() < isolin) &&
832  (p3da[1].getZ() < isolin) &&
833  (p3da[2].getZ() < isolin))
834  return false;
835 
836  if ((p3da[0].getZ() > isolin) &&
837  (p3da[1].getZ() > isolin) &&
838  (p3da[2].getZ() > isolin))
839  return false;
840 
841  for (i = 0; i < 3; i++)
842  {
843  if ((p3da[i].getZ() == isolin) &&
844  (p3da[(i + 1) % 3].getZ() > isolin) &&
845  (p3da[(i + 2) % 3].getZ() > isolin))
846  return false;
847  if ((p3da[i].getZ() == isolin) &&
848  (p3da[(i + 1) % 3].getZ() < isolin) &&
849  (p3da[(i + 2) % 3].getZ() < isolin))
850  return false;
851  }
852 
853  return true;
854 }
855 
856 
857 /*!
858 \brief Function that defines the intersections between an isoline and a triangle
859 \param ptline is a pointer to a Line object
860 \param p3da is a pointer to a Point3d object
861 \return TRUE if the intersections are defined or FALSE otherwise
862 */
863 
864 bool te::mnt::defineInterTriangle(std::vector<te::gm::Point> &ptline, te::gm::Point *p3da, double isolin)
865 {
866  size_t contrl = 0;
867 
868  // Verify if contour intercepts triangle
869  if ((isolin < p3da[0].getZ()) && (isolin < p3da[1].getZ()) &&
870  (isolin < p3da[2].getZ()))
871  return false;
872 
873  if ((isolin > p3da[0].getZ()) && (isolin > p3da[1].getZ()) &&
874  (isolin > p3da[2].getZ()))
875  return false;
876 
877  if (((isolin <= p3da[0].getZ()) && (isolin > p3da[1].getZ())) ||
878  ((isolin > p3da[0].getZ()) && (isolin <= p3da[1].getZ())))
879  {// Calculate intersection with edge 0
880  if (!defineInterEdge(ptline, p3da[0], p3da[1], isolin))
881  return false;
882  contrl++;
883  }
884 
885  if (((isolin <= p3da[1].getZ()) && (isolin > p3da[2].getZ())) ||
886  ((isolin > p3da[1].getZ()) && (isolin <= p3da[2].getZ())))
887  {// Calculate intersection with edge 0
888  if (!defineInterEdge(ptline, p3da[1], p3da[2], isolin))
889  return false;
890  contrl++;
891  }
892 
893  if (((isolin <= p3da[2].getZ()) && (isolin > p3da[0].getZ())) ||
894  ((isolin > p3da[2].getZ()) && (isolin <= p3da[0].getZ())))
895  {// Calculate intersection with edge 0
896  if (!defineInterEdge(ptline, p3da[2], p3da[0], isolin))
897  return false;
898  contrl++;
899  }
900  if (contrl != 2)
901  return false;
902 
903  return true;
904 }
905 
906 
907 /*!
908 \brief Function that defines the intersection with an edge of a triangle
909 \param ptline is a pointer to a Line object
910 \param fpt and spt are the first and second point of the edge
911 \return TRUE if the intersection is defined or FALSE otherwise
912 */
913 
914 bool te::mnt::defineInterEdge(std::vector<te::gm::Point> &ptline, te::gm::Point &fpt, te::gm::Point &spt, double isolin)
915 {
916  te::gm::Point dvect(0, te::gm::PointZType); // Vector from fpt to spt
918  double paux;// Parametric variable
919 
920  if (spt.getZ() == fpt.getZ())
921  return false;
922 
923  dvect.setX(spt.getX() - fpt.getX());
924  dvect.setY(spt.getY() - fpt.getY());
925  dvect.setZ(spt.getZ() - fpt.getZ());
926 
927  paux = (isolin - fpt.getZ()) / dvect.getZ(); // t = (Z - Z0) / C
928 
929  pt.setX((fpt.getX() + dvect.getX() * paux)); // X = X0 + A * t
930  pt.setY((fpt.getY() + dvect.getY() * paux)); // Y = Y0 + B * t
931  pt.setZ(isolin);
932 
933  ptline.push_back(pt);
934  return true;
935 }
936 
937 bool te::mnt::extractLines(std::vector<te::gm::Point> &pline, std::vector< std::unique_ptr< te::gm::LineString > > &clinlist, double scale)
938 {
939  std::vector<te::gm::Point> velin;
941 
942  std::vector<te::gm::Point>::iterator it, itf, itn;
943  short borda; // borda = 1 no boundary reached, 2 one boundary reached.
944 
945 
946  initLineVector(pline, velin);
947  borda = 1;
948 
949  //index pindex to the current point of old line
950  it = itf = pline.begin();
951  itn = ++it;
952  te::gm::Point ptf(*itf);
953  te::gm::Point ptn(*itn);
954  while (it != pline.end())
955  {
956  ptf = *itf;
957  ptn = *itn;
958  pt = velin[velin.size()-1];
959  if (equalFptSpt(ptf, pt, scale))
960  {// conection on ptf
961  velin.push_back(ptn);
962  --it;
963  it = itf = pline.erase(it);
964  itn = pline.erase(it);
965  }
966  else if (equalFptSpt(ptn, pt, scale))
967  {// conection on ptn
968  velin.push_back(ptf);
969  --it;
970  it = itf = pline.erase(it);
971  itn = pline.erase(it);
972  }
973  else
974  {
975  itf = ++it;;
976  if (it != pline.end())
977  itn = ++it;
978  if (itf == pline.end() || itn == pline.end())
979  {// There are no points to match
980  if (borda == 2)
981  {// If first point is on boundary -> open contour
982  assembLine(clinlist, velin);
983  initLineVector(pline, velin); //SSL0296
984  borda = 1;
985  }
986  else
987  {// If not on boundary, invert line points
988  std::reverse(velin.begin(), velin.end());
989  borda = 2;
990  }
991  it = itf = pline.begin();
992  if (it == pline.end())
993  break;
994  itn = ++it;
995  }
996  continue;
997  }
998 
999  ptf = velin[0];
1000  ptn = velin[velin.size()-1];
1001  if (Equal(ptf, ptn, scale))
1002  {// If closed contour
1003  assembLine(clinlist, velin);
1004  initLineVector(pline, velin);
1005  }
1006  it= itf = pline.begin();
1007  if (it == pline.end())
1008  break;
1009  itn = ++it;
1010  }
1011 
1012  assembLine(clinlist, velin);
1013 
1014  return true;
1015 }
1016 
1017 /*************************************************************
1018 NAME : initLineVector
1019 AUTHOR : Laercio Namikawa aug-95
1020 RESUME : Initialize Line Vector with points of a line.
1021 INPUT : pline line
1022 OUTPUT : vect line with first and second points
1023 RETURN : TRUE successful
1024 FALSE failure
1025 *************************************************************/
1026 bool te::mnt::initLineVector(std::vector<te::gm::Point> &pline, std::vector<te::gm::Point> &vect)
1027 {
1028  short c;
1029  std::vector<te::gm::Point>::iterator it;
1030 
1031  if (vect.size() != 0)
1032  vect.clear();
1033 
1034  if (pline.size() < 2)
1035  return true;
1036 
1037  for (c = 0; c < 2; c++)
1038  {
1039  vect.push_back(*pline.begin());
1040  pline.erase(pline.begin());
1041  }
1042 
1043  if (vect.size() != 2)
1044  return false;
1045  return true;
1046 }
1047 
1048 
1049 /*************************************************************
1050 NAME : assembLine
1051 AUTHOR : Laercio Namikawa aug-95
1052 RESUME : Assemble a line with Line points and
1053 save in LineList.
1054 INPUT : vect line with points
1055 OUTPUT : linlout output linelist
1056 RETURN : TRUE successful
1057 FALSE failure
1058 *************************************************************/
1059 bool te::mnt::assembLine(std::vector< std::unique_ptr< te::gm::LineString > > &linlout, std::vector<te::gm::Point> &vect)
1060 {
1061  if (vect.size() <= 1)
1062  return true;
1063 
1064  std::unique_ptr< te::gm::LineString > linout(new te::gm::LineString(vect.size(), te::gm::LineStringZType));
1065 
1066  for (size_t i = 0; i < vect.size(); i++)
1067  linout->setPointN(i, vect[i]);
1068 
1069  linlout.push_back(std::move(linout));
1070 
1071  return true;
1072 }
1073 
1074 /*!
1075 \brief Function that defines the triangle normal vector
1076 \param p3da are pointers to objets Point3d representing the triangle vertices
1077 \param nvector are the coordinates of the normal vector
1078 \return TRUE always
1079 */
1080 
1081 bool te::mnt::triangleNormalVector(te::gm::Point *p3da, double *nvector)
1082 {
1083  double ux, vx, uy, vy, uz, vz;
1084 
1085  if ((p3da == NULL) || (nvector == NULL)){
1086  return false;
1087  }
1088 
1089  nvector[0] = 0.;
1090  nvector[1] = 0.;
1091 
1092  // Define normal vector (uvx,uvy,uvz)
1093  ux = p3da[1].getX() - p3da[0].getX();
1094  vx = p3da[2].getX() - p3da[0].getX();
1095  uy = p3da[1].getY() - p3da[0].getY();
1096  vy = p3da[2].getY() - p3da[0].getY();
1097  uz = p3da[1].getZ() - p3da[0].getZ();
1098  vz = p3da[2].getZ() - p3da[0].getZ();
1099 
1100  if ((ux == 0) && (vx == 0))
1101  {
1102  nvector[0] = 1.;
1103  nvector[1] = 0.;
1104  nvector[2] = 0.;
1105  return true;
1106  }
1107  if ((uy == 0) && (vy == 0))
1108  {
1109  nvector[0] = 0.;
1110  nvector[1] = 1.;
1111  nvector[2] = 0.;
1112  return true;
1113  }
1114  if ((uz == 0) && (vz == 0))
1115  {
1116  nvector[0] = 0.;
1117  nvector[1] = 0.;
1118  nvector[2] = 1.;
1119  return true;
1120  }
1121 
1122  nvector[2] = ux * vy - vx * uy;
1123  if (nvector[2] < 0.)
1124  {
1125  // Make sure that normal vector is always positive
1126  nvector[2] = -nvector[2];
1127  nvector[0] = vy * uz - uy * vz;
1128  nvector[1] = ux * vz - vx * uz;
1129  }
1130  else
1131  {
1132  nvector[0] = uy * vz - vy * uz;
1133  nvector[1] = vx * uz - ux * vz;
1134  }
1135  return true;
1136 }
1137 
1138 /*!
1139 \brief Function that normalize a vector by its size
1140 \param nvector is a pointer to the vector coordinates x, y and z
1141 \return TRUE always
1142 */
1143 
1144 bool te::mnt::normalizeVector(double *nvector)
1145 {
1146  double vectorSize;
1147 
1148  if (nvector == NULL){
1149  return false;
1150  }
1151 
1152  vectorSize = sqrt(nvector[0] * nvector[0] + nvector[1] * nvector[1] + nvector[2] * nvector[2]);
1153 
1154  if (vectorSize != 0.)
1155  {
1156  nvector[0] = nvector[0] / vectorSize;
1157  nvector[1] = nvector[1] / vectorSize;
1158  nvector[2] = nvector[2] / vectorSize;
1159  }
1160  return true;
1161 }
1162 
1163 /*!
1164 \brief Function that checks if a point pt is on a segment
1165 \param pt, fseg, lseg are pointers to Point objects
1166 \param tol is the tolerance distance between the point and the segment
1167 \return true if the point is on the segment or false otherwise
1168 */
1170 {
1171  double pax, pay, bax, bay;
1172  double area2, minxy, daux;
1173 
1174  if ((pt.getX() < fseg.getX()) && (pt.getX() < lseg.getX()))
1175  return false;
1176  if ((pt.getY() < fseg.getY()) && (pt.getY() < lseg.getY()))
1177  return false;
1178  if ((pt.getX() > fseg.getX()) && (pt.getX() > lseg.getX()))
1179  return false;
1180  if ((pt.getY() > fseg.getY()) && (pt.getY() > lseg.getY()))
1181  return false;
1182  pax = pt.getX() - fseg.getX();
1183  bax = lseg.getX() - fseg.getX();
1184  if ((pax == 0.) && (bax == 0.))
1185  // On segment
1186  return true;
1187 
1188  pay = pt.getY() - fseg.getY();
1189  bay = lseg.getY() - fseg.getY();
1190  if ((pay == 0.) && (bay == 0.))
1191  // On segment
1192  return true;
1193 
1194  area2 = fabs((pay * bax) - (pax * bay));
1195  bax = fabs(bax);
1196  bay = fabs(bay);
1197  minxy = bay;
1198  if (bax < bay)
1199  minxy = bax;
1200  daux = area2 / (bax + bay - (minxy / 2));
1201 
1202  if (daux < tol)
1203  // On segment
1204  return true;
1205 
1206  return false;
1207 }
1208 
1209 
1211 {
1212  double a, b, c, ip, ipt;
1213 
1214  a = lseg.getY() - fseg.getY();
1215  b = fseg.getX() - lseg.getX();
1216  c = lseg.getX()*fseg.getY() - fseg.getX()*lseg.getY();
1217  ip = a*pt1.getX() + b*pt1.getY() + c;
1218  if (ip == 0.) // On segment
1219  return -1;
1220  ipt = a*pt2.getX() + b*pt2.getY() + c;
1221  if ((ip > 0.) && (ipt < 0.))
1222  return 0;
1223  if ((ip < 0.) && (ipt > 0.))
1224  return 0;
1225 
1226  // On same side
1227  return 1;
1228 }
1229 
1230 /*!
1231 \brief Function that filters the points that are closer considering a given tolerance
1232 \param p3dl is a pointer to a list of Point3dList objects
1233 \param tol is a tolerance value
1234 \return TRUE always
1235 */
1236 
1237 bool te::mnt::point3dListFilter(std::vector<te::gm::Point> &p3dl, std::vector<bool> &fixed, double tol)
1238 {
1240  int32_t npts, i, j, maxdiffindex = 0;
1241  double x0 = 0, y0 = 0, coef[5];
1242  double maxdiff;
1243  double maxfixptdiff;
1244  short degree;
1245 
1246  npts = 0;
1247 
1248  try
1249  {
1250  double *vectd = new double[200];
1251  double *vectz = new double[200];
1252  double *vectx = new double[200];
1253  double *vecty = new double[200];
1254  double *fvectz = new double[200];
1255  short *ptype = new short[200];
1256 
1257  te::gm::Point *p3dlaux[200];
1258  for(i = 0; i < 200; ++i)
1259  p3dlaux[i] = new te::gm::Point(0, te::gm::PointZType);
1260 
1261  npts = 0;
1262  for (size_t pp = 0; pp < p3dl.size(); pp++)
1263  {
1264  p3d = p3dl[pp];
1265  if ((p3d.getX() >= std::numeric_limits< float >::max()) || (npts > 199))
1266  {
1267  // If last point of a line
1268  maxdiff = std::numeric_limits< float >::max();
1269  maxfixptdiff = std::numeric_limits< float >::max();
1270  j = 4;
1271  while ((maxdiff > tol) && (maxfixptdiff > tol) &&
1272  (j > 3) && (npts > 3))
1273  {
1274  j = 0;
1275  for (i = 0; i < npts; i++)
1276  {
1277  if (ptype[i] == 0)
1278  continue;
1279  vectx[j] = vectd[i];
1280  vecty[j++] = vectz[i];
1281  }
1282  if (j < 3)
1283  break;
1284  if (j < 5)
1285  degree = 1;
1286  else if (j < 8)
1287  degree = 2; //6 is minimum npts for 3rd degree
1288  else
1289  degree = 3; //8 is minimum npts for 3rd degree
1290  Least_square_fitting(vectx, vecty, (short)j, degree, coef);
1291  for (i = 0; i < npts; i++)
1292  {
1293  fvectz[i] = coef[0];
1294  for (j = 1; j <= degree; j++)
1295  fvectz[i] += coef[j] * pow(vectd[i], (double)j);
1296  }
1297  maxfixptdiff = 0.;
1298  for (i = 0; i < npts; i++)
1299  {
1300  if ((ptype[i] == 0) || (ptype[i] == 1))
1301  continue;
1302  if (fabs(fvectz[i] - vectz[i]) > maxfixptdiff)
1303  maxfixptdiff = (float)fabs(fvectz[i] - vectz[i]);
1304  }
1305  maxdiff = 0.;
1306  for (i = 0; i < npts; i++)
1307  {
1308  if ((ptype[i] == 0) || (ptype[i] == 2))
1309  continue;
1310  if (fabs(fvectz[i] - vectz[i]) > maxdiff)
1311  {
1312  maxdiff = (float)fabs(fvectz[i] - vectz[i]);
1313  maxdiffindex = i;
1314  }
1315  }
1316  if (i == 0)
1317  break;
1318  ptype[maxdiffindex] = 0;
1319  }
1320 
1321  for (i = 0; i < npts; i++)
1322  {
1323  p3d = *p3dlaux[i];
1324  p3d.setZ(fvectz[i]);
1325  }
1326  npts = 0;
1327  continue;
1328  }
1329  if (npts == 0)
1330  {
1331  x0 = p3d.getX();
1332  y0 = p3d.getY();
1333  }
1334 
1335  p3dlaux[npts]->setX(p3d.getX());
1336  p3dlaux[npts]->setY(p3d.getY());
1337 
1338  vectd[npts] = sqrt((p3d.getX() - x0)*(p3d.getX() - x0) +
1339  (p3d.getY() - y0)*(p3d.getY() - y0));
1340  if (npts > 0)
1341  vectd[npts] += vectd[npts - 1];
1342  if (p3d.getZ() < std::numeric_limits< float >::max())
1343  ptype[npts] = 1;
1344  else
1345  ptype[npts] = 0;
1346  if (!fixed[pp])
1347  ptype[npts] = 2;
1348  vectz[npts] = p3d.getZ();
1349  fvectz[npts++] = p3d.getZ();
1350  x0 = p3d.getX();
1351  y0 = p3d.getY();
1352  }
1353 
1354  delete[] vectd;
1355  delete[] vectz;
1356  delete[] vectx;
1357  delete[] vecty;
1358  delete[] fvectz;
1359  delete[] ptype;
1360 
1361  for(size_t ii = 0; ii < 200; ++ii)
1362  delete p3dlaux[ii];
1363 
1364  }
1365  catch (std::bad_alloc& ba)
1366  {
1367  std::cerr << "bad_alloc caught: " << ba.what() << '\n';
1368  return false;
1369  }
1370 
1371  return true;
1372 }
1373 
1374 /*!
1375 \brief Function that performs a leat square fitting in a set of points
1376 \param vectx and vecty are the point coordinates
1377 \param np is the number of points
1378 \param deg is degree of the polynomium used in the fitting
1379 \param coef is a pointer to the the polynomiun coefficients
1380 \return TRUE if the fitting was performed with no errors or FALSE otherwise
1381 */
1382 
1383 bool te::mnt::Least_square_fitting(double *vectx, double *vecty, short np, short deg, double *coef)
1384 {
1385  short i, j, m, n;
1386  double matx[6][6];
1387  double *powx,
1388  *sumpow,
1389  *fx;
1390 
1391  if (np > 200)
1392  return false;
1393 
1394  try
1395  {
1396  powx = new double[(unsigned)np];
1397  sumpow = new double[200];
1398  fx = new double[(unsigned)np];
1399  }
1400  catch (std::bad_alloc& ba)
1401  {
1402  std::cerr << "bad_alloc caught: " << ba.what() << '\n';
1403  return false;
1404  }
1405 
1406  // initialization
1407  for (i = 0; i<np; i++)
1408  {
1409  powx[i] = 1.;
1410  fx[i] = vecty[i];
1411  }
1412 
1413  // compute the rigth hand side of the first normal equation
1414  matx[0][deg + 1] = 0;
1415  for (i = 0; i<np; i++)
1416  matx[0][deg + 1] = matx[0][deg + 1] + vecty[i];
1417 
1418  // compute the rigth hand side of the other normal equation
1419  // and also the sums
1420  sumpow[0] = np;
1421  for (i = 1; i <= deg; i++)
1422  {
1423  sumpow[i] = 0;
1424  matx[i][deg + 1] = 0;
1425 
1426  for (j = 0; j< np; j++)
1427  {
1428  powx[j] = powx[j] * vectx[j];
1429  fx[j] = fx[j] * vectx[j];
1430  sumpow[i] = sumpow[i] + powx[j];
1431  matx[i][deg + 1] = matx[i][deg + 1] + fx[j];
1432  }
1433  }
1434 
1435  for (i = deg + 1; i< 2 * (deg + 1); i++)
1436  {
1437  sumpow[i] = 0;
1438  for (j = 0; j<np; j++)
1439  {
1440  powx[j] = powx[j] * vectx[j];
1441  sumpow[i] = sumpow[i] + powx[j];
1442  }
1443  }
1444 
1445  for (i = 0; i <= deg; i++)
1446  for (j = 0; j <= deg; j++)
1447  matx[i][j] = sumpow[i + j];
1448 
1449  // perform Gaussian elimination
1450  m = deg + 1;
1451  n = 1;
1452 
1453  delete[] powx;
1454  delete[] sumpow;
1455  delete[] fx;
1456 
1457  if (!Gauss_elimination(m, n, matx))
1458  {
1459  return false;
1460  }
1461 
1462  for (i = 0; i<deg + 1; i++)
1463  coef[i] = matx[i][m];
1464 
1465  return false;
1466 }
1467 
1468 
1469 /*********************************************************************
1470 NAME : Gauss_elimination
1471 AUTHOR : Jose Claudio Mura oct - 95
1472 RESUME : Solve a system of linear equation throught the Gauss
1473 elimination method.
1474 INPUT : Number of the variables (m), number of equations (n) and
1475 array with the variables (mat).
1476 OUTPUT : Solution in the last column of the (a).
1477 RETURN : TRUE successful
1478 FALSE failure
1479 *********************************************************************/
1480 
1481 bool te::mnt::Gauss_elimination(short m, short n, double mat[6][6])
1482 {
1483  short i, j, k, l, ii, jj, kk;
1484  double aux, piv, eps;
1485 
1486  /*-- estimated error bound (machine epsilon) --*/
1487  eps = .000000001;
1488 
1489  if (m > 1)
1490  {
1491  for (i = 0; i<m - 1; i++)
1492  {
1493  piv = fabs(mat[i][i]);
1494  ii = i + 1;
1495  jj = i;
1496 
1497  /*-- search for the index in of maximum pivot value -*/
1498  for (j = ii; j< m; j++)
1499  {
1500  if (fabs(mat[j][i]) > piv)
1501  {
1502  piv = fabs(mat[j][i]);
1503  jj = j;
1504  }
1505  }
1506 
1507  if (i != jj)
1508  {
1509  /*-- interchange rows i and index jj --*/
1510  for (j = i; j< m + n; j++)
1511  {
1512  aux = mat[i][j];
1513  mat[i][j] = mat[jj][j];
1514  mat[jj][j] = aux;
1515  }
1516  }
1517 
1518  /*-- check if pivot is too smal --*/
1519  if (piv < eps)
1520  {
1521  return false;
1522  }
1523 
1524  /*-- forward elimination step --*/
1525  for (j = ii; j< m; j++)
1526  {
1527  for (k = ii; k< m + n; k++)
1528  mat[j][k] = mat[j][k] - mat[j][i] * mat[i][k] / mat[i][i];
1529  }
1530  }
1531 
1532  if (fabs(mat[m - 1][m - 1]) < eps)
1533  {
1534  return false;
1535  }
1536 
1537  /*-- back substitution --*/
1538  for (i = 0; i<n; i++)
1539  {
1540  mat[m - 1][i + m] = mat[m - 1][i + m] / mat[m - 1][m - 1];
1541 
1542  for (j = 0; j<m - 1; j++)
1543  {
1544  k = m - j - 2;
1545  kk = k + 1;
1546 
1547  for (l = kk; l<m; l++)
1548  mat[k][i + m] = mat[k][i + m] - mat[l][i + m] * mat[k][l];
1549 
1550  mat[k][i + m] = mat[k][i + m] / mat[k][k];
1551  }
1552  }
1553  }
1554  else
1555  {
1556  if (fabs(mat[0][0]) < eps)
1557  {
1558  return false;
1559  }
1560 
1561  for (i = 0; i<n; i++)
1562  mat[0][m + i] = mat[0][m + i] / mat[0][0];
1563  }
1564 
1565  return true;
1566 }
1567 
1568 
1569 bool te::mnt::SaveIso(std::string& outDsetName, te::da::DataSourcePtr &outDsrc, std::vector< std::unique_ptr< te::gm::LineString > > &isolist, std::vector<double> &guidevalues, int srid)
1570 {
1571  std::unique_ptr<te::da::DataSetType> dt(new te::da::DataSetType(outDsetName));
1572 
1573  //Primary key
1574  std::unique_ptr<te::dt::SimpleProperty> prop0(new te::dt::SimpleProperty("FID", te::dt::INT32_TYPE));
1575  prop0->setAutoNumber(true);
1576  std::unique_ptr<te::dt::SimpleProperty> prop1 (new te::dt::SimpleProperty("Z", te::dt::DOUBLE_TYPE));
1577  std::unique_ptr<te::dt::SimpleProperty> prop11(new te::dt::SimpleProperty("type", te::dt::STRING_TYPE));
1578  std::unique_ptr<te::gm::GeometryProperty> prop2(new te::gm::GeometryProperty("iso", 0, te::gm::LineStringZType, true));
1579  prop2->setSRID(srid);
1580  dt->add(prop0.release());
1581  dt->add(prop1.release());
1582  dt->add(prop11.release());
1583  dt->add(prop2.release());
1584 
1585  std::unique_ptr<te::mem::DataSet> ds(new te::mem::DataSet(dt.get()));
1586 
1587  int id = 0;
1588 
1589  te::common::TaskProgress task("Saving Isolines...", te::common::TaskProgress::UNDEFINED, (int)isolist.size());
1590 
1591  for (unsigned int Idx = 0; Idx < isolist.size(); ++Idx)
1592  {
1593  if (!task.isActive())
1594  return false;
1595  task.pulse();
1596 
1597  te::mem::DataSetItem* dataSetItem =new te::mem::DataSetItem(ds.get());
1598  isolist[Idx]->setSRID(srid);
1599  double *zvalue = isolist[Idx]->getZ();
1600  dataSetItem->setInt32(0, id++);
1601  if (zvalue){
1602  dataSetItem->setDouble(1, zvalue[0]);
1603  if (std::find(guidevalues.begin(), guidevalues.end(), zvalue[0]) != guidevalues.end())
1604  dataSetItem->setString(2, "GUIDELINE");
1605  else
1606  dataSetItem->setString(2, "NORMAL");
1607  }
1608  dataSetItem->setGeometry(3, isolist[Idx].release());
1609 
1610  ds->add(dataSetItem);
1611  }
1612  te::vp::Save(outDsrc.get(), ds.get(), dt.get());
1613 
1614  return true;
1615 
1616 }
1617 
1619 {
1620  if (type == 0) //lenght
1621  {
1622  switch (planar->getId())
1623  {
1624  case te::common::UOM_Metre:
1625  val *= 111000.; // 1 degree = 111.000 meters
1626  break;
1628  val *= 111.; // 1 degree = 111 kilometers
1629  break;
1630  case te::common::UOM_Foot:
1631  val *= 364173.24; // 1 feet = 3.28084 meters
1632  break;
1633  default:
1634  return false;
1635  }
1636  }
1637 
1638  if (type == 1) //area
1639  {
1640  switch (planar->getId())
1641  {
1642  case te::common::UOM_Metre:
1643  val *= 111000. * 111000.; // 1 degree = 111.000 meters
1644  break;
1646  val *= 111. * 111.; // 1 degree = 111 kilometers
1647  break;
1648  case te::common::UOM_Foot:
1649  val *= 364173.24 * 364173.24; // 1 feet = 3.28084 meters
1650  break;
1651  default:
1652  return false;
1653  }
1654  }
1655  return true;
1656 }
1657 
1658 
1660 {
1661  switch (unit->getId())
1662  {
1663  case te::common::UOM_Metre:
1664  val /= 111000; // 1 degree = 111.000 meters
1665  break;
1667  val /= 111; // 1 degree = 111 kilometers
1668  break;
1669  case te::common::UOM_Foot:
1670  val /= 364173.24; // 1 feet = 3.28084 meters
1671  break;
1672  default:
1673  return false;
1674  }
1675  return true;
1676 }
1677 
1678 void te::mnt::getMinMax(te::rst::Raster *inputRst, double &vmin, double &vmax)
1679 {
1680  double min = std::numeric_limits<double>::max();
1681  double max = std::numeric_limits<double>::min();
1682 
1683  std::complex<double> pixel;
1684  unsigned int rf = inputRst->getNumberOfRows() - 1;
1685  unsigned int cf = inputRst->getNumberOfColumns() - 1;
1686  double no_data = inputRst->getBand(0)->getProperty()->m_noDataValue;
1687 
1688  for (unsigned r = 0; r <= rf; r++)
1689  for (unsigned c = 0; c <= cf; c++)
1690  {
1691  inputRst->getValue(c, r, pixel);
1692 
1693  if (pixel.real() == no_data)
1694  continue;
1695 
1696  if (pixel.real() < min)
1697  min = pixel.real();
1698 
1699  if (pixel.real() > max)
1700  max = pixel.real();
1701  }
1702 
1703  vmin = min;
1704  vmax = max;
1705 }
1706 
1708 {
1709  double d12, xmin, ymin;
1710 
1711  double xi = first.getX();
1712  double xf = last.getX();
1713  double yi = first.getY();
1714  double yf = last.getY();
1715  double x = pin.getX();
1716  double y = pin.getY();
1717 
1718  double dx = xf - xi;
1719  double dy = yf - yi;
1720  double a2 = (y - yi) * dx - (x - xi)*dy;
1721 
1722  if (dx == 0. && dy == 0.)
1723  {
1724  d12 = sqrt(((x - xi) * (x - xi)) + ((y - yi) * (y - yi)));
1725  d12 *= d12;
1726  }
1727  else
1728  d12 = a2 * a2 / (dx * dx + dy * dy);
1729 
1730  if (dx == 0.)
1731  {
1732  xmin = xi;
1733  ymin = y;
1734  }
1735  else if (dy == 0.)
1736  {
1737  xmin = x;
1738  ymin = yi;
1739  }
1740  else
1741  {
1742  double alfa = dy / dx;
1743  xmin = (x + alfa * (y - yi) + alfa * alfa * xi) / (1. + alfa * alfa);
1744  ymin = (x - xmin) / alfa + y;
1745  }
1746 
1747  pinter.x = xmin;
1748  pinter.y = ymin;
1749  return (sqrt(d12));
1750 }
1751 
1752 
1754 {
1755  if (dt->hasGeom())
1756  {
1758  if (gmType == te::gm::PointType || gmType == te::gm::MultiPointType ||
1759  gmType == te::gm::PointZType || gmType == te::gm::MultiPointZType ||
1760  gmType == te::gm::PointMType || gmType == te::gm::MultiPointMType ||
1761  gmType == te::gm::PointZMType || gmType == te::gm::MultiPointZMType) //samples
1762  return SAMPLE;
1763 
1764  if (gmType == te::gm::LineStringType || gmType == te::gm::MultiLineStringType ||
1765  gmType == te::gm::LineStringZType || gmType == te::gm::MultiLineStringZType ||
1766  gmType == te::gm::LineStringMType || gmType == te::gm::MultiLineStringMType ||
1767  gmType == te::gm::LineStringZMType || gmType == te::gm::MultiLineStringZMType) //isolines
1768  return ISOLINE;
1769 
1770  if (gmType == te::gm::TINZType || gmType == te::gm::MultiPolygonZType || gmType == te::gm::PolyhedralSurfaceZType || gmType == te::gm::PolygonZType ||
1771  gmType == te::gm::GeometryType)//TIN
1772  return TIN;
1773 
1774  }
1775  if (dt->hasRaster()) //GRID
1776  {
1777  return GRID;
1778  }
1779 
1780  return OTHER;
1781 
1782 }
void setZ(std::size_t i, const double &z)
It sets the n-th z coordinate value.
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
TEMNTEXPORT bool Least_square_fitting(double *vectx, double *vecty, short np, short deg, double *coef)
Function that performs a leat square fitting in a set of points.
TEMNTEXPORT bool initLineVector(std::vector< te::gm::Point > &pline, std::vector< te::gm::Point > &vect)
Geometric property.
void init(const double &llx, const double &lly, const double &urx, const double &ury)
It initializes (sets) the envelope bounds.
TEMNTEXPORT bool convertPlanarToAngle(double &val, te::common::UnitOfMeasurePtr unit)
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
double y
y-coordinate.
Definition: Coord2D.h:114
void setDouble(std::size_t i, double value)
It sets the value of the i-th property.
An atomic property like an integer or double.
TEMNTEXPORT te::gm::LineString * DouglasPeuckerTA(te::gm::LineString *lineIn, double simpFactor, double Zvalue)
boost::shared_ptr< DataSource > DataSourcePtr
Coord2D * getCoordinates() const
It returns a pointer to the internal array of coordinates.
Definition: LineString.h:456
static te::dt::Date dx(2010, 12, 31)
bool hasGeom() const
It returns true if the DataSetType has at least one geometry property; otherwise, it returns false...
Definition: DataSetType.h:655
double x
x-coordinate.
Definition: Coord2D.h:113
A class that models the description of a dataset.
Definition: DataSetType.h:72
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
TEMNTEXPORT bool normalizeVector(double *)
Function that normalize a vector by its size.
TEMNTEXPORT bool Equal(te::gm::Point &p1, te::gm::Point &p2, double &tol)
te::gm::LineString * GEOS_DouglasPeucker(te::gm::LineString *ls, double snap)
Definition: GAP.cpp:261
TEMNTEXPORT double Distance(const te::gm::Coord2D &pt1, const te::gm::Coord2D &pt2)
TEMNTEXPORT te::gm::Point Max(te::gm::Point &p1, te::gm::Point &p2)
TEMNTEXPORT bool Gauss_elimination(short m, short n, double mat[6][6])
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
#define MIN(a, b)
Macro that returns min between two values.
TEMNTEXPORT te::gm::LineString * GEOS_DouglasPeucker(te::gm::LineString *ls, double snap, double Zvalue)
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
double getY() const
It returns the y-coordinate.
Definition: Coord2D.h:108
static te::dt::Date ds(2010, 01, 01)
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits<double>::max().
Definition: BandProperty.h:136
TEMNTEXPORT double pointToSegmentDistance(te::gm::Point &fseg, te::gm::Point &lseg, te::gm::Point &pt, te::gm::Point *pti)
double TePerpendicularDistance(const te::gm::Coord2D &first, const te::gm::Coord2D &last, const te::gm::Coord2D &pin, te::gm::Coord2D &pinter)
#define MAX(a, b)
Macro that returns max between two values.
te::gm::Point * pt2
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
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
TEMNTEXPORT bool assembLine(std::vector< std::unique_ptr< te::gm::LineString > > &linlout, std::vector< te::gm::Point > &vect)
TEMNTEXPORT double PerpendicularDistance(te::gm::Coord2D &first, te::gm::Coord2D &last, te::gm::Coord2D &pin, te::gm::Coord2D &pinter)
TEMNTEXPORT size_t ReadPoints(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, te::gm::MultiPoint &mpt, std::string &geostype, te::gm::Envelope &env)
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
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
An Envelope defines a 2D rectangular region.
An abstract class for raster data strucutures.
TEMNTEXPORT bool equalFptSpt(te::gm::Point &fpt, te::gm::Point &spt, double scale)
virtual te::dt::AbstractData * clone() const
It clones the point.
TEMNTEXPORT te::gm::LineString * pointListSimplify(te::gm::LineString *ls, double snap, double maxdist, double Zvalue)
unsigned int getNumberOfRows() const
Returns the raster number of rows.
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
te::gm::Point * pt1
bool hasRaster() const
It returns true if the DataSetType has at least one raster property; otherwise, it returns false...
Definition: DataSetType.h:660
BandProperty * getProperty()
Returns the band property.
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
TEMNTEXPORT bool point3dListFilter(std::vector< te::gm::Point > &p3dl, std::vector< bool > &fixed, double tol)
Function that filters the points that are closer considering a given tolerance.
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
static te::dt::TimeDuration dt(20, 30, 50, 11)
TEMNTEXPORT bool defineInterEdge(std::vector< te::gm::Point > &, te::gm::Point &, te::gm::Point &, double)
Function that defines the intersection with an edge of a triangle.
te::gm::Polygon * p
TEMNTEXPORT bool testVertexValues(double, te::gm::Point *)
Function that test the vertex values.
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
void setPointZ(std::size_t i, const double &x, const double &y, const double &z)
It sets the value of the specified point.
bool is3D() const _NOEXCEPT_OP(true)
It returns true if this geometric object has z coordinate values.
double SegmentDistance(double fx, double fy, double lx, double ly, double ptx, double pty, double *pix, double *piy)
Function that evaluates the distance between a point and a segment.
Definition: GAP.cpp:185
Utility functions for the data access module.
TEMNTEXPORT bool extractLines(std::vector< te::gm::Point > &pline, std::vector< std::unique_ptr< te::gm::LineString > > &clinlist, double scale)
const double & getZ() const
It returns the Point z-coordinate value, if it has one or DoubleNotANumber otherwise.
Definition: Point.h:166
virtual void getValue(unsigned int c, unsigned int r, double &value, std::size_t b=0) const
Returns the attribute value of a band of a cell.
double Distance(const double pt1x, const double pt1y, const double pt2x, const double pt2y)
Definition: GAP.cpp:63
TEMNTEXPORT size_t ReadSamples(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, double max, Simplify alg, te::gm::MultiPoint &mpt, te::gm::MultiLineString &isolines, std::string &geostype, te::gm::Envelope &env, int srid=0)
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
MultiLineString is a MultiCurve whose elements are LineStrings.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
This file contains a class to calculate retangular grid from Samples. Adapted from SPRING...
TEMNTEXPORT double SegmentDistance(double fx, double fy, double lx, double ly, double ptx, double pty, double *pix, double *piy)
Function that evaluates the distance between a point and a segment.
double getX() const
It returns the x-coordinate.
Definition: Coord2D.h:102
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
TEMNTEXPORT int onSameSide(te::gm::Coord2D pt1, te::gm::Coord2D pt2, te::gm::Coord2D fseg, te::gm::Coord2D lseg)
void add(Geometry *g)
It adds the geometry into the collection.
void setSRID(int srid)
It sets the Spatial Reference System ID of the linestring.
TEMNTEXPORT short segIntersect(te::gm::Point &pfr, te::gm::Point &pto, te::gm::Point &lfr, te::gm::Point &lto)
Function for check segment intersection.
This file contains a class to calculate retangular grid from Samples using Spline Grass Interpolation...
const double & getZ(std::size_t i) const
It returns the n-th z coordinate value.
TEMNTEXPORT te::gm::Point Min(te::gm::Point &p1, te::gm::Point &p2)
void setPointN(std::size_t i, const Point &p)
It sets the value of the specified point to this new one.
TEMNTEXPORT bool defineInterTriangle(std::vector< te::gm::Point > &, te::gm::Point *, double)
Function that defines the intersections between an isoline and a triangle.
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
TEMNTEXPORT te::mnt::mntType getMNTType(const te::da::DataSetType *dt)
void setString(std::size_t i, const std::string &value)
It sets the value of the i-th property.
TEMNTEXPORT double coordToSegmentDistance(te::gm::Coord2D &fseg, te::gm::Coord2D &lseg, te::gm::Coord2D &pt, te::gm::Coord2D *pti)
TEMNTEXPORT bool segInterPoint(te::gm::Point &pfr, te::gm::Point &pto, te::gm::Point &lfr, te::gm::Point &lto, te::gm::Point *pt)
Function for determines the point of two segment intersections.
TEMNTEXPORT void getMinMax(te::rst::Raster *inputRst, double &vmin, double &vmax)
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
TEMNTEXPORT bool onSegment(te::gm::Point &pt, te::gm::Point &fseg, te::gm::Point &lseg, double tol)
Function that checks if a point pt is on a segment.
TEMNTEXPORT bool triangleNormalVector(te::gm::Point *, double *)
Function that defines the triangle normal vector.
TEMNTEXPORT bool SaveIso(std::string &outDsetName, te::da::DataSourcePtr &outDsrc, std::vector< std::unique_ptr< te::gm::LineString > > &isolist, std::vector< double > &guidevalues, int srid)
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
bool segInterPoint(te::gm::Coord2D &pfr, te::gm::Coord2D &pto, te::gm::Coord2D &lfr, te::gm::Coord2D &lto, te::gm::Coord2D *pt)
Definition: GAP.cpp:141
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
TEMNTEXPORT short findCenter(te::gm::Point *vert, double *pcx, double *pcy)
Function that finds the center of the vertices of a triangle.
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
TEMNTEXPORT bool convertAngleToPlanar(double &val, te::common::UnitOfMeasurePtr planar, int type)
static te::gm::LineString * pointListSimplify(te::gm::LineString *ls, double snap, double Zvalue)