Skip to content

Commit 87e77e4

Browse files
committed
add shape level inflate method
1 parent dba8141 commit 87e77e4

File tree

5 files changed

+198
-22
lines changed

5 files changed

+198
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ checker/*
77
OLD
88
instances/*
99
output/*
10+
build/*
1011
data/rectangle/imahori2010
1112
data/rectangle_raw/imahori2010
1213
data/irregular/cgshop2024

src/irregular/branching_scheme.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,9 @@ BranchingScheme::BranchingScheme(
757757

758758
void BranchingScheme::compute_inflated_trapezoid_sets()
759759
{
760+
// initialize the inflated trapezoid sets
761+
trapezoid_sets_inflated_.clear();
762+
760763
for (Direction direction: {
761764
Direction::LeftToRightThenBottomToTop,
762765
Direction::LeftToRightThenTopToBottom,
@@ -774,20 +777,53 @@ void BranchingScheme::compute_inflated_trapezoid_sets()
774777
const TrapezoidSet& trapezoid_set = trapezoid_sets_[(int)direction][trapezoid_set_id];
775778
trapezoid_sets_inflated_.back().push_back({});
776779

777-
// Loop through rectangles of the rectangle set.
780+
// get the original item type
781+
ItemTypeId item_type_id = trapezoid_set.item_type_id;
782+
const ItemType& item_type = instance().item_type(item_type_id);
783+
784+
// process the item shape
778785
for (ItemShapePos item_shape_pos = 0;
779786
item_shape_pos < (ItemShapePos)trapezoid_set.shapes.size();
780787
++item_shape_pos) {
781-
const auto& item_shape_trapezoids = trapezoid_set.shapes[item_shape_pos];
782788
trapezoid_sets_inflated_.back().back().push_back({});
783-
784-
for (TrapezoidPos item_shape_trapezoid_pos = 0;
785-
item_shape_trapezoid_pos < (TrapezoidPos)item_shape_trapezoids.size();
786-
++item_shape_trapezoid_pos) {
787-
const auto& item_shape_trapezoid = item_shape_trapezoids[item_shape_trapezoid_pos];
788-
trapezoid_sets_inflated_.back().back().back().push_back(
789-
item_shape_trapezoid.inflate(instance().parameters().item_item_minimum_spacing));
789+
790+
// get the original shape
791+
const ItemShape& item_shape = item_type.shapes[item_shape_pos];
792+
793+
// adjust the shape according to the direction
794+
Shape adjusted_shape = item_shape.shape;
795+
if (direction == Direction::LeftToRightThenTopToBottom) {
796+
adjusted_shape = adjusted_shape.axial_symmetry_x_axis();
797+
} else if (direction == Direction::RightToLeftThenBottomToTop) {
798+
adjusted_shape = adjusted_shape.axial_symmetry_y_axis();
799+
} else if (direction == Direction::RightToLeftThenTopToBottom) {
800+
adjusted_shape = adjusted_shape.axial_symmetry_x_axis();
801+
adjusted_shape = adjusted_shape.axial_symmetry_y_axis();
802+
} else if (direction == Direction::BottomToTopThenLeftToRight) {
803+
adjusted_shape = adjusted_shape.axial_symmetry_identity_line();
804+
} else if (direction == Direction::BottomToTopThenRightToLeft) {
805+
adjusted_shape = adjusted_shape.axial_symmetry_identity_line();
806+
adjusted_shape = adjusted_shape.axial_symmetry_x_axis();
807+
} else if (direction == Direction::TopToBottomThenLeftToRight) {
808+
adjusted_shape = adjusted_shape.axial_symmetry_identity_line();
809+
adjusted_shape = adjusted_shape.axial_symmetry_y_axis();
810+
} else if (direction == Direction::TopToBottomThenRightToLeft) {
811+
adjusted_shape = adjusted_shape.axial_symmetry_identity_line();
812+
adjusted_shape = adjusted_shape.axial_symmetry_y_axis();
813+
adjusted_shape = adjusted_shape.axial_symmetry_x_axis();
790814
}
815+
816+
// clean the shape
817+
Shape cleaned_shape = clean_shape(adjusted_shape);
818+
819+
// inflate the shape
820+
Shape inflated_shape = inflate(cleaned_shape, instance().parameters().item_item_minimum_spacing);
821+
822+
// then perform the trapezoidation on the inflated shape
823+
std::vector<GeneralizedTrapezoid> inflated_trapezoids = trapezoidation(inflated_shape);
824+
825+
// store the trapezoidation result
826+
trapezoid_sets_inflated_.back().back().back() = inflated_trapezoids;
791827
}
792828
}
793829
}

src/irregular/shape.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,3 +368,101 @@ std::vector<Shape> packingsolver::irregular::borders(
368368

369369
return res;
370370
}
371+
372+
Shape irregular::inflate(
373+
const Shape& shape,
374+
LengthDbl value)
375+
{
376+
Shape inflated_shape;
377+
inflated_shape.elements.reserve(shape.elements.size());
378+
379+
for (ElementPos element_pos = 0;
380+
element_pos < (ElementPos)shape.elements.size();
381+
++element_pos) {
382+
const ShapeElement& element = shape.elements[element_pos];
383+
ElementPos element_next_pos = (element_pos + 1) % shape.elements.size();
384+
const ShapeElement& element_next = shape.elements[element_next_pos];
385+
386+
// calculate the normal vector of the current edge
387+
LengthDbl dx = element.end.x - element.start.x;
388+
LengthDbl dy = element.end.y - element.start.y;
389+
LengthDbl length = std::sqrt(dx * dx + dy * dy);
390+
LengthDbl nx = dy / length;
391+
LengthDbl ny = -dx / length;
392+
393+
// calculate the normal vector of the next edge
394+
LengthDbl dx_next = element_next.end.x - element_next.start.x;
395+
LengthDbl dy_next = element_next.end.y - element_next.start.y;
396+
LengthDbl length_next = std::sqrt(dx_next * dx_next + dy_next * dy_next);
397+
LengthDbl nx_next = dy_next / length_next;
398+
LengthDbl ny_next = -dx_next / length_next;
399+
400+
// calculate the average normal vector of the vertex
401+
LengthDbl nx_avg = (nx + nx_next) / 2;
402+
LengthDbl ny_avg = (ny + ny_next) / 2;
403+
LengthDbl length_avg = std::sqrt(nx_avg * nx_avg + ny_avg * ny_avg);
404+
nx_avg /= length_avg;
405+
ny_avg /= length_avg;
406+
407+
// create a new edge
408+
ShapeElement new_element;
409+
new_element.type = element.type;
410+
new_element.start = Point{
411+
element.start.x + nx * value,
412+
element.start.y + ny * value
413+
};
414+
new_element.end = Point{
415+
element.end.x + nx * value,
416+
element.end.y + ny * value
417+
};
418+
419+
// add the arc at the vertex
420+
if (element_pos > 0) {
421+
ShapeElement arc_element;
422+
arc_element.type = ShapeElementType::CircularArc;
423+
arc_element.start = Point{
424+
element.start.x + nx_avg * value,
425+
element.start.y + ny_avg * value
426+
};
427+
arc_element.end = new_element.start;
428+
inflated_shape.elements.push_back(arc_element);
429+
}
430+
431+
inflated_shape.elements.push_back(new_element);
432+
}
433+
434+
// add the arc at the last vertex
435+
if (!shape.elements.empty()) {
436+
const ShapeElement& first_element = shape.elements.front();
437+
const ShapeElement& last_element = shape.elements.back();
438+
439+
LengthDbl dx_first = first_element.end.x - first_element.start.x;
440+
LengthDbl dy_first = first_element.end.y - first_element.start.y;
441+
LengthDbl length_first = std::sqrt(dx_first * dx_first + dy_first * dy_first);
442+
LengthDbl nx_first = dy_first / length_first;
443+
LengthDbl ny_first = -dx_first / length_first;
444+
445+
LengthDbl dx_last = last_element.end.x - last_element.start.x;
446+
LengthDbl dy_last = last_element.end.y - last_element.start.y;
447+
LengthDbl length_last = std::sqrt(dx_last * dx_last + dy_last * dy_last);
448+
LengthDbl nx_last = dy_last / length_last;
449+
LengthDbl ny_last = -dx_last / length_last;
450+
451+
LengthDbl nx_avg = (nx_first + nx_last) / 2;
452+
LengthDbl ny_avg = (ny_first + ny_last) / 2;
453+
LengthDbl length_avg = std::sqrt(nx_avg * nx_avg + ny_avg * ny_avg);
454+
nx_avg /= length_avg;
455+
ny_avg /= length_avg;
456+
457+
ShapeElement arc_element;
458+
arc_element.type = ShapeElementType::CircularArc;
459+
arc_element.start = Point{
460+
first_element.start.x + nx_avg * value,
461+
first_element.start.y + ny_avg * value
462+
};
463+
arc_element.end = inflated_shape.elements.front().start;
464+
inflated_shape.elements.push_back(arc_element);
465+
}
466+
467+
return inflated_shape;
468+
}

src/irregular/shape.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,9 @@ bool operator==(
3030
const Shape& shape_1,
3131
const Shape& shape_2);
3232

33+
Shape inflate(
34+
const Shape& shape,
35+
LengthDbl value);
36+
3337
}
3438
}

src/irregular/trapezoid.hpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -513,30 +513,67 @@ class GeneralizedTrapezoid
513513
GeneralizedTrapezoid inflate(
514514
LengthDbl value) const
515515
{
516+
// calculate the normal vector
516517
LengthDbl l_left = std::sqrt(
517518
(x_top_left() - x_bottom_left()) * (x_top_left() - x_bottom_left())
518519
+ height() * height());
519-
LengthDbl xbl = x_left(y_bottom() - value) - value * l_left / height();
520-
LengthDbl xtl = x_left(y_top() + value) - value * l_left / height();
521-
//std::cout << "l_left " << l_left << std::endl;
522-
//std::cout << "cos_left " << cos_left << std::endl;
523-
//std::cout << "xbl_ " << xbl_ << " -> " << xbl << std::endl;
524520
LengthDbl l_right = std::sqrt(
525521
(x_top_right() - x_bottom_right()) * (x_top_right() - x_bottom_right())
526522
+ height() * height());
527-
LengthDbl xbr = x_right(y_bottom() - value) + value * l_right / height();
528-
LengthDbl xtr = x_right(y_top() + value) + value * l_right / height();
523+
524+
// calculate the unit normal vector (reference the implementation of Clipper2)
525+
LengthDbl dx_left = x_top_left() - x_bottom_left();
526+
LengthDbl dy_left = height();
527+
LengthDbl inverse_hypot_left = 1.0 / l_left;
528+
LengthDbl nx_left = dy_left * inverse_hypot_left;
529+
LengthDbl ny_left = -dx_left * inverse_hypot_left;
530+
531+
LengthDbl dx_right = x_top_right() - x_bottom_right();
532+
LengthDbl dy_right = height();
533+
LengthDbl inverse_hypot_right = 1.0 / l_right;
534+
LengthDbl nx_right = -dy_right * inverse_hypot_right;
535+
LengthDbl ny_right = dx_right * inverse_hypot_right;
536+
537+
// calculate the new vertex positions
538+
LengthDbl xbl = x_bottom_left() + value * nx_left;
539+
LengthDbl ybl = y_bottom() + value * ny_left;
540+
LengthDbl xtl = x_top_left() + value * nx_left;
541+
LengthDbl ytl = y_top() + value * ny_left;
542+
LengthDbl xbr = x_bottom_right() + value * nx_right;
543+
LengthDbl ybr = y_bottom() + value * ny_right;
544+
LengthDbl xtr = x_top_right() + value * nx_right;
545+
LengthDbl ytr = y_top() + value * ny_right;
546+
547+
// calculate the new trapezoid parameters
548+
LengthDbl yb = std::min(ybl, ybr);
549+
LengthDbl yt = std::max(ytl, ytr);
550+
551+
// calculate the new slopes
552+
double a_left_new = (xtl - xbl) / (ytl - ybl);
553+
double a_right_new = (xtr - xbr) / (ytr - ybr);
554+
555+
// calculate the new x coordinates
556+
LengthDbl xbl_new = xbl + (yb - ybl) * a_left_new;
557+
LengthDbl xbr_new = xbr + (yb - ybr) * a_right_new;
558+
LengthDbl xtl_new = xtl + (yt - ytl) * a_left_new;
559+
LengthDbl xtr_new = xtr + (yt - ytr) * a_right_new;
560+
561+
// keep the original output
562+
//std::cout << "l_left " << l_left << std::endl;
563+
//std::cout << "cos_left " << cos_left << std::endl;
564+
//std::cout << "xbl_ " << xbl_ << " -> " << xbl << std::endl;
529565
//std::cout << "a_right " << a_right() << std::endl;
530566
//std::cout << "l_right " << l_right << std::endl;
531567
//std::cout << "cos_right " << cos_right << std::endl;
532568
//std::cout << " xbr " << xbr_ << " -> " << xbr << std::endl;
569+
533570
return GeneralizedTrapezoid(
534-
y_bottom() - value,
535-
y_top() + value,
536-
xbl,
537-
xbr,
538-
xtl,
539-
xtr);
571+
yb,
572+
yt,
573+
xbl_new,
574+
xbr_new,
575+
xtl_new,
576+
xtr_new);
540577
}
541578

542579
GeneralizedTrapezoid axial_symmetry_x_axis() const

0 commit comments

Comments
 (0)