1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_chart2.hxx" 30*cdf0e10cSrcweir #include "Tickmarks_Equidistant.hxx" 31*cdf0e10cSrcweir #include "ViewDefines.hxx" 32*cdf0e10cSrcweir #include <rtl/math.hxx> 33*cdf0e10cSrcweir #include <tools/debug.hxx> 34*cdf0e10cSrcweir #include <memory> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir //............................................................................. 37*cdf0e10cSrcweir namespace chart 38*cdf0e10cSrcweir { 39*cdf0e10cSrcweir //............................................................................. 40*cdf0e10cSrcweir using namespace ::com::sun::star; 41*cdf0e10cSrcweir using namespace ::com::sun::star::chart2; 42*cdf0e10cSrcweir using namespace ::rtl::math; 43*cdf0e10cSrcweir using ::basegfx::B2DVector; 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir //static 46*cdf0e10cSrcweir double EquidistantTickFactory::getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement ) 47*cdf0e10cSrcweir { 48*cdf0e10cSrcweir //the returned value will be <= fMin and on a Major Tick given by rIncrement 49*cdf0e10cSrcweir if(rIncrement.Distance<=0.0) 50*cdf0e10cSrcweir return fMin; 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir double fRet = rIncrement.BaseValue + 53*cdf0e10cSrcweir floor( approxSub( fMin, rIncrement.BaseValue ) 54*cdf0e10cSrcweir / rIncrement.Distance) 55*cdf0e10cSrcweir *rIncrement.Distance; 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir if( fRet > fMin ) 58*cdf0e10cSrcweir { 59*cdf0e10cSrcweir if( !approxEqual(fRet, fMin) ) 60*cdf0e10cSrcweir fRet -= rIncrement.Distance; 61*cdf0e10cSrcweir } 62*cdf0e10cSrcweir return fRet; 63*cdf0e10cSrcweir } 64*cdf0e10cSrcweir //static 65*cdf0e10cSrcweir double EquidistantTickFactory::getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement ) 66*cdf0e10cSrcweir { 67*cdf0e10cSrcweir //the returned value will be >= fMax and on a Major Tick given by rIncrement 68*cdf0e10cSrcweir if(rIncrement.Distance<=0.0) 69*cdf0e10cSrcweir return fMax; 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir double fRet = rIncrement.BaseValue + 72*cdf0e10cSrcweir floor( approxSub( fMax, rIncrement.BaseValue ) 73*cdf0e10cSrcweir / rIncrement.Distance) 74*cdf0e10cSrcweir *rIncrement.Distance; 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir if( fRet < fMax ) 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir if( !approxEqual(fRet, fMax) ) 79*cdf0e10cSrcweir fRet += rIncrement.Distance; 80*cdf0e10cSrcweir } 81*cdf0e10cSrcweir return fRet; 82*cdf0e10cSrcweir } 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir EquidistantTickFactory::EquidistantTickFactory( 85*cdf0e10cSrcweir const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) 86*cdf0e10cSrcweir : m_rScale( rScale ) 87*cdf0e10cSrcweir , m_rIncrement( rIncrement ) 88*cdf0e10cSrcweir , m_xInverseScaling(NULL) 89*cdf0e10cSrcweir , m_pfCurrentValues(NULL) 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir //@todo: make sure that the scale is valid for the scaling 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir m_pfCurrentValues = new double[getTickDepth()]; 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir if( m_rScale.Scaling.is() ) 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir m_xInverseScaling = m_rScale.Scaling->getInverseScaling(); 98*cdf0e10cSrcweir DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir double fMin = m_fScaledVisibleMin = m_rScale.Minimum; 102*cdf0e10cSrcweir if( m_xInverseScaling.is() ) 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin); 105*cdf0e10cSrcweir if(m_rIncrement.PostEquidistant ) 106*cdf0e10cSrcweir fMin = m_fScaledVisibleMin; 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir double fMax = m_fScaledVisibleMax = m_rScale.Maximum; 110*cdf0e10cSrcweir if( m_xInverseScaling.is() ) 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax); 113*cdf0e10cSrcweir if(m_rIncrement.PostEquidistant ) 114*cdf0e10cSrcweir fMax = m_fScaledVisibleMax; 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir //-- 118*cdf0e10cSrcweir m_fOuterMajorTickBorderMin = EquidistantTickFactory::getMinimumAtIncrement( fMin, m_rIncrement ); 119*cdf0e10cSrcweir m_fOuterMajorTickBorderMax = EquidistantTickFactory::getMaximumAtIncrement( fMax, m_rIncrement ); 120*cdf0e10cSrcweir //-- 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin; 123*cdf0e10cSrcweir m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax; 124*cdf0e10cSrcweir if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() ) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); 127*cdf0e10cSrcweir m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax 130*cdf0e10cSrcweir //it is assumed here, that the original range in the given Scale is valid 131*cdf0e10cSrcweir if( !rtl::math::isFinite(m_fOuterMajorTickBorderMin_Scaled) ) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir m_fOuterMajorTickBorderMin += m_rIncrement.Distance; 134*cdf0e10cSrcweir m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir if( !rtl::math::isFinite(m_fOuterMajorTickBorderMax_Scaled) ) 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir m_fOuterMajorTickBorderMax -= m_rIncrement.Distance; 139*cdf0e10cSrcweir m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir } 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir EquidistantTickFactory::~EquidistantTickFactory() 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir delete[] m_pfCurrentValues; 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir sal_Int32 EquidistantTickFactory::getTickDepth() const 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir return static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) + 1; 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir void EquidistantTickFactory::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); 157*cdf0e10cSrcweir double* pfNextParentTick = aIter.firstValue(); 158*cdf0e10cSrcweir if(!pfNextParentTick) 159*cdf0e10cSrcweir return; 160*cdf0e10cSrcweir double fLastParentTick = *pfNextParentTick; 161*cdf0e10cSrcweir pfNextParentTick = aIter.nextValue(); 162*cdf0e10cSrcweir if(!pfNextParentTick) 163*cdf0e10cSrcweir return; 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir sal_Int32 nMaxSubTickCount = this->getMaxTickCount( nDepth ); 166*cdf0e10cSrcweir if(!nMaxSubTickCount) 167*cdf0e10cSrcweir return; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir uno::Sequence< double > aSubTicks(nMaxSubTickCount); 170*cdf0e10cSrcweir sal_Int32 nRealSubTickCount = 0; 171*cdf0e10cSrcweir sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount; 172*cdf0e10cSrcweir 173*cdf0e10cSrcweir double* pValue = NULL; 174*cdf0e10cSrcweir for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue()) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir for( sal_Int32 nPartTick = 1; nPartTick<nIntervalCount; nPartTick++ ) 177*cdf0e10cSrcweir { 178*cdf0e10cSrcweir pValue = this->getMinorTick( nPartTick, nDepth 179*cdf0e10cSrcweir , fLastParentTick, *pfNextParentTick ); 180*cdf0e10cSrcweir if(!pValue) 181*cdf0e10cSrcweir continue; 182*cdf0e10cSrcweir 183*cdf0e10cSrcweir aSubTicks[nRealSubTickCount] = *pValue; 184*cdf0e10cSrcweir nRealSubTickCount++; 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir } 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir aSubTicks.realloc(nRealSubTickCount); 189*cdf0e10cSrcweir rParentTicks[nDepth] = aSubTicks; 190*cdf0e10cSrcweir if(static_cast<sal_Int32>(m_rIncrement.SubIncrements.size())>nDepth) 191*cdf0e10cSrcweir addSubTicks( nDepth+1, rParentTicks ); 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir sal_Int32 EquidistantTickFactory::getMaxTickCount( sal_Int32 nDepth ) const 196*cdf0e10cSrcweir { 197*cdf0e10cSrcweir //return the maximum amount of ticks 198*cdf0e10cSrcweir //possibly open intervals at the two ends of the region are handled as if they were completely visible 199*cdf0e10cSrcweir //(this is necessary for calculating the sub ticks at the borders correctly) 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir if( nDepth >= getTickDepth() ) 202*cdf0e10cSrcweir return 0; 203*cdf0e10cSrcweir if( m_fOuterMajorTickBorderMax < m_fOuterMajorTickBorderMin ) 204*cdf0e10cSrcweir return 0; 205*cdf0e10cSrcweir if( m_rIncrement.Distance<=0.0) 206*cdf0e10cSrcweir return 0; 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir double fSub; 209*cdf0e10cSrcweir if(m_rIncrement.PostEquidistant ) 210*cdf0e10cSrcweir fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin ); 211*cdf0e10cSrcweir else 212*cdf0e10cSrcweir fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum ); 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir if (!isFinite(fSub)) 215*cdf0e10cSrcweir return 0; 216*cdf0e10cSrcweir 217*cdf0e10cSrcweir sal_Int32 nIntervalCount = static_cast<sal_Int32>( fSub / m_rIncrement.Distance ); 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir nIntervalCount+=3; 220*cdf0e10cSrcweir for(sal_Int32 nN=0; nN<nDepth-1; nN++) 221*cdf0e10cSrcweir { 222*cdf0e10cSrcweir if( m_rIncrement.SubIncrements[nN].IntervalCount>1 ) 223*cdf0e10cSrcweir nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount; 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir sal_Int32 nTickCount = nIntervalCount; 227*cdf0e10cSrcweir if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1) 228*cdf0e10cSrcweir nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1); 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir return nTickCount; 231*cdf0e10cSrcweir } 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir double* EquidistantTickFactory::getMajorTick( sal_Int32 nTick ) const 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir m_pfCurrentValues[0] = m_fOuterMajorTickBorderMin + nTick*m_rIncrement.Distance; 236*cdf0e10cSrcweir 237*cdf0e10cSrcweir if(m_pfCurrentValues[0]>m_fOuterMajorTickBorderMax) 238*cdf0e10cSrcweir { 239*cdf0e10cSrcweir if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMax) ) 240*cdf0e10cSrcweir return NULL; 241*cdf0e10cSrcweir } 242*cdf0e10cSrcweir if(m_pfCurrentValues[0]<m_fOuterMajorTickBorderMin) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMin) ) 245*cdf0e10cSrcweir return NULL; 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir //return always the value after scaling 249*cdf0e10cSrcweir if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() ) 250*cdf0e10cSrcweir m_pfCurrentValues[0] = m_rScale.Scaling->doScaling( m_pfCurrentValues[0] ); 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir return &m_pfCurrentValues[0]; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir double* EquidistantTickFactory::getMinorTick( sal_Int32 nTick, sal_Int32 nDepth 256*cdf0e10cSrcweir , double fStartParentTick, double fNextParentTick ) const 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir //check validity of arguments 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir //DBG_ASSERT( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick"); 261*cdf0e10cSrcweir if(fStartParentTick >= fNextParentTick) 262*cdf0e10cSrcweir return NULL; 263*cdf0e10cSrcweir if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<=0) 264*cdf0e10cSrcweir return NULL; 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir //subticks are only calculated if they are laying between parent ticks: 267*cdf0e10cSrcweir if(nTick<=0) 268*cdf0e10cSrcweir return NULL; 269*cdf0e10cSrcweir if(nTick>=m_rIncrement.SubIncrements[nDepth-1].IntervalCount) 270*cdf0e10cSrcweir return NULL; 271*cdf0e10cSrcweir } 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir bool bPostEquidistant = m_rIncrement.SubIncrements[nDepth-1].PostEquidistant; 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir double fAdaptedStartParent = fStartParentTick; 276*cdf0e10cSrcweir double fAdaptedNextParent = fNextParentTick; 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir if( !bPostEquidistant && m_xInverseScaling.is() ) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir fAdaptedStartParent = m_xInverseScaling->doScaling(fStartParentTick); 281*cdf0e10cSrcweir fAdaptedNextParent = m_xInverseScaling->doScaling(fNextParentTick); 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir double fDistance = (fAdaptedNextParent - fAdaptedStartParent)/m_rIncrement.SubIncrements[nDepth-1].IntervalCount; 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir m_pfCurrentValues[nDepth] = fAdaptedStartParent + nTick*fDistance; 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir //return always the value after scaling 289*cdf0e10cSrcweir if(!bPostEquidistant && m_xInverseScaling.is() ) 290*cdf0e10cSrcweir m_pfCurrentValues[nDepth] = m_rScale.Scaling->doScaling( m_pfCurrentValues[nDepth] ); 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir if( !isWithinOuterBorder( m_pfCurrentValues[nDepth] ) ) 293*cdf0e10cSrcweir return NULL; 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir return &m_pfCurrentValues[nDepth]; 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir bool EquidistantTickFactory::isWithinOuterBorder( double fScaledValue ) const 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled) 301*cdf0e10cSrcweir return false; 302*cdf0e10cSrcweir if(fScaledValue<m_fOuterMajorTickBorderMin_Scaled) 303*cdf0e10cSrcweir return false; 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir return true; 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir bool EquidistantTickFactory::isVisible( double fScaledValue ) const 309*cdf0e10cSrcweir { 310*cdf0e10cSrcweir if(fScaledValue>m_fScaledVisibleMax) 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir if( !approxEqual(fScaledValue,m_fScaledVisibleMax) ) 313*cdf0e10cSrcweir return false; 314*cdf0e10cSrcweir } 315*cdf0e10cSrcweir if(fScaledValue<m_fScaledVisibleMin) 316*cdf0e10cSrcweir { 317*cdf0e10cSrcweir if( !approxEqual(fScaledValue,m_fScaledVisibleMin) ) 318*cdf0e10cSrcweir return false; 319*cdf0e10cSrcweir } 320*cdf0e10cSrcweir return true; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir void EquidistantTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const 324*cdf0e10cSrcweir { 325*cdf0e10cSrcweir uno::Sequence< uno::Sequence< double > > aAllTicks; 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir //create point sequences for each tick depth 328*cdf0e10cSrcweir sal_Int32 nDepthCount = this->getTickDepth(); 329*cdf0e10cSrcweir sal_Int32 nMaxMajorTickCount = this->getMaxTickCount( 0 ); 330*cdf0e10cSrcweir 331*cdf0e10cSrcweir aAllTicks.realloc(nDepthCount); 332*cdf0e10cSrcweir aAllTicks[0].realloc(nMaxMajorTickCount); 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir sal_Int32 nRealMajorTickCount = 0; 335*cdf0e10cSrcweir double* pValue = NULL; 336*cdf0e10cSrcweir for( sal_Int32 nMajorTick=0; nMajorTick<nMaxMajorTickCount; nMajorTick++ ) 337*cdf0e10cSrcweir { 338*cdf0e10cSrcweir pValue = this->getMajorTick( nMajorTick ); 339*cdf0e10cSrcweir if(!pValue) 340*cdf0e10cSrcweir continue; 341*cdf0e10cSrcweir aAllTicks[0][nRealMajorTickCount] = *pValue; 342*cdf0e10cSrcweir nRealMajorTickCount++; 343*cdf0e10cSrcweir } 344*cdf0e10cSrcweir if(!nRealMajorTickCount) 345*cdf0e10cSrcweir return; 346*cdf0e10cSrcweir aAllTicks[0].realloc(nRealMajorTickCount); 347*cdf0e10cSrcweir 348*cdf0e10cSrcweir if(nDepthCount>0) 349*cdf0e10cSrcweir this->addSubTicks( 1, aAllTicks ); 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir //so far we have added all ticks between the outer major tick marks 352*cdf0e10cSrcweir //this was necessary to create sub ticks correctly 353*cdf0e10cSrcweir //now we reduce all ticks to the visible ones that lie between the real borders 354*cdf0e10cSrcweir sal_Int32 nDepth = 0; 355*cdf0e10cSrcweir sal_Int32 nTick = 0; 356*cdf0e10cSrcweir for( nDepth = 0; nDepth < nDepthCount; nDepth++) 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir sal_Int32 nInvisibleAtLowerBorder = 0; 359*cdf0e10cSrcweir sal_Int32 nInvisibleAtUpperBorder = 0; 360*cdf0e10cSrcweir //we need only to check all ticks within the first major interval at each border 361*cdf0e10cSrcweir sal_Int32 nCheckCount = 1; 362*cdf0e10cSrcweir for(sal_Int32 nN=0; nN<nDepth; nN++) 363*cdf0e10cSrcweir { 364*cdf0e10cSrcweir if( m_rIncrement.SubIncrements[nN].IntervalCount>1 ) 365*cdf0e10cSrcweir nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount; 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir uno::Sequence< double >& rTicks = aAllTicks[nDepth]; 368*cdf0e10cSrcweir sal_Int32 nCount = rTicks.getLength(); 369*cdf0e10cSrcweir //check lower border 370*cdf0e10cSrcweir for( nTick=0; nTick<nCheckCount && nTick<nCount; nTick++) 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir if( !isVisible( rTicks[nTick] ) ) 373*cdf0e10cSrcweir nInvisibleAtLowerBorder++; 374*cdf0e10cSrcweir } 375*cdf0e10cSrcweir //check upper border 376*cdf0e10cSrcweir for( nTick=nCount-1; nTick>nCount-1-nCheckCount && nTick>=0; nTick--) 377*cdf0e10cSrcweir { 378*cdf0e10cSrcweir if( !isVisible( rTicks[nTick] ) ) 379*cdf0e10cSrcweir nInvisibleAtUpperBorder++; 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir //resize sequence 382*cdf0e10cSrcweir if( !nInvisibleAtLowerBorder && !nInvisibleAtUpperBorder) 383*cdf0e10cSrcweir continue; 384*cdf0e10cSrcweir if( !nInvisibleAtLowerBorder ) 385*cdf0e10cSrcweir rTicks.realloc(nCount-nInvisibleAtUpperBorder); 386*cdf0e10cSrcweir else 387*cdf0e10cSrcweir { 388*cdf0e10cSrcweir sal_Int32 nNewCount = nCount-nInvisibleAtUpperBorder-nInvisibleAtLowerBorder; 389*cdf0e10cSrcweir if(nNewCount<0) 390*cdf0e10cSrcweir nNewCount=0; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir uno::Sequence< double > aOldTicks(rTicks); 393*cdf0e10cSrcweir rTicks.realloc(nNewCount); 394*cdf0e10cSrcweir for(nTick = 0; nTick<nNewCount; nTick++) 395*cdf0e10cSrcweir rTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick]; 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir } 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir //fill return value 400*cdf0e10cSrcweir rAllTickInfos.resize(aAllTicks.getLength()); 401*cdf0e10cSrcweir for( nDepth=0 ;nDepth<aAllTicks.getLength(); nDepth++ ) 402*cdf0e10cSrcweir { 403*cdf0e10cSrcweir sal_Int32 nCount = aAllTicks[nDepth].getLength(); 404*cdf0e10cSrcweir 405*cdf0e10cSrcweir ::std::vector< TickInfo >& rTickInfoVector = rAllTickInfos[nDepth]; 406*cdf0e10cSrcweir rTickInfoVector.clear(); 407*cdf0e10cSrcweir rTickInfoVector.reserve( nCount ); 408*cdf0e10cSrcweir for(sal_Int32 nN = 0; nN<nCount; nN++) 409*cdf0e10cSrcweir { 410*cdf0e10cSrcweir TickInfo aTickInfo(m_xInverseScaling); 411*cdf0e10cSrcweir aTickInfo.fScaledTickValue = aAllTicks[nDepth][nN]; 412*cdf0e10cSrcweir rTickInfoVector.push_back(aTickInfo); 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir } 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir void EquidistantTickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const 418*cdf0e10cSrcweir { 419*cdf0e10cSrcweir ExplicitIncrementData aShiftedIncrement( m_rIncrement ); 420*cdf0e10cSrcweir aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0; 421*cdf0e10cSrcweir EquidistantTickFactory( m_rScale, aShiftedIncrement ).getAllTicks(rAllTickInfos); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir //----------------------------------------------------------------------------- 425*cdf0e10cSrcweir //----------------------------------------------------------------------------- 426*cdf0e10cSrcweir //----------------------------------------------------------------------------- 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks 429*cdf0e10cSrcweir , const ExplicitIncrementData& rIncrement 430*cdf0e10cSrcweir , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) 431*cdf0e10cSrcweir : m_pSimpleTicks(&rTicks) 432*cdf0e10cSrcweir , m_pInfoTicks(0) 433*cdf0e10cSrcweir , m_rIncrement(rIncrement) 434*cdf0e10cSrcweir , m_nMinDepth(0), m_nMaxDepth(0) 435*cdf0e10cSrcweir , m_nTickCount(0), m_pnPositions(NULL) 436*cdf0e10cSrcweir , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) 437*cdf0e10cSrcweir , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) 438*cdf0e10cSrcweir { 439*cdf0e10cSrcweir initIter( nMinDepth, nMaxDepth ); 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks 443*cdf0e10cSrcweir , const ExplicitIncrementData& rIncrement 444*cdf0e10cSrcweir , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) 445*cdf0e10cSrcweir : m_pSimpleTicks(NULL) 446*cdf0e10cSrcweir , m_pInfoTicks(&rTicks) 447*cdf0e10cSrcweir , m_rIncrement(rIncrement) 448*cdf0e10cSrcweir , m_nMinDepth(0), m_nMaxDepth(0) 449*cdf0e10cSrcweir , m_nTickCount(0), m_pnPositions(NULL) 450*cdf0e10cSrcweir , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) 451*cdf0e10cSrcweir , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) 452*cdf0e10cSrcweir { 453*cdf0e10cSrcweir initIter( nMinDepth, nMaxDepth ); 454*cdf0e10cSrcweir } 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir m_nMaxDepth = nMaxDepth; 459*cdf0e10cSrcweir if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth()) 460*cdf0e10cSrcweir m_nMaxDepth=getMaxDepth(); 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir sal_Int32 nDepth = 0; 463*cdf0e10cSrcweir for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) 464*cdf0e10cSrcweir m_nTickCount += getTickCount(nDepth); 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir if(!m_nTickCount) 467*cdf0e10cSrcweir return; 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir m_pnPositions = new sal_Int32[m_nMaxDepth+1]; 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir m_pnPreParentCount = new sal_Int32[m_nMaxDepth+1]; 472*cdf0e10cSrcweir m_pbIntervalFinished = new bool[m_nMaxDepth+1]; 473*cdf0e10cSrcweir m_pnPreParentCount[0] = 0; 474*cdf0e10cSrcweir m_pbIntervalFinished[0] = false; 475*cdf0e10cSrcweir double fParentValue = getTickValue(0,0); 476*cdf0e10cSrcweir for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ ) 477*cdf0e10cSrcweir { 478*cdf0e10cSrcweir m_pbIntervalFinished[nDepth] = false; 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir sal_Int32 nPreParentCount = 0; 481*cdf0e10cSrcweir sal_Int32 nCount = getTickCount(nDepth); 482*cdf0e10cSrcweir for(sal_Int32 nN = 0; nN<nCount; nN++) 483*cdf0e10cSrcweir { 484*cdf0e10cSrcweir if(getTickValue(nDepth,nN) < fParentValue) 485*cdf0e10cSrcweir nPreParentCount++; 486*cdf0e10cSrcweir else 487*cdf0e10cSrcweir break; 488*cdf0e10cSrcweir } 489*cdf0e10cSrcweir m_pnPreParentCount[nDepth] = nPreParentCount; 490*cdf0e10cSrcweir if(nCount) 491*cdf0e10cSrcweir { 492*cdf0e10cSrcweir double fNextParentValue = getTickValue(nDepth,0); 493*cdf0e10cSrcweir if( fNextParentValue < fParentValue ) 494*cdf0e10cSrcweir fParentValue = fNextParentValue; 495*cdf0e10cSrcweir } 496*cdf0e10cSrcweir } 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir EquidistantTickIter::~EquidistantTickIter() 500*cdf0e10cSrcweir { 501*cdf0e10cSrcweir delete[] m_pnPositions; 502*cdf0e10cSrcweir delete[] m_pnPreParentCount; 503*cdf0e10cSrcweir delete[] m_pbIntervalFinished; 504*cdf0e10cSrcweir } 505*cdf0e10cSrcweir 506*cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getStartDepth() const 507*cdf0e10cSrcweir { 508*cdf0e10cSrcweir //find the depth of the first visible tickmark: 509*cdf0e10cSrcweir //it is the depth of the smallest value 510*cdf0e10cSrcweir sal_Int32 nReturnDepth=0; 511*cdf0e10cSrcweir double fMinValue = DBL_MAX; 512*cdf0e10cSrcweir for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) 513*cdf0e10cSrcweir { 514*cdf0e10cSrcweir sal_Int32 nCount = getTickCount(nDepth); 515*cdf0e10cSrcweir if( !nCount ) 516*cdf0e10cSrcweir continue; 517*cdf0e10cSrcweir double fThisValue = getTickValue(nDepth,0); 518*cdf0e10cSrcweir if(fThisValue<fMinValue) 519*cdf0e10cSrcweir { 520*cdf0e10cSrcweir nReturnDepth = nDepth; 521*cdf0e10cSrcweir fMinValue = fThisValue; 522*cdf0e10cSrcweir } 523*cdf0e10cSrcweir } 524*cdf0e10cSrcweir return nReturnDepth; 525*cdf0e10cSrcweir } 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir double* EquidistantTickIter::firstValue() 528*cdf0e10cSrcweir { 529*cdf0e10cSrcweir if( gotoFirst() ) 530*cdf0e10cSrcweir { 531*cdf0e10cSrcweir m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]); 532*cdf0e10cSrcweir return &m_fCurrentValue; 533*cdf0e10cSrcweir } 534*cdf0e10cSrcweir return NULL; 535*cdf0e10cSrcweir } 536*cdf0e10cSrcweir 537*cdf0e10cSrcweir TickInfo* EquidistantTickIter::firstInfo() 538*cdf0e10cSrcweir { 539*cdf0e10cSrcweir if( m_pInfoTicks && gotoFirst() ) 540*cdf0e10cSrcweir return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; 541*cdf0e10cSrcweir return NULL; 542*cdf0e10cSrcweir } 543*cdf0e10cSrcweir 544*cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth ) 545*cdf0e10cSrcweir { 546*cdf0e10cSrcweir if(nDepth>static_cast<sal_Int32>(m_rIncrement.SubIncrements.size()) || nDepth<0) 547*cdf0e10cSrcweir return 0; 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir if(!nDepth) 550*cdf0e10cSrcweir return m_nTickCount; 551*cdf0e10cSrcweir 552*cdf0e10cSrcweir return m_rIncrement.SubIncrements[nDepth-1].IntervalCount; 553*cdf0e10cSrcweir } 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir bool EquidistantTickIter::isAtLastPartTick() 556*cdf0e10cSrcweir { 557*cdf0e10cSrcweir if(!m_nCurrentDepth) 558*cdf0e10cSrcweir return false; 559*cdf0e10cSrcweir sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth ); 560*cdf0e10cSrcweir if(!nIntervalCount || nIntervalCount == 1) 561*cdf0e10cSrcweir return true; 562*cdf0e10cSrcweir if( m_pbIntervalFinished[m_nCurrentDepth] ) 563*cdf0e10cSrcweir return false; 564*cdf0e10cSrcweir sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1; 565*cdf0e10cSrcweir if(m_pnPreParentCount[m_nCurrentDepth]) 566*cdf0e10cSrcweir nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth]; 567*cdf0e10cSrcweir bool bRet = nPos && nPos % (nIntervalCount-1) == 0; 568*cdf0e10cSrcweir if(!nPos && !m_pnPreParentCount[m_nCurrentDepth] 569*cdf0e10cSrcweir && m_pnPositions[m_nCurrentDepth-1]==-1 ) 570*cdf0e10cSrcweir bRet = true; 571*cdf0e10cSrcweir return bRet; 572*cdf0e10cSrcweir } 573*cdf0e10cSrcweir 574*cdf0e10cSrcweir bool EquidistantTickIter::gotoFirst() 575*cdf0e10cSrcweir { 576*cdf0e10cSrcweir if( m_nMaxDepth<0 ) 577*cdf0e10cSrcweir return false; 578*cdf0e10cSrcweir if( !m_nTickCount ) 579*cdf0e10cSrcweir return false; 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) 582*cdf0e10cSrcweir m_pnPositions[nDepth] = -1; 583*cdf0e10cSrcweir 584*cdf0e10cSrcweir m_nCurrentPos = 0; 585*cdf0e10cSrcweir m_nCurrentDepth = getStartDepth(); 586*cdf0e10cSrcweir m_pnPositions[m_nCurrentDepth] = 0; 587*cdf0e10cSrcweir return true; 588*cdf0e10cSrcweir } 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir bool EquidistantTickIter::gotoNext() 591*cdf0e10cSrcweir { 592*cdf0e10cSrcweir if( m_nCurrentPos < 0 ) 593*cdf0e10cSrcweir return false; 594*cdf0e10cSrcweir m_nCurrentPos++; 595*cdf0e10cSrcweir 596*cdf0e10cSrcweir if( m_nCurrentPos >= m_nTickCount ) 597*cdf0e10cSrcweir return false; 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() ) 600*cdf0e10cSrcweir { 601*cdf0e10cSrcweir do 602*cdf0e10cSrcweir { 603*cdf0e10cSrcweir m_pbIntervalFinished[m_nCurrentDepth] = true; 604*cdf0e10cSrcweir m_nCurrentDepth--; 605*cdf0e10cSrcweir } 606*cdf0e10cSrcweir while( m_nCurrentDepth && isAtLastPartTick() ); 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir else if( m_nCurrentDepth<m_nMaxDepth ) 609*cdf0e10cSrcweir { 610*cdf0e10cSrcweir do 611*cdf0e10cSrcweir { 612*cdf0e10cSrcweir m_nCurrentDepth++; 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir while( m_nCurrentDepth<m_nMaxDepth ); 615*cdf0e10cSrcweir } 616*cdf0e10cSrcweir m_pbIntervalFinished[m_nCurrentDepth] = false; 617*cdf0e10cSrcweir m_pnPositions[m_nCurrentDepth] = m_pnPositions[m_nCurrentDepth]+1; 618*cdf0e10cSrcweir return true; 619*cdf0e10cSrcweir } 620*cdf0e10cSrcweir 621*cdf0e10cSrcweir bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex ) 622*cdf0e10cSrcweir { 623*cdf0e10cSrcweir if( nTickIndex < 0 ) 624*cdf0e10cSrcweir return false; 625*cdf0e10cSrcweir if( nTickIndex >= m_nTickCount ) 626*cdf0e10cSrcweir return false; 627*cdf0e10cSrcweir 628*cdf0e10cSrcweir if( nTickIndex < m_nCurrentPos ) 629*cdf0e10cSrcweir if( !gotoFirst() ) 630*cdf0e10cSrcweir return false; 631*cdf0e10cSrcweir 632*cdf0e10cSrcweir while( nTickIndex > m_nCurrentPos ) 633*cdf0e10cSrcweir if( !gotoNext() ) 634*cdf0e10cSrcweir return false; 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir return true; 637*cdf0e10cSrcweir } 638*cdf0e10cSrcweir 639*cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getCurrentIndex() const 640*cdf0e10cSrcweir { 641*cdf0e10cSrcweir return m_nCurrentPos; 642*cdf0e10cSrcweir } 643*cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getMaxIndex() const 644*cdf0e10cSrcweir { 645*cdf0e10cSrcweir return m_nTickCount-1; 646*cdf0e10cSrcweir } 647*cdf0e10cSrcweir 648*cdf0e10cSrcweir double* EquidistantTickIter::nextValue() 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir if( gotoNext() ) 651*cdf0e10cSrcweir { 652*cdf0e10cSrcweir m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]); 653*cdf0e10cSrcweir return &m_fCurrentValue; 654*cdf0e10cSrcweir } 655*cdf0e10cSrcweir return NULL; 656*cdf0e10cSrcweir } 657*cdf0e10cSrcweir 658*cdf0e10cSrcweir TickInfo* EquidistantTickIter::nextInfo() 659*cdf0e10cSrcweir { 660*cdf0e10cSrcweir if( m_pInfoTicks && gotoNext() && 661*cdf0e10cSrcweir static_cast< sal_Int32 >( 662*cdf0e10cSrcweir (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] ) 663*cdf0e10cSrcweir { 664*cdf0e10cSrcweir return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir return NULL; 667*cdf0e10cSrcweir } 668*cdf0e10cSrcweir 669*cdf0e10cSrcweir //............................................................................. 670*cdf0e10cSrcweir } //namespace chart 671*cdf0e10cSrcweir //............................................................................. 672