Skip to content

Commit

Permalink
Extract shape borders function
Browse files Browse the repository at this point in the history
  • Loading branch information
fontanf committed Oct 23, 2024
1 parent 0b35e2f commit c47a550
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 182 deletions.
2 changes: 2 additions & 0 deletions include/packingsolver/irregular/instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ struct Shape
const std::string& file_path) const;
};

Shape build_polygon_shape(const std::vector<Point>& points);

double compute_svg_factor(double width);

std::string to_svg(
Expand Down
164 changes: 22 additions & 142 deletions src/irregular/branching_scheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,152 +155,32 @@ BranchingScheme::BranchingScheme(
BranchingSchemeBinType& bb_bin_type_x = bin_types_[(int)Direction::LeftToRightThenBottomToTop][bin_type_id];
BranchingSchemeBinType& bb_bin_type_y = bin_types_[(int)Direction::BottomToTopThenLeftToRight][bin_type_id];

// Bin borders.
Shape shape_border;
ElementPos element_0_pos = 0;
for (ElementPos element_pos = 0;
element_pos < bin_type.shape.elements.size();
++element_pos) {
const ShapeElement& shape_element = bin_type.shape.elements[element_pos];
if (shape_element.start.x == bin_type.x_min) {
element_0_pos = element_pos;
break;
}
}
// 0: left; 1: bottom; 2: right; 3: top.
const ShapeElement& element_0 = bin_type.shape.elements[element_0_pos];
int start_border = (element_0.start.y == bin_type.y_min)? 1: 0;
LengthDbl start_coordinate = element_0.start.y;
for (ElementPos element_pos = 0;
element_pos < bin_type.shape.elements.size();
++element_pos) {
const ShapeElement& element = bin_type.shape.elements[(element_0_pos + element_pos) % bin_type.shape.elements.size()];
//std::cout << "element_pos " << ((element_0_pos + element_pos) % bin_type.shape.elements.size()) << " / " << bin_type.shape.elements.size() << ": " << element.to_string() << std::endl;
shape_border.elements.push_back(element);
bool close = false;
if (start_border == 0) {
if (equal(element.end.x, bin_type.x_min)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 0;
} else if (equal(element.end.y, bin_type.y_min)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {bin_type.x_min, bin_type.y_min};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 1;
}
} else if (start_border == 1) {
if (equal(element.end.y, bin_type.y_min)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 1;
} else if (equal(element.end.x, bin_type.x_max)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {bin_type.x_max, bin_type.y_min};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 2;
}
} else if (start_border == 2) {
if (equal(element.end.x, bin_type.x_max)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 2;
} else if (equal(element.end.y, bin_type.y_max)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {bin_type.x_max, bin_type.y_max};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 3;
}
} else if (start_border == 3) {
if (equal(element.end.y, bin_type.y_max)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 3;
} else if (equal(element.end.x, bin_type.x_min)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {bin_type.x_min, bin_type.y_max};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 0;
}
}
// New shape.
if (close) {
Shape reversed_shape = shape_border.reverse();
{
Shape cleaned_shape = clean_shape(reversed_shape);
//std::cout << cleaned_shape.to_string(0) << std::endl;
if (cleaned_shape.elements.size() > 2) {
auto trapezoids = polygon_trapezoidation(cleaned_shape);
for (const GeneralizedTrapezoid& trapezoid: trapezoids) {
UncoveredTrapezoid defect(
-1,
trapezoid.clean().inflate(instance.parameters().item_bin_minimum_spacing));
bb_bin_type_x.defects.push_back(defect);
}
for (const Shape& shape_border: borders(bin_type.shape)) {
{
Shape cleaned_shape = clean_shape(shape_border);
//std::cout << cleaned_shape.to_string(0) << std::endl;
if (cleaned_shape.elements.size() > 2) {
auto trapezoids = polygon_trapezoidation(cleaned_shape);
for (const GeneralizedTrapezoid& trapezoid: trapezoids) {
UncoveredTrapezoid defect(
-1,
trapezoid.clean().inflate(instance.parameters().item_bin_minimum_spacing));
bb_bin_type_x.defects.push_back(defect);
}
}
{
Shape sym_shape = reversed_shape.axial_symmetry_identity_line();
Shape cleaned_shape = clean_shape(sym_shape);
if (cleaned_shape.elements.size() > 2) {
auto trapezoids = polygon_trapezoidation(cleaned_shape);
for (const GeneralizedTrapezoid& trapezoid: trapezoids) {
UncoveredTrapezoid defect(
-1,
trapezoid.clean().inflate(instance.parameters().item_bin_minimum_spacing));
bb_bin_type_y.defects.push_back(defect);
}
}
{
Shape sym_shape = shape_border.axial_symmetry_identity_line();
Shape cleaned_shape = clean_shape(sym_shape);
if (cleaned_shape.elements.size() > 2) {
auto trapezoids = polygon_trapezoidation(cleaned_shape);
for (const GeneralizedTrapezoid& trapezoid: trapezoids) {
UncoveredTrapezoid defect(
-1,
trapezoid.clean().inflate(instance.parameters().item_bin_minimum_spacing));
bb_bin_type_y.defects.push_back(defect);
}
}
shape_border.elements.clear();
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/irregular/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,22 @@ void Shape::write_svg(
file << "</svg>" << std::endl;
}

Shape packingsolver::irregular::build_polygon_shape(
const std::vector<Point>& points)
{
Shape shape;
ElementPos pos_prev = points.size() - 1;
for (ElementPos pos = 0; pos < (ElementPos)points.size(); ++pos) {
ShapeElement element;
element.type = ShapeElementType::LineSegment;
element.start = points[pos_prev];
element.end = points[pos];
shape.elements.push_back(element);
pos_prev = pos;
}
return shape;
}

double irregular::compute_svg_factor(
double width)
{
Expand Down
133 changes: 133 additions & 0 deletions src/irregular/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,136 @@ Shape irregular::clean_shape(

return shape_new;
}

std::vector<Shape> packingsolver::irregular::borders(
const Shape& shape)
{
std::vector<Shape> res;

auto mm = shape.compute_min_max();

Shape shape_border;
ElementPos element_0_pos = 0;
for (ElementPos element_pos = 0;
element_pos < shape.elements.size();
++element_pos) {
const ShapeElement& shape_element = shape.elements[element_pos];
if (shape_element.start.x == mm.first.x) {
element_0_pos = element_pos;
break;
}
}
// 0: left; 1: bottom; 2: right; 3: top.
const ShapeElement& element_0 = shape.elements[element_0_pos];
int start_border = (element_0.start.y == mm.first.y)? 1: 0;
LengthDbl start_coordinate = element_0.start.y;
for (ElementPos element_pos = 0;
element_pos < shape.elements.size();
++element_pos) {
const ShapeElement& element = shape.elements[(element_0_pos + element_pos) % shape.elements.size()];
//std::cout << "element_pos " << ((element_0_pos + element_pos) % bin_type.shape.elements.size()) << " / " << bin_type.shape.elements.size() << ": " << element.to_string() << std::endl;
shape_border.elements.push_back(element);
bool close = false;
if (start_border == 0) {
if (equal(element.end.x, mm.first.x)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 0;
} else if (equal(element.end.y, mm.first.y)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {mm.first.x, mm.first.y};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 1;
}
} else if (start_border == 1) {
if (equal(element.end.y, mm.first.y)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 1;
} else if (equal(element.end.x, mm.second.x)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {mm.second.x, mm.first.y};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 2;
}
} else if (start_border == 2) {
if (equal(element.end.x, mm.second.x)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 2;
} else if (equal(element.end.y, mm.second.y)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {mm.second.x, mm.second.y};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 3;
}
} else if (start_border == 3) {
if (equal(element.end.y, mm.second.y)) {
ShapeElement new_element;
new_element.type = ShapeElementType::LineSegment;
new_element.start = element.end;
new_element.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element);
close = true;
start_border = 3;
} else if (equal(element.end.x, mm.first.x)) {
ShapeElement new_element_1;
new_element_1.type = ShapeElementType::LineSegment;
new_element_1.start = element.end;
new_element_1.end = {mm.first.x, mm.second.y};
shape_border.elements.push_back(new_element_1);
ShapeElement new_element_2;
new_element_2.type = ShapeElementType::LineSegment;
new_element_2.start = new_element_1.end;
new_element_2.end = shape_border.elements[0].start;
shape_border.elements.push_back(new_element_2);
close = true;
start_border = 0;
}
}
// New shape.
if (close) {
if (shape_border.elements.size() >= 3)
res.push_back(shape_border.reverse());
shape_border.elements.clear();
}
}

return res;
}
3 changes: 3 additions & 0 deletions src/irregular/shape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ std::pair<bool, Shape> equalize_close_y(
Shape clean_shape(
const Shape& shape);

std::vector<Shape> borders(
const Shape& shape);

}
}
20 changes: 0 additions & 20 deletions test/irregular/polygon_convex_hull_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,6 @@
using namespace packingsolver;
using namespace packingsolver::irregular;

namespace
{

Shape build_polygon_shape(const std::vector<Point>& points)
{
Shape shape;
ElementPos pos_prev = points.size() - 1;
for (ElementPos pos = 0; pos < (ElementPos)points.size(); ++pos) {
ShapeElement element;
element.type = ShapeElementType::LineSegment;
element.start = points[pos_prev];
element.end = points[pos];
shape.elements.push_back(element);
pos_prev = pos;
}
return shape;
}

}

TEST(IrregularPolygonConvexHull, Triangle)
{
Shape shape = build_polygon_shape({{0, 0}, {3, 0}, {1, 3}});
Expand Down
Loading

0 comments on commit c47a550

Please sign in to comment.