Arrange polies: reorder segment to exterior insertion based on length

This commit is contained in:
Thomas Krijnen
2026-05-12 20:52:30 +02:00
parent 7a901c1fce
commit 10f93545da
+86 -62
View File
@@ -1469,6 +1469,7 @@ std::vector<MergedBoxRecord> merge_intersecting_parallel_boxes_iterative(const s
std::vector<size_t> members = clusters[i].members; std::vector<size_t> members = clusters[i].members;
members.insert(members.end(), clusters[j].members.begin(), clusters[j].members.end()); members.insert(members.end(), clusters[j].members.begin(), clusters[j].members.end());
auto merged = BoxCluster{members, merge_cluster_to_box(members, records)}; auto merged = BoxCluster{members, merge_cluster_to_box(members, records)};
std::cout << "Result width: " << merged.box.avg_width << " fromt " << clusters[i].box.avg_width << " & " << clusters[j].box.avg_width << std::endl;
std::vector<BoxCluster> next_clusters; std::vector<BoxCluster> next_clusters;
next_clusters.reserve(clusters.size() - 1); next_clusters.reserve(clusters.size() - 1);
@@ -2170,92 +2171,115 @@ extend_end_vertices_based_on_input_simple(
const K::FT& max_projection_distance) const K::FT& max_projection_distance)
{ {
auto max_intersection_distance = max_projection_distance / 4; auto max_intersection_distance = max_projection_distance / 4;
std::list<std::pair<Point_2, Point_2>> constructed_segments;
for (auto it = G.vertices_begin(); it != G.vertices_end(); ++it) { const auto& process_point = [&](const Point_2& M, const Point_2& incoming) {
if (it->second.size() == 1) { for (auto& bnd : outer_perimiter) {
auto& M = it->first; // if point M is contained in bnd interior:
// if (!bnd.has_on_unbounded_side(M)) {
if (bnd.has_on_bounded_side(M)) {
// create ray incoming -> M
CGAL::Ray_2<K> ray(incoming, M - incoming);
for (auto& bnd : outer_perimiter) { // intersect ray with boundary
// if point M is contained in bnd interior: boost::optional<CGAL::Segment_2<K>> closest_segment;
// if (!bnd.has_on_unbounded_side(M)) { boost::optional<CGAL::Point_2<K>> closest_intersection_point;
if (bnd.has_on_bounded_side(M)) { K::FT sq_distance_along_ray = std::numeric_limits<double>::infinity();
auto& incoming = *it->second.begin(); for (auto jt = bnd.edges_begin(); jt != bnd.edges_end(); ++jt) {
// create ray incoming -> M const auto& seg = *jt;
CGAL::Ray_2<K> ray(incoming, M - incoming); auto x = CGAL::intersection(ray, seg);
if (x) {
if (auto* xp = variant_get<CGAL::Point_2<K>>(&*x)) {
auto dist = ((*xp) - M).squared_length();
if (dist < sq_distance_along_ray) {
if (dist < (max_intersection_distance * max_intersection_distance)) {
closest_segment = seg;
closest_intersection_point = *xp;
sq_distance_along_ray = dist;
} else {
}
}
}
}
}
// intersect ray with boundary if (closest_intersection_point) {
boost::optional<CGAL::Segment_2<K>> closest_segment; return closest_intersection_point;
boost::optional<CGAL::Point_2<K>> closest_intersection_point; // constructed_segments.push_front({M, *closest_intersection_point});
K::FT sq_distance_along_ray = std::numeric_limits<double>::infinity(); } else {
for (auto jt = bnd.edges_begin(); jt != bnd.edges_end(); ++jt) {
const auto& seg = *jt; // Loop over boundary segments, and project point onto it, take the closest
auto x = CGAL::intersection(ray, seg); K::FT closest_distance = std::numeric_limits<double>::infinity();
if (x) { boost::optional<CGAL::Point_2<K>> closest_point;
if (auto* xp = variant_get<CGAL::Point_2<K>>(&*x)) { for (auto& poly : outer_perimiter) {
auto dist = ((*xp) - M).squared_length(); for (auto jt = poly.edges_begin(); jt != poly.edges_end(); ++jt) {
if (dist < sq_distance_along_ray) { auto seg = *jt;
if (dist < (max_intersection_distance * max_intersection_distance)) { auto Pp = seg.supporting_line().projection(M);
closest_segment = seg; if (seg.has_on(Pp)) {
closest_intersection_point = *xp; auto d = CGAL::squared_distance(Pp, M);
sq_distance_along_ray = dist; if (d < (max_projection_distance * max_projection_distance)) {
} else { if (d < closest_distance) {
closest_distance = d;
closest_point = Pp;
} }
} }
} }
} }
} }
if (closest_intersection_point) { if (closest_point) {
constructed_segments.push_front({M, *closest_intersection_point}); return closest_point;
// constructed_segments.push_front({M, *closest_point});
} else { } else {
// Loop over boundary segments, and project point onto it, take the closest
K::FT closest_distance = std::numeric_limits<double>::infinity();
boost::optional<CGAL::Point_2<K>> closest_point;
for (auto& poly : outer_perimiter) { for (auto& poly : outer_perimiter) {
for (auto jt = poly.edges_begin(); jt != poly.edges_end(); ++jt) { for (auto it = poly.begin(); it != poly.end(); ++it) {
auto seg = *jt; auto Pp = *it;
auto Pp = seg.supporting_line().projection(M); auto d = CGAL::squared_distance(Pp, M);
if (seg.has_on(Pp)) { if (d < (max_projection_distance * max_projection_distance)) {
auto d = CGAL::squared_distance(Pp, M); if (d < closest_distance) {
if (d < (max_projection_distance * max_projection_distance)) { closest_distance = d;
if (d < closest_distance) { closest_point = Pp;
closest_distance = d;
closest_point = Pp;
}
} }
} }
} }
} }
if (closest_point) { if (closest_point) {
constructed_segments.push_front({M, *closest_point}); return closest_point;
// constructed_segments.push_front({M, *closest_point});
} else { } else {
for (auto& poly : outer_perimiter) {
for (auto it = poly.begin(); it != poly.end(); ++it) {
auto Pp = *it;
auto d = CGAL::squared_distance(Pp, M);
if (d < (max_projection_distance * max_projection_distance)) {
if (d < closest_distance) {
closest_distance = d;
closest_point = Pp;
}
}
}
}
if (closest_point) {
constructed_segments.push_front({M, *closest_point});
} else {
std::cout << "Unable to find projection or intersection point for interior boundary (" << M.x() << " " << M.y() << ")" << std::endl;
}
} }
} }
} }
} }
} }
return boost::optional<Point_2>{};
};
using solution_length_point_incoming = std::tuple<K::FT, Point_2, Point_2>;
std::vector<solution_length_point_incoming> solutions;
for (auto it = G.vertices_begin(); it != G.vertices_end(); ++it) {
if (it->second.size() == 1) {
auto& M = it->first;
if (auto result = process_point(M, *it->second.begin())) {
auto d = (M - *result).squared_length();
solutions.emplace_back(d, *result, *it->second.begin());
} else {
std::cout << "Unable to find projection or intersection point for interior boundary (" << M.x() << " " << M.y() << ")" << std::endl;
}
}
}
std::sort(solutions.begin(), solutions.end());
std::list<std::pair<Point_2, Point_2>> constructed_segments;
for (auto& [d, point, incoming] : solutions) {
if (auto result = process_point(point, incoming)) {
constructed_segments.push_front({point, *result});
} else {
std::cout << "Unable to find projection or intersection point for interior boundary (" << M.x() << " " << M.y() << ")" << std::endl;
}
} }
return constructed_segments; return constructed_segments;