Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MapMatcher.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 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/****************************************************************************/
18// Utility functions for matching locations to edges (during route parsing)
19/****************************************************************************/
20#pragma once
21#include <config.h>
22
25#include "NamedRTree.h"
26#include "RandHelper.h"
27#include "SUMOVehicleClass.h"
28#include "MsgHandler.h"
29
30#define JUNCTION_TAZ_MISSING_HELP "\nSet option '--junction-taz' or load a TAZ-file"
31
32// ===========================================================================
33// class declarations
34// ===========================================================================
35
36// ===========================================================================
37// class definitions
38// ===========================================================================
44template<class E, class L, class N>
46
47public:
48 void parseGeoEdges(const PositionVector& positions, bool geo, SUMOVehicleClass vClass,
49 std::vector<const E*>& into, const std::string& rid, bool isFrom, bool& ok, bool forceEdge = false) {
50 if (geo && !GeoConvHelper::getFinal().usingGeoProjection()) {
51 WRITE_ERROR(TL("Cannot convert geo-positions because the network has no geo-reference"));
52 ok = false;
53 return;
54 }
55 for (Position pos : positions) {
56 Position orig = pos;
57 if (geo) {
59 }
60 double dist = MIN2(10.0, myMapMatchingDistance);
61 const L* best = getClosestLane(pos, vClass, dist);
62 while (best == nullptr && dist < myMapMatchingDistance) {
63 dist = MIN2(dist * 2, myMapMatchingDistance);
64 best = getClosestLane(pos, vClass, dist);
65 }
66 if (best == nullptr) {
67 myErrorOutput->inform("No edge found near position " + toString(orig, geo ? gPrecisionGeo : gPrecision) + " within the route " + rid + ".");
68 ok = false;
69 } else {
70 const E* bestEdge = &best->getEdge();
71 while (bestEdge->isInternal()) {
72 bestEdge = bestEdge->getSuccessors().front();
73 }
74 if ((myMapMatchJunctions || myMapMatchTAZ) && !forceEdge) {
75 if (myMapMatchTAZ) {
76 bestEdge = getTaz(pos, bestEdge, isFrom);
77 } else {
78 bestEdge = getJunctionTaz(pos, bestEdge, vClass, isFrom);
79 }
80 if (bestEdge != nullptr) {
81 into.push_back(bestEdge);
82 } else {
83 ok = false;
84 }
85 } else {
86 // handle multiple via locations on the same edge without loops
87 if (positions.size() == 1 || into.empty() || into.back() != bestEdge) {
88 into.push_back(bestEdge);
89 }
90 }
91 }
92 }
93 }
94
95
96
97protected:
98 MapMatcher(bool matchJunctions, bool matchTAZ, double matchDistance, MsgHandler* errorOutput):
99 myMapMatchTAZ(matchTAZ),
100 myLaneTree(nullptr),
101 myMapMatchJunctions(matchJunctions),
102 myMapMatchingDistance(matchDistance),
103 myErrorOutput(errorOutput) {}
104
105 virtual ~MapMatcher() {
106 delete myLaneTree;
107 }
108
110 const L* getClosestLane(const Position& pos, SUMOVehicleClass vClass, double distance = -1.) {
111 NamedRTree* t = getLaneTree();
112 Boundary b;
113 b.add(pos);
114 b.grow(distance < 0 ? myMapMatchingDistance : distance);
115 const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
116 const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
117 std::set<const Named*> lanes;
118 Named::StoringVisitor sv(lanes);
119 t->Search(cmin, cmax, sv);
120 // use closest
121 double minDist = std::numeric_limits<double>::max();
122 const L* best = nullptr;
123 for (const Named* o : lanes) {
124 const L* cand = static_cast<const L*>(o);
125 if (!cand->allowsVehicleClass(vClass)) {
126 continue;
127 }
128 double dist = cand->getShape().distance2D(pos);
129 if (dist < minDist) {
130 minDist = dist;
131 best = cand;
132 }
133 }
134 return best;
135 }
136
138 const E* getJunctionTaz(const Position& pos, const E* closestEdge, SUMOVehicleClass vClass, bool isFrom) {
139 if (closestEdge == nullptr) {
140 return nullptr;
141 } else {
142 const N* fromJunction = closestEdge->getFromJunction();
143 const N* toJunction = closestEdge->getToJunction();
144 const bool fromCloser = (fromJunction->getPosition().distanceSquaredTo2D(pos) <
145 toJunction->getPosition().distanceSquaredTo2D(pos));
146 const E* fromSource = retrieveEdge(fromJunction->getID() + "-source");
147 const E* fromSink = retrieveEdge(fromJunction->getID() + "-sink");
148 const E* toSource = retrieveEdge(toJunction->getID() + "-source");
149 const E* toSink = retrieveEdge(toJunction->getID() + "-sink");
150 if (fromSource == nullptr || fromSink == nullptr) {
151 myErrorOutput->inform("Junction-taz '" + fromJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
152 return nullptr;
153 }
154 if (toSource == nullptr || toSink == nullptr) {
155 myErrorOutput->inform("Junction-taz '" + toJunction->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
156 return nullptr;
157 }
158 const bool fromPossible = isFrom ? fromSource->getSuccessors(vClass).size() > 0 : fromSink->getPredecessors().size() > 0;
159 const bool toPossible = isFrom ? toSource->getSuccessors(vClass).size() > 0 : toSink->getPredecessors().size() > 0;
160 //std::cout << "getJunctionTaz pos=" << pos << " isFrom=" << isFrom << " closest=" << closestEdge->getID() << " fromPossible=" << fromPossible << " toPossible=" << toPossible << "\n";
161 if (fromCloser && fromPossible) {
162 // return closest if possible
163 return isFrom ? fromSource : fromSink;
164 } else if (!fromCloser && toPossible) {
165 // return closest if possible
166 return isFrom ? toSource : toSink;
167 } else {
168 // return possible
169 if (fromPossible) {
170 return isFrom ? fromSource : fromSink;
171 } else {
172 return isFrom ? toSource : toSink;
173 }
174 }
175 }
176 }
177
179 const E* getTaz(const Position& pos, const E* closestEdge, bool isFrom) {
180 if (closestEdge == nullptr) {
181 return nullptr;
182 } else {
183 std::vector<const E*> cands;
184 if (isFrom) {
185 for (const E* e : closestEdge->getPredecessors()) {
186 if (e->isTazConnector()) {
187 cands.push_back(e);
188 }
189 }
190 } else {
191 for (const E* e : closestEdge->getSuccessors()) {
192 if (e->isTazConnector()) {
193 cands.push_back(e);
194 }
195 }
196 }
197 if (cands.size() == 0) {
198 myErrorOutput->inform("Taz for edge '" + closestEdge->getID() + "' not found when mapping position " + toString(pos) + "." + JUNCTION_TAZ_MISSING_HELP);
199 return nullptr;
200 }
201 if (cands.size() > 1) {
202 return cands[RandHelper::rand((int)cands.size(), getRNG())];
203 } else {
204 return cands.front();
205 }
206 }
207 }
208
209 virtual SumoRNG* getRNG() {
210 return nullptr;
211 }
212
213 virtual void initLaneTree(NamedRTree* tree) = 0;
214
215 virtual E* retrieveEdge(const std::string& id) = 0;
216
218
219private:
222 if (myLaneTree == nullptr) {
223 myLaneTree = new NamedRTree();
225 }
226 return myLaneTree;
227 }
228
234
235
236private:
238 MapMatcher(const MapMatcher& s) = delete;
239
241 MapMatcher& operator=(const MapMatcher& s) = delete;
242};
#define JUNCTION_TAZ_MISSING_HELP
Definition MapMatcher.h:30
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define TL(string)
Definition MsgHandler.h:315
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:26
int gPrecisionGeo
Definition StdDefs.cpp:27
T MIN2(T a, T b)
Definition StdDefs.h:76
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:78
double ymin() const
Returns minimum y-coordinate.
Definition Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition Boundary.cpp:118
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:343
double ymax() const
Returns maximum y-coordinate.
Definition Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition Boundary.cpp:124
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
Provides utility functions for matching locations to edges (during route parsing)
Definition MapMatcher.h:45
double myMapMatchingDistance
Definition MapMatcher.h:232
virtual E * retrieveEdge(const std::string &id)=0
bool myMapMatchJunctions
Definition MapMatcher.h:231
virtual ~MapMatcher()
Definition MapMatcher.h:105
MapMatcher & operator=(const MapMatcher &s)=delete
Invalidated assignment operator.
const L * getClosestLane(const Position &pos, SUMOVehicleClass vClass, double distance=-1.)
find closest lane within distance for the given position or nullptr
Definition MapMatcher.h:110
virtual SumoRNG * getRNG()
Definition MapMatcher.h:209
MapMatcher(bool matchJunctions, bool matchTAZ, double matchDistance, MsgHandler *errorOutput)
Definition MapMatcher.h:98
MapMatcher(const MapMatcher &s)=delete
Invalidated copy constructor.
bool myMapMatchTAZ
Definition MapMatcher.h:217
virtual void initLaneTree(NamedRTree *tree)=0
const E * getJunctionTaz(const Position &pos, const E *closestEdge, SUMOVehicleClass vClass, bool isFrom)
find closest junction taz given the closest edge
Definition MapMatcher.h:138
void parseGeoEdges(const PositionVector &positions, bool geo, SUMOVehicleClass vClass, std::vector< const E * > &into, const std::string &rid, bool isFrom, bool &ok, bool forceEdge=false)
Definition MapMatcher.h:48
MsgHandler * myErrorOutput
Definition MapMatcher.h:233
NamedRTree * myLaneTree
RTree for finding lanes.
Definition MapMatcher.h:230
const E * getTaz(const Position &pos, const E *closestEdge, bool isFrom)
find closest junction taz given the closest edge
Definition MapMatcher.h:179
NamedRTree * getLaneTree()
initialize lane-RTree
Definition MapMatcher.h:221
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition Named.h:90
Base class for objects which have an id.
Definition Named.h:54
A RT-tree for efficient storing of SUMO's Named objects.
Definition NamedRTree.h:61
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
Definition NamedRTree.h:112
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
A list of positions.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)