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.

511 lines
16 KiB

/***************************************************************************
qsaxis.h
-------------------
version : 0.1
begin :
copyright : (C) 2001 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 QSAXIS_H
#define QSAXIS_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include"qsaxes.h"
#include<qstring.h>
#include<math.h>
#include<list.h>
//---------------------------------------------------------------------------------------------------//
/**
* \brief Tic mark on the axis
*
* Tic mark on the axis.
* @author Kamil Dobkowski
*/
class QSAxisTic;
class QSAxisTic {
public:
double m_value; // value of the tic
bool m_major; // major or minor tics
double m_pos; // tic position on axis in world coordnates
int m_angle; // label angle
QString m_label;
QSGFont m_font;
QSGLine m_line;
QSGFill m_fill; // used to fill area below the tic
bool m_is_fill_defined;
QSAxisTic( double value = 0.0, bool major = true );
~QSAxisTic();
bool operator<( const QSAxisTic& t ) { return m_pos < t.m_pos; }
};
//---------------------------------------------------------------------------------------------------//
/**
* MOC have problems if it is internal QSAxis class !.
*/
typedef struct {
double min;
double max;
double base;
int scale;
bool round;
bool reversed;
} axis_remembered_view_t;
//---------------------------------------------------------------------------------------------------//
/**
* \brief Single axis which can be added to QSAxes
*
* Axis. Its main funtion is to map values from data coordinates to world coordinates ( visible range on the axis
* is mapped to <0,1> ) - see dataToWorld() and from world coordinates to data - see worldToData().
* It can also calculate its auto range and tic mark positions, see tics(). initAxis() forces to recalculate all
* parameters. QSAxes object holds a list of QSAxis child objects. See also QSAxes::CoordinateSystem
* @author Kamil Dobkowski
*/
class QSAxis : public QSAxesChild
{
Q_OBJECT
friend class QSAxes;
Q_PROPERTY( bool visible READ visible WRITE setVisible )
Q_PROPERTY( bool oppositePosition READ oppositePosition WRITE setOppositePosition )
Q_PROPERTY( bool defaultPosition READ defaultPosition WRITE setDefaultPosition )
Q_PROPERTY( bool reversed READ reversed WRITE setReversed )
Q_PROPERTY( bool scrollable READ scrollable WRITE setScrollable )
Q_PROPERTY( QString arrow1 READ arrow1_property WRITE set_arrow1_property )
Q_PROPERTY( QString arrow2 READ arrow2_property WRITE set_arrow2_property )
Q_PROPERTY( double min READ rangeMin WRITE setRangeMin )
Q_PROPERTY( double max READ rangeMax WRITE setRangeMax )
Q_PROPERTY( int scaleType READ scaleType WRITE setScaleType )
Q_PROPERTY( double scaleBase READ scaleBase WRITE setScaleBase )
Q_PROPERTY( double majorGridStep READ majorGridStep WRITE setMajorGridStep )
Q_PROPERTY( double minorGridStep READ minorGridStep WRITE setMinorGridStep )
Q_PROPERTY( double position READ position WRITE setPosition )
Q_PROPERTY( bool ticsVisible READ ticsVisible WRITE setTicsVisible )
Q_PROPERTY( bool ticsOuter READ ticsOuter WRITE setTicsOuter )
Q_PROPERTY( QString ticsFormat READ ticsFormat WRITE setTicsFormat )
Q_PROPERTY( int ticsAngle READ ticsAngle WRITE setTicsAngle )
Q_PROPERTY( bool roundRangeToTicStep READ roundRangeToTicStep WRITE setRoundRangeToTicStep )
Q_PROPERTY( double ticLabelPos1 READ ticLabelPos1 WRITE setTicLabelPos1 )
Q_PROPERTY( double ticLabelPos2 READ ticLabelPos2 WRITE setTicLabelPos2 )
Q_PROPERTY( double titlePosition READ titlePosition WRITE setTitlePosition )
Q_PROPERTY( double titleDistance READ titleDistance WRITE setTitleDistance )
public:
/**
* Minimum logarithm value. Default is 1e-200
*/
static const double minLogValue;
/**
* Minimum value of the logarithm base. Default is 1.001
*/
static const double minScaleBase;
/**
* Minimum value shown on the axis. Default is -1e200
*/
static const double minRangeValue;
/**
* Maximum value shown on the axis. Default is 1e200
*/
static const double maxRangeValue;
/**
* Minimum rangeMax-rangeMin Default 1e-200
*/
static const double minRange;
/**
* The axis scale.
*/
enum AxisScale { LinearScale, LogScale };
/**
* Requested axis range. See min()
*/
enum AxisRange { RangeSet, RangeVisible, RangeData };
/**
* Type of the axis.
*/
enum AxisType { XAxisType, YAxisType, ZAxisType, VAxisType, UnknownAxisType };
/**
* Constructor. You have to add the axis to the parent child list immediately -
* see QSAxes::axisAdd()
*/
QSAxis( AxisType type, QSAxes *parentAxes, const char *name=0 );
/**
* Destructor
*/
virtual ~QSAxis();
/**
* Maps value from an visible axis range to <0,1>. See QSAxes::CoordinateSystem
*/
double dataToWorld( double value ) const;
/**
* Maps a value from <0,1> to visible axis range. See QSAxes::CoordinateSystem
*/
double worldToData( double value ) const;
/**
* Returns the axis type.
*/
AxisType type() const { return m_type; }
/**
* Hides/shows an axis
*/
void setVisible( bool enabled );
/**
* Places an axis on the opposite side.
*/
void setOppositePosition( bool enabled );
/**
* Places an axis at a default position ( opposite or not ).
*/
void setDefaultPosition( bool enabled );
/**
* Reverse direction of an axis.
*/
void setReversed( bool reversed );
/**
* Sets if this axis should be scrolled when scrollbars are moved in a plot view..
*/
void setScrollable( bool enabled );
/**
* Returns if the axis is visible
*/
bool visible() const { return m_visible; }
/**
* Returns whether the axis is placed on the opposite side.
*/
bool oppositePosition() const { return m_opposite; }
/**
* Returns if axis is placed at a default position.
*/
bool defaultPosition() const { return m_default; }
/**
* Turns on a reversed direction on a given axis.
*/
bool reversed() const { return m_reversed; }
/**
* Returns a scrollable state
*/
bool scrollable() const { return m_scrollable; }
/**
* Sets a beginng arrow style.
*/
void setArrow1( const QSGArrow& arrow );
/**
* Sets an ending arrow style
*/
void setArrow2( const QSGArrow& arrow );
/**
* Returns a begging arrow style
*/
QSGArrow arrow1() const { return m_arrow1; }
/**
* Sets an ending arrow style.
*/
QSGArrow arrow2() const { return m_arrow2; }
/**
* Sets the range of the given axis to '< min, max >'.
* If 'min' == 'max', auto range is turned on.
*/
void setRange( double min, double max );
/**
* Sets the range of the given axis to '< min, max >'.
* If 'min' == 'max', auto range is turned on.
*/
void setRangeMin( double min );
/**
* Sets the range of the given axis to '< min, max >'.
* If 'min' == 'max', auto range is turned on.
*/
void setRangeMax( double max );
/**
* Sets the axis scale type.
*/
void setScale( AxisScale scale, double base = 10.0 );
/**
* Sets the axis scale type.
*/
void setScaleType( int scale );
/**
* Sets the axis scale type.
*/
void setScaleBase( double base );
/**
* Sets a position of the given axis in world coordinates.
*/
void setPosition( double pos );
/**
* Returns the axis range . Notice that 'RangeSet' may be
* different from 'RangeVisible'. If you set range to
* <-10, 10> and turn on 'LogScale' the visible range will
* be <minLogValue,10>. 'RangeVisible' and
* 'RangeData' are calculated when plot is redrawn the first
* time ( parent axes object calls initAxis() ), so returned values may be invalid
* sometimes. You can call parentAxes()->initMappings() to force recalculation of ranges
* immediately.
*/
double min( AxisRange type = RangeSet ) const;
/**
* Returns the axis range . See min()
*/
double max( AxisRange type = RangeSet ) const;
/**
* Returns the axis range . See min()
*/
double rangeMin() const { return min(); }
/**
* Returns the axis range . See min()
*/
double rangeMax() const { return max(); }
/**
* Returns the current scale base.
*/
double scaleBase() const { return m_base; }
/**
* Returns the current scale type.
*/
int scaleType() const { return m_scale; }
/**
* Returns the current position.
*/
double position() const { return m_pos; }
/**
* Sets a new grid density.
*/
void setGridStep( double major = -4.0, double minor = -20.0 );
/**
* Sets a new grid step/density.
*/
void setMajorGridStep( double step );
/**
* Sets a new grid step/density.
*/
void setMinorGridStep( double step );
/**
* Returns a major grid step/density.
*/
double majorGridStep() const { return m_majd; }
/**
* Returns a minor grid step/density.
*/
double minorGridStep() const { return m_mind; }
/**
* Tics are generated each time 'initAxis' is called.
*/
const list<QSAxisTic> *tics() const { return &m_tics; }
/**
* For internal use. Only
*/
const QSAxisTic &lastTic() const { return m_last_tic; }
/**
* Sets lengths of tics.
*/
void setTicsVisible( bool visible );
/**
* Outer or inner tic marks..
*/
void setTicsOuter( bool enabled );
/**
* Sets the tics print format for the given axis.
*/
void setTicsFormat( const QString& format );
/**
* Sets the angle of the tic label.
*/
void setTicsAngle( int angle );
/**
* Adjust range for the given axis to contain an whole number of tic marks.
*/
void setRoundRangeToTicStep( bool enabled );
/**
* Returns the label format.
*/
QString ticsFormat() const { return m_tics_format; }
/**
* Returns the tic label angle
*/
int ticsAngle() const { return m_tics_angle; }
/**
* Returns a major tic's length.
*/
bool ticsVisible() const { return m_tics_visible; }
/**
* Outer or inner tic marks
*/
bool ticsOuter() const { return m_tics_outer; }
/**
* Returns the adjust setting.
*/
bool roundRangeToTicStep() const { return m_round; }
/**
* Sets the distance from the axis of the odd tic labels.
*/
void setTicLabelPos1( double pos );
/**
* Sets the distance from the axis of the even tic labels.
*/
void setTicLabelPos2( double pos );
/**
* Returns the distance from the axis of the odd tic labels.
*/
double ticLabelPos1() const { return m_tic_label_pos1; }
/**
* Returns the distance from the axis of the even tic labels.
*/
double ticLabelPos2() const { return m_tic_label_pos2; }
/**
* Sets the position of the title ( parallel to the axis )
*/
void setTitlePosition( double value );
/**
* Sets the distance of the title from the axis
*/
void setTitleDistance( double value );
/**
* Returns the position of the title ( parallel to the axis )
*/
double titlePosition() const { return m_title_position; }
/**
* Returns the distance of the title from the axis
*/
double titleDistance() const { return m_title_distance; }
/**
* Makes a text of the tic with value 'value' on axis 'axis' and
* writes it to 'buffer'.
*/
void sprintfTic( QString& buffer, double value, const QString& format = QString::null );
/**
* Remembered view contains such parameters as axis min ,axis max, axis scale, axis reversed.
* Up to four different views can be remembered ( index must be in 0-3 ).
*/
virtual void rememberCurrentView( int index );
/**
* Sets the view properties
*/
virtual void setRememberedView( int index );
void set_arrow1_property( const QString& data );
void set_arrow2_property( const QString& data );
QString arrow1_property() const;
QString arrow2_property() const;
virtual ColumnType columnType( int channel, int column ) const;
virtual void loadStateFromStream( QDataStream& stream, QSObjectFactory *factory );
virtual void saveStateToStream( QDataStream& stream, QSObjectFactory *factory );
/**
* Channels.
*/
enum Channels {
TicsChannel = 0,
LineStyles = 1,
FontStyles = 2,
FillStyles = 3
};
/**
* Line elements.
*/
enum LineElement {
AxisLine = 0,
MajorGridLine,
MinorGridLine
};
/**
* Font elements.
*/
enum FontElement {
TitleFont = 0,
TicsFont
};
/**
* Makes a text of the tic with value 'value' with
* format 'format' and writes it to 'buffer'.
*/
static void sprintfTic( QString& buffer, const QString& format, double value, double factor, double base, double exponent );
axis_remembered_view_t rememberedViews[3];
protected:
/**
* This function is called by parent axes each time plot is repainted.
* It should calculate range, coordinate mappings and tic positions.
*/
virtual void initAxis( double dataMin, double dataMax, bool isData = true );
private:
bool m_visible;
AxisType m_type; // type of the axis
bool m_opposite;
bool m_default; // default position
QSGArrow m_arrow1;
QSGArrow m_arrow2;
double m_min; // min set by user
double m_max; // max set by user
double m_vmin; // visible axis min
double m_vmax; // visible axis max
double m_dmax; // data min
double m_dmin; // data max
double m_base; // axis scale base
AxisScale m_scale; // scale type
double m_pos; // length proportional to other axes lengths
bool m_round; // adjust range to contain an integer number of tics.
bool m_reversed; // reversed axis direction
bool m_scrollable;
double m_majd; // major density
double m_mind; // minor density
QString m_tics_format; // format of tics values
bool m_tics_outer; // outer tics
bool m_tics_visible; // show tics
int m_tics_angle;
double m_wscale; // see axisToWorld
double m_wmin; // see axisToWorld
double m_tic_label_pos1;
double m_tic_label_pos2;
double m_title_position;
double m_title_distance;
list<QSAxisTic> m_tics; // QList ?!
QSAxisTic m_last_tic;
void init_axis_mappings();
void init_ranges( bool is_data );
void find_closest( double *valM, int *valE, const double MSD[], int MSD_number );
void to_float_point( double value, double *mantissa, int *exponent );
void init_tics();
void init_auto_tics_values();
double round_tic( double v );
};
#endif