flowmapper.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "flowmapper.h"
00014 
00019 void FlowMapper::Run(LinkGraphJob *job)
00020 {
00021   LinkGraph *graph = &job->Graph();
00022   /* Time the graph has been running without being compressed. */
00023   uint runtime = job->JoinDate() - job->Settings().recalc_time - graph->GetLastCompression();
00024 
00025   for (NodeID node_id = 0; node_id < graph->GetSize(); ++node_id) {
00026     Node &prev_node = graph->GetNode(node_id);
00027     NodeAnnotation &prev_anno = job->GetNode(node_id);
00028     StationID prev = prev_node.station;
00029     PathSet &paths = prev_anno.paths;
00030     for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00031       Path *path = *i;
00032       uint flow = path->GetFlow();
00033       if (flow == 0) continue;
00034       /* compress to monthly value */
00035       flow = max(1U, flow * 30 / runtime);
00036       NodeAnnotation &node = job->GetNode(path->GetNode());
00037       StationID via = graph->GetNode(path->GetNode()).station;
00038       assert(prev != via);
00039       StationID origin = graph->GetNode(path->GetOrigin()).station;
00040       assert(via != origin);
00041       FlowStatMap::iterator origin_it = node.flows.find(origin);
00042       /* Mark all of the flow for local consumption at "first". */
00043       if (origin_it == node.flows.end()) {
00044         node.flows.insert(std::make_pair(origin, FlowStat(via, flow)));
00045       } else {
00046         origin_it->second.ChangeShare(via, flow);
00047         /* Find simple circular flows ... */
00048         assert(origin_it->second.GetShare(prev) == 0);
00049       }
00050       /* Pass some of the flow marked for local consumption at "prev" on
00051        * to this node. */
00052       FlowStatMap::iterator prev_it = prev_anno.flows.find(origin);
00053       if (prev_it == prev_anno.flows.end()) {
00054         FlowStat fs(via, flow);
00055         if (prev != origin) fs.AppendShare(INVALID_STATION, flow);
00056         prev_anno.flows.insert(std::make_pair(origin, fs));
00057       } else {
00058         prev_it->second.ChangeShare(via, flow);
00059         if (prev != origin) prev_it->second.ChangeShare(INVALID_STATION, flow);
00060       }
00061     }
00062   }
00063 
00064   for (NodeID node_id = 0; node_id < graph->GetSize(); ++node_id) {
00065     /* Remove local consumption shares marked as invalid. */
00066     FlowStatMap & flows = job->GetNode(node_id).flows;
00067     for (FlowStatMap::iterator i = flows.begin(); i != flows.end(); ++i) {
00068       FlowStat &fs = i->second;
00069       uint local = fs.GetShare(INVALID_STATION);
00070       fs.ChangeShare(graph->GetNode(node_id).station, -local);
00071       fs.ChangeShare(INVALID_STATION, -local);
00072     }
00073     /* Clear paths. */
00074     PathSet &paths = job->GetNode(node_id).paths;
00075     for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00076       delete *i;
00077     }
00078     paths.clear();
00079   }
00080 }