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." );
94 if( target_steps > 0 ) {
96 auto interval_size = max - min;
97 auto step_sz =
step_size( interval_size, target_steps );
101 auto tick = step_sz * std::floor( min / step_sz );
109 while( tick <= max ) {
110 res.push_back( tick );
116 res.push_back( tick );
122 res.push_back( min );
125 res.push_back( max );
131 std::sort( res.begin(), res.end() );
132 auto uniq_end = std::unique( res.begin(), res.end(), [&](
double lhs,
double rhs ){
133 return almost_equal_relative( lhs, rhs, relative_epsilon );
135 res.erase( uniq_end, res.end() );
141 double min,
double max,
size_t target_steps
143 auto res = std::vector<LabeledTick>();
146 auto range = max - min;
148 for(
auto const& tick : ticks ) {
149 auto rel_pos = ( tick - min ) / range;
150 res.emplace_back( rel_pos, tick );
157 auto res = std::vector<LabeledTick>();
160 throw std::runtime_error(
"Cannot calculate logarithmic scale for negative values." );
163 throw std::runtime_error(
"Cannot calculate scale with min >= max." );
166 throw std::runtime_error(
"Cannot calculate logarithmic scale with negative base." );
170 double exp_i = std::floor( std::log( min ) / std::log( base ) );
178 auto const lg_min = std::log( min ) / std::log( base );
179 auto const lg_max = std::log( max ) / std::log( base );
184 while( exp_i <= lim ) {
185 auto const rel_pos = ( exp_i - lg_min ) / ( lg_max - lg_min );
186 res.emplace_back( rel_pos, std::pow( base, exp_i ) );
194 res.emplace_back( 0.0, min );
197 res.emplace_back( 1.0, max );
204 return lhs.relative_position < rhs.relative_position;
206 auto uniq_end = std::unique( res.begin(), res.end(),
208 return almost_equal_relative(
209 lhs.relative_position,
210 rhs.relative_position,
215 res.erase( uniq_end, res.end() );