You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
740 lines
23 KiB
740 lines
23 KiB
#pragma once |
|
#include "comdefs.h" |
|
#include "udunitscpp.h" |
|
#include <ranges> |
|
#include <variant> |
|
|
|
using michlib::real; |
|
|
|
class ProjectionInternals |
|
{ |
|
public: |
|
enum class Type |
|
{ |
|
IRREGULAR, // Набор точек |
|
IRREGULARXY, // Прямоугольная сетка с неравномерным шагом |
|
EQC // Прямоугольная сетка с равномерным шагом |
|
}; |
|
|
|
enum class Metric |
|
{ |
|
SPHERIC, |
|
PLANE |
|
}; |
|
|
|
template<Type type> class ProjData; |
|
|
|
private: |
|
template<class C> struct PrTypeHold; |
|
|
|
template<Type t> struct PrTypeHold<ProjData<t>> |
|
{ |
|
static constexpr Type type = t; |
|
}; |
|
|
|
public: |
|
class Sizes |
|
{ |
|
size_t nx, ny; |
|
|
|
Sizes() = delete; |
|
|
|
public: |
|
Sizes(size_t nx_, size_t ny_): nx(nx_), ny(ny_) {} |
|
|
|
size_t Nx() const { return nx; } |
|
size_t Ny() const { return ny; } |
|
size_t N() const { return nx * ny; } |
|
}; |
|
|
|
template<Type type> static constexpr Metric metric = Metric::SPHERIC; |
|
|
|
// Флаги |
|
// orthogonal - ортогональная сетка |
|
// rectangular - прямоугольная сетка, широта и долгота зависят от одного индекса |
|
// geostep - шаги сетки по широте и долготе фиксированы |
|
// analytic - существует непрерывное преобразование сеточных координат в широту и долготу и наоборот |
|
|
|
template<Type type> static constexpr bool orthogonal = true; |
|
template<Type type> |
|
static constexpr bool rectangular = requires(ProjData<type> pr, size_t i) { |
|
{ pr.Lon(i) } -> std::same_as<real>; |
|
{ pr.Lat(i) } -> std::same_as<real>; |
|
}; |
|
template<Type type> |
|
static constexpr bool geostep = requires(ProjData<type> pr) { |
|
{ pr.LonStep() } -> std::same_as<real>; |
|
{ pr.LatStep() } -> std::same_as<real>; |
|
}; |
|
template<Type type> |
|
static constexpr bool analytic = requires(ProjData<type> pr, real x, real y, real lon, real lat) { |
|
{ pr.LonR(x, y) } -> std::same_as<real>; |
|
{ pr.LatR(x, y) } -> std::same_as<real>; |
|
{ pr.X(lon, lat) } -> std::same_as<real>; |
|
{ pr.Y(lon, lat) } -> std::same_as<real>; |
|
}; |
|
|
|
template<Type type, class... Args> |
|
static constexpr bool validargs = requires(Args... args) { |
|
{ ProjData<type>(args...) }; |
|
}; |
|
|
|
template<class C> static constexpr Type ProjType = PrTypeHold<C>::type; |
|
|
|
using Projection = std::variant<ProjData<Type::IRREGULAR>, ProjData<Type::IRREGULARXY>, ProjData<Type::EQC>>; |
|
}; |
|
|
|
template<> constexpr bool ProjectionInternals::orthogonal<ProjectionInternals::Type::IRREGULAR> = false; |
|
|
|
template<> class ProjectionInternals::ProjData<ProjectionInternals::Type::IRREGULAR>: public ProjectionInternals::Sizes |
|
{ |
|
std::vector<real> datalon, datalat; |
|
|
|
ProjData() = delete; |
|
|
|
public: |
|
ProjData(size_t nx, size_t ny, const std::vector<real>& lons, const std::vector<real>& lats): Sizes{nx, ny}, datalon(lons), datalat(lats) {} |
|
ProjData(size_t nx, size_t ny, std::vector<real>&& lons, std::vector<real>&& lats): Sizes{nx, ny}, datalon(std::move(lons)), datalat(std::move(lats)) {} |
|
|
|
real Lon(size_t ix, size_t iy) const { return datalon[Nx() * iy + ix]; } |
|
real Lat(size_t ix, size_t iy) const { return datalat[Nx() * iy + ix]; } |
|
}; |
|
|
|
template<> class ProjectionInternals::ProjData<ProjectionInternals::Type::IRREGULARXY>: public ProjectionInternals::Sizes |
|
{ |
|
std::vector<real> datalon, datalat; |
|
|
|
ProjData() = delete; |
|
|
|
public: |
|
ProjData(const std::vector<real>& lons, const std::vector<real>& lats): Sizes{lons.size(), lats.size()}, datalon(lons), datalat(lats) {} |
|
ProjData(std::vector<real>&& lons, std::vector<real>&& lats): Sizes{lons.size(), lats.size()}, datalon(std::move(lons)), datalat(std::move(lats)) {} |
|
|
|
real Lon(size_t ix) const { return datalon[ix]; } |
|
real Lat(size_t iy) const { return datalat[iy]; } |
|
}; |
|
|
|
template<> class ProjectionInternals::ProjData<ProjectionInternals::Type::EQC>: public ProjectionInternals::Sizes |
|
{ |
|
real lon0, lat0, lonstep, latstep; |
|
|
|
ProjData() = delete; |
|
|
|
public: |
|
ProjData(size_t nx, size_t ny, real lon0_, real lat0_, real lonstep_, real latstep_): Sizes{nx, ny}, lon0(lon0_), lat0(lat0_), lonstep(lonstep_), latstep(latstep_) {} |
|
ProjData(std::ranges::sized_range auto&& lons, std::ranges::sized_range auto&& lats): |
|
Sizes{lons.size(), lats.size()}, |
|
lon0(lons[0]), |
|
lat0(lats[0]), |
|
lonstep((lons.back() - lons.front()) / (lons.size() - 1)), |
|
latstep((lats.back() - lats.front()) / (lats.size() - 1)) |
|
{ |
|
} |
|
|
|
real Lon(size_t ix) const { return lon0 + ix * lonstep; } |
|
real Lat(size_t iy) const { return lat0 + iy * latstep; } |
|
|
|
real LonStep() const { return lonstep; } |
|
real LatStep() const { return latstep; } |
|
|
|
real LonR(real x, [[maybe_unused]] real y) const { return lon0 + x * lonstep; } |
|
real LatR([[maybe_unused]] real x, real y) const { return lat0 + y * latstep; } |
|
|
|
real X(real lon, [[maybe_unused]] real lat) const { return (lon - lon0) / lonstep; } |
|
real Y([[maybe_unused]] real lon, real lat) const { return (lat - lat0) / latstep; } |
|
}; |
|
|
|
class Projection: public ProjectionInternals, public ProjectionInternals::Projection |
|
{ |
|
Projection() = delete; |
|
Projection(const Projection&) = delete; |
|
|
|
template<Type t> Projection(ProjData<t>&& pr): ProjectionInternals(), ProjectionInternals::Projection(std::move(pr)) {} |
|
|
|
public: |
|
Projection(Projection&&) = default; |
|
|
|
template<Type t, class... Args> static Projection Create(Args&&... args) |
|
{ |
|
if constexpr(t == Type::IRREGULAR) |
|
{ |
|
if constexpr(validargs<Type::IRREGULAR, Args...>) |
|
return Projection(ProjData<Type::IRREGULAR>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Projection::Create"); |
|
} |
|
else if constexpr(t == Type::IRREGULARXY) |
|
{ |
|
if constexpr(validargs<Type::IRREGULARXY, Args...>) |
|
return Projection(ProjData<Type::IRREGULARXY>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Projection::Create"); |
|
} |
|
else if constexpr(t == Type::EQC) |
|
{ |
|
if constexpr(validargs<Type::EQC, Args...>) |
|
return Projection(ProjData<Type::EQC>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Projection::Create"); |
|
} |
|
else |
|
static_assert(false, "Incorrect call of Projection::Create"); |
|
}; |
|
|
|
// From Sizes |
|
size_t Nx() const |
|
{ |
|
return std::visit([](const auto& arg) { return arg.Nx(); }, *this); |
|
} |
|
size_t Ny() const |
|
{ |
|
return std::visit([](const auto& arg) { return arg.Ny(); }, *this); |
|
} |
|
size_t N() const |
|
{ |
|
return std::visit([](const auto& arg) { return arg.N(); }, *this); |
|
} |
|
|
|
// Lon and Lat (ix,iy) |
|
real Lon(size_t ix, size_t iy) const |
|
{ |
|
return std::visit( |
|
[ix = ix, iy = iy](const auto& arg) |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool rect = Projection::rectangular<ProjType<T>>; |
|
if constexpr(rect) |
|
return arg.Lon(ix); |
|
else |
|
return arg.Lon(ix, iy); |
|
}, |
|
*this); |
|
} |
|
real Lat(size_t ix, size_t iy) const |
|
{ |
|
return std::visit( |
|
[ix = ix, iy = iy](const auto& arg) |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool rect = Projection::rectangular<ProjType<T>>; |
|
if constexpr(rect) |
|
return arg.Lat(iy); |
|
else |
|
return arg.Lat(ix, iy); |
|
}, |
|
*this); |
|
} |
|
|
|
// Lon and Lat (i) |
|
real Lon(size_t ix) const |
|
{ |
|
return std::visit( |
|
[ix = ix](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool rect = Projection::rectangular<ProjType<T>>; |
|
if constexpr(rect) |
|
return arg.Lon(ix); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
real Lat(size_t iy) const |
|
{ |
|
return std::visit( |
|
[iy = iy](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool rect = Projection::rectangular<ProjType<T>>; |
|
if constexpr(rect) |
|
return arg.Lat(iy); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
|
|
// LonR, LatR |
|
real LonR(real x, real y) const |
|
{ |
|
return std::visit( |
|
[x = x, y = y](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool analytic = Projection::analytic<ProjType<T>>; |
|
if constexpr(analytic) |
|
return arg.LonR(x, y); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
real LatR(real x, real y) const |
|
{ |
|
return std::visit( |
|
[x = x, y = y](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool analytic = Projection::analytic<ProjType<T>>; |
|
if constexpr(analytic) |
|
return arg.LatR(x, y); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
|
|
// X, Y |
|
real X(real lon, real lat) const |
|
{ |
|
return std::visit( |
|
[lon = lon, lat = lat](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool analytic = Projection::analytic<ProjType<T>>; |
|
if constexpr(analytic) |
|
return arg.X(lon, lat); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
real Y(real lon, real lat) const |
|
{ |
|
return std::visit( |
|
[lon = lon, lat = lat](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool analytic = Projection::analytic<ProjType<T>>; |
|
if constexpr(analytic) |
|
return arg.Y(lon, lat); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
|
|
// Type |
|
Type Type() const |
|
{ |
|
return std::visit([](const auto& arg) { return ProjType<std::decay_t<decltype(arg)>>; }, *this); |
|
} |
|
|
|
// Flags |
|
bool IsOrthogonal() const |
|
{ |
|
return std::visit([](const auto& arg) { return Projection::orthogonal<ProjType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
bool IsRectangular() const |
|
{ |
|
return std::visit([](const auto& arg) { return Projection::rectangular<ProjType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
bool IsAnalytic() const |
|
{ |
|
return std::visit([](const auto& arg) { return Projection::analytic<ProjType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
|
|
// Metric |
|
auto Metric() const |
|
{ |
|
return std::visit([](const auto& arg) { return Projection::metric<ProjType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
}; |
|
|
|
class VerticalInternals |
|
{ |
|
public: |
|
enum class Type |
|
{ |
|
LAYERS, // Глубина слоя зависит от координат |
|
HORIZONTS, // Глубина слоя не зависит от координат |
|
GRID, // Равномерная сетка глубин |
|
FIXED, // Один уровень фиксированой глубины |
|
UNDEFINED // Глубина бессмысленна, например, для ssh или толщины перемешанного слоя |
|
}; |
|
|
|
template<Type type> class VertData; |
|
|
|
private: |
|
template<class C> struct VTypeHold; |
|
|
|
template<Type t> struct VTypeHold<VertData<t>> |
|
{ |
|
static constexpr Type type = t; |
|
}; |
|
|
|
public: |
|
class Sizes |
|
{ |
|
size_t nz; |
|
|
|
Sizes() = delete; |
|
|
|
public: |
|
Sizes(size_t nz_): nz(nz_) {} |
|
|
|
size_t Nz() const { return nz; } |
|
}; |
|
|
|
// Флаги |
|
// up2down - слои заглубляются с увеличением номера |
|
// isotropic - глубина слоя не зависит от горизонтальных координат |
|
// zstep - постоянный шаг между слоями |
|
// valid - глубина определена |
|
|
|
template<Type type> static constexpr bool up2down = true; |
|
template<Type type> |
|
static constexpr bool isotropic = requires(VertData<type> prz, size_t i) { |
|
{ prz.Depth(i) } -> std::same_as<real>; |
|
}; |
|
template<Type type> |
|
static constexpr bool zstep = requires(VertData<type> prz) { |
|
{ prz.ZStep() } -> std::same_as<real>; |
|
}; |
|
template<Type type> |
|
static constexpr bool valid = requires(VertData<type> prz, size_t ix, size_t iy, size_t iz) { |
|
{ prz.Depth(ix, iy, iz) } -> std::same_as<real>; |
|
} || isotropic<type>; |
|
|
|
template<Type type, class... Args> |
|
static constexpr bool validargs = requires(Args... args) { |
|
{ VertData<type>(args...) }; |
|
}; |
|
|
|
template<class C> static constexpr Type VertType = VTypeHold<C>::type; |
|
|
|
using Vertical = std::variant<VertData<Type::LAYERS>, VertData<Type::HORIZONTS>, VertData<Type::GRID>, VertData<Type::FIXED>, VertData<Type::UNDEFINED>>; |
|
}; |
|
|
|
template<> class VerticalInternals::VertData<VerticalInternals::Type::LAYERS>: public VerticalInternals::Sizes |
|
{ |
|
size_t nx, ny; |
|
std::vector<real> zdata; |
|
|
|
VertData() = delete; |
|
|
|
public: |
|
VertData(size_t nx_, size_t ny_, size_t nz_, const std::vector<real>& zdata_): Sizes(nz_), nx(nx_), ny(ny_), zdata(zdata_) {} |
|
VertData(size_t nx_, size_t ny_, size_t nz_, std::vector<real>&& zdata_): Sizes(nz_), nx(nx_), ny(ny_), zdata(std::move(zdata_)) {} |
|
|
|
real Depth(size_t ix, size_t iy, size_t iz) const { return zdata[nx * ny * iz + nx * iy + ix]; } |
|
}; |
|
|
|
template<> class VerticalInternals::VertData<VerticalInternals::Type::HORIZONTS>: public VerticalInternals::Sizes |
|
{ |
|
std::vector<real> zdata; |
|
|
|
VertData() = delete; |
|
|
|
public: |
|
VertData(const std::vector<real>& zdata_): Sizes(zdata_.size()), zdata(zdata_) {} |
|
VertData(std::vector<real>&& zdata_): Sizes(zdata_.size()), zdata(std::move(zdata_)) {} |
|
|
|
real Depth(size_t iz) const { return zdata[iz]; } |
|
}; |
|
|
|
template<> class VerticalInternals::VertData<VerticalInternals::Type::GRID>: public VerticalInternals::Sizes |
|
{ |
|
real z0, zstep; |
|
|
|
VertData() = delete; |
|
|
|
public: |
|
VertData(real z0_, real zstep_, size_t nz_): Sizes(nz_), z0(z0_), zstep(zstep_) {} |
|
VertData(real zstep_, size_t nz_): VertData(0.0, zstep_, nz_) {} |
|
|
|
real Depth(size_t iz) const { return z0 + iz * zstep; } |
|
real ZStep() const { return zstep; } |
|
}; |
|
|
|
template<> class VerticalInternals::VertData<VerticalInternals::Type::FIXED> |
|
{ |
|
real z; |
|
|
|
VertData() = delete; |
|
|
|
public: |
|
VertData(real z_): z(z_) {} |
|
|
|
real Depth([[maybe_unused]] size_t iz) const { return z; } |
|
|
|
constexpr size_t Nz() const { return 1; } |
|
}; |
|
|
|
template<> class VerticalInternals::VertData<VerticalInternals::Type::UNDEFINED> |
|
{ |
|
public: |
|
VertData() = default; |
|
|
|
//real Depth([[maybe_unused]] size_t iz) const { return NAN; } |
|
|
|
constexpr size_t Nz() const { return 1; } |
|
}; |
|
|
|
class Vertical: public VerticalInternals, public VerticalInternals::Vertical |
|
{ |
|
Vertical() = delete; |
|
Vertical(const Vertical&) = delete; |
|
|
|
template<Type t> Vertical(VertData<t>&& prz): VerticalInternals(), VerticalInternals::Vertical(std::move(prz)) {} |
|
|
|
public: |
|
template<Type t, class... Args> static Vertical Create(Args&&... args) |
|
{ |
|
if constexpr(t == Type::LAYERS) |
|
{ |
|
if constexpr(validargs<Type::LAYERS, Args...>) |
|
return Vertical(VertData<Type::LAYERS>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
} |
|
else if constexpr(t == Type::HORIZONTS) |
|
{ |
|
if constexpr(validargs<Type::HORIZONTS, Args...>) |
|
return Vertical(VertData<Type::HORIZONTS>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
} |
|
else if constexpr(t == Type::GRID) |
|
{ |
|
if constexpr(validargs<Type::GRID, Args...>) |
|
return Vertical(VertData<Type::GRID>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
} |
|
else if constexpr(t == Type::FIXED) |
|
{ |
|
if constexpr(validargs<Type::FIXED, Args...>) |
|
return Vertical(VertData<Type::FIXED>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
} |
|
else if constexpr(t == Type::UNDEFINED) |
|
{ |
|
if constexpr(validargs<Type::UNDEFINED, Args...>) |
|
return Vertical(VertData<Type::UNDEFINED>(std::forward<Args>(args)...)); |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
} |
|
else |
|
static_assert(false, "Incorrect call of Vertical::Create"); |
|
}; |
|
|
|
// From Sizes |
|
size_t Nz() const |
|
{ |
|
return std::visit([](const auto& arg) { return arg.Nz(); }, *this); |
|
} |
|
|
|
// Depth (ix,iy,iz) |
|
real Depth(size_t ix, size_t iy, size_t iz) const |
|
{ |
|
return std::visit( |
|
[ix = ix, iy = iy, iz = iz](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool isotropic = Vertical::isotropic<VertType<T>>; |
|
constexpr bool valid = Vertical::valid<VertType<T>>; |
|
if constexpr(!valid) |
|
return NAN; |
|
else if constexpr(isotropic) |
|
return arg.Depth(iz); |
|
else |
|
return arg.Depth(ix, iy, iz); |
|
}, |
|
*this); |
|
} |
|
|
|
// Depth (iz) |
|
real Depth(size_t iz) const |
|
{ |
|
return std::visit( |
|
[iz = iz](const auto& arg) -> real |
|
{ |
|
using T = std::decay_t<decltype(arg)>; |
|
constexpr bool isotropic = Vertical::isotropic<VertType<T>>; |
|
constexpr bool valid = Vertical::valid<VertType<T>>; |
|
if constexpr(isotropic && valid) |
|
return arg.Depth(iz); |
|
else |
|
return NAN; |
|
}, |
|
*this); |
|
} |
|
|
|
// Type |
|
Type Type() const |
|
{ |
|
return std::visit([](const auto& arg) { return VertType<std::decay_t<decltype(arg)>>; }, *this); |
|
} |
|
|
|
// Flags |
|
bool IsIsotropic() const |
|
{ |
|
return std::visit([](const auto& arg) { return Vertical::isotropic<Vertical::VertType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
|
|
bool IsValid() const |
|
{ |
|
return std::visit([](const auto& arg) { return Vertical::valid<Vertical::VertType<std::decay_t<decltype(arg)>>>; }, *this); |
|
} |
|
}; |
|
|
|
class DataMeta |
|
{ |
|
MString unit, stname, lname, comment; |
|
|
|
public: |
|
struct Store |
|
{ |
|
MString unit = "", stname = "", lname = "", comment = ""; |
|
real fillval = NAN; |
|
}; |
|
|
|
private: |
|
struct Store store; |
|
|
|
public: |
|
DataMeta(struct Store&& meta): store(std::move(meta)) {} |
|
|
|
const MString& Unit() const { return store.unit; } |
|
const MString& StandardName() const { return store.stname; } |
|
const MString& LongName() const { return store.lname; } |
|
const MString& Comment() const { return store.comment; } |
|
|
|
real Fillval() const { return store.fillval; } |
|
|
|
void SetFillval(real f) { store.fillval = f; } |
|
}; |
|
|
|
class Data3D: public DataMeta |
|
{ |
|
std::vector<real> data; |
|
std::shared_ptr<Projection> proj; |
|
std::shared_ptr<Vertical> vert; |
|
|
|
Data3D() = delete; |
|
Data3D(const Data3D&) = delete; |
|
|
|
size_t I(size_t ix, size_t iy, size_t iz) const { return ix + iy * Nx() + iz * Nx() * Ny(); } |
|
|
|
Data3D(std::vector<real>&& data_, std::shared_ptr<Projection> proj_, std::shared_ptr<Vertical> vert_, DataMeta::Store&& meta_): |
|
DataMeta(std::move(meta_)), data(std::move(data_)), proj(proj_), vert(vert_) |
|
{ |
|
} |
|
|
|
public: |
|
static Data3D Create(std::vector<real>&& data_, std::shared_ptr<Projection> proj_, std::shared_ptr<Vertical> vert_, DataMeta::Store&& meta_) |
|
{ |
|
return Data3D(std::move(data_), proj_, vert_, std::move(meta_)); |
|
} |
|
Data3D(std::shared_ptr<Projection> proj_, std::shared_ptr<Vertical> vert_, DataMeta::Store&& meta_): |
|
DataMeta(std::move(meta_)), data(proj_->Nx() * proj_->Ny() * vert_->Nz()), proj(proj_), vert(vert_) |
|
{ |
|
} |
|
|
|
const auto& Data() const { return data; } |
|
|
|
bool IsFill(size_t ix, size_t iy, size_t iz) const { return IsFill(I(ix, iy, iz)); } |
|
bool IsFill(size_t i) const { return data[i] == Fillval(); } |
|
|
|
size_t Nx() const { return proj->Nx(); } |
|
size_t Ny() const { return proj->Ny(); } |
|
size_t Nz() const { return vert->Nz(); } |
|
|
|
const real& V(size_t ix, size_t iy, size_t iz) const { return V(I(ix, iy, iz)); } |
|
real& V(size_t ix, size_t iy, size_t iz) { return V(I(ix, iy, iz)); } |
|
|
|
const real& V(size_t i) const { return data[i]; } |
|
real& V(size_t i) { return data[i]; } |
|
|
|
const real& operator()(size_t ix, size_t iy, size_t iz) const { return V(ix, iy, iz); } |
|
real& operator()(size_t ix, size_t iy, size_t iz) { return V(ix, iy, iz); } |
|
const real& operator()(size_t i) const { return V(i); } |
|
real& operator()(size_t i) { return V(i); } |
|
|
|
real Lon(size_t ix, size_t iy) const { return proj->Lon(ix, iy); } |
|
real Lat(size_t ix, size_t iy) const { return proj->Lat(ix, iy); } |
|
real Lon(size_t ix) const { return proj->Lon(ix); } |
|
real Lat(size_t iy) const { return proj->Lat(iy); } |
|
|
|
real LonR(real x, real y) const { return proj->LonR(x, y); } |
|
real LatR(real x, real y) const { return proj->LatR(x, y); } |
|
|
|
real X(real lon, real lat) const { return proj->X(lon, lat); } |
|
real Y(real lon, real lat) const { return proj->Y(lon, lat); } |
|
|
|
real Depth(size_t ix, size_t iy, size_t iz) const { return vert->Depth(ix, iy, iz); } |
|
real Depth(size_t iz) const { return vert->Depth(iz); } |
|
|
|
auto HType() const { return proj->Type(); } |
|
auto VType() const { return vert->Type(); } |
|
|
|
// Flags |
|
bool IsOrthogonal() const { return proj->IsOrthogonal(); } |
|
bool IsRectangular() const { return proj->IsRectangular(); } |
|
bool IsAnalytic() const { return proj->IsAnalytic(); } |
|
bool IsIsotropic() const { return vert->IsIsotropic(); } |
|
bool IsDepthValid() const { return vert->IsValid(); } |
|
|
|
// Metric |
|
auto Metric() const { return proj->Metric(); } |
|
}; |
|
|
|
class Data2D: public DataMeta |
|
{ |
|
std::vector<real> data; |
|
std::shared_ptr<Projection> proj; |
|
|
|
Data2D() = delete; |
|
Data2D(const Data2D&) = delete; |
|
|
|
size_t I(size_t ix, size_t iy) const { return ix + iy * Nx(); } |
|
|
|
Data2D(std::vector<real>&& data_, std::shared_ptr<Projection> proj_, DataMeta::Store&& meta_): DataMeta(std::move(meta_)), data(std::move(data_)), proj(proj_) {} |
|
|
|
public: |
|
static Data2D Create(std::vector<real>&& data_, std::shared_ptr<Projection> proj_, DataMeta::Store&& meta_) { return Data2D(std::move(data_), proj_, std::move(meta_)); } |
|
Data2D(std::shared_ptr<Projection> proj_, DataMeta::Store&& meta_): DataMeta(std::move(meta_)), data(proj_->Nx() * proj_->Ny()), proj(proj_) {} |
|
|
|
const auto& Data() const { return data; } |
|
|
|
bool IsFill(size_t ix, size_t iy) const { return IsFill(I(ix, iy)); } |
|
bool IsFill(size_t i) const { return data[i] == Fillval(); } |
|
|
|
size_t Nx() const { return proj->Nx(); } |
|
size_t Ny() const { return proj->Ny(); } |
|
|
|
const real& V(size_t ix, size_t iy) const { return V(I(ix, iy)); } |
|
real& V(size_t ix, size_t iy) { return V(I(ix, iy)); } |
|
|
|
const real& V(size_t i) const { return data[i]; } |
|
real& V(size_t i) { return data[i]; } |
|
|
|
const real& operator()(size_t ix, size_t iy) const { return V(ix, iy); } |
|
real& operator()(size_t ix, size_t iy) { return V(ix, iy); } |
|
const real& operator()(size_t i) const { return V(i); } |
|
real& operator()(size_t i) { return V(i); } |
|
|
|
real Lon(size_t ix, size_t iy) const { return proj->Lon(ix, iy); } |
|
real Lat(size_t ix, size_t iy) const { return proj->Lat(ix, iy); } |
|
real Lon(size_t ix) const { return proj->Lon(ix); } |
|
real Lat(size_t iy) const { return proj->Lat(iy); } |
|
|
|
real LonR(real x, real y) const { return proj->LonR(x, y); } |
|
real LatR(real x, real y) const { return proj->LatR(x, y); } |
|
|
|
real X(real lon, real lat) const { return proj->X(lon, lat); } |
|
real Y(real lon, real lat) const { return proj->Y(lon, lat); } |
|
|
|
auto HType() const { return proj->Type(); } |
|
|
|
// Flags |
|
bool IsOrthogonal() const { return proj->IsOrthogonal(); } |
|
bool IsRectangular() const { return proj->IsRectangular(); } |
|
bool IsAnalytic() const { return proj->IsAnalytic(); } |
|
|
|
// Metric |
|
auto Metric() const { return proj->Metric(); } |
|
};
|
|
|