#pragma once #include "basedata.h" #include "comdefs.h" using michlib::real; template class LinearInterpolator: public D { public: LinearInterpolator(D&& d): D(std::move(d)) {} real operator()(const struct Point2D& in) const { const auto gp = D::GridPos(in.x, in.y); if(!gp.Valid()) return NAN; if(gp.x == 0.0 && gp.y == 0.0) return D::V(gp.ix, gp.iy); real v00; real v10; real v01; real v11; bool isfill = false; size_t fx, fy; // Count fills for(size_t ix = 0; ix <= 1; ix++) for(size_t iy = 0; iy <= 1; iy++) { if(isfill && D::IsFill(gp.ix + ix, gp.iy + iy)) return NAN; if(D::IsFill(gp.ix + ix, gp.iy + iy)) { fx = ix; fy = iy; isfill = true; } } v00 = D::V(gp.ix, gp.iy); v10 = D::V(gp.ix + 1, gp.iy); v01 = D::V(gp.ix, gp.iy + 1); v11 = D::V(gp.ix + 1, gp.iy + 1); if(isfill && fx == 0 && fy == 0) v00 = (v10 + v01 + v11) / 3.0; if(isfill && fx == 1 && fy == 0) v10 = (v00 + v01 + v11) / 3.0; if(isfill && fx == 0 && fy == 1) v01 = (v10 + v00 + v11) / 3.0; if(isfill && fx == 1 && fy == 1) v11 = (v10 + v01 + v00) / 3.0; return v00 + gp.y * (v01 - v00) + gp.x * ((v10 - v00) + gp.y * (v00 - v01 + v11 - v10)); }; };