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 3075 : 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 3075 : , nFactorForLimitedTextWidth(1)
44 : {
45 3075 : }
46 :
47 779 : double TickInfo::getUnscaledTickValue() const
48 : {
49 779 : if( xInverseScaling.is() )
50 451 : return xInverseScaling->doScaling( fScaledTickValue );
51 : else
52 328 : return fScaledTickValue;
53 : }
54 :
55 82 : sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
56 : {
57 : //return the positive distance between the two first tickmarks in screen values
58 :
59 82 : B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
60 82 : sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
61 82 : if(nRet<0)
62 0 : nRet *= -1;
63 82 : return nRet;
64 : }
65 :
66 164 : PureTickIter::PureTickIter( ::std::vector< TickInfo >& rTickInfoVector )
67 : : m_rTickVector(rTickInfoVector)
68 164 : , m_aTickIter(m_rTickVector.begin())
69 : {
70 164 : }
71 246 : PureTickIter::~PureTickIter()
72 : {
73 246 : }
74 246 : TickInfo* PureTickIter::firstInfo()
75 : {
76 246 : m_aTickIter = m_rTickVector.begin();
77 246 : if(m_aTickIter!=m_rTickVector.end())
78 246 : return &*m_aTickIter;
79 0 : return 0;
80 : }
81 902 : TickInfo* PureTickIter::nextInfo()
82 : {
83 902 : if(m_aTickIter!=m_rTickVector.end())
84 : {
85 861 : ++m_aTickIter;
86 861 : if(m_aTickIter!=m_rTickVector.end())
87 697 : return &*m_aTickIter;
88 : }
89 205 : return 0;
90 : }
91 :
92 : //-----------------------------------------------------------------------------
93 : //-----------------------------------------------------------------------------
94 : //-----------------------------------------------------------------------------
95 :
96 574 : TickFactory::TickFactory(
97 : const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement )
98 : : m_rScale( rScale )
99 : , m_rIncrement( rIncrement )
100 574 : , m_xInverseScaling(NULL)
101 : {
102 : //@todo: make sure that the scale is valid for the scaling
103 :
104 574 : if( m_rScale.Scaling.is() )
105 : {
106 287 : m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
107 : OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return a inverse Scaling" );
108 : }
109 :
110 574 : m_fScaledVisibleMin = m_rScale.Minimum;
111 574 : if( m_xInverseScaling.is() )
112 287 : m_fScaledVisibleMin = m_rScale.Scaling->doScaling(m_fScaledVisibleMin);
113 :
114 574 : m_fScaledVisibleMax = m_rScale.Maximum;
115 574 : if( m_xInverseScaling.is() )
116 287 : m_fScaledVisibleMax = m_rScale.Scaling->doScaling(m_fScaledVisibleMax);
117 574 : }
118 :
119 656 : TickFactory::~TickFactory()
120 : {
121 656 : }
122 :
123 287 : bool TickFactory::isDateAxis() const
124 : {
125 287 : return m_rScale.AxisType == AxisType::DATE;
126 : }
127 :
128 205 : void TickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
129 : {
130 205 : if( isDateAxis() )
131 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
132 : else
133 205 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicks( rAllTickInfos );
134 205 : }
135 :
136 82 : void TickFactory::getAllTicksShifted( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
137 : {
138 82 : if( isDateAxis() )
139 0 : DateTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
140 : else
141 82 : EquidistantTickFactory( m_rScale, m_rIncrement ).getAllTicksShifted( rAllTickInfos );
142 82 : }
143 :
144 : //-----------------------------------------------------------------------------
145 : // ___TickFactory_2D___
146 : //-----------------------------------------------------------------------------
147 492 : 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 492 : , m_fOffset_LogicToScreen(0.0)
158 : {
159 492 : double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
160 492 : if( AxisOrientation_MATHEMATICAL==m_rScale.Orientation )
161 : {
162 492 : m_fStrech_LogicToScreen = 1.0/fWidthY;
163 492 : m_fOffset_LogicToScreen = -m_fScaledVisibleMin;
164 : }
165 : else
166 : {
167 0 : B2DVector aSwap(m_aAxisStartScreenPosition2D);
168 0 : m_aAxisStartScreenPosition2D = m_aAxisEndScreenPosition2D;
169 0 : m_aAxisEndScreenPosition2D = aSwap;
170 :
171 0 : m_fStrech_LogicToScreen = -1.0/fWidthY;
172 0 : m_fOffset_LogicToScreen = -m_fScaledVisibleMax;
173 : }
174 492 : }
175 :
176 984 : TickFactory_2D::~TickFactory_2D()
177 : {
178 984 : }
179 :
180 246 : bool TickFactory_2D::isHorizontalAxis() const
181 : {
182 246 : return ( m_aAxisStartScreenPosition2D.getY() == m_aAxisEndScreenPosition2D.getY() );
183 : }
184 246 : bool TickFactory_2D::isVerticalAxis() const
185 : {
186 246 : return ( m_aAxisStartScreenPosition2D.getX() == m_aAxisEndScreenPosition2D.getX() );
187 : }
188 :
189 : //static
190 82 : 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 82 : const TickInfo* pFirstTickInfo = rIter.firstInfo();
196 82 : const TickInfo* pSecondTickInfo = rIter.nextInfo();
197 82 : if(!pSecondTickInfo || !pFirstTickInfo)
198 0 : return -1;
199 :
200 82 : return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
201 : }
202 :
203 4059 : B2DVector TickFactory_2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
204 : {
205 4059 : B2DVector aRet(m_aAxisStartScreenPosition2D);
206 : aRet += (m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D)
207 4059 : *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStrech_LogicToScreen);
208 4059 : return aRet;
209 : }
210 :
211 984 : 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 984 : if( fInnerDirectionSign==0.0 )
218 0 : fInnerDirectionSign = 1.0;
219 :
220 984 : B2DVector aTickScreenPosition = this->getTickScreenPosition2D(fScaledLogicTickValue);
221 984 : if( bPlaceAtLabels )
222 492 : aTickScreenPosition += m_aAxisLineToLabelLineShift;
223 :
224 984 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
225 984 : aMainDirection.normalize();
226 984 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
227 984 : aOrthoDirection *= fInnerDirectionSign;
228 984 : aOrthoDirection.normalize();
229 :
230 984 : B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
231 984 : B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
232 :
233 984 : rPoints[nSequenceIndex].realloc(2);
234 984 : rPoints[nSequenceIndex][0].X = static_cast<sal_Int32>(aStart.getX());
235 984 : rPoints[nSequenceIndex][0].Y = static_cast<sal_Int32>(aStart.getY());
236 984 : rPoints[nSequenceIndex][1].X = static_cast<sal_Int32>(aEnd.getX());
237 984 : rPoints[nSequenceIndex][1].Y = static_cast<sal_Int32>(aEnd.getY());
238 984 : }
239 :
240 656 : B2DVector TickFactory_2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
241 : {
242 656 : bool bFarAwayLabels = false;
243 656 : if( ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_START == rAxisProperties.m_eLabelPos
244 : || ::com::sun::star::chart::ChartAxisLabelPosition_OUTSIDE_END == rAxisProperties.m_eLabelPos )
245 0 : bFarAwayLabels = true;
246 :
247 656 : double fInnerDirectionSign = rAxisProperties.m_fInnerDirectionSign;
248 656 : if( fInnerDirectionSign==0.0 )
249 0 : fInnerDirectionSign = 1.0;
250 :
251 656 : B2DVector aMainDirection = m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D;
252 656 : aMainDirection.normalize();
253 656 : B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
254 656 : aOrthoDirection *= fInnerDirectionSign;
255 656 : aOrthoDirection.normalize();
256 :
257 656 : B2DVector aStart(0,0), aEnd(0,0);
258 656 : if( bFarAwayLabels )
259 : {
260 0 : TickmarkProperties aProps( AxisProperties::getBiggestTickmarkProperties() );
261 0 : aStart = aOrthoDirection*aProps.RelativePos;
262 0 : aEnd = aStart - aOrthoDirection*aProps.Length;
263 : }
264 : else
265 : {
266 1968 : for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
267 : {
268 656 : const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
269 656 : B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
270 656 : B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
271 656 : if(aNewStart.getLength()>aStart.getLength())
272 656 : aStart=aNewStart;
273 656 : if(aNewEnd.getLength()>aEnd.getLength())
274 0 : aEnd=aNewEnd;
275 656 : }
276 : }
277 :
278 656 : B2DVector aLabelDirection(aStart);
279 656 : if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
280 0 : aLabelDirection = aEnd;
281 :
282 656 : B2DVector aOrthoLabelDirection(aOrthoDirection);
283 656 : if( rAxisProperties.m_fInnerDirectionSign != rAxisProperties.m_fLabelDirectionSign )
284 0 : aOrthoLabelDirection*=-1.0;
285 656 : aOrthoLabelDirection.normalize();
286 656 : if( bIncludeSpaceBetweenTickAndText )
287 656 : aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
288 656 : if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
289 0 : aLabelDirection += m_aAxisLineToLabelLineShift;
290 656 : return aLabelDirection;
291 : }
292 :
293 82 : void TickFactory_2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
294 : {
295 82 : rPoints[0].realloc(2);
296 82 : rPoints[0][0].X = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX());
297 82 : rPoints[0][0].Y = static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY());
298 82 : rPoints[0][1].X = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX());
299 82 : rPoints[0][1].Y = static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY());
300 82 : }
301 :
302 287 : void TickFactory_2D::updateScreenValues( ::std::vector< ::std::vector< TickInfo > >& rAllTickInfos ) const
303 : {
304 : //get the transformed screen values for all tickmarks in rAllTickInfos
305 287 : ::std::vector< ::std::vector< TickInfo > >::iterator aDepthIter = rAllTickInfos.begin();
306 287 : const ::std::vector< ::std::vector< TickInfo > >::const_iterator aDepthEnd = rAllTickInfos.end();
307 861 : for( ; aDepthIter != aDepthEnd; ++aDepthIter )
308 : {
309 574 : ::std::vector< TickInfo >::iterator aTickIter = (*aDepthIter).begin();
310 574 : const ::std::vector< TickInfo >::const_iterator aTickEnd = (*aDepthIter).end();
311 3649 : for( ; aTickIter != aTickEnd; ++aTickIter )
312 : {
313 3075 : TickInfo& rTickInfo = (*aTickIter);
314 : rTickInfo.aTickScreenPosition =
315 3075 : this->getTickScreenPosition2D( rTickInfo.fScaledTickValue );
316 : }
317 : }
318 287 : }
319 :
320 : //.............................................................................
321 : } //namespace chart
322 : //.............................................................................
323 :
324 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|