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