1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: VCoordinateSystem.cxx,v $
10 * $Revision: 1.11.36.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "VCoordinateSystem.hxx"
34 #include "VCartesianCoordinateSystem.hxx"
35 #include "VPolarCoordinateSystem.hxx"
36 #include "ScaleAutomatism.hxx"
37 #include "VSeriesPlotter.hxx"
38 #include "ShapeFactory.hxx"
39 #include "servicenames_coosystems.hxx"
41 #include "AxisIndexDefines.hxx"
42 #include "ObjectIdentifier.hxx"
43 #include "ExplicitCategoriesProvider.hxx"
44 #include "AxisHelper.hxx"
45 #include "ContainerHelper.hxx"
46 #include "VAxisBase.hxx"
47 #include "ViewDefines.hxx"
48 #include "DataSeriesHelper.hxx"
49 #include "chartview/ExplicitValueProvider.hxx"
50 #include <com/sun/star/chart2/AxisType.hpp>
51 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
52 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
54 // header for define DBG_ASSERT
55 #include <tools/debug.hxx>
56 #include <rtl/math.hxx>
58 //.............................................................................
61 //.............................................................................
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::chart2
;
64 using ::com::sun::star::uno::Reference
;
65 using ::com::sun::star::uno::Sequence
;
68 VCoordinateSystem
* VCoordinateSystem::createCoordinateSystem(
69 const Reference
< XCoordinateSystem
>& xCooSysModel
)
71 if( !xCooSysModel
.is() )
74 rtl::OUString aViewServiceName
= xCooSysModel
->getViewServiceName();
76 //@todo: in future the coordinatesystems should be instanciated via service factory
77 VCoordinateSystem
* pRet
=NULL
;
78 if( aViewServiceName
.equals( CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME
) )
79 pRet
= new VCartesianCoordinateSystem(xCooSysModel
);
80 else if( aViewServiceName
.equals( CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME
) )
81 pRet
= new VPolarCoordinateSystem(xCooSysModel
);
83 pRet
= new VCoordinateSystem(xCooSysModel
);
87 VCoordinateSystem::VCoordinateSystem( const Reference
< XCoordinateSystem
>& xCooSys
)
88 : m_xCooSysModel(xCooSys
)
89 , m_xLogicTargetForGrids(0)
90 , m_xLogicTargetForAxes(0)
93 , m_aMatrixSceneToScreen()
94 , m_eLeftWallPos(CuboidPlanePosition_Left
)
95 , m_eBackWallPos(CuboidPlanePosition_Back
)
96 , m_eBottomPos(CuboidPlanePosition_Bottom
)
97 , m_aMergedMinimumAndMaximumSupplier()
98 , m_aExplicitScales(3)
99 , m_aExplicitIncrements(3)
100 , m_aExplicitCategoriesProvider( new ExplicitCategoriesProvider( m_xCooSysModel
) )
102 if( !m_xCooSysModel
.is() || m_xCooSysModel
->getDimension()<3 )
104 m_aExplicitScales
[2].Minimum
= -0.5;
105 m_aExplicitScales
[2].Maximum
= 0.5;
106 m_aExplicitScales
[2].Orientation
= AxisOrientation_MATHEMATICAL
;
109 VCoordinateSystem::~VCoordinateSystem()
113 void SAL_CALL
VCoordinateSystem::initPlottingTargets( const Reference
< drawing::XShapes
>& xLogicTarget
114 , const Reference
< drawing::XShapes
>& xFinalTarget
115 , const Reference
< lang::XMultiServiceFactory
>& xShapeFactory
116 , Reference
< drawing::XShapes
>& xLogicTargetForSeriesBehindAxis
)
117 throw (uno::RuntimeException
)
119 DBG_ASSERT(xLogicTarget
.is()&&xFinalTarget
.is()&&xShapeFactory
.is(),"no proper initialization parameters");
120 //is only allowed to be called once
122 sal_Int32 nDimensionCount
= m_xCooSysModel
->getDimension();
123 //create group shape for grids first thus axes are always painted above grids
124 ShapeFactory
aShapeFactory(xShapeFactory
);
125 if(nDimensionCount
==2)
127 //create and add to target
128 m_xLogicTargetForGrids
= aShapeFactory
.createGroup2D( xLogicTarget
);
129 xLogicTargetForSeriesBehindAxis
= aShapeFactory
.createGroup2D( xLogicTarget
);
130 m_xLogicTargetForAxes
= aShapeFactory
.createGroup2D( xLogicTarget
);
134 //create and added to target
135 m_xLogicTargetForGrids
= aShapeFactory
.createGroup3D( xLogicTarget
);
136 xLogicTargetForSeriesBehindAxis
= aShapeFactory
.createGroup3D( xLogicTarget
);
137 m_xLogicTargetForAxes
= aShapeFactory
.createGroup3D( xLogicTarget
);
139 m_xFinalTarget
= xFinalTarget
;
140 m_xShapeFactory
= xShapeFactory
;
143 void VCoordinateSystem::setParticle( const rtl::OUString
& rCooSysParticle
)
145 m_aCooSysParticle
= rCooSysParticle
;
148 void VCoordinateSystem::setTransformationSceneToScreen(
149 const drawing::HomogenMatrix
& rMatrix
)
151 m_aMatrixSceneToScreen
= rMatrix
;
153 //correct transformation for axis
154 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
155 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
156 for( ; aIt
!= aEnd
; ++aIt
)
158 VAxisBase
* pVAxis
= aIt
->second
.get();
161 if(2==pVAxis
->getDimensionCount())
162 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
167 drawing::HomogenMatrix
VCoordinateSystem::getTransformationSceneToScreen()
169 return m_aMatrixSceneToScreen
;
172 //better performance for big data
173 uno::Sequence
< sal_Int32
> VCoordinateSystem::getCoordinateSystemResolution(
174 const awt::Size
& rPageSize
, const awt::Size
& rPageResolution
)
176 uno::Sequence
< sal_Int32
> aResolution(2);
178 sal_Int32 nDimensionCount
= m_xCooSysModel
->getDimension();
179 if(nDimensionCount
>2)
180 aResolution
.realloc(nDimensionCount
);
182 for( nN
= 0 ;nN
<aResolution
.getLength(); nN
++ )
183 aResolution
[nN
]=1000;
185 ::basegfx::B3DTuple
aScale( BaseGFXHelper::GetScaleFromMatrix(
186 BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
187 m_aMatrixSceneToScreen
) ) );
189 double fCoosysWidth
= static_cast< double >( fabs(aScale
.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME
));
190 double fCoosysHeight
= static_cast< double >( fabs(aScale
.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME
));
192 double fPageWidth
= rPageSize
.Width
;
193 double fPageHeight
= rPageSize
.Height
;
195 //factor 2 to avoid rounding problems
196 sal_Int32 nXResolution
= static_cast<sal_Int32
>(2.0*static_cast<double>(rPageResolution
.Width
)*fCoosysWidth
/fPageWidth
);
197 sal_Int32 nYResolution
= static_cast<sal_Int32
>(2.0*static_cast<double>(rPageResolution
.Height
)*fCoosysHeight
/fPageHeight
);
199 if( nXResolution
< 10 )
201 if( nYResolution
< 10 )
204 if( this->getPropertySwapXAndYAxis() )
205 std::swap(nXResolution
,nYResolution
);
208 if( 2 == aResolution
.getLength() )
210 aResolution
[0]=nXResolution
;
211 aResolution
[1]=nYResolution
;
215 //this maybe can be optimized further ...
216 sal_Int32 nMaxResolution
= std::max( nXResolution
, nYResolution
);
218 for( nN
= 0 ;nN
<aResolution
.getLength(); nN
++ )
219 aResolution
[nN
]=nMaxResolution
;
225 Reference
< XCoordinateSystem
> VCoordinateSystem::getModel() const
227 return m_xCooSysModel
;
230 Reference
< XAxis
> VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
232 if( m_xCooSysModel
.is() )
233 return m_xCooSysModel
->getAxisByDimension( nDimensionIndex
, nAxisIndex
);
237 Sequence
< Reference
< beans::XPropertySet
> > VCoordinateSystem::getGridListFromAxis( const Reference
< XAxis
>& xAxis
)
239 std::vector
< Reference
< beans::XPropertySet
> > aRet
;
243 aRet
.push_back( xAxis
->getGridProperties() );
244 std::vector
< Reference
< beans::XPropertySet
> > aSubGrids( ContainerHelper::SequenceToVector( xAxis
->getSubGridProperties() ) );
245 aRet
.insert( aRet
.end(), aSubGrids
.begin(), aSubGrids
.end() );
248 return ContainerHelper::ContainerToSequence( aRet
);
251 void VCoordinateSystem::impl_adjustDimension( sal_Int32
& rDimensionIndex
) const
253 if( rDimensionIndex
<0 )
255 if( rDimensionIndex
>2 )
259 void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32
& rDimensionIndex
, sal_Int32
& rAxisIndex
) const
261 impl_adjustDimension( rDimensionIndex
);
263 if( rAxisIndex
< 0 || rAxisIndex
> this->getMaximumAxisIndexByDimension(rDimensionIndex
) )
268 Reference
< data::XTextualDataSequence
> VCoordinateSystem::getExplicitCategoriesProvider()
270 return m_aExplicitCategoriesProvider
.getRef();
273 Sequence
< ExplicitScaleData
> VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
275 Sequence
< ExplicitScaleData
> aRet(m_aExplicitScales
);
277 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
278 aRet
[nDimensionIndex
]=this->getExplicitScale( nDimensionIndex
, nAxisIndex
);
283 Sequence
< ExplicitIncrementData
> VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
285 Sequence
< ExplicitIncrementData
> aRet(m_aExplicitIncrements
);
287 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
288 aRet
[nDimensionIndex
]=this->getExplicitIncrement( nDimensionIndex
, nAxisIndex
);
293 ExplicitScaleData
VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
295 ExplicitScaleData aRet
;
297 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
301 aRet
= m_aExplicitScales
[nDimensionIndex
];
305 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
306 tFullExplicitScaleMap::const_iterator aIt
= m_aSecondaryExplicitScales
.find( aFullAxisIndex
);
307 if( aIt
!= m_aSecondaryExplicitScales
.end() )
310 aRet
= m_aExplicitScales
[nDimensionIndex
];
316 ExplicitIncrementData
VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
318 ExplicitIncrementData aRet
;
320 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
324 aRet
= m_aExplicitIncrements
[nDimensionIndex
];
328 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
329 tFullExplicitIncrementMap::const_iterator aIt
= m_aSecondaryExplicitIncrements
.find( aFullAxisIndex
);
330 if( aIt
!= m_aSecondaryExplicitIncrements
.end() )
333 aRet
= m_aExplicitIncrements
[nDimensionIndex
];
339 rtl::OUString
VCoordinateSystem::createCIDForAxis( const Reference
< chart2::XAxis
>& /* xAxis */, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
341 rtl::OUString
aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex
, nAxisIndex
) );
342 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle
, aAxisParticle
);
344 rtl::OUString
VCoordinateSystem::createCIDForGrid( const Reference
< chart2::XAxis
>& /* xAxis */, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
346 rtl::OUString
aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex
, nAxisIndex
) );
347 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle
, aGridParticle
);
350 sal_Int32
VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex
) const
353 tFullExplicitScaleMap::const_iterator aIt
= m_aSecondaryExplicitScales
.begin();
354 tFullExplicitScaleMap::const_iterator aEnd
= m_aSecondaryExplicitScales
.end();
355 for(; aIt
!=aEnd
; ++aIt
)
357 if(aIt
->first
.first
==nDimensionIndex
)
359 sal_Int32 nLocalIdx
= aIt
->first
.second
;
360 if( nRet
< nLocalIdx
)
367 void VCoordinateSystem::createVAxisList(
368 const uno::Reference
< util::XNumberFormatsSupplier
> & /* xNumberFormatsSupplier */
369 , const awt::Size
& /* rFontReferenceSize */
370 , const awt::Rectangle
& /* rMaximumSpaceForLabels */
375 void VCoordinateSystem::initVAxisInList()
378 void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
382 void VCoordinateSystem::prepareScaleAutomatismForDimensionAndIndex( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
)
386 ::rtl::math::setInf(&fMin
, false);
387 ::rtl::math::setInf(&fMax
, true);
390 fMin
= m_aMergedMinimumAndMaximumSupplier
.getMinimumX();
391 fMax
= m_aMergedMinimumAndMaximumSupplier
.getMaximumX();
393 else if( 1 == nDimIndex
)
395 ExplicitScaleData aScale
= getExplicitScale( 0, 0 );
396 fMin
= m_aMergedMinimumAndMaximumSupplier
.getMinimumYInRange(aScale
.Minimum
,aScale
.Maximum
, nAxisIndex
);
397 fMax
= m_aMergedMinimumAndMaximumSupplier
.getMaximumYInRange(aScale
.Minimum
,aScale
.Maximum
, nAxisIndex
);
399 else if( 2 == nDimIndex
)
401 fMin
= m_aMergedMinimumAndMaximumSupplier
.getMinimumZ();
402 fMax
= m_aMergedMinimumAndMaximumSupplier
.getMaximumZ();
405 this->prepareScaleAutomatism( rScaleAutomatism
, fMin
, fMax
, nDimIndex
, nAxisIndex
);
408 void VCoordinateSystem::prepareScaleAutomatism( ScaleAutomatism
& rScaleAutomatism
, double fMin
, double fMax
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
)
410 //merge our values with those already contained in rScaleAutomatism
411 rScaleAutomatism
.expandValueRange( fMin
, fMax
);
413 rScaleAutomatism
.setAutoScalingOptions(
414 m_aMergedMinimumAndMaximumSupplier
.isExpandBorderToIncrementRhythm( nDimIndex
),
415 m_aMergedMinimumAndMaximumSupplier
.isExpandIfValuesCloseToBorder( nDimIndex
),
416 m_aMergedMinimumAndMaximumSupplier
.isExpandWideValuesToZero( nDimIndex
),
417 m_aMergedMinimumAndMaximumSupplier
.isExpandNarrowValuesTowardZero( nDimIndex
) );
419 VAxisBase
* pVAxis( this->getVAxis( nDimIndex
, nAxisIndex
) );
421 rScaleAutomatism
.setMaximumAutoMainIncrementCount( pVAxis
->estimateMaximumAutoMainIncrementCount() );
424 VAxisBase
* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
428 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
430 tVAxisMap::const_iterator aIt
= m_aAxisMap
.find( aFullAxisIndex
);
431 if( aIt
!= m_aAxisMap
.end() )
432 pRet
= aIt
->second
.get();
437 void VCoordinateSystem::setExplicitScaleAndIncrement(
438 sal_Int32 nDimensionIndex
439 , sal_Int32 nAxisIndex
440 , const ExplicitScaleData
& rExplicitScale
441 , const ExplicitIncrementData
& rExplicitIncrement
)
443 impl_adjustDimension( nDimensionIndex
);
447 m_aExplicitScales
[nDimensionIndex
]=rExplicitScale
;
448 m_aExplicitIncrements
[nDimensionIndex
]=rExplicitIncrement
;
452 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
453 m_aSecondaryExplicitScales
[aFullAxisIndex
] = rExplicitScale
;
454 m_aSecondaryExplicitIncrements
[aFullAxisIndex
] = rExplicitIncrement
;
458 void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos
, CuboidPlanePosition eBackWallPos
, CuboidPlanePosition eBottomPos
)
460 m_eLeftWallPos
= eLeftWallPos
;
461 m_eBackWallPos
= eBackWallPos
;
462 m_eBottomPos
= eBottomPos
;
465 void VCoordinateSystem::createMaximumAxesLabels()
467 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
468 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
469 for( ; aIt
!= aEnd
; ++aIt
)
471 VAxisBase
* pVAxis
= aIt
->second
.get();
474 if(2==pVAxis
->getDimensionCount())
475 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
476 pVAxis
->createMaximumLabels();
480 void VCoordinateSystem::createAxesLabels()
482 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
483 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
484 for( ; aIt
!= aEnd
; ++aIt
)
486 VAxisBase
* pVAxis
= aIt
->second
.get();
489 if(2==pVAxis
->getDimensionCount())
490 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
491 pVAxis
->createLabels();
496 void VCoordinateSystem::updatePositions()
498 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
499 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
500 for( ; aIt
!= aEnd
; ++aIt
)
502 VAxisBase
* pVAxis
= aIt
->second
.get();
505 if(2==pVAxis
->getDimensionCount())
506 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
507 pVAxis
->updatePositions();
512 void VCoordinateSystem::createAxesShapes()
514 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
515 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
516 for( ; aIt
!= aEnd
; ++aIt
)
518 VAxisBase
* pVAxis
= aIt
->second
.get();
521 if(2==pVAxis
->getDimensionCount())
522 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
524 tFullAxisIndex aFullAxisIndex
= aIt
->first
;
525 if( aFullAxisIndex
.second
== 0 )
527 if( aFullAxisIndex
.first
== 0 )
529 if( AxisType::CATEGORY
!=m_aExplicitScales
[1].AxisType
)
530 pVAxis
->setExrtaLinePositionAtOtherAxis(
531 m_aExplicitScales
[1].Origin
);
533 else if( aFullAxisIndex
.first
== 1 )
535 if( AxisType::CATEGORY
!=m_aExplicitScales
[0].AxisType
)
536 pVAxis
->setExrtaLinePositionAtOtherAxis(
537 m_aExplicitScales
[0].Origin
);
541 pVAxis
->createShapes();
545 void VCoordinateSystem::createGridShapes()
548 void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
550 m_aMergedMinimumAndMaximumSupplier
.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier
);
553 bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
555 return m_aMergedMinimumAndMaximumSupplier
.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier
);
558 void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
560 m_aMergedMinimumAndMaximumSupplier
.clearMinimumAndMaximumSupplierList();
563 bool VCoordinateSystem::getPropertySwapXAndYAxis() const
565 Reference
<beans::XPropertySet
> xProp(m_xCooSysModel
, uno::UNO_QUERY
);
566 sal_Bool bSwapXAndY
= false;
569 xProp
->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY
;
571 catch( uno::Exception
& e
)
573 ASSERT_EXCEPTION( e
);
578 bool VCoordinateSystem::needSeriesNamesForAxis() const
580 return ( m_xCooSysModel
.is() && m_xCooSysModel
->getDimension() == 3 );
582 void VCoordinateSystem::setSeriesNamesForAxis( const Sequence
< rtl::OUString
>& rSeriesNames
)
584 m_aSeriesNamesForZAxis
= rSeriesNames
;
587 sal_Int32
VCoordinateSystem::getNumberFormatKeyForAxis(
588 const Reference
< chart2::XAxis
>& xAxis
589 , const Reference
< util::XNumberFormatsSupplier
>& xNumberFormatsSupplier
)
591 return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
592 xAxis
, m_xCooSysModel
, xNumberFormatsSupplier
);
595 //.............................................................................
597 //.............................................................................