bump product version to 4.1.6.2
[LibreOffice.git] / chart2 / source / view / charttypes / AreaChart.cxx
blob025441cc2cb48185ca7d74d6ae072dc3ca91f42f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AreaChart.hxx"
21 #include "PlottingPositionHelper.hxx"
22 #include "ShapeFactory.hxx"
23 #include "CommonConverters.hxx"
24 #include "macros.hxx"
25 #include "ViewDefines.hxx"
26 #include "ObjectIdentifier.hxx"
27 #include "Splines.hxx"
28 #include "ChartTypeHelper.hxx"
29 #include "LabelPositionHelper.hxx"
30 #include "Clipping.hxx"
31 #include "Stripe.hxx"
32 #include "PolarLabelPositionHelper.hxx"
33 #include "DateHelper.hxx"
35 #include <com/sun/star/chart2/Symbol.hpp>
36 #include <com/sun/star/chart/DataLabelPlacement.hpp>
37 #include <com/sun/star/chart/MissingValueTreatment.hpp>
39 #include <editeng/unoprnms.hxx>
40 #include <rtl/math.hxx>
42 #include <com/sun/star/drawing/DoubleSequence.hpp>
43 #include <com/sun/star/drawing/NormalsKind.hpp>
44 #include <com/sun/star/lang/XServiceName.hpp>
46 //.............................................................................
47 namespace chart
49 //.............................................................................
50 using namespace ::com::sun::star;
51 using namespace ::rtl::math;
52 using namespace ::com::sun::star::chart2;
54 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
56 //-----------------------------------------------------------------------------
58 AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel
59 , sal_Int32 nDimensionCount
60 , bool bCategoryXAxis
61 , bool bNoArea
62 , PlottingPositionHelper* pPlottingPositionHelper
63 , bool bConnectLastToFirstPoint
64 , bool bExpandIfValuesCloseToBorder
65 , sal_Int32 nKeepAspectRatio
66 , const drawing::Direction3D& rAspectRatio
68 : VSeriesPlotter( xChartTypeModel, nDimensionCount, bCategoryXAxis )
69 , m_pMainPosHelper(pPlottingPositionHelper)
70 , m_bArea(!bNoArea)
71 , m_bLine(bNoArea)
72 , m_bSymbol( ChartTypeHelper::isSupportingSymbolProperties(xChartTypeModel,nDimensionCount) )
73 , m_bIsPolarCooSys( bConnectLastToFirstPoint )
74 , m_bConnectLastToFirstPoint( bConnectLastToFirstPoint )
75 , m_bExpandIfValuesCloseToBorder( bExpandIfValuesCloseToBorder )
76 , m_nKeepAspectRatio(nKeepAspectRatio)
77 , m_aGivenAspectRatio(rAspectRatio)
78 , m_eCurveStyle(CurveStyle_LINES)
79 , m_nCurveResolution(20)
80 , m_nSplineOrder(3)
81 , m_xSeriesTarget(0)
82 , m_xErrorBarTarget(0)
83 , m_xTextTarget(0)
84 , m_xRegressionCurveEquationTarget(0)
86 if( !m_pMainPosHelper )
87 m_pMainPosHelper = new PlottingPositionHelper();
88 if( m_pMainPosHelper )
90 m_pMainPosHelper->AllowShiftXAxisPos(true);
91 m_pMainPosHelper->AllowShiftZAxisPos(true);
93 PlotterBase::m_pPosHelper = m_pMainPosHelper;
94 VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
96 try
98 if( m_xChartTypeModelProps.is() )
100 m_xChartTypeModelProps->getPropertyValue("CurveStyle") >>= m_eCurveStyle;
101 m_xChartTypeModelProps->getPropertyValue("CurveResolution") >>= m_nCurveResolution;
102 m_xChartTypeModelProps->getPropertyValue("SplineOrder") >>= m_nSplineOrder;
105 catch( uno::Exception& e )
107 //the above properties are not supported by all charttypes supported by this class (e.g. area or net chart)
108 //in that cases this exception is ok
109 e.Context.is();//to have debug information without compilation warnings
113 AreaChart::~AreaChart()
115 delete m_pMainPosHelper;
118 double AreaChart::getMaximumX()
120 double fMax = VSeriesPlotter::getMaximumX();
121 if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling
122 fMax += 1.0;
123 return fMax;
126 bool AreaChart::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
128 return m_bExpandIfValuesCloseToBorder &&
129 VSeriesPlotter::isExpandIfValuesCloseToBorder( nDimensionIndex );
132 bool AreaChart::isSeparateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
134 // no separate stacking in all types of line/area charts
135 return false;
138 //-----------------------------------------------------------------
140 LegendSymbolStyle AreaChart::getLegendSymbolStyle()
142 if( m_bArea || m_nDimension == 3 )
143 return LegendSymbolStyle_BOX;
144 return LegendSymbolStyle_LINE;
147 uno::Any AreaChart::getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex )
149 uno::Any aRet;
151 Symbol* pSymbolProperties = rSeries.getSymbolProperties( nPointIndex );
152 if( pSymbolProperties )
154 aRet = uno::makeAny(*pSymbolProperties);
157 return aRet;
160 drawing::Direction3D AreaChart::getPreferredDiagramAspectRatio() const
162 if( m_nKeepAspectRatio == 1 )
163 return m_aGivenAspectRatio;
164 drawing::Direction3D aRet(1,-1,1);
165 if( m_nDimension == 2 )
166 aRet = drawing::Direction3D(-1,-1,-1);
167 else
169 drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
170 aRet.DirectionZ = aScale.DirectionZ*0.2;
171 if(aRet.DirectionZ>1.0)
172 aRet.DirectionZ=1.0;
173 if(aRet.DirectionZ>10)
174 aRet.DirectionZ=10;
176 return aRet;
179 bool AreaChart::keepAspectRatio() const
181 if( m_nKeepAspectRatio == 0 )
182 return false;
183 if( m_nKeepAspectRatio == 1 )
184 return true;
185 if( m_nDimension == 2 )
187 if( !m_bSymbol )
188 return false;
190 return true;
193 void AreaChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
195 if( m_bArea && !m_bIsPolarCooSys && pSeries )
197 sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment();
198 if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
199 pSeries->setMissingValueTreatment( ::com::sun::star::chart::MissingValueTreatment::USE_ZERO );
201 if( m_nDimension == 3 && !m_bCategoryXAxis )
203 //3D xy always deep
204 OSL_ENSURE( zSlot==-1,"3D xy charts should be deep stacked in model also" );
205 zSlot=-1;
206 xSlot=0;
207 ySlot=0;
209 VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
212 void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, PlottingPositionHelper& rPosHelper )
214 sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength();
215 if(!nPolyCount)
216 return;
218 drawing::PolyPolygonShape3D aTmp;
219 aTmp.SequenceX.realloc(nPolyCount);
220 aTmp.SequenceY.realloc(nPolyCount);
221 aTmp.SequenceZ.realloc(nPolyCount);
223 for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; nPolygonIndex++ )
225 drawing::DoubleSequence* pOuterSourceX = &rPolyPoly.SequenceX.getArray()[nPolygonIndex];
226 drawing::DoubleSequence* pOuterSourceY = &rPolyPoly.SequenceY.getArray()[nPolygonIndex];
227 drawing::DoubleSequence* pOuterSourceZ = &rPolyPoly.SequenceZ.getArray()[nPolygonIndex];
229 drawing::DoubleSequence* pOuterTargetX = &aTmp.SequenceX.getArray()[nPolygonIndex];
230 drawing::DoubleSequence* pOuterTargetY = &aTmp.SequenceY.getArray()[nPolygonIndex];
231 drawing::DoubleSequence* pOuterTargetZ = &aTmp.SequenceZ.getArray()[nPolygonIndex];
233 sal_Int32 nPointCount = pOuterSourceX->getLength();
234 if( !nPointCount )
235 continue;
237 pOuterTargetX->realloc(nPointCount);
238 pOuterTargetY->realloc(nPointCount);
239 pOuterTargetZ->realloc(nPointCount);
241 double* pSourceX = pOuterSourceX->getArray();
242 double* pSourceY = pOuterSourceY->getArray();
243 double* pSourceZ = pOuterSourceZ->getArray();
245 double* pTargetX = pOuterTargetX->getArray();
246 double* pTargetY = pOuterTargetY->getArray();
247 double* pTargetZ = pOuterTargetZ->getArray();
249 //copy first point
250 *pTargetX=*pSourceX++;
251 *pTargetY=*pSourceY++;
252 *pTargetZ=*pSourceZ++;
253 sal_Int32 nTargetPointCount=1;
255 for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ )
257 if( !rPosHelper.isSameForGivenResolution( *pTargetX, *pTargetY, *pTargetZ
258 , *pSourceX, *pSourceY, *pSourceZ ) )
260 pTargetX++; pTargetY++; pTargetZ++;
261 *pTargetX=*pSourceX;
262 *pTargetY=*pSourceY;
263 *pTargetZ=*pSourceZ;
264 nTargetPointCount++;
266 pSourceX++; pSourceY++; pSourceZ++;
269 //free unused space
270 if( nTargetPointCount<nPointCount )
272 pOuterTargetX->realloc(nTargetPointCount);
273 pOuterTargetY->realloc(nTargetPointCount);
274 pOuterTargetZ->realloc(nTargetPointCount);
277 pOuterSourceX->realloc(0);
278 pOuterSourceY->realloc(0);
279 pOuterSourceZ->realloc(0);
282 //free space
283 rPolyPoly.SequenceX.realloc(nPolyCount);
284 rPolyPoly.SequenceY.realloc(nPolyCount);
285 rPolyPoly.SequenceZ.realloc(nPolyCount);
287 rPolyPoly=aTmp;
290 bool AreaChart::create_stepped_line( drawing::PolyPolygonShape3D aStartPoly, chart2::CurveStyle eCurveStyle, PlottingPositionHelper* pPosHelper, drawing::PolyPolygonShape3D &aPoly )
292 drawing::PolyPolygonShape3D aSteppedPoly;
294 aSteppedPoly.SequenceX.realloc(0);
295 aSteppedPoly.SequenceY.realloc(0);
296 aSteppedPoly.SequenceZ.realloc(0);
298 sal_uInt32 nOuterCount = aStartPoly.SequenceX.getLength();
299 if ( !nOuterCount )
300 return false;
302 aSteppedPoly.SequenceX.realloc(nOuterCount);
303 aSteppedPoly.SequenceY.realloc(nOuterCount);
304 aSteppedPoly.SequenceZ.realloc(nOuterCount);
305 for( sal_uInt32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
307 if( aStartPoly.SequenceX[nOuter].getLength() <= 1 )
308 continue; //we need at least two points
310 sal_uInt32 nMaxIndexPoints = aStartPoly.SequenceX[nOuter].getLength()-1; // is >1
311 sal_uInt32 nNewIndexPoints = 0;
312 if ( CurveStyle_STEP_START==eCurveStyle || CurveStyle_STEP_END==eCurveStyle)
313 nNewIndexPoints = nMaxIndexPoints * 2 + 1;
314 else
315 nNewIndexPoints = nMaxIndexPoints * 3 + 1;
317 const double* pOldX = aStartPoly.SequenceX[nOuter].getConstArray();
318 const double* pOldY = aStartPoly.SequenceY[nOuter].getConstArray();
319 const double* pOldZ = aStartPoly.SequenceZ[nOuter].getConstArray();
321 aSteppedPoly.SequenceX[nOuter].realloc( nNewIndexPoints );
322 aSteppedPoly.SequenceY[nOuter].realloc( nNewIndexPoints );
323 aSteppedPoly.SequenceZ[nOuter].realloc( nNewIndexPoints );
325 double* pNewX = aSteppedPoly.SequenceX[nOuter].getArray();
326 double* pNewY = aSteppedPoly.SequenceY[nOuter].getArray();
327 double* pNewZ = aSteppedPoly.SequenceZ[nOuter].getArray();
329 pNewX[0] = pOldX[0];
330 pNewY[0] = pOldY[0];
331 pNewZ[0] = pOldZ[0];
332 for( sal_uInt32 oi = 0; oi < nMaxIndexPoints; oi++ )
334 switch ( eCurveStyle )
336 case CurveStyle_STEP_START:
337 /** O
341 O-----+
343 // create the intermediate point
344 pNewX[1+oi*2] = pOldX[oi+1];
345 pNewY[1+oi*2] = pOldY[oi];
346 pNewZ[1+oi*2] = pOldZ[oi];
347 // and now the normal one
348 pNewX[1+oi*2+1] = pOldX[oi+1];
349 pNewY[1+oi*2+1] = pOldY[oi+1];
350 pNewZ[1+oi*2+1] = pOldZ[oi+1];
351 break;
352 case CurveStyle_STEP_END:
353 /** +------O
359 // create the intermediate point
360 pNewX[1+oi*2] = pOldX[oi];
361 pNewY[1+oi*2] = pOldY[oi+1];
362 pNewZ[1+oi*2] = pOldZ[oi];
363 // and now the normal one
364 pNewX[1+oi*2+1] = pOldX[oi+1];
365 pNewY[1+oi*2+1] = pOldY[oi+1];
366 pNewZ[1+oi*2+1] = pOldZ[oi+1];
367 break;
368 case CurveStyle_STEP_CENTER_X:
369 /** +--O
373 O--+
375 // create the first intermediate point
376 pNewX[1+oi*3] = (pOldX[oi]+pOldX[oi+1])/2;
377 pNewY[1+oi*3] = pOldY[oi];
378 pNewZ[1+oi*3] = pOldZ[oi];
379 // create the second intermediate point
380 pNewX[1+oi*3+1] = (pOldX[oi]+pOldX[oi+1])/2;
381 pNewY[1+oi*3+1] = pOldY[oi+1];
382 pNewZ[1+oi*3+1] = pOldZ[oi];
383 // and now the normal one
384 pNewX[1+oi*3+2] = pOldX[oi+1];
385 pNewY[1+oi*3+2] = pOldY[oi+1];
386 pNewZ[1+oi*3+2] = pOldZ[oi+1];
387 break;
388 case CurveStyle_STEP_CENTER_Y:
389 /** O
391 +-----+
395 // create the first intermediate point
396 pNewX[1+oi*3] = pOldX[oi];
397 pNewY[1+oi*3] = (pOldY[oi]+pOldY[oi+1])/2;
398 pNewZ[1+oi*3] = pOldZ[oi];
399 // create the second intermediate point
400 pNewX[1+oi*3+1] = pOldX[oi+1];
401 pNewY[1+oi*3+1] = (pOldY[oi]+pOldY[oi+1])/2;
402 pNewZ[1+oi*3+1] = pOldZ[oi];
403 // and now the normal one
404 pNewX[1+oi*3+2] = pOldX[oi+1];
405 pNewY[1+oi*3+2] = pOldY[oi+1];
406 pNewZ[1+oi*3+2] = pOldZ[oi+1];
407 break;
408 default:
409 // this should never be executed
410 OSL_FAIL("Unknown curvestyle in AreaChart::create_stepped_line");
414 Clipping::clipPolygonAtRectangle( aSteppedPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
416 return true;
419 bool AreaChart::impl_createLine( VDataSeries* pSeries
420 , drawing::PolyPolygonShape3D* pSeriesPoly
421 , PlottingPositionHelper* pPosHelper )
423 //return true if a line was created successfully
424 uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
426 drawing::PolyPolygonShape3D aPoly;
427 if(CurveStyle_CUBIC_SPLINES==m_eCurveStyle)
429 drawing::PolyPolygonShape3D aSplinePoly;
430 SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution );
431 lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
432 Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
434 else if(CurveStyle_B_SPLINES==m_eCurveStyle)
436 drawing::PolyPolygonShape3D aSplinePoly;
437 SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution, m_nSplineOrder );
438 lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
439 Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
441 else if (CurveStyle_STEP_START==m_eCurveStyle ||
442 CurveStyle_STEP_END==m_eCurveStyle ||
443 CurveStyle_STEP_CENTER_Y==m_eCurveStyle ||
444 CurveStyle_STEP_CENTER_X==m_eCurveStyle
447 if (!create_stepped_line(*pSeriesPoly, m_eCurveStyle, pPosHelper, aPoly))
449 return false;
452 else
453 { // default to creating a straight line
454 SAL_WARN_IF(CurveStyle_LINES != m_eCurveStyle, "chart2.areachart", "Unknown curve style");
455 bool bIsClipped = false;
456 if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
458 // do NOT connect last and first point, if one is NAN, and NAN handling is NAN_AS_GAP
459 double fFirstY = pSeries->getYValue( 0 );
460 double fLastY = pSeries->getYValue( VSeriesPlotter::getPointCount() - 1 );
461 if( (pSeries->getMissingValueTreatment() != ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
462 || (::rtl::math::isFinite( fFirstY ) && ::rtl::math::isFinite( fLastY )) )
464 // connect last point in last polygon with first point in first polygon
465 ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() );
466 drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly);
467 drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]);
468 // add connector line to last polygon
469 AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->SequenceX.getLength() - 1 );
470 Clipping::clipPolygonAtRectangle( aTmpPoly, aScaledLogicClipDoubleRect, aPoly );
471 bIsClipped = true;
475 if( !bIsClipped )
476 Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
479 if(!ShapeFactory::hasPolygonAnyLines(aPoly))
480 return false;
482 //transformation 3) -> 4)
483 pPosHelper->transformScaledLogicToScene( aPoly );
485 //create line:
486 uno::Reference< drawing::XShape > xShape(NULL);
487 if(m_nDimension==3)
489 double fDepth = this->getTransformedDepth();
490 sal_Int32 nPolyCount = aPoly.SequenceX.getLength();
491 for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++)
493 sal_Int32 nPointCount = aPoly.SequenceX[nPoly].getLength();
494 for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++)
496 drawing::Position3D aPoint1, aPoint2;
497 aPoint1.PositionX = aPoly.SequenceX[nPoly][nPoint+1];
498 aPoint1.PositionY = aPoly.SequenceY[nPoly][nPoint+1];
499 aPoint1.PositionZ = aPoly.SequenceZ[nPoly][nPoint+1];
501 aPoint2.PositionX = aPoly.SequenceX[nPoly][nPoint];
502 aPoint2.PositionY = aPoly.SequenceY[nPoly][nPoint];
503 aPoint2.PositionZ = aPoly.SequenceZ[nPoly][nPoint];
505 Stripe aStripe( aPoint1, aPoint2, fDepth );
507 m_pShapeFactory->createStripe(xSeriesGroupShape_Shapes
508 , Stripe( aPoint1, aPoint2, fDepth )
509 , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 );
513 else //m_nDimension!=3
515 xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes
516 , PolyToPointSequence( aPoly ) );
517 this->setMappedProperties( xShape
518 , pSeries->getPropertiesOfSeries()
519 , PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
520 //because of this name this line will be used for marking
521 m_pShapeFactory->setShapeName(xShape, "MarkHandles");
523 return true;
526 bool AreaChart::impl_createArea( VDataSeries* pSeries
527 , drawing::PolyPolygonShape3D* pSeriesPoly
528 , drawing::PolyPolygonShape3D* pPreviousSeriesPoly
529 , PlottingPositionHelper* pPosHelper )
531 //return true if an area was created successfully
533 uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
534 double zValue = pSeries->m_fLogicZPos;
536 drawing::PolyPolygonShape3D aPoly( *pSeriesPoly );
537 //add second part to the polygon (grounding points or previous series points)
538 if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
540 if( pPreviousSeriesPoly )
541 addPolygon( aPoly, *pPreviousSeriesPoly );
543 else if(!pPreviousSeriesPoly)
545 double fMinX = pSeries->m_fLogicMinX;
546 double fMaxX = pSeries->m_fLogicMaxX;
547 double fY = pPosHelper->getBaseValueY();//logic grounding
548 if( m_nDimension==3 )
549 fY = pPosHelper->getLogicMinY();
551 //clip to scale
552 if(fMaxX<pPosHelper->getLogicMinX() || fMinX>pPosHelper->getLogicMaxX())
553 return false;//no visible shape needed
554 pPosHelper->clipLogicValues( &fMinX, &fY, 0 );
555 pPosHelper->clipLogicValues( &fMaxX, 0, 0 );
557 //apply scaling
559 pPosHelper->doLogicScaling( &fMinX, &fY, &zValue );
560 pPosHelper->doLogicScaling( &fMaxX, 0, 0 );
563 AddPointToPoly( aPoly, drawing::Position3D( fMaxX,fY,zValue) );
564 AddPointToPoly( aPoly, drawing::Position3D( fMinX,fY,zValue) );
566 else
568 appendPoly( aPoly, *pPreviousSeriesPoly );
570 ShapeFactory::closePolygon(aPoly);
572 //apply clipping
574 drawing::PolyPolygonShape3D aClippedPoly;
575 Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
576 ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping
577 aPoly = aClippedPoly;
580 if(!ShapeFactory::hasPolygonAnyLines(aPoly))
581 return false;
583 //transformation 3) -> 4)
584 pPosHelper->transformScaledLogicToScene( aPoly );
586 //create area:
587 uno::Reference< drawing::XShape > xShape(NULL);
588 if(m_nDimension==3)
590 xShape = m_pShapeFactory->createArea3D( xSeriesGroupShape_Shapes
591 , aPoly, this->getTransformedDepth() );
593 else //m_nDimension!=3
595 xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes
596 , aPoly );
598 this->setMappedProperties( xShape
599 , pSeries->getPropertiesOfSeries()
600 , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
601 //because of this name this line will be used for marking
602 m_pShapeFactory->setShapeName(xShape, "MarkHandles");
603 return true;
606 void AreaChart::impl_createSeriesShapes()
608 //the polygon shapes for each series need to be created before
610 //iterate through all series again to create the series shapes
611 ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
612 const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
613 //=============================================================================
614 for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, ++nZ )
616 ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
617 const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
619 //=============================================================================
620 for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
622 ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
624 ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
625 const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
626 //=============================================================================
628 std::map< sal_Int32, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex
629 drawing::PolyPolygonShape3D* pSeriesPoly = NULL;
631 //iterate through all series
632 for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
634 sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
635 PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
636 if(!pPosHelper)
637 pPosHelper = m_pMainPosHelper;
638 PlotterBase::m_pPosHelper = pPosHelper;
640 createRegressionCurvesShapes( **aSeriesIter, m_xErrorBarTarget, m_xRegressionCurveEquationTarget,
641 m_pPosHelper->maySkipPointsInRegressionCalculation());
643 pSeriesPoly = &(*aSeriesIter)->m_aPolyPolygonShape3D;
644 if( m_bArea )
646 if( !impl_createArea( *aSeriesIter, pSeriesPoly, aPreviousSeriesPolyMap[nAttachedAxisIndex], pPosHelper ) )
647 continue;
649 if( m_bLine )
651 if( !impl_createLine( *aSeriesIter, pSeriesPoly, pPosHelper ) )
652 continue;
654 aPreviousSeriesPolyMap[nAttachedAxisIndex] = pSeriesPoly;
655 }//next series in x slot (next y slot)
656 }//next x slot
657 }//next z slot
660 namespace
663 void lcl_reorderSeries( ::std::vector< ::std::vector< VDataSeriesGroup > >& rZSlots )
665 ::std::vector< ::std::vector< VDataSeriesGroup > > aRet( rZSlots.size() );
667 ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZIt( rZSlots.rbegin() );
668 ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZEnd( rZSlots.rend() );
669 for( ; aZIt != aZEnd; ++aZIt )
671 ::std::vector< VDataSeriesGroup > aXSlot( aZIt->size() );
673 ::std::vector< VDataSeriesGroup >::reverse_iterator aXIt( aZIt->rbegin() );
674 ::std::vector< VDataSeriesGroup >::reverse_iterator aXEnd( aZIt->rend() );
675 for( ; aXIt != aXEnd; ++aXIt )
676 aXSlot.push_back(*aXIt);
678 aRet.push_back(aXSlot);
681 rZSlots.clear();
682 rZSlots = aRet;
685 }//anonymous namespace
687 //better performance for big data
688 struct FormerPoint
690 FormerPoint( double fX, double fY, double fZ )
691 : m_fX(fX), m_fY(fY), m_fZ(fZ)
693 FormerPoint()
695 ::rtl::math::setNan( &m_fX );
696 ::rtl::math::setNan( &m_fY );
697 ::rtl::math::setNan( &m_fZ );
700 double m_fX;
701 double m_fY;
702 double m_fZ;
705 void AreaChart::createShapes()
707 if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
708 return;
710 if( m_nDimension == 2 && ( m_bArea || !m_bCategoryXAxis ) )
711 lcl_reorderSeries( m_aZSlots );
713 OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized");
714 if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
715 return;
717 //the text labels should be always on top of the other series shapes
718 //for area chart the error bars should be always on top of the other series shapes
720 //therefore create an own group for the texts and the error bars to move them to front
721 //(because the text group is created after the series group the texts are displayed on top)
722 m_xSeriesTarget = createGroupShape( m_xLogicTarget,OUString() );
723 if( m_bArea )
724 m_xErrorBarTarget = createGroupShape( m_xLogicTarget,OUString() );
725 else
726 m_xErrorBarTarget = m_xSeriesTarget;
727 m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,OUString() );
728 m_xRegressionCurveEquationTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,OUString() );
730 //---------------------------------------------
731 //check necessary here that different Y axis can not be stacked in the same group? ... hm?
733 //update/create information for current group
734 double fLogicZ = 1.0;//as defined
736 sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale
737 sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
738 if(nEndIndex<=0)
739 nEndIndex=1;
741 //better performance for big data
742 std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
743 m_bPointsWereSkipped = false;
744 sal_Int32 nSkippedPoints = 0;
745 sal_Int32 nCreatedPoints = 0;
748 bool bDateCategory = (m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis());
750 //=============================================================================
751 //iterate through all x values per indices
752 for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
754 ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
755 const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
757 std::map< sal_Int32, double > aLogicYSumMap;//one for each different nAttachedAxisIndex
758 for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
760 ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
761 const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
763 //iterate through all x slots in this category to get 100percent sum
764 for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
766 std::vector<VDataSeries*>& rSeriesList = aXSlotIter->m_aSeriesVector;
767 std::vector<VDataSeries*>::iterator aSeriesIter = rSeriesList.begin();
768 const std::vector<VDataSeries*>::iterator aSeriesEnd = rSeriesList.end();
770 for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
772 VDataSeries* pSeries( *aSeriesIter );
773 if(!pSeries)
774 continue;
776 if (bDateCategory)
777 pSeries->doSortByXValues();
779 sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
780 if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
781 aLogicYSumMap[nAttachedAxisIndex]=0.0;
783 PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
784 if(!pPosHelper)
785 pPosHelper = m_pMainPosHelper;
786 PlotterBase::m_pPosHelper = pPosHelper;
788 double fAdd = pSeries->getYValue( nIndex );
789 if( !::rtl::math::isNan(fAdd) && !::rtl::math::isInf(fAdd) )
790 aLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd );
795 //=============================================================================
796 aZSlotIter = m_aZSlots.begin();
797 for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, ++nZ )
799 ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
800 const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
802 //for the area chart there should be at most one x slot (no side by side stacking available)
803 //attention different: xSlots are always interpreted as independent areas one behind the other: @todo this doesn't work why not???
804 for( sal_Int32 nX=0; aXSlotIter != aXSlotEnd; ++aXSlotIter, ++nX )
806 std::vector<VDataSeries*>& rSeriesList = aXSlotIter->m_aSeriesVector;
807 std::vector<VDataSeries*>::const_iterator aSeriesIter = rSeriesList.begin();
808 const std::vector<VDataSeries*>::const_iterator aSeriesEnd = rSeriesList.end();
810 std::map< sal_Int32, double > aLogicYForNextSeriesMap;//one for each different nAttachedAxisIndex
811 //=============================================================================
812 //iterate through all series
813 for( sal_Int32 nSeriesIndex = 0; aSeriesIter != aSeriesEnd; ++aSeriesIter, ++nSeriesIndex )
815 VDataSeries* pSeries( *aSeriesIter );
816 if(!pSeries)
817 continue;
819 /* #i70133# ignore points outside of series length in standard area
820 charts. Stacked area charts will use missing points as zeros. In
821 standard charts, pSeriesList contains only one series. */
822 if( m_bArea && (rSeriesList.size() == 1) && (nIndex >= (*aSeriesIter)->getTotalPointCount()) )
823 continue;
825 uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(*aSeriesIter, m_xSeriesTarget);
827 sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
828 PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
829 if(!pPosHelper)
830 pPosHelper = m_pMainPosHelper;
831 PlotterBase::m_pPosHelper = pPosHelper;
833 if(m_nDimension==3)
834 fLogicZ = nZ+0.5;
835 (*aSeriesIter)->m_fLogicZPos = fLogicZ;
837 //collect data point information (logic coordinates, style ):
838 double fLogicX = (*aSeriesIter)->getXValue(nIndex);
839 if (bDateCategory)
840 fLogicX = DateHelper::RasterizeDateValue( fLogicX, m_aNullDate, m_nTimeResolution );
841 double fLogicY = (*aSeriesIter)->getYValue(nIndex);
843 if( m_bIsPolarCooSys && m_bArea &&
844 ( ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) ) )
846 if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
848 if( rSeriesList.size() == 1 || nSeriesIndex == 0 )
850 fLogicY = pPosHelper->getLogicMinY();
851 if( !pPosHelper->isMathematicalOrientationY() )
852 fLogicY = pPosHelper->getLogicMaxY();
854 else
855 fLogicY = 0.0;
859 if( m_nDimension==3 && m_bArea && rSeriesList.size()!=1 )
860 fLogicY = fabs( fLogicY );
862 if( pPosHelper->isPercentY() && !::rtl::math::approxEqual( aLogicYSumMap[nAttachedAxisIndex], 0.0 ) )
864 fLogicY = fabs( fLogicY )/aLogicYSumMap[nAttachedAxisIndex];
867 if( ::rtl::math::isNan(fLogicX) || ::rtl::math::isInf(fLogicX)
868 || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY)
869 || ::rtl::math::isNan(fLogicZ) || ::rtl::math::isInf(fLogicZ) )
871 if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
873 drawing::PolyPolygonShape3D& rPolygon = (*aSeriesIter)->m_aPolyPolygonShape3D;
874 sal_Int32& rIndex = (*aSeriesIter)->m_nPolygonIndex;
875 if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() )
877 if( rPolygon.SequenceX[ rIndex ].getLength() )
878 rIndex++; //start a new polygon for the next point if the current poly is not empty
881 continue;
884 if( aLogicYForNextSeriesMap.find(nAttachedAxisIndex) == aLogicYForNextSeriesMap.end() )
885 aLogicYForNextSeriesMap[nAttachedAxisIndex] = 0.0;
887 double fLogicValueForLabeDisplay = fLogicY;
889 fLogicY += aLogicYForNextSeriesMap[nAttachedAxisIndex];
890 aLogicYForNextSeriesMap[nAttachedAxisIndex] = fLogicY;
892 bool bIsVisible = pPosHelper->isLogicVisible( fLogicX, fLogicY, fLogicZ );
894 //remind minimal and maximal x values for area 'grounding' points
895 //only for filled area
897 double& rfMinX = (*aSeriesIter)->m_fLogicMinX;
898 if(!nIndex||fLogicX<rfMinX)
899 rfMinX=fLogicX;
900 double& rfMaxX = (*aSeriesIter)->m_fLogicMaxX;
901 if(!nIndex||fLogicX>rfMaxX)
902 rfMaxX=fLogicX;
905 drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
906 drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
907 pPosHelper->doLogicScaling( aScaledLogicPosition );
909 //transformation 3) -> 4)
910 drawing::Position3D aScenePosition( pPosHelper->transformLogicToScene( fLogicX,fLogicY,fLogicZ, false ) );
912 //better performance for big data
913 FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
914 pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
915 if( !pSeries->isAttributedDataPoint(nIndex)
917 pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ
918 , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) )
920 ++nSkippedPoints;
921 m_bPointsWereSkipped = true;
922 continue;
924 aSeriesFormerPointMap[pSeries] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
927 //store point information for series polygon
928 //for area and/or line (symbols only do not need this)
929 if( isValidPosition(aScaledLogicPosition) )
931 AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
933 //prepare clipping for filled net charts
934 if( !bIsVisible && m_bIsPolarCooSys && m_bArea )
936 drawing::Position3D aClippedPos(aScaledLogicPosition);
937 pPosHelper->clipScaledLogicValues( 0, &aClippedPos.PositionY, 0 );
938 if( pPosHelper->isLogicVisible( aClippedPos.PositionX, aClippedPos.PositionY, aClippedPos.PositionZ ) )
940 AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aClippedPos, (*aSeriesIter)->m_nPolygonIndex );
941 AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
946 //create a single datapoint if point is visible
947 //apply clipping:
948 if( !bIsVisible )
949 continue;
951 bool bCreateYErrorBar = false, bCreateXErrorBar = false;
953 uno::Reference< beans::XPropertySet > xErrorBarProp(pSeries->getYErrorBarProperties(nIndex));
954 if( xErrorBarProp.is() )
956 bool bShowPositive = false;
957 bool bShowNegative = false;
958 xErrorBarProp->getPropertyValue("ShowPositiveError") >>= bShowPositive;
959 xErrorBarProp->getPropertyValue("ShowNegativeError") >>= bShowNegative;
960 bCreateYErrorBar = bShowPositive || bShowNegative;
963 xErrorBarProp = pSeries->getXErrorBarProperties(nIndex);
964 if ( xErrorBarProp.is() )
966 bool bShowPositive = false;
967 bool bShowNegative = false;
968 xErrorBarProp->getPropertyValue("ShowPositiveError") >>= bShowPositive;
969 xErrorBarProp->getPropertyValue("ShowNegativeError") >>= bShowNegative;
970 bCreateXErrorBar = bShowPositive || bShowNegative;
974 Symbol* pSymbolProperties = m_bSymbol ? (*aSeriesIter)->getSymbolProperties( nIndex ) : 0;
975 bool bCreateSymbol = pSymbolProperties && (pSymbolProperties->Style != SymbolStyle_NONE);
977 if( !bCreateSymbol && !bCreateYErrorBar &&
978 !bCreateXErrorBar && !pSeries->getDataPointLabelIfLabel(nIndex) )
979 continue;
981 //create a group shape for this point and add to the series shape:
982 OUString aPointCID = ObjectIdentifier::createPointCID(
983 (*aSeriesIter)->getPointCID_Stub(), nIndex );
984 uno::Reference< drawing::XShapes > xPointGroupShape_Shapes(
985 createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
986 uno::Reference<drawing::XShape> xPointGroupShape_Shape =
987 uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
990 nCreatedPoints++;
992 //create data point
993 drawing::Direction3D aSymbolSize(0,0,0);
994 if( bCreateSymbol )
996 if(m_nDimension!=3)
998 if( pSymbolProperties )
1000 if( pSymbolProperties->Style != SymbolStyle_NONE )
1002 aSymbolSize.DirectionX = pSymbolProperties->Size.Width;
1003 aSymbolSize.DirectionY = pSymbolProperties->Size.Height;
1006 if( pSymbolProperties->Style == SymbolStyle_STANDARD )
1008 sal_Int32 nSymbol = pSymbolProperties->StandardSymbol;
1009 m_pShapeFactory->createSymbol2D( xPointGroupShape_Shapes
1010 , aScenePosition, aSymbolSize
1011 , nSymbol
1012 , pSymbolProperties->BorderColor
1013 , pSymbolProperties->FillColor );
1015 else if( pSymbolProperties->Style == SymbolStyle_GRAPHIC )
1017 m_pShapeFactory->createGraphic2D( xPointGroupShape_Shapes
1018 , aScenePosition , aSymbolSize
1019 , pSymbolProperties->Graphic );
1021 //@todo other symbol styles
1025 //create error bars
1026 if (bCreateXErrorBar)
1027 createErrorBar_X( aUnscaledLogicPosition, **aSeriesIter, nIndex, m_xErrorBarTarget );
1029 if (bCreateYErrorBar)
1030 createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nIndex, m_xErrorBarTarget );
1032 //create data point label
1033 if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) )
1035 LabelAlignment eAlignment = LABEL_ALIGN_TOP;
1036 drawing::Position3D aScenePosition3D( aScenePosition.PositionX
1037 , aScenePosition.PositionY
1038 , aScenePosition.PositionZ+this->getTransformedDepth() );
1040 sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
1042 switch(nLabelPlacement)
1044 case ::com::sun::star::chart::DataLabelPlacement::TOP:
1045 aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
1046 eAlignment = LABEL_ALIGN_TOP;
1047 break;
1048 case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
1049 aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
1050 eAlignment = LABEL_ALIGN_BOTTOM;
1051 break;
1052 case ::com::sun::star::chart::DataLabelPlacement::LEFT:
1053 aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
1054 eAlignment = LABEL_ALIGN_LEFT;
1055 break;
1056 case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
1057 aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
1058 eAlignment = LABEL_ALIGN_RIGHT;
1059 break;
1060 case ::com::sun::star::chart::DataLabelPlacement::CENTER:
1061 eAlignment = LABEL_ALIGN_CENTER;
1062 //todo implement this different for area charts
1063 break;
1064 default:
1065 OSL_FAIL("this label alignment is not implemented yet");
1066 aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
1067 eAlignment = LABEL_ALIGN_TOP;
1068 break;
1071 awt::Point aScreenPosition2D;//get the screen position for the labels
1072 sal_Int32 nOffset = 100; //todo maybe calculate this font height dependent
1073 if( m_bIsPolarCooSys && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE )
1075 PolarPlottingPositionHelper* pPolarPosHelper = dynamic_cast<PolarPlottingPositionHelper*>(pPosHelper);
1076 if( pPolarPosHelper )
1078 PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory);
1079 aScreenPosition2D = awt::Point( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
1080 eAlignment, fLogicX, fLogicY, fLogicZ, nOffset ));
1083 else
1085 if(LABEL_ALIGN_CENTER==eAlignment || m_nDimension == 3 )
1086 nOffset = 0;
1087 aScreenPosition2D = awt::Point( LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
1088 .transformSceneToScreenPosition( aScenePosition3D ) );
1091 this->createDataLabel( m_xTextTarget, **aSeriesIter, nIndex
1092 , fLogicValueForLabeDisplay
1093 , aLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset );
1097 //remove PointGroupShape if empty
1098 if(!xPointGroupShape_Shapes->getCount())
1099 xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape);
1101 }//next series in x slot (next y slot)
1102 }//next x slot
1103 }//next z slot
1104 }//next category
1105 //=============================================================================
1106 //=============================================================================
1107 //=============================================================================
1109 impl_createSeriesShapes();
1111 /* @todo remove series shapes if empty
1112 //remove and delete point-group-shape if empty
1113 if(!xSeriesGroupShape_Shapes->getCount())
1115 (*aSeriesIter)->m_xShape.set(NULL);
1116 m_xLogicTarget->remove(xSeriesGroupShape_Shape);
1120 //remove and delete series-group-shape if empty
1122 //... todo
1124 OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< area chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
1127 //.............................................................................
1128 } //namespace chart
1129 //.............................................................................
1131 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */