1218 {
1220 return false;
1221 }
1222 if (accumulate_s == nullptr || lateral == nullptr ||
1223 min_distance == nullptr) {
1224 return false;
1225 }
1226 double min_distance_sqr = std::numeric_limits<double>::infinity();
1227 int estimate_nearest_segment_idx = -1;
1228 std::vector<double> distance_sqr_to_segments;
1229 distance_sqr_to_segments.reserve(
segments_.size());
1230 for (
size_t i = 0; i <
segments_.size(); ++i) {
1231 const double distance_sqr =
segments_[i].DistanceSquareTo(point);
1232 distance_sqr_to_segments.push_back(distance_sqr);
1233 if (distance_sqr < min_distance_sqr) {
1234 min_distance_sqr = distance_sqr;
1235 estimate_nearest_segment_idx = static_cast<int>(i);
1236 }
1237 }
1238 if (estimate_nearest_segment_idx < 0) {
1239 return false;
1240 }
1241 const auto& original_segments = path.segments();
1242 const int num_original_segments = static_cast<int>(original_segments.size());
1243 const auto& original_accumulated_s = path.accumulated_s();
1244 double min_distance_sqr_with_error =
1245 Sqr(sqrt(min_distance_sqr) +
1247 *min_distance = std::numeric_limits<double>::infinity();
1248 int nearest_segment_idx = -1;
1249 for (
size_t i = 0; i <
segments_.size(); ++i) {
1250 if (distance_sqr_to_segments[i] >= min_distance_sqr_with_error) {
1251 continue;
1252 }
1255 double max_original_projection = std::numeric_limits<double>::infinity();
1256 if (first_segment_idx < last_segment_idx) {
1258 const double projection = segment.ProjectOntoUnit(point);
1259 const double prod_sqr =
Sqr(segment.ProductOntoUnit(point));
1260 if (prod_sqr >= min_distance_sqr_with_error) {
1261 continue;
1262 }
1263 const double scan_distance = sqrt(min_distance_sqr_with_error - prod_sqr);
1264 const double min_projection = projection - scan_distance;
1265 max_original_projection =
projections_[i] + projection + scan_distance;
1266 if (min_projection > 0.0) {
1268 const int sample_index =
1269 std::max(0, static_cast<int>(limit / kSampleDistance));
1271 first_segment_idx = last_segment_idx;
1272 } else {
1273 first_segment_idx =
1274 std::max(first_segment_idx,
1276 if (first_segment_idx >= last_segment_idx) {
1277 first_segment_idx = last_segment_idx;
1278 } else {
1279 while (first_segment_idx < last_segment_idx &&
1281 limit) {
1282 ++first_segment_idx;
1283 }
1284 }
1285 }
1286 }
1287 }
1288 bool min_distance_updated = false;
1289 bool is_within_end_point = false;
1290 for (int idx = first_segment_idx; idx <= last_segment_idx; ++idx) {
1292 break;
1293 }
1294 const auto& original_segment = original_segments[idx];
1295 const double x0 = point.x() - original_segment.start().x();
1296 const double y0 = point.y() - original_segment.start().y();
1297 const double ux = original_segment.unit_direction().x();
1298 const double uy = original_segment.unit_direction().y();
1299 double proj = x0 * ux + y0 * uy;
1300 double distance = 0.0;
1301 if (proj < 0.0) {
1302 if (is_within_end_point) {
1303 continue;
1304 }
1305 is_within_end_point = true;
1306 distance = hypot(x0, y0);
1307 } else if (proj <= original_segment.length()) {
1308 is_within_end_point = true;
1309 distance = std::abs(x0 * uy - y0 * ux);
1310 } else {
1311 is_within_end_point = false;
1312 if (idx != last_segment_idx) {
1313 continue;
1314 }
1315 distance = original_segment.end().DistanceTo(point);
1316 }
1317 if (distance < *min_distance) {
1318 min_distance_updated = true;
1319 *min_distance = distance;
1320 nearest_segment_idx = idx;
1321 }
1322 }
1323 if (min_distance_updated) {
1324 min_distance_sqr_with_error =
Sqr(*min_distance +
max_error_);
1325 }
1326 }
1327 if (nearest_segment_idx >= 0) {
1328 const auto& segment = original_segments[nearest_segment_idx];
1329 double proj = segment.ProjectOntoUnit(point);
1330 const double prod = segment.ProductOntoUnit(point);
1331 if (nearest_segment_idx > 0) {
1332 proj = std::max(0.0, proj);
1333 }
1334 if (nearest_segment_idx + 1 < num_original_segments) {
1335 proj = std::min(segment.length(), proj);
1336 }
1337 *accumulate_s = original_accumulated_s[nearest_segment_idx] + proj;
1338 if ((nearest_segment_idx == 0 && proj < 0.0) ||
1339 (nearest_segment_idx + 1 == num_original_segments &&
1340 proj > segment.length())) {
1341 *lateral = prod;
1342 } else {
1343 *lateral = (prod > 0 ? (*min_distance) : -(*min_distance));
1344 }
1345 return true;
1346 }
1347 return false;
1348}
int num_projection_samples_
std::vector< common::math::LineSegment2d > segments_
std::vector< double > min_original_projections_to_right_
std::vector< int > sampled_max_original_projections_to_left_
std::vector< double > max_error_per_segment_
std::vector< double > projections_
std::vector< int > original_ids_
std::vector< double > max_original_projections_to_left_
double Sqr(const double x)