Changeset - r15043:7fa98651a1ef
[Not reviewed]
master
0 1 0
terkhen - 14 years ago 2010-04-18 20:23:35
terkhen@openttd.org
(svn r19673) -Codechange: Optimize calculation of graph grid size (method by Alberth).
-Fix: Remove a gcc 3.3 warning.
1 file changed with 14 insertions and 32 deletions:
0 comments (0 inline, 0 general)
src/graph_gui.cpp
Show inline comments
 
@@ -2,49 +2,48 @@
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file graph_gui.cpp GUI that shows performance graphs. */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "graph_gui.h"
 
#include "window_gui.h"
 
#include "company_base.h"
 
#include "company_gui.h"
 
#include "economy_func.h"
 
#include "cargotype.h"
 
#include "strings_func.h"
 
#include "window_func.h"
 
#include "date_func.h"
 
#include "gfx_func.h"
 
#include "sortlist_type.h"
 
#include "core/geometry_func.hpp"
 
#include <math.h>
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 

	
 
/* Bitmasks of company and cargo indices that shouldn't be drawn. */
 
static uint _legend_excluded_companies;
 
static uint _legend_excluded_cargo;
 

	
 
/* Apparently these don't play well with enums. */
 
static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
 
static const uint INVALID_DATAPOINT_POS = UINT_MAX;  // Used to determine if the previous point was drawn.
 

	
 
/****************/
 
/* GRAPH LEGEND */
 
/****************/
 

	
 
/** Widget numbers of the graph legend window. */
 
enum GraphLegendWidgetNumbers {
 
	GLW_BACKGROUND,
 

	
 
	GLW_FIRST_COMPANY,
 
	GLW_LAST_COMPANY = GLW_FIRST_COMPANY + MAX_COMPANIES - 1,
 
};
 

	
 
@@ -219,81 +218,64 @@ protected:
 

	
 
		for (int i = 0; i < this->num_dataset; i++) {
 
			if (HasBit(this->excluded_data, i)) continue;
 
			for (int j = 0; j < this->num_on_x_axis; j++) {
 
				OverflowSafeInt64 datapoint = this->cost[i][j];
 

	
 
				if (datapoint != INVALID_DATAPOINT) {
 
					current_interval.highest = max(current_interval.highest, datapoint);
 
					current_interval.lowest  = min(current_interval.lowest, datapoint);
 
				}
 
			}
 
		}
 

	
 
		/* Prevent showing values too close to the graph limits. */
 
		current_interval.highest = (11 * current_interval.highest) / 10;
 
		current_interval.lowest =  (11 * current_interval.lowest) / 10;
 

	
 
		/* Always include zero in the shown range. */
 
		OverflowSafeInt64 abs_lower  = (current_interval.lowest > 0) ? (OverflowSafeInt64)0 : abs(current_interval.lowest);
 
		OverflowSafeInt64 abs_higher = (current_interval.highest < 0) ? (OverflowSafeInt64)0 : current_interval.highest;
 

	
 
		int num_pos_grids;
 
		int grid_size;
 

	
 
		if (abs_lower == 0) {
 
			if (abs_higher == 0) {
 
				/* If both values are zero, show an empty graph. */
 
				num_pos_grids = num_hori_lines / 2;
 
				grid_size = 1;
 
			} else {
 
				/* The positive part of the graph can use all grids. */
 
				num_pos_grids = num_hori_lines;
 
				grid_size = ceil((float)abs_higher / num_hori_lines);
 
			}
 
		if (abs_lower != 0 || abs_higher != 0) {
 
			/* The number of grids to reserve for the positive part is: */
 
			num_pos_grids = RoundDivSU(abs_higher * num_hori_lines, abs_higher + abs_lower);
 

	
 
			/* If there are any positive or negative values, force that they have at least one grid. */
 
			if (num_pos_grids == 0 && abs_higher != 0) num_pos_grids++;
 
			if (num_pos_grids == num_hori_lines && abs_lower != 0) num_pos_grids--;
 

	
 
			/* Get the required grid size for each side and use the maximum one. */
 
			int grid_size_higher = (abs_higher > 0) ? (int)(abs_higher + num_pos_grids - 1) / num_pos_grids : 0;
 
			int grid_size_lower = (abs_lower > 0) ? (int)(abs_lower + num_hori_lines - num_pos_grids - 1) / (num_hori_lines - num_pos_grids) : 0;
 
			grid_size = max(grid_size_higher, grid_size_lower);
 
		} else {
 
			if (abs_higher == 0) {
 
				/* The negative part of the graph can use all grids. */
 
				num_pos_grids = 0;
 
				grid_size = ceil((float)abs_lower / num_hori_lines);
 
			} else {
 
				/* Get the smallest grid size required and the number of grids for each part of the graph. */
 
				int min_pos_grids = 1;
 
				int min_grid_size = INT_MAX;
 
				for (num_pos_grids = 1; num_pos_grids <= num_hori_lines - 1; num_pos_grids++) {
 
					/* Size required for each part of the graph given this number of grids. */
 
					int pos_grid_size = ceil((float)abs_higher / num_pos_grids);
 
					int neg_grid_size = ceil((float)abs_lower / (num_hori_lines - num_pos_grids));
 
					grid_size = max(pos_grid_size, neg_grid_size);
 
					if (grid_size < min_grid_size) {
 
						min_pos_grids = num_pos_grids;
 
						min_grid_size = grid_size;
 
					}
 
				}
 
				grid_size = min_grid_size;
 
				num_pos_grids = min_pos_grids;
 
			}
 
			/* If both values are zero, show an empty graph. */
 
			num_pos_grids = num_hori_lines / 2;
 
			grid_size = 1;
 
		}
 

	
 
		current_interval.highest = num_pos_grids * grid_size;
 
		current_interval.lowest = -(num_hori_lines - num_pos_grids) * grid_size;
 
		return current_interval;
 
	}
 

	
 
	/** Get width for Y labels.
 
	 * @param current_interval Interval that contains all of the graph data.
 
	 * @param num_hori_lines Number of horizontal lines to be drawn.
 
	 */
 
	uint GetYLabelWidth(ValuesInterval current_interval, int num_hori_lines) const
 
	{
 
		/* draw text strings on the y axis */
 
		int64 y_label = current_interval.highest;
 
		int64 y_label_separation = (current_interval.highest - current_interval.lowest) / num_hori_lines;
 

	
 
		uint max_width = 0;
 

	
 
		for (int i = 0; i < (num_hori_lines + 1); i++) {
 
			SetDParam(0, this->format_str_y_axis);
 
			SetDParam(1, y_label);
 
			Dimension d = GetStringBoundingBox(STR_GRAPH_Y_LABEL);
 
			if (d.width > max_width) max_width = d.width;
0 comments (0 inline, 0 general)