Description: * Fixes for 3D Graph->Dots, Lines and Solid. Author: Prathibha B --- The information above should follow the Patch Tagging Guidelines, please checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here are templates for supplementary fields that you might want to add: Origin: , Bug: Bug-Debian: https://bugs.debian.org/ Bug-Ubuntu: https://launchpad.net/bugs/ Forwarded: Reviewed-By: Last-Update: --- kalgebra-4.14.2.orig/src/CMakeLists.txt +++ kalgebra-4.14.2/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(kalgebra_SRCS variablesdelegate.cpp viewportwidget.cpp functionedit.cpp + graph3d.cpp ) #uncomment this if oxygen icons for kalgebra are available --- /dev/null +++ kalgebra-4.14.2/src/graph3d.cpp @@ -0,0 +1,536 @@ +/************************************************************************************* + * Copyright (C) 2007 by Aleix Pol * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#include "graph3d.h" + +#if defined(Q_WS_MAC) + #include +#else + #include +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::fabs; +using std::log10; + +using namespace Analitza; + +enum ActionsEnum { + KEYRIGHT=1<<0, KEYLEFT=1<<1, KEYUP=1<<2, KEYDOWN=1<<3, KEYAVPAG=1<<4, KEYREPAG=1<<5, KEYS=1<<6, KEYW=1<<7, + KEYQ=1<<8, KEYE=1<<9, LCLICK=1<<10, RCLICK=1<<11, MCLICK=1<<12 }; + +Graph3D::Graph3D(QWidget *parent) : QGLWidget(parent), + default_step(0.15f), default_size(10.0f), zoom(1.0f), points(0), alpha(60.), + method(Solid), trans(false), keyspressed(0), m_n(4) +{ + setFocusPolicy(Qt::ClickFocus); + rotation[0] = 90.0; + rotation[1] = 0.0; + rotation[2] = 0.0; +} + + +Graph3D::~Graph3D() +{ + if(points) { + const int j= 2*static_cast(default_size/default_step); + + for(int i=0; ibutton() == Qt::LeftButton) { + press = e->pos(); + keyspressed |= LCLICK; + } +} + +void Graph3D::mouseReleaseEvent(QMouseEvent *e) +{ + if(e->button() == Qt::LeftButton) + keyspressed &= ~LCLICK; +} + +void Graph3D::mouseMoveEvent(QMouseEvent *e) +{ + if(keyspressed & LCLICK){ + QPoint rel = e->pos() - press; + rotation[0] += rel.y(); + rotation[2] -= rel.x(); + + press = e->pos(); + repaint(); + } +} + +void Graph3D::drawAxes() +{ + glColor3f(0.8, 0.8, 0.4); + renderText(11.0, 0.0, 0.0, "Y"); + renderText(0.0, 11.0, 0.0, "X"); + renderText(0.0, 0.0,-11.0, "Z"); + + glBegin(GL_LINES); + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(-10.0f, 0.0f, 0.0f); + glVertex3f( 10.0f, 0.0f, 0.0f); + glColor3f(0.0f, 1.0f, 0.0f); + glVertex3f( 0.0f, 10.0f, 0.0f); + glVertex3f( 0.0f,-10.0f, 0.0f); + glColor3f(0.0f, 0.0f, 1.0f); + glVertex3f( 0.0f, 0.0f, 10.0f); + glVertex3f( 0.0f, 0.0f,-10.0f); + glEnd(); +} + +void Graph3D::paintGL() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(keyspressed & KEYDOWN) rotation[0]+=3.f; + if(keyspressed & KEYUP) rotation[0]-=3.f; + if(keyspressed & KEYAVPAG) rotation[1]+=3.f; + if(keyspressed & KEYREPAG) rotation[1]-=3.f; + if(keyspressed & KEYLEFT) rotation[2]+=3.f; + if(keyspressed & KEYRIGHT) rotation[2]-=3.f; + if(keyspressed & KEYW) alpha/=2.f; + if(keyspressed & KEYS && alpha<=90.f) alpha*=2.f; + if(keyspressed & KEYQ) { zoom/=2.0f; create(a.expression()); } + if(keyspressed & KEYE) { zoom*=2.0f; create(a.expression()); } + + if(rotation[0]>=360.f) rotation[0]-=360.f; + if(rotation[1]>=360.f) rotation[1]-=360.f; + if(rotation[2]>=360.f) rotation[2]-=360.f; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(alpha,(GLfloat)width()/(GLfloat)height(),0.1f,100.0f); + + float z=25.f; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0,0,-z); + glRotatef(rotation[0], 1.0, 0.0, 0.0); + glRotatef(rotation[1], 0.0, 1.0, 0.0); + glRotatef(rotation[2], 0.0, 0.0, 1.0); + + const double mida=default_size*zoom, step=default_step*zoom; + uint bound=(2*mida/step)-1; + drawAxes(); + + if(!points) + return; + + if(method==Dots) { + glBegin(GL_POINTS); + for(uint i=0; i(mida/step)*2; + + int part = k/m_n; + QList threads; + + a.setExpression(func3d); + + QTime t; + t.restart(); + + for(int i=0; isetTo(2*static_cast(default_size/default_step)); + + threads << r; + r->start(); + } + + bool ret=true; + QList::const_iterator it = threads.constBegin(); + for(; it!=threads.constEnd(); ++it) { + if(!(*it)->wait(1000)) { + ret=false; + (*it)->terminate(); + } + } + +// qDebug() << "Elapsed time" << t.elapsed(); + + qDeleteAll(threads); + return ret; +} + +void Calculate3D::run() +{ + Q_ASSERT(a.isCorrect()); + Q_ASSERT(points); + + const int k= static_cast(size/step)*2; + + Cn *x=new Cn; + Cn *y=new Cn; + + QVector runStack; + runStack.append(x); + runStack.append(y); + a.setStack(runStack); + + for(int j=from; jsetValue(j*step-size); + for(int i=0; isetValue(i*step-size); + points[j][i] = -a.calculateLambda().toReal().value(); + } + } + qDeleteAll(runStack); +} + +void Graph3D::wheelEvent(QWheelEvent * e) +{ + if(e->delta()>0) + alpha/=2.f; + else if(alpha<=90.f) + alpha*=2.f; + repaint(); +} + +void Graph3D::keyPressEvent( QKeyEvent *e ) +{ + switch(e->key()) { + case Qt::Key_Up: + keyspressed |= KEYUP; + break; + case Qt::Key_Down: + keyspressed |= KEYDOWN; + break; + case Qt::Key_Left: + keyspressed |= KEYLEFT; + break; + case Qt::Key_Right: + keyspressed |= KEYRIGHT; + break; + case Qt::Key_PageUp: + keyspressed |= KEYREPAG; + break; + case Qt::Key_PageDown: + keyspressed |= KEYAVPAG; + break; + case Qt::Key_W: + keyspressed |= KEYW; + break; + case Qt::Key_S: + keyspressed |= KEYS; + break; + case Qt::Key_Q: //Be careful + keyspressed |= KEYQ; + break; + case Qt::Key_E: //Be careful + keyspressed |= KEYE; + break; + } +// sendStatus(QString("-%1-").arg(keyspressed, 16)); + repaint(); +} + +void Graph3D::keyReleaseEvent( QKeyEvent *e ) +{ + switch(e->key()) { + case Qt::Key_Up: + keyspressed &= ~KEYUP; + break; + case Qt::Key_Down: + keyspressed &= ~KEYDOWN; + break; + case Qt::Key_Left: + keyspressed &= ~KEYLEFT; + break; + case Qt::Key_Right: + keyspressed &= ~KEYRIGHT; + break; + case Qt::Key_PageUp: + keyspressed &= ~KEYREPAG; + break; + case Qt::Key_PageDown: + keyspressed &= ~KEYAVPAG; + break; + case Qt::Key_W: + keyspressed &= ~KEYW; + break; + case Qt::Key_S: + keyspressed &= ~KEYS; + break; + case Qt::Key_Q: //Be careful + keyspressed &= ~KEYQ; + break; + case Qt::Key_E: //Be careful + keyspressed &= ~KEYE; + break; + + } +// sendStatus(QString(".%1.").arg(keyspressed, 16)); + repaint(); +} + +void Graph3D::timeOut() +{ + rotation[0] += 20.0; + rotation[1] += 20.0; + rotation[2] += 20.0; + repaint(); +} + +bool Graph3D::checkExpression(const QStringList& bvars, const Analitza::ExpressionType& actual) +{ + if(bvars!=(QStringList("x") << "y")) { + return false; + } + + static ExpressionType expected=ExpressionType(ExpressionType::Lambda) + .addParameter(ExpressionType::Value) + .addParameter(ExpressionType::Value) + .addParameter(ExpressionType::Value); + + return actual.canReduceTo(expected); +} + +void Graph3D::setFunc(const Expression& exp) +{ + if(exp.isCorrect()) { + Analitza::Analyzer f3d; + f3d.setExpression(exp); + f3d.setExpression(f3d.dependenciesToLambda()); + f3d.simplify(); + + if(!checkExpression(f3d.expression().bvarList(), f3d.type())) { + sendStatus(i18n("Error: Wrong type of function")); + return; + } + + if(f3d.isCorrect()) { + QTime t; + t.restart(); + mem(); + create(f3d.expression()); + // xgettext: no-c-format + sendStatus(i18nc("3D graph done in x milliseconds", "Done: %1ms", t.elapsed())); + } + else + sendStatus(i18n("Error: %1", f3d.errors().join(", "))); + } else + sendStatus(i18n("Error: %1", exp.error().join(", "))); +} + +void Graph3D::mem() +{ + const int j= 2*static_cast(default_size/default_step); + if(points!=0){ + for(int i=0; i * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#ifndef GRAPH3D_H +#define GRAPH3D_H + +#include +#include + +#include "analitza/analyzer.h" + +/** + * Used to calculate 3D Graphs in parallel. + * @author Aleix Pol i Gonzalez + */ + +class Calculate3D : public QThread +{ +public: + /** Constructor. Creates a Calculate3D thread. + @param p parent object. + @param na Analitza module used fot the calculations. + @param poi memory space where the results will be located. + @param fr Beginning of the calculated values. + @param to End of the calculated values. + @param m Distance of each dimension from the (0, 0) to be calculated. + @param s Step between each 2 values. + */ + Calculate3D(QObject *p, const Analitza::Analyzer &na, double** poi, int fr, int to, double m, double s) : + QThread(p), a(na), points(poi), from(fr), to(to), size(m), step(s) {} + + /** Runs the thread. */ + void run(); + + /** Sets the end of the segment to calculate. */ + void setTo(int nto) { to = nto; } +private: + Analitza::Analyzer a; + double **points; + int from; + int to; + + double size; + double step; +}; + +/** + * The Graph3D provides a 3D OpenGL graph representation. + * @author Aleix Pol i Gonzalez + */ + +class Graph3D : public QGLWidget +{ + Q_OBJECT + public: + /** Defines how will be the graph representated. */ + enum Type { + Dots=0, ///< Dots will be drawn. + Lines=1, ///< Lines will be drawn. + Solid=2 ///< A solid graph will be drawn with a line texture. + }; + + /** Constructor. Creates a new Graph3D widget. */ + Graph3D(QWidget *parent = 0); + + /** Destructor. */ + ~Graph3D(); + + /** Sets @p exp as the function's expression. */ + void setFunc(const Analitza::Expression& exp); + + /** Toggles the transparency for Solid graphs. */ + void setTransparency(bool tr) { trans = tr; glDraw(); } + + /** Returns whether there is transparency. */ + bool transparency() const { return trans; } + + /** Returns the pixmap painting. */ + QPixmap toPixmap(); + + /** Sets the @p max maximum size. */ + void setSize(double max); + + /** Sets the interval between two points. */ + void setStep(double res); + + /** Sets the Z coordinate. */ + void setZoom(float alpha); + + /** Sets the showed method. */ + void setMethod(Type m); + + void wheelEvent(QWheelEvent *e); + + static bool checkExpression(const QStringList& bvars, const Analitza::ExpressionType& actual); + + public slots: + /** Resets the view coordinates. */ + void resetView(); + + signals: + /** Emits a status message. */ + void status(const QString &msg); + + private: + void drawAxes(); + + virtual void initializeGL() ; + virtual void resizeGL( int width, int height ) ; + virtual void paintGL() ; + + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); + void timeOut(); + void mousePressEvent(QMouseEvent *e); QPoint press; + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mem(); + bool create(const Analitza::Expression& func3d); + void sendStatus(const QString& msg) { emit status(msg); } + + Analitza::Analyzer a; + double default_step; + double default_size; + double zoom; + double **points; + float rotation[3]; + float alpha; + Type method; + bool trans; + unsigned short keyspressed; + + int m_n; +}; + +#endif --- kalgebra-4.14.2.orig/src/kalgebra.cpp +++ kalgebra-4.14.2/src/kalgebra.cpp @@ -25,7 +25,8 @@ #include "viewportwidget.h" #include "functionedit.h" #ifdef HAVE_OPENGL -# include +//# include +#include "graph3d.h" #endif #include @@ -83,7 +84,7 @@ class Add2DOption : public InlineOptions KAlgebra* m_kalgebra; }; -#ifdef HAVE_OPENGL +/*#ifdef HAVE_OPENGL class Add3DOption : public InlineOptions { public: @@ -104,6 +105,30 @@ class Add3DOption : public InlineOptions private: KAlgebra* m_kalgebra; }; +#endif */ + +#ifdef HAVE_OPENGL +class Add3DOption : public InlineOptions +{ + public: + Add3DOption(KAlgebra* c) + : m_kalgebra(c) + {} + + virtual QString id() const { return "add3d"; } + virtual bool matchesExpression(const Analitza::Expression& exp, const Analitza::ExpressionType& functype) const + { + return Graph3D::checkExpression(exp.bvarList(), functype); + //return NULL; + } + + virtual QString caption() const { return i18n("Plot 3D"); } + + virtual void triggerOption(const Analitza::Expression& exp) { m_kalgebra->add3D(exp); } + + private: + KAlgebra* m_kalgebra; +}; #endif QColor randomFunctionColor() { return QColor::fromHsv(qrand()%255, 255, 255); } @@ -538,31 +563,39 @@ void KAlgebra::new_func3d() Analitza::Expression exp = t_exp->expression(); Analitza::PlotBuilder plot = Analitza::PlotsFactory::self()->requestPlot(exp, Analitza::Dim3D, c_results->analitza()->variables()); if(plot.canDraw()) { - t_model3d->clear(); - t_model3d->addPlot(plot.create(Qt::yellow, "func3d")); + //t_model3d->clear(); + //t_model3d->addPlot(plot.create(Qt::yellow, "func3d")); + m_graph3d->setFunc(t_exp->expression()); + m_graph3d->setFocus(); + changeStatusBar(i18nc("@info:status", "Ready")); } else changeStatusBar(i18n("Errors: %1", plot.errors().join(i18n(", ")))); + //m_graph3d->setFunc(t_exp->expression()); + //m_graph3d->setFocus(); #endif } void KAlgebra::set_dots() { #ifdef HAVE_OPENGL - m_graph3d->setPlotStyle(Analitza::Dots); + //m_graph3d->setPlotStyle(Analitza::Dots); + m_graph3d->setMethod(Graph3D::Dots); #endif } void KAlgebra::set_lines() { #ifdef HAVE_OPENGL - m_graph3d->setPlotStyle(Analitza::Wired); + //m_graph3d->setPlotStyle(Analitza::Wired); + m_graph3d->setMethod(Graph3D::Lines); #endif } void KAlgebra::set_solid() { #ifdef HAVE_OPENGL - m_graph3d->setPlotStyle(Analitza::Solid); + //m_graph3d->setPlotStyle(Analitza::Solid); + m_graph3d->setMethod(Graph3D::Solid); #endif } @@ -728,10 +761,12 @@ void KAlgebra::varsContextMenu(const QPo void KAlgebra::add3D(const Analitza::Expression& exp) { #ifdef HAVE_OPENGL - t_model3d->clear(); + /*t_model3d->clear(); Analitza::PlotBuilder plot = Analitza::PlotsFactory::self()->requestPlot(exp, Analitza::Dim3D, c_results->analitza()->variables()); Q_ASSERT(plot.canDraw()); t_model3d->addPlot(plot.create(Qt::yellow, "func3d_console")); + m_tabs->setCurrentIndex(2);*/ + m_graph3d->setFunc(exp); m_tabs->setCurrentIndex(2); #endif } @@ -773,10 +808,11 @@ void KAlgebra::set3DGraph() t_exp->setAns("x"); t_exp->setFocus(); - t_model3d = new Analitza::PlotsModel(this); - m_graph3d = new Analitza::PlotsView3D(tridim); - m_graph3d->setModel(t_model3d); - m_graph3d->setUseSimpleRotation(true); + //t_model3d = new Analitza::PlotsModel(this); + //m_graph3d = new Analitza::PlotsView3D(tridim); + m_graph3d = new Graph3D(tridim); + //m_graph3d->setModel(t_model3d); + //m_graph3d->setUseSimpleRotation(true); connect(t_exp, SIGNAL(returnPressed()), this, SLOT(new_func3d())); t_layo->addWidget(m_graph3d); t_layo->addWidget(t_exp); --- kalgebra-4.14.2.orig/src/kalgebra.h +++ kalgebra-4.14.2/src/kalgebra.h @@ -31,7 +31,7 @@ namespace Analitza { class PlotsView2D; -class PlotsView3D; +//class PlotsView3D; class PlotsModel; class VariablesModel; class ExpressionEdit; @@ -40,6 +40,7 @@ class ExpressionEdit; class ConsoleHtml; class FunctionEdit; class KRecentFilesAction; +class Graph3D; namespace Analitza { class Expression; } @@ -82,7 +83,8 @@ class KAlgebra : public KMainWindow //graph 3d QMenu* t_menu; Analitza::ExpressionEdit *t_exp; - Analitza::PlotsView3D *m_graph3d; + //Analitza::PlotsView3D *m_graph3d; + Graph3D *m_graph3d; Analitza::PlotsModel* t_model3d; #endif //Dictionary