[Libreoffice-commits] core.git: chart2/source

Marco Cecchetti marco.cecchetti at collabora.com
Mon Feb 9 04:43:21 PST 2015


 chart2/source/view/charttypes/PieChart.cxx          |   58 +++++++++++++++
 chart2/source/view/charttypes/PieChart.hxx          |   12 +++
 chart2/source/view/charttypes/VSeriesPlotter.cxx    |   21 +++++
 chart2/source/view/inc/PlotterBase.hxx              |    4 +
 chart2/source/view/inc/PlottingPositionHelper.hxx   |   35 ++++++++-
 chart2/source/view/inc/PolarLabelPositionHelper.hxx |   11 +++
 chart2/source/view/inc/VSeriesPlotter.hxx           |   35 +++++++++
 chart2/source/view/main/PlottingPositionHelper.cxx  |   73 ++++++++++++++++++++
 8 files changed, 245 insertions(+), 4 deletions(-)

New commits:
commit 1a595052b205f8505776699f61c1a0b89bc42380
Author: Marco Cecchetti <marco.cecchetti at collabora.com>
Date:   Mon Feb 9 13:36:49 2015 +0100

    Added doc notes for classes and methods used for pie charts.

diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
index 3edf2af..5c29b36 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 2b88b1a..2929f96 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 8acf427..5fdd37b 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 887f8ca..b7515c4 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 e913cdd..969d886 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 5b9b1d4..cb7ae63 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 16218f7..03bbc80 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 d72b1dd..9575726 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;


More information about the Libreoffice-commits mailing list