Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "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 : 886 : BarChart::BarChart( const uno::Reference<XChartType>& xChartTypeModel
45 : : , sal_Int32 nDimensionCount )
46 : : : VSeriesPlotter( xChartTypeModel, nDimensionCount )
47 [ + - ][ + - ]: 886 : , m_pMainPosHelper( new BarPositionHelper() )
[ + - ][ + - ]
48 : : {
49 [ + - ]: 886 : PlotterBase::m_pPosHelper = m_pMainPosHelper;
50 [ + - ]: 886 : VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper;
51 : :
52 : : try
53 : : {
54 [ + - ]: 886 : if( m_xChartTypeModelProps.is() )
55 : : {
56 [ + - ][ + - ]: 886 : m_xChartTypeModelProps->getPropertyValue( C2U( "OverlapSequence" ) ) >>= m_aOverlapSequence;
[ + - ][ + - ]
57 [ + - ][ + - ]: 886 : m_xChartTypeModelProps->getPropertyValue( C2U( "GapwidthSequence" ) ) >>= m_aGapwidthSequence;
[ + - ][ # # ]
[ + - ]
58 : : }
59 : : }
60 [ # # ]: 0 : catch( const uno::Exception& e )
61 : : {
62 : : ASSERT_EXCEPTION( e );
63 : : }
64 : 886 : }
65 : :
66 [ + - ][ + - ]: 886 : BarChart::~BarChart()
67 : : {
68 [ + - ][ + - ]: 886 : delete m_pMainPosHelper;
69 [ - + ]: 1772 : }
70 : :
71 : : //-------------------------------------------------------------------------
72 : :
73 : 11108 : PlottingPositionHelper& BarChart::getPlottingPositionHelper( sal_Int32 nAxisIndex ) const
74 : : {
75 : 11108 : PlottingPositionHelper& rPosHelper = VSeriesPlotter::getPlottingPositionHelper( nAxisIndex );
76 [ - + ]: 11108 : BarPositionHelper* pBarPosHelper = dynamic_cast<BarPositionHelper*>(&rPosHelper);
77 [ + - ][ + - ]: 11108 : if( pBarPosHelper && nAxisIndex >= 0 )
78 : : {
79 [ + - ]: 11108 : if( nAxisIndex < m_aOverlapSequence.getLength() )
80 : 11108 : pBarPosHelper->setInnerDistance( -m_aOverlapSequence[nAxisIndex]/100.0 );
81 [ + - ]: 11108 : if( nAxisIndex < m_aGapwidthSequence.getLength() )
82 : 11108 : pBarPosHelper->setOuterDistance( m_aGapwidthSequence[nAxisIndex]/100.0 );
83 : : }
84 : 11108 : return rPosHelper;
85 : : }
86 : :
87 : 886 : drawing::Direction3D BarChart::getPreferredDiagramAspectRatio() const
88 : : {
89 : 886 : drawing::Direction3D aRet(1.0,1.0,1.0);
90 [ + + ]: 886 : if( m_nDimension == 3 )
91 : : {
92 : 3 : aRet = drawing::Direction3D(1.0,-1.0,1.0);
93 [ - + ][ + - ]: 3 : BarPositionHelper* pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( MAIN_AXIS_INDEX) ) );
94 [ + - ]: 3 : drawing::Direction3D aScale( pPosHelper->getScaledLogicWidth() );
95 [ + - ]: 3 : if(aScale.DirectionX!=0.0)
96 : : {
97 : 3 : double fXSlotCount = 1.0;
98 [ + - ]: 3 : if(!m_aZSlots.empty())
99 : 3 : fXSlotCount = m_aZSlots.begin()->size();
100 : :
101 [ + - ]: 3 : aRet.DirectionZ = aScale.DirectionZ/(aScale.DirectionX + aScale.DirectionX*(fXSlotCount-1.0)*pPosHelper->getScaledSlotWidth());
102 : : }
103 : : else
104 [ # # ]: 0 : return VSeriesPlotter::getPreferredDiagramAspectRatio();
105 [ - + ]: 3 : if(aRet.DirectionZ<0.05)
106 : 0 : aRet.DirectionZ=0.05;
107 [ - + ]: 3 : if(aRet.DirectionZ>10)
108 : 0 : aRet.DirectionZ=10;
109 : :
110 [ + - ][ - + ]: 3 : if( m_pMainPosHelper && m_pMainPosHelper->isSwapXAndY() )
[ - + ]
111 : : {
112 : 0 : double fTemp = aRet.DirectionX;
113 : 0 : aRet.DirectionX = aRet.DirectionY;
114 : 3 : aRet.DirectionY = fTemp;
115 : : }
116 : : }
117 : : else
118 : 883 : aRet = drawing::Direction3D(-1,-1,-1);
119 : 886 : 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 : 244 : 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 : 244 : double fX = fScaledX;
137 : 244 : double fY = fScaledUpperYValue;
138 : 244 : double fZ = fScaledZ;
139 [ + - ]: 244 : bool bReverse = !pPosHelper->isMathematicalOrientationY();
140 : 244 : bool bNormalOutside = (!bReverse == !!(fBaseValue < fScaledUpperYValue));
141 : 244 : double fDepth = fScaledUpperBarDepth;
142 : :
143 [ + - - - : 244 : switch(nLabelPlacement)
- - - -
- ]
144 : : {
145 : : case ::com::sun::star::chart::DataLabelPlacement::TOP:
146 : : {
147 [ + - ]: 244 : if( !pPosHelper->isSwapXAndY() )
148 : : {
149 [ - + ]: 244 : fY = bReverse ? fScaledLowerYValue : fScaledUpperYValue;
150 : 244 : rAlignment = LABEL_ALIGN_TOP;
151 [ - + ]: 244 : 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 : 244 : 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 [ - + ]: 244 : if(3==m_nDimension)
258 : 0 : fZ -= fDepth/2.0;
259 : :
260 : : drawing::Position3D aScenePosition3D( pPosHelper->
261 [ + - ]: 244 : transformScaledLogicToScene( fX, fY, fZ, true ) );
262 [ + - ]: 244 : return LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory)
263 [ + - ][ + - ]: 244 : .transformSceneToScreenPosition( aScenePosition3D );
[ + - ]
264 : : }
265 : :
266 : 36 : 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 : 36 : bool bRoundedEdges = true;
274 : : try
275 : : {
276 [ + - ]: 36 : if( xObjectProperties.is() )
277 : : {
278 : 36 : sal_Int16 nPercentDiagonal = 0;
279 [ + - ][ + - ]: 36 : xObjectProperties->getPropertyValue( C2U( "PercentDiagonal" ) ) >>= nPercentDiagonal;
[ + - ][ # # ]
280 [ + - ]: 36 : if( nPercentDiagonal < 5 )
281 : 36 : bRoundedEdges = false;
282 : : }
283 : : }
284 : 0 : catch( const uno::Exception& e )
285 : : {
286 : : ASSERT_EXCEPTION( e );
287 : : }
288 : :
289 : 36 : uno::Reference< drawing::XShape > xShape(NULL);
290 [ - - - + ]: 36 : 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 [ + - ][ + - ]: 36 : , PropertyMapper::getPropertyNameMapForFilledSeriesProperties(), bRoundedEdges );
[ + - ]
307 : 36 : return xShape;
308 : : }
309 [ # # ]: 0 : if( nGeometry3D != DataPointGeometry3D::PYRAMID )
310 [ # # ][ # # ]: 0 : this->setMappedProperties( xShape, xObjectProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
311 : 36 : return xShape;
312 : : }
313 : :
314 : : namespace
315 : : {
316 : 280 : bool lcl_hasGeometry3DVariableWidth( sal_Int32 nGeometry3D )
317 : : {
318 : 280 : bool bRet = false;
319 [ - + ]: 280 : 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 : 280 : bRet = false;
329 : 280 : break;
330 : : }
331 : 280 : return bRet;
332 : : }
333 : : }// end anonymous namespace
334 : :
335 : 2833 : void BarChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot )
336 : : {
337 [ - + ]: 2833 : if( !pSeries )
338 : 2833 : return;
339 [ + + ]: 2833 : 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 : 2824 : sal_Int32 nAxisIndex = pSeries->getAttachedAxisIndex();
345 : 2824 : zSlot = nAxisIndex;
346 : :
347 [ - + ]: 2824 : if( !pSeries->getGroupBarsPerAxis() )
348 : 0 : zSlot = 0;
349 [ + + ]: 2824 : if(zSlot>=static_cast<sal_Int32>(m_aZSlots.size()))
350 : 883 : m_aZSlots.resize(zSlot+1);
351 : : }
352 : 2833 : VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot );
353 : : }
354 : :
355 : : //better performance for big data
356 : : struct FormerBarPoint
357 : : {
358 : 10969 : FormerBarPoint( double fX, double fUpperY, double fLowerY, double fZ )
359 : 10969 : : m_fX(fX), m_fUpperY(fUpperY), m_fLowerY(fLowerY), m_fZ(fZ)
360 : 10969 : {}
361 : 2802 : FormerBarPoint()
362 : : {
363 : 2802 : ::rtl::math::setNan( &m_fX );
364 : 2802 : ::rtl::math::setNan( &m_fUpperY );
365 : 2802 : ::rtl::math::setNan( &m_fLowerY );
366 : 2802 : ::rtl::math::setNan( &m_fZ );
367 : 2802 : }
368 : :
369 : : double m_fX;
370 : : double m_fUpperY;
371 : : double m_fLowerY;
372 : : double m_fZ;
373 : : };
374 : :
375 : 886 : 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 : 886 : VDataSeries* pFirstSeries = getFirstSeries();
381 [ - + ][ - + ]: 886 : 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 : 886 : }
404 : :
405 : 886 : void BarChart::createShapes()
406 : : {
407 [ + - ][ + - ]: 886 : 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 [ + - ][ + - ]: 886 : 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 [ + - ]: 886 : createGroupShape( m_xLogicTarget,rtl::OUString() ));
423 : : uno::Reference< drawing::XShapes > xRegressionCurveTarget(
424 [ + - ]: 886 : createGroupShape( m_xLogicTarget,rtl::OUString() ));
425 : : uno::Reference< drawing::XShapes > xTextTarget(
426 [ + - ]: 886 : m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() ));
427 : :
428 : :
429 : : //---------------------------------------------
430 : : uno::Reference< drawing::XShapes > xRegressionCurveEquationTarget(
431 [ + - ]: 886 : 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 : 886 : double fLogicZ = 1.0;//as defined
435 : :
436 : 886 : bool bDrawConnectionLines = false;
437 : 886 : bool bDrawConnectionLinesInited = false;
438 : 886 : bool bOnlyConnectionLinesForThisPoint = false;
439 : :
440 [ + - ]: 886 : adaptOverlapAndGapwidthForGroupBarsPerAxis();
441 : :
442 : : //better performance for big data
443 [ + - ]: 886 : std::map< VDataSeries*, FormerBarPoint > aSeriesFormerPointMap;
444 : 886 : m_bPointsWereSkipped = false;
445 : 886 : sal_Int32 nSkippedPoints = 0;
446 : 886 : sal_Int32 nCreatedPoints = 0;
447 : : //
448 : :
449 : 886 : sal_Int32 nStartIndex = 0;
450 [ + - ]: 886 : sal_Int32 nEndIndex = VSeriesPlotter::getPointCount();
451 : : //=============================================================================
452 : : //iterate through all x values per indices
453 [ + + ]: 4432 : for( sal_Int32 nPointIndex = nStartIndex; nPointIndex < nEndIndex; nPointIndex++ )
454 : : {
455 : 3546 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
456 [ + - ]: 3546 : 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 [ + - ]: 3546 : ::std::map< sal_Int32, double > aLogicYSumMap;
460 [ + - ][ + + ]: 7092 : for( ; aZSlotIter != aZSlotEnd; ++aZSlotIter )
461 : : {
462 : 3546 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
463 [ + - ]: 3546 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
464 : :
465 [ + - ][ + + ]: 14651 : for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; ++aXSlotIter )
466 : : {
467 [ + - ]: 11105 : sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
468 [ + - ][ + - ]: 11105 : if( aLogicYSumMap.find(nAttachedAxisIndex)==aLogicYSumMap.end() )
[ + + ]
469 [ + - ]: 3546 : aLogicYSumMap[nAttachedAxisIndex]=0.0;
470 : :
471 : 11105 : double fMinimumY = 0.0, fMaximumY = 0.0;
472 : : aXSlotIter->calculateYMinAndMaxForCategory( nPointIndex
473 [ + - ][ + - ]: 11105 : , isSeperateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
474 : :
475 [ + + ][ + + ]: 11105 : if( !::rtl::math::isNan( fMaximumY ) && fMaximumY > 0)
[ + + ]
476 [ + - ]: 10881 : aLogicYSumMap[nAttachedAxisIndex] += fMaximumY;
477 [ + + ][ + + ]: 11105 : if( !::rtl::math::isNan( fMinimumY ) && fMinimumY < 0)
[ + + ]
478 [ + - ]: 190 : aLogicYSumMap[nAttachedAxisIndex] += fabs(fMinimumY);
479 : : }
480 : : }
481 : :
482 : : //=============================================================================
483 : 3546 : aZSlotIter = m_aZSlots.begin();
484 [ + - ][ + + ]: 7092 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, nZ++ )
485 : : {
486 : 3546 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
487 [ + - ]: 3546 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
488 : :
489 : : //=============================================================================
490 : : //iterate through all x slots in this category
491 : 3546 : double fSlotX=0;
492 [ + - ][ + + ]: 14651 : for( aXSlotIter = aZSlotIter->begin(); aXSlotIter != aXSlotEnd; ++aXSlotIter, fSlotX+=1.0 )
493 : : {
494 : 11105 : sal_Int32 nAttachedAxisIndex = 0;
495 : 11105 : BarPositionHelper* pPosHelper = m_pMainPosHelper;
496 [ + - ][ + - ]: 11105 : if( aXSlotIter != aXSlotEnd )
497 : : {
498 [ + - ]: 11105 : nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
499 : : //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
500 [ + - ][ - + ]: 11105 : pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
501 [ - + ]: 11105 : if(!pPosHelper)
502 : 0 : pPosHelper = m_pMainPosHelper;
503 : : }
504 [ + - ]: 11105 : PlotterBase::m_pPosHelper = pPosHelper;
505 : :
506 : : //update/create information for current group
507 [ + - ]: 11105 : pPosHelper->updateSeriesCount( aZSlotIter->size() );
508 [ + - ]: 11105 : double fLogicBaseWidth = pPosHelper->getScaledSlotWidth();
509 : :
510 : 11105 : ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
511 : :
512 : : // get distance from base value to maximum and minimum
513 : :
514 : 11105 : double fMinimumY = 0.0, fMaximumY = 0.0;
515 : : aXSlotIter->calculateYMinAndMaxForCategory( nPointIndex
516 [ + - ][ + - ]: 11105 : , isSeperateStackingForDifferentSigns( 1 ), fMinimumY, fMaximumY, nAttachedAxisIndex );
517 : :
518 : 11105 : double fLogicPositiveYSum = 0.0;
519 [ + + ]: 11105 : if( !::rtl::math::isNan( fMaximumY ) )
520 : 11089 : fLogicPositiveYSum = fMaximumY;
521 : :
522 : 11105 : double fLogicNegativeYSum = 0.0;
523 [ + + ]: 11105 : if( !::rtl::math::isNan( fMinimumY ) )
524 : 11089 : fLogicNegativeYSum = fMinimumY;
525 : :
526 [ + - ][ - + ]: 11105 : 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 : 11105 : double fBaseValue = 0.0;
549 [ + - ][ + - ]: 11105 : if( !pPosHelper->isPercentY() && pSeriesList->size()<=1 )
[ + - ][ + - ]
550 [ + - ]: 11105 : fBaseValue = pPosHelper->getBaseValueY();
551 : 11105 : double fPositiveLogicYForNextSeries = fBaseValue;
552 : 11105 : double fNegativeLogicYForNextSeries = fBaseValue;
553 : :
554 [ + - ]: 11105 : ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
555 [ + - ]: 11105 : const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
556 [ + - ]: 11105 : aSeriesIter = pSeriesList->begin();
557 : : //=============================================================================
558 : : //iterate through all series in this x slot
559 [ + - ][ + + ]: 22210 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
560 : : {
561 : 11105 : VDataSeries* pSeries( *aSeriesIter );
562 [ - + ]: 11105 : if(!pSeries)
563 : 0 : continue;
564 : :
565 : 11105 : bOnlyConnectionLinesForThisPoint = false;
566 : :
567 [ + + ]: 11105 : if(nPointIndex==nStartIndex)//do not create a regression line for each point
568 : 2833 : createRegressionCurvesShapes( **aSeriesIter, xRegressionCurveTarget, xRegressionCurveEquationTarget,
569 [ + - ]: 5666 : m_pPosHelper->maySkipPointsInRegressionCalculation());
570 : :
571 [ + + ]: 11105 : if( !bDrawConnectionLinesInited )
572 : : {
573 [ + - ]: 886 : bDrawConnectionLines = pSeries->getConnectBars();
574 [ + + ]: 886 : if( m_nDimension==3 )
575 : 3 : bDrawConnectionLines = false;
576 [ - + ][ # # ]: 886 : if( bDrawConnectionLines && pSeriesList->size()==1 )
[ - + ]
577 : : {
578 : : //detect whether we have a stacked chart or not:
579 [ # # ]: 0 : StackingDirection eDirection = pSeries->getStackingDirection();
580 [ # # ]: 0 : if( eDirection != StackingDirection_Y_STACKING )
581 : 0 : bDrawConnectionLines = false;
582 : : }
583 : 886 : bDrawConnectionLinesInited = true;
584 : : }
585 : :
586 : : //------------
587 : :
588 : : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
589 [ + - ]: 11105 : getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
590 : :
591 : : //collect data point information (logic coordinates, style ):
592 [ + - ]: 11105 : double fUnscaledLogicX = (*aSeriesIter)->getXValue( nPointIndex );
593 [ + - ]: 11105 : fUnscaledLogicX = DateHelper::RasterizeDateValue( fUnscaledLogicX, m_aNullDate, m_nTimeResolution );
594 [ + - ][ - + ]: 11105 : if(fUnscaledLogicX<pPosHelper->getLogicMinX())
595 : 0 : continue;//point not visible
596 [ + - ][ - + ]: 11105 : if(fUnscaledLogicX>pPosHelper->getLogicMaxX())
597 : 0 : continue;//point not visible
598 [ + - ][ + - ]: 11105 : if(pPosHelper->isStrongLowerRequested(0) && fUnscaledLogicX==pPosHelper->getLogicMaxX())
[ + - ][ - + ]
[ - + ]
599 : 0 : continue;//point not visible
600 [ + - ]: 11105 : double fLogicX = pPosHelper->getScaledSlotPos( fUnscaledLogicX, fSlotX );
601 : :
602 [ + - ]: 11105 : double fLogicBarHeight = (*aSeriesIter)->getYValue( nPointIndex );
603 [ + + ]: 11105 : if( ::rtl::math::isNan( fLogicBarHeight )) //no value at this category
604 : 16 : continue;
605 : :
606 : 11089 : double fLogicValueForLabeDisplay = fLogicBarHeight;
607 : 11089 : fLogicBarHeight-=fBaseValue;
608 : :
609 [ + - ][ - + ]: 11089 : if( pPosHelper->isPercentY() )
610 : : {
611 [ # # ]: 0 : if(fLogicPositiveYSum!=0.0)
612 : 0 : fLogicBarHeight = fabs( fLogicBarHeight )/fLogicPositiveYSum;
613 : : else
614 : 0 : fLogicBarHeight = 0.0;
615 : : }
616 : :
617 : : //sort negative and positive values, to display them on different sides of the x axis
618 : 11089 : bool bPositive = fLogicBarHeight >= 0.0;
619 [ + + ]: 11089 : double fLowerYValue = bPositive ? fPositiveLogicYForNextSeries : fNegativeLogicYForNextSeries;
620 : 11089 : double fUpperYValue = fLowerYValue+fLogicBarHeight;
621 [ + + ]: 11089 : if( bPositive )
622 : 10899 : fPositiveLogicYForNextSeries += fLogicBarHeight;
623 : : else
624 : 190 : fNegativeLogicYForNextSeries += fLogicBarHeight;
625 : :
626 [ + + ]: 11089 : if(m_nDimension==3)
627 : 36 : fLogicZ = nZ+0.5;
628 : :
629 : 11089 : drawing::Position3D aUnscaledLogicPosition( fUnscaledLogicX, fUpperYValue, fLogicZ );
630 : :
631 : : //@todo ... start an iteration over the different breaks of the axis
632 : : //each subsystem may add an additional shape to form the whole point
633 : : //create a group shape for this point and add to the series shape:
634 : : // uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( createGroupShape(xSeriesGroupShape_Shapes) );
635 : : // uno::Reference<drawing::XShape> xPointGroupShape_Shape =
636 : : // uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY );
637 : : //as long as we do not iterate we do not need to create an additional group for each point
638 : 11089 : uno::Reference< drawing::XShapes > xPointGroupShape_Shapes = xSeriesGroupShape_Shapes;
639 [ + - ]: 11089 : uno::Reference< beans::XPropertySet > xDataPointProperties( (*aSeriesIter)->getPropertiesOfPoint( nPointIndex ) );
640 : 11089 : sal_Int32 nGeometry3D = DataPointGeometry3D::CUBOID;
641 [ + + ]: 11089 : if(m_nDimension==3) try
642 : : {
643 [ + - ][ + - ]: 36 : xDataPointProperties->getPropertyValue( C2U( "Geometry3D" )) >>= nGeometry3D;
[ + - ][ # # ]
644 : : }
645 [ # # ]: 0 : catch( const uno::Exception& e )
646 : : {
647 : : ASSERT_EXCEPTION( e );
648 : : }
649 : :
650 : : //@todo iterate through all subsystems to create partial points
651 : : {
652 : : //@todo select a suiteable PositionHelper for this subsystem
653 : 11089 : BarPositionHelper* pSubPosHelper = pPosHelper;
654 : :
655 : 11089 : double fUnclippedUpperYValue = fUpperYValue;
656 : :
657 : : //apply clipping to Y
658 [ + - ][ + + ]: 11089 : if( !pPosHelper->clipYRange(fLowerYValue,fUpperYValue) )
659 : : {
660 [ - + ]: 120 : if( bDrawConnectionLines )
661 : 0 : bOnlyConnectionLinesForThisPoint = true;
662 : : else
663 : 120 : continue;
664 : : }
665 : : //@todo clipping of X and Z is not fully integrated so far, as there is a need to create different objects
666 : :
667 : : //apply scaling to Y before calculating width (necessary to maintain gradient in clipped objects)
668 [ + - ]: 10969 : pSubPosHelper->doLogicScaling(NULL,&fLowerYValue,NULL);
669 [ + - ]: 10969 : pSubPosHelper->doLogicScaling(NULL,&fUpperYValue,NULL);
670 : : //scaling of X and Z is not provided as the created objects should be symmetric in that dimensions
671 : :
672 [ + - ]: 10969 : pSubPosHelper->doLogicScaling(NULL,&fUnclippedUpperYValue,NULL);
673 : :
674 : : //calculate resulting width
675 [ + + ]: 10969 : double fCompleteHeight = bPositive ? fLogicPositiveYSum : fLogicNegativeYSum;
676 [ + - ][ - + ]: 10969 : if( pPosHelper->isPercentY() )
677 : 0 : fCompleteHeight = 1.0;
678 : 10969 : double fLogicBarWidth = fLogicBaseWidth;
679 : 10969 : double fTopHeight=approxSub(fCompleteHeight,fUpperYValue);
680 [ + + ]: 10969 : if(!bPositive)
681 : 190 : fTopHeight=approxSub(fCompleteHeight,fLowerYValue);
682 [ + + ]: 10969 : double fLogicYStart = bPositive ? fLowerYValue : fUpperYValue;
683 : 10969 : double fMiddleHeight = fUpperYValue-fLowerYValue;
684 [ + + ]: 10969 : if(!bPositive)
685 : 190 : fMiddleHeight*=-1.0;
686 : 10969 : double fLogicBarDepth = 0.5;
687 [ + + ]: 10969 : if(m_nDimension==3)
688 : : {
689 [ - + ][ # # ]: 36 : if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
[ - + ]
690 : : {
691 : 0 : double fHeight = fCompleteHeight-fLowerYValue;
692 [ # # ]: 0 : if(!bPositive)
693 : 0 : fHeight = fCompleteHeight-fUpperYValue;
694 : 0 : fLogicBarWidth = fLogicBaseWidth*fHeight/(fCompleteHeight);
695 [ # # ]: 0 : if(fLogicBarWidth<=0.0)
696 : 0 : fLogicBarWidth=fLogicBaseWidth;
697 : 0 : fLogicBarDepth = fLogicBarDepth*fHeight/(fCompleteHeight);
698 [ # # ]: 0 : if(fLogicBarDepth<=0.0)
699 : 0 : fLogicBarDepth*=-1.0;
700 : : }
701 : : }
702 : :
703 : : //better performance for big data
704 [ + - ]: 10969 : FormerBarPoint aFormerPoint( aSeriesFormerPointMap[pSeries] );
705 [ + - ]: 10969 : pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution );
706 [ + - ][ + + ]: 21694 : if( !pSeries->isAttributedDataPoint(nPointIndex)
[ - + ][ # # ]
[ - + ]
707 : : &&
708 : : pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fUpperY, aFormerPoint.m_fZ
709 [ + - ]: 10725 : , fLogicX, fUpperYValue, fLogicZ )
710 : : &&
711 : : pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fLowerY, aFormerPoint.m_fZ
712 [ # # ]: 0 : , fLogicX, fLowerYValue, fLogicZ )
713 : : )
714 : : {
715 : 0 : nSkippedPoints++;
716 : 0 : m_bPointsWereSkipped = true;
717 : 0 : continue;
718 : : }
719 [ + - ]: 10969 : aSeriesFormerPointMap[pSeries] = FormerBarPoint(fLogicX,fUpperYValue,fLowerYValue,fLogicZ);
720 : : //
721 : :
722 : : //
723 [ - + ]: 10969 : 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 [ - + ]: 10969 : 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 : 10969 : nCreatedPoints++;
745 : : //create partial point
746 [ + + ]: 10969 : if( !approxEqual(fLowerYValue,fUpperYValue) )
747 : : {
748 : 10951 : uno::Reference< drawing::XShape > xShape;
749 [ + + ]: 10951 : if( m_nDimension==3 )
750 : : {
751 : 36 : drawing::Position3D aLogicBottom (fLogicX,fLogicYStart,fLogicZ);
752 : 36 : drawing::Position3D aLogicLeftBottomFront (fLogicX+fLogicBarWidth/2.0,fLogicYStart,fLogicZ-fLogicBarDepth/2.0);
753 : 36 : drawing::Position3D aLogicRightDeepTop (fLogicX-fLogicBarWidth/2.0,fLogicYStart+fMiddleHeight,fLogicZ+fLogicBarDepth/2.0);
754 : 36 : drawing::Position3D aLogicTopTop (fLogicX,fLogicYStart+fMiddleHeight+fTopHeight,fLogicZ);
755 : :
756 [ + - ]: 36 : uno::Reference< XTransformation > xTransformation = pSubPosHelper->getTransformationScaledLogicToScene();
757 : :
758 : : //transformation 3) -> 4)
759 [ + - ][ + - ]: 36 : drawing::Position3D aTransformedBottom ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicBottom) ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
760 [ + - ][ + - ]: 36 : drawing::Position3D aTransformedLeftBottomFront ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicLeftBottomFront) ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
761 [ + - ][ + - ]: 36 : drawing::Position3D aTransformedRightDeepTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicRightDeepTop) ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
762 [ + - ][ + - ]: 36 : drawing::Position3D aTransformedTopTop ( SequenceToPosition3D( xTransformation->transform( Position3DToSequence(aLogicTopTop) ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
763 : :
764 [ + - ]: 36 : drawing::Direction3D aSize = aTransformedRightDeepTop - aTransformedLeftBottomFront;
765 [ + - ]: 36 : drawing::Direction3D aTopSize( aTransformedTopTop - aTransformedRightDeepTop );
766 : 36 : fTopHeight = aTopSize.DirectionY;
767 : :
768 : 36 : sal_Int32 nRotateZAngleHundredthDegree = 0;
769 [ - + ]: 36 : if( pPosHelper->isSwapXAndY() )
770 : : {
771 : 0 : fTopHeight = aTopSize.DirectionX;
772 : 0 : nRotateZAngleHundredthDegree = 90*100;
773 : 0 : aSize = drawing::Direction3D(aSize.DirectionY,aSize.DirectionX,aSize.DirectionZ);
774 : : }
775 : :
776 [ + - ]: 36 : if( aSize.DirectionX < 0 )
777 : 36 : aSize.DirectionX *= -1.0;
778 [ + - ]: 36 : if( aSize.DirectionZ < 0 )
779 : 36 : aSize.DirectionZ *= -1.0;
780 [ - + ]: 36 : if( fTopHeight < 0 )
781 : 0 : fTopHeight *= -1.0;
782 : :
783 : : xShape = createDataPoint3D_Bar(
784 : : xPointGroupShape_Shapes, aTransformedBottom, aSize, fTopHeight, nRotateZAngleHundredthDegree
785 [ + - ][ + - ]: 36 : , xDataPointProperties, nGeometry3D );
786 : : }
787 : : else //m_nDimension!=3
788 : : {
789 [ + - ]: 10915 : drawing::PolyPolygonShape3D aPoly;
790 : 10915 : drawing::Position3D aLeftUpperPoint( fLogicX-fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
791 : 10915 : drawing::Position3D aRightUpperPoint( fLogicX+fLogicBarWidth/2.0,fUpperYValue,fLogicZ );
792 : :
793 [ + - ]: 10915 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
794 [ + - ]: 10915 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX+fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
795 [ + - ]: 10915 : AddPointToPoly( aPoly, aRightUpperPoint );
796 [ + - ]: 10915 : AddPointToPoly( aPoly, aLeftUpperPoint );
797 [ + - ]: 10915 : AddPointToPoly( aPoly, drawing::Position3D( fLogicX-fLogicBarWidth/2.0,fLowerYValue,fLogicZ) );
798 [ + - ]: 10915 : pPosHelper->transformScaledLogicToScene( aPoly );
799 [ + - ][ + - ]: 10915 : xShape = m_pShapeFactory->createArea2D( xPointGroupShape_Shapes, aPoly );
800 [ + - ][ + - ]: 10915 : this->setMappedProperties( xShape, xDataPointProperties, PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
[ + - ]
801 : : }
802 : : //set name/classified ObjectID (CID)
803 : : ShapeFactory::setShapeName(xShape
804 : : , ObjectIdentifier::createPointCID(
805 [ + - ][ + - ]: 10951 : (*aSeriesIter)->getPointCID_Stub(),nPointIndex) );
[ + - ]
806 : : }
807 : :
808 : : //create error bar
809 [ + - ]: 10969 : createErrorBar_Y( aUnscaledLogicPosition, **aSeriesIter, nPointIndex, m_xLogicTarget, &fLogicX );
810 : :
811 : : //------------
812 : : //create data point label
813 [ + - ][ + + ]: 10969 : if( (**aSeriesIter).getDataPointLabelIfLabel(nPointIndex) )
814 : : {
815 [ + - ]: 244 : double fLogicSum = aLogicYSumMap[nAttachedAxisIndex];
816 : :
817 : 244 : LabelAlignment eAlignment(LABEL_ALIGN_CENTER);
818 [ + - ]: 244 : sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nPointIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() );
819 : :
820 : 244 : double fLowerBarDepth = fLogicBarDepth;
821 : 244 : double fUpperBarDepth = fLogicBarDepth;
822 : : {
823 : 244 : double fOuterBarDepth = fLogicBarDepth;
824 [ - + ][ # # ]: 244 : if( lcl_hasGeometry3DVariableWidth(nGeometry3D) && fCompleteHeight!=0.0 )
[ - + ]
825 : : {
826 : 0 : fOuterBarDepth = fLogicBarDepth * (fTopHeight)/(fabs(fCompleteHeight));
827 [ # # ]: 0 : fLowerBarDepth = (fBaseValue < fUpperYValue) ? fabs(fLogicBarDepth) : fabs(fOuterBarDepth);
828 [ # # ]: 0 : fUpperBarDepth = (fBaseValue < fUpperYValue) ? fabs(fOuterBarDepth) : fabs(fLogicBarDepth);
829 : : }
830 : : }
831 : :
832 : : awt::Point aScreenPosition2D( this->getLabelScreenPositionAndAlignment(
833 : : eAlignment, nLabelPlacement
834 : : , fLogicX, fLowerYValue, fUpperYValue, fLogicZ
835 [ + - ]: 244 : , fLowerBarDepth, fUpperBarDepth, fBaseValue, pPosHelper ));
836 : 244 : sal_Int32 nOffset = 0;
837 [ + - ]: 244 : if(LABEL_ALIGN_CENTER!=eAlignment)
838 : : {
839 : 244 : nOffset = 100;//add some spacing //@todo maybe get more intelligent values
840 [ - + ]: 244 : if( m_nDimension == 3 )
841 : 0 : nOffset = 260;
842 : : }
843 : 244 : this->createDataLabel( xTextTarget, **aSeriesIter, nPointIndex
844 [ + - ]: 11089 : , fLogicValueForLabeDisplay, fLogicSum, aScreenPosition2D, eAlignment, nOffset );
845 : : }
846 : :
847 : : }//end iteration through partial points
848 : :
849 [ + + ][ + + ]: 11105 : }//next series in x slot (next y slot)
[ + + ]
850 : : }//next x slot
851 : : }//next z slot
852 : 3546 : }//next category
853 : : //=============================================================================
854 : : //=============================================================================
855 : : //=============================================================================
856 [ - + ]: 886 : if( bDrawConnectionLines )
857 : : {
858 : 0 : ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin();
859 [ # # ]: 0 : const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end();
860 : : //=============================================================================
861 [ # # ][ # # ]: 0 : for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; ++aZSlotIter, nZ++ )
862 : : {
863 : 0 : ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin();
864 [ # # ]: 0 : const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end();
865 : :
866 : 0 : BarPositionHelper* pPosHelper = m_pMainPosHelper;
867 [ # # ][ # # ]: 0 : if( aXSlotIter != aXSlotEnd )
868 : : {
869 [ # # ]: 0 : sal_Int32 nAttachedAxisIndex = aXSlotIter->getAttachedAxisIndexForFirstSeries();
870 : : //2ND_AXIS_IN_BARS so far one can assume to have the same plotter for each z slot
871 [ # # ][ # # ]: 0 : pPosHelper = dynamic_cast<BarPositionHelper*>(&( this->getPlottingPositionHelper( nAttachedAxisIndex ) ) );
872 [ # # ]: 0 : if(!pPosHelper)
873 : 0 : pPosHelper = m_pMainPosHelper;
874 : : }
875 [ # # ]: 0 : PlotterBase::m_pPosHelper = pPosHelper;
876 : :
877 : : //=============================================================================
878 : : //iterate through all x slots in this category
879 [ # # ][ # # ]: 0 : for( double fSlotX=0; aXSlotIter != aXSlotEnd; ++aXSlotIter, fSlotX+=1.0 )
880 : : {
881 : 0 : ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector);
882 : :
883 [ # # ]: 0 : ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin();
884 [ # # ]: 0 : const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end();
885 [ # # ]: 0 : aSeriesIter = pSeriesList->begin();
886 : : //=============================================================================
887 : : //iterate through all series in this x slot
888 [ # # ][ # # ]: 0 : for( ; aSeriesIter != aSeriesEnd; ++aSeriesIter )
889 : : {
890 : 0 : VDataSeries* pSeries( *aSeriesIter );
891 [ # # ]: 0 : if(!pSeries)
892 : 0 : continue;
893 : 0 : drawing::PolyPolygonShape3D* pSeriesPoly = &pSeries->m_aPolyPolygonShape3D;
894 [ # # ][ # # ]: 0 : if(!ShapeFactory::hasPolygonAnyLines(*pSeriesPoly))
895 : 0 : continue;
896 : :
897 [ # # ]: 0 : drawing::PolyPolygonShape3D aPoly;
898 [ # # ][ # # ]: 0 : Clipping::clipPolygonAtRectangle( *pSeriesPoly, pPosHelper->getScaledLogicClipDoubleRect(), aPoly );
899 : :
900 [ # # ][ # # ]: 0 : if(!ShapeFactory::hasPolygonAnyLines(aPoly))
901 : 0 : continue;
902 : :
903 : : //transformation 3) -> 4)
904 [ # # ]: 0 : pPosHelper->transformScaledLogicToScene( aPoly );
905 : :
906 : : uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes(
907 [ # # ]: 0 : getSeriesGroupShape(*aSeriesIter, xSeriesTarget) );
908 : : uno::Reference< drawing::XShape > xShape( m_pShapeFactory->createLine2D(
909 [ # # ][ # # ]: 0 : xSeriesGroupShape_Shapes, PolyToPointSequence( aPoly ) ) );
[ # # ]
910 : : this->setMappedProperties( xShape, pSeries->getPropertiesOfSeries()
911 [ # # ][ # # ]: 0 : , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() );
[ # # ]
912 [ # # ][ # # ]: 0 : }
913 : : }
914 : : }
915 : : }
916 : :
917 : : /* @todo remove series shapes if empty
918 : : */
919 : :
920 : 886 : OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< bar chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints );
921 : : }
922 : :
923 : : //.............................................................................
924 : : } //namespace chart
925 : : //.............................................................................
926 : :
927 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|