/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" #include "TickmarkHelper.hxx" #include "ViewDefines.hxx" #include #include #include //............................................................................. namespace chart { //............................................................................. using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; using namespace ::rtl::math; using ::basegfx::B2DVector; TickInfo::TickInfo() : fScaledTickValue( 0.0 ) , fUnscaledTickValue( 0.0 ) , aTickScreenPosition(0.0,0.0) , bPaintIt( true ) , xTextShape( NULL ) , nFactorForLimitedTextWidth(1) { } void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseScaling ) { if( xInverseScaling.is() ) this->fUnscaledTickValue = xInverseScaling->doScaling( this->fScaledTickValue ); else this->fUnscaledTickValue = this->fScaledTickValue; } sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const { //return the positive distance between the two first tickmarks in screen values B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition; sal_Int32 nRet = static_cast(aDistance.getLength()); if(nRet<0) nRet *= -1; return nRet; } PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector ) : m_rTickVector(rTickInfoVector) , m_aTickIter(m_rTickVector.begin()) { } PureTickIter::~PureTickIter() { } TickInfo* PureTickIter::firstInfo() { m_aTickIter = m_rTickVector.begin(); if(m_aTickIter!=m_rTickVector.end()) return &*m_aTickIter; return 0; } TickInfo* PureTickIter::nextInfo() { m_aTickIter++; if(m_aTickIter!=m_rTickVector.end()) return &*m_aTickIter; return 0; } EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) : m_pSimpleTicks(&rTicks) , m_pInfoTicks(0) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) { initIter( nMinDepth, nMaxDepth ); } EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks , const ExplicitIncrementData& rIncrement , sal_Int32 nMinDepth, sal_Int32 nMaxDepth ) : m_pSimpleTicks(NULL) , m_pInfoTicks(&rTicks) , m_rIncrement(rIncrement) , m_nMinDepth(0), m_nMaxDepth(0) , m_nTickCount(0), m_pnPositions(NULL) , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL) , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 ) { initIter( nMinDepth, nMaxDepth ); } void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth ) { m_nMaxDepth = nMaxDepth; if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth()) m_nMaxDepth=getMaxDepth(); sal_Int32 nDepth = 0; for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) m_nTickCount += getTickCount(nDepth); if(!m_nTickCount) return; m_pnPositions = new sal_Int32[m_nMaxDepth+1]; m_pnPreParentCount = new sal_Int32[m_nMaxDepth+1]; m_pbIntervalFinished = new bool[m_nMaxDepth+1]; m_pnPreParentCount[0] = 0; m_pbIntervalFinished[0] = false; double fParentValue = getTickValue(0,0); for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ ) { m_pbIntervalFinished[nDepth] = false; sal_Int32 nPreParentCount = 0; sal_Int32 nCount = getTickCount(nDepth); for(sal_Int32 nN = 0; nNm_rIncrement.SubIncrements.getLength() || nDepth<0) return 0; if(!nDepth) return m_nTickCount; return m_rIncrement.SubIncrements[nDepth-1].IntervalCount; } bool EquidistantTickIter::isAtLastPartTick() { if(!m_nCurrentDepth) return false; sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth ); if(!nIntervalCount || nIntervalCount == 1) return true; if( m_pbIntervalFinished[m_nCurrentDepth] ) return false; sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1; if(m_pnPreParentCount[m_nCurrentDepth]) nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth]; bool bRet = nPos && nPos % (nIntervalCount-1) == 0; if(!nPos && !m_pnPreParentCount[m_nCurrentDepth] && m_pnPositions[m_nCurrentDepth-1]==-1 ) bRet = true; return bRet; } bool EquidistantTickIter::gotoFirst() { if( m_nMaxDepth<0 ) return false; if( !m_nTickCount ) return false; for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ ) m_pnPositions[nDepth] = -1; m_nCurrentPos = 0; m_nCurrentDepth = getStartDepth(); m_pnPositions[m_nCurrentDepth] = 0; return true; } bool EquidistantTickIter::gotoNext() { if( m_nCurrentPos < 0 ) return false; m_nCurrentPos++; if( m_nCurrentPos >= m_nTickCount ) return false; if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() ) { do { m_pbIntervalFinished[m_nCurrentDepth] = true; m_nCurrentDepth--; } while( m_nCurrentDepth && isAtLastPartTick() ); } else if( m_nCurrentDepth= m_nTickCount ) return false; if( nTickIndex < m_nCurrentPos ) if( !gotoFirst() ) return false; while( nTickIndex > m_nCurrentPos ) if( !gotoNext() ) return false; return true; } sal_Int32 EquidistantTickIter::getCurrentIndex() const { return m_nCurrentPos; } sal_Int32 EquidistantTickIter::getMaxIndex() const { return m_nTickCount-1; } double* EquidistantTickIter::nextValue() { if( gotoNext() ) { m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]); return &m_fCurrentValue; } return NULL; } TickInfo* EquidistantTickIter::nextInfo() { if( m_pInfoTicks && gotoNext() && static_cast< sal_Int32 >( (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] ) { return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]]; } return NULL; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //static double TickmarkHelper::getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement ) { //the returned value will be <= fMin and on a Major Tick given by rIncrement if(rIncrement.Distance<=0.0) return fMin; double fRet = rIncrement.BaseValue + floor( approxSub( fMin, rIncrement.BaseValue ) / rIncrement.Distance) *rIncrement.Distance; if( fRet > fMin ) { if( !approxEqual(fRet, fMin) ) fRet -= rIncrement.Distance; } return fRet; } //static double TickmarkHelper::getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement ) { //the returned value will be >= fMax and on a Major Tick given by rIncrement if(rIncrement.Distance<=0.0) return fMax; double fRet = rIncrement.BaseValue + floor( approxSub( fMax, rIncrement.BaseValue ) / rIncrement.Distance) *rIncrement.Distance; if( fRet < fMax ) { if( !approxEqual(fRet, fMax) ) fRet += rIncrement.Distance; } return fRet; } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- TickmarkHelper::TickmarkHelper( const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) : m_rScale( rScale ) , m_rIncrement( rIncrement ) , m_xInverseScaling(NULL) , m_pfCurrentValues(NULL) { //@todo: make sure that the scale is valid for the scaling m_pfCurrentValues = new double[getTickDepth()]; if( m_rScale.Scaling.is() ) { m_xInverseScaling = m_rScale.Scaling->getInverseScaling(); DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" ); } double fMin = m_fScaledVisibleMin = m_rScale.Minimum; if( m_xInverseScaling.is() ) { m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin); if(m_rIncrement.PostEquidistant ) fMin = m_fScaledVisibleMin; } double fMax = m_fScaledVisibleMax = m_rScale.Maximum; if( m_xInverseScaling.is() ) { m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax); if(m_rIncrement.PostEquidistant ) fMax = m_fScaledVisibleMax; } //-- m_fOuterMajorTickBorderMin = TickmarkHelper::getMinimumAtIncrement( fMin, m_rIncrement ); m_fOuterMajorTickBorderMax = TickmarkHelper::getMaximumAtIncrement( fMax, m_rIncrement ); //-- m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin; m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax; if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() ) { m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax //it is assumed here, that the original range in the given Scale is valid if( !rtl::math::isFinite(m_fOuterMajorTickBorderMin_Scaled) ) { m_fOuterMajorTickBorderMin += m_rIncrement.Distance; m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin); } if( !rtl::math::isFinite(m_fOuterMajorTickBorderMax_Scaled) ) { m_fOuterMajorTickBorderMax -= m_rIncrement.Distance; m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax); } } } TickmarkHelper* TickmarkHelper::createShiftedTickmarkHelper() const { ExplicitIncrementData aShiftedIncrement( m_rIncrement ); aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0; return new TickmarkHelper( m_rScale, aShiftedIncrement ); } TickmarkHelper::~TickmarkHelper() { delete[] m_pfCurrentValues; } sal_Int32 TickmarkHelper::getTickDepth() const { return m_rIncrement.SubIncrements.getLength() + 1; } sal_Int32 TickmarkHelper::getMaxTickCount( sal_Int32 nDepth ) const { //return the maximum amount of ticks //possibly open intervals at the two ends of the region are handled as if they were completely visible //(this is necessary for calculating the sub ticks at the borders correctly) if( nDepth >= getTickDepth() ) return 0; if( m_fOuterMajorTickBorderMax < m_fOuterMajorTickBorderMin ) return 0; if( m_rIncrement.Distance<=0.0) return 0; double fSub; if(m_rIncrement.PostEquidistant ) fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin ); else fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum ); if (!isFinite(fSub)) return 0; sal_Int32 nIntervalCount = static_cast( fSub / m_rIncrement.Distance ); nIntervalCount+=3; for(sal_Int32 nN=0; nN1 ) nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount; } sal_Int32 nTickCount = nIntervalCount; if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1) nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1); return nTickCount; } double* TickmarkHelper::getMajorTick( sal_Int32 nTick ) const { m_pfCurrentValues[0] = m_fOuterMajorTickBorderMin + nTick*m_rIncrement.Distance; if(m_pfCurrentValues[0]>m_fOuterMajorTickBorderMax) { if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMax) ) return NULL; } if(m_pfCurrentValues[0]doScaling( m_pfCurrentValues[0] ); return &m_pfCurrentValues[0]; } double* TickmarkHelper::getMinorTick( sal_Int32 nTick, sal_Int32 nDepth , double fStartParentTick, double fNextParentTick ) const { //check validity of arguments { //DBG_ASSERT( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick"); if(fStartParentTick >= fNextParentTick) return NULL; if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<=0) return NULL; //subticks are only calculated if they are laying between parent ticks: if(nTick<=0) return NULL; if(nTick>=m_rIncrement.SubIncrements[nDepth-1].IntervalCount) return NULL; } bool bPostEquidistant = m_rIncrement.SubIncrements[nDepth-1].PostEquidistant; double fAdaptedStartParent = fStartParentTick; double fAdaptedNextParent = fNextParentTick; if( !bPostEquidistant && m_xInverseScaling.is() ) { fAdaptedStartParent = m_xInverseScaling->doScaling(fStartParentTick); fAdaptedNextParent = m_xInverseScaling->doScaling(fNextParentTick); } double fDistance = (fAdaptedNextParent - fAdaptedStartParent)/m_rIncrement.SubIncrements[nDepth-1].IntervalCount; m_pfCurrentValues[nDepth] = fAdaptedStartParent + nTick*fDistance; //return always the value after scaling if(!bPostEquidistant && m_xInverseScaling.is() ) m_pfCurrentValues[nDepth] = m_rScale.Scaling->doScaling( m_pfCurrentValues[nDepth] ); if( !isWithinOuterBorder( m_pfCurrentValues[nDepth] ) ) return NULL; return &m_pfCurrentValues[nDepth]; } bool TickmarkHelper::isWithinOuterBorder( double fScaledValue ) const { if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled) return false; if(fScaledValuem_fScaledVisibleMax) { if( !approxEqual(fScaledValue,m_fScaledVisibleMax) ) return false; } if(fScaledValue >& rAllTickInfos ) const { uno::Sequence< uno::Sequence< double > > aAllTicks; //create point sequences for each tick depth sal_Int32 nDepthCount = this->getTickDepth(); sal_Int32 nMaxMajorTickCount = this->getMaxTickCount( 0 ); aAllTicks.realloc(nDepthCount); aAllTicks[0].realloc(nMaxMajorTickCount); sal_Int32 nRealMajorTickCount = 0; double* pValue = NULL; for( sal_Int32 nMajorTick=0; nMajorTickgetMajorTick( nMajorTick ); if(!pValue) continue; aAllTicks[0][nRealMajorTickCount] = *pValue; nRealMajorTickCount++; } if(!nRealMajorTickCount) return; aAllTicks[0].realloc(nRealMajorTickCount); if(nDepthCount>0) this->addSubTicks( 1, aAllTicks ); //so far we have added all ticks between the outer major tick marks //this was necessary to create sub ticks correctly //now we reduce all ticks to the visible ones that lie between the real borders sal_Int32 nDepth = 0; sal_Int32 nTick = 0; for( nDepth = 0; nDepth < nDepthCount; nDepth++) { sal_Int32 nInvisibleAtLowerBorder = 0; sal_Int32 nInvisibleAtUpperBorder = 0; //we need only to check all ticks within the first major interval at each border sal_Int32 nCheckCount = 1; for(sal_Int32 nN=0; nN1 ) nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount; } uno::Sequence< double >& rTicks = aAllTicks[nDepth]; sal_Int32 nCount = rTicks.getLength(); //check lower border for( nTick=0; nTicknCount-1-nCheckCount && nTick>=0; nTick--) { if( !isVisible( rTicks[nTick] ) ) nInvisibleAtUpperBorder++; } //resize sequence if( !nInvisibleAtLowerBorder && !nInvisibleAtUpperBorder) continue; if( !nInvisibleAtLowerBorder ) rTicks.realloc(nCount-nInvisibleAtUpperBorder); else { sal_Int32 nNewCount = nCount-nInvisibleAtUpperBorder-nInvisibleAtLowerBorder; if(nNewCount<0) nNewCount=0; uno::Sequence< double > aOldTicks(rTicks); rTicks.realloc(nNewCount); for(nTick = 0; nTick >& rAllTickInfos ) const { std::auto_ptr< TickmarkHelper > apShiftedTickmarkHelper( createShiftedTickmarkHelper() ); apShiftedTickmarkHelper->getAllTicks( rAllTickInfos ); } void TickmarkHelper::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const { EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 ); double* pfNextParentTick = aIter.firstValue(); if(!pfNextParentTick) return; double fLastParentTick = *pfNextParentTick; pfNextParentTick = aIter.nextValue(); if(!pfNextParentTick) return; sal_Int32 nMaxSubTickCount = this->getMaxTickCount( nDepth ); if(!nMaxSubTickCount) return; uno::Sequence< double > aSubTicks(nMaxSubTickCount); sal_Int32 nRealSubTickCount = 0; sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount; double* pValue = NULL; for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue()) { for( sal_Int32 nPartTick = 1; nPartTickgetMinorTick( nPartTick, nDepth , fLastParentTick, *pfNextParentTick ); if(!pValue) continue; aSubTicks[nRealSubTickCount] = *pValue; nRealSubTickCount++; } } aSubTicks.realloc(nRealSubTickCount); rParentTicks[nDepth] = aSubTicks; if(m_rIncrement.SubIncrements.getLength()>nDepth) addSubTicks( nDepth+1, rParentTicks ); } //----------------------------------------------------------------------------- // ___TickmarkHelper_2D___ //----------------------------------------------------------------------------- TickmarkHelper_2D::TickmarkHelper_2D( const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement //, double fStrech_SceneToScreen, double fOffset_SceneToScreen ) , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos , const B2DVector& rAxisLineToLabelLineShift ) : TickmarkHelper( rScale, rIncrement ) , m_aAxisStartScreenPosition2D(rStartScreenPos) , m_aAxisEndScreenPosition2D(rEndScreenPos) , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift) , m_fStrech_LogicToScreen(1.0) , m_fOffset_LogicToScreen(0.0) { double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin; if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation ) { m_fStrech_LogicToScreen = 1.0/fWidthY; m_fOffset_LogicToScreen = -m_fScaledVisibleMin; } else { B2DVector aSwap(m_aAxisStartScreenPosition2D); m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D; m_aAxisEndScreenPosition2D = aSwap; m_fStrech_LogicToScreen = -1.0/fWidthY; m_fOffset_LogicToScreen = -m_fScaledVisibleMax; } } TickmarkHelper* TickmarkHelper_2D::createShiftedTickmarkHelper() const { ExplicitIncrementData aShiftedIncrement( m_rIncrement ); aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0; ::basegfx::B2DVector aStart( m_aAxisStartScreenPosition2D ); ::basegfx::B2DVector aEnd( m_aAxisEndScreenPosition2D ); if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation ) std::swap( aStart, aEnd ); return new TickmarkHelper_2D( m_rScale, aShiftedIncrement, aStart, aEnd, m_aAxisLineToLabelLineShift ); } TickmarkHelper_2D::~TickmarkHelper_2D() { } bool TickmarkHelper_2D::isHorizontalAxis() const { return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() ); } bool TickmarkHelper_2D::isVerticalAxis() const { return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() ); } //static sal_Int32 TickmarkHelper_2D::getTickScreenDistance( TickIter& rIter ) { //return the positive distance between the two first tickmarks in screen values //if there are less than two tickmarks -1 is returned const TickInfo* pFirstTickInfo = rIter.firstInfo(); const TickInfo* pSecondTickInfo = rIter.nextInfo(); if(!pSecondTickInfo || !pFirstTickInfo) return -1; return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo ); } B2DVector TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const { B2DVector aRet(m_aAxisStartScreenPosition2D); aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D) *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen); return aRet; } void TickmarkHelper_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints , sal_Int32 nSequenceIndex , double fScaledLogicTickValue, double fInnerDirectionSign , const TickmarkProperties& rTickmarkProperties , bool bPlaceAtLabels ) const { if( fInnerDirectionSign==0.0 ) fInnerDirectionSign = 1.0; B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue); if( bPlaceAtLabels ) aTickScreenPosition += m_aAxisLineToLabelLineShift; B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; aMainDirection.normalize(); B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); aOrthoDirection *= fInnerDirectionSign; aOrthoDirection.normalize(); B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos; B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length; rPoints[nSequenceIndex].realloc(2); rPoints[nSequenceIndex][0].X = static_cast(aStart.getX()); rPoints[nSequenceIndex][0].Y = static_cast(aStart.getY()); rPoints[nSequenceIndex][1].X = static_cast(aEnd.getX()); rPoints[nSequenceIndex][1].Y = static_cast(aEnd.getY()); } B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const { bool bFarAwayLabels = false; if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos ) bFarAwayLabels = true; double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign; if( fInnerDirectionSign==0.0 ) fInnerDirectionSign = 1.0; B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D; aMainDirection.normalize(); B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX()); aOrthoDirection *= fInnerDirectionSign; aOrthoDirection.normalize(); B2DVector aStart(0,0), aEnd(0,0); if( bFarAwayLabels ) { TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() ); aStart = aOrthoDirection*aProps.RelativePos; aEnd = aStart - aOrthoDirection*aProps.Length; } else { for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;) { const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN]; B2DVector aNewStart = aOrthoDirection*rProps.RelativePos; B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length; if(aNewStart.getLength()>aStart.getLength()) aStart=aNewStart; if(aNewEnd.getLength()>aEnd.getLength()) aEnd=aNewEnd; } } B2DVector aLabelDirection(aStart); if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) aLabelDirection = aEnd; B2DVector aOrthoLabelDirection(aOrthoDirection); if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign ) aOrthoLabelDirection*=-1.0; aOrthoLabelDirection.normalize(); if( bIncludeSpaceBetweenTickAndText ) aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING; if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo ) aLabelDirection += m_aAxisLineToLabelLineShift; return aLabelDirection; } void TickmarkHelper_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const { rPoints[0].realloc(2); rPoints[0][0].X = static_cast(m_aAxisStartScreenPosition2D.getX()); rPoints[0][0].Y = static_cast(m_aAxisStartScreenPosition2D.getY()); rPoints[0][1].X = static_cast(m_aAxisEndScreenPosition2D.getX()); rPoints[0][1].Y = static_cast(m_aAxisEndScreenPosition2D.getY()); } void TickmarkHelper_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const { //get the transformed screen values for all tickmarks in rAllTickInfos ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin(); const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end(); for( ; aDepthIter != aDepthEnd; aDepthIter++ ) { ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin(); const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end(); for( ; aTickIter != aTickEnd; aTickIter++ ) { TickInfo& rTickInfo = (*aTickIter); rTickInfo.aTickScreenPosition = this->getTickScreenPosition2D( rTickInfo.fScaledTickValue ); } } } //----------------------------------------------------------------------------- // ___TickmarkHelper_3D___ //----------------------------------------------------------------------------- TickmarkHelper_3D::TickmarkHelper_3D( const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement ) : TickmarkHelper( rScale, rIncrement ) { } TickmarkHelper* TickmarkHelper_3D::createShiftedTickmarkHelper() const { ExplicitIncrementData aShiftedIncrement( m_rIncrement ); aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0; return new TickmarkHelper_3D( m_rScale, aShiftedIncrement ); } TickmarkHelper_3D::~TickmarkHelper_3D() { } //............................................................................. } //namespace chart //.............................................................................