1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "VCoordinateSystem.hxx"
21 #include "VCartesianCoordinateSystem.hxx"
22 #include "VPolarCoordinateSystem.hxx"
23 #include "ScaleAutomatism.hxx"
24 #include "VSeriesPlotter.hxx"
25 #include "AbstractShapeFactory.hxx"
26 #include "servicenames_coosystems.hxx"
28 #include "AxisIndexDefines.hxx"
29 #include "ObjectIdentifier.hxx"
30 #include "ExplicitCategoriesProvider.hxx"
31 #include "AxisHelper.hxx"
32 #include "ContainerHelper.hxx"
33 #include "VAxisBase.hxx"
34 #include "ViewDefines.hxx"
35 #include "DataSeriesHelper.hxx"
36 #include "defines.hxx"
37 #include "chartview/ExplicitValueProvider.hxx"
38 #include <com/sun/star/chart2/AxisType.hpp>
39 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
40 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
42 #include <rtl/math.hxx>
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::chart2
;
48 using ::com::sun::star::uno::Reference
;
49 using ::com::sun::star::uno::Sequence
;
51 VCoordinateSystem
* VCoordinateSystem::createCoordinateSystem(
52 const Reference
< XCoordinateSystem
>& xCooSysModel
)
54 if( !xCooSysModel
.is() )
57 OUString aViewServiceName
= xCooSysModel
->getViewServiceName();
59 //@todo: in future the coordinatesystems should be instantiated via service factory
60 VCoordinateSystem
* pRet
=NULL
;
61 if( aViewServiceName
== CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME
)
62 pRet
= new VCartesianCoordinateSystem(xCooSysModel
);
63 else if( aViewServiceName
== CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME
)
64 pRet
= new VPolarCoordinateSystem(xCooSysModel
);
66 pRet
= new VCoordinateSystem(xCooSysModel
);
70 VCoordinateSystem::VCoordinateSystem( const Reference
< XCoordinateSystem
>& xCooSys
)
71 : m_xCooSysModel(xCooSys
)
72 , m_xLogicTargetForGrids(0)
73 , m_xLogicTargetForAxes(0)
76 , m_aMatrixSceneToScreen()
77 , m_eLeftWallPos(CuboidPlanePosition_Left
)
78 , m_eBackWallPos(CuboidPlanePosition_Back
)
79 , m_eBottomPos(CuboidPlanePosition_Bottom
)
80 , m_aMergedMinMaxSupplier()
81 , m_aExplicitScales(3)
82 , m_aExplicitIncrements(3)
83 , m_apExplicitCategoriesProvider(NULL
)
85 if( !m_xCooSysModel
.is() || m_xCooSysModel
->getDimension()<3 )
87 m_aExplicitScales
[2].Minimum
= 1.0;
88 m_aExplicitScales
[2].Maximum
= 2.0;
89 m_aExplicitScales
[2].Orientation
= AxisOrientation_MATHEMATICAL
;
92 VCoordinateSystem::~VCoordinateSystem()
96 void VCoordinateSystem::initPlottingTargets( const Reference
< drawing::XShapes
>& xLogicTarget
97 , const Reference
< drawing::XShapes
>& xFinalTarget
98 , const Reference
< lang::XMultiServiceFactory
>& xShapeFactory
99 , Reference
< drawing::XShapes
>& xLogicTargetForSeriesBehindAxis
)
100 throw (uno::RuntimeException
)
102 OSL_PRECOND(xLogicTarget
.is()&&xFinalTarget
.is()&&xShapeFactory
.is(),"no proper initialization parameters");
103 //is only allowed to be called once
105 sal_Int32 nDimensionCount
= m_xCooSysModel
->getDimension();
106 //create group shape for grids first thus axes are always painted above grids
107 AbstractShapeFactory
* pShapeFactory
= AbstractShapeFactory::getOrCreateShapeFactory(xShapeFactory
);
108 if(nDimensionCount
==2)
110 //create and add to target
111 m_xLogicTargetForGrids
= pShapeFactory
->createGroup2D( xLogicTarget
);
112 xLogicTargetForSeriesBehindAxis
= pShapeFactory
->createGroup2D( xLogicTarget
);
113 m_xLogicTargetForAxes
= pShapeFactory
->createGroup2D( xLogicTarget
);
117 //create and added to target
118 m_xLogicTargetForGrids
= pShapeFactory
->createGroup3D( xLogicTarget
);
119 xLogicTargetForSeriesBehindAxis
= pShapeFactory
->createGroup3D( xLogicTarget
);
120 m_xLogicTargetForAxes
= pShapeFactory
->createGroup3D( xLogicTarget
);
122 m_xFinalTarget
= xFinalTarget
;
123 m_xShapeFactory
= xShapeFactory
;
126 void VCoordinateSystem::setParticle( const OUString
& rCooSysParticle
)
128 m_aCooSysParticle
= rCooSysParticle
;
131 void VCoordinateSystem::setTransformationSceneToScreen(
132 const drawing::HomogenMatrix
& rMatrix
)
134 m_aMatrixSceneToScreen
= rMatrix
;
136 //correct transformation for axis
137 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
138 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
139 for( ; aIt
!= aEnd
; ++aIt
)
141 VAxisBase
* pVAxis
= aIt
->second
.get();
144 if(2==pVAxis
->getDimensionCount())
145 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
150 //better performance for big data
151 uno::Sequence
< sal_Int32
> VCoordinateSystem::getCoordinateSystemResolution(
152 const awt::Size
& rPageSize
, const awt::Size
& rPageResolution
)
154 uno::Sequence
< sal_Int32
> aResolution(2);
156 sal_Int32 nDimensionCount
= m_xCooSysModel
->getDimension();
157 if(nDimensionCount
>2)
158 aResolution
.realloc(nDimensionCount
);
160 for( nN
= 0 ;nN
<aResolution
.getLength(); nN
++ )
161 aResolution
[nN
]=1000;
163 ::basegfx::B3DTuple
aScale( BaseGFXHelper::GetScaleFromMatrix(
164 BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
165 m_aMatrixSceneToScreen
) ) );
167 double fCoosysWidth
= static_cast< double >( fabs(aScale
.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME
));
168 double fCoosysHeight
= static_cast< double >( fabs(aScale
.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME
));
170 double fPageWidth
= rPageSize
.Width
;
171 double fPageHeight
= rPageSize
.Height
;
173 //factor 2 to avoid rounding problems
174 sal_Int32 nXResolution
= static_cast<sal_Int32
>(2.0*static_cast<double>(rPageResolution
.Width
)*fCoosysWidth
/fPageWidth
);
175 sal_Int32 nYResolution
= static_cast<sal_Int32
>(2.0*static_cast<double>(rPageResolution
.Height
)*fCoosysHeight
/fPageHeight
);
177 if( nXResolution
< 10 )
179 if( nYResolution
< 10 )
182 if( this->getPropertySwapXAndYAxis() )
183 std::swap(nXResolution
,nYResolution
);
186 if( 2 == aResolution
.getLength() )
188 aResolution
[0]=nXResolution
;
189 aResolution
[1]=nYResolution
;
193 //this maybe can be optimized further ...
194 sal_Int32 nMaxResolution
= std::max( nXResolution
, nYResolution
);
196 for( nN
= 0 ;nN
<aResolution
.getLength(); nN
++ )
197 aResolution
[nN
]=nMaxResolution
;
203 Reference
< XAxis
> VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
205 if( m_xCooSysModel
.is() )
206 return m_xCooSysModel
->getAxisByDimension( nDimensionIndex
, nAxisIndex
);
210 Sequence
< Reference
< beans::XPropertySet
> > VCoordinateSystem::getGridListFromAxis( const Reference
< XAxis
>& xAxis
)
212 std::vector
< Reference
< beans::XPropertySet
> > aRet
;
216 aRet
.push_back( xAxis
->getGridProperties() );
217 std::vector
< Reference
< beans::XPropertySet
> > aSubGrids( ContainerHelper::SequenceToVector( xAxis
->getSubGridProperties() ) );
218 aRet
.insert( aRet
.end(), aSubGrids
.begin(), aSubGrids
.end() );
221 return ContainerHelper::ContainerToSequence( aRet
);
224 void VCoordinateSystem::impl_adjustDimension( sal_Int32
& rDimensionIndex
)
226 if( rDimensionIndex
<0 )
228 if( rDimensionIndex
>2 )
232 void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32
& rDimensionIndex
, sal_Int32
& rAxisIndex
) const
234 impl_adjustDimension( rDimensionIndex
);
236 if( rAxisIndex
< 0 || rAxisIndex
> this->getMaximumAxisIndexByDimension(rDimensionIndex
) )
240 void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider
* pExplicitCategoriesProvider
/*takes ownership*/ )
242 m_apExplicitCategoriesProvider
.reset(pExplicitCategoriesProvider
);
245 ExplicitCategoriesProvider
* VCoordinateSystem::getExplicitCategoriesProvider()
247 return m_apExplicitCategoriesProvider
.get();
250 std::vector
< ExplicitScaleData
> VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
252 std::vector
< ExplicitScaleData
> aRet(m_aExplicitScales
);
254 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
255 aRet
[nDimensionIndex
]=this->getExplicitScale( nDimensionIndex
, nAxisIndex
);
260 std::vector
< ExplicitIncrementData
> VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
262 std::vector
< ExplicitIncrementData
> aRet(m_aExplicitIncrements
);
264 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
265 aRet
[nDimensionIndex
]=this->getExplicitIncrement( nDimensionIndex
, nAxisIndex
);
270 ExplicitScaleData
VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
272 ExplicitScaleData aRet
;
274 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
278 aRet
= m_aExplicitScales
[nDimensionIndex
];
282 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
283 tFullExplicitScaleMap::const_iterator aIt
= m_aSecondaryExplicitScales
.find( aFullAxisIndex
);
284 if( aIt
!= m_aSecondaryExplicitScales
.end() )
287 aRet
= m_aExplicitScales
[nDimensionIndex
];
293 ExplicitIncrementData
VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
) const
295 ExplicitIncrementData aRet
;
297 impl_adjustDimensionAndIndex( nDimensionIndex
, nAxisIndex
);
301 aRet
= m_aExplicitIncrements
[nDimensionIndex
];
305 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
306 tFullExplicitIncrementMap::const_iterator aIt
= m_aSecondaryExplicitIncrements
.find( aFullAxisIndex
);
307 if( aIt
!= m_aSecondaryExplicitIncrements
.end() )
310 aRet
= m_aExplicitIncrements
[nDimensionIndex
];
316 OUString
VCoordinateSystem::createCIDForAxis( const Reference
< chart2::XAxis
>& /* xAxis */, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
318 OUString
aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex
, nAxisIndex
) );
319 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle
, aAxisParticle
);
321 OUString
VCoordinateSystem::createCIDForGrid( const Reference
< chart2::XAxis
>& /* xAxis */, sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
323 OUString
aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex
, nAxisIndex
) );
324 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle
, aGridParticle
);
327 sal_Int32
VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex
) const
330 tFullExplicitScaleMap::const_iterator aIt
= m_aSecondaryExplicitScales
.begin();
331 tFullExplicitScaleMap::const_iterator aEnd
= m_aSecondaryExplicitScales
.end();
332 for(; aIt
!=aEnd
; ++aIt
)
334 if(aIt
->first
.first
==nDimensionIndex
)
336 sal_Int32 nLocalIdx
= aIt
->first
.second
;
337 if( nRet
< nLocalIdx
)
344 void VCoordinateSystem::createVAxisList(
345 const uno::Reference
<chart2::XChartDocument
> & /* xChartDoc */
346 , const awt::Size
& /* rFontReferenceSize */
347 , const awt::Rectangle
& /* rMaximumSpaceForLabels */
352 void VCoordinateSystem::initVAxisInList()
355 void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
359 void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism
& rScaleAutomatism
, sal_Int32 nDimIndex
, sal_Int32 nAxisIndex
)
361 if( rScaleAutomatism
.getScale().AxisType
==AxisType::DATE
&& nDimIndex
==0 )
363 // This is a date X dimension. Determine proper time resolution.
364 sal_Int32 nTimeResolution
= ::com::sun::star::chart::TimeUnit::MONTH
;
365 if( !(rScaleAutomatism
.getScale().TimeIncrement
.TimeResolution
>>= nTimeResolution
) )
367 nTimeResolution
= m_aMergedMinMaxSupplier
.calculateTimeResolutionOnXAxis();
368 rScaleAutomatism
.setAutomaticTimeResolution( nTimeResolution
);
370 m_aMergedMinMaxSupplier
.setTimeResolutionOnXAxis( nTimeResolution
, rScaleAutomatism
.getNullDate() );
375 ::rtl::math::setInf(&fMin
, false);
376 ::rtl::math::setInf(&fMax
, true);
380 fMin
= m_aMergedMinMaxSupplier
.getMinimumX();
381 fMax
= m_aMergedMinMaxSupplier
.getMaximumX();
383 else if( 1 == nDimIndex
)
386 ExplicitScaleData aScale
= getExplicitScale( 0, 0 );
387 fMin
= m_aMergedMinMaxSupplier
.getMinimumYInRange(aScale
.Minimum
,aScale
.Maximum
, nAxisIndex
);
388 fMax
= m_aMergedMinMaxSupplier
.getMaximumYInRange(aScale
.Minimum
,aScale
.Maximum
, nAxisIndex
);
390 else if( 2 == nDimIndex
)
393 fMin
= m_aMergedMinMaxSupplier
.getMinimumZ();
394 fMax
= m_aMergedMinMaxSupplier
.getMaximumZ();
397 //merge our values with those already contained in rScaleAutomatism
398 rScaleAutomatism
.expandValueRange( fMin
, fMax
);
400 rScaleAutomatism
.setAutoScalingOptions(
401 m_aMergedMinMaxSupplier
.isExpandBorderToIncrementRhythm( nDimIndex
),
402 m_aMergedMinMaxSupplier
.isExpandIfValuesCloseToBorder( nDimIndex
),
403 m_aMergedMinMaxSupplier
.isExpandWideValuesToZero( nDimIndex
),
404 m_aMergedMinMaxSupplier
.isExpandNarrowValuesTowardZero( nDimIndex
) );
406 VAxisBase
* pVAxis
= getVAxis(nDimIndex
, nAxisIndex
);
408 rScaleAutomatism
.setMaximumAutoMainIncrementCount( pVAxis
->estimateMaximumAutoMainIncrementCount() );
411 VAxisBase
* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex
, sal_Int32 nAxisIndex
)
415 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
417 tVAxisMap::const_iterator aIt
= m_aAxisMap
.find( aFullAxisIndex
);
418 if( aIt
!= m_aAxisMap
.end() )
419 pRet
= aIt
->second
.get();
424 void VCoordinateSystem::setExplicitScaleAndIncrement(
425 sal_Int32 nDimensionIndex
426 , sal_Int32 nAxisIndex
427 , const ExplicitScaleData
& rExplicitScale
428 , const ExplicitIncrementData
& rExplicitIncrement
)
430 impl_adjustDimension( nDimensionIndex
);
434 m_aExplicitScales
[nDimensionIndex
]=rExplicitScale
;
435 m_aExplicitIncrements
[nDimensionIndex
]=rExplicitIncrement
;
439 tFullAxisIndex
aFullAxisIndex( nDimensionIndex
, nAxisIndex
);
440 m_aSecondaryExplicitScales
[aFullAxisIndex
] = rExplicitScale
;
441 m_aSecondaryExplicitIncrements
[aFullAxisIndex
] = rExplicitIncrement
;
445 void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos
, CuboidPlanePosition eBackWallPos
, CuboidPlanePosition eBottomPos
)
447 m_eLeftWallPos
= eLeftWallPos
;
448 m_eBackWallPos
= eBackWallPos
;
449 m_eBottomPos
= eBottomPos
;
452 void VCoordinateSystem::createMaximumAxesLabels()
454 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
455 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
456 for( ; aIt
!= aEnd
; ++aIt
)
458 VAxisBase
* pVAxis
= aIt
->second
.get();
461 if(2==pVAxis
->getDimensionCount())
462 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
463 pVAxis
->createMaximumLabels();
467 void VCoordinateSystem::createAxesLabels()
469 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
470 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
471 for( ; aIt
!= aEnd
; ++aIt
)
473 VAxisBase
* pVAxis
= aIt
->second
.get();
476 if(2==pVAxis
->getDimensionCount())
477 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
478 pVAxis
->createLabels();
483 void VCoordinateSystem::updatePositions()
485 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
486 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
487 for( ; aIt
!= aEnd
; ++aIt
)
489 VAxisBase
* pVAxis
= aIt
->second
.get();
492 if(2==pVAxis
->getDimensionCount())
493 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
494 pVAxis
->updatePositions();
499 void VCoordinateSystem::createAxesShapes()
501 tVAxisMap::iterator
aIt( m_aAxisMap
.begin() );
502 tVAxisMap::const_iterator
aEnd( m_aAxisMap
.end() );
503 for( ; aIt
!= aEnd
; ++aIt
)
505 VAxisBase
* pVAxis
= aIt
->second
.get();
508 if(2==pVAxis
->getDimensionCount())
509 pVAxis
->setTransformationSceneToScreen( m_aMatrixSceneToScreen
);
511 tFullAxisIndex aFullAxisIndex
= aIt
->first
;
512 if( aFullAxisIndex
.second
== 0 )
514 if( aFullAxisIndex
.first
== 0 )
516 if( AxisType::CATEGORY
!=m_aExplicitScales
[1].AxisType
)
517 pVAxis
->setExtraLinePositionAtOtherAxis(
518 m_aExplicitScales
[1].Origin
);
520 else if( aFullAxisIndex
.first
== 1 )
522 if( AxisType::CATEGORY
!=m_aExplicitScales
[0].AxisType
)
523 pVAxis
->setExtraLinePositionAtOtherAxis(
524 m_aExplicitScales
[0].Origin
);
528 pVAxis
->createShapes();
532 void VCoordinateSystem::createGridShapes()
535 void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
537 m_aMergedMinMaxSupplier
.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier
);
540 bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier
* pMinimumAndMaximumSupplier
)
542 return m_aMergedMinMaxSupplier
.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier
);
545 void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
547 m_aMergedMinMaxSupplier
.clearMinimumAndMaximumSupplierList();
550 bool VCoordinateSystem::getPropertySwapXAndYAxis() const
552 Reference
<beans::XPropertySet
> xProp(m_xCooSysModel
, uno::UNO_QUERY
);
553 bool bSwapXAndY
= false;
556 xProp
->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY
;
558 catch( const uno::Exception
& e
)
560 ASSERT_EXCEPTION( e
);
565 bool VCoordinateSystem::needSeriesNamesForAxis() const
567 return ( m_xCooSysModel
.is() && m_xCooSysModel
->getDimension() == 3 );
569 void VCoordinateSystem::setSeriesNamesForAxis( const Sequence
< OUString
>& rSeriesNames
)
571 m_aSeriesNamesForZAxis
= rSeriesNames
;
574 sal_Int32
VCoordinateSystem::getNumberFormatKeyForAxis(
575 const Reference
< chart2::XAxis
>& xAxis
576 , const Reference
<chart2::XChartDocument
>& xChartDoc
)
578 return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
579 xAxis
, m_xCooSysModel
, xChartDoc
);
584 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */