16 #ifndef FACT_Interpolator2D 17 #define FACT_Interpolator2D 32 vec(
double _x=0,
double _y=0) : x(_x), y(_y) { }
36 double dist(
const vec &v)
const {
return hypot(x-v.
x, y-v.
y); }
48 point(
unsigned int _i=0,
double _x=0,
double _y=0) :
vec(_x, _y), i(_i) { }
58 return ((b-a)^(p1-a))*((b-a)^(p2-a)) > 0;
63 return sameSide(v, p[0], p[1], p[2]) && sameSide(v, p[1], p[0], p[2]) && sameSide(v, p[2], p[0], p[1]);
92 circles.reserve(2*inputGrid.size());
95 for (
auto it0=inputGrid.cbegin(); it0<inputGrid.cend(); it0++)
97 for (
auto it1=inputGrid.cbegin(); it1<it0; it1++)
99 for (
auto it2=inputGrid.cbegin(); it2<it1; it2++)
104 const vec v1 = *it1 - *it0;
105 const vec v2 = *it2 - *it1;
112 const vec p1 = (*it0 + *it1)/2;
113 const vec p2 = (*it1 + *it2)/2;
118 const double denom = n1^n2;
122 const vec x(n1.
x, n2.x);
123 const vec y(n1.
y, n2.y);
125 const vec w(p1^(p1+n1), p2^(p2+n2));
136 auto it3 = inputGrid.cbegin();
137 for (; it3<inputGrid.cend(); it3++)
139 if (it3==it0 || it3==it1 || it3==it2)
147 if (it3!=inputGrid.cend())
156 circles.push_back(c);
174 weights.reserve(outputGrid.size());
177 for (
auto ip=outputGrid.cbegin(); ip<outputGrid.cend(); ip++)
179 double mindd = DBL_MAX;
181 auto mint = circles.cend();
182 auto minc = circles.cend();
183 auto mind = circles.cend();
185 for (
auto ic=circles.cbegin(); ic<circles.cend(); ic++)
188 if (ic->isInsideTriangle(*ip))
190 if (mint==circles.cend() || ic->r<mint->r)
195 if (mint!=circles.cend())
199 const double dd = ic->dist(*ip);
202 if (minc==circles.cend() || ic->r<minc->r)
207 if (minc!=circles.cend())
219 const auto it = mint==circles.cend() ? (minc==circles.cend() ? mind : minc) : mint;
220 if (it==circles.cend())
224 const vec &p1 = it->p[0];
225 const vec &p2 = it->p[1];
226 const vec &p3 = it->p[2];
228 const double dy23 = p2.
y - p3.
y;
229 const double dy31 = p3.
y - p1.
y;
230 const double dy12 = p1.
y - p2.
y;
232 const double dx32 = p3.
x - p2.
x;
233 const double dx13 = p1.
x - p3.
x;
234 const double dx21 = p2.
x - p1.
x;
236 const double dxy23 = p2^p3;
237 const double dxy31 = p3^p1;
238 const double dxy12 = p1^p2;
240 const double det = dxy12 + dxy23 + dxy31;
242 const double w1 = (dy23*ip->x + dx32*ip->y + dxy23)/det;
243 const double w2 = (dy31*ip->x + dx13*ip->y + dxy31)/det;
244 const double w3 = (dy12*ip->x + dx21*ip->y + dxy12)/det;
256 weights.push_back(w);
310 static std::vector<Interpolator2D::vec>
ReadGrid(
const std::string &filename)
312 std::vector<Interpolator2D::vec> grid;
314 std::ifstream fin(filename);
316 return std::vector<Interpolator2D::vec>();
326 grid.emplace_back(x, y);
329 return fin.bad() ? std::vector<Interpolator2D::vec>() : grid;
354 inputGrid.reserve(n);
355 for (
unsigned int i=0;
i<n;
i++)
356 inputGrid.emplace_back(
i, x[
i], y[i]);
368 inputGrid.reserve(v.size());
369 for (
unsigned int i=0;
i<v.size();
i++)
370 inputGrid.emplace_back(
i, v[
i]);
392 const auto grid =
ReadGrid(filename);
421 if (inputGrid.empty() && n==0)
427 outputGrid.reserve(n);
428 for (std::size_t
i=0;
i<n;
i++)
429 outputGrid.emplace_back(
i, x[
i], y[i]);
452 if (inputGrid.empty())
458 outputGrid.reserve(v.size());
459 for (std::size_t
i=0;
i<v.size();
i++)
460 outputGrid.emplace_back(
i, v[
i]);
467 const auto grid =
ReadGrid(filename);
488 std::vector<double>
Interpolate(
const std::vector<double> &z)
const 490 if (z.size()!=inputGrid.size())
491 return std::vector<double>();
493 std::vector<double> rc;
494 rc.reserve(z.size());
496 for (
auto it=weights.cbegin(); it<weights.cend(); it++)
497 rc.push_back(z[it->c.p[0].i] * it->w[0] + z[it->c.p[1].i] * it->w[1] + z[it->c.p[2].i] * it->w[2]);
std::vector< double > Interpolate(const std::vector< double > &z) const
bool SetOutputGrid(std::size_t n, double *x, double *y)
bool isInsideTriangle(const vec &v) const
bool ReadInputGrid(const std::string &filename)
void CalculateGrid()
the weights used for the interpolation
Interpolator2D()
Default constructor. Does nothing.
bool ReadOutputGrid(const std::string &filename)
static bool sameSide(const vec &p1, const vec &p2, const vec &a, const vec &b)
const std::vector< Interpolator2D::point > getInputGrid() const
const std::vector< Interpolator2D::point > getOutputGrid() const
void SetInputGrid(unsigned int n, double *x, double *y)
vec operator+(const vec &v) const
Extra- and interpolate in 2D.
double dist(const vec &v) const
vec operator/(double b) const
std::vector< point > outputGrid
positions of the data points (e.g. sensors)
point(unsigned int _i, const vec &_v)
Interpolator2D(int n, double *x, double *y)
void SetInputGrid(const std::vector< Interpolator2D::vec > &v)
vec operator-(const vec &v) const
std::vector< point > inputGrid
std::vector< circle > circles
positions at which inter-/extrapolated values should be provided
point(unsigned int _i=0, double _x=0, double _y=0)
std::vector< weight > weights
the calculated circles/triangles
const std::vector< Interpolator2D::weight > getWeights() const
Interpolator2D(const std::vector< Interpolator2D::vec > &v)
bool SetOutputGrid(const std::vector< Interpolator2D::vec > &v)
bool isInsideCircle(const vec &v) const
static std::vector< Interpolator2D::vec > ReadGrid(const std::string &filename)
vec(double _x=0, double _y=0)
double operator^(const vec &v) const