1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TickmarkHelper.cxx,v $
10 * $Revision: 1.15.8.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "TickmarkHelper.hxx"
34 #include "ViewDefines.hxx"
35 #include <rtl/math.hxx>
36 #include <tools/debug.hxx>
39 //.............................................................................
42 //.............................................................................
43 using namespace ::com::sun::star
;
44 using namespace ::com::sun::star::chart2
;
45 using namespace ::rtl::math
;
46 using ::basegfx::B2DVector
;
49 : fScaledTickValue( 0.0 )
50 , fUnscaledTickValue( 0.0 )
51 , aTickScreenPosition(0.0,0.0)
57 void TickInfo::updateUnscaledValue( const uno::Reference
< XScaling
>& xInverseScaling
)
59 if( xInverseScaling
.is() )
60 this->fUnscaledTickValue
= xInverseScaling
->doScaling( this->fScaledTickValue
);
62 this->fUnscaledTickValue
= this->fScaledTickValue
;
65 TickIter::TickIter( const uno::Sequence
< uno::Sequence
< double > >& rTicks
66 , const ExplicitIncrementData
& rIncrement
67 , sal_Int32 nMinDepth
, sal_Int32 nMaxDepth
)
68 : m_pSimpleTicks(&rTicks
), m_pInfoTicks(NULL
)
69 , m_rIncrement(rIncrement
)
70 , m_nMinDepth(0), m_nMaxDepth(0)
71 , m_nTickCount(0), m_pnPositions(NULL
)
72 , m_pnPreParentCount(NULL
), m_pbIntervalFinished(NULL
)
73 , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
75 initIter( nMinDepth
, nMaxDepth
);
78 TickIter::TickIter( ::std::vector
< ::std::vector
< TickInfo
> >& rTicks
79 , const ExplicitIncrementData
& rIncrement
80 , sal_Int32 nMinDepth
, sal_Int32 nMaxDepth
)
81 : m_pSimpleTicks(NULL
), m_pInfoTicks(&rTicks
)
82 , m_rIncrement(rIncrement
)
83 , m_nMinDepth(0), m_nMaxDepth(0)
84 , m_nTickCount(0), m_pnPositions(NULL
)
85 , m_pnPreParentCount(NULL
), m_pbIntervalFinished(NULL
)
86 , m_nCurrentDepth(-1), m_nCurrentPos(-1), m_fCurrentValue( 0.0 )
88 initIter( nMinDepth
, nMaxDepth
);
91 void TickIter::initIter( sal_Int32
/*nMinDepth*/, sal_Int32 nMaxDepth
)
93 m_nMaxDepth
= nMaxDepth
;
94 if(nMaxDepth
<0 || m_nMaxDepth
>getMaxDepth())
95 m_nMaxDepth
=getMaxDepth();
98 for( nDepth
= 0; nDepth
<=m_nMaxDepth
;nDepth
++ )
99 m_nTickCount
+= getTickCount(nDepth
);
104 m_pnPositions
= new sal_Int32
[m_nMaxDepth
+1];
106 m_pnPreParentCount
= new sal_Int32
[m_nMaxDepth
+1];
107 m_pbIntervalFinished
= new bool[m_nMaxDepth
+1];
108 m_pnPreParentCount
[0] = 0;
109 m_pbIntervalFinished
[0] = false;
110 double fParentValue
= getTickValue(0,0);
111 for( nDepth
= 1; nDepth
<=m_nMaxDepth
;nDepth
++ )
113 m_pbIntervalFinished
[nDepth
] = false;
115 sal_Int32 nPreParentCount
= 0;
116 sal_Int32 nCount
= getTickCount(nDepth
);
117 for(sal_Int32 nN
= 0; nN
<nCount
; nN
++)
119 if(getTickValue(nDepth
,nN
) < fParentValue
)
124 m_pnPreParentCount
[nDepth
] = nPreParentCount
;
127 double fNextParentValue
= getTickValue(nDepth
,0);
128 if( fNextParentValue
< fParentValue
)
129 fParentValue
= fNextParentValue
;
134 TickIter::~TickIter()
136 delete[] m_pnPositions
;
137 delete[] m_pnPreParentCount
;
138 delete[] m_pbIntervalFinished
;
141 sal_Int32
TickIter::getStartDepth() const
143 //find the depth of the first visible tickmark:
144 //it is the depth of the smallest value
145 sal_Int32 nReturnDepth
=0;
146 double fMinValue
= DBL_MAX
;
147 for(sal_Int32 nDepth
= 0; nDepth
<=m_nMaxDepth
;nDepth
++ )
149 sal_Int32 nCount
= getTickCount(nDepth
);
152 double fThisValue
= getTickValue(nDepth
,0);
153 if(fThisValue
<fMinValue
)
155 nReturnDepth
= nDepth
;
156 fMinValue
= fThisValue
;
162 double* TickIter::firstValue()
166 m_fCurrentValue
= getTickValue(m_nCurrentDepth
, m_pnPositions
[m_nCurrentDepth
]);
167 return &m_fCurrentValue
;
172 TickInfo
* TickIter::firstInfo()
174 if( m_pInfoTicks
&& gotoFirst() )
175 return &(*m_pInfoTicks
)[m_nCurrentDepth
][m_pnPositions
[m_nCurrentDepth
]];
179 sal_Int32
TickIter::getIntervalCount( sal_Int32 nDepth
)
181 if(nDepth
>m_rIncrement
.SubIncrements
.getLength() || nDepth
<0)
187 return m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
;
190 bool TickIter::isAtLastPartTick()
194 sal_Int32 nIntervalCount
= getIntervalCount( m_nCurrentDepth
);
195 if(!nIntervalCount
|| nIntervalCount
== 1)
197 if( m_pbIntervalFinished
[m_nCurrentDepth
] )
199 sal_Int32 nPos
= m_pnPositions
[m_nCurrentDepth
]+1;
200 if(m_pnPreParentCount
[m_nCurrentDepth
])
201 nPos
+= nIntervalCount
-1 - m_pnPreParentCount
[m_nCurrentDepth
];
202 bool bRet
= nPos
&& nPos
% (nIntervalCount
-1) == 0;
203 if(!nPos
&& !m_pnPreParentCount
[m_nCurrentDepth
]
204 && m_pnPositions
[m_nCurrentDepth
-1]==-1 )
209 bool TickIter::gotoFirst()
216 for(sal_Int32 nDepth
= 0; nDepth
<=m_nMaxDepth
;nDepth
++ )
217 m_pnPositions
[nDepth
] = -1;
220 m_nCurrentDepth
= getStartDepth();
221 m_pnPositions
[m_nCurrentDepth
] = 0;
225 bool TickIter::gotoNext()
227 if( m_nCurrentPos
< 0 )
231 if( m_nCurrentPos
>= m_nTickCount
)
234 if( m_nCurrentDepth
==m_nMaxDepth
&& isAtLastPartTick() )
238 m_pbIntervalFinished
[m_nCurrentDepth
] = true;
241 while( m_nCurrentDepth
&& isAtLastPartTick() );
243 else if( m_nCurrentDepth
<m_nMaxDepth
)
249 while( m_nCurrentDepth
<m_nMaxDepth
);
251 m_pbIntervalFinished
[m_nCurrentDepth
] = false;
252 m_pnPositions
[m_nCurrentDepth
] = m_pnPositions
[m_nCurrentDepth
]+1;
256 bool TickIter::gotoIndex( sal_Int32 nTickIndex
)
260 if( nTickIndex
>= m_nTickCount
)
263 if( nTickIndex
< m_nCurrentPos
)
267 while( nTickIndex
> m_nCurrentPos
)
274 sal_Int32
TickIter::getCurrentIndex() const
276 return m_nCurrentPos
;
278 sal_Int32
TickIter::getMaxIndex() const
280 return m_nTickCount
-1;
283 double* TickIter::nextValue()
287 m_fCurrentValue
= getTickValue(m_nCurrentDepth
, m_pnPositions
[m_nCurrentDepth
]);
288 return &m_fCurrentValue
;
293 TickInfo
* TickIter::nextInfo()
295 if( m_pInfoTicks
&& gotoNext() &&
296 static_cast< sal_Int32
>(
297 (*m_pInfoTicks
)[m_nCurrentDepth
].size()) > m_pnPositions
[m_nCurrentDepth
] )
299 return &(*m_pInfoTicks
)[m_nCurrentDepth
][m_pnPositions
[m_nCurrentDepth
]];
304 //-----------------------------------------------------------------------------
305 //-----------------------------------------------------------------------------
306 //-----------------------------------------------------------------------------
309 double TickmarkHelper::getMinimumAtIncrement( double fMin
, const ExplicitIncrementData
& rIncrement
)
311 //the returned value will be <= fMin and on a Major Tick given by rIncrement
312 if(rIncrement
.Distance
<=0.0)
315 double fRet
= rIncrement
.BaseValue
+
316 floor( approxSub( fMin
, rIncrement
.BaseValue
)
317 / rIncrement
.Distance
)
318 *rIncrement
.Distance
;
322 if( !approxEqual(fRet
, fMin
) )
323 fRet
-= rIncrement
.Distance
;
328 double TickmarkHelper::getMaximumAtIncrement( double fMax
, const ExplicitIncrementData
& rIncrement
)
330 //the returned value will be >= fMax and on a Major Tick given by rIncrement
331 if(rIncrement
.Distance
<=0.0)
334 double fRet
= rIncrement
.BaseValue
+
335 floor( approxSub( fMax
, rIncrement
.BaseValue
)
336 / rIncrement
.Distance
)
337 *rIncrement
.Distance
;
341 if( !approxEqual(fRet
, fMax
) )
342 fRet
+= rIncrement
.Distance
;
347 //-----------------------------------------------------------------------------
348 //-----------------------------------------------------------------------------
349 //-----------------------------------------------------------------------------
351 TickmarkHelper::TickmarkHelper(
352 const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rIncrement
)
354 , m_rIncrement( rIncrement
)
355 , m_xInverseScaling(NULL
)
356 , m_pfCurrentValues(NULL
)
358 //@todo: make sure that the scale is valid for the scaling
360 m_pfCurrentValues
= new double[getTickDepth()];
362 if( m_rScale
.Scaling
.is() )
364 m_xInverseScaling
= m_rScale
.Scaling
->getInverseScaling();
365 DBG_ASSERT( m_xInverseScaling
.is(), "each Scaling needs to return a inverse Scaling" );
368 double fMin
= m_fScaledVisibleMin
= m_rScale
.Minimum
;
369 if( m_xInverseScaling
.is() )
371 m_fScaledVisibleMin
= m_rScale
.Scaling
->doScaling(m_fScaledVisibleMin
);
372 if(m_rIncrement
.PostEquidistant
)
373 fMin
= m_fScaledVisibleMin
;
376 double fMax
= m_fScaledVisibleMax
= m_rScale
.Maximum
;
377 if( m_xInverseScaling
.is() )
379 m_fScaledVisibleMax
= m_rScale
.Scaling
->doScaling(m_fScaledVisibleMax
);
380 if(m_rIncrement
.PostEquidistant
)
381 fMax
= m_fScaledVisibleMax
;
385 m_fOuterMajorTickBorderMin
= TickmarkHelper::getMinimumAtIncrement( fMin
, m_rIncrement
);
386 m_fOuterMajorTickBorderMax
= TickmarkHelper::getMaximumAtIncrement( fMax
, m_rIncrement
);
389 m_fOuterMajorTickBorderMin_Scaled
= m_fOuterMajorTickBorderMin
;
390 m_fOuterMajorTickBorderMax_Scaled
= m_fOuterMajorTickBorderMax
;
391 if(!m_rIncrement
.PostEquidistant
&& m_xInverseScaling
.is() )
393 m_fOuterMajorTickBorderMin_Scaled
= m_rScale
.Scaling
->doScaling(m_fOuterMajorTickBorderMin
);
394 m_fOuterMajorTickBorderMax_Scaled
= m_rScale
.Scaling
->doScaling(m_fOuterMajorTickBorderMax
);
396 //check validity of new range: m_fOuterMajorTickBorderMin <-> m_fOuterMajorTickBorderMax
397 //it is assumed here, that the original range in the given Scale is valid
398 if( !rtl::math::isFinite(m_fOuterMajorTickBorderMin_Scaled
) )
400 m_fOuterMajorTickBorderMin
+= m_rIncrement
.Distance
;
401 m_fOuterMajorTickBorderMin_Scaled
= m_rScale
.Scaling
->doScaling(m_fOuterMajorTickBorderMin
);
403 if( !rtl::math::isFinite(m_fOuterMajorTickBorderMax_Scaled
) )
405 m_fOuterMajorTickBorderMax
-= m_rIncrement
.Distance
;
406 m_fOuterMajorTickBorderMax_Scaled
= m_rScale
.Scaling
->doScaling(m_fOuterMajorTickBorderMax
);
411 TickmarkHelper
* TickmarkHelper::createShiftedTickmarkHelper() const
413 ExplicitIncrementData
aShiftedIncrement( m_rIncrement
);
414 aShiftedIncrement
.BaseValue
= m_rIncrement
.BaseValue
-m_rIncrement
.Distance
/2.0;
415 return new TickmarkHelper( m_rScale
, aShiftedIncrement
);
418 TickmarkHelper::~TickmarkHelper()
420 delete[] m_pfCurrentValues
;
423 sal_Int32
TickmarkHelper::getTickDepth() const
425 return m_rIncrement
.SubIncrements
.getLength() + 1;
428 sal_Int32
TickmarkHelper::getMaxTickCount( sal_Int32 nDepth
) const
430 //return the maximum amount of ticks
431 //possibly open intervals at the two ends of the region are handled as if they were completely visible
432 //(this is necessary for calculating the sub ticks at the borders correctly)
434 if( nDepth
>= getTickDepth() )
436 if( m_fOuterMajorTickBorderMax
< m_fOuterMajorTickBorderMin
)
438 if( m_rIncrement
.Distance
<=0.0)
441 sal_Int32 nIntervalCount
;
442 if(m_rIncrement
.PostEquidistant
)
443 nIntervalCount
= static_cast<sal_Int32
>
444 ( approxSub( m_fScaledVisibleMax
, m_fScaledVisibleMin
)
445 / m_rIncrement
.Distance
);
447 nIntervalCount
= static_cast<sal_Int32
>
448 ( approxSub( m_rScale
.Maximum
, m_rScale
.Minimum
)
449 / m_rIncrement
.Distance
);
451 for(sal_Int32 nN
=0; nN
<nDepth
-1; nN
++)
453 if( m_rIncrement
.SubIncrements
[nN
].IntervalCount
>1 )
454 nIntervalCount
*= m_rIncrement
.SubIncrements
[nN
].IntervalCount
;
457 sal_Int32 nTickCount
= nIntervalCount
;
458 if(nDepth
>0 && m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
>1)
459 nTickCount
= nIntervalCount
* (m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
-1);
464 double* TickmarkHelper::getMajorTick( sal_Int32 nTick
) const
466 m_pfCurrentValues
[0] = m_fOuterMajorTickBorderMin
+ nTick
*m_rIncrement
.Distance
;
468 if(m_pfCurrentValues
[0]>m_fOuterMajorTickBorderMax
)
470 if( !approxEqual(m_pfCurrentValues
[0],m_fOuterMajorTickBorderMax
) )
473 if(m_pfCurrentValues
[0]<m_fOuterMajorTickBorderMin
)
475 if( !approxEqual(m_pfCurrentValues
[0],m_fOuterMajorTickBorderMin
) )
479 //return always the value after scaling
480 if(!m_rIncrement
.PostEquidistant
&& m_xInverseScaling
.is() )
481 m_pfCurrentValues
[0] = m_rScale
.Scaling
->doScaling( m_pfCurrentValues
[0] );
483 return &m_pfCurrentValues
[0];
486 double* TickmarkHelper::getMinorTick( sal_Int32 nTick
, sal_Int32 nDepth
487 , double fStartParentTick
, double fNextParentTick
) const
489 //check validity of arguments
491 //DBG_ASSERT( fStartParentTick < fNextParentTick, "fStartParentTick >= fNextParentTick");
492 if(fStartParentTick
>= fNextParentTick
)
494 if(nDepth
>m_rIncrement
.SubIncrements
.getLength() || nDepth
<=0)
497 //subticks are only calculated if they are laying between parent ticks:
500 if(nTick
>=m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
)
504 bool bPostEquidistant
= m_rIncrement
.SubIncrements
[nDepth
-1].PostEquidistant
;
506 double fAdaptedStartParent
= fStartParentTick
;
507 double fAdaptedNextParent
= fNextParentTick
;
509 if( !bPostEquidistant
&& m_xInverseScaling
.is() )
511 fAdaptedStartParent
= m_xInverseScaling
->doScaling(fStartParentTick
);
512 fAdaptedNextParent
= m_xInverseScaling
->doScaling(fNextParentTick
);
515 double fDistance
= (fAdaptedNextParent
- fAdaptedStartParent
)/m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
;
517 m_pfCurrentValues
[nDepth
] = fAdaptedStartParent
+ nTick
*fDistance
;
519 //return always the value after scaling
520 if(!bPostEquidistant
&& m_xInverseScaling
.is() )
521 m_pfCurrentValues
[nDepth
] = m_rScale
.Scaling
->doScaling( m_pfCurrentValues
[nDepth
] );
523 if( !isWithinOuterBorder( m_pfCurrentValues
[nDepth
] ) )
526 return &m_pfCurrentValues
[nDepth
];
529 bool TickmarkHelper::isWithinOuterBorder( double fScaledValue
) const
531 if(fScaledValue
>m_fOuterMajorTickBorderMax_Scaled
)
533 if(fScaledValue
<m_fOuterMajorTickBorderMin_Scaled
)
540 bool TickmarkHelper::isVisible( double fScaledValue
) const
542 if(fScaledValue
>m_fScaledVisibleMax
)
544 if( !approxEqual(fScaledValue
,m_fScaledVisibleMax
) )
547 if(fScaledValue
<m_fScaledVisibleMin
)
549 if( !approxEqual(fScaledValue
,m_fScaledVisibleMin
) )
555 void TickmarkHelper::getAllTicks( ::std::vector
< ::std::vector
< TickInfo
> >& rAllTickInfos
) const
557 uno::Sequence
< uno::Sequence
< double > > aAllTicks
;
559 //create point sequences for each tick depth
560 sal_Int32 nDepthCount
= this->getTickDepth();
561 sal_Int32 nMaxMajorTickCount
= this->getMaxTickCount( 0 );
563 aAllTicks
.realloc(nDepthCount
);
564 aAllTicks
[0].realloc(nMaxMajorTickCount
);
566 sal_Int32 nRealMajorTickCount
= 0;
567 double* pValue
= NULL
;
568 for( sal_Int32 nMajorTick
=0; nMajorTick
<nMaxMajorTickCount
; nMajorTick
++ )
570 pValue
= this->getMajorTick( nMajorTick
);
573 aAllTicks
[0][nRealMajorTickCount
] = *pValue
;
574 nRealMajorTickCount
++;
576 if(!nRealMajorTickCount
)
578 aAllTicks
[0].realloc(nRealMajorTickCount
);
581 this->addSubTicks( 1, aAllTicks
);
583 //so far we have added all ticks between the outer major tick marks
584 //this was necessary to create sub ticks correctly
585 //now we reduce all ticks to the visible ones that lie between the real borders
586 sal_Int32 nDepth
= 0;
588 for( nDepth
= 0; nDepth
< nDepthCount
; nDepth
++)
590 sal_Int32 nInvisibleAtLowerBorder
= 0;
591 sal_Int32 nInvisibleAtUpperBorder
= 0;
592 //we need only to check all ticks within the first major interval at each border
593 sal_Int32 nCheckCount
= 1;
594 for(sal_Int32 nN
=0; nN
<nDepth
; nN
++)
596 if( m_rIncrement
.SubIncrements
[nN
].IntervalCount
>1 )
597 nCheckCount
*= m_rIncrement
.SubIncrements
[nN
].IntervalCount
;
599 uno::Sequence
< double >& rTicks
= aAllTicks
[nDepth
];
600 sal_Int32 nCount
= rTicks
.getLength();
602 for( nTick
=0; nTick
<nCheckCount
&& nTick
<nCount
; nTick
++)
604 if( !isVisible( rTicks
[nTick
] ) )
605 nInvisibleAtLowerBorder
++;
608 for( nTick
=nCount
-1; nTick
>nCount
-1-nCheckCount
&& nTick
>=0; nTick
--)
610 if( !isVisible( rTicks
[nTick
] ) )
611 nInvisibleAtUpperBorder
++;
614 if( !nInvisibleAtLowerBorder
&& !nInvisibleAtUpperBorder
)
616 if( !nInvisibleAtLowerBorder
)
617 rTicks
.realloc(nCount
-nInvisibleAtUpperBorder
);
620 sal_Int32 nNewCount
= nCount
-nInvisibleAtUpperBorder
-nInvisibleAtLowerBorder
;
624 uno::Sequence
< double > aOldTicks(rTicks
);
625 rTicks
.realloc(nNewCount
);
626 for(nTick
= 0; nTick
<nNewCount
; nTick
++)
627 rTicks
[nTick
] = aOldTicks
[nInvisibleAtLowerBorder
+nTick
];
632 rAllTickInfos
.resize(aAllTicks
.getLength());
633 for( nDepth
=0 ;nDepth
<aAllTicks
.getLength(); nDepth
++ )
635 sal_Int32 nCount
= aAllTicks
[nDepth
].getLength();
636 rAllTickInfos
[nDepth
].resize( nCount
);
637 for(sal_Int32 nN
= 0; nN
<nCount
; nN
++)
639 rAllTickInfos
[nDepth
][nN
].fScaledTickValue
= aAllTicks
[nDepth
][nN
];
644 void TickmarkHelper::getAllTicksShifted( ::std::vector
< ::std::vector
< TickInfo
> >& rAllTickInfos
) const
646 std::auto_ptr
< TickmarkHelper
> apShiftedTickmarkHelper( createShiftedTickmarkHelper() );
647 apShiftedTickmarkHelper
->getAllTicks( rAllTickInfos
);
650 void TickmarkHelper::addSubTicks( sal_Int32 nDepth
, uno::Sequence
< uno::Sequence
< double > >& rParentTicks
) const
652 TickIter
aIter( rParentTicks
, m_rIncrement
, 0, nDepth
-1 );
653 double* pfNextParentTick
= aIter
.firstValue();
654 if(!pfNextParentTick
)
656 double fLastParentTick
= *pfNextParentTick
;
657 pfNextParentTick
= aIter
.nextValue();
658 if(!pfNextParentTick
)
661 sal_Int32 nMaxSubTickCount
= this->getMaxTickCount( nDepth
);
662 if(!nMaxSubTickCount
)
665 uno::Sequence
< double > aSubTicks(nMaxSubTickCount
);
666 sal_Int32 nRealSubTickCount
= 0;
667 sal_Int32 nIntervalCount
= m_rIncrement
.SubIncrements
[nDepth
-1].IntervalCount
;
669 double* pValue
= NULL
;
670 for(; pfNextParentTick
; fLastParentTick
=*pfNextParentTick
, pfNextParentTick
= aIter
.nextValue())
672 for( sal_Int32 nPartTick
= 1; nPartTick
<nIntervalCount
; nPartTick
++ )
674 pValue
= this->getMinorTick( nPartTick
, nDepth
675 , fLastParentTick
, *pfNextParentTick
);
679 aSubTicks
[nRealSubTickCount
] = *pValue
;
684 aSubTicks
.realloc(nRealSubTickCount
);
685 rParentTicks
[nDepth
] = aSubTicks
;
686 if(m_rIncrement
.SubIncrements
.getLength()>nDepth
)
687 addSubTicks( nDepth
+1, rParentTicks
);
690 //-----------------------------------------------------------------------------
691 // ___TickmarkHelper_2D___
692 //-----------------------------------------------------------------------------
693 TickmarkHelper_2D::TickmarkHelper_2D(
694 const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rIncrement
695 //, double fStrech_SceneToScreen, double fOffset_SceneToScreen )
696 , const B2DVector
& rStartScreenPos
, const B2DVector
& rEndScreenPos
697 , const B2DVector
& rAxisLineToLabelLineShift
)
698 : TickmarkHelper( rScale
, rIncrement
)
699 , m_aAxisStartScreenPosition2D(rStartScreenPos
)
700 , m_aAxisEndScreenPosition2D(rEndScreenPos
)
701 , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift
)
702 , m_fStrech_LogicToScreen(1.0)
703 , m_fOffset_LogicToScreen(0.0)
705 double fWidthY
= m_fScaledVisibleMax
- m_fScaledVisibleMin
;
706 if( AxisOrientation_MATHEMATICAL
==m_rScale
.Orientation
)
708 m_fStrech_LogicToScreen
= 1.0/fWidthY
;
709 m_fOffset_LogicToScreen
= -m_fScaledVisibleMin
;
713 B2DVector
aSwap(m_aAxisStartScreenPosition2D
);
714 m_aAxisStartScreenPosition2D
= m_aAxisEndScreenPosition2D
;
715 m_aAxisEndScreenPosition2D
= aSwap
;
717 m_fStrech_LogicToScreen
= -1.0/fWidthY
;
718 m_fOffset_LogicToScreen
= -m_fScaledVisibleMax
;
722 TickmarkHelper
* TickmarkHelper_2D::createShiftedTickmarkHelper() const
724 ExplicitIncrementData
aShiftedIncrement( m_rIncrement
);
725 aShiftedIncrement
.BaseValue
= m_rIncrement
.BaseValue
-m_rIncrement
.Distance
/2.0;
727 ::basegfx::B2DVector
aStart( m_aAxisStartScreenPosition2D
);
728 ::basegfx::B2DVector
aEnd( m_aAxisEndScreenPosition2D
);
729 if( AxisOrientation_MATHEMATICAL
==m_rScale
.Orientation
)
730 std::swap( aStart
, aEnd
);
732 return new TickmarkHelper_2D( m_rScale
, aShiftedIncrement
, aStart
, aEnd
, m_aAxisLineToLabelLineShift
);
735 TickmarkHelper_2D::~TickmarkHelper_2D()
739 bool TickmarkHelper_2D::isHorizontalAxis() const
741 return ( m_aAxisStartScreenPosition2D
.getY() == m_aAxisEndScreenPosition2D
.getY() );
743 bool TickmarkHelper_2D::isVerticalAxis() const
745 return ( m_aAxisStartScreenPosition2D
.getX() == m_aAxisEndScreenPosition2D
.getX() );
749 sal_Int32
TickmarkHelper_2D::getTickScreenDistance( TickIter
& rIter
)
751 //return the positive distance between the two first tickmarks in screen values
752 //if there are less than two tickmarks -1 is returned
754 const TickInfo
* pFirstTickInfo
= rIter
.firstInfo();
755 const TickInfo
* pSecondTickInfo
= rIter
.nextInfo();
756 if(!pSecondTickInfo
|| !pFirstTickInfo
)
759 B2DVector aDistance
= pSecondTickInfo
->aTickScreenPosition
-pFirstTickInfo
->aTickScreenPosition
;
760 sal_Int32 nRet
= static_cast<sal_Int32
>(aDistance
.getLength());
766 B2DVector
TickmarkHelper_2D::getTickScreenPosition2D( double fScaledLogicTickValue
) const
768 B2DVector
aRet(m_aAxisStartScreenPosition2D
);
769 aRet
+= (m_aAxisEndScreenPosition2D
-m_aAxisStartScreenPosition2D
)
770 *((fScaledLogicTickValue
+m_fOffset_LogicToScreen
)*m_fStrech_LogicToScreen
);
774 void TickmarkHelper_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence
& rPoints
775 , sal_Int32 nSequenceIndex
776 , double fScaledLogicTickValue
, double fInnerDirectionSign
777 , const TickmarkProperties
& rTickmarkProperties
778 , bool bPlaceAtLabels
) const
780 if( fInnerDirectionSign
==0.0 )
781 fInnerDirectionSign
= 1.0;
783 B2DVector aTickScreenPosition
= this->getTickScreenPosition2D(fScaledLogicTickValue
);
785 aTickScreenPosition
+= m_aAxisLineToLabelLineShift
;
787 B2DVector aMainDirection
= m_aAxisEndScreenPosition2D
-m_aAxisStartScreenPosition2D
;
788 aMainDirection
.normalize();
789 B2DVector
aOrthoDirection(-aMainDirection
.getY(),aMainDirection
.getX());
790 aOrthoDirection
*= fInnerDirectionSign
;
791 aOrthoDirection
.normalize();
793 B2DVector aStart
= aTickScreenPosition
+ aOrthoDirection
*rTickmarkProperties
.RelativePos
;
794 B2DVector aEnd
= aStart
- aOrthoDirection
*rTickmarkProperties
.Length
;
796 rPoints
[nSequenceIndex
].realloc(2);
797 rPoints
[nSequenceIndex
][0].X
= static_cast<sal_Int32
>(aStart
.getX());
798 rPoints
[nSequenceIndex
][0].Y
= static_cast<sal_Int32
>(aStart
.getY());
799 rPoints
[nSequenceIndex
][1].X
= static_cast<sal_Int32
>(aEnd
.getX());
800 rPoints
[nSequenceIndex
][1].Y
= static_cast<sal_Int32
>(aEnd
.getY());
803 B2DVector
TickmarkHelper_2D::getDistanceAxisTickToText( const AxisProperties
& rAxisProperties
) const
805 bool bFarAwayLabels
= false;
806 if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START
== rAxisProperties
.m_eLabelPos
807 || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END
== rAxisProperties
.m_eLabelPos
)
808 bFarAwayLabels
= true;
810 double fInnerDirectionSign
= rAxisProperties
.m_fInnerDirectionSign
;
811 if( fInnerDirectionSign
==0.0 )
812 fInnerDirectionSign
= 1.0;
814 B2DVector aMainDirection
= m_aAxisEndScreenPosition2D
-m_aAxisStartScreenPosition2D
;
815 aMainDirection
.normalize();
816 B2DVector
aOrthoDirection(-aMainDirection
.getY(),aMainDirection
.getX());
817 aOrthoDirection
*= fInnerDirectionSign
;
818 aOrthoDirection
.normalize();
820 B2DVector
aStart(0,0), aEnd(0,0);
823 TickmarkProperties
aProps( AxisProperties::getBiggestTickmarkProperties() );
824 aStart
= aOrthoDirection
*aProps
.RelativePos
;
825 aEnd
= aStart
- aOrthoDirection
*aProps
.Length
;
829 for( sal_Int32 nN
=rAxisProperties
.m_aTickmarkPropertiesList
.size();nN
--;)
831 const TickmarkProperties
& rProps
= rAxisProperties
.m_aTickmarkPropertiesList
[nN
];
832 B2DVector aNewStart
= aOrthoDirection
*rProps
.RelativePos
;
833 B2DVector aNewEnd
= aNewStart
- aOrthoDirection
*rProps
.Length
;
834 if(aNewStart
.getLength()>aStart
.getLength())
836 if(aNewEnd
.getLength()>aEnd
.getLength())
841 B2DVector
aLabelDirection(aStart
);
842 if( rAxisProperties
.m_fInnerDirectionSign
!= rAxisProperties
.m_fLabelDirectionSign
)
843 aLabelDirection
= aEnd
;
845 B2DVector
aOrthoLabelDirection(aOrthoDirection
);
846 if( rAxisProperties
.m_fInnerDirectionSign
!= rAxisProperties
.m_fLabelDirectionSign
)
847 aOrthoLabelDirection
*=-1.0;
848 aOrthoLabelDirection
.normalize();
849 aLabelDirection
+= aOrthoLabelDirection
*AXIS2D_TICKLABELSPACING
;
851 aLabelDirection
+= m_aAxisLineToLabelLineShift
;
852 return aLabelDirection
;
855 void TickmarkHelper_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence
& rPoints
) const
857 rPoints
[0].realloc(2);
858 rPoints
[0][0].X
= static_cast<sal_Int32
>(m_aAxisStartScreenPosition2D
.getX());
859 rPoints
[0][0].Y
= static_cast<sal_Int32
>(m_aAxisStartScreenPosition2D
.getY());
860 rPoints
[0][1].X
= static_cast<sal_Int32
>(m_aAxisEndScreenPosition2D
.getX());
861 rPoints
[0][1].Y
= static_cast<sal_Int32
>(m_aAxisEndScreenPosition2D
.getY());
864 void TickmarkHelper_2D::updateScreenValues( ::std::vector
< ::std::vector
< TickInfo
> >& rAllTickInfos
) const
866 //get the transformed screen values for all tickmarks in rAllTickInfos
867 ::std::vector
< ::std::vector
< TickInfo
> >::iterator aDepthIter
= rAllTickInfos
.begin();
868 const ::std::vector
< ::std::vector
< TickInfo
> >::const_iterator aDepthEnd
= rAllTickInfos
.end();
869 for( ; aDepthIter
!= aDepthEnd
; aDepthIter
++ )
871 ::std::vector
< TickInfo
>::iterator aTickIter
= (*aDepthIter
).begin();
872 const ::std::vector
< TickInfo
>::const_iterator aTickEnd
= (*aDepthIter
).end();
873 for( ; aTickIter
!= aTickEnd
; aTickIter
++ )
875 TickInfo
& rTickInfo
= (*aTickIter
);
876 rTickInfo
.aTickScreenPosition
=
877 this->getTickScreenPosition2D( rTickInfo
.fScaledTickValue
);
882 //'hide' tickmarks with identical screen values in aAllTickInfos
883 void TickmarkHelper_2D::hideIdenticalScreenValues(
884 ::std::vector
< ::std::vector
< TickInfo
> >& rAllTickInfos
) const
886 TickIter
aIter( rAllTickInfos
, m_rIncrement
);
888 TickInfo
* pPreviousTickInfo
= aIter
.firstInfo();
889 if(!pPreviousTickInfo
)
891 pPreviousTickInfo
->bPaintIt
= true;
892 for( TickInfo
* pTickInfo
= aIter
.nextInfo(); pTickInfo
; pTickInfo
= aIter
.nextInfo())
894 pTickInfo
->bPaintIt
=
895 ( static_cast<sal_Int32
>(pTickInfo
->aTickScreenPosition
.getX())
896 != static_cast<sal_Int32
>(pPreviousTickInfo
->aTickScreenPosition
.getX()) )
898 ( static_cast<sal_Int32
>(pTickInfo
->aTickScreenPosition
.getY())
899 != static_cast<sal_Int32
>(pPreviousTickInfo
->aTickScreenPosition
.getY()) );
900 pPreviousTickInfo
= pTickInfo
;
903 //-----------------------------------------------------------------------------
904 // ___TickmarkHelper_3D___
905 //-----------------------------------------------------------------------------
906 TickmarkHelper_3D::TickmarkHelper_3D(
907 const ExplicitScaleData
& rScale
, const ExplicitIncrementData
& rIncrement
)
908 : TickmarkHelper( rScale
, rIncrement
)
912 TickmarkHelper
* TickmarkHelper_3D::createShiftedTickmarkHelper() const
914 ExplicitIncrementData
aShiftedIncrement( m_rIncrement
);
915 aShiftedIncrement
.BaseValue
= m_rIncrement
.BaseValue
-m_rIncrement
.Distance
/2.0;
916 return new TickmarkHelper_3D( m_rScale
, aShiftedIncrement
);
919 TickmarkHelper_3D::~TickmarkHelper_3D()
923 //.............................................................................
925 //.............................................................................