Commit ab182a46 authored by David Saxton's avatar David Saxton

Fixed root-finding: was ignoring the type of plot (it was assuming the plot

was not a derivative or integral).

svn path=/trunk/KDE/kdeedu/kmplot/; revision=530483
parent 8bdf3484
......@@ -252,10 +252,10 @@ double View::value( Equation * eq, Function::PMode mode, double x )
return XParser::self()->fkt( eq, x );
case Function::Derivative1:
return XParser::self()->derivative1( eq, x, dx );
return XParser::self()->derivative( 0, Function::Derivative1, eq, x, dx );
case Function::Derivative2:
return XParser::self()->derivative2( eq, x, dx );
return XParser::self()->derivative( 0, Function::Derivative2, eq, x, dx );
case Function::Integral:
return XParser::self()->integral( eq, x, dx );
......@@ -456,7 +456,18 @@ void View::plotFunction(Function *ufkt, QPainter *pDC)
if(mflg<=1)
{
if ( drawIntegral && (x >= m_integralDrawSettings.dmin) && (x <= m_integralDrawSettings.dmax) )
pDC->drawRect( QRectF( p1, QSizeF( p2.x()-p1.x(), p2.y() - CDiagr::self()->yToPixel( 0 ) ) ) );
{
double y0 = CDiagr::self()->yToPixel( 0 );
QPointF points[4];
points[0] = QPointF( p1.x(), y0 );
points[1] = QPointF( p2.x(), y0 );
points[2] = QPointF( p2.x(), p2.y() );
points[3] = QPointF( p1.x(), p1.y() );
pDC->drawPolygon( points, 4 );
// pDC->drawRect( QRectF( p1, QSizeF( p2.x()-p1.x(), CDiagr::self()->yToPixel( 0 ) - p2.y() ) ) );
}
else
{
if ( penShouldDraw( totalLength, ufkt, p_mode ) )
......@@ -779,7 +790,7 @@ void View::setpi(QString *s)
}
bool View::root(double *x0, Equation *it)
bool View::findRoot( double *x0, Function::PMode plot, Equation *it )
{
if(m_haveRoot)
return false;
......@@ -797,13 +808,13 @@ bool View::root(double *x0, Equation *it)
double dx;
do
{
double df = XParser::self()->derivative1( it, *x0, (m_xmax-m_xmin)*1e-5 );
double df = XParser::self()->derivative( 1, plot, it, *x0, (m_xmax-m_xmin)*1e-5 );
if ( qAbs(df) < 1e-20 )
df = 1e-20 * ((df < 0) ? -1 : 1);
dx = y / df;
*x0 -= dx;
y = XParser::self()->fkt( it, *x0 );
y = value( it, plot, *x0 );
kDebug() << "k="<<k<<": ("<<*x0<<","<<y<<")\n";
......@@ -1409,7 +1420,7 @@ bool View::updateCrosshairPosition()
else if(fabs(CDiagr::self()->yToReal(ptl.y())) < (m_ymax-m_ymin)/80)
{
double x0;
if ( root( &x0, it->eq[0] ) )
if ( findRoot( &x0, m_currentFunctionPlot, it->eq[0] ) )
{
QString str=" ";
str+=i18n("root");
......
......@@ -147,7 +147,9 @@ class View : public QWidget, virtual public ViewIface
KToggleAction * m_menuSliderAction;
void updateSliders(); /// show only needed sliders
/// Convert a width in mm to a suitable QPen width for drawing
/**
* Convert a width in mm to a suitable QPen width for drawing.
*/
double mmToPenWidth( double width_mm, bool antialias ) const;
/** Current plot range endge. */
......@@ -200,12 +202,12 @@ protected slots:
signals:
void setStatusBarText(const QString &);
protected:
/// called when focus is lost
virtual void focusOutEvent( QFocusEvent * );
/// called when focus is gained
virtual void focusInEvent( QFocusEvent * );
protected:
/// called when focus is lost
virtual void focusOutEvent( QFocusEvent * );
/// called when focus is gained
virtual void focusInEvent( QFocusEvent * );
private:
/**
* Print out table with additional information. Only for printing.
......@@ -233,7 +235,7 @@ protected:
* \p x (which is then set to the exact root if found).
* \returns whether a root was found.
*/
bool root( double * x, Equation * eq );
bool findRoot( double * x, Function::PMode plot, Equation * eq );
///return the inverted color
void invertColor(QColor &, QColor &);
/// Changes the text in the statusbar
......@@ -273,17 +275,16 @@ protected:
* \return the function position of the closest plot if one was found.
*/
QPointF getPlotUnderMouse();
/**
* Finds the closest point to \p pos to the given function.
* \return the parametization (angle or t) that gives the closest point.
*/
double getClosestPoint( const QPointF & pos, Function * function, Function::PMode mode );
/**
* Calculates the pixel distance from \p pos to the display point of the
* given function at \p x.
*/
double pixelDistance( const QPointF & pos, Function * function, Function::PMode mode, double x );
/**
* Finds the closest point to \p pos to the given function.
* \return the parametization (angle or t) that gives the closest point.
*/
double getClosestPoint( const QPointF & pos, Function * function, Function::PMode mode );
/**
* Calculates the pixel distance from \p pos to the display point of the
* given function at \p x.
*/
double pixelDistance( const QPointF & pos, Function * function, Function::PMode mode, double x );
/**
* Convenience function for calculating the value of \p eq using the
* given \p mode
......
......@@ -458,7 +458,7 @@ void FunctionEditor::createParametric()
m_functionID = XParser::self()->addFunction( QString("x%1(t)=0").arg( name ), QString("y%1(t)=0").arg( name ), Function::Parametric );
assert( m_functionID != -1 );
kDebug() << "Created parametric, so requestion state save.\n";
kDebug() << "Created parametric, so requesting state save.\n";
MainDlg::self()->requestSaveCurrentState();
}
......
......@@ -138,16 +138,49 @@ bool XParser::getext( Function *item, const QString fstr )
return true;
}
double XParser::derivative1( Equation *u_item, double x, double h )
{
return ( fkt(u_item, x + h ) - fkt( u_item, x ) ) / h;
}
double XParser::derivative2( Equation *u_item, double x, double h )
double XParser::derivative( unsigned n, Function::PMode plot, Equation * eq, double x, double h )
{
return ( fkt( u_item, x + h + h ) - 2 * fkt( u_item, x + h ) + fkt( u_item, x ) ) / h / h;
switch ( plot )
{
case Function::Derivative0:
break;
case Function::Derivative1:
n += 1;
break;
case Function::Derivative2:
n += 2;
break;
case Function::Integral:
{
if ( n == 0 )
return integral( eq, x, h );
n -= 1;
break;
}
}
switch ( n )
{
case 0:
return fkt( eq, x );
case 1:
return ( fkt(eq, x + (h/2) ) - fkt( eq, x - (h/2) ) ) / h;
case 2:
return ( fkt( eq, x + h ) - 2 * fkt( eq, x ) + fkt( eq, x - h ) ) / (h*h);
default:
return ( derivative( n-1, Function::Derivative0, eq, x+(h/2), (h/4) ) - derivative( n-1, Function::Derivative0, eq, x-(h/2), (h/4) ) ) / h;
}
}
void XParser::findFunctionName(QString &function_name, int const id, int const type)
{
char last_character;
......
......@@ -47,18 +47,25 @@ class XParser : public Parser
static XParser * self( bool * modified = 0 );
~XParser();
/// Evaluates the 1st dreivative of the function with intex \a ix
double derivative1( Equation * eq, double x, double h );
/// Evaluates the 2nd dreivative of the function with intex \a ix
double derivative2( Equation * eq, double x, double h );
/**
* Evaluates the \p n th derivative of the function using numerical
* stepsize \p h .
* \param plot This should be the plot to take the derivative of, and
* it adjusts \p n accordingly. For example, passing \p plot =
* Derivative1 and \p n = 1 is the same as passing \p plot = Derivative0
* and \p n = 2.
*/
double derivative( unsigned n, Function::PMode plot, Equation * eq, double x, double h );
/**
* Calculates the value of the equation using numerical integration
* with the given step size \p h (which is only used as a hint).
*/
double integral( Equation * eq, double x, double h );
/// Line width default
QColor defaultColor(int function);
/**
* The settings contain 10 default function colors. This returns the
* (function % 10)th color.
*/
QColor defaultColor(int function);
virtual int addFunction( QString, QString, Function::Type type );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment