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)