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