SplineGrassMitasova.cpp
Go to the documentation of this file.
1 /*!
2 \file terralib/mnt/core/SplineGrassMitasova.cpp
3 
4 \brief This file contains a class to calculate a grid from Sample using spline grass mitasova interpolator.
5 
6 */
7 
8 #include "SplineGrassMitasova.h"
9 #include "Utils.h"
10 
11 #include "../../common/progress/TaskProgress.h"
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <vector>
16 
17 
19 {
20  m_minimoPontos = minPoints * 2;
21  m_tension = tension;
22  m_smooth = smooth;
23 }
24 
26  default;
27 
28 void te::mnt::SplineInterpolationGrassMitasova::setControlPoints(double xMin, double xMax, double yMin, double yMax, int nMax, double xOrigem, double yOrigem, double dnorm)
29 {
30  std::size_t nVectorPoints = m_dataset.size();
31 
32  m_pointsRegion.clear();
33  for (std::size_t i = 0; i<nVectorPoints; i++)
34  {
35  te::gm::Point pp3d = m_dataset[i].second;
36  if ((pp3d.getX() >= xMin) && (pp3d.getX() < xMax) && (pp3d.getY() >= yMin) && (pp3d.getY() < yMax))
37  {
38  //update new point
39  double nX = (pp3d.getX() - xOrigem) / dnorm;
40  double nY = (pp3d.getY() - yOrigem) / dnorm;
41 
43  npp3d.setX(nX);
44  npp3d.setY(nY);
45  npp3d.setZ(pp3d.getZ());
46 
47  //add a new point
48  m_pointsRegion.push_back(npp3d);
49 
50  if (m_pointsRegion.size() == static_cast<size_t>(nMax))
51  break;
52  }
53  }
54 }
55 
56 double te::mnt::SplineInterpolationGrassMitasova::amax1(double arg1, double arg2)
57 {
58  double res;
59 
60  if (arg1 >= arg2)
61  res = arg1;
62  else
63  res = arg2;
64  return res;
65 }
66 
67 double te::mnt::SplineInterpolationGrassMitasova::amin1(double arg1, double arg2)
68 {
69  double res;
70 
71  if (arg1 <= arg2)
72  res = arg1;
73  else
74  res = arg2;
75  return res;
76 }
77 
79 /*
80 * Radial basis function - completely regularized spline with
81 * tension (d=2)
82 */
83 {
84  double rfsta2 = fi * fi * r / 4.;
85 
86  static double c[4] = { 8.5733287401, 18.0590169730, 8.6347608925,
87  0.2677737343 };
88  static double b[4] = { 9.5733223454, 25.6329561486, 21.0996530827,
89  3.9584969228 };
90  double ce = 0.57721566;
91 
92  static double u[10] = { 1.e+00, -.25e+00,
93  .055555555555556e+00, -.010416666666667e+00, /*fixed bug 415.. repl. by 416..*/
94  .166666666666667e-02, -2.31481481481482e-04,
95  2.83446712018141e-05, -3.10019841269841e-06,
96  3.06192435822065e-07, -2.75573192239859e-08 };
97  double x = rfsta2;
98  double res;
99 
100  double e1, ea, eb;
101 
102  if (x < 1.e+00)
103  {
104  res = x * (u[0] + x * (u[1] + x * (u[2] + x * (u[3] + x * (u[4] + x *
105  (u[5] + x * (u[6] + x * (u[7] + x * (u[8] + x * u[9])))))))));
106  return (res);
107  }
108 
109  if (x > 25.e+00)
110  e1 = 0.00;
111  else
112  {
113  ea = c[3] + x * (c[2] + x * (c[1] + x * (c[0] + x)));
114  eb = b[3] + x * (b[2] + x * (b[1] + x * (b[0] + x)));
115  e1 = (ea / eb) / (x * exp(x));
116  }
117  res = e1 + ce + log(x);
118  return (res);
119 }
120 
121 void te::mnt::SplineInterpolationGrassMitasova::G_lubksb(std::vector< std::vector<double> > &a, int n, std::vector<int> &indx, std::vector<double> &b)
122 {
123  int i, ii, ip, j;
124  double sum;
125 
126  ii = -1;
127  for (i = 0; i<n; i++)
128  {
129  ip = indx[static_cast<size_t>(i)];
130  sum = b[static_cast<size_t>(ip)];
131  b[static_cast<size_t>(ip)] = b[static_cast<size_t>(i)];
132  if (ii >= 0)
133  for (j = ii; j<i; j++)
134  sum -= a[static_cast<size_t>(i)][static_cast<size_t>(j)] * b[static_cast<size_t>(j)];
135  else if (sum > 0)
136  ii = i;
137  b[static_cast<size_t>(i)] = sum;
138  }
139  for (i = n - 1; i >= 0; i--)
140  {
141  sum = b[static_cast<size_t>(i)];
142  for (j = i + 1; j<n; j++)
143  sum -= a[static_cast<size_t>(i)][static_cast<size_t>(j)] * b[static_cast<size_t>(j)];
144  b[static_cast<size_t>(i)] = sum / a[static_cast<size_t>(i)][static_cast<size_t>(i)];
145  }
146 }
147 
148 #define TINY 1.0e-20;
149 
150 int te::mnt::SplineInterpolationGrassMitasova::G_ludcmp(std::vector< std::vector<double> > &a, int n, std::vector<int> &indx, double &d)
151 {
152  int i, imax = 0, j, k;
153  double big, dum, sum, temp;
154  std::vector<double> vv;
155 
156  vv.resize(static_cast<size_t>(n));
157  d = 1.0;
158  for (i = 0; i<n; i++)
159  {
160  big = 0.0;
161  for (j = 0; j<n; j++)
162  if ((temp = fabs(a[static_cast<size_t>(i)][static_cast<size_t>(j)])) > big)
163  big = temp;
164  if (big == 0.0)
165  {
166  d = 0.0;
167  vv.clear();
168  return 0; /* Singular matrix */
169  }
170  vv[static_cast<size_t>(i)] = 1.0 / big;
171  }
172  for (j = 0; j<n; j++)
173  {
174  for (i = 0; i<j; i++)
175  {
176  sum = a[static_cast<size_t>(i)][static_cast<size_t>(j)];
177  for (k = 0; k<i; k++)
178  sum -= a[static_cast<size_t>(i)][static_cast<size_t>(k)] * a[static_cast<size_t>(k)][static_cast<size_t>(j)];
179  a[static_cast<size_t>(i)][static_cast<size_t>(j)] = sum;
180  }
181  big = 0.0;
182  for (i = j; i<n; i++)
183  {
184  sum = a[static_cast<size_t>(i)][static_cast<size_t>(j)];
185  for (k = 0; k<j; k++)
186  sum -= a[static_cast<size_t>(i)][static_cast<size_t>(k)] * a[static_cast<size_t>(k)][static_cast<size_t>(j)];
187  a[static_cast<size_t>(i)][static_cast<size_t>(j)] = sum;
188  if ((dum = vv[static_cast<size_t>(i)] * fabs(sum)) >= big)
189  {
190  big = dum;
191  imax = i;
192  }
193  }
194  if (j != imax)
195  {
196  for (k = 0; k<n; k++)
197  {
198  dum = a[static_cast<size_t>(imax)][static_cast<size_t>(k)];
199  a[static_cast<size_t>(imax)][static_cast<size_t>(k)] = a[static_cast<size_t>(j)][static_cast<size_t>(k)];
200  a[static_cast<size_t>(j)][static_cast<size_t>(k)] = dum;
201  }
202  d = -(d);
203  vv[static_cast<size_t>(imax)] = vv[static_cast<size_t>(j)];
204  }
205  indx[static_cast<size_t>(j)] = imax;
206  if (a[static_cast<size_t>(j)][static_cast<size_t>(j)] == 0.0)
207  a[static_cast<size_t>(j)][static_cast<size_t>(j)] = TINY;
208  if (j != n)
209  {
210  dum = 1.0 / (a[static_cast<size_t>(j)][static_cast<size_t>(j)]);
211  for (i = j + 1; i<n; i++)
212  a[static_cast<size_t>(i)][static_cast<size_t>(j)] *= dum;
213  }
214  }
215  vv.clear();
216  return 1;
217 }
218 
219 #undef TINY
220 
222  std::vector< std::vector <double> > &matrix, /* matrix */
223  std::vector<int> &indx, double fi, double rsm, int KMAX2
224  )
225  /*
226  Creates system of linear equations represented by matrix using given points
227  and interpolating function interp()
228  */
229 {
230  double xx, yy;
231  double r;
232  double d;
233  std::vector<double> A;
234  double RO, amaxa;
235  std::size_t i, i1, j, k, k1, k2, l, m;
236 
237  std::size_t n_points = m_pointsRegion.size();
238 
239  std::size_t n1 = n_points + 1;
240 
241  /*
242  C
243  C GENERATION OF MATRIX
244  C
245  C FIRST COLUMN
246  C
247  */
248  A.resize(static_cast<size_t>(KMAX2 + 2)*static_cast<size_t>(KMAX2 + 2) + 1);
249 
250  A[1] = 0;
251  for (k = 1; k <= n_points; k++)
252  {
253  i1 = k + 1;
254  A[i1] = 1.;
255  }
256  /*
257  C
258  C OTHER COLUMNS
259  C
260  */
261  RO = -rsm;
262 
263  for (k = 1; k <= n_points; k++)
264  {
265  k1 = k * n1 + 1;
266  k2 = k + 1;
267  i1 = k1 + k;
268  if (rsm >= 0.) /*indicates variable smoothing */
269  {
270  A[i1] = RO; /* constant smoothing*/
271  }
272 
273  for (l = k2; l <= n_points; l++)
274  {
275  te::gm::Point pp3dK = m_pointsRegion[k - 1];
276  te::gm::Point pp3dL = m_pointsRegion[l - 1];
277 
278  xx = pp3dK.getX() - pp3dL.getX();
279  yy = pp3dK.getY() - pp3dL.getY();
280 
281  {
282  r = xx*xx + yy*yy;
283  // rfsta2 = fstar2 * (xx * xx + yy * yy);
284  }
285 
286  i1 = k1 + l;
287  A[i1] = IL_crst(r, fi);
288  }
289  }
290  /*
291  C
292  C SYMMETRISATION
293  C
294  */
295  amaxa = 1.;
296  for (k = 1; k <= n1; k++)
297  {
298  k1 = (k - 1) * n1;
299  k2 = k + 1;
300  for (l = k2; l <= n1; l++)
301  {
302  m = (l - 1) * n1 + k;
303  A[m] = A[k1 + l];
304  amaxa = amax1(A[m], amaxa);
305  }
306  }
307  m = 0;
308  for (i = 0; i <= n_points; i++) {
309  for (j = 0; j <= n_points; j++) {
310  m++;
311  matrix[i][j] = A[m];
312  }
313  }
314 
315  if (G_ludcmp(matrix, static_cast<int>(n_points + 1), indx, d) <= 0)
316  { /* find the inverse of the matrix */
317  A.clear();
318  return -1;
319  }
320 
321  A.clear();
322  return 1;
323 }
324 
326 {
327  unsigned int nro_neighb;
328  double rx1, ry2;
329  unsigned int NCols;
330  unsigned int NLines;
331 
332  m_tolerance = m_resx / 4.;
333 
334  std::unique_ptr<te::rst::Raster> rst = Initialize(true, nro_neighb, rx1, ry2, NCols, NLines);
335 
336  double deltx = m_env.getUpperRightX() - m_env.getLowerLeftX();
337  double delty = m_env.getUpperRightY() - m_env.getLowerLeftY();
338 
339  //divide em x partes overlaping
340  int nPartsX = 50;
341  int nPartsY = 50;
342  double ew_region = deltx / static_cast<double>(nPartsX);
343  double ns_region = delty / static_cast<double>(nPartsY);
344 
345  double X1 = m_env.getLowerLeftX();
346  double Y1 = m_env.getLowerLeftY();
347 
348  double percentageDist = 0.5;
349 
350  size_t KMAX2 = 2 * 2 * static_cast<size_t>(m_minimoPontos);
351  double fi = m_tension;
352  double rsm = m_smooth;
353 
354  std::size_t NPOINT = m_dataset.size();
355  double dnorm = sqrt((deltx * delty * m_minimoPontos) / NPOINT);
356 
357  std::size_t nallPoints = m_dataset.size();
358  te::gm::Point pp03d = m_dataset[0].second;
359  double zmin = pp03d.getZ();
360  double zmax = pp03d.getZ();
361  for (std::size_t i = 1; i<nallPoints; i++)
362  {
363  te::gm::Point pp3d = m_dataset[i].second;
364  zmin = amin1(zmin, pp3d.getZ());
365  zmax = amax1(zmax, pp3d.getZ());
366  }
367 
368  int nsteps = static_cast<int>(nPartsY*nPartsX + 1);
369  te::common::TaskProgress task("Generating DTM...", te::common::TaskProgress::UNDEFINED, nsteps);
370 
371  for (int iy = 0; iy < nPartsY; iy++)
372  {
373  double begin_y = Y1 + (iy*ns_region);
374  double end_y = Y1 + ((iy + 1)*ns_region);
375 
376  double disty = (end_y - begin_y) * percentageDist;
377 
378  for (int jx = 0; jx < nPartsX; jx++)
379  {
380  if (!task.isActive())
381  return false;
382  task.pulse();
383 
384  //computes the beginning and end area
385  double begin_x = X1 + (jx*ew_region);
386  double end_x = X1 + ((jx + 1)*ew_region);
387 
388  double distx = (end_x - begin_x) * percentageDist;
389 
390  int nOverlaping = 1;
391  bool poucosPontos = false;
392  do
393  {
394  double overlapDistX = distx*nOverlaping;
395  double overlapDistY = disty*nOverlaping;
396  //adds control points and the overlaping area
397  setControlPoints(begin_x - overlapDistX, end_x + overlapDistX, begin_y - overlapDistY, end_y + overlapDistY, static_cast<int>(KMAX2), begin_x, begin_y, dnorm);
398 
399  poucosPontos = m_pointsRegion.size() < static_cast<size_t>(m_minimoPontos);
400  nOverlaping++;
401 
402  } while (poucosPontos);
403 
404  std::vector<int> indx;
405  std::vector< std::vector<double> > matrix;
406  std::vector<double> b;
407 
408  indx.resize(KMAX2 + 1);
409  for (int ii = 0; ii < static_cast<int>(KMAX2) + 1; ++ii)
410  {
411  std::vector<double> maux;
412  maux.resize(KMAX2 + 1);
413  matrix.push_back(maux);
414  }
415  b.resize(KMAX2 + 3);
416 
417  //create matrix
418  if (IL_matrix_create(matrix, indx, fi, rsm, static_cast<int>(KMAX2)) < 0)
419  {
420  b.clear();
421  indx.clear();
422  for (int ii = 0; ii < static_cast<int>(KMAX2) + 1; ++ii)
423  matrix[static_cast<size_t>(ii)].clear();
424  matrix.clear();
425  return false;
426  }
427 
428  std::size_t n_points = m_pointsRegion.size();
429  for (std::size_t jj = 0; jj < n_points; jj++)
430  {
431  te::gm::Point pp3d = m_pointsRegion.at(jj);
432  b[jj + 1] = pp3d.getZ();
433  }
434  b[0] = 0;
435 
436  G_lubksb(matrix, static_cast<int>(n_points) + 1, indx, b);
437  double errotot = 0.;
438  IL_check_at_points_2d(b, errotot, zmin, dnorm, fi);
439 
440  indx.clear();
441  for (unsigned ii = 0; ii < matrix.size(); ++ii)
442  matrix[ii].clear();
443  matrix.clear();
444 
445  //Computes the grid
446  if (!IL_grid_calc(begin_x, end_x, begin_y, end_y, zmin, zmax, static_cast<int>(KMAX2), b, fi, dnorm))
447  {
448  b.clear();
449  return false;
450  }
451  b.clear();
452  }
453  }
454 
455  rst.release();
456  return true;
457 }
458 
460  std::vector<double>& b, /* solution of linear equations */
461  double &ertot, /* total error */
462  double zmin, /* min z-value */
463  double /*dnorm*/, double fi
464  )
465 
466  /*
467  * Checks if interpolating function interp() evaluates correct z-values at
468  * given points. If smoothing is used calculate the maximum error caused
469  * by smoothing.
470  */
471 
472 {
473  size_t n_points = m_pointsRegion.size();/* number of points */
474  double h, xx, yy, r2, hz, zz, err, r;
475  size_t mm, m;
476 
477  for (mm = 1; mm <= n_points; mm++)
478  {
479  te::gm::Point pp3dMM = m_pointsRegion[mm - 1];
480  h = b[0];
481  for (m = 1; m <= n_points; m++)
482  {
483  te::gm::Point pp3dM = m_pointsRegion[m - 1];
484  xx = pp3dMM.getX() - pp3dM.getX();
485  yy = pp3dMM.getY() - pp3dM.getY();
486 
487  r2 = yy * yy + xx * xx;
488  if (r2 != 0.)
489  {
490  r = r2;
491  h = h + b[m] * IL_crst(r, fi);
492  }
493  }
494 
495  hz = h + zmin;
496  zz = pp3dMM.getZ() + zmin;
497  err = hz - zz;
498 
499  (ertot) += err * err;
500  }
501 
502  return 1;
503 }
504 
505 bool te::mnt::SplineInterpolationGrassMitasova::IL_grid_calc(double xMin, double xMax, double yMin, double yMax, double /*zMin*/, double /*zMax*/, int KMAX2, std::vector<double>& b, double fi, double dnorm)
506 {
507  double x_or = xMin;
508 
509  double x1 = m_env.getLowerLeftX();
510  double y2 = m_env.getUpperRightY();
511 
512  double ns_res = m_resy;
513  double ew_res = m_resx;
514 
515  double deltx = xMax - xMin;
516  double delty = yMax - yMin;
517 
518  int n_rows = static_cast<int>(delty / ns_res);
519  int n_cols = static_cast<int>(deltx / ew_res);
520 
521  size_t n_points = m_pointsRegion.size();
522 
523  int ngstc = static_cast<int>((x_or - x1) / ew_res + 0.5);
524  int nszc = ngstc + n_cols;
525  int ngstr = static_cast<int>((y2 - yMax) / ns_res + 0.5);
526  int nszr = ngstr + n_rows;
527 
528  double stepix = ew_res / dnorm;
529  double stepiy = ns_res / dnorm;
530 
531  std::vector<double> w2;
532  std::vector<double> w;
533 
534  w.resize(static_cast<size_t>(KMAX2) + 9);
535  w2.resize(static_cast<size_t>(KMAX2) + 9);
536 
537  int contadory = 0;
538 
539  for (int k = ngstr; k <= nszr; k++)
540  {
541  double yg = (k - ngstr) * stepiy + stepiy / 2.; // fixed by J.H. in July 01
542  for (size_t m = 1; m <= n_points; m++)
543  {
544  te::gm::Point pp3d = m_pointsRegion[m - 1];
545  double wm = yg - pp3d.getY();
546  w[m] = wm;
547  w2[m] = wm * wm;
548  }
549 
550  for (int l = ngstc; l <= nszc; l++)
551  {
552  double xg = (l - ngstc) * stepix + stepix / 2.; //fixed by J.H. in July 01
553 
554  // compute everything for area which is * not masked out
555  double h = b[0];
556  for (size_t m = 1; m <= n_points; m++)
557  {
558  te::gm::Point pp3d = m_pointsRegion[m - 1];
559  double xx = xg - pp3d.getX();
560  double xx2 = xx * xx;
561  double r2 = xx2 + w2[m];
562  double r = r2;
563 
564  h = h + b[m] * IL_crst(r, fi);
565  }
566 
567  double zz = h;
568  int row = nszr - contadory;
569  if (row >= 0 && row < static_cast<int>(m_rst->getNumberOfRows()) &&
570  l >= 0 && l < static_cast<int>(m_rst->getNumberOfColumns()))
571  {
572  if (zz != m_nodatavalue)
573  {
574  m_max = (zz > m_max) ? zz : m_max;
575  m_min = (zz < m_min) ? zz : m_min;
576  }
577  m_rst->setValue(static_cast<unsigned int>(l), static_cast<unsigned int>(row), zz);
578  }
579  }
580  contadory++;
581  }
582 
583  w.clear();
584  w2.clear();
585 
586  return true;
587 }
588 
double m_nodatavalue
no data value
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.
int G_ludcmp(std::vector< std::vector< double > > &, int, std::vector< int > &, double &)
int IL_check_at_points_2d(std::vector< double > &b, double &ertot, double zmin, double dnorm, double fi)
#define TINY
void setControlPoints(double xMin, double xMax, double yMin, double yMax, int nMax, double xOrigem, double yOrigem, double dnorm)
std::unique_ptr< te::rst::Raster > Initialize(bool spline, unsigned int &nro_neighb, double &rx1, double &ry2, unsigned int &outputWidth, unsigned int &outputHeight)
bool IL_grid_calc(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax, int KMAX2, std::vector< double > &b, double fi, double dnorm)
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
const double & getUpperRightX() const
It returns a constant refernce to the x coordinate of the upper right corner.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
double amax1(double arg1, double arg2)
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
double amin1(double arg1, double arg2)
double m_max
Output DTM limits.
const double & getUpperRightY() const
It returns a constant refernce to the x coordinate of the upper right corner.
void G_lubksb(std::vector< std::vector< double > > &a, int n, std::vector< int > &indx, std::vector< double > &b)
bool isActive() const
Verify if the task is active.
Utility functions for MNT support.
int b
Definition: TsRtree.cpp:32
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
std::vector< te::gm::Point > m_pointsRegion
Control Points of grid region.
unsigned int getNumberOfRows() const
Returns the raster number of rows.
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
virtual ~SplineInterpolationGrassMitasova()
Destructor.
int IL_matrix_create(std::vector< std::vector< double > > &matrix, std::vector< int > &indx, double fi, double rsm, int KMAX2)
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
te::gm::Envelope m_env
Attribute used to restrict the area to generate the raster.
const double & getZ() const
It returns the Point z-coordinate value, if it has one or DoubleNotANumber otherwise.
Definition: Point.h:166
std::vector< std::pair< te::gm::Coord2D, te::gm::Point > > m_dataset
void setX(const double &x)
It sets the Point x-coordinate value.
Definition: Point.h:145
This file contains a class to calculate retangular grid from Samples using Spline Grass Mitasova Inte...
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
SplineInterpolationGrassMitasova(int minPoints=mitasovaMINPOINTS, double tension=mitasovaTENSION, double smooth=mitasovaSMOOTH)
Contructors.
void setY(const double &y)
It sets the Point y-coordinate value.
Definition: Point.h:159
te::rst::Raster * m_rst
double m_resy
grid resolution in X and Y
const double & getX() const
It returns the Point x-coordinate value.
Definition: Point.h:138
void setZ(const double &z)
It sets the Point z-coordinate value.
Definition: Point.h:173
double m_tolerance
tolerance used to simplify lines