/*************************************************************************** qsplot.h ------------------- version : 0.1 begin : 01-January-2000 copyright : (C) 2000 by Kamil Dobkowski email : kamildobk@poczta.onet.pl ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef QSPLOT_H #define QSPLOT_H #ifdef HAVE_CONFIG_H #include #endif #include"qsaxes.h" #include"qsaxis.h" #include"qsdrv.h" #include #include /** * \brief Dataset, which can be diplayed using QSAxes * * Dataset, which can be diplayed using QSAxes, see QSAxes::plotAdd(). You can bind this dataset to some axes * in the parent object using setDefaultAxis(). You can map coordinates from data to world coordinates using * worldToData(). QSPlot contains support for drawing legends, see drawLegendItem(), legendItemSize(). QSCLegend * uses them extensively. There is also support for 'Data picker' tool implemented, see posInfo(). * For implementing your own dataset types you will have to reimplement : getAxisRange(), start(), step(), end(), * and also drawLegendItem(), legendItemSize(), posInfo(), and optionaly allocRuntimeData(), freeRuntimeData(). * @author Kamil Dobkowski */ class QSPlot : public QSAxesChild { Q_OBJECT friend class QSAxes; Q_PROPERTY( int defaultXAxis READ defaultXAxis WRITE setDefaultXAxis ) Q_PROPERTY( int defaultYAxis READ defaultYAxis WRITE setDefaultYAxis ) Q_PROPERTY( int defaultZAxis READ defaultZAxis WRITE setDefaultZAxis ) Q_PROPERTY( int defaultVAxis READ defaultVAxis WRITE setDefaultVAxis ) Q_PROPERTY( bool legendItemVisible READ legendItemVisible WRITE setLegendItemVisible ) Q_PROPERTY( QString gradient READ gradientProperty WRITE setGradientProperty ) public: /** * Constructor. You must add the plot immedialtely to the parent child list * ( see QSAxes::plotAdd() ) */ QSPlot( QSAxes *parentAxes=0, const char *name=0 ); /** * Destructor. */ virtual ~QSPlot(); /** * Sets an axis to which to bind to. Type of this axis is taken from QSAxis::type() . */ void setDefaultAxis( QSAxis *axis ); /** * Sets the default axis. */ void setDefaultXAxis( int axisIndex ); /** * Sets the default axis. */ void setDefaultYAxis( int axisIndex ); /** * Sets the default axis. */ void setDefaultZAxis( int axisIndex ); /** * Sets the default axis. */ void setDefaultVAxis( int axisIndex ); /** * Returns an index of the default axis */ int defaultXAxis() const { return m_axes->axisIndex(m_daxes[QSAxis::XAxisType]); } /** * Returns an index of the default axis */ int defaultYAxis() const { return m_axes->axisIndex(m_daxes[QSAxis::YAxisType]); } /** * Returns an index of the default axis */ int defaultZAxis() const { return m_axes->axisIndex(m_daxes[QSAxis::ZAxisType]); } /** * Returns an index of the default axis */ int defaultVAxis() const { return m_axes->axisIndex(m_daxes[QSAxis::VAxisType]); } /** * Returns default axis. 'axisType' must be one of * QSAxes::AxisType' ! */ QSAxis *defaultAxis( int axisType ) const { return m_daxes[axisType]; } /** * Sets a gradient object */ void setGradient( const QSGGradient& gradient ); /** * Returns a gradient */ const QSGGradient gradient() const { return m_gradient; } /** * Show legend item corresponding to this plot in legend object */ void setLegendItemVisible( bool visible ); /** * Returns legend setting. */ bool legendItemVisible() const { return m_is_legend; } /** * Returns info or QString::null */ virtual QString posInfo( QSPt2f& pos ); /** * Returns item size */ virtual QSPt2f legendItemSize( QSDrv *drv ); /** * Draw legend item at position 'pos' */ virtual void drawLegendItem( const QSPt2f& pos, QSDrv *drv ); /** * Maps a point from an visible axis range to <0,1> */ QSPt2f dataToWorld( const QSPt2f& p ) const; /** * Maps a point from an visible axis range to <0,1> */ QSPt3f dataToWorld( const QSPt3f& p ) const; /** * Maps a point from an visible axis range to <0,1> */ QSPt3f dataToWorldV( const QSPt3f& p ) const; /** * Maps a point from <0,1> to an visible axis range. */ QSPt2f worldToData( const QSPt2f& p ) const; /** * Maps a point from <0,1> to an visible axis range */ QSPt3f worldToData( const QSPt3f& p ) const; /** * Maps a point from <0,1> to an visible axis range */ QSPt3f worldToDataV( const QSPt3f& p ) const; /** * Sets a new gradient. */ void setGradientProperty( const QString& string ); /** * Returns gradient as QString */ QString gradientProperty() const { return toQString(m_gradient); } virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); protected slots: /** * Check if this plot is not bound to a removed axis. * if it is, find another axis of the same type - there * always should be at least one such axis.. */ virtual void axisRemoved( QSData *object ); protected: /** * Must be reimplemented and return data range on each axis or * false when no data is set. This functions is always called * outside 'start()' and 'end()' ! */ virtual bool getAxisRange( QSAxis *axis, double& min, double& max ); /** * Start drawing. Called by parent axes. * Time-expensive operations should be * performed in little parts during 'step()' * call. If returns false - 'end()' is called * immediately, if returns true - 'step()' is * called next. */ virtual bool start(); /** * This function will be called to make drawing * until it returns false. Notice that drawing * should be stopped at any time. Even if this * function returns true parent axes object may * decide to call end(). */ virtual bool step(); /** * This can be called by parent axes to stop drawing. * Normally called after 'step()' returned false; */ virtual void end(); /** * Called from start(). Everyting which goes to start() may be put here. * inits m_curr_driver, m_curr_dpi, m_csize, m_cpos fields with values * taken from parent axes */ virtual void allocRuntimeData(); /** * Called from end().Everyting which goes to end() may be put here. */ virtual void freeRuntimeData(); static const int work_steps = 30; bool m_busy; bool m_is_legend; int m_bkg_handler; double m_curr_dpi; QSDrv *m_drv; QSPt2f m_csize; QSPt2f m_cpos; QSAxis *m_daxes[5]; QSAxes *m_axes; QSGGradient m_gradient; const QSProjection *m_proj; }; //--------------------------------------------------------------------------------------// /** * \brief 2D Dataset * * Ups ,,, There is no new functionality added to this class, yet. It is the same as QSPlot.. * @author Kamil Dobkowski */ class QSPlot2D : public QSPlot { Q_OBJECT public: /** * Constructor. */ QSPlot2D( QSAxes *parentAxes, const char *name=0 ); /** * Destructor. */ virtual ~QSPlot2D(); }; //--------------------------------------------------------------------------------------// /** * \brief 3D Dataset * * Base class for all 3d datasets ( which draw 3d mesh ). Allows setting * mesh parameters, which are used to initialize QSDrv and to draw 3d polygons * with drawPolygon(). * @author Kamil Dobkowski */ class QSPlot3D : public QSPlot { Q_OBJECT Q_PROPERTY( bool colored READ colored WRITE setColored ) Q_PROPERTY( bool topBottom READ topBottom WRITE setTopBottom ) Q_PROPERTY( bool autoDivide READ autoDivide WRITE setAutoDivide ) Q_PROPERTY( int edgeAutoColor READ edgeAutoColor WRITE setEdgeAutoColor ) public: /** * Constructor. */ QSPlot3D( QSAxes *parentAxes, const char *name=0 ); /** * Destructor. */ virtual ~QSPlot3D(); /** * Enables/disables coloring of the 3d mesh. */ void setColored( bool enabled ); /** * */ void setTopBottom( bool enabled ); /** * */ void setAutoDivide( bool enabled ); /** * */ void setEdgeAutoColor( int value ); /** * */ void setClipping( bool clipping ); /** * */ bool topBottom() const { return m_topbottom; } /** * */ bool autoDivide() const { return m_divide; } /** * */ int edgeAutoColor() const { return m_edge_auto_color; } /** * */ bool clipping() { return m_clipping; } /** * Returns the current color setting. */ bool colored() const { return m_colored; } virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); /** * See QSGraphicalData::setFill() */ enum FillElement { TMeshFill, BMeshFill }; /** * See QSGraphicalData::setLine() */ enum LineElement { MeshLine }; /** * See QSGraphicalData::setPoint() */ enum PointElement { PointMark }; protected: bool m_clipping; bool m_colored; int m_edge_auto_color; bool m_divide; bool m_topbottom; QSDrv::CNormals m_cnormals; QSDrv::CColors m_ccolors; QSDrv::COrdering m_corder; /** * Draws a surface mesh. It is almost the same as QSDrv::drawPoly3(), but draws using a nice colored gradient ( divides polygon into levels ). * If 'values' is not NULL draws 4D data, 'values' must be table with npoints elements int this case. */ void drawPolygon( const QSPt3f pts[], int npoints, QSPt3f *norm, const double *values=NULL, const bool *edges=NULL ); /** * Reimplemented. Inits m_ccolors, m_cnormals, m_corder */ virtual void allocRuntimeData(); /** * Called from end().Everyting which goes to end() may be put here. */ virtual void freeRuntimeData(); /** * Draws gradient legend */ virtual QSPt2f standardLegendItemSize( QSDrv *drv, QSAxis *axis, const QString& title ); /** * Draws gradient legend */ virtual void drawStandardLegendItem( const QSPt2f& pos, QSDrv *drv, QSAxis *axis, const QString& title, const QSGGradient *gradient ); private: struct plot3d_runtime_data; struct plot3d_runtime_data *d; }; #endif