29#include <unordered_map>
30#include <unordered_set>
44 static constexpr double EPSILON = 10.0 * std::numeric_limits<double>::epsilon();
52 static std::vector<T>
ConcatVectors(std::vector<T> dst, std::vector<T> src) {
53 if (src.size() > dst.size()) {
58 std::make_move_iterator(src.begin()),
59 std::make_move_iterator(src.end()));
80 template <
typename FuncT>
86 for (
const auto &pair : lane_section.
GetLanes()) {
87 const auto &lane = pair.second;
88 if (lane.GetId() == 0) {
101 template <
typename FuncT>
108 for (
const auto &pair : lane_section.
GetLanes()) {
109 const auto &lane = pair.second;
110 if (lane.GetId() == 0) {
113 if ((
static_cast<int32_t
>(lane.GetType()) &
static_cast<int32_t
>(lane_type)) > 0) {
116 lane_section.
GetId(),
124 template <
typename FuncT>
126 for (
const auto &lane_section :
road.GetLaneSections()) {
131 std::forward<FuncT>(func));
136 template <
typename FuncT>
138 for (
const auto &lane_section :
road.GetLaneSections()) {
144 std::forward<FuncT>(func));
149 template <
typename FuncT>
151 for (
const auto &lane_section :
road.GetLaneSectionsAt(
distance)) {
156 std::forward<FuncT>(func));
172 int32_t lane_type)
const {
173 std::vector<Rtree::TreeElement> query_result =
176 const Lane &lane = GetLane(element.second.first);
177 return (lane_type & static_cast<int32_t>(lane.GetType())) > 0;
180 if (query_result.size() == 0) {
181 return std::optional<Waypoint>{};
191 Waypoint result_start = query_result.front().second.first;
192 Waypoint result_end = query_result.front().second.second;
194 if (
GetLane(result_start).IsPositiveDirection()) {
195 double delta_s = distance_to_segment.first;
196 double final_s = result_start.
s + delta_s;
197 if (final_s >= result_end.
s) {
199 }
else if (delta_s <= 0) {
202 return GetNext(result_start, delta_s).front();
205 double delta_s = distance_to_segment.first;
206 double final_s = result_start.
s - delta_s;
207 if (final_s <= result_end.
s) {
209 }
else if (delta_s <= 0) {
212 return GetNext(result_start, delta_s).front();
219 int32_t lane_type)
const {
222 if (!w.has_value()) {
228 const auto half_lane_width =
231 if (dist < half_lane_width) {
235 return std::optional<Waypoint>{};
251 return std::optional<Waypoint>{};
256 if (s < 0.0f || s >=
road.GetLength()) {
257 return std::optional<Waypoint>{};
261 bool lane_found =
false;
262 for (
auto §ion :
road.GetLaneSectionsAt(s)) {
263 if (section.ContainsLane(lane_id)) {
272 return std::optional<Waypoint>{};
291 const auto s = waypoint.
s;
293 const auto &lane =
GetLane(waypoint);
300 return lane_width_info->GetPolynomial().Evaluate(s);
311 std::pair<const RoadInfoMarkRecord *, const RoadInfoMarkRecord *>
315 return std::make_pair(
nullptr,
nullptr);
317 const auto s = waypoint.
s;
319 const auto ¤t_lane =
GetLane(waypoint);
323 const auto inner_lane_id = waypoint.
lane_id < 0 ?
327 const auto &inner_lane = current_lane.GetRoad()->GetLaneById(waypoint.
section_id, inner_lane_id);
332 return std::make_pair(current_lane_info, inner_lane_info);
338 const auto &lane =
GetLane(waypoint);
339 const bool forward = lane.IsPositiveDirection();
341 const double relative_s = waypoint.
s - lane.GetDistance();
342 const double remaining_lane_length = forward ? lane.GetLength() - relative_s : relative_s;
346 std::vector<SignalSearchData> result;
350 if (
distance <= remaining_lane_length) {
352 waypoint.
s, waypoint.
s + signed_distance);
353 for(
auto* signal : signals){
354 double distance_to_signal = 0;
355 if (lane.IsPositiveDirection()){
356 distance_to_signal = signal->
GetDistance() - waypoint.
s;
358 distance_to_signal = waypoint.
s - signal->GetDistance();
361 bool is_valid =
false;
362 for (
auto &validity : signal->GetValidities()) {
363 if (waypoint.
lane_id >= validity._from_lane &&
364 waypoint.
lane_id <= validity._to_lane) {
372 if (distance_to_signal == 0) {
375 distance_to_signal});
378 {signal,
GetNext(waypoint, distance_to_signal).front(),
379 distance_to_signal});
385 const double signed_remaining_length = forward ? remaining_lane_length : -remaining_lane_length;
389 waypoint.
s, waypoint.
s + signed_remaining_length);
390 for(
auto* signal : signals){
391 double distance_to_signal = 0;
392 if (lane.IsPositiveDirection()){
393 distance_to_signal = signal->
GetDistance() - waypoint.
s;
395 distance_to_signal = waypoint.
s - signal->GetDistance();
398 bool is_valid =
false;
399 for (
auto &validity : signal->GetValidities()) {
400 if (waypoint.
lane_id >= validity._from_lane &&
401 waypoint.
lane_id <= validity._to_lane) {
409 if (distance_to_signal == 0) {
412 distance_to_signal});
415 {signal,
GetNext(waypoint, distance_to_signal).front(),
416 distance_to_signal});
425 GetLaneByDistance(successor.s, successor.lane_id);
427 if (
GetLane(successor).IsPositiveDirection()) {
428 successor.s = sucessor_lane.GetDistance();
430 successor.s = sucessor_lane.GetDistance() + sucessor_lane.GetLength();
433 successor,
distance - remaining_lane_length, stop_at_junction);
434 for(
auto& signal : sucessor_signals){
435 signal.accumulated_s += remaining_lane_length;
442 std::vector<const element::RoadInfoSignal*>
444 std::vector<const element::RoadInfoSignal*> result;
446 const auto &
road = road_pair.second;
448 for(
const auto* road_info : road_infos) {
449 result.push_back(road_info);
455 std::vector<const element::RoadInfoStencil*>
457 std::vector<const element::RoadInfoStencil*> result;
459 const auto &
road = road_pair.second;
461 for(
const auto* road_info : road_infos) {
462 result.push_back(road_info);
471 const auto &lane =
GetLane(waypoint);
472 const bool forward = lane.IsPositiveDirection();
473 const double relative_s = waypoint.
s - lane.GetDistance();
474 const double remaining_lane_length = forward ? lane.GetLength() - relative_s : relative_s;
478 std::vector<StencilSearchData> result;
482 const double in_lane_distance = std::min(
distance, remaining_lane_length);
483 const double signed_distance = forward ? in_lane_distance : -in_lane_distance;
485 waypoint.
s, waypoint.
s + signed_distance);
486 for(
auto* stencil : stencils){
487 double distance_to_stencil = 0;
488 if (lane.IsPositiveDirection()){
489 distance_to_stencil = stencil->
GetS() - waypoint.
s;
491 distance_to_stencil = waypoint.
s - stencil->GetS();
494 if (distance_to_stencil >= 0) {
500 result.push_back(data);
503 if (
distance <= remaining_lane_length) {
509 if (stop_at_junction &&
IsJunction(successor.road_id)) {
513 successor,
distance - remaining_lane_length, stop_at_junction);
514 for(
auto& stencil : successor_stencils){
515 stencil.accumulated_s += remaining_lane_length;
529 std::vector<geom::Location> result;
532 const auto &
road = pair.second;
534 if (crosswalks.size() > 0) {
535 for (
auto crosswalk : crosswalks) {
537 std::vector<geom::Location> points;
540 for (
const auto §ion :
road.GetLaneSectionsAt(crosswalk->GetS())) {
542 for (
const auto &lane : section.GetLanes()) {
544 if (lane.first == 0) {
549 waypoint.
s = crosswalk->GetS();
565 const float heading_deg =
566 geom::Math::ToDegrees<float>(
static_cast<float>(crosswalk->GetHeading()));
571 geom::Vector3D v(
static_cast<float>(crosswalk->GetT()), 0.0f, 0.0f);
580 const double s0 = crosswalk->GetS();
581 const double road_length =
road.GetLength();
582 const double z0 =
road.GetElevationOn(s0).Evaluate(s0);
585 for (
auto corner : crosswalk->GetPoints()) {
587 static_cast<float>(corner.u),
588 static_cast<float>(corner.v),
589 static_cast<float>(corner.z));
599 static_cast<double>((v2.
x - base.
location.
x) * forward.
x +
602 const double z_corner =
road.GetElevationOn(s_corner).Evaluate(s_corner);
603 v2.
z = base.
location.
z +
static_cast<float>(z_corner - z0) +
604 static_cast<float>(corner.z);
605 result.push_back(v2);
619 std::vector<Waypoint> result;
620 result.reserve(next_lanes.size());
621 for (
auto *next_lane : next_lanes) {
622 if (next_lane ==
nullptr) {
625 const auto lane_id = next_lane->GetId();
629 const auto *section = next_lane->GetLaneSection();
630 if (section ==
nullptr) {
633 const auto *
road = next_lane->GetRoad();
634 if (
road ==
nullptr) {
645 std::vector<Waypoint> result;
646 result.reserve(prev_lanes.size());
647 for (
auto *next_lane : prev_lanes) {
648 if (next_lane ==
nullptr) {
651 const auto lane_id = next_lane->GetId();
655 const auto *section = next_lane->GetLaneSection();
656 if (section ==
nullptr) {
659 const auto *
road = next_lane->GetRoad();
660 if (
road ==
nullptr) {
676 const auto &lane =
GetLane(waypoint);
677 const bool forward = lane.IsPositiveDirection();
679 const double relative_s = waypoint.
s - lane.GetDistance();
680 const double remaining_lane_length = forward ? lane.GetLength() - relative_s : relative_s;
685 if (
distance <= remaining_lane_length) {
687 result.
s += signed_distance;
694 std::vector<Waypoint> result;
697 successor.road_id != waypoint.
road_id ||
698 successor.section_id != waypoint.
section_id ||
699 successor.lane_id != waypoint.
lane_id);
702 bool is_broken =
false;
703 for (
const auto &future_successor :
GetSuccessors(successor)) {
704 if (future_successor.road_id == waypoint.
road_id
705 && future_successor.lane_id == waypoint.
lane_id
706 && future_successor.section_id == waypoint.
section_id){
725 const auto &lane =
GetLane(waypoint);
726 const bool forward = !lane.IsPositiveDirection();
728 const double relative_s = waypoint.
s - lane.GetDistance();
729 const double remaining_lane_length = forward ? lane.GetLength() - relative_s : relative_s;
734 if (
distance <= remaining_lane_length) {
736 result.
s += signed_distance;
743 std::vector<Waypoint> result;
746 successor.road_id != waypoint.
road_id ||
747 successor.section_id != waypoint.
section_id ||
748 successor.lane_id != waypoint.
lane_id);
751 bool is_broken =
false;
753 if (future_predecessor.road_id == waypoint.
road_id
754 && future_predecessor.lane_id == waypoint.
lane_id
755 && future_predecessor.section_id == waypoint.
section_id){
778 if (std::abs(waypoint.
lane_id) == 1) {
780 }
else if (waypoint.
lane_id > 0) {
793 if (std::abs(waypoint.
lane_id) == 1) {
795 }
else if (waypoint.
lane_id > 0) {
813 std::vector<Waypoint> result;
815 const auto &
road = pair.second;
818 result.emplace_back(waypoint);
826 std::vector<Waypoint> result;
828 const auto &
road = pair.second;
830 for (
const auto &lane_section :
road.GetLaneSectionsAt(0.0)) {
831 for (
const auto &lane : lane_section.GetLanes()) {
832 if (lane.second.IsPositiveDirection() &&
833 static_cast<int32_t
>(lane.second.GetType()) &
static_cast<int32_t
>(lane_type)) {
834 result.emplace_back(
Waypoint{
road.GetId(), lane_section.GetId(), lane.second.GetId(), 0.0 });
839 const auto road_len =
road.GetLength();
840 for (
const auto &lane_section :
road.GetLaneSectionsAt(road_len)) {
841 for (
const auto &lane : lane_section.GetLanes()) {
843 if (!lane.second.IsPositiveDirection() &&
844 static_cast<int32_t
>(lane.second.GetType()) &
static_cast<int32_t
>(lane_type)) {
846 Waypoint{
road.GetId(), lane_section.GetId(), lane.second.GetId(), road_len });
857 std::vector<Waypoint> result;
861 for (
const auto &lane_section :
road.GetLaneSectionsAt(0.0)) {
862 for (
const auto &lane : lane_section.GetLanes()) {
863 if (lane.second.IsPositiveDirection() &&
864 static_cast<int32_t
>(lane.second.GetType()) &
static_cast<int32_t
>(lane_type)) {
865 result.emplace_back(
Waypoint{
road.GetId(), lane_section.GetId(), lane.second.GetId(), 0.0 });
870 const auto road_len =
road.GetLength();
871 for (
const auto &lane_section :
road.GetLaneSectionsAt(road_len)) {
872 for (
const auto &lane : lane_section.GetLanes()) {
873 if (!lane.second.IsPositiveDirection() &&
874 static_cast<int32_t
>(lane.second.GetType()) &
static_cast<int32_t
>(lane_type)) {
876 Waypoint{
road.GetId(), lane_section.GetId(), lane.second.GetId(), road_len });
885 std::vector<std::pair<Waypoint, Waypoint>> result;
887 const auto &
road = pair.second;
890 if (successors.size() == 0){
893 if (last_waypoint.has_value()){
894 result.push_back({waypoint, *last_waypoint});
899 result.push_back({waypoint, successor});
908 std::vector<std::pair<Waypoint, Waypoint>> result;
910 for(
auto &connections :
junction->GetConnections()) {
913 const auto& lane =
GetLane(waypoint);
916 lane_end.
s = final_s;
917 result.push_back({waypoint, lane_end});
923 std::unordered_map<road::RoadId, std::unordered_set<road::RoadId>>
926 const float epsilon = 0.0001f;
929 std::unordered_map<road::RoadId, std::unordered_set<road::RoadId>>
933 typedef boost::geometry::model::point
934 <float, 2, boost::geometry::cs::cartesian> Point2d;
935 typedef boost::geometry::model::segment<Point2d> Segment2d;
936 typedef boost::geometry::model::box<Rtree::BPoint> Box;
939 auto bbox_pos =
junction->GetBoundingBox().location;
940 auto bbox_ext =
junction->GetBoundingBox().extent;
942 bbox_pos.x - bbox_ext.x,
943 bbox_pos.y - bbox_ext.y,
944 bbox_pos.z - bbox_ext.z - epsilon);
946 bbox_pos.x + bbox_ext.x,
947 bbox_pos.y + bbox_ext.y,
948 bbox_pos.z + bbox_ext.z + epsilon);
949 Box box({min_corner.x, min_corner.y, min_corner.z},
950 {max_corner.x, max_corner.y, max_corner.z});
953 for (
size_t i = 0; i < segments.size(); ++i){
954 auto &segment1 = segments[i];
955 auto waypoint1 = segment1.second.first;
961 Segment2d seg1{{segment1.first.first.get<0>(), segment1.first.first.get<1>()},
962 {segment1.first.second.get<0>(), segment1.first.second.get<1>()}};
963 for (
size_t j = i + 1; j < segments.size(); ++j){
964 auto &segment2 = segments[j];
965 auto waypoint2 = segment2.second.first;
972 if(waypoint1.road_id == waypoint2.road_id){
975 Segment2d seg2{{segment2.first.first.get<0>(), segment2.first.first.get<1>()},
976 {segment2.first.second.get<0>(), segment2.first.second.get<1>()}};
978 double distance = boost::geometry::distance(seg1, seg2);
983 if(conflicts[waypoint1.road_id].count(waypoint2.road_id) == 0){
984 conflicts[waypoint1.road_id].insert(waypoint2.road_id);
986 if(conflicts[waypoint2.road_id].count(waypoint1.road_id) == 0){
987 conflicts[waypoint2.road_id].insert(waypoint1.road_id);
1005 std::vector<Rtree::TreeElement> &rtree_elements,
1020 rtree_elements.emplace_back(std::make_pair(
Rtree::BSegment(init, end),
1021 std::make_pair(current_waypoint, next_waypoint)));
1026 std::vector<Rtree::TreeElement> &rtree_elements,
1032 current_waypoint, next_waypoint);
1033 current_waypoint = next_waypoint;
1034 current_transform = next_transform;
1048 const double epsilon = 0.000001;
1050 const double min_delta_s = 1;
1053 constexpr double angle_threshold = geom::Math::Pi<double>() / 100.0;
1055 constexpr double max_segment_length = 100.0;
1058 std::vector<Waypoint> topology;
1060 const auto &
road = pair.second;
1062 if(waypoint.lane_id != 0) {
1063 topology.push_back(waypoint);
1069 std::vector<Rtree::TreeElement> rtree_elements;
1071 for (
auto &waypoint : topology) {
1072 auto &lane_start_waypoint = waypoint;
1074 auto current_waypoint = lane_start_waypoint;
1082 double delta_s = min_delta_s;
1083 double remaining_length =
1085 remaining_length -= epsilon;
1086 delta_s = remaining_length;
1087 if (delta_s < epsilon) {
1090 auto next =
GetNext(current_waypoint, delta_s);
1093 RELEASE_ASSERT(next.front().road_id == current_waypoint.road_id);
1094 auto next_waypoint = next.front();
1103 auto next_waypoint = current_waypoint;
1108 double delta_s = min_delta_s;
1109 double remaining_length =
1111 remaining_length -= epsilon;
1112 delta_s = std::min(delta_s, remaining_length);
1114 if (delta_s < epsilon) {
1123 auto next =
GetNext(next_waypoint, delta_s);
1124 if (next.size() != 1 ||
1125 current_waypoint.section_id != next.front().section_id) {
1134 next_waypoint = next.front();
1139 if (std::abs(angle) > angle_threshold ||
1140 std::abs(current_waypoint.s - next_waypoint.s) > max_segment_length) {
1147 current_waypoint = next_waypoint;
1148 current_transform = next_transform;
1167 const float extra_width,
1168 const bool smooth_junctions)
const {
1178 const auto &
road = pair.second;
1179 if (
road.IsJunction()) {
1187 const auto &
junction = junc_pair.second;
1188 std::vector<std::unique_ptr<geom::Mesh>> lane_meshes;
1189 for(
const auto &connection_pair :
junction.GetConnections()) {
1190 const auto &connection = connection_pair.second;
1192 for (
auto &&lane_section :
road.GetLaneSections()) {
1193 for (
auto &&lane_pair : lane_section.GetLanes()) {
1194 lane_meshes.push_back(mesh_factory.
Generate(lane_pair.second));
1198 if(smooth_junctions) {
1202 for(
auto& lane : lane_meshes) {
1203 junction_mesh += *lane;
1205 out_mesh += junction_mesh;
1223 constexpr double kMaxSliverLength = 2.0;
1224 return !
road.IsJunction() &&
1225 road.GetLength() < kMaxSliverLength &&
1226 road.GetNexts().empty() &&
1227 road.GetPrevs().empty();
1241 const Map &map,
const std::unordered_set<RoadId> &candidate_ids) {
1242 std::unordered_set<RoadId> duplicates;
1243 if (candidate_ids.empty()) {
1246 constexpr double kSampleStep = 4.0;
1247 constexpr double kMaxXY = 2.0;
1248 constexpr double kMaxZ = 1.0;
1249 constexpr double kMinOverlapFraction = 0.4;
1251 const auto CellKey = [](
double x,
double y) {
1252 const auto ix =
static_cast<int64_t
>(std::floor(
x / kMaxXY));
1253 const auto iy =
static_cast<int64_t
>(std::floor(
y / kMaxXY));
1254 return (ix << 32) ^ (iy & 0xffffffff);
1256 std::unordered_map<int64_t, std::vector<geom::Location>> support_grid;
1257 std::unordered_map<RoadId, std::vector<geom::Location>> candidate_points;
1258 for (
const auto &wp : waypoints) {
1260 if (candidate_ids.count(wp.road_id) != 0u) {
1261 candidate_points[wp.road_id].push_back(loc);
1263 support_grid[CellKey(loc.
x, loc.
y)].push_back(loc);
1266 for (
const auto &entry : candidate_points) {
1267 size_t supported = 0u;
1270 for (
int dx = -1; dx <= 1 && !found; ++dx) {
1271 for (
int dy = -1; dy <= 1 && !found; ++dy) {
1272 const auto it = support_grid.find(
1273 CellKey(loc.x + dx * kMaxXY, loc.y + dy * kMaxXY));
1274 if (it == support_grid.end()) {
1278 const double dxy = std::hypot(loc.x - other.x, loc.y - other.y);
1279 if (dxy < kMaxXY && std::abs(loc.z - other.z) < kMaxZ) {
1290 if (!entry.second.empty() &&
1291 static_cast<double>(supported) /
static_cast<double>(entry.second.size()) >=
1292 kMinOverlapFraction) {
1293 duplicates.insert(entry.first);
1300 std::unordered_set<RoadId> candidate_ids;
1301 std::unordered_set<RoadId> skipped;
1303 const auto &
road = pair.second;
1304 if (
road.IsJunction() || !
road.GetNexts().empty() || !
road.GetPrevs().empty()) {
1308 skipped.insert(pair.first);
1310 candidate_ids.insert(pair.first);
1322 std::vector<std::unique_ptr<geom::Mesh>> out_mesh_list;
1324 std::unordered_map<JuncId, geom::Mesh> junction_map;
1327 const auto &
road = pair.second;
1328 if (!
road.IsJunction() && skipped_roads.count(pair.first) == 0u) {
1329 std::vector<std::unique_ptr<geom::Mesh>> road_mesh_list =
1332 out_mesh_list.insert(
1333 out_mesh_list.end(),
1334 std::make_move_iterator(road_mesh_list.begin()),
1335 std::make_move_iterator(road_mesh_list.end()));
1341 const auto &
junction = junc_pair.second;
1342 std::vector<std::unique_ptr<geom::Mesh>> lane_meshes;
1343 std::vector<std::unique_ptr<geom::Mesh>> sidewalk_lane_meshes;
1344 for(
const auto &connection_pair :
junction.GetConnections()) {
1345 const auto &connection = connection_pair.second;
1347 for (
auto &&lane_section :
road.GetLaneSections()) {
1348 for (
auto &&lane_pair : lane_section.GetLanes()) {
1349 const auto &lane = lane_pair.second;
1351 lane_meshes.push_back(mesh_factory.
Generate(lane));
1353 sidewalk_lane_meshes.push_back(mesh_factory.
Generate(lane));
1363 *merged_mesh += *fill;
1365 for(
auto& lane : sidewalk_lane_meshes) {
1366 *merged_mesh += *lane;
1368 out_mesh_list.push_back(std::move(merged_mesh));
1370 std::unique_ptr<geom::Mesh> junction_mesh = std::make_unique<geom::Mesh>();
1371 for(
auto& lane : lane_meshes) {
1372 *junction_mesh += *lane;
1375 *junction_mesh += *fill;
1377 for(
auto& lane : sidewalk_lane_meshes) {
1378 *junction_mesh += *lane;
1380 out_mesh_list.push_back(std::move(junction_mesh));
1391 if (out_mesh_list.empty()) {
1395 bool found_seed =
false;
1397 for (
auto & mesh : out_mesh_list) {
1398 if (!mesh->GetVertices().empty()) {
1399 const auto &seed_vertex = mesh->GetVertices().front();
1410 auto max_pos = min_pos;
1411 for (
auto & mesh : out_mesh_list) {
1412 if (mesh->GetVertices().empty()) {
1415 auto vertex = mesh->GetVertices().front();
1416 min_pos.
x = std::min(min_pos.
x, vertex.x);
1417 min_pos.
y = std::min(min_pos.
y, vertex.y);
1418 max_pos.x = std::max(max_pos.x, vertex.x);
1419 max_pos.y = std::max(max_pos.y, vertex.y);
1421 size_t mesh_amount_x =
static_cast<size_t>((max_pos.x - min_pos.
x)/params.
max_road_length) + 1;
1422 size_t mesh_amount_y =
static_cast<size_t>((max_pos.y - min_pos.
y)/params.
max_road_length) + 1;
1423 std::vector<std::unique_ptr<geom::Mesh>> result;
1424 result.reserve(mesh_amount_x*mesh_amount_y);
1425 for (
size_t i = 0; i < mesh_amount_x*mesh_amount_y; ++i) {
1426 result.emplace_back(std::make_unique<geom::Mesh>());
1428 for (
auto & mesh : out_mesh_list) {
1429 if (mesh->GetVertices().empty()) {
1432 auto vertex = mesh->GetVertices().front();
1433 size_t x_pos =
static_cast<size_t>((vertex.x - min_pos.
x) / params.
max_road_length);
1434 size_t y_pos =
static_cast<size_t>((vertex.y - min_pos.
y) / params.
max_road_length);
1435 *(result[x_pos + mesh_amount_x*y_pos]) += *mesh;
1441 std::map<road::Lane::LaneType , std::vector<std::unique_ptr<geom::Mesh>>>
1448 std::map<road::Lane::LaneType, std::vector<std::unique_ptr<geom::Mesh>>> road_out_mesh_list;
1449 std::map<road::Lane::LaneType, std::vector<std::unique_ptr<geom::Mesh>>> junction_out_mesh_list;
1452 minpos, maxpos, &junction_out_mesh_list);
1458 RoadsIDToGenerate.erase(
1459 std::remove_if(RoadsIDToGenerate.begin(), RoadsIDToGenerate.end(),
1460 [&skipped_roads](
RoadId id) { return skipped_roads.count(id) != 0u; }),
1461 RoadsIDToGenerate.end());
1463 size_t num_roads = RoadsIDToGenerate.size();
1464 size_t num_roads_per_thread = 30;
1465 size_t num_threads = (num_roads / num_roads_per_thread) + 1;
1466 num_threads = num_threads > 1 ? num_threads : 1;
1467 std::vector<std::thread> workers;
1468 std::mutex write_mutex;
1469 std::cout <<
"Generating " << std::to_string(num_roads) <<
" roads" << std::endl;
1471 for (
size_t i = 0; i < num_threads; ++i ) {
1472 std::thread neworker(
1473 [
this, &write_mutex, &mesh_factory, &RoadsIDToGenerate, &road_out_mesh_list, i, num_roads_per_thread]() {
1474 std::map<road::Lane::LaneType, std::vector<std::unique_ptr<geom::Mesh>>> Current =
1476 std::scoped_lock<std::mutex> guard(write_mutex);
1477 for (
auto&& pair : Current ) {
1478 if (road_out_mesh_list.find(pair.first) != road_out_mesh_list.end()) {
1479 road_out_mesh_list[pair.first].insert(road_out_mesh_list[pair.first].end(),
1480 std::make_move_iterator(pair.second.begin()),
1481 std::make_move_iterator(pair.second.end()));
1483 road_out_mesh_list[pair.first] = std::move(pair.second);
1487 workers.push_back(std::move(neworker));
1490 for (
size_t i = 0; i < workers.size(); ++i) {
1494 for (
size_t i = 0; i < workers.size(); ++i) {
1495 if (workers[i].joinable()) {
1500 juntction_thread.join();
1501 for (
auto&& pair : junction_out_mesh_list) {
1502 if (road_out_mesh_list.find(pair.first) != road_out_mesh_list.end())
1504 road_out_mesh_list[pair.first].insert(road_out_mesh_list[pair.first].end(),
1505 std::make_move_iterator(pair.second.begin()),
1506 std::make_move_iterator(pair.second.end()));
1510 road_out_mesh_list[pair.first] = std::move(pair.second);
1513 std::cout <<
"Generated " << std::to_string(num_roads) <<
" roads" << std::endl;
1515 return road_out_mesh_list;
1521 float distancebetweentrees,
1522 float distancefromdrivinglineborder,
1524 bool measure_from_curb,
1525 bool keep_on_sidewalk)
const {
1527 std::vector<std::pair<geom::Transform, std::string>> transforms;
1534 auto FindCurbLane = [measure_from_curb](
1537 sidewalk_lane =
nullptr;
1539 if (!measure_from_curb) {
1542 const auto &lanes = section.
GetLanes();
1543 const LaneId step = driving_lane->GetId() < 0 ? -1 : 1;
1544 for (
LaneId id = driving_lane->GetId() + step;;
id += step) {
1545 const auto it = lanes.find(
id);
1546 if (it == lanes.end()) {
1549 const auto type = it->second.GetType();
1551 sidewalk_lane = &it->second;
1557 curb_lane = &it->second;
1563 for (
RoadId id : RoadsIDToGenerate ) {
1565 if (!
road.IsJunction()) {
1566 for (
auto &&lane_section :
road.GetLaneSections()) {
1569 for (
auto &pairlane : lane_section.GetLanes()) {
1571 if (pairlane.first < 0 && (min_lane == 0 || pairlane.first < min_lane)) {
1572 min_lane = pairlane.first;
1573 }
else if (pairlane.first > 0 && pairlane.first > max_lane) {
1574 max_lane = pairlane.first;
1583 const LaneId outer_lane = (min_lane != 0) ? min_lane : max_lane;
1584 if (outer_lane == 0)
continue;
1586 const road::Lane* lane = lane_section.GetLane(outer_lane);
1588 double s_current = lane_section.
GetDistance() + s_offset;
1589 const double s_end = lane_section.GetDistance() + lane_section.GetLength();
1590 while(s_current < s_end){
1591 if(lane->
GetWidth(s_current) != 0.0f){
1596 const double director_squared_length =
1597 static_cast<double>(director.
x) *
static_cast<double>(director.
x) +
1598 static_cast<double>(director.
y) *
static_cast<double>(director.
y) +
1599 static_cast<double>(director.
z) *
static_cast<double>(director.
z);
1604 s_current += distancebetweentrees;
1610 const bool is_positive_lane = (lane->
GetId() > 0);
1614 is_positive_lane ? second_corner : first_corner;
1616 is_positive_lane ? first_corner : second_corner;
1618 (outer_corner - inner_corner).MakeUnitVector();
1626 float offset = distancefromdrivinglineborder;
1628 const road::Lane *curb_lane = FindCurbLane(lane_section, lane, sidewalk_lane);
1629 if (curb_lane != lane) {
1633 const float d_first = (curb_edges.first - inner_corner).
x * outward_direction.
x +
1634 (curb_edges.first - inner_corner).y * outward_direction.
y;
1635 const float d_second = (curb_edges.second - inner_corner).
x * outward_direction.
x +
1636 (curb_edges.second - inner_corner).y * outward_direction.
y;
1637 outer_corner = d_first > d_second ? curb_edges.first : curb_edges.second;
1639 if (keep_on_sidewalk && sidewalk_lane !=
nullptr) {
1640 const float sidewalk_width =
static_cast<float>(sidewalk_lane->
GetWidth(s_current));
1641 if (sidewalk_width > 0.0f) {
1642 offset = std::min(offset, 0.5f * sidewalk_width);
1646 outer_corner + outward_direction * offset;
1654 const geom::Vector3D inward_direction = outward_direction * (-1.0f);
1664 transforms.push_back(std::make_pair(treeTransform, roadinfo->
GetType()));
1666 transforms.push_back(std::make_pair(treeTransform,
"Town"));
1669 s_current += distancebetweentrees;
1684 if (crosswalk_vertex.empty()) {
1695 auto AddCrosswalkPolygon = [&out_mesh](
const std::vector<geom::Vector3D> &poly) {
1696 if (poly.size() < 3) {
1700 float longest_len2 = -1.0f;
1701 for (
size_t k = 0; k < poly.size(); ++k) {
1702 const auto &p = poly[k];
1703 const auto &q = poly[(k + 1) % poly.size()];
1704 const float dx = q.x - p.x, dy = q.y - p.y;
1705 const float len2 = dx * dx + dy * dy;
1706 if (len2 > longest_len2) {
1707 longest_len2 = len2;
1712 if (longest_len2 > 1e-6f) {
1713 const auto &p = poly[longest];
1714 const auto &q = poly[(longest + 1) % poly.size()];
1715 const float inv = 1.0f / std::sqrt(longest_len2);
1719 float a_min = std::numeric_limits<float>::max(), b_min = a_min;
1720 float a_max = std::numeric_limits<float>::lowest(), b_max = a_max;
1721 std::vector<std::pair<float, float>> local;
1722 local.reserve(poly.size());
1723 for (
const auto &p : poly) {
1724 const float a = p.x * u_dir.
x + p.y * u_dir.
y;
1725 const float b = p.x * v_dir.
x + p.y * v_dir.
y;
1726 local.emplace_back(a, b);
1727 a_min = std::min(a_min, a); a_max = std::max(a_max, a);
1728 b_min = std::min(b_min, b); b_max = std::max(b_max, b);
1730 const float depth = std::max(b_max - b_min, 0.5f);
1732 for (
size_t k = 0; k < poly.size(); ++k) {
1735 (local[k].
first - a_min) / depth,
1736 (local[k].second - b_min) / depth));
1738 for (
size_t k = 1; k + 1 < poly.size(); ++k) {
1747 size_t start_vertex_index = 0;
1749 std::vector<geom::Vector3D> vertices;
1754 if (i != 0 && crosswalk_vertex[start_vertex_index] == crosswalk_vertex[i]) {
1756 AddCrosswalkPolygon(vertices);
1759 if (i >= crosswalk_vertex.size() - 1) {
1762 start_vertex_index = ++i;
1765 vertices.push_back(crosswalk_vertex[i++]);
1766 }
while (i < crosswalk_vertex.size());
1777 std::vector<std::string>& outinfo )
const
1779 std::vector<std::unique_ptr<geom::Mesh>> LineMarks;
1792 auto HasSingleConnectingRoad = [
this](
JuncId junction_id) {
1797 std::unordered_set<RoadId> connecting_roads;
1798 for (
const auto &connection_pair :
junction->GetConnections()) {
1799 connecting_roads.insert(connection_pair.second.connecting_road);
1801 return connecting_roads.size() == 1;
1806 for (
RoadId id : RoadsIDToGenerate ) {
1808 if (skipped_roads.count(
id) != 0u) {
1811 if (!
road.IsJunction() || HasSingleConnectingRoad(
road.GetJunctionId())) {
1820 std::vector<carla::geom::BoundingBox> returning;
1822 const auto&
junction = junc_pair.second;
1823 float box_extraextension_factor = 1.5f;
1825 bb.
extent *= box_extraextension_factor;
1826 returning.push_back(bb);
1836 std::map<road::Lane::LaneType, std::vector<std::unique_ptr<geom::Mesh>>>
1838 const std::vector<RoadId>& RoadsId,
1839 const size_t index,
const size_t number_of_roads_per_thread)
const
1841 std::map<road::Lane::LaneType, std::vector<std::unique_ptr<geom::Mesh>>> out;
1843 size_t start = index * number_of_roads_per_thread;
1844 size_t endoffset = (index+1) * number_of_roads_per_thread;
1845 size_t end = RoadsId.size();
1847 for (
size_t i = start; i < endoffset && i < end; ++i) {
1849 if (!
road.IsJunction()) {
1853 std::cout <<
"Generated roads from " + std::to_string(index * number_of_roads_per_thread) +
" to " + std::to_string((index+1) * number_of_roads_per_thread ) << std::endl;
1862 std::vector<std::unique_ptr<geom::Mesh>>>* junction_out_mesh_list)
const {
1865 size_t num_junctions = JunctionsToGenerate.size();
1866 std::cout <<
"Generating " << std::to_string(num_junctions) <<
" junctions" << std::endl;
1867 size_t num_junctions_per_thread = 5;
1868 size_t num_threads = (num_junctions / num_junctions_per_thread) + 1;
1869 num_threads = num_threads > 1 ? num_threads : 1;
1870 std::vector<std::thread> workers;
1871 std::mutex write_mutex;
1873 for (
size_t i = 0; i < num_threads; ++i ) {
1874 std::thread neworker(
1875 [
this, &write_mutex, &mesh_factory, &junction_out_mesh_list, JunctionsToGenerate, i, num_junctions_per_thread, num_junctions]() {
1877 std::vector<std::unique_ptr<geom::Mesh>>> junctionsofthisthread;
1880 if( (i + 1) * num_junctions_per_thread < num_junctions ){
1881 minimum = (i + 1) * num_junctions_per_thread;
1883 minimum = num_junctions;
1885 std::cout <<
"Generating Junctions between " << std::to_string(i * num_junctions_per_thread) <<
" and " << std::to_string(minimum) << std::endl;
1887 for (
size_t junctionindex = i * num_junctions_per_thread;
1888 junctionindex < minimum;
1893 std::cout <<
"Generated Junctions between " << std::to_string(i * num_junctions_per_thread) <<
" and " << std::to_string(minimum) << std::endl;
1894 std::scoped_lock<std::mutex> guard(write_mutex);
1895 for (
auto&& pair : junctionsofthisthread ) {
1896 if ((*junction_out_mesh_list).find(pair.first) != (*junction_out_mesh_list).end()) {
1897 (*junction_out_mesh_list)[pair.first].insert((*junction_out_mesh_list)[pair.first].end(),
1898 std::make_move_iterator(pair.second.begin()),
1899 std::make_move_iterator(pair.second.end()));
1901 (*junction_out_mesh_list)[pair.first] = std::move(pair.second);
1905 workers.push_back(std::move(neworker));
1908 for (
size_t i = 0; i < workers.size(); ++i) {
1912 for (
size_t i = 0; i < workers.size(); ++i) {
1913 if (workers[i].joinable()) {
1922 std::cout <<
"Filtered from " + std::to_string(
_data.
GetJunctions().size() ) +
" junctions " << std::endl;
1923 std::vector<JuncId> ToReturn;
1926 if( minpos.
x < junctionLocation.
x && junctionLocation.
x < maxpos.
x &&
1927 minpos.
y > junctionLocation.
y && junctionLocation.
y > maxpos.
y ) {
1928 ToReturn.push_back(
junction.first);
1931 std::cout <<
"To " + std::to_string(ToReturn.size() ) +
" junctions " << std::endl;
1939 std::vector<RoadId> ToReturn;
1940 std::cout <<
"Filtered from " + std::to_string(
_data.
GetRoads().size() ) +
" roads " << std::endl;
1942 auto &&lane_section = (*
road.second.GetLaneSections().begin());
1943 const road::Lane* lane =
road.second.IsRHT() ? lane_section.GetLane(-1) : lane_section.GetLane(1);
1949 int best_abs_id = std::numeric_limits<int>::max();
1950 for (
const auto& pairlane : lane_section.GetLanes()) {
1952 const int abs_id = std::abs(pairlane.first);
1953 if (abs_id < best_abs_id) {
1954 best_abs_id = abs_id;
1955 lane = &pairlane.second;
1961 const double s_check = lane_section.
GetDistance() + lane_section.GetLength() * 0.5;
1963 if( minpos.
x < roadLocation.
x && roadLocation.
x < maxpos.
x &&
1964 minpos.
y > roadLocation.
y && roadLocation.
y > maxpos.
y ) {
1965 ToReturn.push_back(
road.first);
1969 std::cout <<
"To " + std::to_string(ToReturn.size() ) +
" roads " << std::endl;
1991 struct Tri { Vec3 a, b, c; };
1993 constexpr float kCell = 0.5f;
1994 constexpr float kBin = 4.0f;
1995 constexpr float kCapLength = 5.0f;
1996 constexpr float kArmSnap = 3.0f;
1997 constexpr float kZBelow = 0.015f;
1998 constexpr int kMargin = 2;
1999 constexpr size_t kMaxVertices = 4000000;
2002 const auto &idx = corridor_mesh.
GetIndexes();
2003 if (verts.size() < 3 || idx.size() < 3) {
2007 std::vector<Tri> corridor_tris;
2008 corridor_tris.reserve(idx.size() / 3);
2009 for (
size_t i = 0; i + 2 < idx.size(); i += 3) {
2011 corridor_tris.push_back({verts[idx[i] - 1], verts[idx[i + 1] - 1], verts[idx[i + 2] - 1]});
2021 std::vector<Vec3> corridor_ends;
2022 std::unordered_set<RoadId> arm_candidates;
2024 for (
const auto &connection_pair :
junction.GetConnections()) {
2025 const auto &connection = connection_pair.second;
2026 const auto it = roads.find(connection.connecting_road);
2027 if (it == roads.end()) {
2030 const auto &
cr = it->second;
2031 corridor_ends.push_back(
cr.GetDirectedPointIn(0.0).location);
2032 corridor_ends.push_back(
cr.GetDirectedPointIn(
cr.GetLength()).location);
2033 arm_candidates.insert(connection.incoming_road);
2034 arm_candidates.insert(
cr.GetPredecessor());
2035 arm_candidates.insert(
cr.GetSuccessor());
2038 auto NearestCorridorEnd = [&corridor_ends](
const Vec3 &p) {
2039 float best = std::numeric_limits<float>::max();
2040 for (
const auto &e : corridor_ends) {
2041 best = std::min(best, (e - p).Length2D());
2046 std::vector<Tri> cap_tris;
2047 for (
RoadId arm_id : arm_candidates) {
2048 const auto it = roads.find(arm_id);
2049 if (it == roads.end() || it->second.IsJunction()) {
2052 const auto &arm = it->second;
2053 const double length = arm.GetLength();
2054 if (length < 1e-3) {
2057 const Vec3 p_start = arm.GetDirectedPointIn(0.0).location;
2058 const Vec3 p_end = arm.GetDirectedPointIn(length).location;
2059 const float d_start = NearestCorridorEnd(p_start);
2060 const float d_end = NearestCorridorEnd(p_end);
2061 if (std::min(d_start, d_end) > kArmSnap) {
2064 const bool at_end = d_end < d_start;
2065 const double s_c = at_end ? length : 0.0;
2066 const double s_in = at_end ? std::max(0.0, length - 1.0) : std::min(length, 1.0);
2067 const Vec3 p_in = arm.GetDirectedPointIn(s_in).location;
2068 Vec3 outward = at_end ? Vec3(p_end.x - p_in.x, p_end.y - p_in.y, 0.0f)
2069 : Vec3(p_start.x - p_in.x, p_start.y - p_in.y, 0.0f);
2071 if (outward.Length2D() < 1e-4f) {
2074 outward = outward.MakeUnitVector();
2075 const Vec3 normal(-outward.y, outward.x, 0.0f);
2077 bool have_corner =
false;
2078 float t_min = 0.0f, t_max = 0.0f;
2080 for (
const road::Lane *lane : arm.GetLanesByDistance(s_c)) {
2081 if (lane ==
nullptr || lane->GetId() == 0 ||
2086 const auto corners = lane->GetCornerPositions(s_c, 0.0f);
2087 for (
const Vec3 &c : {corners.first, corners.second}) {
2088 const float t = (c.x - p_start.x) * normal.x + (c.y - p_start.y) * normal.y;
2089 if (!have_corner || t < t_min) { t_min = t; c_min = c; }
2090 if (!have_corner || t > t_max) { t_max = t; c_max = c; }
2094 if (!have_corner || (t_max - t_min) < 0.5f) {
2097 const Vec3 o = outward * kCapLength;
2098 cap_tris.push_back({c_min, c_max, c_max + o});
2099 cap_tris.push_back({c_min, c_max + o, c_min + o});
2103 float min_x = std::numeric_limits<float>::max(), min_y = min_x;
2104 float max_x = std::numeric_limits<float>::lowest(), max_y = max_x;
2105 auto Extend = [&](
const Vec3 &v) {
2106 min_x = std::min(min_x, v.x); max_x = std::max(max_x, v.x);
2107 min_y = std::min(min_y, v.y); max_y = std::max(max_y, v.y);
2109 for (
const auto &v : verts) { Extend(v); }
2110 for (
const auto &t : cap_tris) { Extend(t.a); Extend(t.b); Extend(t.c); }
2112 const float origin_x = min_x - kMargin * kCell;
2113 const float origin_y = min_y - kMargin * kCell;
2114 const int nvx =
static_cast<int>(std::ceil((max_x - min_x) / kCell)) + 2 * kMargin + 1;
2115 const int nvy =
static_cast<int>(std::ceil((max_y - min_y) / kCell)) + 2 * kMargin + 1;
2116 if (nvx < 3 || nvy < 3 ||
static_cast<size_t>(nvx) *
static_cast<size_t>(nvy) > kMaxVertices) {
2117#ifdef LIBCARLA_JFILL_DEBUG
2118 std::cout <<
"[jfill] junction " <<
junction.GetId() <<
" BAIL grid " << nvx <<
"x" << nvy << std::endl;
2122 const int ncx = nvx - 1, ncy = nvy - 1;
2125 const int nbx =
static_cast<int>((nvx * kCell) / kBin) + 1;
2126 const int nby =
static_cast<int>((nvy * kCell) / kBin) + 1;
2127 auto BinX = [&](
float x) {
return std::clamp(
static_cast<int>((
x - origin_x) / kBin), 0, nbx - 1); };
2128 auto BinY = [&](
float y) {
return std::clamp(
static_cast<int>((
y - origin_y) / kBin), 0, nby - 1); };
2129 std::vector<std::vector<int>> corridor_bins(
static_cast<size_t>(nbx) * nby);
2130 std::vector<std::vector<int>> cap_bins(
static_cast<size_t>(nbx) * nby);
2131 std::vector<std::vector<int>> vertex_bins(
static_cast<size_t>(nbx) * nby);
2132 auto BinTris = [&](
const std::vector<Tri> &tris, std::vector<std::vector<int>> &bins) {
2133 for (
size_t i = 0; i < tris.size(); ++i) {
2134 const Tri &t = tris[i];
2135 const int bx0 = BinX(std::min({t.a.x, t.b.x, t.c.x}));
2136 const int bx1 = BinX(std::max({t.a.x, t.b.x, t.c.x}));
2137 const int by0 = BinY(std::min({t.a.y, t.b.y, t.c.y}));
2138 const int by1 = BinY(std::max({t.a.y, t.b.y, t.c.y}));
2139 for (
int by = by0; by <= by1; ++by) {
2140 for (
int bx = bx0; bx <= bx1; ++bx) {
2141 bins[
static_cast<size_t>(by) * nbx + bx].push_back(
static_cast<int>(i));
2146 BinTris(corridor_tris, corridor_bins);
2147 BinTris(cap_tris, cap_bins);
2148 for (
size_t i = 0; i < verts.size(); ++i) {
2149 vertex_bins[
static_cast<size_t>(BinY(verts[i].
y)) * nbx + BinX(verts[i].
x)].push_back(
static_cast<int>(i));
2153 auto HitTriangle = [](
const Tri &t,
float px,
float py,
float &z_out) {
2154 const float denom = (t.b.y - t.c.y) * (t.a.x - t.c.x) + (t.c.x - t.b.x) * (t.a.y - t.c.y);
2155 if (std::abs(denom) < 1e-9f) {
2158 const float w0 = ((t.b.y - t.c.y) * (px - t.c.x) + (t.c.x - t.b.x) * (py - t.c.y)) / denom;
2159 const float w1 = ((t.c.y - t.a.y) * (px - t.c.x) + (t.a.x - t.c.x) * (py - t.c.y)) / denom;
2160 const float w2 = 1.0f - w0 - w1;
2161 constexpr float eps = -1e-3f;
2162 if (w0 < eps || w1 < eps || w2 < eps) {
2165 z_out = w0 * t.a.z + w1 * t.b.z + w2 * t.c.z;
2170 std::vector<uint8_t> v_corridor(
static_cast<size_t>(nvx) * nvy, 0);
2171 std::vector<uint8_t> v_cap(
static_cast<size_t>(nvx) * nvy, 0);
2172 std::vector<float> v_z(
static_cast<size_t>(nvx) * nvy, 0.0f);
2173 for (
int vy = 0; vy < nvy; ++vy) {
2174 for (
int vx = 0; vx < nvx; ++vx) {
2175 const float px = origin_x + vx * kCell;
2176 const float py = origin_y + vy * kCell;
2177 const size_t vid =
static_cast<size_t>(vy) * nvx + vx;
2178 const size_t bin =
static_cast<size_t>(BinY(py)) * nbx + BinX(px);
2180 for (
int ti : corridor_bins[bin]) {
2181 if (HitTriangle(corridor_tris[ti], px, py,
z)) {
2182 v_corridor[vid] = 1;
2187 for (
int ti : cap_bins[bin]) {
2188 if (HitTriangle(cap_tris[ti], px, py,
z)) {
2197 auto CellId = [&](
int cx,
int cy) {
return static_cast<size_t>(cy) * ncx + cx; };
2198 std::vector<uint8_t> blocked(
static_cast<size_t>(ncx) * ncy, 0);
2199 std::vector<uint8_t> full(
static_cast<size_t>(ncx) * ncy, 0);
2200 for (
int cy = 0; cy < ncy; ++cy) {
2201 for (
int cx = 0; cx < ncx; ++cx) {
2202 const size_t v00 =
static_cast<size_t>(cy) * nvx + cx;
2203 const size_t v10 = v00 + 1, v01 = v00 + nvx, v11 = v01 + 1;
2204 const int n_corr = v_corridor[v00] + v_corridor[v10] + v_corridor[v01] + v_corridor[v11];
2205 const bool any_cap = v_cap[v00] || v_cap[v10] || v_cap[v01] || v_cap[v11];
2206 full[CellId(cx, cy)] = (n_corr == 4);
2207 blocked[CellId(cx, cy)] = (n_corr == 4 || any_cap);
2226 const float bbox_extent = std::max(max_x - min_x, max_y - min_y);
2227 const float close_radius = std::clamp(0.12f * bbox_extent, 8.0f, 20.0f);
2229 const float r_cells = close_radius / kCell;
2230 const float kInf = 1e9f;
2231 std::vector<float> dist(
static_cast<size_t>(ncx) * ncy, kInf);
2232 auto Chamfer = [&](std::vector<float> &d) {
2233 for (
int cy = 0; cy < ncy; ++cy) {
2234 for (
int cx = 0; cx < ncx; ++cx) {
2235 float v = d[CellId(cx, cy)];
2236 if (cx > 0) v = std::min(v, d[CellId(cx - 1, cy)] + 1.0f);
2237 if (cy > 0) v = std::min(v, d[CellId(cx, cy - 1)] + 1.0f);
2238 if (cx > 0 && cy > 0) v = std::min(v, d[CellId(cx - 1, cy - 1)] + 1.4142f);
2239 if (cx + 1 < ncx && cy > 0) v = std::min(v, d[CellId(cx + 1, cy - 1)] + 1.4142f);
2240 d[CellId(cx, cy)] = v;
2243 for (
int cy = ncy - 1; cy >= 0; --cy) {
2244 for (
int cx = ncx - 1; cx >= 0; --cx) {
2245 float v = d[CellId(cx, cy)];
2246 if (cx + 1 < ncx) v = std::min(v, d[CellId(cx + 1, cy)] + 1.0f);
2247 if (cy + 1 < ncy) v = std::min(v, d[CellId(cx, cy + 1)] + 1.0f);
2248 if (cx + 1 < ncx && cy + 1 < ncy) v = std::min(v, d[CellId(cx + 1, cy + 1)] + 1.4142f);
2249 if (cx > 0 && cy + 1 < ncy) v = std::min(v, d[CellId(cx - 1, cy + 1)] + 1.4142f);
2250 d[CellId(cx, cy)] = v;
2254 for (
size_t i = 0; i < full.size(); ++i) {
2255 if (full[i]) dist[i] = 0.0f;
2258 std::vector<float> dist2(
static_cast<size_t>(ncx) * ncy, kInf);
2259 for (
size_t i = 0; i < dist.size(); ++i) {
2260 if (dist[i] > r_cells) dist2[i] = 0.0f;
2263 for (
size_t i = 0; i < dist2.size(); ++i) {
2267 if (dist2[i] > r_cells && !blocked[i]) {
2274 std::vector<uint8_t> outside(
static_cast<size_t>(ncx) * ncy, 0);
2275 std::vector<std::pair<int, int>> stack;
2276 auto Seed = [&](
int cx,
int cy) {
2277 const size_t id = CellId(cx, cy);
2278 if (!blocked[
id] && !outside[
id]) {
2280 stack.emplace_back(cx, cy);
2283 for (
int cx = 0; cx < ncx; ++cx) { Seed(cx, 0); Seed(cx, ncy - 1); }
2284 for (
int cy = 0; cy < ncy; ++cy) { Seed(0, cy); Seed(ncx - 1, cy); }
2285 while (!stack.empty()) {
2286 const auto [cx, cy] = stack.back();
2288 if (cx > 0) Seed(cx - 1, cy);
2289 if (cx + 1 < ncx) Seed(cx + 1, cy);
2290 if (cy > 0) Seed(cx, cy - 1);
2291 if (cy + 1 < ncy) Seed(cx, cy + 1);
2296 auto BlendZ = [&](
float px,
float py,
bool &ok) {
2297 const int bx = BinX(px), by = BinY(py);
2298 double sum_w = 0.0, sum_z = 0.0;
2300 for (
int r = 0; r <= 12 && (found < 4 || r == 0); ++r) {
2301 for (
int y = by - r;
y <= by + r; ++
y) {
2302 if (y < 0 || y >= nby)
continue;
2303 for (
int x = bx - r;
x <= bx + r; ++
x) {
2304 if (x < 0 || x >= nbx)
continue;
2305 if (std::abs(
x - bx) != r && std::abs(
y - by) != r)
continue;
2306 for (
int vi : vertex_bins[
static_cast<size_t>(
y) * nbx +
x]) {
2307 const Vec3 &v = verts[vi];
2308 const double dx = v.x - px, dy = v.y - py;
2309 const double w = 1.0 / (dx * dx + dy * dy + 1e-2);
2318 return ok ?
static_cast<float>(sum_z / sum_w) : 0.0f;
2323 std::vector<size_t> mesh_index(
static_cast<size_t>(nvx) * nvy, 0);
2324 auto VertexIndex = [&](
int vx,
int vy,
bool &ok) ->
size_t {
2325 const size_t vid =
static_cast<size_t>(vy) * nvx + vx;
2326 if (mesh_index[vid] != 0) {
2328 return mesh_index[vid];
2330 const float px = origin_x + vx * kCell;
2331 const float py = origin_y + vy * kCell;
2333 if (v_corridor[vid]) {
2337 z = BlendZ(px, py, ok);
2342 out_mesh.
AddVertex(Vec3(px, py,
z - kZBelow));
2344 return mesh_index[vid];
2347 size_t filled_cells = 0;
2349 for (
int cy = 0; cy < ncy; ++cy) {
2350 for (
int cx = 0; cx < ncx; ++cx) {
2351 const size_t id = CellId(cx, cy);
2355 const bool is_closing_fill = (blocked[id] == 2);
2356 const bool is_hole = (!blocked[id] && !outside[id]);
2357 if (!is_closing_fill && !is_hole) {
2360 bool ok0, ok1, ok2, ok3;
2361 const size_t i00 = VertexIndex(cx, cy, ok0);
2362 const size_t i10 = VertexIndex(cx + 1, cy, ok1);
2363 const size_t i11 = VertexIndex(cx + 1, cy + 1, ok2);
2364 const size_t i01 = VertexIndex(cx, cy + 1, ok3);
2365 if (!(ok0 && ok1 && ok2 && ok3)) {
2377#ifdef LIBCARLA_JFILL_DEBUG
2378 std::cout <<
"[jfill] junction " <<
junction.GetId() <<
" grid " << nvx <<
"x" << nvy
2379 <<
" corridors " << corridor_tris.size() <<
" caps " << cap_tris.size()
2380 <<
" filled " << filled_cells << std::endl;
2382 if (filled_cells == 0) {
2385 return std::make_unique<geom::Mesh>(std::move(out_mesh));
2389 const std::vector<geom::Vector3D>& ,
2392 float box_extraextension_factor = 1.2f;
2393 const double CubeSize = 0.5;
2398 geom::Vector3D worldloc(
static_cast<float>(pos.x),
static_cast<float>(pos.y),
static_cast<float>(pos.z));
2400 if (CheckingWaypoint) {
2414 if (Distance.
Length2D() < CubeSize * 1.1 && pos.z < 0.2) {
2417 return Distance.
Length() * -1.0;
2421 domain.
min = { MinOffset.
x, MinOffset.
y, MinOffset.
z };
2422 domain.
size = { bb.
extent.
x * box_extraextension_factor * 2, bb.
extent.
y * box_extraextension_factor * 2, 0.4 };
2428 for (
auto& cv : mesh.vertices) {
2430 newvertex.
x =
static_cast<float>(cv.x);
2431 newvertex.
y =
static_cast<float>(cv.y);
2432 newvertex.
z =
static_cast<float>(cv.z);
2437 for (
auto ct : mesh.triangles) {
2438 out_mesh.
AddIndex(
static_cast<size_t>(ct[1] + 1));
2439 out_mesh.
AddIndex(
static_cast<size_t>(ct[0] + 1));
2440 out_mesh.
AddIndex(
static_cast<size_t>(ct[2] + 1));
2445 if (!CheckingWaypoint)
2455 return std::make_unique<geom::Mesh>(out_mesh);
2461 junction_out_mesh_list)
const {
2464 if (
junction.GetConnections().size() > 2) {
2465 std::vector<std::unique_ptr<geom::Mesh>> lane_meshes;
2466 std::vector<std::unique_ptr<geom::Mesh>> sidewalk_lane_meshes;
2467 std::vector<carla::geom::Vector3D> perimeterpoints;
2472 for (
const auto& connection_pair :
junction.GetConnections()) {
2473 const auto& connection = connection_pair.second;
2475 for (
auto&& lane_section :
road.GetLaneSections()) {
2476 for (
auto&& lane_pair : lane_section.GetLanes()) {
2477 const auto& lane = lane_pair.second;
2479 std::optional<element::Waypoint> sw =
2480 GetWaypoint(
road.GetId(), lane_pair.first,
static_cast<float>(lane.GetDistance() + (lane.GetLength() * 0.5)));
2488 std::unique_ptr<geom::Mesh> sidewalk_mesh = std::make_unique<geom::Mesh>();
2489 for (
auto& lane : sidewalk_lane_meshes) {
2490 *sidewalk_mesh += *lane;
2494 std::vector<std::unique_ptr<geom::Mesh>> lane_meshes;
2495 std::vector<std::unique_ptr<geom::Mesh>> sidewalk_lane_meshes;
2496 for (
const auto& connection_pair :
junction.GetConnections()) {
2497 const auto& connection = connection_pair.second;
2499 for (
auto&& lane_section :
road.GetLaneSections()) {
2500 for (
auto&& lane_pair : lane_section.GetLanes()) {
2501 const auto& lane = lane_pair.second;
2511 std::unique_ptr<geom::Mesh> merged_mesh = std::make_unique<geom::Mesh>();
2512 for (
auto& lane : lane_meshes) {
2513 *merged_mesh += *lane;
2515 std::unique_ptr<geom::Mesh> sidewalk_mesh = std::make_unique<geom::Mesh>();
2516 for (
auto& lane : sidewalk_lane_meshes) {
2517 *sidewalk_mesh += *lane;
#define DEBUG_ASSERT(predicate)
#define RELEASE_ASSERT(pred)
std::map< std::string, unsigned int > road
std::map< std::string, unsigned int > junction
Location location
Center of the BoundingBox in local space.
Vector3D extent
Half the size of the BoundingBox in local space.
value_type Evaluate(const value_type &x) const
Evaluates f(x) = a + bx + cx^2 + dx^3.
static double GetVectorAngle(const Vector3D &a, const Vector3D &b)
Returns the angle between 2 vectors in radians.
static auto Distance2D(const Vector3D &a, const Vector3D &b)
static std::pair< float, float > DistanceSegmentToPoint(const Vector3D &p, const Vector3D &v, const Vector3D &w)
Returns a pair containing:
static constexpr T ToDegrees(T rad)
static constexpr T Clamp(T a, T min=T(0), T max=T(1))
std::unique_ptr< Mesh > GenerateSidewalk(const road::LaneSection &lane_section) const
std::unique_ptr< Mesh > MergeAndSmooth(std::vector< std::unique_ptr< Mesh > > &lane_meshes) const
void GenerateLaneMarkForRoad(const road::Road &road, std::vector< std::unique_ptr< Mesh > > &inout, std::vector< std::string > &outinfo) const
RoadParameters road_param
std::unique_ptr< Mesh > Generate(const road::Road &road) const
Generates a mesh that defines a road.
std::unique_ptr< Mesh > GenerateTesselated(const road::Lane &lane, const double s_start, const double s_end) const
Generates a mesh that defines a lane from a given s start and end with bigger tesselation.
std::vector< std::unique_ptr< Mesh > > GenerateAllWithMaxLen(const road::Road &road) const
Generates a chunked road with all the features needed for simulation.
void GenerateAllOrderedWithMaxLen(const road::Road &road, std::map< road::Lane::LaneType, std::vector< std::unique_ptr< Mesh > > > &roads) const
Mesh data container, validator and exporter.
void AddIndex(index_type index)
Appends a index to the indexes list.
void AddVertex(vertex_type vertex)
Appends a vertex to the vertices list.
void AddUV(uv_type uv)
Appends a vertex to the vertices list, they will be read 3 in 3.
const std::vector< index_type > & GetIndexes() const
size_t GetVerticesNum() const
void AddMaterial(const std::string &material_name)
Starts applying a new material to the new added triangles.
void EndMaterial()
Stops applying the material to the new added triangles.
const std::vector< vertex_type > & GetVertices() const
Euler angles of a rotation in CARLA's / Unreal's left-handed frame: x forward, y right,...
Vector3D GetForwardVector() const
boost::geometry::model::point< float, 3, boost::geometry::cs::cartesian > BPoint
boost::geometry::model::segment< BPoint > BSegment
std::vector< TreeElement > GetNearestNeighboursWithFilter(const Geometry &geometry, Filter filter, size_t number_neighbours=1) const
Return nearest neighbors with a user defined filter.
std::pair< BSegment, std::pair< Waypoint, Waypoint > > TreeElement
std::vector< TreeElement > GetIntersections(const Geometry &geometry) const
Returns segments that intersec the specified geometry Warning: intersection between 3D segments is no...
void InsertElements(const std::vector< TreeElement > &elements)
carla::geom::BoundingBox GetBoundingBox() const
bool ContainsLane(LaneId id) const
std::map< LaneId, Lane > & GetLanes()
bool IsStraight() const
Checks whether the geometry is straight or not.
const std::vector< Lane * > & GetNextLanes() const
double GetWidth(const double s) const
Returns the total lane width given a s.
geom::Transform ComputeTransform(const double s) const
const T * GetInfo(const double s) const
LaneType
Can be used as flags.
double GetDistance() const
std::pair< geom::Vector3D, geom::Vector3D > GetCornerPositions(const double s, const float extra_width=0.f) const
Computes the location of the edges given a s.
const std::vector< Lane * > & GetPreviousLanes() const
bool IsPositiveDirection() const
std::unordered_map< RoadId, Road > & GetRoads()
Road & GetRoad(const RoadId id)
bool ContainsRoad(RoadId id) const
std::unordered_map< JuncId, Junction > & GetJunctions()
Junction * GetJunction(JuncId id)
std::vector< std::pair< Waypoint, Waypoint > > GenerateTopology() const
Generate the minimum set of waypoints that define the topology of map.
std::vector< SignalSearchData > GetSignalsInDistance(Waypoint waypoint, double distance, bool stop_at_junction=false) const
Searches signals from an initial waypoint until the defined distance.
JuncId GetJunctionId(RoadId road_id) const
std::vector< Waypoint > GetPrevious(Waypoint waypoint, double distance) const
Return the list of waypoints at distance in the reversed direction that a vehicle at waypoint could d...
bool IsJunction(RoadId road_id) const
std::optional< Waypoint > GetLeft(Waypoint waypoint) const
Return a waypoint at the lane of waypoint's left lane.
Lane::LaneType GetLaneType(Waypoint waypoint) const
std::unique_ptr< geom::Mesh > SDFToMesh(const road::Junction &jinput, const std::vector< geom::Vector3D > &sdfinput, int grid_cells_per_dim) const
double GetLaneWidth(Waypoint waypoint) const
std::vector< std::pair< geom::Transform, std::string > > GetTreesTransform(const geom::Vector3D &minpos, const geom::Vector3D &maxpos, float distancebetweentrees, float distancefromdrivinglineborder, float s_offset=0, bool measure_from_curb=false, bool keep_on_sidewalk=false) const
std::vector< RoadId > FilterRoadsByPosition(const geom::Vector3D &minpos, const geom::Vector3D &maxpos) const
void AddElementToRtreeAndUpdateTransforms(std::vector< Rtree::TreeElement > &rtree_elements, geom::Transform ¤t_transform, Waypoint ¤t_waypoint, Waypoint &next_waypoint)
std::vector< Waypoint > GenerateWaypointsOnRoadEntries(Lane::LaneType lane_type=Lane::LaneType::Driving) const
Generate waypoints on each lane at the start of each road.
std::pair< const element::RoadInfoMarkRecord *, const element::RoadInfoMarkRecord * > GetMarkRecord(Waypoint waypoint) const
std::vector< element::LaneMarking > CalculateCrossedLanes(const geom::Location &origin, const geom::Location &destination) const
std::vector< const element::RoadInfoStencil * > GetAllStencilReferences() const
Return all RoadInfoStencil in the map.
std::unordered_set< road::RoadId > ComputeSkippedGenerationRoads() const
Roads excluded from mesh/marking generation: link-less sub-2m slivers and link-less duplicate traces ...
std::vector< carla::geom::BoundingBox > GetJunctionsBoundingBoxes() const
std::vector< JuncId > FilterJunctionsByPosition(const geom::Vector3D &minpos, const geom::Vector3D &maxpos) const
std::map< road::Lane::LaneType, std::vector< std::unique_ptr< geom::Mesh > > > GenerateRoadsMultithreaded(const carla::geom::MeshFactory &mesh_factory, const std::vector< RoadId > &RoadsID, const size_t index, const size_t number_of_roads_per_thread) const
std::optional< element::Waypoint > GetWaypoint(const geom::Location &location, int32_t lane_type=static_cast< int32_t >(Lane::LaneType::Driving)) const
geom::Mesh GetAllCrosswalkMesh() const
Buids a mesh of all crosswalks based on the OpenDRIVE.
std::vector< Waypoint > GetNext(Waypoint waypoint, double distance) const
Return the list of waypoints at distance such that a vehicle at waypoint could drive to.
std::optional< Waypoint > GetRight(Waypoint waypoint) const
Return a waypoint at the lane of waypoint's right lane.
Junction * GetJunction(JuncId id)
std::optional< element::Waypoint > GetClosestWaypointOnRoad(const geom::Location &location, int32_t lane_type=static_cast< int32_t >(Lane::LaneType::Driving)) const
========================================================================
void GenerateJunctions(const carla::geom::MeshFactory &mesh_factory, const rpc::OpendriveGenerationParameters ¶ms, const geom::Vector3D &minpos, const geom::Vector3D &maxpos, std::map< road::Lane::LaneType, std::vector< std::unique_ptr< geom::Mesh > > > *juntion_out_mesh_list) const
std::vector< Waypoint > GenerateWaypointsInRoad(RoadId road_id, Lane::LaneType lane_type=Lane::LaneType::Driving) const
Generate waypoints at the entry of each lane of the specified road.
std::vector< std::unique_ptr< geom::Mesh > > GenerateChunkedMesh(const rpc::OpendriveGenerationParameters ¶ms) const
geom::Transform ComputeTransform(Waypoint waypoint) const
std::vector< StencilSearchData > GetStencilsInDistance(Waypoint waypoint, double distance, bool stop_at_junction=false) const
Searches stencils from an initial waypoint until the defined distance.
std::vector< Waypoint > GenerateWaypoints(double approx_distance) const
Generate all the waypoints in map separated by approx_distance.
std::map< road::Lane::LaneType, std::vector< std::unique_ptr< geom::Mesh > > > GenerateOrderedChunkedMeshInLocations(const rpc::OpendriveGenerationParameters ¶ms, const geom::Vector3D &minpos, const geom::Vector3D &maxpos) const
void GenerateSingleJunction(const carla::geom::MeshFactory &mesh_factory, const JuncId Id, std::map< road::Lane::LaneType, std::vector< std::unique_ptr< geom::Mesh > > > *junction_out_mesh_list) const
std::vector< Waypoint > GetPredecessors(Waypoint waypoint) const
std::vector< Waypoint > GetSuccessors(Waypoint waypoint) const
========================================================================
std::vector< geom::Location > GetAllCrosswalkZones() const
Returns a list of locations defining 2d areas, when a location is repeated an area is finished.
std::vector< std::unique_ptr< geom::Mesh > > GenerateLineMarkings(const rpc::OpendriveGenerationParameters ¶ms, const geom::Vector3D &minpos, const geom::Vector3D &maxpos, std::vector< std::string > &outinfo) const
Buids a list of meshes related with LineMarkings.
float GetZPosInDeformation(float posx, float posy) const
void AddElementToRtree(std::vector< Rtree::TreeElement > &rtree_elements, geom::Transform ¤t_transform, geom::Transform &next_transform, Waypoint ¤t_waypoint, Waypoint &next_waypoint)
Helper Functions for constructing the rtree element list.
std::vector< const element::RoadInfoSignal * > GetAllSignalReferences() const
Return all RoadInfoSignal in the map.
std::vector< std::pair< Waypoint, Waypoint > > GetJunctionWaypoints(JuncId id, Lane::LaneType lane_type) const
Generate waypoints of the junction.
std::unordered_map< road::RoadId, std::unordered_set< road::RoadId > > ComputeJunctionConflicts(JuncId id) const
std::unique_ptr< geom::Mesh > GenerateJunctionFill(const road::Junction &junction, const geom::Mesh &corridor_mesh) const
Paves the regions a junction's lane corridors enclose but don't cover (see GenerateChunkedMesh).
const Lane & GetLane(Waypoint waypoint) const
========================================================================
geom::Mesh GenerateMesh(const double distance, const float extra_width=0.6f, const bool smooth_junctions=true) const
Buids a mesh based on the OpenDRIVE.
Lane & GetLaneById(SectionId section_id, LaneId lane_id)
JuncId GetJunctionId() const
LaneSection & GetLaneSectionById(SectionId id)
static std::vector< LaneMarking > Calculate(const Map &map, const geom::Location &origin, const geom::Location &destination)
Lane Width RecordEach lane within a road’scross section can be provided with severalwidth entries.
const geom::CubicPolynomial & GetPolynomial() const
Each lane within a road cross section can be provided with several road markentries.
std::string GetType() const
double GetDistance() const
Distance from road's start location.
Mesh MarchCube(Fun3s const &sdf, Rect3 const &domain)
Reconstructs a triangle mesh from a given signed distance function using Marching Cubes.
double GetRemainingLength(const Lane &lane, double current_s)
static bool IsOrphanSliverRoad(const road::Road &road)
static void ForEachDrivableLane(const Road &road, FuncT &&func)
Return a waypoint for each drivable lane on each lane section of road.
static constexpr double EPSILON
We use this epsilon to shift the waypoints away from the edges of the lane sections to avoid floating...
static std::unordered_set< RoadId > ComputeDuplicateTraceRoads(const Map &map, const std::unordered_set< RoadId > &candidate_ids)
static bool IsLanePresent(const MapData &data, Waypoint waypoint)
Assumes road_id and section_id are valid.
static void ForEachDrivableLaneAt(const Road &road, double distance, FuncT &&func)
Return a waypoint for each drivable lane at distance on road.
static void ForEachDrivableLaneImpl(RoadId road_id, const LaneSection &lane_section, double distance, FuncT &&func)
Return a waypoint for each drivable lane on lane_section.
static void ForEachLane(const Road &road, Lane::LaneType lane_type, FuncT &&func)
Return a waypoint for each lane of the specified type on each lane section of road.
static void ForEachLaneImpl(RoadId road_id, const LaneSection &lane_section, double distance, Lane::LaneType lane_type, FuncT &&func)
static double GetDistanceAtStartOfLane(const Lane &lane)
static std::vector< T > ConcatVectors(std::vector< T > dst, std::vector< T > src)
static double GetDistanceAtEndOfLane(const Lane &lane)
static constexpr double TREE_PLACEMENT_EPSILON
This file contains definitions of common data structures used in traffic manager.
Vector3D MakeUnitVector(const float epsilon=2.0f *std::numeric_limits< float >::epsilon()) const
Return a unit-length copy of this vector.
Data structure for the signal search.
Data structure for the stencil search.
const element::RoadInfoStencil * stencil
Seting for map generation from opendrive without additional geometry.