* Get the interval that contains the graph's data. Excluded data is ignored to show smaller values in * better detail when disabling higher ones. * @param num_hori_lines Number of horizontal lines to be drawn. * @return Highest and lowest values of the graph (ignoring disabled data). */
| 275 | * @return Highest and lowest values of the graph (ignoring disabled data). |
| 276 | */ |
| 277 | ValuesInterval GetValuesInterval(int num_hori_lines) const |
| 278 | { |
| 279 | assert(num_hori_lines > 0); |
| 280 | |
| 281 | ValuesInterval current_interval; |
| 282 | current_interval.highest = INT64_MIN; |
| 283 | current_interval.lowest = INT64_MAX; |
| 284 | |
| 285 | for (const DataSet &dataset : this->data) { |
| 286 | if (HasBit(this->excluded_data, dataset.exclude_bit)) continue; |
| 287 | if (HasBit(this->excluded_range, dataset.range_bit)) continue; |
| 288 | |
| 289 | for (const OverflowSafeInt64 &datapoint : this->GetDataSetRange(dataset)) { |
| 290 | if (datapoint != INVALID_DATAPOINT) { |
| 291 | current_interval.highest = std::max(current_interval.highest, datapoint); |
| 292 | current_interval.lowest = std::min(current_interval.lowest, datapoint); |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | /* Always include zero in the shown range. */ |
| 298 | double abs_lower = (current_interval.lowest > 0) ? 0 : (double)abs(current_interval.lowest); |
| 299 | double abs_higher = (current_interval.highest < 0) ? 0 : (double)current_interval.highest; |
| 300 | |
| 301 | /* Prevent showing values too close to the graph limits. */ |
| 302 | abs_higher = (11.0 * abs_higher) / 10.0; |
| 303 | abs_lower = (11.0 * abs_lower) / 10.0; |
| 304 | |
| 305 | int num_pos_grids; |
| 306 | OverflowSafeInt64 grid_size; |
| 307 | |
| 308 | if (abs_lower != 0 || abs_higher != 0) { |
| 309 | /* The number of grids to reserve for the positive part is: */ |
| 310 | num_pos_grids = (int)floor(0.5 + num_hori_lines * abs_higher / (abs_higher + abs_lower)); |
| 311 | |
| 312 | /* If there are any positive or negative values, force that they have at least one grid. */ |
| 313 | if (num_pos_grids == 0 && abs_higher != 0) num_pos_grids++; |
| 314 | if (num_pos_grids == num_hori_lines && abs_lower != 0) num_pos_grids--; |
| 315 | |
| 316 | /* Get the required grid size for each side and use the maximum one. */ |
| 317 | |
| 318 | OverflowSafeInt64 grid_size_higher = 0; |
| 319 | if (abs_higher > 0) { |
| 320 | grid_size_higher = abs_higher > INT64_MAX_IN_DOUBLE ? INT64_MAX : static_cast<int64_t>(abs_higher); |
| 321 | grid_size_higher = (grid_size_higher + num_pos_grids - 1) / num_pos_grids; |
| 322 | } |
| 323 | |
| 324 | OverflowSafeInt64 grid_size_lower = 0; |
| 325 | if (abs_lower > 0) { |
| 326 | grid_size_lower = abs_lower > INT64_MAX_IN_DOUBLE ? INT64_MAX : static_cast<int64_t>(abs_lower); |
| 327 | grid_size_lower = (grid_size_lower + num_hori_lines - num_pos_grids - 1) / (num_hori_lines - num_pos_grids); |
| 328 | } |
| 329 | |
| 330 | grid_size = std::max(grid_size_higher, grid_size_lower); |
| 331 | } else { |
| 332 | /* If both values are zero, show an empty graph. */ |
| 333 | num_pos_grids = num_hori_lines / 2; |
| 334 | grid_size = 1; |
nothing calls this directly
no test coverage detected