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