nss: upgrade to release 3.73
[LibreOffice.git] / chart2 / source / view / axes / VCoordinateSystem.cxx
blob1c900b392233177197493e897efa120acf820079
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <BaseGFXHelper.hxx>
21 #include <VCoordinateSystem.hxx>
22 #include "VCartesianCoordinateSystem.hxx"
23 #include "VPolarCoordinateSystem.hxx"
24 #include <ScaleAutomatism.hxx>
25 #include <ShapeFactory.hxx>
26 #include <servicenames_coosystems.hxx>
27 #include <ObjectIdentifier.hxx>
28 #include <ExplicitCategoriesProvider.hxx>
29 #include "VAxisBase.hxx"
30 #include <defines.hxx>
31 #include <chartview/ExplicitValueProvider.hxx>
32 #include <com/sun/star/chart/TimeUnit.hpp>
33 #include <com/sun/star/chart2/AxisType.hpp>
34 #include <com/sun/star/chart2/XCoordinateSystem.hpp>
35 #include <comphelper/sequence.hxx>
36 #include <tools/diagnose_ex.h>
37 #include <algorithm>
38 #include <rtl/math.hxx>
40 namespace chart
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::chart2;
44 using ::com::sun::star::uno::Reference;
45 using ::com::sun::star::uno::Sequence;
47 std::unique_ptr<VCoordinateSystem> VCoordinateSystem::createCoordinateSystem(
48 const Reference< XCoordinateSystem >& xCooSysModel )
50 if( !xCooSysModel.is() )
51 return nullptr;
53 OUString aViewServiceName = xCooSysModel->getViewServiceName();
55 //@todo: in future the coordinatesystems should be instantiated via service factory
56 std::unique_ptr<VCoordinateSystem> pRet;
57 if( aViewServiceName == CHART2_COOSYSTEM_CARTESIAN_VIEW_SERVICE_NAME )
58 pRet.reset( new VCartesianCoordinateSystem(xCooSysModel) );
59 else if( aViewServiceName == CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME )
60 pRet.reset( new VPolarCoordinateSystem(xCooSysModel) );
61 if(!pRet)
62 pRet.reset( new VCoordinateSystem(xCooSysModel) );
63 return pRet;
66 VCoordinateSystem::VCoordinateSystem( const Reference< XCoordinateSystem >& xCooSys )
67 : m_xCooSysModel(xCooSys)
68 , m_aMatrixSceneToScreen()
69 , m_eLeftWallPos(CuboidPlanePosition_Left)
70 , m_eBackWallPos(CuboidPlanePosition_Back)
71 , m_eBottomPos(CuboidPlanePosition_Bottom)
72 , m_aMergedMinMaxSupplier()
73 , m_aExplicitScales(3)
74 , m_aExplicitIncrements(3)
76 if( !m_xCooSysModel.is() || m_xCooSysModel->getDimension()<3 )
78 m_aExplicitScales[2].Minimum = 1.0;
79 m_aExplicitScales[2].Maximum = 2.0;
80 m_aExplicitScales[2].Orientation = AxisOrientation_MATHEMATICAL;
83 VCoordinateSystem::~VCoordinateSystem()
87 void VCoordinateSystem::initPlottingTargets( const Reference< drawing::XShapes >& xLogicTarget
88 , const Reference< drawing::XShapes >& xFinalTarget
89 , const Reference< lang::XMultiServiceFactory >& xShapeFactory
90 , Reference< drawing::XShapes >& xLogicTargetForSeriesBehindAxis )
92 OSL_PRECOND(xLogicTarget.is()&&xFinalTarget.is()&&xShapeFactory.is(),"no proper initialization parameters");
93 //is only allowed to be called once
95 sal_Int32 nDimensionCount = m_xCooSysModel->getDimension();
96 //create group shape for grids first thus axes are always painted above grids
97 ShapeFactory* pShapeFactory = ShapeFactory::getOrCreateShapeFactory(xShapeFactory);
98 if(nDimensionCount==2)
100 //create and add to target
101 m_xLogicTargetForGrids = pShapeFactory->createGroup2D( xLogicTarget );
102 xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup2D( xLogicTarget );
103 m_xLogicTargetForAxes = pShapeFactory->createGroup2D( xLogicTarget );
105 else
107 //create and added to target
108 m_xLogicTargetForGrids = pShapeFactory->createGroup3D( xLogicTarget );
109 xLogicTargetForSeriesBehindAxis = pShapeFactory->createGroup3D( xLogicTarget );
110 m_xLogicTargetForAxes = pShapeFactory->createGroup3D( xLogicTarget );
112 m_xFinalTarget = xFinalTarget;
113 m_xShapeFactory = xShapeFactory;
116 void VCoordinateSystem::setParticle( const OUString& rCooSysParticle )
118 m_aCooSysParticle = rCooSysParticle;
121 void VCoordinateSystem::setTransformationSceneToScreen(
122 const drawing::HomogenMatrix& rMatrix )
124 m_aMatrixSceneToScreen = rMatrix;
126 //correct transformation for axis
127 for (auto const& elem : m_aAxisMap)
129 VAxisBase* pVAxis = elem.second.get();
130 if( pVAxis )
132 if(pVAxis->getDimensionCount()==2)
133 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
138 //better performance for big data
139 uno::Sequence< sal_Int32 > VCoordinateSystem::getCoordinateSystemResolution(
140 const awt::Size& rPageSize, const awt::Size& rPageResolution )
142 uno::Sequence<sal_Int32> aResolution(
143 std::max<sal_Int32>(m_xCooSysModel->getDimension(), 2));
145 for( auto& i : aResolution )
146 i = 1000;
148 ::basegfx::B3DTuple aScale( BaseGFXHelper::GetScaleFromMatrix(
149 BaseGFXHelper::HomogenMatrixToB3DHomMatrix(
150 m_aMatrixSceneToScreen ) ) );
152 double fCoosysWidth = fabs(aScale.getX()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
153 double fCoosysHeight = fabs(aScale.getY()*FIXED_SIZE_FOR_3D_CHART_VOLUME);
155 double fPageWidth = rPageSize.Width;
156 double fPageHeight = rPageSize.Height;
158 //factor 2 to avoid rounding problems
159 sal_Int32 nXResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Width)*fCoosysWidth/fPageWidth);
160 sal_Int32 nYResolution = static_cast<sal_Int32>(2.0*static_cast<double>(rPageResolution.Height)*fCoosysHeight/fPageHeight);
162 if( nXResolution < 10 )
163 nXResolution = 10;
164 if( nYResolution < 10 )
165 nYResolution = 10;
167 if( getPropertySwapXAndYAxis() )
168 std::swap(nXResolution,nYResolution);
170 //2D
171 if( aResolution.getLength() == 2 )
173 aResolution[0]=nXResolution;
174 aResolution[1]=nYResolution;
176 else
178 //this maybe can be optimized further ...
179 sal_Int32 nMaxResolution = std::max( nXResolution, nYResolution );
180 nMaxResolution*=2;
181 for( auto& i : aResolution )
182 i = nMaxResolution;
185 return aResolution;
188 Reference< XAxis > VCoordinateSystem::getAxisByDimension( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
190 if( m_xCooSysModel.is() )
191 return m_xCooSysModel->getAxisByDimension( nDimensionIndex, nAxisIndex );
192 return nullptr;
195 Sequence< Reference< beans::XPropertySet > > VCoordinateSystem::getGridListFromAxis( const Reference< XAxis >& xAxis )
197 std::vector< Reference< beans::XPropertySet > > aRet;
199 if( xAxis.is() )
201 aRet.push_back( xAxis->getGridProperties() );
202 auto aSubGrids( comphelper::sequenceToContainer<std::vector< Reference< beans::XPropertySet > > >( xAxis->getSubGridProperties() ) );
203 aRet.insert( aRet.end(), aSubGrids.begin(), aSubGrids.end() );
206 return comphelper::containerToSequence( aRet );
209 void VCoordinateSystem::impl_adjustDimension( sal_Int32& rDimensionIndex )
211 if( rDimensionIndex<0 )
212 rDimensionIndex=0;
213 if( rDimensionIndex>2 )
214 rDimensionIndex=2;
217 void VCoordinateSystem::impl_adjustDimensionAndIndex( sal_Int32& rDimensionIndex, sal_Int32& rAxisIndex ) const
219 impl_adjustDimension( rDimensionIndex );
221 if( rAxisIndex < 0 || rAxisIndex > getMaximumAxisIndexByDimension(rDimensionIndex) )
222 rAxisIndex = 0;
225 void VCoordinateSystem::setExplicitCategoriesProvider( ExplicitCategoriesProvider* pExplicitCategoriesProvider /*takes ownership*/ )
227 m_apExplicitCategoriesProvider.reset(pExplicitCategoriesProvider);
230 ExplicitCategoriesProvider* VCoordinateSystem::getExplicitCategoriesProvider()
232 return m_apExplicitCategoriesProvider.get();
235 std::vector< ExplicitScaleData > VCoordinateSystem::getExplicitScales( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
237 std::vector< ExplicitScaleData > aRet(m_aExplicitScales);
239 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
240 aRet[nDimensionIndex]=getExplicitScale( nDimensionIndex, nAxisIndex );
242 return aRet;
245 std::vector< ExplicitIncrementData > VCoordinateSystem::getExplicitIncrements( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
247 std::vector< ExplicitIncrementData > aRet(m_aExplicitIncrements);
249 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
250 aRet[nDimensionIndex]=getExplicitIncrement( nDimensionIndex, nAxisIndex );
252 return aRet;
255 ExplicitScaleData VCoordinateSystem::getExplicitScale( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
257 ExplicitScaleData aRet;
259 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
261 if( nAxisIndex == 0)
263 aRet = m_aExplicitScales[nDimensionIndex];
265 else
267 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
268 tFullExplicitScaleMap::const_iterator aIt = m_aSecondaryExplicitScales.find( aFullAxisIndex );
269 if( aIt != m_aSecondaryExplicitScales.end() )
270 aRet = aIt->second;
271 else
272 aRet = m_aExplicitScales[nDimensionIndex];
275 return aRet;
278 ExplicitIncrementData VCoordinateSystem::getExplicitIncrement( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) const
280 ExplicitIncrementData aRet;
282 impl_adjustDimensionAndIndex( nDimensionIndex, nAxisIndex );
284 if( nAxisIndex == 0)
286 aRet = m_aExplicitIncrements[nDimensionIndex];
288 else
290 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
291 tFullExplicitIncrementMap::const_iterator aIt = m_aSecondaryExplicitIncrements.find( aFullAxisIndex );
292 if( aIt != m_aSecondaryExplicitIncrements.end() )
293 aRet = aIt->second;
294 else
295 aRet = m_aExplicitIncrements[nDimensionIndex];
298 return aRet;
301 OUString VCoordinateSystem::createCIDForAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
303 OUString aAxisParticle( ObjectIdentifier::createParticleForAxis( nDimensionIndex, nAxisIndex ) );
304 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aAxisParticle );
306 OUString VCoordinateSystem::createCIDForGrid( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
308 OUString aGridParticle( ObjectIdentifier::createParticleForGrid( nDimensionIndex, nAxisIndex ) );
309 return ObjectIdentifier::createClassifiedIdentifierForParticles( m_aCooSysParticle, aGridParticle );
312 sal_Int32 VCoordinateSystem::getMaximumAxisIndexByDimension( sal_Int32 nDimensionIndex ) const
314 sal_Int32 nRet = 0;
315 for (auto const& elem : m_aSecondaryExplicitScales)
317 if(elem.first.first==nDimensionIndex)
319 sal_Int32 nLocalIdx = elem.first.second;
320 if( nRet < nLocalIdx )
321 nRet = nLocalIdx;
324 return nRet;
327 void VCoordinateSystem::createVAxisList(
328 const uno::Reference<chart2::XChartDocument> & /* xChartDoc */
329 , const awt::Size& /* rFontReferenceSize */
330 , const awt::Rectangle& /* rMaximumSpaceForLabels */
331 , bool /* bLimitSpaceForLabels */
336 void VCoordinateSystem::initVAxisInList()
339 void VCoordinateSystem::updateScalesAndIncrementsOnAxes()
343 void VCoordinateSystem::prepareAutomaticAxisScaling( ScaleAutomatism& rScaleAutomatism, sal_Int32 nDimIndex, sal_Int32 nAxisIndex )
345 if( rScaleAutomatism.getScale().AxisType==AxisType::DATE && nDimIndex==0 )
347 // This is a date X dimension. Determine proper time resolution.
348 sal_Int32 nTimeResolution = css::chart::TimeUnit::MONTH;
349 if( !(rScaleAutomatism.getScale().TimeIncrement.TimeResolution >>= nTimeResolution) )
351 nTimeResolution = m_aMergedMinMaxSupplier.calculateTimeResolutionOnXAxis();
352 rScaleAutomatism.setAutomaticTimeResolution( nTimeResolution );
354 m_aMergedMinMaxSupplier.setTimeResolutionOnXAxis( nTimeResolution, rScaleAutomatism.getNullDate() );
357 double fMin = 0.0;
358 double fMax = 0.0;
359 ::rtl::math::setInf(&fMin, false);
360 ::rtl::math::setInf(&fMax, true);
361 if( nDimIndex == 0 )
363 // x dimension
364 fMin = m_aMergedMinMaxSupplier.getMinimumX();
365 fMax = m_aMergedMinMaxSupplier.getMaximumX();
367 else if( nDimIndex == 1 )
369 // y dimension
370 ExplicitScaleData aScale = getExplicitScale( 0, 0 );
371 fMin = m_aMergedMinMaxSupplier.getMinimumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
372 fMax = m_aMergedMinMaxSupplier.getMaximumYInRange(aScale.Minimum,aScale.Maximum, nAxisIndex);
374 else if( nDimIndex == 2 )
376 // z dimension
377 fMin = m_aMergedMinMaxSupplier.getMinimumZ();
378 fMax = m_aMergedMinMaxSupplier.getMaximumZ();
381 //merge our values with those already contained in rScaleAutomatism
382 rScaleAutomatism.expandValueRange( fMin, fMax );
384 rScaleAutomatism.setAutoScalingOptions(
385 m_aMergedMinMaxSupplier.isExpandBorderToIncrementRhythm( nDimIndex ),
386 m_aMergedMinMaxSupplier.isExpandIfValuesCloseToBorder( nDimIndex ),
387 m_aMergedMinMaxSupplier.isExpandWideValuesToZero( nDimIndex ),
388 m_aMergedMinMaxSupplier.isExpandNarrowValuesTowardZero( nDimIndex ) );
390 VAxisBase* pVAxis = getVAxis(nDimIndex, nAxisIndex);
391 if( pVAxis )
392 rScaleAutomatism.setMaximumAutoMainIncrementCount( pVAxis->estimateMaximumAutoMainIncrementCount() );
395 VAxisBase* VCoordinateSystem::getVAxis( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
397 VAxisBase* pRet = nullptr;
399 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
401 tVAxisMap::const_iterator aIt = m_aAxisMap.find( aFullAxisIndex );
402 if( aIt != m_aAxisMap.end() )
403 pRet = aIt->second.get();
405 return pRet;
408 void VCoordinateSystem::setExplicitScaleAndIncrement(
409 sal_Int32 nDimensionIndex
410 , sal_Int32 nAxisIndex
411 , const ExplicitScaleData& rExplicitScale
412 , const ExplicitIncrementData& rExplicitIncrement )
414 impl_adjustDimension( nDimensionIndex );
416 if( nAxisIndex==0 )
418 m_aExplicitScales[nDimensionIndex]=rExplicitScale;
419 m_aExplicitIncrements[nDimensionIndex]=rExplicitIncrement;
421 else
423 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
424 m_aSecondaryExplicitScales[aFullAxisIndex] = rExplicitScale;
425 m_aSecondaryExplicitIncrements[aFullAxisIndex] = rExplicitIncrement;
429 void VCoordinateSystem::set3DWallPositions( CuboidPlanePosition eLeftWallPos, CuboidPlanePosition eBackWallPos, CuboidPlanePosition eBottomPos )
431 m_eLeftWallPos = eLeftWallPos;
432 m_eBackWallPos = eBackWallPos;
433 m_eBottomPos = eBottomPos;
436 void VCoordinateSystem::createMaximumAxesLabels()
438 for (auto const& elem : m_aAxisMap)
440 VAxisBase* pVAxis = elem.second.get();
441 if( pVAxis )
443 if(pVAxis->getDimensionCount()==2)
444 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
445 pVAxis->createMaximumLabels();
449 void VCoordinateSystem::createAxesLabels()
451 for (auto const& elem : m_aAxisMap)
453 VAxisBase* pVAxis = elem.second.get();
454 if( pVAxis )
456 if(pVAxis->getDimensionCount()==2)
457 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
458 pVAxis->createLabels();
463 void VCoordinateSystem::updatePositions()
465 for (auto const& elem : m_aAxisMap)
467 VAxisBase* pVAxis = elem.second.get();
468 if( pVAxis )
470 if(pVAxis->getDimensionCount()==2)
471 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
472 pVAxis->updatePositions();
477 void VCoordinateSystem::createAxesShapes()
479 for (auto const& elem : m_aAxisMap)
481 VAxisBase* pVAxis = elem.second.get();
482 if( pVAxis )
484 if(pVAxis->getDimensionCount()==2)
485 pVAxis->setTransformationSceneToScreen( m_aMatrixSceneToScreen );
487 tFullAxisIndex aFullAxisIndex = elem.first;
488 if( aFullAxisIndex.second == 0 )
490 if( aFullAxisIndex.first == 0 )
492 if( m_aExplicitScales[1].AxisType!=AxisType::CATEGORY )
493 pVAxis->setExtraLinePositionAtOtherAxis(
494 m_aExplicitScales[1].Origin );
496 else if( aFullAxisIndex.first == 1 )
498 if( m_aExplicitScales[0].AxisType!=AxisType::CATEGORY )
499 pVAxis->setExtraLinePositionAtOtherAxis(
500 m_aExplicitScales[0].Origin );
504 pVAxis->createShapes();
508 void VCoordinateSystem::createGridShapes()
511 void VCoordinateSystem::addMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
513 m_aMergedMinMaxSupplier.addMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
516 bool VCoordinateSystem::hasMinimumAndMaximumSupplier( MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
518 return m_aMergedMinMaxSupplier.hasMinimumAndMaximumSupplier(pMinimumAndMaximumSupplier);
521 void VCoordinateSystem::clearMinimumAndMaximumSupplierList()
523 m_aMergedMinMaxSupplier.clearMinimumAndMaximumSupplierList();
526 bool VCoordinateSystem::getPropertySwapXAndYAxis() const
528 Reference<beans::XPropertySet> xProp(m_xCooSysModel, uno::UNO_QUERY );
529 bool bSwapXAndY = false;
530 if( xProp.is()) try
532 xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndY;
534 catch( const uno::Exception& )
536 TOOLS_WARN_EXCEPTION("chart2", "" );
538 return bSwapXAndY;
541 bool VCoordinateSystem::needSeriesNamesForAxis() const
543 return ( m_xCooSysModel.is() && m_xCooSysModel->getDimension() == 3 );
545 void VCoordinateSystem::setSeriesNamesForAxis( const Sequence< OUString >& rSeriesNames )
547 m_aSeriesNamesForZAxis = rSeriesNames;
550 sal_Int32 VCoordinateSystem::getNumberFormatKeyForAxis(
551 const Reference< chart2::XAxis >& xAxis
552 , const Reference<chart2::XChartDocument>& xChartDoc)
554 return ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
555 xAxis, m_xCooSysModel, xChartDoc);
558 } //namespace chart
560 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */