src/terralib/geometry/Utils.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/geometry/Utils.cpp
22 
23  \brief Utility functions for the Geometry Module.
24 */
25 
26 // TerraLib
27 #include "../common/STLUtils.h"
28 #include "../core/translator/Translator.h"
29 #include "Curve.h"
30 #include "Envelope.h"
31 #include "Exception.h"
32 #include "Geometry.h"
33 #include "GeometryCollection.h"
34 #include "GEOSGeometryFactory.h"
35 #include "GEOSReader.h"
36 #include "GEOSWriter.h"
37 #include "Line.h"
38 #include "LinearRing.h"
39 #include "LineString.h"
40 #include "MultiLineString.h"
41 #include "MultiPolygon.h"
42 #include "Point.h"
43 #include "Polygon.h"
44 #include "Utils.h"
45 
46 // STL
47 #include <cmath>
48 #include <memory>
49 
50 #include <geos/algorithm/CentroidArea.h>
51 #include <geos/algorithm/CGAlgorithms.h>
52 #include <geos/algorithm/LineIntersector.h>
53 #include <geos/geom/Coordinate.h>
54 #include <geos/geom/Geometry.h>
55 #include <geos/geom/LineSegment.h>
56 #include <geos/geom/Point.h>
57 #include <geos/geom/Polygon.h>
58 #include <geos/operation/polygonize/Polygonizer.h>
59 #include <geos/operation/union/CascadedPolygonUnion.h>
60 #include <geos/operation/union/UnaryUnionOp.h>
61 #include <geos/operation/distance/DistanceOp.h>
62 #include <geos/operation/overlay/snap/GeometrySnapper.h>
63 #include <geos/operation/valid/IsValidOp.h>
64 #include <geos/util/GEOSException.h>
65 
66 const double TOLERANCE = 0.000000001;
67 
68 bool te::gm::IsEqual(const te::gm::Point& p1, const te::gm::Point& p2)
69 {
70  if ((p1.getX() == p2.getX()) && (p1.getY() == p2.getY()))
71  {
72  return true;
73  }
74 
75  return false;
76 }
77 
78 bool te::gm::IsEqual(const te::gm::Point& p1, const te::gm::Point& p2, double tol)
79 {
80  if (std::fabs(p1.getX() - p2.getX()) > tol)
81  {
82  return false;
83  }
84  if (std::fabs(p1.getY() - p2.getY()) > tol)
85  {
86  return false;
87  }
88 
89  return true;
90 }
91 
92 te::gm::Envelope te::gm::CreateEnvelope(double x1, double y1, double x2, double y2)
93 {
94  te::gm::Envelope envelope(std::min(x1, x2)
95  , std::min(y1, y2)
96  , std::max(x1, x2)
97  , std::max(y1, y2));
98 
99  return envelope;
100 }
101 
103 {
104  te::gm::Envelope envelope(std::min(p1.getX(), p2.getX())
105  , std::min(p1.getY(), p2.getY())
106  , std::max(p1.getX(), p2.getX())
107  , std::max(p1.getY(), p2.getY()));
108 
109  return envelope;
110 }
111 
112 std::unique_ptr<te::gm::Geometry> te::gm::GetGeometryUnion(const std::vector<gm::Geometry*> &geomVec)
113 {
114  std::unique_ptr<te::gm::Geometry> geometry;
115 
116  if (geomVec.size() == 1)
117  {
118  te::dt::AbstractData* abs = geomVec[0]->clone();
119  geometry.reset(static_cast<te::gm::Geometry*>(abs));
120  }
121  else if (geomVec.size() > 1)
122  {
123  //First clone the vector
125 
126  std::vector<te::gm::Geometry*> geomVecCopy;
127  geomVecCopy.reserve(geomVec.size());
128 
129 
130  for (std::size_t i = 0; i < geomVec.size(); ++i)
131  {
132  te::gm::Geometry* geometry = static_cast<te::gm::Geometry*>(geomVec[i]->clone());
133 
134  rtree.insert(*geometry->getMBR(), geomVecCopy.size());
135  geomVecCopy.push_back(geometry);
136  }
137 
138  for (std::size_t i = 0; i < geomVecCopy.size(); ++i)
139  {
140  const te::gm::Envelope* env_A = geomVecCopy[i]->getMBR();
141 
142  te::gm::Envelope expandedEnv_A(env_A->m_llx - TOLERANCE, env_A->m_lly - TOLERANCE, env_A->m_urx + TOLERANCE, env_A->m_ury + TOLERANCE);
143 
144  std::vector<std::size_t> vecCandidatesIndexes;
145  rtree.search(expandedEnv_A, vecCandidatesIndexes);
146 
147  if (vecCandidatesIndexes.empty())
148  {
149  continue;
150  }
151 
152  //we copy the geom vector so we can remove the current geometry from it
153  std::vector<te::gm::Geometry*> geomVecCopyFiltered;
154  for (std::size_t j = 0; j < vecCandidatesIndexes.size(); ++j)
155  {
156  std::size_t index = vecCandidatesIndexes[j];
157  if(i == index)
158  {
159  continue;
160  }
161 
162  te::gm::Geometry* geometry = geomVecCopy[index];
163  geomVecCopyFiltered.push_back(geometry);
164  }
165 
166  bool wasChanged = false;
167  std::unique_ptr<te::gm::Geometry> geometryResult(te::gm::PrepareGeometriesToIntersection(geomVecCopy[i], geomVecCopyFiltered, wasChanged));
168 
169  if (wasChanged == true)
170  {
171  //then we replace the resulted geometry into our base geometry vector
172  delete geomVecCopy[i];
173  geomVecCopy[i] = geometryResult.release();
174  }
175  }
176 
177  std::unique_ptr<te::gm::GeometryCollection> gc(new te::gm::GeometryCollection(0, te::gm::GeometryCollectionType, geomVec[0]->getSRID()));
178 
179  for (std::size_t i = 0; i < geomVecCopy.size(); ++i)
180  gc->add(geomVecCopy[i]);
181 
182  bool success = false;
183 
184  try
185  {
186  geometry.reset(te::gm::UnaryUnion(gc.get()));
187  success = true;
188  }
189  catch(...)
190  {
191  }
192 
193  if(success == false)
194  {
195  try
196  {
197  std::unique_ptr<te::gm::Geometry> bufferedGeometry(gc->buffer(0));
198  geometry.reset(te::gm::UnaryUnion(bufferedGeometry.get()));
199  }
200  catch(geos::util::GEOSException& e)
201  {
202  throw Exception(e.what());
203  }
204  }
205  }
206 
207  return geometry;
208 }
209 
211 {
212 // create an outer ring with the same envelope as our envelope
213  LinearRing* r = new LinearRing(5, LineStringType, srid, new Envelope(*e));
214 
215  r->setPoint(0, e->m_llx, e->m_lly);
216  r->setPoint(1, e->m_urx, e->m_lly);
217  r->setPoint(2, e->m_urx, e->m_ury);
218  r->setPoint(3, e->m_llx, e->m_ury);
219  r->setPoint(4, e->m_llx, e->m_lly);
220 
221 // create the polygon
222  Polygon* p = new Polygon(1, PolygonType, srid, new Envelope(*e));
223  p->setRingN(0, r);
224 
225  return p;
226 }
227 
229  const Geometry* g2,
230  SpatialRelation relation)
231 {
232  switch(relation)
233  {
234  case CONTAINS:
235  return g1->contains(g2);
236 
237  case COVEREDBY:
238  return g1->coveredBy(g2);
239 
240  case COVERS:
241  return g1->covers(g2);
242 
243  case CROSSES:
244  return g1->crosses(g2);
245 
246  case DISJOINT:
247  return g1->disjoint(g2);
248 
249  case EQUALS:
250  return g1->equals(g2);
251 
252  case INTERSECTS:
253  return g1->intersects(g2);
254 
255  case OVERLAPS:
256  return g1->overlaps(g2);
257 
258  case TOUCHES:
259  return g1->touches(g2);
260 
261  case WITHIN:
262  return g1->within(g2);
263 
264  default:
265  throw Exception(TE_TR("Invalid spatial relation!"));
266  }
267 }
268 
269 te::gm::Envelope te::gm::AdjustToCut(const Envelope & env, double bWidth, double bHeight)
270 {
271  double auxD;
272  int auxI;
273 
274  int magicX;
275  auxD = env.m_llx/bWidth;
276  auxI = static_cast<int>(env.m_llx/bWidth);
277  if (env.m_llx < 0 && (auxD - auxI) != 0)
278  magicX = static_cast<int>(env.m_llx/bWidth - 1);
279  else
280  magicX = auxI;
281 
282  int magicY;
283  auxD = env.m_lly/bHeight;
284  auxI = static_cast<int>(env.m_lly/bHeight);
285  if (env.m_lly < 0 && (auxD - auxI) != 0)
286  magicY = static_cast<int>(env.m_lly/bHeight - 1);
287  else
288  magicY = auxI;
289 
290  double xi = magicX*bWidth;
291  double yi = magicY*bHeight;
292 
293  int magicX2;
294  auxD = env.m_urx/bWidth;
295  auxI = static_cast<int>(env.m_urx/bWidth);
296  if ((env.m_urx < 0) || (auxD - auxI) == 0)
297  magicX2 = static_cast<int>(env.m_urx/bWidth);
298  else
299  magicX2 = static_cast<int>(env.m_urx/bWidth + 1);
300 
301  int magicY2;
302  auxD = env.m_ury/bHeight;
303  auxI = static_cast<int>(env.m_ury/bHeight);
304  if ((env.m_ury < 0) || (auxD - auxI) == 0)
305  magicY2 = static_cast<int>(env.m_ury/bHeight);
306  else
307  magicY2 = static_cast<int>(env.m_ury/bHeight + 1);
308 
309  double xf = (magicX2)*bWidth;
310  double yf = (magicY2)*bHeight;
311 
312  return te::gm::Envelope(xi,yi,xf,yf);
313 }
314 
315 template<class T1, class T2> bool te::gm::Intersects(const T1& o1, const T2& o2)
316 {
317  return o1->intersects(o2);
318 }
319 
320 template<> bool te::gm::Intersects(const te::gm::Point& point, const te::gm::Envelope& e)
321 {
322  // point to the right of envelope
323  if(point.getX() > e.m_urx)
324  return false;
325 
326  // point to the left of envelope
327  if(e.m_llx > point.getX())
328  return false;
329 
330  // point is above envelope
331  if(point.getY() > e.m_ury)
332  return false;
333 
334  // point is below envelope
335  if(e.m_lly > point.getY())
336  return false;
337 
338  return true;
339 }
340 
341 te::gm::Coord2D* te::gm::locateAlong(const LineString* line, double initial, double final, double target)
342 {
343  double tTof; // Distance of target to fist point
344 
345  std::map<int, double> pointLenghtFromFirst;
346 
347  double fullLineLenght = 0;
348 
349  pointLenghtFromFirst[0] = 0;
350  for(std::size_t i = 1; i < line->getNPoints(); i++)
351  {
352  std::unique_ptr<Point> pA = line->getPointN(i);
353  std::unique_ptr<Point> pB = line->getPointN(i - 1);
354 
355  fullLineLenght += pA->distance(pB.get());
356  pointLenghtFromFirst[static_cast<int>(i)] = fullLineLenght;
357  }
358 
359  double diference = final-initial;
360 
361  tTof = ((target-initial)*fullLineLenght)/diference;
362 
363  int onTheFly = -1;
364 
365  int pointBeforeTarget = -1;
366 
367  for(std::size_t i = 0; i < pointLenghtFromFirst.size(); i++)
368  {
369  if(pointLenghtFromFirst[static_cast<int>(i)] == tTof)
370  {
371  onTheFly = static_cast<int>(i);
372  break;
373  }
374  if(tTof >= pointLenghtFromFirst[static_cast<int>(i)] && tTof < pointLenghtFromFirst[static_cast<int>(i+1)])
375  {
376  pointBeforeTarget = static_cast<int>(i);
377  break;
378  }
379  }
380 
381  te::gm::Coord2D* targetCoord = new te::gm::Coord2D();
382 
383  if(onTheFly >= 0)
384  {
385  targetCoord->x = line->getPointN(static_cast<std::size_t>(onTheFly))->getX();
386  targetCoord->y = line->getPointN(static_cast<std::size_t>(onTheFly))->getY();
387 
388  return targetCoord;
389  }
390 
391  std::unique_ptr<Point> p1 = line->getPointN(static_cast<std::size_t>(pointBeforeTarget));
392  std::unique_ptr<Point> p2 = line->getPointN(static_cast<std::size_t>(pointBeforeTarget + 1));
393 
394  // Partial distance: target to p1
395  double pd = tTof - pointLenghtFromFirst[pointBeforeTarget];
396 
397  // Total distance: p2 to p1
398  double td = pointLenghtFromFirst[pointBeforeTarget+1] - pointLenghtFromFirst[pointBeforeTarget];
399 
400  targetCoord->x = ((pd*(p2->getX()-p1->getX()))/td)+p1->getX();
401 
402  targetCoord->y = ((pd*(p2->getY()-p1->getY()))/td)+p1->getY();
403 
404  return targetCoord;
405 }
406 
407 void te::gm::Multi2Single(const te::gm::Geometry* g, std::vector<te::gm::Geometry*>& geoms)
408 {
409  const te::gm::GeometryCollection* gc = dynamic_cast<const te::gm::GeometryCollection*>(g);
410  if (gc)
411  {
412  for (std::size_t i = 0; i < gc->getNumGeometries(); ++i)
413  {
414  te::gm::Geometry* currentGeom = gc->getGeometryN(i);
415  currentGeom->setSRID(gc->getSRID());
416  Multi2Single(currentGeom, geoms);
417  }
418  }
419  else
420  geoms.push_back(dynamic_cast<te::gm::Geometry*>(g->clone()));
421 }
422 
423 te::gm::Geometry* te::gm::CascadedPolygonUnion(const std::vector<Polygon*>& polygonVector)
424 {
425 #ifdef TERRALIB_GEOS_ENABLED
426 
427  std::vector<geos::geom::Polygon*> geosPolygonVector;
428 
429  try
430  {
431  if(polygonVector.empty())
432  return nullptr;
433 
434  int srid = polygonVector[0]->getSRID();
435 
436  for(auto i : polygonVector)
437  {
438  if(i->getGeomTypeId() == te::gm::PolygonType)
439  {
440  geos::geom::Polygon* geosPolygon = GEOSWriter::write(i);
441  geosPolygonVector.push_back(geosPolygon);
442  }
443  }
444 
445  std::unique_ptr<geos::geom::Geometry> unionGeom(geos::operation::geounion::CascadedPolygonUnion::Union(&geosPolygonVector));
446 
447  te::common::FreeContents(geosPolygonVector);
448 
449  if(unionGeom == nullptr)
450  return nullptr;
451 
452  unionGeom->setSRID(srid);
453 
454  return GEOSReader::read(unionGeom.get());
455  }
456  catch(geos::util::GEOSException& e)
457  {
458  te::common::FreeContents(geosPolygonVector);
459  throw Exception(e.what());
460  }
461 
462 #else
463  throw te::common::Exception(TE_TR("CascadedPolygonUnion routine is supported by GEOS! Please, enable the GEOS support."));
464 #endif
465 }
466 
468 {
469 #ifdef TERRALIB_GEOS_ENABLED
470 
471  try
472  {
473  std::unique_ptr<geos::geom::Geometry> geomGeos(GEOSWriter::write(geom));
474 
475  std::unique_ptr<geos::geom::Geometry> unionGeom = geos::operation::geounion::UnaryUnionOp::Union(*(geomGeos.get()));
476 
477  unionGeom->setSRID(geom->getSRID());
478 
479  return GEOSReader::read(unionGeom.get());
480  }
481  catch(geos::util::GEOSException& e)
482  {
483  throw Exception(e.what());
484  }
485 
486 #else
487  throw te::common::Exception(TE_TR("Union routine is supported by GEOS! Please, enable the GEOS support."));
488 #endif
489 }
490 
492  te::gm::Coord2D& coordA, te::gm::Coord2D& coordB)
493 {
494 #ifdef TERRALIB_GEOS_ENABLED
495  std::unique_ptr<geos::geom::Geometry> thisGeomA(GEOSWriter::write(geomA));
496  std::unique_ptr<geos::geom::Geometry> thisGeomB(GEOSWriter::write(geomB));
497 
498  geos::operation::distance::DistanceOp op(thisGeomA.get(), thisGeomB.get());
499 
500  geos::geom::CoordinateSequence* cs = op.closestPoints();
501 
502  if (cs->getSize() == 2)
503  {
504  coordA = te::gm::Coord2D(cs->getAt(0).x, cs->getAt(0).y);
505  coordB = te::gm::Coord2D(cs->getAt(1).x, cs->getAt(1).y);
506  }
507 
508  delete cs;
509 
510 #else
511  throw te::common::Exception(TE_TR("getCentroid routine is supported by GEOS! Please, enable the GEOS support."));
512 #endif
513 }
514 
516 {
517  std::vector<te::gm::Geometry*> geomVec;
518  std::unique_ptr<te::gm::Point> pRef(new te::gm::Point(coord.x, coord.y, geom->getSRID()));
519 
520  te::gm::Multi2Single(geom, geomVec);
521 
522  for (std::size_t t = 0; t < geomVec.size(); ++t)
523  {
524  te::gm::Geometry* g = geomVec[t];
525 
527  {
528  te::gm::LineString* ls = static_cast<te::gm::LineString*>(g);
529 
530  if (ls->getNPoints() == 2)
531  {
532  std::unique_ptr<te::gm::Point> p0 = ls->getPointN(0);
533  std::unique_ptr<te::gm::Point> p1 = ls->getPointN(1);
534 
536 
537  line->setCoord(0, p0->getX(), p0->getY());
538  line->setCoord(1, p1->getX(), p1->getY());
539 
540  return line;
541  }
542  else
543  {
544  for (std::size_t p = 0; p < ls->getNPoints() - 1; ++p)
545  {
546  std::unique_ptr<te::gm::Point> p0 = ls->getPointN(p);
547  std::unique_ptr<te::gm::Point> p1 = ls->getPointN(p + 1);
548 
549  std::unique_ptr<te::gm::Line> line(new te::gm::Line(te::gm::LineStringType, geom->getSRID()));
550  line->setCoord(0, p0->getX(), p0->getY());
551  line->setCoord(1, p1->getX(), p1->getY());
552 
553  std::unique_ptr<te::gm::Geometry> geomMBR(te::gm::GetGeomFromEnvelope(line->getMBR(), geom->getSRID()));
554 
555  if (geomMBR->intersects(pRef.get()))
556  {
557  return line.release();
558  }
559  }
560  }
561  }
562  }
563 
564  return nullptr;
565 }
566 
568 {
569  if (coordA.x == coordB.x)
570  {
571  return 1.57079632679489661923;
572  }
573 
574  if (coordA.y == coordB.y)
575  {
576  return 0.0;
577  }
578 
579  double dx = (coordA.x - coordB.x);
580  double dy = (coordA.y - coordB.y);
581 
582  double rad = std::atan(dy / dx);
583 
584  //Convert radians to degrees
585  double angle = rad / 0.01745329251994329576;
586 
587  return angle;
588 }
589 
591 {
592  double alfa;
593  double dx, dy;
594  double x, y;
595  double xr, yr;
596 
597  try
598  {
599  if (l->size() < 2)
600  return (false);
601 
602  //transform Degree to Radius
603  alfa = (4.*std::atan(1.)*angle) / 180.;
604 
605  dx = pr.getX();
606  dy = pr.getY();
607 
608  for (std::size_t count = 0; count < l->size(); count++)
609  {
610  std::unique_ptr<te::gm::Point> curPoint = l->getPointN(count);
611 
612  x = curPoint->getX() - dx;
613  y = curPoint->getY() - dy;
614 
615  xr = x * std::cos(alfa) - y * std::sin(alfa);
616  yr = x * std::sin(alfa) + y * std::cos(alfa);
617 
618  lOut->setPoint(count, xr + dx, yr + dy);
619  }
620  }
621  catch (...)
622  {
623  return false;
624  }
625 
626  return true;
627 }
628 
630 {
631  double vL_norm1;
632  double vL_norm2;
633 
634  try
635  {
636  if (P0->getX() == P1->getX() && P0->getY() == P1->getY())
637  return false;
638 
639  te::gm::Coord2D vL1((P1->getX() - P0->getX()), (P1->getY() - P0->getY()));
640  te::gm::Coord2D vL2(-1 * (P1->getX() - P0->getX()), -1 * (P1->getY() - P0->getY()));
641  vL_norm1 = std::sqrt(vL1.getX() * vL1.getX() + vL1.getY() * vL1.getY());
642  vL_norm2 = std::sqrt(vL2.getX() * vL2.getX() + vL2.getY() * vL2.getY());
643 
644  te::gm::Coord2D uL1((vL1.getX() / vL_norm1), (vL1.getY() / vL_norm1));
645  te::gm::Coord2D uL2((vL2.getX() / vL_norm2), (vL2.getY() / vL_norm2));
646 
647  te::gm::Point* pFim1 = new te::gm::Point(P0->getX() + uL1.getX() * d0, P0->getY() + uL1.getY() * d0, P0->getSRID());
648  te::gm::Point* pFim2 = new te::gm::Point(P0->getX() + uL2.getX() * d0, P0->getY() + uL2.getY() * d0, P1->getSRID());
649 
650  if (pFim1->distance(P1) <= pFim2->distance(P1))
651  {
652  P0out.x = P0->getX();
653  P0out.y = P0->getY();
654  P1out.x = pFim1->getX();
655  P1out.y = pFim1->getY();
656  }
657  else
658  {
659  P0out.x = P0->getX();
660  P0out.y = P0->getY();
661  P1out.x = pFim2->getX();
662  P1out.y = pFim2->getY();
663  }
664  }
665  catch (...)
666  {
667  return false;
668  }
669 
670  return true;
671 }
672 
673 void te::gm::Polygonizer(te::gm::Geometry* g, std::vector<te::gm::Polygon*>& pols)
674 {
675 #ifdef TERRALIB_GEOS_ENABLED
676 
678 
679  std::unique_ptr<geos::geom::Geometry> geomGeos(GEOSWriter::write(g));
680  polygonizer.add(geomGeos.get());
681 
682  std::vector <geos::geom::Polygon*>* vecpolGeos = polygonizer.getPolygons();
683 
684  for (std::size_t i = 0; i < vecpolGeos->size(); i++)
685  {
686  vecpolGeos->at(i)->setSRID(g->getSRID());
687  pols.push_back(GEOSReader::read(vecpolGeos->at(i)));
688  }
689 
690 #else
691  throw te::common::Exception(TE_TR("Polygonizer routine is supported by GEOS! Please, enable the GEOS support."));
692 #endif
693 }
694 
696 {
697 #ifdef TERRALIB_GEOS_ENABLED
698 
699  try
700  {
701  std::unique_ptr<geos::geom::Geometry> g(GEOSWriter::write(geom));
702 
703  geos::operation::valid::IsValidOp vop(g.get());
704 
705  geos::operation::valid::TopologyValidationError* err = vop.getValidationError();
706 
707  if (err)
708  {
709  error.m_coordinate = Coord2D(err->getCoordinate().x, err->getCoordinate().y);
710  error.m_message = err->getMessage();
711 
712  return false;
713  }
714 
715  return true;
716  }
717  catch(const geos::util::GEOSException& e)
718  {
719  error.m_message = e.what();
720 
721  return false;
722  }
723 
724 #else
725  throw Exception(TE_TR("isValid routine is supported by GEOS! Please, enable the GEOS support."));
726 #endif
727 }
728 
730 {
731 #ifdef TERRALIB_GEOS_ENABLED
732 
733  std::unique_ptr<geos::geom::Geometry> g(GEOSWriter::write(geom));
734 
735  std::vector<te::gm::Geometry*> pAdd;
737 
738  switch (g->getGeometryTypeId())
739  {
740  case geos::geom::GEOS_POLYGON:
741  {
742  if (g->isValid())
743  {
744  g->normalize(); // validate does not pick up rings in the wrong order - this will fix that
745  return GEOSReader::read(g.get()); // If the polygon is valid just return it
746  }
747 
748  AddPolygon(dynamic_cast<te::gm::Polygon*>(GEOSReader::read(g.get())), pAdd);
749  }
750  break;
751 
752  case geos::geom::GEOS_MULTIPOLYGON:
753  {
754  if (g->isValid()){
755  g->normalize(); // validate does not pick up rings in the wrong order - this will fix that
756  return GEOSReader::read(g.get()); // If the multipolygon is valid just return it
757  }
758 
759  for (std::size_t n = g->getNumGeometries(); n-- > 0;)
760  AddPolygon(dynamic_cast<te::gm::Polygon*>(GEOSReader::read(g->getGeometryN(n))), pAdd);
761 
762  }
763  break;
764 
765  default:
766  return geom;
767  }
768 
769  for (std::size_t i = 0; i < pAdd.size(); i++)
770  polygonizer.add(GEOSWriter::write(pAdd[i]));
771 
773 
774  std::vector <geos::geom::Polygon*>* vecpolGeos = polygonizer.getPolygons();
775 
776  switch (vecpolGeos->size())
777  {
778  case 1:
779  vecpolGeos->at(0)->setSRID(geom->getSRID());
780  return GEOSReader::read(vecpolGeos->at(0)); // single polygon - no need to wrap
781  default:
782  {
783  //filter the invalid polygons
784  std::size_t i = 0;
785  while (i < vecpolGeos->size())
786  {
787  if (!vecpolGeos->at(i)->isValid())
788  {
789  vecpolGeos->erase(vecpolGeos->begin() + static_cast<int>(i));
790  }
791  else
792  {
793  ++i;
794  }
795  }
796 
797  //polygons may still overlap! Need to sym difference them
798  vecpolGeos->at(0)->setSRID(geom->getSRID());
799  te::gm::Geometry* ret = GEOSReader::read(vecpolGeos->at(0));
800 
801  for (std::size_t p = 1; p < vecpolGeos->size(); p++)
802  {
803  vecpolGeos->at(p)->setSRID(geom->getSRID());
804  ret = ret->symDifference(GEOSReader::read(vecpolGeos->at(p)));
805  }
806 
807  te::common::FreeContents(*vecpolGeos);
808 
809  return ret;
810  }
811  }
812 
813 #else
814  throw Exception(TE_TR("validate routine is supported by GEOS! Please, enable the GEOS support."));
815 #endif
816 }
817 
818 void te::gm::AddPolygon(te::gm::Polygon* polygon, std::vector<te::gm::Geometry*>& pAdd)
819 {
820 #ifdef TERRALIB_GEOS_ENABLED
821 
822  AddLineString(dynamic_cast<te::gm::LineString*>(polygon->getExteriorRing()), pAdd);
823 
824  for (std::size_t n = polygon->getNumInteriorRings(); n-- > 0;){
825  AddLineString(dynamic_cast<te::gm::LineString*>(polygon->getInteriorRingN(n)), pAdd);
826  }
827 
828 #else
829  throw Exception(TE_TR("addPolygon routine is supported by GEOS! Please, enable the GEOS support."));
830 #endif
831 }
832 
833 void te::gm::AddLineString(te::gm::LineString* lineString, std::vector<te::gm::Geometry*>& pAdd)
834 {
835 #ifdef TERRALIB_GEOS_ENABLED
836 
837  std::unique_ptr<geos::geom::LineString> ls(GEOSWriter::write(lineString));
838 
839  // unioning the linestring with the point makes any self intersections explicit.
840  geos::geom::Point* point = GEOSGeometryFactory::getGeomFactory()->createPoint(ls->getCoordinateN(0));
841 
842  geos::geom::Geometry* toAdd = ls->Union(point);
843 
844  pAdd.push_back(GEOSReader::read(toAdd));
845 
846 #else
847  throw Exception(TE_TR("addLineString routine is supported by GEOS! Please, enable the GEOS support."));
848 #endif
849 }
850 
852  const te::gm::Point& last,
853  te::gm::Point& pin, te::gm::Point& pinter)
854 {
855 #ifdef TERRALIB_GEOS_ENABLED
856  double d12, xmin, ymin;
857 
858  double xi = first.getX();
859  double xf = last.getX();
860  double yi = first.getY();
861  double yf = last.getY();
862  double x = pin.getX();
863  double y = pin.getY();
864 
865  double dx = xf - xi;
866  double dy = yf - yi;
867  double a2 = (y - yi) * dx - (x - xi)*dy;
868 
869  if (dx == 0. && dy == 0.)
870  {
871  d12 = sqrt(((x - xi) * (x - xi)) + ((y - yi) * (y - yi)));
872  d12 *= d12;
873  }
874  else
875  d12 = a2 * a2 / (dx * dx + dy * dy);
876 
877  if (dx == 0.)
878  {
879  xmin = xi;
880  ymin = y;
881  }
882  else if (dy == 0.)
883  {
884  xmin = x;
885  ymin = yi;
886  }
887  else
888  {
889  double alfa = dy / dx;
890  xmin = (x + alfa * (y - yi) + alfa * alfa * xi) / (1. + alfa * alfa);
891  ymin = (x - xmin) / alfa + y;
892  }
893 
894  pinter = te::gm::Point(xmin, ymin, pin.getSRID());
895 
896  return (sqrt(d12));
897 
898 #else
899  throw Exception(TE_TR("PerpendicularDistance routine is supported by GEOS! Please, enable the GEOS support."));
900 #endif
901 }
902 
904 {
905  std::vector<te::gm::Geometry*> vecGeomB;
906  vecGeomB.push_back(geomB);
907 
908  return te::gm::PrepareGeometriesToIntersection(geom_A, vecGeomB, wasChanged);
909 }
910 
911 te::gm::Geometry* te::gm::PrepareGeometriesToIntersection(const te::gm::Geometry* geom_A, const std::vector<te::gm::Geometry*>& vecGeomB, bool& wasChanged)
912 {
913  wasChanged = false;
914 
915 #ifdef TERRALIB_GEOS_ENABLED
916 
917  // Check if MBRs of both LineStrings have intersection.
918  const te::gm::Envelope* env_A = geom_A->getMBR();
919  te::gm::Envelope expandedEnv_A(env_A->m_llx - TOLERANCE,
920  env_A->m_lly - TOLERANCE,
921  env_A->m_urx + TOLERANCE,
922  env_A->m_ury + TOLERANCE);
923 
924  te::gm::Geometry* geomResult = nullptr;
925 
926  GeomType geomTypeA = geom_A->getGeomTypeId();
927 
928  std::vector<te::gm::MultiLineString*> multiLineStringVectorA = GetAsMultiLineStringVector(*geom_A);
929 
930 
931  // Creating the RTree with the ls_B segment boxes intersects ls_A segment box
933  std::vector<te::gm::LineString> rtreeSegments;
934 
935  //we decompose all geometries in vecGeomB into line segments, and then we index it
936  for (std::size_t i = 0; i < vecGeomB.size(); ++i)
937  {
938  te::gm::Geometry* geometryB = vecGeomB[i];
939 
940  const te::gm::Envelope* envGeometryB = geometryB->getMBR();
941  te::gm::Envelope expandedGeometryEnv_B(envGeometryB->m_llx - TOLERANCE,
942  envGeometryB->m_lly - TOLERANCE,
943  envGeometryB->m_urx + TOLERANCE,
944  envGeometryB->m_ury + TOLERANCE);
945 
946  if (expandedEnv_A.intersects(expandedGeometryEnv_B) == false)
947  {
948  continue;
949  }
950 
951  std::vector<te::gm::MultiLineString*> multiLineStringVectorB = GetAsMultiLineStringVector(*vecGeomB[i]);
952  for (std::size_t j = 0; j < multiLineStringVectorB.size(); ++j)
953  {
954  te::gm::MultiLineString* multiLineB = multiLineStringVectorB[j];
955  const std::vector<te::gm::Geometry*>& vecGeometries = multiLineB->getGeometries();
956 
957  for (std::size_t k = 0; k < vecGeometries.size(); ++k)
958  {
959  te::gm::LineString* lineB = static_cast<te::gm::LineString*>(vecGeometries[k]);
960 
961  const te::gm::Envelope* envLineB = lineB->getMBR();
962  te::gm::Envelope expandedLineEnv_B(envLineB->m_llx - TOLERANCE,
963  envLineB->m_lly - TOLERANCE,
964  envLineB->m_urx + TOLERANCE,
965  envLineB->m_ury + TOLERANCE);
966 
967  if (expandedEnv_A.intersects(expandedLineEnv_B) == false)
968  {
969  continue;
970  }
971 
972  //finally we get all the segments
973  std::size_t nSegmentsB = lineB->size() - 1;
974  for (std::size_t s = 0; s < nSegmentsB; ++s)
975  {
976 
977  te::gm::Envelope currentSegmentEnvelope = CreateEnvelope(lineB->getX(s), lineB->getY(s), lineB->getX(s + 1), lineB->getY(s + 1));
978 
979  te::gm::Envelope expandedSegmentEnv_B(currentSegmentEnvelope.getLowerLeftX() - TOLERANCE,
980  currentSegmentEnvelope.getLowerLeftY() - TOLERANCE,
981  currentSegmentEnvelope.getUpperRightX() + TOLERANCE,
982  currentSegmentEnvelope.getUpperRightY() + TOLERANCE);
983 
984  if (expandedEnv_A.intersects(expandedSegmentEnv_B) == true)
985  {
986  te::gm::LineString segment_B(2, te::gm::LineStringType, geom_A->getSRID());
987 
988  segment_B.setPoint(0, lineB->getX(s), lineB->getY(s));
989  segment_B.setPoint(1, lineB->getX(s + 1), lineB->getY(s + 1));
990 
991  rtree.insert(currentSegmentEnvelope, rtreeSegments.size());
992  rtreeSegments.push_back(segment_B);
993  }
994  }
995  }
996  }
997  te::common::FreeContents(multiLineStringVectorB);
998  }
999 
1000  for (std::size_t i = 0; i < multiLineStringVectorA.size(); ++i)
1001  {
1002  bool currentWasChanged = false;
1003  std::unique_ptr<te::gm::MultiLineString> currentResult(PrepareGeometriesToIntersection(*multiLineStringVectorA[i], rtree, rtreeSegments, currentWasChanged));
1004 
1005  if (currentWasChanged == true)
1006  {
1007  wasChanged = true;
1008  delete multiLineStringVectorA[i];
1009  multiLineStringVectorA[i] = currentResult.release();
1010  }
1011  }
1012 
1013  if (wasChanged)
1014  {
1015  std::unique_ptr<te::gm::Geometry> preparedGeometryResult(MultiLineToDefinedType(multiLineStringVectorA, geomTypeA));
1016 
1018  bool result = CheckValidity(preparedGeometryResult.get(), error);
1019  if (result == false)
1020  {
1021  preparedGeometryResult.reset(preparedGeometryResult->buffer(0));
1022  }
1023 
1024  geomResult = preparedGeometryResult.release();
1025  }
1026  else
1027  {
1028  geomResult = dynamic_cast<te::gm::Geometry*>(geom_A->clone());
1029  }
1030 
1031 
1032  te::common::FreeContents(multiLineStringVectorA);
1033 
1034  return geomResult;
1035 
1036 #else
1037  throw Exception(TE_TR("PrepareGeometriesToIntersection routine is supported by GEOS! Please, enable the GEOS support."));
1038 #endif
1039 }
1040 
1043  std::vector<te::gm::LineString>& vecRtreeSegments,
1044  bool& wasChanged)
1045 {
1046  wasChanged = false;
1047 
1048 #ifdef TERRALIB_GEOS_ENABLED
1049 
1050  te::gm::MultiLineString* multiLineStringResult = new te::gm::MultiLineString(0, mline_A.getGeomTypeId(), mline_A.getSRID());
1051 
1052  const std::vector<te::gm::Geometry*>& geometryVectorA = mline_A.getGeometries();
1053 
1054  for (std::size_t i = 0; i < geometryVectorA.size(); ++i)
1055  {
1056  bool currentWasChanged = false;
1057 
1058  te::gm::Geometry* singleResult = PrepareGeometriesToIntersection(*dynamic_cast<te::gm::LineString*>(geometryVectorA[i]), rtree, vecRtreeSegments, currentWasChanged);
1059  multiLineStringResult->add(singleResult);
1060 
1061  if (currentWasChanged == true)
1062  {
1063  wasChanged = true;
1064  }
1065  }
1066 
1067  return multiLineStringResult;
1068 
1069 #else
1070  throw Exception(TE_TR("PrepareGeometriesToIntersection routine is supported by GEOS! Please, enable the GEOS support."));
1071 #endif
1072 }
1073 
1076  std::vector<te::gm::LineString>& vecRtreeSegments,
1077  bool& wasChanged)
1078 {
1079  wasChanged = false;
1080 
1081 #ifdef TERRALIB_GEOS_ENABLED
1082 
1083  // First try to snap the points from ls_A in the points of ls_B
1084  bool wasSnapped = false;
1085 
1086  //if there are none candidate segments, we avoid some processing
1087  std::vector<std::size_t> report;
1088  rtree.search(*ls_A.getMBR(), report);
1089 
1090  if (report.empty())
1091  {
1092  return static_cast<te::gm::LineString*>(ls_A.clone());
1093  }
1094 
1095  std::size_t n_pointsA = ls_A.getNPoints();
1096  std::size_t n_segments_A = n_pointsA - 1;
1097 
1098  std::vector<te::gm::Point> vecOutputPoints;
1099  vecOutputPoints.reserve(n_pointsA);
1100 
1101  std::set<std::size_t> setIndexesIgnored;
1102  for (std::size_t i = 0; i < n_segments_A; ++i)
1103  {
1104  te::gm::Point segmentP1(ls_A.getX(i), ls_A.getY(i));
1105  te::gm::Point segmentP2(ls_A.getX(i+1), ls_A.getY(i+1));
1106 
1107  te::gm::Envelope segmentEnvelope = CreateEnvelope(segmentP1.getX(), segmentP1.getY(), segmentP2.getX(), segmentP2.getY());
1108 
1109  //now we create an ignore list based in all candidate segments that are EQUAL to the segments in the prepared line
1110  std::vector<std::size_t> segmentReport;
1111  rtree.search(segmentEnvelope, segmentReport);
1112 
1113  for (std::size_t i = 0; i < segmentReport.size(); ++i)
1114  {
1115  std::size_t index = segmentReport[i];
1116  //if it is already ignored, we go to the next one
1117  if (setIndexesIgnored.find(index) != setIndexesIgnored.end())
1118  {
1119  continue;
1120  }
1121 
1122  const te::gm::LineString& candidate = vecRtreeSegments[index];
1123 
1124  //if the boxes arent igual, the segment must not be ignored
1125  if(segmentEnvelope.equals(*candidate.getMBR()) == false)
1126  {
1127  continue;
1128  }
1129 
1130  //if the boxes are equal, we must check the coordinates
1131  //if one coordinate is equal, necessarely the other one is tool
1132  //so we can check only the first coordinate
1133  te::gm::Point candidateP1(candidate.getX(0), candidate.getY(0));
1134  te::gm::Point candidateP2(candidate.getX(1), candidate.getY(1));
1135 
1136  //if the segment fist point is not equal any point of the candidate line, the segment must not be ignored
1137  if (IsEqual(segmentP1, candidateP1) == false && IsEqual(segmentP1, candidateP2) == false)
1138  {
1139  continue;
1140  }
1141 
1142  //if we got here, both segments are equal and so they can be added to the ignore list
1143  setIndexesIgnored.insert(index);
1144  }
1145  }
1146 
1147  std::unique_ptr<te::gm::LineString> lr_Result(dynamic_cast<te::gm::LineString*>(ls_A.clone()));
1148  lr_Result.reset(SnapLineToPoints(rtree, vecRtreeSegments, setIndexesIgnored, *lr_Result.get(), wasSnapped));
1149 
1150  lr_Result.reset(AddIntersectionPoints(rtree, vecRtreeSegments, setIndexesIgnored, *lr_Result.get(), true));
1151  lr_Result.reset(AddIntersectionPoints(rtree, vecRtreeSegments, setIndexesIgnored, *lr_Result.get()));
1152 
1153  if (wasSnapped == true || lr_Result->size() != ls_A.size())
1154  {
1155  wasChanged = true;
1156  }
1157 
1158  return lr_Result.release();
1159 
1160 #else
1161  throw Exception(TE_TR("PrepareGeometriesToIntersection routine is supported by GEOS! Please, enable the GEOS support."));
1162 #endif
1163 }
1164 
1166  const std::vector<te::gm::LineString>& referenceSegments,
1167  const std::set<std::size_t>& setIndexesIgnored,
1168  const LineString& linearRingToSnap, bool& wasChanged)
1169 {
1170  wasChanged = false;
1171 
1172 #ifdef TERRALIB_GEOS_ENABLED
1173 
1174  te::gm::LineString* lr_Result = dynamic_cast<te::gm::LineString*>(linearRingToSnap.clone());
1175 
1176  std::size_t npoints_A = linearRingToSnap.getNPoints();
1177 
1178  for (std::size_t i = 0; i < npoints_A; ++i)
1179  {
1180  std::unique_ptr<Point> currentPoint = lr_Result->getPointN(i);
1181 
1182  te::gm::Envelope expandedEnv;
1183  expandedEnv.init(
1184  currentPoint->getX() - TOLERANCE, currentPoint->getY() - TOLERANCE,
1185  currentPoint->getX() + TOLERANCE, currentPoint->getY() + TOLERANCE);
1186 
1187  std::vector<size_t> report;
1188  rtree.search(expandedEnv, report);
1189 
1190  if (report.empty())
1191  continue;
1192 
1193  // Extracts all the points.
1194  std::vector<te::gm::Point> candidates;
1195  for (std::size_t ls = 0; ls < report.size(); ++ls)
1196  {
1197  std::size_t index = report[ls];
1198 
1199  //we the candidate is in the ignore list, we go to the next one
1200  if (setIndexesIgnored.find(index) != setIndexesIgnored.end())
1201  {
1202  continue;
1203  }
1204 
1205  std::unique_ptr<Point> pStart = referenceSegments[index].getPointN(0);
1206  candidates.push_back(*pStart.get());
1207 
1208  std::unique_ptr<Point> pEnd = referenceSegments[index].getPointN(1);
1209  candidates.push_back(*pEnd.get());
1210  }
1211 
1212  if (candidates.empty() == true)
1213  {
1214  continue;
1215  }
1216 
1217  //Checks if there is on point that is within the tolerance.
1218  //If there is more than one, is found the closest.
1219  DistanceOrderFunctor func(*currentPoint);
1220  std::sort(candidates.begin(), candidates.end(), func);
1221 
1222  double distance = currentPoint->distance(&candidates[0]);
1223  if(distance != 0 && distance <= TOLERANCE)
1224  {
1225  wasChanged = true;
1226 
1227  lr_Result->setPointN(i, candidates[0]);
1228 
1229  if (i == 0)
1230  {
1231  lr_Result->setPointN(npoints_A - 1, candidates[0]);
1232  }
1233  }
1234  }
1235 
1236  return lr_Result;
1237 
1238 #else
1239  throw Exception(TE_TR("SnapLineToPoints routine is supported by GEOS! Please, enable the GEOS support."));
1240 #endif
1241 }
1242 
1244  const std::vector<te::gm::LineString>& candidateSegments,
1245  const std::set<std::size_t>& setIndexesIgnored,
1246  const LineString& lr_Reference,
1247  const bool& usePerpendicularDistance)
1248 {
1249 #ifdef TERRALIB_GEOS_ENABLED
1250 
1251  bool addedIntersectionPoints = false;
1252 
1253  std::size_t n_pointsA = lr_Reference.getNPoints();
1254  std::size_t n_segments_A = n_pointsA - 1;
1255 
1256  std::vector<te::gm::Point> vecOutputPoints;
1257  vecOutputPoints.reserve(n_pointsA);
1258 
1259  for (std::size_t i = 0; i < n_segments_A; ++i)
1260  {
1261  // Search for candidates.
1262  te::gm::Envelope currentSegmentEnvelope = CreateEnvelope(lr_Reference.getX(i), lr_Reference.getY(i), lr_Reference.getX(i + 1), lr_Reference.getY(i + 1));
1263 
1264  std::unique_ptr<Point> pCurrentStartPoint = lr_Reference.getPointN(i);
1265 
1266  vecOutputPoints.push_back(*pCurrentStartPoint.get());
1267 
1268  te::gm::Envelope expandedEnv(currentSegmentEnvelope.getLowerLeftX() - TOLERANCE,
1269  currentSegmentEnvelope.getLowerLeftY() - TOLERANCE,
1270  currentSegmentEnvelope.getUpperRightX() + TOLERANCE,
1271  currentSegmentEnvelope.getUpperRightY() + TOLERANCE);
1272 
1273  std::vector<size_t> report;
1274  rtree.search(expandedEnv, report);
1275 
1276  if (report.empty())
1277  continue;
1278 
1279  //creates the curent segment
1280  te::gm::LineString segment_A(2, te::gm::LineStringType, lr_Reference.getSRID());
1281  segment_A.setPoint(0, lr_Reference.getX(i), lr_Reference.getY(i));
1282  segment_A.setPoint(1, lr_Reference.getX(i + 1), lr_Reference.getY(i + 1));
1283 
1284  std::vector<te::gm::LineString> candidates;
1285  candidates.reserve(report.size());
1286  for(std::size_t ls = 0; ls < report.size(); ++ls)
1287  {
1288  std::size_t index = report[ls];
1289 
1290  //we the candidate is in the ignore list, we go to the next one
1291  if (setIndexesIgnored.find(index) != setIndexesIgnored.end())
1292  {
1293  continue;
1294  }
1295 
1296  const te::gm::LineString& segmentCandidate = candidateSegments[index];
1297  candidates.push_back(segmentCandidate);
1298  }
1299 
1300  if (candidates.empty() == true)
1301  {
1302  continue;
1303  }
1304 
1305  // Executes the intersection for each candidate point, and get the coordinates.
1306  std::vector<te::gm::Point> vecIntersectionPoints;
1307 
1308  if(usePerpendicularDistance)
1309  vecIntersectionPoints = GetIntersectionPointsByPerpendicularDistance(segment_A, candidates);
1310  else
1311  vecIntersectionPoints = GetIntersectionPointsByOperators(segment_A, candidates);
1312 
1313  DistanceOrderFunctor func(*pCurrentStartPoint.get());
1314  std::sort(vecIntersectionPoints.begin(), vecIntersectionPoints.end(), func);
1315 
1316  for (std::size_t j = 0; j < vecIntersectionPoints.size(); ++j)
1317  {
1318  const te::gm::Point& currentIntersectionPoint = vecIntersectionPoints[j];
1319  const te::gm::Point& lastPoint = vecOutputPoints[vecOutputPoints.size() - 1];
1320 
1321  if (IsEqual(currentIntersectionPoint, lastPoint, TOLERANCE) == true)
1322  {
1323  continue;
1324  }
1325  if (IsEqual(currentIntersectionPoint, *pCurrentStartPoint.get(), TOLERANCE) == true)
1326  {
1327  continue;
1328  }
1329  std::unique_ptr<Point> pCurrentEndPoint = lr_Reference.getPointN(i + 1);
1330  if (IsEqual(currentIntersectionPoint, *pCurrentEndPoint.get(), TOLERANCE) == true)
1331  {
1332  continue;
1333  }
1334 
1335  addedIntersectionPoints = true;
1336  vecOutputPoints.push_back(vecIntersectionPoints[j]);
1337  }
1338  }
1339 
1340  //we onlye create anew line if we detected at least one distinct intersection point
1341  if (addedIntersectionPoints == false)
1342  {
1343  return dynamic_cast<te::gm::LineString*>(lr_Reference.clone());
1344  }
1345 
1346  // Set the end point in the output vector.
1347  std::unique_ptr<Point> pStart = lr_Reference.getStartPoint();
1348  vecOutputPoints.push_back(*pStart.get());
1349 
1350  te::gm::LineString* result = new te::gm::LineString(vecOutputPoints.size(), te::gm::LineStringType, lr_Reference.getSRID());
1351 
1352  for (std::size_t i = 0; i < vecOutputPoints.size(); ++i)
1353  result->setPointN(i, vecOutputPoints[i]);
1354 
1355  return result;
1356 
1357 #else
1358  throw Exception(TE_TR("GetIntersectionPoints routine is supported by GEOS! Please, enable the GEOS support."));
1359 #endif
1360 }
1361 
1362 std::vector<te::gm::Point> te::gm::GetIntersectionPointsByOperators(
1363  const te::gm::LineString& lsReference,
1364  const std::vector<te::gm::LineString>& candidates)
1365 {
1366 #ifdef TERRALIB_GEOS_ENABLED
1367 
1368  std::vector<te::gm::Point> intersectionPoints;
1369  std::unique_ptr<te::gm::Point> startPoint;
1370  std::unique_ptr<te::gm::Point> endPoint;
1371 
1372  geos::geom::Coordinate referenceP1(lsReference.getX(0), lsReference.getY(0));
1373  geos::geom::Coordinate referenceP2(lsReference.getX(1), lsReference.getY(1));
1374 
1375  for (std::size_t i = 0; i < candidates.size(); ++i)
1376  {
1377  const te::gm::LineString& lineCandidate = candidates[i];
1378 
1379  geos::geom::Coordinate candidateP1(lineCandidate.getX(0), lineCandidate.getY(0));
1380  geos::geom::Coordinate candidateP2(lineCandidate.getX(1), lineCandidate.getY(1));
1381 
1382  geos::algorithm::LineIntersector intersector;
1383  intersector.computeIntersection(referenceP1, referenceP2, candidateP1, candidateP2);
1384  if (intersector.hasIntersection() == false)
1385  {
1386  continue;
1387  }
1388 
1389  std::vector<te::gm::Point> candidatesIntersectionPoints;
1390  int numberOfIntersections = intersector.getIntersectionNum();
1391  for (int j = 0; j < numberOfIntersections; ++j)
1392  {
1393  const geos::geom::Coordinate& interCoord = intersector.getIntersection(j);
1394 
1395  candidatesIntersectionPoints.push_back(te::gm::Point(interCoord.x, interCoord.y, lsReference.getSRID()));
1396  }
1397 
1398  for (std::size_t j = 0; j < candidatesIntersectionPoints.size(); ++j)
1399  {
1400  if (startPoint.get() == nullptr || endPoint.get() == nullptr)
1401  {
1402  startPoint = lsReference.getStartPoint();
1403  endPoint = lsReference.getEndPoint();
1404  }
1405 
1406  const te::gm::Point& candidateIntersectionPoint = candidatesIntersectionPoints[j];
1407 
1408  //if the candidate intersection point is "near" to the start or end point of the current segment, we drop it
1409  if (IsEqual(candidateIntersectionPoint, *startPoint.get(), TOLERANCE) == true || IsEqual(candidateIntersectionPoint, *endPoint.get(), TOLERANCE) == true)
1410  {
1411  continue;
1412  }
1413 
1414  std::unique_ptr<te::gm::Point>candidateStartPoint = candidates[i].getStartPoint();
1415  std::unique_ptr<te::gm::Point>candidateEndPoint = candidates[i].getEndPoint();
1416 
1417  // If the calculated intersection point is "near" the start or end point of the current segment, just snap it.
1418  double distanceStartPointB = candidateIntersectionPoint.distance(candidateStartPoint.get());
1419  double distanceEndPointB = candidateIntersectionPoint.distance(candidateEndPoint.get());
1420 
1421  if (distanceStartPointB <= TOLERANCE)
1422  {
1423  intersectionPoints.push_back(*candidateStartPoint.get());
1424  }
1425  else if (distanceEndPointB <= TOLERANCE)
1426  {
1427  intersectionPoints.push_back(*candidateEndPoint.get());
1428  }
1429  else
1430  {
1431  intersectionPoints.push_back(candidateIntersectionPoint);
1432  }
1433  }
1434  }
1435 
1436  return intersectionPoints;
1437 
1438 #else
1439  throw Exception(TE_TR("GetIntersectionPointsByOperators routine is supported by GEOS! Please, enable the GEOS support."));
1440 #endif
1441 }
1442 
1444  const te::gm::LineString& lsReference,
1445  const std::vector<te::gm::LineString>& candidates)
1446 {
1447 #ifdef TERRALIB_GEOS_ENABLED
1448 
1449  std::vector<te::gm::Point> intersectionPoints;
1450 
1451  std::unique_ptr<te::gm::Point> startPoint = lsReference.getStartPoint();
1452  std::unique_ptr<te::gm::Point> endPoint = lsReference.getEndPoint();
1453 
1454  for (std::size_t i = 0; i < candidates.size(); ++i)
1455  {
1456  std::unique_ptr<te::gm::Point>candidateStartPoint = candidates[i].getStartPoint();
1457  std::unique_ptr<te::gm::Point>candidateEndPoint = candidates[i].getEndPoint();
1458 
1459  std::unique_ptr<geos::geom::LineSegment> lineSegment(
1460  new geos::geom::LineSegment(startPoint->getX(), startPoint->getY(),
1461  endPoint->getX(), endPoint->getY()));
1462 
1463  //we try to find the an intersection point touching our current segment
1464  //we first compare our segment to the candidate start point
1465  te::gm::Point pInterStart;
1466  double startDistance = te::gm::PerpendicularDistance(*startPoint.get(), *endPoint.get(), *candidateStartPoint.get(), pInterStart);
1467 
1468  if (IsEqual(*startPoint.get(), pInterStart, TOLERANCE) == false && IsEqual(*endPoint.get(), pInterStart, TOLERANCE) == false)
1469  {
1470  std::unique_ptr<geos::geom::Coordinate> coordStart(new geos::geom::Coordinate(pInterStart.getX(), pInterStart.getY()));
1471 
1472  double projFactorStart = lineSegment->projectionFactor(*coordStart.get());
1473  if (startDistance <= TOLERANCE && (projFactorStart >= 0 && projFactorStart <= 1))
1474  {
1475  intersectionPoints.push_back(*candidateStartPoint.get());
1476  }
1477  }
1478 
1479 
1480  //then we compare our segment to the candidate end point
1481  te::gm::Point pInterEnd;
1482  double endDistance = te::gm::PerpendicularDistance(*startPoint.get(), *endPoint.get(), *candidateEndPoint.get(), pInterEnd);
1483 
1484  if (IsEqual(*startPoint.get(), pInterEnd, TOLERANCE) == false && IsEqual(*endPoint.get(), pInterEnd, TOLERANCE) == false)
1485  {
1486  std::unique_ptr<geos::geom::Coordinate> coordEnd(new geos::geom::Coordinate(pInterEnd.getX(), pInterEnd.getY()));
1487 
1488  double projFactorEnd = lineSegment->projectionFactor(*coordEnd.get());
1489  if (endDistance <= TOLERANCE && (projFactorEnd >= 0 && projFactorEnd <= 1))
1490  {
1491  intersectionPoints.push_back(*candidateEndPoint.get());
1492  }
1493  }
1494  }
1495 
1496  return intersectionPoints;
1497 
1498 #else
1499  throw Exception(TE_TR("GetIntersectionPointsByPerpendicularDistance routine is supported by GEOS! Please, enable the GEOS support."));
1500 #endif
1501 }
1502 
1503 std::vector<te::gm::MultiLineString*> te::gm::GetAsMultiLineStringVector(const te::gm::Geometry& geometry)
1504 {
1505  std::vector<te::gm::MultiLineString*> multiLineStringVector;
1506 
1507  switch(geometry.getGeomTypeId())
1508  {
1513  {
1514  te::gm::MultiLineString* multiLineString = new te::gm::MultiLineString(0, GetMultiLineStringType(geometry), geometry.getSRID());
1515 
1516  te::gm::LineString* lineString = dynamic_cast<te::gm::LineString*>(geometry.clone());
1517 
1518  multiLineString->add(lineString);
1519 
1520  multiLineStringVector.push_back(multiLineString);
1521  }
1522  break;
1523 
1528  {
1529  te::gm::MultiLineString* multiLineString = new te::gm::MultiLineString(0, GetMultiLineStringType(geometry), geometry.getSRID());
1530 
1531  std::vector<te::gm::Geometry*> geometryVector;
1532  te::gm::Multi2Single(&geometry, geometryVector);
1533 
1534  for(auto g : geometryVector)
1535  {
1536  te::gm::LineString* lineString = dynamic_cast<te::gm::LineString*>(g->clone());
1537 
1538  multiLineString->add(lineString);
1539 
1540  multiLineStringVector.push_back(multiLineString);
1541  }
1542 
1543  te::common::FreeContents(geometryVector);
1544  }
1545  break;
1546 
1547  case te::gm::PolygonType:
1548  case te::gm::PolygonMType:
1549  case te::gm::PolygonZType:
1550  case te::gm::PolygonZMType:
1551  {
1552  te::gm::MultiLineString* multiLineString = new te::gm::MultiLineString(0, GetMultiLineStringType(geometry), geometry.getSRID());
1553 
1554  const te::gm::Polygon* polygon = dynamic_cast<const te::gm::Polygon*>(&geometry);
1555 
1556  const std::vector<te::gm::Curve*>& curveVector = polygon->getRings();
1557 
1558  for (auto curve : curveVector)
1559  {
1560  te::gm::LineString* lineString = dynamic_cast<te::gm::LineString*>(curve->clone());
1561 
1562  multiLineString->add(lineString);
1563  }
1564 
1565  multiLineStringVector.push_back(multiLineString);
1566  }
1567  break;
1568 
1573  {
1574  std::vector<te::gm::Geometry*> geometryVector;
1575  Multi2Single(&geometry, geometryVector);
1576 
1577  for(auto g : geometryVector)
1578  {
1579  std::vector<te::gm::MultiLineString*> multiLineStringVectorTemp = GetAsMultiLineStringVector(*g);
1580 
1581  multiLineStringVector.insert(multiLineStringVector.end(), multiLineStringVectorTemp.begin(), multiLineStringVectorTemp.end());
1582  }
1583 
1584  te::common::FreeContents(geometryVector);
1585  }
1586  break;
1587 
1588  default:
1589  throw Exception("This type of geometry is not composed by LineString.");
1590  }
1591 
1592  return multiLineStringVector;
1593 }
1594 
1595 te::gm::Geometry* te::gm::MultiLineToDefinedType(const std::vector<te::gm::MultiLineString*>& multiLineStringVector, te::gm::GeomType geometryType)
1596 {
1597  te::gm::Geometry* geometry = nullptr;
1598 
1599  if(multiLineStringVector.empty())
1600  return geometry;
1601 
1602  int srid = multiLineStringVector[0]->getSRID();
1603 
1604  switch (geometryType)
1605  {
1610  {
1611  te::gm::MultiLineString* mls = multiLineStringVector[0];
1612 
1613  if(mls->isEmpty())
1614  return geometry;
1615 
1616  geometry = dynamic_cast<te::gm::Geometry*>(mls->getGeometryN(0)->clone());
1617  }
1618  break;
1619 
1620  case te::gm::PolygonType:
1621  case te::gm::PolygonZType:
1622  case te::gm::PolygonMType:
1623  case te::gm::PolygonZMType:
1624  {
1625  te::gm::MultiLineString* mls = multiLineStringVector[0];
1626 
1627  if(mls->isEmpty())
1628  return geometry;
1629 
1630  te::gm::Polygon* polygon = new te::gm::Polygon(0, geometryType, srid);
1631 
1632  for(auto g : mls->getGeometries())
1633  polygon->add(dynamic_cast<te::gm::Curve*>(g->clone()));
1634 
1635  geometry = polygon;
1636  }
1637  break;
1638 
1643  {
1644  te::gm::MultiLineString* outMls = new te::gm::MultiLineString(0, geometryType, srid);
1645 
1646  for(auto inMls : multiLineStringVector)
1647  {
1648  if(inMls->isEmpty())
1649  continue;
1650 
1651  for(auto g : inMls->getGeometries())
1652  outMls->add(dynamic_cast<te::gm::Geometry*>(g->clone()));
1653  }
1654 
1655  geometry = outMls;
1656  }
1657  break;
1658 
1663  {
1664  te::gm::MultiPolygon* outMPolygon = new te::gm::MultiPolygon(0, geometryType, srid);
1665 
1666  for(auto inMls : multiLineStringVector)
1667  {
1668  if(inMls->getGeometries().empty())
1669  continue;
1670 
1671  std::size_t numRings = inMls->getGeometries().size();
1672 
1673  te::gm::Polygon* polygon = new te::gm::Polygon(numRings, GetSimpleType(geometryType), srid);
1674 
1675  for (std::size_t j = 0; j < numRings; ++j)
1676  {
1677  polygon->setRingN(j, dynamic_cast<te::gm::Curve*>(inMls->getGeometryN(j)->clone()));
1678  }
1679 
1680  outMPolygon->add(polygon);
1681  }
1682 
1683  geometry = outMPolygon;
1684  }
1685  break;
1686 
1687  default:
1688  throw Exception("This type of geometry is not composed by LineString.");
1689  }
1690 
1691  return geometry;
1692 }
1693 
1695 {
1696  switch (geometry.getGeomTypeId())
1697  {
1699  case te::gm::PolygonZType:
1703 
1705  case te::gm::PolygonMType:
1709 
1711  case te::gm::PolygonZMType:
1715 
1716  default:
1718  }
1719 }
1720 
1722 {
1723  switch(geomType)
1724  {
1741  return true;
1742  default:
1743  return false;
1744  }
1745 }
1746 
1748 {
1749  switch(geomType)
1750  {
1752  return te::gm::LineStringType;
1754  return te::gm::LineStringMType;
1756  return te::gm::LineStringZType;
1758  return te::gm::LineStringZMType;
1760  return te::gm::PointType;
1762  return te::gm::PointMType;
1764  return te::gm::PointZType;
1766  return te::gm::PointZMType;
1768  return te::gm::PolygonType;
1770  return te::gm::PolygonMType;
1772  return te::gm::PolygonZType;
1774  return te::gm::PolygonZMType;
1776  return te::gm::GeometryType;
1778  return te::gm::GeometryMType;
1780  return te::gm::GeometryZType;
1782  return te::gm::GeometryZMType;
1783  default:
1785  }
1786 }
1787 
1789 {
1790  switch (geomType)
1791  {
1800  case te::gm::PointType:
1801  return te::gm::MultiPointType;
1802  case te::gm::PointMType:
1803  return te::gm::MultiPointMType;
1804  case te::gm::PointZType:
1805  return te::gm::MultiPointZType;
1806  case te::gm::PointZMType:
1807  return te::gm::MultiPointZMType;
1808  case te::gm::PolygonType:
1809  return te::gm::MultiPolygonType;
1810  case te::gm::PolygonMType:
1812  case te::gm::PolygonZType:
1814  case te::gm::PolygonZMType:
1816  case te::gm::GeometryType:
1818  case te::gm::GeometryMType:
1820  case te::gm::GeometryZType:
1824  default:
1826  }
1827 }
1828 
1829 te::gm::LineString te::gm::CreateLine(const te::gm::Coord2D& startCoord, const te::gm::Coord2D& endCoord, const int& srid, const int& numberOfIntermediateCoords)
1830 {
1831  double gapX = (endCoord.getX() - startCoord.getX()) / static_cast<double>(numberOfIntermediateCoords + 1);
1832  double gapY = (endCoord.getY() - startCoord.getY()) / static_cast<double>(numberOfIntermediateCoords + 1);
1833 
1834  std::vector<te::gm::Coord2D> coords;
1835 
1836  coords.push_back(startCoord);
1837  for (std::size_t i = 0; i < static_cast<std::size_t>(numberOfIntermediateCoords); ++i)
1838  {
1839  std::size_t coordIndex = i + 1;
1840  te::gm::Coord2D coord(startCoord.getX() + (coordIndex * gapX), startCoord.getY() + (coordIndex * gapY));
1841  coords.push_back(coord);
1842  }
1843  coords.push_back(endCoord);
1844 
1845  te::gm::LineString resultLine(coords.size(), te::gm::LineStringType, srid);
1846 
1847  for (std::size_t t = 0; t < coords.size(); ++t)
1848  resultLine.setPoint(t, coords[t].getX(), coords[t].getY());
1849 
1850  return resultLine;
1851 }
1852 
1853 te::gm::Polygon te::gm::CreatePolygon(const te::gm::Envelope& box, const int& srid, const int& numberOfIntermediateCoords)
1854 {
1855  te::gm::Coord2D lowerLeft(box.m_llx, box.m_lly);
1856  te::gm::Coord2D lowerRight(box.m_urx, box.m_lly);
1857 
1858  te::gm::Coord2D upperLeft(box.m_llx, box.m_ury);
1859  te::gm::Coord2D upperRight(box.m_urx, box.m_ury);
1860 
1861  te::gm::LineString bottomLine = CreateLine(lowerLeft, lowerRight, srid, numberOfIntermediateCoords);
1862  te::gm::LineString leftLine = CreateLine(lowerRight, upperRight, srid, numberOfIntermediateCoords);
1863  te::gm::LineString topLine = CreateLine(upperRight, upperLeft, srid, numberOfIntermediateCoords);
1864  te::gm::LineString rightLine = CreateLine(upperLeft, lowerLeft, srid, numberOfIntermediateCoords);
1865 
1866  std::vector<te::gm::Coord2D> coords;
1867 
1868  //we do not add the last coord to avoid duplicity
1869  for (std::size_t i = 0; i < bottomLine.size() - 1; ++i)
1870  coords.push_back(te::gm::Coord2D(bottomLine.getX(i), bottomLine.getY(i)));
1871 
1872  for (std::size_t i = 0; i < leftLine.size() - 1; ++i)
1873  coords.push_back(te::gm::Coord2D(leftLine.getX(i), leftLine.getY(i)));
1874 
1875  for (std::size_t i = 0; i < topLine.size() - 1; ++i)
1876  coords.push_back(te::gm::Coord2D(topLine.getX(i), topLine.getY(i)));
1877 
1878  for (std::size_t i = 0; i < rightLine.size() - 1; ++i)
1879  coords.push_back(te::gm::Coord2D(rightLine.getX(i), rightLine.getY(i)));
1880 
1881  te::gm::LineString* fullLine = new te::gm::LineString(coords.size(), te::gm::LineStringType);
1882 
1883  for (std::size_t t = 0; t < coords.size(); ++t)
1884  fullLine->setPoint(t, coords[t].getX(), coords[t].getY());
1885 
1886  te::gm::Polygon polygon(1, te::gm::PolygonType, srid);
1887  polygon.setRingN(0, fullLine);
1888 
1889  return polygon;
1890 }
static te::dt::TimeDuration td(20, 30, 50, 11)
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
Curve * getInteriorRingN(std::size_t i) const
It returns the n-th interior ring for this curve polygon as a curve.
TEGEOMEXPORT te::gm::Geometry * UnaryUnion(te::gm::Geometry *geom)
It will get the union of the input geometries.
std::unique_ptr< Point > getEndPoint() const
It returns the curve end point.
TEGEOMEXPORT std::vector< MultiLineString * > GetAsMultiLineStringVector(const te::gm::Geometry &geometry)
Get the vector of MultLineStrings that compose the Geometry.
void add(Curve *ring)
It adds the ring to the curve polygon.
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
void init(const double &llx, const double &lly, const double &urx, const double &ury)
It initializes (sets) the envelope bounds.
The global factory used by TerraLib in order to create GEOS geometries.
std::vector< Curve * > & getRings()
It returns the polygon rings.
Definition: CurvePolygon.h:294
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
A Line is LineString with 2 points.
Definition: Line.h:50
virtual Geometry * symDifference(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns a geometric object that represents the point set symetric difference with another geometry...
double y
y-coordinate.
Definition: Coord2D.h:114
A Line is LineString with 2 points.
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
A LinearRing is a LineString that is both closed and simple.
TEGEOMEXPORT bool Rotate(te::gm::Coord2D pr, te::gm::LineString *l, double angle, te::gm::LineString *lOut)
virtual double distance(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns the shortest distance between any two points in the two geometry objects.
static te::dt::Date dx(2010, 12, 31)
double x
x-coordinate.
Definition: Coord2D.h:113
Base exception class for plugin module.
virtual te::dt::AbstractData * clone() const
It clones the linestring.
TEGEOMEXPORT te::gm::GeomType GetMultiType(te::gm::GeomType geomType)
Get the collection type of GeomType.
std::size_t getNumInteriorRings() const
It returns the number of interior rings in this CurvePolygon.
GeomType getGeomTypeId() const _NOEXCEPT_OP(true)
It returns the geometry subclass type identifier.
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
A point with x and y coordinate values.
TEGEOMEXPORT bool SatisfySpatialRelation(const Geometry *g1, const Geometry *g2, SpatialRelation relation)
It returns if two geometries satisfy a given spatial relation.
TEGEOMEXPORT te::gm::LineString CreateLine(const te::gm::Coord2D &startCoord, const te::gm::Coord2D &endCoord, const int &srid, const int &numberOfIntermediateCoords)
Creates a LineString between the given startCoord and endCoord with the given number of intermediate ...
TEGEOMEXPORT bool AdjustSegment(te::gm::Point *P0, te::gm::Point *P1, double d0, te::gm::Coord2D &P0out, te::gm::Coord2D &P1out)
Curve * getExteriorRing() const
It returns the exterior ring of this CurvePolygon.
double m_urx
Upper right corner x-coordinate.
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
TEGEOMEXPORT double PerpendicularDistance(const te::gm::Point &first, const te::gm::Point &last, te::gm::Point &pin, Point &pinter)
Calculate the perpendicular distance of a point in a segment.
const double TOLERANCE
virtual bool disjoint(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object is spatially disjoint from rhs geometry.
TEGEOMEXPORT bool IsMultiType(te::gm::GeomType geomType)
Verifies if the geomType is a collection type.
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
TEGEOMEXPORT std::unique_ptr< te::gm::Geometry > GetGeometryUnion(const std::vector< te::gm::Geometry * > &geomVec)
It returns the union of a geometry vector.
SpatialRelation
Spatial relations between geometric objects.
TEGEOMEXPORT te::gm::GeomType GetSimpleType(te::gm::GeomType geomType)
Get the simple type of GeomType.
TEGEOMEXPORT te::gm::Envelope CreateEnvelope(double x1, double y1, double x2, double y2)
Creates an envelope that fits the given coordinates. It makes all the adjustments needed to return a ...
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
double getY() const
It returns the y-coordinate.
Definition: Coord2D.h:108
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
virtual Geometry * Union(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns a geometric object that represents the point set union with another geometry.
virtual bool intersects(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object spatially intersects rhs geometry.
virtual bool touches(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object spatially touches rhs geometry.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
TEGEOMEXPORT void Multi2Single(const te::gm::Geometry *g, std::vector< te::gm::Geometry * > &geoms)
It will get a GeometryCollection and distribute in a vector.
This struct is used sorts a vector of points by distance.
TEGEOMEXPORT te::gm::Geometry * MultiLineToDefinedType(const std::vector< te::gm::MultiLineString * > &multiLineStringVector, te::gm::GeomType geometryType)
A geometry is built based on a Vector of MultiLineString and the origin geometry type.
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
virtual bool overlaps(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if this geometry object spatially overlaps rhs geometry.
unsigned int line
te::gm::GeometryCollection * gc
Utility functions for the Geometry Module.
TEGEOMEXPORT LineString * SnapLineToPoints(const te::sam::rtree::Index< std::size_t, 8 > &rtree, const std::vector< te::gm::LineString > &referenceSegments, const std::set< std::size_t > &setIndexesIgnored, const te::gm::LineString &linearRingToSnap, bool &wasChanged)
Snaps a LinearRing based on a set of LineString.
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
double m_llx
Lower left corner x-coordinate.
An Envelope defines a 2D rectangular region.
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
const Envelope * getMBR() const _NOEXCEPT_OP(true)
It returns the minimum bounding rectangle for the geometry in an internal representation.
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
An Envelope defines a 2D rectangular region.
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
MultiLineString is a MultiCurve whose elements are LineStrings.
virtual bool within(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object is spatially within rhs geometry.
virtual bool isEmpty() const _NOEXCEPT_OP(false)
It returns true if this geometric object is the empty Geometry.
TEGEOMEXPORT te::gm::Geometry * CascadedPolygonUnion(const std::vector< te::gm::Polygon * > &polygonVector)
Provides an efficient method of unioning a collection of Polygonal geometries. This algorithm is fast...
TEGEOMEXPORT Coord2D * locateAlong(const LineString *line, double initial, double final, double target)
Make the line interpolation to find a target.
te::gm::Polygon * p
MultiPolygon is a MultiSurface whose elements are Polygons.
void setCoord(int index, double x, double y, double z=0., double m=0.)
Definition: Line.cpp:114
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
virtual bool contains(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if this geometry object spatially contains rhs geometry.
virtual AbstractData * clone() const =0
It returns a clone of this object.
TEGEOMEXPORT te::gm::Geometry * PrepareGeometriesToIntersection(const te::gm::Geometry *geom_A, te::gm::Geometry *geomB, bool &wasChanged)
Prepares the geometry A with intersection points in geometry B.
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
A class that converts a GEOS geometry to a TerraLib geometry.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
TEGEOMEXPORT void Polygonizer(te::gm::Geometry *g, std::vector< te::gm::Polygon * > &pols)
It will get a list of polygons formed by the polygonization.
Curve is an abstract class that represents 1-dimensional geometric objects stored as a sequence of co...
A class that converts a TerraLib geometry to a GEOS geometry.
bool Intersects(const T1 &o1, const T2 &o2)
double m_lly
Lower left corner y-coordinate.
TEGEOMEXPORT std::vector< te::gm::Point > GetIntersectionPointsByOperators(const te::gm::LineString &lsReference, const std::vector< te::gm::LineString > &candidates)
Gets a vector of LineString reference points including intersection points using GEOS operators...
TEGEOMEXPORT void ClosestPoints(te::gm::Geometry *geomA, te::gm::Geometry *geomB, te::gm::Coord2D &coordA, te::gm::Coord2D &coordB)
Compute the the closest points of two geometries.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
TEGEOMEXPORT double GetAngle(te::gm::Coord2D coordA, te::gm::Coord2D coordB)
MultiLineString is a MultiCurve whose elements are LineStrings.
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
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
double m_ury
Upper right corner y-coordinate.
void add(Geometry *g)
It adds the geometry into the collection.
te::gm::Geometry * Union(te::gm::Geometry *g1, te::gm::Geometry *g2)
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
const std::vector< Geometry * > & getGeometries() const
It returns a reference to the internal list of geometries.
virtual void setSRID(int srid) _NOEXCEPT_OP(true)=0
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
TEGEOMEXPORT bool CheckValidity(const Geometry *geom, te::gm::TopologyValidationError &error)
It check geometry validity using GEOS.
TEGEOMEXPORT Envelope AdjustToCut(const Envelope &env, double bWidth, double bHeight)
Finds the correspondent smallest box that allows a box to be cut in blocks of a given size...
TEGEOMEXPORT std::vector< te::gm::Point > GetIntersectionPointsByPerpendicularDistance(const te::gm::LineString &lsReference, const std::vector< te::gm::LineString > &candidates)
Gets a vector of LineString reference points including intersection points using perpendicular distan...
TEGEOMEXPORT bool IsEqual(const te::gm::Point &p1, const te::gm::Point &p2)
Checks if a point p1 is exactly equal to the point p2.
LineString is a curve with linear interpolation between points.
void setPointN(std::size_t i, const Point &p)
It sets the value of the specified point to this new one.
TEGEOMEXPORT void AddPolygon(te::gm::Polygon *polygon, std::vector< te::gm::Geometry * > &pAdd)
Add all line strings from the polygon given to the vector given.
TEGEOMEXPORT LineString * AddIntersectionPoints(const te::sam::rtree::Index< std::size_t, 8 > &rtree, const std::vector< te::gm::LineString > &candidateSegments, const std::set< std::size_t > &setIndexesIgnored, const te::gm::LineString &lr_Reference, const bool &usePerpendicularDistance=false)
Add intersection points in a LinearRing based on a Vector of LineString as reference.
TEGEOMEXPORT void AddLineString(te::gm::LineString *lineString, std::vector< te::gm::Geometry * > &pAdd)
Add the linestring given to the vector.
virtual bool crosses(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object spatially crosses rhs geometry.
It is a collection of other geometric objects.
TEGEOMEXPORT te::gm::Polygon CreatePolygon(const te::gm::Envelope &box, const int &srid, const int &numberOfIntermediateCoords)
Creates a Polygon from the given envelope and with the given number of intermediate coordinates in ea...
TEGEOMEXPORT te::gm::Line * GetIntersectionLine(te::gm::Geometry *geom, te::gm::Coord2D coord)
This struct contains informations about GEOS TopologyValidationError.
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
An exception class for the Geometry module.
std::unique_ptr< Point > getStartPoint() const
The length of this Curve in its associated spatial reference.
TEGEOMEXPORT te::gm::GeomType GetMultiLineStringType(const te::gm::Geometry &geometry)
Get the LineStrings that compose the Geometry.
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
TEGEOMEXPORT te::gm::Geometry * Validate(te::gm::Geometry *geom)
Get/create a valid version of the geometry given. If the geometry is a polygon or multi polygon...
It is a collection of other geometric objects.
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
virtual bool coveredBy(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if this geometry object is spatially covered by rhs geometry.
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
virtual bool equals(const Geometry *const rhs, const bool exact=false) const _NOEXCEPT_OP(false)
It returns true if the geometry object is spatially equal to rhs geometry.
void setRingN(std::size_t i, Curve *r)
It sets the informed position ring to the new one.
virtual bool covers(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if this geometry object spatially covers the rhs geometry.