Changeset - r24193:cc815a8a1615
[Not reviewed]
master
0 7 0
dP - 4 years ago 2020-05-11 22:36:28
dp@dpointer.org
Codechange: Refactor FindStationsAroundTiles to avoid code duplication
7 files changed with 61 insertions and 75 deletions:
0 comments (0 inline, 0 general)
src/industry_cmd.cpp
Show inline comments
 
@@ -1697,20 +1697,10 @@ static void PopulateStationsNearby(Indus
 
		return;
 
	}
 

	
 
	/* Get our list of nearby stations. */
 
	FindStationsAroundTiles(ind->location, &ind->stations_near, false);
 

	
 
	/* Test if industry can accept cargo */
 
	uint cargo_index;
 
	for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
 
		if (ind->accepts_cargo[cargo_index] != CT_INVALID) break;
 
	}
 
	if (cargo_index >= lengthof(ind->accepts_cargo)) return;
 

	
 
	/* Cargo is accepted, add industry to nearby stations nearby industry list. */
 
	for (Station *st : ind->stations_near) {
 
		st->industries_near.insert(ind);
 
	}
 
	ForAllStationsAroundTiles(ind->location, [ind](Station *st) {
 
		ind->stations_near.insert(st);
 
		st->AddIndustryToDeliver(ind);
 
	});
 
}
 

	
 
/**
src/station.cpp
Show inline comments
 
@@ -359,12 +359,11 @@ Rect Station::GetCatchmentRect() const
 
/**
 
 * Add nearby industry to station's industries_near list if it accepts cargo.
 
 * @param ind Industry
 
 * @param st Station
 
 */
 
static void AddIndustryToDeliver(Industry *ind, Station *st)
 
void Station::AddIndustryToDeliver(Industry *ind)
 
{
 
	/* Don't check further if this industry is already in the list */
 
	if (st->industries_near.find(ind) != st->industries_near.end()) return;
 
	if (this->industries_near.find(ind) != this->industries_near.end()) return;
 

	
 
	/* Include only industries that can accept cargo */
 
	uint cargo_index;
 
@@ -373,7 +372,7 @@ static void AddIndustryToDeliver(Industr
 
	}
 
	if (cargo_index >= lengthof(ind->accepts_cargo)) return;
 

	
 
	st->industries_near.insert(ind);
 
	this->industries_near.insert(ind);
 
}
 

	
 
/**
 
@@ -464,7 +463,7 @@ void Station::RecomputeCatchment()
 
			i->stations_near.insert(this);
 

	
 
			/* Add if we can deliver to this industry as well */
 
			AddIndustryToDeliver(i, this);
 
			this->AddIndustryToDeliver(i);
 
		}
 
	}
 
}
src/station_base.h
Show inline comments
 
@@ -503,6 +503,7 @@ public:
 
	uint GetCatchmentRadius() const;
 
	Rect GetCatchmentRect() const;
 
	bool CatchmentCoversTown(TownID t) const;
 
	void AddIndustryToDeliver(Industry *ind);
 
	void RemoveFromAllNearbyLists();
 

	
 
	inline bool TileIsInCatchment(TileIndex tile) const
 
@@ -557,4 +558,39 @@ public:
 

	
 
void RebuildStationKdtree();
 

	
 
/**
 
 * Call a function on all stations that have any part of the requested area within their catchment.
 
 * @param area The tile area to check
 
 */
 
template<typename Func>
 
void ForAllStationsAroundTiles(const TileArea &ta, Func func)
 
{
 
	/* Not using, or don't have a nearby stations list, so we need to scan. */
 
	std::set<StationID> seen_stations;
 

	
 
	/* Scan an area around the building covering the maximum possible station
 
	 * to find the possible nearby stations. */
 
	uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED;
 
	TileArea ta_ext = TileArea(ta).Expand(max_c);
 
	TILE_AREA_LOOP(tile, ta_ext) {
 
		if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile));
 
	}
 

	
 
	for (StationID stationid : seen_stations) {
 
		Station *st = Station::GetIfValid(stationid);
 
		if (st == nullptr) continue; /* Waypoint */
 

	
 
		/* Check if station is attached to an industry */
 
		if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue;
 

	
 
		/* Test if the tile is within the station's catchment */
 
		TILE_AREA_LOOP(tile, ta) {
 
			if (st->TileIsInCatchment(tile)) {
 
				func(st);
 
				break;
 
			}
 
		}
 
	}
 
}
 

	
 
#endif /* STATION_BASE_H */
src/station_cmd.cpp
Show inline comments
 
@@ -36,6 +36,7 @@
 
#include "animated_tile_func.h"
 
#include "elrail_func.h"
 
#include "station_base.h"
 
#include "station_func.h"
 
#include "station_kdtree.h"
 
#include "roadstop_base.h"
 
#include "newgrf_railtype.h"
 
@@ -3966,69 +3967,27 @@ static void AddNearbyStationsByCatchment
 
}
 

	
 
/**
 
 * Find all stations around a rectangular producer (industry, house, headquarter, ...)
 
 *
 
 * @param location The location/area of the producer
 
 * @param[out] stations The list to store the stations in
 
 * @param use_nearby Use nearby station list of industry/town associated with location.tile
 
 */
 
void FindStationsAroundTiles(const TileArea &location, StationList * const stations, bool use_nearby)
 
{
 
	if (use_nearby) {
 
		/* Industries and towns maintain a list of nearby stations */
 
		if (IsTileType(location.tile, MP_INDUSTRY)) {
 
			/* Industry nearby stations are already filtered by catchment. */
 
			*stations = Industry::GetByTile(location.tile)->stations_near;
 
			return;
 
		} else if (IsTileType(location.tile, MP_HOUSE)) {
 
			/* Town nearby stations need to be filtered per tile. */
 
			assert(location.w == 1 && location.h == 1);
 
			AddNearbyStationsByCatchment(location.tile, stations, Town::GetByTile(location.tile)->stations_near);
 
			return;
 
		}
 
	}
 

	
 
	/* Not using, or don't have a nearby stations list, so we need to scan. */
 
	std::set<StationID> seen_stations;
 

	
 
	/* Scan an area around the building covering the maximum possible station
 
	 * to find the possible nearby stations. */
 
	uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED;
 
	TileArea ta = TileArea(location).Expand(max_c);
 
	TILE_AREA_LOOP(tile, ta) {
 
		if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile));
 
	}
 

	
 
	for (StationID stationid : seen_stations) {
 
		Station *st = Station::GetIfValid(stationid);
 
		if (st == nullptr) continue; /* Waypoint */
 

	
 
		/* Check if station is attached to an industry */
 
		if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue;
 

	
 
		/* Test if the tile is within the station's catchment */
 
		TILE_AREA_LOOP(tile, location) {
 
			if (st->TileIsInCatchment(tile)) {
 
				stations->insert(st);
 
				break;
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Run a tile loop to find stations around a tile, on demand. Cache the result for further requests
 
 * @return pointer to a StationList containing all stations found
 
 */
 
const StationList *StationFinder::GetStations()
 
{
 
	if (this->tile != INVALID_TILE) {
 
		FindStationsAroundTiles(*this, &this->stations);
 
		if (IsTileType(this->tile, MP_HOUSE)) {
 
			/* Town nearby stations need to be filtered per tile. */
 
			assert(this->w == 1 && this->h == 1);
 
			AddNearbyStationsByCatchment(this->tile, &this->stations, Town::GetByTile(this->tile)->stations_near);
 
		} else {
 
			ForAllStationsAroundTiles(*this, [this](Station *st) {
 
				this->stations.insert(st);
 
			});
 
		}
 
		this->tile = INVALID_TILE;
 
	}
 
	return &this->stations;
 
}
 

	
 

	
 
static bool CanMoveGoodsToStation(const Station *st, CargoID type)
 
{
 
	/* Is the station reserved exclusively for somebody else? */
src/station_func.h
Show inline comments
 
@@ -22,8 +22,6 @@
 

	
 
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
 

	
 
void FindStationsAroundTiles(const TileArea &location, StationList *stations, bool use_nearby = true);
 

	
 
void ShowStationViewWindow(StationID station);
 
void UpdateAllStationVirtCoords();
 
void ClearAllStationCachedNames();
src/station_gui.cpp
Show inline comments
 
@@ -102,7 +102,7 @@ static void FindStationsAroundSelection(
 

	
 
	Station *adjacent = nullptr;
 

	
 
	/* Direct loop instead of FindStationsAroundTiles as we are not interested in catchment area */
 
	/* Direct loop instead of ForAllStationsAroundTiles as we are not interested in catchment area */
 
	TILE_AREA_LOOP(tile, ta) {
 
		if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
 
			Station *st = Station::GetByTile(tile);
src/town_cmd.cpp
Show inline comments
 
@@ -2249,7 +2249,11 @@ static void MakeTownHouse(TileIndex t, T
 
	if (size & BUILDING_2_TILES_X)   ClearMakeHouseTile(t + TileDiffXY(1, 0), town, counter, stage, ++type, random_bits);
 
	if (size & BUILDING_HAS_4_TILES) ClearMakeHouseTile(t + TileDiffXY(1, 1), town, counter, stage, ++type, random_bits);
 

	
 
	if (!_generating_world) FindStationsAroundTiles(TileArea(t, (size & BUILDING_2_TILES_X) ? 2 : 1, (size & BUILDING_2_TILES_Y) ? 2 : 1), &town->stations_near, false);
 
	if (!_generating_world) {
 
		ForAllStationsAroundTiles(TileArea(t, (size & BUILDING_2_TILES_X) ? 2 : 1, (size & BUILDING_2_TILES_Y) ? 2 : 1), [town](Station *st) {
 
			town->stations_near.insert(st);
 
		});
 
	}
 
}
 

	
 

	
0 comments (0 inline, 0 general)