25#include <com/sun/star/chart/TimeUnit.hpp>
26#include <com/sun/star/chart2/AxisType.hpp>
28#include <rtl/math.hxx>
36using ::com::sun::star::chart::TimeUnit::DAY;
37using ::com::sun::star::chart::TimeUnit::MONTH;
38using ::com::sun::star::chart::TimeUnit::YEAR;
45 sal_Int32 nMaximumAutoIncrementCount = 10;
46 if( nAxisType==AxisType::DATE )
48 return nMaximumAutoIncrementCount;
54void lcl_ensureMaximumSubIncrementCount( sal_Int32& rnSubIntervalCount )
66 ,
Orientation(css::chart2::AxisOrientation_MATHEMATICAL)
68 , m_bShiftedCategoryPosition(false)
69 , TimeResolution(css::
chart::TimeUnit::
DAY)
70 , NullDate(30,12,1899)
76 , PostEquidistant(true)
81 : MajorTimeInterval(1,css::
chart::TimeUnit::
DAY)
82 , MinorTimeInterval(1,css::
chart::TimeUnit::
DAY)
84 , PostEquidistant(true)
90 : m_aSourceScale( rSourceScale )
91 , m_fValueMinimum( 0.0 )
92 , m_fValueMaximum( 0.0 )
94 , m_bExpandBorderToIncrementRhythm( false )
95 , m_bExpandIfValuesCloseToBorder( false )
96 , m_bExpandWideValuesToZero( false )
97 , m_bExpandNarrowValuesTowardZero( false )
98 , m_nTimeResolution(css::
chart::TimeUnit::
DAY)
99 , m_aNullDate(rNullDate)
103 double fExplicitOrigin = 0.0;
128 bool bExpandBorderToIncrementRhythm,
129 bool bExpandIfValuesCloseToBorder,
130 bool bExpandWideValuesToZero,
131 bool bExpandNarrowValuesTowardZero )
145 if( nMaximumAutoMainIncrementCount < 2 )
179 rExplicitScale.
Minimum = 36526.0;
195 rExplicitScale.
Maximum = 40179.0;
206 bool bIsLogarithm =
false;
226 double fDefaulOrigin = bIsLogarithm ? 1.0 : 0.0;
228 if( fDefaulOrigin < rExplicitScale.
Minimum )
229 fDefaulOrigin = rExplicitScale.
Minimum;
230 else if( fDefaulOrigin > rExplicitScale.
Maximum )
231 fDefaulOrigin = rExplicitScale.
Maximum;
233 rExplicitScale.
Origin = fDefaulOrigin;
240 bool bAutoMinimum,
bool bAutoMaximum )
const
243 rExplicitScale.
Scaling.clear();
264 double fDistanceCount = ::rtl::math::approxFloor( (rExplicitScale.
Maximum-rExplicitScale.
Minimum) / rExplicitIncrement.
Distance );
267 double fMinimumFloor = ::rtl::math::approxFloor( rExplicitScale.
Minimum );
268 double fMaximumCeil = ::rtl::math::approxCeil( rExplicitScale.
Maximum );
273 sal_Int32 nSubCount =
m_aSourceScale.IncrementData.SubIncrements.getLength();
274 for( sal_Int32 nN=0; nN<nSubCount; nN++ )
277 const SubIncrement& rSubIncrement=
m_aSourceScale.IncrementData.SubIncrements[nN];
278 if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.
IntervalCount))
284 lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.
IntervalCount );
285 if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.
PostEquidistant))
290 rExplicitIncrement.
SubIncrements.push_back(aExplicitSubIncrement);
297 bool bAutoMinimum,
bool bAutoMaximum )
const
301 const double fInputMinimum = rExplicitScale.
Minimum;
302 const double fInputMaximum = rExplicitScale.
Maximum;
304 double fSourceMinimum = rExplicitScale.
Minimum;
305 double fSourceMaximum = rExplicitScale.
Maximum;
319 fSourceMinimum = xScaling->doScaling( fSourceMinimum );
320 if( !std::isfinite( fSourceMinimum ) )
321 fSourceMinimum = 0.0;
322 else if( ::rtl::math::approxEqual( fSourceMinimum, ::rtl::math::approxFloor( fSourceMinimum ) ) )
323 fSourceMinimum = ::rtl::math::approxFloor( fSourceMinimum );
325 fSourceMaximum = xScaling->doScaling( fSourceMaximum );
326 if( !std::isfinite( fSourceMaximum ) )
327 fSourceMaximum = 0.0;
328 else if( ::rtl::math::approxEqual( fSourceMaximum, ::rtl::math::approxFloor( fSourceMaximum ) ) )
329 fSourceMaximum = ::rtl::math::approxFloor( fSourceMaximum );
334 if( fSourceMinimum > fSourceMaximum )
337 if( bAutoMaximum || !bAutoMinimum )
338 fSourceMaximum = fSourceMinimum;
340 fSourceMinimum = fSourceMaximum;
349 bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
350 if( bSwapAndNegateRange )
352 double fTempValue = fSourceMinimum;
353 fSourceMinimum = -fSourceMaximum;
354 fSourceMaximum = -fTempValue;
355 std::swap( bAutoMinimum, bAutoMaximum );
360 double fTempMinimum = fSourceMinimum;
361 double fTempMaximum = fSourceMaximum;
366 if( bAutoMinimum && (fTempMinimum > 0.0) )
368 double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
369 double fMaximumFloor = ::rtl::math::approxFloor( fTempMaximum );
371 if( ::rtl::math::approxEqual( fTempMaximum, fMaximumFloor ) )
372 fMaximumFloor -= 1.0;
374 if( fMinimumFloor == fMaximumFloor )
385 if( fTempMinimum == fTempMaximum )
387 if( bAutoMinimum && (fTempMaximum > 0.0) )
401 rExplicitIncrement.
BaseValue = fTempMinimum;
402 else if( !bAutoMaximum )
403 rExplicitIncrement.
BaseValue = fTempMaximum;
415 sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
419 bool bNeedIteration =
true;
420 bool bHasCalculatedDistance =
false;
421 while( bNeedIteration )
426 if( !bHasCalculatedDistance )
428 double fMinimumFloor = ::rtl::math::approxFloor( fTempMinimum );
429 double fMaximumCeil = ::rtl::math::approxCeil( fTempMaximum );
430 rExplicitIncrement.
Distance = ::rtl::math::approxCeil( (fMaximumCeil - fMinimumFloor) / nMaxMainIncrementCount );
439 bHasCalculatedDistance =
true;
444 double fAxisMinimum = fTempMinimum;
445 double fAxisMaximum = fTempMaximum;
455 double fCheck = xInverseScaling->doScaling( fAxisMinimum );
456 if( !std::isfinite( fCheck ) || fCheck <= 0 )
458 bAutoDistance =
true;
459 bHasCalculatedDistance =
false;
471 double fCheck = xInverseScaling->doScaling( fAxisMaximum );
472 if( !std::isfinite( fCheck ) || fCheck <= 0 )
474 bAutoDistance =
true;
475 bHasCalculatedDistance =
false;
482 if( bSwapAndNegateRange )
484 rExplicitScale.
Minimum = -fAxisMaximum;
485 rExplicitScale.
Maximum = -fAxisMinimum;
489 rExplicitScale.
Minimum = fAxisMinimum;
490 rExplicitScale.
Maximum = fAxisMaximum;
496 double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.
Distance );
497 bNeedIteration =
static_cast< sal_Int32
>( fDistanceCount ) > nMaxMainIncrementCount;
500 bAutoDistance =
true;
503 rExplicitScale.
Minimum = xInverseScaling->doScaling( rExplicitScale.
Minimum );
504 rExplicitScale.
Maximum = xInverseScaling->doScaling( rExplicitScale.
Maximum );
507 if( !std::isfinite( rExplicitScale.
Minimum ) || rExplicitScale.
Minimum <= 0)
509 rExplicitScale.
Minimum = fInputMinimum;
510 if( !std::isfinite( rExplicitScale.
Minimum ) || rExplicitScale.
Minimum <= 0 )
513 if( !std::isfinite( rExplicitScale.
Maximum) || rExplicitScale.
Maximum <= 0 )
515 rExplicitScale.
Maximum= fInputMaximum;
516 if( !std::isfinite( rExplicitScale.
Maximum) || rExplicitScale.
Maximum <= 0 )
524 sal_Int32 nSubCount =
m_aSourceScale.IncrementData.SubIncrements.getLength();
525 for( sal_Int32 nN=0; nN<nSubCount; nN++ )
528 const SubIncrement& rSubIncrement =
m_aSourceScale.IncrementData.SubIncrements[nN];
529 if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.
IntervalCount))
535 lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.
IntervalCount );
536 if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.
PostEquidistant))
541 rExplicitIncrement.
SubIncrements.push_back(aExplicitSubIncrement);
548 bool bAutoMinimum,
bool bAutoMaximum )
const
554 if( aMinDate > aMaxDate )
556 std::swap(aMinDate,aMaxDate);
578 if( bAutoMaximum || !bAutoMinimum )
593 if( bAutoMaximum || !bAutoMinimum )
608 sal_Int32 nMaxMainIncrementCount = bAutoMajor ?
610 if( nMaxMainIncrementCount > 1 )
611 nMaxMainIncrementCount--;
626 nIntervalDayCount*=31;
629 nIntervalDayCount*=365;
632 nMainIncrementCount = nDayCount/nIntervalDayCount;
633 if( nMainIncrementCount > nMaxMainIncrementCount )
639 tools::Long nIntervalDays = nDayCount / nMaxMainIncrementCount;
640 double nDaysPerInterval = 1.0;
644 nDaysPerInterval = 365.0;
649 nDaysPerInterval = 31.0;
654 nDaysPerInterval = 1.0;
657 nNumer =
static_cast<sal_Int32
>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) );
662 if( nNumer>2 && nNumer<7 )
667 nDaysPerInterval = 31.0;
668 nNumer =
static_cast<sal_Int32
>( rtl::math::approxFloor( nIntervalDays/nDaysPerInterval ) );
674 nMainIncrementCount =
static_cast<tools::Long>(nDayCount/(nNumer*nDaysPerInterval));
688 nIntervalDayCount*=31;
691 nIntervalDayCount*=365;
694 if( nDayCount/nIntervalDayCount > nMaxMainIncrementCount )
702 if( nMainIncrementCount > 100 )
740 bool bAutoMinimum,
bool bAutoMaximum )
const
744 double fSourceMinimum = rExplicitScale.
Minimum;
745 double fSourceMaximum = rExplicitScale.
Maximum;
754 if( fSourceMinimum > fSourceMaximum )
757 if( bAutoMaximum || !bAutoMinimum )
758 fSourceMaximum = fSourceMinimum;
760 fSourceMinimum = fSourceMaximum;
769 bool bSwapAndNegateRange = (fSourceMinimum < 0.0) && (fSourceMaximum <= 0.0);
770 if( bSwapAndNegateRange )
772 double fTempValue = fSourceMinimum;
773 fSourceMinimum = -fSourceMaximum;
774 fSourceMaximum = -fTempValue;
775 std::swap( bAutoMinimum, bAutoMaximum );
780 double fTempMinimum = fSourceMinimum;
781 double fTempMaximum = fSourceMaximum;
786 if( bAutoMinimum && (fTempMinimum > 0.0) )
790 if( (fTempMinimum == fTempMaximum) || (fTempMinimum / fTempMaximum < 5.0 / 6.0) )
801 fTempMinimum -= (fTempMaximum - fTempMinimum) / 2.0;
807 if( fTempMinimum == fTempMaximum )
809 if( bAutoMaximum || !bAutoMinimum )
812 if( fTempMaximum == 0.0 )
820 if( fTempMinimum == 0.0 )
833 rExplicitIncrement.
BaseValue = fTempMinimum;
834 else if( !bAutoMaximum )
835 rExplicitIncrement.
BaseValue = fTempMaximum;
844 sal_Int32 nMaxMainIncrementCount = bAutoDistance ?
847 double fDistanceMagnitude = 0.0;
848 double fDistanceNormalized = 0.0;
849 bool bHasNormalizedDistance =
false;
852 bool bNeedIteration =
true;
853 while( bNeedIteration )
858 if( !bHasNormalizedDistance )
861 double fDistance = (fTempMaximum - fTempMinimum) / nMaxMainIncrementCount;
864 if( fDistance <= 1.0e-307 )
866 fDistanceNormalized = 1.0;
867 fDistanceMagnitude = 1.0e-307;
869 else if ( !std::isfinite(fDistance) )
872 fDistanceNormalized = 1.0;
873 fDistanceMagnitude = std::numeric_limits<double>::max();
878 int nExponent =
static_cast< int >( ::rtl::math::approxFloor( log10( fDistance ) ) );
879 fDistanceMagnitude = ::rtl::math::pow10Exp( 1.0, nExponent );
882 fDistanceNormalized = fDistance / fDistanceMagnitude;
883 if( fDistanceNormalized <= 1.0 )
884 fDistanceNormalized = 1.0;
885 else if( fDistanceNormalized <= 2.0 )
886 fDistanceNormalized = 2.0;
887 else if( fDistanceNormalized <= 5.0 )
888 fDistanceNormalized = 5.0;
891 fDistanceNormalized = 1.0;
892 fDistanceMagnitude *= 10;
896 bHasNormalizedDistance =
true;
901 if( fDistanceNormalized == 1.0 )
902 fDistanceNormalized = 2.0;
903 else if( fDistanceNormalized == 2.0 )
904 fDistanceNormalized = 5.0;
907 fDistanceNormalized = 1.0;
908 fDistanceMagnitude *= 10;
913 rExplicitIncrement.
Distance = fDistanceNormalized * fDistanceMagnitude;
918 double fAxisMinimum = fTempMinimum;
919 double fAxisMaximum = fTempMaximum;
929 if( (fAxisMinimum != 0.0) && ((fAxisMaximum - fSourceMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) )
930 fAxisMinimum -= rExplicitIncrement.
Distance;
939 if( (fAxisMaximum != 0.0) && ((fSourceMaximum - fAxisMinimum) / (fAxisMaximum - fAxisMinimum) > 20.0 / 21.0) )
940 fAxisMaximum += rExplicitIncrement.
Distance;
944 if( bSwapAndNegateRange )
946 rExplicitScale.
Minimum = -fAxisMaximum;
947 rExplicitScale.
Maximum = -fAxisMinimum;
951 rExplicitScale.
Minimum = fAxisMinimum;
952 rExplicitScale.
Maximum = fAxisMaximum;
958 double fDistanceCount = ::rtl::math::approxFloor( (fAxisMaximum - fAxisMinimum) / rExplicitIncrement.
Distance );
959 bNeedIteration =
static_cast< sal_Int32
>( fDistanceCount ) > nMaxMainIncrementCount;
962 bAutoDistance =
true;
966 sal_Int32 nSubCount =
m_aSourceScale.IncrementData.SubIncrements.getLength();
967 for( sal_Int32 nN=0; nN<nSubCount; nN++ )
970 const SubIncrement& rSubIncrement=
m_aSourceScale.IncrementData.SubIncrements[nN];
971 if(!(rSubIncrement.IntervalCount>>=aExplicitSubIncrement.
IntervalCount))
977 lcl_ensureMaximumSubIncrementCount( aExplicitSubIncrement.
IntervalCount );
978 if(!(rSubIncrement.PostEquidistant>>=aExplicitSubIncrement.
PostEquidistant))
983 rExplicitIncrement.
SubIncrements.push_back(aExplicitSubIncrement);
void AddDays(sal_Int32 nAddDays)
void SetMonth(sal_uInt16 nNewMonth)
void SetDay(sal_uInt16 nNewDay)
static bool isLogarithmic(const css::uno::Reference< css::chart2::XScaling > &xScaling)
static css::uno::Reference< css::chart2::XScaling > createLogarithmicScaling(double fBase=10.0)
static Date GetDateSomeYearsAway(const Date &rD, sal_Int32 nYearDistance)
static Date GetDateSomeMonthsAway(const Date &rD, sal_Int32 nMonthDistance)
static bool IsLessThanOneYearAway(const Date &rD1, const Date &rD2)
static bool IsLessThanOneMonthAway(const Date &rD1, const Date &rD2)
static double getMinimumAtIncrement(double fMin, const ExplicitIncrementData &rIncrement)
static double getMaximumAtIncrement(double fMax, const ExplicitIncrementData &rIncrement)
void calculateExplicitIncrementAndScaleForLinear(ExplicitScaleData &rExplicitScale, ExplicitIncrementData &rExplicitIncrement, bool bAutoMinimum, bool bAutoMaximum) const
Fills the passed scale data and increment data for linear scaling.
ScaleAutomatism(const css::chart2::ScaleData &rSourceScale, const Date &rNullDate)
bool m_bExpandBorderToIncrementRhythm
Maximum number of automatic main increments.
void calculateExplicitScaleAndIncrement(ExplicitScaleData &rExplicitScale, ExplicitIncrementData &rExplicitIncrement) const
Fills the passed scale data and increment data according to the own settings.
sal_Int32 m_nTimeResolution
true = Expand narrow range toward zero (add half of range).
void calculateExplicitIncrementAndScaleForDateTimeAxis(ExplicitScaleData &rExplicitScale, ExplicitIncrementData &rExplicitIncrement, bool bAutoMinimum, bool bAutoMaximum) const
Fills the passed scale data and increment data for date-time axis.
void setAutoScalingOptions(bool bExpandBorderToIncrementRhythm, bool bExpandIfValuesCloseToBorder, bool bExpandWideValuesToZero, bool bExpandNarrowValuesTowardZero)
Sets additional auto scaling options.
void calculateExplicitIncrementAndScaleForCategory(ExplicitScaleData &rExplicitScale, ExplicitIncrementData &rExplicitIncrement, bool bAutoMinimum, bool bAutoMaximum) const
Fills the passed scale data and increment data for category scaling.
void calculateExplicitIncrementAndScaleForLogarithmic(ExplicitScaleData &rExplicitScale, ExplicitIncrementData &rExplicitIncrement, bool bAutoMinimum, bool bAutoMaximum) const
Fills the passed scale data and increment data for logarithmic scaling.
void setMaximumAutoMainIncrementCount(sal_Int32 nMaximumAutoMainIncrementCount)
Sets the maximum allowed number of automatic main increments.
bool m_bExpandNarrowValuesTowardZero
true = Expand wide spread values to zero.
sal_Int32 m_nMaximumAutoMainIncrementCount
Maximum of all source values.
bool m_bExpandWideValuesToZero
true = Expand if values are too close to the borders.
void setAutomaticTimeResolution(sal_Int32 nTimeResolution)
Sets the time resolution to be used in case it is not set explicitly within the scale.
bool m_bExpandIfValuesCloseToBorder
true = Expand to main increments.
void expandValueRange(double fMinimum, double fMaximum)
Expands own value range with the passed minimum and maximum.
double m_fValueMaximum
Minimum of all source values.
css::chart2::ScaleData m_aSourceScale
static sal_Int32 lcl_getMaximumAutoIncrementCount(sal_Int32 nAxisType)
const sal_Int32 MAXIMUM_MANUAL_INCREMENT_COUNT
const sal_Int32 MAXIMUM_SUB_INCREMENT_COUNT
describes how tickmarks are positioned on the scale of an axis.
std::vector< ExplicitSubIncrement > SubIncrements
<member>SubIncrements</member> describes the positioning of further sub tickmarks on the scale of an ...
double Distance
the other members are for not date-time axis
css::chart::TimeInterval MajorTimeInterval
the following two members are only for date-time axis
css::chart::TimeInterval MinorTimeInterval
bool PostEquidistant
<member>PostEquidistant</member> rules whether the member <member>Distance</member> describes a dista...
double BaseValue
The <member>BaseValue</member> gives a starting point on the scale to which all further main tickmark...
This structure contains the explicit values for a scale like Minimum and Maximum.
css::uno::Reference< css::chart2::XScaling > Scaling
css::chart2::AxisOrientation Orientation
bool m_bShiftedCategoryPosition
sal_Int32 IntervalCount
Numbers of intervals between two superior ticks.
bool PostEquidistant
If <TRUE>, the distance between two sub-tick-marks on the screen is always the same.