2015-07-11 18:56:02 +08:00
/*
2024-02-06 21:50:49 +08:00
Copyright ( c ) 2008 - 2024 Jan W . Krieger ( < jan @ jkrieger . de > )
2015-07-11 18:56:02 +08:00
2015-07-12 22:34:27 +08:00
2015-07-11 18:56:02 +08:00
This software is free software : you can redistribute it and / or modify
it under the terms of the GNU Lesser General Public License ( LGPL ) as published by
2019-02-08 00:24:46 +08:00
the Free Software Foundation , either version 2.1 of the License , or
2015-07-11 18:56:02 +08:00
( 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 Lesser General Public License ( LGPL ) for more details .
You should have received a copy of the GNU Lesser General Public License ( LGPL )
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2019-06-20 22:06:31 +08:00
# include "jkqtplotter/graphs/jkqtpparsedfunction.h"
# include "jkqtplotter/graphs/jkqtpscatter.h"
2018-11-26 03:25:44 +08:00
# include "jkqtplotter/jkqtpbaseplotter.h"
2019-02-08 00:24:46 +08:00
# include "jkqtplotter/jkqtplotter.h"
2019-05-30 04:40:02 +08:00
# include "jkqtplotter/jkqtptools.h"
2015-07-11 18:56:02 +08:00
# include <stdlib.h>
# include <QDebug>
# include <QElapsedTimer>
2018-12-24 03:27:24 +08:00
# include <utility>
2015-07-11 18:56:02 +08:00
2020-09-08 02:57:25 +08:00
JKQTPParsedFunctionLineGraphBase : : JKQTPParsedFunctionLineGraphBase ( const QString & dependentVariableName_ , const QString & function_ , JKQTBasePlotter * parent ) :
JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase ( parent ) ,
dependentVariableName ( dependentVariableName_ ) ,
function ( function_ )
2018-12-24 22:07:14 +08:00
{
2020-09-08 02:57:25 +08:00
fdata . parser = std : : make_shared < JKQTPMathParser > ( ) ;
2018-12-24 22:07:14 +08:00
fdata . node = nullptr ;
fdata . varcount = 0 ;
2020-09-08 02:57:25 +08:00
efdata . parser = std : : make_shared < JKQTPMathParser > ( ) ;
2018-12-24 22:07:14 +08:00
efdata . node = nullptr ;
efdata . varcount = 0 ;
}
2020-09-08 02:57:25 +08:00
JKQTPParsedFunctionLineGraphBase : : JKQTPParsedFunctionLineGraphBase ( const QString & dependentVariableName , const QString & function , JKQTPlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( dependentVariableName , function , parent - > getPlotter ( ) )
2018-12-24 22:07:14 +08:00
{
}
2020-09-08 02:57:25 +08:00
JKQTPParsedFunctionLineGraphBase : : JKQTPParsedFunctionLineGraphBase ( const QString & dependentVariableName , JKQTBasePlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( dependentVariableName , QString ( ) , parent )
{
}
JKQTPParsedFunctionLineGraphBase : : JKQTPParsedFunctionLineGraphBase ( const QString & dependentVariableName , JKQTPlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( dependentVariableName , QString ( ) , parent )
{
}
JKQTPParsedFunctionLineGraphBase : : ~ JKQTPParsedFunctionLineGraphBase ( )
2018-12-24 22:07:14 +08:00
{
}
2020-09-08 02:57:25 +08:00
void JKQTPParsedFunctionLineGraphBase : : setFunction ( const QString & __value )
2019-04-22 19:27:50 +08:00
{
this - > function = __value ;
}
2020-09-08 02:57:25 +08:00
QString JKQTPParsedFunctionLineGraphBase : : getFunction ( ) const
2019-04-22 19:27:50 +08:00
{
return this - > function ;
}
2020-09-08 02:57:25 +08:00
void JKQTPParsedFunctionLineGraphBase : : setErrorFunction ( const QString & __value )
2019-04-22 19:27:50 +08:00
{
this - > errorFunction = __value ;
}
2020-09-08 02:57:25 +08:00
QString JKQTPParsedFunctionLineGraphBase : : getErrorFunction ( ) const
2019-04-22 19:27:50 +08:00
{
return this - > errorFunction ;
}
2018-12-24 22:07:14 +08:00
2020-09-08 02:57:25 +08:00
QString JKQTPParsedFunctionLineGraphBase : : getDependentVariableName ( ) const
2018-12-24 22:07:14 +08:00
{
2020-09-08 02:57:25 +08:00
return dependentVariableName ;
}
double JKQTPParsedFunctionLineGraphBase : : evaluateParsedFunction ( double t , ParsedFunctionLineGraphFunctionData * fdata ) {
JKQTPParsedFunctionLineGraphBase : : ParsedFunctionLineGraphFunctionData * d = fdata ; //static_cast<JKQTPXParsedFunctionLineGraph::JKQTPXParsedFunctionLineGraphFunctionData*>(data);
if ( d & & d - > parser & & d - > node ) {
try {
d - > parser - > addVariableDouble ( d - > dependentVariableName . toStdString ( ) , t ) ;
JKQTPMathParser : : jkmpResult r = d - > node - > evaluate ( ) ;
if ( r . isValid ) {
if ( r . type = = JKQTPMathParser : : jkmpBool ) {
return r . boolean ? 1.0 : 0.0 ;
} else if ( r . type = = JKQTPMathParser : : jkmpDouble ) {
return r . num ;
}
}
} catch ( std : : exception & E ) {
qDebug ( ) < < QString ( " parser error: %1 " ) . arg ( E . what ( ) ) ;
/*ok= QMessageBox::critical(this, tr("QuickFit-table"),
tr ( " An error occured while parsing the expression '%1' in cell (row, column)=(%3, %4): \n %2 \n \n \" OK \" will still go on evaluating \n \" Cancel \" will cancel evaluation for the rest of the cells. " ) . arg ( dlgMathExpression - > getExpression ( ) ) . arg ( E . what ( ) ) . arg ( row ) . arg ( column ) ,
QMessageBox : : Ok | QMessageBox : : Cancel , QMessageBox : : Ok ) = = QMessageBox : : Ok ; */
}
}
return NAN ;
}
JKQTPXParsedFunctionLineGraph : : JKQTPXParsedFunctionLineGraph ( JKQTBasePlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " x " ) , parent )
{
}
JKQTPXParsedFunctionLineGraph : : JKQTPXParsedFunctionLineGraph ( JKQTPlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " x " ) , parent )
{
}
JKQTPXParsedFunctionLineGraph : : JKQTPXParsedFunctionLineGraph ( const QString & function , JKQTBasePlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " x " ) , function , parent )
{
}
JKQTPXParsedFunctionLineGraph : : JKQTPXParsedFunctionLineGraph ( const QString & function , JKQTPlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " x " ) , function , parent )
{
}
JKQTPXParsedFunctionLineGraph : : ~ JKQTPXParsedFunctionLineGraph ( )
{
}
void JKQTPXParsedFunctionLineGraph : : draw ( JKQTPEnhancedPainter & painter )
{
drawXGraph ( painter ) ;
}
JKQTPEvaluatedFunctionGraphBase : : PlotFunctorSpec JKQTPXParsedFunctionLineGraph : : buildPlotFunctorSpec ( )
{
JKQTPEvaluatedFunctionGraphBase : : PlotFunctorSpec spec ;
if ( parent = = nullptr ) return spec ; // return an invalid PlotFunctorSpec
2018-12-24 22:07:14 +08:00
for ( int i = 0 ; i < fdata . varcount ; i + + ) {
fdata . parser - > deleteVariable ( std : : string ( " p " ) + jkqtp_inttostr ( i + 1 ) ) ;
}
fdata . varcount = 0 ;
try {
2020-09-05 19:47:46 +08:00
for ( const auto & p : getInternalParams ( ) ) {
fdata . parser - > addVariableDouble ( std : : string ( " p " ) + jkqtp_inttostr ( fdata . varcount + 1 ) , p ) ;
fdata . varcount = fdata . varcount + 1 ;
2018-12-24 22:07:14 +08:00
}
2020-09-08 02:57:25 +08:00
fdata . dependentVariableName = getDependentVariableName ( ) ;
fdata . parser - > addVariableDouble ( getDependentVariableName ( ) . toStdString ( ) , 0.0 ) ;
fdata . node = std : : shared_ptr < JKQTPMathParser : : jkmpNode > ( fdata . parser - > parse ( function . toStdString ( ) ) ) ;
2019-04-22 19:27:50 +08:00
} catch ( std : : exception & E ) {
qDebug ( ) < < QString ( " parser error: %1 " ) . arg ( E . what ( ) ) ;
2018-12-24 22:07:14 +08:00
}
2020-09-08 02:57:25 +08:00
jkqtpSimplePlotFunctionType plotFunction = std : : bind ( & JKQTPXParsedFunctionLineGraph : : evaluateParsedFunction , std : : placeholders : : _1 , & fdata ) ;
// the actual function to use
2020-09-09 17:45:33 +08:00
spec . func = std : : bind ( [ = ] ( double x ) - > QPointF { return QPointF ( x , plotFunction ( x ) ) ; } , std : : placeholders : : _1 ) ;
// range over which to evaluate func
spec . range_start = parent - > getXMin ( ) ;
spec . range_end = parent - > getXMax ( ) ;
2020-09-08 02:57:25 +08:00
return spec ;
}
std : : function < QPointF ( double ) > JKQTPXParsedFunctionLineGraph : : buildErrorFunctorSpec ( )
{
std : : function < QPointF ( double ) > spec ;
2018-12-24 22:07:14 +08:00
for ( int i = 0 ; i < efdata . varcount ; i + + ) {
efdata . parser - > deleteVariable ( std : : string ( " p " ) + jkqtp_inttostr ( i + 1 ) ) ;
}
efdata . varcount = 0 ;
try {
2020-09-08 02:57:25 +08:00
for ( const auto & p : getInternalErrorParams ( ) ) {
efdata . parser - > addVariableDouble ( std : : string ( " p " ) + jkqtp_inttostr ( efdata . varcount + 1 ) , p ) ;
efdata . varcount = efdata . varcount + 1 ;
2018-12-24 22:07:14 +08:00
}
2020-09-08 02:57:25 +08:00
efdata . dependentVariableName = getDependentVariableName ( ) ;
efdata . parser - > addVariableDouble ( getDependentVariableName ( ) . toStdString ( ) , 0.0 ) ;
efdata . node = std : : shared_ptr < JKQTPMathParser : : jkmpNode > ( efdata . parser - > parse ( errorFunction . toStdString ( ) ) ) ;
2018-12-24 22:07:14 +08:00
} catch ( std : : exception & /*E*/ ) {
//qDebug()<<QString("parser error: %1").arg(E.what());
}
2020-09-08 02:57:25 +08:00
jkqtpSimplePlotFunctionType errorPlotFunction = std : : bind ( & JKQTPXParsedFunctionLineGraph : : evaluateParsedFunction , std : : placeholders : : _1 , & efdata ) ;
// the actual function to use
spec = std : : bind ( [ = ] ( double x ) - > QPointF { return QPointF ( 0 , errorPlotFunction ( x ) ) ; } , std : : placeholders : : _1 ) ;
2018-12-24 22:07:14 +08:00
2020-09-08 02:57:25 +08:00
return spec ;
2018-12-24 22:07:14 +08:00
}
2015-07-11 18:56:02 +08:00
2020-09-08 02:57:25 +08:00
2015-07-11 18:56:02 +08:00
2018-12-24 22:07:14 +08:00
2019-01-20 17:49:29 +08:00
JKQTPYParsedFunctionLineGraph : : JKQTPYParsedFunctionLineGraph ( JKQTBasePlotter * parent ) :
2020-09-08 02:57:25 +08:00
JKQTPParsedFunctionLineGraphBase ( QString ( " y " ) , parent )
2015-07-11 18:56:02 +08:00
{
}
2019-01-20 23:15:10 +08:00
JKQTPYParsedFunctionLineGraph : : JKQTPYParsedFunctionLineGraph ( JKQTPlotter * parent ) :
2020-09-08 02:57:25 +08:00
JKQTPParsedFunctionLineGraphBase ( QString ( " y " ) , parent )
2015-08-02 19:36:54 +08:00
{
}
2018-12-24 22:07:14 +08:00
2020-09-08 02:57:25 +08:00
JKQTPYParsedFunctionLineGraph : : JKQTPYParsedFunctionLineGraph ( const QString & function , JKQTBasePlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " y " ) , function , parent )
2015-07-11 18:56:02 +08:00
{
}
2020-09-08 02:57:25 +08:00
JKQTPYParsedFunctionLineGraph : : JKQTPYParsedFunctionLineGraph ( const QString & function , JKQTPlotter * parent ) :
JKQTPParsedFunctionLineGraphBase ( QString ( " y " ) , function , parent )
2019-04-22 19:27:50 +08:00
{
}
2020-09-08 02:57:25 +08:00
JKQTPYParsedFunctionLineGraph : : ~ JKQTPYParsedFunctionLineGraph ( )
2019-04-22 19:27:50 +08:00
{
}
2020-09-08 02:57:25 +08:00
void JKQTPYParsedFunctionLineGraph : : draw ( JKQTPEnhancedPainter & painter )
2019-04-22 19:27:50 +08:00
{
2020-09-08 02:57:25 +08:00
drawYGraph ( painter ) ;
2019-04-22 19:27:50 +08:00
}
2020-09-08 02:57:25 +08:00
JKQTPEvaluatedFunctionGraphBase : : PlotFunctorSpec JKQTPYParsedFunctionLineGraph : : buildPlotFunctorSpec ( )
2015-07-11 18:56:02 +08:00
{
2020-09-08 02:57:25 +08:00
JKQTPEvaluatedFunctionGraphBase : : PlotFunctorSpec spec ;
if ( parent = = nullptr ) return spec ; // return an invalid PlotFunctorSpec
2015-07-11 18:56:02 +08:00
for ( int i = 0 ; i < fdata . varcount ; i + + ) {
fdata . parser - > deleteVariable ( std : : string ( " p " ) + jkqtp_inttostr ( i + 1 ) ) ;
}
fdata . varcount = 0 ;
try {
2020-09-05 19:47:46 +08:00
for ( const auto & p : getInternalParams ( ) ) {
fdata . parser - > addVariableDouble ( std : : string ( " p " ) + jkqtp_inttostr ( fdata . varcount + 1 ) , p ) ;
fdata . varcount = fdata . varcount + 1 ;
2015-07-11 18:56:02 +08:00
}
2020-09-08 02:57:25 +08:00
fdata . dependentVariableName = getDependentVariableName ( ) ;
fdata . parser - > addVariableDouble ( getDependentVariableName ( ) . toStdString ( ) , 0.0 ) ;
fdata . node = std : : shared_ptr < JKQTPMathParser : : jkmpNode > ( fdata . parser - > parse ( function . toStdString ( ) ) ) ;
2019-04-22 19:27:50 +08:00
} catch ( std : : exception & E ) {
qDebug ( ) < < QString ( " parser error: %1 " ) . arg ( E . what ( ) ) ;
2015-07-11 18:56:02 +08:00
}
2020-09-08 02:57:25 +08:00
jkqtpSimplePlotFunctionType plotFunction = std : : bind ( & JKQTPXParsedFunctionLineGraph : : evaluateParsedFunction , std : : placeholders : : _1 , & fdata ) ;
// the actual function to use
2020-09-09 17:45:33 +08:00
spec . func = std : : bind ( [ = ] ( double y ) - > QPointF { return QPointF ( plotFunction ( y ) , y ) ; } , std : : placeholders : : _1 ) ;
2020-09-08 02:57:25 +08:00
// range over which to evaluate func
2020-09-09 17:45:33 +08:00
spec . range_start = parent - > getYMin ( ) ;
spec . range_end = parent - > getYMax ( ) ;
2020-09-08 02:57:25 +08:00
return spec ;
}
std : : function < QPointF ( double ) > JKQTPYParsedFunctionLineGraph : : buildErrorFunctorSpec ( )
{
std : : function < QPointF ( double ) > spec ;
2015-07-11 18:56:02 +08:00
for ( int i = 0 ; i < efdata . varcount ; i + + ) {
efdata . parser - > deleteVariable ( std : : string ( " p " ) + jkqtp_inttostr ( i + 1 ) ) ;
}
efdata . varcount = 0 ;
try {
2020-09-08 02:57:25 +08:00
for ( const auto & p : getInternalErrorParams ( ) ) {
efdata . parser - > addVariableDouble ( std : : string ( " p " ) + jkqtp_inttostr ( efdata . varcount + 1 ) , p ) ;
efdata . varcount = efdata . varcount + 1 ;
2015-07-11 18:56:02 +08:00
}
2020-09-08 02:57:25 +08:00
efdata . dependentVariableName = getDependentVariableName ( ) ;
efdata . parser - > addVariableDouble ( getDependentVariableName ( ) . toStdString ( ) , 0.0 ) ;
efdata . node = std : : shared_ptr < JKQTPMathParser : : jkmpNode > ( efdata . parser - > parse ( errorFunction . toStdString ( ) ) ) ;
} catch ( std : : exception & /*E*/ ) {
//qDebug()<<QString("parser error: %1").arg(E.what());
2015-07-11 18:56:02 +08:00
}
2018-12-24 22:07:14 +08:00
2020-09-08 02:57:25 +08:00
jkqtpSimplePlotFunctionType errorPlotFunction = std : : bind ( & JKQTPXParsedFunctionLineGraph : : evaluateParsedFunction , std : : placeholders : : _1 , & efdata ) ;
// the actual function to use
spec = std : : bind ( [ = ] ( double y ) - > QPointF { return QPointF ( errorPlotFunction ( y ) , 0 ) ; } , std : : placeholders : : _1 ) ;
2018-12-24 22:07:14 +08:00
2020-09-08 02:57:25 +08:00
return spec ;
2018-12-24 22:07:14 +08:00
}