FixGeometryTopology.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 FixGeometryTopology.cpp
22  */
23 
24 #include "../common/progress/TaskProgress.h"
25 #include "../common/STLUtils.h"
26 #include "../core/logger/Logger.h"
27 #include "../core/translator/Translator.h"
28 
29 #include "Curve.h"
30 #include "FixGeometryTopology.h"
31 #include "LineString.h"
32 #include "Polygon.h"
33 #include "MultiPolygon.h"
34 
36  std::vector<Geometry *>& fixedGeometryVector,
37  TopologyValidationError topologyError)
38 {
39  std::unique_ptr<te::gm::Geometry> newGeometry(dynamic_cast<te::gm::Geometry*>(geometry.clone()));
40 
41  if(!closeGeometryRing(*newGeometry.get(), topologyError))
42  {
43  return false;
44  }
45 
46  if(!fixSelfIntersection(*newGeometry.get(), fixedGeometryVector, topologyError))
47  {
48  return false;
49  }
50 
51  return true;
52 }
53 
55  TopologyValidationError topologyError)
56 {
57  te::gm::GeomType type = geometry.getGeomTypeId();
58  if(type == te::gm::PolygonType ||
59  type == te::gm::PolygonZType ||
60  type == te::gm::PolygonMType ||
61  type == te::gm::PolygonZMType)
62  {
63  const te::gm::Polygon* polygon = dynamic_cast<const te::gm::Polygon*>(&geometry);
64  std::vector<te::gm::Curve*> curveVec = polygon->getRings();
65  for(auto c : curveVec)
66  {
67  if (!c->isClosed())
68  {
69  std::unique_ptr<te::gm::Point> startPoint = c->getStartPoint();
70  te::gm::LineString* ls = dynamic_cast<te::gm::LineString*>(c);
71 
72  std::size_t nPoints = ls->getNPoints();
73  ls->setNumCoordinates(nPoints + 1);
74 
75  ls->setPointN(nPoints, *startPoint);
76  }
77  }
78 
79  return true;
80  }
81  else if (type == te::gm::MultiPolygonType ||
82  type == te::gm::MultiPolygonZType ||
83  type == te::gm::MultiPolygonMType ||
85  {
86  const te::gm::MultiPolygon* mPolygon = dynamic_cast<const te::gm::MultiPolygon*>(&geometry);
87  std::vector<te::gm::Geometry*> geometryVec = mPolygon->getGeometries();
88  for (auto g : geometryVec)
89  {
90  if(!closeGeometryRing(*g, topologyError))
91  {
92  return false;
93  }
94  }
95  return true;
96  }
97  else
98  {
99  topologyError.m_message = TE_TR("Unexpected geometry type!");
100  return false;
101  }
102 }
103 
104 
106  std::vector<te::gm::Geometry*>& fixedGeometryVector,
107  TopologyValidationError topologyError)
108 {
109  std::unique_ptr<te::gm::Geometry> geomBuffer(geometry.buffer(0.0));
110 
111  if(geomBuffer->getGeomTypeId() != te::gm::MultiPolygonType &&
112  geomBuffer->getGeomTypeId() != te::gm::PolygonType)
113  {
114  topologyError.m_coordinate = geomBuffer->getCentroid();
115  topologyError.m_message = TE_TR("It was generated a geometry with an unexpected type.");
116  return false;
117  }
118 
119  std::vector<te::gm::Geometry*> vecSingleGeoms;
120  te::gm::Multi2Single(geomBuffer.get(), vecSingleGeoms);
121 
122  for(auto g : vecSingleGeoms)
123  {
124  bool isValid = CheckValidity(g, topologyError);
125 
126  if(!isValid)
127  {
128  te::common::FreeContents(vecSingleGeoms);
129  return false;
130  }
131  }
132 
133  if (geometry.getGeomTypeId() == te::gm::MultiPolygonType)
134  {
135  for (std::size_t i = 0; i < vecSingleGeoms.size(); ++i)
136  {
138 
139  pol->add((te::gm::Geometry*)vecSingleGeoms[i]);
140 
141  fixedGeometryVector.push_back(pol);
142  }
143  }
144  else if (geometry.getGeomTypeId() == te::gm::PolygonType)
145  {
146  for (std::size_t i = 0; i < vecSingleGeoms.size(); ++i)
147  {
148  fixedGeometryVector.push_back((te::gm::Geometry*)vecSingleGeoms[i]);
149  }
150  }
151  else
152  {
153  te::common::FreeContents(vecSingleGeoms);
154  topologyError.m_coordinate = geometry.getCentroid();
155  topologyError.m_message = TE_TR("Unexpected geometry type!");
156 
157  return false;
158  }
159 
160  return true;
161 }
static bool fixSelfIntersection(const te::gm::Geometry &geometry, std::vector< te::gm::Geometry * > &fixedGeometryVector, TopologyValidationError topologyError)
This function fixes geometries with self-intersection.
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
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.
virtual Geometry * buffer(const double &distance) const _NOEXCEPT_OP(false)
This method calculates the buffer of a geometry.
GeomType getGeomTypeId() const _NOEXCEPT_OP(true)
It returns the geometry subclass type identifier.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
TEGEOMEXPORT void Multi2Single(const te::gm::Geometry *g, std::vector< te::gm::Geometry * > &geoms)
It will get a GeometryCollection and distribute in a vector.
te::gm::Coord2D getCentroid() const _NOEXCEPT_OP(false)
It will get the centroid of the input geometries.
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
Functions to fix geometry topology.
void setNumCoordinates(std::size_t size)
It reserves room for the number of coordinates in this LineString.
static bool closeGeometryRing(const te::gm::Geometry &geometry, TopologyValidationError topologyError)
This function closes an opened geometry ring.
MultiPolygon is a MultiSurface whose elements are Polygons.
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
virtual AbstractData * clone() const =0
It returns a clone of this object.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Curve is an abstract class that represents 1-dimensional geometric objects stored as a sequence of co...
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
void add(Geometry *g)
It adds the geometry into the collection.
static bool fixTopology(const te::gm::Geometry &geometry, std::vector< te::gm::Geometry * > &fixedGeometryVector, TopologyValidationError topologyError)
This method gets a topologically inconsistent geometry and calls specific functions to fix this geome...
const std::vector< Geometry * > & getGeometries() const
It returns a reference to the internal list of geometries.
TEGEOMEXPORT bool CheckValidity(const Geometry *geom, te::gm::TopologyValidationError &error)
It check geometry validity using GEOS.
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.
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