Slope.cpp
Go to the documentation of this file.
1 /*!
2 \file terralib/mnt/core/Slope.cpp
3 
4 \brief This file contains a class to generate Slope grid.
5 
6 */
7 
8 #include "Slope.h"
9 #include "Utils.h"
10 
11 //terralib
12 #include "../../common/progress/TaskProgress.h"
13 #include "../../dataaccess/utils/Utils.h"
14 #include "../../geometry/GeometryProperty.h"
15 #include "../../raster.h"
16 #include "../../raster/BandProperty.h"
17 #include "../../raster/Grid.h"
18 #include "../../raster/RasterFactory.h"
19 #include "../../srs/SpatialReferenceSystemManager.h"
20 
22 :m_tol(0.000001)
23 {
24 }
25 
26 te::mnt::Slope::~Slope() = default;
27 
29  std::string inDsetName,
30  std::unique_ptr<te::da::DataSetType> inDsetType)
31 {
32  m_inDsrc = inDsrc;
33  m_inDsetName = inDsetName;
34  m_inDsetType = std::move(inDsetType);
35 
36 }
37 
38 void te::mnt::Slope::setOutput(std::map<std::string, std::string> &dsinfo)
39 {
40  m_dsinfo = dsinfo;
41 }
42 
43 void te::mnt::Slope::setParams(double resx, double resy, char grad, char slope, int srid, double dummy)
44 {
45  m_resx = resx;
46  m_resy = resy;
47  m_gradtype = grad;
48  m_slopetype = slope;
49  m_srid = srid;
50  m_dummy = dummy;
51 }
52 
54 {
55  std::unique_ptr<te::rst::Raster> in_raster;
56  if (m_inDsetType->hasRaster()) //GRID
57  {
58  m_inputType = GRID;
60  std::unique_ptr<te::da::DataSet> dsRaster = m_inDsrc->getDataSet(m_inDsetName);
61  in_raster = dsRaster->getRaster(rasterProp->getName());
62  m_env = *in_raster->getExtent();
63  m_resx = in_raster->getResolutionX();
64  m_resy = in_raster->getResolutionY();
65  in_raster->getBand(0)->getProperty()->m_noDataValue = m_dummy;
66  }
67  else
68  {
69  m_inputType = TIN;
71  return false;
72  // Calculate derivatives
73  if (!NodeDerivatives())
74  return false;
75  }
76 
77  //Create greater box 1/2 resolution
78  double rx1 = m_env.getLowerLeftX();
79  double ry2 = m_env.getUpperRightY();
80 
81  unsigned int outputWidth = (unsigned int)ceil(m_env.getWidth() / m_resx);
82  unsigned int outputHeight = (unsigned int)ceil(m_env.getHeight() / m_resy);
83 
84  te::gm::Coord2D ulc(rx1, ry2);
85 
86  te::rst::Grid* grid = new te::rst::Grid(outputWidth, outputHeight, m_resx, m_resy, &ulc, m_srid);
87 
88  std::vector<te::rst::BandProperty*> bands;
89 
90  bands.push_back(new te::rst::BandProperty(0, te::dt::DOUBLE_TYPE, "DTM GRID"));
91  bands[0]->m_nblocksx = 1;
92  bands[0]->m_nblocksy = (int)outputHeight;
93  bands[0]->m_blkw = (int)outputWidth;
94  bands[0]->m_blkh = 1;
95  bands[0]->m_colorInterp = te::rst::GrayIdxCInt;
96  bands[0]->m_noDataValue = m_nodatavalue;
97 
98  // create raster
99  std::unique_ptr<te::rst::Raster> rst(te::rst::RasterFactory::make("GDAL", grid, bands, m_dsinfo));
100 
101  m_rst = rst.get();
102 
103  if (m_inputType == TIN)
104  {
105  int32_t nodesid[3];
106  int32_t flin, llin, fcol, lcol;
107  double m1, m2;
108 
109  te::common::TaskProgress task("Calculating Slope...", te::common::TaskProgress::UNDEFINED, (int)m_ltriang);
110  //To each triangle
111  for (unsigned int i = 0; i < (unsigned int)m_ltriang; i++)
112  {
113  if (!task.isActive())
114  return false;
115 
116  task.pulse();
117  // Find Triangle Box
118  if (!NodesId((int32_t)i, nodesid))
119  continue;
120  if (!DefineInterLinesColumns(nodesid, flin, llin, fcol, lcol))
121  continue;
122 
123  //Special cases
124  m1 = m2 = std::numeric_limits<double>::max();
125  if ((m_node[(unsigned int)nodesid[1]].getY() - m_node[(unsigned int)nodesid[0]].getY()) != 0.0)
126  m1 = (m_node[(unsigned int)nodesid[1]].getX() - m_node[(unsigned int)nodesid[0]].getX()) /
127  (m_node[(unsigned int)nodesid[1]].getY() - m_node[(unsigned int)nodesid[0]].getY());
128 
129  if ((m_node[(unsigned int)nodesid[2]].getY() - m_node[(unsigned int)nodesid[0]].getY()) != 0.0)
130  m2 = (m_node[(unsigned int)nodesid[2]].getX() - m_node[(unsigned int)nodesid[0]].getX()) /
131  (m_node[(unsigned int)nodesid[2]].getY() - m_node[(unsigned int)nodesid[0]].getY());
132 
133  if (fabs(m1 - m2) < m_tol)
134  FillGridValue((int32_t)i, flin, llin, fcol, lcol, m_nodatavalue);
135  else
136  {
137  // Calculate gradient of triangle
138  double decvalue = TriangleGradient(nodesid, m_gradtype, m_slopetype);
139  FillGridValue((int32_t)i, flin, llin, fcol, lcol, decvalue);
140  }
141  }
142  }
143  else
144  {
145  double pi180 = 180. / 3.1415927;
146  double dzdy, dzdx;
147  double zvalue;
148  double EPSILON = 1.0e-40;
149 
150  m_min = in_raster->getBand(0)->getMinValue(true, 0, 0, outputHeight-1, outputWidth-1).real();
151  m_max = in_raster->getBand(0)->getMaxValue(true, 0, 0, outputHeight-1, outputWidth-1).real();
152 
153  m_dx = m_resx;
154  m_dy = m_resy;
155 
157 
158  if (unitin && unitin->getId() == te::common::UOM_Degree)
159  {
160  m_dx *= 111000; // 1 degree = 111.000 meters
161  m_dy *= 111000; // 1 degree = 111.000 meters
162  }
163 
164  te::common::TaskProgress task("Calculating Slope...", te::common::TaskProgress::UNDEFINED, (int)(in_raster->getNumberOfRows()*in_raster->getNumberOfColumns()));
165  for (unsigned l = 1; l < in_raster->getNumberOfRows() - 1; l++)
166  {
167  for (unsigned c = 1; c < in_raster->getNumberOfColumns() - 1; c++)
168  {
169  if (!task.isActive())
170  return false;
171  task.pulse();
172  if (CalcGradientRst(in_raster, l, c, dzdx, dzdy))
173  {
174  if (m_gradtype == 's')
175  { // Slope
176  if (m_slopetype == 'g') // graus
177  zvalue = (pi180*atan(sqrt((dzdx*dzdx) + (dzdy*dzdy))));
178  else // percentagem
179  zvalue = (sqrt((dzdx*dzdx) + (dzdy*dzdy))*100.);
180  }
181  else
182  { // Aspect
183  if ((dzdx > (-EPSILON)) && (dzdx < EPSILON)){ // dzdx ~= 0.
184  if (dzdy > EPSILON)
185  zvalue = 180.0;
186  else if (dzdy < (-EPSILON))
187  zvalue = 0.0;
188  else zvalue = m_nodatavalue; // nao existe exposicao
189  }
190  else
191  {
192  zvalue = 90. - (pi180*atan2(dzdy, dzdx));
193  if (zvalue < 0.) zvalue = 360. + zvalue;
194  zvalue = 360. - zvalue;
195  }
196  }
197  } // if (CalcGradientRst...
198  else
199  zvalue = m_nodatavalue;
200 
201  m_rst->setValue(c, l, zvalue);
202  } //for (int c = 1; ...
203  } //for (int l = 1; ...
204  }
205 
206  return true;
207 }
208 
209 
210 double te::mnt::Slope::TriangleGradient(int32_t *nodesid, char gradtype, char slopetype)
211 {
212  te::gm::Point p3da[3];
213  double nvector[3];
214  double moduv, decliv;
215  double pi180 = 180. / 3.1415927;
216  double m1, m2;
217  short j;
218 
219  for (j = 0; j < 3; j++)
220  {
221  p3da[j].setX(m_node[(unsigned int)nodesid[j]].getX());
222  p3da[j].setY(m_node[(unsigned int)nodesid[j]].getY());
223  p3da[j].setZ(m_node[(unsigned int)nodesid[j]].getZ());
224  }
225 
226  //Special cases
227  m1 = m2 = std::numeric_limits<double>::max();
228 
229  if ((p3da[1].getY() - p3da[0].getY()) != 0.0)
230  m1 = (p3da[1].getX() - p3da[0].getX()) / (p3da[1].getY() - p3da[0].getY());
231 
232  if ((p3da[2].getY() - p3da[0].getY()) != 0.0)
233  m2 = (p3da[2].getX() - p3da[0].getX()) / (p3da[2].getY() - p3da[0].getY());
234 
235  if (fabs(m1 - m2) < m_tol)
236  // Triangle with DUMMY Value
237  return m_nodatavalue;
238 
239  if ((p3da[0].getZ() >= m_nodatavalue) || (p3da[1].getZ() >= m_nodatavalue) ||
240  (p3da[2].getZ() >= m_nodatavalue)) // Triangle with DUMMY Value
241  return m_nodatavalue;
242 
243  if ((p3da[0].getZ() == p3da[1].getZ()) && (p3da[0].getZ() == p3da[2].getZ()))
244  {
245  if (gradtype == 's')
246  // Slope is zero
247  return 0.;
248  else
249  //exposition DUMMY
250  return m_nodatavalue;
251  }
252 
253  triangleNormalVector(p3da, nvector);
254  moduv = sqrt(pow(nvector[0], 2.) + pow(nvector[1], 2.) + pow(nvector[2], 2.));
255 
256  if (gradtype == 's')
257  {
258  // Case Slope
259  if (slopetype == 'g') // degrees
260  decliv = pi180*acos(nvector[2] / moduv);
261  else
262  decliv = tan(acos(nvector[2] / moduv)) * 100.;
263  }
264  else
265  {
266  // Caso exposicao
267  decliv = 90. - pi180*atan2(nvector[1], nvector[0]);
268  if (decliv < 0.)
269  decliv = 360. + decliv;
270  }
271 
272  return decliv;
273 }
274 
275 bool te::mnt::Slope::CalcGradientRst(std::unique_ptr<te::rst::Raster> &raster, unsigned l, unsigned c, double& dzdx, double& dzdy)
276 {
277  bool gradient = true;
278 
279  double pixlantcant;
280  double pixlantc;
281  double pixlantcpos;
282  double pixlcant;
283  double pixlcpos;
284  double pixlposcant;
285  double pixlposc;
286  double pixlposcpos;
287 
288  raster->getValue(c - 1, l - 1, pixlantcant);
289  raster->getValue(c, l - 1, pixlantc);
290  raster->getValue(c + 1, l - 1, pixlantcpos);
291  raster->getValue(c - 1, l, pixlcant);
292  raster->getValue(c + 1, l, pixlcpos);
293  raster->getValue(c - 1, l + 1, pixlposcant);
294  raster->getValue(c, l + 1, pixlposc);
295  raster->getValue(c + 1, l + 1, pixlposcpos);
296 
297  if ((pixlantc <= m_max && pixlantc >= m_min) && (pixlcant <= m_max && pixlcant >= m_min) &&
298  (pixlposc <= m_max && pixlposc >= m_min) && (pixlcpos <= m_max && pixlcpos >= m_min))
299  {
300  if ((pixlantcant <= m_max && pixlantcant >= m_min) && (pixlantcpos <= m_max && pixlantcpos >= m_min) &&
301  (pixlposcant <= m_max && pixlposcant >= m_min) && (pixlposcpos <= m_max && pixlposcpos >= m_min))
302  { // vizinhanca 8
303  // Calculate dzdx and dzdy derivative values with neighbourhood 8
304  dzdx = (((pixlposcpos + 2.*pixlcpos + pixlantcpos)
305  - (pixlposcant + 2.*pixlcant + pixlantcant)) / (8.*m_dx));
306  dzdy = (((pixlposcpos + 2.*pixlposc + pixlposcant)
307  - (pixlantcpos + 2.*pixlantc + pixlantcant)) / (8.*m_dy));
308  }
309  else
310  { // vizinhanca 4 usando os vizinhos do meio
311  // Calculate dzdx and dzdy derivative values with the neighbourhood 4
312  dzdx = ((pixlcpos - pixlcant) / (2.*m_dx));
313  dzdy = ((pixlposc - pixlantc) / (2.*m_dy));
314  }
315  }
316  else // vizinhanca 4 usando os vizinhos extremos
317  {
318  if ((pixlantcant <= m_max && pixlantcant >= m_min) && (pixlantcpos <= m_max && pixlantcpos >= m_min) &&
319  (pixlposcant <= m_max && pixlposcant >= m_min) && (pixlposcpos <= m_max && pixlposcpos >= m_min))
320  { // visinhanca 8
321  // Calculate dzdx and dzdy derivative values with neighbourhood
322  dzdx = (((pixlposcpos + pixlantcpos)
323  - (pixlposcant + pixlantcant)) / (4.*m_dx));
324  dzdy = (((pixlposcpos + pixlposcant)
325  - (pixlantcpos + pixlantcant)) / (4.*m_dy));
326  }
327  else
328  gradient = false;
329  }
330 
331  return gradient;
332 }
333 
int m_srid
Attribute with spatial reference information.
Definition: Tin.h:596
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
TEDATAACCESSEXPORT te::rst::RasterProperty * GetFirstRasterProperty(const DataSetType *dt)
void setOutput(std::map< std::string, std::string > &dsinfo)
Definition: Slope.cpp:38
bool CalcGradientRst(std::unique_ptr< te::rst::Raster > &raster, unsigned l, unsigned c, double &dzdx, double &dzdy)
METHOD TO CALCULATE GRADIENT VECTOR COMPONENTS IN THE POINT L,C OF THE GRID.
Definition: Slope.cpp:275
double m_max
Definition: Slope.h:74
double m_dy
Definition: Slope.h:75
double m_dx
Definition: Slope.h:75
Index into a lookup table.
bool FillGridValue(int32_t triid, int32_t flin, int32_t llin, int32_t fcol, int32_t lcol, double zvalue)
Method that fills the grid locations, inside a triangle, with a zvalue.
Definition: Tin.cpp:3256
bool NodesId(int32_t triangId, int32_t *nodeIds)
Method that reads the identification number of the nodes of a given triangle.
Definition: Tin.cpp:913
boost::shared_ptr< DataSource > DataSourcePtr
double m_resx
Definition: Tin.h:627
A raster band description.
Definition: BandProperty.h:61
bool NodeDerivatives()
Method that calculates the first and second derivatives in the nodes of a given triangle.
Definition: Tin.cpp:1743
te::gm::Envelope m_env
Attribute used to restrict the area to generate the samples.
Definition: Tin.h:598
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
double getWidth() const
It returns the envelope width.
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
char m_gradtype
Definition: Slope.h:69
bool isActive() const
Verify if the task is active.
Raster property.
This file contains a class to generate a Slope grid. Adapted from SPRING.
te::da::DataSourcePtr m_inDsrc
Definition: Slope.h:64
char m_slopetype
Definition: Slope.h:69
std::unique_ptr< te::da::DataSetType > m_inDsetType
Definition: Slope.h:66
bool DefineInterLinesColumns(int32_t *nodesid, int32_t &flin, int32_t &llin, int32_t &fcol, int32_t &lcol)
Method that calculates the lines and the columns intercepted by a triangle.
Definition: Tin.cpp:3279
double m_dummy
Definition: Slope.h:76
double m_nodatavalue
Definition: Tin.h:622
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
double m_tol
Definition: Slope.h:73
std::map< std::string, std::string > m_dsinfo
Definition: Slope.h:68
list bands
Definition: compose.py:2
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
double m_resy
Definition: Tin.h:627
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, std::unique_ptr< te::da::DataSetType > inDsetType)
Definition: Slope.cpp:28
Utility functions for the data access module.
const double & getZ() const
It returns the Point z-coordinate value, if it has one or DoubleNotANumber otherwise.
Definition: Point.h:166
te::rst::Raster * m_rst
Definition: Tin.h:626
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
std::vector< TinNode > m_node
Triangulation nodes vector.
Definition: Tin.h:606
static Raster * make()
It creates and returns an empty raster with default raster driver.
mntType m_inputType
Input type (TIN, GRID)
Definition: Slope.h:71
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
bool LoadTin(te::da::DataSourcePtr &inDsrc, std::string &inDsetName, double zmin=std::numeric_limits< double >::min(), double zmax=std::numeric_limits< double >::max())
Method used to load a triangular network (TIN)
Definition: Tin.cpp:1624
void setParams(double resx, double resy, char gradtype, char slopetype, int srid, double dummy)
Definition: Slope.cpp:43
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:159
double m_min
Definition: Slope.h:74
A rectified grid is the spatial support for raster data.
Definition: raster/Grid.h:68
int32_t m_ltriang
Triangulation last triangle number.
Definition: Tin.h:619
TEMNTEXPORT bool triangleNormalVector(te::gm::Point *, double *)
Function that defines the triangle normal vector.
double getHeight() const
It returns the envelope height.
double TriangleGradient(int32_t *nodesid, char gradtype, char slopetype)
Method that calculates a gradient value (slope or aspect) in a given triangle.
Definition: Slope.cpp:210
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
std::string m_inDsetName
Definition: Slope.h:65
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
bool run()
Definition: Slope.cpp:53
const std::string & getName() const
It returns the property name.
Definition: Property.h:127