From fc8685d618dd8d8e031943dd1cecce862971964b Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 19 Nov 2024 20:29:56 +0000 Subject: [PATCH] Codechange: Use functor for Kdtree's XYFunc. (#13074) Kdtree uses a function pointer and incorrectly calls it a functor. The function pointer needs to be passed on instantiaton. Instead, use an actual functor. This simplifies instantiation. --- src/core/kdtree.hpp | 29 ++++++++++++++--------------- src/station.cpp | 2 +- src/station_kdtree.h | 10 ++++++++-- src/town_cmd.cpp | 2 +- src/town_gui.cpp | 2 +- src/town_kdtree.h | 9 +++++++-- src/viewport.cpp | 2 +- src/viewport_kdtree.h | 12 +++++++----- 8 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/core/kdtree.hpp b/src/core/kdtree.hpp index 9a5eeaab5e..b810bfed9e 100644 --- a/src/core/kdtree.hpp +++ b/src/core/kdtree.hpp @@ -47,7 +47,6 @@ class Kdtree { std::vector nodes; ///< Pool of all nodes in the tree std::vector free_list; ///< List of dead indices in the nodes vector size_t root; ///< Index of root node - TxyFunc xyfunc; ///< Functor to extract a coordinate from an element size_t unbalanced; ///< Number approximating how unbalanced the tree might be /** Create one new node in the tree, return its index in the pool */ @@ -69,8 +68,8 @@ class Kdtree { CoordT SelectSplitCoord(It begin, It end, int level) { It mid = begin + (end - begin) / 2; - std::nth_element(begin, mid, end, [&](T a, T b) { return this->xyfunc(a, level % 2) < this->xyfunc(b, level % 2); }); - return this->xyfunc(*mid, level % 2); + std::nth_element(begin, mid, end, [&](T a, T b) { return TxyFunc()(a, level % 2) < TxyFunc()(b, level % 2); }); + return TxyFunc()(*mid, level % 2); } /** Construct a subtree from elements between begin and end iterators, return index of root */ @@ -85,7 +84,7 @@ class Kdtree { return this->AddNode(*begin); } else if (count > 1) { CoordT split_coord = SelectSplitCoord(begin, end, level); - It split = std::partition(begin, end, [&](T v) { return this->xyfunc(v, level % 2) < split_coord; }); + It split = std::partition(begin, end, [&](T v) { return TxyFunc()(v, level % 2) < split_coord; }); size_t newidx = this->AddNode(*split); this->nodes[newidx].left = this->BuildSubtree(begin, split, level + 1); this->nodes[newidx].right = this->BuildSubtree(split + 1, end, level + 1); @@ -129,9 +128,9 @@ class Kdtree { node &n = this->nodes[node_idx]; /* Coordinate of element splitting at this node */ - CoordT nc = this->xyfunc(n.element, dim); + CoordT nc = TxyFunc()(n.element, dim); /* Coordinate of the new element */ - CoordT ec = this->xyfunc(element, dim); + CoordT ec = TxyFunc()(element, dim); /* Which side to insert on */ size_t &next = (ec < nc) ? n.left : n.right; @@ -202,9 +201,9 @@ class Kdtree { /* Dimension index of current level */ int dim = level % 2; /* Coordinate of element splitting at this node */ - CoordT nc = this->xyfunc(n.element, dim); + CoordT nc = TxyFunc()(n.element, dim); /* Coordinate of the element being removed */ - CoordT ec = this->xyfunc(element, dim); + CoordT ec = TxyFunc()(element, dim); /* Which side to remove from */ size_t next = (ec < nc) ? n.left : n.right; assert(next != INVALID_NODE); // node must exist somewhere and must be found before a leaf is reached @@ -222,7 +221,7 @@ class Kdtree { DistT ManhattanDistance(const T &element, CoordT x, CoordT y) const { - return abs((DistT)this->xyfunc(element, 0) - (DistT)x) + abs((DistT)this->xyfunc(element, 1) - (DistT)y); + return abs((DistT)TxyFunc()(element, 0) - (DistT)x) + abs((DistT)TxyFunc()(element, 1) - (DistT)y); } /** A data element and its distance to a searched-for point */ @@ -245,7 +244,7 @@ class Kdtree { const node &n = this->nodes[node_idx]; /* Coordinate of element splitting at this node */ - CoordT c = this->xyfunc(n.element, dim); + CoordT c = TxyFunc()(n.element, dim); /* This node's distance to target */ DistT thisdist = ManhattanDistance(n.element, xy[0], xy[1]); /* Assume this node is the best choice for now */ @@ -280,9 +279,9 @@ class Kdtree { const node &n = this->nodes[node_idx]; /* Coordinate of element splitting at this node */ - CoordT ec = this->xyfunc(n.element, dim); + CoordT ec = TxyFunc()(n.element, dim); /* Opposite coordinate of element */ - CoordT oc = this->xyfunc(n.element, 1 - dim); + CoordT oc = TxyFunc()(n.element, 1 - dim); /* Test if this element is within rectangle */ if (ec >= p1[dim] && ec < p2[dim] && oc >= p1[1 - dim] && oc < p2[1 - dim]) outputter(n.element); @@ -321,8 +320,8 @@ class Kdtree { if (node_idx == INVALID_NODE) return; const node &n = this->nodes[node_idx]; - CoordT cx = this->xyfunc(n.element, 0); - CoordT cy = this->xyfunc(n.element, 1); + CoordT cx = TxyFunc()(n.element, 0); + CoordT cy = TxyFunc()(n.element, 1); assert(cx >= min_x); assert(cx < max_x); @@ -350,7 +349,7 @@ class Kdtree { public: /** Construct a new Kdtree with the given xyfunc */ - Kdtree(TxyFunc xyfunc) : root(INVALID_NODE), xyfunc(xyfunc), unbalanced(0) { } + Kdtree() : root(INVALID_NODE), unbalanced(0) { } /** * Clear and rebuild the tree from a new sequence of elements, diff --git a/src/station.cpp b/src/station.cpp index ef1579d9af..0bf1926ef6 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -36,7 +36,7 @@ StationPool _station_pool("Station"); INSTANTIATE_POOL_METHODS(Station) -StationKdtree _station_kdtree(Kdtree_StationXYFunc); +StationKdtree _station_kdtree{}; void RebuildStationKdtree() { diff --git a/src/station_kdtree.h b/src/station_kdtree.h index 11dd8b0679..084876a6fd 100644 --- a/src/station_kdtree.h +++ b/src/station_kdtree.h @@ -15,8 +15,14 @@ #include "station_base.h" #include "map_func.h" -inline uint16_t Kdtree_StationXYFunc(StationID stid, int dim) { return (dim == 0) ? TileX(BaseStation::Get(stid)->xy) : TileY(BaseStation::Get(stid)->xy); } -typedef Kdtree StationKdtree; +struct Kdtree_StationXYFunc { + inline uint16_t operator()(StationID stid, int dim) + { + return (dim == 0) ? TileX(BaseStation::Get(stid)->xy) : TileY(BaseStation::Get(stid)->xy); + } +}; + +using StationKdtree = Kdtree; extern StationKdtree _station_kdtree; /** diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 1a536ec4b5..53f08c4b44 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -68,7 +68,7 @@ TownPool _town_pool("Town"); INSTANTIATE_POOL_METHODS(Town) -TownKdtree _town_kdtree(&Kdtree_TownXYFunc); +TownKdtree _town_kdtree{}; void RebuildTownKdtree() { diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 656b4efd13..8b011c9191 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -50,7 +50,7 @@ #include "safeguards.h" -TownKdtree _town_local_authority_kdtree(&Kdtree_TownXYFunc); +TownKdtree _town_local_authority_kdtree{}; typedef GUIList GUITownList; diff --git a/src/town_kdtree.h b/src/town_kdtree.h index 74898bc23b..e22d3da13f 100644 --- a/src/town_kdtree.h +++ b/src/town_kdtree.h @@ -13,9 +13,14 @@ #include "core/kdtree.hpp" #include "town.h" -inline uint16_t Kdtree_TownXYFunc(TownID tid, int dim) { return (dim == 0) ? TileX(Town::Get(tid)->xy) : TileY(Town::Get(tid)->xy); } -typedef Kdtree TownKdtree; +struct Kdtree_TownXYFunc { + inline uint16_t operator()(TownID tid, int dim) + { + return (dim == 0) ? TileX(Town::Get(tid)->xy) : TileY(Town::Get(tid)->xy); + } +}; +using TownKdtree = Kdtree; extern TownKdtree _town_kdtree; extern TownKdtree _town_local_authority_kdtree; diff --git a/src/viewport.cpp b/src/viewport.cpp index b083f9f3b4..286273319c 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -102,7 +102,7 @@ Point _tile_fract_coords; -ViewportSignKdtree _viewport_sign_kdtree(&Kdtree_ViewportSignXYFunc); +ViewportSignKdtree _viewport_sign_kdtree{}; static int _viewport_sign_maxwidth = 0; diff --git a/src/viewport_kdtree.h b/src/viewport_kdtree.h index 3c2f49c2e4..141315b6bd 100644 --- a/src/viewport_kdtree.h +++ b/src/viewport_kdtree.h @@ -70,12 +70,14 @@ struct ViewportSignKdtreeItem { static ViewportSignKdtreeItem MakeSign(SignID id); }; -inline int32_t Kdtree_ViewportSignXYFunc(const ViewportSignKdtreeItem &item, int dim) -{ - return (dim == 0) ? item.center : item.top; -} +struct Kdtree_ViewportSignXYFunc { + inline int32_t operator()(const ViewportSignKdtreeItem &item, int dim) + { + return (dim == 0) ? item.center : item.top; + } +}; -typedef Kdtree ViewportSignKdtree; +using ViewportSignKdtree = Kdtree; extern ViewportSignKdtree _viewport_sign_kdtree; void RebuildViewportKdtree();