Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
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"
34 : :
35 : : #include <com/sun/star/chart2/Symbol.hpp>
36 : : #include <com/sun/star/chart/DataLabelPlacement.hpp>
37 : : #include <com/sun/star/chart/MissingValueTreatment.hpp>
38 : :
39 : : #include <editeng/unoprnms.hxx>
40 : : #include <rtl/math.hxx>
41 : :
42 : : #include <com/sun/star/drawing/DoubleSequence.hpp>
43 : : #include <com/sun/star/drawing/NormalsKind.hpp>
44 : : #include <com/sun/star/lang/XServiceName.hpp>
45 : :
46 : : //.............................................................................
47 : : namespace chart
48 : : {
49 : : //.............................................................................
50 : : using namespace ::com::sun::star;
51 : : using namespace ::rtl::math;
52 : : using namespace ::com::sun::star::chart2;
53 : :
54 : : //-----------------------------------------------------------------------------
55 : : //-----------------------------------------------------------------------------
56 : : //-----------------------------------------------------------------------------
57 : :
58 : 72 : 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
67 : : )
68 : : : VSeriesPlotter( xChartTypeModel, nDimensionCount, bCategoryXAxis )
69 : : , m_pMainPosHelper(pPlottingPositionHelper)
70 : 72 : , m_bArea(!bNoArea)
71 : : , m_bLine(bNoArea)
72 [ + - ]: 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 [ + - ][ + - ]: 144 : , m_xRegressionCurveEquationTarget(0)
[ + - ][ + - ]
85 : : {
86 [ + - ]: 72 : if( !m_pMainPosHelper )
87 [ + - ][ + - ]: 72 : m_pMainPosHelper = new PlottingPositionHelper();
88 [ + - ]: 72 : if( m_pMainPosHelper )
89 : : {
90 [ + - ]: 72 : m_pMainPosHelper->AllowShiftXAxisPos(true);
91 [ + - ]: 72 : m_pMainPosHelper->AllowShiftZAxisPos(true);
92 : : }
93 : 72 : PlotterBase::m_pPosHelper = m_pMainPosHelper;
94 : 72 : VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
95 : :
96 : : try
97 : : {
98 [ + - ]: 72 : if( m_xChartTypeModelProps.is() )
99 : : {
100 [ + - ][ + - ]: 72 : m_xChartTypeModelProps->getPropertyValue( C2U( "CurveStyle" ) ) >>= m_eCurveStyle;
[ + - ][ + - ]
101 [ + - ][ + - ]: 72 : m_xChartTypeModelProps->getPropertyValue( C2U( "CurveResolution" ) ) >>= m_nCurveResolution;
[ + - ]
102 [ + - ][ + - ]: 72 : m_xChartTypeModelProps->getPropertyValue( C2U( "SplineOrder" ) ) >>= m_nSplineOrder;
[ # # ][ + - ]
103 : : }
104 : : }
105 [ # # ]: 0 : catch( uno::Exception& e )
106 : : {
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 : 0 : e.Context.is();//to have debug information without compilation warnings
110 : : }
111 : 72 : }
112 : :
113 : 72 : AreaChart::~AreaChart()
114 : : {
115 [ + - ][ + - ]: 72 : delete m_pMainPosHelper;
116 [ - + ]: 144 : }
117 : :
118 : 158 : double AreaChart::getMaximumX()
119 : : {
120 : 158 : double fMax = VSeriesPlotter::getMaximumX();
121 [ - + ][ + - ]: 158 : if( m_bCategoryXAxis && m_bIsPolarCooSys )//the angle axis in net charts needs a different autoscaling
122 : 0 : fMax += 1.0;
123 : 158 : return fMax;
124 : : }
125 : :
126 : 352 : bool AreaChart::isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex )
127 : : {
128 : : return m_bExpandIfValuesCloseToBorder &&
129 [ + - ][ + + ]: 352 : VSeriesPlotter::isExpandIfValuesCloseToBorder( nDimensionIndex );
130 : : }
131 : :
132 : 1304 : bool AreaChart::isSeperateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ )
133 : : {
134 : : // no separate stacking in all types of line/area charts
135 : 1304 : return false;
136 : : }
137 : :
138 : : //-----------------------------------------------------------------
139 : :
140 : 357 : LegendSymbolStyle AreaChart::getLegendSymbolStyle()
141 : : {
142 [ + - ][ + + ]: 357 : if( m_bArea || m_nDimension == 3 )
143 : 33 : return LegendSymbolStyle_BOX;
144 : 357 : return LegendSymbolStyle_LINE;
145 : : }
146 : :
147 : 296 : uno::Any AreaChart::getExplicitSymbol( const VDataSeries& rSeries, sal_Int32 nPointIndex )
148 : : {
149 : 296 : uno::Any aRet;
150 : :
151 [ + - ]: 296 : Symbol* pSymbolProperties = rSeries.getSymbolProperties( nPointIndex );
152 [ + - ]: 296 : if( pSymbolProperties )
153 : : {
154 [ + - ]: 296 : aRet = uno::makeAny(*pSymbolProperties);
155 : : }
156 : :
157 : 296 : return aRet;
158 : : }
159 : :
160 : 72 : drawing::Direction3D AreaChart::getPreferredDiagramAspectRatio() const
161 : : {
162 [ - + ]: 72 : if( m_nKeepAspectRatio == 1 )
163 : 0 : return m_aGivenAspectRatio;
164 : 72 : drawing::Direction3D aRet(1,-1,1);
165 [ + + ]: 72 : if( m_nDimension == 2 )
166 : 61 : aRet = drawing::Direction3D(-1,-1,-1);
167 : : else
168 : : {
169 [ + - ]: 11 : drawing::Direction3D aScale( m_pPosHelper->getScaledLogicWidth() );
170 : 11 : aRet.DirectionZ = aScale.DirectionZ*0.2;
171 [ - + ]: 11 : if(aRet.DirectionZ>1.0)
172 : 0 : aRet.DirectionZ=1.0;
173 [ - + ]: 11 : if(aRet.DirectionZ>10)
174 : 11 : aRet.DirectionZ=10;
175 : : }
176 : 72 : return aRet;
177 : : }
178 : :
179 : 0 : bool AreaChart::keepAspectRatio() const
180 : : {
181 [ # # ]: 0 : if( m_nKeepAspectRatio == 0 )
182 : 0 : return false;
183 [ # # ]: 0 : if( m_nKeepAspectRatio == 1 )
184 : 0 : return true;
185 [ # # ]: 0 : if( m_nDimension == 2 )
186 : : {
187 [ # # ]: 0 : if( !m_bSymbol )
188 : 0 : return false;
189 : : }
190 : 0 : return true;
191 : : }
192 : :
193 : 296 : void AreaChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
194 : : {
195 [ - + ][ # # ]: 296 : if( m_bArea && !m_bIsPolarCooSys && pSeries )
[ # # ]
196 : : {
197 : 0 : sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment();
198 [ # # ]: 0 : if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
199 : 0 : pSeries->setMissingValueTreatment( ::com::sun::star::chart::MissingValueTreatment::USE_ZERO );
200 : : }
201 [ + + ][ - + ]: 296 : if( m_nDimension == 3 && !m_bCategoryXAxis )
202 : : {
203 : : //3D xy always deep
204 : : OSL_ENSURE( zSlot==-1,"3D xy charts should be deep stacked in model also" );
205 : 0 : zSlot=-1;
206 : 0 : xSlot=0;
207 : 0 : ySlot=0;
208 : : }
209 : 296 : VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
210 : 296 : }
211 : :
212 : 0 : void lcl_removeDuplicatePoints( drawing::PolyPolygonShape3D& rPolyPoly, PlottingPositionHelper& rPosHelper )
213 : : {
214 : 0 : sal_Int32 nPolyCount = rPolyPoly.SequenceX.getLength();
215 [ # # ]: 0 : if(!nPolyCount)
216 : 0 : return;
217 : :
218 [ # # ]: 0 : drawing::PolyPolygonShape3D aTmp;
219 [ # # ]: 0 : aTmp.SequenceX.realloc(nPolyCount);
220 [ # # ]: 0 : aTmp.SequenceY.realloc(nPolyCount);
221 [ # # ]: 0 : aTmp.SequenceZ.realloc(nPolyCount);
222 : :
223 [ # # ]: 0 : for( sal_Int32 nPolygonIndex = 0; nPolygonIndex<nPolyCount; nPolygonIndex++ )
224 : : {
225 [ # # ]: 0 : drawing::DoubleSequence* pOuterSourceX = &rPolyPoly.SequenceX.getArray()[nPolygonIndex];
226 [ # # ]: 0 : drawing::DoubleSequence* pOuterSourceY = &rPolyPoly.SequenceY.getArray()[nPolygonIndex];
227 [ # # ]: 0 : drawing::DoubleSequence* pOuterSourceZ = &rPolyPoly.SequenceZ.getArray()[nPolygonIndex];
228 : :
229 [ # # ]: 0 : drawing::DoubleSequence* pOuterTargetX = &aTmp.SequenceX.getArray()[nPolygonIndex];
230 [ # # ]: 0 : drawing::DoubleSequence* pOuterTargetY = &aTmp.SequenceY.getArray()[nPolygonIndex];
231 [ # # ]: 0 : drawing::DoubleSequence* pOuterTargetZ = &aTmp.SequenceZ.getArray()[nPolygonIndex];
232 : :
233 : 0 : sal_Int32 nPointCount = pOuterSourceX->getLength();
234 [ # # ]: 0 : if( !nPointCount )
235 : 0 : continue;
236 : :
237 [ # # ]: 0 : pOuterTargetX->realloc(nPointCount);
238 [ # # ]: 0 : pOuterTargetY->realloc(nPointCount);
239 [ # # ]: 0 : pOuterTargetZ->realloc(nPointCount);
240 : :
241 [ # # ]: 0 : double* pSourceX = pOuterSourceX->getArray();
242 [ # # ]: 0 : double* pSourceY = pOuterSourceY->getArray();
243 [ # # ]: 0 : double* pSourceZ = pOuterSourceZ->getArray();
244 : :
245 [ # # ]: 0 : double* pTargetX = pOuterTargetX->getArray();
246 [ # # ]: 0 : double* pTargetY = pOuterTargetY->getArray();
247 [ # # ]: 0 : double* pTargetZ = pOuterTargetZ->getArray();
248 : :
249 : : //copy first point
250 : 0 : *pTargetX=*pSourceX++;
251 : 0 : *pTargetY=*pSourceY++;
252 : 0 : *pTargetZ=*pSourceZ++;
253 : 0 : sal_Int32 nTargetPointCount=1;
254 : :
255 [ # # ]: 0 : for( sal_Int32 nSource=1; nSource<nPointCount; nSource++ )
256 : : {
257 [ # # ]: 0 : if( !rPosHelper.isSameForGivenResolution( *pTargetX, *pTargetY, *pTargetZ
258 [ # # ]: 0 : , *pSourceX, *pSourceY, *pSourceZ ) )
259 : : {
260 : 0 : pTargetX++; pTargetY++; pTargetZ++;
261 : 0 : *pTargetX=*pSourceX;
262 : 0 : *pTargetY=*pSourceY;
263 : 0 : *pTargetZ=*pSourceZ;
264 : 0 : nTargetPointCount++;
265 : : }
266 : 0 : pSourceX++; pSourceY++; pSourceZ++;
267 : : }
268 : :
269 : : //free unused space
270 [ # # ]: 0 : if( nTargetPointCount<nPointCount )
271 : : {
272 [ # # ]: 0 : pOuterTargetX->realloc(nTargetPointCount);
273 [ # # ]: 0 : pOuterTargetY->realloc(nTargetPointCount);
274 [ # # ]: 0 : pOuterTargetZ->realloc(nTargetPointCount);
275 : : }
276 : :
277 [ # # ]: 0 : pOuterSourceX->realloc(0);
278 [ # # ]: 0 : pOuterSourceY->realloc(0);
279 [ # # ]: 0 : pOuterSourceZ->realloc(0);
280 : : }
281 : :
282 : : //free space
283 [ # # ]: 0 : rPolyPoly.SequenceX.realloc(nPolyCount);
284 [ # # ]: 0 : rPolyPoly.SequenceY.realloc(nPolyCount);
285 [ # # ]: 0 : rPolyPoly.SequenceZ.realloc(nPolyCount);
286 : :
287 [ # # ][ # # ]: 0 : rPolyPoly=aTmp;
288 : : }
289 : :
290 : 296 : bool AreaChart::impl_createLine( VDataSeries* pSeries
291 : : , drawing::PolyPolygonShape3D* pSeriesPoly
292 : : , PlottingPositionHelper* pPosHelper )
293 : : {
294 : : //return true if a line was created successfully
295 [ + - ]: 296 : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
296 : :
297 [ + - ]: 296 : drawing::PolyPolygonShape3D aPoly;
298 [ - + ]: 296 : if(CurveStyle_CUBIC_SPLINES==m_eCurveStyle)
299 : : {
300 [ # # ]: 0 : drawing::PolyPolygonShape3D aSplinePoly;
301 [ # # ]: 0 : SplineCalculater::CalculateCubicSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution );
302 [ # # ]: 0 : lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
303 [ # # ][ # # ]: 0 : Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
[ # # ]
304 : : }
305 [ - + ]: 296 : else if(CurveStyle_B_SPLINES==m_eCurveStyle)
306 : : {
307 [ # # ]: 0 : drawing::PolyPolygonShape3D aSplinePoly;
308 [ # # ]: 0 : SplineCalculater::CalculateBSplines( *pSeriesPoly, aSplinePoly, m_nCurveResolution, m_nSplineOrder );
309 [ # # ]: 0 : lcl_removeDuplicatePoints( aSplinePoly, *pPosHelper );
310 [ # # ][ # # ]: 0 : Clipping::clipPolygonAtRectangle( aSplinePoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
[ # # ]
311 : : }
312 : : else
313 : : {
314 : 296 : bool bIsClipped = false;
315 [ - + ][ # # ]: 296 : if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
[ # # ][ - + ]
316 : : {
317 : : // do NOT connect last and first point, if one is NAN, and NAN handling is NAN_AS_GAP
318 [ # # ]: 0 : double fFirstY = pSeries->getYValue( 0 );
319 [ # # ][ # # ]: 0 : double fLastY = pSeries->getYValue( VSeriesPlotter::getPointCount() - 1 );
320 [ # # ][ # # : 0 : if( (pSeries->getMissingValueTreatment() != ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
# # # # ]
[ # # ]
321 : 0 : || (::rtl::math::isFinite( fFirstY ) && ::rtl::math::isFinite( fLastY )) )
322 : : {
323 : : // connect last point in last polygon with first point in first polygon
324 [ # # ]: 0 : ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() );
325 [ # # ]: 0 : drawing::PolyPolygonShape3D aTmpPoly(*pSeriesPoly);
326 [ # # ][ # # ]: 0 : drawing::Position3D aLast(aScaledLogicClipDoubleRect.getMaxX(),aTmpPoly.SequenceY[0][0],aTmpPoly.SequenceZ[0][0]);
[ # # ][ # # ]
[ # # ]
327 : : // add connector line to last polygon
328 [ # # ]: 0 : AddPointToPoly( aTmpPoly, aLast, pSeriesPoly->SequenceX.getLength() - 1 );
329 [ # # ]: 0 : Clipping::clipPolygonAtRectangle( aTmpPoly, aScaledLogicClipDoubleRect, aPoly );
330 [ # # ]: 0 : bIsClipped = true;
331 : : }
332 : : }
333 : :
334 [ + - ]: 296 : if( !bIsClipped )
335 [ + - ][ + - ]: 296 : Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
336 : : }
337 : :
338 [ + - ][ - + ]: 296 : if(!ShapeFactory::hasPolygonAnyLines(aPoly))
339 : 0 : return false;
340 : :
341 : : //transformation 3) -> 4)
342 [ + - ]: 296 : pPosHelper->transformScaledLogicToScene( aPoly );
343 : :
344 : : //create line:
345 [ + - ]: 296 : uno::Reference< drawing::XShape > xShape(NULL);
346 [ + + ]: 296 : if(m_nDimension==3)
347 : : {
348 [ + - ]: 33 : double fDepth = this->getTransformedDepth();
349 : 33 : sal_Int32 nPolyCount = aPoly.SequenceX.getLength();
350 [ + + ]: 66 : for(sal_Int32 nPoly=0;nPoly<nPolyCount;nPoly++)
351 : : {
352 [ + - ]: 33 : sal_Int32 nPointCount = aPoly.SequenceX[nPoly].getLength();
353 [ + + ]: 429 : for(sal_Int32 nPoint=0;nPoint<nPointCount-1;nPoint++)
354 : : {
355 : 396 : drawing::Position3D aPoint1, aPoint2;
356 [ + - ][ + - ]: 396 : aPoint1.PositionX = aPoly.SequenceX[nPoly][nPoint+1];
357 [ + - ][ + - ]: 396 : aPoint1.PositionY = aPoly.SequenceY[nPoly][nPoint+1];
358 [ + - ][ + - ]: 396 : aPoint1.PositionZ = aPoly.SequenceZ[nPoly][nPoint+1];
359 : :
360 [ + - ][ + - ]: 396 : aPoint2.PositionX = aPoly.SequenceX[nPoly][nPoint];
361 [ + - ][ + - ]: 396 : aPoint2.PositionY = aPoly.SequenceY[nPoly][nPoint];
362 [ + - ][ + - ]: 396 : aPoint2.PositionZ = aPoly.SequenceZ[nPoly][nPoint];
363 : :
364 [ + - ]: 396 : Stripe aStripe( aPoint1, aPoint2, fDepth );
365 : :
366 : : m_pShapeFactory->createStripe(xSeriesGroupShape_Shapes
367 : : , Stripe( aPoint1, aPoint2, fDepth )
368 [ + - ][ + - ]: 396 : , pSeries->getPropertiesOfSeries(), PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), true, 1 );
[ + - ][ + - ]
369 : : }
370 : : }
371 : : }
372 : : else //m_nDimension!=3
373 : : {
374 : : xShape = m_pShapeFactory->createLine2D( xSeriesGroupShape_Shapes
375 [ + - ][ + - ]: 263 : , PolyToPointSequence( aPoly ) );
[ + - ][ + - ]
376 : : this->setMappedProperties( xShape
377 : : , pSeries->getPropertiesOfSeries()
378 [ + - ][ + - ]: 263 : , PropertyMapper::getPropertyNameMapForLineSeriesProperties() );
[ + - ]
379 : : //because of this name this line will be used for marking
380 [ + - ][ + - ]: 263 : m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
381 : : }
382 [ + - ]: 296 : return true;
383 : : }
384 : :
385 : 0 : bool AreaChart::impl_createArea( VDataSeries* pSeries
386 : : , drawing::PolyPolygonShape3D* pSeriesPoly
387 : : , drawing::PolyPolygonShape3D* pPreviousSeriesPoly
388 : : , PlottingPositionHelper* pPosHelper )
389 : : {
390 : : //return true if an area was created successfully
391 : :
392 [ # # ]: 0 : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeBackChild(pSeries, m_xSeriesTarget);
393 : 0 : double zValue = pSeries->m_fLogicZPos;
394 : :
395 [ # # ]: 0 : drawing::PolyPolygonShape3D aPoly( *pSeriesPoly );
396 : : //add second part to the polygon (grounding points or previous series points)
397 [ # # ][ # # ]: 0 : if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) )
[ # # ][ # # ]
398 : : {
399 [ # # ]: 0 : if( pPreviousSeriesPoly )
400 [ # # ]: 0 : addPolygon( aPoly, *pPreviousSeriesPoly );
401 : : }
402 [ # # ]: 0 : else if(!pPreviousSeriesPoly)
403 : : {
404 : 0 : double fMinX = pSeries->m_fLogicMinX;
405 : 0 : double fMaxX = pSeries->m_fLogicMaxX;
406 [ # # ]: 0 : double fY = pPosHelper->getBaseValueY();//logic grounding
407 [ # # ]: 0 : if( m_nDimension==3 )
408 [ # # ]: 0 : fY = pPosHelper->getLogicMinY();
409 : :
410 : : //clip to scale
411 [ # # ][ # # ]: 0 : if(fMaxX<pPosHelper->getLogicMinX() || fMinX>pPosHelper->getLogicMaxX())
[ # # ][ # # ]
[ # # ]
412 : 0 : return false;//no visible shape needed
413 [ # # ]: 0 : pPosHelper->clipLogicValues( &fMinX, &fY, 0 );
414 [ # # ]: 0 : pPosHelper->clipLogicValues( &fMaxX, 0, 0 );
415 : :
416 : : //apply scaling
417 : : {
418 [ # # ]: 0 : pPosHelper->doLogicScaling( &fMinX, &fY, &zValue );
419 [ # # ]: 0 : pPosHelper->doLogicScaling( &fMaxX, 0, 0 );
420 : : }
421 : :
422 [ # # ]: 0 : AddPointToPoly( aPoly, drawing::Position3D( fMaxX,fY,zValue) );
423 [ # # ]: 0 : AddPointToPoly( aPoly, drawing::Position3D( fMinX,fY,zValue) );
424 : : }
425 : : else
426 : : {
427 [ # # ]: 0 : appendPoly( aPoly, *pPreviousSeriesPoly );
428 : : }
429 [ # # ]: 0 : ShapeFactory::closePolygon(aPoly);
430 : :
431 : : //apply clipping
432 : : {
433 [ # # ]: 0 : drawing::PolyPolygonShape3D aClippedPoly;
434 [ # # ][ # # ]: 0 : Clipping::clipPolygonAtRectangle( aPoly, pPosHelper->getScaledLogicClipDoubleRect(), aClippedPoly, false );
435 [ # # ]: 0 : ShapeFactory::closePolygon(aClippedPoly); //again necessary after clipping
436 [ # # ][ # # ]: 0 : aPoly = aClippedPoly;
437 : : }
438 : :
439 [ # # ][ # # ]: 0 : if(!ShapeFactory::hasPolygonAnyLines(aPoly))
440 : 0 : return false;
441 : :
442 : : //transformation 3) -> 4)
443 [ # # ]: 0 : pPosHelper->transformScaledLogicToScene( aPoly );
444 : :
445 : : //create area:
446 [ # # ]: 0 : uno::Reference< drawing::XShape > xShape(NULL);
447 [ # # ]: 0 : if(m_nDimension==3)
448 : : {
449 : : xShape = m_pShapeFactory->createArea3D( xSeriesGroupShape_Shapes
450 [ # # ][ # # ]: 0 : , aPoly, this->getTransformedDepth() );
[ # # ]
451 : : }
452 : : else //m_nDimension!=3
453 : : {
454 : : xShape = m_pShapeFactory->createArea2D( xSeriesGroupShape_Shapes
455 [ # # ][ # # ]: 0 : , aPoly );
456 : : }
457 : : this->setMappedProperties( xShape
458 : : , pSeries->getPropertiesOfSeries()
459 [ # # ][ # # ]: 0 : , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
[ # # ]
460 : : //because of this name this line will be used for marking
461 [ # # ][ # # ]: 0 : m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") );
462 [ # # ]: 0 : return true;
463 : : }
464 : :
465 : 72 : void AreaChart::impl_createSeriesShapes()
466 : : {
467 : : //the polygon shapes for each series need to be created before
468 : :
469 : : //iterate through all series again to create the series shapes
470 : 72 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
471 [ + - ]: 72 : const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
472 : : //=============================================================================
473 [ + - ][ + + ]: 162 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, ++nZ )
474 : : {
475 : 90 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
476 [ + - ]: 90 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
477 : :
478 : : //=============================================================================
479 [ + - ][ + + ]: 374 : for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
480 : : {
481 : 284 : ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
482 : :
483 [ + - ]: 284 : ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
484 [ + - ]: 284 : const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
485 : : //=============================================================================
486 : :
487 [ + - ]: 284 : std::map< sal_Int32, drawing::PolyPolygonShape3D* > aPreviousSeriesPolyMap;//a PreviousSeriesPoly for each different nAttachedAxisIndex
488 : 284 : drawing::PolyPolygonShape3D* pSeriesPoly = NULL;
489 : :
490 : : //iterate through all series
491 [ + - ][ + + ]: 580 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
492 : : {
493 [ + - ]: 296 : sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
494 [ + - ]: 296 : PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
495 [ - + ]: 296 : if(!pPosHelper)
496 : 0 : pPosHelper = m_pMainPosHelper;
497 : 296 : PlotterBase::m_pPosHelper = pPosHelper;
498 : :
499 : 296 : createRegressionCurvesShapes( **aSeriesIter, m_xErrorBarTarget, m_xRegressionCurveEquationTarget,
500 [ + - ]: 592 : m_pPosHelper->maySkipPointsInRegressionCalculation());
501 : :
502 : 296 : pSeriesPoly = &(*aSeriesIter)->m_aPolyPolygonShape3D;
503 [ - + ]: 296 : if( m_bArea )
504 : : {
505 [ # # ][ # # ]: 0 : if( !impl_createArea( *aSeriesIter, pSeriesPoly, aPreviousSeriesPolyMap[nAttachedAxisIndex], pPosHelper ) )
[ # # ]
506 : 0 : continue;
507 : : }
508 [ + - ]: 296 : if( m_bLine )
509 : : {
510 [ + - ][ - + ]: 296 : if( !impl_createLine( *aSeriesIter, pSeriesPoly, pPosHelper ) )
511 : 0 : continue;
512 : : }
513 [ + - ]: 296 : aPreviousSeriesPolyMap[nAttachedAxisIndex] = pSeriesPoly;
514 : : }//next series in x slot (next y slot)
515 : 284 : }//next x slot
516 : : }//next z slot
517 : 72 : }
518 : :
519 : : namespace
520 : : {
521 : :
522 : 0 : void lcl_reorderSeries( ::std::vector< ::std::vector< VDataSeriesGroup > >& rZSlots )
523 : : {
524 [ # # ]: 0 : ::std::vector< ::std::vector< VDataSeriesGroup > > aRet( rZSlots.size() );
525 : :
526 : 0 : ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZIt( rZSlots.rbegin() );
527 : 0 : ::std::vector< ::std::vector< VDataSeriesGroup > >::reverse_iterator aZEnd( rZSlots.rend() );
528 [ # # ][ # # ]: 0 : for( ; aZIt != aZEnd; ++aZIt )
[ # # ]
529 : : {
530 [ # # ][ # # ]: 0 : ::std::vector< VDataSeriesGroup > aXSlot( aZIt->size() );
531 : :
532 [ # # ]: 0 : ::std::vector< VDataSeriesGroup >::reverse_iterator aXIt( aZIt->rbegin() );
533 [ # # ]: 0 : ::std::vector< VDataSeriesGroup >::reverse_iterator aXEnd( aZIt->rend() );
534 [ # # ][ # # ]: 0 : for( ; aXIt != aXEnd; ++aXIt )
[ # # ]
535 [ # # ][ # # ]: 0 : aXSlot.push_back(*aXIt);
536 : :
537 [ # # ]: 0 : aRet.push_back(aXSlot);
538 : 0 : }
539 : :
540 : 0 : rZSlots.clear();
541 [ # # ]: 0 : rZSlots = aRet;
542 : 0 : }
543 : :
544 : : }//anonymous namespace
545 : :
546 : : //better performance for big data
547 : : struct FormerPoint
548 : : {
549 : 2538 : FormerPoint( double fX, double fY, double fZ )
550 : 2538 : : m_fX(fX), m_fY(fY), m_fZ(fZ)
551 : 2538 : {}
552 : 296 : FormerPoint()
553 : : {
554 : 296 : ::rtl::math::setNan( &m_fX );
555 : 296 : ::rtl::math::setNan( &m_fY );
556 : 296 : ::rtl::math::setNan( &m_fZ );
557 : 296 : }
558 : :
559 : : double m_fX;
560 : : double m_fY;
561 : : double m_fZ;
562 : : };
563 : :
564 : 72 : void AreaChart::createShapes()
565 : : {
566 [ + - ][ + - ]: 72 : if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
567 : : return;
568 : :
569 [ + + ][ + - ]: 72 : if( m_nDimension == 2 && ( m_bArea || !m_bCategoryXAxis ) )
[ - + ]
570 [ # # ]: 0 : lcl_reorderSeries( m_aZSlots );
571 : :
572 : : OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"AreaChart is not proper initialized");
573 [ + - ][ + - ]: 72 : if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
[ - + ][ + - ]
574 : : return;
575 : :
576 : : //the text labels should be always on top of the other series shapes
577 : : //for area chart the error bars should be always on top of the other series shapes
578 : :
579 : : //therefore create an own group for the texts and the error bars to move them to front
580 : : //(because the text group is created after the series group the texts are displayed on top)
581 [ + - ][ + - ]: 72 : m_xSeriesTarget = createGroupShape( m_xLogicTarget,rtl::OUString() );
582 [ - + ]: 72 : if( m_bArea )
583 [ # # ][ # # ]: 0 : m_xErrorBarTarget = createGroupShape( m_xLogicTarget,rtl::OUString() );
584 : : else
585 [ + - ]: 72 : m_xErrorBarTarget = m_xSeriesTarget;
586 [ + - ][ + - ]: 72 : m_xTextTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() );
587 [ + - ][ + - ]: 72 : m_xRegressionCurveEquationTarget = m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() );
588 : :
589 : : //---------------------------------------------
590 : : //check necessary here that different Y axis can not be stacked in the same group? ... hm?
591 : :
592 : : //update/create information for current group
593 : 72 : double fLogicZ = 1.0;//as defined
594 : :
595 : 72 : sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale
596 [ + - ]: 72 : sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
597 [ - + ]: 72 : if(nEndIndex<=0)
598 : 0 : nEndIndex=1;
599 : :
600 : : //better performance for big data
601 [ + - ]: 72 : std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap;
602 : 72 : m_bPointsWereSkipped = false;
603 : 72 : sal_Int32 nSkippedPoints = 0;
604 : 72 : sal_Int32 nCreatedPoints = 0;
605 : : //
606 : :
607 [ + - ][ + - ]: 72 : bool bDateCategory = (m_pExplicitCategoriesProvider && m_pExplicitCategoriesProvider->isDateAxis());
[ - + ]
608 : :
609 : : //=============================================================================
610 : : //iterate through all x values per indices
611 [ + + ]: 838 : for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ )
612 : : {
613 : 766 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
614 [ + - ]: 766 : const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
615 : :
616 [ + - ]: 766 : std::map< sal_Int32, double > aLogicYSumMap;//one for each different nAttachedAxisIndex
617 [ + - ][ + + ]: 1766 : for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
618 : : {
619 : 1000 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
620 [ + - ]: 1000 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
621 : :
622 : : //iterate through all x slots in this category to get 100percent sum
623 [ + - ][ + + ]: 3382 : for( ; aXSlotIter != aXSlotEnd; ++aXSlotIter )
624 : : {
625 : 2382 : std::vector<VDataSeries*>& rSeriesList = aXSlotIter->m_aSeriesVector;
626 : 2382 : std::vector<VDataSeries*>::iterator aSeriesIter = rSeriesList.begin();
627 : 2382 : const std::vector<VDataSeries*>::iterator aSeriesEnd = rSeriesList.end();
628 : :
629 [ + - ][ + + ]: 4920 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
630 : : {
631 : 2538 : VDataSeries* pSeries( *aSeriesIter );
632 [ - + ]: 2538 : if(!pSeries)
633 : 0 : continue;
634 : :
635 [ - + ]: 2538 : if (bDateCategory)
636 [ # # ]: 0 : pSeries->doSortByXValues();
637 : :
638 [ + - ]: 2538 : sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex();
639 [ + - ][ + - ]: 2538 : if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
[ + + ]
640 [ + - ]: 766 : aLogicYSumMap[nAttachedAxisIndex]=0.0;
641 : :
642 [ + - ]: 2538 : PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
643 [ - + ]: 2538 : if(!pPosHelper)
644 : 0 : pPosHelper = m_pMainPosHelper;
645 : 2538 : PlotterBase::m_pPosHelper = pPosHelper;
646 : :
647 [ + - ]: 2538 : double fAdd = pSeries->getYValue( nIndex );
648 [ + - ][ + - ]: 2538 : if( !::rtl::math::isNan(fAdd) && !::rtl::math::isInf(fAdd) )
[ + - ]
649 [ + - ]: 2538 : aLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd );
650 : : }
651 : : }
652 : : }
653 : :
654 : : //=============================================================================
655 : 766 : aZSlotIter = m_aZSlots.begin();
656 [ + - ][ + + ]: 1766 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, ++nZ )
657 : : {
658 : 1000 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
659 [ + - ]: 1000 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
660 : :
661 : : //for the area chart there should be at most one x slot (no side by side stacking available)
662 : : //attention different: xSlots are always interpreted as independent areas one behind the other: @todo this doesn't work why not???
663 : 1000 : aXSlotIter = aZSlotIter->begin();
664 [ + - ][ + + ]: 3382 : for( sal_Int32 nX=0; aXSlotIter != aXSlotEnd; ++aXSlotIter, ++nX )
665 : : {
666 : 2382 : std::vector<VDataSeries*>& rSeriesList = aXSlotIter->m_aSeriesVector;
667 [ + - ]: 2382 : std::vector<VDataSeries*>::const_iterator aSeriesIter = rSeriesList.begin();
668 [ + - ]: 2382 : const std::vector<VDataSeries*>::const_iterator aSeriesEnd = rSeriesList.end();
669 : :
670 [ + - ]: 2382 : std::map< sal_Int32, double > aLogicYForNextSeriesMap;//one for each different nAttachedAxisIndex
671 : : //=============================================================================
672 : : //iterate through all series
673 [ + - ][ + + ]: 4920 : for( sal_Int32 nSeriesIndex = 0; aSeriesIter != aSeriesEnd; ++aSeriesIter, ++nSeriesIndex )
674 : : {
675 : 2538 : VDataSeries* pSeries( *aSeriesIter );
676 [ - + ]: 2538 : if(!pSeries)
677 : 0 : continue;
678 : :
679 : : /* #i70133# ignore points outside of series length in standard area
680 : : charts. Stacked area charts will use missing points as zeros. In
681 : : standard charts, pSeriesList contains only one series. */
682 [ - + ][ # # ]: 2538 : if( m_bArea && (rSeriesList.size() == 1) && (nIndex >= (*aSeriesIter)->getTotalPointCount()) )
[ # # ][ # # ]
[ - + ]
683 : 0 : continue;
684 : :
685 [ + - ]: 2538 : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShapeFrontChild(*aSeriesIter, m_xSeriesTarget);
686 : :
687 [ + - ]: 2538 : sal_Int32 nAttachedAxisIndex = (*aSeriesIter)->getAttachedAxisIndex();
688 [ + - ]: 2538 : PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex ));
689 [ - + ]: 2538 : if(!pPosHelper)
690 : 0 : pPosHelper = m_pMainPosHelper;
691 : 2538 : PlotterBase::m_pPosHelper = pPosHelper;
692 : :
693 [ + + ]: 2538 : if(m_nDimension==3)
694 : 429 : fLogicZ = nZ+0.5;
695 : 2538 : (*aSeriesIter)->m_fLogicZPos = fLogicZ;
696 : :
697 : : //collect data point information (logic coordinates, style ):
698 [ + - ]: 2538 : double fLogicX = (*aSeriesIter)->getXValue(nIndex);
699 [ - + ]: 2538 : if (bDateCategory)
700 [ # # ]: 0 : fLogicX = DateHelper::RasterizeDateValue( fLogicX, m_aNullDate, m_nTimeResolution );
701 [ + - ]: 2538 : double fLogicY = (*aSeriesIter)->getYValue(nIndex);
702 : :
703 [ - + ][ # # : 2538 : if( m_bIsPolarCooSys && m_bArea &&
# # # # ]
[ - + ]
704 : 0 : ( ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) ) )
705 : : {
706 [ # # ][ # # ]: 0 : if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
707 : : {
708 [ # # ][ # # ]: 0 : if( rSeriesList.size() == 1 || nSeriesIndex == 0 )
[ # # ]
709 : : {
710 [ # # ]: 0 : fLogicY = pPosHelper->getLogicMinY();
711 [ # # ][ # # ]: 0 : if( !pPosHelper->isMathematicalOrientationY() )
712 [ # # ]: 0 : fLogicY = pPosHelper->getLogicMaxY();
713 : : }
714 : : else
715 : 0 : fLogicY = 0.0;
716 : : }
717 : : }
718 : :
719 [ + + ][ - + ]: 2538 : if( m_nDimension==3 && m_bArea && rSeriesList.size()!=1 )
[ # # ][ - + ]
720 : 0 : fLogicY = fabs( fLogicY );
721 : :
722 [ + - ][ + + ]: 2538 : if( pPosHelper->isPercentY() && !::rtl::math::approxEqual( aLogicYSumMap[nAttachedAxisIndex], 0.0 ) )
[ + - ][ + - ]
[ + + ]
723 : : {
724 [ + - ]: 156 : fLogicY = fabs( fLogicY )/aLogicYSumMap[nAttachedAxisIndex];
725 : : }
726 : :
727 [ + - ][ + - : 12690 : if( ::rtl::math::isNan(fLogicX) || ::rtl::math::isInf(fLogicX)
+ - + - +
- - + ]
[ - + ]
728 : 5076 : || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY)
729 : 5076 : || ::rtl::math::isNan(fLogicZ) || ::rtl::math::isInf(fLogicZ) )
730 : : {
731 [ # # ][ # # ]: 0 : if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP )
732 : : {
733 : 0 : drawing::PolyPolygonShape3D& rPolygon = (*aSeriesIter)->m_aPolyPolygonShape3D;
734 : 0 : sal_Int32& rIndex = (*aSeriesIter)->m_nPolygonIndex;
735 [ # # ][ # # ]: 0 : if( 0<= rIndex && rIndex < rPolygon.SequenceX.getLength() )
[ # # ]
736 : : {
737 [ # # ][ # # ]: 0 : if( rPolygon.SequenceX[ rIndex ].getLength() )
738 : 0 : rIndex++; //start a new polygon for the next point if the current poly is not empty
739 : : }
740 : : }
741 : 0 : continue;
742 : : }
743 : :
744 [ + - ][ + - ]: 2538 : if( aLogicYForNextSeriesMap.find(nAttachedAxisIndex) == aLogicYForNextSeriesMap.end() )
[ + + ]
745 [ + - ]: 2382 : aLogicYForNextSeriesMap[nAttachedAxisIndex] = 0.0;
746 : :
747 : 2538 : double fLogicValueForLabeDisplay = fLogicY;
748 : :
749 [ + - ]: 2538 : fLogicY += aLogicYForNextSeriesMap[nAttachedAxisIndex];
750 [ + - ]: 2538 : aLogicYForNextSeriesMap[nAttachedAxisIndex] = fLogicY;
751 : :
752 [ + - ]: 2538 : bool bIsVisible = pPosHelper->isLogicVisible( fLogicX, fLogicY, fLogicZ );
753 : :
754 : : //remind minimal and maximal x values for area 'grounding' points
755 : : //only for filled area
756 : : {
757 : 2538 : double& rfMinX = (*aSeriesIter)->m_fLogicMinX;
758 [ - + ][ + + ]: 2538 : if(!nIndex||fLogicX<rfMinX)
759 : 296 : rfMinX=fLogicX;
760 : 2538 : double& rfMaxX = (*aSeriesIter)->m_fLogicMaxX;
761 [ + - ][ + + ]: 2538 : if(!nIndex||fLogicX>rfMaxX)
762 : 2538 : rfMaxX=fLogicX;
763 : : }
764 : :
765 : 2538 : drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ );
766 : 2538 : drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition);
767 [ + - ]: 2538 : pPosHelper->doLogicScaling( aScaledLogicPosition );
768 : :
769 : : //transformation 3) -> 4)
770 [ + - ]: 2538 : drawing::Position3D aScenePosition( pPosHelper->transformLogicToScene( fLogicX,fLogicY,fLogicZ, false ) );
771 : :
772 : : //better performance for big data
773 [ + - ]: 2538 : FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
774 [ + - ]: 2538 : pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
775 [ + - ][ + - ]: 5076 : if( !pSeries->isAttributedDataPoint(nIndex)
[ - + ][ - + ]
776 : : &&
777 : : pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ
778 [ + - ]: 2538 : , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) )
779 : : {
780 : 0 : ++nSkippedPoints;
781 : 0 : m_bPointsWereSkipped = true;
782 : 0 : continue;
783 : : }
784 [ + - ]: 2538 : aSeriesFormerPointMap[pSeries] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ);
785 : : //
786 : :
787 : : //store point information for series polygon
788 : : //for area and/or line (symbols only do not need this)
789 [ + - ][ + - ]: 2538 : if( isValidPosition(aScaledLogicPosition) )
790 : : {
791 [ + - ]: 2538 : AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
792 : :
793 : : //prepare clipping for filled net charts
794 [ - + ][ # # ]: 2538 : if( !bIsVisible && m_bIsPolarCooSys && m_bArea )
[ # # ]
795 : : {
796 : 0 : drawing::Position3D aClippedPos(aScaledLogicPosition);
797 [ # # ]: 0 : pPosHelper->clipScaledLogicValues( 0, &aClippedPos.PositionY, 0 );
798 [ # # ][ # # ]: 0 : if( pPosHelper->isLogicVisible( aClippedPos.PositionX, aClippedPos.PositionY, aClippedPos.PositionZ ) )
799 : : {
800 [ # # ]: 0 : AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aClippedPos, (*aSeriesIter)->m_nPolygonIndex );
801 [ # # ]: 0 : AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aScaledLogicPosition, (*aSeriesIter)->m_nPolygonIndex );
802 : : }
803 : : }
804 : : }
805 : :
806 : : //create a single datapoint if point is visible
807 : : //apply clipping:
808 [ - + ]: 2538 : if( !bIsVisible )
809 : 0 : continue;
810 : :
811 : 2538 : bool bCreateYErrorBar = false, bCreateXErrorBar = false;
812 : : {
813 [ + - ]: 2538 : uno::Reference< beans::XPropertySet > xErrorBarProp(pSeries->getYErrorBarProperties(nIndex));
814 [ + + ]: 2538 : if( xErrorBarProp.is() )
815 : : {
816 : 1014 : bool bShowPositive = false;
817 : 1014 : bool bShowNegative = false;
818 [ + - ][ + - ]: 1014 : xErrorBarProp->getPropertyValue( C2U( "ShowPositiveError" )) >>= bShowPositive;
[ + - ]
819 [ + - ][ + - ]: 1014 : xErrorBarProp->getPropertyValue( C2U( "ShowNegativeError" )) >>= bShowNegative;
[ + - ]
820 [ - + ][ + + ]: 1014 : bCreateYErrorBar = bShowPositive || bShowNegative;
821 : : }
822 : :
823 [ + - ][ + - ]: 2538 : xErrorBarProp = pSeries->getXErrorBarProperties(nIndex);
824 [ - + ]: 2538 : if ( xErrorBarProp.is() )
825 : : {
826 : 0 : bool bShowPositive = false;
827 : 0 : bool bShowNegative = false;
828 [ # # ][ # # ]: 0 : xErrorBarProp->getPropertyValue( C2U( "ShowPositiveError" )) >>= bShowPositive;
[ # # ]
829 [ # # ][ # # ]: 0 : xErrorBarProp->getPropertyValue( C2U( "ShowNegativeError" )) >>= bShowNegative;
[ # # ]
830 [ # # ][ # # ]: 0 : bCreateXErrorBar = bShowPositive || bShowNegative;
831 : 2538 : }
832 : : }
833 : :
834 [ + - ][ + + ]: 2538 : Symbol* pSymbolProperties = m_bSymbol ? (*aSeriesIter)->getSymbolProperties( nIndex ) : 0;
835 [ + + ][ - + ]: 2538 : bool bCreateSymbol = pSymbolProperties && (pSymbolProperties->Style != SymbolStyle_NONE);
836 : :
837 [ + - ][ + + ]: 4569 : if( !bCreateSymbol && !bCreateYErrorBar &&
[ + - ][ + + ]
[ + + ]
838 [ + - ]: 2031 : !bCreateXErrorBar && !pSeries->getDataPointLabelIfLabel(nIndex) )
839 : 510 : continue;
840 : :
841 : : //create a group shape for this point and add to the series shape:
842 : : rtl::OUString aPointCID = ObjectIdentifier::createPointCID(
843 [ + - ][ + - ]: 2028 : (*aSeriesIter)->getPointCID_Stub(), nIndex );
844 : : uno::Reference< drawing::XShapes > xPointGroupShape_Shapes(
845 [ + - ]: 2028 : createGroupShape(xSeriesGroupShape_Shapes,aPointCID) );
846 : : uno::Reference<drawing::XShape> xPointGroupShape_Shape =
847 [ + - ]: 2028 : uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
848 : :
849 : : {
850 : 2028 : nCreatedPoints++;
851 : :
852 : : //create data point
853 : 2028 : drawing::Direction3D aSymbolSize(0,0,0);
854 [ - + ]: 2028 : if( bCreateSymbol )
855 : : {
856 [ # # ]: 0 : if(m_nDimension!=3)
857 : : {
858 [ # # ]: 0 : if( pSymbolProperties )
859 : : {
860 [ # # ]: 0 : if( pSymbolProperties->Style != SymbolStyle_NONE )
861 : : {
862 : 0 : aSymbolSize.DirectionX = pSymbolProperties->Size.Width;
863 : 0 : aSymbolSize.DirectionY = pSymbolProperties->Size.Height;
864 : : }
865 : :
866 [ # # ]: 0 : if( pSymbolProperties->Style == SymbolStyle_STANDARD )
867 : : {
868 : 0 : sal_Int32 nSymbol = pSymbolProperties->StandardSymbol;
869 : : m_pShapeFactory->createSymbol2D( xPointGroupShape_Shapes
870 : : , aScenePosition, aSymbolSize
871 : : , nSymbol
872 : : , pSymbolProperties->BorderColor
873 [ # # ]: 0 : , pSymbolProperties->FillColor );
874 : : }
875 [ # # ]: 0 : else if( pSymbolProperties->Style == SymbolStyle_GRAPHIC )
876 : : {
877 : : m_pShapeFactory->createGraphic2D( xPointGroupShape_Shapes
878 : : , aScenePosition , aSymbolSize
879 [ # # ]: 0 : , pSymbolProperties->Graphic );
880 : : }
881 : : //@todo other symbol styles
882 : : }
883 : : }
884 : : }
885 : : //create error bars
886 [ - + ]: 2028 : if (bCreateXErrorBar)
887 [ # # ]: 0 : createErrorBar_X( aUnscaledLogicPosition, **aSeriesIter, nIndex, m_xErrorBarTarget );
888 : :
889 [ + + ]: 2028 : if (bCreateYErrorBar)
890 [ + - ]: 507 : createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nIndex, m_xErrorBarTarget );
891 : :
892 : : //create data point label
893 [ + - ][ + - ]: 2028 : if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) )
894 : : {
895 : 2028 : LabelAlignment eAlignment = LABEL_ALIGN_TOP;
896 : : drawing::Position3D aScenePosition3D( aScenePosition.PositionX
897 : : , aScenePosition.PositionY
898 [ + - ]: 2028 : , aScenePosition.PositionZ+this->getTransformedDepth() );
899 : :
900 [ + - ]: 2028 : sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
901 : :
902 [ + - - - : 2028 : switch(nLabelPlacement)
- - ]
903 : : {
904 : : case ::com::sun::star::chart::DataLabelPlacement::TOP:
905 : 2028 : aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
906 : 2028 : eAlignment = LABEL_ALIGN_TOP;
907 : 2028 : break;
908 : : case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
909 : 0 : aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1);
910 : 0 : eAlignment = LABEL_ALIGN_BOTTOM;
911 : 0 : break;
912 : : case ::com::sun::star::chart::DataLabelPlacement::LEFT:
913 : 0 : aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1);
914 : 0 : eAlignment = LABEL_ALIGN_LEFT;
915 : 0 : break;
916 : : case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
917 : 0 : aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1);
918 : 0 : eAlignment = LABEL_ALIGN_RIGHT;
919 : 0 : break;
920 : : case ::com::sun::star::chart::DataLabelPlacement::CENTER:
921 : 0 : eAlignment = LABEL_ALIGN_CENTER;
922 : : //todo implement this different for area charts
923 : 0 : break;
924 : : default:
925 : : OSL_FAIL("this label alignment is not implemented yet");
926 : 0 : aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1);
927 : 0 : eAlignment = LABEL_ALIGN_TOP;
928 : 0 : break;
929 : : }
930 : :
931 : 2028 : awt::Point aScreenPosition2D;//get the screen position for the labels
932 : 2028 : sal_Int32 nOffset = 100; //todo maybe calculate this font height dependent
933 [ # # ][ - + ]: 2028 : if( m_bIsPolarCooSys && nLabelPlacement == ::com::sun::star::chart::DataLabelPlacement::OUTSIDE )
934 : : {
935 [ # # ]: 0 : PolarPlottingPositionHelper* pPolarPosHelper = dynamic_cast<PolarPlottingPositionHelper*>(pPosHelper);
936 [ # # ]: 0 : if( pPolarPosHelper )
937 : : {
938 [ # # ]: 0 : PolarLabelPositionHelper aPolarLabelPositionHelper(pPolarPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory);
939 : : aScreenPosition2D = awt::Point( aPolarLabelPositionHelper.getLabelScreenPositionAndAlignmentForLogicValues(
940 [ # # ][ # # ]: 0 : eAlignment, fLogicX, fLogicY, fLogicZ, nOffset ));
941 : 0 : }
942 : : }
943 : : else
944 : : {
945 [ + - ][ + + ]: 2028 : if(LABEL_ALIGN_CENTER==eAlignment || m_nDimension == 3 )
946 : 429 : nOffset = 0;
947 : : aScreenPosition2D = awt::Point( LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
948 [ + - ][ + - ]: 2028 : .transformSceneToScreenPosition( aScenePosition3D ) );
[ + - ]
949 : : }
950 : :
951 : 2028 : this->createDataLabel( m_xTextTarget, **aSeriesIter, nIndex
952 : : , fLogicValueForLabeDisplay
953 [ + - + - ]: 4056 : , aLogicYSumMap[nAttachedAxisIndex], aScreenPosition2D, eAlignment, nOffset );
954 : : }
955 : : }
956 : :
957 : : //remove PointGroupShape if empty
958 [ + - ][ + - ]: 2028 : if(!xPointGroupShape_Shapes->getCount())
[ + - ]
959 [ + - ][ + - ]: 2028 : xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape);
960 : :
961 [ + + ]: 2538 : }//next series in x slot (next y slot)
962 : 2382 : }//next x slot
963 : : }//next z slot
964 : 766 : }//next category
965 : : //=============================================================================
966 : : //=============================================================================
967 : : //=============================================================================
968 : :
969 [ + - ]: 72 : impl_createSeriesShapes();
970 : :
971 : : /* @todo remove series shapes if empty
972 : : //remove and delete point-group-shape if empty
973 : : if(!xSeriesGroupShape_Shapes->getCount())
974 : : {
975 : : (*aSeriesIter)->m_xShape.set(NULL);
976 : : m_xLogicTarget->remove(xSeriesGroupShape_Shape);
977 : : }
978 : : */
979 : :
980 : : //remove and delete series-group-shape if empty
981 : :
982 : : //... todo
983 : :
984 : 72 : OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< area chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
985 : : }
986 : :
987 : : //.............................................................................
988 : : } //namespace chart
989 : : //.............................................................................
990 : :
991 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|