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)