summaryrefslogtreecommitdiff
path: root/CSXCAD/src/ParameterObjects.cpp
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2016-07-05 18:02:38 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2016-07-05 18:02:38 +0200
commitef962f6008f25ab7cbd4ca21bcc72b97a1e2d76f (patch)
tree8149bee93d1a3f91d4503bfb3853adac4af0a85e /CSXCAD/src/ParameterObjects.cpp
Imported Upstream version 0.0.34
Diffstat (limited to 'CSXCAD/src/ParameterObjects.cpp')
-rw-r--r--CSXCAD/src/ParameterObjects.cpp713
1 files changed, 713 insertions, 0 deletions
diff --git a/CSXCAD/src/ParameterObjects.cpp b/CSXCAD/src/ParameterObjects.cpp
new file mode 100644
index 0000000..161d4dd
--- /dev/null
+++ b/CSXCAD/src/ParameterObjects.cpp
@@ -0,0 +1,713 @@
+/*
+* Copyright (C) 2008,2009,2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published
+* by the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ParameterObjects.h"
+#include <sstream>
+#include <iostream>
+#include "tinyxml.h"
+#include "CSFunctionParser.h"
+#include "CSUseful.h"
+
+bool ReadTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, double val)
+{
+ double dHelp;
+
+ PS.SetValue(val); // set default value
+ const char* chHelp=elem.Attribute(attr);
+ if (chHelp==NULL)
+ return false;
+ PS.SetValue(chHelp); // set string value if found
+ return true;
+}
+
+void WriteTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, bool mode, bool scientific)
+{
+ if (PS.GetMode() && mode)
+ elem.SetAttribute(attr,PS.GetString().c_str());
+ else
+ {
+ if (PS.GetValue()==NAN)
+ return;
+ if (scientific)
+ {
+ char doubleVal[50];
+ sprintf(doubleVal,"%e",PS.GetValue());
+ elem.SetAttribute(attr,doubleVal);
+ }
+ else
+ elem.SetDoubleAttribute(attr,PS.GetValue());
+ }
+}
+
+bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, double val, const char delimiter)
+{
+ return ReadVectorTerm(PS, elem, attr.c_str(), val, delimiter);
+}
+
+bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, double val, const char delimiter)
+{
+ //initialize with default value
+ for (int n=0;n<3;++n)
+ PS[n].SetValue(val);
+
+ const char* values = elem.Attribute(attr);
+ if (values==NULL)
+ return false;
+ std::vector<std::string> val_list = SplitString2Vector(values, delimiter);
+ if (val_list.size()>3)
+ return false;
+
+ for (int n=0;n<3;++n)
+ PS[n].SetValue(val);
+ for (int n=0;n<(int)val_list.size();++n)
+ {
+ std::string sHelp=val_list.at(n);
+ bool ok;
+ double val = String2Double(sHelp, ok);
+ if (ok)
+ PS[n].SetValue(val);
+ else
+ PS[n].SetValue(sHelp.c_str());
+ }
+ return true;
+}
+
+void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, bool mode, bool scientific, const char delimiter)
+{
+ WriteVectorTerm(PS, elem, attr.c_str(), mode, scientific, delimiter);
+}
+
+void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, bool mode, bool sci, const char delimiter)
+{
+ std::stringstream ss;
+ if (sci)
+ ss << std::scientific;
+ for (int i=0;i<3;++i)
+ {
+ if (PS[i].GetMode() && mode)
+ ss << PS[i].GetString();
+ else if (PS[i].GetValue()==NAN)
+ ss << "NAN" << std::endl;
+ else
+ ss << PS[i].GetValue();
+ if (i<2)
+ ss << delimiter;
+ }
+ elem.SetAttribute(attr,ss.str().c_str());
+}
+
+Parameter::Parameter()
+{
+ bModified=true;
+ dValue=0;
+ Type=Const;
+ bSweep=true;
+// Set=NULL;
+}
+
+Parameter::Parameter(const std::string Paraname, double val)
+{
+ sName=Paraname;
+ SetValue(val);
+ Type=Const;
+ bSweep=true;
+// Set=NULL;
+}
+
+Parameter::~Parameter()
+{
+// if (Set!=NULL) Set->RemoveParameter(this);
+}
+
+
+void Parameter::PrintSelf(FILE* /*out*/)
+{
+ fprintf(stderr," Parameter: %s Value: %f Type %d\n\n",sName.c_str(),dValue,Type);
+}
+
+bool Parameter::Write2XML(TiXmlNode& root)
+{
+ TiXmlElement *elem=NULL;
+ if (Type==Const)
+ {
+ elem = new TiXmlElement("Parameter");
+ elem->SetAttribute("Type","Const");
+ }
+ else elem = root.ToElement();
+ if (elem==NULL) return false;
+ elem->SetAttribute("name",sName.c_str());
+ elem->SetAttribute("Sweep",bSweep);
+ elem->SetDoubleAttribute("value",dValue);
+ if (Type==Const) root.LinkEndChild(elem);
+ return true;
+}
+
+bool Parameter::ReadFromXML(TiXmlNode &root)
+{
+ TiXmlElement *elem = root.ToElement();
+ if (elem==NULL) return false;
+
+ int iAtt=0;
+ if (elem->QueryIntAttribute("Sweep",&iAtt)!=TIXML_SUCCESS) bSweep=true;
+ else if (iAtt>0) bSweep=true;
+ else bSweep=false;
+
+ double val=0;
+ if (elem->QueryDoubleAttribute("value",&val)!=TIXML_SUCCESS) return false;
+ SetValue(val);
+
+ const char* att=elem->Attribute("name");
+ if (att==NULL) sName=std::string();
+ else sName=std::string(att);
+
+ return true;
+}
+
+Parameter* Parameter::GetParameterFromXML(TiXmlNode &/*root*/)
+{
+ return NULL;
+}
+
+LinearParameter::LinearParameter() : Parameter()
+{
+ Type=Linear;
+ dMin=dMax=dStep=0;
+}
+
+LinearParameter::LinearParameter(const std::string Paraname, double val, double min, double max, double step) : Parameter(Paraname,val)
+{
+ //sName=string(Paraname);
+ if (max<min) max=min;
+ dMin=min;
+ dMax=max;
+ if (step<0) step=0;
+ dStep=step;
+ Type=Linear;
+
+ SetValue(dValue);
+}
+
+LinearParameter::LinearParameter(const LinearParameter *parameter) : Parameter(parameter)
+{
+ if (parameter->Type==Linear)
+ {
+ dMin=parameter->dMin;
+ dMax=parameter->dMax;
+ dStep=parameter->dStep;
+ }
+ else
+ {
+ Type=Linear;
+ dMin=dMax=dStep=0;
+ }
+ SetValue(dValue);
+}
+
+void LinearParameter::SetValue(double val)
+{
+ if (val>dMax) val=dMax;
+ else if (val<dMin) val=dMin;
+ if (dStep==0) dValue=val;
+ else
+ {
+ dValue=dMin+dStep*floor((val-dMin)/dStep+0.5);
+ if (dValue>dMax) dValue=dValue-dStep;
+ }
+ bModified=true;
+}
+
+bool LinearParameter::IncreaseStep()
+{
+ if (dValue+dStep>dMax) return false;
+ SetValue(dValue+dStep);
+ return true;
+}
+
+void LinearParameter::PrintSelf(FILE* /*out*/)
+{
+ fprintf(stderr," Parameter: %s Value: %f\n from %f to %f; Stepsize: %f\n",sName.c_str(),dValue,dMin,dMax,dStep);
+}
+
+bool LinearParameter::Write2XML(TiXmlNode& root)
+{
+ TiXmlElement para("Parameter");
+ para.SetAttribute("Type","Linear");
+ Parameter::Write2XML(para);
+ para.SetDoubleAttribute("min",dMin);
+ para.SetDoubleAttribute("max",dMax);
+ para.SetDoubleAttribute("step",dStep);
+ root.InsertEndChild(para);
+ return true;
+}
+
+bool LinearParameter::ReadFromXML(TiXmlNode &root)
+{
+ TiXmlElement *elem = root.ToElement();
+ if (elem==NULL) return false;
+
+ if (elem->QueryDoubleAttribute("min",&dMin)!=TIXML_SUCCESS) return false;
+ if (elem->QueryDoubleAttribute("max",&dMax)!=TIXML_SUCCESS) return false;
+ if (elem->QueryDoubleAttribute("step",&dStep)!=TIXML_SUCCESS) return false;
+
+ if (Parameter::ReadFromXML(root)==false) return false;
+// const char* att=elem->Attribute("name");
+// if (att==NULL) return false;
+// sName=string(att);
+
+// if (elem->QueryDoubleAttribute("value",&dValue)!=TIXML_SUCCESS) return false;
+
+ return true;
+}
+
+
+ParameterSet::ParameterSet(void)
+{
+ bModified=true;
+}
+
+ParameterSet::~ParameterSet(void)
+{
+ clear();
+}
+
+size_t ParameterSet::LinkParameter(Parameter* newPara)
+{
+ vParameter.push_back(newPara);
+// newPara->ParameterSet(this);
+ return vParameter.size();
+}
+
+size_t ParameterSet::DeleteParameter(size_t index)
+{
+ if (index>=vParameter.size()) return vParameter.size();
+ std::vector<Parameter*>::iterator pIter=vParameter.begin();
+ vParameter.erase(pIter+index);
+
+ return vParameter.size();
+}
+
+size_t ParameterSet::DeleteParameter(Parameter* para)
+{
+ std::vector<Parameter*>::iterator pIter=vParameter.begin();
+ while (pIter!=vParameter.end())
+ {
+ if (*pIter==para)
+ {
+ vParameter.erase(pIter);
+ return vParameter.size();
+ }
+ ++pIter;
+ }
+ return vParameter.size();
+}
+
+void ParameterSet::clear()
+{
+ for (size_t i=0; i<vParameter.size();++i)
+ {
+ delete vParameter.at(i);
+ }
+ vParameter.clear();
+// ParameterString.clear();
+// ParameterValueString.clear();
+}
+
+bool ParameterSet::GetModified()
+{
+ if (bModified==true) return true;
+ for (size_t i=0; i<vParameter.size();++i) if (vParameter.at(i)->GetModified()==true) return true;
+ return false;
+}
+
+void ParameterSet::SetModified(bool mod)
+{
+ if (mod==true)
+ {
+ bModified=true;
+ return;
+ }
+ bModified=false;
+ for (size_t i=0; i<vParameter.size();++i) vParameter.at(i)->SetModified(false);
+}
+
+double* ParameterSet::GetValueArray(double *array)
+{
+ if (array==NULL) return array;
+ for (size_t i=0; i<vParameter.size();++i)
+ {
+ array[i]=vParameter.at(i)->GetValue();
+ }
+ return array;
+}
+
+int ParameterSet::CountSweepSteps(int SweepMode)
+{
+ int count=0;
+ switch (SweepMode)
+ {
+ case 1:
+ for (size_t i=0; i<vParameter.size();++i)
+ if (vParameter.at(i)->GetSweep())
+ {
+ if (count==0) count=vParameter.at(i)->CountSteps();
+ else count*=vParameter.at(i)->CountSteps();
+ }
+ return count;
+ break;
+ case 2:
+ for (size_t i=0; i<vParameter.size();++i) if (vParameter.at(i)->GetSweep()) count+=vParameter.at(i)->CountSteps();
+ return count;
+ break;
+ }
+ return 0;
+}
+
+void ParameterSet::InitSweep()
+{
+ for (size_t i=0; i<vParameter.size();++i)
+ if (vParameter.at(i)->GetSweep())
+ {
+ vParameter.at(i)->Save();
+ vParameter.at(i)->InitSweep();
+ }
+ SweepPara=0;
+}
+
+void ParameterSet::EndSweep()
+{
+ for (size_t i=0; i<vParameter.size();++i)
+ if (vParameter.at(i)->GetSweep())
+ {
+ vParameter.at(i)->Restore();
+ }
+}
+
+bool ParameterSet::NextSweepPos(int SweepMode)
+{
+ switch (SweepMode)
+ {
+ case 1:
+ {
+ int level=vParameter.size()-1;
+ while (level>=0)
+ {
+ if (vParameter.at(level)->GetSweep())
+ {
+ if (vParameter.at(level)->IncreaseStep()) return true;
+ else
+ {
+ vParameter.at(level)->InitSweep();
+ --level;
+ }
+ }
+ else --level;
+ }
+ return false;
+ break;
+ }
+ case 2:
+ if ((unsigned int)SweepPara>=vParameter.size()) return false;
+ if (vParameter.at(SweepPara)->GetSweep())
+ {
+ if (vParameter.at(SweepPara)->IncreaseStep()) return true;
+ else ++SweepPara;
+ return NextSweepPos(SweepMode);
+ }
+ else
+ {
+ ++SweepPara;
+ return NextSweepPos(SweepMode);
+ }
+ break;
+ }
+ return false;
+}
+
+
+const std::string ParameterSet::GetParameterString(const std::string spacer)
+{
+ std::string ParameterString;
+ for (size_t i=0; i<vParameter.size();++i)
+ {
+ if (i>0) ParameterString+=spacer;
+ ParameterString+=vParameter.at(i)->GetName();
+ }
+ return ParameterString;
+}
+
+const std::string ParameterSet::GetParameterValueString(const std::string spacer, bool ValuesOnly)
+{
+ std::string ParameterValueString;
+ for (size_t i=0; i<vParameter.size();++i)
+ {
+ if (i>0) ParameterValueString+=spacer;
+ if (!ValuesOnly)
+ {
+ ParameterValueString+=vParameter.at(i)->GetName();
+ ParameterValueString+="=";
+ }
+ std::ostringstream os;
+ os << vParameter.at(i)->GetValue();
+ ParameterValueString+=os.str();
+ }
+ return ParameterValueString.c_str();
+}
+
+void ParameterSet::PrintSelf(FILE* out)
+{
+ fprintf(out," Parameter-Set Printout, Qty of Parameter: %d\n",(int)vParameter.size());
+ for (size_t i=0; i<vParameter.size();++i)
+ {
+ fprintf(out,"----Nr. %d----\n",(int)i);
+ vParameter.at(i)->PrintSelf(out);
+ }
+}
+
+bool ParameterSet::Write2XML(TiXmlNode& root)
+{
+ TiXmlElement pSet("ParameterSet");
+ //pSet.SetAttribute("QtyParameter",(int)vParameter.size());
+ for (size_t i=0;i<vParameter.size();++i) vParameter.at(i)->Write2XML(pSet);
+
+ root.InsertEndChild(pSet);
+ return true;
+}
+
+bool ParameterSet::ReadFromXML(TiXmlNode &root)
+{
+ TiXmlNode* paraNode = root.FirstChild("Parameter");
+ while (paraNode!=NULL)
+ {
+ TiXmlElement *elem = paraNode->ToElement();
+ if (elem!=NULL)
+ {
+ const char* att=elem->Attribute("Type");
+ if (att!=NULL)
+ {
+ Parameter* newPara=NULL;
+ if (strcmp(att,"Const")==0) newPara = new Parameter();
+ else if (strcmp(att,"Linear")==0) newPara = new LinearParameter();
+ if (newPara!=NULL)
+ {
+ if (newPara->ReadFromXML(*elem)==true) this->InsertParameter(newPara);
+ }
+ }
+ }
+ paraNode=paraNode->NextSiblingElement("Parameter");
+ };
+ return true;
+}
+
+
+ParameterScalar::ParameterScalar()
+{
+ clParaSet=NULL;
+ bModified=true;
+ ParameterMode=false;
+ sValue.clear();
+ dValue=0;
+}
+
+ParameterScalar::ParameterScalar(ParameterSet* ParaSet, const std::string value)
+{
+ SetParameterSet(ParaSet);
+ SetValue(value);
+}
+
+ParameterScalar::ParameterScalar(ParameterSet* ParaSet, double value)
+{
+ SetParameterSet(ParaSet);
+ bModified=true;
+ SetValue(value);
+}
+
+ParameterScalar::ParameterScalar(ParameterScalar* ps)
+{
+ Copy(ps);
+}
+
+ParameterScalar::~ParameterScalar()
+{
+}
+
+void ParameterScalar::SetParameterSet(ParameterSet *paraSet)
+{
+ clParaSet=paraSet;
+}
+
+int ParameterScalar::SetValue(const std::string value, bool Eval)
+{
+ if (value.empty()) return -1;
+
+ //check if string is only a plain double
+ char *pEnd;
+ double val = strtod(value.c_str(),&pEnd);
+ if (*pEnd == 0)
+ SetValue(val);
+
+ ParameterMode=true;
+ bModified=true;
+ sValue=value;
+
+ if (Eval) return Evaluate();
+
+ return 0;
+}
+
+void ParameterScalar::SetValue(double value)
+{
+ ParameterMode=false;
+ dValue=value;
+ sValue.clear();
+}
+
+double ParameterScalar::GetValue() const
+{
+ return dValue;
+}
+
+const std::string ParameterScalar::GetValueString() const
+{
+ if (ParameterMode)
+ return sValue;
+ std::stringstream numString;
+ numString << dValue;
+ return numString.str();
+}
+
+int ParameterScalar::Evaluate()
+{
+ if (ParameterMode==false) return 0;
+ if (clParaSet!=NULL)
+ bModified = bModified || clParaSet->GetModified();
+ if (bModified==false)
+ return 0;
+
+ CSFunctionParser fParse;
+ dValue=0;
+
+ if (clParaSet!=NULL)
+ fParse.Parse(sValue,clParaSet->GetParameterString());
+ else
+ fParse.Parse(sValue,"");
+
+ if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR) return fParse.GetParseErrorType()+100;
+ bModified=false;
+
+ if (clParaSet!=NULL)
+ {
+ double *vars = new double[clParaSet->GetQtyParameter()];
+ vars=clParaSet->GetValueArray(vars);
+ dValue=fParse.Eval(vars);
+ delete[] vars;vars=NULL;
+ }
+ else
+ dValue=fParse.Eval(NULL);
+ return fParse.EvalError();
+}
+
+double ParameterScalar::GetEvaluated(double* ParaValues, int &EC)
+{
+ if (ParameterMode==false) return dValue;
+ CSFunctionParser fParse;
+ fParse.Parse(sValue,clParaSet->GetParameterString());
+ if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR)
+ {
+ EC = fParse.GetParseErrorType()+100;
+ return 0;
+ }
+ double dvalue = fParse.Eval(ParaValues);
+ EC = fParse.EvalError();
+ return dvalue;
+}
+
+void ParameterScalar::Copy(ParameterScalar* ps)
+{
+ SetParameterSet(ps->clParaSet);
+ bModified=ps->bModified;
+ ParameterMode=ps->ParameterMode;
+ sValue=std::string(ps->sValue);
+ dValue=ps->dValue;
+}
+
+std::string PSErrorCode2Msg(int code)
+{
+ std::string msg;
+ PSErrorCode2Msg(code,&msg);
+ return msg;
+}
+
+void PSErrorCode2Msg(int code, std::string *msg)
+{
+ switch (code)
+ {
+ case -1:
+ msg->append("Internal Error");
+ break;
+ case 0:
+ msg->append("No Error");
+ break;
+ case 1:
+ msg->append("Division by zero");
+ break;
+ case 2:
+ msg->append("sqrt error (sqrt of a negative value)");
+ break;
+ case 3:
+ msg->append("log error (logarithm of a negative value)");
+ break;
+ case 4:
+ msg->append("trigonometric error (asin or acos of illegal value)");
+ break;
+ case 5:
+ msg->append("Maximum recursion level reached");
+ break;
+ case 100:
+ msg->append("Syntax error (check Parameter)");
+ break;
+ case 101:
+ msg->append("Mismatched parenthesis");
+ break;
+ case 102:
+ msg->append("Missing \')\'");
+ break;
+ case 103:
+ msg->append("Empty parentheses");
+ break;
+ case 104:
+ msg->append("Syntax error: Operator expected");
+ break;
+ case 105:
+ msg->append("Not enough memory");
+ break;
+ case 106:
+ msg->append("An unexpected error occurred");
+ break;
+ case 107:
+ msg->append("Syntax error in parameters");
+ break;
+ case 108:
+ msg->append("Illegal number of parameters to function");
+ break;
+ case 109:
+ msg->append("Syntax error: Premature end of string");
+ break;
+ case 110:
+ msg->append("Syntax error: Expecting ( after function");
+ break;
+ };
+}