OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

linkgraph.h
Go to the documentation of this file.
1 /* $Id: linkgraph.h 26646 2014-06-14 13:35:39Z fonsinchen $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #ifndef LINKGRAPH_H
13 #define LINKGRAPH_H
14
15 #include "../core/pool_type.hpp"
16 #include "../core/smallmap_type.hpp"
17 #include "../core/smallmatrix_type.hpp"
18 #include "../station_base.h"
19 #include "../cargotype.h"
20 #include "../date_func.h"
21 #include "linkgraph_type.h"
22
23 struct SaveLoad;
24 class LinkGraph;
25
30 typedef Pool<LinkGraph, LinkGraphID, 32, 0xFFFF> LinkGraphPool;
32 extern LinkGraphPool _link_graph_pool;
33
40 class LinkGraph : public LinkGraphPool::PoolItem<&_link_graph_pool> {
41 public:
42
48 struct BaseNode {
49 uint supply;
50 uint demand;
51 StationID station;
52 TileIndex xy;
53 Date last_update;
54 void Init(TileIndex xy = INVALID_TILE, StationID st = INVALID_STATION, uint demand = 0);
55 };
56
63 struct BaseEdge {
64 uint capacity;
65 uint usage;
66 Date last_unrestricted_update;
67 Date last_restricted_update;
68 NodeID next_edge;
69 void Init();
70 };
71
76 template<typename Tedge>
77 class EdgeWrapper {
78 protected:
79 Tedge &edge;
80
81 public:
82
87 EdgeWrapper (Tedge &edge) : edge(edge) {}
88
93 uint Capacity() const { return this->edge.capacity; }
94
99 uint Usage() const { return this->edge.usage; }
100
105 Date LastUnrestrictedUpdate() const { return this->edge.last_unrestricted_update; }
106
111 Date LastRestrictedUpdate() const { return this->edge.last_restricted_update; }
112
117 Date LastUpdate() const { return max(this->edge.last_unrestricted_update, this->edge.last_restricted_update); }
118 };
119
125 template<typename Tnode, typename Tedge>
126 class NodeWrapper {
127 protected:
128 Tnode &node;
129 Tedge *edges;
130 NodeID index;
131
132 public:
133
140 NodeWrapper(Tnode &node, Tedge *edges, NodeID index) : node(node),
141 edges(edges), index(index) {}
142
147 uint Supply() const { return this->node.supply; }
148
153 uint Demand() const { return this->node.demand; }
154
159 StationID Station() const { return this->node.station; }
160
165 Date LastUpdate() const { return this->node.last_update; }
166
171 TileIndex XY() const { return this->node.xy; }
172 };
173
181 template <class Tedge, class Tedge_wrapper, class Titer>
182 class BaseEdgeIterator {
183 protected:
184 Tedge *base;
185 NodeID current;
186
193 class FakePointer : public SmallPair<NodeID, Tedge_wrapper> {
194 public:
195
200 FakePointer(const SmallPair<NodeID, Tedge_wrapper> &pair) : SmallPair<NodeID, Tedge_wrapper>(pair) {}
201
206 SmallPair<NodeID, Tedge_wrapper> *operator->() { return this; }
207 };
208
209 public:
215 BaseEdgeIterator (Tedge *base, NodeID current) :
216 base(base),
217 current(current == INVALID_NODE ? current : base[current].next_edge)
218 {}
219
224 Titer &operator++()
225 {
226 this->current = this->base[this->current].next_edge;
227 return static_cast<Titer &>(*this);
228 }
229
234 Titer operator++(int)
235 {
236 Titer ret(static_cast<Titer &>(*this));
237 this->current = this->base[this->current].next_edge;
238 return ret;
239 }
240
248 template<class Tother>
249 bool operator==(const Tother &other)
250 {
251 return this->base == other.base && this->current == other.current;
252 }
253
261 template<class Tother>
262 bool operator!=(const Tother &other)
263 {
264 return this->base != other.base || this->current != other.current;
265 }
266
271 SmallPair<NodeID, Tedge_wrapper> operator*() const
272 {
273 return SmallPair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
274 }
275
280 FakePointer operator->() const {
281 return FakePointer(this->operator*());
282 }
283 };
284
288 typedef EdgeWrapper<const BaseEdge> ConstEdge;
289
293 class Edge : public EdgeWrapper<BaseEdge> {
294 public:
299 Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {}
300 void Update(uint capacity, uint usage, EdgeUpdateMode mode);
301 void Restrict() { this->edge.last_unrestricted_update = INVALID_DATE; }
302 void Release() { this->edge.last_restricted_update = INVALID_DATE; }
303 };
304
309 class ConstEdgeIterator : public BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator> {
310 public:
316 ConstEdgeIterator(const BaseEdge *edges, NodeID current) :
317 BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator>(edges, current) {}
318 };
319
324 class EdgeIterator : public BaseEdgeIterator<BaseEdge, Edge, EdgeIterator> {
325 public:
331 EdgeIterator(BaseEdge *edges, NodeID current) :
332 BaseEdgeIterator<BaseEdge, Edge, EdgeIterator>(edges, current) {}
333 };
334
339 class ConstNode : public NodeWrapper<const BaseNode, const BaseEdge> {
340 public:
346 ConstNode(const LinkGraph *lg, NodeID node) :
347 NodeWrapper<const BaseNode, const BaseEdge>(lg->nodes[node], lg->edges[node], node)
348 {}
349
356 ConstEdge operator[](NodeID to) const { return ConstEdge(this->edges[to]); }
357
362 ConstEdgeIterator Begin() const { return ConstEdgeIterator(this->edges, this->index); }
363
368 ConstEdgeIterator End() const { return ConstEdgeIterator(this->edges, INVALID_NODE); }
369 };
370
374 class Node : public NodeWrapper<BaseNode, BaseEdge> {
375 public:
381 Node(LinkGraph *lg, NodeID node) :
382 NodeWrapper<BaseNode, BaseEdge>(lg->nodes[node], lg->edges[node], node)
383 {}
384
391 Edge operator[](NodeID to) { return Edge(this->edges[to]); }
392
397 EdgeIterator Begin() { return EdgeIterator(this->edges, this->index); }
398
403 EdgeIterator End() { return EdgeIterator(this->edges, INVALID_NODE); }
404
409 void UpdateSupply(uint supply)
410 {
411 this->node.supply += supply;
412 this->node.last_update = _date;
413 }
414
419 void UpdateLocation(TileIndex xy)
420 {
421 this->node.xy = xy;
422 }
423
428 void SetDemand(uint demand)
429 {
430 this->node.demand = demand;
431 }
432
433 void AddEdge(NodeID to, uint capacity, uint usage, EdgeUpdateMode mode);
434 void UpdateEdge(NodeID to, uint capacity, uint usage, EdgeUpdateMode mode);
435 void RemoveEdge(NodeID to);
436 };
437
438 typedef SmallVector<BaseNode, 16> NodeVector;
439 typedef SmallMatrix<BaseEdge> EdgeMatrix;
440
442 static const uint MIN_TIMEOUT_DISTANCE = 32;
443
445 static const uint COMPRESSION_INTERVAL = 256;
446
455 inline static uint Scale(uint val, uint target_age, uint orig_age)
456 {
457 return val > 0 ? max(1U, val * target_age / orig_age) : 0;
458 }
459
461 LinkGraph() : cargo(INVALID_CARGO), last_compression(0) {}
466 LinkGraph(CargoID cargo) : cargo(cargo), last_compression(_date) {}
467
468 void Init(uint size);
469 void ShiftDates(int interval);
470 void Compress();
471 void Merge(LinkGraph *other);
472
473 /* Splitting link graphs is intentionally not implemented.
474 * The overhead in determining connectedness would probably outweigh the
475 * benefit of having to deal with smaller graphs. In real world examples
476 * networks generally grow. Only rarely a network is permanently split.
477 * Reacting to temporary splits here would obviously create performance
478 * problems and detecting the temporary or permanent nature of splits isn't
479 * trivial. */
480
486 inline Node operator[](NodeID num) { return Node(this, num); }
487
493 inline ConstNode operator[](NodeID num) const { return ConstNode(this, num); }
494
499 inline uint Size() const { return this->nodes.Length(); }
500
505 inline Date LastCompression() const { return this->last_compression; }
506
511 inline CargoID Cargo() const { return this->cargo; }
512
518 inline uint Monthly(uint base) const
519 {
520 return base * 30 / (_date - this->last_compression + 1);
521 }
522
523 NodeID AddNode(const Station *st);
524 void RemoveNode(NodeID id);
525
526 protected:
527 friend class LinkGraph::ConstNode;
528 friend class LinkGraph::Node;
529 friend const SaveLoad *GetLinkGraphDesc();
530 friend const SaveLoad *GetLinkGraphJobDesc();
531 friend void SaveLoad_LinkGraph(LinkGraph &lg);
532
533 CargoID cargo;
534 Date last_compression;
535 NodeVector nodes;
536 EdgeMatrix edges;
537 };
538
539 #define FOR_ALL_LINK_GRAPHS(var) FOR_ALL_ITEMS_FROM(LinkGraph, link_graph_index, var, 0)
540
541 #endif /* LINKGRAPH_H */