3 #include <lanelet2_core/geometry/Area.h>
4 #include <lanelet2_core/geometry/Lanelet.h>
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;
16 between.reserve(size);
18 between.insert(between.end(),
std::next(startIt), wrappedLS.end());
19 between.insert(between.end(), wrappedLS.begin(), endIt);
21 between.insert(between.end(),
std::next(startIt), endIt);
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");
34 auto endIt = std::find(bounds.begin(), bounds.end(), rearCommon);
35 if (endIt == bounds.end()) {
36 throw InvalidInputError(
"line string rear not found");
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));
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");
49 auto idx = std::distance(bounds.begin(), frontIt);
50 return extractBetween(bounds, idx, idx);
54 const bool omitLast,
const bool omitFirst) {
55 auto compound = CompoundLineString3d(lss);
56 if (compound.size() < ((omitLast || omitFirst) ? (omitFirst && omitLast) ? 3 : 2 : 1)) {
60 target.insert(target.end(),
std::next(compound.basicBegin(), omitFirst ? 1 : 0),
61 std::prev(compound.basicEnd(), omitLast ? 1 : 0));
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));
70 appendLineStrings(lss, target, reversed,
false,
true);
74 appendLineStrings(lss, target,
false,
false,
false);
78 appendLineStrings(lss, target,
false,
true,
true);
82 ConstLaneletOrArea
cur;
86 enum class LaneletAdjacency { Following, Preceding,
Left,
Right };
87 struct LaneletPairAdjacency {
91 struct AdjacencyAndBorder {
92 LaneletAdjacency
adjacency{LaneletAdjacency::Preceding};
105 return AdjacencyAndBorder{LaneletAdjacency::Following, *res};
109 return AdjacencyAndBorder{LaneletAdjacency::Preceding, *res};
112 return AdjacencyAndBorder{LaneletAdjacency::Right,
ll.leftBound().invert()};
115 return AdjacencyAndBorder{LaneletAdjacency::Left,
ll.rightBound()};
120 LaneletPairAdjacency getLaneletAdjacency(
const ConstLanelet&
ll,
const ConstLanelet&
other) {
122 return LaneletPairAdjacency{LaneletAdjacency::Preceding, LaneletAdjacency::Following};
125 return LaneletPairAdjacency{LaneletAdjacency::Following, LaneletAdjacency::Preceding};
128 return LaneletPairAdjacency{LaneletAdjacency::Right, LaneletAdjacency::Left};
131 return LaneletPairAdjacency{LaneletAdjacency::Left, LaneletAdjacency::Right};
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()));
146 throw InvalidInputError(
"Invalid adjacency");
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()));
160 throw InvalidInputError(
"Invalid adjacency");
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()));
174 throw InvalidInputError(
"Invalid adjacency");
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);
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);
205 void appendLaneletBounds(BoundsResult& br,
const ConstLanelet&
ll,
const LaneletAdjacency& in,
206 const LaneletAdjacency& out) {
207 appendLaneletBoundsLeft(br.left,
ll, in, out);
209 appendLaneletBoundsRight(br.right,
ll, in, out);
218 ConstLineString3d getBorder(BoundsResult& br,
const Head& head) {
219 if (head.next->isArea()) {
221 if (!br.prevBorder) {
222 throw GeometryError(
"No shared line string found between adjacent primitives");
224 return br.prevBorder->invert();
226 auto adj = getLaneletAdjacency(*head.next->lanelet(), *head.cur.area());
228 throw GeometryError(
"No shared line string found between adjacent primitives");
230 br.llAdjacency = adj->adjacency;
234 void addLaneletPair(BoundsResult& res,
const Head& head,
const bool notTail =
true) {
235 auto adj = getLaneletAdjacency(*head.cur.lanelet(), *head.next->lanelet());
237 appendFirst(res.left, *head.cur.lanelet(), adj.ll);
239 appendLaneletBounds(res, *head.cur.lanelet(), notTail ? *res.llAdjacency : adj.ll, adj.ll);
240 res.llAdjacency = adj.other;
243 void addLaneletAreaHead(BoundsResult& res,
const Head& head,
const bool notTail =
true) {
244 auto adj = getLaneletAdjacency(*head.cur.lanelet(), *head.next->area());
246 throw std::runtime_error(
"Did not find adjacency");
249 appendFirst(res.left, *head.cur.lanelet(), adj->adjacency);
251 appendLaneletBounds(res, *head.cur.lanelet(), notTail ? *res.llAdjacency : adj->adjacency, adj->adjacency);
252 res.prevBorder = adj->border;
255 void addLanelet(BoundsResult& res,
const Head& head) {
257 appendLaneletBounds(res, *head.cur.lanelet(), *res.llAdjacency, *res.llAdjacency);
259 }
else if (head.next->isLanelet()) {
260 addLaneletPair(res, head);
262 addLaneletAreaHead(res, head);
266 void addFirstArea(BoundsResult& res,
const Head& head) {
267 auto thisBorder = getBorder(res, head);
268 if (!head.cur.area()) {
269 throw GeometryError(
"Uninitialized area");
271 appendLineStrings(extractExceptBorder(*head.cur.area(), thisBorder), res.left);
274 void addFirstLanelet(BoundsResult& res,
const Head& head) {
276 throw std::runtime_error(
"Following primitive not intialized");
278 if (head.next->isLanelet()) {
279 addLaneletPair(res, head,
false);
281 addLaneletAreaHead(res, head,
false);
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);
293 BoundsResult appendTail(
const Head& head) {
296 throw InvalidInputError(
"Tail must have successor, results must be empty");
298 if (head.cur.isArea()) {
299 addFirstArea(res, head);
301 addFirstLanelet(res, head);
306 void appendFinalArea(
const Head& head, BoundsResult& br) {
307 if (!br.prevBorder) {
308 throw InvalidInputError(
"border not given for area");
310 appendLineStringsExceptFirstAndLast(extractExceptBorder(*head.cur.area(), *br.prevBorder), br.left);
313 void appendBounds(
const Head& head, BoundsResult& br) {
314 if (head.cur.isLanelet()) {
315 addLanelet(br, head);
318 appendFinalArea(head, br);
328 while (laneletPosition !=
lanelets_.end()) {
329 lane.push_back(*laneletPosition);
342 if (path.
size() == 1ul) {
345 auto boundsResult = appendTail(Head{path[0], path[1]});
346 for (
size_t curIdx = 1; curIdx < path.
size(); ++curIdx) {
350 boundsResult.left.insert(boundsResult.left.end(), boundsResult.right.rbegin(), boundsResult.right.rend());
351 return std::move(boundsResult.left);