diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index df9286308e..9978145fac 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -156,8 +156,7 @@ Industry::~Industry() } if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) { - TileArea ta(this->location.tile - TileDiffXY(min(TileX(this->location.tile), 21), min(TileY(this->location.tile), 21)), 42, 42); - ta.ClampToMap(); + TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21); /* Remove the farmland and convert it to regular tiles over time. */ TILE_AREA_LOOP(tile_cur, ta) { @@ -1533,6 +1532,8 @@ static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, /* Check that all tiles in area and surrounding are clear * this determines that there are no obstructing items */ + /* TileArea::Expand is not used here as we need to abort + * instead of clamping if the bounds cannot expanded. */ TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform), max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform); @@ -1593,9 +1594,7 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int t /* On a large map with many industries, it may be faster to check an area. */ static const int dmax = 14; if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) { - const int tx = TileX(tile); - const int ty = TileY(tile); - TileArea tile_area = TileArea(TileXY(max(0, tx - dmax), max(0, ty - dmax)), TileXY(min(MapMaxX(), tx + dmax), min(MapMaxY(), ty + dmax))); + TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax); TILE_AREA_LOOP(atile, tile_area) { if (GetTileType(atile) == MP_INDUSTRY) { const Industry *i2 = Industry::GetByTile(atile); diff --git a/src/script/api/script_tilelist.cpp b/src/script/api/script_tilelist.cpp index 933a92c4cb..adddb989cc 100644 --- a/src/script/api/script_tilelist.cpp +++ b/src/script/api/script_tilelist.cpp @@ -66,7 +66,7 @@ ScriptTileList_IndustryAccepting::ScriptTileList_IndustryAccepting(IndustryID in if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED; - TileArea ta(i->location.tile - ::TileDiffXY(radius, radius), i->location.w + radius * 2, i->location.h + radius * 2); + TileArea ta = TileArea(i->location).Expand(radius); TILE_AREA_LOOP(cur_tile, ta) { if (!::IsValidTile(cur_tile)) continue; /* Exclude all tiles that belong to this industry */ @@ -102,7 +102,7 @@ ScriptTileList_IndustryProducing::ScriptTileList_IndustryProducing(IndustryID in if (!_settings_game.station.modified_catchment) radius = CA_UNMODIFIED; - TileArea ta(i->location.tile - ::TileDiffXY(radius, radius), i->location.w + radius * 2, i->location.h + radius * 2); + TileArea ta = TileArea(i->location).Expand(radius); TILE_AREA_LOOP(cur_tile, ta) { if (!::IsValidTile(cur_tile)) continue; /* Exclude all tiles that belong to this industry */ diff --git a/src/station.cpp b/src/station.cpp index b211c6422e..85603a38c8 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -449,7 +449,7 @@ void Station::RecomputeCatchment() if (r == CA_NONE) continue; /* This tile sub-loop doesn't need to test any tiles, they are simply added to the catchment set. */ - TileArea ta2(TileXY(max(TileX(tile) - r, 0), max(TileY(tile) - r, 0)), TileXY(min(TileX(tile) + r, MapMaxX()), min(TileY(tile) + r, MapMaxY()))); + TileArea ta2 = TileArea(tile, 1, 1).Expand(r); TILE_AREA_LOOP(tile2, ta2) this->catchment_tiles.SetTile(tile2); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index acffe113dd..4aa6401279 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -101,9 +101,7 @@ bool IsHangar(TileIndex t) template CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st) { - ta.tile -= TileDiffXY(1, 1); - ta.w += 2; - ta.h += 2; + ta.Expand(1); /* check around to see if there are any stations there owned by the company */ TILE_AREA_LOOP(tile_cur, ta) { @@ -495,25 +493,8 @@ static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *c CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) { CargoArray produced; - - int x = TileX(tile); - int y = TileY(tile); - - /* expand the region by rad tiles on each side - * while making sure that we remain inside the board. */ - int x2 = min(x + w + rad, MapSizeX()); - int x1 = max(x - rad, 0); - - int y2 = min(y + h + rad, MapSizeY()); - int y1 = max(y - rad, 0); - - assert(x1 < x2); - assert(y1 < y2); - assert(w > 0); - assert(h > 0); - std::set industries; - TileArea ta(TileXY(x1, y1), TileXY(x2 - 1, y2 - 1)); + TileArea ta = TileArea(tile, w, h).Expand(rad); /* Loop over all tiles to get the produced cargo of * everything except industries */ @@ -553,30 +534,13 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, Cargo CargoArray acceptance; if (always_accepted != nullptr) *always_accepted = 0; - int x = TileX(tile); - int y = TileY(tile); - - /* expand the region by rad tiles on each side - * while making sure that we remain inside the board. */ - int x2 = min(x + w + rad, MapSizeX()); - int y2 = min(y + h + rad, MapSizeY()); - int x1 = max(x - rad, 0); - int y1 = max(y - rad, 0); + TileArea ta = TileArea(tile, w, h).Expand(rad); - assert(x1 < x2); - assert(y1 < y2); - assert(w > 0); - assert(h > 0); - - for (int yc = y1; yc != y2; yc++) { - for (int xc = x1; xc != x2; xc++) { - TileIndex tile = TileXY(xc, yc); - - /* Ignore industry if it has a neutral station. */ - if (!_settings_game.station.serve_neutral_industries && IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != nullptr) continue; + TILE_AREA_LOOP(tile, ta) { + /* Ignore industry if it has a neutral station. */ + if (!_settings_game.station.serve_neutral_industries && IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile)->neutral_station != nullptr) continue; - AddAcceptedCargo(tile, acceptance, always_accepted); - } + AddAcceptedCargo(tile, acceptance, always_accepted); } return acceptance; @@ -3858,15 +3822,12 @@ void FindStationsAroundTiles(const TileArea &location, StationList * const stati } /* Not using, or don't have a nearby stations list, so we need to scan. */ - uint x = TileX(location.tile); - uint y = TileY(location.tile); - std::set 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(TileXY(max(0, x - max_c), max(0, y - max_c)), TileXY(min(MapMaxX(), x + location.w + max_c), min(MapMaxY(), y + location.h + max_c))); + TileArea ta = TileArea(location).Expand(max_c); TILE_AREA_LOOP(tile, ta) { if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile)); } diff --git a/src/tilearea.cpp b/src/tilearea.cpp index ec3b9aafbb..33850c7203 100644 --- a/src/tilearea.cpp +++ b/src/tilearea.cpp @@ -117,6 +117,27 @@ bool OrthogonalTileArea::Contains(TileIndex tile) const return IsInsideBS(tile_x, left, this->w) && IsInsideBS(tile_y, top, this->h); } +/** + * Expand a tile area by rad tiles in each direction, keeping within map bounds. + * @param rad Number of tiles to expand + * @return The OrthogonalTileArea. + */ +OrthogonalTileArea &OrthogonalTileArea::Expand(int rad) +{ + int x = TileX(this->tile); + int y = TileY(this->tile); + + int sx = max(x - rad, 0); + int sy = max(y - rad, 0); + int ex = min(x + this->w + rad, MapSizeX()); + int ey = min(y + this->h + rad, MapSizeY()); + + this->tile = TileXY(sx, sy); + this->w = ex - sx; + this->h = ey - sy; + return *this; +} + /** * Clamp the tile area to map borders. */ diff --git a/src/tilearea_type.h b/src/tilearea_type.h index 45bfb3d4c0..c599753498 100644 --- a/src/tilearea_type.h +++ b/src/tilearea_type.h @@ -48,6 +48,8 @@ struct OrthogonalTileArea { bool Contains(TileIndex tile) const; + OrthogonalTileArea &Expand(int rad); + void ClampToMap(); /** diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 4c677a88ac..76326a3a42 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -200,7 +200,7 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint } Waypoint *wp = nullptr; - TileArea new_location(TileArea(start_tile, width, height)); + TileArea new_location(start_tile, width, height); CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, new_location, &wp); if (ret.Failed()) return ret;