52 if( target_steps == 0 ) {
53 throw std::invalid_argument(
"Cannot calculate tickmark step size for 0 steps." );
55 if( interval_size <= 0.0 ) {
56 throw std::invalid_argument(
"Cannot calculate tickmark step size for negative intervals." );
60 auto const step_guess = interval_size /
static_cast<double>( target_steps );
63 auto const mag = std::floor( std::log10( step_guess ));
64 auto const mag_pow = std::pow( 10, mag );
67 auto mag_msd =
static_cast<int>( step_guess / mag_pow + 0.5 );
72 }
else if( mag_msd > 2 ) {
74 }
else if( mag_msd > 1 ) {
77 assert( mag_msd == 1 );
80 return static_cast<double>( mag_msd ) * mag_pow;
86 auto res = std::vector<double>();
89 throw std::runtime_error(
"Cannot calculate scale with max < min." );
91 auto const interval_size = max - min;
98 auto const rounding_accuracy = 15;
102 if( target_steps > 0 ) {
104 auto const step_sz =
step_size( interval_size, target_steps );
108 auto tick = step_sz * std::floor( min / step_sz );
116 while( tick <= max ) {
117 res.push_back(
round_to( tick, rounding_accuracy ));
123 res.push_back(
round_to( tick, rounding_accuracy ));
129 res.push_back(
round_to( min, rounding_accuracy ));
132 res.push_back(
round_to( max, rounding_accuracy ));
138 std::sort( res.begin(), res.end() );
139 auto uniq_end = std::unique( res.begin(), res.end(), [&](
double lhs,
double rhs ){
140 return almost_equal_relative( lhs, rhs, relative_epsilon );
142 res.erase( uniq_end, res.end() );
148 double min,
double max,
size_t target_steps
150 auto res = std::vector<LabeledTick>();
153 auto range = max - min;
155 for(
auto const& tick : ticks ) {
156 auto rel_pos = ( tick - min ) / range;
157 res.emplace_back( rel_pos, tick );
164 auto res = std::vector<LabeledTick>();
167 throw std::runtime_error(
"Cannot calculate logarithmic scale for negative values." );
170 throw std::runtime_error(
"Cannot calculate scale with min >= max." );
173 throw std::runtime_error(
"Cannot calculate logarithmic scale with negative base." );
177 double exp_i = std::floor( std::log( min ) / std::log( base ) );
185 auto const lg_min = std::log( min ) / std::log( base );
186 auto const lg_max = std::log( max ) / std::log( base );
191 while( exp_i <= lim ) {
192 auto const rel_pos = ( exp_i - lg_min ) / ( lg_max - lg_min );
193 res.emplace_back( rel_pos, std::pow( base, exp_i ) );
201 res.emplace_back( 0.0, min );
204 res.emplace_back( 1.0, max );
211 return lhs.relative_position < rhs.relative_position;
213 auto uniq_end = std::unique( res.begin(), res.end(),
215 return almost_equal_relative(
216 lhs.relative_position,
217 rhs.relative_position,
222 res.erase( uniq_end, res.end() );