LaneletPath.cpp
Go to the documentation of this file.
2 
3 #include <lanelet2_core/geometry/Area.h>
4 #include <lanelet2_core/geometry/Lanelet.h>
5 
6 namespace lanelet {
7 namespace routing {
8 
9 namespace {
10 
11 ConstLineStrings3d extractBetween(const ConstLineStrings3d& wrappedLS, const size_t start, const size_t end) {
12  auto startIt = std::next(wrappedLS.begin(), start);
13  auto endIt = std::next(wrappedLS.begin(), end);
14  auto size = (start >= end) ? wrappedLS.size() - (start - end) - 1 : end - start - 1;
15  ConstLineStrings3d between;
16  between.reserve(size);
17  if (start >= end) {
18  between.insert(between.end(), std::next(startIt), wrappedLS.end());
19  between.insert(between.end(), wrappedLS.begin(), endIt);
20  } else {
21  between.insert(between.end(), std::next(startIt), endIt);
22  }
23  return between;
24 }
25 
26 std::pair<ConstLineStrings3d, ConstLineStrings3d> extractBounds(const ConstArea& area,
27  const ConstLineString3d& rearCommon,
28  const ConstLineString3d& frontCommon) {
29  const auto& bounds = area.outerBound();
30  auto frontIt = std::find(bounds.begin(), bounds.end(), frontCommon);
31  if (frontIt == bounds.end()) {
32  throw InvalidInputError("line string front not found");
33  }
34  auto endIt = std::find(bounds.begin(), bounds.end(), rearCommon);
35  if (endIt == bounds.end()) {
36  throw InvalidInputError("line string rear not found");
37  }
38  auto start = std::distance(bounds.begin(), frontIt);
39  auto end = std::distance(bounds.begin(), endIt);
40  return std::make_pair(extractBetween(bounds, end, start), extractBetween(bounds, start, end));
41 }
42 
43 ConstLineStrings3d extractExceptBorder(const ConstArea& area, const ConstLineString3d& border) {
44  const auto& bounds = area.outerBound();
45  auto frontIt = std::find_if(bounds.begin(), bounds.end(), [&border](auto& ls) { return ls == border; });
46  if (frontIt == bounds.end()) {
47  throw InvalidInputError("Given line string not in area");
48  }
49  auto idx = std::distance(bounds.begin(), frontIt);
50  return extractBetween(bounds, idx, idx);
51 }
52 
53 void appendLineStrings(const ConstLineStrings3d& lss, BasicLineString3d& target, const bool reversed,
54  const bool omitLast, const bool omitFirst) {
55  auto compound = CompoundLineString3d(lss);
56  if (compound.size() < ((omitLast || omitFirst) ? (omitFirst && omitLast) ? 3 : 2 : 1)) {
57  return;
58  }
59  if (!reversed) {
60  target.insert(target.end(), std::next(compound.basicBegin(), omitFirst ? 1 : 0),
61  std::prev(compound.basicEnd(), omitLast ? 1 : 0));
62  } else {
63  const auto& basicLS = compound.basicLineString();
64  target.insert(target.end(), std::next(basicLS.rbegin(), omitFirst ? 1 : 0),
65  std::prev(basicLS.rend(), omitLast ? 1 : 0));
66  }
67 }
68 
69 void appendLineStringsExceptFirst(const ConstLineStrings3d& lss, BasicLineString3d& target, const bool reversed) {
70  appendLineStrings(lss, target, reversed, false, true);
71 }
72 
73 void appendLineStrings(const ConstLineStrings3d& lss, BasicLineString3d& target) {
74  appendLineStrings(lss, target, false, false, false);
75 }
76 
77 void appendLineStringsExceptFirstAndLast(const ConstLineStrings3d& lss, BasicLineString3d& target) {
78  appendLineStrings(lss, target, false, true, true);
79 }
80 
81 struct Head {
82  ConstLaneletOrArea cur;
84 };
85 
86 enum class LaneletAdjacency { Following, Preceding, Left, Right };
87 struct LaneletPairAdjacency {
88  LaneletAdjacency ll;
89  LaneletAdjacency other;
90 };
91 struct AdjacencyAndBorder {
92  LaneletAdjacency adjacency{LaneletAdjacency::Preceding};
93  ConstLineString3d border;
94 };
95 struct BoundsResult {
98  BasicPolygon3d left;
99  BasicPolygon3d right;
100 };
101 
102 Optional<AdjacencyAndBorder> getLaneletAdjacency(const ConstLanelet& ll, const ConstArea& ar) {
104  if (res) {
105  return AdjacencyAndBorder{LaneletAdjacency::Following, *res};
106  }
108  if (res) {
109  return AdjacencyAndBorder{LaneletAdjacency::Preceding, *res};
110  }
111  if (geometry::leftOf(ll, ar)) {
112  return AdjacencyAndBorder{LaneletAdjacency::Right, ll.leftBound().invert()}; // must be inverted relative to area
113  }
114  if (geometry::rightOf(ll, ar)) {
115  return AdjacencyAndBorder{LaneletAdjacency::Left, ll.rightBound()}; // must be inverted relative to area
116  }
117  return {};
118 }
119 
120 LaneletPairAdjacency getLaneletAdjacency(const ConstLanelet& ll, const ConstLanelet& other) {
121  if (geometry::follows(ll, other)) {
122  return LaneletPairAdjacency{LaneletAdjacency::Preceding, LaneletAdjacency::Following};
123  }
124  if (geometry::follows(other, ll)) {
125  return LaneletPairAdjacency{LaneletAdjacency::Following, LaneletAdjacency::Preceding};
126  }
127  if (geometry::leftOf(other, ll)) {
128  return LaneletPairAdjacency{LaneletAdjacency::Right, LaneletAdjacency::Left};
129  }
130  if (geometry::rightOf(other, ll)) {
131  return LaneletPairAdjacency{LaneletAdjacency::Left, LaneletAdjacency::Right};
132  }
133  return {};
134 }
135 
136 void appendExtractedClockwise(BasicPolygon3d& target, const ConstLanelet& ll, const LaneletAdjacency& adj) {
137  if (adj == LaneletAdjacency::Right) {
138  target.insert(target.end(), ll.leftBound().basicBegin() + 1, ll.leftBound().basicEnd());
139  } else if (adj == LaneletAdjacency::Preceding) {
140  target.emplace_back(utils::toBasicPoint(ll.rightBound().back()));
141  } else if (adj == LaneletAdjacency::Left) {
142  target.insert(target.end(), ll.rightBound().invert().basicBegin() + 1, ll.rightBound().invert().basicEnd());
143  } else if (adj == LaneletAdjacency::Following) {
144  target.emplace_back(utils::toBasicPoint(ll.leftBound().front()));
145  } else {
146  throw InvalidInputError("Invalid adjacency");
147  }
148 }
149 
150 void appendExtractedCounterClockwise(BasicPolygon3d& target, const ConstLanelet& ll, const LaneletAdjacency& adj) {
151  if (adj == LaneletAdjacency::Right) {
152  target.insert(target.end(), ll.leftBound().invert().basicBegin() + 1, ll.leftBound().invert().basicEnd());
153  } else if (adj == LaneletAdjacency::Preceding) {
154  target.emplace_back(utils::toBasicPoint(ll.leftBound().back()));
155  } else if (adj == LaneletAdjacency::Left) {
156  target.insert(target.end(), ll.rightBound().basicBegin() + 1, ll.rightBound().basicEnd());
157  } else if (adj == LaneletAdjacency::Following) {
158  target.emplace_back(utils::toBasicPoint(ll.rightBound().front()));
159  } else {
160  throw InvalidInputError("Invalid adjacency");
161  }
162 }
163 
164 void appendFirst(BasicPolygon3d& poly, const ConstLanelet& ll, const LaneletAdjacency& in) {
165  if (in == LaneletAdjacency::Following) {
166  poly.emplace_back(utils::toBasicPoint(ll.leftBound().front()));
167  } else if (in == LaneletAdjacency::Right) {
168  poly.emplace_back(utils::toBasicPoint(ll.leftBound().back()));
169  } else if (in == LaneletAdjacency::Preceding) {
170  poly.emplace_back(utils::toBasicPoint(ll.rightBound().back()));
171  } else if (in == LaneletAdjacency::Left) {
172  poly.emplace_back(utils::toBasicPoint(ll.rightBound().front()));
173  } else {
174  throw InvalidInputError("Invalid adjacency");
175  }
176 }
177 
178 using AdjMap = std::map<LaneletAdjacency, LaneletAdjacency>;
179 void appendLaneletBoundsLeft(BasicPolygon3d& poly, const ConstLanelet& ll, const LaneletAdjacency& in,
180  const LaneletAdjacency& out) {
181  const AdjMap cw{{LaneletAdjacency::Left, LaneletAdjacency::Following},
182  {LaneletAdjacency::Following, LaneletAdjacency::Right},
183  {LaneletAdjacency::Right, LaneletAdjacency::Preceding},
184  {LaneletAdjacency::Preceding, LaneletAdjacency::Left}};
185  auto cwNext = cw.at(in);
186  while (cwNext != out) {
187  appendExtractedClockwise(poly, ll, cwNext);
188  cwNext = cw.at(cwNext);
189  }
190 }
191 
192 void appendLaneletBoundsRight(BasicPolygon3d& poly, const ConstLanelet& ll, const LaneletAdjacency& in,
193  const LaneletAdjacency& out) {
194  const AdjMap ccw{{LaneletAdjacency::Left, LaneletAdjacency::Preceding},
195  {LaneletAdjacency::Preceding, LaneletAdjacency::Right},
196  {LaneletAdjacency::Right, LaneletAdjacency::Following},
197  {LaneletAdjacency::Following, LaneletAdjacency::Left}};
198  auto ccwNext = ccw.at(in);
199  while (ccwNext != out) {
200  appendExtractedCounterClockwise(poly, ll, ccwNext);
201  ccwNext = ccw.at(ccwNext);
202  }
203 }
204 
205 void appendLaneletBounds(BoundsResult& br, const ConstLanelet& ll, const LaneletAdjacency& in,
206  const LaneletAdjacency& out) {
207  appendLaneletBoundsLeft(br.left, ll, in, out);
208  if (in != out) {
209  appendLaneletBoundsRight(br.right, ll, in, out);
210  }
211 }
218 ConstLineString3d getBorder(BoundsResult& br, const Head& head) {
219  if (head.next->isArea()) {
220  br.prevBorder = geometry::determineCommonLine(*(head.next->area()), *head.cur.area());
221  if (!br.prevBorder) {
222  throw GeometryError("No shared line string found between adjacent primitives");
223  }
224  return br.prevBorder->invert();
225  }
226  auto adj = getLaneletAdjacency(*head.next->lanelet(), *head.cur.area());
227  if (!adj) {
228  throw GeometryError("No shared line string found between adjacent primitives");
229  }
230  br.llAdjacency = adj->adjacency;
231  return adj->border;
232 }
233 
234 void addLaneletPair(BoundsResult& res, const Head& head, const bool notTail = true) {
235  auto adj = getLaneletAdjacency(*head.cur.lanelet(), *head.next->lanelet());
236  if (!notTail) {
237  appendFirst(res.left, *head.cur.lanelet(), adj.ll);
238  }
239  appendLaneletBounds(res, *head.cur.lanelet(), notTail ? *res.llAdjacency : adj.ll, adj.ll);
240  res.llAdjacency = adj.other;
241 }
242 
243 void addLaneletAreaHead(BoundsResult& res, const Head& head, const bool notTail = true) {
244  auto adj = getLaneletAdjacency(*head.cur.lanelet(), *head.next->area());
245  if (!adj) {
246  throw std::runtime_error("Did not find adjacency");
247  }
248  if (!notTail) {
249  appendFirst(res.left, *head.cur.lanelet(), adj->adjacency);
250  }
251  appendLaneletBounds(res, *head.cur.lanelet(), notTail ? *res.llAdjacency : adj->adjacency, adj->adjacency);
252  res.prevBorder = adj->border;
253 }
254 
255 void addLanelet(BoundsResult& res, const Head& head) {
256  if (!head.next) {
257  appendLaneletBounds(res, *head.cur.lanelet(), *res.llAdjacency, *res.llAdjacency);
258  res.left.pop_back(); // ugly AF
259  } else if (head.next->isLanelet()) {
260  addLaneletPair(res, head);
261  } else {
262  addLaneletAreaHead(res, head);
263  }
264 }
265 
266 void addFirstArea(BoundsResult& res, const Head& head) {
267  auto thisBorder = getBorder(res, head);
268  if (!head.cur.area()) {
269  throw GeometryError("Uninitialized area");
270  }
271  appendLineStrings(extractExceptBorder(*head.cur.area(), thisBorder), res.left);
272 }
273 
274 void addFirstLanelet(BoundsResult& res, const Head& head) {
275  if (!head.next) {
276  throw std::runtime_error("Following primitive not intialized");
277  }
278  if (head.next->isLanelet()) {
279  addLaneletPair(res, head, false);
280  } else {
281  addLaneletAreaHead(res, head, false);
282  }
283 }
284 
285 void addArea(BoundsResult& br, const Head& head) {
286  auto oldBorder = *br.prevBorder;
287  auto border = getBorder(br, head);
288  auto bounds = extractBounds(*head.cur.area(), oldBorder, border);
289  appendLineStringsExceptFirst(bounds.first, br.left, false);
290  appendLineStringsExceptFirst(bounds.second, br.right, true);
291 }
292 
293 BoundsResult appendTail(const Head& head) {
294  BoundsResult res;
295  if (!head.next) {
296  throw InvalidInputError("Tail must have successor, results must be empty");
297  }
298  if (head.cur.isArea()) {
299  addFirstArea(res, head);
300  } else {
301  addFirstLanelet(res, head);
302  }
303  return res;
304 }
305 
306 void appendFinalArea(const Head& head, BoundsResult& br) {
307  if (!br.prevBorder) {
308  throw InvalidInputError("border not given for area");
309  }
310  appendLineStringsExceptFirstAndLast(extractExceptBorder(*head.cur.area(), *br.prevBorder), br.left);
311 }
312 
313 void appendBounds(const Head& head, BoundsResult& br) {
314  if (head.cur.isLanelet()) {
315  addLanelet(br, head);
316  } else {
317  if (!head.next) {
318  appendFinalArea(head, br);
319  } else {
320  addArea(br, head);
321  }
322  }
323 }
324 } // namespace
325 
327  ConstLanelets lane;
328  while (laneletPosition != lanelets_.end()) {
329  lane.push_back(*laneletPosition);
330  if (laneletPosition + 1 == lanelets_.end() || !geometry::follows(*laneletPosition, *std::next(laneletPosition))) {
331  break;
332  }
333  ++laneletPosition;
334  }
335  return lane;
336 }
337 
339  if (path.empty()) {
340  return BasicPolygon3d();
341  }
342  if (path.size() == 1ul) {
343  return path.front().boundingPolygon().basicPolygon();
344  }
345  auto boundsResult = appendTail(Head{path[0], path[1]});
346  for (size_t curIdx = 1; curIdx < path.size(); ++curIdx) {
347  appendBounds(Head{path[curIdx], (curIdx + 1 < path.size()) ? path[curIdx + 1] : Optional<ConstLaneletOrArea>()},
348  boundsResult);
349  }
350  boundsResult.left.insert(boundsResult.left.end(), boundsResult.right.rbegin(), boundsResult.right.rend());
351  return std::move(boundsResult.left);
352 }
353 } // namespace routing
354 } // namespace lanelet
ConstLineStrings3d
std::vector< ConstLineString3d > ConstLineStrings3d
lanelet::CompoundPolygon3d::basicPolygon
BasicPolygon3d basicPolygon() const
lanelet::routing::LaneletOrAreaPath::empty
bool empty() const
Definition: LaneletPath.h:61
lanelet::geometry::determineCommonLineFollowing
Optional< ConstLineString3d > determineCommonLineFollowing(const ConstArea &ar, const ConstLanelet &ll)
lanelet
lanelet::LaneletSequence
next
Optional< ConstLaneletOrArea > next
Definition: LaneletPath.cpp:83
cur
ConstLaneletOrArea cur
Definition: LaneletPath.cpp:82
lanelet::geometry::follows
bool follows(const ConstArea &prev, const ConstLanelet &next)
lanelet::routing::LaneletOrAreaPath::size
size_t size() const
Definition: LaneletPath.h:60
right
BasicPolygon3d right
Definition: LaneletPath.cpp:99
Optional
boost::optional< T > Optional
other
LaneletAdjacency other
Definition: LaneletPath.cpp:89
lanelet::geometry::determineCommonLine
Optional< ConstLineString3d > determineCommonLine(const ConstArea &ar, const ConstLanelet &ll)
lanelet::BasicPolygon3d
lanelet::routing::LaneletPath::lanelets_
ConstLanelets lanelets_
Definition: LaneletPath.h:45
LaneletPath.h
lanelet::routing::RelationType::Left
@ Left
(the only) directly adjacent, reachable left neighbour
lanelet::routing::LaneletOrAreaPath
Similar to LaneletPath, but can also contain areas.
Definition: LaneletPath.h:49
lanelet::geometry::determineCommonLinePreceding
Optional< ConstLineString3d > determineCommonLinePreceding(const ConstLanelet &ll, const ConstArea &ar)
other
lanelet::routing::LaneletOrAreaPath::front
const ConstLaneletOrArea & front() const
Definition: LaneletPath.h:62
left
BasicPolygon3d left
Definition: LaneletPath.cpp:98
prevBorder
Optional< ConstLineString3d > prevBorder
Definition: LaneletPath.cpp:96
lanelet::ConstLaneletOrArea::boundingPolygon
CompoundPolygon3d boundingPolygon() const
lanelet::routing::LaneletPath::getRemainingLane
LaneletSequence getRemainingLane(const_iterator laneletPosition) const
Returns all succeeding lanelets from the current position that can be reached without changing lanes.
Definition: LaneletPath.cpp:326
lanelet::geometry::leftOf
bool leftOf(const ConstLanelet &right, const ConstArea &left)
border
ConstLineString3d border
Definition: LaneletPath.cpp:93
adjacency
LaneletAdjacency adjacency
Definition: LaneletPath.cpp:92
ll
LaneletAdjacency ll
Definition: LaneletPath.cpp:88
lanelet::geometry::rightOf
bool rightOf(const ConstLanelet &left, const ConstArea &area)
lanelet::routing::RelationType::Right
@ Right
(the only) directly adjacent, reachable right neighbour
lanelet::ConstLanelets
std::vector< ConstLanelet > ConstLanelets
llAdjacency
Optional< LaneletAdjacency > llAdjacency
Definition: LaneletPath.cpp:97
lanelet::routing::getEnclosingPolygon3d
BasicPolygon3d getEnclosingPolygon3d(const LaneletOrAreaPath &path)
Definition: LaneletPath.cpp:338
lanelet::routing::LaneletPath::const_iterator
ConstLanelets::const_iterator const_iterator
Definition: LaneletPath.h:16
BasicLineString3d
BasicPoints3d BasicLineString3d


lanelet2_routing
Author(s): Matthias Mayr
autogenerated on Sun Oct 27 2024 02:27:49