File indexing completed on 2024-05-05 03:41:15

0001 /*************************************************************************************
0002  *  Copyright (C) 2010-2012 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com> *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 #include "private/abstractplanecurve.h"
0020 #include "private/functiongraphfactory.h"
0021 
0022 #include <QRect>
0023 #include <qmath.h>
0024 #include <QDebug>
0025 #include <QBitArray>
0026 #include <QLineF>
0027 
0028 #include <analitza/value.h>
0029 #include <analitza/expressiontype.h>
0030 #include <analitza/variable.h>
0031 #include <analitza/variables.h>
0032 #include "private/utils/marchingsquares.h"
0033 
0034 #ifndef M_PI
0035 #define M_PI           3.14159265358979323846
0036 #endif
0037 
0038 using namespace Analitza;
0039 
0040 class FunctionImplicit : public AbstractPlaneCurve, public MarchingSquares
0041 {
0042 public:
0043     CONSTRUCTORS(FunctionImplicit)
0044     TYPE_NAME(QT_TRANSLATE_NOOP("Function type", "Implicit Curve"))
0045     EXPRESSION_TYPE(Analitza::ExpressionType(Analitza::ExpressionType::Lambda)
0046         .addParameter(Analitza::ExpressionType(Analitza::ExpressionType::Value))
0047         .addParameter(Analitza::ExpressionType(Analitza::ExpressionType::Value))
0048         .addParameter(Analitza::ExpressionType(Analitza::ExpressionType::Value)))
0049     COORDDINATE_SYSTEM(Cartesian)
0050     PARAMETERS(QStringList(QStringLiteral("x")) << QStringLiteral("y"))
0051     ICON_NAME(QStringLiteral("newimplicit"))
0052     EXAMPLES(QStringList(QStringLiteral("x^3-y^2+2")) << QStringLiteral("y^2*(y^2-10)-x^2*(x^2-9)"))
0053 
0054     void update(const QRectF& viewport) override;
0055 
0056     QPair<QPointF, QString> image(const QPointF &mousepos) override;
0057     QLineF tangent(const QPointF &mousepos) override ;
0058 
0059     //
0060     virtual double evalScalarField(double x, double y) override;
0061 
0062 private:
0063     double getFValue(double xValue, double yValue);
0064 };
0065 
0066 void FunctionImplicit::update(const QRectF& vp)
0067 {
0068     points.clear();
0069     jumps.clear();
0070 
0071     double minx = vp.left();
0072     double maxx = vp.right();
0073     double miny = vp.top();
0074     double maxy = vp.bottom();
0075     
0076     if (hasIntervals())
0077     {
0078         QPair<double, double> intervalx = interval(QStringLiteral("x"));
0079         QPair<double, double> intervaly = interval(QStringLiteral("y"));
0080 
0081         minx = intervalx.first;
0082         maxx = intervalx.second;
0083         miny = intervaly.first;
0084         maxy = intervaly.second;
0085     }
0086     
0087     setWorld(minx, maxx, miny, maxy);
0088     buildGeometry();
0089 
0090     for (int i = 0;  i < _faces_.size(); ++i)
0091     {
0092         points << _faces_[i].first <<  _faces_[i].second;
0093         jumps.append(points.size());
0094     }
0095 
0096 //     if (points.size() <= 2) // y aunque/PESE a que el viewport se corta con el dominio
0097 //     {
0098 //         appendError(QCoreApplication::translate("This function can't be represented as a curve. To draw implicit curve, the function has to satisfy the implicit function theorem.", "Implicit function undefined in the plane"));
0099 //     }
0100 }
0101 
0102 //Own
0103 QPair<QPointF, QString> FunctionImplicit::image(const QPointF &/*point*/)
0104 {
0105 
0106     return qMakePair(QPointF(), QString());
0107 
0108     //TODO port
0109 
0110 //     QVector<Analitza::Object*> vxStack;
0111 //     vxStack.append(m_x);
0112 //     QVector<Analitza::Object*> vyStack;
0113 //     vyStack.append(m_y);
0114 //
0115 //     QString expLiteral = analyzer.expression().lambdaBody().toString();
0116 //     expLiteral.replace("y", QString::number(point.y()));
0117 //     expLiteral.prepend("x->");
0118 //
0119 //     Analitza::Analyzer f(analyzer.variables());
0120 //     f.setExpression(Analitza::Expression(expLiteral, false));
0121 //     f.setStack(vxStack);
0122 //
0123 //     Analitza::Analyzer df(analyzer.variables());
0124 //     df.setExpression(f.derivative("x"));
0125 //     df.setStack(vxStack);
0126 //
0127 //     const int MAX_I = 256;
0128 //     const double E = 0.0001;
0129 //     double x0 = point.x();
0130 //     double x = x0;
0131 //     double error = 1000.0;
0132 //     int i = 0;
0133 //     bool has_root_x = true;
0134 //
0135 //
0136 //     if (!f.isCorrect() || !df.isCorrect())
0137 //     {
0138 //         return QPair<QPointF, QString>(QPointF(), QString());
0139 //     }
0140 //
0141 //     while (true)
0142 //     {
0143 //         arg("x")->setValue(x0);
0144 //
0145 //         double r = f.calculateLambda().toReal().value();
0146 //         double d = df.calculateLambda().toReal().value();
0147 //
0148 //         i++;
0149 //         x = x0 - r/d;
0150 //
0151 //         if (error < E) break;
0152 //         if (i > MAX_I)
0153 //         {
0154 //             has_root_x = false;
0155 //             break;
0156 //         }
0157 //
0158 //         error = fabs(x - x0);
0159 //         x0 = x;
0160 //     }
0161 //
0162 //
0163 //     if (!has_root_x)
0164 //     {
0165 //         expLiteral = analyzer.expression().lambdaBody().toString();
0166 //         expLiteral.replace("x", QString::number(point.x()));
0167 //         expLiteral.prepend("y->");
0168 //
0169 //         Analitza::Analyzer f(analyzer.variables());
0170 //         f.setExpression(Analitza::Expression(expLiteral, false));
0171 //         f.setStack(vyStack);
0172 //
0173 //         Analitza::Analyzer df(analyzer.variables());
0174 //         df.setExpression(f.derivative("y"));
0175 //         df.setStack(vyStack);
0176 //
0177 //         double y0 = point.y();
0178 //         double y = y0;
0179 //         error = 1000.0;
0180 //         i = 0;
0181 //         bool has_root_y = true;
0182 //
0183 //         while (true)
0184 //         {
0185 //             arg("y")->setValue(y0);
0186 //
0187 //             double r = f.calculateLambda().toReal().value();
0188 //             double d = df.calculateLambda().toReal().value();
0189 //
0190 //             i++;
0191 //             y = y0 - r/d;
0192 //
0193 //             if (error < E) break;
0194 //             if (i > MAX_I)
0195 //             {
0196 //                 has_root_y = false;
0197 //                 break;
0198 //             }
0199 //
0200 //             error = fabs(y - y0);
0201 //             y0 = y;
0202 //         }
0203 //
0204 //         if (has_root_y)
0205 //             last_calc = QPointF(point.x(), y);
0206 //         return QPair<QPointF, QString>(last_calc, QString());
0207 //     }
0208 //     else
0209 //     {
0210 //         last_calc = QPointF(x, point.y());
0211 //
0212 //         return QPair<QPointF, QString>(last_calc, QString());
0213 //     }
0214 
0215 }
0216 
0217 QLineF FunctionImplicit::tangent(const QPointF &/*mousepos*/)
0218 {
0219     return QLineF();
0220 }
0221 
0222 double FunctionImplicit::getFValue(double xValue, double yValue)
0223 {
0224     arg(QStringLiteral("x"))->setValue(xValue);
0225     arg(QStringLiteral("y"))->setValue(yValue);
0226 
0227 //     return analyzer->calculateLambda().toReal().value();
0228     
0229     Analitza::Expression r=analyzer->calculateLambda();
0230 
0231     if(r.isReal())
0232     {
0233         Analitza::Cn z = analyzer->calculateLambda().toReal();
0234 
0235         if(z.format()==Analitza::Cn::Real)
0236             return z.value();
0237     }
0238     
0239     return 0;
0240 }
0241 
0242 double FunctionImplicit::evalScalarField(double x, double y)
0243 {
0244 //     qDebug() << x << y;
0245 
0246     return getFValue(x,y);
0247 }
0248 
0249 REGISTER_PLANECURVE(FunctionImplicit)