File indexing completed on 2024-05-05 03:41:16
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 #include <private/utils/mathutils.h> 0023 0024 #include <QRectF> 0025 #include <analitza/value.h> 0026 0027 #ifndef M_PI 0028 #define M_PI 3.14159265358979323846 0029 #endif 0030 0031 using namespace Analitza; 0032 0033 class FunctionPolar : public AbstractPlaneCurve 0034 { 0035 public: 0036 FunctionPolar(const Analitza::Expression& e, const QSharedPointer<Analitza::Variables>& v = {}); 0037 TYPE_NAME(QT_TRANSLATE_NOOP("Function type", "Polar Curve r=F(p: Polar)")) 0038 EXPRESSION_TYPE(Analitza::ExpressionType(Analitza::ExpressionType::Lambda).addParameter( 0039 Analitza::ExpressionType(Analitza::ExpressionType::Value)).addParameter( 0040 Analitza::ExpressionType(Analitza::ExpressionType::Value))) 0041 COORDDINATE_SYSTEM(Polar) 0042 PARAMETERS(QStringList(QStringLiteral("q"))) //q:theta 0043 ICON_NAME(QStringLiteral("newpolar")) 0044 EXAMPLES(QStringList(QStringLiteral("q->3*sin(q/0.142)")) << QStringLiteral("q->q+3")) 0045 0046 void update(const QRectF& viewport) override; 0047 0048 QPair<QPointF, QString> image(const QPointF &mousepos) override; 0049 QLineF tangent(const QPointF &mousepos) override ; 0050 0051 Analitza::Cn *p; 0052 }; 0053 0054 FunctionPolar::FunctionPolar(const Analitza::Expression& e, const QSharedPointer<Analitza::Variables>& v): AbstractPlaneCurve(e, v) 0055 { 0056 p = arg(QStringLiteral("q")); 0057 } 0058 0059 void FunctionPolar::update(const QRectF& viewport) 0060 { 0061 points.clear(); 0062 jumps.clear(); 0063 0064 double dlimit = 0; 0065 double ulimit = 0; 0066 double inv_res = 0; 0067 0068 if (!hasIntervals()) { 0069 double pi_factor = qMax(qMax(qAbs(viewport.left()), qAbs(viewport.right())), 0070 qMax(qAbs(viewport.bottom()), qAbs(viewport.top()))); 0071 0072 pi_factor = qMax(pi_factor, 16.); // 16 steps at minimum 0073 0074 dlimit = -M_PI*pi_factor; 0075 ulimit = M_PI*pi_factor; 0076 0077 inv_res = qMin(viewport.size().width(), viewport.size().height())/(M_PI*M_PI*pi_factor); 0078 0079 points.reserve(10*static_cast<int>(pi_factor)); 0080 } else { 0081 QPair< double, double> limits = interval(QStringLiteral("q")); 0082 dlimit = limits.first; 0083 ulimit = limits.second; 0084 inv_res = (ulimit-dlimit)/(M_PI*M_PI*16); 0085 } 0086 Q_ASSERT(inv_res!=0); 0087 0088 double final=ulimit-inv_res; 0089 if((final<0) != (inv_res<0)) { 0090 inv_res *= -1; 0091 } 0092 0093 for(double th=dlimit; th<final; th+=inv_res) { 0094 p->setValue(th); 0095 double r = analyzer->calculateLambda().toReal().value(); 0096 0097 addPoint(polarToCartesian(r,th)); 0098 } 0099 } 0100 0101 0102 //Own 0103 QPair<QPointF, QString> FunctionPolar::image(const QPointF &p) 0104 { 0105 QPointF dp=p; 0106 QString pos; 0107 // if(p==QPointF(0., 0.)) 0108 // return QPair<QPointF, QString>(dp, QCoreApplication::translate("", "center")); 0109 // double th=atan(p.y()/ p.x()), r=1., d, d2; 0110 // if(p.x()<0.) th += pi; 0111 // else if(th<0.) th += 2.*pi; 0112 // 0113 // 0114 // //TODO CACHE en intervalvalues!!! 0115 // static QPair<double, double> c_limits = interval("p"); 0116 // 0117 // // if () 0118 // // 0119 // // static QPair<double, double> o_limits = c_limits; 0120 // 0121 // 0122 // double ulimit=c_limits.second; 0123 // double dlimit=c_limits.first; 0124 // 0125 // th=qMax(th, dlimit); 0126 // th=qMin(th, ulimit); 0127 // 0128 // // analyzer.setStack(m_runStack); 0129 // QPointF dist; 0130 // arg("p")->setValue(th); 0131 // do { 0132 // arg("p")->setValue(th); 0133 // r = analyzer->calculateLambda().toReal().value(); 0134 // 0135 // dp = polarToCartesian(r,th); 0136 // dist = (dp-p); 0137 // d = sqrt(dist.x()*dist.x() + dist.y()*dist.y()); 0138 // 0139 // arg("p")->setValue(th+2.*pi); 0140 // r = analyzer->calculateLambda().toReal().value(); 0141 // 0142 // dp = polarToCartesian(r,th); 0143 // dist = (dp-p); 0144 // d2 = sqrt(dist.x()*dist.x() + dist.y()*dist.y()); 0145 // 0146 // th += 2.*pi; 0147 // } while(d>d2); 0148 // th -= 2.*pi; 0149 // 0150 // arg("p")->setValue(th); 0151 // Analitza::Expression res=analyzer->calculateLambda(); 0152 // 0153 // if(!res.isReal()) 0154 // appendError(QCoreApplication::translate("", "We can only draw Real results.")); 0155 // r = res.toReal().value(); 0156 // 0157 // 0158 // 0159 // dp = polarToCartesian(r,th); 0160 // 0161 // pos = QStringLiteral("r=%1 th=%2").arg(r,3,'f',2).arg(th,3,'f',2); 0162 return QPair<QPointF, QString>(dp, pos); 0163 } 0164 0165 QLineF FunctionPolar::tangent(const QPointF &/*mousepos*/) 0166 { 0167 // //TODO review calc and this method 0168 // 0169 // QString rt = analyzer.expression().lambdaBody().toString(); 0170 // rt.replace("q", "t"); 0171 // 0172 // QString comp1str = rt + "*cos(t)"; 0173 // QString comp2str = rt + "*sin(t)"; 0174 // 0175 // QString polart; 0176 // polart = "t->vector{" + comp1str + ", " + comp2str + "}"; 0177 // 0178 // Analitza::Analyzer newfunc(analyzer.variables()); 0179 // newanalyzer.setExpression(Analitza::Expression(polart, false)); 0180 // 0181 // Q_ASSERT(newanalyzer.isCorrect() && newanalyzer.expression().lambdaBody().isVector()); 0182 // 0183 // Analitza::Analyzer f(newanalyzer.variables()); 0184 // f.setStack(m_runStack); 0185 // f.setExpression(Analitza::Expression("t->" + newanalyzer.expression().lambdaBody().elementAt(0).toString() + "+" + QString::number(-1.0*point.x()), false)); 0186 // 0187 // Analitza::Analyzer df(newanalyzer.variables()); 0188 // df.setStack(m_runStack); 0189 // df.setExpression(f.derivative("t")); 0190 // 0191 // if (!df.isCorrect()) return QLineF(); 0192 // 0193 // //TODO 0194 // // Analitza::Analyzer g(analyzer.variables()); 0195 // // g.setExpression(Analitza::Expression("t->" + analyzer.expression().lambdaBody().elementAt(1).toString() + "+" + QString::number(-1.0*point.y()), false)); 0196 // // g.refExpression()->parameters()[0]->value() = vx; 0197 // // 0198 // // Analitza::Analyzer dg(analyzer.variables()); 0199 // // dg.setExpression(g.derivative("t")); 0200 // // dg.refExpression()->parameters()[0]->value() = vx; 0201 // 0202 // const int MAX_I = 256; 0203 // const double E = 0.0001; 0204 // double t0 = atan(point.y()/ point.x()); 0205 // 0206 // if(point.x()<0.) t0 += pi; 0207 // else if(t0<0.) t0 += 2.*pi; 0208 // 0209 // t0=qBound(downlimit(), t0, uplimit()); 0210 // 0211 // double t = t0; 0212 // double error = 1000.0; 0213 // int i = 0; 0214 // 0215 // while (true) 0216 // { 0217 // m_th->setValue(t0); 0218 // 0219 // double r = f.calculateLambda().toReal().value(); 0220 // double d = df.calculateLambda().toReal().value(); 0221 // 0222 // i++; 0223 // t = t0 - r/d; 0224 // 0225 // if ((error < E) || (i > MAX_I)) 0226 // break; 0227 // 0228 // error = fabs(t - t0); 0229 // t0 = t; 0230 // } 0231 // 0232 // //TODO 0233 // // t0 = 1.0; 0234 // // t = t0; 0235 // // error = 1000.0; 0236 // // i = 0; 0237 // // 0238 // // while (true) 0239 // // { 0240 // // m_th->setValue(t0); 0241 // // 0242 // // double r = g.calculateLambda().toReal().value(); 0243 // // double d = dg.calculateLambda().toReal().value(); 0244 // // 0245 // // i++; 0246 // // t = t0 - r/d; 0247 // // 0248 // // if ((error < E) || (i > MAX_I)) 0249 // // break; 0250 // // 0251 // // error = fabs(t - t0); 0252 // // t0 = t; 0253 // // } 0254 // 0255 // Analitza::Analyzer dfunc(newanalyzer.variables()); 0256 // danalyzer.setExpression(newanalyzer.derivative("t")); 0257 // danalyzer.setStack(m_runStack); 0258 // 0259 // m_th->setValue(t); 0260 // 0261 // Expression res = danalyzer.calculateLambda(); 0262 // Cn comp1 = res.elementAt(0).toReal(); 0263 // Cn comp2 = res.elementAt(1).toReal(); 0264 // 0265 // double m = comp2.value()/comp1.value(); 0266 // 0267 // return FunctionUtils::slopeToLine(m); 0268 return QLineF(); 0269 } 0270 0271 REGISTER_PLANECURVE(FunctionPolar) 0272