Commit f9ed94d4 authored by David Saxton's avatar David Saxton

Fixed hacky way that parametric function were stored. Before, had two Ufkts

representing each equation; now, they are in the same object (Function).

svn path=/trunk/KDE/kdeedu/kmplot/; revision=526313
parent 52ee4b86
......@@ -113,3 +113,5 @@ kmplot/coordsconfigdialog.cpp
kmplot/coordsconfigdialog.h
kmplot/function.cpp
kmplot/function.h
kmplot/kmplot.cpp
kmplot/kmplot.h
This diff is collapsed.
......@@ -208,12 +208,12 @@ private:
* parametric function.
* \return the parametization (angle or t) that gives the closest point.
*/
double getClosestPoint( double real_x, double real_y, Function * function1, Function * function2 );
double getClosestPoint( double real_x, double real_y, Function * function );
/**
* 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, Function * function1, Function * function2, double x );
double pixelDistance( double real_x, double real_y, Function * function, double x );
/// for areadrawing when printing
......
......@@ -102,10 +102,16 @@ Equation::~ Equation()
QString Equation::fname( ) const
{
if ( m_fstr.isEmpty() )
{
// kWarning() << k_funcinfo << "m_fstr is empty.\n";
return QString();
}
int pos = m_fstr.indexOf( '(' );
if ( pos == -1 )
{
kWarning() << k_funcinfo << "No bracket!\n";
// kWarning() << k_funcinfo << "No bracket!\n";
return QString();
}
......@@ -115,10 +121,16 @@ QString Equation::fname( ) const
QString Equation::fvar( ) const
{
if ( m_fstr.isEmpty() )
{
// kWarning() << k_funcinfo << "m_fstr is empty.\n";
return QString();
}
int p1 = m_fstr.indexOf( '(' );
if ( p1 == -1 )
{
kWarning() << k_funcinfo << "No bracket!\n";
// kWarning() << k_funcinfo << "No bracket!\n";
return QString();
}
......@@ -128,7 +140,7 @@ QString Equation::fvar( ) const
if ( p2 == -1 )
{
kWarning() << k_funcinfo << "No closing!\n";
// kWarning() << k_funcinfo << "No closing!\n";
return QString();
}
......@@ -138,6 +150,12 @@ QString Equation::fvar( ) const
QString Equation::fpar( ) const
{
if ( m_fstr.isEmpty() )
{
// kWarning() << k_funcinfo << "m_fstr is empty.\n";
return QString();
}
int p1 = m_fstr.indexOf( ',' );
if ( p1 == -1 )
{
......@@ -148,7 +166,7 @@ QString Equation::fpar( ) const
int p2 = m_fstr.indexOf( ')' );
if ( p2 == -1 )
{
kWarning() << k_funcinfo << "No closing bracket!\n";
// kWarning() << k_funcinfo << "No closing bracket!\n";
return QString();
}
......@@ -158,7 +176,7 @@ QString Equation::fpar( ) const
bool Equation::setFstr( const QString & fstr, bool force )
{
// kDebug() << "fstr: "<<fstr<<endl;
// kDebug() << k_funcinfo << "fstr: "<<fstr<<endl;
if ( force )
{
......@@ -169,7 +187,7 @@ bool Equation::setFstr( const QString & fstr, bool force )
if ( !XParser::self()->isFstrValid( fstr ) )
{
XParser::self()->parserError( true );
// kDebug() << "invalid fstr\n";
// kDebug() << k_funcinfo << "invalid fstr\n";
return false;
}
......@@ -180,12 +198,12 @@ bool Equation::setFstr( const QString & fstr, bool force )
{
m_fstr = prevFstr;
XParser::self()->initEquation( this );
// kDebug() << "BAD\n";
// kDebug() << k_funcinfo << "BAD\n";
return false;
}
else
{
// kDebug() << "GoOd :)\n";
// kDebug() << k_funcinfo << "GoOd :)\n";
return true;
}
}
......@@ -196,12 +214,23 @@ bool Equation::setFstr( const QString & fstr, bool force )
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
);
eq[1] = 0;
switch ( m_type )
{
case Cartesian:
eq[0] = new Equation( Equation::Cartesian, this );
break;
case Polar:
eq[0] = new Equation( Equation::Polar, this );
break;
case Parametric:
eq[0] = new Equation( Equation::ParametricX, this );
eq[1] = new Equation( Equation::ParametricY, this );
break;
}
id = 0;
f0.visible = true;
......@@ -221,7 +250,11 @@ Function::Function( Type type )
Function::~Function()
{
delete eq;
for ( unsigned i = 0; i < 2; ++i )
{
delete eq[i];
eq[i] = 0;
}
}
......@@ -242,18 +275,14 @@ bool Function::copyFrom( const Function & function )
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
COPY_AND_CHECK( dmin ); // 5
COPY_AND_CHECK( dmax ); // 6
COPY_AND_CHECK( starty ); // 7
COPY_AND_CHECK( startx ); // 8
COPY_AND_CHECK( integral_precision ); // 9
COPY_AND_CHECK( use_slider ); // 10
COPY_AND_CHECK( usecustomxmin ); // 11
COPY_AND_CHECK( usecustomxmax ); // 12
// handle parameters separately
if ( parameters.count() != function.parameters.count() )
......@@ -277,4 +306,39 @@ bool Function::copyFrom( const Function & function )
// kDebug() << k_funcinfo << "changed="<<changed<<endl;
return changed;
}
QString Function::typeToString( Type type )
{
switch ( type )
{
case Cartesian:
return "cartesian";
case Parametric:
return "parametric";
case Polar:
return "polar";
}
kWarning() << "Unknown type " << type << endl;
return "unknown";
}
Function::Type Function::stringToType( const QString & type )
{
if ( type == "cartesian" )
return Cartesian;
if ( type == "parametric" )
return Parametric;
if ( type == "polar" )
return Polar;
kWarning() << "Unknown type " << type << endl;
return Cartesian;
}
//END class Function
......@@ -178,8 +178,7 @@ class Function
enum Type
{
Cartesian,
ParametricX,
ParametricY,
Parametric,
Polar,
};
......@@ -188,7 +187,14 @@ class Function
/// The type of function
Type type() const { return m_type; }
/**
* 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 parameter.
*/
......@@ -211,7 +217,7 @@ class Function
bool copyFrom( const Function & function );
uint id;
Equation * eq;
Equation * eq[2];
Plot f0; ///< The actual function - the "zero'th derivative"
Plot f1; ///< First derivative
......
......@@ -54,9 +54,7 @@ class FunctionEditorWidget : public QWidget, public Ui::FunctionEditorWidget
FunctionEditor::FunctionEditor( KMenu * createNewPlotsMenu, QWidget * parent )
: QDockWidget( i18n("Function Editor"), parent )
{
m_function = -1;
m_functionX = -1;
m_functionY = -1;
m_functionID = -1;
m_createNewPlotsMenu = createNewPlotsMenu;
// need a name for saving and restoring the position of this dock widget
......@@ -149,16 +147,13 @@ void FunctionEditor::deleteCurrent()
return;
}
if ( !View::self()->parser()->delfkt( functionItem->function1() ) )
if ( !View::self()->parser()->delfkt( functionItem->function() ) )
{
kDebug() << "Couldn't delete function 1.\n";
kDebug() << "Couldn't delete function.\n";
// couldn't delete it, as e.g. another function depends on it
return;
}
kDebug() << "Deleting function 2 status: " <<
View::self()->parser()->delfkt( functionItem->function2() ) << endl;
kDebug() << "Deleted current, so requestion state save.\n";
View::self()->mainDlg()->requestSaveCurrentState();
View::self()->drawPlot();
......@@ -187,9 +182,7 @@ void FunctionEditor::syncFunctionList()
{
FunctionListItem * item = static_cast<FunctionListItem*>(m_functionList->item( row ));
currentFunctionItems << item;
currentIDs[ item->function1() ] = item;
if ( item->function2() != -1 )
currentIDs[ item->function2() ] = item;
currentIDs[ item->function() ] = item;
// also update what is displayed
item->update();
......@@ -210,20 +203,7 @@ void FunctionEditor::syncFunctionList()
continue;
}
if ( function->type() == Function::ParametricY )
continue;
int f1 = function->id;
int f2 = -1;
if ( function->type() == Function::ParametricX )
{
++it;
assert( it != View::self()->parser()->m_ufkt.end() );
f2 = (*it)->id;
}
toSelect = new FunctionListItem( m_functionList, f1, f2 );
toSelect = new FunctionListItem( m_functionList, function->id );
newFunctionCount++;
}
......@@ -237,14 +217,8 @@ void FunctionEditor::syncFunctionList()
// Now, any IDs left in currentIDs are of functions that have been deleted
foreach ( FunctionListItem * item, currentFunctionItems )
{
if ( m_function == item->function1() )
m_function = -1;
else if ( m_functionX == item->function1() || m_functionY == item->function2() )
{
m_functionX = -1;
m_functionY = -1;
}
if ( m_functionID == item->function() )
m_functionID = -1;
delete m_functionList->takeItem( m_functionList->row( item ) );
}
......@@ -273,7 +247,7 @@ void FunctionEditor::setCurrentFunction( int functionID )
for ( int row = 0; row < m_functionList->count(); ++row )
{
FunctionListItem * item = static_cast<FunctionListItem*>(m_functionList->item( row ));
if ( (item->function1() != functionID) && (item->function2() != functionID) )
if ( item->function() != functionID )
continue;
m_functionList->setCurrentRow( row );
......@@ -290,27 +264,24 @@ void FunctionEditor::functionSelected( QListWidgetItem * item )
FunctionListItem * functionItem = static_cast<FunctionListItem*>(item);
if ( functionItem->function2() != -1 )
{
m_function = -1;
m_functionX = functionItem->function1();
m_functionY = functionItem->function2();
initFromParametric();
}
else
m_functionID = functionItem->function();
Function * f = XParser::self()->functionWithID( m_functionID );
if ( !f )
return;
switch ( f->type() )
{
m_function = functionItem->function1();
m_functionX = -1;
m_functionY = -1;
if ( Function * function = View::self()->parser()->functionWithID(m_function) )
{
if ( function->type() == Function::Polar )
initFromPolar();
else
initFromCartesian();
}
case Function::Cartesian:
initFromCartesian();
break;
case Function::Polar:
initFromPolar();
break;
case Function::Parametric:
initFromParametric();
break;
}
functionItem->update();
......@@ -321,17 +292,17 @@ void FunctionEditor::initFromCartesian()
{
// kDebug() << k_funcinfo << endl;
Function * f = View::self()->parser()->functionWithID(m_function);
Function * f = View::self()->parser()->functionWithID(m_functionID);
if ( !f )
{
kWarning() << k_funcinfo << "No f!\n";
kWarning() << k_funcinfo << "No f! (id="<<m_functionID<<")\n";
return;
}
m_parameters = f->parameters;
m_editor->cartesianEquation->setText( f->eq->fstr() );
m_editor->cartesianEquation->setText( f->eq[0]->fstr() );
m_editor->cartesian_f_lineWidth->setValue( f->f0.lineWidth );
m_editor->cartesian_f_lineColor->setColor( f->f0.color );
......@@ -382,12 +353,12 @@ void FunctionEditor::initFromPolar()
{
// kDebug() << k_funcinfo << endl;
Function * f = View::self()->parser()->functionWithID(m_function);
Function * f = View::self()->parser()->functionWithID(m_functionID);
if ( !f )
return;
QString function = f->eq->fstr();
QString function = f->eq[0]->fstr();
function = function.mid( 1 );
m_editor->polarEquation->setText( function );
m_editor->polarCustomMin->setChecked( f->usecustomxmin );
......@@ -406,26 +377,25 @@ void FunctionEditor::initFromParametric()
{
// kDebug() << k_funcinfo << endl;
Function * fx = View::self()->parser()->functionWithID(m_functionX);
Function * fy = View::self()->parser()->functionWithID(m_functionY);
Function * f = View::self()->parser()->functionWithID(m_functionID);
if ( !fx || !fy )
if ( !f )
return;
QString name, expression;
splitParametricEquation( fx->eq->fstr(), & name, & expression );
splitParametricEquation( f->eq[0]->fstr(), & name, & expression );
m_editor->parametricName->setText( name );
m_editor->parametricX->setText( expression );
splitParametricEquation( fy->eq->fstr(), & name, & expression );
splitParametricEquation( f->eq[1]->fstr(), & name, & expression );
m_editor->parametricY->setText( expression );
m_editor->parametricMin->setText( fx->dmin.expression() );
m_editor->parametricMax->setText( fx->dmax.expression() );
m_editor->parametricMin->setText( f->dmin.expression() );
m_editor->parametricMax->setText( f->dmax.expression() );
m_editor->parametricLineWidth->setValue( fx->f0.lineWidth );
m_editor->parametricLineColor->setColor( fx->f0.color );
m_editor->parametricLineWidth->setValue( f->f0.lineWidth );
m_editor->parametricLineColor->setColor( f->f0.color );
m_editor->stackedWidget->setCurrentIndex( 1 );
m_editor->parametricName->setFocus();
......@@ -446,9 +416,7 @@ void FunctionEditor::splitParametricEquation( const QString equation, QString *
void FunctionEditor::resetFunctionEditing()
{
m_function = -1;
m_functionX = -1;
m_functionY = -1;
m_functionID = -1;
// page 3 is an empty page
m_editor->stackedWidget->setCurrentIndex( 3 );
......@@ -477,16 +445,14 @@ void FunctionEditor::createNewPlot()
void FunctionEditor::createCartesian()
{
m_function = -1;
m_functionX = -1;
m_functionY = -1;
m_functionID = -1;
// find a name not already used
QString fname( "f(x)=0" );
View::self()->parser()->fixFunctionName( fname, Equation::Cartesian, -1 );
m_function = View::self()->parser()->addFunction( fname );
assert( m_function != -1 );
m_functionID = View::self()->parser()->addFunction( fname, 0 );
assert( m_functionID != -1 );
kDebug() << "Created cartesian, so requestion state save.\n";
View::self()->mainDlg()->requestSaveCurrentState();
......@@ -495,46 +461,31 @@ void FunctionEditor::createCartesian()
void FunctionEditor::createParametric()
{
m_function = -1;
m_functionX = -1;
m_functionY = -1;
m_functionID = -1;
// find a name not already used
QString fname;
View::self()->parser()->fixFunctionName( fname, Equation::ParametricX, -1 );
QString name = fname.mid( 1, fname.indexOf('(')-1 );
kDebug() << "AAA\n";
m_functionX = View::self()->parser()->addfkt( QString("x%1(t)=0").arg( name ), Function::ParametricX );
assert( m_functionX != -1 );
kDebug() << "BBB\n";
m_functionY = View::self()->parser()->addfkt( QString("y%1(t)=0").arg( name ), Function::ParametricY );
assert( m_functionY != -1 );
kDebug() << "CCC\n";
m_functionID = View::self()->parser()->addfkt( 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";
View::self()->mainDlg()->requestSaveCurrentState();
kDebug() << "DDD\n";
}
void FunctionEditor::createPolar()
{
m_function = -1;
m_functionX = -1;
m_functionY = -1;
m_functionID = -1;
// find a name not already used
QString fname( "f(x)=0" );
View::self()->parser()->fixFunctionName( fname, Equation::Polar, -1 );
m_function = View::self()->parser()->addFunction( fname );
assert( m_function != -1 );
m_functionID = View::self()->parser()->addFunction( fname, 0 );
assert( m_functionID != -1 );
View::self()->mainDlg()->requestSaveCurrentState();
}
......@@ -544,20 +495,23 @@ void FunctionEditor::save()
{
// kDebug() << k_funcinfo << endl;
if ( m_function != -1 )
Function * f = View::self()->parser()->functionWithID( m_functionID );
if ( !f )
return;
switch ( f->type() )
{
Function * f = View::self()->parser()->functionWithID( m_function );
if ( !f )
return;
if ( f->type() == Function::Polar )
m_savePolarTimer->start( 0 );
else
case Function::Cartesian:
m_saveCartesianTimer->start( 0 );
}
else if ( (m_functionX != -1) && (m_functionY != -1) )
{
m_saveParametricTimer->start( 0 );
break;
case Function::Polar:
m_savePolarTimer->start( 0 );
break;
case Function::Parametric:
m_saveParametricTimer->start( 0 );
break;
}
}
......@@ -566,7 +520,7 @@ void FunctionEditor::saveCartesian()
{
// kDebug() << k_funcinfo << endl;
Function * f = View::self()->parser()->functionWithID( m_function );
Function * f = View::self()->parser()->functionWithID( m_functionID );
if ( !f )
return;
......@@ -650,7 +604,7 @@ void FunctionEditor::saveCartesian()
return;
}
QString const old_fstr = f->eq->fstr();
QString const old_fstr = f->eq[0]->fstr();
if ( ( (!m_parameters.isEmpty() &&
m_editor->cartesianParametersList->isChecked() ) ||
m_editor->cartesianParameterSlider->isChecked() ) &&
......@@ -659,7 +613,7 @@ void FunctionEditor::saveCartesian()
fixCartesianArguments( & f_str ); //adding an extra argument for the parameter value
}
if ( !f->eq->setFstr( f_str ) )
if ( !f->eq[0]->setFstr( f_str ) )
{
// raise();
// showPage(0);
......@@ -670,7 +624,7 @@ void FunctionEditor::saveCartesian()
//save all settings in the function now when we know no errors have appeared
bool changed = f->copyFrom( tempFunction );
changed |= (old_fstr != f->eq->fstr() );
changed |= (old_fstr != f->eq[0]->fstr() );
// kDebug() << "old_fstr="<<old_fstr<<" f->eq->fstr()="<<f->eq->fstr()<<" changed="<<changed<<endl;
if ( !changed )
return;
......@@ -714,7 +668,7 @@ void FunctionEditor::savePolar()
{
// kDebug() << k_funcinfo << endl;
Function * f = View::self()->parser()->functionWithID( m_function );