Skip to content

Commit e0b8a9b

Browse files
committed
Improve shape cleaning robustness
1 parent 6ce1f9a commit e0b8a9b

File tree

6 files changed

+601
-551
lines changed

6 files changed

+601
-551
lines changed

data/irregular/users/2024-08-08_solution.json

Lines changed: 334 additions & 334 deletions
Large diffs are not rendered by default.

data/irregular/users/2024-08-08_sub_2_solution.json

Lines changed: 150 additions & 150 deletions
Large diffs are not rendered by default.

extern/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ FetchContent_MakeAvailable(optimizationtools)
1414
FetchContent_Declare(
1515
shape
1616
GIT_REPOSITORY https://github.com/fontanf/shape.git
17-
GIT_TAG 3eb30c9538fd0ca8d9cb0c6e251169dc1ce4ba54
17+
GIT_TAG cb7899d6a1596a36b142c83a0483941bbf624b7d
1818
#SOURCE_DIR "${PROJECT_SOURCE_DIR}/../shape/"
1919
EXCLUDE_FROM_ALL)
2020
FetchContent_MakeAvailable(shape)

src/irregular/branching_scheme.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ BranchingScheme::BranchingScheme(
155155
border_pos < (DefectId)simplified_bin_type.borders.size();
156156
++border_pos) {
157157
const Shape& simplified_inflated_shape = simplified_bin_type.borders[border_pos].shape_inflated;
158-
Shape shape_inflated = convert_shape(simplified_inflated_shape, direction);
159-
shape_inflated = clean_shape(shape_inflated, true);
158+
const Shape& shape_inflated = convert_shape(simplified_inflated_shape, direction);
160159

161160
// Supports.
162161
shape::ShapeSupports supports = shape::compute_shape_supports(shape_inflated, false);
@@ -186,8 +185,7 @@ BranchingScheme::BranchingScheme(
186185
++defect_id) {
187186
//std::cout << "defect_id " << defect_id << std::endl;
188187
const Shape& simplified_inflated_shape = simplified_bin_type.defects[defect_id].shape_inflated;
189-
Shape shape_inflated = convert_shape(simplified_inflated_shape, direction);
190-
shape_inflated = clean_shape(shape_inflated, true);
188+
const Shape& shape_inflated = convert_shape(simplified_inflated_shape, direction);
191189

192190
// Supports.
193191
shape::ShapeSupports supports = shape::compute_shape_supports(shape_inflated, false);
@@ -206,8 +204,7 @@ BranchingScheme::BranchingScheme(
206204
hole_pos < (ShapePos)simplified_bin_type.defects[defect_id].holes_deflated.size();
207205
++hole_pos) {
208206
const Shape& simplified_deflated_shape = simplified_bin_type.defects[defect_id].holes_deflated[hole_pos];
209-
Shape shape_deflated = convert_shape(simplified_deflated_shape, direction);
210-
shape_deflated = clean_shape(shape_deflated, false);
207+
const Shape& shape_deflated = convert_shape(simplified_deflated_shape, direction);
211208

212209
// Update trapezoidation input.
213210
holes_deflated.push_back(shape_deflated);
@@ -271,6 +268,12 @@ BranchingScheme::BranchingScheme(
271268
const ItemShape& item_shape = item_type.shapes[item_shape_pos];
272269
const Shape& simplified_shape = simplified_item_type.shapes[item_shape_pos].shape;
273270
const Shape& simplified_inflated_shape = simplified_item_type.shapes[item_shape_pos].shape_inflated;
271+
//std::cout << "item_type_id " << item_type_id
272+
// << " item_shape_pos " << item_shape_pos
273+
// << " angle " << angle_range.first
274+
// << " mirror " << mirror
275+
// << " simplified_shape " << simplified_shape.to_string(2)
276+
// << std::endl;
274277

275278
if (write_shapes) {
276279
simplified_shape.write_svg(
@@ -283,10 +286,8 @@ BranchingScheme::BranchingScheme(
283286
+ "_inflated_simplified.svg");
284287
}
285288

286-
Shape shape = convert_shape(simplified_shape, angle_range.first, mirror, direction);
287-
Shape shape_inflated = convert_shape(simplified_inflated_shape, angle_range.first, mirror, direction);
288-
shape = clean_shape(shape, true);
289-
shape_inflated = clean_shape(shape_inflated, true);
289+
const Shape& shape = convert_shape(simplified_shape, angle_range.first, mirror, direction);
290+
const Shape& shape_inflated = convert_shape(simplified_inflated_shape, angle_range.first, mirror, direction);
290291

291292
if (write_shapes) {
292293
simplified_inflated_shape.write_svg(
@@ -331,8 +332,7 @@ BranchingScheme::BranchingScheme(
331332
++hole_pos) {
332333
const Shape& simplified_shape = simplified_item_type.shapes[item_shape_pos].holes[hole_pos];
333334

334-
Shape shape = convert_shape(simplified_shape, angle_range.first, mirror, direction);
335-
shape = clean_shape(shape, true);
335+
const Shape& shape = convert_shape(simplified_shape, angle_range.first, mirror, direction);
336336

337337
// Update trapezoidation input.
338338
holes.push_back(shape);
@@ -358,8 +358,7 @@ BranchingScheme::BranchingScheme(
358358
++hole_pos) {
359359
const Shape& simplified_deflated_shape = simplified_item_type.shapes[item_shape_pos].holes_deflated[hole_pos];
360360

361-
Shape shape_deflated = convert_shape(simplified_deflated_shape, angle_range.first, mirror, direction);
362-
shape_deflated = clean_shape(shape_deflated, true);
361+
const Shape& shape_deflated = convert_shape(simplified_deflated_shape, angle_range.first, mirror, direction);
363362

364363
// Update trapezoidation input.
365364
holes_deflated.push_back(shape_deflated);

src/irregular/instance_builder.cpp

Lines changed: 96 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "shape/offset.hpp"
44
#include "shape/extract_borders.hpp"
5+
#include "shape/self_intersections_removal.hpp"
56

67
#include <sstream>
78

@@ -432,6 +433,49 @@ void InstanceBuilder::read(
432433
//////////////////////////////////// Build /////////////////////////////////////
433434
////////////////////////////////////////////////////////////////////////////////
434435

436+
namespace
437+
{
438+
439+
std::pair<Shape, std::vector<Shape>> process_shape_outer(
440+
const Shape& shape)
441+
{
442+
bool outer = true;
443+
Shape shape_tmp = shape::approximate_by_line_segments(shape, 1, outer);
444+
for (int i;; ++i) {
445+
if (i == 100) {
446+
throw std::runtime_error(
447+
"packingsolver::irregular::process_shape_outer: "
448+
"too many iterations.");
449+
}
450+
auto res = shape::clean_extreme_slopes(shape_tmp, outer);
451+
if (!res.first)
452+
break;
453+
shape_tmp = res.second;
454+
}
455+
return shape::remove_self_intersections(shape_tmp);
456+
}
457+
458+
std::vector<Shape> process_shape_inner(
459+
const Shape& shape)
460+
{
461+
bool outer = false;
462+
Shape shape_tmp = shape::approximate_by_line_segments(shape, 1, outer);
463+
for (int i = 0;; ++i) {
464+
if (i == 100) {
465+
throw std::runtime_error(
466+
"packingsolver::irregular::process_shape_inner: "
467+
"too many iterations.");
468+
}
469+
auto res = shape::clean_extreme_slopes(shape_tmp, outer);
470+
if (!res.first)
471+
break;
472+
shape_tmp = res.second;
473+
}
474+
return shape::extract_all_holes_from_self_intersecting_hole(shape_tmp);
475+
}
476+
477+
}
478+
435479
Instance InstanceBuilder::build()
436480
{
437481
// Compute scale value.
@@ -466,9 +510,17 @@ Instance InstanceBuilder::build()
466510
ItemShape& item_shape = item_type.shapes[shape_pos];
467511
if (!item_shape.shape_scaled.elements.empty())
468512
continue;
469-
item_shape.shape_scaled = instance_.parameters().scale_value * item_shape.shape_orig;
470-
for (const Shape& hole: item_shape.holes_orig)
471-
item_shape.holes_scaled.push_back(instance_.parameters().scale_value * hole);
513+
514+
auto res = process_shape_outer(instance_.parameters().scale_value * item_shape.shape_orig);
515+
item_shape.shape_scaled = res.first;
516+
for (const Shape& hole: res.second)
517+
item_shape.holes_scaled.push_back(hole);
518+
519+
for (const Shape& hole: item_shape.holes_orig) {
520+
auto res = process_shape_inner(instance_.parameters().scale_value * hole);
521+
for (const Shape& hole: res)
522+
item_shape.holes_scaled.push_back(hole);
523+
}
472524
}
473525

474526
// Compute inflated shapes.
@@ -478,18 +530,22 @@ Instance InstanceBuilder::build()
478530
ItemShape& item_shape = item_type.shapes[shape_pos];
479531
if (!item_shape.shape_inflated.elements.empty())
480532
continue;
481-
auto inflated_item_shape = inflate(
533+
auto shape_tmp_0 = inflate(
482534
item_shape.shape_scaled,
483-
instance_.parameters().scale_value * instance_.parameters().item_item_minimum_spacing);
484-
item_shape.shape_inflated = inflated_item_shape.first;
485-
for (const Shape& hole: inflated_item_shape.second)
535+
instance_.parameters().scale_value * instance_.parameters().item_item_minimum_spacing,
536+
false);
537+
auto res = process_shape_outer(shape_tmp_0.first);
538+
item_shape.shape_inflated = res.first;
539+
for (const Shape& hole: res.second)
486540
item_shape.holes_deflated.push_back(hole);
487541

488542
for (const Shape& hole: item_shape.holes_scaled) {
489-
auto deflated_hole = deflate(
543+
auto shape_tmp_0 = deflate(
490544
hole,
491-
instance_.parameters().scale_value * instance_.parameters().item_item_minimum_spacing);
492-
for (const Shape& hole: deflated_hole)
545+
instance_.parameters().scale_value * instance_.parameters().item_item_minimum_spacing,
546+
false);
547+
auto res = process_shape_inner(shape_tmp_0.front());
548+
for (const Shape& hole: res)
493549
item_shape.holes_deflated.push_back(hole);
494550
}
495551
}
@@ -545,9 +601,16 @@ Instance InstanceBuilder::build()
545601
if (bin_type.shape_scaled.elements.empty()) {
546602
bin_type.shape_scaled = instance_.parameters().scale_value * bin_type.shape_orig;
547603
for (Defect& defect: bin_type.defects) {
548-
defect.shape_scaled = instance_.parameters().scale_value * defect.shape_orig;
549-
for (const Shape& hole: defect.holes_orig)
550-
defect.holes_scaled.push_back(instance_.parameters().scale_value * hole);
604+
auto res = process_shape_outer(instance_.parameters().scale_value * defect.shape_orig);
605+
defect.shape_scaled = res.first;
606+
for (const Shape& hole: res.second)
607+
defect.holes_scaled.push_back(hole);
608+
609+
for (const Shape& hole: defect.holes_orig) {
610+
auto res = process_shape_inner(instance_.parameters().scale_value * hole);
611+
for (const Shape& hole: res)
612+
defect.holes_scaled.push_back(hole);
613+
}
551614
}
552615
}
553616

@@ -556,34 +619,42 @@ Instance InstanceBuilder::build()
556619
if (!defect.shape_inflated.elements.empty())
557620
continue;
558621

559-
auto inflated_defect_shape = inflate(
622+
auto shape_tmp_0 = inflate(
560623
defect.shape_scaled,
561-
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing);
562-
defect.shape_inflated = inflated_defect_shape.first;
563-
for (const Shape& hole: inflated_defect_shape.second)
624+
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing,
625+
false);
626+
auto res = process_shape_outer(shape_tmp_0.first);
627+
defect.shape_inflated = res.first;
628+
for (const Shape& hole: res.second)
564629
defect.holes_deflated.push_back(hole);
565630

566631
for (const Shape& hole: defect.holes_scaled) {
567-
auto deflated_hole = deflate(
632+
auto shape_tmp_0 = deflate(
568633
hole,
569-
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing);
570-
for (const Shape& hole: deflated_hole)
634+
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing,
635+
false);
636+
auto res = process_shape_inner(shape_tmp_0.front());
637+
for (const Shape& hole: res)
571638
defect.holes_deflated.push_back(hole);
572639
}
573640
}
574641

575642
// Compute inflated borders.
576643
if (bin_type.borders.empty()) {
577644
for (const Shape& shape_border: extract_borders(bin_type.shape_scaled)) {
578-
auto inflated_shape_border = inflate(
579-
shape_border,
580-
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing);
581645
Defect border;
582646
border.type = -2;
583647
border.shape_scaled = shape_border;
584-
border.shape_inflated = inflated_shape_border.first;
585-
for (const Shape& hole: inflated_shape_border.second)
648+
649+
auto shape_tmp_0 = inflate(
650+
shape_border,
651+
instance_.parameters().scale_value * instance_.parameters().item_bin_minimum_spacing,
652+
false);
653+
auto res = process_shape_outer(shape_tmp_0.first);
654+
border.shape_inflated = res.first;
655+
for (const Shape& hole: res.second)
586656
border.holes_deflated.push_back(hole);
657+
587658
bin_type.borders.push_back(border);
588659
}
589660
}

src/irregular/shape_simplification.cpp

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,8 @@ SimplifiedInstance irregular::shape_simplification(
8686
total_bin_area -= bin_type.copies * border.shape_scaled.compute_area();
8787

8888
bool outer = true;
89-
Shape shape = shape::approximate_by_line_segments(border.shape_inflated, 1, outer);
90-
shape = shape::clean_shape(shape, outer);
9189
SimplifyInputShape simplify_input_shape;
92-
simplify_input_shape.shape = shape;
90+
simplify_input_shape.shape = border.shape_inflated;
9391
simplify_input_shape.copies = bin_type.copies;
9492
simplify_input_shape.outer = outer;
9593
simplify_inflated_bin_types_input.push_back(simplify_input_shape);
@@ -109,10 +107,8 @@ SimplifiedInstance irregular::shape_simplification(
109107
total_bin_area -= bin_type.copies * defect.shape_scaled.compute_area();
110108

111109
bool outer = true;
112-
Shape shape = shape::approximate_by_line_segments(defect.shape_inflated, 1, outer);
113-
shape = shape::clean_shape(shape, outer);
114110
SimplifyInputShape simplify_input_shape;
115-
simplify_input_shape.shape = shape;
111+
simplify_input_shape.shape = defect.shape_inflated;
116112
simplify_input_shape.copies = bin_type.copies;
117113
simplify_input_shape.outer = outer;
118114
simplify_inflated_bin_types_input.push_back(simplify_input_shape);
@@ -142,10 +138,8 @@ SimplifiedInstance irregular::shape_simplification(
142138
continue;
143139

144140
bool outer = false;
145-
Shape shape = shape::approximate_by_line_segments(hole_deflated, 1, outer);
146-
shape = shape::clean_shape(shape, outer);
147141
SimplifyInputShape simplify_input_shape;
148-
simplify_input_shape.shape = shape;
142+
simplify_input_shape.shape = hole_deflated;
149143
simplify_input_shape.copies = bin_type.copies;
150144
simplify_input_shape.outer = outer;
151145
simplify_inflated_bin_types_input.push_back(simplify_input_shape);
@@ -176,9 +170,8 @@ SimplifiedInstance irregular::shape_simplification(
176170

177171
{
178172
bool outer = true;
179-
Shape shape = shape::clean_shape(item_shape.shape_scaled, outer);
180173
SimplifyInputShape simplify_input_shape;
181-
simplify_input_shape.shape = shape;
174+
simplify_input_shape.shape = item_shape.shape_scaled;
182175
simplify_input_shape.copies = item_type.copies;
183176
simplify_input_shape.outer = outer;
184177
simplify_item_types_input.push_back(simplify_input_shape);
@@ -191,18 +184,8 @@ SimplifiedInstance irregular::shape_simplification(
191184
}
192185
{
193186
bool outer = true;
194-
Shape shape = shape::approximate_by_line_segments(item_shape.shape_inflated, 1, outer);
195-
//shape.write_svg(
196-
// "item_type_" + std::to_string(item_type_id)
197-
// + "_shape_pos_" + std::to_string(item_shape_pos)
198-
// + "_inflated_approximated.svg");
199-
shape = shape::clean_shape(shape, outer);
200-
//shape.write_svg(
201-
// "item_type_" + std::to_string(item_type_id)
202-
// + "_shape_pos_" + std::to_string(item_shape_pos)
203-
// + "_inflated_approximated_cleaned.svg");
204187
SimplifyInputShape simplify_input_shape;
205-
simplify_input_shape.shape = shape;
188+
simplify_input_shape.shape = item_shape.shape_inflated;
206189
simplify_input_shape.copies = item_type.copies;
207190
simplify_input_shape.outer = outer;
208191
simplify_inflated_item_types_input.push_back(simplify_input_shape);
@@ -225,9 +208,8 @@ SimplifiedInstance irregular::shape_simplification(
225208
total_item_area -= item_type.copies * hole.compute_area();
226209

227210
bool outer = false;
228-
Shape shape = shape::clean_shape(hole, outer);
229211
SimplifyInputShape simplify_input_shape;
230-
simplify_input_shape.shape = shape;
212+
simplify_input_shape.shape = hole;
231213
simplify_input_shape.copies = item_type.copies;
232214
simplify_input_shape.outer = outer;
233215
simplify_item_types_input.push_back(simplify_input_shape);
@@ -249,10 +231,8 @@ SimplifiedInstance irregular::shape_simplification(
249231
continue;
250232

251233
bool outer = false;
252-
Shape shape = shape::approximate_by_line_segments(hole_deflated, 1, outer);
253-
shape = shape::clean_shape(shape, outer);
254234
SimplifyInputShape simplify_input_shape;
255-
simplify_input_shape.shape = shape;
235+
simplify_input_shape.shape = hole_deflated;
256236
simplify_input_shape.copies = item_type.copies;
257237
simplify_input_shape.outer = outer;
258238
simplify_inflated_item_types_input.push_back(simplify_input_shape);

0 commit comments

Comments
 (0)