|
|
|
#pragma once
|
|
|
|
#include "traits.h"
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using TIndex = std::vector<size_t>;
|
|
|
|
|
|
|
|
class BaseParameters
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~BaseParameters();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Region
|
|
|
|
{
|
|
|
|
real lonb, lone, latb, late;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GridPoint
|
|
|
|
{
|
|
|
|
size_t ix = 0, iy = 0;
|
|
|
|
real x = -1.0, y = -1.0;
|
|
|
|
|
|
|
|
bool Valid() const { return x >= 0.0 && y >= 0.0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Point2D
|
|
|
|
{
|
|
|
|
real x, y;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class VarPresence
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
INTERNAL,
|
|
|
|
DERIVED
|
|
|
|
};
|
|
|
|
|
|
|
|
class BaseData
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
static constexpr real fillval = 1.0e10;
|
|
|
|
std::vector<real> data;
|
|
|
|
MString unit, stname, lname, comment;
|
|
|
|
|
|
|
|
BaseData(size_t n, MString&& unit_ = ""): data(n), unit(std::move(unit_)) {}
|
|
|
|
|
|
|
|
public:
|
|
|
|
BaseData() = default;
|
|
|
|
BaseData(const BaseData&) = delete;
|
|
|
|
BaseData(BaseData&&) = default;
|
|
|
|
|
|
|
|
BaseData& operator=(BaseData&&) = default;
|
|
|
|
|
|
|
|
const real& V(size_t i) const { return data[i]; }
|
|
|
|
real& V(size_t i) { return data[i]; }
|
|
|
|
|
|
|
|
const real& operator()(size_t i) const { return data[i]; }
|
|
|
|
real& operator()(size_t i) { return data[i]; }
|
|
|
|
|
|
|
|
size_t N() const { return data.size(); }
|
|
|
|
|
|
|
|
bool IsFill(size_t i) const { return V(i) == Fillval(); }
|
|
|
|
|
|
|
|
static real Fillval() { return fillval; }
|
|
|
|
|
|
|
|
explicit operator bool() const { return N() != 0; }
|
|
|
|
|
|
|
|
void SetUnit(const MString& str) { unit = str; }
|
|
|
|
void SetStandartName(const MString& str) { stname = str; }
|
|
|
|
void SetLongName(const MString& str) { lname = str; }
|
|
|
|
void SetComment(const MString& str) { comment = str; }
|
|
|
|
|
|
|
|
const MString& Unit() const { return unit; }
|
|
|
|
const MString& StandartName() const { return stname; }
|
|
|
|
const MString& LongName() const { return lname; }
|
|
|
|
const MString& Comment() const { return comment; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class UngriddedData: public BaseData
|
|
|
|
{
|
|
|
|
std::vector<real> lons, lats;
|
|
|
|
|
|
|
|
public:
|
|
|
|
template<class Lon, class Lat> UngriddedData(size_t n, Lon genlon, Lat genlat, MString&& unit = ""): BaseData(n, std::move(unit)), lons(n), lats(n)
|
|
|
|
{
|
|
|
|
for(size_t i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
lons[i] = genlon(i);
|
|
|
|
lats[i] = genlat(i);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
UngriddedData() = default;
|
|
|
|
|
|
|
|
real Lon(size_t i) const { return lons[i]; }
|
|
|
|
real Lat(size_t i) const { return lats[i]; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class Data> class DefaultAverager: public Data
|
|
|
|
{
|
|
|
|
static constexpr bool isuv = IsUVData<Data>;
|
|
|
|
std::vector<size_t> count;
|
|
|
|
|
|
|
|
static bool DataOk(const Data* d, size_t i)
|
|
|
|
{
|
|
|
|
if constexpr(isuv)
|
|
|
|
return d->U(i) != Data::Fillval() && d->V(i) != Data::Fillval();
|
|
|
|
else
|
|
|
|
return d->V(i) != Data::Fillval();
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
void Add(Data&& d)
|
|
|
|
{
|
|
|
|
if(!d) return;
|
|
|
|
if(!*this)
|
|
|
|
{
|
|
|
|
*static_cast<Data*>(this) = std::move(d);
|
|
|
|
count.resize(Data::N());
|
|
|
|
for(size_t i = 0; i < Data::N(); i++) count[i] = DataOk(this, i) ? 1 : 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Data::N() != d.N()) return;
|
|
|
|
for(size_t i = 0; i < Data::N(); i++)
|
|
|
|
if(DataOk(&d, i))
|
|
|
|
{
|
|
|
|
if(DataOk(this, i))
|
|
|
|
{
|
|
|
|
if constexpr(isuv)
|
|
|
|
{
|
|
|
|
Data::U(i) += d.U(i);
|
|
|
|
Data::U2(i) += d.U2(i);
|
|
|
|
}
|
|
|
|
Data::V(i) += d.V(i);
|
|
|
|
count[i]++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if constexpr(isuv)
|
|
|
|
{
|
|
|
|
Data::U(i) = d.U(i);
|
|
|
|
Data::U2(i) = d.U2(i);
|
|
|
|
}
|
|
|
|
Data::V(i) = d.V(i);
|
|
|
|
count[i] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DefaultAverager& Div()
|
|
|
|
{
|
|
|
|
if(!*this) return *this;
|
|
|
|
for(size_t i = 0; i < Data::N(); i++)
|
|
|
|
if(count[i] != 0)
|
|
|
|
{
|
|
|
|
if constexpr(isuv)
|
|
|
|
{
|
|
|
|
Data::U(i) /= count[i];
|
|
|
|
Data::U2(i) /= count[i];
|
|
|
|
}
|
|
|
|
Data::V(i) /= count[i];
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
template<class Data, class Dummy = void> struct GetAverager_
|
|
|
|
{
|
|
|
|
using type = DefaultAverager<Data>;
|
|
|
|
};
|
|
|
|
template<class Data> struct GetAverager_<Data, void_<typename Data::Averager>>
|
|
|
|
{
|
|
|
|
using type = typename Data::Averager;
|
|
|
|
};
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
template<class Data> using Averager = internal::GetAverager_<Data>::type;
|