Commit 52ee4b86 authored by David Saxton's avatar David Saxton

Split the Ufkt class into a visual part - Function, and the equation part -

Equation. This is in preparation for fixing the hacked way that Parametric
functions are stored.

svn path=/trunk/KDE/kdeedu/kmplot/; revision=526110
parent 5bb5791e
......@@ -98,7 +98,7 @@ MainDlg::MainDlg(QWidget *parentWidget, const char *, QObject *parent ) : DCOPO
View::self()->setMinMaxDlg(minmaxdlg);
setupActions();
View::self()->parser()->constants()->load();
kmplotio = new KmPlotIO(View::self()->parser());
kmplotio = new KmPlotIO();
m_config = KGlobal::config();
m_recentFiles->loadEntries( m_config );
......
This diff is collapsed.
......@@ -84,11 +84,11 @@ public:
/// @see getSettings
void init();
/// Finding the minimum or maximum value
void findMinMaxValue(Ufkt *, char, bool, double &, double &,const QString &);
void findMinMaxValue(Function *, char, bool, double &, double &,const QString &);
/// get a y-value from a x-value
void getYValue(Ufkt * , char, double , double &,const QString &);
void getYValue(Function * , char, double , double &,const QString &);
/// draw and calculate the area between the graph and the x-axis.
void areaUnderGraph(Ufkt *, Ufkt::PMode, double &, double &, const QString &, QPainter* );
void areaUnderGraph(Function *, Function::PMode, double &, double &, const QString &, QPainter* );
/// the calculation was cancelled by the user
bool isCalculationStopped();
......@@ -113,7 +113,7 @@ public:
/// trace mode stuff, must be accessible in KMinMax
int csmode, csparam;
Ufkt::PMode cstype;
Function::PMode cstype;
public slots:
/// Called when the user want to cancel the drawing
......@@ -167,13 +167,13 @@ private:
/// Only for printing.
void drawHeaderTable(QPainter *);
/// Draw the function plots.
void plotfkt(Ufkt *ufkt, QPainter*);
void plotfkt(Function *ufkt, QPainter*);
/// @return an appropriate pen for drawing the plot
QPen penForPlot( Ufkt * ufkt, Ufkt::PMode, bool antialias ) const;
QPen penForPlot( Function * ufkt, Function::PMode, bool antialias ) const;
/// Gets the greek pi symbol.
void setpi(QString *);
/// in trace mode checks, if the function is (near by) zero
bool root(double *, Ufkt *);
bool root(double *, Equation *);
///return the inverted color
void invertColor(QColor &, QColor &);
/// Changes the text in the statusbar
......@@ -208,18 +208,18 @@ private:
* parametric function.
* \return the parametization (angle or t) that gives the closest point.
*/
double getClosestPoint( double real_x, double real_y, Ufkt * function1, Ufkt * function2 );
double getClosestPoint( double real_x, double real_y, Function * function1, Function * function2 );
/**
* Calculates the pixel distance from \p real_x and \p real_y to the display
* point of the given polar or parametric parametric function at \p x.
*/
double pixelDistance( double real_x, double real_y, Ufkt * function1, Ufkt * function2, double x );
double pixelDistance( double real_x, double real_y, Function * function1, Function * function2, double x );
/// for areadrawing when printing
bool areaDraw;
Ufkt * areaUfkt;
Ufkt::PMode areaPMode;
Function * areaFunction;
Function::PMode areaPMode;
double areaMin, areaMax;
QString areaParameter;
......@@ -241,7 +241,7 @@ private:
bool rootflg;
/// @return whether csxpos is in the range of the view or in the custom range for the given \p plot
bool csxposValid( Ufkt * plot ) const;
bool csxposValid( Function * plot ) const;
CDiagr dgr; ///< Coordinate system
QPoint ref;
......
......@@ -32,6 +32,35 @@
#include <cmath>
//BEGIN class Value
Value::Value( const QString & expression )
{
m_value = 0.0;
if ( ! expression.isEmpty() )
updateExpression( expression );
}
bool Value::updateExpression( const QString & expression )
{
double newValue = XParser::self()->eval( expression );
if ( XParser::self()->parserError( false ) )
return false;
m_value = newValue;
m_expression = expression;
return true;
}
bool Value::operator == ( const Value & other )
{
return m_expression == other.expression();
}
//END class Value
//BEGIN class Plot
Plot::Plot( )
{
......@@ -50,97 +79,28 @@ bool Plot::operator !=( const Plot & other ) const
//END class Plot
//BEGIN class Ufkt
Ufkt::Ufkt( Type type )
: m_type( type )
//BEGIN class Equation
Equation::Equation( Type type, Function * parent )
: m_type( type ),
m_parent( parent )
{
id = 0;
mem = new unsigned char [MEMSIZE];
mptr = 0;
k = 0;
oldy = 0;
f0.visible = true;
integral_use_precision = false;
oldyprim = 0.0;
oldx = 0.0;
starty = 0.0;
startx = 0.0;
integral_precision = Settings::stepWidth();
use_slider = -1;
// min/max stuff
dmin = -M_PI;
dmax = M_PI;
str_dmin = QString("-")+QChar(960);
str_dmax = QChar(960);
usecustomxmin = false;
usecustomxmax = false;
oldy = 0;
}
Ufkt::~Ufkt()
Equation::~ Equation()
{
delete [] mem;
mem = 0;
}
bool Ufkt::copyFrom( const Ufkt & function )
{
bool changed = false;
int i = 0;
#define COPY_AND_CHECK(s) \
if ( s != function.s ) \
{ \
s = function.s; \
changed = true; \
} \
i++;
COPY_AND_CHECK( f0 ); // 0
COPY_AND_CHECK( f1 ); // 1
COPY_AND_CHECK( f2 ); // 2
COPY_AND_CHECK( integral ); // 3
COPY_AND_CHECK( integral_use_precision ); // 4
COPY_AND_CHECK( str_dmin ); // 5
COPY_AND_CHECK( str_dmax ); // 6
COPY_AND_CHECK( dmin ); // 7
COPY_AND_CHECK( dmax ); // 8
COPY_AND_CHECK( str_startx ); // 9
COPY_AND_CHECK( str_starty ); // 10
COPY_AND_CHECK( starty ); // 11
COPY_AND_CHECK( startx ); // 12
COPY_AND_CHECK( integral_precision ); // 13
COPY_AND_CHECK( use_slider ); // 14
COPY_AND_CHECK( usecustomxmin ); // 15
COPY_AND_CHECK( usecustomxmax ); // 16
// handle parameters separately
if ( parameters.count() != function.parameters.count() )
{
changed = true;
parameters = function.parameters;
}
else
{
foreach ( ParameterValueItem p, parameters )
{
if ( !function.parameters.contains( p ) )
{
changed = true;
parameters = function.parameters;
break;
}
}
}
// kDebug() << k_funcinfo << "changed="<<changed<<endl;
return changed;
}
QString Ufkt::fname( ) const
QString Equation::fname( ) const
{
int pos = m_fstr.indexOf( '(' );
if ( pos == -1 )
......@@ -153,7 +113,7 @@ QString Ufkt::fname( ) const
}
QString Ufkt::fvar( ) const
QString Equation::fvar( ) const
{
int p1 = m_fstr.indexOf( '(' );
if ( p1 == -1 )
......@@ -176,7 +136,7 @@ QString Ufkt::fvar( ) const
}
QString Ufkt::fpar( ) const
QString Equation::fpar( ) const
{
int p1 = m_fstr.indexOf( ',' );
if ( p1 == -1 )
......@@ -196,7 +156,7 @@ QString Ufkt::fpar( ) const
}
bool Ufkt::setFstr( const QString & fstr, bool force )
bool Equation::setFstr( const QString & fstr, bool force )
{
// kDebug() << "fstr: "<<fstr<<endl;
......@@ -215,11 +175,11 @@ bool Ufkt::setFstr( const QString & fstr, bool force )
QString prevFstr = m_fstr;
m_fstr = fstr;
XParser::self()->initFunction( this );
XParser::self()->initEquation( this );
if ( XParser::self()->parserError( true ) != Parser::ParseSuccess )
{
m_fstr = prevFstr;
XParser::self()->initFunction( this );
XParser::self()->initEquation( this );
// kDebug() << "BAD\n";
return false;
}
......@@ -229,4 +189,92 @@ bool Ufkt::setFstr( const QString & fstr, bool force )
return true;
}
}
//END class Ufkt
//END class Equation
//BEGIN class Function
Function::Function( Type type )
: m_type( type )
{
eq = new Equation(
(type == Cartesian) ? Equation::Cartesian :
(type == ParametricX) ? Equation::ParametricX :
(type == ParametricY) ? Equation::ParametricY : Equation::Polar,
this
);
id = 0;
f0.visible = true;
integral_use_precision = false;
k = 0;
integral_precision = Settings::stepWidth();
use_slider = -1;
// min/max stuff
dmin.updateExpression( QString("-")+QChar(960) );
dmax.updateExpression( QChar(960) );
usecustomxmin = false;
usecustomxmax = false;
}
Function::~Function()
{
delete eq;
}
bool Function::copyFrom( const Function & function )
{
bool changed = false;
int i = 0;
#define COPY_AND_CHECK(s) \
if ( s != function.s ) \
{ \
s = function.s; \
changed = true; \
} \
i++;
COPY_AND_CHECK( f0 ); // 0
COPY_AND_CHECK( f1 ); // 1
COPY_AND_CHECK( f2 ); // 2
COPY_AND_CHECK( integral ); // 3
COPY_AND_CHECK( integral_use_precision ); // 4
COPY_AND_CHECK( dmin.expression() ); // 5
COPY_AND_CHECK( dmax.expression() ); // 6
COPY_AND_CHECK( dmin ); // 7
COPY_AND_CHECK( dmax ); // 8
COPY_AND_CHECK( startx.expression() ); // 9
COPY_AND_CHECK( starty.expression() ); // 10
COPY_AND_CHECK( starty ); // 11
COPY_AND_CHECK( startx ); // 12
COPY_AND_CHECK( integral_precision ); // 13
COPY_AND_CHECK( use_slider ); // 14
COPY_AND_CHECK( usecustomxmin ); // 15
COPY_AND_CHECK( usecustomxmax ); // 16
// handle parameters separately
if ( parameters.count() != function.parameters.count() )
{
changed = true;
parameters = function.parameters;
}
else
{
foreach ( Value p, parameters )
{
if ( !function.parameters.contains( p ) )
{
changed = true;
parameters = function.parameters;
break;
}
}
}
// kDebug() << k_funcinfo << "changed="<<changed<<endl;
return changed;
}
//END class Function
......@@ -31,27 +31,49 @@
#include <QString>
/// A parameter expression and value
class ParameterValueItem
class Equation;
class Function;
/**
* This stores a string which evaluates directly to a number (i.e. without any
* input variables such as x).
*/
class Value
{
public:
ParameterValueItem(const QString &e, double v)
{
expression = e;
value = v;
};
ParameterValueItem() {;};
QString expression;
double value;
Value( const QString & expression = QString() );
bool operator==( const ParameterValueItem & vi )
{
return (vi.value == value) && (vi.expression == expression);
};
/**
* @return The value of the current expression.
*/
double value() const { return m_value; }
/**
* @return The current expression.
*/
QString expression() const { return m_expression; }
/**
* Sets the current expression. If the expression could be evaluated
* (i.e. no errors), then value is updated, the expression is saved and
* true is returned. Otherwise, just returns false.
*/
bool updateExpression( const QString & expression );
/**
* This checks if the expression strings (and hence values) are
* identical.
*/
bool operator == ( const Value & other );
/**
* Checks for inequality.
*/
bool operator != ( const Value & other ) { return !((*this) == other); }
protected:
QString m_expression;
double m_value;
};
/**
* Stores details of a plot of a function (e.g. its derivative or integral).
*/
......@@ -68,19 +90,12 @@ class Plot
};
/** Here are all atitrbutes for a function stored. */
class Ufkt
/**
* This is the non-visual mathematical expression.
*/
class Equation
{
public:
enum PMode
{
Function,
Derivative1,
Derivative2,
Integral,
};
enum Type
{
Cartesian,
......@@ -89,26 +104,24 @@ class Ufkt
Polar,
};
Ufkt( Type type );
~Ufkt();
Equation( Type type, Function * parent );
~Equation();
/// The type of function
Type type() const { return m_type; }
/**
* Copies data members across, while avoiding id, mem, mptr type
* variables.
* @return whether any values have changed.
* Pointer to the allocated memory for the tokens.
*/
bool copyFrom( const Ufkt & function );
/// Sets the parameter
void setParameter( double p ) { k = p; };
uint id;
unsigned char *mem; ///< Pointer to the allocated memory for the tokens.
unsigned char *mptr; ///< Pointer to the token.
unsigned char *mem;
/**
* Pointer to the token.
*/
unsigned char *mptr;
/**
* @return a pointer to Function parent of this Equation.
*/
Function * parent() const { return m_parent; }
/**
* @return the name of the function, e.g. for the cartesian function
* f(x)=x^2, this would return "f".
......@@ -138,37 +151,112 @@ class Ufkt
*/
bool setFstr( const QString & fstr, bool force = false );
double k, ///< Function parameter.
oldy; ///< The last y-value needed for Euler's method
QList<int> dep; /// A list with all functions this function depends on
double oldx; ///< needed for Euler's method, the last x-value
double oldy; ///< The last y-value needed for Euler's method
double oldyprim; ///< needed for Euler's method, the last y'.value
protected:
const Type m_type;
QString m_fstr;
Function * m_parent;
};
/** Here are all atitrbutes for a function. */
class Function
{
public:
enum PMode
{
Derivative0,
Derivative1,
Derivative2,
Integral,
};
enum Type
{
Cartesian,
ParametricX,
ParametricY,
Polar,
};
Function( Type type );
~Function();
/// The type of function
Type type() const { return m_type; }
/**
* Sets the parameter.
*/
void setParameter( double p ) { k = p; };
/**
* The function parameter, as set by e.g. a slider.
*/
double k;
/**
* A list with all functions this function depends on.
*/
QList<int> dep;
/**
* Copies data members across, while avoiding id, mem, mptr type
* variables.
* @return whether any values have changed.
*/
bool copyFrom( const Function & function );
uint id;
Equation * eq;
Plot f0; ///< The actual function - the "zero'th derivative"
Plot f1; ///< First derivative
Plot f2; ///< Second derivative
Plot integral; ///< integral
bool integral_use_precision:1; ///< The user can specify an unic precision for numeric prime-functions
/** Number of parameter values.
* @see FktExt::k_liste */
QString str_dmin, str_dmax, str_startx, str_starty ; /// Plot range, input strings.
double dmin, ///< Custom plot range, lower boundage.
dmax, ///< Custom plot range, upper boundage.
/** List of parameter values.
* @see FktExt::k_anz */
oldyprim, ///< needed for Euler's method, the last y'.value
oldx, ///< needed for Euler's method, the last x-value
starty,///< startposition for Euler's method, the initial y-value
startx, ///< startposition for Euler's method, the initial x-value last y'.valuenitial x-value last y'.valuenitial x-value
integral_precision; ///<precision when drawing numeric prime-functions
int use_slider; ///< -1: none (use list), else: slider number
QList<ParameterValueItem> parameters; ///< List with parameter for the function
/**
* The user can specify an unique precision for numeric prime-functions.
*/
bool integral_use_precision:1;
/**
* Custom plot range, lower boundary.
*/
Value dmin;
/**
* Custom plot range, upper boundary.
*/
Value dmax;
/**
* Start position for Euler's method, the initial y-value.
*/
Value starty;
/**
* Start position for Euler's method, the initial x-value.
*/
Value startx;
/**
* Precision when drawing numeric prime-functions.
*/
double integral_precision;
/**
* -1: None (use list)
* else: slider number.
*/
int use_slider;
/**
* List with parameter for the function.
*/
QList<Value> parameters;
bool usecustomxmin:1;
bool usecustomxmax:1;
// TODO double slider_min, slider_max; ///< extreme values of the slider
// TODO double slider_min, slider_max; ///< extreme values of the slider
protected:
const Type m_type;
QString m_fstr;
};
......
This diff is collapsed.
......@@ -42,7 +42,7 @@ class FunctionListItem;
class FunctionListWidget;
class KMenu;
class QTimer;
class Ufkt;
class Function;
class View;
class XParser;
......@@ -180,7 +180,7 @@ class FunctionEditor : public QDockWidget
* If we are currently editing a cartesian function, this will be set
* to its parameter list.
*/
QList<ParameterValueItem> m_parameters;
QList<Value> m_parameters;
/**
* The list of functions.
*/
......
......@@ -100,10 +100,10 @@ void KConstantEditor::cmdDelete_clicked()
{
QChar currentConstant = constantText[0];
// for( QVector<Ufkt>::iterator it = View::self()->parser()->ufkt.begin(); it != View::self()->parser()->ufkt.end(); ++it)
foreach ( Ufkt * it, View::self()->parser()->m_ufkt )
// for( QVector<Function>::iterator it = View::self()->parser()->ufkt.begin(); it != View::self()->parser()->ufkt.end(); ++it)
foreach ( Function * it, View::self()->parser()->m_ufkt )
{
QString str = it->fstr();
QString str = it->eq->fstr();
if ( str.indexOf( currentConstant, str.indexOf(')') ) != -1 )
{
KMessageBox::sorry(this, i18n("A function uses this constant; therefore, it cannot be removed."));
......
......@@ -143,25 +143,25 @@ void KMinMax::updateFunctions()
m_mainWidget->list->clear();