Codechange: [Linkgraph] Drop node/edge wrappers from LinkGraph.

This commit is contained in:
Michael Lutz
2023-01-03 13:48:42 +01:00
parent 4d3da0cf14
commit aab580e0ac
9 changed files with 94 additions and 409 deletions

View File

@@ -56,6 +56,16 @@ public:
*/
uint32 TravelTime() const { return this->travel_time_sum / this->capacity; }
/**
* Get the date of the last update to any part of the edge's capacity.
* @return Last update.
*/
Date LastUpdate() const { return std::max(this->last_unrestricted_update, this->last_restricted_update); }
void Update(uint capacity, uint usage, uint32 time, EdgeUpdateMode mode);
void Restrict() { this->last_unrestricted_update = INVALID_DATE; }
void Release() { this->last_restricted_update = INVALID_DATE; }
/** Comparison operator based on \c dest_node. */
bool operator <(const BaseEdge &rhs) const
{
@@ -88,357 +98,6 @@ public:
std::vector<BaseEdge> edges; ///< Sorted list of outgoing edges from this node.
BaseNode(TileIndex xy = INVALID_TILE, StationID st = INVALID_STATION, uint demand = 0);
};
/**
* Wrapper for an edge (const or not) allowing retrieval, but no modification.
* @tparam Tedge Actual edge class, may be "const BaseEdge" or just "BaseEdge".
*/
template<typename Tedge>
class EdgeWrapper {
protected:
Tedge &edge; ///< Actual edge to be used.
public:
/**
* Wrap a an edge.
* @param edge Edge to be wrapped.
*/
EdgeWrapper (Tedge &edge) : edge(edge) {}
/**
* Get edge's capacity.
* @return Capacity.
*/
uint Capacity() const { return this->edge.capacity; }
/**
* Get edge's usage.
* @return Usage.
*/
uint Usage() const { return this->edge.usage; }
/**
* Get edge's average travel time.
* @return Travel time, in ticks.
*/
uint32 TravelTime() const { return this->edge.TravelTime(); }
/**
* Get the date of the last update to the edge's unrestricted capacity.
* @return Last update.
*/
Date LastUnrestrictedUpdate() const { return this->edge.last_unrestricted_update; }
/**
* Get the date of the last update to the edge's restricted capacity.
* @return Last update.
*/
Date LastRestrictedUpdate() const { return this->edge.last_restricted_update; }
/**
* Get the date of the last update to any part of the edge's capacity.
* @return Last update.
*/
Date LastUpdate() const { return std::max(this->edge.last_unrestricted_update, this->edge.last_restricted_update); }
};
/**
* Wrapper for a node (const or not) allowing retrieval, but no modification.
* @tparam Tnode Actual node class, may be "const BaseNode" or just "BaseNode".
*/
template<typename Tnode>
class NodeWrapper {
protected:
Tnode &node; ///< Node being wrapped.
NodeID index; ///< ID of wrapped node.
auto GetEdge(NodeID dest) const
{
return std::lower_bound(this->node.edges.begin(), this->node.edges.end(), dest);
}
public:
/**
* Wrap a node.
* @param node Node to be wrapped.
* @param index ID of node to be wrapped.
*/
NodeWrapper(Tnode &node, NodeID index) : node(node), index(index) {}
/**
* Get supply of wrapped node.
* @return Supply.
*/
uint Supply() const { return this->node.supply; }
/**
* Get demand of wrapped node.
* @return Demand.
*/
uint Demand() const { return this->node.demand; }
/**
* Get ID of station belonging to wrapped node.
* @return ID of node's station.
*/
StationID Station() const { return this->node.station; }
/**
* Get node's last update.
* @return Last update.
*/
Date LastUpdate() const { return this->node.last_update; }
/**
* Get the location of the station associated with the node.
* @return Location of the station.
*/
TileIndex XY() const { return this->node.xy; }
/**
* Check if an edge to a destination is present.
* @param dest Wanted edge destination.
* @return True if an edge is present.
*/
bool HasEdgeTo(NodeID dest) const
{
return std::binary_search(this->node.edges.begin(), this->node.edges.end(), dest);
}
};
/**
* Base class for iterating across outgoing edges of a node. Only the real
* edges (those with capacity) are iterated. The ones with only distance
* information are skipped.
* @tparam Tedge Actual edge class. May be "BaseEdge" or "const BaseEdge".
* @tparam Titer Actual iterator class.
*/
template <class Tedge, class Tedge_wrapper, class Titer>
class BaseEdgeIterator {
protected:
span<Tedge> base; ///< Array of edges being iterated.
size_t current; ///< Current offset in edges array.
/**
* A "fake" pointer to enable operator-> on temporaries. As the objects
* returned from operator* aren't references but real objects, we have
* to return something that implements operator->, but isn't a pointer
* from operator->. A fake pointer.
*/
class FakePointer : public std::pair<NodeID, Tedge_wrapper> {
public:
/**
* Construct a fake pointer from a pair of NodeID and edge.
* @param pair Pair to be "pointed" to (in fact shallow-copied).
*/
FakePointer(const std::pair<NodeID, Tedge_wrapper> &pair) : std::pair<NodeID, Tedge_wrapper>(pair) {}
/**
* Retrieve the pair by operator->.
* @return Pair being "pointed" to.
*/
std::pair<NodeID, Tedge_wrapper> *operator->() { return this; }
};
public:
/**
* Constructor.
* @param base Array of edges to be iterated.
* @param end Make the iterator the end sentinel?
*/
BaseEdgeIterator(span<Tedge> base, bool end) : base(base), current(end ? base.size() : 0) {}
/**
* Prefix-increment.
* @return This.
*/
Titer &operator++()
{
if (this->current < this->base.size()) this->current++;
return static_cast<Titer &>(*this);
}
/**
* Postfix-increment.
* @return Version of this before increment.
*/
Titer operator++(int)
{
Titer ret(static_cast<Titer &>(*this));
++(*this);
return ret;
}
/**
* Compare with some other edge iterator. The other one may be of a
* child class.
* @tparam Tother Class of other iterator.
* @param other Instance of other iterator.
* @return If the iterators have the same edge array and current node.
*/
template<class Tother>
bool operator==(const Tother &other)
{
return this->base.data() == other.base.data() && this->current == other.current;
}
/**
* Compare for inequality with some other edge iterator. The other one
* may be of a child class.
* @tparam Tother Class of other iterator.
* @param other Instance of other iterator.
* @return If either the edge arrays or the current nodes differ.
*/
template<class Tother>
bool operator!=(const Tother &other)
{
return this->base.data() != other.base.data() || this->current != other.current;
}
/**
* Dereference with operator*.
* @return Pair of current target NodeID and edge object.
*/
std::pair<NodeID, Tedge_wrapper> operator*() const
{
return std::pair<NodeID, Tedge_wrapper>(this->base[this->current].dest_node, Tedge_wrapper(this->base[this->current]));
}
/**
* Dereference with operator->.
* @return Fake pointer to Pair of current target NodeID and edge object.
*/
FakePointer operator->() const {
return FakePointer(this->operator*());
}
};
/**
* A constant edge class.
*/
typedef EdgeWrapper<const BaseEdge> ConstEdge;
/**
* An updatable edge class.
*/
class Edge : public EdgeWrapper<BaseEdge> {
public:
/**
* Constructor
* @param edge Edge to be wrapped.
*/
Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {}
void Update(uint capacity, uint usage, uint32 time, EdgeUpdateMode mode);
void Restrict() { this->edge.last_unrestricted_update = INVALID_DATE; }
void Release() { this->edge.last_restricted_update = INVALID_DATE; }
};
/**
* An iterator for const edges. Cannot be typedef'ed because of
* template-reference to ConstEdgeIterator itself.
*/
class ConstEdgeIterator : public BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator> {
public:
/**
* Constructor.
* @param edges Array of edges to be iterated over.
* @param end Make the iterator the end sentinel?
*/
ConstEdgeIterator(span<const BaseEdge> edges, bool end) :
BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator>(edges, end) {}
};
/**
* An iterator for non-const edges. Cannot be typedef'ed because of
* template-reference to EdgeIterator itself.
*/
class EdgeIterator : public BaseEdgeIterator<BaseEdge, Edge, EdgeIterator> {
public:
/**
* Constructor.
* @param edges Array of edges to be iterated over.
* @param end Make the iterator the end sentinel?
*/
EdgeIterator(span<BaseEdge> edges, bool end) :
BaseEdgeIterator<BaseEdge, Edge, EdgeIterator>(edges, end) {}
};
/**
* Constant node class. Only retrieval operations are allowed on both the
* node itself and its edges.
*/
class ConstNode : public NodeWrapper<const BaseNode> {
public:
/**
* Constructor.
* @param lg LinkGraph to get the node from.
* @param node ID of the node.
*/
ConstNode(const LinkGraph *lg, NodeID node) : NodeWrapper<const BaseNode>(lg->nodes[node], node) {}
/**
* Get a ConstEdge. This is not a reference as the wrapper objects are
* not actually persistent.
* @param to ID of end node of edge.
* @return Constant edge wrapper.
*/
ConstEdge operator[](NodeID to) const
{
assert(this->HasEdgeTo(to));
return ConstEdge(*this->GetEdge(to));
}
/**
* Get an iterator pointing to the start of the edges array.
* @return Constant edge iterator.
*/
ConstEdgeIterator Begin() const { return ConstEdgeIterator(this->node.edges, false); }
/**
* Get an iterator pointing beyond the end of the edges array.
* @return Constant edge iterator.
*/
ConstEdgeIterator End() const { return ConstEdgeIterator(this->node.edges, true); }
};
/**
* Updatable node class. The node itself as well as its edges can be modified.
*/
class Node : public NodeWrapper<BaseNode> {
public:
/**
* Constructor.
* @param lg LinkGraph to get the node from.
* @param node ID of the node.
*/
Node(LinkGraph *lg, NodeID node) : NodeWrapper<BaseNode>(lg->nodes[node], node) {}
/**
* Get an Edge. This is not a reference as the wrapper objects are not
* actually persistent.
* @param to ID of end node of edge.
* @return Edge wrapper.
*/
Edge operator[](NodeID to)
{
assert(this->HasEdgeTo(to));
return Edge(*this->GetEdge(to));
}
/**
* Get an iterator pointing to the start of the edges array.
* @return Edge iterator.
*/
EdgeIterator Begin() { return EdgeIterator(this->node.edges, false); }
/**
* Get an iterator pointing beyond the end of the edges array.
* @return Constant edge iterator.
*/
EdgeIterator End() { return EdgeIterator(this->node.edges, true); }
/**
* Update the node's supply and set last_update to the current date.
@@ -446,8 +105,8 @@ public:
*/
void UpdateSupply(uint supply)
{
this->node.supply += supply;
this->node.last_update = _date;
this->supply += supply;
this->last_update = _date;
}
/**
@@ -456,7 +115,7 @@ public:
*/
void UpdateLocation(TileIndex xy)
{
this->node.xy = xy;
this->xy = xy;
}
/**
@@ -465,12 +124,45 @@ public:
*/
void SetDemand(uint demand)
{
this->node.demand = demand;
this->demand = demand;
}
void AddEdge(NodeID to, uint capacity, uint usage, uint32 time, EdgeUpdateMode mode);
void UpdateEdge(NodeID to, uint capacity, uint usage, uint32 time, EdgeUpdateMode mode);
void RemoveEdge(NodeID to);
/**
* Check if an edge to a destination is present.
* @param dest Wanted edge destination.
* @return True if an edge is present.
*/
bool HasEdgeTo(NodeID dest) const
{
return std::binary_search(this->edges.begin(), this->edges.end(), dest);
}
BaseEdge &operator[](NodeID to)
{
assert(this->HasEdgeTo(to));
return *GetEdge(to);
}
const BaseEdge &operator[](NodeID to) const
{
assert(this->HasEdgeTo(to));
return *GetEdge(to);
}
private:
std::vector<BaseEdge>::iterator GetEdge(NodeID dest)
{
return std::lower_bound(this->edges.begin(), this->edges.end(), dest);
}
std::vector<BaseEdge>::const_iterator GetEdge(NodeID dest) const
{
return std::lower_bound(this->edges.begin(), this->edges.end(), dest);
}
};
typedef std::vector<BaseNode> NodeVector;
@@ -523,14 +215,14 @@ public:
* @param num ID of the node.
* @return the Requested node.
*/
inline Node operator[](NodeID num) { return Node(this, num); }
inline BaseNode &operator[](NodeID num) { return this->nodes[num]; }
/**
* Get a const reference to a node with the specified id.
* @param num ID of the node.
* @return the Requested node.
*/
inline ConstNode operator[](NodeID num) const { return ConstNode(this, num); }
inline const BaseNode &operator[](NodeID num) const { return this->nodes[num]; }
/**
* Get the current size of the component.
@@ -564,8 +256,6 @@ public:
void RemoveNode(NodeID id);
protected:
friend class LinkGraph::ConstNode;
friend class LinkGraph::Node;
friend SaveLoadTable GetLinkGraphDesc();
friend SaveLoadTable GetLinkGraphJobDesc();
friend class SlLinkgraphNode;