LinkGraph: Increase caching of link graph lines/point details
This commit is contained in:
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
#include "../3rdparty/cpp-btree/btree_map.h"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,6 +60,40 @@ void LinkGraphOverlay::RebuildCache()
|
|||||||
DrawPixelInfo dpi;
|
DrawPixelInfo dpi;
|
||||||
this->GetWidgetDpi(&dpi);
|
this->GetWidgetDpi(&dpi);
|
||||||
|
|
||||||
|
struct LinkCacheItem {
|
||||||
|
Point from_pt;
|
||||||
|
Point to_pt;
|
||||||
|
LinkProperties prop;
|
||||||
|
};
|
||||||
|
btree::btree_map<std::pair<StationID, StationID>, LinkCacheItem> link_cache_map;
|
||||||
|
|
||||||
|
auto AddLinks = [&](const Station *from, const Station *to, Point from_pt, Point to_pt) {
|
||||||
|
LinkCacheItem *item = nullptr;
|
||||||
|
CargoID c;
|
||||||
|
FOR_EACH_SET_CARGO_ID(c, this->cargo_mask) {
|
||||||
|
if (!CargoSpec::Get(c)->IsValid()) continue;
|
||||||
|
const GoodsEntry &ge = from->goods[c];
|
||||||
|
if (!LinkGraph::IsValidID(ge.link_graph) ||
|
||||||
|
ge.link_graph != to->goods[c].link_graph) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const LinkGraph &lg = *LinkGraph::Get(ge.link_graph);
|
||||||
|
ConstEdge edge = lg[ge.node][to->goods[c].node];
|
||||||
|
if (edge.Capacity() > 0) {
|
||||||
|
if (!item) {
|
||||||
|
item = &link_cache_map[std::make_pair(from->index, to->index)];
|
||||||
|
if (item->prop.capacity == 0) {
|
||||||
|
item->from_pt = from_pt;
|
||||||
|
item->to_pt = to_pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->AddStats(lg.Monthly(edge.Capacity()), lg.Monthly(edge.Usage()),
|
||||||
|
ge.flows.GetFlowVia(to->index), from->owner == OWNER_NONE || to->owner == OWNER_NONE,
|
||||||
|
item->prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const Station *sta;
|
const Station *sta;
|
||||||
FOR_ALL_STATIONS(sta) {
|
FOR_ALL_STATIONS(sta) {
|
||||||
if (sta->rect.IsEmpty()) continue;
|
if (sta->rect.IsEmpty()) continue;
|
||||||
@@ -65,7 +101,6 @@ void LinkGraphOverlay::RebuildCache()
|
|||||||
Point pta = this->GetStationMiddle(sta);
|
Point pta = this->GetStationMiddle(sta);
|
||||||
|
|
||||||
StationID from = sta->index;
|
StationID from = sta->index;
|
||||||
StationLinkMap &seen_links = this->cached_links[from];
|
|
||||||
|
|
||||||
uint supply = 0;
|
uint supply = 0;
|
||||||
CargoID c;
|
CargoID c;
|
||||||
@@ -79,7 +114,7 @@ void LinkGraphOverlay::RebuildCache()
|
|||||||
for (ConstEdgeIterator i = from_node.Begin(); i != from_node.End(); ++i) {
|
for (ConstEdgeIterator i = from_node.Begin(); i != from_node.End(); ++i) {
|
||||||
StationID to = lg[i->first].Station();
|
StationID to = lg[i->first].Station();
|
||||||
assert(from != to);
|
assert(from != to);
|
||||||
if (!Station::IsValidID(to) || seen_links.find(to) != seen_links.end()) {
|
if (!Station::IsValidID(to) || link_cache_map.count(std::make_pair(from, to))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Station *stb = Station::Get(to);
|
const Station *stb = Station::Get(to);
|
||||||
@@ -89,16 +124,22 @@ void LinkGraphOverlay::RebuildCache()
|
|||||||
if (stb->owner != OWNER_NONE && sta->owner != OWNER_NONE && !HasBit(this->company_mask, stb->owner)) continue;
|
if (stb->owner != OWNER_NONE && sta->owner != OWNER_NONE && !HasBit(this->company_mask, stb->owner)) continue;
|
||||||
if (stb->rect.IsEmpty()) continue;
|
if (stb->rect.IsEmpty()) continue;
|
||||||
|
|
||||||
if (!this->IsLinkVisible(pta, this->GetStationMiddle(stb), &dpi)) continue;
|
Point ptb = this->GetStationMiddle(stb);
|
||||||
|
|
||||||
this->AddLinks(sta, stb);
|
if (!this->IsLinkVisible(pta, ptb, &dpi)) continue;
|
||||||
seen_links[to]; // make sure it is created and marked as seen
|
|
||||||
|
AddLinks(sta, stb, pta, ptb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->IsPointVisible(pta, &dpi)) {
|
if (this->IsPointVisible(pta, &dpi)) {
|
||||||
this->cached_stations.push_back(std::make_pair(from, supply));
|
this->cached_stations.push_back({ from, supply, pta });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->cached_links.reserve(link_cache_map.size());
|
||||||
|
for (auto &iter : link_cache_map) {
|
||||||
|
this->cached_links.push_back({ iter.first.first, iter.first.second, iter.second.from_pt, iter.second.to_pt, iter.second.prop });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,31 +174,6 @@ inline bool LinkGraphOverlay::IsLinkVisible(Point pta, Point ptb, const DrawPixe
|
|||||||
ptb.y > dpi->top + dpi->height + padding));
|
ptb.y > dpi->top + dpi->height + padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all "interesting" links between the given stations to the cache.
|
|
||||||
* @param from The source station.
|
|
||||||
* @param to The destination station.
|
|
||||||
*/
|
|
||||||
void LinkGraphOverlay::AddLinks(const Station *from, const Station *to)
|
|
||||||
{
|
|
||||||
CargoID c;
|
|
||||||
FOR_EACH_SET_CARGO_ID(c, this->cargo_mask) {
|
|
||||||
if (!CargoSpec::Get(c)->IsValid()) continue;
|
|
||||||
const GoodsEntry &ge = from->goods[c];
|
|
||||||
if (!LinkGraph::IsValidID(ge.link_graph) ||
|
|
||||||
ge.link_graph != to->goods[c].link_graph) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const LinkGraph &lg = *LinkGraph::Get(ge.link_graph);
|
|
||||||
ConstEdge edge = lg[ge.node][to->goods[c].node];
|
|
||||||
if (edge.Capacity() > 0) {
|
|
||||||
this->AddStats(lg.Monthly(edge.Capacity()), lg.Monthly(edge.Usage()),
|
|
||||||
ge.flows.GetFlowVia(to->index), from->owner == OWNER_NONE || to->owner == OWNER_NONE,
|
|
||||||
this->cached_links[from->index][to->index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add information from a given pair of link stat and flow stat to the given
|
* Add information from a given pair of link stat and flow stat to the given
|
||||||
* link properties. The shown usage or plan is always the maximum of all link
|
* link properties. The shown usage or plan is always the maximum of all link
|
||||||
@@ -180,12 +196,35 @@ void LinkGraphOverlay::AddLinks(const Station *from, const Station *to)
|
|||||||
if (new_shared) cargo.shared = true;
|
if (new_shared) cargo.shared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkGraphOverlay::RefreshDrawCache()
|
||||||
|
{
|
||||||
|
for (StationSupplyList::iterator i(this->cached_stations.begin()); i != this->cached_stations.end(); ++i) {
|
||||||
|
const Station *st = Station::GetIfValid(i->id);
|
||||||
|
if (st == NULL) continue;
|
||||||
|
|
||||||
|
i->pt = this->GetStationMiddle(st);
|
||||||
|
}
|
||||||
|
for (LinkList::iterator i(this->cached_links.begin()); i != this->cached_links.end(); ++i) {
|
||||||
|
const Station *sta = Station::GetIfValid(i->from_id);
|
||||||
|
if (sta == NULL) continue;
|
||||||
|
const Station *stb = Station::GetIfValid(i->to_id);
|
||||||
|
if (stb == NULL) continue;
|
||||||
|
|
||||||
|
i->from_pt = this->GetStationMiddle(sta);
|
||||||
|
i->to_pt = this->GetStationMiddle(stb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the linkgraph overlay or some part of it, in the area given.
|
* Draw the linkgraph overlay or some part of it, in the area given.
|
||||||
* @param dpi Area to be drawn to.
|
* @param dpi Area to be drawn to.
|
||||||
*/
|
*/
|
||||||
void LinkGraphOverlay::Draw(const DrawPixelInfo *dpi) const
|
void LinkGraphOverlay::Draw(const DrawPixelInfo *dpi)
|
||||||
{
|
{
|
||||||
|
if (this->last_update_number != GetWindowUpdateNumber()) {
|
||||||
|
this->last_update_number = GetWindowUpdateNumber();
|
||||||
|
this->RefreshDrawCache();
|
||||||
|
}
|
||||||
this->DrawLinks(dpi);
|
this->DrawLinks(dpi);
|
||||||
this->DrawStationDots(dpi);
|
this->DrawStationDots(dpi);
|
||||||
}
|
}
|
||||||
@@ -196,15 +235,11 @@ void LinkGraphOverlay::Draw(const DrawPixelInfo *dpi) const
|
|||||||
*/
|
*/
|
||||||
void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
|
void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
|
||||||
{
|
{
|
||||||
for (LinkMap::const_iterator i(this->cached_links.begin()); i != this->cached_links.end(); ++i) {
|
for (LinkList::const_iterator i(this->cached_links.begin()); i != this->cached_links.end(); ++i) {
|
||||||
if (!Station::IsValidID(i->first)) continue;
|
if (!this->IsLinkVisible(i->from_pt, i->to_pt, dpi, this->scale + 2)) continue;
|
||||||
Point pta = this->GetStationMiddle(Station::Get(i->first));
|
if (!Station::IsValidID(i->from_id)) continue;
|
||||||
for (StationLinkMap::const_iterator j(i->second.begin()); j != i->second.end(); ++j) {
|
if (!Station::IsValidID(i->to_id)) continue;
|
||||||
if (!Station::IsValidID(j->first)) continue;
|
this->DrawContent(i->from_pt, i->to_pt, i->prop);
|
||||||
Point ptb = this->GetStationMiddle(Station::Get(j->first));
|
|
||||||
if (!this->IsLinkVisible(pta, ptb, dpi, this->scale + 2)) continue;
|
|
||||||
this->DrawContent(pta, ptb, j->second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,12 +276,13 @@ void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &c
|
|||||||
void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
||||||
{
|
{
|
||||||
for (StationSupplyList::const_iterator i(this->cached_stations.begin()); i != this->cached_stations.end(); ++i) {
|
for (StationSupplyList::const_iterator i(this->cached_stations.begin()); i != this->cached_stations.end(); ++i) {
|
||||||
const Station *st = Station::GetIfValid(i->first);
|
const Point &pt = i->pt;
|
||||||
if (st == NULL) continue;
|
|
||||||
Point pt = this->GetStationMiddle(st);
|
|
||||||
if (!this->IsPointVisible(pt, dpi, 3 * this->scale)) continue;
|
if (!this->IsPointVisible(pt, dpi, 3 * this->scale)) continue;
|
||||||
|
|
||||||
uint r = this->scale * 2 + this->scale * 2 * min(200, i->second) / 200;
|
const Station *st = Station::GetIfValid(i->id);
|
||||||
|
if (st == NULL) continue;
|
||||||
|
|
||||||
|
uint r = this->scale * 2 + this->scale * 2 * min(200, i->quantity) / 200;
|
||||||
|
|
||||||
LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
|
LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
|
||||||
_colour_gradient[st->owner != OWNER_NONE ?
|
_colour_gradient[st->owner != OWNER_NONE ?
|
||||||
|
@@ -37,9 +37,22 @@ struct LinkProperties {
|
|||||||
*/
|
*/
|
||||||
class LinkGraphOverlay {
|
class LinkGraphOverlay {
|
||||||
public:
|
public:
|
||||||
typedef std::map<StationID, LinkProperties> StationLinkMap;
|
struct StationSupplyInfo {
|
||||||
typedef std::map<StationID, StationLinkMap> LinkMap;
|
StationID id;
|
||||||
typedef std::vector<std::pair<StationID, uint> > StationSupplyList;
|
uint quantity;
|
||||||
|
Point pt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LinkInfo {
|
||||||
|
StationID from_id;
|
||||||
|
StationID to_id;
|
||||||
|
Point from_pt;
|
||||||
|
Point to_pt;
|
||||||
|
LinkProperties prop;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<StationSupplyInfo> StationSupplyList;
|
||||||
|
typedef std::vector<LinkInfo> LinkList;
|
||||||
|
|
||||||
static const uint8 LINK_COLOURS[];
|
static const uint8 LINK_COLOURS[];
|
||||||
|
|
||||||
@@ -56,7 +69,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
void RebuildCache();
|
void RebuildCache();
|
||||||
void Draw(const DrawPixelInfo *dpi) const;
|
void Draw(const DrawPixelInfo *dpi);
|
||||||
void SetCargoMask(uint32 cargo_mask);
|
void SetCargoMask(uint32 cargo_mask);
|
||||||
void SetCompanyMask(uint32 company_mask);
|
void SetCompanyMask(uint32 company_mask);
|
||||||
|
|
||||||
@@ -71,13 +84,14 @@ protected:
|
|||||||
const uint widget_id; ///< ID of Widget in Window to be drawn to.
|
const uint widget_id; ///< ID of Widget in Window to be drawn to.
|
||||||
uint32 cargo_mask; ///< Bitmask of cargos to be displayed.
|
uint32 cargo_mask; ///< Bitmask of cargos to be displayed.
|
||||||
uint32 company_mask; ///< Bitmask of companies to be displayed.
|
uint32 company_mask; ///< Bitmask of companies to be displayed.
|
||||||
LinkMap cached_links; ///< Cache for links to reduce recalculation.
|
LinkList cached_links; ///< Cache for links to reduce recalculation.
|
||||||
StationSupplyList cached_stations; ///< Cache for stations to be drawn.
|
StationSupplyList cached_stations; ///< Cache for stations to be drawn.
|
||||||
uint scale; ///< Width of link lines.
|
uint scale; ///< Width of link lines.
|
||||||
|
uint64 last_update_number = 0; ///< Last window update number
|
||||||
|
|
||||||
Point GetStationMiddle(const Station *st) const;
|
Point GetStationMiddle(const Station *st) const;
|
||||||
|
|
||||||
void AddLinks(const Station *sta, const Station *stb);
|
void RefreshDrawCache();
|
||||||
void DrawLinks(const DrawPixelInfo *dpi) const;
|
void DrawLinks(const DrawPixelInfo *dpi) const;
|
||||||
void DrawStationDots(const DrawPixelInfo *dpi) const;
|
void DrawStationDots(const DrawPixelInfo *dpi) const;
|
||||||
void DrawContent(Point pta, Point ptb, const LinkProperties &cargo) const;
|
void DrawContent(Point pta, Point ptb, const LinkProperties &cargo) const;
|
||||||
|
Reference in New Issue
Block a user