OGS
Raster.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "Raster.h"
5
6#include <fstream>
7
8// BaseLib
9#include "BaseLib/FileTools.h"
10#include "BaseLib/StringTools.h"
11#include "Triangle.h"
12
13namespace GeoLib
14{
15void Raster::refineRaster(std::size_t scaling)
16{
17 std::vector<double> new_raster_data(_header.n_rows * _header.n_cols *
18 scaling * scaling);
19
20 for (std::size_t row(0); row < _header.n_rows; row++)
21 {
22 for (std::size_t col(0); col < _header.n_cols; col++)
23 {
24 const std::size_t idx(row * _header.n_cols + col);
25 for (std::size_t new_row(row * scaling);
26 new_row < (row + 1) * scaling;
27 new_row++)
28 {
29 const std::size_t idx0(new_row * _header.n_cols * scaling);
30 for (std::size_t new_col(col * scaling);
31 new_col < (col + 1) * scaling;
32 new_col++)
33 {
34 new_raster_data[idx0 + new_col] = _raster_data[idx];
35 }
36 }
37 }
38 }
39
40 std::swap(_raster_data, new_raster_data);
41 _header.cell_size /= scaling;
42 _header.n_cols *= scaling;
43 _header.n_rows *= scaling;
44}
45
47{
48 if (pnt[0] >= _header.origin[0] &&
49 pnt[0] < (_header.origin[0] + (_header.cell_size * _header.n_cols)) &&
50 pnt[1] >= _header.origin[1] &&
51 pnt[1] < (_header.origin[1] + (_header.cell_size * _header.n_rows)))
52 {
53 auto cell_x = static_cast<int>(
54 std::floor((pnt[0] - _header.origin[0]) / _header.cell_size));
55 auto cell_y = static_cast<int>(
56 std::floor((pnt[1] - _header.origin[1]) / _header.cell_size));
57
58 // use raster boundary values if node is outside raster due to rounding
59 // errors or floating point arithmetic
60 cell_x = (cell_x < 0) ? 0
61 : ((cell_x > static_cast<int>(_header.n_cols))
62 ? static_cast<int>(_header.n_cols - 1)
63 : cell_x);
64 cell_y = (cell_y < 0) ? 0
65 : ((cell_y > static_cast<int>(_header.n_rows))
66 ? static_cast<int>(_header.n_rows - 1)
67 : cell_y);
68
69 const std::size_t index = cell_y * _header.n_cols + cell_x;
70 return _raster_data[index];
71 }
72 return _header.no_data;
73}
74
76{
77 // position in raster
78 double const xPos((pnt[0] - _header.origin[0]) / _header.cell_size);
79 double const yPos((pnt[1] - _header.origin[1]) / _header.cell_size);
80 // raster cell index
81 double const xIdx(std::floor(xPos)); // carry out computions in double
82 double const yIdx(std::floor(yPos)); // so not to over- or underflow.
83
84 // weights for bilinear interpolation
85 double const xShift = std::abs((xPos - xIdx) - 0.5);
86 double const yShift = std::abs((yPos - yIdx) - 0.5);
87 Eigen::Vector4d weight = {(1 - xShift) * (1 - yShift),
88 xShift * (1 - yShift), xShift * yShift,
89 (1 - xShift) * yShift};
90
91 // neighbors to include in interpolation
92 int const xShiftIdx = (xPos - xIdx >= 0.5) ? 1 : -1;
93 int const yShiftIdx = (yPos - yIdx >= 0.5) ? 1 : -1;
94 std::array<int, 4> const x_nb = {{0, xShiftIdx, xShiftIdx, 0}};
95 std::array<int, 4> const y_nb = {{0, 0, yShiftIdx, yShiftIdx}};
96
97 // get pixel values
98 Eigen::Vector4d pix_val{};
99 unsigned no_data_count(0);
100 for (unsigned j = 0; j < 4; ++j)
101 {
102 // check if neighbour pixel is still on the raster, otherwise substitute
103 // a no data value. This also allows the cast to unsigned type.
104 if ((xIdx + x_nb[j]) < 0 || (yIdx + y_nb[j]) < 0 ||
105 (xIdx + x_nb[j]) > (_header.n_cols - 1) ||
106 (yIdx + y_nb[j]) > (_header.n_rows - 1))
107 {
108 pix_val[j] = _header.no_data;
109 }
110 else
111 {
112 pix_val[j] = _raster_data[static_cast<std::size_t>(yIdx + y_nb[j]) *
113 _header.n_cols +
114 static_cast<std::size_t>(xIdx + x_nb[j])];
115 }
116
117 // remove no data values
118 if (std::abs(pix_val[j] - _header.no_data) <
119 std::numeric_limits<double>::epsilon())
120 {
121 weight[j] = 0;
122 no_data_count++;
123 }
124 }
125
126 // adjust weights if necessary
127 if (no_data_count > 0)
128 {
129 if (no_data_count == 4 || weight.sum() == 0)
130 { // if there is absolutely no data just use the default value
131 return _header.no_data;
132 }
133
134 weight /= weight.sum();
135 }
136
137 // new value
138 return weight.dot(pix_val);
139}
140
142{
143 return !(
144 (pnt[0] < _header.origin[0]) ||
145 (pnt[0] > _header.origin[0] + (_header.n_cols * _header.cell_size)) ||
146 (pnt[1] < _header.origin[1]) ||
147 (pnt[1] > _header.origin[1] + (_header.n_rows * _header.cell_size)));
148}
149
150} // end namespace GeoLib
GeoLib::RasterHeader _header
Definition Raster.h:140
std::vector< double > _raster_data
Definition Raster.h:141
void refineRaster(std::size_t scaling)
Definition Raster.cpp:15
double getValueAtPoint(const MathLib::Point3d &pnt) const
Definition Raster.cpp:46
bool isPntOnRaster(MathLib::Point3d const &pnt) const
Definition Raster.cpp:141
double interpolateValueAtPoint(const MathLib::Point3d &pnt) const
Definition Raster.cpp:75