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.
150 lines
2.9 KiB
150 lines
2.9 KiB
#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; |
|
}; |
|
|
|
class BaseData |
|
{ |
|
protected: |
|
static constexpr real fillval = 1.0e10; |
|
std::vector<real> data; |
|
MString unit; |
|
|
|
BaseData(size_t n, MString&& unit_ = ""): data(n), unit(std::move(unit_)) {} |
|
|
|
public: |
|
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; } |
|
|
|
const MString& Unit() const { return unit; } |
|
}; |
|
|
|
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(const Data& d) |
|
{ |
|
if(!d) return; |
|
if(!*this) |
|
{ |
|
*static_cast<Data*>(this) = 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;
|
|
|