ScatterDraw: Improved user equations handling

git-svn-id: svn://ultimatepp.org/upp/trunk@11840 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
koldo 2018-03-17 09:29:19 +00:00
parent a27679e85c
commit 32e034bd0e
5 changed files with 73 additions and 25 deletions

View file

@ -89,6 +89,8 @@ int ExplicitEquation::maxFitFunctionEvaluations = 1000;
double PolynomialEquation::f(double x) {
if (x < 0)
return Null;
double y = 0;
for (int i = 0; i < coeff.GetCount(); ++i)
y += coeff[i]*pow(x, i);
@ -133,8 +135,8 @@ String FourierEquation::GetEquation(int numDigits) {
return ret;
}
static double DegToRad(double deg) {return deg*M_PI/180.;}
static double RadToDeg(double rad) {return rad*180./M_PI;}
static inline double DegToRad(double deg) {return deg*M_PI/180.;}
static inline double RadToDeg(double rad) {return rad*180./M_PI;}
void EvalExpr::EvalThrowError(CParser &p, const char *s) {
CParser::Pos pos = p.GetPos();
@ -152,8 +154,7 @@ EvalExpr::EvalExpr() {
noCase = false;
errorIfUndefined = false;
constants.Add("PI", M_PI);
constants.Add("M_PI", M_PI);
constants.Add("pi", M_PI);
constants.Add("e", M_E);
functions.Add("abs", fabs);
@ -190,7 +191,7 @@ double EvalExpr::Term(CParser& p) {
}
String strsearch;
if (noCase)
strsearch = ToUpper(strId);
strsearch = ToLower(strId);
else
strsearch = strId;
double ret = constants.Get(strsearch, Null);
@ -198,7 +199,7 @@ double EvalExpr::Term(CParser& p) {
ret = variables.Get(strsearch, Null);
if (IsNull(ret)) {
if (errorIfUndefined)
EvalThrowError(p, Format(t_("Unknown var '%s'"), strId));
EvalThrowError(p, Format(t_("Unknown identifier '%s'"), strId));
ret = variables.GetAdd(strsearch, 0);
}
}
@ -214,9 +215,11 @@ double EvalExpr::Term(CParser& p) {
double EvalExpr::Pow(CParser& p) {
double x = Term(p);
for(;;) {
if(p.Char('^'))
if(p.Char('^')) {
if (x < 0)
EvalThrowError(p, t_("Complex number"));
x = pow(x, Term(p));
else
} else
return x;
}
}
@ -263,7 +266,7 @@ double EvalExpr::Eval(String line) {
if(p.Char('=')) {
double ret = Exp(p);
if (noCase)
var = ToUpper(var);
var = ToLower(var);
variables.GetAdd(var) = ret;
return ret;
} else {
@ -289,7 +292,7 @@ String EvalExpr::TermStr(CParser& p, int numDigits) {
return strId + "(" + x + ")";
}
if (noCase)
strId = ToUpper(strId);
strId = ToLower(strId);
if (IsNull(numDigits)) {
if (constants.Find(strId) < 0)
variables.GetAdd(strId, 0);

View file

@ -99,7 +99,9 @@ class LinearEquation : public ExplicitEquation {
public:
LinearEquation() {SetCoeff(0, 0);}
LinearEquation(double c0, double c1){SetCoeff(c0, c1);}
double f(double x) {return coeff[0] + x*coeff[1];}
double f(double x) {
return coeff[0] + x*coeff[1];
}
virtual String GetName() {return t_("Linear");}
virtual String GetEquation(int numDigits = 3) {
String ret = Format("%s + %s*x", FormatCoeff(0, numDigits), FormatCoeff(1, numDigits));
@ -278,7 +280,11 @@ class RealExponentEquation : public ExplicitEquation {
public:
RealExponentEquation() {SetCoeff(1, 1);}
RealExponentEquation(double a, double b) {SetCoeff(a, b);}
double f(double x) {return coeff[0]*pow(x, coeff[1]);}
double f(double x) {
if (x < 0)
return Null;
return coeff[0]*pow(x, coeff[1]);
}
virtual String GetName() {return t_("RealExponent");}
virtual String GetEquation(int numDigits = 3) {
String ret = Format("%s*x^%s", FormatCoeff(0, numDigits), FormatCoeff(1, numDigits));
@ -334,15 +340,15 @@ public:
const String &GetFunction(int id) {return functions.GetKey(id);}
int GetFunctionsCount() {return functions.GetCount();}
void SetConstant(String name, double value = 0) {constants.GetAdd(name, value);}
void SetConstant(String name, double value = 0) {constants.GetAdd(name) = value;}
void SetConstant(int id, double value = 0) {constants[id] = value;}
double GetConstant(String name) {return constants.Get(name, Null);}
void GetConstant(int id, String &name, double &value) {name = constants.GetKey(id); value = constants[id];}
int GetConstantsCount() {return constants.GetCount();}
void SetVariable(String name, double value = 0) {variables.GetAdd(name, value);}
void SetVariable(String name, double value = 0) {variables.GetAdd(name) = value;}
void SetVariable(int id, double value = 0) {variables[id] = value;}
double GetVariable(String name) {return variables.Get(name, Null);}
double GetVariable(String name) {return variables.GetAdd(name);}
void GetVariable(int id, String &name, double &value) {name = variables.GetKey(id); value = variables[id];}
int GetVariablesCount() {return variables.GetCount();}
void ClearVariables();
@ -353,7 +359,7 @@ public:
CParser p;
static void EvalThrowError(CParser &p, const char *s);
static void EvalThrowError(CParser &p, const char *s);
protected:
double Exp(CParser& p);
@ -363,6 +369,9 @@ protected:
VectorMap<String, double> variables;
bool errorIfUndefined;
bool IsFunction(String str) {return functions.Get(str, 0);}
bool IsConstant(String str) {return !IsNull(GetConstant(str));}
private:
void *Functions_Get(CParser& p);
double Term(CParser& p);
@ -381,22 +390,46 @@ public:
UserEquation(String _name, String _strEquation, String varHoriz = "x") {Init(_name, _strEquation, varHoriz);}
void Init(String _name, String _strEquation, String varHoriz = "x") {
name = _name;
strEquation = _strEquation;
_strEquation.Replace(" ", "");
StringStream str(_strEquation);
Vector<String> parts = GetCsvLine(str, ';', CHARSET_DEFAULT);
if (parts.IsEmpty())
return;
strEquation = parts[0];
eval.Init();
eval.SetConstant(varHoriz);
idx = eval.GetConstantsCount() - 1;
eval.EvalStr(strEquation);
coeff.SetCount(eval.GetVariablesCount());
for (int i = 0; i < coeff.GetCount(); ++i)
coeff[i] = 0.1;
coeff.Clear();
varNames.Clear();
for (int i = 0; i < eval.GetVariablesCount(); ++i) {
String varName;
double dummy;
eval.GetVariable(i, varName, dummy);
varNames << varName;
int istr;
for (istr = 1; istr < parts.GetCount(); ++istr) {
String strVar = varName + "=";
int ifound = parts[istr].Find(strVar);
if (ifound >= 0) {
double val = ScanDouble(parts[istr].Mid(strVar.GetCount()));
coeff << val;
break;
}
}
if (istr == parts.GetCount())
coeff << 0.1;
}
}
double f(double x) {
eval.SetConstant(idx, x);
for (int i = 0; i < coeff.GetCount(); ++i)
eval.SetVariable(i, coeff[i]);
for (int i = 0; i < coeff.GetCount(); ++i) {
eval.SetVariable(varNames[i], coeff[i]);
double ret = eval.GetVariable(varNames[i]);
}
return eval.Eval(strEquation);
}
void SetName(String _name) {name = _name;}
void SetName(String _name) {name = _name;}
virtual String GetName() {return name;}
virtual String GetEquation(int numDigits = 3) {return eval.EvalStr(strEquation, numDigits);}
virtual void GuessCoeff(DataSource &series) {}
@ -405,6 +438,7 @@ public:
private:
String name;
String strEquation;
Vector<String> varNames;
EvalExpr eval;
int idx;
};

View file

@ -1,5 +1,8 @@
#include "ScatterDraw.h"
#define TFILE <ScatterDraw/ScatterDraw.t>
#include <Core/t.h>
ScatterDraw& ScatterDraw::SetColor(const Color& _color) {
graphColor = _color;
return *this;
@ -1943,6 +1946,7 @@ ScatterDraw::ScatterDraw() {
stacked = false;
serializeFormat = true;
mouseHandlingX = mouseHandlingY = false;
selectedSeries = Null;
}
void DrawLine(Draw &w, double x0, double y0, double x1, double y1, double width, const Color &color) {

View file

@ -943,6 +943,7 @@ private:
bool labelsChanged;
bool stacked;
bool serializeFormat;
int selectedSeries;
};
template <class T>

View file

@ -24,9 +24,15 @@ esES("Error en %s(%f)")
euES("")
frFR("")
T_("Unknown var '%s'")
T_("Unknown identifier '%s'")
caES("")
esES("Variable '%s' desconocida")
esES("Identificador desconocido '%s'")
euES("")
frFR("")
T_("Complex number")
caES("")
esES("N\303\272mero complejo")
euES("")
frFR("")