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 : #include <memory>
26 :
27 : //.............................................................................
28 : namespace chart
29 : {
30 : //.............................................................................
31 : using namespace ::com::sun::star;
32 : using namespace ::com::sun::star::chart2;
33 : using namespace ::rtl::math;
34 : using ::basegfx::B2DVector;
35 :
36 38779 : TickInfo::TickInfo( const ::com::sun::star::uno::Reference<
37 : ::com::sun::star::chart2::XScaling >& xInverse )
38 : : fScaledTickValue( 0.0 )
39 : , xInverseScaling( xInverse )
40 : , aTickScreenPosition(0.0,0.0)
41 : , bPaintIt( true )
42 : , xTextShape( NULL )
43 38779 : , nFactorForLimitedTextWidth(1)
44 : {
45 38779 : }
46 :
47 8827 : double TickInfo::getUnscaledTickValue() const
48 : {
49 8827 : if( xInverseScaling.is() )
50 4557 : return xInverseScaling->doScaling( fScaledTickValue );
51 : else
52 4270 : return fScaledTickValue;
53 : }
54 :
55 924 : sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
56 : {
57 : //return the positive distance between the two first tickmarks in screen values
58 :
59 924 : B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
60 924 : sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
61 924 : if(nRet<0)
62 0 : nRet *= -1;
63 924 : return nRet;
64 : }
65 :
66 1883 : PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector )
67 : : m_rTickVector(rTickInfoVector)
68 1883 : , m_aTickIter(m_rTickVector.begin())
69 : {
70 1883 : }
71 2808 : PureTickIter::~PureTickIter()
72 : {
73 2808 : }
74 2876 : TickInfo* PureTickIter::firstInfo()
75 : {
76 2876 : m_aTickIter = m_rTickVector.begin();
77 2876 : if(m_aTickIter!=m_rTickVector.end())
78 2876 : return &*m_aTickIter;
79 0 : return 0;
80 : }
81 10952 : TickInfo* PureTickIter::nextInfo()
82 : {
83 10952 : if(m_aTickIter!=m_rTickVector.end())
84 : {
85 10475 : ++m_aTickIter;
86 10475 : if(m_aTickIter!=m_rTickVector.end())
87 8582 : return &*m_aTickIter;
88 : }
89 2370 : return 0;
90 : }
91 :
92 : //-----------------------------------------------------------------------------
93 : //-----------------------------------------------------------------------------
94 : //-----------------------------------------------------------------------------
95 :
96 6846 : TickFactory::TickFactory(
97 : const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
98 : : m_rScale( rScale )
99 : , m_rIncrement( rIncrement )
100 6846 : , m_xInverseScaling(NULL)
101 : {
102 : //@todo: make sure that the scale is valid for the scaling
103 :
104 6846 : if( m_rScale.Scaling.is() )
105 : {
106 3200 : m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
107 : OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" );
108 : }
109 :
110 6846 : m_fScaledVisibleMin = m_rScale.Minimum;
111 6846 : if( m_xInverseScaling.is() )
112 3200 : m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
113 :
114 6846 : m_fScaledVisibleMax = m_rScale.Maximum;
115 6846 : if( m_xInverseScaling.is() )
116 3200 : m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
117 6846 : }
118 :
119 7890 : TickFactory::~TickFactory()
120 : {
121 7890 : }
122 :
123 3516 : bool TickFactory::isDateAxis() const
124 : {
125 3516 : return m_rScale.AxisType == AxisType::DATE;
126 : }
127 :
128 2544 : void TickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
129 : {
130 2544 : if( isDateAxis() )
131 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
132 : else
133 2544 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
134 2544 : }
135 :
136 972 : void TickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
137 : {
138 972 : if( isDateAxis() )
139 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
140 : else
141 972 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
142 972 : }
143 :
144 : //-----------------------------------------------------------------------------
145 : // ___TickFactory_2D___
146 : //-----------------------------------------------------------------------------
147 5802 : TickFactory_2D::TickFactory_2D(
148 : const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
149 : //, double fStrech_SceneToScreen, double fOffset_SceneToScreen )
150 : , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
151 : , const B2DVector& rAxisLineToLabelLineShift )
152 : : TickFactory( rScale, rIncrement )
153 : , m_aAxisStartScreenPosition2D(rStartScreenPos)
154 : , m_aAxisEndScreenPosition2D(rEndScreenPos)
155 : , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
156 : , m_fStrech_LogicToScreen(1.0)
157 5802 : , m_fOffset_LogicToScreen(0.0)
158 : {
159 5802 : double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
160 5802 : if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation )
161 : {
162 5785 : m_fStrech_LogicToScreen = 1.0/fWidthY;
163 5785 : m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
164 : }
165 : else
166 : {
167 17 : B2DVector aSwap(m_aAxisStartScreenPosition2D);
168 17 : m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
169 17 : m_aAxisEndScreenPosition2D = aSwap;
170 :
171 17 : m_fStrech_LogicToScreen = -1.0/fWidthY;
172 17 : m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
173 : }
174 5802 : }
175 :
176 11604 : TickFactory_2D::~TickFactory_2D()
177 : {
178 11604 : }
179 :
180 2815 : bool TickFactory_2D::isHorizontalAxis() const
181 : {
182 2815 : return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() );
183 : }
184 2815 : bool TickFactory_2D::isVerticalAxis() const
185 : {
186 2815 : return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() );
187 : }
188 :
189 : //static
190 925 : sal_Int32 TickFactory_2D::getTickScreenDistance( TickIter& rIter )
191 : {
192 : //return the positive distance between the two first tickmarks in screen values
193 : //if there are less than two tickmarks -1 is returned
194 :
195 925 : const TickInfo* pFirstTickInfo = rIter.firstInfo();
196 925 : const TickInfo* pSecondTickInfo = rIter.nextInfo();
197 925 : if(!pSecondTickInfo || !pFirstTickInfo)
198 1 : return -1;
199 :
200 924 : return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
201 : }
202 :
203 47911 : B2DVector TickFactory_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
204 : {
205 47911 : B2DVector aRet(m_aAxisStartScreenPosition2D);
206 143733 : aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
207 143733 : *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen);
208 47911 : return aRet;
209 : }
210 :
211 12001 : void TickFactory_2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
212 : , sal_Int32 nSequenceIndex
213 : , double fScaledLogicTickValue, double fInnerDirectionSign
214 : , const TickmarkProperties& rTickmarkProperties
215 : , bool bPlaceAtLabels ) const
216 : {
217 12001 : if( fInnerDirectionSign==0.0 )
218 0 : fInnerDirectionSign = 1.0;
219 :
220 12001 : B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue);
221 12001 : if( bPlaceAtLabels )
222 6012 : aTickScreenPosition += m_aAxisLineToLabelLineShift;
223 :
224 24002 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
225 12001 : aMainDirection.normalize();
226 24002 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
227 12001 : aOrthoDirection *= fInnerDirectionSign;
228 12001 : aOrthoDirection.normalize();
229 :
230 24002 : B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
231 24002 : B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
232 :
233 12001 : rPoints[nSequenceIndex].realloc(2);
234 12001 : rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX());
235 12001 : rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY());
236 12001 : rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX());
237 24002 : rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY());
238 12001 : }
239 :
240 7463 : B2DVector TickFactory_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
241 : {
242 7463 : bool bFarAwayLabels = false;
243 7463 : if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos
244 7182 : || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos )
245 281 : bFarAwayLabels = true;
246 :
247 7463 : double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign;
248 7463 : if( fInnerDirectionSign==0.0 )
249 0 : fInnerDirectionSign = 1.0;
250 :
251 7463 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
252 7463 : aMainDirection.normalize();
253 14926 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
254 7463 : aOrthoDirection *= fInnerDirectionSign;
255 7463 : aOrthoDirection.normalize();
256 :
257 14926 : B2DVector aStart(0,0), aEnd(0,0);
258 7463 : if( bFarAwayLabels )
259 : {
260 281 : TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
261 281 : aStart = aOrthoDirection*aProps.RelativePos;
262 281 : aEnd = aStart - aOrthoDirection*aProps.Length;
263 : }
264 : else
265 : {
266 21603 : for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
267 : {
268 7239 : const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
269 7239 : B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
270 14478 : B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
271 7239 : if(aNewStart.getLength()>aStart.getLength())
272 7239 : aStart=aNewStart;
273 7239 : if(aNewEnd.getLength()>aEnd.getLength())
274 114 : aEnd=aNewEnd;
275 7239 : }
276 : }
277 :
278 7463 : B2DVector aLabelDirection(aStart);
279 7463 : if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
280 30 : aLabelDirection = aEnd;
281 :
282 14926 : B2DVector aOrthoLabelDirection(aOrthoDirection);
283 7463 : if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
284 30 : aOrthoLabelDirection*=-1.0;
285 7463 : aOrthoLabelDirection.normalize();
286 7463 : if( bIncludeSpaceBetweenTickAndText )
287 7463 : aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
288 7463 : if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
289 281 : aLabelDirection += m_aAxisLineToLabelLineShift;
290 14926 : return aLabelDirection;
291 : }
292 :
293 974 : void TickFactory_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
294 : {
295 974 : rPoints[0].realloc(2);
296 974 : rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX());
297 974 : rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY());
298 974 : rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX());
299 974 : rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY());
300 974 : }
301 :
302 3284 : void TickFactory_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
303 : {
304 : //get the transformed screen values for all tickmarks in rAllTickInfos
305 3284 : ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin();
306 3284 : const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end();
307 9786 : for( ; aDepthIter != aDepthEnd; ++aDepthIter )
308 : {
309 6502 : ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin();
310 6502 : const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end();
311 42412 : for( ; aTickIter != aTickEnd; ++aTickIter )
312 : {
313 35910 : TickInfo& rTickInfo = (*aTickIter);
314 71820 : rTickInfo.aTickScreenPosition =
315 35910 : this->getTickScreenPosition2D( rTickInfo.fScaledTickValue );
316 : }
317 : }
318 3284 : }
319 :
320 : //.............................................................................
321 : } //namespace chart
322 : //.............................................................................
323 :
324 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|