You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
12 KiB

/***************************************************************************
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 <config.h>
#endif
#include"qsaxes.h"
#include"qsaxis.h"
#include"qsdrv.h"
#include<qstring.h>
#include<math.h>
/**
* \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