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.

380 lines
12 KiB

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