/* * PanelPlotOutput.hh * * Created on: 29 oct. 2013 * Author: CS */ #ifndef PANELPLOTOUTPUT_HH_ #define PANELPLOTOUTPUT_HH_ #include "ParamOutput.hh" #include "Panel.hh" #include "ParameterAxes.hh" #include #include #include "ParameterData.hh" #include #include #include "PlotLogger.hh" #include "PanelPlotOutputException.hh" #include "Layout.hh" #include "ContextFileWriter.hh" #include namespace plot { // 0 => xmin // 1 => xmax // 2 => ymin // 3 => ymax typedef std::tuple PlWindow; // 0 => x major tick space // 1 => x minor tick number // 2 => y major tick space // 3 => y minor tick number typedef std::tuple TickConf; /** * Margin. */ struct Margin { double _left; double _right; double _top; double _bottom; }; class PanelPlotOutput { public: static const float DEFAULT_TICK_LENGTH_FACTOR; /** * Width character proportion is approximatively 0.83 times smaller than height. */ static const float CHAR_RATIO; /** * This two next attribute tell from which tick length plplot is insufficient to calculate space between tickmarks and ticks. * Space between the two is static and can't be modified by user request. * So when limit is reached we must bypass problem by setting two different viewport to let sufficient space between tickmarks and ticks. */ static const float VERTICAL_TICK_LENGTH_LIMIT; static const float HORIZONTAL_TICK_LENGTH_LIMIT; static const float YAXISMARGIN; PanelPlotOutput(AMDA::Parameters::ParameterManager& manager, boost::shared_ptr panel, bool isStandalone = true); virtual ~PanelPlotOutput(); /** * type name. This name is used to identify nodes in xml config * and xml request. * @return */ virtual const std::string typeName() = 0; /** * type name. This name is used to identify nodes in xml config * and xml request. * @return */ virtual const std::string subTypeName() = 0; /** * @brief Compute the initial plot area for the panel */ virtual void preparePlotArea (double startTime, double stopTime, int intervalIndex); /** * @brief Retrieve plot area bounds for the panel */ virtual void getPlotAreaBounds (Bounds &plotAreaBounds); /** * @brief Force the plot area horizontal position and width */ virtual void forcePlotAreaPosAndWidth(double plotAreaX, double plotAreaWidth); /** * @brief Retrieve left axis tickMark width */ virtual int getLeftAxisTickMarkWidth (void); /** * @brief Force left axis tickmark width for the panel */ virtual void forceLeftAxisTickMarkWidth(int leftAxisTickMarkWidth); /** * @brief draw the plot for the current time interval */ virtual bool draw(double startTime, double stopTime, int intervalIndex, bool isFirstInterval, bool isLastInterval); /** * @brief Write plot context */ virtual void writeContext(ContextFileWriter &writer, AMDA::Parameters::TimeIntervalList::iterator currentTimeInterval); /* * @brief Set a pointer to the time intervals list */ void setTimeIntervalListPtr(AMDA::Parameters::TimeIntervalList *timeIntervalListPtr); /** * Sets PLplot stream to draw panel and plot */ virtual void setPlStream(std::shared_ptr& pls); /** * Adds a parameter */ virtual void addParam(const std::string& name) { ParameterAxes newParameter(name); _parameterAxesList.push_back(newParameter); } virtual ParameterAxes& getParameter(const std::string& name) { for (ParameterAxes& param : _parameterAxesList) { if (param._originalParamId == name) { return param; } } ParameterAxes newParameter(name); _parameterAxesList.push_back(newParameter); return _parameterAxesList.back(); } /* * Create a sampled parameter from an original parameter and a sampling value */ AMDA::Parameters::ParameterSPtr createSampledParameter(AMDA::Parameters::ParameterSPtr& originalParam, float samplingValue, int gap = -1); /* * Create a sampled parameter from an original parameter and a reference parameter for time definition */ AMDA::Parameters::ParameterSPtr createSampledParameterUnderReferenceParameter(AMDA::Parameters::ParameterSPtr& originalParam, AMDA::Parameters::ParameterSPtr& refParam); /** * Create parameters needed for this plot * By default, the creation method create parameters for a time serie. * Override it for other plot type */ virtual void createParameters(std::list& usedParametersId_); /** * Get related ParameterAxes for a given color serie id */ ParameterAxes* getParameterAxesByColorSerieId(int colorSerieId); /** * Get related ParameterAxes for a given x serie id */ ParameterAxes* getParameterAxesByXSerieId(int xSerieId); /** * Gets sampling value from resolution (point-per-plot) according to * the plot time interval and the base parameter sampling value. */ virtual double getCorrectedSamplingValue(int maxResolution, double samplingValue); /** * @brief Get the list of indexes used for a parameter */ virtual std::vector getParamUsedIndexes(std::string paramId, int dim1Size, int dim2Size = -1); const Margin getMargin(){ Bounds panelBounds(_panel->getBoundsInPlPage()); Margin m; m._left = _plotAreaBounds._x - panelBounds._x; m._right = (panelBounds._x + panelBounds._width) - (_plotAreaBounds._x + _plotAreaBounds._width); m._top = (panelBounds._y + panelBounds._height) - (_plotAreaBounds._y + _plotAreaBounds._height); m._bottom = _plotAreaBounds._y - panelBounds._y; return m; } /** * @brief reset plot */ virtual void resetPlot() { if (_panel != nullptr) _panel->resetPlot(); _automaticSerieColorCursor = 0; _nbSeriesByYAxisMap.clear(); _pls.reset(); } /* * @brief Set pointer to params values */ void setParameterValues(std::map *pParameterValues); /* * @brief Get computed values (in relation with the y axis definition) for a y serie, an index of the serie and a time interval * Do not forget to delete (*computedValues) !! * Do not delete (*timeValues), the buffer is not copied !! */ bool getComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, AMDA::Common::ParameterIndexComponent index, double** computedValues, double** timeValues, int& nbValues); /* * @brief Get computed values (in relation with the color axis definition) for a color serie and a time interval * Do not forget to delete computedValues !! * Don't delete timeValues !! */ bool getColoredComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, double** computedValues, double** timeValues, int& nbValues); /* * @brief Get computed values (in relation with the y axis definition) for a y serie and a time interval * Do not forget to delete computedValues !! * Don't delete timeValues !! */ bool getErrorComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, AMDA::Common::ParameterIndexComponent &pParamIndex, double** minComputedValues, double** minTimeValues, int& nbMinValues, double** maxComputedValues, double** maxTimeValues, int& nbMaxValues); /** *@brief Defines the layout constraint to be used for the panel when used within a layout */ virtual PanelConstraint getLayoutConstraint (void) { return PanelConstraint::MaxWidth; } /** * @brief Get nb series to draw by y axis */ std::map& getNbSeriesByYAxis(); /* * @brief Return the color to draw the line of a serie */ Color getSerieLineColor(SeriesProperties &rSeriesProperties, bool moreThanOneSerieForAxis); /** * @brief Plot container */ boost::shared_ptr _panel; /** * @brief Parameters and series info */ ParameterAxesList _parameterAxesList; /* * @brief Type used to define a matrix grid */ struct GridPart { double x[2]; double y[2]; double value; double isColorIndex; }; typedef std::vector MatrixGrid; // datastore for sauvaud plot struct SauvaudPart { double x[2]; double y[2]; std::vector value; double isColorIndex; }; typedef std::vector SauvaudGrid; /* * @brief Draw a matrix */ void drawMatrix(MatrixGrid& matrixGrid, double minDataVal, double maxDataVal, Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); void draw2DMatrix(SauvaudGrid& sauvaudGrid, double minDataVal, double maxDataVal, Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); /** * @brief Reset cursor used to attribute automatically a color to a serie */ void resetAutomaticSerieColorCursor() { _automaticSerieColorCursor = 0; } /** * Draw a rectangle */ void drawRectangle(double xmin, double xmax, double ymin, double ymax, Color& pColor, double alpha = 1.); bool isStandalone() { return _isStandalone; } AMDA::Parameters::ParameterManager& _parameterManager; std::map *_pParameterValues; bool isHeightFixed(){ return _isHeightFixed; } void setHeightFixed(bool isHeightFixed){ _isHeightFixed = isHeightFixed; } protected: AMDA::Parameters::TimeIntervalList* _timeIntervalListPtr; /** * @brief Compute plot area. * @note If ratio need to be kept, ratio will be kept between width and height. * @param bounds_ plot area bounds. It is updated by this method. */ virtual void calculatePlotArea(const Bounds& panelBounds_, Bounds& bounds_); /** *@brief computes Panel Plot XY ratio */ void computePanelPlotXYRatio(void); /** * @brief Get colored value associated to a data value. Return false if the value is filtered. */ bool getColoredValue(double value, double filterMin, double filterMax, bool useLog0AsMin, PLFLT &col); /** *@brief Draw fill area between parameter and constant or between parameters */ virtual void drawFills(double startDate, double stopDate); /** * Draw list of symbols */ void drawSymbols(SymbolType pType, int pSize, double pFactor, Color pColor, int pNbData, double* pXData, double* pYData, double* pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); /** * Draw list of lines */ void drawLines(LineType pType, LineStyle pStyle, int pWidth, Color& pColor, int pNbData, double* pXData, double* pYData, double* pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); /** * Draw errors segments */ void drawYErrors (LineType pType, LineStyle pStyle, int pWidth, Color& pColor, int pNbData, double* pXData, double* pYMinData, double* pYMaxData); /** *@brief Draw the serie of a parameter component on plot. */ virtual void drawSeries(double startDate, double stopDate, int intervalIndex, std::string pParamId, SeriesProperties& pSeries, AMDA::Common::ParameterIndexComponent pParamIndex, ParameterAxes& param, bool moreThanOneSerieForAxis); /** *@brief Draw the spectro of a parameter on plot. */ virtual void drawSpectro(double startDate, double stopDate, std::string pParamId, SpectroProperties& pSpectro); /** *@brief Draw sauvaud plot of a parameter on plot. */ virtual void drawSauvaud(double startDate, double stopDate, std::string pParamId, SauvaudProperties& pSauvaud, int subIndex, int subsNumber, std::string opositeLegend); virtual void drawIntervals(double startDate, double stopDate, std::string pParamId, IntervalsProperties& pIntervals); /* * @brief Draw interval */ virtual void drawSerieInterval(SeriesProperties& pSeries, double* xValues, double* yValues, double* timeValues, int nbValues, int intervalIndex); /** * Draw an horizontal axis. * Subclasses may override it to take into account decorator attached to that axis (for instance). * @param pXAxis axis to draw. * @param pPlWindow real word ranges. * @param pPlotAreaSize plot ranges. * @param pTickConf ticks configuration. */ virtual void drawXAxis(boost::shared_ptr pXAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); /** * Draw a vertical axis. * Subclasses may override it to take into account decorator attached to that axis (for instance). * @param pXAxis axis to draw. * @param pPlWindow real word ranges. * @param pPlotAreaSize plot ranges. * @param pTickConf ticks configuration. */ virtual void drawYAxis(boost::shared_ptr pXAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); /** * @brief Draw legend for each axis. * @param pAxis axis to draw. * @param pPlWindow real word ranges. * @param pPlotAreaSize plot ranges. */ virtual void drawLegends(boost::shared_ptr& pAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize); /** * @brief Add space if there is an exponent or indice * * @param legend legend to check * @param lPosition position to modify */ void addSpaceForExInd(std::string &legend, double &lPosition); /** * @brief Draw parameters legend. */ virtual void drawParamsLegend(void); /** * @brief Draw text legends. */ virtual void drawTextLegends(void); /** * Convert an X axis string value to a double X value * Subclasses may override it to take into account specific value meaning. * @param value string value to convert. */ virtual double convertXAxisValue(const std::string &value); /** * Convert an Y axis string value to a double Y value * Subclasses may override it to take into account specific value meaning. * @param value string value to convert. */ virtual double convertYAxisValue(const std::string &value); /** * Draw X constant lines linked to an axis. * Subclasses may override it to take into account decorator attached (for instance). * @param pXAxis axis to draw. * @param pPlWindow real word ranges. */ virtual void drawXConstantLines(boost::shared_ptr pAxis, PlWindow& pPlWindow); /** * Draw X constant lines linked to an axis. * Subclasses may override it to take into account decorator attached (for instance). * @param pXAxis axis to draw. * @param pPlWindow real word ranges. */ virtual void drawYConstantLines(boost::shared_ptr pAxis, PlWindow& pPlWindow); /** * Draw textPlots for a panel. * Subclasses may override it for specific drawings. * @param pPlWindow real word ranges. */ virtual void drawTextPlots(boost::shared_ptr pXAxis, boost::shared_ptr pYAxis, PlWindow& pPlWindow, const TextPlots &textPlots); /** * Draw curvePlot for a panel. * Subclasses may override it for specific drawings. * @param curvePlot curve properties. */ virtual void drawCurvePlot(CurvePlot &curvePlot); /** * @brief Identify if other side of the plot area need to be drawn or not. * @note A plot area side need to be drawn when there is no axis associated to it. */ virtual std::string drawOppositeSide(boost::shared_ptr pAxis); /** *@brief Draw additional objects on plot. */ virtual void drawAdditionalObjects (); /** * Draw a z axis */ virtual void drawZAxis(boost::shared_ptr pZAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); /** * Get X Axis range for a serie */ Range getXAxisRange (SeriesProperties& pSeries, boost::shared_ptr pAxis); /** * Get Y Axis range for a serie */ Range getYAxisRange (SeriesProperties& pSeries, boost::shared_ptr pAxis); /** * Get Z Axis range for a serie */ Range getZAxisRange (SeriesProperties& pSeries, boost::shared_ptr pAxis); /* * @brief Return the color to draw the symbols of a serie */ Color getSerieSymbolColor(SeriesProperties &rSeriesProperties, Color &pLineColor); /** * @brief Configure params legend for a plot. */ virtual void configureParamsLegend(double startTime, double stopTime, int intervalIndex); /** * @brief Add a serie to the param legend */ void addSerieToParamsLegend(SeriesProperties& lSeriesProperties, AMDA::Common::ParameterIndexComponent& index, std::string originalParamId, Color& lineColor, Color& symbolColor, double startTime, double stopTime, int intervalIndex); /* * @brief Return the associated params legend to a serie */ virtual std::string getSerieParamsLegendString(SeriesProperties &rSeriesProperties, AMDA::Common::ParameterIndexComponent& index, std::string originalParamId); /** * @brief plplot stream */ std::shared_ptr _pls; /* * Dumps properties for test. */ virtual void dump(std::ostream& out_); /** * @brief Fill the background of the plot area * * @param pls */ void fillBackground(std::shared_ptr &pls); private: void drawAxis(boost::shared_ptr pAxis, TickConf& pTickConf, std::string pXAxisOptions, std::string pYAxisOptions); double estimateZAxisWidth(boost::shared_ptr pZAxis); /** * @brief _plotAreaSideSet Store which side of plot area is linked to an axis. */ std::map _plotAreaSideSet; /** * @brief nb series to draw by y axis */ std::map _nbSeriesByYAxisMap; /** * @brief plot array on which to draw data. */ Bounds _plotAreaBounds; /* * @brief Panel XY ratio used for angular conversion */ double _panelPlotXYRatio; /* * @brief Panel left axis tickmark width */ double _leftAxisTickMarkWidth; /* * @brief cursor use to set a default color to a serie */ int _automaticSerieColorCursor; /* * */ bool _isStandalone; bool _isHeightFixed; void reserveSpaceForAxis (boost::shared_ptr& pAxis, double titleHeight, std::map nbAxesBySide, double& topSpace, double& bottomSpace, double& leftSpace, double& rightSpace); void reserveSpaceForTextLegend (boost::shared_ptr& pTextLegendProp, double titleHeight, double& topSpace, double& bottomSpace, double& leftSpace, double& rightSpace); }; /** * Calculate room taken by tick. */ double getHorizontalTickLength(Axis* pAxis, double charHeight); /** * Calculate room taken by tick. */ double getVerticalTickLength(Axis* pAxis, double charHeight); } /* namespace plot */ #endif /* PANELPLOTOUTPUT_HH_ */