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
477 lines
11 KiB
C
|
5 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_
|
||
|
|
|