diff options
author | Marco Cecchetti <marco.cecchetti@collabora.com> | 2015-02-09 13:36:49 +0100 |
---|---|---|
committer | Marco Cecchetti <marco.cecchetti@collabora.com> | 2015-02-09 13:42:19 +0100 |
commit | 1a595052b205f8505776699f61c1a0b89bc42380 (patch) | |
tree | 524a7942fc4002aa6e93ea21fb2705e484912a66 /chart2 | |
parent | ab50e4f8e5b34b15e4f6a338fb7326035b7d3180 (diff) |
Added doc notes for classes and methods used for pie charts.
Diffstat (limited to 'chart2')
-rw-r--r-- | chart2/source/view/charttypes/PieChart.cxx | 58 | ||||
-rw-r--r-- | chart2/source/view/charttypes/PieChart.hxx | 12 | ||||
-rw-r--r-- | chart2/source/view/charttypes/VSeriesPlotter.cxx | 21 | ||||
-rw-r--r-- | chart2/source/view/inc/PlotterBase.hxx | 4 | ||||
-rw-r--r-- | chart2/source/view/inc/PlottingPositionHelper.hxx | 35 | ||||
-rw-r--r-- | chart2/source/view/inc/PolarLabelPositionHelper.hxx | 11 | ||||
-rw-r--r-- | chart2/source/view/inc/VSeriesPlotter.hxx | 35 | ||||
-rw-r--r-- | chart2/source/view/main/PlottingPositionHelper.cxx | 73 |
8 files changed, 245 insertions, 4 deletions
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 3edf2af46d62..5c29b3606c77 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -41,13 +41,38 @@ namespace chart { struct PieChart::ShapeParam { + // the start angle of the slice double mfUnitCircleStartAngleDegree; + + // the angle width of the slice double mfUnitCircleWidthAngleDegree; + + // the normalized outer radius of the ring the slice belongs to. double mfUnitCircleOuterRadius; + + // the normalized inner radius of the ring the slice belongs to double mfUnitCircleInnerRadius; + + // relative distance offset of a slice from the pie center; + // this parameter is used for instance when the user performs manual + // dragging of a slice (the drag operation is possible only for slices that + // belong to the outer ring and only along the ray bisecting the slice); + // the value for the given entry in the data series is obtained by the + // `Offset` property attached to each entry; note that the value + // provided by the `Offset` property is used both as a logical value in + // `PiePositionHelper::getInnerAndOuterRadius` and as a percentage value in + // the `PieChart::createDataPoint` and `PieChart::createTextLabelShape` + // methods; since the logical height of a ring is always 1, this duality + // does not cause any incorrect behavior. double mfExplodePercentage; - double mfLogicYSum; // sum of all Y values in a single series. + + // sum of all Y values in a single series. + double mfLogicYSum; + + // for 3D pie chart: label z coordinate double mfLogicZ; + + // for 3D pie chart: height double mfDepth; ShapeParam() : @@ -86,6 +111,18 @@ PiePositionHelper::~PiePositionHelper() { } +/* Compute the outer and the inner radius for the current ring (not for the + * whole donut!), in general it is: + * inner_radius = (ring_index + 1) - 0.5 + max_offset, + * outer_radius = (ring_index + 1) + 0.5 + max_offset. + * When orientation for the radius axis is reversed these values are swapped. + * (Indeed the the orientation for the radius axis is always reversed! + * See `PieChartTypeTemplate::adaptScales`.) + * The maximum relative offset (see notes for P`ieChart::getMaxOffset`) is + * added to both the inner and the outer radius. + * It returns true if the ring is visible (that is not out of the radius + * axis scale range). + */ bool PiePositionHelper::getInnerAndOuterRadius( double fCategoryX , double& fLogicInnerRadius, double& fLogicOuterRadius , bool bUseRings, double fMaxOffset ) const @@ -230,6 +267,10 @@ void PieChart::createTextLabelShape( // There is no text label for this data point. Nothing to do. return; + //by using the `mfExplodePercentage` parameter a normalized offset is added + // to both normalized radii. (See notes for + // `PolarPlottingPositionHelper::transformToRadius`, especially example 3, + // and related comments). if (!rtl::math::approxEqual(rParam.mfExplodePercentage, 0.0)) { double fExplodeOffset = (rParam.mfUnitCircleOuterRadius-rParam.mfUnitCircleInnerRadius)*rParam.mfExplodePercentage; @@ -237,6 +278,8 @@ void PieChart::createTextLabelShape( rParam.mfUnitCircleOuterRadius += fExplodeOffset; } + //get the required label placement type. Available placements are + //`AVOID_OVERLAP`, `CENTER`, `OUTSIDE` and `INSIDE`. sal_Int32 nLabelPlacement = rSeries.getLabelPlacement( nPointIndex, m_xChartTypeModel, m_nDimension, m_pPosHelper->isSwapXAndY()); @@ -249,6 +292,12 @@ void PieChart::createTextLabelShape( // does. nLabelPlacement = ::com::sun::star::chart::DataLabelPlacement::CENTER; + //for `OUTSIDE` (`INSIDE`) label placements an offset of 150 (-150), in the + //radius direction, is added to the final screen position of the label + //anchor point. This is required in order to ensure that the label is + //completely outside (inside) the related slice. Indeed this value should + //depend on the font height. + Pay attention: 150 is not a big offset, in fact the screen position coordinates for label anchor points are in the 10000-20000 range, hence these are coordinates of a virtual screen and 150 is a small value. LabelAlignment eAlignment(LABEL_ALIGN_CENTER); sal_Int32 nScreenValueOffsetInRadiusDirection = 0 ; if( nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE ) @@ -256,12 +305,16 @@ void PieChart::createTextLabelShape( else if( nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::INSIDE ) nScreenValueOffsetInRadiusDirection = (3!=m_nDimension) ? -150 : 0;//todo maybe calculate this font height dependent + //the scene position of the label anchor point is calculated (see notes for + //`PolarLabelPositionHelper::getLabelScreenPositionAndAlignmentForUnitCircleValues`), + //and immediately transformed into the screen position. PolarLabelPositionHelper aPolarPosHelper(m_pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory); awt::Point aScreenPosition2D( aPolarPosHelper.getLabelScreenPositionAndAlignmentForUnitCircleValues(eAlignment, nLabelPlacement , rParam.mfUnitCircleStartAngleDegree, rParam.mfUnitCircleWidthAngleDegree , rParam.mfUnitCircleInnerRadius, rParam.mfUnitCircleOuterRadius, rParam.mfLogicZ+0.5, 0 )); + //the screen position of the pie/donut center is calculated. PieLabelInfo aPieLabelInfo; aPieLabelInfo.aFirstPosition = basegfx::B2IVector( aScreenPosition2D.X, aScreenPosition2D.Y ); awt::Point aOrigin( aPolarPosHelper.transformSceneToScreenPosition( m_pPosHelper->transformUnitCircleToScene( 0.0, 0.0, rParam.mfLogicZ+1.0 ) ) ); @@ -276,10 +329,13 @@ void PieChart::createTextLabelShape( aScreenPosition2D.Y += aDirection.getY(); } + //the text shape for the label is created double nVal = rSeries.getYValue(nPointIndex); aPieLabelInfo.xTextShape = createDataLabel( xTextTarget, rSeries, nPointIndex, nVal, rParam.mfLogicYSum, aScreenPosition2D, eAlignment); + //a new `PieLabelInfo` instance is initialized with all the info related to + //the current label in order to simplify later label position rearrangement. uno::Reference< container::XChild > xChild( aPieLabelInfo.xTextShape, uno::UNO_QUERY ); if( xChild.is() ) aPieLabelInfo.xLabelGroupShape = uno::Reference<drawing::XShape>( xChild->getParent(), uno::UNO_QUERY ); diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx index 2b88b1a0ca56..2929f963aa58 100644 --- a/chart2/source/view/charttypes/PieChart.hxx +++ b/chart2/source/view/charttypes/PieChart.hxx @@ -75,6 +75,18 @@ private: //methods const css::uno::Reference<css::drawing::XShapes>& xTextTarget, VDataSeries& rSeries, sal_Int32 nPointIndex, ShapeParam& rParam ); + /** This method sets `m_fMaxOffset` to the maximum `Offset` property and + * returns it. There is a `Offset` property for each entry in a data + * series, moreover there exists a shared `Offset` property attached to + * the whole data series. The `Offset` property represents the + * relative distance offset of a slice from the pie center. + * The shared property is used for exploded pie chart, while the property + * attached to single data series entries is used for manual dragging of + * a slice. + * `m_fMaxOffset` is used by `PiePositionHelper::getInnerAndOuterRadius`. + * Note that only the `Offset` properties of the first (x slot) data series + * and its entries are utilized for computing the maximum offset. + */ double getMaxOffset(); bool detectLabelOverlapsAndMove(const ::com::sun::star::awt::Size& rPageSize);//returns true when there might be more to do void resetLabelPositionsToPreviousState(); diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index 8acf4273e1d8..5fdd37bab82d 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -449,6 +449,11 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re //prepare legend symbol + // get the font size for the label through the "CharHeight" property + // attached to the passed data series entry. + // (By tracing font height values it results that for pie chart the + // font size is not the same for all labels, but here no font size + // modification occurs). float fViewFontSize( 10.0 ); { uno::Reference< beans::XPropertySet > xProps( rDataSeries.getPropertiesOfPoint( nPointIndex ) ); @@ -457,6 +462,9 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re // pt -> 1/100th mm fViewFontSize *= (2540.0f / 72.0f); } + + // the font height is used for computing the size of an optional legend + // symbol to be prepended to the text label. Reference< drawing::XShape > xSymbol; if(pLabel->ShowLegendSymbol) { @@ -485,6 +493,8 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if(xPointProps.is()) { xPointProps->getPropertyValue( "LabelSeparator" ) >>= aSeparator; + // Extract the optional text rotation through the + // "TextRotation" property attached to the passed data point. xPointProps->getPropertyValue( "TextRotation" ) >>= fRotationDegrees; } } @@ -492,6 +502,11 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re { ASSERT_EXCEPTION( e ); } + + // check if data series entry percent value and absolute value have to + // be appended to the text label, and what should be the separator + // character (comma, space, new line). In case it is a new line we get + // a multi-line label. bool bMultiLineLabel = aSeparator == "\n"; sal_Int32 nLineCountForSymbolsize = 0; { @@ -543,6 +558,8 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re tAnySequence* pPropValues; if( !rDataSeries.getTextLabelMultiPropertyLists( nPointIndex, pPropNames, pPropValues ) ) return xTextShape; + + // set text alignment for the text shape to be created. LabelPositionHelper::changeTextAdjustment( *pPropValues, *pPropNames, eAlignment ); //create text shape @@ -553,6 +570,8 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re if( !xTextShape.is() ) return xTextShape; + // in case text is rotated, the transformation property of the text + // shape is modified. const awt::Point aUnrotatedTextPos( xTextShape->getPosition() ); if( fRotationDegrees != 0.0 ) { @@ -563,6 +582,8 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re LabelPositionHelper::correctPositionForRotation( xTextShape, eAlignment, fRotationDegrees, true /*bRotateAroundCenter*/ ); } + // in case legend symbol has to be displayed, text shape position is + // slightly changed. if( xSymbol.is() ) { const awt::Point aOldTextPos( xTextShape->getPosition() ); diff --git a/chart2/source/view/inc/PlotterBase.hxx b/chart2/source/view/inc/PlotterBase.hxx index 887f8ca96ae4..b7515c49860c 100644 --- a/chart2/source/view/inc/PlotterBase.hxx +++ b/chart2/source/view/inc/PlotterBase.hxx @@ -39,6 +39,10 @@ namespace chart class AbstractShapeFactory; class PlottingPositionHelper; +/** This class provides methods for setting axis scales and for performing + * scene to screen transformations. It is used as the base class for all + * plotter classes. + */ class PlotterBase { public: diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx b/chart2/source/view/inc/PlottingPositionHelper.hxx index e913cdd0ed51..969d886a3483 100644 --- a/chart2/source/view/inc/PlottingPositionHelper.hxx +++ b/chart2/source/view/inc/PlottingPositionHelper.hxx @@ -160,10 +160,25 @@ public: virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTransformation > getTransformationScaledLogicToScene() const SAL_OVERRIDE; - //the resulting values should be used for input to the transformation - //received with 'getTransformationScaledLogicToScene' + //the resulting values provided by the following 3 methods should be used + //for input to the transformation received with + //'getTransformationScaledLogicToScene' + + /** Given a value in the radius axis scale range, it returns the normalized + * value. + */ double transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling=true ) const; + + /** Given a value in the angle axis scale range (e.g. [0,1] for pie charts) + * this method returns the related angle in degree. + */ double transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling=true ) const; + + /** Given 2 values in the angle axis scale range (e.g. [0,1] for pie charts) + * this method returns the angle between the 2 values keeping into account + * the correct axis orientation; (for instance, this method is used for + * computing the angle width of a pie slice). + */ double getWidthAngleDegree( double& fStartLogicValueOnAngleAxis, double& fEndLogicValueOnAngleAxis ) const; virtual ::com::sun::star::drawing::Position3D @@ -172,6 +187,11 @@ public: transformScaledLogicToScene( double fX, double fY, double fZ, bool bClip ) const SAL_OVERRIDE; ::com::sun::star::drawing::Position3D transformAngleRadiusToScene( double fLogicValueOnAngleAxis, double fLogicValueOnRadiusAxis, double fLogicZ, bool bDoScaling=true ) const; + + /** It returns the scene coordinates of the passed point: this point is + * described through a normalized cylindrical coordinate system. + * (For a pie chart the origin of the coordinate system is the pie center). + */ ::com::sun::star::drawing::Position3D transformUnitCircleToScene( double fUnitAngleDegree, double fUnitRadius, double fLogicZ, bool bDoScaling=true ) const; @@ -182,9 +202,18 @@ public: inline bool isMathematicalOrientationAngle() const; inline bool isMathematicalOrientationRadius() const; public: + //m_bSwapXAndY (inherited): by default the X axis (scale[0]) represents + //the angle axis and the Y axis (scale[1]) represents the radius axis; + //when this parameter is true, the opposite happens (this is the case for + //pie charts). + //Offset for radius axis in absolute logic scaled values (1.0 == 1 category) + //For a donut, it represents the non-normalized inner radius (see notes for + //transformToRadius) double m_fRadiusOffset; - //Offset for angle axis in real degree + //Offset for angle axis in real degree. + //For a pie it represents the angle offset at which the first slice have to + //start; double m_fAngleDegreeOffset; private: diff --git a/chart2/source/view/inc/PolarLabelPositionHelper.hxx b/chart2/source/view/inc/PolarLabelPositionHelper.hxx index 5b9b1d4487e8..cb7ae63ad887 100644 --- a/chart2/source/view/inc/PolarLabelPositionHelper.hxx +++ b/chart2/source/view/inc/PolarLabelPositionHelper.hxx @@ -48,6 +48,17 @@ public: , double fLogicZ , sal_Int32 nScreenValueOffsetInRadiusDirection=0 ) const; + /** Calculate the anchor point position for a text label. + * When the requested label placement is of `INSIDE` or `OUTSIDE` type the + * returned anchor point for the text label is the middle point of the + * outer arc for the given slice; when the requested label placement is of + * `CENTER` type the returned anchor point for the text label is the + * middle point of the line segment bisecting the slice. + * The text alignment is always centered when the requested label + * placement is of `CENTER` type else it is dependent on the value of the + * angle defined by the horizontal axis and the ray bisecting the slice. + * + */ ::com::sun::star::awt::Point getLabelScreenPositionAndAlignmentForUnitCircleValues( LabelAlignment& rAlignment, sal_Int32 nLabelPlacement /*see ::com::sun::star::chart::DataLabelPlacement*/ , double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx index 16218f7a4a9d..03bbc8083eb2 100644 --- a/chart2/source/view/inc/VSeriesPlotter.hxx +++ b/chart2/source/view/inc/VSeriesPlotter.hxx @@ -179,6 +179,9 @@ public: void getMinimumAndMaximiumX( double& rfMinimum, double& rfMaximum ) const; void getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, double& rfMaxY, double fMinX, double fMaxX, sal_Int32 nAxisIndex ) const; + + // Methods for handling legends and legend entries. + virtual std::vector< ViewLegendEntry > createLegendEntries( const ::com::sun::star::awt::Size& rEntryKeyAspectRatio, ::com::sun::star::chart::ChartLegendExpansion eLegendExpansion, @@ -225,6 +228,7 @@ public: ::std::vector< VDataSeries* > getAllSeries(); + // This method creates a series plotter of the requested type; e.g. : return new PieChart .... static VSeriesPlotter* createSeriesPlotter( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartTypeModel , sal_Int32 nDimensionCount @@ -232,6 +236,8 @@ public: sal_Int32 getPointCount() const; + // Methods for number formats and color schemes + void setNumberFormatsSupplier( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xNumFmtSupplier ); void setAxesNumberFormats( const AxesNumberFormats& rAxesNumberFormats ) { m_aAxesNumberFormats = rAxesNumberFormats; }; @@ -270,6 +276,8 @@ protected: , sal_Int32 nDimensionCount , bool bCategoryXAxis=true ); + // Methods for group shapes. + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > getSeriesGroupShape( VDataSeries* pDataSeries , const::com::sun::star:: uno::Reference< @@ -287,6 +295,8 @@ protected: , const::com::sun::star:: uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget ); + /// This method creates a 2D group shape for containing all text shapes + /// needed for this series; the group is added to the text target; ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > getLabelsGroupShape( VDataSeries& rDataSeries , const::com::sun::star:: uno::Reference< @@ -297,6 +307,29 @@ protected: , const::com::sun::star:: uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget, bool bYError ); + /** This method creates a text shape for a label related to a data point + * and append it to the root text shape group (xTarget). + * + * @param xTarget + * the main root text shape group. + * @param rDataSeries + * the data series, the data point belongs to. + * @param nPointIndex + * the index of the data point the label is related to. + * @param fValue + * the value of the data point. + * @param fSumValue + * the sum of all data point values in the data series. + * @param rScreenPosition2D + * the anchor point position for the label. + * @param eAlignment + * the required alignment of the label. + * @param offset + * an optional offset depending on the label alignment. + * + * @return + * a reference to the created text shape. + */ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createDataLabel( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget @@ -308,6 +341,8 @@ protected: , LabelAlignment eAlignment=LABEL_ALIGN_CENTER , sal_Int32 nOffset=0 ); + /// This method returns a text string representation of the passed numeric + /// value by exploiting a NumberFormatterWrapper object. OUString getLabelTextForValue( VDataSeries& rDataSeries , sal_Int32 nPointIndex , double fValue diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx index d72b1dd88021..957572674e74 100644 --- a/chart2/source/view/main/PlottingPositionHelper.cxx +++ b/chart2/source/view/main/PlottingPositionHelper.cxx @@ -452,6 +452,10 @@ double PolarPlottingPositionHelper::getWidthAngleDegree( double& fStartLogicValu return fWidthAngleDegree; } +//This method does a lot of computation for understanding which scale to +//utilize and if reverse orientation should be used. Indeed, for a pie or donut, +//the final result is as simple as multiplying by 360 and adding +//`m_fAngleDegreeOffset`. double PolarPlottingPositionHelper::transformToAngleDegree( double fLogicValueOnAngleAxis, bool bDoScaling ) const { double fRet=0.0; @@ -503,6 +507,75 @@ double PolarPlottingPositionHelper::transformToAngleDegree( double fLogicValueOn return fRet; } +/* + * Given a value in the radius axis scale range, it returns, in the simplest + * case (that is when `m_fRadiusOffset` is zero), the normalized value; when + * `m_fRadiusOffset` is not zero (e.g. as in the case of a donut), the interval + * used for normalization is extended by `m_fRadiusOffset`: if the axis + * orientation is not reversed the new interval becomes + * [scale.Minimum - m_fRadiusOffset, scale.Maximum] else it becomes + * [scale.Minimum, scale.Maximum + m_fRadiusOffset]. + * Pay attention here! For the latter case, since the axis orientation is + * reversed, the normalization is reversed too. Indeed, we have + * `transformToRadius(scale.Maximum + m_fRadiusOffset) = 0` and + * `transformToRadius(scale.Minimum) = 1`. + * + * For a pie chart the radius axis scale range is initialized by the + * `getMinimum` and `getMaximum` methods of the `PieChart` object (see notes + * for `VCoordinateSystem::prepareAutomaticAxisScaling`). + * So we have scale.Minimum = 0.5 (always constant!) and + * scale.Maximum = 0.5 + number_of_rings + max_offset + * (see notes for `PieChart::getMaxOffset`). + * Hence we get the following general formulas for computing normalized inner + * and outer radius: + * + * 1- transformToRadius(inner_radius) = + * (number_of_rings - (ring_index + 1) + m_fRadiusOffset) + * / (number_of_rings + max_offset + m_fRadiusOffset) + * + * 2- transformToRadius(outer_radius) = + * (1 + number_of_rings - (ring_index + 1) + m_fRadiusOffset) + * / (number_of_rings + max_offset + m_fRadiusOffset). + * + * Here you have to take into account that values for inner and outer radius + * are swapped since the radius axis is reversed (See notes for + * `PiePositionHelper::getInnerAndOuterRadius`). So indeed inner_radius is + * the outer and outer_radius is the inner. Anyway still because of the reverse + * orientation, the normalization performed by `transformToRadius` is reversed + * too, as we have seen above. Hence `transformToRadius(inner_radius)` is + * really the normalized inner radius and `transformToRadius(outer_radius)` is + * really the normalized outer radius. + * + * Some basic examples where we apply the above formulas: + * 1- For a non-exploded pie chart we have: + * `transformToRadius(inner_radius) = 0`, + * `transformToRadius(outer_radius) = 1`. + * 2- For a non-exploded donut with a single ring we have: + * `transformToRadius(inner_radius) = + * m_fRadiusOffset/(1 + m_fRadiusOffset)`, + * `transformToRadius(outer_radius) = + * (1 + m_fRadiusOffset)/(1 + m_fRadiusOffset) = 1`. + * 3- For an exploded pie chart we have: + * `transformToRadius(inner_radius) = 0/(1 + max_offset) = 0`, + * `transformToRadius(outer_radius) = 1/(1 + max_offset)`. + * + * The third example needs some remark. Both the logical inner and outer + * radius passed to `transformToRadius` are offset by `max_offset`. + * However the returned normalized values do not contain any (normalized) + * offset term at all, otherwise the returned values would be + * `max_offset/(1 + max_offset)` and `1`. Hence, for exploded pie/donut, + * `transformToRadius` returns the normalized value of radii without any + * offset term. These values are smaller than in the non-exploded case by an + * amount equals to the value of the normalized maximum offset + * (`max_offset/(1 + max_offset)` in the example above). That is due to the + * fact that the normalization keeps into account the space needed for the + * offset. This is the correct behavior, in fact the offset for the current + * slice could be different from the maximum offset. + * These remarks should clarify why the `PieChart::createDataPoint` and + * `PieChart::createTextLabelShape` methods add the normalized offset (for the + * current slice) to the normalized radii in order to achieve the correct + * placement of slice and text shapes. + */ double PolarPlottingPositionHelper::transformToRadius( double fLogicValueOnRadiusAxis, bool bDoScaling ) const { double fNormalRadius = 0.0; |