Logo Search packages:      
Sourcecode: kdeedu-kde4 version File versions  Download package

function.h

/*
* KmPlot - a math. function plotter for the KDE-Desktop
*
* Copyright (C) 1998, 1999, 2000, 2002  Klaus-Dieter M´┐Żler <kd.moeller@t-online.de>
*                                 2006  David Saxton <david@bluehaze.org>
*               
* This file is part of the KDE Project.
* KmPlot is part of the KDE-EDU Project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#ifndef FUNCTION_H
#define FUNCTION_H

#include "vector.h"

#include <QByteArray>
#include <QColor>
#include <QFlags>
#include <QGradient>

#include <QVector>

class Equation;
class Function;
class Plot;


/**
 * Maximum number of plus-minus-s; each added one doubles the number of combinations
 * which quickly grows. So put a bound on the number allowed.
 */
extern int MAX_PM; 


/**
 * This stores a string which evaluates directly to a number (i.e. without any
 * input variables such as x).
 */
00054 class Value
{
      public:
            /**
             * Initializes Value with \p expression.
             * This will have the value 0 if \p expression is empty or unparsable.
             */
            Value( const QString & expression = QString() );
            /**
             * Converts \p value to a string (see Parser::number) and initializes
             * this with the \p value.
             */
            explicit Value( double value );
            
            /**
             * @return The value of the current expression.
             */
00071             double value() const { return m_value; }
            /**
             * @return The current expression.
             */
00075             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 );
            /**
             * Converts \p value to a string (see Parser::number) and uses it for
             * the current expression.
             */
            void updateExpression( double value );
            /**
             * This checks if the expression strings (and hence values) are
             * identical.
             */
            bool operator == ( const Value & other ) const;
            /**
             * Checks for inequality.
             */
00095             bool operator != ( const Value & other ) const { return !((*this) == other); }
            
      protected:
            QString m_expression;
            double m_value;
};


/**
 * Stores details of the appearance of a plot of a function (e.g. its
 * derivative or integral).
 */
00107 class PlotAppearance
{
      public:
            PlotAppearance();
            
            // NOTE: When adding more members to this class, remember to update
            // the function PlotAppearance::operator!= and the functions in
            // KmPlotIO for saving / loading the plot appearance

00116             double lineWidth;       ///< line width in mm
00117             QColor color;                 ///< color that the plot will be drawn in
00118             Qt::PenStyle style;           ///< pen style (e.g. dolif, dashes, dotted, etc)
00119             QGradient gradient;           ///< the gradient if useGradient is true
00120             bool useGradient:1;           ///< for plots with parameters, whether to use gradient instead of color
00121             bool showExtrema:1;           ///< for cartesian functions, whether to show the extreme values of the function
00122             bool showTangentField:1;///< whether to draw the tangent field (for differential equations
00123             bool visible:1;               ///< whether to display this plot
00124             bool showPlotName:1;    ///< whether to show the name of the plot on the graph
            
            bool operator != ( const PlotAppearance & other ) const;
            
            /**
             * Converts a pen style to a string (for non-displaying uses such as
             * saving to file).
             */
            static QString penStyleToString( Qt::PenStyle style );
            /**
             * Converts a string (as returned by penStyleTostring) to a pen style.
             */
            static Qt::PenStyle stringToPenStyle( const QString & style );
};


/**
 * Used in differential equations; contains the initial conditions and the
 * currently calculated value (used as a cache).
 */
00144 class DifferentialState
{
      public:
            DifferentialState();
            DifferentialState( int order );
            
            /**
             * Resizes y, y0. Also calls resetToInitial.
             */
            void setOrder( int order );
            /**
             * Sets y=y0, x=x0.
             */
            void resetToInitial();
            
00159             Value x0; ///< the initial x-value
00160             QVector<Value> y0; ///< the value of ( f, f', f'', ...., f^(n) ) at x0
00161             double x; ///< the current x value
00162             Vector y; ///< the value of ( f, f', f'', ...., f^(n) ) at x
            
            /**
             * Whether the initial conditions and current state are the same.
             */
            bool operator == ( const DifferentialState & other ) const;
};


class DifferentialStates
{
      public:
            DifferentialStates();
            
            /**
             * For Cartesian equations, can only have one state (for integrals).
             */
            void setUniqueState( bool unique );
            /**
             * \see order()
             */
            void setOrder( int order );
            /**
             * Creates a differential state. If this is for a Cartesian equation
             * and there is already a differential state, then that will be
             * returned instead, since a Cartesian equation can only have one
             * differential state.
             */
            DifferentialState * add();
            /**
             * The order of the differential equations, e.g. "f''(x) = -f" is of
             * order 2.
             */
            int order() const { return m_order; }
            /**
             * The number of differential states.
             */
            int size() const { return m_data.size(); }
            /**
             * Calls DifferentialState::resetToInitial for each state; i.e. resets
             * the cached information about the state of the differential equation.
             */
            void resetToInitial();
            /**
             * The maximum step-size (and hence minimum precision) used in the RK4
             * method (see XParser::differential). Of course, a smaller step size
             * may be used in the visible section of a differential plot.
             */
            Value step() const { return m_step; }
            /**
             * \see maximumStep();
             * \return whether could successfully set the step, i.e. that it is
             * strictly positive.
             */
            bool setStep( const Value & step );
            
            bool operator == ( const DifferentialStates & other ) const { return (m_data == other.m_data) && (m_step == other.m_step); }
            bool operator != ( const DifferentialStates & other ) const { return !(*this == other); }
            DifferentialState & operator[] ( int i ) { return m_data[i]; }
            const DifferentialState & operator[] ( int i ) const { return m_data[i]; }
            void remove ( int i ) { m_data.remove(i); }
            void remove ( int i, int count ) { m_data.remove( i, count ); }
            void removeAll() { m_data.clear(); }
            
      protected:
            QVector<DifferentialState> m_data;
            int m_order;
            bool m_uniqueState;
            Value m_step;
};


/**
 * This is the non-visual mathematical expression.
 * \note when adding new member variables, make sure to update operator !=
 * and operator =.
 */
00239 class Equation
{
      public:
            enum Type
            {
            Constant,
                  Cartesian,
                  ParametricX,
                  ParametricY,
                  Polar,
                  Implicit,
                  Differential
            };
            
            Equation( Type type, Function * parent );
            ~Equation();
            
            /// The type of function
00257             Type type() const { return m_type; }
            /**
             * \return whether this Equation has different user-entered values to
             * the \p other equation.
             */
            bool operator != ( const Equation & other );
            /**
             * Assigns the value in \p other to this equation.
             */
            Equation & operator = ( const Equation & other );
            /**
             * Pointer to the allocated memory for the tokens.
             */
00270             QByteArray mem;
            /**
             * Array index to the token.
             */
00274             char *mptr;
            /**
             * @return a pointer to Function parent of this Equation.
             */
00278             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".
             */
            QString name( bool removePrimes = true ) const;
            /**
             * \return a list of variables, e.g. {x} for "f(x)=y", and {x,y,k} for
             * "f(x,y,k)=(x+k)(y+k)".
             */
00288             QStringList variables() const { return m_variables; }
            /**
             * \return whether the function accepts a parameter in addition to the x
             * (and possibly y) variables.
             */
00293             bool usesParameter() const { return m_usesParameter; }
            /**
             * \return the name of the parameter variable (or a blank string if a
             * parameter is not used).
             */
            QString parameterName() const;
            /**
             * The full function expression, e.g. "f(x,k)=(x+k)(x-k)".
             */
00302             QString fstr() const { return m_fstr; }
            /**
             * @see fstr()
             * @param string the equation
             * @param error if non-null, then will be set to the parser error (or
             * success).
             * @param errorPosition the error position
             * @param force Update the internal equation string even if it could not
             * be parsed correctly. Used in opening old files, for example, in case
             * something internal to kmplot has changed that results in the equation
             * no longer being parsable.
             * @return whether \p fstr could be parsed correctly. Note that if it
             * was not parsed correctly, then this will return false and this class
             * will not be updated.
             */
            bool setFstr( const QString & string, int * error = 0, int * errorPosition = 0, bool force = false );
            /**
             * \return true if the fstr looks like "f(x) = ..."
             * \return false if the fstr looks like "y = ..." (note that this
             * depends on the type of equation, so if this is a Cartesian equation
             * and the fstr looks like "a = ..." (not y) then it'll be considered a
             * function, even if it isn't a very useful one.
             */
            bool looksLikeFunction() const;
            /**
             * \return the order of the differential equations.
             */
            int order() const;
            /**
             * \return the number of plus-minus symbols in the equation.
             */
            int pmCount() const;
            
            /// For differential equations, all the states
00336             DifferentialStates differentialStates;
            
            /**
             * The current plus-minus signature (true for plus, false for minus).
             */
00341             QVector<bool> pmSignature() const { return m_pmSignature; }
            /**
             * \see pmSignature.
             */
            void setPMSignature( QVector<bool> pmSignature );
            
      protected:
            /**
             * Updates m_variables.
             */
            void updateVariables();
            
            bool m_usesParameter;
            const Type m_type;
            QString m_fstr;
            Function * m_parent;
            QVector<bool> m_pmSignature;
            /**
             * Cached list of variables. Updated when setFstr is called.
             */
00361             QStringList m_variables;
};


/**
 * Which parameters to use and how.
 */
00368  class ParameterSettings
{
      public:
            ParameterSettings();
            
            bool operator == ( const ParameterSettings & other ) const;
            bool operator != ( const ParameterSettings & other ) const { return !((*this) == other); }
            
00376             bool animating; ///< if true, then useSlider and useList are ignored, parameter value is assumed to be updated
            bool useSlider;
            int sliderID;
            bool useList;
            QList< Value > list;
};


/**
 * Uniquely identifies a parameter (which could be from the list of Values
 * stored in a Function or from a Slider.
 */
00388  class Parameter
{
      public:
            enum Type { Unknown, Animated, Slider, List };
            Parameter( Type type = Unknown );
            
            Type type() const { return m_type; }
            /**
             * The slider ID specifies which slider to use (e.g. "2" specifies the
             * third slider).
             */
00399             void setSliderID( int id ) { m_sliderID = id; }
            /**
             * The list pos specifies which parameter to use in the list
             * ParameterSettings::list.
             */
00404             void setListPos( int pos ) { m_listPos = pos; }
            /**
             * \see setSliderID
             */
00408             int sliderID() const { return m_sliderID; }
            /**
             * \see setListPos
             */
00412             int listPos() const { return m_listPos; }
            /**
             * \return Whether the parameter referred to is the same.
             */
            bool operator == ( const Parameter & other ) const;
            
      protected:
            Type m_type;
            int m_sliderID;
            int m_listPos;
};


/** Here are all atitrbutes for a function. */
00426 class Function
{
      public:
            enum PMode
            {
                  Derivative0,
                  Derivative1,
                  Derivative2,
                  Integral
            };
            
            enum Type
            {
                  Cartesian,
                  Parametric,
                  Polar,
                  Implicit,
                  Differential
            };
            
            Function( Type type );
            ~Function();
            
            /**
             * \return the type of function.
             */
00452             Type type() const { return m_type; }
            
00454             enum PlotCombination
            {
00456                   DifferentParameters           = 0x1,            ///< For all the different parameters
00457                   DifferentDerivatives    = 0x2,            ///< Derivatives of the function
00458                   DifferentPMSignatures   = 0x4,            ///< Plus-minus combinations
00459                   DifferentInitialStates  = 0x8,            ///< For differential equations; different states
                  AllCombinations               = 0x20-1
            };
            typedef QFlags<PlotCombination> PlotCombinations;
            
            /**
             * \return a list of plots for this function, 
             */
            QList< Plot > plots( PlotCombinations combinations = AllCombinations ) const;
            /**
             * \return A string for displaying to the user that identifies this
             * function. For identifying plots uniquely, see Plot::name()
             */
            QString name() const;
            /**
             * Converts the type to a string (which is used in save files).
             */
            static QString typeToString( Type type );
            /**
             * Converts the string to a type (used when loading files).
             */
            static Type stringToType( const QString & type );
            /**
             * Sets the current working parameter (which is used in calculations).
             */
00484             void setParameter( double p ) { k = p; }
            /**
             * The function parameter, as set by e.g. a slider.
             */
00488             double k;
            /**
             * Clears the list of functions that this function depends on.
             */
00492             void clearFunctionDependencies() { m_dependencies.clear(); }
            /**
             * Adds \p function to the list of functions that this function depends
             * on. For example, if this function is "f(x) = 1 + g(x)", then this
             * function depends on the function g(x).
             */
            void addFunctionDependency( Function * function );
            /**
             * \return whether this function or any of the functions that this
             * function depend on, etc, depend on \p function.
             */
            bool dependsOn( Function * function ) const;
            /**
             * Copies data members across, while avoiding id, mem, mptr type
             * variables.
             * @return whether any values have changed.
             */
            bool copyFrom( const Function & function );
            /**
             * \return the function ID, used to identify it from the parser.
             */
00513             uint id() const { return m_id; }
            /**
             * \see id()
             */
00517             void setId( uint id ) { m_id = id; }
            QVector<Equation*> eq;
            /**
             * \return A reference to the appearance of the given plot type.
             */
            PlotAppearance & plotAppearance( PMode plot );
            /**
             * \return The appearance of the given plot type.
             */
            PlotAppearance plotAppearance( PMode plot ) const;
            /**
             * \returns true if all plots are hidden (i.e. plotAppearance().visible
             * is false for all plot types).
             * \returns false otherwise.
             */
            bool allPlotsAreHidden() const;
            /**
             * Custom plot range, lower boundary.
             */
00536             Value dmin;
            /**
             * Custom plot range, upper boundary.
             */
00540             Value dmax;
            
            ParameterSettings m_parameters;
            
            bool usecustomxmin:1;
            bool usecustomxmax:1;
            // TODO double slider_min, slider_max; ///< extreme values of the slider
            
            /**
             * For use with implicit functions, when either x or y is held fixed.
             */
00551             enum ImplicitMode
            {
                  FixedX,
                  FixedY,
                  UnfixedXY
            };
            ImplicitMode m_implicitMode;
            /**
             * The value of x when this is an implicit function and x is fixed.
             */
00561             double x;
            /**
             * The value of y when this is an implicit function and y is fixed.
             */
00565             double y;
            
            /**
             * A list with all functions that this function depends on.
             */
00570             QList<int> m_dependencies;
            
      protected:
            uint m_id;
            const Type m_type;
            
00576             PlotAppearance f0;            ///< The actual function - the "zero'th derivative"
00577             PlotAppearance f1;            ///< First derivative
00578             PlotAppearance f2;            ///< Second derivative
00579             PlotAppearance integral;      ///< integral
};




/**
 * Uniquely identifies a single plot (i.e. a single curvy line in the View).
 */
00588 class Plot
{
      public:
            Plot();
            
            bool operator == ( const Plot & other ) const;
            
            void setFunctionID( int id );
            /**
             * Changes the plotMode equivalent to differentiating.
             */
            void differentiate();
            /**
             * Changes the plotMode equivalent to integrating.
             */
            void integrate();
            int functionID() const { return m_functionID; }
            /**
             * \return a pointer to the function with ID as set by setFunctionID
             */
00608             Function * function() const { return m_function; }
            /**
             * \return the value of the parameter associated with this plot.
             */
            double parameterValue() const;
            /**
             * Generates a name appropriate for distinguishing the plot from others.
             */
            QString name() const;
            /**
             * The color that the plot should be drawn with.
             */
            QColor color() const;
            /**
             * Parameter in use.
             */
00624             Parameter parameter;
            /**
             * Which derivative.
             */
00628             Function::PMode plotMode;
            /**
             * Converts the plotMode to the derivative number, e.g.
             * Function::Derivative1 -> 1, and Function::Integral -> -1
             */
            int derivativeNumber() const;
            /**
             * Assigned when Function::allPlots() is called. The plots for each
             * plotMode are numbered 0 to *.
             */
00638             int plotNumber;
            /**
             * The total number of plots of the same plotMode as this.
             */
00642             int plotNumberCount;
            /**
             * Updates the current working parameter value in the function that
             * this plot is for and the plus-minus signature for the function's
             * equations.
             */
            void updateFunction() const;
            /**
             * For differential equations, which state to draw. It's probably
             * easier to use the function differentialState(), however.
             */
00653             int stateNumber;
            /**
             * \return the differential state for the plot (or 0 if no state).
             */
            DifferentialState * state() const;
            /**
             * For equations containing a plus-minus symbols, this indicates
             * whether to take the plus or the minus for each one. The list is for
             * each equation of the function (so typically, the list will only be
             * of size one, but parametric functions will have two).
             */
00664             QList< QVector<bool> > pmSignature;
            
      protected:
            void updateCached();
            
00669             int m_functionID;             ///< ID of function
00670             Function * m_function;        ///< Cached pointer to function
};


#endif      // FUNCTION_H

Generated by  Doxygen 1.6.0   Back to index