Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "Tickmarks.hxx"
21 : #include "Tickmarks_Equidistant.hxx"
22 : #include "Tickmarks_Dates.hxx"
23 : #include "ViewDefines.hxx"
24 : #include <rtl/math.hxx>
25 :
26 : using namespace ::com::sun::star;
27 : using namespace ::rtl::math;
28 : using ::basegfx::B2DVector;
29 :
30 : namespace chart {
31 :
32 80153 : TickInfo::TickInfo( const uno::Reference<chart2::XScaling>& xInverse )
33 : : fScaledTickValue( 0.0 )
34 : , xInverseScaling( xInverse )
35 : , aTickScreenPosition(0.0,0.0)
36 : , bPaintIt( true )
37 : , xTextShape( NULL )
38 80153 : , nFactorForLimitedTextWidth(1)
39 : {
40 80153 : }
41 :
42 16481 : double TickInfo::getUnscaledTickValue() const
43 : {
44 16481 : if( xInverseScaling.is() )
45 9073 : return xInverseScaling->doScaling( fScaledTickValue );
46 : else
47 7408 : return fScaledTickValue;
48 : }
49 :
50 1837 : sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
51 : {
52 : //return the positive distance between the two first tickmarks in screen values
53 :
54 1837 : B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
55 1837 : sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
56 1837 : if(nRet<0)
57 0 : nRet *= -1;
58 1837 : return nRet;
59 : }
60 :
61 3577 : PureTickIter::PureTickIter( TickInfoArrayType& rTickInfoVector )
62 : : m_rTickVector(rTickInfoVector)
63 3577 : , m_aTickIter(m_rTickVector.begin())
64 : {
65 3577 : }
66 5416 : PureTickIter::~PureTickIter()
67 : {
68 5416 : }
69 5561 : TickInfo* PureTickIter::firstInfo()
70 : {
71 5561 : m_aTickIter = m_rTickVector.begin();
72 5561 : if(m_aTickIter!=m_rTickVector.end())
73 5561 : return &*m_aTickIter;
74 0 : return 0;
75 : }
76 22180 : TickInfo* PureTickIter::nextInfo()
77 : {
78 22180 : if(m_aTickIter!=m_rTickVector.end())
79 : {
80 21316 : ++m_aTickIter;
81 21316 : if(m_aTickIter!=m_rTickVector.end())
82 17717 : return &*m_aTickIter;
83 : }
84 4463 : return 0;
85 : }
86 :
87 13719 : TickFactory::TickFactory(
88 : const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
89 : : m_rScale( rScale )
90 : , m_rIncrement( rIncrement )
91 13719 : , m_xInverseScaling(NULL)
92 : {
93 : //@todo: make sure that the scale is valid for the scaling
94 :
95 13719 : if( m_rScale.Scaling.is() )
96 : {
97 6584 : m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
98 : OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" );
99 : }
100 :
101 13719 : m_fScaledVisibleMin = m_rScale.Minimum;
102 13719 : if( m_xInverseScaling.is() )
103 6584 : m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
104 :
105 13719 : m_fScaledVisibleMax = m_rScale.Maximum;
106 13719 : if( m_xInverseScaling.is() )
107 6584 : m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
108 13719 : }
109 :
110 15808 : TickFactory::~TickFactory()
111 : {
112 15808 : }
113 :
114 6935 : bool TickFactory::isDateAxis() const
115 : {
116 6935 : return m_rScale.AxisType == chart2::AxisType::DATE;
117 : }
118 :
119 5069 : void TickFactory::getAllTicks( TickInfoArraysType& rAllTickInfos ) const
120 : {
121 5069 : if( isDateAxis() )
122 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
123 : else
124 5069 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
125 5069 : }
126 :
127 1866 : void TickFactory::getAllTicksShifted( TickInfoArraysType& rAllTickInfos ) const
128 : {
129 1866 : if( isDateAxis() )
130 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
131 : else
132 1866 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
133 1866 : }
134 :
135 0 : void TickFactory::updateScreenValues( TickInfoArraysType& /*rAllTickInfos*/ ) const
136 : {
137 0 : }
138 :
139 : // ___TickFactory_2D___
140 11620 : TickFactory2D::TickFactory2D(
141 : const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
142 : //, double fStretch_SceneToScreen, double fOffset_SceneToScreen )
143 : , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
144 : , const B2DVector& rAxisLineToLabelLineShift )
145 : : TickFactory( rScale, rIncrement )
146 : , m_aAxisStartScreenPosition2D(rStartScreenPos)
147 : , m_aAxisEndScreenPosition2D(rEndScreenPos)
148 : , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
149 : , m_fStretch_LogicToScreen(1.0)
150 11620 : , m_fOffset_LogicToScreen(0.0)
151 : {
152 11620 : double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
153 11620 : if (chart2::AxisOrientation_MATHEMATICAL == m_rScale.Orientation)
154 : {
155 11550 : m_fStretch_LogicToScreen = 1.0/fWidthY;
156 11550 : m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
157 : }
158 : else
159 : {
160 70 : B2DVector aSwap(m_aAxisStartScreenPosition2D);
161 70 : m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
162 70 : m_aAxisEndScreenPosition2D = aSwap;
163 :
164 70 : m_fStretch_LogicToScreen = -1.0/fWidthY;
165 70 : m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
166 : }
167 11620 : }
168 :
169 23240 : TickFactory2D::~TickFactory2D()
170 : {
171 23240 : }
172 :
173 7630 : bool TickFactory2D::isHorizontalAxis() const
174 : {
175 7630 : return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() );
176 : }
177 7630 : bool TickFactory2D::isVerticalAxis() const
178 : {
179 7630 : return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() );
180 : }
181 :
182 : //static
183 1839 : sal_Int32 TickFactory2D::getTickScreenDistance( TickIter& rIter )
184 : {
185 : //return the positive distance between the two first tickmarks in screen values
186 : //if there are less than two tickmarks -1 is returned
187 :
188 1839 : const TickInfo* pFirstTickInfo = rIter.firstInfo();
189 1839 : const TickInfo* pSecondTickInfo = rIter.nextInfo();
190 1839 : if(!pSecondTickInfo || !pFirstTickInfo)
191 2 : return -1;
192 :
193 1837 : return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
194 : }
195 :
196 96039 : B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
197 : {
198 96039 : B2DVector aRet(m_aAxisStartScreenPosition2D);
199 288117 : aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
200 288117 : *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStretch_LogicToScreen);
201 96039 : return aRet;
202 : }
203 :
204 21185 : void TickFactory2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
205 : , sal_Int32 nSequenceIndex
206 : , double fScaledLogicTickValue, double fInnerDirectionSign
207 : , const TickmarkProperties& rTickmarkProperties
208 : , bool bPlaceAtLabels ) const
209 : {
210 21185 : if( fInnerDirectionSign==0.0 )
211 36 : fInnerDirectionSign = 1.0;
212 :
213 21185 : B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue);
214 21185 : if( bPlaceAtLabels )
215 10250 : aTickScreenPosition += m_aAxisLineToLabelLineShift;
216 :
217 42370 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
218 21185 : aMainDirection.normalize();
219 42370 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
220 21185 : aOrthoDirection *= fInnerDirectionSign;
221 21185 : aOrthoDirection.normalize();
222 :
223 42370 : B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
224 42370 : B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
225 :
226 21185 : rPoints[nSequenceIndex].realloc(2);
227 21185 : rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX());
228 21185 : rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY());
229 21185 : rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX());
230 42370 : rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY());
231 21185 : }
232 :
233 15271 : B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
234 : {
235 15271 : bool bFarAwayLabels = false;
236 15271 : if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos
237 14879 : || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos )
238 392 : bFarAwayLabels = true;
239 :
240 15271 : double fInnerDirectionSign = rAxisProperties.maLabelAlignment.mfInnerTickDirection;
241 15271 : if( fInnerDirectionSign==0.0 )
242 10 : fInnerDirectionSign = 1.0;
243 :
244 15271 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
245 15271 : aMainDirection.normalize();
246 30542 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
247 15271 : aOrthoDirection *= fInnerDirectionSign;
248 15271 : aOrthoDirection.normalize();
249 :
250 30542 : B2DVector aStart(0,0), aEnd(0,0);
251 15271 : if( bFarAwayLabels )
252 : {
253 392 : TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
254 392 : aStart = aOrthoDirection*aProps.RelativePos;
255 392 : aEnd = aStart - aOrthoDirection*aProps.Length;
256 : }
257 : else
258 : {
259 43733 : for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
260 : {
261 13975 : const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
262 13975 : B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
263 27950 : B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
264 13975 : if(aNewStart.getLength()>aStart.getLength())
265 13955 : aStart=aNewStart;
266 13975 : if(aNewEnd.getLength()>aEnd.getLength())
267 563 : aEnd=aNewEnd;
268 13975 : }
269 : }
270 :
271 15271 : B2DVector aLabelDirection(aStart);
272 15271 : if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
273 182 : aLabelDirection = aEnd;
274 :
275 30542 : B2DVector aOrthoLabelDirection(aOrthoDirection);
276 15271 : if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
277 182 : aOrthoLabelDirection*=-1.0;
278 15271 : aOrthoLabelDirection.normalize();
279 15271 : if( bIncludeSpaceBetweenTickAndText )
280 15271 : aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
281 15271 : if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
282 392 : aLabelDirection += m_aAxisLineToLabelLineShift;
283 30542 : return aLabelDirection;
284 : }
285 :
286 1859 : void TickFactory2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
287 : {
288 1859 : rPoints[0].realloc(2);
289 1859 : rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX());
290 1859 : rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY());
291 1859 : rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX());
292 1859 : rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY());
293 1859 : }
294 :
295 6454 : void TickFactory2D::updateScreenValues( TickInfoArraysType& rAllTickInfos ) const
296 : {
297 : //get the transformed screen values for all tickmarks in rAllTickInfos
298 6454 : TickInfoArraysType::iterator aDepthIter = rAllTickInfos.begin();
299 6454 : const TickInfoArraysType::const_iterator aDepthEnd = rAllTickInfos.end();
300 19172 : for( ; aDepthIter != aDepthEnd; ++aDepthIter )
301 : {
302 12718 : TickInfoArrayType::iterator aTickIter = (*aDepthIter).begin();
303 12718 : const TickInfoArrayType::const_iterator aTickEnd = (*aDepthIter).end();
304 87572 : for( ; aTickIter != aTickEnd; ++aTickIter )
305 : {
306 74854 : TickInfo& rTickInfo = (*aTickIter);
307 149708 : rTickInfo.aTickScreenPosition =
308 74854 : this->getTickScreenPosition2D( rTickInfo.fScaledTickValue );
309 : }
310 : }
311 6454 : }
312 :
313 : } //namespace chart
314 :
315 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|