arrange_polygons: settings, simplify based on growing boxes; more...

This commit is contained in:
Thomas Krijnen
2026-04-10 21:45:14 +02:00
parent a3efa7e9ee
commit 158756e921
6 changed files with 1503 additions and 258 deletions
+2 -1
View File
@@ -42,6 +42,7 @@ WHITE = numpy.array((1.0, 1.0, 1.0))
DO_NOTHING = lambda *args: None DO_NOTHING = lambda *args: None
ARRANGE_POLYGON_SETTINGS = W.arrange_polygon_settings() if hasattr(W, 'arrange_polygon_settings') else None
@dataclass @dataclass
class draw_settings: class draw_settings:
@@ -536,7 +537,7 @@ def main(
*(tup for i, tup in enumerate(zip(path_objects, section_polies, polies)) if has_relevant_zone(i)) *(tup for i, tup in enumerate(zip(path_objects, section_polies, polies)) if has_relevant_zone(i))
) )
arranged = W.arrange_polygons(polies) arranged = W.arrange_polygons(*filter(None, (ARRANGE_POLYGON_SETTINGS,)), polies)
svg_data_3 = W.polygons_to_svg(arranged, False) svg_data_3 = W.polygons_to_svg(arranged, False)
dom3 = parseString(svg_data_3) dom3 = parseString(svg_data_3)
svg3 = dom3.childNodes[0] svg3 = dom3.childNodes[0]
+3 -2
View File
@@ -1166,6 +1166,7 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
%ignore svgfill::line_segments_to_polygons; %ignore svgfill::line_segments_to_polygons;
%ignore svgfill::svg_to_polygons; %ignore svgfill::svg_to_polygons;
%ignore svgfill::arrange_polygons; %ignore svgfill::arrange_polygons;
%ignore svgfill::abstract_arrangement;
%template(svg_line_segments) std::vector<std::array<svgfill::point_2, 2>>; %template(svg_line_segments) std::vector<std::array<svgfill::point_2, 2>>;
%template(svg_groups_of_line_segments) std::vector<std::vector<std::array<svgfill::point_2, 2>>>; %template(svg_groups_of_line_segments) std::vector<std::vector<std::array<svgfill::point_2, 2>>>;
@@ -1287,9 +1288,9 @@ ifcopenshell::geometry::taxonomy::item::ptr try_upcast(PyObject* obj0, swig_type
} }
} }
std::vector<svgfill::polygon_2> arrange_polygons(const std::vector<svgfill::polygon_2>& polygons) { std::vector<svgfill::polygon_2> arrange_polygons(svgfill::arrange_polygon_settings settings, const std::vector<svgfill::polygon_2>& polygons) {
std::vector<svgfill::polygon_2> r; std::vector<svgfill::polygon_2> r;
if (svgfill::arrange_polygons(polygons, r)) { if (svgfill::arrange_polygons(settings, polygons, r)) {
return r; return r;
} else { } else {
throw std::runtime_error("Failed to arrange polygons"); throw std::runtime_error("Failed to arrange polygons");
File diff suppressed because it is too large Load Diff
+7
View File
@@ -346,6 +346,13 @@ public:
} }
} }
template <typename T>
void from_arrangement(T& arr) {
for (auto it = arr.edges_begin(); it != arr.edges_end(); ++it) {
insert(it->source()->point(), it->target()->point());
}
}
void assert_symmetric() { void assert_symmetric() {
#ifdef SVGFILL_DEBUG #ifdef SVGFILL_DEBUG
#if 0 #if 0
+12
View File
@@ -483,6 +483,18 @@ public:
return ps; return ps;
} }
size_t delete_same_facet_edge_pairs() {
size_t n_deleted = 0;
for (auto it = arr.edges_begin(); it != arr.edges_end();) {
decltype(it) current = it++;
if (current->face() == current->twin()->face()) {
arr.remove_edge(current);
n_deleted++;
}
}
return n_deleted;
}
void merge(const std::vector<int>& edge_indices) { void merge(const std::vector<int>& edge_indices) {
if (edge_indices.empty()) { if (edge_indices.empty()) {
return; return;
+22 -2
View File
@@ -67,6 +67,7 @@ namespace svgfill {
virtual std::vector<int> get_face_pairs() = 0; virtual std::vector<int> get_face_pairs() = 0;
virtual size_t num_edges() = 0; virtual size_t num_edges() = 0;
virtual size_t num_faces() = 0; virtual size_t num_faces() = 0;
virtual size_t delete_same_facet_edge_pairs() = 0;
}; };
class SVGFILL_API context { class SVGFILL_API context {
@@ -101,6 +102,7 @@ namespace svgfill {
void write(std::vector<std::vector<polygon_2>>&); void write(std::vector<std::vector<polygon_2>>&);
size_t num_edges() { return arr_->num_edges(); } size_t num_edges() { return arr_->num_edges(); }
size_t num_faces() { return arr_->num_faces(); } size_t num_faces() { return arr_->num_faces(); }
size_t delete_same_facet_edge_pairs() { return arr_->delete_same_facet_edge_pairs(); }
~context() { ~context() {
delete arr_; delete arr_;
@@ -113,7 +115,25 @@ namespace svgfill {
SVGFILL_API std::string polygons_to_svg(const std::vector<std::vector<polygon_2>>& polygons, bool random_color=false); SVGFILL_API std::string polygons_to_svg(const std::vector<std::vector<polygon_2>>& polygons, bool random_color=false);
SVGFILL_API std::string polygons_to_svg(const std::vector<polygon_2>& polygons, bool random_color = false); SVGFILL_API std::string polygons_to_svg(const std::vector<polygon_2>& polygons, bool random_color = false);
SVGFILL_API bool svg_to_polygons(const std::string& data, const boost::optional<std::string>& class_name, std::vector<polygon_2>& polygons); SVGFILL_API bool svg_to_polygons(const std::string& data, const boost::optional<std::string>& class_name, std::vector<polygon_2>& polygons);
SVGFILL_API bool arrange_polygons(const std::vector<polygon_2>& polygons, std::vector<polygon_2>& arranged);
} struct SVGFILL_API arrange_polygon_settings {
bool debug_output = false;
// -1: compute from average edge length
double polygon_offset_distance = -1.;
// 0: use offset - union - negative offset to find the outer perimeter
// 1: radial walk along vertices; exact, but can only reuse vertices, not create new positions by means of intersections
int outer_perimiter_algo = 0;
// 0: outer perimiter and corridor center lines
// 1: input polygons, corridor center lines and segments connecting corridor center lines to input polygons
int topology_reconstruction_algo = 0;
// 0: join segment runs
// 1: local badness reduction
int line_cleaning_algo = 0;
bool perform_cleanup = true;
double subdivision_factor = 16.;
};
SVGFILL_API bool arrange_polygons(arrange_polygon_settings settings, const std::vector<polygon_2>& polygons, std::vector<polygon_2>& arranged);
}
#endif #endif