xref: /AOO41X/main/chart2/source/view/axes/TickmarkHelper.cxx (revision cde9e8dc2218e857da4894ecba5c903312256674)
1*cde9e8dcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*cde9e8dcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*cde9e8dcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*cde9e8dcSAndrew Rist  * distributed with this work for additional information
6*cde9e8dcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*cde9e8dcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*cde9e8dcSAndrew Rist  * "License"); you may not use this file except in compliance
9*cde9e8dcSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*cde9e8dcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*cde9e8dcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*cde9e8dcSAndrew Rist  * software distributed under the License is distributed on an
15*cde9e8dcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*cde9e8dcSAndrew Rist  * KIND, either express or implied.  See the License for the
17*cde9e8dcSAndrew Rist  * specific language governing permissions and limitations
18*cde9e8dcSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*cde9e8dcSAndrew Rist  *************************************************************/
21*cde9e8dcSAndrew Rist 
22*cde9e8dcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_chart2.hxx"
26cdf0e10cSrcweir #include "TickmarkHelper.hxx"
27cdf0e10cSrcweir #include "ViewDefines.hxx"
28cdf0e10cSrcweir #include <rtl/math.hxx>
29cdf0e10cSrcweir #include <tools/debug.hxx>
30cdf0e10cSrcweir #include <memory>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir //.............................................................................
33cdf0e10cSrcweir namespace chart
34cdf0e10cSrcweir {
35cdf0e10cSrcweir //.............................................................................
36cdf0e10cSrcweir using namespace ::com::sun::star;
37cdf0e10cSrcweir using namespace ::com::sun::star::chart2;
38cdf0e10cSrcweir using namespace ::rtl::math;
39cdf0e10cSrcweir using ::basegfx::B2DVector;
40cdf0e10cSrcweir 
TickInfo()41cdf0e10cSrcweir TickInfo::TickInfo()
42cdf0e10cSrcweir : fScaledTickValue( 0.0 )
43cdf0e10cSrcweir , fUnscaledTickValue( 0.0 )
44cdf0e10cSrcweir , aTickScreenPosition(0.0,0.0)
45cdf0e10cSrcweir , bPaintIt( true )
46cdf0e10cSrcweir , xTextShape( NULL )
47cdf0e10cSrcweir , nFactorForLimitedTextWidth(1)
48cdf0e10cSrcweir {
49cdf0e10cSrcweir }
50cdf0e10cSrcweir 
updateUnscaledValue(const uno::Reference<XScaling> & xInverseScaling)51cdf0e10cSrcweir void TickInfo::updateUnscaledValue( const uno::Reference< XScaling >& xInverseScaling )
52cdf0e10cSrcweir {
53cdf0e10cSrcweir     if( xInverseScaling.is() )
54cdf0e10cSrcweir         this->fUnscaledTickValue = xInverseScaling->doScaling( this->fScaledTickValue );
55cdf0e10cSrcweir     else
56cdf0e10cSrcweir         this->fUnscaledTickValue = this->fScaledTickValue;
57cdf0e10cSrcweir }
58cdf0e10cSrcweir 
getScreenDistanceBetweenTicks(const TickInfo & rOherTickInfo) const59cdf0e10cSrcweir sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     //return the positive distance between the two first tickmarks in screen values
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
64cdf0e10cSrcweir     sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
65cdf0e10cSrcweir     if(nRet<0)
66cdf0e10cSrcweir         nRet *= -1;
67cdf0e10cSrcweir     return nRet;
68cdf0e10cSrcweir }
69cdf0e10cSrcweir 
PureTickIter(::std::vector<TickInfo> & rTickInfoVector)70cdf0e10cSrcweir PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector )
71cdf0e10cSrcweir             : m_rTickVector(rTickInfoVector)
72cdf0e10cSrcweir             , m_aTickIter(m_rTickVector.begin())
73cdf0e10cSrcweir {
74cdf0e10cSrcweir }
~PureTickIter()75cdf0e10cSrcweir PureTickIter::~PureTickIter()
76cdf0e10cSrcweir {
77cdf0e10cSrcweir }
firstInfo()78cdf0e10cSrcweir TickInfo* PureTickIter::firstInfo()
79cdf0e10cSrcweir {
80cdf0e10cSrcweir     m_aTickIter = m_rTickVector.begin();
81cdf0e10cSrcweir     if(m_aTickIter!=m_rTickVector.end())
82cdf0e10cSrcweir         return &*m_aTickIter;
83cdf0e10cSrcweir     return 0;
84cdf0e10cSrcweir }
nextInfo()85cdf0e10cSrcweir TickInfo* PureTickIter::nextInfo()
86cdf0e10cSrcweir {
87cdf0e10cSrcweir     m_aTickIter++;
88cdf0e10cSrcweir     if(m_aTickIter!=m_rTickVector.end())
89cdf0e10cSrcweir         return &*m_aTickIter;
90cdf0e10cSrcweir     return 0;
91cdf0e10cSrcweir }
92cdf0e10cSrcweir 
EquidistantTickIter(const uno::Sequence<uno::Sequence<double>> & rTicks,const ExplicitIncrementData & rIncrement,sal_Int32 nMinDepth,sal_Int32 nMaxDepth)93cdf0e10cSrcweir EquidistantTickIter::EquidistantTickIter( const uno::Sequence< uno::Sequence< double > >& rTicks
94cdf0e10cSrcweir                    , const ExplicitIncrementData& rIncrement
95cdf0e10cSrcweir                    , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
96cdf0e10cSrcweir                 : m_pSimpleTicks(&rTicks)
97cdf0e10cSrcweir                 , m_pInfoTicks(0)
98cdf0e10cSrcweir                 , m_rIncrement(rIncrement)
99cdf0e10cSrcweir                 , m_nMinDepth(0), m_nMaxDepth(0)
100cdf0e10cSrcweir                 , m_nTickCount(0), m_pnPositions(NULL)
101cdf0e10cSrcweir                 , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL)
102cdf0e10cSrcweir                 , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir     initIter( nMinDepth, nMaxDepth );
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
EquidistantTickIter(::std::vector<::std::vector<TickInfo>> & rTicks,const ExplicitIncrementData & rIncrement,sal_Int32 nMinDepth,sal_Int32 nMaxDepth)107cdf0e10cSrcweir EquidistantTickIter::EquidistantTickIter( ::std::vector< ::std::vector< TickInfo > >& rTicks
108cdf0e10cSrcweir                    , const ExplicitIncrementData& rIncrement
109cdf0e10cSrcweir                    , sal_Int32 nMinDepth, sal_Int32 nMaxDepth )
110cdf0e10cSrcweir                 : m_pSimpleTicks(NULL)
111cdf0e10cSrcweir                 , m_pInfoTicks(&rTicks)
112cdf0e10cSrcweir                 , m_rIncrement(rIncrement)
113cdf0e10cSrcweir                 , m_nMinDepth(0), m_nMaxDepth(0)
114cdf0e10cSrcweir                 , m_nTickCount(0), m_pnPositions(NULL)
115cdf0e10cSrcweir                 , m_pnPreParentCount(NULL), m_pbIntervalFinished(NULL)
116cdf0e10cSrcweir                 , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     initIter( nMinDepth, nMaxDepth );
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
initIter(sal_Int32,sal_Int32 nMaxDepth)121cdf0e10cSrcweir void EquidistantTickIter::initIter( sal_Int32 /*nMinDepth*/, sal_Int32 nMaxDepth )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     m_nMaxDepth = nMaxDepth;
124cdf0e10cSrcweir     if(nMaxDepth<0 || m_nMaxDepth>getMaxDepth())
125cdf0e10cSrcweir         m_nMaxDepth=getMaxDepth();
126cdf0e10cSrcweir 
127cdf0e10cSrcweir     sal_Int32 nDepth = 0;
128cdf0e10cSrcweir     for( nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
129cdf0e10cSrcweir         m_nTickCount += getTickCount(nDepth);
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     if(!m_nTickCount)
132cdf0e10cSrcweir         return;
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     m_pnPositions      = new sal_Int32[m_nMaxDepth+1];
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     m_pnPreParentCount = new sal_Int32[m_nMaxDepth+1];
137cdf0e10cSrcweir     m_pbIntervalFinished = new bool[m_nMaxDepth+1];
138cdf0e10cSrcweir     m_pnPreParentCount[0] = 0;
139cdf0e10cSrcweir     m_pbIntervalFinished[0] = false;
140cdf0e10cSrcweir     double fParentValue = getTickValue(0,0);
141cdf0e10cSrcweir     for( nDepth = 1; nDepth<=m_nMaxDepth ;nDepth++ )
142cdf0e10cSrcweir     {
143cdf0e10cSrcweir         m_pbIntervalFinished[nDepth] = false;
144cdf0e10cSrcweir 
145cdf0e10cSrcweir         sal_Int32 nPreParentCount = 0;
146cdf0e10cSrcweir         sal_Int32 nCount = getTickCount(nDepth);
147cdf0e10cSrcweir         for(sal_Int32 nN = 0; nN<nCount; nN++)
148cdf0e10cSrcweir         {
149cdf0e10cSrcweir             if(getTickValue(nDepth,nN) < fParentValue)
150cdf0e10cSrcweir                 nPreParentCount++;
151cdf0e10cSrcweir             else
152cdf0e10cSrcweir                 break;
153cdf0e10cSrcweir         }
154cdf0e10cSrcweir         m_pnPreParentCount[nDepth] = nPreParentCount;
155cdf0e10cSrcweir         if(nCount)
156cdf0e10cSrcweir         {
157cdf0e10cSrcweir             double fNextParentValue = getTickValue(nDepth,0);
158cdf0e10cSrcweir             if( fNextParentValue < fParentValue )
159cdf0e10cSrcweir                 fParentValue = fNextParentValue;
160cdf0e10cSrcweir         }
161cdf0e10cSrcweir     }
162cdf0e10cSrcweir }
163cdf0e10cSrcweir 
~EquidistantTickIter()164cdf0e10cSrcweir EquidistantTickIter::~EquidistantTickIter()
165cdf0e10cSrcweir {
166cdf0e10cSrcweir     delete[] m_pnPositions;
167cdf0e10cSrcweir     delete[] m_pnPreParentCount;
168cdf0e10cSrcweir     delete[] m_pbIntervalFinished;
169cdf0e10cSrcweir }
170cdf0e10cSrcweir 
getStartDepth() const171cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getStartDepth() const
172cdf0e10cSrcweir {
173cdf0e10cSrcweir     //find the depth of the first visible tickmark:
174cdf0e10cSrcweir     //it is the depth of the smallest value
175cdf0e10cSrcweir     sal_Int32 nReturnDepth=0;
176cdf0e10cSrcweir     double fMinValue = DBL_MAX;
177cdf0e10cSrcweir     for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
178cdf0e10cSrcweir     {
179cdf0e10cSrcweir         sal_Int32 nCount = getTickCount(nDepth);
180cdf0e10cSrcweir         if( !nCount )
181cdf0e10cSrcweir             continue;
182cdf0e10cSrcweir         double fThisValue = getTickValue(nDepth,0);
183cdf0e10cSrcweir         if(fThisValue<fMinValue)
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir             nReturnDepth = nDepth;
186cdf0e10cSrcweir             fMinValue = fThisValue;
187cdf0e10cSrcweir         }
188cdf0e10cSrcweir     }
189cdf0e10cSrcweir     return nReturnDepth;
190cdf0e10cSrcweir }
191cdf0e10cSrcweir 
firstValue()192cdf0e10cSrcweir double* EquidistantTickIter::firstValue()
193cdf0e10cSrcweir {
194cdf0e10cSrcweir     if( gotoFirst() )
195cdf0e10cSrcweir     {
196cdf0e10cSrcweir         m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
197cdf0e10cSrcweir         return &m_fCurrentValue;
198cdf0e10cSrcweir     }
199cdf0e10cSrcweir     return NULL;
200cdf0e10cSrcweir }
201cdf0e10cSrcweir 
firstInfo()202cdf0e10cSrcweir TickInfo* EquidistantTickIter::firstInfo()
203cdf0e10cSrcweir {
204cdf0e10cSrcweir     if( m_pInfoTicks && gotoFirst() )
205cdf0e10cSrcweir         return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
206cdf0e10cSrcweir     return NULL;
207cdf0e10cSrcweir }
208cdf0e10cSrcweir 
getIntervalCount(sal_Int32 nDepth)209cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getIntervalCount( sal_Int32 nDepth )
210cdf0e10cSrcweir {
211cdf0e10cSrcweir     if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<0)
212cdf0e10cSrcweir         return 0;
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     if(!nDepth)
215cdf0e10cSrcweir         return m_nTickCount;
216cdf0e10cSrcweir 
217cdf0e10cSrcweir     return m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
218cdf0e10cSrcweir }
219cdf0e10cSrcweir 
isAtLastPartTick()220cdf0e10cSrcweir bool EquidistantTickIter::isAtLastPartTick()
221cdf0e10cSrcweir {
222cdf0e10cSrcweir     if(!m_nCurrentDepth)
223cdf0e10cSrcweir         return false;
224cdf0e10cSrcweir     sal_Int32 nIntervalCount = getIntervalCount( m_nCurrentDepth );
225cdf0e10cSrcweir     if(!nIntervalCount || nIntervalCount == 1)
226cdf0e10cSrcweir         return true;
227cdf0e10cSrcweir     if( m_pbIntervalFinished[m_nCurrentDepth] )
228cdf0e10cSrcweir         return false;
229cdf0e10cSrcweir     sal_Int32 nPos = m_pnPositions[m_nCurrentDepth]+1;
230cdf0e10cSrcweir     if(m_pnPreParentCount[m_nCurrentDepth])
231cdf0e10cSrcweir         nPos += nIntervalCount-1 - m_pnPreParentCount[m_nCurrentDepth];
232cdf0e10cSrcweir     bool bRet = nPos && nPos % (nIntervalCount-1) == 0;
233cdf0e10cSrcweir     if(!nPos && !m_pnPreParentCount[m_nCurrentDepth]
234cdf0e10cSrcweir              && m_pnPositions[m_nCurrentDepth-1]==-1 )
235cdf0e10cSrcweir          bRet = true;
236cdf0e10cSrcweir     return bRet;
237cdf0e10cSrcweir }
238cdf0e10cSrcweir 
gotoFirst()239cdf0e10cSrcweir bool EquidistantTickIter::gotoFirst()
240cdf0e10cSrcweir {
241cdf0e10cSrcweir     if( m_nMaxDepth<0 )
242cdf0e10cSrcweir         return false;
243cdf0e10cSrcweir     if( !m_nTickCount )
244cdf0e10cSrcweir         return false;
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     for(sal_Int32 nDepth = 0; nDepth<=m_nMaxDepth ;nDepth++ )
247cdf0e10cSrcweir         m_pnPositions[nDepth] = -1;
248cdf0e10cSrcweir 
249cdf0e10cSrcweir     m_nCurrentPos   = 0;
250cdf0e10cSrcweir     m_nCurrentDepth = getStartDepth();
251cdf0e10cSrcweir     m_pnPositions[m_nCurrentDepth] = 0;
252cdf0e10cSrcweir     return true;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir 
gotoNext()255cdf0e10cSrcweir bool EquidistantTickIter::gotoNext()
256cdf0e10cSrcweir {
257cdf0e10cSrcweir     if( m_nCurrentPos < 0 )
258cdf0e10cSrcweir         return false;
259cdf0e10cSrcweir     m_nCurrentPos++;
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     if( m_nCurrentPos >= m_nTickCount )
262cdf0e10cSrcweir         return false;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     if( m_nCurrentDepth==m_nMaxDepth && isAtLastPartTick() )
265cdf0e10cSrcweir     {
266cdf0e10cSrcweir         do
267cdf0e10cSrcweir         {
268cdf0e10cSrcweir             m_pbIntervalFinished[m_nCurrentDepth] = true;
269cdf0e10cSrcweir             m_nCurrentDepth--;
270cdf0e10cSrcweir         }
271cdf0e10cSrcweir         while( m_nCurrentDepth && isAtLastPartTick() );
272cdf0e10cSrcweir     }
273cdf0e10cSrcweir     else if( m_nCurrentDepth<m_nMaxDepth )
274cdf0e10cSrcweir     {
275cdf0e10cSrcweir         do
276cdf0e10cSrcweir         {
277cdf0e10cSrcweir             m_nCurrentDepth++;
278cdf0e10cSrcweir         }
279cdf0e10cSrcweir         while( m_nCurrentDepth<m_nMaxDepth );
280cdf0e10cSrcweir     }
281cdf0e10cSrcweir     m_pbIntervalFinished[m_nCurrentDepth] = false;
282cdf0e10cSrcweir     m_pnPositions[m_nCurrentDepth] = m_pnPositions[m_nCurrentDepth]+1;
283cdf0e10cSrcweir     return true;
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
gotoIndex(sal_Int32 nTickIndex)286cdf0e10cSrcweir bool EquidistantTickIter::gotoIndex( sal_Int32 nTickIndex )
287cdf0e10cSrcweir {
288cdf0e10cSrcweir     if( nTickIndex < 0 )
289cdf0e10cSrcweir         return false;
290cdf0e10cSrcweir     if( nTickIndex >= m_nTickCount )
291cdf0e10cSrcweir         return false;
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     if( nTickIndex < m_nCurrentPos )
294cdf0e10cSrcweir         if( !gotoFirst() )
295cdf0e10cSrcweir             return false;
296cdf0e10cSrcweir 
297cdf0e10cSrcweir     while( nTickIndex > m_nCurrentPos )
298cdf0e10cSrcweir         if( !gotoNext() )
299cdf0e10cSrcweir             return false;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir     return true;
302cdf0e10cSrcweir }
303cdf0e10cSrcweir 
getCurrentIndex() const304cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getCurrentIndex() const
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     return m_nCurrentPos;
307cdf0e10cSrcweir }
getMaxIndex() const308cdf0e10cSrcweir sal_Int32 EquidistantTickIter::getMaxIndex() const
309cdf0e10cSrcweir {
310cdf0e10cSrcweir     return m_nTickCount-1;
311cdf0e10cSrcweir }
312cdf0e10cSrcweir 
nextValue()313cdf0e10cSrcweir double* EquidistantTickIter::nextValue()
314cdf0e10cSrcweir {
315cdf0e10cSrcweir     if( gotoNext() )
316cdf0e10cSrcweir     {
317cdf0e10cSrcweir         m_fCurrentValue = getTickValue(m_nCurrentDepth, m_pnPositions[m_nCurrentDepth]);
318cdf0e10cSrcweir         return &m_fCurrentValue;
319cdf0e10cSrcweir     }
320cdf0e10cSrcweir     return NULL;
321cdf0e10cSrcweir }
322cdf0e10cSrcweir 
nextInfo()323cdf0e10cSrcweir TickInfo* EquidistantTickIter::nextInfo()
324cdf0e10cSrcweir {
325cdf0e10cSrcweir     if( m_pInfoTicks && gotoNext() &&
326cdf0e10cSrcweir         static_cast< sal_Int32 >(
327cdf0e10cSrcweir             (*m_pInfoTicks)[m_nCurrentDepth].size()) > m_pnPositions[m_nCurrentDepth] )
328cdf0e10cSrcweir     {
329cdf0e10cSrcweir         return &(*m_pInfoTicks)[m_nCurrentDepth][m_pnPositions[m_nCurrentDepth]];
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir     return NULL;
332cdf0e10cSrcweir }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir //-----------------------------------------------------------------------------
335cdf0e10cSrcweir //-----------------------------------------------------------------------------
336cdf0e10cSrcweir //-----------------------------------------------------------------------------
337cdf0e10cSrcweir 
getMinimumAtIncrement(double fMin,const ExplicitIncrementData & rIncrement)338cdf0e10cSrcweir double TickmarkHelper::getMinimumAtIncrement( double fMin, const ExplicitIncrementData& rIncrement )
339cdf0e10cSrcweir {
340cdf0e10cSrcweir     //the returned value will be <= fMin and on a Major Tick given by rIncrement
341cdf0e10cSrcweir     if(rIncrement.Distance<=0.0)
342cdf0e10cSrcweir         return fMin;
343cdf0e10cSrcweir 
344cdf0e10cSrcweir     double fRet = rIncrement.BaseValue +
345cdf0e10cSrcweir         floor( approxSub( fMin, rIncrement.BaseValue )
346cdf0e10cSrcweir                     / rIncrement.Distance)
347cdf0e10cSrcweir             *rIncrement.Distance;
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     if( fRet > fMin )
350cdf0e10cSrcweir     {
351cdf0e10cSrcweir         if( !approxEqual(fRet, fMin) )
352cdf0e10cSrcweir             fRet -= rIncrement.Distance;
353cdf0e10cSrcweir     }
354cdf0e10cSrcweir     return fRet;
355cdf0e10cSrcweir }
getMaximumAtIncrement(double fMax,const ExplicitIncrementData & rIncrement)356cdf0e10cSrcweir double TickmarkHelper::getMaximumAtIncrement( double fMax, const ExplicitIncrementData& rIncrement )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir     //the returned value will be >= fMax and on a Major Tick given by rIncrement
359cdf0e10cSrcweir     if(rIncrement.Distance<=0.0)
360cdf0e10cSrcweir         return fMax;
361cdf0e10cSrcweir 
362cdf0e10cSrcweir     double fRet = rIncrement.BaseValue +
363cdf0e10cSrcweir         floor( approxSub( fMax, rIncrement.BaseValue )
364cdf0e10cSrcweir                     / rIncrement.Distance)
365cdf0e10cSrcweir             *rIncrement.Distance;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir     if( fRet < fMax )
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         if( !approxEqual(fRet, fMax) )
370cdf0e10cSrcweir             fRet += rIncrement.Distance;
371cdf0e10cSrcweir     }
372cdf0e10cSrcweir     return fRet;
373cdf0e10cSrcweir }
374cdf0e10cSrcweir 
375cdf0e10cSrcweir //-----------------------------------------------------------------------------
376cdf0e10cSrcweir //-----------------------------------------------------------------------------
377cdf0e10cSrcweir //-----------------------------------------------------------------------------
378cdf0e10cSrcweir 
TickmarkHelper(const ExplicitScaleData & rScale,const ExplicitIncrementData & rIncrement)379cdf0e10cSrcweir TickmarkHelper::TickmarkHelper(
380cdf0e10cSrcweir           const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
381cdf0e10cSrcweir             : m_rScale( rScale )
382cdf0e10cSrcweir             , m_rIncrement( rIncrement )
383cdf0e10cSrcweir             , m_xInverseScaling(NULL)
384cdf0e10cSrcweir             , m_pfCurrentValues(NULL)
385cdf0e10cSrcweir {
386cdf0e10cSrcweir     //@todo: make sure that the scale is valid for the scaling
387cdf0e10cSrcweir 
388cdf0e10cSrcweir     m_pfCurrentValues = new double[getTickDepth()];
389cdf0e10cSrcweir 
390cdf0e10cSrcweir     if( m_rScale.Scaling.is() )
391cdf0e10cSrcweir     {
392cdf0e10cSrcweir         m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
393cdf0e10cSrcweir         DBG_ASSERT( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" );
394cdf0e10cSrcweir     }
395cdf0e10cSrcweir 
396cdf0e10cSrcweir     double fMin = m_fScaledVisibleMin = m_rScale.Minimum;
397cdf0e10cSrcweir     if( m_xInverseScaling.is() )
398cdf0e10cSrcweir     {
399cdf0e10cSrcweir         m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
400cdf0e10cSrcweir         if(m_rIncrement.PostEquidistant )
401cdf0e10cSrcweir             fMin = m_fScaledVisibleMin;
402cdf0e10cSrcweir     }
403cdf0e10cSrcweir 
404cdf0e10cSrcweir     double fMax = m_fScaledVisibleMax = m_rScale.Maximum;
405cdf0e10cSrcweir     if( m_xInverseScaling.is() )
406cdf0e10cSrcweir     {
407cdf0e10cSrcweir         m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
408cdf0e10cSrcweir         if(m_rIncrement.PostEquidistant )
409cdf0e10cSrcweir             fMax = m_fScaledVisibleMax;
410cdf0e10cSrcweir     }
411cdf0e10cSrcweir 
412cdf0e10cSrcweir     //--
413cdf0e10cSrcweir     m_fOuterMajorTickBorderMin = TickmarkHelper::getMinimumAtIncrement( fMin, m_rIncrement );
414cdf0e10cSrcweir     m_fOuterMajorTickBorderMax = TickmarkHelper::getMaximumAtIncrement( fMax, m_rIncrement );
415cdf0e10cSrcweir     //--
416cdf0e10cSrcweir 
417cdf0e10cSrcweir     m_fOuterMajorTickBorderMin_Scaled = m_fOuterMajorTickBorderMin;
418cdf0e10cSrcweir     m_fOuterMajorTickBorderMax_Scaled = m_fOuterMajorTickBorderMax;
419cdf0e10cSrcweir     if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() )
420cdf0e10cSrcweir     {
421cdf0e10cSrcweir         m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin);
422cdf0e10cSrcweir         m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax);
423cdf0e10cSrcweir 
424cdf0e10cSrcweir         //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax
425cdf0e10cSrcweir         //it is assumed here, that the original range in the given Scale is valid
426cdf0e10cSrcweir         if( !rtl::math::isFinite(m_fOuterMajorTickBorderMin_Scaled) )
427cdf0e10cSrcweir         {
428cdf0e10cSrcweir             m_fOuterMajorTickBorderMin += m_rIncrement.Distance;
429cdf0e10cSrcweir             m_fOuterMajorTickBorderMin_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMin);
430cdf0e10cSrcweir         }
431cdf0e10cSrcweir         if( !rtl::math::isFinite(m_fOuterMajorTickBorderMax_Scaled) )
432cdf0e10cSrcweir         {
433cdf0e10cSrcweir             m_fOuterMajorTickBorderMax -= m_rIncrement.Distance;
434cdf0e10cSrcweir             m_fOuterMajorTickBorderMax_Scaled = m_rScale.Scaling->doScaling(m_fOuterMajorTickBorderMax);
435cdf0e10cSrcweir         }
436cdf0e10cSrcweir     }
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
createShiftedTickmarkHelper() const439cdf0e10cSrcweir TickmarkHelper* TickmarkHelper::createShiftedTickmarkHelper() const
440cdf0e10cSrcweir {
441cdf0e10cSrcweir     ExplicitIncrementData aShiftedIncrement( m_rIncrement );
442cdf0e10cSrcweir     aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
443cdf0e10cSrcweir     return new TickmarkHelper( m_rScale, aShiftedIncrement );
444cdf0e10cSrcweir }
445cdf0e10cSrcweir 
~TickmarkHelper()446cdf0e10cSrcweir TickmarkHelper::~TickmarkHelper()
447cdf0e10cSrcweir {
448cdf0e10cSrcweir     delete[] m_pfCurrentValues;
449cdf0e10cSrcweir }
450cdf0e10cSrcweir 
getTickDepth() const451cdf0e10cSrcweir sal_Int32 TickmarkHelper::getTickDepth() const
452cdf0e10cSrcweir {
453cdf0e10cSrcweir     return m_rIncrement.SubIncrements.getLength() + 1;
454cdf0e10cSrcweir }
455cdf0e10cSrcweir 
getMaxTickCount(sal_Int32 nDepth) const456cdf0e10cSrcweir sal_Int32 TickmarkHelper::getMaxTickCount( sal_Int32 nDepth ) const
457cdf0e10cSrcweir {
458cdf0e10cSrcweir     //return the maximum amount of ticks
459cdf0e10cSrcweir     //possibly open intervals at the two ends of the region are handled as if they were completely visible
460cdf0e10cSrcweir     //(this is necessary for calculating the sub ticks at the borders correctly)
461cdf0e10cSrcweir 
462cdf0e10cSrcweir     if( nDepth >= getTickDepth() )
463cdf0e10cSrcweir         return 0;
464cdf0e10cSrcweir     if( m_fOuterMajorTickBorderMax < m_fOuterMajorTickBorderMin )
465cdf0e10cSrcweir         return 0;
466cdf0e10cSrcweir     if( m_rIncrement.Distance<=0.0)
467cdf0e10cSrcweir         return 0;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir     double fSub;
470cdf0e10cSrcweir     if(m_rIncrement.PostEquidistant  )
471cdf0e10cSrcweir         fSub = approxSub( m_fScaledVisibleMax, m_fScaledVisibleMin );
472cdf0e10cSrcweir     else
473cdf0e10cSrcweir         fSub = approxSub( m_rScale.Maximum, m_rScale.Minimum );
474cdf0e10cSrcweir 
475cdf0e10cSrcweir     if (!isFinite(fSub))
476cdf0e10cSrcweir         return 0;
477cdf0e10cSrcweir 
478cdf0e10cSrcweir     sal_Int32 nIntervalCount = static_cast<sal_Int32>( fSub / m_rIncrement.Distance );
479cdf0e10cSrcweir 
480cdf0e10cSrcweir     nIntervalCount+=3;
481cdf0e10cSrcweir     for(sal_Int32 nN=0; nN<nDepth-1; nN++)
482cdf0e10cSrcweir     {
483cdf0e10cSrcweir         if( m_rIncrement.SubIncrements[nN].IntervalCount>1 )
484cdf0e10cSrcweir             nIntervalCount *= m_rIncrement.SubIncrements[nN].IntervalCount;
485cdf0e10cSrcweir     }
486cdf0e10cSrcweir 
487cdf0e10cSrcweir     sal_Int32 nTickCount = nIntervalCount;
488cdf0e10cSrcweir     if(nDepth>0 && m_rIncrement.SubIncrements[nDepth-1].IntervalCount>1)
489cdf0e10cSrcweir         nTickCount = nIntervalCount * (m_rIncrement.SubIncrements[nDepth-1].IntervalCount-1);
490cdf0e10cSrcweir 
491cdf0e10cSrcweir     return nTickCount;
492cdf0e10cSrcweir }
493cdf0e10cSrcweir 
getMajorTick(sal_Int32 nTick) const494cdf0e10cSrcweir double* TickmarkHelper::getMajorTick( sal_Int32 nTick ) const
495cdf0e10cSrcweir {
496cdf0e10cSrcweir     m_pfCurrentValues[0] = m_fOuterMajorTickBorderMin + nTick*m_rIncrement.Distance;
497cdf0e10cSrcweir 
498cdf0e10cSrcweir     if(m_pfCurrentValues[0]>m_fOuterMajorTickBorderMax)
499cdf0e10cSrcweir     {
500cdf0e10cSrcweir         if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMax) )
501cdf0e10cSrcweir             return NULL;
502cdf0e10cSrcweir     }
503cdf0e10cSrcweir     if(m_pfCurrentValues[0]<m_fOuterMajorTickBorderMin)
504cdf0e10cSrcweir     {
505cdf0e10cSrcweir         if( !approxEqual(m_pfCurrentValues[0],m_fOuterMajorTickBorderMin) )
506cdf0e10cSrcweir             return NULL;
507cdf0e10cSrcweir     }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir     //return always the value after scaling
510cdf0e10cSrcweir     if(!m_rIncrement.PostEquidistant && m_xInverseScaling.is() )
511cdf0e10cSrcweir         m_pfCurrentValues[0] = m_rScale.Scaling->doScaling( m_pfCurrentValues[0] );
512cdf0e10cSrcweir 
513cdf0e10cSrcweir     return &m_pfCurrentValues[0];
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
getMinorTick(sal_Int32 nTick,sal_Int32 nDepth,double fStartParentTick,double fNextParentTick) const516cdf0e10cSrcweir double* TickmarkHelper::getMinorTick( sal_Int32 nTick, sal_Int32 nDepth
517cdf0e10cSrcweir                             , double fStartParentTick, double fNextParentTick ) const
518cdf0e10cSrcweir {
519cdf0e10cSrcweir     //check validity of arguments
520cdf0e10cSrcweir     {
521cdf0e10cSrcweir         //DBG_ASSERT( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick");
522cdf0e10cSrcweir         if(fStartParentTick >= fNextParentTick)
523cdf0e10cSrcweir             return NULL;
524cdf0e10cSrcweir         if(nDepth>m_rIncrement.SubIncrements.getLength() || nDepth<=0)
525cdf0e10cSrcweir             return NULL;
526cdf0e10cSrcweir 
527cdf0e10cSrcweir         //subticks are only calculated if they are laying between parent ticks:
528cdf0e10cSrcweir         if(nTick<=0)
529cdf0e10cSrcweir             return NULL;
530cdf0e10cSrcweir         if(nTick>=m_rIncrement.SubIncrements[nDepth-1].IntervalCount)
531cdf0e10cSrcweir             return NULL;
532cdf0e10cSrcweir     }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir     bool    bPostEquidistant = m_rIncrement.SubIncrements[nDepth-1].PostEquidistant;
535cdf0e10cSrcweir 
536cdf0e10cSrcweir     double fAdaptedStartParent = fStartParentTick;
537cdf0e10cSrcweir     double fAdaptedNextParent  = fNextParentTick;
538cdf0e10cSrcweir 
539cdf0e10cSrcweir     if( !bPostEquidistant && m_xInverseScaling.is() )
540cdf0e10cSrcweir     {
541cdf0e10cSrcweir         fAdaptedStartParent = m_xInverseScaling->doScaling(fStartParentTick);
542cdf0e10cSrcweir         fAdaptedNextParent  = m_xInverseScaling->doScaling(fNextParentTick);
543cdf0e10cSrcweir     }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir     double fDistance = (fAdaptedNextParent - fAdaptedStartParent)/m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
546cdf0e10cSrcweir 
547cdf0e10cSrcweir     m_pfCurrentValues[nDepth] = fAdaptedStartParent + nTick*fDistance;
548cdf0e10cSrcweir 
549cdf0e10cSrcweir     //return always the value after scaling
550cdf0e10cSrcweir     if(!bPostEquidistant && m_xInverseScaling.is() )
551cdf0e10cSrcweir         m_pfCurrentValues[nDepth] = m_rScale.Scaling->doScaling( m_pfCurrentValues[nDepth] );
552cdf0e10cSrcweir 
553cdf0e10cSrcweir     if( !isWithinOuterBorder( m_pfCurrentValues[nDepth] ) )
554cdf0e10cSrcweir         return NULL;
555cdf0e10cSrcweir 
556cdf0e10cSrcweir     return &m_pfCurrentValues[nDepth];
557cdf0e10cSrcweir }
558cdf0e10cSrcweir 
isWithinOuterBorder(double fScaledValue) const559cdf0e10cSrcweir bool TickmarkHelper::isWithinOuterBorder( double fScaledValue ) const
560cdf0e10cSrcweir {
561cdf0e10cSrcweir     if(fScaledValue>m_fOuterMajorTickBorderMax_Scaled)
562cdf0e10cSrcweir         return false;
563cdf0e10cSrcweir     if(fScaledValue<m_fOuterMajorTickBorderMin_Scaled)
564cdf0e10cSrcweir         return false;
565cdf0e10cSrcweir 
566cdf0e10cSrcweir     return true;
567cdf0e10cSrcweir }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 
isVisible(double fScaledValue) const570cdf0e10cSrcweir bool TickmarkHelper::isVisible( double fScaledValue ) const
571cdf0e10cSrcweir {
572cdf0e10cSrcweir     if(fScaledValue>m_fScaledVisibleMax)
573cdf0e10cSrcweir     {
574cdf0e10cSrcweir         if( !approxEqual(fScaledValue,m_fScaledVisibleMax) )
575cdf0e10cSrcweir             return false;
576cdf0e10cSrcweir     }
577cdf0e10cSrcweir     if(fScaledValue<m_fScaledVisibleMin)
578cdf0e10cSrcweir     {
579cdf0e10cSrcweir         if( !approxEqual(fScaledValue,m_fScaledVisibleMin) )
580cdf0e10cSrcweir             return false;
581cdf0e10cSrcweir     }
582cdf0e10cSrcweir     return true;
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
getAllTicks(::std::vector<::std::vector<TickInfo>> & rAllTickInfos) const585cdf0e10cSrcweir void TickmarkHelper::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
586cdf0e10cSrcweir {
587cdf0e10cSrcweir     uno::Sequence< uno::Sequence< double > > aAllTicks;
588cdf0e10cSrcweir 
589cdf0e10cSrcweir     //create point sequences for each tick depth
590cdf0e10cSrcweir     sal_Int32 nDepthCount = this->getTickDepth();
591cdf0e10cSrcweir     sal_Int32 nMaxMajorTickCount = this->getMaxTickCount( 0 );
592cdf0e10cSrcweir 
593cdf0e10cSrcweir     aAllTicks.realloc(nDepthCount);
594cdf0e10cSrcweir     aAllTicks[0].realloc(nMaxMajorTickCount);
595cdf0e10cSrcweir 
596cdf0e10cSrcweir     sal_Int32 nRealMajorTickCount = 0;
597cdf0e10cSrcweir     double* pValue = NULL;
598cdf0e10cSrcweir     for( sal_Int32 nMajorTick=0; nMajorTick<nMaxMajorTickCount; nMajorTick++ )
599cdf0e10cSrcweir     {
600cdf0e10cSrcweir         pValue = this->getMajorTick( nMajorTick );
601cdf0e10cSrcweir         if(!pValue)
602cdf0e10cSrcweir             continue;
603cdf0e10cSrcweir         aAllTicks[0][nRealMajorTickCount] = *pValue;
604cdf0e10cSrcweir         nRealMajorTickCount++;
605cdf0e10cSrcweir     }
606cdf0e10cSrcweir     if(!nRealMajorTickCount)
607cdf0e10cSrcweir         return;
608cdf0e10cSrcweir     aAllTicks[0].realloc(nRealMajorTickCount);
609cdf0e10cSrcweir 
610cdf0e10cSrcweir     if(nDepthCount>0)
611cdf0e10cSrcweir         this->addSubTicks( 1, aAllTicks );
612cdf0e10cSrcweir 
613cdf0e10cSrcweir     //so far we have added all ticks between the outer major tick marks
614cdf0e10cSrcweir     //this was necessary to create sub ticks correctly
615cdf0e10cSrcweir     //now we reduce all ticks to the visible ones that lie between the real borders
616cdf0e10cSrcweir     sal_Int32 nDepth = 0;
617cdf0e10cSrcweir     sal_Int32 nTick = 0;
618cdf0e10cSrcweir     for( nDepth = 0; nDepth < nDepthCount; nDepth++)
619cdf0e10cSrcweir     {
620cdf0e10cSrcweir         sal_Int32 nInvisibleAtLowerBorder = 0;
621cdf0e10cSrcweir         sal_Int32 nInvisibleAtUpperBorder = 0;
622cdf0e10cSrcweir         //we need only to check all ticks within the first major interval at each border
623cdf0e10cSrcweir         sal_Int32 nCheckCount = 1;
624cdf0e10cSrcweir         for(sal_Int32 nN=0; nN<nDepth; nN++)
625cdf0e10cSrcweir         {
626cdf0e10cSrcweir             if( m_rIncrement.SubIncrements[nN].IntervalCount>1 )
627cdf0e10cSrcweir                 nCheckCount *= m_rIncrement.SubIncrements[nN].IntervalCount;
628cdf0e10cSrcweir         }
629cdf0e10cSrcweir         uno::Sequence< double >& rTicks = aAllTicks[nDepth];
630cdf0e10cSrcweir         sal_Int32 nCount = rTicks.getLength();
631cdf0e10cSrcweir         //check lower border
632cdf0e10cSrcweir         for( nTick=0; nTick<nCheckCount && nTick<nCount; nTick++)
633cdf0e10cSrcweir         {
634cdf0e10cSrcweir             if( !isVisible( rTicks[nTick] ) )
635cdf0e10cSrcweir                 nInvisibleAtLowerBorder++;
636cdf0e10cSrcweir         }
637cdf0e10cSrcweir         //check upper border
638cdf0e10cSrcweir         for( nTick=nCount-1; nTick>nCount-1-nCheckCount && nTick>=0; nTick--)
639cdf0e10cSrcweir         {
640cdf0e10cSrcweir             if( !isVisible( rTicks[nTick] ) )
641cdf0e10cSrcweir                 nInvisibleAtUpperBorder++;
642cdf0e10cSrcweir         }
643cdf0e10cSrcweir         //resize sequence
644cdf0e10cSrcweir         if( !nInvisibleAtLowerBorder && !nInvisibleAtUpperBorder)
645cdf0e10cSrcweir             continue;
646cdf0e10cSrcweir         if( !nInvisibleAtLowerBorder )
647cdf0e10cSrcweir             rTicks.realloc(nCount-nInvisibleAtUpperBorder);
648cdf0e10cSrcweir         else
649cdf0e10cSrcweir         {
650cdf0e10cSrcweir             sal_Int32 nNewCount = nCount-nInvisibleAtUpperBorder-nInvisibleAtLowerBorder;
651cdf0e10cSrcweir             if(nNewCount<0)
652cdf0e10cSrcweir                 nNewCount=0;
653cdf0e10cSrcweir 
654cdf0e10cSrcweir             uno::Sequence< double > aOldTicks(rTicks);
655cdf0e10cSrcweir             rTicks.realloc(nNewCount);
656cdf0e10cSrcweir             for(nTick = 0; nTick<nNewCount; nTick++)
657cdf0e10cSrcweir                 rTicks[nTick] = aOldTicks[nInvisibleAtLowerBorder+nTick];
658cdf0e10cSrcweir         }
659cdf0e10cSrcweir     }
660cdf0e10cSrcweir 
661cdf0e10cSrcweir     //fill return value
662cdf0e10cSrcweir     rAllTickInfos.resize(aAllTicks.getLength());
663cdf0e10cSrcweir     for( nDepth=0 ;nDepth<aAllTicks.getLength(); nDepth++ )
664cdf0e10cSrcweir     {
665cdf0e10cSrcweir         sal_Int32 nCount = aAllTicks[nDepth].getLength();
666cdf0e10cSrcweir         rAllTickInfos[nDepth].resize( nCount );
667cdf0e10cSrcweir         for(sal_Int32 nN = 0; nN<nCount; nN++)
668cdf0e10cSrcweir         {
669cdf0e10cSrcweir             rAllTickInfos[nDepth][nN].fScaledTickValue = aAllTicks[nDepth][nN];
670cdf0e10cSrcweir         }
671cdf0e10cSrcweir     }
672cdf0e10cSrcweir }
673cdf0e10cSrcweir 
getAllTicksShifted(::std::vector<::std::vector<TickInfo>> & rAllTickInfos) const674cdf0e10cSrcweir void TickmarkHelper::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
675cdf0e10cSrcweir {
676cdf0e10cSrcweir     std::auto_ptr< TickmarkHelper > apShiftedTickmarkHelper( createShiftedTickmarkHelper() );
677cdf0e10cSrcweir     apShiftedTickmarkHelper->getAllTicks( rAllTickInfos );
678cdf0e10cSrcweir }
679cdf0e10cSrcweir 
addSubTicks(sal_Int32 nDepth,uno::Sequence<uno::Sequence<double>> & rParentTicks) const680cdf0e10cSrcweir void TickmarkHelper::addSubTicks( sal_Int32 nDepth, uno::Sequence< uno::Sequence< double > >& rParentTicks ) const
681cdf0e10cSrcweir {
682cdf0e10cSrcweir     EquidistantTickIter aIter( rParentTicks, m_rIncrement, 0, nDepth-1 );
683cdf0e10cSrcweir     double* pfNextParentTick = aIter.firstValue();
684cdf0e10cSrcweir     if(!pfNextParentTick)
685cdf0e10cSrcweir         return;
686cdf0e10cSrcweir     double fLastParentTick = *pfNextParentTick;
687cdf0e10cSrcweir     pfNextParentTick = aIter.nextValue();
688cdf0e10cSrcweir     if(!pfNextParentTick)
689cdf0e10cSrcweir         return;
690cdf0e10cSrcweir 
691cdf0e10cSrcweir     sal_Int32 nMaxSubTickCount = this->getMaxTickCount( nDepth );
692cdf0e10cSrcweir     if(!nMaxSubTickCount)
693cdf0e10cSrcweir         return;
694cdf0e10cSrcweir 
695cdf0e10cSrcweir     uno::Sequence< double > aSubTicks(nMaxSubTickCount);
696cdf0e10cSrcweir     sal_Int32 nRealSubTickCount = 0;
697cdf0e10cSrcweir     sal_Int32 nIntervalCount = m_rIncrement.SubIncrements[nDepth-1].IntervalCount;
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     double* pValue = NULL;
700cdf0e10cSrcweir     for(; pfNextParentTick; fLastParentTick=*pfNextParentTick, pfNextParentTick = aIter.nextValue())
701cdf0e10cSrcweir     {
702cdf0e10cSrcweir         for( sal_Int32 nPartTick = 1; nPartTick<nIntervalCount; nPartTick++ )
703cdf0e10cSrcweir         {
704cdf0e10cSrcweir             pValue = this->getMinorTick( nPartTick, nDepth
705cdf0e10cSrcweir                         , fLastParentTick, *pfNextParentTick );
706cdf0e10cSrcweir             if(!pValue)
707cdf0e10cSrcweir                 continue;
708cdf0e10cSrcweir 
709cdf0e10cSrcweir             aSubTicks[nRealSubTickCount] = *pValue;
710cdf0e10cSrcweir             nRealSubTickCount++;
711cdf0e10cSrcweir         }
712cdf0e10cSrcweir     }
713cdf0e10cSrcweir 
714cdf0e10cSrcweir     aSubTicks.realloc(nRealSubTickCount);
715cdf0e10cSrcweir     rParentTicks[nDepth] = aSubTicks;
716cdf0e10cSrcweir     if(m_rIncrement.SubIncrements.getLength()>nDepth)
717cdf0e10cSrcweir         addSubTicks( nDepth+1, rParentTicks );
718cdf0e10cSrcweir }
719cdf0e10cSrcweir 
720cdf0e10cSrcweir //-----------------------------------------------------------------------------
721cdf0e10cSrcweir // ___TickmarkHelper_2D___
722cdf0e10cSrcweir //-----------------------------------------------------------------------------
TickmarkHelper_2D(const ExplicitScaleData & rScale,const ExplicitIncrementData & rIncrement,const B2DVector & rStartScreenPos,const B2DVector & rEndScreenPos,const B2DVector & rAxisLineToLabelLineShift)723cdf0e10cSrcweir TickmarkHelper_2D::TickmarkHelper_2D(
724cdf0e10cSrcweir           const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
725cdf0e10cSrcweir           //, double fStrech_SceneToScreen, double fOffset_SceneToScreen )
726cdf0e10cSrcweir           , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
727cdf0e10cSrcweir           , const B2DVector& rAxisLineToLabelLineShift )
728cdf0e10cSrcweir           : TickmarkHelper( rScale, rIncrement )
729cdf0e10cSrcweir           , m_aAxisStartScreenPosition2D(rStartScreenPos)
730cdf0e10cSrcweir           , m_aAxisEndScreenPosition2D(rEndScreenPos)
731cdf0e10cSrcweir           , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
732cdf0e10cSrcweir           , m_fStrech_LogicToScreen(1.0)
733cdf0e10cSrcweir           , m_fOffset_LogicToScreen(0.0)
734cdf0e10cSrcweir {
735cdf0e10cSrcweir     double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
736cdf0e10cSrcweir     if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation )
737cdf0e10cSrcweir     {
738cdf0e10cSrcweir         m_fStrech_LogicToScreen = 1.0/fWidthY;
739cdf0e10cSrcweir         m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
740cdf0e10cSrcweir     }
741cdf0e10cSrcweir     else
742cdf0e10cSrcweir     {
743cdf0e10cSrcweir         B2DVector aSwap(m_aAxisStartScreenPosition2D);
744cdf0e10cSrcweir         m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
745cdf0e10cSrcweir         m_aAxisEndScreenPosition2D = aSwap;
746cdf0e10cSrcweir 
747cdf0e10cSrcweir         m_fStrech_LogicToScreen = -1.0/fWidthY;
748cdf0e10cSrcweir         m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
749cdf0e10cSrcweir     }
750cdf0e10cSrcweir }
751cdf0e10cSrcweir 
createShiftedTickmarkHelper() const752cdf0e10cSrcweir TickmarkHelper* TickmarkHelper_2D::createShiftedTickmarkHelper() const
753cdf0e10cSrcweir {
754cdf0e10cSrcweir     ExplicitIncrementData aShiftedIncrement( m_rIncrement );
755cdf0e10cSrcweir     aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
756cdf0e10cSrcweir 
757cdf0e10cSrcweir     ::basegfx::B2DVector aStart( m_aAxisStartScreenPosition2D );
758cdf0e10cSrcweir     ::basegfx::B2DVector aEnd( m_aAxisEndScreenPosition2D );
759cdf0e10cSrcweir     if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation )
760cdf0e10cSrcweir         std::swap( aStart, aEnd );
761cdf0e10cSrcweir 
762cdf0e10cSrcweir     return new TickmarkHelper_2D( m_rScale, aShiftedIncrement, aStart, aEnd, m_aAxisLineToLabelLineShift );
763cdf0e10cSrcweir }
764cdf0e10cSrcweir 
~TickmarkHelper_2D()765cdf0e10cSrcweir TickmarkHelper_2D::~TickmarkHelper_2D()
766cdf0e10cSrcweir {
767cdf0e10cSrcweir }
768cdf0e10cSrcweir 
isHorizontalAxis() const769cdf0e10cSrcweir bool TickmarkHelper_2D::isHorizontalAxis() const
770cdf0e10cSrcweir {
771cdf0e10cSrcweir     return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() );
772cdf0e10cSrcweir }
isVerticalAxis() const773cdf0e10cSrcweir bool TickmarkHelper_2D::isVerticalAxis() const
774cdf0e10cSrcweir {
775cdf0e10cSrcweir     return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() );
776cdf0e10cSrcweir }
777cdf0e10cSrcweir 
getTickScreenDistance(TickIter & rIter)778cdf0e10cSrcweir sal_Int32 TickmarkHelper_2D::getTickScreenDistance( TickIter& rIter )
779cdf0e10cSrcweir {
780cdf0e10cSrcweir     //return the positive distance between the two first tickmarks in screen values
781cdf0e10cSrcweir     //if there are less than two tickmarks -1 is returned
782cdf0e10cSrcweir 
783cdf0e10cSrcweir     const TickInfo* pFirstTickInfo = rIter.firstInfo();
784cdf0e10cSrcweir     const TickInfo* pSecondTickInfo = rIter.nextInfo();
785cdf0e10cSrcweir     if(!pSecondTickInfo  || !pFirstTickInfo)
786cdf0e10cSrcweir         return -1;
787cdf0e10cSrcweir 
788cdf0e10cSrcweir     return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
789cdf0e10cSrcweir }
790cdf0e10cSrcweir 
getTickScreenPosition2D(double fScaledLogicTickValue) const791cdf0e10cSrcweir B2DVector TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
792cdf0e10cSrcweir {
793cdf0e10cSrcweir     B2DVector aRet(m_aAxisStartScreenPosition2D);
794cdf0e10cSrcweir     aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
795cdf0e10cSrcweir                 *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen);
796cdf0e10cSrcweir     return aRet;
797cdf0e10cSrcweir }
798cdf0e10cSrcweir 
addPointSequenceForTickLine(drawing::PointSequenceSequence & rPoints,sal_Int32 nSequenceIndex,double fScaledLogicTickValue,double fInnerDirectionSign,const TickmarkProperties & rTickmarkProperties,bool bPlaceAtLabels) const799cdf0e10cSrcweir void TickmarkHelper_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
800cdf0e10cSrcweir                                 , sal_Int32 nSequenceIndex
801cdf0e10cSrcweir                                 , double fScaledLogicTickValue, double fInnerDirectionSign
802cdf0e10cSrcweir                                 , const TickmarkProperties& rTickmarkProperties
803cdf0e10cSrcweir                                 , bool bPlaceAtLabels ) const
804cdf0e10cSrcweir {
805cdf0e10cSrcweir     if( fInnerDirectionSign==0.0 )
806cdf0e10cSrcweir         fInnerDirectionSign = 1.0;
807cdf0e10cSrcweir 
808cdf0e10cSrcweir     B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue);
809cdf0e10cSrcweir     if( bPlaceAtLabels )
810cdf0e10cSrcweir         aTickScreenPosition += m_aAxisLineToLabelLineShift;
811cdf0e10cSrcweir 
812cdf0e10cSrcweir     B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
813cdf0e10cSrcweir     aMainDirection.normalize();
814cdf0e10cSrcweir     B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
815cdf0e10cSrcweir     aOrthoDirection *= fInnerDirectionSign;
816cdf0e10cSrcweir     aOrthoDirection.normalize();
817cdf0e10cSrcweir 
818cdf0e10cSrcweir     B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
819cdf0e10cSrcweir     B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
820cdf0e10cSrcweir 
821cdf0e10cSrcweir     rPoints[nSequenceIndex].realloc(2);
822cdf0e10cSrcweir     rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX());
823cdf0e10cSrcweir     rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY());
824cdf0e10cSrcweir     rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX());
825cdf0e10cSrcweir     rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY());
826cdf0e10cSrcweir }
827cdf0e10cSrcweir 
getDistanceAxisTickToText(const AxisProperties & rAxisProperties,bool bIncludeFarAwayDistanceIfSo,bool bIncludeSpaceBetweenTickAndText) const828cdf0e10cSrcweir B2DVector TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
829cdf0e10cSrcweir {
830cdf0e10cSrcweir     bool bFarAwayLabels = false;
831cdf0e10cSrcweir     if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos
832cdf0e10cSrcweir         || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos )
833cdf0e10cSrcweir         bFarAwayLabels = true;
834cdf0e10cSrcweir 
835cdf0e10cSrcweir     double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign;
836cdf0e10cSrcweir     if( fInnerDirectionSign==0.0 )
837cdf0e10cSrcweir         fInnerDirectionSign = 1.0;
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
840cdf0e10cSrcweir     aMainDirection.normalize();
841cdf0e10cSrcweir     B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
842cdf0e10cSrcweir     aOrthoDirection *= fInnerDirectionSign;
843cdf0e10cSrcweir     aOrthoDirection.normalize();
844cdf0e10cSrcweir 
845cdf0e10cSrcweir     B2DVector aStart(0,0), aEnd(0,0);
846cdf0e10cSrcweir     if( bFarAwayLabels )
847cdf0e10cSrcweir     {
848cdf0e10cSrcweir         TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
849cdf0e10cSrcweir         aStart = aOrthoDirection*aProps.RelativePos;
850cdf0e10cSrcweir         aEnd = aStart - aOrthoDirection*aProps.Length;
851cdf0e10cSrcweir     }
852cdf0e10cSrcweir     else
853cdf0e10cSrcweir     {
854cdf0e10cSrcweir         for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
855cdf0e10cSrcweir         {
856cdf0e10cSrcweir             const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
857cdf0e10cSrcweir             B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
858cdf0e10cSrcweir             B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
859cdf0e10cSrcweir             if(aNewStart.getLength()>aStart.getLength())
860cdf0e10cSrcweir                 aStart=aNewStart;
861cdf0e10cSrcweir             if(aNewEnd.getLength()>aEnd.getLength())
862cdf0e10cSrcweir                 aEnd=aNewEnd;
863cdf0e10cSrcweir         }
864cdf0e10cSrcweir     }
865cdf0e10cSrcweir 
866cdf0e10cSrcweir     B2DVector aLabelDirection(aStart);
867cdf0e10cSrcweir     if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
868cdf0e10cSrcweir         aLabelDirection = aEnd;
869cdf0e10cSrcweir 
870cdf0e10cSrcweir     B2DVector aOrthoLabelDirection(aOrthoDirection);
871cdf0e10cSrcweir     if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
872cdf0e10cSrcweir         aOrthoLabelDirection*=-1.0;
873cdf0e10cSrcweir     aOrthoLabelDirection.normalize();
874cdf0e10cSrcweir     if( bIncludeSpaceBetweenTickAndText )
875cdf0e10cSrcweir         aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
876cdf0e10cSrcweir     if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
877cdf0e10cSrcweir         aLabelDirection += m_aAxisLineToLabelLineShift;
878cdf0e10cSrcweir     return aLabelDirection;
879cdf0e10cSrcweir }
880cdf0e10cSrcweir 
createPointSequenceForAxisMainLine(drawing::PointSequenceSequence & rPoints) const881cdf0e10cSrcweir void TickmarkHelper_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
882cdf0e10cSrcweir {
883cdf0e10cSrcweir     rPoints[0].realloc(2);
884cdf0e10cSrcweir     rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX());
885cdf0e10cSrcweir     rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY());
886cdf0e10cSrcweir     rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX());
887cdf0e10cSrcweir     rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY());
888cdf0e10cSrcweir }
889cdf0e10cSrcweir 
updateScreenValues(::std::vector<::std::vector<TickInfo>> & rAllTickInfos) const890cdf0e10cSrcweir void TickmarkHelper_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
891cdf0e10cSrcweir {
892cdf0e10cSrcweir     //get the transformed screen values for all tickmarks in rAllTickInfos
893cdf0e10cSrcweir     ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter       = rAllTickInfos.begin();
894cdf0e10cSrcweir     const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd  = rAllTickInfos.end();
895cdf0e10cSrcweir     for( ; aDepthIter != aDepthEnd; aDepthIter++ )
896cdf0e10cSrcweir     {
897cdf0e10cSrcweir         ::std::vector< TickInfo >::iterator       aTickIter = (*aDepthIter).begin();
898cdf0e10cSrcweir         const ::std::vector< TickInfo >::const_iterator aTickEnd  = (*aDepthIter).end();
899cdf0e10cSrcweir         for( ; aTickIter != aTickEnd; aTickIter++ )
900cdf0e10cSrcweir         {
901cdf0e10cSrcweir             TickInfo& rTickInfo = (*aTickIter);
902cdf0e10cSrcweir             rTickInfo.aTickScreenPosition =
903cdf0e10cSrcweir                 this->getTickScreenPosition2D( rTickInfo.fScaledTickValue );
904cdf0e10cSrcweir         }
905cdf0e10cSrcweir     }
906cdf0e10cSrcweir }
907cdf0e10cSrcweir 
908cdf0e10cSrcweir //-----------------------------------------------------------------------------
909cdf0e10cSrcweir // ___TickmarkHelper_3D___
910cdf0e10cSrcweir //-----------------------------------------------------------------------------
TickmarkHelper_3D(const ExplicitScaleData & rScale,const ExplicitIncrementData & rIncrement)911cdf0e10cSrcweir TickmarkHelper_3D::TickmarkHelper_3D(
912cdf0e10cSrcweir           const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
913cdf0e10cSrcweir           : TickmarkHelper( rScale, rIncrement )
914cdf0e10cSrcweir {
915cdf0e10cSrcweir }
916cdf0e10cSrcweir 
createShiftedTickmarkHelper() const917cdf0e10cSrcweir TickmarkHelper* TickmarkHelper_3D::createShiftedTickmarkHelper() const
918cdf0e10cSrcweir {
919cdf0e10cSrcweir     ExplicitIncrementData aShiftedIncrement( m_rIncrement );
920cdf0e10cSrcweir     aShiftedIncrement.BaseValue = m_rIncrement.BaseValue-m_rIncrement.Distance/2.0;
921cdf0e10cSrcweir     return new TickmarkHelper_3D( m_rScale, aShiftedIncrement );
922cdf0e10cSrcweir }
923cdf0e10cSrcweir 
~TickmarkHelper_3D()924cdf0e10cSrcweir TickmarkHelper_3D::~TickmarkHelper_3D()
925cdf0e10cSrcweir {
926cdf0e10cSrcweir }
927cdf0e10cSrcweir 
928cdf0e10cSrcweir //.............................................................................
929cdf0e10cSrcweir } //namespace chart
930cdf0e10cSrcweir //.............................................................................
931