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 "BarChart.hxx"
21 : #include "ShapeFactory.hxx"
22 : #include "CommonConverters.hxx"
23 : #include "ObjectIdentifier.hxx"
24 : #include "LabelPositionHelper.hxx"
25 : #include "BarPositionHelper.hxx"
26 : #include "macros.hxx"
27 : #include "AxisIndexDefines.hxx"
28 : #include "Clipping.hxx"
29 : #include "DateHelper.hxx"
30 :
31 : #include <com/sun/star/chart/DataLabelPlacement.hpp>
32 :
33 : #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
34 : #include <rtl/math.hxx>
35 :
36 : namespace chart
37 : {
38 : using namespace ::com::sun::star;
39 : using namespace ::rtl::math;
40 : using namespace ::com::sun::star::chart2;
41 :
42 884 : BarChart::BarChart( const uno::Reference<XChartType>& xChartTypeModel
43 : , sal_Int32 nDimensionCount )
44 : : VSeriesPlotter( xChartTypeModel, nDimensionCount )
45 884 : , m_pMainPosHelper( new BarPositionHelper() )
46 : {
47 884 : PlotterBase::m_pPosHelper = m_pMainPosHelper;
48 884 : VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
49 :
50 : try
51 : {
52 884 : if( m_xChartTypeModelProps.is() )
53 : {
54 884 : m_xChartTypeModelProps->getPropertyValue( "OverlapSequence" ) >>= m_aOverlapSequence;
55 884 : m_xChartTypeModelProps->getPropertyValue( "GapwidthSequence" ) >>= m_aGapwidthSequence;
56 : }
57 : }
58 0 : catch( const uno::Exception& e )
59 : {
60 : ASSERT_EXCEPTION( e );
61 : }
62 884 : }
63 :
64 2652 : BarChart::~BarChart()
65 : {
66 884 : delete m_pMainPosHelper;
67 1768 : }
68 :
69 10467 : PlottingPositionHelper& BarChart::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
70 : {
71 10467 : PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper( nAxisIndex );
72 10467 : BarPositionHelper* pBarPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper);
73 10467 : if( pBarPosHelper && nAxisIndex >= 0 )
74 : {
75 10467 : if( nAxisIndex < m_aOverlapSequence.getLength() )
76 10467 : pBarPosHelper->setInnerDistance( -m_aOverlapSequence[nAxisIndex]/100.0 );
77 10467 : if( nAxisIndex < m_aGapwidthSequence.getLength() )
78 10467 : pBarPosHelper->setOuterDistance( m_aGapwidthSequence[nAxisIndex]/100.0 );
79 : }
80 10467 : return rPosHelper;
81 : }
82 :
83 884 : drawing::Direction3D BarChart::getPreferredDiagramAspectRatio() const
84 : {
85 884 : drawing::Direction3D aRet(1.0,1.0,1.0);
86 884 : if( m_nDimension == 3 )
87 : {
88 42 : aRet = drawing::Direction3D(1.0,-1.0,1.0);
89 42 : BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( MAIN_AXIS_INDEX) ) );
90 42 : if (pPosHelper)
91 : {
92 42 : drawing::Direction3D aScale( pPosHelper->getScaledLogicWidth() );
93 42 : if(aScale.DirectionX!=0.0)
94 : {
95 42 : double fXSlotCount = 1.0;
96 42 : if(!m_aZSlots.empty())
97 : {
98 42 : fXSlotCount = m_aZSlots.begin()->size();
99 : }
100 84 : aRet.DirectionZ = aScale.DirectionZ /
101 84 : (aScale.DirectionX + aScale.DirectionX * (fXSlotCount-1.0) * pPosHelper->getScaledSlotWidth());
102 : }
103 : else
104 : {
105 0 : return VSeriesPlotter::getPreferredDiagramAspectRatio();
106 : }
107 : }
108 : else
109 : {
110 0 : return VSeriesPlotter::getPreferredDiagramAspectRatio();
111 : }
112 :
113 42 : if(aRet.DirectionZ<0.05)
114 : {
115 0 : aRet.DirectionZ=0.05;
116 : }
117 42 : else if(aRet.DirectionZ>10)
118 : {
119 0 : aRet.DirectionZ=10;
120 : }
121 42 : if( m_pMainPosHelper && m_pMainPosHelper->isSwapXAndY() )
122 : {
123 11 : double fTemp = aRet.DirectionX;
124 11 : aRet.DirectionX = aRet.DirectionY;
125 11 : aRet.DirectionY = fTemp;
126 : }
127 : }
128 : else
129 842 : aRet = drawing::Direction3D(-1,-1,-1);
130 884 : return aRet;
131 : }
132 :
133 0 : bool BarChart::keepAspectRatio() const
134 : {
135 0 : return true;
136 : }
137 :
138 399 : awt::Point BarChart::getLabelScreenPositionAndAlignment(
139 : LabelAlignment& rAlignment, sal_Int32 nLabelPlacement
140 : , double fScaledX, double fScaledLowerYValue, double fScaledUpperYValue, double fScaledZ
141 : , double fScaledLowerBarDepth, double fScaledUpperBarDepth, double fBaseValue
142 : , BarPositionHelper* pPosHelper
143 : ) const
144 : {
145 399 : double fX = fScaledX;
146 399 : double fY = fScaledUpperYValue;
147 399 : double fZ = fScaledZ;
148 399 : bool bReverse = !pPosHelper->isMathematicalOrientationY();
149 399 : bool bNormalOutside = (!bReverse == !!(fBaseValue < fScaledUpperYValue));
150 399 : double fDepth = fScaledUpperBarDepth;
151 :
152 399 : switch(nLabelPlacement)
153 : {
154 : case ::com::sun::star::chart::DataLabelPlacement::TOP:
155 : {
156 223 : if( !pPosHelper->isSwapXAndY() )
157 : {
158 223 : fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
159 223 : rAlignment = LABEL_ALIGN_TOP;
160 223 : if(3==m_nDimension)
161 0 : fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
162 : }
163 : else
164 : {
165 0 : fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
166 0 : rAlignment = LABEL_ALIGN_CENTER;
167 : OSL_FAIL( "top label placement is not really supported by horizontal bar charts" );
168 : }
169 : }
170 223 : break;
171 : case ::com::sun::star::chart::DataLabelPlacement::BOTTOM:
172 : {
173 0 : if(!pPosHelper->isSwapXAndY())
174 : {
175 0 : fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
176 0 : rAlignment = LABEL_ALIGN_BOTTOM;
177 0 : if(3==m_nDimension)
178 0 : fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
179 : }
180 : else
181 : {
182 0 : fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
183 0 : rAlignment = LABEL_ALIGN_CENTER;
184 : OSL_FAIL( "bottom label placement is not supported by horizontal bar charts" );
185 : }
186 : }
187 0 : break;
188 : case ::com::sun::star::chart::DataLabelPlacement::LEFT:
189 : {
190 0 : if( pPosHelper->isSwapXAndY() )
191 : {
192 0 : fY = bReverse ? fScaledUpperYValue : fScaledLowerYValue;
193 0 : rAlignment = LABEL_ALIGN_LEFT;
194 0 : if(3==m_nDimension)
195 0 : fDepth = bReverse ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
196 : }
197 : else
198 : {
199 0 : fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
200 0 : rAlignment = LABEL_ALIGN_CENTER;
201 : OSL_FAIL( "left label placement is not supported by column charts" );
202 : }
203 : }
204 0 : break;
205 : case ::com::sun::star::chart::DataLabelPlacement::RIGHT:
206 : {
207 14 : if( pPosHelper->isSwapXAndY() )
208 : {
209 14 : fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
210 14 : rAlignment = LABEL_ALIGN_RIGHT;
211 14 : if(3==m_nDimension)
212 0 : fDepth = bReverse ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
213 : }
214 : else
215 : {
216 0 : fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
217 0 : rAlignment = LABEL_ALIGN_CENTER;
218 : OSL_FAIL( "right label placement is not supported by column charts" );
219 : }
220 : }
221 14 : break;
222 : case ::com::sun::star::chart::DataLabelPlacement::OUTSIDE:
223 : {
224 42 : fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
225 42 : if( pPosHelper->isSwapXAndY() )
226 18 : rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
227 : else
228 24 : rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
229 42 : if(3==m_nDimension)
230 2 : fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
231 : }
232 42 : break;
233 : case ::com::sun::star::chart::DataLabelPlacement::INSIDE:
234 : {
235 8 : fY = (fBaseValue < fScaledUpperYValue) ? fScaledUpperYValue : fScaledLowerYValue;
236 8 : if( pPosHelper->isSwapXAndY() )
237 8 : rAlignment = bNormalOutside ? LABEL_ALIGN_LEFT : LABEL_ALIGN_RIGHT;
238 : else
239 0 : rAlignment = bNormalOutside ? LABEL_ALIGN_BOTTOM : LABEL_ALIGN_TOP;
240 8 : if(3==m_nDimension)
241 0 : fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledUpperBarDepth) : fabs(fScaledLowerBarDepth);
242 : }
243 8 : break;
244 : case ::com::sun::star::chart::DataLabelPlacement::NEAR_ORIGIN:
245 : {
246 11 : fY = (fBaseValue < fScaledUpperYValue) ? fScaledLowerYValue : fScaledUpperYValue;
247 11 : if( pPosHelper->isSwapXAndY() )
248 8 : rAlignment = bNormalOutside ? LABEL_ALIGN_RIGHT : LABEL_ALIGN_LEFT;
249 : else
250 3 : rAlignment = bNormalOutside ? LABEL_ALIGN_TOP : LABEL_ALIGN_BOTTOM;
251 11 : if(3==m_nDimension)
252 0 : fDepth = (fBaseValue < fScaledUpperYValue) ? fabs(fScaledLowerBarDepth) : fabs(fScaledUpperBarDepth);
253 : }
254 11 : break;
255 : case ::com::sun::star::chart::DataLabelPlacement::CENTER:
256 101 : fY -= (fScaledUpperYValue-fScaledLowerYValue)/2.0;
257 101 : rAlignment = LABEL_ALIGN_CENTER;
258 101 : if(3==m_nDimension)
259 69 : fDepth = fabs(fScaledUpperBarDepth-fScaledLowerBarDepth)/2.0;
260 101 : break;
261 : default:
262 : OSL_FAIL("this label alignment is not implemented yet");
263 :
264 0 : break;
265 : }
266 399 : if(3==m_nDimension)
267 71 : fZ -= fDepth/2.0;
268 :
269 : drawing::Position3D aScenePosition3D( pPosHelper->
270 399 : transformScaledLogicToScene( fX, fY, fZ, true ) );
271 399 : return LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
272 798 : .transformSceneToScreenPosition( aScenePosition3D );
273 : }
274 :
275 502 : uno::Reference< drawing::XShape > BarChart::createDataPoint3D_Bar(
276 : const uno::Reference< drawing::XShapes >& xTarget
277 : , const drawing::Position3D& rPosition, const drawing::Direction3D& rSize
278 : , double fTopHeight, sal_Int32 nRotateZAngleHundredthDegree
279 : , const uno::Reference< beans::XPropertySet >& xObjectProperties
280 : , sal_Int32 nGeometry3D )
281 : {
282 502 : bool bRoundedEdges = true;
283 : try
284 : {
285 502 : if( xObjectProperties.is() )
286 : {
287 502 : sal_Int16 nPercentDiagonal = 0;
288 502 : xObjectProperties->getPropertyValue( "PercentDiagonal" ) >>= nPercentDiagonal;
289 502 : if( nPercentDiagonal < 5 )
290 502 : bRoundedEdges = false;
291 : }
292 : }
293 0 : catch( const uno::Exception& e )
294 : {
295 : ASSERT_EXCEPTION( e );
296 : }
297 :
298 502 : uno::Reference< drawing::XShape > xShape(NULL);
299 502 : switch( nGeometry3D )
300 : {
301 : case DataPointGeometry3D::CYLINDER:
302 108 : xShape = m_pShapeFactory->createCylinder( xTarget, rPosition, rSize, nRotateZAngleHundredthDegree );
303 108 : break;
304 : case DataPointGeometry3D::CONE:
305 144 : xShape = m_pShapeFactory->createCone( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree );
306 144 : break;
307 : case DataPointGeometry3D::PYRAMID:
308 0 : xShape = m_pShapeFactory->createPyramid( xTarget, rPosition, rSize, fTopHeight, nRotateZAngleHundredthDegree>0
309 0 : , xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
310 0 : break;
311 : case DataPointGeometry3D::CUBOID:
312 : default:
313 1000 : xShape = m_pShapeFactory->createCube( xTarget, rPosition, rSize
314 : , nRotateZAngleHundredthDegree, xObjectProperties
315 750 : , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges );
316 250 : return xShape;
317 : }
318 252 : if( nGeometry3D != DataPointGeometry3D::PYRAMID )
319 252 : setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
320 252 : return xShape;
321 : }
322 :
323 : namespace
324 : {
325 922 : bool lcl_hasGeometry3DVariableWidth( sal_Int32 nGeometry3D )
326 : {
327 922 : bool bRet = false;
328 922 : switch( nGeometry3D )
329 : {
330 : case DataPointGeometry3D::PYRAMID:
331 : case DataPointGeometry3D::CONE:
332 180 : bRet = true;
333 180 : break;
334 : case DataPointGeometry3D::CUBOID:
335 : case DataPointGeometry3D::CYLINDER:
336 : default:
337 742 : bRet = false;
338 742 : break;
339 : }
340 922 : return bRet;
341 : }
342 : }// end anonymous namespace
343 :
344 2681 : void BarChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
345 : {
346 2681 : if( !pSeries )
347 2681 : return;
348 2681 : if(m_nDimension==2)
349 : {
350 : //2ND_AXIS_IN_BARS put series on second scales to different z slot as temporary workaround
351 : //this needs to be redesigned if 3d bars are also able to display secondary axes
352 :
353 2553 : sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex();
354 2553 : zSlot = nAxisIndex;
355 :
356 2553 : if( !pSeries->getGroupBarsPerAxis() )
357 0 : zSlot = 0;
358 2553 : if(zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
359 841 : m_aZSlots.resize(zSlot+1);
360 : }
361 2681 : VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
362 : }
363 :
364 : //better performance for big data
365 : struct FormerBarPoint
366 : {
367 10501 : FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
368 10501 : : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
369 10501 : {}
370 2659 : FormerBarPoint()
371 : {
372 2659 : ::rtl::math::setNan( &m_fX );
373 2659 : ::rtl::math::setNan( &m_fUpperY );
374 2659 : ::rtl::math::setNan( &m_fLowerY );
375 2659 : ::rtl::math::setNan( &m_fZ );
376 2659 : }
377 :
378 : double m_fX;
379 : double m_fUpperY;
380 : double m_fLowerY;
381 : double m_fZ;
382 : };
383 :
384 883 : void BarChart::adaptOverlapAndGapwidthForGroupBarsPerAxis()
385 : {
386 : //adapt m_aOverlapSequence and m_aGapwidthSequence for the groupBarsPerAxis feature
387 : //thus the different series use the same settings
388 :
389 883 : VDataSeries* pFirstSeries = getFirstSeries();
390 883 : if(pFirstSeries && !pFirstSeries->getGroupBarsPerAxis() )
391 : {
392 0 : sal_Int32 nAxisIndex = pFirstSeries->getAttachedAxisIndex();
393 0 : sal_Int32 nN = 0;
394 0 : sal_Int32 nUseThisIndex = nAxisIndex;
395 0 : if( nUseThisIndex < 0 || nUseThisIndex >= m_aOverlapSequence.getLength() )
396 0 : nUseThisIndex = 0;
397 0 : for( nN = 0; nN < m_aOverlapSequence.getLength(); nN++ )
398 : {
399 0 : if(nN!=nUseThisIndex)
400 0 : m_aOverlapSequence[nN] = m_aOverlapSequence[nUseThisIndex];
401 : }
402 :
403 0 : nUseThisIndex = nAxisIndex;
404 0 : if( nUseThisIndex < 0 || nUseThisIndex >= m_aGapwidthSequence.getLength() )
405 0 : nUseThisIndex = 0;
406 0 : for( nN = 0; nN < m_aGapwidthSequence.getLength(); nN++ )
407 : {
408 0 : if(nN!=nUseThisIndex)
409 0 : m_aGapwidthSequence[nN] = m_aGapwidthSequence[nUseThisIndex];
410 : }
411 : }
412 883 : }
413 :
414 884 : void BarChart::createShapes()
415 : {
416 884 : if( m_aZSlots.begin() == m_aZSlots.end() ) //no series
417 2 : return;
418 :
419 : OSL_ENSURE(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BarChart is not proper initialized");
420 883 : if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is()))
421 0 : return;
422 :
423 : //the text labels should be always on top of the other series shapes
424 : //therefore create an own group for the texts to move them to front
425 : //(because the text group is created after the series group the texts are displayed on top)
426 :
427 : //the regression curves should always be on top of the bars but beneath the text labels
428 : //to achieve this the regression curve target is created after the series target and before the text target
429 :
430 : uno::Reference< drawing::XShapes > xSeriesTarget(
431 883 : createGroupShape( m_xLogicTarget,OUString() ));
432 : uno::Reference< drawing::XShapes > xRegressionCurveTarget(
433 1766 : createGroupShape( m_xLogicTarget,OUString() ));
434 : uno::Reference< drawing::XShapes > xTextTarget(
435 1766 : m_pShapeFactory->createGroup2D( m_xFinalTarget,OUString() ));
436 :
437 : uno::Reference< drawing::XShapes > xRegressionCurveEquationTarget(
438 1766 : m_pShapeFactory->createGroup2D( m_xFinalTarget,OUString() ));
439 : //check necessary here that different Y axis can not be stacked in the same group? ... hm?
440 :
441 883 : double fLogicZ = 1.0;//as defined
442 :
443 883 : bool bDrawConnectionLines = false;
444 883 : bool bDrawConnectionLinesInited = false;
445 883 : bool bOnlyConnectionLinesForThisPoint = false;
446 :
447 883 : adaptOverlapAndGapwidthForGroupBarsPerAxis();
448 :
449 : //better performance for big data
450 1766 : std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap;
451 883 : m_bPointsWereSkipped = false;
452 883 : sal_Int32 nSkippedPoints = 0;
453 883 : sal_Int32 nCreatedPoints = 0;
454 :
455 883 : sal_Int32 nStartIndex = 0;
456 883 : sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
457 : //iterate through all x values per indices
458 4474 : for( sal_Int32 nPointIndex = nStartIndex; nPointIndex < nEndIndex; nPointIndex++ )
459 : {
460 3591 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
461 3591 : const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
462 :
463 : //sum up the values for all series in a complete z zlot per attached axis
464 3591 : ::std::map< sal_Int32, double > aLogicYSumMap;
465 7182 : for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
466 : {
467 3591 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
468 3591 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
469 :
470 14016 : for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; ++aXSlotIter )
471 : {
472 10425 : sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
473 10425 : if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
474 3591 : aLogicYSumMap[nAttachedAxisIndex]=0.0;
475 :
476 10425 : double fMinimumY = 0.0, fMaximumY = 0.0;
477 : aXSlotIter->calculateYMinAndMaxForCategory( nPointIndex
478 10425 : , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
479 :
480 10425 : if( !::rtl::math::isNan( fMaximumY ) && fMaximumY > 0)
481 10221 : aLogicYSumMap[nAttachedAxisIndex] += fMaximumY;
482 10425 : if( !::rtl::math::isNan( fMinimumY ) && fMinimumY < 0)
483 152 : aLogicYSumMap[nAttachedAxisIndex] += fabs(fMinimumY);
484 : }
485 : }
486 :
487 3591 : aZSlotIter = m_aZSlots.begin();
488 7182 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, nZ++ )
489 : {
490 3591 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
491 3591 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
492 :
493 : //iterate through all x slots in this category
494 3591 : double fSlotX=0;
495 14016 : for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; ++aXSlotIter, fSlotX+=1.0 )
496 : {
497 10425 : sal_Int32 nAttachedAxisIndex = 0;
498 10425 : BarPositionHelper* pPosHelper = m_pMainPosHelper;
499 10425 : if( aXSlotIter != aXSlotEnd )
500 : {
501 10425 : nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
502 : //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
503 10425 : pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
504 10425 : if(!pPosHelper)
505 0 : pPosHelper = m_pMainPosHelper;
506 : }
507 10425 : PlotterBase::m_pPosHelper = pPosHelper;
508 :
509 : //update/create information for current group
510 10425 : pPosHelper->updateSeriesCount( aZSlotIter->size() );
511 10425 : double fLogicBaseWidth = pPosHelper->getScaledSlotWidth();
512 :
513 10425 : ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
514 :
515 : // get distance from base value to maximum and minimum
516 :
517 10425 : double fMinimumY = 0.0, fMaximumY = 0.0;
518 : aXSlotIter->calculateYMinAndMaxForCategory( nPointIndex
519 10425 : , isSeparateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
520 :
521 10425 : double fLogicPositiveYSum = 0.0;
522 10425 : if( !::rtl::math::isNan( fMaximumY ) )
523 10400 : fLogicPositiveYSum = fMaximumY;
524 :
525 10425 : double fLogicNegativeYSum = 0.0;
526 10425 : if( !::rtl::math::isNan( fMinimumY ) )
527 10400 : fLogicNegativeYSum = fMinimumY;
528 :
529 10425 : if( pPosHelper->isPercentY() )
530 : {
531 : /* #i70395# fLogicPositiveYSum contains sum of all positive
532 : values, if any, otherwise the highest negative value.
533 : fLogicNegativeYSum contains sum of all negative values,
534 : if any, otherwise the lowest positive value.
535 : Afterwards, fLogicPositiveYSum will contain the maximum
536 : (positive) value that is related to 100%. */
537 :
538 : // do nothing if there are positive values only
539 32 : if( fLogicNegativeYSum < 0.0 )
540 : {
541 : // fLogicPositiveYSum<0 => negative values only, use absolute of negative sum
542 0 : if( fLogicPositiveYSum < 0.0 )
543 0 : fLogicPositiveYSum = -fLogicNegativeYSum;
544 : // otherwise there are positive and negative values, calculate total distance
545 : else
546 0 : fLogicPositiveYSum -= fLogicNegativeYSum;
547 : }
548 32 : fLogicNegativeYSum = 0.0;
549 : }
550 :
551 10425 : double fBaseValue = 0.0;
552 10425 : if( !pPosHelper->isPercentY() && pSeriesList->size()<=1 )
553 10344 : fBaseValue = pPosHelper->getBaseValueY();
554 10425 : double fPositiveLogicYForNextSeries = fBaseValue;
555 10425 : double fNegativeLogicYForNextSeries = fBaseValue;
556 :
557 10425 : ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
558 10425 : const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
559 : //iterate through all series in this x slot
560 21038 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
561 : {
562 10613 : VDataSeries* pSeries( *aSeriesIter );
563 10613 : if(!pSeries)
564 112 : continue;
565 :
566 10613 : bool bHasFillColorMapping = pSeries->hasPropertyMapping("FillColor");
567 :
568 10613 : bOnlyConnectionLinesForThisPoint = false;
569 :
570 10613 : if(nPointIndex==nStartIndex)//do not create a regression line for each point
571 2681 : createRegressionCurvesShapes( **aSeriesIter, xRegressionCurveTarget, xRegressionCurveEquationTarget,
572 5362 : m_pPosHelper->maySkipPointsInRegressionCalculation());
573 :
574 10613 : if( !bDrawConnectionLinesInited )
575 : {
576 883 : bDrawConnectionLines = pSeries->getConnectBars();
577 883 : if( m_nDimension==3 )
578 42 : bDrawConnectionLines = false;
579 883 : if( bDrawConnectionLines && pSeriesList->size()==1 )
580 : {
581 : //detect whether we have a stacked chart or not:
582 0 : StackingDirection eDirection = pSeries->getStackingDirection();
583 0 : if( eDirection != StackingDirection_Y_STACKING )
584 0 : bDrawConnectionLines = false;
585 : }
586 883 : bDrawConnectionLinesInited = true;
587 : }
588 :
589 : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
590 10613 : getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
591 :
592 : //collect data point information (logic coordinates, style ):
593 10613 : double fUnscaledLogicX = (*aSeriesIter)->getXValue( nPointIndex );
594 10613 : fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution );
595 10613 : if(fUnscaledLogicX<pPosHelper->getLogicMinX())
596 0 : continue;//point not visible
597 10613 : if(fUnscaledLogicX>pPosHelper->getLogicMaxX())
598 0 : continue;//point not visible
599 10613 : if(pPosHelper->isStrongLowerRequested(0) && fUnscaledLogicX==pPosHelper->getLogicMaxX())
600 0 : continue;//point not visible
601 10613 : double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX );
602 :
603 10613 : double fLogicBarHeight = (*aSeriesIter)->getYValue( nPointIndex );
604 10613 : if( ::rtl::math::isNan( fLogicBarHeight )) //no value at this category
605 25 : continue;
606 :
607 10588 : double fLogicValueForLabeDisplay = fLogicBarHeight;
608 10588 : fLogicBarHeight-=fBaseValue;
609 :
610 10588 : if( pPosHelper->isPercentY() )
611 : {
612 96 : if(fLogicPositiveYSum!=0.0)
613 96 : fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum;
614 : else
615 0 : fLogicBarHeight = 0.0;
616 : }
617 :
618 : //sort negative and positive values, to display them on different sides of the x axis
619 10588 : bool bPositive = fLogicBarHeight >= 0.0;
620 10588 : double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries;
621 10588 : double fUpperYValue = fLowerYValue+fLogicBarHeight;
622 10588 : if( bPositive )
623 10436 : fPositiveLogicYForNextSeries += fLogicBarHeight;
624 : else
625 152 : fNegativeLogicYForNextSeries += fLogicBarHeight;
626 :
627 10588 : if(m_nDimension==3)
628 550 : fLogicZ = nZ+0.5;
629 :
630 10588 : drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, fUpperYValue, fLogicZ );
631 :
632 : //@todo ... start an iteration over the different breaks of the axis
633 : //each subsystem may add an additional shape to form the whole point
634 : //create a group shape for this point and add to the series shape:
635 : // uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) );
636 : // uno::Reference<drawing::XShape> xPointGroupShape_Shape =
637 : // uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
638 : //as long as we do not iterate we do not need to create an additional group for each point
639 21089 : uno::Reference< drawing::XShapes > xPointGroupShape_Shapes = xSeriesGroupShape_Shapes;
640 21089 : uno::Reference< beans::XPropertySet > xDataPointProperties( (*aSeriesIter)->getPropertiesOfPoint( nPointIndex ) );
641 10588 : sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
642 10588 : if(m_nDimension==3) try
643 : {
644 550 : xDataPointProperties->getPropertyValue( "Geometry3D") >>= nGeometry3D;
645 : }
646 0 : catch( const uno::Exception& e )
647 : {
648 : ASSERT_EXCEPTION( e );
649 : }
650 :
651 : //@todo iterate through all subsystems to create partial points
652 : {
653 : //@todo select a suitable PositionHelper for this subsystem
654 10588 : BarPositionHelper* pSubPosHelper = pPosHelper;
655 :
656 10588 : double fUnclippedUpperYValue = fUpperYValue;
657 :
658 : //apply clipping to Y
659 10588 : if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) )
660 : {
661 87 : if( bDrawConnectionLines )
662 0 : bOnlyConnectionLinesForThisPoint = true;
663 : else
664 174 : continue;
665 : }
666 : //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects
667 :
668 : //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects)
669 10501 : pSubPosHelper->doLogicScaling(NULL,&fLowerYValue,NULL);
670 10501 : pSubPosHelper->doLogicScaling(NULL,&fUpperYValue,NULL);
671 : //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions
672 :
673 10501 : pSubPosHelper->doLogicScaling(NULL,&fUnclippedUpperYValue,NULL);
674 :
675 : //calculate resulting width
676 10501 : double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum;
677 10501 : if( pPosHelper->isPercentY() )
678 69 : fCompleteHeight = 1.0;
679 10501 : double fLogicBarWidth = fLogicBaseWidth;
680 10501 : double fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
681 10501 : if(!bPositive)
682 152 : fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
683 10501 : double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue;
684 10501 : double fMiddleHeight = fUpperYValue-fLowerYValue;
685 10501 : if(!bPositive)
686 152 : fMiddleHeight*=-1.0;
687 10501 : double fLogicBarDepth = 0.5;
688 10501 : if(m_nDimension==3)
689 : {
690 523 : if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
691 : {
692 144 : double fHeight = fCompleteHeight-fLowerYValue;
693 144 : if(!bPositive)
694 0 : fHeight = fCompleteHeight-fUpperYValue;
695 144 : fLogicBarWidth = fLogicBaseWidth*fHeight/(fCompleteHeight);
696 144 : if(fLogicBarWidth<=0.0)
697 0 : fLogicBarWidth=fLogicBaseWidth;
698 144 : fLogicBarDepth = fLogicBarDepth*fHeight/(fCompleteHeight);
699 144 : if(fLogicBarDepth<=0.0)
700 0 : fLogicBarDepth*=-1.0;
701 : }
702 : }
703 :
704 : //better performance for big data
705 10501 : FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
706 10501 : pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
707 21002 : if( !pSeries->isAttributedDataPoint(nPointIndex)
708 10223 : &&
709 : pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
710 10223 : , fLogicX, fUpperYValue, fLogicZ )
711 10501 : &&
712 : pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
713 0 : , fLogicX, fLowerYValue, fLogicZ )
714 : )
715 : {
716 0 : nSkippedPoints++;
717 0 : m_bPointsWereSkipped = true;
718 0 : continue;
719 : }
720 10501 : aSeriesFormerPointMap[pSeries] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
721 :
722 10501 : if( bDrawConnectionLines )
723 : {
724 : //store point information for connection lines
725 :
726 0 : drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
727 0 : drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUnclippedUpperYValue,fLogicZ );
728 :
729 0 : if( isValidPosition(aLeftUpperPoint) )
730 0 : AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aLeftUpperPoint );
731 0 : if( isValidPosition(aRightUpperPoint) )
732 0 : AddPointToPoly( (*aSeriesIter)->m_aPolyPolygonShape3D, aRightUpperPoint );
733 : }
734 :
735 10501 : if( bOnlyConnectionLinesForThisPoint )
736 0 : continue;
737 :
738 : //maybe additional possibility for performance improvement
739 : //bool bCreateLineInsteadOfComplexGeometryDueToMissingSpace = false;
740 : //pPosHelper->isSameForGivenResolution( fLogicX-fLogicBarWidth/2.0, fLowerYValue, fLogicZ
741 : // , fLogicX+fLogicBarWidth/2.0, fLowerYValue, fLogicZ );
742 :
743 10501 : nCreatedPoints++;
744 : //create partial point
745 10501 : if( !approxEqual(fLowerYValue,fUpperYValue) )
746 : {
747 10465 : uno::Reference< drawing::XShape > xShape;
748 10465 : if( m_nDimension==3 )
749 : {
750 502 : drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ);
751 502 : drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
752 502 : drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
753 502 : drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
754 :
755 502 : uno::Reference< XTransformation > xTransformation = pSubPosHelper->getTransformationScaledLogicToScene();
756 :
757 : //transformation 3) -> 4)
758 502 : drawing::Position3D aTransformedBottom ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicBottom) ) ) );
759 502 : drawing::Position3D aTransformedLeftBottomFront ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicLeftBottomFront) ) ) );
760 502 : drawing::Position3D aTransformedRightDeepTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicRightDeepTop) ) ) );
761 502 : drawing::Position3D aTransformedTopTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicTopTop) ) ) );
762 :
763 502 : drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront;
764 502 : drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop );
765 502 : fTopHeight = aTopSize.DirectionY;
766 :
767 502 : sal_Int32 nRotateZAngleHundredthDegree = 0;
768 502 : if( pPosHelper->isSwapXAndY() )
769 : {
770 132 : fTopHeight = aTopSize.DirectionX;
771 132 : nRotateZAngleHundredthDegree = 90*100;
772 132 : aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
773 : }
774 :
775 502 : if( aSize.DirectionX < 0 )
776 502 : aSize.DirectionX *= -1.0;
777 502 : if( aSize.DirectionZ < 0 )
778 502 : aSize.DirectionZ *= -1.0;
779 502 : if( fTopHeight < 0 )
780 0 : fTopHeight *= -1.0;
781 :
782 1004 : xShape = createDataPoint3D_Bar(
783 : xPointGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree
784 1004 : , xDataPointProperties, nGeometry3D );
785 : }
786 : else //m_nDimension!=3
787 : {
788 : // performance improvement: alloc the sequence before the rendering
789 : // otherwise we have 2 realloc calls
790 9963 : drawing::PolyPolygonShape3D aPoly;
791 9963 : aPoly.SequenceX.realloc(1);
792 9963 : aPoly.SequenceY.realloc(1);
793 9963 : aPoly.SequenceZ.realloc(1);
794 9963 : drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
795 9963 : drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
796 :
797 9963 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
798 9963 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
799 9963 : AddPointToPoly( aPoly, aRightUpperPoint );
800 9963 : AddPointToPoly( aPoly, aLeftUpperPoint );
801 9963 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
802 9963 : pPosHelper->transformScaledLogicToScene( aPoly );
803 9963 : xShape = m_pShapeFactory->createArea2D( xPointGroupShape_Shapes, aPoly );
804 9963 : setMappedProperties( xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
805 : }
806 :
807 10465 : if(bHasFillColorMapping)
808 : {
809 0 : double nPropVal = pSeries->getValueByProperty(nPointIndex, "FillColor");
810 0 : if(!rtl::math::isNan(nPropVal))
811 : {
812 0 : uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW );
813 0 : xProps->setPropertyValue("FillColor", uno::makeAny(static_cast<sal_Int32>(nPropVal)));
814 : }
815 : }
816 : //set name/classified ObjectID (CID)
817 : ShapeFactory::setShapeName(xShape
818 : , ObjectIdentifier::createPointCID(
819 10465 : (*aSeriesIter)->getPointCID_Stub(),nPointIndex) );
820 : }
821 :
822 : //create error bar
823 10501 : createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nPointIndex, m_xLogicTarget, &fLogicX );
824 :
825 : //create data point label
826 10501 : if( (**aSeriesIter).getDataPointLabelIfLabel(nPointIndex) )
827 : {
828 399 : double fLogicSum = aLogicYSumMap[nAttachedAxisIndex];
829 :
830 399 : LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
831 399 : sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
832 :
833 399 : double fLowerBarDepth = fLogicBarDepth;
834 399 : double fUpperBarDepth = fLogicBarDepth;
835 : {
836 399 : double fOuterBarDepth = fLogicBarDepth;
837 399 : if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
838 : {
839 36 : fOuterBarDepth = fLogicBarDepth * (fTopHeight)/(fabs(fCompleteHeight));
840 36 : fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
841 36 : fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
842 : }
843 : }
844 :
845 : awt::Point aScreenPosition2D = getLabelScreenPositionAndAlignment(
846 : eAlignment, nLabelPlacement, fLogicX, fLowerYValue, fUpperYValue, fLogicZ,
847 399 : fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper);
848 399 : sal_Int32 nOffset = 0;
849 399 : if(LABEL_ALIGN_CENTER!=eAlignment)
850 : {
851 298 : nOffset = 100;//add some spacing //@todo maybe get more intelligent values
852 298 : if( m_nDimension == 3 )
853 2 : nOffset = 260;
854 : }
855 : createDataLabel(
856 399 : xTextTarget, **aSeriesIter, nPointIndex,
857 798 : fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset);
858 : }
859 :
860 : }//end iteration through partial points
861 :
862 10501 : }//next series in x slot (next y slot)
863 : }//next x slot
864 : }//next z slot
865 3591 : }//next category
866 883 : if( bDrawConnectionLines )
867 : {
868 0 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
869 0 : const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
870 0 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, nZ++ )
871 : {
872 0 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
873 0 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
874 :
875 0 : BarPositionHelper* pPosHelper = m_pMainPosHelper;
876 0 : if( aXSlotIter != aXSlotEnd )
877 : {
878 0 : sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
879 : //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
880 0 : pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
881 0 : if(!pPosHelper)
882 0 : pPosHelper = m_pMainPosHelper;
883 : }
884 0 : PlotterBase::m_pPosHelper = pPosHelper;
885 :
886 : //iterate through all x slots in this category
887 0 : for( double fSlotX=0; aXSlotIter != aXSlotEnd; ++aXSlotIter, fSlotX+=1.0 )
888 : {
889 0 : ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
890 :
891 0 : ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
892 0 : const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
893 : //iterate through all series in this x slot
894 0 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
895 : {
896 0 : VDataSeries* pSeries( *aSeriesIter );
897 0 : if(!pSeries)
898 0 : continue;
899 0 : drawing::PolyPolygonShape3D* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
900 0 : if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly))
901 0 : continue;
902 :
903 0 : drawing::PolyPolygonShape3D aPoly;
904 0 : Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
905 :
906 0 : if(!ShapeFactory::hasPolygonAnyLines(aPoly))
907 0 : continue;
908 :
909 : //transformation 3) -> 4)
910 0 : pPosHelper->transformScaledLogicToScene( aPoly );
911 :
912 : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
913 0 : getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
914 : uno::Reference< drawing::XShape > xShape( m_pShapeFactory->createLine2D(
915 0 : xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) ) );
916 : setMappedProperties( xShape, pSeries->getPropertiesOfSeries()
917 0 : , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
918 0 : }
919 : }
920 : }
921 : }
922 :
923 : /* @todo remove series shapes if empty
924 : */
925 :
926 : SAL_INFO(
927 : "chart2",
928 : "skipped points: " << nSkippedPoints << " created points: "
929 883 : << nCreatedPoints);
930 : }
931 :
932 : } //namespace chart
933 :
934 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|