Axis.hh 6.52 KB
/*
 * Axis.hh
 *
 *  Created on: 20 nov. 2013
 *      Author: guillaume
 */

#ifndef AXIS_HH_
#define AXIS_HH_

#include "Color.hh"
#include "PlotCommon.hh"
#include "Range.hh"
#include "Tick.hh"
#include "Label.hh"
#include "ConstantLine.hh"
#include "ContextFileWriter.hh"
#include <boost/shared_ptr.hpp>
#include <list>

namespace plot {

typedef void (*LabelGeneratorFunction)(PLINT, PLFLT, char *, PLINT, void *);

struct LabelGenerator {
	LabelGenerator() :
			_function(nullptr), _data(nullptr) {
	}

	virtual ~LabelGenerator() {
	}

	LabelGeneratorFunction _function;
	PLPointer _data;
};

class DefaultPlotConfiguration;

class Axis {

public:
	enum Scale {
			LOGARITHMIC, LINEAR
	};

	Axis(bool isZAxis = false);
	Axis(const Axis& axis);
	virtual ~Axis();

	virtual Range getRange() {
		if (_reverse) {
			Range lRange(_range.getMax(), _range.getMin());
			lRange._extend = _range._extend;
			return lRange;
		} else {
			return _range;
		}
	}

	void setRange(Range const& pRange) {
		_range = pRange;
	}

	void setRange(double pMin, double pMax) {
		_range.setMin(pMin);
		_range.setMax(pMax);
	}

	void setRequestedRange(double pMin, double pMax) {
		setRange(pMin, pMax);
		_requestedRange.setMin(pMin);
		_requestedRange.setMax(pMax);
	}

	void setExtended(bool pExtend) {
		_range._extend = pExtend;
	}

	bool isExtended() {
		return _range._extend;
	}

	bool isZAxis() {
		return _isZAxis;
	}

	/**
	 * @brief Write axis context
	 */
	void writeContext(ContextFileWriter& writer);

	/**
	 * @brief axis identifier (associated to parameter)
	 */
	std::string _id;

	/**
	 * @brief _color Color of axis and so color used to plot parameter(s)
	 */
	Color _color;

	/**
	 * @brief  _origin, to draw y axis on origin (must be 0)
	 */
	double _origin;

	/**
	 * @brief _position left, right for abscissa axis and top, bottom for ordinate axis.
	 */
	PlotCommon::Position _position;

	/**
	 * @brief  _reverse Tell if axis is in reversed orientation [0;100] => [100;0]
	 */
	bool _reverse;

	/**
	 * @brief _tick Define graduation for minor and major tick
	 */
	Tick _tick;

	/**
	 * @brief Is axis virtual or not
	 */
	bool _visible;

	/**
	 * @brief Axis is used for the plot or not
	 */
	bool _used;

	/**
	 * @brief Axis draw thickness
	 */
	int _thickness;

	/**
	 * @brief Axis label
	 */
	Label _legend;

	/**
	 * @brief _drawn Define if axis is already drawn (true) or not (false).
	 */
	bool _drawn;

	/**
	 * @brief _additionalObjDrawn Define if additional objects were already drawn (true) or not (false).
	 */
	bool _additionalObjDrawn;

	/**
	 * @brief _isZAxis Define if it's a ZAxis.
	 */
	bool _isZAxis;

	/**
	 * @brief Set axis scale (linear or logarithmic).
	 */
	void setScale(const std::string& value) {
		if (value == "linear") {
			_scale = Scale::LINEAR;
		} else if (value == "logarithmic") {
			_scale = Scale::LOGARITHMIC;
		}
	}

	Scale _scale;

	/**
	 * @brief Set Legend visibility flag for an axis
	 */
	void setShowLegend(bool showLegend) {
		_showLegend = showLegend;
	}

	bool  _showLegend;

	/**
	 * @brief Set TickMark visibility flag for an axis
	 */
	void setShowTickMark(bool showTickMark) {
		_showTickMark = showTickMark;
	}

	bool  _showTickMark;

	/**
	 * @brief For TU
	 */
	virtual void dump(std::ostream& out);

	/**
	 * @brief Gets string options for the current axis according to previous properties.
	 */
	virtual std::string getPlotOpt();

	/**
	 * @brief Gets automatically calculated major tick space, default is 0
	 * to let plplot do it itself
	 */
	virtual double getAutoMajorTickSpace(double /*min*/, double /*max*/) {
		return 0;
	}

	/**
	 * @brief Gets automatically calculated minor tick number between 2 major ticks, default is 0
	 * to let plplot do it itself
	 */
	virtual double getAutoMinorTickNumber(double /*min*/, double /*max*/) {
		return 0;
	}

	/**
	 * @brief Gets adjusted value according to axis specifications as log scale, min, max.
	 * by default returns originalValues_.
	 * @param originalValues_ IN values
	 * @param size_ IN number of values
	 * @param min_ min value
	 * @param max_ max value
	 */
	virtual double* getComputedValues(double* originalValues_, int /*size_*/,
			double /*min_*/, double /*max*/) {
		return originalValues_;
	}

	/**
	 * @brief Get tick mark size.
	 * @note This is used to set sufficient space for tick mark to be visible
	 */
	virtual std::pair<int, int> getTickMarkSize();
	/**
	 * gets the number of line for each tickMark. This information is used
	 * by Axis::getTickMarkSize to compute tick mark bounds.
	 * @return number of line for each tickMark.
	 */
	int getTickMarkLines() const {
		return _tickMarkLines;
	}
	/**
	 * sets the number of line for each tickMark.
	 * @param tickMarkLines_ the number of lines to take into account.
	 */
	void setTickMarkLines(int tickMarkLines_) {
		_tickMarkLines = tickMarkLines_;
	}

	double getAxisOffset() const {
		return _axisOffset;
	}

	void setAxisOffset(double axisOffset) {
		_axisOffset = axisOffset;
	}

	std::string getAxisUnits() const {
		return _axisUnits;
	}

	void setAxisUnits(std::string units) {
		_axisUnits = units;
	}

	/**
	 * @brief fixed tickMark width for the axe (-1 means tickmark width is computed)
	 */
	int _fixedTickMarkWidth;

	void setFixedTickMarkWidth(int fixedTickMarkWidth) {
		_fixedTickMarkWidth = fixedTickMarkWidth;
	}

	/**
	 * _labelFunc Function used to format label.
	 */
	boost::shared_ptr<LabelGenerator> _labelGenerator;

	/**
	 * @brief constant lines on axis
	 */
	std::list<boost::shared_ptr<ConstantLine>> _constantLines;

	/**
	 * @brief Reset for next time interval plot
	 */
	void reset()
	{
		_drawn = false;
		_additionalObjDrawn = false;
		_range = Range(_requestedRange);
		for(auto constant : _constantLines)
			constant.reset();
	}

private:
	/**
	 * @brief _range Limit of axis
	 */
	Range _range;

	/*
	 * @brief Keep the range defined in the request
	 */
	Range _requestedRange;

	/**
	 * @brief number of line for tickMark
	 */
	int _tickMarkLines;
	/**
	 * @brief axe offset used for multi-axes
	 */
	double _axisOffset;

	/*
	 * @brief axe units
	 */
	std::string _axisUnits;

};

std::ostream& operator <<(std::ostream& out, Axis& axis);

/**
 * @brief Gets world coordinate space between 2 major ticks, returns 0 to let
 * plplot do this it self.
 */
double getMajorTickSpace(Axis* axis, double min, double max);

/**
 * @brief Gets number of minor tick between 2 major ones.
 */
int getMinorTickNumber(Axis* xAxis, double min, double max,
		double majorTickSpace);

/**
 * @brief Calculates major tick number on given axis.
 */
double getMajorTickNumber(Axis* axis, double min, double max);

} /* namespace plot */
#endif /* AXIS_HH_ */