Skip to content
Merged

Dev #188

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/packingsolver/irregular/shape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ struct ShapeElement

ShapeElement axial_symmetry_y_axis() const;

/** Get the middle point on the element. */
Point middle() const;

/** Compute the smallest and greatest x and y of the shape. */
std::pair<Point, Point> min_max() const;

std::string to_string() const;

nlohmann::json to_json() const;
Expand Down
126 changes: 80 additions & 46 deletions src/irregular/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,77 @@ Angle irregular::angle_radian(
return a;
}

Point ShapeElement::middle() const
{
switch (type) {
case ShapeElementType::LineSegment: {
Point point;
point.x = (this->start.x + this->end.x) / 2;
point.y = (this->start.y + this->end.y) / 2;
return point;
} case ShapeElementType::CircularArc: {
Angle angle = (this->anticlockwise)?
angle_radian(
this->start - this->center,
this->end - this->center):
angle_radian(
this->end - this->center,
this->start - this->center);
return this->start.rotate_radians(this->center, angle);
}
}
return {0, 0};
}

std::pair<Point, Point> ShapeElement::min_max() const
{
LengthDbl x_min = (std::min)(this->start.x, this->end.x);
LengthDbl x_max = (std::max)(this->start.x, this->end.x);
LengthDbl y_min = (std::min)(this->start.y, this->end.y);
LengthDbl y_max = (std::max)(this->start.y, this->end.y);

if (this->type == ShapeElementType::CircularArc) {
LengthDbl radius = distance(this->center, this->start);
Angle starting_angle = irregular::angle_radian(this->start - this->center);
Angle ending_angle = irregular::angle_radian(this->end - this->center);
if (!this->anticlockwise)
std::swap(starting_angle, ending_angle);
//std::cout << "starting_angle " << starting_angle << " ending_angle " << ending_angle << std::endl;
if (starting_angle <= ending_angle) {
if (starting_angle <= M_PI
&& ending_angle >= M_PI) {
x_min = std::min(x_min, this->center.x - radius);
}
if (starting_angle == 0)
x_max = std::max(x_max, this->center.x + radius);
if (starting_angle <= 3 * M_PI / 2
&& ending_angle >= 3 * M_PI / 2 ) {
y_min = std::min(y_min, this->center.y - radius);
}
if (starting_angle <= M_PI / 2
&& ending_angle >= M_PI / 2) {
y_max = std::max(y_max, this->center.y + radius);
}
} else { // starting_angle > ending_angle
if (starting_angle <= M_PI
|| ending_angle >= M_PI) {
x_min = std::min(x_min, this->center.x - radius);
}
x_max = std::max(x_max, this->center.x + radius);
if (starting_angle <= 3 * M_PI / 2
|| ending_angle >= 3 * M_PI / 2) {
y_min = std::min(y_min, this->center.y - radius);
}
if (starting_angle <= M_PI / 2
|| ending_angle >= M_PI / 2) {
y_max = std::max(y_max, this->center.y + radius);
}
}
}

return {{x_min, y_min}, {x_max, y_max}};
}

int irregular::counter_clockwise(
const Point& point_1,
const Point& point_2,
Expand Down Expand Up @@ -587,52 +658,15 @@ std::pair<Point, Point> Shape::compute_min_max(
LengthDbl x_max = -std::numeric_limits<LengthDbl>::infinity();
LengthDbl y_min = std::numeric_limits<LengthDbl>::infinity();
LengthDbl y_max = -std::numeric_limits<LengthDbl>::infinity();
for (const ShapeElement& element: elements) {
Point point = (!mirror)?
element.start.rotate(angle):
element.start.axial_symmetry_y_axis().rotate(angle);
x_min = std::min(x_min, point.x);
x_max = std::max(x_max, point.x);
y_min = std::min(y_min, point.y);
y_max = std::max(y_max, point.y);

if (element.type == ShapeElementType::CircularArc) {
LengthDbl radius = distance(element.center, element.start);
Angle starting_angle = irregular::angle_radian(element.start - element.center);
Angle ending_angle = irregular::angle_radian(element.end - element.center);
if (!element.anticlockwise)
std::swap(starting_angle, ending_angle);
if (starting_angle <= ending_angle) {
if (starting_angle <= M_PI
&& M_PI <= ending_angle) {
x_min = std::min(x_min, element.center.x - radius);
}
if (starting_angle == 0)
x_max = std::max(x_max, element.center.x + radius);
if (starting_angle <= 3 * M_PI / 2
&& 3 * M_PI / 2 <= ending_angle) {
y_min = std::min(y_min, element.center.y - radius);
}
if (starting_angle <= M_PI / 2
&& M_PI / 2 <= ending_angle) {
y_max = std::max(y_max, element.center.y + radius);
}
} else { // starting_angle > ending_angle
if (starting_angle <= M_PI
|| ending_angle <= M_PI) {
x_min = std::min(x_min, element.center.x - radius);
}
x_max = std::max(x_max, element.center.x + radius);
if (starting_angle <= 3 * M_PI / 4
|| ending_angle <= 3 * M_PI / 4) {
y_min = std::min(y_min, element.center.y - radius);
}
if (starting_angle <= M_PI / 2
|| ending_angle <= M_PI / 2) {
y_max = std::max(y_max, element.center.y + radius);
}
}
}
for (const ShapeElement& element_orig: elements) {
ShapeElement element = (!mirror)?
element_orig.rotate(angle):
element_orig.axial_symmetry_y_axis().rotate(angle);
auto mm = element.min_max();
x_min = std::min(x_min, mm.first.x);
x_max = std::max(x_max, mm.second.x);
y_min = std::min(y_min, mm.first.y);
y_max = std::max(y_max, mm.second.y);
}
return {{x_min, y_min}, {x_max, y_max}};
}
Expand Down
29 changes: 29 additions & 0 deletions src/irregular/shape_element_intersections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,32 @@ std::vector<Point> irregular::compute_intersections(
throw std::invalid_argument("irregular::compute_intersections: Invalid element types");
return {};
}

bool irregular::intersect(
const Shape& shape_1,
const Shape& shape_2,
bool strict)
{
for (const ShapeElement& element_1: shape_1.elements) {
for (const ShapeElement& element_2: shape_2.elements) {
auto intersections = compute_intersections(
element_1,
element_2,
strict);
if (!intersections.empty())
return true;
}
}
for (const ShapeElement& element_1: shape_1.elements) {
Point middle = element_1.middle();
if (shape_2.contains(middle, strict))
return true;
}
for (const ShapeElement& element_2: shape_2.elements) {
Point middle = element_2.middle();
if (shape_1.contains(middle, strict))
return true;
}

return false;
}
5 changes: 5 additions & 0 deletions src/irregular/shape_element_intersections.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ std::vector<Point> compute_intersections(
const ShapeElement& element_2,
bool strict = false);

bool intersect(
const Shape& shape_1,
const Shape& shape_2,
bool strict = false);

}
}
16 changes: 16 additions & 0 deletions src/irregular/shape_self_intersections_removal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,22 @@ std::pair<Shape, std::vector<Shape>> packingsolver::irregular::remove_self_inter
return {new_shape, new_holes};
}

std::pair<Shape, std::vector<Shape>> irregular::compute_union(
const Shape& shape_1,
const Shape& shape_2)
{
Shape shape_tmp;
shape_tmp.elements.insert(
shape_tmp.elements.end(),
shape_1.elements.begin(),
shape_1.elements.end());
shape_tmp.elements.insert(
shape_tmp.elements.end(),
shape_2.elements.begin(),
shape_2.elements.end());
return remove_self_intersections(shape_tmp);
}

std::vector<Shape> irregular::extract_all_holes_from_self_intersecting_hole(
const Shape& shape)
{
Expand Down
4 changes: 4 additions & 0 deletions src/irregular/shape_self_intersections_removal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ namespace irregular
std::pair<Shape, std::vector<Shape>> remove_self_intersections(
const Shape& shape);

std::pair<Shape, std::vector<Shape>> compute_union(
const Shape& shape_1,
const Shape& shape_2);

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

Expand Down
Loading
Loading