You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

477 lines
11 KiB
C

4 years ago
/*!
* \file CyclopsGrid.h
* \date 2019/12/03
*
* \author Lin, Chi
* Contact: lin.chi@hzleaper.com
*
*
* \note
*/
#ifndef __CyclopsGrid_h_
#define __CyclopsGrid_h_
#include <vector>
#include <memory>
#include <sstream>
#include "CVUtils.h"
#include "CyclopsParam.h"
struct CyclopsGrid
{
virtual void serialize(FileStorage& fs) const = 0;
virtual void deserialize(const FileNode& node) = 0;
virtual bool genNextValue() = 0;
virtual void resetGrid() = 0;
virtual size_t getType() const = 0;
virtual CyclopsGrid* copy() const = 0;
virtual int getParamIdx() const = 0;
virtual void assign(CyclopsParam* param) const = 0;
virtual int size() const = 0;
virtual void print(std::stringstream& ss) const = 0;
};
class CyclopsGrids;
template<typename T>
struct CyclopsGridX : public CyclopsGrid
{
int paramIdx;
T val;
T minVal;
T maxVal;
T stepVal;
bool logStep;
CyclopsGridX(int idx, const T& minV, const T& maxV, const T& stepV, bool isLogSep) :
paramIdx(idx), minVal(minV), maxVal(maxV), stepVal(stepV), logStep(isLogSep)
{
resetGrid();
}
virtual ~CyclopsGridX() {}
virtual void serialize(FileStorage& fs) const {
fs << "paramIdx" << paramIdx;
fs << "val" << val;
fs << "min" << minVal;
fs << "max" << maxVal;
fs << "step" << stepVal;
fs << "log" << logStep;
}
virtual void deserialize(const FileNode& node) {
node["paramIdx"] >> paramIdx;
node["val"] >> val;
node["min"] >> minVal;
node["max"] >> maxVal;
node["step"] >> stepVal;
node["log"] >> logStep;
}
virtual bool genNextValue() {
T v = logStep ? val * stepVal : val + stepVal;
if (v <= maxVal) {
val = v;
return true;
}
else {
return false;
}
}
virtual void resetGrid() {
val = minVal;
}
virtual size_t getType() const {
return typeid(T).hash_code();
}
virtual CyclopsGrid* copy() const {
CyclopsGridX* p = new CyclopsGridX(paramIdx, minVal, maxVal, stepVal, logStep);
p->val = val;
return p;
}
virtual int getParamIdx() const {
return paramIdx;
}
virtual void assign(CyclopsParam* param) const {
if (param->getType() != getType())
return; // different type;
CyclopsParamX<T>* realParam = dynamic_cast<CyclopsParamX<T>*>(param);
if (!realParam) return; // type case failed
realParam->setValue(val);
}
virtual int size() const {
if (logStep) return (floor(std::log(maxVal / minVal) / std::log(stepVal)) + 1);
else return (maxVal - minVal) / stepVal + 1;
}
virtual void print(std::stringstream& ss) const {
ss << val;
}
protected:
friend class CyclopsGrids;
CyclopsGridX() {};
};
typedef CyclopsGridX<int> CyclopsGridInt;
typedef CyclopsGridX<double> CyclopsGridDouble;
typedef CyclopsGridX<bool> CyclopsGridBool;
// spacial instantiation for bool param
int CyclopsGridBool::size() const {
return 2; // true and false
}
bool CyclopsGridBool::genNextValue() {
val = !val;
return !val;
}
void CyclopsGridBool::resetGrid() {
val = false;
}
typedef CyclopsGridX<Size> CyclopsGridSize;
// special instantiation for size param
bool CyclopsGridSize::genNextValue() {
Size v = val;
v.width = (logStep ? (v.width * stepVal.width) : (v.width + stepVal.width));
if (v.width > maxVal.width) {
// try height
v.width = minVal.width;
v.height = (logStep ? (v.height * stepVal.height) : (v.height + stepVal.height));
if (v.height > maxVal.height) {
return false;
}
}
val = v;
return true;
}
void CyclopsGridSize::resetGrid() {
val.width = minVal.width;
val.height = minVal.height;
}
int CyclopsGridSize::size() const {
if (logStep) {
int wsize = floor(std::log(maxVal.width / minVal.width) / std::log(stepVal.width)) + 1;
int hsize = floor(std::log(maxVal.height / minVal.height) / std::log(stepVal.height)) + 1;
return wsize * hsize;
}
else {
return (((maxVal.width - minVal.width) / stepVal.width) + 1) *
(((maxVal.height - minVal.height) / stepVal.height) + 1);
}
}
void CyclopsGridSize::print(std::stringstream& ss) const {
ss << val.width << " x " << val.height;
}
// add more CyclopsParamX for other data types
// special enum grid
struct CyclopsGridEnum : public CyclopsGridInt
{
int curIdx;
std::vector<int> validVals;
CyclopsGridEnum(int idx, const std::vector<int>& validV)
: validVals(validV)
{
paramIdx = idx;
resetGrid();
}
virtual ~CyclopsGridEnum() {}
virtual void serialize(FileStorage& fs) const {
fs << "paramIdx" << paramIdx;
fs << "val" << val;
fs << "curIdx" << curIdx;
fs << "validVals" << validVals;
}
virtual void deserialize(const FileNode& node) {
node["paramIdx"] >> paramIdx;
node["val"] >> val;
node["curIdx"] >> curIdx;
node["validVals"] >> validVals;
}
virtual bool genNextValue() {
int idx = curIdx + 1;
if (idx >= 0 && idx < validVals.size()) {
val = validVals[idx];
curIdx = idx;
return true;
}
else {
return false;
}
}
virtual void resetGrid() {
curIdx = 0;
val = validVals[0];
}
virtual CyclopsGrid* copy() const {
CyclopsGridEnum* p = new CyclopsGridEnum(paramIdx, validVals);
p->val = val;
p->curIdx = curIdx;
return p;
}
virtual int size() const {
return validVals.size();
}
protected:
friend class CyclopsGrids;
CyclopsGridEnum() {};
};
struct CyclopsGrids
{
public:
CyclopsGrids() {}
CyclopsGrids(const std::string& name) : targetName(name) {}
~CyclopsGrids() {
for (CyclopsGrid* g : grids) delete g;
grids.clear();
}
CyclopsGrids(const CyclopsGrids& other) {
targetName = other.targetName;
for (const CyclopsGrid* g : other.grids) {
grids.push_back(g->copy());
}
}
void operator= (const CyclopsParams& other) = delete;
const std::string& getTargetName() const { return targetName; }
void setTargetName(const std::string& n) { targetName = n; }
template<typename T>
bool addGrid(int paramIdx, const T& minV, const T& maxV, const T& stepV, bool logStep = false) {
if (minV > maxV) return false;
if (!logStep && minV + stepV <= minV) return false;
if (logStep && minV * stepV <= minV) return false;
grids.push_back(new CyclopsGridX<T>(paramIdx, minV, maxV, stepV, logStep));
return true;
}
template<>
bool addGrid<Size>(int paramIdx, const Size& minV, const Size& maxV, const Size& stepV, bool logStep) {
if (minV > maxV) return false;
if (!logStep && (stepV.width <= 0 || stepV.height <= 0)) return false;
if (logStep && (stepV.width <= 1 || stepV.height <= 1)) return false;
grids.push_back(new CyclopsGridX<Size>(paramIdx, minV, maxV, stepV, logStep));
return true;
}
template<>
bool addGrid<bool>(int paramIdx, const bool& minV, const bool& maxV, const bool& stepV, bool logStep) = delete;
bool addBool(int paramIdx) {
grids.push_back(new CyclopsGridBool(paramIdx,
false, true, true, false)); // meaningless settings
return true;
}
bool addEnum(int paramIdx, const std::vector<int>& validVals) {
if (validVals.empty()) return false;
grids.push_back(new CyclopsGridEnum(paramIdx, validVals));
return true;
}
bool removeGrid(int paramIdx) {
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
if (g->getParamIdx() == paramIdx) {
delete g;
grids.erase(grids.begin() + i);
return true;
}
}
return true;
}
int count() const { return grids.size(); }
void serialize(FileStorage& fs) const {
fs << "targetName" << targetName;
fs << "grids" << "[";
for (const CyclopsGrid* g : grids) {
fs << "{:";
fs << "type" << std::to_string(g->getType());
g->serialize(fs);
fs << "}";
}
fs << "]";
}
void deserialize(const FileNode& node) {
node["targetName"] >> targetName;
FileNode gNode = node["grids"];
if (gNode.isNone()) return;
if (!grids.empty()) return;
for (auto it = gNode.begin(); it != gNode.end(); ++it) {
std::string typecode;
(*it)["type"] >> typecode;
size_t typeId = std::stoull(typecode);
CyclopsGrid* g = nullptr;
if (typeId == typeid(int).hash_code()) {
if ((*it)["validVals"].isNone())
g = new CyclopsGridInt();
else
g = new CyclopsGridEnum();
}
else if (typeId == typeid(double).hash_code()) {
g = new CyclopsGridDouble();
}
else if (typeId == typeid(bool).hash_code()) {
g = new CyclopsGridBool();
}
else if (typeId == typeid(Size).hash_code()) {
g = new CyclopsGridSize();
}
else {
// invalid type code
continue;
}
g->deserialize(*it);
grids.push_back(g);
}
}
bool genNextGrid()
{
int c = grids.size();
for (int i = 0; i < c; ++i) {
CyclopsGrid* g = grids[i];
if (!g) continue;
if (g->genNextValue()) {
// reset all previous to first value
for (int j = 0; j < i; ++j) {
CyclopsGrid* p = grids[j];
p->resetGrid();
}
return true;
}
}
return false;
}
const CyclopsGrid* getGrid(int paramIdx) const {
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
if (g->getParamIdx() == paramIdx) {
return g;
}
}
return nullptr;
}
const CyclopsGrid* itemGrid(int index) const {
if (index < 0 || index >= grids.size()) return nullptr;
return grids[index];
}
template<typename T>
T getValue(int paramIdx, bool* ok) const {
const CyclopsGrid* g = getGrid(paramIdx);
if (g) {
const CyclopsGridX<T>* gt = dynamic_cast<const CyclopsGridX<T>*>(g);
if (ok) *ok = true;
return gt->val;
}
if (ok) *ok = false;
return T();
}
void reset() {
for (CyclopsGrid* g : grids) {
g->resetGrid();
}
}
template<typename T>
void getSetting(int paramIdx, T* pMinVal = nullptr, T* pMaxVal = nullptr, T* pStepVal = nullptr) const {
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
if (g->getParamIdx() == paramIdx) {
const CyclopsGridX<T>* gt = dynamic_cast<const CyclopsGridX<T>*>(g);
if (gt) {
if (pMinVal) *pMinVal = gt->minVal;
if (pMaxVal) *pMaxVal = gt->maxVal;
if (pStepVal) *pStepVal = gt->stepVal;
}
}
}
}
void getEnumSetting(int paramIdx, std::vector<int>& validVals) const {
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
if (g->getParamIdx() == paramIdx) {
const CyclopsGridEnum* gt = dynamic_cast<const CyclopsGridEnum*>(g);
if (gt) {
validVals = gt->validVals;
}
}
}
}
template<typename T>
bool checkParamType(int idx) const {
if (idx < 0 || idx > grids.size()) return false;
return grids[idx]->getType() == typeid(T).hash_code();
}
void assign(CyclopsParams* params) {
for (int i = 0; i < params->count(); ++i) {
const CyclopsGrid* g = getGrid(i);
if (!g) continue;
g->assign(params->get(i));
}
params->setDirtyBit(true);
}
int size() const {
int ret = 1;
for (CyclopsGrid* g : grids) {
ret *= g->size();
}
return ret;
}
std::string print() {
std::stringstream ss;
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
g->print(ss);
ss << ",";
}
return ss.str();
}
std::string print(const CyclopsParams* params) {
std::stringstream ss;
for (int i = 0; i < grids.size(); ++i) {
const CyclopsGrid* g = grids[i];
const CyclopsParam* p = params->get(g->getParamIdx());
p->print(ss);
ss << ",";
}
return ss.str();
}
private:
std::string targetName;
std::vector<CyclopsGrid*> grids;
};
#endif // CyclopsGrid_h_