Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file RODFNet.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Eric Nicolay
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @date Thu, 16.03.2006
20 : ///
21 : // A DFROUTER-network
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <cassert>
26 : #include <iostream>
27 : #include <map>
28 : #include <queue>
29 : #include <vector>
30 : #include <iterator>
31 : #include "RODFNet.h"
32 : #include "RODFDetector.h"
33 : #include "RODFRouteDesc.h"
34 : #include "RODFDetectorFlow.h"
35 : #include "RODFEdge.h"
36 : #include <cmath>
37 : #include <utils/common/MsgHandler.h>
38 : #include <utils/common/ToString.h>
39 : #include <utils/common/UtilExceptions.h>
40 : #include <utils/geom/GeomHelper.h>
41 :
42 :
43 : // ===========================================================================
44 : // method definitions
45 : // ===========================================================================
46 437 : RODFNet::RODFNet(bool amInHighwayMode) :
47 437 : RONet(), myAmInHighwayMode(amInHighwayMode),
48 437 : mySourceNumber(0), mySinkNumber(0), myInBetweenNumber(0), myInvalidNumber(0),
49 437 : myMaxSpeedFactorPKW(1),
50 437 : myMaxSpeedFactorLKW(1),
51 437 : myAvgSpeedFactorPKW(1),
52 437 : myAvgSpeedFactorLKW(1) {
53 437 : myDisallowedEdges = OptionsCont::getOptions().getStringVector("disallowed-edges");
54 437 : myAllowedVClass = getVehicleClassID(OptionsCont::getOptions().getString("vclass"));
55 437 : myKeepTurnarounds = OptionsCont::getOptions().getBool("keep-turnarounds");
56 437 : }
57 :
58 :
59 874 : RODFNet::~RODFNet() {
60 1311 : }
61 :
62 :
63 : bool
64 6974 : RODFNet::isAllowed(const ROEdge* const edge) const {
65 6244 : return (!edge->isInternal() && !edge->isWalkingArea() && !edge->isCrossing() &&
66 6244 : (edge->getPermissions() & myAllowedVClass) == myAllowedVClass &&
67 6242 : find(myDisallowedEdges.begin(), myDisallowedEdges.end(), edge->getID()) == myDisallowedEdges.end());
68 :
69 : }
70 :
71 :
72 : void
73 201 : RODFNet::buildApproachList() {
74 3790 : for (ROEdge* const ce : ROEdge::getAllEdges()) {
75 3589 : if (!isAllowed(ce)) {
76 746 : continue;
77 : }
78 6228 : for (ROEdge* const help : ce->getSuccessors()) {
79 3385 : if (!isAllowed(help)) {
80 : // blocked edges will not be used
81 22 : continue;
82 : }
83 3363 : if (!myKeepTurnarounds && help->getToJunction() == ce->getFromJunction()) {
84 : // do not use turnarounds
85 98 : continue;
86 : }
87 : // add the connection help->ce to myApproachingEdges
88 3265 : myApproachingEdges[help].push_back(ce);
89 : // add the connection ce->help to myApproachingEdges
90 3265 : myApproachedEdges[ce].push_back(help);
91 : }
92 : }
93 201 : }
94 :
95 :
96 : void
97 334 : RODFNet::buildDetectorEdgeDependencies(RODFDetectorCon& detcont) const {
98 : myDetectorsOnEdges.clear();
99 : myDetectorEdges.clear();
100 334 : const std::vector<RODFDetector*>& dets = detcont.getDetectors();
101 3300 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
102 2966 : ROEdge* e = getDetectorEdge(**i);
103 2966 : myDetectorsOnEdges[e].push_back((*i)->getID());
104 2966 : myDetectorEdges[(*i)->getID()] = e;
105 : }
106 334 : }
107 :
108 :
109 : void
110 165 : RODFNet::computeTypes(RODFDetectorCon& detcont,
111 : bool sourcesStrict) const {
112 330 : PROGRESS_BEGIN_MESSAGE(TL("Computing detector types"));
113 165 : const std::vector< RODFDetector*>& dets = detcont.getDetectors();
114 : // build needed information. first
115 165 : buildDetectorEdgeDependencies(detcont);
116 : // compute detector types then
117 1576 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
118 1411 : if (isSource(**i, detcont, sourcesStrict)) {
119 331 : (*i)->setType(SOURCE_DETECTOR);
120 331 : mySourceNumber++;
121 : }
122 1411 : if (isDestination(**i, detcont)) {
123 243 : (*i)->setType(SINK_DETECTOR);
124 243 : mySinkNumber++;
125 : }
126 1411 : if ((*i)->getType() == TYPE_NOT_DEFINED) {
127 868 : (*i)->setType(BETWEEN_DETECTOR);
128 868 : myInBetweenNumber++;
129 : }
130 : }
131 : // recheck sources
132 1576 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
133 1411 : if ((*i)->getType() == SOURCE_DETECTOR && isFalseSource(**i, detcont)) {
134 19 : (*i)->setType(DISCARDED_DETECTOR);
135 19 : myInvalidNumber++;
136 19 : mySourceNumber--;
137 : }
138 : }
139 : // print results
140 165 : PROGRESS_DONE_MESSAGE();
141 165 : WRITE_MESSAGE(TL("Computed detector types:"));
142 330 : WRITE_MESSAGEF(TL(" % source detectors"), toString(mySourceNumber));
143 330 : WRITE_MESSAGEF(TL(" % sink detectors"), toString(mySinkNumber));
144 330 : WRITE_MESSAGEF(TL(" % in-between detectors"), toString(myInBetweenNumber));
145 330 : WRITE_MESSAGEF(TL(" % invalid detectors"), toString(myInvalidNumber));
146 165 : }
147 :
148 :
149 : bool
150 3081 : RODFNet::hasInBetweenDetectorsOnly(ROEdge* edge,
151 : const RODFDetectorCon& detectors) const {
152 : assert(myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end());
153 : const std::vector<std::string>& detIDs = myDetectorsOnEdges.find(edge)->second;
154 : std::vector<std::string>::const_iterator i;
155 5446 : for (i = detIDs.begin(); i != detIDs.end(); ++i) {
156 3831 : const RODFDetector& det = detectors.getDetector(*i);
157 3831 : if (det.getType() != BETWEEN_DETECTOR) {
158 : return false;
159 : }
160 : }
161 : return true;
162 : }
163 :
164 :
165 : bool
166 1466 : RODFNet::hasSourceDetector(ROEdge* edge,
167 : const RODFDetectorCon& detectors) const {
168 : assert(myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end());
169 : const std::vector<std::string>& detIDs = myDetectorsOnEdges.find(edge)->second;
170 : std::vector<std::string>::const_iterator i;
171 3163 : for (i = detIDs.begin(); i != detIDs.end(); ++i) {
172 1732 : const RODFDetector& det = detectors.getDetector(*i);
173 1732 : if (det.getType() == SOURCE_DETECTOR) {
174 : return true;
175 : }
176 : }
177 : return false;
178 : }
179 :
180 :
181 :
182 : void
183 1252 : RODFNet::computeRoutesFor(ROEdge* edge, RODFRouteDesc& base, int /*no*/,
184 : bool keepUnfoundEnds,
185 : bool keepShortestOnly,
186 : ROEdgeVector& /*visited*/,
187 : const RODFDetector& det, RODFRouteCont& into,
188 : const RODFDetectorCon& detectors,
189 : int maxFollowingLength,
190 : ROEdgeVector& seen) const {
191 : std::vector<RODFRouteDesc> unfoundEnds;
192 : std::priority_queue<RODFRouteDesc, std::vector<RODFRouteDesc>, DFRouteDescByTimeComperator> toSolve;
193 : std::map<ROEdge*, ROEdgeVector > dets2Follow;
194 1252 : dets2Follow[edge] = ROEdgeVector();
195 1252 : base.passedNo = 0;
196 1252 : double minDist = OptionsCont::getOptions().getFloat("min-route-length");
197 1252 : toSolve.push(base);
198 6920 : while (!toSolve.empty()) {
199 5668 : RODFRouteDesc current = toSolve.top();
200 5668 : toSolve.pop();
201 5668 : ROEdge* last = *(current.edges2Pass.end() - 1);
202 5668 : if (hasDetector(last)) {
203 4509 : if (dets2Follow.find(last) == dets2Follow.end()) {
204 3052 : dets2Follow[last] = ROEdgeVector();
205 : }
206 5095 : for (ROEdgeVector::reverse_iterator i = current.edges2Pass.rbegin() + 1; i != current.edges2Pass.rend(); ++i) {
207 3843 : if (hasDetector(*i)) {
208 3257 : dets2Follow[*i].push_back(last);
209 : break;
210 : }
211 : }
212 : }
213 :
214 : // do not process an edge twice
215 5668 : if (find(seen.begin(), seen.end(), last) != seen.end() && keepShortestOnly) {
216 116 : continue;
217 : }
218 5552 : seen.push_back(last);
219 : // end if the edge has no further connections
220 5552 : if (!hasApproached(last)) {
221 : // ok, no further connections to follow
222 598 : current.factor = 1.;
223 598 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
224 598 : if (minDist < cdist) {
225 594 : into.addRouteDesc(current);
226 : }
227 598 : continue;
228 598 : }
229 : // check for passing detectors:
230 : // if the current last edge is not the one the detector is placed on ...
231 : bool addNextNoFurther = false;
232 4954 : if (last != getDetectorEdge(det)) {
233 : // ... if there is a detector ...
234 3760 : if (hasDetector(last)) {
235 3081 : if (!hasInBetweenDetectorsOnly(last, detectors)) {
236 : // ... and it's not an in-between-detector
237 : // -> let's add this edge and the following, but not any further
238 : addNextNoFurther = true;
239 1466 : current.lastDetectorEdge = last;
240 1466 : current.duration2Last = (SUMOTime) current.duration_2;
241 1466 : current.distance2Last = current.distance;
242 1466 : current.endDetectorEdge = last;
243 1466 : if (hasSourceDetector(last, detectors)) {
244 : ///!!! //toDiscard.push_back(current);
245 : }
246 1466 : current.factor = 1.;
247 1466 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
248 1466 : if (minDist < cdist) {
249 1462 : into.addRouteDesc(current);
250 : }
251 1466 : continue;
252 1466 : } else {
253 : // ... if it's an in-between-detector
254 : // -> mark the current route as to be continued
255 1615 : current.passedNo = 0;
256 1615 : current.duration2Last = (SUMOTime) current.duration_2;
257 1615 : current.distance2Last = current.distance;
258 1615 : current.lastDetectorEdge = last;
259 : }
260 : }
261 : }
262 : // check for highway off-ramps
263 3488 : if (myAmInHighwayMode) {
264 : // if it's beside the highway...
265 0 : if (last->getSpeedLimit() < 19.4 && last != getDetectorEdge(det)) {
266 : // ... and has more than one following edge
267 0 : if (myApproachedEdges.find(last)->second.size() > 1) {
268 : // -> let's add this edge and the following, but not any further
269 : addNextNoFurther = true;
270 : }
271 :
272 : }
273 : }
274 : // check for missing end connections
275 : if (!addNextNoFurther) {
276 : // ... if this one would be processed, but already too many edge
277 : // without a detector occurred
278 3488 : if (current.passedNo > maxFollowingLength) {
279 : // mark not to process any further
280 0 : WRITE_WARNINGF(TL("Could not close route for '%'"), det.getID());
281 0 : unfoundEnds.push_back(current);
282 0 : current.factor = 1.;
283 0 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
284 0 : if (minDist < cdist) {
285 0 : into.addRouteDesc(current);
286 : }
287 0 : continue;
288 0 : }
289 : }
290 : // ... else: loop over the next edges
291 : const ROEdgeVector& appr = myApproachedEdges.find(last)->second;
292 : bool hadOne = false;
293 7997 : for (int i = 0; i < (int)appr.size(); i++) {
294 4509 : if (find(current.edges2Pass.begin(), current.edges2Pass.end(), appr[i]) != current.edges2Pass.end()) {
295 : // do not append an edge twice (do not build loops)
296 93 : continue;
297 : }
298 4416 : RODFRouteDesc t(current);
299 4416 : t.duration_2 += (appr[i]->getLength() / appr[i]->getSpeedLimit()); //!!!
300 4416 : t.distance += appr[i]->getLength();
301 4416 : t.edges2Pass.push_back(appr[i]);
302 4416 : if (!addNextNoFurther) {
303 4416 : t.passedNo++;
304 4416 : toSolve.push(t);
305 : } else {
306 0 : if (!hadOne) {
307 0 : t.factor = (double) 1. / (double) appr.size();
308 0 : double cdist = current.edges2Pass[0]->getFromJunction()->getPosition().distanceTo(current.edges2Pass.back()->getToJunction()->getPosition());
309 0 : if (minDist < cdist) {
310 0 : into.addRouteDesc(t);
311 : }
312 : hadOne = true;
313 : }
314 : }
315 : }
316 : }
317 : //
318 1252 : if (!keepUnfoundEnds) {
319 : std::vector<RODFRouteDesc>::iterator i;
320 : ConstROEdgeVector lastDetEdges;
321 1252 : for (i = unfoundEnds.begin(); i != unfoundEnds.end(); ++i) {
322 0 : if (find(lastDetEdges.begin(), lastDetEdges.end(), (*i).lastDetectorEdge) == lastDetEdges.end()) {
323 0 : lastDetEdges.push_back((*i).lastDetectorEdge);
324 : } else {
325 0 : bool ok = into.removeRouteDesc(*i);
326 : assert(ok);
327 : UNUSED_PARAMETER(ok); // only used for assertion
328 : }
329 : }
330 1252 : } else {
331 : // !!! patch the factors
332 : }
333 1252 : while (!toSolve.empty()) {
334 : // RODFRouteDesc d = toSolve.top();
335 0 : toSolve.pop();
336 : // delete d;
337 : }
338 1252 : }
339 :
340 :
341 : void
342 169 : RODFNet::buildRoutes(RODFDetectorCon& detcont, bool keepUnfoundEnds, bool includeInBetween,
343 : bool keepShortestOnly, int maxFollowingLength) const {
344 : // build needed information first
345 169 : buildDetectorEdgeDependencies(detcont);
346 : // then build the routes
347 : std::map<ROEdge*, RODFRouteCont* > doneEdges;
348 169 : const std::vector< RODFDetector*>& dets = detcont.getDetectors();
349 1724 : for (std::vector< RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
350 1555 : ROEdge* e = getDetectorEdge(**i);
351 1555 : if (doneEdges.find(e) != doneEdges.end()) {
352 : // use previously build routes
353 303 : (*i)->addRoutes(new RODFRouteCont(*doneEdges[e]));
354 303 : continue;
355 : }
356 : ROEdgeVector seen;
357 1252 : RODFRouteCont* routes = new RODFRouteCont();
358 1252 : doneEdges[e] = routes;
359 : RODFRouteDesc rd;
360 1252 : rd.edges2Pass.push_back(e);
361 1252 : rd.duration_2 = (e->getLength() / e->getSpeedLimit()); //!!!;
362 1252 : rd.endDetectorEdge = nullptr;
363 1252 : rd.lastDetectorEdge = nullptr;
364 1252 : rd.distance = e->getLength();
365 1252 : rd.distance2Last = 0;
366 1252 : rd.duration2Last = 0;
367 :
368 1252 : rd.overallProb = 0;
369 :
370 : ROEdgeVector visited;
371 1252 : visited.push_back(e);
372 1252 : computeRoutesFor(e, rd, 0, keepUnfoundEnds, keepShortestOnly,
373 : visited, **i, *routes, detcont, maxFollowingLength, seen);
374 : //!!!routes->removeIllegal(illegals);
375 1252 : (*i)->addRoutes(routes);
376 :
377 : // add routes to in-between detectors if wished
378 1252 : if (includeInBetween) {
379 : // go through the routes
380 : const std::vector<RODFRouteDesc>& r = routes->get();
381 12 : for (std::vector<RODFRouteDesc>::const_iterator j = r.begin(); j != r.end(); ++j) {
382 : const RODFRouteDesc& mrd = *j;
383 6 : double duration = mrd.duration_2;
384 6 : double distance = mrd.distance;
385 : // go through each route's edges
386 : ROEdgeVector::const_iterator routeend = mrd.edges2Pass.end();
387 18 : for (ROEdgeVector::const_iterator k = mrd.edges2Pass.begin(); k != routeend; ++k) {
388 : // check whether any detectors lies on the current edge
389 12 : if (myDetectorsOnEdges.find(*k) == myDetectorsOnEdges.end()) {
390 0 : duration -= (*k)->getLength() / (*k)->getSpeedLimit();
391 0 : distance -= (*k)->getLength();
392 0 : continue;
393 : }
394 : // go through the detectors
395 24 : for (const std::string& l : myDetectorsOnEdges.find(*k)->second) {
396 12 : const RODFDetector& m = detcont.getDetector(l);
397 12 : if (m.getType() == BETWEEN_DETECTOR) {
398 : RODFRouteDesc nrd;
399 : copy(k, routeend, back_inserter(nrd.edges2Pass));
400 4 : nrd.duration_2 = duration;//!!!;
401 4 : nrd.endDetectorEdge = mrd.endDetectorEdge;
402 4 : nrd.lastDetectorEdge = mrd.lastDetectorEdge;
403 4 : nrd.distance = distance;
404 4 : nrd.distance2Last = mrd.distance2Last;
405 4 : nrd.duration2Last = mrd.duration2Last;
406 4 : nrd.overallProb = mrd.overallProb;
407 4 : nrd.factor = mrd.factor;
408 4 : ((RODFDetector&) m).addRoute(nrd);
409 : }
410 : }
411 12 : duration -= (*k)->getLength() / (*k)->getSpeedLimit();
412 12 : distance -= (*k)->getLength();
413 : }
414 : }
415 : }
416 :
417 2504 : }
418 169 : }
419 :
420 :
421 : void
422 0 : RODFNet::revalidateFlows(const RODFDetector* detector,
423 : RODFDetectorFlows& flows,
424 : SUMOTime startTime, SUMOTime endTime,
425 : SUMOTime stepOffset) {
426 : {
427 0 : if (flows.knows(detector->getID())) {
428 0 : const std::vector<FlowDef>& detFlows = flows.getFlowDefs(detector->getID());
429 0 : for (std::vector<FlowDef>::const_iterator j = detFlows.begin(); j != detFlows.end(); ++j) {
430 0 : if ((*j).qPKW > 0 || (*j).qLKW > 0) {
431 : return;
432 : }
433 : }
434 : }
435 : }
436 : // ok, there is no information for the whole time;
437 : // lets find preceding detectors and rebuild the flows if possible
438 0 : WRITE_WARNINGF(TL("Detector '%' has no flows.\n Trying to rebuild."), detector->getID());
439 : // go back and collect flows
440 : ROEdgeVector previous;
441 : {
442 : std::vector<IterationEdge> missing;
443 : IterationEdge ie;
444 0 : ie.depth = 0;
445 0 : ie.edge = getDetectorEdge(*detector);
446 0 : missing.push_back(ie);
447 : bool maxDepthReached = false;
448 0 : while (!missing.empty() && !maxDepthReached) {
449 0 : IterationEdge last = missing.back();
450 : missing.pop_back();
451 0 : ROEdgeVector approaching = myApproachingEdges[last.edge];
452 0 : for (ROEdgeVector::const_iterator j = approaching.begin(); j != approaching.end(); ++j) {
453 0 : if (hasDetector(*j)) {
454 0 : previous.push_back(*j);
455 : } else {
456 0 : ie.depth = last.depth + 1;
457 0 : ie.edge = *j;
458 0 : missing.push_back(ie);
459 0 : if (ie.depth > 5) {
460 : maxDepthReached = true;
461 : }
462 : }
463 : }
464 0 : }
465 0 : if (maxDepthReached) {
466 0 : WRITE_WARNING(TL(" Could not build list of previous flows."));
467 : }
468 0 : }
469 : // Edges with previous detectors are now in "previous";
470 : // compute following
471 : ROEdgeVector latter;
472 : {
473 : std::vector<IterationEdge> missing;
474 0 : for (ROEdgeVector::const_iterator k = previous.begin(); k != previous.end(); ++k) {
475 : IterationEdge ie;
476 0 : ie.depth = 0;
477 0 : ie.edge = *k;
478 0 : missing.push_back(ie);
479 : }
480 : bool maxDepthReached = false;
481 0 : while (!missing.empty() && !maxDepthReached) {
482 0 : IterationEdge last = missing.back();
483 : missing.pop_back();
484 0 : ROEdgeVector approached = myApproachedEdges[last.edge];
485 0 : for (ROEdgeVector::const_iterator j = approached.begin(); j != approached.end(); ++j) {
486 0 : if (*j == getDetectorEdge(*detector)) {
487 0 : continue;
488 : }
489 0 : if (hasDetector(*j)) {
490 0 : latter.push_back(*j);
491 : } else {
492 : IterationEdge ie;
493 0 : ie.depth = last.depth + 1;
494 0 : ie.edge = *j;
495 0 : missing.push_back(ie);
496 0 : if (ie.depth > 5) {
497 : maxDepthReached = true;
498 : }
499 : }
500 : }
501 0 : }
502 0 : if (maxDepthReached) {
503 0 : WRITE_WARNING(TL(" Could not build list of latter flows."));
504 : return;
505 : }
506 0 : }
507 : // Edges with latter detectors are now in "latter";
508 :
509 : // lets not validate them by now - surely this should be done
510 : // for each time step: collect incoming flows; collect outgoing;
511 : std::vector<FlowDef> mflows;
512 : int index = 0;
513 0 : for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
514 : // collect incoming
515 : FlowDef inFlow;
516 : inFlow.qLKW = 0;
517 : inFlow.qPKW = 0;
518 : inFlow.vLKW = 0;
519 : inFlow.vPKW = 0;
520 : // !! time difference is missing
521 0 : for (const ROEdge* const e : previous) {
522 0 : const std::vector<FlowDef>& eflows = static_cast<const RODFEdge*>(e)->getFlows();
523 0 : if (eflows.size() != 0) {
524 0 : const FlowDef& srcFD = eflows[index];
525 0 : inFlow.qLKW += srcFD.qLKW;
526 0 : inFlow.qPKW += srcFD.qPKW;
527 0 : inFlow.vLKW += srcFD.vLKW;
528 0 : inFlow.vPKW += srcFD.vPKW;
529 : }
530 : }
531 0 : inFlow.vLKW /= (double) previous.size();
532 0 : inFlow.vPKW /= (double) previous.size();
533 : // collect outgoing
534 : FlowDef outFlow;
535 : outFlow.qLKW = 0;
536 : outFlow.qPKW = 0;
537 : outFlow.vLKW = 0;
538 : outFlow.vPKW = 0;
539 : // !! time difference is missing
540 0 : for (const ROEdge* const e : latter) {
541 0 : const std::vector<FlowDef>& eflows = static_cast<const RODFEdge*>(e)->getFlows();
542 0 : if (eflows.size() != 0) {
543 0 : const FlowDef& srcFD = eflows[index];
544 0 : outFlow.qLKW += srcFD.qLKW;
545 0 : outFlow.qPKW += srcFD.qPKW;
546 0 : outFlow.vLKW += srcFD.vLKW;
547 0 : outFlow.vPKW += srcFD.vPKW;
548 : }
549 : }
550 0 : outFlow.vLKW /= (double) latter.size();
551 0 : outFlow.vPKW /= (double) latter.size();
552 : //
553 : FlowDef mFlow;
554 0 : mFlow.qLKW = inFlow.qLKW - outFlow.qLKW;
555 0 : mFlow.qPKW = inFlow.qPKW - outFlow.qPKW;
556 0 : mFlow.vLKW = (inFlow.vLKW + outFlow.vLKW) / (double) 2.;
557 0 : mFlow.vPKW = (inFlow.vPKW + outFlow.vPKW) / (double) 2.;
558 0 : mflows.push_back(mFlow);
559 : }
560 0 : static_cast<RODFEdge*>(getDetectorEdge(*detector))->setFlows(mflows);
561 0 : flows.setFlows(detector->getID(), mflows);
562 0 : }
563 :
564 :
565 : void
566 0 : RODFNet::revalidateFlows(const RODFDetectorCon& detectors,
567 : RODFDetectorFlows& flows,
568 : SUMOTime startTime, SUMOTime endTime,
569 : SUMOTime stepOffset) {
570 0 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
571 0 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
572 : // check whether there is at least one entry with a flow larger than zero
573 0 : revalidateFlows(*i, flows, startTime, endTime, stepOffset);
574 : }
575 0 : }
576 :
577 :
578 :
579 : void
580 7 : RODFNet::removeEmptyDetectors(RODFDetectorCon& detectors,
581 : RODFDetectorFlows& flows) {
582 7 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
583 106 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end();) {
584 : bool remove = true;
585 : // check whether there is at least one entry with a flow larger than zero
586 99 : if (flows.knows((*i)->getID())) {
587 : remove = false;
588 : }
589 : if (remove) {
590 21 : WRITE_MESSAGEF(TL("Removed detector '%' because no flows for him exist."), (*i)->getID());
591 7 : flows.removeFlow((*i)->getID());
592 7 : detectors.removeDetector((*i)->getID());
593 : i = dets.begin();
594 : } else {
595 : i++;
596 : }
597 : }
598 7 : }
599 :
600 :
601 :
602 : void
603 7 : RODFNet::reportEmptyDetectors(RODFDetectorCon& detectors,
604 : RODFDetectorFlows& flows) {
605 7 : const std::vector<RODFDetector*>& dets = detectors.getDetectors();
606 70 : for (std::vector<RODFDetector*>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
607 : bool remove = true;
608 : // check whether there is at least one entry with a flow larger than zero
609 63 : if (flows.knows((*i)->getID())) {
610 : remove = false;
611 : }
612 : if (remove) {
613 21 : WRITE_MESSAGEF(TL("Detector '%' has no flow."), (*i)->getID());
614 : }
615 : }
616 7 : }
617 :
618 :
619 :
620 : ROEdge*
621 28142 : RODFNet::getDetectorEdge(const RODFDetector& det) const {
622 56284 : const std::string edgeName = SUMOXMLDefinitions::getEdgeIDFromLane(det.getLaneID());
623 : ROEdge* ret = getEdge(edgeName);
624 28142 : if (ret == nullptr) {
625 0 : throw ProcessError("Edge '" + edgeName + "' used by detector '" + det.getID() + "' is not known.");
626 : }
627 28142 : return ret;
628 : }
629 :
630 :
631 : bool
632 3505 : RODFNet::hasApproaching(ROEdge* edge) const {
633 : return myApproachingEdges.find(edge) != myApproachingEdges.end()
634 6283 : && myApproachingEdges.find(edge)->second.size() != 0;
635 : }
636 :
637 :
638 : bool
639 8400 : RODFNet::hasApproached(ROEdge* edge) const {
640 : return myApproachedEdges.find(edge) != myApproachedEdges.end()
641 15880 : && myApproachedEdges.find(edge)->second.size() != 0;
642 : }
643 :
644 :
645 : bool
646 1472894 : RODFNet::hasDetector(ROEdge* edge) const {
647 : return myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
648 1472894 : && myDetectorsOnEdges.find(edge)->second.size() != 0;
649 : }
650 :
651 :
652 : const std::vector<std::string>&
653 0 : RODFNet::getDetectorList(ROEdge* edge) const {
654 0 : return myDetectorsOnEdges.find(edge)->second;
655 : }
656 :
657 :
658 : double
659 0 : RODFNet::getAbsPos(const RODFDetector& det) const {
660 1870 : if (det.getPos() >= 0) {
661 : return det.getPos();
662 : }
663 1380 : return getDetectorEdge(det)->getLength() + det.getPos();
664 : }
665 :
666 : bool
667 1411 : RODFNet::isSource(const RODFDetector& det, const RODFDetectorCon& detectors,
668 : bool strict) const {
669 : ROEdgeVector seen;
670 2822 : return isSource(det, getDetectorEdge(det), seen, detectors, strict);
671 1411 : }
672 :
673 : bool
674 300 : RODFNet::isFalseSource(const RODFDetector& det, const RODFDetectorCon& detectors) const {
675 : ROEdgeVector seen;
676 600 : return isFalseSource(det, getDetectorEdge(det), seen, detectors);
677 300 : }
678 :
679 : bool
680 1411 : RODFNet::isDestination(const RODFDetector& det, const RODFDetectorCon& detectors) const {
681 : ROEdgeVector seen;
682 2822 : return isDestination(det, getDetectorEdge(det), seen, detectors);
683 1411 : }
684 :
685 :
686 : bool
687 3561 : RODFNet::isSource(const RODFDetector& det, ROEdge* edge,
688 : ROEdgeVector& seen,
689 : const RODFDetectorCon& detectors,
690 : bool strict) const {
691 3561 : if (seen.size() == 1000) { // !!!
692 0 : WRITE_WARNINGF(TL("Quitting checking for being a source for detector '%' due to seen edge limit."), det.getID());
693 0 : return false;
694 : }
695 3561 : if (edge == getDetectorEdge(det)) {
696 : // maybe there is another detector at the same edge
697 : // get the list of this/these detector(s)
698 : const std::vector<std::string>& detsOnEdge = myDetectorsOnEdges.find(edge)->second;
699 3348 : for (std::vector<std::string>::const_iterator i = detsOnEdge.begin(); i != detsOnEdge.end(); ++i) {
700 1993 : if ((*i) == det.getID()) {
701 1393 : continue;
702 : }
703 600 : const RODFDetector& sec = detectors.getDetector(*i);
704 600 : if (getAbsPos(sec) < getAbsPos(det)) {
705 : // ok, there is another detector on the same edge and it is
706 : // before this one -> no source
707 : return false;
708 : }
709 : }
710 : }
711 : // it's a source if no edges are approaching the edge
712 3505 : if (!hasApproaching(edge)) {
713 727 : if (edge != getDetectorEdge(det)) {
714 555 : if (hasDetector(edge)) {
715 : return false;
716 : }
717 : }
718 : return true;
719 : }
720 2778 : if (edge != getDetectorEdge(det)) {
721 : // ok, we are at one of the edges in front
722 1595 : if (myAmInHighwayMode) {
723 0 : if (edge->getSpeedLimit() >= 19.4) {
724 0 : if (hasDetector(edge)) {
725 : // we are still on the highway and there is another detector
726 : return false;
727 : }
728 : // the next is a hack for the A100 scenario...
729 : // We have to look into further edges herein edges
730 : const ROEdgeVector& appr = myApproachingEdges.find(edge)->second;
731 : int noFalse = 0;
732 : int noSkipped = 0;
733 0 : for (int i = 0; i < (int)appr.size(); i++) {
734 0 : if (hasDetector(appr[i])) {
735 0 : noFalse++;
736 : }
737 : }
738 0 : if (noFalse + noSkipped == (int)appr.size()) {
739 : return false;
740 : }
741 : }
742 : }
743 : }
744 :
745 2778 : if (myAmInHighwayMode) {
746 0 : if (edge->getSpeedLimit() < 19.4 && edge != getDetectorEdge(det)) {
747 : // we have left the highway already
748 : // -> the detector will be a highway source
749 0 : if (!hasDetector(edge)) {
750 : return true;
751 : }
752 : }
753 : }
754 : if (myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
755 2778 : &&
756 2311 : myDetectorEdges.find(det.getID())->second != edge) {
757 : return false;
758 : }
759 :
760 : // let's check the edges in front
761 : const ROEdgeVector& appr = myApproachingEdges.find(edge)->second;
762 : int numOk = 0;
763 : int numFalse = 0;
764 : int numSkipped = 0;
765 1650 : seen.push_back(edge);
766 3911 : for (int i = 0; i < (int)appr.size(); i++) {
767 2261 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
768 2261 : if (!had) {
769 2150 : if (isSource(det, appr[i], seen, detectors, strict)) {
770 363 : numOk++;
771 : } else {
772 1787 : numFalse++;
773 : }
774 : } else {
775 111 : numSkipped++;
776 : }
777 : }
778 1650 : if (strict) {
779 0 : return numOk + numSkipped == (int)appr.size();
780 : }
781 1650 : return numFalse + numSkipped != (int)appr.size();
782 : }
783 :
784 :
785 : bool
786 2904 : RODFNet::isDestination(const RODFDetector& det, ROEdge* edge, ROEdgeVector& seen,
787 : const RODFDetectorCon& detectors) const {
788 2904 : if (seen.size() == 1000) { // !!!
789 0 : WRITE_WARNINGF(TL("Quitting checking for being a destination for detector '%' due to seen edge limit."), det.getID());
790 0 : return false;
791 : }
792 2904 : if (edge == getDetectorEdge(det)) {
793 : // maybe there is another detector at the same edge
794 : // get the list of this/these detector(s)
795 : const std::vector<std::string>& detsOnEdge = myDetectorsOnEdges.find(edge)->second;
796 3308 : for (std::vector<std::string>::const_iterator i = detsOnEdge.begin(); i != detsOnEdge.end(); ++i) {
797 1953 : if ((*i) == det.getID()) {
798 1373 : continue;
799 : }
800 580 : const RODFDetector& sec = detectors.getDetector(*i);
801 580 : if (getAbsPos(sec) > getAbsPos(det)) {
802 : // ok, there is another detector on the same edge and it is
803 : // after this one -> no destination
804 : return false;
805 : }
806 : }
807 : }
808 2848 : if (!hasApproached(edge)) {
809 322 : if (edge != getDetectorEdge(det)) {
810 269 : if (hasDetector(edge)) {
811 : return false;
812 : }
813 : }
814 : return true;
815 : }
816 2526 : if (edge != getDetectorEdge(det)) {
817 : // ok, we are at one of the edges coming behind
818 1224 : if (myAmInHighwayMode) {
819 0 : if (edge->getSpeedLimit() >= 19.4) {
820 0 : if (hasDetector(edge)) {
821 : // we are still on the highway and there is another detector
822 : return false;
823 : }
824 : }
825 : }
826 : }
827 :
828 2526 : if (myAmInHighwayMode) {
829 0 : if (edge->getSpeedLimit() < 19.4 && edge != getDetectorEdge(det)) {
830 0 : if (hasDetector(edge)) {
831 : return true;
832 : }
833 0 : if (myApproachedEdges.find(edge)->second.size() > 1) {
834 : return true;
835 : }
836 :
837 : }
838 : }
839 :
840 : if (myDetectorsOnEdges.find(edge) != myDetectorsOnEdges.end()
841 2526 : &&
842 2365 : myDetectorEdges.find(det.getID())->second != edge) {
843 : return false;
844 : }
845 : const ROEdgeVector& appr = myApproachedEdges.find(edge)->second;
846 : bool isall = true;
847 1463 : seen.push_back(edge);
848 2957 : for (int i = 0; i < (int)appr.size() && isall; i++) {
849 1494 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
850 1494 : if (!had) {
851 1493 : if (!isDestination(det, appr[i], seen, detectors)) {
852 : isall = false;
853 : }
854 : }
855 : }
856 : return isall;
857 : }
858 :
859 : bool
860 1347 : RODFNet::isFalseSource(const RODFDetector& det, ROEdge* edge, ROEdgeVector& seen,
861 : const RODFDetectorCon& detectors) const {
862 1347 : if (seen.size() == 1000) { // !!!
863 0 : WRITE_WARNINGF(TL("Quitting checking for being a false source for detector '%' due to seen edge limit."), det.getID());
864 0 : return false;
865 : }
866 1347 : seen.push_back(edge);
867 1347 : if (edge != getDetectorEdge(det)) {
868 : // ok, we are at one of the edges coming behind
869 1047 : if (hasDetector(edge)) {
870 : const std::vector<std::string>& dets = myDetectorsOnEdges.find(edge)->second;
871 621 : for (std::vector<std::string>::const_iterator i = dets.begin(); i != dets.end(); ++i) {
872 621 : if (detectors.getDetector(*i).getType() == SINK_DETECTOR) {
873 : return false;
874 : }
875 462 : if (detectors.getDetector(*i).getType() == BETWEEN_DETECTOR) {
876 : return false;
877 : }
878 19 : if (detectors.getDetector(*i).getType() == SOURCE_DETECTOR) {
879 : return true;
880 : }
881 : }
882 : } else {
883 426 : if (myAmInHighwayMode && edge->getSpeedLimit() < 19.) {
884 : return false;
885 : }
886 : }
887 : }
888 :
889 726 : if (myApproachedEdges.find(edge) == myApproachedEdges.end()) {
890 : return false;
891 : }
892 :
893 : const ROEdgeVector& appr = myApproachedEdges.find(edge)->second;
894 : bool isall = false;
895 1816 : for (int i = 0; i < (int)appr.size() && !isall; i++) {
896 : //printf("checking %s->\n", appr[i].c_str());
897 1139 : bool had = std::find(seen.begin(), seen.end(), appr[i]) != seen.end();
898 1139 : if (!had) {
899 1047 : if (isFalseSource(det, appr[i], seen, detectors)) {
900 : isall = true;
901 : }
902 : }
903 : }
904 : return isall;
905 : }
906 :
907 :
908 : void
909 104 : RODFNet::buildEdgeFlowMap(const RODFDetectorFlows& flows,
910 : const RODFDetectorCon& detectors,
911 : SUMOTime startTime, SUMOTime endTime,
912 : SUMOTime stepOffset) {
913 : std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
914 : double speedFactorSumPKW = 0;
915 : double speedFactorSumLKW = 0;
916 : double speedFactorCountPKW = 0;
917 : double speedFactorCountLKW = 0;
918 1006 : for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
919 902 : ROEdge* into = (*i).first;
920 902 : const double maxSpeedPKW = into->getVClassMaxSpeed(SVC_PASSENGER);
921 902 : const double maxSpeedLKW = into->getVClassMaxSpeed(SVC_TRUCK);
922 :
923 : const std::vector<std::string>& dets = (*i).second;
924 : std::map<double, std::vector<std::string> > cliques;
925 : std::vector<std::string>* maxClique = nullptr;
926 1955 : for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
927 1053 : if (!flows.knows(*j)) {
928 154 : continue;
929 : }
930 899 : const RODFDetector& det = detectors.getDetector(*j);
931 : bool found = false;
932 899 : for (auto& k : cliques) {
933 82 : if (fabs(k.first - det.getPos()) < 1) {
934 82 : k.second.push_back(*j);
935 82 : if (maxClique == nullptr || k.second.size() > maxClique->size()) {
936 : maxClique = &k.second;
937 : }
938 : found = true;
939 : break;
940 : }
941 : }
942 899 : if (!found) {
943 817 : cliques[det.getPos()].push_back(*j);
944 817 : maxClique = &cliques[det.getPos()];
945 : }
946 : }
947 902 : if (maxClique == nullptr) {
948 : continue;
949 : }
950 : std::vector<FlowDef> mflows; // !!! reserve
951 310610 : for (SUMOTime t = startTime; t < endTime; t += stepOffset) {
952 : FlowDef fd;
953 309793 : fd.qPKW = 0;
954 309793 : fd.qLKW = 0;
955 309793 : fd.vLKW = 0;
956 309793 : fd.vPKW = 0;
957 309793 : fd.fLKW = 0;
958 309793 : fd.isLKW = 0;
959 309793 : mflows.push_back(fd);
960 : }
961 1716 : for (std::vector<std::string>::iterator l = maxClique->begin(); l != maxClique->end(); ++l) {
962 : bool didWarn = false;
963 899 : const std::vector<FlowDef>& dflows = flows.getFlowDefs(*l);
964 : int index = 0;
965 402872 : for (SUMOTime t = startTime; t < endTime; t += stepOffset, index++) {
966 401973 : const FlowDef& srcFD = dflows[index];
967 : FlowDef& fd = mflows[index];
968 401973 : fd.qPKW += srcFD.qPKW;
969 401973 : fd.qLKW += srcFD.qLKW;
970 401973 : fd.vLKW += srcFD.vLKW / (double) maxClique->size();
971 401973 : fd.vPKW += srcFD.vPKW / (double) maxClique->size();
972 401973 : fd.fLKW += srcFD.fLKW / (double) maxClique->size();
973 401973 : fd.isLKW += srcFD.isLKW / (double) maxClique->size();
974 401973 : const double speedFactorPKW = srcFD.vPKW / 3.6 / maxSpeedPKW;
975 401973 : const double speedFactorLKW = srcFD.vLKW / 3.6 / maxSpeedLKW;
976 401973 : myMaxSpeedFactorPKW = MAX2(myMaxSpeedFactorPKW, speedFactorPKW);
977 401973 : myMaxSpeedFactorLKW = MAX2(myMaxSpeedFactorLKW, speedFactorLKW);
978 401973 : speedFactorCountPKW += srcFD.qPKW;
979 401973 : speedFactorCountLKW += srcFD.qLKW;
980 401973 : speedFactorSumPKW += srcFD.qPKW * speedFactorPKW;
981 401973 : speedFactorSumLKW += srcFD.qLKW * speedFactorLKW;
982 401973 : if (!didWarn && srcFD.vPKW > 0 && srcFD.vPKW < 255 && srcFD.vPKW / 3.6 > into->getSpeedLimit()) {
983 3012 : WRITE_MESSAGE("Detected PKW speed (" + toString(srcFD.vPKW / 3.6, 3) + ") higher than allowed speed (" + toString(into->getSpeedLimit(), 3) + ") at '" + (*l) + "' on edge '" + into->getID() + "'.");
984 : didWarn = true;
985 : }
986 401220 : if (!didWarn && srcFD.vLKW > 0 && srcFD.vLKW < 255 && srcFD.vLKW / 3.6 > into->getSpeedLimit()) {
987 32 : WRITE_MESSAGE("Detected LKW speed (" + toString(srcFD.vLKW / 3.6, 3) + ") higher than allowed speed (" + toString(into->getSpeedLimit(), 3) + ") at '" + (*l) + "' on edge '" + into->getID() + "'.");
988 : didWarn = true;
989 : }
990 : }
991 : }
992 817 : static_cast<RODFEdge*>(into)->setFlows(mflows);
993 817 : }
994 : // @note: this assumes that the speedFactors are independent of location and time
995 104 : if (speedFactorCountPKW > 0) {
996 99 : myAvgSpeedFactorPKW = speedFactorSumPKW / speedFactorCountPKW;
997 198 : WRITE_MESSAGEF(TL("Average speedFactor for PKW is % maximum speedFactor is %."), toString(myAvgSpeedFactorPKW), toString(myMaxSpeedFactorPKW));
998 : }
999 104 : if (speedFactorCountLKW > 0) {
1000 25 : myAvgSpeedFactorLKW = speedFactorSumLKW / speedFactorCountLKW;
1001 50 : WRITE_MESSAGEF(TL("Average speedFactor for LKW is % maximum speedFactor is %."), toString(myAvgSpeedFactorLKW), toString(myMaxSpeedFactorLKW));
1002 : }
1003 :
1004 104 : }
1005 :
1006 :
1007 : void
1008 0 : RODFNet::buildDetectorDependencies(RODFDetectorCon& detectors) {
1009 : // !!! this will not work when several detectors are lying on the same edge on different positions
1010 :
1011 :
1012 0 : buildDetectorEdgeDependencies(detectors);
1013 : // for each detector, compute the lists of predecessor and following detectors
1014 : std::map<std::string, ROEdge*>::const_iterator i;
1015 0 : for (i = myDetectorEdges.begin(); i != myDetectorEdges.end(); ++i) {
1016 0 : const RODFDetector& det = detectors.getDetector((*i).first);
1017 0 : if (!det.hasRoutes()) {
1018 0 : continue;
1019 : }
1020 : // mark current detectors
1021 : std::vector<RODFDetector*> last;
1022 : {
1023 0 : const std::vector<std::string>& detNames = myDetectorsOnEdges.find((*i).second)->second;
1024 0 : for (std::vector<std::string>::const_iterator j = detNames.begin(); j != detNames.end(); ++j) {
1025 0 : last.push_back(&detectors.getModifiableDetector(*j));
1026 : }
1027 : }
1028 : // iterate over the current detector's routes
1029 0 : const std::vector<RODFRouteDesc>& routes = det.getRouteVector();
1030 0 : for (std::vector<RODFRouteDesc>::const_iterator j = routes.begin(); j != routes.end(); ++j) {
1031 : const ROEdgeVector& edges2Pass = (*j).edges2Pass;
1032 0 : for (ROEdgeVector::const_iterator k = edges2Pass.begin() + 1; k != edges2Pass.end(); ++k) {
1033 0 : if (myDetectorsOnEdges.find(*k) != myDetectorsOnEdges.end()) {
1034 : const std::vector<std::string>& detNames = myDetectorsOnEdges.find(*k)->second;
1035 : // ok, consecutive detector found
1036 0 : for (std::vector<RODFDetector*>::iterator l = last.begin(); l != last.end(); ++l) {
1037 : // mark as follower of current
1038 0 : for (std::vector<std::string>::const_iterator m = detNames.begin(); m != detNames.end(); ++m) {
1039 0 : detectors.getModifiableDetector(*m).addPriorDetector(*l);
1040 0 : (*l)->addFollowingDetector(&detectors.getDetector(*m));
1041 : }
1042 : }
1043 : last.clear();
1044 0 : for (std::vector<std::string>::const_iterator m = detNames.begin(); m != detNames.end(); ++m) {
1045 0 : last.push_back(&detectors.getModifiableDetector(*m));
1046 : }
1047 : }
1048 : }
1049 : }
1050 0 : }
1051 0 : }
1052 :
1053 :
1054 : void
1055 0 : RODFNet::mesoJoin(RODFDetectorCon& detectors, RODFDetectorFlows& flows) {
1056 0 : buildDetectorEdgeDependencies(detectors);
1057 : std::map<ROEdge*, std::vector<std::string>, idComp>::iterator i;
1058 0 : for (i = myDetectorsOnEdges.begin(); i != myDetectorsOnEdges.end(); ++i) {
1059 : const std::vector<std::string>& dets = (*i).second;
1060 : std::map<double, std::vector<std::string> > cliques;
1061 : // compute detector cliques
1062 0 : for (std::vector<std::string>::const_iterator j = dets.begin(); j != dets.end(); ++j) {
1063 0 : const RODFDetector& det = detectors.getDetector(*j);
1064 : bool found = false;
1065 0 : for (std::map<double, std::vector<std::string> >::iterator k = cliques.begin(); !found && k != cliques.end(); ++k) {
1066 0 : if (fabs((*k).first - det.getPos()) < 10.) {
1067 0 : (*k).second.push_back(*j);
1068 : found = true;
1069 : }
1070 : }
1071 0 : if (!found) {
1072 0 : cliques[det.getPos()] = std::vector<std::string>();
1073 0 : cliques[det.getPos()].push_back(*j);
1074 : }
1075 : }
1076 : // join detector cliques
1077 0 : for (std::map<double, std::vector<std::string> >::iterator m = cliques.begin(); m != cliques.end(); ++m) {
1078 0 : std::vector<std::string> clique = (*m).second;
1079 : // do not join if only one
1080 0 : if (clique.size() == 1) {
1081 : continue;
1082 : }
1083 : std::string nid;
1084 0 : for (std::vector<std::string>::iterator n = clique.begin(); n != clique.end(); ++n) {
1085 0 : std::cout << *n << " ";
1086 0 : if (n != clique.begin()) {
1087 0 : nid = nid + "_";
1088 : }
1089 0 : nid = nid + *n;
1090 : }
1091 : std::cout << ":" << nid << std::endl;
1092 0 : flows.mesoJoin(nid, (*m).second);
1093 0 : detectors.mesoJoin(nid, (*m).second);
1094 0 : }
1095 : }
1096 0 : }
1097 :
1098 :
1099 : /****************************************************************************/
|