File indexing completed on 2023-05-30 10:42:17
0001 /* 0002 KmPlot - a math. function plotter for the KDE-Desktop 0003 0004 SPDX-FileCopyrightText: 2004 Fredrik Edemar <f_edemar@linux.se> 0005 SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org> 0006 0007 This file is part of the KDE Project. 0008 KmPlot is part of the KDE-EDU Project. 0009 0010 SPDX-License-Identifier: GPL-2.0-or-later 0011 0012 */ 0013 0014 #include "functiontools.h" 0015 #include "ui_functiontools.h" 0016 #include "view.h" 0017 #include "xparser.h" 0018 #include <QDialogButtonBox> 0019 0020 class FunctionToolsWidget : public QWidget, public Ui::FunctionTools 0021 { 0022 public: 0023 FunctionToolsWidget(QWidget *parent = 0) 0024 : QWidget(parent) 0025 { 0026 setupUi(this); 0027 } 0028 }; 0029 0030 // BEGIN class FunctionTools 0031 FunctionTools::FunctionTools(QWidget *parent) 0032 : QDialog(parent) 0033 { 0034 m_widget = new FunctionToolsWidget(this); 0035 0036 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); 0037 connect(buttonBox, &QDialogButtonBox::rejected, this, &FunctionTools::reject); 0038 QVBoxLayout *dialogLayout = new QVBoxLayout(this); 0039 dialogLayout->addWidget(m_widget); 0040 dialogLayout->addWidget(buttonBox); 0041 0042 init(CalculateArea); 0043 0044 connect(m_widget->min, &EquationEdit::editingFinished, this, &FunctionTools::rangeEdited); 0045 connect(m_widget->max, &EquationEdit::editingFinished, this, &FunctionTools::rangeEdited); 0046 connect(m_widget->list, &QListWidget::currentRowChanged, this, &FunctionTools::equationSelected); 0047 } 0048 0049 FunctionTools::~FunctionTools() 0050 { 0051 } 0052 0053 void FunctionTools::init(Mode m) 0054 { 0055 m_mode = m; 0056 0057 switch (m_mode) { 0058 case FindMinimum: { 0059 m_widget->rangeTitle->setText(i18n("Search between:")); 0060 setWindowTitle(i18nc("@title:window", "Find Minimum Point")); 0061 break; 0062 } 0063 0064 case FindMaximum: { 0065 m_widget->rangeTitle->setText(i18n("Search between:")); 0066 setWindowTitle(i18nc("@title:window", "Find Maximum Point")); 0067 break; 0068 } 0069 0070 case CalculateArea: { 0071 m_widget->rangeTitle->setText(i18n("Calculate the area between:")); 0072 setWindowTitle(i18nc("@title:window", "Area Under Graph")); 0073 break; 0074 } 0075 } 0076 0077 m_widget->min->setText(XParser::self()->number(View::self()->m_xmin)); 0078 m_widget->max->setText(XParser::self()->number(View::self()->m_xmax)); 0079 m_widget->min->setFocus(); 0080 0081 updateEquationList(); 0082 setEquation(EquationPair(View::self()->m_currentPlot, 0)); 0083 } 0084 0085 void FunctionTools::updateEquationList() 0086 { 0087 EquationPair previousEquation = equation(); 0088 0089 m_widget->list->clear(); 0090 m_equations.clear(); 0091 0092 for (Function *function : qAsConst(XParser::self()->m_ufkt)) { 0093 if (function->type() != Function::Cartesian && function->type() != Function::Differential) 0094 continue; 0095 0096 QList<Plot> plots = function->plots(); 0097 0098 for (int i = 0; i < function->eq.size(); ++i) { 0099 for (const Plot &plot : qAsConst(plots)) 0100 m_equations << EquationPair(plot, i); 0101 } 0102 } 0103 0104 for (const EquationPair &eq : qAsConst(m_equations)) { 0105 Equation *equation = eq.first.function()->eq[eq.second]; 0106 QListWidgetItem *item = new QListWidgetItem(equation->fstr(), m_widget->list); 0107 item->setForeground(eq.first.color()); 0108 } 0109 0110 setEquation(previousEquation); 0111 } 0112 0113 EquationPair FunctionTools::equation() const 0114 { 0115 int row = m_widget->list->currentRow(); 0116 if (row < 0 || row >= m_equations.size()) 0117 return EquationPair(); 0118 else 0119 return m_equations[row]; 0120 } 0121 0122 void FunctionTools::setEquation(const EquationPair &equation) 0123 { 0124 int row = m_equations.indexOf(equation); 0125 if (row < 0) 0126 row = 0; 0127 m_widget->list->setCurrentRow(row); 0128 equationSelected(row); 0129 } 0130 0131 void FunctionTools::equationSelected(int equation) 0132 { 0133 if (equation < 0 || equation >= m_equations.size()) 0134 return; 0135 EquationPair current = m_equations[equation]; 0136 0137 switch (m_mode) { 0138 case FindMinimum: 0139 findMinimum(current); 0140 break; 0141 0142 case FindMaximum: 0143 findMaximum(current); 0144 break; 0145 0146 case CalculateArea: 0147 calculateArea(current); 0148 break; 0149 } 0150 } 0151 0152 void FunctionTools::rangeEdited() 0153 { 0154 switch (m_mode) { 0155 case FindMinimum: 0156 findMinimum(equation()); 0157 break; 0158 0159 case FindMaximum: 0160 findMaximum(equation()); 0161 break; 0162 0163 case CalculateArea: 0164 calculateArea(equation()); 0165 break; 0166 } 0167 } 0168 0169 void FunctionTools::findMinimum(const EquationPair &equation) 0170 { 0171 if (!equation.first.function()) 0172 return; 0173 0174 QPointF extremum = View::self()->findMinMaxValue(equation.first, View::Minimum, m_widget->min->value(), m_widget->max->value()); 0175 0176 m_widget->rangeResult->setText(i18n("Minimum is at x = %1, %2(x) = %3", extremum.x(), equation.first.function()->eq[0]->name(), extremum.y())); 0177 } 0178 0179 void FunctionTools::findMaximum(const EquationPair &equation) 0180 { 0181 if (!equation.first.function()) 0182 return; 0183 0184 QPointF extremum = View::self()->findMinMaxValue(equation.first, View::Maximum, m_widget->min->value(), m_widget->max->value()); 0185 0186 m_widget->rangeResult->setText(i18n("Maximum is at x = %1, %2(x) = %3", extremum.x(), equation.first.function()->eq[0]->name(), extremum.y())); 0187 } 0188 0189 void FunctionTools::calculateArea(const EquationPair &equation) 0190 { 0191 if (!equation.first.function()) 0192 return; 0193 0194 IntegralDrawSettings s; 0195 s.plot = equation.first; 0196 s.dmin = m_widget->min->value(); 0197 s.dmax = m_widget->max->value(); 0198 0199 double area = View::self()->areaUnderGraph(s); 0200 0201 m_widget->rangeResult->setText(i18n("Area is %1", area)); 0202 } 0203 // END class FunctionTools