All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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/edit/Utils.cpp
22 
23  \brief Utility functions for TerraLib Edit module.
24 */
25 
26 // TerraLib
27 #include "../dataaccess/dataset/DataSet.h"
28 #include "../dataaccess/dataset/ObjectId.h"
29 #include "../dataaccess/utils/Utils.h"
30 #include "../datatype/SimpleData.h"
31 #include "../geometry/Coord2D.h"
32 #include "../geometry/Envelope.h"
33 #include "../geometry/GeometryCollection.h"
34 #include "../geometry/GeometryProperty.h"
35 #include "../geometry/LineString.h"
36 #include "../geometry/MultiPoint.h"
37 #include "../geometry/Point.h"
38 #include "../geometry/Polygon.h"
39 #include "../geometry/Utils.h"
40 #include "../srs/Config.h"
41 #include "Feature.h"
42 #include "RepositoryManager.h"
43 #include "SnapManager.h"
44 #include "Utils.h"
45 
46 // Boost
47 #include <boost/uuid/random_generator.hpp>
48 #include <boost/uuid/uuid_io.hpp>
49 
50 // STL
51 #include <cassert>
52 #include <cmath>
53 #include <memory>
54 
56 {
57  if(layer->getVisibility() != te::map::VISIBLE || !layer->isValid())
58  return 0;
59 
60  te::gm::Envelope reprojectedEnvelope(env);
61 
62  if((layer->getSRID() != TE_UNKNOWN_SRS) && (srid != TE_UNKNOWN_SRS) && (layer->getSRID() != srid))
63  reprojectedEnvelope.transform(srid, layer->getSRID());
64 
65  // Try retrieves from RepositoryManager...
66  Feature* f = RepositoryManager::getInstance().getFeature(layer->getId(), env, srid);
67  if(f)
68  return f->clone();
69 
70  // ...else, retrieve from layer
71 
72  if(!reprojectedEnvelope.intersects(layer->getExtent()))
73  return 0;
74 
75  std::auto_ptr<const te::map::LayerSchema> schema(layer->getSchema());
76 
77  if(!schema->hasGeom())
78  return 0;
79 
80  std::vector<std::string> oidPropertyNames;
81  te::da::GetOIDPropertyNames(schema.get(), oidPropertyNames);
82 
84 
85  // Gets the dataset
86  std::auto_ptr<te::da::DataSet> dataset = layer->getData(gp->getName(), &reprojectedEnvelope, te::gm::INTERSECTS);
87 
88  if(dataset.get() == 0)
89  return 0;
90 
91  // Generates a geometry from the given extent. It will be used to refine the results
92  std::auto_ptr<te::gm::Geometry> geometryFromEnvelope(te::gm::GetGeomFromEnvelope(&reprojectedEnvelope, layer->getSRID()));
93 
94  // The restriction point. It will be used to refine the results
95  te::gm::Coord2D center = reprojectedEnvelope.getCenter();
96  te::gm::Point point(center.x, center.y, layer->getSRID());
97 
98  while(dataset->moveNext())
99  {
100  std::auto_ptr<te::gm::Geometry> g(dataset->getGeometry(gp->getName()));
101 
102  if(g->contains(&point) || g->crosses(geometryFromEnvelope.get()) || geometryFromEnvelope->contains(g.get())) // Geometry found!
103  return new Feature(te::da::GenerateOID(dataset.get(), oidPropertyNames), g.release());
104  }
105 
106  return 0;
107 }
108 
109 void te::edit::GetLines(te::gm::Geometry* geom, std::vector<te::gm::LineString*>& lines)
110 {
111  if(geom == 0)
112  return;
113 
114  switch(geom->getGeomTypeId())
115  {
118  GetLines(dynamic_cast<te::gm::GeometryCollection*>(geom), lines);
119  break;
120 
121  case te::gm::PolygonType:
122  GetLines(dynamic_cast<te::gm::Polygon*>(geom), lines);
123  break;
124 
126  GetLines(dynamic_cast<te::gm::LineString*>(geom), lines);
127  break;
128 
129  default:
130  return;
131  }
132 }
133 
134 void te::edit::GetLines(te::gm::GeometryCollection* gc, std::vector<te::gm::LineString*>& lines)
135 {
136  assert(gc);
137 
138  for(std::size_t i = 0; i < gc->getNumGeometries(); ++i)
139  GetLines(gc->getGeometryN(i), lines);
140 }
141 
142 void te::edit::GetLines(te::gm::Polygon* p, std::vector<te::gm::LineString*>& lines)
143 {
144  assert(p);
145 
146  std::vector<te::gm::Curve*>& rings = p->getRings();
147 
148  for(std::size_t i = 0; i < rings.size(); ++i) // for each ring
149  GetLines(dynamic_cast<te::gm::LineString*>(rings[i]), lines);
150 }
151 
152 void te::edit::GetLines(te::gm::LineString* l, std::vector<te::gm::LineString*>& lines)
153 {
154  assert(l);
155  lines.push_back(l);
156 }
157 
158 void te::edit::MoveVertex(std::vector<te::gm::LineString*>& lines, const VertexIndex& index, const double& x, const double& y)
159 {
160  assert(index.isValid());
161  assert(index.m_line < lines.size());
162 
163  te::gm::LineString* l = lines[index.m_line];
164 
165  assert(index.m_pos < l->getNPoints());
166 
167  if(IsSpecialRingVertex(l, index))
168  {
169  l->setPoint(0, x, y);
170  l->setPoint(l->getNPoints() - 1, x, y);
171  }
172  else
173  l->setPoint(index.m_pos, x, y);
174 }
175 
176 void te::edit::RemoveVertex(std::vector<te::gm::LineString*>& lines, const VertexIndex& index)
177 {
178  assert(index.isValid());
179  assert(index.m_line < lines.size());
180 
181  te::gm::LineString* currentLine = lines[index.m_line];
182 
183  te::gm::LineString* newLine = new te::gm::LineString(currentLine->getNPoints() - 1, currentLine->getGeomTypeId(), currentLine->getSRID());
184 
185  std::size_t pos = 0;
186  for(std::size_t i = 0; i < currentLine->getNPoints(); ++i)
187  {
188  // Skip the vertex
189  if(i == index.m_pos)
190  continue;
191 
192  if(IsSpecialRingVertex(currentLine, index) && ((i == 0) || (i == currentLine->getNPoints() - 1)))
193  continue;
194 
195  newLine->setPoint(pos, currentLine->getX(i), currentLine->getY(i));
196  ++pos;
197  }
198 
199  if(currentLine->isClosed())
200  newLine->setPoint(newLine->size() - 1, newLine->getX(0), newLine->getY(0));
201 
202  // Copy the new line
203  *currentLine = *newLine;
204 
205  delete newLine;
206 }
207 
208 void te::edit::AddVertex(std::vector<te::gm::LineString*>& lines, const double& x, const double& y, const te::gm::Envelope& env, int srid)
209 {
210  VertexIndex index = FindSegment(lines, env, srid);
211  assert(index.isValid());
212 
213  te::gm::LineString* currentLine = lines[index.m_line];
214 
215  te::gm::LineString* newLine = new te::gm::LineString(currentLine->getNPoints() + 1,
216  currentLine->getGeomTypeId(), currentLine->getSRID());
217 
218  std::size_t pos = 0;
219  for(std::size_t i = 0; i < currentLine->getNPoints(); ++i)
220  {
221  newLine->setPoint(pos, currentLine->getX(i), currentLine->getY(i));
222  ++pos;
223 
224  if(i == index.m_pos)
225  {
226  newLine->setPoint(pos, x, y);
227  ++pos;
228  }
229  }
230 
231  // Copy the new line
232  *currentLine = *newLine;
233 
234  delete newLine;
235 }
236 
237 te::edit::VertexIndex te::edit::FindSegment(std::vector<te::gm::LineString*>& lines, const te::gm::Envelope& env, int srid)
238 {
239  VertexIndex index;
240  index.makeInvalid();
241 
242  bool found = false;
243 
244  std::auto_ptr<te::gm::Geometry> geometryFromEnvelope(te::gm::GetGeomFromEnvelope(&env, srid));
245 
246  for(std::size_t i = 0; i < lines.size(); ++i) // for each line
247  {
248  te::gm::LineString* line = lines[i];
249 
250  for(std::size_t j = 0; j < line->getNPoints() - 1; ++j) // for each vertex
251  {
252  // Build the segment
253  std::auto_ptr<te::gm::LineString> segment(new te::gm::LineString(2, line->getGeomTypeId(), line->getSRID()));
254  segment->setPoint(0, line->getX(j), line->getY(j));
255  segment->setPoint(1, line->getX(j + 1), line->getY(j + 1));
256 
257  if(geometryFromEnvelope->intersects(segment.get()))
258  {
259  index.m_line = i;
260  index.m_pos = j;
261  found = true;
262  break;
263  }
264  }
265 
266  if(found)
267  break;
268  }
269 
270  return index;
271 }
272 
273 void te::edit::MoveGeometry(te::gm::Geometry* geom, const double& deltax, const double& deltay)
274 {
275  assert(geom);
276 
277  std::vector<te::gm::LineString*> lines;
278  GetLines(geom, lines);
279 
280  for(std::size_t i = 0; i < lines.size(); ++i)
281  {
282  te::gm::LineString* l = lines[i];
283  assert(l);
284 
285  for(std::size_t j = 0; j < l->getNPoints(); ++j)
286  l->setPoint(j, l->getX(j) + deltax, l->getY(j) + deltay);
287  }
288 }
289 
291 {
292  return l->isClosed() && ((index.m_pos == 0) || (index.m_pos == l->getNPoints() - 1));
293 }
294 
296 {
297  return sqrt(((c1.x - c2.x) * (c1.x - c2.x)) + ((c1.y - c2.y) * (c1.y - c2.y)));
298 }
299 
300 void te::edit::GetCoordinates(te::gm::Geometry* geom, std::vector<te::gm::Coord2D>& coords)
301 {
302  assert(geom);
303 
304  // Try extract lines
305  std::vector<te::gm::LineString*> lines;
306  GetLines(geom, lines);
307 
308  if(!lines.empty())
309  {
310  for(std::size_t i = 0; i < lines.size(); ++i) // for each line
311  {
312  te::gm::LineString* line = lines[i];
313  for(std::size_t j = 0; j < line->getNPoints(); ++j) // for each line point
314  coords.push_back(te::gm::Coord2D(line->getX(j), line->getY(j)));
315  }
316 
317  return;
318  }
319 
320  // Is it a point?
321  te::gm::AbstractPoint* point = dynamic_cast<te::gm::AbstractPoint*>(geom);
322  if(point)
323  {
324  coords.push_back(te::gm::Coord2D(point->getX(), point->getY()));
325  return;
326  }
327 
328  // Is it a multi point collection?
330  {
331  te::gm::MultiPoint* mp = dynamic_cast<te::gm::MultiPoint*>(geom);
332  assert(mp);
333 
334  for(std::size_t i = 0; i < mp->getNumGeometries(); ++i)
335  {
336  te::gm::AbstractPoint* point = dynamic_cast<te::gm::AbstractPoint*>(mp->getGeometryN(i));
337  assert(point);
338  coords.push_back(te::gm::Coord2D(point->getX(), point->getY()));
339  }
340  }
341 }
342 
343 void te::edit::TrySnap(te::gm::Coord2D& coord, int srid)
344 {
345  try
346  {
347  te::gm::Coord2D result;
348 
349  if(SnapManager::getInstance().search(coord, srid, result) == false)
350  return;
351 
352  coord.x = result.x;
353  coord.y = result.y;
354  }
355  catch(...)
356  {
357  return;
358  }
359 }
360 
362 {
363  static boost::uuids::basic_random_generator<boost::mt19937> gen;
364 
365  boost::uuids::uuid u = gen();
366  std::string id = boost::uuids::to_string(u);
367 
368  te::dt::String* data = new te::dt::String(id);
369 
371  oid->addValue(data);
372 
373  return oid;
374 }
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
int getSRID() const
It returns the Spatial Reference System ID associated to this geometric object.
Definition: Geometry.h:189
SimpleData< std::string, STRING_TYPE > String
Definition: SimpleData.h:229
Geometric property.
std::vector< Curve * > & getRings()
It returns the polygon rings.
Definition: CurvePolygon.h:300
Utility functions for the data access module.
virtual const double & getY() const =0
It returns the point y-coordinate value.
TEEDITEXPORT void MoveVertex(std::vector< te::gm::LineString * > &lines, const VertexIndex &index, const double &x, const double &y)
Definition: Utils.cpp:158
double y
y-coordinate.
Definition: Coord2D.h:114
bool intersects(const Envelope &rhs) const
It returns true if the envelopes "spatially intersects".
Definition: Envelope.h:493
TEEDITEXPORT te::da::ObjectId * GenerateId()
Definition: Utils.cpp:361
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
Definition: Utils.cpp:446
double x
x-coordinate.
Definition: Coord2D.h:113
Feature * clone() const
Definition: Feature.cpp:116
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
void addValue(te::dt::AbstractData *data)
It adds a property value to uniquely identify a data set element.
Definition: ObjectId.cpp:61
This is a singleton for managing edit repositories.
This class represents a geographic feature.
virtual const double & getX() const =0
It returns the point x-coordinate value.
TEEDITEXPORT void GetCoordinates(te::gm::Geometry *geom, std::vector< te::gm::Coord2D > &coords)
Definition: Utils.cpp:300
bool isClosed() const
It returns true if the curve is closed (startPoint = endPoint).
Definition: LineString.cpp:259
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
Definition: LineString.cpp:391
Coord2D getCenter() const
It returns the rectangle's center coordinate.
Definition: Envelope.cpp:51
TEEDITEXPORT void RemoveVertex(std::vector< te::gm::LineString * > &lines, const VertexIndex &index)
Definition: Utils.cpp:176
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
A point with x and y coordinate values.
Definition: Point.h:50
void setPoint(std::size_t i, const double &x, const double &y)
It sets the value of the specified point.
Definition: LineString.cpp:353
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
#define TE_UNKNOWN_SRS
A numeric value to represent a unknown SRS identification in TerraLib.
Definition: Config.h:44
const double & getX(std::size_t i) const
It returns the n-th x coordinate value.
Definition: LineString.cpp:385
This class represents an unique id for a data set element.
Definition: ObjectId.h:47
TEEDITEXPORT Feature * PickFeature(const te::map::AbstractLayerPtr &layer, const te::gm::Envelope &env, int srid)
Definition: Utils.cpp:55
TEEDITEXPORT double GetDistance(const te::gm::Coord2D &c1, const te::gm::Coord2D &c2)
Definition: Utils.cpp:295
std::size_t getNPoints() const
It returns the number of points (vertexes) in the linestring.
Definition: LineString.h:193
GeomType getGeomTypeId() const
It returns the geometry subclass type identifier.
Definition: Geometry.h:178
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
This is a singleton for managing geometries snap.
TEEDITEXPORT void MoveGeometry(te::gm::Geometry *geom, const double &deltax, const double &deltay)
Definition: Utils.cpp:273
std::size_t m_pos
Definition: Utils.h:80
TEEDITEXPORT void AddVertex(std::vector< te::gm::LineString * > &lines, const double &x, const double &y, const te::gm::Envelope &env, int srid)
Definition: Utils.cpp:208
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
TEEDITEXPORT void TrySnap(te::gm::Coord2D &coord, int srid)
Definition: Utils.cpp:343
std::size_t m_line
Definition: Utils.h:79
TEEDITEXPORT void GetLines(te::gm::Geometry *geom, std::vector< te::gm::LineString * > &lines)
Definition: Utils.cpp:109
bool isValid() const
Definition: Utils.h:74
TEEDITEXPORT bool IsSpecialRingVertex(te::gm::LineString *l, const VertexIndex &index)
Definition: Utils.cpp:290
TEDATAACCESSEXPORT void GetOIDPropertyNames(const DataSetType *type, std::vector< std::string > &pnames)
Definition: Utils.cpp:309
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
void makeInvalid()
Definition: Utils.h:68
It is a collection of other geometric objects.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:557
boost::intrusive_ptr< AbstractLayer > AbstractLayerPtr
void transform(int oldsrid, int newsrid)
It will transform the coordinates of the Envelope from the old SRS to the new one.
Definition: Envelope.cpp:92
A base abstract class for 0-dimensional geometric objects that represents a single location in coordi...
Definition: AbstractPoint.h:50
TEGEOMEXPORT Geometry * GetGeomFromEnvelope(const Envelope *const e, int srid)
It creates a Geometry (a polygon) from the given envelope.
Definition: Utils.cpp:38
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
TEEDITEXPORT VertexIndex FindSegment(std::vector< te::gm::LineString * > &lines, const te::gm::Envelope &env, int srid)
Definition: Utils.cpp:237