chart2/source/view/charttypes/BarChart.cxx       |  850 +++++++++++------------
 chart2/source/view/charttypes/BarChart.hxx       |   47 +
 chart2/source/view/charttypes/VSeriesPlotter.cxx |    2 
 chart2/source/view/inc/VSeriesPlotter.hxx        |    2 
 4 files changed, 477 insertions(+), 424 deletions(-)

New commits:
commit b0c68f982dfabd33b6049c3614734401f70bae50
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Wed Jan 12 14:21:58 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Thu Jan 13 07:36:24 2022 +0100

    split the BarChart rendering method down a little
    
    into slightly more manageable chunks
    
    Change-Id: I2a8c031618516102e2dccf071beef51fe9917f82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128347
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/chart2/source/view/charttypes/BarChart.cxx 
b/chart2/source/view/charttypes/BarChart.cxx
index 57dc851e2035..06e041e800df 100644
--- a/chart2/source/view/charttypes/BarChart.cxx
+++ b/chart2/source/view/charttypes/BarChart.cxx
@@ -385,30 +385,6 @@ void BarChart::addSeries( std::unique_ptr<VDataSeries> 
pSeries, sal_Int32 zSlot,
     VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot );
 }
 
-namespace {
-
-//better performance for big data
-struct FormerBarPoint
-{
-    FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
-        : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
-        {}
-    FormerBarPoint()
-        : m_fX(std::numeric_limits<double>::quiet_NaN())
-        , m_fUpperY(std::numeric_limits<double>::quiet_NaN())
-        , m_fLowerY(std::numeric_limits<double>::quiet_NaN())
-        , m_fZ(std::numeric_limits<double>::quiet_NaN())
-    {
-    }
-
-    double m_fX;
-    double m_fUpperY;
-    double m_fLowerY;
-    double m_fZ;
-};
-
-}
-
 void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis()
 {
     //adapt m_aOverlapSequence and m_aGapwidthSequence for the 
groupBarsPerAxis feature
@@ -465,11 +441,8 @@ void BarChart::createShapes()
         ShapeFactory::createGroup2D( m_xFinalTarget );
     //check necessary here that different Y axis can not be stacked in the 
same group? ... hm?
 
-    double fLogicZ        = 1.0;//as defined
-
     bool bDrawConnectionLines = false;
     bool bDrawConnectionLinesInited = false;
-    bool bOnlyConnectionLinesForThisPoint = false;
 
     std::unordered_set<rtl::Reference<SvxShape>> aShapeSet;
 
@@ -497,8 +470,6 @@ void BarChart::createShapes()
     //better performance for big data
     std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap;
     m_bPointsWereSkipped = false;
-    sal_Int32 nSkippedPoints = 0;
-    sal_Int32 nCreatedPoints = 0;
 
     sal_Int32 nStartIndex = 0;
     sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
@@ -532,395 +503,9 @@ void BarChart::createShapes()
         sal_Int32 nZ=1;
         for( auto& rZSlot : m_aZSlots )
         {
-            //iterate through all x slots in this category
-            double fSlotX=0;
-            for( auto& rXSlot : rZSlot )
-            {
-                sal_Int32 nAttachedAxisIndex = 
rXSlot.getAttachedAxisIndexForFirstSeries();
-                //2ND_AXIS_IN_BARS so far one can assume to have the same 
plotter for each z slot
-                BarPositionHelper* pPosHelper = 
dynamic_cast<BarPositionHelper*>(&( getPlottingPositionHelper( 
nAttachedAxisIndex ) ) );
-                if(!pPosHelper)
-                    pPosHelper = m_pMainPosHelper.get();
-
-                PlotterBase::m_pPosHelper = pPosHelper;
-
-                //update/create information for current group
-                pPosHelper->updateSeriesCount( rZSlot.size() );
-                double fLogicBaseWidth = pPosHelper->getScaledSlotWidth();
-
-                // get distance from base value to maximum and minimum
-
-                double fMinimumY = 0.0, fMaximumY = 0.0;
-                if( nPointIndex < rXSlot.getPointCount())
-                    rXSlot.calculateYMinAndMaxForCategory( nPointIndex
-                        , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, 
fMaximumY, nAttachedAxisIndex );
-
-                double fLogicPositiveYSum = 0.0;
-                if( !std::isnan( fMaximumY ) )
-                    fLogicPositiveYSum = fMaximumY;
-
-                double fLogicNegativeYSum = 0.0;
-                if( !std::isnan( fMinimumY ) )
-                    fLogicNegativeYSum = fMinimumY;
-
-                if( pPosHelper->isPercentY() )
-                {
-                    /*  #i70395# fLogicPositiveYSum contains sum of all 
positive
-                        values, if any, otherwise the highest negative value.
-                        fLogicNegativeYSum contains sum of all negative values,
-                        if any, otherwise the lowest positive value.
-                        Afterwards, fLogicPositiveYSum will contain the maximum
-                        (positive) value that is related to 100%. */
-
-                    // do nothing if there are positive values only
-                    if( fLogicNegativeYSum < 0.0 )
-                    {
-                        // fLogicPositiveYSum<0 => negative values only, use 
absolute of negative sum
-                        if( fLogicPositiveYSum < 0.0 )
-                            fLogicPositiveYSum = -fLogicNegativeYSum;
-                        // otherwise there are positive and negative values, 
calculate total distance
-                        else
-                            fLogicPositiveYSum -= fLogicNegativeYSum;
-                    }
-                    fLogicNegativeYSum = 0.0;
-                }
-
-                double fBaseValue = 0.0;
-                if( !pPosHelper->isPercentY() && 
rXSlot.m_aSeriesVector.size()<=1 )
-                    fBaseValue = pPosHelper->getBaseValueY();
-                double fPositiveLogicYForNextSeries = fBaseValue;
-                double fNegativeLogicYForNextSeries = fBaseValue;
-
-                //iterate through all series in this x slot
-                for( std::unique_ptr<VDataSeries> const & pSeries : 
rXSlot.m_aSeriesVector )
-                {
-                    if(!pSeries)
-                        continue;
-
-                    bool bHasFillColorMapping = 
pSeries->hasPropertyMapping("FillColor");
-
-                    bOnlyConnectionLinesForThisPoint = false;
-
-                    if(nPointIndex==nStartIndex)//do not create a regression 
line for each point
-                        createRegressionCurvesShapes( *pSeries, 
xRegressionCurveTarget, xRegressionCurveEquationTarget,
-                                                      
m_pPosHelper->maySkipPointsInRegressionCalculation());
-
-                    if( !bDrawConnectionLinesInited )
-                    {
-                        bDrawConnectionLines = pSeries->getConnectBars();
-                        if( m_nDimension==3 )
-                            bDrawConnectionLines = false;
-                        if( bDrawConnectionLines && 
rXSlot.m_aSeriesVector.size()==1 )
-                        {
-                            //detect whether we have a stacked chart or not:
-                            StackingDirection eDirection = 
pSeries->getStackingDirection();
-                            if( eDirection  != StackingDirection_Y_STACKING )
-                                bDrawConnectionLines = false;
-                        }
-                        bDrawConnectionLinesInited = true;
-                    }
-
-                    // Use another XShapes for background, so we can avoid 
needing to set the Z-order on all of them,
-                    // which is expensive in bulk.
-                    rtl::Reference<SvxShapeGroupAnyD> 
xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget));
-                    rtl::Reference<SvxShapeGroupAnyD> 
xSeriesBackgroundShape_Shapes(getSeriesGroupShape(pSeries.get(), 
xSeriesTarget));
-                    aShapeSet.insert(xSeriesGroupShape_Shapes);
-                    aShapeSet.insert(xSeriesBackgroundShape_Shapes);
-                    // Suspend setting rects dirty for the duration of this 
call
-                    E3dScene* pScene = 
dynamic_cast<E3dScene*>(xSeriesGroupShape_Shapes->GetSdrObject());
-                    if (pScene)
-                        pScene->SuspendReportingDirtyRects();
-                    pScene = 
dynamic_cast<E3dScene*>(xSeriesBackgroundShape_Shapes->GetSdrObject());
-                    if (pScene)
-                        pScene->SuspendReportingDirtyRects();
-
-                    //collect data point information (logic coordinates, style 
):
-                    double fUnscaledLogicX = pSeries->getXValue( nPointIndex );
-                    fUnscaledLogicX = DateHelper::RasterizeDateValue( 
fUnscaledLogicX, m_aNullDate, m_nTimeResolution );
-                    if(std::isnan(fUnscaledLogicX))
-                        continue;//point not visible
-                    if(fUnscaledLogicX<pPosHelper->getLogicMinX())
-                        continue;//point not visible
-                    if(fUnscaledLogicX>pPosHelper->getLogicMaxX())
-                        continue;//point not visible
-                    if(pPosHelper->isStrongLowerRequested(0) && 
fUnscaledLogicX==pPosHelper->getLogicMaxX())
-                        continue;//point not visible
-                    double fLogicX = pPosHelper->getScaledSlotPos( 
fUnscaledLogicX, fSlotX );
-
-                    double fLogicBarHeight = pSeries->getYValue( nPointIndex );
-                    if( std::isnan( fLogicBarHeight )) //no value at this 
category
-                        continue;
-
-                    double fLogicValueForLabeDisplay = fLogicBarHeight;
-                    fLogicBarHeight-=fBaseValue;
-
-                    if( pPosHelper->isPercentY() )
-                    {
-                        if(fLogicPositiveYSum!=0.0)
-                            fLogicBarHeight = fabs( fLogicBarHeight 
)/fLogicPositiveYSum;
-                        else
-                            fLogicBarHeight = 0.0;
-                    }
-
-                    // tdf#114141 to draw the top of the zero height 3D bar
-                    // we set a small positive value, here the smallest one 
for the type double (DBL_MIN)
-                    if( fLogicBarHeight == 0.0 )
-                        fLogicBarHeight = DBL_MIN;
-
-                    //sort negative and positive values, to display them on 
different sides of the x axis
-                    bool bPositive = fLogicBarHeight >= 0.0;
-                    double fLowerYValue = bPositive ? 
fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries;
-                    double fUpperYValue = fLowerYValue+fLogicBarHeight;
-                    if( bPositive )
-                        fPositiveLogicYForNextSeries += fLogicBarHeight;
-                    else
-                        fNegativeLogicYForNextSeries += fLogicBarHeight;
-
-                    if(m_nDimension==3)
-                        fLogicZ = nZ+0.5;
-
-                    drawing::Position3D aUnscaledLogicPosition( 
fUnscaledLogicX, fUpperYValue, fLogicZ );
-
-                    //@todo ... start an iteration over the different breaks 
of the axis
-                    //each subsystem may add an additional shape to form the 
whole point
-                    //create a group shape for this point and add to the 
series shape:
-    //              uno::Reference< drawing::XShapes > 
xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) );
-    //              uno::Reference<drawing::XShape> xPointGroupShape_Shape =
-    //                      uno::Reference<drawing::XShape>( 
xPointGroupShape_Shapes, uno::UNO_QUERY );
-                    //as long as we do not iterate we do not need to create an 
additional group for each point
-                    uno::Reference< beans::XPropertySet > 
xDataPointProperties( pSeries->getPropertiesOfPoint( nPointIndex ) );
-                    sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
-                    if(m_nDimension==3) try
-                    {
-                        xDataPointProperties->getPropertyValue( "Geometry3D") 
>>= nGeometry3D;
-                    }
-                    catch( const uno::Exception& )
-                    {
-                        TOOLS_WARN_EXCEPTION("chart2", "" );
-                    }
-
-                    //@todo iterate through all subsystems to create partial 
points
-                    {
-                        //@todo select a suitable PositionHelper for this 
subsystem
-                        BarPositionHelper* pSubPosHelper = pPosHelper;
-
-                        double fUnclippedUpperYValue = fUpperYValue;
-
-                        //apply clipping to Y
-                        if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) 
)
-                        {
-                            if( bDrawConnectionLines )
-                                bOnlyConnectionLinesForThisPoint = true;
-                            else
-                                continue;
-                        }
-                        //@todo clipping of X and Z is not fully integrated so 
far, as there is a need to create different objects
-
-                        //apply scaling to Y before calculating width 
(necessary to maintain gradient in clipped objects)
-                        
pSubPosHelper->doLogicScaling(nullptr,&fLowerYValue,nullptr);
-                        
pSubPosHelper->doLogicScaling(nullptr,&fUpperYValue,nullptr);
-                        //scaling of X and Z is not provided as the created 
objects should be symmetric in that dimensions
-
-                        
pSubPosHelper->doLogicScaling(nullptr,&fUnclippedUpperYValue,nullptr);
-
-                        //calculate resulting width
-                        double fCompleteHeight = bPositive ? 
fLogicPositiveYSum : fLogicNegativeYSum;
-                        if( pPosHelper->isPercentY() )
-                            fCompleteHeight = 1.0;
-                        double fLogicBarWidth = fLogicBaseWidth;
-                        double 
fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
-                        if(!bPositive)
-                            fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
-                        double fLogicYStart = bPositive ? fLowerYValue : 
fUpperYValue;
-                        double fMiddleHeight = fUpperYValue-fLowerYValue;
-                        if(!bPositive)
-                            fMiddleHeight*=-1.0;
-                        double fLogicBarDepth = 0.5;
-                        if(m_nDimension==3)
-                        {
-                            if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && 
fCompleteHeight!=0.0 )
-                            {
-                                double fHeight = fCompleteHeight-fLowerYValue;
-                                if(!bPositive)
-                                    fHeight = fCompleteHeight-fUpperYValue;
-                                fLogicBarWidth = 
fLogicBaseWidth*fHeight/fCompleteHeight;
-                                if(fLogicBarWidth<=0.0)
-                                    fLogicBarWidth=fLogicBaseWidth;
-                                fLogicBarDepth = 
fLogicBarDepth*fHeight/fCompleteHeight;
-                                if(fLogicBarDepth<=0.0)
-                                    fLogicBarDepth*=-1.0;
-                            }
-                        }
-
-                        //better performance for big data
-                        FormerBarPoint aFormerPoint( 
aSeriesFormerPointMap[pSeries.get()] );
-                        pPosHelper->setCoordinateSystemResolution( 
m_aCoordinateSystemResolution );
-                        if( !pSeries->isAttributedDataPoint(nPointIndex)
-                            &&
-                            pPosHelper->isSameForGivenResolution( 
aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
-                                                            , fLogicX, 
fUpperYValue, fLogicZ )
-                            &&
-                            pPosHelper->isSameForGivenResolution( 
aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
-                                                            , fLogicX, 
fLowerYValue, fLogicZ )
-                                                            )
-                        {
-                            nSkippedPoints++;
-                            m_bPointsWereSkipped = true;
-                            continue;
-                        }
-                        aSeriesFormerPointMap[pSeries.get()] = 
FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
-
-                        if( bDrawConnectionLines )
-                        {
-                            //store point information for connection lines
-
-                            drawing::Position3D aLeftUpperPoint( 
fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
-                            drawing::Position3D aRightUpperPoint( 
fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
-
-                            if( isValidPosition(aLeftUpperPoint) )
-                                AddPointToPoly( 
pSeries->m_aPolyPolygonShape3D, aLeftUpperPoint );
-                            if( isValidPosition(aRightUpperPoint) )
-                                AddPointToPoly( 
pSeries->m_aPolyPolygonShape3D, aRightUpperPoint );
-                        }
-
-                        if( bOnlyConnectionLinesForThisPoint )
-                            continue;
-
-                        //maybe additional possibility for performance 
improvement
-                        //bool 
bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false;
-                        //pPosHelper->isSameForGivenResolution( 
fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ
-                        //                            , 
fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ );
-
-                        nCreatedPoints++;
-                        //create partial point
-                        if( !approxEqual(fLowerYValue,fUpperYValue) )
-                        {
-                            if( m_nDimension==3 )
-                            {
-                                drawing::Position3D aLogicBottom            
(fLogicX,fLogicYStart,fLogicZ);
-                                drawing::Position3D aLogicLeftBottomFront   
(fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
-                                drawing::Position3D aLogicRightDeepTop      
(fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
-                                drawing::Position3D aLogicTopTop            
(fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
-
-                                ::chart::XTransformation2* pTransformation = 
pSubPosHelper->getTransformationScaledLogicToScene();
-
-                                //transformation 3) -> 4)
-                                drawing::Position3D aTransformedBottom         
 ( pTransformation->transform( aLogicBottom ) );
-                                drawing::Position3D 
aTransformedLeftBottomFront ( pTransformation->transform( aLogicLeftBottomFront 
) );
-                                drawing::Position3D aTransformedRightDeepTop   
 ( pTransformation->transform( aLogicRightDeepTop ) );
-                                drawing::Position3D aTransformedTopTop         
 ( pTransformation->transform( aLogicTopTop ) );
-
-                                drawing::Direction3D aSize = 
aTransformedRightDeepTop - aTransformedLeftBottomFront;
-                                drawing::Direction3D aTopSize( 
aTransformedTopTop - aTransformedRightDeepTop );
-                                fTopHeight = aTopSize.DirectionY;
-
-                                sal_Int32 nRotateZAngleHundredthDegree = 0;
-                                if( pPosHelper->isSwapXAndY() )
-                                {
-                                    fTopHeight = aTopSize.DirectionX;
-                                    nRotateZAngleHundredthDegree = 90*100;
-                                    aSize = 
drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
-                                }
-
-                                if( aSize.DirectionX < 0 )
-                                    aSize.DirectionX *= -1.0;
-                                if( aSize.DirectionZ < 0 )
-                                    aSize.DirectionZ *= -1.0;
-                                if( fTopHeight < 0 )
-                                    fTopHeight *= -1.0;
-
-                                rtl::Reference< SvxShape > xShape = 
createDataPoint3D_Bar(
-                                    xSeriesGroupShape_Shapes, 
aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree
-                                    , xDataPointProperties, nGeometry3D );
-
-                                if(bHasFillColorMapping)
-                                {
-                                    double nPropVal = 
pSeries->getValueByProperty(nPointIndex, "FillColor");
-                                    if(!std::isnan(nPropVal))
-                                    {
-                                        xShape->setPropertyValue("FillColor", 
uno::Any(static_cast<sal_Int32>(nPropVal)));
-                                    }
-                                }
-                                //set name/classified ObjectID (CID)
-                                ShapeFactory::setShapeName(xShape
-                                    , ObjectIdentifier::createPointCID(
-                                        
pSeries->getPointCID_Stub(),nPointIndex) );
-                            }
-                            else //m_nDimension!=3
-                            {
-                                // performance improvement: alloc the sequence 
before the rendering
-                                // otherwise we have 2 realloc calls
-                                
std::vector<std::vector<css::drawing::Position3D>> aPoly;
-                                aPoly.resize(1);
-                                drawing::Position3D aLeftUpperPoint( 
fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
-                                drawing::Position3D aRightUpperPoint( 
fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
-
-                                AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
-                                AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
-                                AddPointToPoly( aPoly, aRightUpperPoint );
-                                AddPointToPoly( aPoly, aLeftUpperPoint );
-                                AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
-                                pPosHelper->transformScaledLogicToScene( aPoly 
);
-                                std::optional<sal_Int32> xFillColor;
-                                if(bHasFillColorMapping)
-                                {
-                                    double nPropVal = 
pSeries->getValueByProperty(nPointIndex, "FillColor");
-                                    if(!std::isnan(nPropVal))
-                                        xFillColor = 
static_cast<sal_Int32>(nPropVal);
-                                }
-                                SdrPathObj* pShape = 
ShapeFactory::createArea2D( xSeriesGroupShape_Shapes, aPoly, 
/*bSetZOrderToZero*/false );
-                                
PropertyMapper::setPropertyNameMapForFilledSeriesProperties(pShape, 
xDataPointProperties, xFillColor);
-
-                                //set name/classified ObjectID (CID)
-                                ShapeFactory::setShapeName(pShape
-                                    , ObjectIdentifier::createPointCID(
-                                        
pSeries->getPointCID_Stub(),nPointIndex) );
-                            }
-
-                        }
-
-                        //create error bar
-                        createErrorBar_Y( aUnscaledLogicPosition, *pSeries, 
nPointIndex, m_xLogicTarget, &fLogicX );
-
-                        //create data point label
-                        if( pSeries->getDataPointLabelIfLabel(nPointIndex) )
-                        {
-                            double fLogicSum = 
aLogicYSumMap[nAttachedAxisIndex];
-
-                            LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
-                            sal_Int32 nLabelPlacement = 
pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, 
pPosHelper->isSwapXAndY() );
-
-                            double fLowerBarDepth = fLogicBarDepth;
-                            double fUpperBarDepth = fLogicBarDepth;
-                            {
-                                if( 
lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
-                                {
-                                    double fOuterBarDepth = fLogicBarDepth * 
fTopHeight/(fabs(fCompleteHeight));
-                                    fLowerBarDepth = (fBaseValue < 
fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
-                                    fUpperBarDepth = (fBaseValue < 
fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
-                                }
-                            }
-
-                            awt::Point aScreenPosition2D = 
getLabelScreenPositionAndAlignment(
-                                eAlignment, nLabelPlacement, fLogicX, 
fLowerYValue, fUpperYValue, fLogicZ,
-                                fLowerBarDepth, fUpperBarDepth, fBaseValue, 
pPosHelper);
-                            sal_Int32 nOffset = 0;
-                            if(eAlignment!=LABEL_ALIGN_CENTER)
-                            {
-                                nOffset = 100;//add some spacing //@todo maybe 
get more intelligent values
-                                if( m_nDimension == 3 )
-                                    nOffset = 260;
-                            }
-                            createDataLabel(
-                                xTextTarget, *pSeries, nPointIndex,
-                                fLogicValueForLabeDisplay, fLogicSum, 
aScreenPosition2D, eAlignment, nOffset);
-                        }
-
-                    }//end iteration through partial points
-
-                }//next series in x slot (next y slot)
-                fSlotX+=1.0;
-            }//next x slot
+            doZSlot(bDrawConnectionLines, bDrawConnectionLinesInited, rZSlot, 
nZ, nPointIndex, nStartIndex,
+                    xSeriesTarget, xRegressionCurveTarget, 
xRegressionCurveEquationTarget, xTextTarget,
+                    aShapeSet, aSeriesFormerPointMap, aLogicYSumMap);
             ++nZ;
         }//next z slot
     }//next category
@@ -973,11 +558,432 @@ void BarChart::createShapes()
 
     /* @todo remove series shapes if empty
     */
+}
+
+void BarChart::doZSlot(
+        bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+        const std::vector< VDataSeriesGroup >& rZSlot,
+        const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 
nStartIndex,
+        rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+        rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+        rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+        rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+        std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+        std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+        std::map< sal_Int32,  double >& aLogicYSumMap)
+{
+    //iterate through all x slots in this category
+    double fSlotX=0;
+    for( auto& rXSlot : rZSlot )
+    {
+        sal_Int32 nAttachedAxisIndex = 
rXSlot.getAttachedAxisIndexForFirstSeries();
+        //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for 
each z slot
+        BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( 
getPlottingPositionHelper( nAttachedAxisIndex ) ) );
+        if(!pPosHelper)
+            pPosHelper = m_pMainPosHelper.get();
+
+        PlotterBase::m_pPosHelper = pPosHelper;
+
+        //update/create information for current group
+        pPosHelper->updateSeriesCount( rZSlot.size() );
+        double fLogicBaseWidth = pPosHelper->getScaledSlotWidth();
+
+        // get distance from base value to maximum and minimum
+
+        double fMinimumY = 0.0, fMaximumY = 0.0;
+        if( nPointIndex < rXSlot.getPointCount())
+            rXSlot.calculateYMinAndMaxForCategory( nPointIndex
+                , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, 
fMaximumY, nAttachedAxisIndex );
+
+        double fLogicPositiveYSum = 0.0;
+        if( !std::isnan( fMaximumY ) )
+            fLogicPositiveYSum = fMaximumY;
+
+        double fLogicNegativeYSum = 0.0;
+        if( !std::isnan( fMinimumY ) )
+            fLogicNegativeYSum = fMinimumY;
+
+        if( pPosHelper->isPercentY() )
+        {
+            /*  #i70395# fLogicPositiveYSum contains sum of all positive
+                values, if any, otherwise the highest negative value.
+                fLogicNegativeYSum contains sum of all negative values,
+                if any, otherwise the lowest positive value.
+                Afterwards, fLogicPositiveYSum will contain the maximum
+                (positive) value that is related to 100%. */
+
+            // do nothing if there are positive values only
+            if( fLogicNegativeYSum < 0.0 )
+            {
+                // fLogicPositiveYSum<0 => negative values only, use absolute 
of negative sum
+                if( fLogicPositiveYSum < 0.0 )
+                    fLogicPositiveYSum = -fLogicNegativeYSum;
+                // otherwise there are positive and negative values, calculate 
total distance
+                else
+                    fLogicPositiveYSum -= fLogicNegativeYSum;
+            }
+            fLogicNegativeYSum = 0.0;
+        }
+
+        doXSlot(rXSlot, bDrawConnectionLines, bDrawConnectionLinesInited, nZ, 
nPointIndex, nStartIndex,
+                xSeriesTarget, xRegressionCurveTarget, 
xRegressionCurveEquationTarget, xTextTarget,
+                aShapeSet, aSeriesFormerPointMap, aLogicYSumMap,
+                fLogicBaseWidth, fSlotX, pPosHelper, fLogicPositiveYSum, 
fLogicNegativeYSum, nAttachedAxisIndex);
+
+        fSlotX+=1.0;
+    }//next x slot
+}
+
+
+void BarChart::doXSlot(
+    const VDataSeriesGroup& rXSlot,
+    bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+    const sal_Int32 nZ, const sal_Int32 nPointIndex, const sal_Int32 
nStartIndex,
+    rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+    rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+    rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+    rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+    std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+    std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+    std::map< sal_Int32,  double >& aLogicYSumMap,
+    const double fLogicBaseWidth, const double fSlotX,
+    BarPositionHelper* const pPosHelper,
+    const double fLogicPositiveYSum, const double fLogicNegativeYSum,
+    const sal_Int32 nAttachedAxisIndex)
+{
+    double fBaseValue = 0.0;
+    if( !pPosHelper->isPercentY() && rXSlot.m_aSeriesVector.size()<=1 )
+        fBaseValue = pPosHelper->getBaseValueY();
+    double fPositiveLogicYForNextSeries = fBaseValue;
+    double fNegativeLogicYForNextSeries = fBaseValue;
+
+    //iterate through all series in this x slot
+    for( std::unique_ptr<VDataSeries> const & pSeries : rXSlot.m_aSeriesVector 
)
+    {
+        if(!pSeries)
+            continue;
+
+        bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor");
+
+        bool bOnlyConnectionLinesForThisPoint = false;
+
+        if(nPointIndex==nStartIndex)//do not create a regression line for each 
point
+            createRegressionCurvesShapes( *pSeries, xRegressionCurveTarget, 
xRegressionCurveEquationTarget,
+                                          
m_pPosHelper->maySkipPointsInRegressionCalculation());
+
+        if( !bDrawConnectionLinesInited )
+        {
+            bDrawConnectionLines = pSeries->getConnectBars();
+            if( m_nDimension==3 )
+                bDrawConnectionLines = false;
+            if( bDrawConnectionLines && rXSlot.m_aSeriesVector.size()==1 )
+            {
+                //detect whether we have a stacked chart or not:
+                StackingDirection eDirection = pSeries->getStackingDirection();
+                if( eDirection  != StackingDirection_Y_STACKING )
+                    bDrawConnectionLines = false;
+            }
+            bDrawConnectionLinesInited = true;
+        }
+
+        // Use another XShapes for background, so we can avoid needing to set 
the Z-order on all of them,
+        // which is expensive in bulk.
+        rtl::Reference<SvxShapeGroupAnyD> 
xSeriesGroupShape_Shapes(getSeriesGroupShape(pSeries.get(), xSeriesTarget));
+        rtl::Reference<SvxShapeGroupAnyD> 
xSeriesBackgroundShape_Shapes(getSeriesGroupShape(pSeries.get(), 
xSeriesTarget));
+        aShapeSet.insert(xSeriesGroupShape_Shapes);
+        aShapeSet.insert(xSeriesBackgroundShape_Shapes);
+        // Suspend setting rects dirty for the duration of this call
+        E3dScene* pScene = 
dynamic_cast<E3dScene*>(xSeriesGroupShape_Shapes->GetSdrObject());
+        if (pScene)
+            pScene->SuspendReportingDirtyRects();
+        pScene = 
dynamic_cast<E3dScene*>(xSeriesBackgroundShape_Shapes->GetSdrObject());
+        if (pScene)
+            pScene->SuspendReportingDirtyRects();
+
+        //collect data point information (logic coordinates, style ):
+        double fUnscaledLogicX = pSeries->getXValue( nPointIndex );
+        fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, 
m_aNullDate, m_nTimeResolution );
+        if(std::isnan(fUnscaledLogicX))
+            continue;//point not visible
+        if(fUnscaledLogicX<pPosHelper->getLogicMinX())
+            continue;//point not visible
+        if(fUnscaledLogicX>pPosHelper->getLogicMaxX())
+            continue;//point not visible
+        if(pPosHelper->isStrongLowerRequested(0) && 
fUnscaledLogicX==pPosHelper->getLogicMaxX())
+            continue;//point not visible
+        double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX 
);
+
+        double fLogicBarHeight = pSeries->getYValue( nPointIndex );
+        if( std::isnan( fLogicBarHeight )) //no value at this category
+            continue;
+
+        double fLogicValueForLabeDisplay = fLogicBarHeight;
+        fLogicBarHeight-=fBaseValue;
+
+        if( pPosHelper->isPercentY() )
+        {
+            if(fLogicPositiveYSum!=0.0)
+                fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum;
+            else
+                fLogicBarHeight = 0.0;
+        }
+
+        // tdf#114141 to draw the top of the zero height 3D bar
+        // we set a small positive value, here the smallest one for the type 
double (DBL_MIN)
+        if( fLogicBarHeight == 0.0 )
+            fLogicBarHeight = DBL_MIN;
+
+        //sort negative and positive values, to display them on different 
sides of the x axis
+        bool bPositive = fLogicBarHeight >= 0.0;
+        double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : 
fNegativeLogicYForNextSeries;
+        double fUpperYValue = fLowerYValue+fLogicBarHeight;
+        if( bPositive )
+            fPositiveLogicYForNextSeries += fLogicBarHeight;
+        else
+            fNegativeLogicYForNextSeries += fLogicBarHeight;
+
+        double fLogicZ        = 1.0;//as defined
+        if(m_nDimension==3)
+            fLogicZ = nZ+0.5;
+
+        drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, 
fUpperYValue, fLogicZ );
+
+        //@todo ... start an iteration over the different breaks of the axis
+        //each subsystem may add an additional shape to form the whole point
+        //create a group shape for this point and add to the series shape:
+//              uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( 
createGroupShape(xSeriesGroupShape_Shapes) );
+//              uno::Reference<drawing::XShape> xPointGroupShape_Shape =
+//                      uno::Reference<drawing::XShape>( 
xPointGroupShape_Shapes, uno::UNO_QUERY );
+        //as long as we do not iterate we do not need to create an additional 
group for each point
+        uno::Reference< beans::XPropertySet > xDataPointProperties( 
pSeries->getPropertiesOfPoint( nPointIndex ) );
+        sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
+        if(m_nDimension==3) try
+        {
+            xDataPointProperties->getPropertyValue( "Geometry3D") >>= 
nGeometry3D;
+        }
+        catch( const uno::Exception& )
+        {
+            TOOLS_WARN_EXCEPTION("chart2", "" );
+        }
+
+        //@todo iterate through all subsystems to create partial points
+        {
+            //@todo select a suitable PositionHelper for this subsystem
+            BarPositionHelper* pSubPosHelper = pPosHelper;
+
+            double fUnclippedUpperYValue = fUpperYValue;
+
+            //apply clipping to Y
+            if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) )
+            {
+                if( bDrawConnectionLines )
+                    bOnlyConnectionLinesForThisPoint = true;
+                else
+                    continue;
+            }
+            //@todo clipping of X and Z is not fully integrated so far, as 
there is a need to create different objects
+
+            //apply scaling to Y before calculating width (necessary to 
maintain gradient in clipped objects)
+            pSubPosHelper->doLogicScaling(nullptr,&fLowerYValue,nullptr);
+            pSubPosHelper->doLogicScaling(nullptr,&fUpperYValue,nullptr);
+            //scaling of X and Z is not provided as the created objects should 
be symmetric in that dimensions
+
+            
pSubPosHelper->doLogicScaling(nullptr,&fUnclippedUpperYValue,nullptr);
+
+            //calculate resulting width
+            double fCompleteHeight = bPositive ? fLogicPositiveYSum : 
fLogicNegativeYSum;
+            if( pPosHelper->isPercentY() )
+                fCompleteHeight = 1.0;
+            double fLogicBarWidth = fLogicBaseWidth;
+            double fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
+            if(!bPositive)
+                fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
+            double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue;
+            double fMiddleHeight = fUpperYValue-fLowerYValue;
+            if(!bPositive)
+                fMiddleHeight*=-1.0;
+            double fLogicBarDepth = 0.5;
+            if(m_nDimension==3)
+            {
+                if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && 
fCompleteHeight!=0.0 )
+                {
+                    double fHeight = fCompleteHeight-fLowerYValue;
+                    if(!bPositive)
+                        fHeight = fCompleteHeight-fUpperYValue;
+                    fLogicBarWidth = fLogicBaseWidth*fHeight/fCompleteHeight;
+                    if(fLogicBarWidth<=0.0)
+                        fLogicBarWidth=fLogicBaseWidth;
+                    fLogicBarDepth = fLogicBarDepth*fHeight/fCompleteHeight;
+                    if(fLogicBarDepth<=0.0)
+                        fLogicBarDepth*=-1.0;
+                }
+            }
+
+            //better performance for big data
+            FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries.get()] 
);
+            pPosHelper->setCoordinateSystemResolution( 
m_aCoordinateSystemResolution );
+            if( !pSeries->isAttributedDataPoint(nPointIndex)
+                &&
+                pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, 
aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
+                                                , fLogicX, fUpperYValue, 
fLogicZ )
+                &&
+                pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, 
aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
+                                                , fLogicX, fLowerYValue, 
fLogicZ )
+                                                )
+            {
+                m_bPointsWereSkipped = true;
+                continue;
+            }
+            aSeriesFormerPointMap[pSeries.get()] = 
FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
+
+            if( bDrawConnectionLines )
+            {
+                //store point information for connection lines
+
+                drawing::Position3D aLeftUpperPoint( 
fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+                drawing::Position3D aRightUpperPoint( 
fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
+
+                if( isValidPosition(aLeftUpperPoint) )
+                    AddPointToPoly( pSeries->m_aPolyPolygonShape3D, 
aLeftUpperPoint );
+                if( isValidPosition(aRightUpperPoint) )
+                    AddPointToPoly( pSeries->m_aPolyPolygonShape3D, 
aRightUpperPoint );
+            }
+
+            if( bOnlyConnectionLinesForThisPoint )
+                continue;
+
+            //maybe additional possibility for performance improvement
+            //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = 
false;
+            //pPosHelper->isSameForGivenResolution( 
fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ
+            //                            , fLogicX+fLogicBarWidth/2.0, 
fLowerYValue, fLogicZ );
+
+            //create partial point
+            if( !approxEqual(fLowerYValue,fUpperYValue) )
+            {
+                if( m_nDimension==3 )
+                {
+                    drawing::Position3D aLogicBottom            
(fLogicX,fLogicYStart,fLogicZ);
+                    drawing::Position3D aLogicLeftBottomFront   
(fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
+                    drawing::Position3D aLogicRightDeepTop      
(fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
+                    drawing::Position3D aLogicTopTop            
(fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
+
+                    ::chart::XTransformation2* pTransformation = 
pSubPosHelper->getTransformationScaledLogicToScene();
+
+                    //transformation 3) -> 4)
+                    drawing::Position3D aTransformedBottom          ( 
pTransformation->transform( aLogicBottom ) );
+                    drawing::Position3D aTransformedLeftBottomFront ( 
pTransformation->transform( aLogicLeftBottomFront ) );
+                    drawing::Position3D aTransformedRightDeepTop    ( 
pTransformation->transform( aLogicRightDeepTop ) );
+                    drawing::Position3D aTransformedTopTop          ( 
pTransformation->transform( aLogicTopTop ) );
+
+                    drawing::Direction3D aSize = aTransformedRightDeepTop - 
aTransformedLeftBottomFront;
+                    drawing::Direction3D aTopSize( aTransformedTopTop - 
aTransformedRightDeepTop );
+                    fTopHeight = aTopSize.DirectionY;
+
+                    sal_Int32 nRotateZAngleHundredthDegree = 0;
+                    if( pPosHelper->isSwapXAndY() )
+                    {
+                        fTopHeight = aTopSize.DirectionX;
+                        nRotateZAngleHundredthDegree = 90*100;
+                        aSize = 
drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
+                    }
+
+                    if( aSize.DirectionX < 0 )
+                        aSize.DirectionX *= -1.0;
+                    if( aSize.DirectionZ < 0 )
+                        aSize.DirectionZ *= -1.0;
+                    if( fTopHeight < 0 )
+                        fTopHeight *= -1.0;
+
+                    rtl::Reference< SvxShape > xShape = createDataPoint3D_Bar(
+                        xSeriesGroupShape_Shapes, aTransformedBottom, aSize, 
fTopHeight, nRotateZAngleHundredthDegree
+                        , xDataPointProperties, nGeometry3D );
+
+                    if(bHasFillColorMapping)
+                    {
+                        double nPropVal = 
pSeries->getValueByProperty(nPointIndex, "FillColor");
+                        if(!std::isnan(nPropVal))
+                        {
+                            xShape->setPropertyValue("FillColor", 
uno::Any(static_cast<sal_Int32>(nPropVal)));
+                        }
+                    }
+                    //set name/classified ObjectID (CID)
+                    ShapeFactory::setShapeName(xShape
+                        , ObjectIdentifier::createPointCID(
+                            pSeries->getPointCID_Stub(),nPointIndex) );
+                }
+                else //m_nDimension!=3
+                {
+                    // performance improvement: alloc the sequence before the 
rendering
+                    // otherwise we have 2 realloc calls
+                    std::vector<std::vector<css::drawing::Position3D>> aPoly;
+                    aPoly.resize(1);
+                    drawing::Position3D aLeftUpperPoint( 
fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+                    drawing::Position3D aRightUpperPoint( 
fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
+
+                    AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+                    AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+                    AddPointToPoly( aPoly, aRightUpperPoint );
+                    AddPointToPoly( aPoly, aLeftUpperPoint );
+                    AddPointToPoly( aPoly, drawing::Position3D( 
fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
+                    pPosHelper->transformScaledLogicToScene( aPoly );
+                    std::optional<sal_Int32> xFillColor;
+                    if(bHasFillColorMapping)
+                    {
+                        double nPropVal = 
pSeries->getValueByProperty(nPointIndex, "FillColor");
+                        if(!std::isnan(nPropVal))
+                            xFillColor = static_cast<sal_Int32>(nPropVal);
+                    }
+                    SdrPathObj* pShape = ShapeFactory::createArea2D( 
xSeriesGroupShape_Shapes, aPoly, /*bSetZOrderToZero*/false );
+                    
PropertyMapper::setPropertyNameMapForFilledSeriesProperties(pShape, 
xDataPointProperties, xFillColor);
+
+                    //set name/classified ObjectID (CID)
+                    ShapeFactory::setShapeName(pShape
+                        , ObjectIdentifier::createPointCID(
+                            pSeries->getPointCID_Stub(),nPointIndex) );
+                }
+
+            }
+
+            //create error bar
+            createErrorBar_Y( aUnscaledLogicPosition, *pSeries, nPointIndex, 
m_xLogicTarget, &fLogicX );
+
+            //create data point label
+            if( pSeries->getDataPointLabelIfLabel(nPointIndex) )
+            {
+                double fLogicSum = aLogicYSumMap[nAttachedAxisIndex];
+
+                LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
+                sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( 
nPointIndex, m_xChartTypeModel, pPosHelper->isSwapXAndY() );
+
+                double fLowerBarDepth = fLogicBarDepth;
+                double fUpperBarDepth = fLogicBarDepth;
+                {
+                    if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && 
fCompleteHeight!=0.0 )
+                    {
+                        double fOuterBarDepth = fLogicBarDepth * 
fTopHeight/(fabs(fCompleteHeight));
+                        fLowerBarDepth = (fBaseValue < fUpperYValue) ? 
fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
+                        fUpperBarDepth = (fBaseValue < fUpperYValue) ? 
fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
+                    }
+                }
+
+                awt::Point aScreenPosition2D = 
getLabelScreenPositionAndAlignment(
+                    eAlignment, nLabelPlacement, fLogicX, fLowerYValue, 
fUpperYValue, fLogicZ,
+                    fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper);
+                sal_Int32 nOffset = 0;
+                if(eAlignment!=LABEL_ALIGN_CENTER)
+                {
+                    nOffset = 100;//add some spacing //@todo maybe get more 
intelligent values
+                    if( m_nDimension == 3 )
+                        nOffset = 260;
+                }
+                createDataLabel(
+                    xTextTarget, *pSeries, nPointIndex,
+                    fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, 
eAlignment, nOffset);
+            }
+
+        }//end iteration through partial points
 
-    SAL_INFO(
-        "chart2",
-        "skipped points: " << nSkippedPoints << " created points: "
-            << nCreatedPoints);
+    }//next series in x slot (next y slot)
 }
 
 } //namespace chart
diff --git a/chart2/source/view/charttypes/BarChart.hxx 
b/chart2/source/view/charttypes/BarChart.hxx
index 08eaeadab2e6..5e9ab5e49f48 100644
--- a/chart2/source/view/charttypes/BarChart.hxx
+++ b/chart2/source/view/charttypes/BarChart.hxx
@@ -61,6 +61,53 @@ private: //methods
 
     void adaptOverlapAndGapwidthForGroupBarsPerAxis();
 
+    //better performance for big data
+    struct FormerBarPoint
+    {
+        FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
+            : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
+            {}
+        FormerBarPoint()
+            : m_fX(std::numeric_limits<double>::quiet_NaN())
+            , m_fUpperY(std::numeric_limits<double>::quiet_NaN())
+            , m_fLowerY(std::numeric_limits<double>::quiet_NaN())
+            , m_fZ(std::numeric_limits<double>::quiet_NaN())
+        {
+        }
+
+        double m_fX;
+        double m_fUpperY;
+        double m_fLowerY;
+        double m_fZ;
+    };
+
+    void doZSlot(
+            bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited, 
const std::vector< VDataSeriesGroup >& rZSlot,
+            sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex,
+            rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+            std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+            std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+            std::map< sal_Int32,  double >& aLogicYSumMap);
+
+    void doXSlot(
+            const VDataSeriesGroup& rXSlot,
+            bool& bDrawConnectionLines, bool& bDrawConnectionLinesInited,
+            sal_Int32 nZ, sal_Int32 nPointIndex, sal_Int32 nStartIndex,
+            rtl::Reference<SvxShapeGroupAnyD>& xSeriesTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xRegressionCurveEquationTarget,
+            rtl::Reference<SvxShapeGroupAnyD>& xTextTarget,
+            std::unordered_set<rtl::Reference<SvxShape>>& aShapeSet,
+            std::map< VDataSeries*, FormerBarPoint >& aSeriesFormerPointMap,
+            std::map< sal_Int32,  double >& aLogicYSumMap,
+            double fLogicBaseWidth, double fSlotX,
+            BarPositionHelper* const pPosHelper,
+            double fLogicPositiveYSum, double fLogicNegativeYSum,
+            sal_Int32 nAttachedAxisIndex);
+
 private: //member
     std::unique_ptr<BarPositionHelper>   m_pMainPosHelper;
     css::uno::Sequence< sal_Int32 >      m_aOverlapSequence;
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx 
b/chart2/source/view/charttypes/VSeriesPlotter.cxx
index d2ee85a6a100..3cff976ac66f 100644
--- a/chart2/source/view/charttypes/VSeriesPlotter.cxx
+++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx
@@ -2092,7 +2092,7 @@ void 
VDataSeriesGroup::getMinimumAndMaximumYInContinuousXRange(
 
 void VDataSeriesGroup::calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
         , bool bSeparateStackingForDifferentSigns
-        , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex )
+        , double& rfMinimumY, double& rfMaximumY, sal_Int32 nAxisIndex ) const
 {
     assert(nCategoryIndex >= 0);
     assert(nCategoryIndex < getPointCount());
diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx 
b/chart2/source/view/inc/VSeriesPlotter.hxx
index cc92aa969dda..83d97bc8b671 100644
--- a/chart2/source/view/inc/VSeriesPlotter.hxx
+++ b/chart2/source/view/inc/VSeriesPlotter.hxx
@@ -90,7 +90,7 @@ public:
 
     void calculateYMinAndMaxForCategory( sal_Int32 nCategoryIndex
                                             , bool 
bSeparateStackingForDifferentSigns
-                                            , double& rfMinimumY, double& 
rfMaximumY, sal_Int32 nAxisIndex );
+                                            , double& rfMinimumY, double& 
rfMaximumY, sal_Int32 nAxisIndex ) const;
     void calculateYMinAndMaxForCategoryRange( sal_Int32 nStartCategoryIndex, 
sal_Int32 nEndCategoryIndex
                                                 , bool 
bSeparateStackingForDifferentSigns
                                                 , double& rfMinimumY, double& 
rfMaximumY, sal_Int32 nAxisIndex );

Reply via email to