/*************************************************************************** qscontour.h ------------------- 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 QSCONTOUR_H #define QSCONTOUR_H #ifdef HAVE_CONFIG_H #include #endif #include"qsaxes.h" #include"qsplot.h" #include /** * \brief Abstract base class for contour datasets. * * Draws contours. It contains a pure virtual functions which must be * reimplemented to get it to work. * @author Kamil Dobkowski */ class QSContour : public QSPlot2D { Q_OBJECT Q_PROPERTY( bool contourFills READ contourFills WRITE setContourFills ) Q_PROPERTY( bool contourLines READ contourLines WRITE setContourLines ) Q_PROPERTY( bool contourLabels READ contourLabels WRITE setContourLabels ) Q_PROPERTY( double labelSpacing READ labelSpacing WRITE setLabelSpacing ) public: /** * Constructor. */ QSContour(QSAxes* parent, const char * name=0); /** * Destructor. */ virtual ~QSContour(); void setContourFills( bool visible ); void setContourLines( bool visible ); void setContourLabels( bool visible ); void setLabelSpacing( double labelSpacing ); bool contourFills() const { return m_fills; } bool contourLines() const { return m_lines; } bool contourLabels() const { return m_labels; } double labelSpacing() const { return m_label_spacing; } virtual QString posInfo( QSPt2f& pos ); virtual bool isClicked( const QSPt2f& pos ); virtual QSPt2f legendItemSize( QSDrv *drv ); virtual void drawLegendItem( const QSPt2f& pos, QSDrv *drv ); virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); /** * See QSGraphicalData::setPoint() */ enum PointElement { PointMark = 0 }; /** * See QSGraphicalData::setLine() */ enum LineElement { Grid = 0 }; protected: /** * See getTriangle() */ static const double EPS_VALUE; virtual void allocRuntimeData(); virtual void freeRuntimeData(); virtual bool start(); /** * This will be called until it returns true and can be reimplemented for * some in the background stuff. */ virtual bool prepare() { return true; } virtual bool step(); virtual void end(); /** * Returns a total number of triangles. */ virtual int triangles() = 0; /** * Returns triangle number 'number'. * The first edge is between pts[0] and pts[1] * the second one is between pts[1] and pts[2] * the third one is between pts[2] and pts[0] * point z values must not be equal to level. If there is such point add EPS_VALUE * to its z coordinate. * see: getNeighboutingTriangle() */ virtual void getTriangle( int number, QSPt3f pts[3], double level = -10.0 ) = 0; /** * Returns if there is a neighbouring triangle. In 'number' and 'edge' * returns a neighbouring triangle and edge of triangle 'number' and edge 'edge'. */ virtual bool getNeighbouringTriangle( int *number, int *edge ) = 0; /** * Returns a number of a triangle which contains the point 'pos' if any or -1. * Used by 'isClicked' and 'posInfo' subroutines. * Nothing really nessesary */ virtual int triangleAtPos( const QSPt2f& pos ) = 0; /** * Returns info about the vertex 'v' of the triangle 't'. * Nothing really nessesary */ virtual QString vertexInfo( int t, int v, QSPt2f& pos ) = 0; /** * Draw grid ( lines connecting data points ) */ virtual void drawGrid() = 0; /** * Draw point marks */ virtual void drawPoints() = 0; /** * Reimplement this to return true if the contour is drawn over rectangle grid. * The getRectangle() method should be reimplemented too in this case. Rectangles * are assumed be divided into four triangles. Rectangle 0 contains triangles 0-3, * rectangle 1 contains triangles 4-7 etc ... */ virtual bool rectangleGrid() const { return false; } /** * Reimplement this to return rectangle coordinates if the contour is drawn over rectangle grid. * The rectangleGrid() method should be reimplemented too in this case. Rectangles * are assumed be divided into four triangles. Rectangle 0 contains triangles 0-3, * rectangle 1 contains triangles 4-7 etc ... The function id provided for efficiency only. * Whole rectangles ( four triangles ) will be processed in a single step during drawing. */ virtual void getRectangle( int triangleNumber, QSPt3f pts[4] ) {} private: bool m_labels; bool m_fills; bool m_lines; double m_label_spacing; struct contour_runtime_data; struct contour_levels_data; struct contour_runtime_data *d; void init_triangle_buffer(); void call_prepare(); void start_drawing_fills(); void drawing_fills(); void start_drawing_grid(); void drawing_grid(); void start_drawing_lines(); void drawing_lines(); void start_drawing_labels(); void drawing_labels(); void start_drawing_points(); void drawing_points(); void calculate_levels_data( contour_levels_data *data ); void free_levels_data( contour_levels_data *data ); void start_contour( const QSPt3f& p1, const QSPt3f& p2, int level ); void draw_contour( const QSPt3f& p1, const QSPt3f& p2, int level ); void end_contour( int level ); void draw_line_buffer( int level ); void cut_polygon( double level, const QSPt3f *pts, int npts, QSPt3f *above_pts, int *above_npts, QSPt3f *under_pts, int *under_npts, QSPt3f *cross_line = NULL, int *cross_npts = NULL ); inline double distance( const QSPt2f& p1, const QSPt2f& p2 ); int find_level_greater_than( double value ); void flush_rectangle_buffer(); bool draw_rectangle( const QSPt3f pts[4] ); }; inline double QSContour::distance( const QSPt2f& p1, const QSPt2f& p2 ) { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); } //------------------------------------------------------------------------------------------------------------------// /** * \brief Dataset : Draws contours over gridded data. * * Data format is described in QSGriddedContour::Channels . See also QSAxes::plotAdd() . * @author Kamil Dobkowski */ class QSGriddedContour : public QSContour { Q_OBJECT public: /** * Descriptive names of data channels. See QSData::setMatrix(). * Data contains Z values, * XVector ( optional ) contains x coordinates of a grid, YVector ( optional ) contains y coordinates of a grid. * cols(XVector) == cols(Data) and rows(YVector) == rows(Data), both vectors must be monotone. */ enum Channels { XVector = 0, YVector = 1, // Column vector, monotone. Size 1 x h+1 Data = 2 }; /** * Destructor. */ QSGriddedContour(QSAxes* parent, const char * name=0); /** * Destructor. */ virtual ~QSGriddedContour(); virtual ColumnType columnType( int channel, int column ) const; virtual QString channelVariable( int channel ) const; virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); protected: virtual bool getAxisRange( QSAxis *axis, double& min, double& max ); virtual void dataChanged( int channel = -1 ); virtual void allocRuntimeData(); virtual void freeRuntimeData(); virtual int triangles(); virtual void getTriangle( int number, QSPt3f pts[3], double level = -10.0 ); virtual bool getNeighbouringTriangle( int *number, int *edge ); virtual int triangleAtPos( const QSPt2f& pos ); virtual QString vertexInfo( int t, int v, QSPt2f& pos ); virtual void drawGrid(); virtual void drawPoints(); virtual bool rectangleGrid() const { return true; } virtual void getRectangle( int triangleNumber, QSPt3f pts[4] ); private: double m_dmin; double m_dmax; bool m_evalid; void calculate_data_range(); double xvector( int col ); double yvector( int row ); struct gridded_contour_runtime_data; gridded_contour_runtime_data *d; void load_mesh_into_buffer( int triangleNumber ); }; //------------------------------------------------------------------------------------------------------------------// /** * \brief Dataset: Draws contours over non-gridded data. * * Data format is described in QSNonGriddedContour::Channels . See also QSAxes::plotAdd() . * @author Kamil Dobkowski */ class QSNonGriddedContour : public QSContour { Q_OBJECT public: /** * Descriptive names of data channels. See QSData::setMatrix(). * VXCoords, VYCoord, VZCoord must have a one column and the same number of rows. * VXCoord contains x coordinates, VYCords contains y coordinates, and VZCoord contains z coordinates. * The same row in all those matrices defines a one data point, so we have rows(VXCoord) data points. * Triangles must have three columns and must contain indices to rows in Coord matrices, so one index * defines one point. One row in Triangles defines a one traingle. Such matrix can be calculated by * triangulating the given set of points, Traiangles is required because this object just can't draw * contour using only data points. */ enum Channels { VXCoord = 0, VYCoord = 1, VZCoord = 2, Triangles = 3 // size 3 x number of triangles }; /** * Destructor. */ QSNonGriddedContour(QSAxes* parent, const char * name=0); /** * Destructor. */ virtual ~QSNonGriddedContour(); virtual ColumnType columnType( int channel, int column ) const; virtual QString channelVariable( int channel ) const; virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory ); virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory ); protected: virtual bool getAxisRange( QSAxis *axis, double& min, double& max ); virtual void dataChanged( int channel = -1 ); virtual bool prepare(); virtual void allocRuntimeData(); virtual void freeRuntimeData(); virtual int triangles(); virtual void getTriangle( int number, QSPt3f pts[3], double level = -10.0 ); virtual bool getNeighbouringTriangle( int *number, int *edge ); virtual int triangleAtPos( const QSPt2f& pos ); virtual QString vertexInfo( int t, int v, QSPt2f& pos ); virtual void drawGrid(); virtual void drawPoints(); private: bool m_evalid; double m_xmax; double m_ymax; double m_zmax; double m_xmin; double m_ymin; double m_zmin; int *m_neighbours[3]; struct non_gridded_contour_runtime_data; non_gridded_contour_runtime_data *d; QSPt3f point( int index ); void search_for_neighbours(); void make_visible_triangles_list(); }; #endif