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