LibreOffice Module chart2 (master) 1
Tickmarks.cxx
Go to the documentation of this file.
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"
22#include "Tickmarks_Dates.hxx"
23#include <ViewDefines.hxx>
24#include "VAxisProperties.hxx"
25#include <osl/diagnose.h>
26#include <com/sun/star/chart2/AxisType.hpp>
27#include <utility>
28
29using namespace ::com::sun::star;
30using ::basegfx::B2DVector;
31
32namespace chart {
33
34TickInfo::TickInfo( uno::Reference<chart2::XScaling> xInverse )
35: fScaledTickValue( 0.0 )
36, xInverseScaling(std::move( xInverse ))
37, aTickScreenPosition(0.0,0.0)
38, nFactorForLimitedTextWidth(1)
39, bPaintIt( true )
40{
41}
42
43double TickInfo::getUnscaledTickValue() const
44{
45 if( xInverseScaling.is() )
46 return xInverseScaling->doScaling( fScaledTickValue );
47 else
48 return fScaledTickValue;
49}
50
51sal_Int32 TickInfo::getScreenDistanceBetweenTicks( const TickInfo& rOherTickInfo ) const
52{
53 //return the positive distance between the two first tickmarks in screen values
54
55 B2DVector aDistance = rOherTickInfo.aTickScreenPosition - aTickScreenPosition;
56 sal_Int32 nRet = static_cast<sal_Int32>(aDistance.getLength());
57 if(nRet<0)
58 nRet *= -1;
59 return nRet;
60}
61
62PureTickIter::PureTickIter( TickInfoArrayType& rTickInfoVector )
63 : m_rTickVector(rTickInfoVector)
64 , m_aTickIter(m_rTickVector.begin())
65{
66}
68{
69}
71{
72 m_aTickIter = m_rTickVector.begin();
73 if(m_aTickIter!=m_rTickVector.end())
74 return &*m_aTickIter;
75 return nullptr;
76}
78{
79 if(m_aTickIter!=m_rTickVector.end())
80 {
82 if(m_aTickIter!=m_rTickVector.end())
83 return &*m_aTickIter;
84 }
85 return nullptr;
86}
87
89 ExplicitScaleData aScale, ExplicitIncrementData aIncrement )
90 : m_rScale(std::move( aScale ))
91 , m_rIncrement(std::move( aIncrement ))
92{
93 //@todo: make sure that the scale is valid for the scaling
94
95 if( m_rScale.Scaling.is() )
96 {
97 m_xInverseScaling = m_rScale.Scaling->getInverseScaling();
98 OSL_ENSURE( m_xInverseScaling.is(), "each Scaling needs to return an inverse Scaling" );
99 }
100
102 if( m_xInverseScaling.is() )
104
106 if( m_xInverseScaling.is() )
108}
109
111{
112}
113
115{
116 return m_rScale.AxisType == chart2::AxisType::DATE;
117}
118
120{
121 if( isDateAxis() )
123 else
125}
126
128{
129 if( isDateAxis() )
131 else
133}
134
135// ___TickFactory_2D___
137 const ExplicitScaleData& rScale, const ExplicitIncrementData& rIncrement
138 //, double fStretch_SceneToScreen, double fOffset_SceneToScreen )
139 , const B2DVector& rStartScreenPos, const B2DVector& rEndScreenPos
140 , const B2DVector& rAxisLineToLabelLineShift )
141 : TickFactory( rScale, rIncrement )
142 , m_aAxisStartScreenPosition2D(rStartScreenPos)
143 , m_aAxisEndScreenPosition2D(rEndScreenPos)
144 , m_aAxisLineToLabelLineShift(rAxisLineToLabelLineShift)
145 , m_fStretch_LogicToScreen(1.0)
146 , m_fOffset_LogicToScreen(0.0)
147{
148 double fWidthY = m_fScaledVisibleMax - m_fScaledVisibleMin;
149 if (m_rScale.Orientation == chart2::AxisOrientation_MATHEMATICAL)
150 {
151 m_fStretch_LogicToScreen = 1.0/fWidthY;
153 }
154 else
155 {
156 B2DVector aSwap(m_aAxisStartScreenPosition2D);
159
160 m_fStretch_LogicToScreen = -1.0/fWidthY;
162 }
163}
164
166{
167}
168
170{
171 // check trivial cases:
173 return true;
175 return false;
176
177 // for skew axes compare angle with horizontal vector
178 double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(1.0, 0.0)));
179 return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4);
180}
182{
183 // check trivial cases:
185 return true;
187 return false;
188
189 // for skew axes compare angle with vertical vector
190 double fInclination = std::abs(B2DVector(m_aAxisEndScreenPosition2D-m_aAxisStartScreenPosition2D).angle(B2DVector(0.0, -1.0)));
191 return fInclination < M_PI_4 || fInclination > (M_PI-M_PI_4);
192}
193//static
195{
196 //return the positive distance between the two first tickmarks in screen values
197 //if there are less than two tickmarks -1 is returned
198
199 const TickInfo* pFirstTickInfo = rIter.firstInfo();
200 const TickInfo* pSecondTickInfo = rIter.nextInfo();
201 if(!pSecondTickInfo || !pFirstTickInfo)
202 return -1;
203
204 return pFirstTickInfo->getScreenDistanceBetweenTicks( *pSecondTickInfo );
205}
206
207B2DVector TickFactory2D::getTickScreenPosition2D( double fScaledLogicTickValue ) const
208{
209 B2DVector aRet(m_aAxisStartScreenPosition2D);
211 *((fScaledLogicTickValue+m_fOffset_LogicToScreen)*m_fStretch_LogicToScreen);
212 return aRet;
213}
214
215void TickFactory2D::addPointSequenceForTickLine( drawing::PointSequenceSequence& rPoints
216 , sal_Int32 nSequenceIndex
217 , double fScaledLogicTickValue, double fInnerDirectionSign
218 , const TickmarkProperties& rTickmarkProperties
219 , bool bPlaceAtLabels ) const
220{
221 if( fInnerDirectionSign==0.0 )
222 fInnerDirectionSign = 1.0;
223
224 B2DVector aTickScreenPosition = getTickScreenPosition2D(fScaledLogicTickValue);
225 if( bPlaceAtLabels )
226 aTickScreenPosition += m_aAxisLineToLabelLineShift;
227
229 aMainDirection.normalize();
230 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
231 aOrthoDirection *= fInnerDirectionSign;
232 aOrthoDirection.normalize();
233
234 B2DVector aStart = aTickScreenPosition + aOrthoDirection*rTickmarkProperties.RelativePos;
235 B2DVector aEnd = aStart - aOrthoDirection*rTickmarkProperties.Length;
236
237 rPoints.getArray()[nSequenceIndex]
238 = { { static_cast<sal_Int32>(aStart.getX()), static_cast<sal_Int32>(aStart.getY()) },
239 { static_cast<sal_Int32>(aEnd.getX()), static_cast<sal_Int32>(aEnd.getY()) } };
240}
241
242B2DVector TickFactory2D::getDistanceAxisTickToText( const AxisProperties& rAxisProperties, bool bIncludeFarAwayDistanceIfSo, bool bIncludeSpaceBetweenTickAndText ) const
243{
244 bool bFarAwayLabels = false;
245 if( rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_START
246 || rAxisProperties.m_eLabelPos == css::chart::ChartAxisLabelPosition_OUTSIDE_END )
247 bFarAwayLabels = true;
248
249 double fInnerDirectionSign = rAxisProperties.maLabelAlignment.mfInnerTickDirection;
250 if( fInnerDirectionSign==0.0 )
251 fInnerDirectionSign = 1.0;
252
254 aMainDirection.normalize();
255 B2DVector aOrthoDirection(-aMainDirection.getY(),aMainDirection.getX());
256 aOrthoDirection *= fInnerDirectionSign;
257 aOrthoDirection.normalize();
258
259 B2DVector aStart(0,0), aEnd(0,0);
260 if( bFarAwayLabels )
261 {
263 aStart = aOrthoDirection*aProps.RelativePos;
264 aEnd = aStart - aOrthoDirection*aProps.Length;
265 }
266 else
267 {
268 for( sal_Int32 nN=rAxisProperties.m_aTickmarkPropertiesList.size();nN--;)
269 {
270 const TickmarkProperties& rProps = rAxisProperties.m_aTickmarkPropertiesList[nN];
271 B2DVector aNewStart = aOrthoDirection*rProps.RelativePos;
272 B2DVector aNewEnd = aNewStart - aOrthoDirection*rProps.Length;
273 if(aNewStart.getLength()>aStart.getLength())
274 aStart=aNewStart;
275 if(aNewEnd.getLength()>aEnd.getLength())
276 aEnd=aNewEnd;
277 }
278 }
279
280 B2DVector aLabelDirection(aStart);
281 if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
282 aLabelDirection = aEnd;
283
284 B2DVector aOrthoLabelDirection(aOrthoDirection);
285 if (rAxisProperties.maLabelAlignment.mfInnerTickDirection != rAxisProperties.maLabelAlignment.mfLabelDirection)
286 aOrthoLabelDirection*=-1.0;
287 aOrthoLabelDirection.normalize();
288 if( bIncludeSpaceBetweenTickAndText )
289 aLabelDirection += aOrthoLabelDirection*AXIS2D_TICKLABELSPACING;
290 if( bFarAwayLabels && bIncludeFarAwayDistanceIfSo )
291 aLabelDirection += m_aAxisLineToLabelLineShift;
292 return aLabelDirection;
293}
294
295void TickFactory2D::createPointSequenceForAxisMainLine( drawing::PointSequenceSequence& rPoints ) const
296{
297 rPoints.getArray()[0] = { { static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getX()),
298 static_cast<sal_Int32>(m_aAxisStartScreenPosition2D.getY()) },
299 { static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getX()),
300 static_cast<sal_Int32>(m_aAxisEndScreenPosition2D.getY()) } };
301}
302
304{
305 //get the transformed screen values for all tickmarks in rAllTickInfos
306 for (auto & tickInfos : rAllTickInfos)
307 {
308 for (auto & tickInfo : tickInfos)
309 {
310 tickInfo.aTickScreenPosition =
311 getTickScreenPosition2D(tickInfo.fScaledTickValue);
312 }
313 }
314}
315
316} //namespace chart
317
318/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
B2DVector & normalize()
TYPE getX() const
TYPE getY() const
void getAllTicks(TickInfoArraysType &rAllTickInfos) const
void getAllTicksShifted(TickInfoArraysType &rAllTickInfos) const
void getAllTicksShifted(TickInfoArraysType &rAllTickInfos) const
void getAllTicks(TickInfoArraysType &rAllTickInfos) const
virtual ~PureTickIter() override
Definition: Tickmarks.cxx:67
TickInfoArrayType & m_rTickVector
Definition: Tickmarks.hxx:78
virtual TickInfo * nextInfo() override
Definition: Tickmarks.cxx:77
virtual TickInfo * firstInfo() override
Definition: Tickmarks.cxx:70
TickInfoArrayType::iterator m_aTickIter
Definition: Tickmarks.hxx:79
::basegfx::B2DVector m_aAxisEndScreenPosition2D
Definition: Tickmarks.hxx:150
::basegfx::B2DVector getTickScreenPosition2D(double fScaledLogicTickValue) const
Definition: Tickmarks.cxx:207
static sal_Int32 getTickScreenDistance(TickIter &rIter)
Definition: Tickmarks.cxx:194
bool isHorizontalAxis() const
Definition: Tickmarks.cxx:169
void addPointSequenceForTickLine(css::drawing::PointSequenceSequence &rPoints, sal_Int32 nSequenceIndex, double fScaledLogicTickValue, double fInnerDirectionSign, const TickmarkProperties &rTickmarkProperties, bool bPlaceAtLabels) const
Definition: Tickmarks.cxx:215
::basegfx::B2DVector m_aAxisStartScreenPosition2D
Definition: Tickmarks.hxx:149
TickFactory2D(const ExplicitScaleData &rScale, const ExplicitIncrementData &rIncrement, const ::basegfx::B2DVector &rStartScreenPos, const ::basegfx::B2DVector &rEndScreenPos, const ::basegfx::B2DVector &rAxisLineToLabelLineShift)
Definition: Tickmarks.cxx:136
::basegfx::B2DVector getDistanceAxisTickToText(const AxisProperties &rAxisProperties, bool bIncludeFarAwayDistanceIfSo=false, bool bIncludeSpaceBetweenTickAndText=true) const
Definition: Tickmarks.cxx:242
double m_fStretch_LogicToScreen
Definition: Tickmarks.hxx:156
bool isVerticalAxis() const
Definition: Tickmarks.cxx:181
void updateScreenValues(TickInfoArraysType &rAllTickInfos) const
Determine the screen positions of all ticks based on their numeric values.
Definition: Tickmarks.cxx:303
void createPointSequenceForAxisMainLine(css::drawing::PointSequenceSequence &rPoints) const
Definition: Tickmarks.cxx:295
virtual ~TickFactory2D() override
Definition: Tickmarks.cxx:165
::basegfx::B2DVector m_aAxisLineToLabelLineShift
Definition: Tickmarks.hxx:154
double m_fOffset_LogicToScreen
Definition: Tickmarks.hxx:157
double m_fScaledVisibleMax
Definition: Tickmarks.hxx:103
double m_fScaledVisibleMin
Definition: Tickmarks.hxx:102
ExplicitIncrementData m_rIncrement
Definition: Tickmarks.hxx:98
virtual ~TickFactory()
Definition: Tickmarks.cxx:110
css::uno::Reference< css::chart2::XScaling > m_xInverseScaling
Definition: Tickmarks.hxx:99
ExplicitScaleData m_rScale
Definition: Tickmarks.hxx:97
TickFactory(ExplicitScaleData aScale, ExplicitIncrementData aIncrement)
Definition: Tickmarks.cxx:88
bool isDateAxis() const
Definition: Tickmarks.cxx:114
void getAllTicksShifted(TickInfoArraysType &rAllTickInfos) const
Definition: Tickmarks.cxx:127
void getAllTicks(TickInfoArraysType &rAllTickInfos) const
Definition: Tickmarks.cxx:119
virtual TickInfo * nextInfo()=0
virtual TickInfo * firstInfo()=0
std::vector< TickInfoArrayType > TickInfoArraysType
Definition: Tickmarks.hxx:59
const sal_Int32 AXIS2D_TICKLABELSPACING
Definition: ViewDefines.hxx:31
std::vector< TickInfo > TickInfoArrayType
Definition: Tickmarks.hxx:58
enumrange< T >::Iterator begin(enumrange< T >)
double mfInnerTickDirection
which direction the labels are to be drawn.
static TickmarkProperties getBiggestTickmarkProperties()
AxisLabelAlignment maLabelAlignment
std::vector< TickmarkProperties > m_aTickmarkPropertiesList
css::chart::ChartAxisLabelPosition m_eLabelPos
describes how tickmarks are positioned on the scale of an axis.
This structure contains the explicit values for a scale like Minimum and Maximum.
css::uno::Reference< css::chart2::XScaling > Scaling
css::chart2::AxisOrientation Orientation
sal_Int32 getScreenDistanceBetweenTicks(const TickInfo &rOherTickInfo) const
Definition: Tickmarks.cxx:51
::basegfx::B2DVector aTickScreenPosition
Definition: Tickmarks.hxx:41
TickInfo()=delete
o3tl::enumarray< SvxBoxItemLine, sal_uInt16 > aDistance