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