File indexing completed on 2024-05-05 03:41:15
0001 /************************************************************************************* 0002 * Copyright (C) 2007-2009 by Aleix Pol <aleixpol@kde.org> * 0003 * Copyright (C) 2010-2012 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or * 0006 * modify it under the terms of the GNU General Public License * 0007 * as published by the Free Software Foundation; either version 2 * 0008 * of the License, or (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the Free Software * 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 0018 *************************************************************************************/ 0019 0020 #include "private/abstractplanecurve.h" 0021 #include "private/functiongraphfactory.h" 0022 0023 #include <QRectF> 0024 #include <analitza/value.h> 0025 #include <analitza/vector.h> 0026 0027 using namespace Analitza; 0028 0029 #ifndef M_PI 0030 #define M_PI 3.14159265358979323846 0031 #endif 0032 0033 class FunctionParametric : public AbstractPlaneCurve 0034 { 0035 public: 0036 FunctionParametric(const Expression& e, const QSharedPointer<Analitza::Variables>& v); 0037 TYPE_NAME(QT_TRANSLATE_NOOP("Function type", "Parametric Curve 2D")) 0038 EXPRESSION_TYPE( 0039 Analitza::ExpressionType(Analitza::ExpressionType::Lambda) 0040 .addParameter(Analitza::ExpressionType(Analitza::ExpressionType::Value)) 0041 .addParameter(Analitza::ExpressionType(Analitza::ExpressionType::Vector, Analitza::ExpressionType(Analitza::ExpressionType::Value), 2))) 0042 COORDDINATE_SYSTEM(Cartesian) 0043 PARAMETERS(QStringList(QStringLiteral("t"))) 0044 ICON_NAME(QStringLiteral("newparametric")) 0045 EXAMPLES(QStringList(QStringLiteral("t->vector {t,t**2}"))) 0046 0047 void update(const QRectF& viewport) override; 0048 0049 QPair<QPointF, QString> image(const QPointF &mousepos) override; 0050 QLineF tangent(const QPointF &mousepos) override ; 0051 0052 Analitza::Cn *t; 0053 0054 private: 0055 Cn findTValueForPoint(const QPointF& p); 0056 int resolution() { return 5000; } 0057 }; 0058 0059 FunctionParametric::FunctionParametric(const Expression& e, const QSharedPointer<Analitza::Variables>& v): AbstractPlaneCurve(e, v) 0060 { 0061 t = arg(QStringLiteral("t")); 0062 } 0063 0064 void FunctionParametric::update(const QRectF& viewport) 0065 { 0066 QPair< double, double > theInterval; 0067 if(hasIntervals()) 0068 theInterval = interval(QStringLiteral("t")); 0069 else 0070 theInterval = qMakePair(-3.1415*5, 3.1415*5); 0071 double dlimit=theInterval.first; 0072 double ulimit=theInterval.second; 0073 0074 points.clear(); 0075 jumps.clear(); 0076 points.reserve(resolution()); 0077 0078 double inv_res= double((ulimit-dlimit)/resolution()); 0079 QRectF vp(viewport); 0080 0081 vp.setTop(viewport.top() - 2); 0082 vp.setBottom(viewport.bottom() + 2); 0083 vp.setLeft(viewport.left() + 2); 0084 vp.setRight(viewport.right() - 2); 0085 0086 int i = 0; 0087 0088 for(double t=dlimit; t<ulimit; t+=inv_res, ++i) { 0089 arg(QStringLiteral("t"))->setValue(t); 0090 Expression res=analyzer->calculateLambda(); 0091 0092 Cn x=res.elementAt(0).toReal(); 0093 Cn y=res.elementAt(1).toReal(); 0094 0095 QPointF curp = QPointF(x.value(), y.value()); 0096 addPoint(curp); 0097 Q_ASSERT(res.isVector()); 0098 } 0099 } 0100 0101 QPair<QPointF, QString> FunctionParametric::image(const QPointF &point) 0102 { 0103 0104 arg(QStringLiteral("t"))->setValue(findTValueForPoint(point).value()); 0105 0106 Expression res=analyzer->calculateLambda(); 0107 Analitza::Cn comp1 = res.elementAt(0).toReal(); 0108 Analitza::Cn comp2 = res.elementAt(1).toReal(); 0109 0110 return QPair<QPointF, QString>(QPointF(comp1.value(), comp2.value()), QString()); 0111 0112 } 0113 0114 QLineF FunctionParametric::tangent(const QPointF &/*mousepos*/) 0115 { 0116 // if(m_deriv) 0117 // { 0118 // double theT = findTValueForPoint(point).value(); 0119 // 0120 // Analitza::Analyzer a; 0121 // a.setExpression(*m_deriv); 0122 // a.setStack(m_runStack); 0123 // arg("t")->setValue(theT); 0124 // Expression exp = a.calculateLambda(); 0125 // 0126 // Analitza::Cn comp1 = exp.elementAt(0).toReal(); 0127 // Analitza::Cn comp2 = exp.elementAt(1).toReal(); 0128 // 0129 // double m = comp2.value()/comp1.value(); 0130 // 0131 // return FunctionUtils::slopeToLine(m); 0132 // } 0133 // else 0134 // return QLineF(); 0135 return QLineF(); 0136 } 0137 0138 Cn FunctionParametric::findTValueForPoint(const QPointF& /*p*/) 0139 { 0140 //TODO doesn't work well 0141 0142 // Q_ASSERT(analyzer.isCorrect() && analyzer.expression().lambdaBody().isVector()); 0143 // 0144 // Analitza::Analyzer f(analyzer.variables()); 0145 // f.setExpression(analyzer.expression().lambdaBody().elementAt(0)); 0146 // f.setExpression(f.dependenciesToLambda()); 0147 // f.setStack(m_runStack); 0148 // 0149 // Analitza::Analyzer df(analyzer.variables()); 0150 // df.setExpression(f.derivative("t")); 0151 // df.setStack(m_runStack); 0152 // 0153 // //TODO 0154 // // Analitza::Analyzer g(analyzer.variables()); 0155 // // g.setExpression(Analitza::Expression("t->" + analyzer.expression().lambdaBody().elementAt(1).toString() + "+" + QString::number(-1.0*point.y()), false)); 0156 // // g.refExpression()->parameters()[0]->value() = vx; 0157 // // 0158 // // Analitza::Analyzer dg(analyzer.variables()); 0159 // // dg.setExpression(g.derivative("t")); 0160 // // dg.refExpression()->parameters()[0]->value() = vx; 0161 // 0162 // const int MAX_I = 256; 0163 // const double E = 0.0001; 0164 // double t0 = 1.0; 0165 // double t = t0; 0166 // double error = 1000.0; 0167 // int i = 0; 0168 // 0169 // while (true) 0170 // { 0171 // arg("t")->setValue(t0); 0172 // 0173 // double r = f.calculateLambda().toReal().value()-p.x(); 0174 // double d = df.calculateLambda().toReal().value(); 0175 // 0176 // i++; 0177 // t = t0 - r/d; 0178 // 0179 // if ((error < E) || (i > MAX_I)) 0180 // break; 0181 // 0182 // error = fabs(t - t0); 0183 // t0 = t; 0184 // } 0185 // 0186 // //TODO 0187 // // t0 = 1.0; 0188 // // t = t0; 0189 // // error = 1000.0; 0190 // // i = 0; 0191 // // 0192 // // while (true) 0193 // // { 0194 // // arg("t")->setValue(t0); 0195 // // 0196 // // double r = g.calculateLambda().toReal().value(); 0197 // // double d = dg.calculateLambda().toReal().value(); 0198 // // 0199 // // i++; 0200 // // t = t0 - r/d; 0201 // // 0202 // // if ((error < E) || (i > MAX_I)) 0203 // // break; 0204 // // 0205 // // error = fabs(t - t0); 0206 // // t0 = t; 0207 // // } 0208 // return Cn(t); 0209 0210 return Cn(0.0); 0211 } 0212 0213 REGISTER_PLANECURVE(FunctionParametric)