chart2/source/inc/BaseGFXHelper.hxx                |    2 
 chart2/source/inc/CommonConverters.hxx             |   20 +
 chart2/source/tools/BaseGFXHelper.cxx              |   32 +
 chart2/source/tools/CommonConverters.cxx           |  138 ++++++-
 chart2/source/view/axes/VCartesianGrid.cxx         |   12 
 chart2/source/view/charttypes/AreaChart.cxx        |  197 ++++-------
 chart2/source/view/charttypes/AreaChart.hxx        |   10 
 chart2/source/view/charttypes/BarChart.cxx         |   12 
 chart2/source/view/charttypes/CandleStickChart.cxx |   12 
 chart2/source/view/charttypes/NetChart.cxx         |   31 -
 chart2/source/view/charttypes/NetChart.hxx         |    6 
 chart2/source/view/charttypes/Splines.cxx          |  374 +++++++++++++++++++++
 chart2/source/view/charttypes/Splines.hxx          |   11 
 chart2/source/view/charttypes/VSeriesPlotter.cxx   |   10 
 chart2/source/view/inc/Clipping.hxx                |    6 
 chart2/source/view/inc/PlottingPositionHelper.hxx  |    1 
 chart2/source/view/inc/ShapeFactory.hxx            |   17 
 chart2/source/view/inc/VDataSeries.hxx             |    3 
 chart2/source/view/main/Clipping.cxx               |  124 ++++++
 chart2/source/view/main/PlottingPositionHelper.cxx |   19 +
 chart2/source/view/main/ShapeFactory.cxx           |  213 +++++++++++
 chart2/source/view/main/VDataSeries.cxx            |    4 
 22 files changed, 1052 insertions(+), 202 deletions(-)

New commits:
commit f242cc6d5be5c6f5446976fd6a7c26ad0cee7683
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Tue Jan 11 14:32:45 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Tue Jan 11 17:35:32 2022 +0100

    use vectors to build up point data, instead of Sequence
    
    which shaves 1% off the load time of a large chart
    
    Change-Id: Ieb8f029f760f41c3bef63bbc4cd221c1473f0f49
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128283
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/chart2/source/inc/BaseGFXHelper.hxx 
b/chart2/source/inc/BaseGFXHelper.hxx
index a5b66d1278f4..fd24fa2b45b6 100644
--- a/chart2/source/inc/BaseGFXHelper.hxx
+++ b/chart2/source/inc/BaseGFXHelper.hxx
@@ -38,6 +38,8 @@ namespace chart::BaseGFXHelper
 
 OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DRange getBoundVolume( const 
css::drawing::PolyPolygonShape3D& rPolyPoly );
 
+OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B3DRange getBoundVolume( const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly );
+
 OOO_DLLPUBLIC_CHARTTOOLS ::basegfx::B2IRectangle makeRectangle(
             const css::awt::Point& rPosition,
             const css::awt::Size& rSize );
diff --git a/chart2/source/inc/CommonConverters.hxx 
b/chart2/source/inc/CommonConverters.hxx
index 989e4002d148..bbe5ec92cb7b 100644
--- a/chart2/source/inc/CommonConverters.hxx
+++ b/chart2/source/inc/CommonConverters.hxx
@@ -85,9 +85,16 @@ OOO_DLLPUBLIC_CHARTTOOLS
 void AddPointToPoly( css::drawing::PolyPolygonShape3D& rPoly
                 , const css::drawing::Position3D& rPos
                 , sal_Int32 nSequenceIndex=0 );
+OOO_DLLPUBLIC_CHARTTOOLS
+void AddPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly
+                , const css::drawing::Position3D& rPos
+                , sal_Int32 nSequenceIndex=0 );
 
 /** get a single Point from a Polygon
 */
+OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly(
+                  const std::vector<std::vector<css::drawing::Position3D>>& 
rPolygon
+                , sal_Int32 nPointIndex, sal_Int32 nPolyIndex );
 OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly(
                   const css::drawing::PolyPolygonShape3D& rPolygon
                 , sal_Int32 nPointIndex, sal_Int32 nPolyIndex );
@@ -95,11 +102,14 @@ OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D 
getPointFromPoly(
 OOO_DLLPUBLIC_CHARTTOOLS
 void addPolygon( css::drawing::PolyPolygonShape3D& rRet
                 , const css::drawing::PolyPolygonShape3D& rAdd );
+OOO_DLLPUBLIC_CHARTTOOLS
+void addPolygon( std::vector<std::vector<css::drawing::Position3D>>& rRet
+                , const std::vector<std::vector<css::drawing::Position3D>>& 
rAdd );
 /** PolyPolygonShape3D + PolyPolygonShape3D -> PolyPolygonShape3D
 */
 OOO_DLLPUBLIC_CHARTTOOLS
-void appendPoly( css::drawing::PolyPolygonShape3D& rRet
-                , const css::drawing::PolyPolygonShape3D& rAdd );
+void appendPoly( std::vector<std::vector<css::drawing::Position3D>>& rRet
+                , const std::vector<std::vector<css::drawing::Position3D>>& 
rAdd );
 
 /** PolyPolygonBezierCoords -> PolyPolygonShape3D
 */
@@ -112,12 +122,18 @@ css::drawing::PolyPolygonShape3D BezierToPoly(
 OOO_DLLPUBLIC_CHARTTOOLS
 css::drawing::PointSequenceSequence PolyToPointSequence(
                 const css::drawing::PolyPolygonShape3D& rPolyPolygon );
+OOO_DLLPUBLIC_CHARTTOOLS
+css::drawing::PointSequenceSequence PolyToPointSequence(
+                const std::vector<std::vector<css::drawing::Position3D>>& 
rPolyPolygon );
 
 /** PolyPolygonShape3D ->  basegfx::B2DPolyPolygon (2D)
 */
 OOO_DLLPUBLIC_CHARTTOOLS
 basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
                 const css::drawing::PolyPolygonShape3D& rPolyPolygon );
+OOO_DLLPUBLIC_CHARTTOOLS
+basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
+                const std::vector<std::vector<css::drawing::Position3D>>& 
rPolyPolygon );
 
 /** drawing::PointSequenceSequence + drawing::PointSequenceSequence
 */
diff --git a/chart2/source/tools/BaseGFXHelper.cxx 
b/chart2/source/tools/BaseGFXHelper.cxx
index 9c475bc759d1..b518e7dd8b8c 100644
--- a/chart2/source/tools/BaseGFXHelper.cxx
+++ b/chart2/source/tools/BaseGFXHelper.cxx
@@ -60,6 +60,38 @@ namespace chart::BaseGFXHelper
     return aRet;
 }
 
+::basegfx::B3DRange getBoundVolume( const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly )
+{
+    ::basegfx::B3DRange aRet;
+
+    bool bInited = false;
+    sal_Int32 nPolyCount = rPolyPoly.size();
+    for(sal_Int32 nPoly = 0; nPoly < nPolyCount; nPoly++)
+    {
+        sal_Int32 nPointCount = rPolyPoly[nPoly].size();
+        for( sal_Int32 nPoint = 0; nPoint < nPointCount; nPoint++)
+        {
+            if(!bInited)
+            {
+                aRet = ::basegfx::B3DRange(::basegfx::B3DTuple(
+                          rPolyPoly[nPoly][nPoint].PositionX
+                        , rPolyPoly[nPoly][nPoint].PositionY
+                        , rPolyPoly[nPoly][nPoint].PositionZ));
+                bInited = true;
+            }
+            else
+            {
+                aRet.expand( ::basegfx::B3DTuple(
+                          rPolyPoly[nPoly][nPoint].PositionX
+                        , rPolyPoly[nPoly][nPoint].PositionY
+                        , rPolyPoly[nPoly][nPoint].PositionZ));
+            }
+        }
+    }
+
+    return aRet;
+}
+
 B2IRectangle makeRectangle( const awt::Point& rPos, const awt::Size& rSize )
 {
     return B2IRectangle(rPos.X,rPos.Y,rPos.X+rSize.Width,rPos.Y+rSize.Height);
diff --git a/chart2/source/tools/CommonConverters.cxx 
b/chart2/source/tools/CommonConverters.cxx
index 43069cd40ad3..0c8f8bd8665a 100644
--- a/chart2/source/tools/CommonConverters.cxx
+++ b/chart2/source/tools/CommonConverters.cxx
@@ -181,6 +181,24 @@ void AddPointToPoly( drawing::PolyPolygonShape3D& rPoly, 
const drawing::Position
     pInnerSequenceZ[nOldPointCount] = rPos.PositionZ;
 }
 
+void AddPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& 
rPoly, const drawing::Position3D& rPos, sal_Int32 nPolygonIndex )
+{
+    if(nPolygonIndex<0)
+    {
+        OSL_FAIL( "The polygon index needs to be > 0");
+        nPolygonIndex=0;
+    }
+
+    //make sure that we have enough polygons
+    if(nPolygonIndex >= static_cast<sal_Int32>(rPoly.size()) )
+    {
+        rPoly.resize(nPolygonIndex+1);
+    }
+
+    std::vector<css::drawing::Position3D>* pOuterSequence = 
&rPoly[nPolygonIndex];
+    pOuterSequence->push_back(rPos);
+}
+
 drawing::Position3D getPointFromPoly( const drawing::PolyPolygonShape3D& 
rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex )
 {
     drawing::Position3D aRet(0.0,0.0,0.0);
@@ -205,6 +223,28 @@ drawing::Position3D getPointFromPoly( const 
drawing::PolyPolygonShape3D& rPolygo
     return aRet;
 }
 
+drawing::Position3D getPointFromPoly( const 
std::vector<std::vector<css::drawing::Position3D>>& rPolygon, sal_Int32 
nPointIndex, sal_Int32 nPolyIndex )
+{
+    drawing::Position3D aRet(0.0,0.0,0.0);
+
+    if( nPolyIndex>=0 && nPolyIndex<static_cast<sal_Int32>(rPolygon.size()))
+    {
+        if(nPointIndex<static_cast<sal_Int32>(rPolygon[nPolyIndex].size()))
+        {
+            aRet = rPolygon[nPolyIndex][nPointIndex];
+        }
+        else
+        {
+            OSL_FAIL("polygon was accessed with a wrong index");
+        }
+    }
+    else
+    {
+        OSL_FAIL("polygon was accessed with a wrong index");
+    }
+    return aRet;
+}
+
 void addPolygon( drawing::PolyPolygonShape3D& rRet, const 
drawing::PolyPolygonShape3D& rAdd )
 {
     sal_Int32 nAddOuterCount = rAdd.SequenceX.getLength();
@@ -231,41 +271,51 @@ void addPolygon( drawing::PolyPolygonShape3D& rRet, const 
drawing::PolyPolygonSh
     }
 }
 
-void appendPoly( drawing::PolyPolygonShape3D& rRet, const 
drawing::PolyPolygonShape3D& rAdd )
+void addPolygon( std::vector<std::vector<css::drawing::Position3D>>& rRet, 
const std::vector<std::vector<css::drawing::Position3D>>& rAdd )
 {
-    sal_Int32 nOuterCount = std::max( rRet.SequenceX.getLength(), 
rAdd.SequenceX.getLength() );
-    rRet.SequenceX.realloc(nOuterCount);
-    auto pSequenceX = rRet.SequenceX.getArray();
-    rRet.SequenceY.realloc(nOuterCount);
-    auto pSequenceY = rRet.SequenceY.getArray();
-    rRet.SequenceZ.realloc(nOuterCount);
-    auto pSequenceZ =rRet.SequenceZ.getArray();
+    sal_Int32 nAddOuterCount = rAdd.size();
+    sal_Int32 nOuterCount = rRet.size() + nAddOuterCount;
+    rRet.resize( nOuterCount );
+    auto pSequence = rRet.data();
+
+    sal_Int32 nIndex = 0;
+    sal_Int32 nOuter = nOuterCount - nAddOuterCount;
+    for( ; nOuter < nOuterCount; nOuter++ )
+    {
+        if( nIndex >= nAddOuterCount )
+            break;
+
+        pSequence[nOuter] = rAdd[nIndex];
+
+        nIndex++;
+    }
+}
+
+void appendPoly( std::vector<std::vector<css::drawing::Position3D>>& rRet, 
const std::vector<std::vector<css::drawing::Position3D>>& rAdd )
+{
+    sal_Int32 nOuterCount = std::max( rRet.size(), rAdd.size() );
+    rRet.resize(nOuterCount);
+    auto pSequence = rRet.data();
 
     for( sal_Int32 nOuter=0;nOuter<nOuterCount;nOuter++ )
     {
-        sal_Int32 nOldPointCount = rRet.SequenceX[nOuter].getLength();
+        sal_Int32 nOldPointCount = rRet[nOuter].size();
         sal_Int32 nAddPointCount = 0;
-        if(nOuter<rAdd.SequenceX.getLength())
-            nAddPointCount = rAdd.SequenceX[nOuter].getLength();
+        if(nOuter<static_cast<sal_Int32>(rAdd.size()))
+            nAddPointCount = rAdd[nOuter].size();
         if(!nAddPointCount)
             continue;
 
         sal_Int32 nNewPointCount = nOldPointCount + nAddPointCount;
 
-        pSequenceX[nOuter].realloc(nNewPointCount);
-        auto pSequenceX_nOuter = pSequenceX[nOuter].getArray();
-        pSequenceY[nOuter].realloc(nNewPointCount);
-        auto pSequenceY_nOuter = pSequenceY[nOuter].getArray();
-        pSequenceZ[nOuter].realloc(nNewPointCount);
-        auto pSequenceZ_nOuter = pSequenceZ[nOuter].getArray();
+        pSequence[nOuter].resize(nNewPointCount);
+        auto pSequence_nOuter = pSequence[nOuter].data();
 
         sal_Int32 nPointTarget=nOldPointCount;
         sal_Int32 nPointSource=nAddPointCount;
         for( ; nPointSource-- ; nPointTarget++ )
         {
-            pSequenceX_nOuter[nPointTarget] = 
rAdd.SequenceX[nOuter][nPointSource];
-            pSequenceY_nOuter[nPointTarget] = 
rAdd.SequenceY[nOuter][nPointSource];
-            pSequenceZ_nOuter[nPointTarget] = 
rAdd.SequenceZ[nOuter][nPointSource];
+            pSequence_nOuter[nPointTarget] = rAdd[nOuter][nPointSource];
         }
     }
 }
@@ -346,6 +396,27 @@ drawing::PointSequenceSequence PolyToPointSequence(
     return aRet;
 }
 
+drawing::PointSequenceSequence PolyToPointSequence(
+                const std::vector<std::vector<css::drawing::Position3D>>& 
rPolyPolygon )
+{
+    drawing::PointSequenceSequence aRet;
+    aRet.realloc( rPolyPolygon.size() );
+    auto pRet = aRet.getArray();
+
+    for(sal_Int32 nN = 0; nN < static_cast<sal_Int32>(rPolyPolygon.size()); 
nN++)
+    {
+        sal_Int32 nInnerLength = rPolyPolygon[nN].size();
+        pRet[nN].realloc( nInnerLength );
+        auto pRet_nN = pRet[nN].getArray();
+        for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+        {
+            pRet_nN[nM].X = 
static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionX);
+            pRet_nN[nM].Y = 
static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionY);
+        }
+    }
+    return aRet;
+}
+
 basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
                 const drawing::PolyPolygonShape3D& rPolyPolygon )
 {
@@ -373,6 +444,33 @@ basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
     return aRetval;
 }
 
+basegfx::B2DPolyPolygon PolyToB2DPolyPolygon(
+                const std::vector<std::vector<css::drawing::Position3D>>& 
rPolyPolygon )
+{
+    basegfx::B2DPolyPolygon aRetval;
+
+    for(sal_Int32 nN = 0; nN < static_cast<sal_Int32>(rPolyPolygon.size()); 
nN++)
+    {
+        basegfx::B2DPolygon aNewPolygon;
+        sal_Int32 nInnerLength = rPolyPolygon[nN].size();
+        if(nInnerLength)
+        {
+            aNewPolygon.reserve(nInnerLength);
+            for( sal_Int32 nM = 0; nM < nInnerLength; nM++)
+            {
+                auto X = 
static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionX);
+                auto Y = 
static_cast<sal_Int32>(rPolyPolygon[nN][nM].PositionY);
+                aNewPolygon.append(basegfx::B2DPoint(X, Y));
+            }
+            // check for closed state flag
+            basegfx::utils::checkClosed(aNewPolygon);
+        }
+        aRetval.append(std::move(aNewPolygon));
+    }
+
+    return aRetval;
+}
+
 void appendPointSequence( drawing::PointSequenceSequence& rTarget
                         , drawing::PointSequenceSequence& rAdd )
 {
diff --git a/chart2/source/view/axes/VCartesianGrid.cxx 
b/chart2/source/view/axes/VCartesianGrid.cxx
index 93ebb6eb3e78..283703ba5984 100644
--- a/chart2/source/view/axes/VCartesianGrid.cxx
+++ b/chart2/source/view/axes/VCartesianGrid.cxx
@@ -149,7 +149,7 @@ static void addLine2D( drawing::PointSequenceSequence& 
rPoints, sal_Int32 nIndex
             { static_cast<sal_Int32>(aPB.PositionX), 
static_cast<sal_Int32>(aPB.PositionY) } };
 }
 
-static void addLine3D( drawing::PolyPolygonShape3D& rPoints, sal_Int32 nIndex
+static void addLine3D( std::vector<std::vector<css::drawing::Position3D>>& 
rPoints, sal_Int32 nIndex
             , const GridLinePoints& rBasePoints
             , const Reference< XTransformation > & xTransformation )
 {
@@ -281,10 +281,8 @@ void VCartesianGrid::createShapes()
             GridLinePoints aGridLinePoints( m_pPosHelper, m_nDimensionIndex, 
m_eLeftWallPos, m_eBackWallPos, m_eBottomPos );
 
             sal_Int32 nPointCount = (*aDepthIter).size();
-            drawing::PolyPolygonShape3D aPoints;
-            aPoints.SequenceX.realloc(nPointCount);
-            aPoints.SequenceY.realloc(nPointCount);
-            aPoints.SequenceZ.realloc(nPointCount);
+            std::vector<std::vector<css::drawing::Position3D>> aPoints;
+            aPoints.resize(nPointCount);
 
             sal_Int32 nRealPointCount = 0;
             sal_Int32 nPolyIndex = 0;
@@ -301,9 +299,7 @@ void VCartesianGrid::createShapes()
                 nRealPointCount+=3;
                 ++nPolyIndex;
             }
-            aPoints.SequenceX.realloc(nRealPointCount);
-            aPoints.SequenceY.realloc(nRealPointCount);
-            aPoints.SequenceZ.realloc(nRealPointCount);
+            aPoints.resize(nRealPointCount);
             ShapeFactory::createLine3D( xTarget, aPoints, 
aLinePropertiesList[nDepth] );
         }
     }
diff --git a/chart2/source/view/charttypes/AreaChart.cxx 
b/chart2/source/view/charttypes/AreaChart.cxx
index e4864cca63f7..e5409ce5dff1 100644
--- a/chart2/source/view/charttypes/AreaChart.cxx
+++ b/chart2/source/view/charttypes/AreaChart.cxx
@@ -154,126 +154,95 @@ void AreaChart::addSeries( std::unique_ptr<VDataSeries> 
pSeries, sal_Int32 zSlot
     VSeriesPlotter::addSeries( std::move(pSeries), zSlot, xSlot, ySlot );
 }
 
-static void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, 
PlottingPositionHelper& rPosHelper )
+static void lcl_removeDuplicatePoints( 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPoly, 
PlottingPositionHelper& rPosHelper )
 {
-    sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength();
+    sal_Int32 nPolyCount = rPolyPoly.size();
     if(!nPolyCount)
         return;
 
-    drawing::PolyPolygonShape3D aTmp;
-    aTmp.SequenceX.realloc(nPolyCount);
-    aTmp.SequenceY.realloc(nPolyCount);
-    aTmp.SequenceZ.realloc(nPolyCount);
+    // TODO we could do with without a temporary array
+    std::vector<std::vector<css::drawing::Position3D>> aTmp;
+    aTmp.resize(nPolyCount);
 
     for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; 
nPolygonIndex++ )
     {
-        drawing::DoubleSequence* pOuterSourceX = 
&rPolyPoly.SequenceX.getArray()[nPolygonIndex];
-        drawing::DoubleSequence* pOuterSourceY = 
&rPolyPoly.SequenceY.getArray()[nPolygonIndex];
-        drawing::DoubleSequence* pOuterSourceZ = 
&rPolyPoly.SequenceZ.getArray()[nPolygonIndex];
+        std::vector<css::drawing::Position3D>* pOuterSource = 
&rPolyPoly[nPolygonIndex];
+        std::vector<css::drawing::Position3D>* pOuterTarget = 
&aTmp[nPolygonIndex];
 
-        drawing::DoubleSequence* pOuterTargetX = 
&aTmp.SequenceX.getArray()[nPolygonIndex];
-        drawing::DoubleSequence* pOuterTargetY = 
&aTmp.SequenceY.getArray()[nPolygonIndex];
-        drawing::DoubleSequence* pOuterTargetZ = 
&aTmp.SequenceZ.getArray()[nPolygonIndex];
-
-        sal_Int32 nPointCount = pOuterSourceX->getLength();
+        sal_Int32 nPointCount = pOuterSource->size();
         if( !nPointCount )
             continue;
 
-        pOuterTargetX->realloc(nPointCount);
-        pOuterTargetY->realloc(nPointCount);
-        pOuterTargetZ->realloc(nPointCount);
-
-        double* pSourceX = pOuterSourceX->getArray();
-        double* pSourceY = pOuterSourceY->getArray();
-        double* pSourceZ = pOuterSourceZ->getArray();
+        pOuterTarget->resize(nPointCount);
 
-        double* pTargetX = pOuterTargetX->getArray();
-        double* pTargetY = pOuterTargetY->getArray();
-        double* pTargetZ = pOuterTargetZ->getArray();
+        css::drawing::Position3D* pSource = pOuterSource->data();
+        css::drawing::Position3D* pTarget = pOuterTarget->data();
 
         //copy first point
-        *pTargetX=*pSourceX++;
-        *pTargetY=*pSourceY++;
-        *pTargetZ=*pSourceZ++;
+        *pTarget=*pSource++;
         sal_Int32 nTargetPointCount=1;
 
         for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ )
         {
-            if( !rPosHelper.isSameForGivenResolution( *pTargetX, *pTargetY, 
*pTargetZ
-                                                   , *pSourceX, *pSourceY, 
*pSourceZ ) )
+            if( !rPosHelper.isSameForGivenResolution( pTarget->PositionX, 
pTarget->PositionY, pTarget->PositionZ
+                                                   , pSource->PositionX, 
pSource->PositionY, pSource->PositionZ ) )
             {
-                pTargetX++; pTargetY++; pTargetZ++;
-                *pTargetX=*pSourceX;
-                *pTargetY=*pSourceY;
-                *pTargetZ=*pSourceZ;
+                pTarget++;
+                *pTarget=*pSource;
                 nTargetPointCount++;
             }
-            pSourceX++; pSourceY++; pSourceZ++;
+            pSource++;
         }
 
         //free unused space
         if( nTargetPointCount<nPointCount )
         {
-            pOuterTargetX->realloc(nTargetPointCount);
-            pOuterTargetY->realloc(nTargetPointCount);
-            pOuterTargetZ->realloc(nTargetPointCount);
+            pOuterTarget->resize(nTargetPointCount);
         }
 
-        pOuterSourceX->realloc(0);
-        pOuterSourceY->realloc(0);
-        pOuterSourceZ->realloc(0);
+        pOuterSource->clear();
     }
 
     //free space
-    rPolyPoly.SequenceX.realloc(nPolyCount);
-    rPolyPoly.SequenceY.realloc(nPolyCount);
-    rPolyPoly.SequenceZ.realloc(nPolyCount);
+    rPolyPoly.resize(nPolyCount);
 
-    rPolyPoly=aTmp;
+    rPolyPoly = std::move(aTmp);
 }
 
-bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, 
chart2::CurveStyle eCurveStyle, PlottingPositionHelper const * pPosHelper, 
drawing::PolyPolygonShape3D &aPoly )
+bool AreaChart::create_stepped_line(
+        std::vector<std::vector<css::drawing::Position3D>> aStartPoly,
+        chart2::CurveStyle eCurveStyle,
+        PlottingPositionHelper const * pPosHelper,
+        std::vector<std::vector<css::drawing::Position3D>> &aPoly )
 {
-    sal_uInt32 nOuterCount = aStartPoly.SequenceX.getLength();
+    sal_uInt32 nOuterCount = aStartPoly.size();
     if ( !nOuterCount )
         return false;
 
-    drawing::PolyPolygonShape3D aSteppedPoly;
-    aSteppedPoly.SequenceX.realloc(nOuterCount);
-    aSteppedPoly.SequenceY.realloc(nOuterCount);
-    aSteppedPoly.SequenceZ.realloc(nOuterCount);
+    std::vector<std::vector<css::drawing::Position3D>> aSteppedPoly;
+    aSteppedPoly.resize(nOuterCount);
 
-    auto pSequenceX = aSteppedPoly.SequenceX.getArray();
-    auto pSequenceY = aSteppedPoly.SequenceY.getArray();
-    auto pSequenceZ = aSteppedPoly.SequenceZ.getArray();
+    auto pSequence = aSteppedPoly.data();
 
     for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
     {
-        if( aStartPoly.SequenceX[nOuter].getLength() <= 1 )
+        if( aStartPoly[nOuter].size() <= 1 )
             continue; //we need at least two points
 
-        sal_uInt32 nMaxIndexPoints = 
aStartPoly.SequenceX[nOuter].getLength()-1; // is >1
+        sal_uInt32 nMaxIndexPoints = aStartPoly[nOuter].size()-1; // is >1
         sal_uInt32 nNewIndexPoints = 0;
         if ( eCurveStyle==CurveStyle_STEP_START || 
eCurveStyle==CurveStyle_STEP_END)
             nNewIndexPoints = nMaxIndexPoints * 2 + 1;
         else
             nNewIndexPoints = nMaxIndexPoints * 3 + 1;
 
-        const double* pOldX = aStartPoly.SequenceX[nOuter].getConstArray();
-        const double* pOldY = aStartPoly.SequenceY[nOuter].getConstArray();
-        const double* pOldZ = aStartPoly.SequenceZ[nOuter].getConstArray();
+        const css::drawing::Position3D* pOld = aStartPoly[nOuter].data();
 
-        pSequenceX[nOuter].realloc( nNewIndexPoints );
-        pSequenceY[nOuter].realloc( nNewIndexPoints );
-        pSequenceZ[nOuter].realloc( nNewIndexPoints );
+        pSequence[nOuter].resize( nNewIndexPoints );
 
-        double* pNewX = pSequenceX[nOuter].getArray();
-        double* pNewY = pSequenceY[nOuter].getArray();
-        double* pNewZ = pSequenceZ[nOuter].getArray();
+        css::drawing::Position3D* pNew = pSequence[nOuter].data();
 
-        pNewX[0] = pOldX[0];
-        pNewY[0] = pOldY[0];
-        pNewZ[0] = pOldZ[0];
+        pNew[0] = pOld[0];
         for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ )
         {
             switch ( eCurveStyle )
@@ -286,13 +255,11 @@ bool AreaChart::create_stepped_line( 
drawing::PolyPolygonShape3D aStartPoly, cha
                              O-----+
                      */
                     // create the intermediate point
-                    pNewX[1+oi*2] = pOldX[oi+1];
-                    pNewY[1+oi*2] = pOldY[oi];
-                    pNewZ[1+oi*2] = pOldZ[oi];
+                    pNew[1+oi*2].PositionX = pOld[oi+1].PositionX;
+                    pNew[1+oi*2].PositionY = pOld[oi].PositionY;
+                    pNew[1+oi*2].PositionZ = pOld[oi].PositionZ;
                     // and now the normal one
-                    pNewX[1+oi*2+1] = pOldX[oi+1];
-                    pNewY[1+oi*2+1] = pOldY[oi+1];
-                    pNewZ[1+oi*2+1] = pOldZ[oi+1];
+                    pNew[1+oi*2+1] = pOld[oi+1];
                     break;
                 case CurveStyle_STEP_END:
                      /**    +------O
@@ -302,13 +269,11 @@ bool AreaChart::create_stepped_line( 
drawing::PolyPolygonShape3D aStartPoly, cha
                             O
                      */
                     // create the intermediate point
-                    pNewX[1+oi*2] = pOldX[oi];
-                    pNewY[1+oi*2] = pOldY[oi+1];
-                    pNewZ[1+oi*2] = pOldZ[oi];
+                    pNew[1+oi*2].PositionX = pOld[oi].PositionX;
+                    pNew[1+oi*2].PositionY = pOld[oi+1].PositionY;
+                    pNew[1+oi*2].PositionZ = pOld[oi].PositionZ;
                     // and now the normal one
-                    pNewX[1+oi*2+1] = pOldX[oi+1];
-                    pNewY[1+oi*2+1] = pOldY[oi+1];
-                    pNewZ[1+oi*2+1] = pOldZ[oi+1];
+                    pNew[1+oi*2+1] = pOld[oi+1];
                     break;
                 case CurveStyle_STEP_CENTER_X:
                      /**        +--O
@@ -318,17 +283,15 @@ bool AreaChart::create_stepped_line( 
drawing::PolyPolygonShape3D aStartPoly, cha
                              O--+
                      */
                     // create the first intermediate point
-                    pNewX[1+oi*3] = (pOldX[oi]+pOldX[oi+1])/2;
-                    pNewY[1+oi*3] = pOldY[oi];
-                    pNewZ[1+oi*3] = pOldZ[oi];
+                    pNew[1+oi*3].PositionX = (pOld[oi].PositionX + 
pOld[oi+1].PositionX) / 2;
+                    pNew[1+oi*3].PositionY = pOld[oi].PositionY;
+                    pNew[1+oi*3].PositionZ = pOld[oi].PositionZ;
                     // create the second intermediate point
-                    pNewX[1+oi*3+1] = (pOldX[oi]+pOldX[oi+1])/2;
-                    pNewY[1+oi*3+1] = pOldY[oi+1];
-                    pNewZ[1+oi*3+1] = pOldZ[oi];
+                    pNew[1+oi*3+1].PositionX = (pOld[oi].PositionX + 
pOld[oi+1].PositionX) / 2;
+                    pNew[1+oi*3+1].PositionY = pOld[oi+1].PositionY;
+                    pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ;
                     // and now the normal one
-                    pNewX[1+oi*3+2] = pOldX[oi+1];
-                    pNewY[1+oi*3+2] = pOldY[oi+1];
-                    pNewZ[1+oi*3+2] = pOldZ[oi+1];
+                    pNew[1+oi*3+2] = pOld[oi+1];
                     break;
                 case CurveStyle_STEP_CENTER_Y:
                      /**           O
@@ -338,17 +301,15 @@ bool AreaChart::create_stepped_line( 
drawing::PolyPolygonShape3D aStartPoly, cha
                              O
                      */
                     // create the first intermediate point
-                    pNewX[1+oi*3] = pOldX[oi];
-                    pNewY[1+oi*3] = (pOldY[oi]+pOldY[oi+1])/2;
-                    pNewZ[1+oi*3] = pOldZ[oi];
+                    pNew[1+oi*3].PositionX = pOld[oi].PositionX;
+                    pNew[1+oi*3].PositionY = (pOld[oi].PositionY + 
pOld[oi+1].PositionY) / 2;
+                    pNew[1+oi*3].PositionZ = pOld[oi].PositionZ;
                     // create the second intermediate point
-                    pNewX[1+oi*3+1] = pOldX[oi+1];
-                    pNewY[1+oi*3+1] = (pOldY[oi]+pOldY[oi+1])/2;
-                    pNewZ[1+oi*3+1] = pOldZ[oi];
+                    pNew[1+oi*3+1].PositionX = pOld[oi+1].PositionX;
+                    pNew[1+oi*3+1].PositionY = (pOld[oi].PositionY + 
pOld[oi+1].PositionY) / 2;
+                    pNew[1+oi*3+1].PositionZ = pOld[oi].PositionZ;
                     // and now the normal one
-                    pNewX[1+oi*3+2] = pOldX[oi+1];
-                    pNewY[1+oi*3+2] = pOldY[oi+1];
-                    pNewZ[1+oi*3+2] = pOldZ[oi+1];
+                    pNew[1+oi*3+2] = pOld[oi+1];
                     break;
                 default:
                     // this should never be executed
@@ -362,23 +323,23 @@ bool AreaChart::create_stepped_line( 
drawing::PolyPolygonShape3D aStartPoly, cha
 }
 
 bool AreaChart::impl_createLine( VDataSeries* pSeries
-                , drawing::PolyPolygonShape3D const * pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pSeriesPoly
                 , PlottingPositionHelper* pPosHelper )
 {
     //return true if a line was created successfully
     rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = 
getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
 
-    drawing::PolyPolygonShape3D aPoly;
+    std::vector<std::vector<css::drawing::Position3D>> aPoly;
     if(m_eCurveStyle==CurveStyle_CUBIC_SPLINES)
     {
-        drawing::PolyPolygonShape3D aSplinePoly;
+        std::vector<std::vector<css::drawing::Position3D>> aSplinePoly;
         SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, 
m_nCurveResolution );
         lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
         Clipping::clipPolygonAtRectangle( aSplinePoly, 
pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
     }
     else if(m_eCurveStyle==CurveStyle_B_SPLINES)
     {
-        drawing::PolyPolygonShape3D aSplinePoly;
+        std::vector<std::vector<css::drawing::Position3D>> aSplinePoly;
         SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, 
m_nCurveResolution, m_nSplineOrder );
         lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
         Clipping::clipPolygonAtRectangle( aSplinePoly, 
pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
@@ -411,20 +372,15 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries
     if(m_nDimension==3)
     {
         double fDepth = getTransformedDepth();
-        sal_Int32 nPolyCount = aPoly.SequenceX.getLength();
+        sal_Int32 nPolyCount = aPoly.size();
         for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++)
         {
-            sal_Int32 nPointCount = aPoly.SequenceX[nPoly].getLength();
+            sal_Int32 nPointCount = aPoly[nPoly].size();
             for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++)
             {
                 drawing::Position3D aPoint1, aPoint2;
-                aPoint1.PositionX = aPoly.SequenceX[nPoly][nPoint+1];
-                aPoint1.PositionY = aPoly.SequenceY[nPoly][nPoint+1];
-                aPoint1.PositionZ = aPoly.SequenceZ[nPoly][nPoint+1];
-
-                aPoint2.PositionX = aPoly.SequenceX[nPoly][nPoint];
-                aPoint2.PositionY = aPoly.SequenceY[nPoly][nPoint];
-                aPoint2.PositionZ = aPoly.SequenceZ[nPoly][nPoint];
+                aPoint1 = aPoly[nPoly][nPoint+1];
+                aPoint2 = aPoly[nPoly][nPoint];
 
                 ShapeFactory::createStripe(xSeriesGroupShape_Shapes
                     , Stripe( aPoint1, aPoint2, fDepth )
@@ -434,8 +390,7 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries
     }
     else //m_nDimension!=3
     {
-        xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes
-                , PolyToPointSequence( aPoly ) );
+        xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly );
         PropertyMapper::setMappedProperties( *xShape
                 , pSeries->getPropertiesOfSeries()
                 , PropertyMapper::getPropertyNameMapForLineSeriesProperties() 
);
@@ -446,8 +401,8 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries
 }
 
 bool AreaChart::impl_createArea( VDataSeries* pSeries
-                , drawing::PolyPolygonShape3D const * pSeriesPoly
-                , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pPreviousSeriesPoly
                 , PlottingPositionHelper const * pPosHelper )
 {
     //return true if an area was created successfully
@@ -455,7 +410,7 @@ bool AreaChart::impl_createArea( VDataSeries* pSeries
     rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = 
getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
     double zValue = pSeries->m_fLogicZPos;
 
-    drawing::PolyPolygonShape3D aPoly( *pSeriesPoly );
+    std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly );
     //add second part to the polygon (grounding points or previous series 
points)
     if(!pPreviousSeriesPoly)
     {
@@ -488,7 +443,7 @@ bool AreaChart::impl_createArea( VDataSeries* pSeries
 
     //apply clipping
     {
-        drawing::PolyPolygonShape3D aClippedPoly;
+        std::vector<std::vector<css::drawing::Position3D>> aClippedPoly;
         Clipping::clipPolygonAtRectangle( aPoly, 
pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
         ShapeFactory::closePolygon(aClippedPoly); //again necessary after 
clipping
         aPoly = aClippedPoly;
@@ -533,8 +488,8 @@ void AreaChart::impl_createSeriesShapes()
     {
         for( auto const& rXSlot : rZSlot )
         {
-            std::map< sal_Int32, drawing::PolyPolygonShape3D* > 
aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different 
nAttachedAxisIndex
-            drawing::PolyPolygonShape3D* pSeriesPoly = nullptr;
+            std::map< sal_Int32, 
std::vector<std::vector<css::drawing::Position3D>>* > 
aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different 
nAttachedAxisIndex
+            std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = 
nullptr;
 
             //iterate through all series
             for( std::unique_ptr<VDataSeries> const & pSeries : 
rXSlot.m_aSeriesVector )
@@ -746,11 +701,11 @@ void AreaChart::createShapes()
                     {
                         if( pSeries->getMissingValueTreatment() == 
css::chart::MissingValueTreatment::LEAVE_GAP )
                         {
-                            drawing::PolyPolygonShape3D& rPolygon = 
pSeries->m_aPolyPolygonShape3D;
+                            
std::vector<std::vector<css::drawing::Position3D>>& rPolygon = 
pSeries->m_aPolyPolygonShape3D;
                             sal_Int32& rIndex = pSeries->m_nPolygonIndex;
-                            if( 0<= rIndex && rIndex < 
rPolygon.SequenceX.getLength() )
+                            if( 0<= rIndex && rIndex < 
static_cast<sal_Int32>(rPolygon.size()) )
                             {
-                                if( rPolygon.SequenceX[ rIndex ].hasElements() 
)
+                                if( !rPolygon[ rIndex ].empty() )
                                     rIndex++; //start a new polygon for the 
next point if the current poly is not empty
                             }
                         }
diff --git a/chart2/source/view/charttypes/AreaChart.hxx 
b/chart2/source/view/charttypes/AreaChart.hxx
index ce7bd7d2f965..23d8adb0b4f1 100644
--- a/chart2/source/view/charttypes/AreaChart.hxx
+++ b/chart2/source/view/charttypes/AreaChart.hxx
@@ -52,16 +52,16 @@ public:
 private: //methods
     void impl_createSeriesShapes();
     bool impl_createArea( VDataSeries* pSeries
-                , css::drawing::PolyPolygonShape3D const * pSeriesPoly
-                , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pPreviousSeriesPoly
                 , PlottingPositionHelper const * pPosHelper );
     bool impl_createLine( VDataSeries* pSeries
-                , css::drawing::PolyPolygonShape3D const * pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pSeriesPoly
                 , PlottingPositionHelper* pPosHelper );
-    static bool create_stepped_line( css::drawing::PolyPolygonShape3D 
aStartPoly
+    static bool create_stepped_line( 
std::vector<std::vector<css::drawing::Position3D>> aStartPoly
                 , css::chart2::CurveStyle eCurveStyle
                 , PlottingPositionHelper const * pPosHelper
-                , css::drawing::PolyPolygonShape3D &aPoly );
+                , std::vector<std::vector<css::drawing::Position3D>> &aPoly );
 
 private: //member
     std::unique_ptr<PlottingPositionHelper>
diff --git a/chart2/source/view/charttypes/BarChart.cxx 
b/chart2/source/view/charttypes/BarChart.cxx
index 3709476daae0..efcf1dd13831 100644
--- a/chart2/source/view/charttypes/BarChart.cxx
+++ b/chart2/source/view/charttypes/BarChart.cxx
@@ -850,10 +850,8 @@ void BarChart::createShapes()
                             {
                                 // performance improvement: alloc the sequence 
before the rendering
                                 // otherwise we have 2 realloc calls
-                                drawing::PolyPolygonShape3D aPoly;
-                                aPoly.SequenceX.realloc(1);
-                                aPoly.SequenceY.realloc(1);
-                                aPoly.SequenceZ.realloc(1);
+                                
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 );
 
@@ -949,11 +947,11 @@ void BarChart::createShapes()
                 {
                     if(!pSeries)
                         continue;
-                    drawing::PolyPolygonShape3D* pSeriesPoly = 
&pSeries->m_aPolyPolygonShape3D;
+                    std::vector<std::vector<css::drawing::Position3D>>* 
pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
                     if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly))
                         continue;
 
-                    drawing::PolyPolygonShape3D aPoly;
+                    std::vector<std::vector<css::drawing::Position3D>> aPoly;
                     Clipping::clipPolygonAtRectangle( *pSeriesPoly, 
pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
 
                     if(!ShapeFactory::hasPolygonAnyLines(aPoly))
@@ -965,7 +963,7 @@ void BarChart::createShapes()
                     rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes(
                         getSeriesGroupShape(pSeries.get(), xSeriesTarget) );
                     rtl::Reference<SvxShapePolyPolygon> xShape( 
ShapeFactory::createLine2D(
-                        xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) 
) );
+                        xSeriesGroupShape_Shapes, aPoly ) );
                     PropertyMapper::setMappedProperties( *xShape, 
pSeries->getPropertiesOfSeries()
                         , 
PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
                 }
diff --git a/chart2/source/view/charttypes/CandleStickChart.cxx 
b/chart2/source/view/charttypes/CandleStickChart.cxx
index 3138c5611c5d..2b636d3d83c3 100644
--- a/chart2/source/view/charttypes/CandleStickChart.cxx
+++ b/chart2/source/view/charttypes/CandleStickChart.cxx
@@ -216,14 +216,13 @@ void CandleStickChart::createShapes()
                     //create min-max line
                     if( isValidPosition(aPosMiddleMinimum) && 
isValidPosition(aPosMiddleMaximum) )
                     {
-                        drawing::PolyPolygonShape3D aPoly;
+                        std::vector<std::vector<css::drawing::Position3D>> 
aPoly;
                         sal_Int32 nLineIndex =0;
                         AddPointToPoly( aPoly, aPosMiddleMinimum, nLineIndex);
                         AddPointToPoly( aPoly, aPosMiddleMaximum, nLineIndex);
 
                         rtl::Reference<SvxShapePolyPolygon> xShape =
-                            ShapeFactory::createLine2D( 
xPointGroupShape_Shapes,
-                                    PolyToPointSequence(aPoly));
+                            ShapeFactory::createLine2D( 
xPointGroupShape_Shapes, aPoly);
                         PropertyMapper::setMappedProperties( *xShape, 
xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
                     }
 
@@ -251,7 +250,7 @@ void CandleStickChart::createShapes()
                     }
                     else
                     {
-                        drawing::PolyPolygonShape3D aPoly;
+                        std::vector<std::vector<css::drawing::Position3D>> 
aPoly;
 
                         sal_Int32 nLineIndex = 0;
                         if( bShowFirst &&  pPosHelper->isLogicVisible( 
fUnscaledX, fUnscaledY_First ,fLogicZ )
@@ -267,11 +266,10 @@ void CandleStickChart::createShapes()
                             AddPointToPoly( aPoly, aPosRightLast, nLineIndex );
                         }
 
-                        if( aPoly.SequenceX.hasElements() )
+                        if( !aPoly.empty() )
                         {
                             rtl::Reference<SvxShapePolyPolygon> xShape =
-                                ShapeFactory::createLine2D( 
xPointGroupShape_Shapes,
-                                        PolyToPointSequence(aPoly) );
+                                ShapeFactory::createLine2D( 
xPointGroupShape_Shapes, aPoly );
                             PropertyMapper::setMappedProperties( *xShape, 
xPointProp, PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
                         }
                     }
diff --git a/chart2/source/view/charttypes/NetChart.cxx 
b/chart2/source/view/charttypes/NetChart.cxx
index cd1b6eea193d..5507e30e0579 100644
--- a/chart2/source/view/charttypes/NetChart.cxx
+++ b/chart2/source/view/charttypes/NetChart.cxx
@@ -111,13 +111,13 @@ drawing::Direction3D 
NetChart::getPreferredDiagramAspectRatio() const
 }
 
 bool NetChart::impl_createLine( VDataSeries* pSeries
-                , drawing::PolyPolygonShape3D* pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>>* 
pSeriesPoly
                 , PlottingPositionHelper const * pPosHelper )
 {
     //return true if a line was created successfully
     rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = 
getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
 
-    drawing::PolyPolygonShape3D aPoly;
+    std::vector<std::vector<css::drawing::Position3D>> aPoly;
     {
         bool bIsClipped = false;
         if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
@@ -130,10 +130,10 @@ bool NetChart::impl_createLine( VDataSeries* pSeries
             {
                 // connect last point in last polygon with first point in 
first polygon
                 ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( 
pPosHelper->getScaledLogicClipDoubleRect() );
-                drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly);
-                drawing::Position3D 
aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]);
+                std::vector<std::vector<css::drawing::Position3D>> 
aTmpPoly(*pSeriesPoly);
+                drawing::Position3D 
aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly[0][0].PositionY,aTmpPoly[0][0].PositionZ);
                 // add connector line to last polygon
-                AddPointToPoly( aTmpPoly, aLast, 
pSeriesPoly->SequenceX.getLength() - 1 );
+                AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->size() - 1 );
                 Clipping::clipPolygonAtRectangle( aTmpPoly, 
aScaledLogicClipDoubleRect, aPoly );
                 bIsClipped = true;
             }
@@ -152,8 +152,7 @@ bool NetChart::impl_createLine( VDataSeries* pSeries
     //create line:
     rtl::Reference<SvxShapePolyPolygon> xShape;
     {
-        xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes
-                , PolyToPointSequence( aPoly ) );
+        xShape = ShapeFactory::createLine2D( xSeriesGroupShape_Shapes, aPoly );
         PropertyMapper::setMappedProperties( *xShape
                 , pSeries->getPropertiesOfSeries()
                 , PropertyMapper::getPropertyNameMapForLineSeriesProperties() 
);
@@ -164,8 +163,8 @@ bool NetChart::impl_createLine( VDataSeries* pSeries
 }
 
 bool NetChart::impl_createArea( VDataSeries* pSeries
-                , drawing::PolyPolygonShape3D* pSeriesPoly
-                , drawing::PolyPolygonShape3D const * pPreviousSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>>* 
pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pPreviousSeriesPoly
                 , PlottingPositionHelper const * pPosHelper )
 {
     //return true if an area was created successfully
@@ -173,7 +172,7 @@ bool NetChart::impl_createArea( VDataSeries* pSeries
     rtl::Reference<SvxShapeGroupAnyD> xSeriesGroupShape_Shapes = 
getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
     double zValue = pSeries->m_fLogicZPos;
 
-    drawing::PolyPolygonShape3D aPoly( *pSeriesPoly );
+    std::vector<std::vector<css::drawing::Position3D>> aPoly( *pSeriesPoly );
     //add second part to the polygon (grounding points or previous series 
points)
     if( !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
     {
@@ -209,7 +208,7 @@ bool NetChart::impl_createArea( VDataSeries* pSeries
 
     //apply clipping
     {
-        drawing::PolyPolygonShape3D aClippedPoly;
+        std::vector<std::vector<css::drawing::Position3D>> aClippedPoly;
         Clipping::clipPolygonAtRectangle( aPoly, 
pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
         ShapeFactory::closePolygon(aClippedPoly); //again necessary after 
clipping
         aPoly = aClippedPoly;
@@ -240,8 +239,8 @@ void NetChart::impl_createSeriesShapes()
     {
         for( auto const& rXSlot : rZSlot )
         {
-            std::map< sal_Int32, drawing::PolyPolygonShape3D* > 
aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different 
nAttachedAxisIndex
-            drawing::PolyPolygonShape3D* pSeriesPoly = nullptr;
+            std::map< sal_Int32, 
std::vector<std::vector<css::drawing::Position3D>>* > 
aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different 
nAttachedAxisIndex
+            std::vector<std::vector<css::drawing::Position3D>>* pSeriesPoly = 
nullptr;
 
             //iterate through all series
             for( std::unique_ptr<VDataSeries> const & pSeries : 
rXSlot.m_aSeriesVector )
@@ -437,11 +436,11 @@ void NetChart::createShapes()
                     {
                         if( pSeries->getMissingValueTreatment() == 
css::chart::MissingValueTreatment::LEAVE_GAP )
                         {
-                            drawing::PolyPolygonShape3D& rPolygon = 
pSeries->m_aPolyPolygonShape3D;
+                            
std::vector<std::vector<css::drawing::Position3D>>& rPolygon = 
pSeries->m_aPolyPolygonShape3D;
                             sal_Int32& rIndex = pSeries->m_nPolygonIndex;
-                            if( 0<= rIndex && rIndex < 
rPolygon.SequenceX.getLength() )
+                            if( 0<= rIndex && rIndex < 
static_cast<sal_Int32>(rPolygon.size()) )
                             {
-                                if( rPolygon.SequenceX[ rIndex ].hasElements() 
)
+                                if( !rPolygon[ rIndex ].empty() )
                                     rIndex++; //start a new polygon for the 
next point if the current poly is not empty
                             }
                         }
diff --git a/chart2/source/view/charttypes/NetChart.hxx 
b/chart2/source/view/charttypes/NetChart.hxx
index 4ab3432bb777..9883ba118ac2 100644
--- a/chart2/source/view/charttypes/NetChart.hxx
+++ b/chart2/source/view/charttypes/NetChart.hxx
@@ -53,11 +53,11 @@ public:
 private: //methods
     void impl_createSeriesShapes();
     bool impl_createArea( VDataSeries* pSeries
-                , css::drawing::PolyPolygonShape3D* pSeriesPoly
-                , css::drawing::PolyPolygonShape3D const * pPreviousSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>>* 
pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>> const * 
pPreviousSeriesPoly
                 , PlottingPositionHelper const * pPosHelper );
     bool impl_createLine( VDataSeries* pSeries
-                , css::drawing::PolyPolygonShape3D* pSeriesPoly
+                , std::vector<std::vector<css::drawing::Position3D>>* 
pSeriesPoly
                 , PlottingPositionHelper const * pPosHelper );
 
 private: //member
diff --git a/chart2/source/view/charttypes/Splines.cxx 
b/chart2/source/view/charttypes/Splines.cxx
index 89203d3da182..c79fbbcb9fc7 100644
--- a/chart2/source/view/charttypes/Splines.cxx
+++ b/chart2/source/view/charttypes/Splines.cxx
@@ -20,6 +20,7 @@
 #include "Splines.hxx"
 #include <osl/diagnose.h>
 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
 
 #include <vector>
 #include <algorithm>
@@ -648,6 +649,114 @@ void SplineCalculater::CalculateCubicSplines(
     }
 }
 
+// Calculates uniform parametric splines with subinterval length 1,
+// according ODF1.2 part 1, chapter 'chart interpolation'.
+void SplineCalculater::CalculateCubicSplines(
+    const std::vector<std::vector<css::drawing::Position3D>>& rInput
+    , std::vector<std::vector<css::drawing::Position3D>>& rResult
+    , sal_uInt32 nGranularity )
+{
+    OSL_PRECOND( nGranularity > 0, "Granularity is invalid" );
+
+    sal_uInt32 nOuterCount = rInput.size();
+
+    rResult.resize(nOuterCount);
+
+    auto pSequence = rResult.data();
+
+    if( !nOuterCount )
+        return;
+
+    for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+    {
+        if( rInput[nOuter].size() <= 1 )
+            continue; //we need at least two points
+
+        sal_uInt32 nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1
+        const css::drawing::Position3D* pOld = rInput[nOuter].data();
+
+        std::vector < double > aParameter(nMaxIndexPoints+1);
+        aParameter[0]=0.0;
+        for( sal_uInt32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ )
+        {
+            aParameter[nIndex]=aParameter[nIndex-1]+1;
+        }
+
+        // Split the calculation to X, Y and Z coordinate
+        tPointVecType aInputX;
+        aInputX.resize(nMaxIndexPoints+1);
+        tPointVecType aInputY;
+        aInputY.resize(nMaxIndexPoints+1);
+        tPointVecType aInputZ;
+        aInputZ.resize(nMaxIndexPoints+1);
+        for (sal_uInt32 nN=0;nN<=nMaxIndexPoints; nN++ )
+        {
+          aInputX[ nN ].first=aParameter[nN];
+          aInputX[ nN ].second=pOld[ nN ].PositionX;
+          aInputY[ nN ].first=aParameter[nN];
+          aInputY[ nN ].second=pOld[ nN ].PositionY;
+          aInputZ[ nN ].first=aParameter[nN];
+          aInputZ[ nN ].second=pOld[ nN ].PositionZ;
+        }
+
+        // generate a spline for each coordinate. It holds the complete
+        // information to calculate each point of the curve
+        std::unique_ptr<lcl_SplineCalculation> aSplineX;
+        std::unique_ptr<lcl_SplineCalculation> aSplineY;
+        // lcl_SplineCalculation* aSplineZ; the z-coordinates of all points in
+        // a data series are equal. No spline calculation needed, but copy
+        // coordinate to output
+
+        if( pOld[ 0 ].PositionX == pOld[nMaxIndexPoints].PositionX &&
+            pOld[ 0 ].PositionY == pOld[nMaxIndexPoints].PositionY &&
+            pOld[ 0 ].PositionZ == pOld[nMaxIndexPoints].PositionZ &&
+            nMaxIndexPoints >=2 )
+        {   // periodic spline
+            aSplineX.reset(new lcl_SplineCalculation( std::move(aInputX)));
+            aSplineY.reset(new lcl_SplineCalculation( std::move(aInputY)));
+            // aSplineZ = new lcl_SplineCalculation( aInputZ) ;
+        }
+        else // generate the kind "natural spline"
+        {
+            double fXDerivation = std::numeric_limits<double>::infinity();
+            double fYDerivation = std::numeric_limits<double>::infinity();
+            aSplineX.reset(new lcl_SplineCalculation( std::move(aInputX), 
fXDerivation, fXDerivation ));
+            aSplineY.reset(new lcl_SplineCalculation( std::move(aInputY), 
fYDerivation, fYDerivation ));
+        }
+
+        // fill result polygon with calculated values
+        pSequence[nOuter].resize( nMaxIndexPoints*nGranularity + 1);
+
+        css::drawing::Position3D* pNew = pSequence[nOuter].data();
+
+        sal_uInt32 nNewPointIndex = 0; // Index in result points
+
+        for( sal_uInt32 ni = 0; ni < nMaxIndexPoints; ni++ )
+        {
+            // given point is surely a curve point
+            pNew[nNewPointIndex].PositionX = pOld[ni].PositionX;
+            pNew[nNewPointIndex].PositionY = pOld[ni].PositionY;
+            pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ;
+            nNewPointIndex++;
+
+            // calculate intermediate points
+            double fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / 
static_cast< double >( nGranularity );
+            for(sal_uInt32 nj = 1; nj < nGranularity; nj++)
+            {
+                double fParam = aParameter[ni] + ( fInc * static_cast< double 
>( nj ) );
+
+                pNew[nNewPointIndex].PositionX = 
aSplineX->GetInterpolatedValue( fParam );
+                pNew[nNewPointIndex].PositionY = 
aSplineY->GetInterpolatedValue( fParam );
+                // pNewZ[nNewPointIndex]=aSplineZ->GetInterpolatedValue( 
fParam );
+                pNew[nNewPointIndex].PositionZ = pOld[ni].PositionZ;
+                nNewPointIndex++;
+            }
+        }
+        // add last point
+        pNew[nNewPointIndex] = pOld[nMaxIndexPoints];
+    }
+}
+
 // The implementation follows closely ODF1.2 spec, chapter chart:interpolation
 // using the same names as in spec as far as possible, without prefix.
 // More details can be found on
@@ -931,6 +1040,271 @@ void SplineCalculater::CalculateBSplines(
     } // next piece of the series
 }
 
+void SplineCalculater::CalculateBSplines(
+            const std::vector<std::vector<css::drawing::Position3D>>& rInput
+            , std::vector<std::vector<css::drawing::Position3D>>& rResult
+            , sal_uInt32 nResolution
+            , sal_uInt32 nDegree )
+{
+    // nResolution is ODF1.2 file format attribute chart:spline-resolution and
+    // ODF1.2 spec variable k. Causion, k is used as index in the spec in 
addition.
+    // nDegree is ODF1.2 file format attribute chart:spline-order and
+    // ODF1.2 spec variable p
+    OSL_ASSERT( nResolution > 1 );
+    OSL_ASSERT( nDegree >= 1 );
+
+    // limit the b-spline degree at 15 to prevent insanely large sets of points
+    sal_uInt32 p = std::min<sal_uInt32>(nDegree, 15);
+
+    sal_Int32 nOuterCount = rInput.size();
+
+    rResult.resize(nOuterCount);
+
+    auto pSequence = rResult.data();
+
+    if( !nOuterCount )
+        return; // no input
+
+    for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+    {
+        if( rInput[nOuter].size() <= 1 )
+            continue; // need at least 2 points, next piece of the series
+
+        // Copy input to vector of points and remove adjacent double points. 
The
+        // Z-coordinate is equal for all points in a series and holds the depth
+        // in 3D mode, simple copying is enough.
+        lcl_tSizeType nMaxIndexPoints = rInput[nOuter].size()-1; // is >=1
+        const css::drawing::Position3D* pOld = rInput[nOuter].data();
+        double fZCoordinate = pOld[0].PositionZ;
+        tPointVecType aPointsIn;
+        aPointsIn.resize(nMaxIndexPoints+1);
+        for (lcl_tSizeType i = 0; i <= nMaxIndexPoints; ++i )
+        {
+          aPointsIn[ i ].first = pOld[i].PositionX;
+          aPointsIn[ i ].second = pOld[i].PositionY;
+        }
+        aPointsIn.erase( std::unique( aPointsIn.begin(), aPointsIn.end()),
+                     aPointsIn.end() );
+
+        // n is the last valid index to the reduced aPointsIn
+        // There are n+1 valid data points.
+        const lcl_tSizeType n = aPointsIn.size() - 1;
+        if (n < 1 || p > n)
+            continue; // need at least 2 points, degree p needs at least n+1 
points
+                      // next piece of series
+
+        std::unique_ptr<double[]> t(new double [n+1]);
+        if (!createParameterT(aPointsIn, t.get()))
+        {
+            continue; // next piece of series
+        }
+
+        lcl_tSizeType m = n + p + 1;
+        std::unique_ptr<double[]> u(new double [m+1]);
+        createKnotVector(n, p, t.get(), u.get());
+
+        // The matrix N contains the B-spline basis functions applied to 
parameters.
+        // In each row only p+1 adjacent elements are non-zero. The starting
+        // column in a higher row is equal or greater than in the lower row.
+        // To store this matrix the non-zero elements are shifted to column 0
+        // and the amount of shifting is remembered in an array.
+        std::unique_ptr<double*[]> aMatN(new double*[n+1]);
+        for (lcl_tSizeType row = 0; row <=n; ++row)
+        {
+            aMatN[row] = new double[p+1];
+            for (sal_uInt32 col = 0; col <= p; ++col)
+            aMatN[row][col] = 0.0;
+        }
+        std::unique_ptr<lcl_tSizeType[]> aShift(new lcl_tSizeType[n+1]);
+        aMatN[0][0] = 1.0; //all others are zero
+        aShift[0] = 0;
+        aMatN[n][0] = 1.0;
+        aShift[n] = n;
+        for (lcl_tSizeType k = 1; k<=n-1; ++k)
+        { // all basis functions are applied to t_k,
+            // results are elements in row k in matrix N
+
+            // find the one interval with u_i <= t_k < u_(i+1)
+            // remember u_0 = ... = u_p = 0.0 and u_(m-p) = ... u_m = 1.0 and 
0<t_k<1
+            lcl_tSizeType i = p;
+            while (u[i] > t[k] || t[k] >= u[i+1])
+            {
+                ++i;
+            }
+
+            // index in reduced matrix aMatN = (index in full matrix N) - (i-p)
+            aShift[k] = i - p;
+
+            applyNtoParameterT(i, t[k], p, u.get(), aMatN[k]);
+        } // next row k
+
+        // Get matrix C of control points from the matrix equation aMatN * C = 
aPointsIn
+        // aPointsIn is overwritten with C.
+        // Gaussian elimination is possible without pivoting, see reference
+        lcl_tSizeType r = 0; // true row index
+        lcl_tSizeType c = 0; // true column index
+        double fDivisor = 1.0; // used for diagonal element
+        double fEliminate = 1.0; // used for the element, that will become zero
+        double fHelp;
+        tPointType aHelp;
+        lcl_tSizeType nHelp; // used in triangle change
+        bool bIsSuccessful = true;
+        for (c = 0 ; c <= n && bIsSuccessful; ++c)
+        {
+            // search for first non-zero downwards
+            r = c;
+            while ( r < n && aMatN[r][c-aShift[r]] == 0 )
+            {
+                ++r;
+            }
+            if (aMatN[r][c-aShift[r]] == 0.0)
+            {
+                // Matrix N is singular, although this is mathematically 
impossible
+                bIsSuccessful = false;
+            }
+            else
+            {
+                // exchange total row r with total row c if necessary
+                if (r != c)
+                {
+                    for ( sal_uInt32 i = 0; i <= p ; ++i)
+                    {
+                        fHelp = aMatN[r][i];
+                        aMatN[r][i] = aMatN[c][i];
+                        aMatN[c][i] = fHelp;
+                    }
+                    aHelp = aPointsIn[r];
+                    aPointsIn[r] = aPointsIn[c];
+                    aPointsIn[c] = aHelp;
+                    nHelp = aShift[r];
+                    aShift[r] = aShift[c];
+                    aShift[c] = nHelp;
+                }
+
+                // divide row c, so that element(c,c) becomes 1
+                fDivisor = aMatN[c][c-aShift[c]]; // not zero, see above
+                for (sal_uInt32 i = 0; i <= p; ++i)
+                {
+                    aMatN[c][i] /= fDivisor;
+                }
+                aPointsIn[c].first /= fDivisor;
+                aPointsIn[c].second /= fDivisor;
+
+                // eliminate forward, examine row c+1 to n-1 (worst case)
+                // stop if first non-zero element in row has an higher column 
as c
+                // look at nShift for that, elements in nShift are equal or 
increasing
+                for ( r = c+1; r < n && aShift[r]<=c ; ++r)
+                {
+                    fEliminate = aMatN[r][0];
+                    if (fEliminate != 0.0) // else accidentally zero, nothing 
to do
+                    {
+                        for (sal_uInt32 i = 1; i <= p; ++i)
+                        {
+                            aMatN[r][i-1] = aMatN[r][i] - fEliminate * 
aMatN[c][i];
+                        }
+                        aMatN[r][p]=0;
+                        aPointsIn[r].first -= fEliminate * aPointsIn[c].first;
+                        aPointsIn[r].second -= fEliminate * 
aPointsIn[c].second;
+                        ++aShift[r];
+                    }
+                }
+            }
+        }// upper triangle form is reached
+        if( bIsSuccessful)
+        {
+            // eliminate backwards, begin with last column
+            for (lcl_tSizeType cc = n; cc >= 1; --cc )
+            {
+                // In row cc the diagonal element(cc,cc) == 1 and all elements 
left from
+                // diagonal are zero and do not influence other rows.
+                // Full matrix N has semibandwidth < p, therefore element(r,c) 
is
+                // zero, if abs(r-cc)>=p.  abs(r-cc)=cc-r, because r<cc.
+                r = cc - 1;
+                while ( r !=0 && cc-r < p )
+                {
+                    fEliminate = aMatN[r][ cc - aShift[r] ];
+                    if ( fEliminate != 0.0) // else element is accidentally 
zero, no action needed
+                    {
+                        // row r -= fEliminate * row cc only relevant for 
right side
+                        aMatN[r][cc - aShift[r]] = 0.0;
+                        aPointsIn[r].first -= fEliminate * aPointsIn[cc].first;
+                        aPointsIn[r].second -= fEliminate * 
aPointsIn[cc].second;
+                    }
+                    --r;
+                }
+            }
+            // aPointsIn contains the control points now.
+
+            // calculate the intermediate points according given resolution
+            // using deBoor-Cox algorithm
+            lcl_tSizeType nNewSize = nResolution * n + 1;
+            pSequence[nOuter].resize(nNewSize);
+            css::drawing::Position3D* pNew = pSequence[nOuter].data();
+            pNew[0].PositionX = aPointsIn[0].first;
+            pNew[0].PositionY = aPointsIn[0].second;
+            pNew[0].PositionZ = fZCoordinate; // Precondition: z-coordinates 
of all points of a series are equal
+            pNew[nNewSize -1 ].PositionX = aPointsIn[n].first;
+            pNew[nNewSize -1 ].PositionY = aPointsIn[n].second;
+            pNew[nNewSize -1 ].PositionZ = fZCoordinate;
+            std::unique_ptr<double[]> aP(new double[m+1]);
+            lcl_tSizeType nLow = 0;
+            for ( lcl_tSizeType nTIndex = 0; nTIndex <= n-1; ++nTIndex)
+            {
+                for (sal_uInt32 nResolutionStep = 1;
+                     nResolutionStep <= nResolution && ( nTIndex != n-1 || 
nResolutionStep != nResolution);
+                     ++nResolutionStep)
+                {
+                    lcl_tSizeType nNewIndex = nTIndex * nResolution + 
nResolutionStep;
+                    double ux = t[nTIndex] + nResolutionStep * ( t[nTIndex+1] 
- t[nTIndex]) /nResolution;
+
+                    // get index nLow, so that u[nLow]<= ux < u[nLow +1]
+                    // continue from previous nLow
+                    while ( u[nLow] <= ux)
+                    {
+                        ++nLow;
+                    }
+                    --nLow;
+
+                    // x-coordinate
+                    for (lcl_tSizeType i = nLow-p; i <= nLow; ++i)
+                    {
+                        aP[i] = aPointsIn[i].first;
+                    }
+                    for (sal_uInt32 lcl_Degree = 1; lcl_Degree <= p; 
++lcl_Degree)
+                    {
+                        for (lcl_tSizeType i = nLow; i >= nLow + lcl_Degree - 
p; --i)
+                        {
+                            double fFactor = ( ux - u[i] ) / ( 
u[i+p+1-lcl_Degree] - u[i]);
+                            aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i];
+                        }
+                    }
+                    pNew[nNewIndex].PositionX = aP[nLow];
+
+                    // y-coordinate
+                    for (lcl_tSizeType i = nLow - p; i <= nLow; ++i)
+                    {
+                        aP[i] = aPointsIn[i].second;
+                    }
+                    for (sal_uInt32 lcl_Degree = 1; lcl_Degree <= p; 
++lcl_Degree)
+                    {
+                        for (lcl_tSizeType i = nLow; i >= nLow +lcl_Degree - 
p; --i)
+                        {
+                            double fFactor = ( ux - u[i] ) / ( 
u[i+p+1-lcl_Degree] - u[i]);
+                            aP[i] = (1 - fFactor)* aP[i-1] + fFactor * aP[i];
+                        }
+                    }
+                    pNew[nNewIndex].PositionY = aP[nLow];
+                    pNew[nNewIndex].PositionZ = fZCoordinate;
+                }
+            }
+        }
+        for (lcl_tSizeType row = 0; row <=n; ++row)
+        {
+            delete[] aMatN[row];
+        }
+    } // next piece of the series
+}
+
 } //namespace chart
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/charttypes/Splines.hxx 
b/chart2/source/view/charttypes/Splines.hxx
index 4ceb65fc05c0..3cd36131550e 100644
--- a/chart2/source/view/charttypes/Splines.hxx
+++ b/chart2/source/view/charttypes/Splines.hxx
@@ -20,8 +20,10 @@
 #pragma once
 
 #include <sal/types.h>
+#include <vector>
 
 namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+namespace com::sun::star::drawing { struct Position3D; }
 
 namespace chart
 {
@@ -33,12 +35,21 @@ public:
             const css::drawing::PolyPolygonShape3D& rPoints
             , css::drawing::PolyPolygonShape3D& rResult
             , sal_uInt32 nGranularity );
+    static void CalculateCubicSplines(
+            const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+            , std::vector<std::vector<css::drawing::Position3D>>& rResult
+            , sal_uInt32 nGranularity );
 
     static void CalculateBSplines(
             const css::drawing::PolyPolygonShape3D& rPoints
             , css::drawing::PolyPolygonShape3D& rResult
             , sal_uInt32 nGranularity
             , sal_uInt32 nSplineDepth );
+    static void CalculateBSplines(
+            const std::vector<std::vector<css::drawing::Position3D>>& rPoints
+            , std::vector<std::vector<css::drawing::Position3D>>& rResult
+            , sal_uInt32 nGranularity
+            , sal_uInt32 nSplineDepth );
 };
 
 } //namespace chart
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx 
b/chart2/source/view/charttypes/VSeriesPlotter.cxx
index bb3ecd8037eb..d2ee85a6a100 100644
--- a/chart2/source/view/charttypes/VSeriesPlotter.cxx
+++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx
@@ -866,7 +866,7 @@ double lcl_getErrorBarLogicLength(
 }
 
 void lcl_AddErrorBottomLine( const drawing::Position3D& rPosition, 
::basegfx::B2DVector aMainDirection
-                , drawing::PolyPolygonShape3D& rPoly, sal_Int32 nSequenceIndex 
)
+                , std::vector<std::vector<css::drawing::Position3D>>& rPoly, 
sal_Int32 nSequenceIndex )
 {
     double fFixedWidth = 200.0;
 
@@ -1050,7 +1050,7 @@ void VSeriesPlotter::createErrorBar(
         if(!bShowPositive && !bShowNegative)
             return;
 
-        drawing::PolyPolygonShape3D aPoly;
+        std::vector<std::vector<css::drawing::Position3D>> aPoly;
 
         sal_Int32 nSequenceIndex=0;
         if( bShowNegative )
@@ -1072,7 +1072,7 @@ void VSeriesPlotter::createErrorBar(
             lcl_AddErrorBottomLine( aPositive, aMainDirection, aPoly, 
nSequenceIndex );
         }
 
-        rtl::Reference<SvxShapePolyPolygon> xShape = 
ShapeFactory::createLine2D( xTarget, PolyToPointSequence( aPoly) );
+        rtl::Reference<SvxShapePolyPolygon> xShape = 
ShapeFactory::createLine2D( xTarget, aPoly );
         PropertyMapper::setMappedProperties( *xShape, xErrorBarProperties, 
PropertyMapper::getPropertyNameMapForLineProperties() );
     }
     catch( const uno::Exception & )
@@ -1088,12 +1088,12 @@ void VSeriesPlotter::addErrorBorder(
      ,const rtl::Reference<SvxShapeGroupAnyD>& rTarget
      ,const uno::Reference< beans::XPropertySet >& rErrorBorderProp )
 {
-    drawing::PolyPolygonShape3D aPoly;
+    std::vector<std::vector<css::drawing::Position3D>> aPoly;
     sal_Int32 nSequenceIndex = 0;
     AddPointToPoly( aPoly, rPos0, nSequenceIndex );
     AddPointToPoly( aPoly, rPos1, nSequenceIndex );
     rtl::Reference<SvxShapePolyPolygon> xShape = ShapeFactory::createLine2D(
-                    rTarget, PolyToPointSequence( aPoly) );
+                    rTarget, aPoly );
     PropertyMapper::setMappedProperties( *xShape, rErrorBorderProp,
                     PropertyMapper::getPropertyNameMapForLineProperties() );
 }
diff --git a/chart2/source/view/inc/Clipping.hxx 
b/chart2/source/view/inc/Clipping.hxx
index 64697dfb9714..e816e7aa79b1 100644
--- a/chart2/source/view/inc/Clipping.hxx
+++ b/chart2/source/view/inc/Clipping.hxx
@@ -22,6 +22,7 @@
 #include <basegfx/range/b2drectangle.hxx>
 
 namespace com::sun::star::drawing { struct PolyPolygonShape3D; }
+namespace com::sun::star::drawing { struct Position3D; }
 
 namespace chart
 {
@@ -48,6 +49,11 @@ public:
                                 , const ::basegfx::B2DRectangle& rRectangle
                                 , css::drawing::PolyPolygonShape3D& aResult
                                 , bool bSplitPiecesToDifferentPolygons = true 
);
+    static void clipPolygonAtRectangle(
+                                const 
std::vector<std::vector<css::drawing::Position3D>>& rPolygon
+                                , const ::basegfx::B2DRectangle& rRectangle
+                                , 
std::vector<std::vector<css::drawing::Position3D>>& aResult
+                                , bool bSplitPiecesToDifferentPolygons = true 
);
 };
 
 } //namespace chart
diff --git a/chart2/source/view/inc/PlottingPositionHelper.hxx 
b/chart2/source/view/inc/PlottingPositionHelper.hxx
index f5360942b2d7..14e22375df17 100644
--- a/chart2/source/view/inc/PlottingPositionHelper.hxx
+++ b/chart2/source/view/inc/PlottingPositionHelper.hxx
@@ -84,6 +84,7 @@ public:
             transformScaledLogicToScene( double fX, double fY, double fZ, bool 
bClip ) const;
 
     void    transformScaledLogicToScene( css::drawing::PolyPolygonShape3D& 
rPoly ) const;
+    void    transformScaledLogicToScene( 
std::vector<std::vector<css::drawing::Position3D>>& rPoly ) const;
 
     static css::awt::Point transformSceneToScreenPosition(
                   const css::drawing::Position3D& rScenePosition3D
diff --git a/chart2/source/view/inc/ShapeFactory.hxx 
b/chart2/source/view/inc/ShapeFactory.hxx
index f198f074f519..e8ff694f32cc 100644
--- a/chart2/source/view/inc/ShapeFactory.hxx
+++ b/chart2/source/view/inc/ShapeFactory.hxx
@@ -154,11 +154,19 @@ public:
         createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
                     , const css::drawing::PolyPolygonShape3D& rPolyPolygon
                     , double fDepth);
+    static rtl::Reference<Svx3DExtrudeObject>
+        createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+                    , double fDepth);
 
     static SdrPathObj*
         createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
                     , const css::drawing::PolyPolygonShape3D& rPolyPolygon
                     , bool bSetZOrderToZero = true);
+    static SdrPathObj*
+        createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+                    , bool bSetZOrderToZero = true);
 
     static rtl::Reference<SvxShapePolyPolygon>
         createSymbol2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
@@ -178,6 +186,10 @@ public:
         createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
                     , const css::drawing::PointSequenceSequence& rPoints
                     , const VLineProperties* pLineProperties = nullptr );
+    static rtl::Reference<SvxShapePolyPolygon>
+        createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPoints
+                    , const VLineProperties* pLineProperties = nullptr );
 
     static rtl::Reference<SvxShapePolyPolygon>
         createLine ( const rtl::Reference<SvxShapeGroupAnyD>& xTarget,
@@ -185,7 +197,7 @@ public:
 
     static rtl::Reference<Svx3DPolygonObject>
         createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& xTarget
-                    , const css::drawing::PolyPolygonShape3D& rPoints
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPoints
                     , const VLineProperties& rLineProperties );
 
     static rtl::Reference<SvxShapeCircle>
@@ -262,8 +274,11 @@ public:
     static OUString getStackedString( const OUString& rString, bool bStacked );
 
     static bool hasPolygonAnyLines( css::drawing::PolyPolygonShape3D& rPoly );
+    static bool hasPolygonAnyLines( const 
std::vector<std::vector<css::drawing::Position3D>>& rPoly );
     static bool isPolygonEmptyOrSinglePoint( css::drawing::PolyPolygonShape3D& 
rPoly );
+    static bool isPolygonEmptyOrSinglePoint( const 
std::vector<std::vector<css::drawing::Position3D>>& rPoly );
     static void closePolygon( css::drawing::PolyPolygonShape3D& rPoly );
+    static void closePolygon( 
std::vector<std::vector<css::drawing::Position3D>>& rPoly );
 
     static css::awt::Size calculateNewSizeRespectingAspectRatio(
             const css::awt::Size& rTargetSize
diff --git a/chart2/source/view/inc/VDataSeries.hxx 
b/chart2/source/view/inc/VDataSeries.hxx
index 48ea0d4234ff..bfbc6c9b20ea 100644
--- a/chart2/source/view/inc/VDataSeries.hxx
+++ b/chart2/source/view/inc/VDataSeries.hxx
@@ -22,6 +22,7 @@
 
 #include <com/sun/star/chart2/StackingDirection.hpp>
 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
 #include <com/sun/star/awt/Size.hpp>
 #include <com/sun/star/awt/Point.hpp>
 #include <rtl/ref.hxx>
@@ -142,7 +143,7 @@ public:
     void setRoleOfSequenceForDataLabelNumberFormatDetection( 
std::u16string_view rRole );
 
     //this is only temporarily here for area chart:
-    css::drawing::PolyPolygonShape3D       m_aPolyPolygonShape3D;
+    std::vector<std::vector<css::drawing::Position3D>> m_aPolyPolygonShape3D;
     sal_Int32   m_nPolygonIndex;
     double m_fLogicMinX;
     double m_fLogicMaxX;
diff --git a/chart2/source/view/main/Clipping.cxx 
b/chart2/source/view/main/Clipping.cxx
index 463b74975a91..7509f53fb28d 100644
--- a/chart2/source/view/main/Clipping.cxx
+++ b/chart2/source/view/main/Clipping.cxx
@@ -204,6 +204,47 @@ void lcl_addPointToPoly( drawing::PolyPolygonShape3D& rPoly
     rResultPointCount[nPolygonIndex]=nNewResultPointCount;
 }
 
+void lcl_addPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& 
rPoly
+        , const drawing::Position3D& rPos
+        , sal_Int32 nPolygonIndex
+        , std::vector< sal_Int32 >& rResultPointCount
+        , sal_Int32 nReservePointCount )
+{
+    if(nPolygonIndex<0)
+    {
+        OSL_FAIL( "The polygon index needs to be > 0");
+        nPolygonIndex=0;
+    }
+
+    //make sure that we have enough polygons
+    if(nPolygonIndex >= static_cast<sal_Int32>(rPoly.size()) )
+    {
+        rPoly.resize(nPolygonIndex+1);
+        rResultPointCount.resize(nPolygonIndex+1,0);
+    }
+
+    std::vector<css::drawing::Position3D>* pOuterSequence = 
&rPoly[nPolygonIndex];
+
+    sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
+    sal_Int32 nSeqLength = pOuterSequence->size();
+
+    if( nSeqLength <= nNewResultPointCount )
+    {
+        sal_Int32 nReallocLength = nReservePointCount > SAL_MAX_INT16 ? 
round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount;
+        if( nNewResultPointCount > nReallocLength )
+        {
+            nReallocLength = nNewResultPointCount;
+            OSL_FAIL("this should not be the case to avoid performance 
problems");
+        }
+        pOuterSequence->resize(nReallocLength);
+    }
+
+    css::drawing::Position3D* pInnerSequence = pOuterSequence->data();
+
+    pInnerSequence[nNewResultPointCount-1] = rPos;
+    rResultPointCount[nPolygonIndex]=nNewResultPointCount;
+}
+
 }//end anonymous namespace
 
 void Clipping::clipPolygonAtRectangle( const drawing::PolyPolygonShape3D& 
rPolygon
@@ -295,6 +336,89 @@ void Clipping::clipPolygonAtRectangle( const 
drawing::PolyPolygonShape3D& rPolyg
     }
 }
 
+void Clipping::clipPolygonAtRectangle( const 
std::vector<std::vector<css::drawing::Position3D>>& rPolygon
+                                      , const B2DRectangle& rRectangle
+                                      , 
std::vector<std::vector<css::drawing::Position3D>>& aResult
+                                      , bool bSplitPiecesToDifferentPolygons )
+{
+    aResult.clear();
+
+    if(rPolygon.empty())
+        return;
+
+    //need clipping?:
+    {
+        ::basegfx::B3DRange a3DRange( BaseGFXHelper::getBoundVolume( rPolygon 
) );
+        ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), 
a3DRange.getMaxX(), a3DRange.getMaxY() );
+        if( rRectangle.isInside( a2DRange ) )
+        {
+            aResult = rPolygon;
+            return;
+        }
+        else
+        {
+            a2DRange.intersect( rRectangle );
+            if( a2DRange.isEmpty() )
+                return;
+        }
+    }
+
+    std::vector< sal_Int32 > aResultPointCount;//per polygon index
+
+    //apply clipping:
+    drawing::Position3D aFrom;
+    drawing::Position3D aTo;
+
+    sal_Int32 nNewPolyIndex = 0;
+    sal_Int32 nOldPolyCount = rPolygon.size();
+    for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; 
nOldPolyIndex++, nNewPolyIndex++ )
+    {
+        sal_Int32 nOldPointCount = rPolygon[nOldPolyIndex].size();
+
+        // set last point to a position outside the rectangle, such that the 
first
+        // time lcl_clip2d returns true, the comparison to last will always 
yield false
+        drawing::Position3D 
aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
+
+        for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
+        {
+            aFrom = getPointFromPoly(rPolygon,nOldPoint-1,nOldPolyIndex);
+            aTo = getPointFromPoly(rPolygon,nOldPoint,nOldPolyIndex);
+            if( lcl_clip2d_(aFrom, aTo, rRectangle) )
+            {
+                // compose a Polygon of as many consecutive points as possible
+                if(aFrom == aLast)
+                {
+                    if( aTo != aFrom )
+                    {
+                        lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, 
aResultPointCount, nOldPointCount );
+                    }
+                }
+                else
+                {
+                    if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
+                    {
+                        if( nNewPolyIndex < 
static_cast<sal_Int32>(aResult.size())
+                                && aResultPointCount[nNewPolyIndex]>0 )
+                            nNewPolyIndex++;
+                    }
+                    lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, 
aResultPointCount, nOldPointCount );
+                    if( aTo != aFrom )
+                        lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, 
aResultPointCount, nOldPointCount );
+                }
+                aLast = aTo;
+            }
+        }
+    }
+    //free unused space
+    for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
+    {
+        std::vector<css::drawing::Position3D>* pOuterSequence = 
&aResult[nPolygonIndex];
+
+        sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
+        pOuterSequence->resize(nUsedPointCount);
+    }
+}
+
 } //namespace chart
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx 
b/chart2/source/view/main/PlottingPositionHelper.cxx
index 350c0942ae78..0c2084aae2e2 100644
--- a/chart2/source/view/main/PlottingPositionHelper.cxx
+++ b/chart2/source/view/main/PlottingPositionHelper.cxx
@@ -238,6 +238,25 @@ void PlottingPositionHelper::transformScaledLogicToScene( 
drawing::PolyPolygonSh
     }
 }
 
+void PlottingPositionHelper::transformScaledLogicToScene( 
std::vector<std::vector<css::drawing::Position3D>>& rPolygon ) const
+{
+    drawing::Position3D aScenePosition;
+    for( sal_Int32 nS = static_cast<sal_Int32>(rPolygon.size()); nS--;)
+    {
+        auto valuesRange = rPolygon[nS].data();
+        for( sal_Int32 nP = rPolygon[nS].size(); nP--; )
+        {
+            double& fX = valuesRange[nP].PositionX;
+            double& fY = valuesRange[nP].PositionY;
+            double& fZ = valuesRange[nP].PositionZ;
+            aScenePosition = transformScaledLogicToScene( fX,fY,fZ,true );
+            fX = aScenePosition.PositionX;
+            fY = aScenePosition.PositionY;
+            fZ = aScenePosition.PositionZ;
+        }
+    }
+}
+
 void PlottingPositionHelper::clipScaledLogicValues( double* pX, double* pY, 
double* pZ ) const
 {
     //get logic clip values:
diff --git a/chart2/source/view/main/ShapeFactory.cxx 
b/chart2/source/view/main/ShapeFactory.cxx
index 98afa8bba4da..92167165ba14 100644
--- a/chart2/source/view/main/ShapeFactory.cxx
+++ b/chart2/source/view/main/ShapeFactory.cxx
@@ -83,6 +83,34 @@ void lcl_addProperty(uno::Sequence<OUString> & 
rPropertyNames, uno::Sequence<uno
     rPropertyValues.getArray()[rPropertyValues.getLength() - 1] = rAny;
 }
 
+css::drawing::PolyPolygonShape3D toPolyPolygonShape3D(const 
std::vector<std::vector<css::drawing::Position3D>>& rPoints)
+{
+    css::drawing::PolyPolygonShape3D aUnoPoly;
+    aUnoPoly.SequenceX.realloc(rPoints.size());
+    aUnoPoly.SequenceY.realloc(rPoints.size());
+    aUnoPoly.SequenceZ.realloc(rPoints.size());
+    for (sal_Int32 nPolygonIndex=0; 
nPolygonIndex<static_cast<sal_Int32>(rPoints.size()); ++nPolygonIndex)
+    {
+        drawing::DoubleSequence* pOuterSequenceX = 
&aUnoPoly.SequenceX.getArray()[nPolygonIndex];
+        drawing::DoubleSequence* pOuterSequenceY = 
&aUnoPoly.SequenceY.getArray()[nPolygonIndex];
+        drawing::DoubleSequence* pOuterSequenceZ = 
&aUnoPoly.SequenceZ.getArray()[nPolygonIndex];
+        pOuterSequenceX->realloc(rPoints[nPolygonIndex].size());
+        pOuterSequenceY->realloc(rPoints[nPolygonIndex].size());
+        pOuterSequenceZ->realloc(rPoints[nPolygonIndex].size());
+        double* pInnerSequenceX = pOuterSequenceX->getArray();
+        double* pInnerSequenceY = pOuterSequenceY->getArray();
+        double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+        for (sal_Int32 nPointIndex=0; 
nPointIndex<static_cast<sal_Int32>(rPoints[nPolygonIndex].size()); 
++nPointIndex)
+        {
+            auto& rPos = rPoints[nPolygonIndex][nPointIndex];
+            pInnerSequenceX[nPointIndex] = rPos.PositionX;
+            pInnerSequenceY[nPointIndex] = rPos.PositionY;
+            pInnerSequenceZ[nPointIndex] = rPos.PositionZ;
+        }
+    }
+    return aUnoPoly;
+}
+
 } // end anonymous namespace
 
 rtl::Reference<SvxShapeGroupAnyD> ShapeFactory::getOrCreateChartRootShape(
@@ -1081,6 +1109,61 @@ rtl::Reference<Svx3DExtrudeObject>
     return xShape;
 }
 
+rtl::Reference<Svx3DExtrudeObject>
+        ShapeFactory::createArea3D( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+                    , double fDepth )
+{
+    if( !xTarget.is() )
+        return nullptr;
+
+    if( rPolyPolygon.empty() )
+        return nullptr;
+
+    //create shape
+    rtl::Reference<Svx3DExtrudeObject> xShape = new 
Svx3DExtrudeObject(nullptr);
+    xShape->setShapeKind(SdrObjKind::E3D_Extrusion);
+    xTarget->add(xShape);
+
+    css::drawing::PolyPolygonShape3D aUnoPolyPolygon = 
toPolyPolygonShape3D(rPolyPolygon);
+
+    //set properties
+    try
+    {
+        uno::Sequence<OUString> aPropertyNames{
+            UNO_NAME_3D_EXTRUDE_DEPTH,
+            UNO_NAME_3D_PERCENT_DIAGONAL,
+            UNO_NAME_3D_POLYPOLYGON3D,
+            UNO_NAME_3D_DOUBLE_SIDED,
+        };
+
+        uno::Sequence<uno::Any> aPropertyValues {
+            uno::Any(sal_Int32(fDepth)), // depth
+            uno::Any(sal_Int16(0)),      // PercentDiagonal
+            uno::Any(aUnoPolyPolygon),      // Polygon
+            uno::Any(true)               // DoubleSided
+        };
+
+        //the z component of the polygon is now ignored by the drawing layer,
+        //so we need to translate the object via transformation matrix
+
+        //Matrix for position
+        if (!rPolyPolygon.empty() && !rPolyPolygon[0].empty())
+        {
+            basegfx::B3DHomMatrix aM;
+            aM.translate(0, 0, rPolyPolygon[0][0].PositionZ);
+            drawing::HomogenMatrix aHM = B3DHomMatrixToHomogenMatrix(aM);
+            lcl_addProperty(aPropertyNames, aPropertyValues, 
UNO_NAME_3D_TRANSFORM_MATRIX, uno::Any(aHM));
+        }
+        xShape->setPropertyValues(aPropertyNames, aPropertyValues);
+    }
+    catch( const uno::Exception& )
+    {
+        TOOLS_WARN_EXCEPTION("chart2", "" );
+    }
+    return xShape;
+}
+
 SdrPathObj*
         ShapeFactory::createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget
                     , const drawing::PolyPolygonShape3D& rPolyPolygon
@@ -1113,6 +1196,38 @@ SdrPathObj*
     return pPath;
 }
 
+SdrPathObj*
+        ShapeFactory::createArea2D( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPolyPolygon
+                    , bool bSetZOrderToZero )
+{
+    if( !xTarget.is() )
+        return nullptr;
+
+    //create shape
+    SdrPathObj* pPath = new 
SdrPathObj(xTarget->GetSdrObject()->getSdrModelFromSdrObject(), 
SdrObjKind::Polygon);
+    if (bSetZOrderToZero)
+        // insert at ZOrder 0, an area should always be behind other shapes
+        xTarget->GetSdrObject()->GetSubList()->InsertObject(pPath, 0);
+    else
+        xTarget->GetSdrObject()->GetSubList()->InsertObject(pPath);
+
+    //set properties
+    try
+    {
+        // Polygon
+        basegfx::B2DPolyPolygon aNewPolyPolygon( 
PolyToB2DPolyPolygon(rPolyPolygon) );
+        // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 
100thmm
+        pPath->ForceMetricToItemPoolMetric(aNewPolyPolygon);
+        pPath->SetPathPoly(aNewPolyPolygon);
+    }
+    catch( const uno::Exception& )
+    {
+        TOOLS_WARN_EXCEPTION("chart2", "" );
+    }
+    return pPath;
+}
+
 static drawing::PolyPolygonShape3D createPolyPolygon_Symbol( const 
drawing::Position3D& rPos
                                  , const drawing::Direction3D& rSize
                                  , sal_Int32 nStandardSymbol )
@@ -1860,13 +1975,13 @@ rtl::Reference<SvxShapeCircle>
 
 rtl::Reference<Svx3DPolygonObject>
         ShapeFactory::createLine3D( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget
-                    , const drawing::PolyPolygonShape3D& rPoints
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPoints
                     , const VLineProperties& rLineProperties )
 {
     if( !xTarget.is() )
         return nullptr;
 
-    if(!rPoints.SequenceX.hasElements())
+    if(rPoints.empty())
         return nullptr;
 
     //create shape
@@ -1874,6 +1989,8 @@ rtl::Reference<Svx3DPolygonObject>
     xShape->setShapeKind(SdrObjKind::E3D_Polygon);
     xTarget->add(xShape);
 
+    css::drawing::PolyPolygonShape3D aUnoPoly = toPolyPolygonShape3D(rPoints);
+
     //set properties
     try
     {
@@ -1883,7 +2000,7 @@ rtl::Reference<Svx3DPolygonObject>
         };
 
         uno::Sequence<uno::Any> aPropertyValues {
-            uno::Any(rPoints),  // Polygon
+            uno::Any(aUnoPoly),  // Polygon
             uno::Any(true)      // LineOnly
         };
 
@@ -1990,6 +2107,71 @@ rtl::Reference<SvxShapePolyPolygon>
     return xShape;
 }
 
+rtl::Reference<SvxShapePolyPolygon>
+        ShapeFactory::createLine2D( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget
+                    , const 
std::vector<std::vector<css::drawing::Position3D>>& rPoints
+                    , const VLineProperties* pLineProperties )
+{
+    if( !xTarget.is() )
+        return nullptr;
+
+    if(rPoints.empty())
+        return nullptr;
+
+    //create shape
+    rtl::Reference<SvxShapePolyPolygon> xShape = new 
SvxShapePolyPolygon(nullptr);
+    xShape->setShapeKind(SdrObjKind::PolyLine);
+    xTarget->add(xShape);
+
+    drawing::PointSequenceSequence aAnyPoints = PolyToPointSequence(rPoints);
+
+    //set properties
+    try
+    {
+        //Polygon
+        xShape->SvxShape::setPropertyValue( UNO_NAME_POLYPOLYGON
+            , uno::Any( aAnyPoints ) );
+
+        if(pLineProperties)
+        {
+            //Transparency
+            if(pLineProperties->Transparence.hasValue())
+                xShape->SvxShape::setPropertyValue( UNO_NAME_LINETRANSPARENCE
+                    , pLineProperties->Transparence );
+
+            //LineStyle
+            if(pLineProperties->LineStyle.hasValue())
+                xShape->SvxShape::setPropertyValue( UNO_NAME_LINESTYLE
+                    , pLineProperties->LineStyle );
+
+            //LineWidth
+            if(pLineProperties->Width.hasValue())
+                xShape->SvxShape::setPropertyValue( UNO_NAME_LINEWIDTH
+                    , pLineProperties->Width );
+
+            //LineColor
+            if(pLineProperties->Color.hasValue())
+                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECOLOR
+                    , pLineProperties->Color );
+
+            //LineDashName
+            if(pLineProperties->DashName.hasValue())
+                xShape->SvxShape::setPropertyValue( "LineDashName"
+                    , pLineProperties->DashName );
+
+            //LineCap
+            if(pLineProperties->LineCap.hasValue())
+                xShape->SvxShape::setPropertyValue( UNO_NAME_LINECAP
+                    , pLineProperties->LineCap );
+        }
+    }
+    catch( const uno::Exception& )
+    {
+        TOOLS_WARN_EXCEPTION("chart2", "" );
+    }
+    return xShape;
+}
+
 rtl::Reference<SvxShapePolyPolygon>
     ShapeFactory::createLine ( const rtl::Reference<SvxShapeGroupAnyD>& 
xTarget,
             const awt::Size& rSize, const awt::Point& rPosition )
@@ -2465,6 +2647,15 @@ bool ShapeFactory::hasPolygonAnyLines( 
drawing::PolyPolygonShape3D& rPoly)
     return false;
 }
 
+bool ShapeFactory::hasPolygonAnyLines( const 
std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+    // #i67757# check all contained polygons, if at least one polygon contains 
2 or more points, return true
+    for( auto const & i : rPoly )
+        if( i.size() > 1 )
+            return true;
+    return false;
+}
+
 bool ShapeFactory::isPolygonEmptyOrSinglePoint( drawing::PolyPolygonShape3D& 
rPoly)
 {
     // true, if empty polypolygon or one polygon with one point
@@ -2472,6 +2663,12 @@ bool ShapeFactory::isPolygonEmptyOrSinglePoint( 
drawing::PolyPolygonShape3D& rPo
         ((rPoly.SequenceX.getLength() == 1) && (rPoly.SequenceX[0].getLength() 
<= 1));
 }
 
+bool ShapeFactory::isPolygonEmptyOrSinglePoint( const 
std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+    // true, if empty polypolygon or one polygon with one point
+    return rPoly.empty() || ((rPoly.size() == 1) && (rPoly[0].size() <= 1));
+}
+
 void ShapeFactory::closePolygon( drawing::PolyPolygonShape3D& rPoly)
 {
     OSL_ENSURE( rPoly.SequenceX.getLength() <= 1, "ShapeFactory::closePolygon 
- single polygon expected" );
@@ -2482,6 +2679,16 @@ void ShapeFactory::closePolygon( 
drawing::PolyPolygonShape3D& rPoly)
     AddPointToPoly( rPoly, aFirst );
 }
 
+void ShapeFactory::closePolygon( 
std::vector<std::vector<css::drawing::Position3D>>& rPoly)
+{
+    OSL_ENSURE( rPoly.size() <= 1, "ShapeFactory::closePolygon - single 
polygon expected" );
+    //add a last point == first point
+    if(isPolygonEmptyOrSinglePoint(rPoly))
+        return;
+    drawing::Position3D aFirst(rPoly[0][0]);
+    AddPointToPoly( rPoly, aFirst );
+}
+
 awt::Size ShapeFactory::calculateNewSizeRespectingAspectRatio(
          const awt::Size& rTargetSize
          , const awt::Size& rSourceSizeWithCorrectAspectRatio )
diff --git a/chart2/source/view/main/VDataSeries.cxx 
b/chart2/source/view/main/VDataSeries.cxx
index 14d204a8cf9e..8ae407488b8d 100644
--- a/chart2/source/view/main/VDataSeries.cxx
+++ b/chart2/source/view/main/VDataSeries.cxx
@@ -294,9 +294,7 @@ void VDataSeries::releaseShapes()
     m_xFrontSubGroupShape.set(nullptr);
     m_xBackSubGroupShape.set(nullptr);
 
-    m_aPolyPolygonShape3D.SequenceX.realloc(0);
-    m_aPolyPolygonShape3D.SequenceY.realloc(0);
-    m_aPolyPolygonShape3D.SequenceZ.realloc(0);
+    m_aPolyPolygonShape3D.clear();
     m_nPolygonIndex = 0;
 }
 

Reply via email to