Profile.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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/mnt/core/Profile.cpp
22 
23  \brief This file contains a class that represents the profile.
24 
25  */
26 
27 //TerraLib
28 
29 #include "../../core/translator/Translator.h"
30 #include "../../common/progress/TaskProgress.h"
31 #include "../../core/logger/Logger.h"
32 #include "../../common/UnitsOfMeasureManager.h"
33 
34 #include "../../dataaccess/dataset/DataSetTypeConverter.h"
35 #include "../../dataaccess/dataset/DataSetTypeCapabilities.h"
36 #include "../../dataaccess/datasource/DataSource.h"
37 #include "../../dataaccess/datasource/DataSourceFactory.h"
38 #include "../../dataaccess/datasource/DataSourceInfo.h"
39 #include "../../dataaccess/datasource/DataSourceManager.h"
40 #include "../../dataaccess/query/EqualTo.h"
41 
42 #include "../../datatype/Property.h"
43 #include "../../datatype/SimpleProperty.h"
44 #include "../../datatype/StringProperty.h"
45 
46 #include "../../geometry/Geometry.h"
47 #include "../../geometry/GeometryProperty.h"
48 #include "../../geometry/Line.h"
49 #include "../../geometry/MultiLineString.h"
50 #include "../../geometry/MultiPolygon.h"
51 #include "../../geometry/Point.h"
52 #include "../../geometry/Polygon.h"
53 
54 #include "../../maptools/AbstractLayer.h"
55 
56 #include "../../memory/DataSet.h"
57 #include "../../memory/DataSetItem.h"
58 
59 #include "../../raster/RasterProperty.h"
60 #include "../../raster/RasterFactory.h"
61 #include "../../raster/Utils.h"
62 #include "../../raster/BandProperty.h"
63 
64 #include "../../srs/SpatialReferenceSystemManager.h"
65 #include "../../statistics/core/Enums.h"
66 
67 #include "Profile.h"
68 #include "Utils.h"
69 
70 //STL
71 #include <cassert>
72 
73 //Boost
74 #include <boost/lexical_cast.hpp>
75 
76 te::mnt::Profile::Profile() = default;
77 
78 te::mnt::Profile::~Profile() = default;
79 
80 void te::mnt::Profile::setInput(te::da::DataSourcePtr inDsrc, std::string inName, std::unique_ptr<te::da::DataSetType> inDsetType, double dummy, std::string zattr)
81 {
82  m_inDsrc = inDsrc;
83  m_inName = inName;
84  m_inDsType = std::move(inDsetType);
85  m_dummy = dummy;
86  m_attrZ = zattr;
87 }
88 
89 
90 std::unique_ptr<te::rst::Raster> te::mnt::Profile::getPrepareRaster()
91 {
92  std::unique_ptr<te::da::DataSetType>dsTypeRaster = m_inDsrc->getDataSetType(m_inName);
93  //prepare raster
94  te::rst::RasterProperty* inProp = te::da::GetFirstRasterProperty(dsTypeRaster.get());
95  std::unique_ptr<te::da::DataSet> ds = m_inDsrc->getDataSet(m_inName);
96  std::unique_ptr<te::rst::Raster> raster = ds->getRaster(inProp->getName());
97  return raster;
98 }
99 
100 
101 bool te::mnt::Profile::runRasterProfile(std::vector<te::gm::LineString*> visadas, std::vector<te::gm::LineString*>& profileSet)
102 {
103  double distbase = 0;
104  int ind_pf = -1;
105  int ind_pfant = -1;
106 
107  double xmin, xmax, ymin, ymax, zval, pt1X, pt1Y, pt2X, pt2Y;
108  unsigned int col, row;
109 
110  te::gm::Coord2D collin;
111 
112  std::map<double, double> line;
113 
114  std::unique_ptr<te::rst::Raster> raster = getPrepareRaster();
115  if (!raster.get())
116  {
117  return false;
118  }
119 
120  double boxLowerLeft = raster->getExtent()->getLowerLeftX(); //x1 = lowerLeftX
121  double boxUpperRigth = raster->getExtent()->getUpperRightY(); //y2 = UpperRigthY
122 
123  double resX = raster->getResolutionX();
124  double resY = raster->getResolutionY();
125  bool isll = false;
126 
127  m_srid = raster->getSRID();
128 
129  if (m_srid)
130  {
131  te::common::UnitOfMeasurePtr unitin = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(m_srid));
132  if (unitin && unitin->getId() != te::common::UOM_Metre)
133  isll = true;
134  }
136 
137  for (std::size_t v = 0; v < visadas.size(); ++v)
138  {
139  te::gm::LineString *l = visadas[v];
140  for (std::size_t i = 0; i < l->getNPoints()-1; i++)
141  {
142  pt1X = l->getX(i);
143  pt1Y = l->getY(i);
144 
145  collin = raster->getGrid()->geoToGrid(pt1X, pt1Y);
146  col = static_cast<unsigned int>(collin.getX());
147  row = static_cast<unsigned int>(collin.getY());
148 
149  if (col >= raster->getNumberOfColumns() || row >= raster->getNumberOfRows())
150  continue;
151  raster->getValue(col, row, zval);
152  if (zval == m_dummy)
153  continue;
154 
155  if (!line.size()) //first element to insert
156  line.insert(std::map<double, double>::value_type(0.0, zval));
157 
158  ind_pf++;
159 
160  pt2X = l->getX(i+1);
161  pt2Y = l->getY(i+1);
162 
163  if (pt1X > pt2X)
164  {
165  xmin = pt2X;
166  xmax = pt1X;
167  }
168  else
169  {
170  xmin = pt1X;
171  xmax = pt2X;
172  }
173 
174  if (pt1Y > pt2Y)
175  {
176  ymin = pt2Y;
177  ymax = pt1Y;
178  }
179  else
180  {
181  ymin = pt1Y;
182  ymax = pt2Y;
183  }
184 
185  int initcol = static_cast<int>((xmin - boxLowerLeft) / resX);
186  int finalcol = static_cast<int>((xmax - boxLowerLeft) / resX + .9999);
187  int initline = static_cast<int>((boxUpperRigth - ymax) / resY);
188  int finalline = static_cast<int>((boxUpperRigth - ymin) / resY + .9999);
189 
190  double dx = pt2X - pt1X;
191  double dy = pt2Y - pt1Y;
192 
193  //Calculate intersections of the segment with the columns
194  if (((finalcol - initcol) > 1) && (fabs(static_cast<double>(dx)) > 1.0e-6))
195  {
196  for (int c = (initcol + 1); c < finalcol; c++)
197  {
198  double x = (boxLowerLeft + c * resX);
199  double y = (pt1Y + (dy / dx) * (x - pt1X));
200 
201  collin = raster->getGrid()->geoToGrid(x, y);
202  col = static_cast<unsigned int>(collin.getX());
203  row = static_cast<unsigned int>(collin.getY());
204 
205  if (col >= raster->getNumberOfColumns() || row >= raster->getNumberOfRows())
206  continue;
207 
208  raster->getValue(col, row, zval);
209  if (zval != m_dummy)
210  {
211  double dist = sqrt((static_cast<double>(x - pt1X)*static_cast<double>(x - pt1X)) + (static_cast<double>(y - pt1Y)*static_cast<double>(y - pt1Y))) + distbase;
212  if (isll)
213  convertAngleToPlanar(dist, unitout, 0);
214  line.insert(std::map<double, double>::value_type(dist, zval));
215  ind_pf++;
216  }
217  }
218  }
219 
220  //Calculate intersections of the segment with the lines
221  if (((finalline - initline) > 1) && (fabs((double)dy) > 1.0e-6))
222  {
223  for (int ll = (initline + 1); ll < finalline; ll++)
224  {
225  //Calculate intersections of the segment with the bottom line
226  double y = boxUpperRigth - (ll * resY);
227  double x = pt1X + (dx / dy) * (y - pt1Y);
228 
229  collin = raster->getGrid()->geoToGrid(x, y);
230  col = static_cast<unsigned int>(collin.getX());
231  row = static_cast<unsigned int>(collin.getY());
232 
233  if (col >= raster->getNumberOfColumns() || row >= raster->getNumberOfRows())
234  continue;
235 
236  raster->getValue(col, row, zval);
237  if (zval != m_dummy)
238  {
239  //Calculates the distance of the current point with point x1, y1
240  double dist = sqrt((static_cast<double>(x - pt1X)*static_cast<double>(x - pt1X)) + (static_cast<double>(y - pt1Y)*static_cast<double>(y - pt1Y))) + distbase;
241  if (isll)
242  convertAngleToPlanar(dist, unitout, 0);
243  line.insert(std::map<double, double>::value_type(dist, zval));
244  ind_pf++;
245  }
246  }
247  }
248 
249  //Stores second end (pt2) in the profile structure
250  collin = raster->getGrid()->geoToGrid(pt2X, pt2Y);
251  col = static_cast<unsigned int>(collin.getX());
252  row = static_cast<unsigned int>(collin.getY());
253 
254  if (col >= raster->getNumberOfColumns() || row >= raster->getNumberOfRows())
255  continue;
256  raster->getValue(col, row, zval);
257  if (zval != m_dummy)
258  {
259  double dist = sqrt((static_cast<double>(dx) * static_cast<double>(dx)) + (static_cast<double>(dy)* static_cast<double>(dy))) + distbase;
260 
261  if (ind_pf != ind_pfant)
262  distbase = dist;
263 
264  ind_pfant = ind_pf;
265  pt1X = pt2X;
266  pt1Y = pt2Y;
267  if (isll)
268  convertAngleToPlanar(dist, unitout, 0);
269  line.insert(std::map<double, double>::value_type(dist, zval));
270  }
271  }
272 
274  std::map<double, double>::iterator it = line.begin();
275 
276  while (it != line.end())
277  {
278  profile->setNumCoordinates(profile->size() + 1);
279  profile->setPoint(profile->size() - 1, it->first, it->second);
280  it++;
281  }
282 
283  profileSet.push_back(profile);
284  line.clear();
285  distbase = 0;
286  }
287 
288  return true;
289 }
290 
291 te::gm::LineString* te::mnt::Profile::calculateProfile(std::vector<te::gm::Geometry*> &isolines, te::gm::LineString &trajectory)
292 {
293  //std::unique_ptr<te::gm::Geometry> resultGeom;
294  te::gm::LineString* iso;
297  double dist = 0.;
299  std::map<double, double> line;
300  te::gm::Point ptinter(0, te::gm::PointZType);
301 
302  for (std::size_t t = 0; t < trajectory.size() - 1; t++)
303  {
304  seg.setCoord(0, trajectory.getX(t), trajectory.getY(t));
305  seg.setPoint(1, trajectory.getX(t + 1), trajectory.getY(t + 1));
306  for (std::size_t i = 0; i < isolines.size(); i++)
307  {
308  iso = dynamic_cast<te::gm::LineString*>(isolines[i]);
309  for (std::size_t j = 0; j < iso->getNPoints() - 1; j++)
310  {
311  seg1.setCoord(0, iso->getX(j), iso->getY(j));
312  seg1.setPoint(1, iso->getX(j + 1), iso->getY(j + 1));
313  if (seg.intersection(seg1, ptinter))
314  {
315  double dist0 = Distance(trajectory.getX(t), trajectory.getY(t), ptinter.getX(), ptinter.getY());
316  line.insert(std::map<double, double>::value_type(dist + dist0, *iso->getZ()));
317  }
318  }
319  }
320  dist += Distance(trajectory.getX(t), trajectory.getY(t), trajectory.getX(t + 1), trajectory.getY(t + 1));
321  }
322 
323  std::map<double, double>::iterator it = line.begin();
324 
325  while (it != line.end())
326  {
327  profile->setNumCoordinates(profile->size() + 1);
328  profile->setPoint(profile->size() - 1, it->first, it->second);
329  it++;
330  }
331  line.clear();
332  return profile;
333 }
334 
335 bool te::mnt::Profile::runIsolinesProfile(std::vector<te::gm::LineString*> visadas, std::vector<te::gm::LineString*>& profileSet)
336 {
337  std::unique_ptr<te::da::DataSetType>dsType = m_inDsrc->getDataSetType(m_inName);
338 
339  if (m_srid)
340  {
341  te::common::UnitOfMeasurePtr unitin = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(m_srid));
342  }
343 
346 
347  std::string geostype;
348  te::gm::Envelope env;
349 
350  if (ReadSamples(m_inName, m_inDsrc, m_attrZ, 0, 0, None, mpt, isolines, geostype, env, m_srid) == 0)
351  return true;
352 
354  for (size_t i = 0; i < isolines.getNumGeometries(); ++i)
355  {
356  linetree.insert(*isolines.getGeometryN(i)->getMBR(), dynamic_cast<te::gm::Geometry*>(isolines.getGeometryN(i)));
357  }
358 
359  std::vector<te::gm::Geometry*> reportline;
360  for (std::size_t v = 0; v < visadas.size(); ++v)
361  {
362  reportline.clear();
363  linetree.search(*visadas[v]->getMBR(), reportline);
364  if (reportline.size())
365  {
366  te::gm::LineString* profile = calculateProfile(reportline, *visadas[v]);
367  if (profile)
368  profileSet.push_back(profile);
369  }
370  }
371  return true;
372 }
373 
374 bool te::mnt::Profile::runTINProfile(std::vector<te::gm::LineString*> visadas, std::vector<te::gm::LineString*>& profileSet)
375 {
376  std::unique_ptr<te::da::DataSetType>dsType = m_inDsrc->getDataSetType(m_inName);
377 
378  if (m_srid)
379  {
380  te::common::UnitOfMeasurePtr unitin = te::srs::SpatialReferenceSystemManager::getInstance().getUnit(static_cast<unsigned int>(m_srid));
381  }
382 
383  std::unique_ptr<te::da::DataSet> inDset = m_inDsrc->getDataSet(m_inName);
384  std::size_t geo_pos = te::da::GetFirstPropertyPos(inDset.get(), te::dt::GEOMETRY_TYPE);
385  std::unique_ptr<te::gm::GeometryProperty>geomProp(te::da::GetFirstGeomProperty(dsType.get()));
386 
387  inDset->moveBeforeFirst();
388 
389  std::vector<te::gm::Polygon *> vp;
390  te::gm::LineString *edge;
392  std::vector<te::gm::Geometry*> reportline;
393 
394  try
395  {
396  while (inDset->moveNext())
397  {
398  std::unique_ptr<te::gm::Geometry> gin = inDset->getGeometry(geo_pos);
399 
400  if ((gin->getGeomTypeId()) % 1000 == te::gm::MultiPolygonType)
401  {
402  te::gm::MultiPolygon *mg = dynamic_cast<te::gm::MultiPolygon*>(gin.get()->clone());
403  if (!mg)
404  throw te::common::Exception(TE_TR("Isn't possible to read data!"));
405 
406  std::size_t np = mg->getNumGeometries();
407  for (std::size_t i = 0; i < np; i++)
408  vp.push_back(dynamic_cast<te::gm::Polygon*>(mg->getGeometryN(i)));
409  }
410  if ((gin->getGeomTypeId()) % 1000 == te::gm::PolygonType)
411  {
412  te::gm::Polygon *pol = dynamic_cast<te::gm::Polygon*>(gin.get()->clone());
413  if (!pol)
414  throw te::common::Exception(TE_TR("Isn't possible to read data!"));
415  vp.push_back(pol);
416  }
417  for (std::size_t i = 0; i < vp.size(); ++i)
418  {
419  te::gm::Polygon *pol = vp[i];
420  te::gm::Curve* c = pol->getRingN(0);
421  te::gm::LinearRing* lr = dynamic_cast<te::gm::LinearRing*>(c);
422  for (std::size_t p = 0; p < 3; p++)
423  {
425  edge->setPointZ(0, lr->getPointN(p)->getX(), lr->getPointN(p)->getY(), lr->getPointN(p)->getZ());
426  edge->setPointZ(1, lr->getPointN(p + 1)->getX(), lr->getPointN(p + 1)->getY(), lr->getPointN(p)->getZ());
427  reportline.clear();
428  linetree.search(*edge->getMBR(), reportline);
429  if (reportline.size())
430  continue;
431  linetree.insert(*edge->getMBR(), dynamic_cast<te::gm::Geometry*>(edge));
432  }
433  }
434  vp.clear();
435  }
436 
437  for (std::size_t v = 0; v < visadas.size(); ++v)
438  {
439  reportline.clear();
440  linetree.search(*visadas[v]->getMBR(), reportline);
441  if (reportline.size())
442  {
443  te::gm::LineString* profile = calculateProfile(reportline, *visadas[v]);
444  if (profile)
445  profileSet.push_back(profile);
446  }
447  }
448 
449  reportline.clear();
450  linetree.clear();
451  }
452  catch (te::common::Exception& e)
453  {
454 #ifdef TERRALIB_LOGGER_ENABLED
455  TE_CORE_LOG_DEBUG("mnt", e.what());
456 #endif
457  dsType.release();
458  throw te::common::Exception(e.what());
459  }
460 
461  dsType.release();
462 
463  return true;
464 }
465 
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
A Line is LineString with 2 points.
Definition: Line.h:50
std::string m_attrZ
Z attribute name.
Definition: Profile.h:103
te::da::DataSourcePtr m_inDsrc
Input Datasource.
Definition: Profile.h:100
int m_srid
Attribute with spatial reference information.
Definition: Profile.h:98
boost::shared_ptr< DataSource > DataSourcePtr
static te::dt::Date dx(2010, 12, 31)
A class that represents an R-tree.
std::string m_inName
Input data name.
Definition: Profile.h:101
Curve is an abstract class that represents 1-dimensional geometric objects stored as a sequence of co...
Definition: Curve.h:58
TEMNTEXPORT double Distance(const te::gm::Coord2D &pt1, const te::gm::Coord2D &pt2)
bool runIsolinesProfile(std::vector< te::gm::LineString * > visadas, std::vector< te::gm::LineString * > &profileSet)
Calculate Profile from isolines.
Definition: Profile.cpp:335
virtual const char * what() const
It outputs the exception message.
#define TE_CORE_LOG_DEBUG(channel, message)
Use this tag in order to log a message to a specified logger with the DEBUG level.
Definition: Logger.h:225
std::unique_ptr< Point > getPointN(std::size_t i) const
It returns the specified point in this LineString.
bool intersection(const Line &line, Point &coord) const
Definition: Line.cpp:87
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
double getY() const
It returns the y-coordinate.
Definition: Coord2D.h:108
static te::dt::Date ds(2010, 01, 01)
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
std::unique_ptr< te::rst::Raster > getPrepareRaster()
Reads raster.
Definition: Profile.cpp:90
Raster property.
const double & getY(std::size_t i) const
It returns the n-th y coordinate value.
Utility functions for MNT support.
unsigned int line
A LinearRing is a LineString that is both closed and simple.
Definition: LinearRing.h:53
void setInput(te::da::DataSourcePtr inDsrc, std::string inName, std::unique_ptr< te::da::DataSetType > inDsetType, double dummy, std::string zattr)
Sets input parameters to calculate profile.
Definition: Profile.cpp:80
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
const double & getY() const
It returns the Point y-coordinate value.
Definition: Point.h:152
static SpatialReferenceSystemManager & getInstance()
It returns a reference to the singleton instance.
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.
Profile()
Default constructor.
void setNumCoordinates(std::size_t size)
It reserves room for the number of coordinates in this LineString.
te::gm::Polygon * p
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
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
void setPointZ(std::size_t i, const double &x, const double &y, const double &z)
It sets the value of the specified point.
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.
double m_dummy
Nodata value.
Definition: Profile.h:99
TEMNTEXPORT size_t ReadSamples(std::string &inDsetName, te::da::DataSourcePtr &inDsrc, std::string &atrZ, double tol, double max, Simplify alg, te::gm::MultiPoint &mpt, te::gm::MultiLineString &isolines, std::string &geostype, te::gm::Envelope &env, int srid=0)
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
MultiLineString is a MultiCurve whose elements are LineStrings.
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
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.
std::unique_ptr< te::da::DataSetType > m_inDsType
Input datasettype.
Definition: Profile.h:102
bool runTINProfile(std::vector< te::gm::LineString * > visadas, std::vector< te::gm::LineString * > &profileSet)
Calculate Profile from TIN.
Definition: Profile.cpp:374
const double & getZ(std::size_t i) const
It returns the n-th z coordinate value.
~Profile()
Virtual destructor.
UnitOfMeasurePtr find(unsigned int id) const
Returns a unit of measure identified by its identificaton.
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
te::gm::LineString * calculateProfile(std::vector< te::gm::Geometry * > &isolines, te::gm::LineString &trajectory)
Definition: Profile.cpp:291
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
unsigned int col
Curve * getRingN(std::size_t i) const
It returns the n-th ring for this curve polygon as a curve.
Definition: CurvePolygon.h:193
std::size_t size() const
It returns the number of points (vertexes) in the geometry.
Definition: LineString.h:262
This file contains a class that represents the profile.
TEMNTEXPORT bool convertAngleToPlanar(double &val, te::common::UnitOfMeasurePtr planar, int type)
const std::string & getName() const
It returns the property name.
Definition: Property.h:127
bool runRasterProfile(std::vector< te::gm::LineString * > visadas, std::vector< te::gm::LineString * > &profileSet)
Calculate Profile from raster.
Definition: Profile.cpp:101