Implemented non-rectangular (general convex) beds inside sequential scheduler.

This commit is contained in:
surynek 2025-02-05 23:16:58 +01:00 committed by Lukas Matena
parent ba506413f8
commit 4dac6fea8a
6 changed files with 1013 additions and 248 deletions

View File

@ -34,9 +34,10 @@ namespace Sequential
struct PrinterGeometry
{
// must be convex; for best performance a rectangle is recommended
Slic3r::Polygon plate;
// at least height 0 (corresponding to nozzle) must be present in convex_height
// at least height 0 (corresponding to nozzle) must be present in convex_heights
std::set<coord_t> convex_heights;
std::set<coord_t> box_heights;

View File

@ -85,10 +85,7 @@ bool PrinterGeometry::convert_Geometry2PlateBounds(Slic3r::BoundingBox &plate_bo
{
plate_bounding_polygon.points.insert(plate_bounding_polygon.points.begin() + i, Point(plate.points[i].x() / SEQ_SLICER_SCALE_FACTOR,
plate.points[i].y() / SEQ_SLICER_SCALE_FACTOR));
}
// non-rectangular plate is currently not supported
assert(false);
}
return false;
}
else
@ -442,7 +439,7 @@ void schedule_ObjectsForSequentialPrint(const SolverConfiguration &solver
#endif
if (optimized)
{
{
#ifdef DEBUG
{
printf("Polygon positions:\n");

View File

@ -868,21 +868,36 @@ bool check_PolygonSizeFitToPlate(const SolverConfiguration &solver_configuration
{
BoundingBox polygon_box = get_extents(polygon);
// general plate polygons are currently not supported
assert(solver_configuration.plate_bounding_polygon.points.size() == 0);
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()))
if (solver_configuration.plate_bounding_polygon.points.size() == 0)
{
return false;
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()))
{
return false;
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (solver_configuration.plate_bounding_box.max.y() - solver_configuration.plate_bounding_box.min.y()))
{
return false;
}
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (solver_configuration.plate_bounding_box.max.y() - solver_configuration.plate_bounding_box.min.y()))
else
{
return false;
}
BoundingBox plate_box = get_extents(solver_configuration.plate_bounding_polygon);
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (plate_box.max.x() - plate_box.min.x()))
{
return false;
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (plate_box.max.y() - plate_box.min.y()))
{
return false;
}
}
return true;
}
@ -890,17 +905,31 @@ bool check_PolygonPositionWithinPlate(const SolverConfiguration &solver_configur
{
BoundingBox polygon_box = get_extents(polygon);
// general plate polygons are currently not supported
assert(solver_configuration.plate_bounding_polygon.points.size() == 0);
if (x + polygon_box.min.x() < solver_configuration.plate_bounding_box.min.x() || x + polygon_box.max.x() > solver_configuration.plate_bounding_box.max.x())
if (solver_configuration.plate_bounding_polygon.points.size() == 0)
{
return false;
if (x + polygon_box.min.x() < solver_configuration.plate_bounding_box.min.x() || x + polygon_box.max.x() > solver_configuration.plate_bounding_box.max.x())
{
return false;
}
if (y + polygon_box.min.y() < solver_configuration.plate_bounding_box.min.y() || y + polygon_box.max.y() > solver_configuration.plate_bounding_box.max.y())
{
return false;
}
}
if (y + polygon_box.min.y() < solver_configuration.plate_bounding_box.min.y() || y + polygon_box.max.y() > solver_configuration.plate_bounding_box.max.y())
else
{
return false;
}
if ( contains(solver_configuration.plate_bounding_polygon, Point(x + polygon_box.min.x(), y + polygon_box.min.y()))
&& contains(solver_configuration.plate_bounding_polygon, Point(x + polygon_box.max.x(), y + polygon_box.min.y()))
&& contains(solver_configuration.plate_bounding_polygon, Point(x + polygon_box.max.x(), y + polygon_box.max.y()))
&& contains(solver_configuration.plate_bounding_polygon, Point(x + polygon_box.min.x(), y + polygon_box.max.y())))
{
return true;
}
else
{
return false;
}
}
return true;
}
@ -909,19 +938,34 @@ bool check_PolygonSizeFitToPlate(const SolverConfiguration &solver_configuration
{
BoundingBox polygon_box = get_extents(polygon);
// general plate polygons are currently not supported
assert(solver_configuration.plate_bounding_polygon.points.size() == 0);
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()) * scale_factor)
if (solver_configuration.plate_bounding_polygon.points.size() == 0)
{
return false;
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()) * scale_factor)
{
return false;
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()) * scale_factor)
{
return false;
}
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (solver_configuration.plate_bounding_box.max.x() - solver_configuration.plate_bounding_box.min.x()) * scale_factor)
else
{
return false;
BoundingBox plate_box = get_extents(solver_configuration.plate_bounding_polygon);
coord_t x_size = polygon_box.max.x() - polygon_box.min.x();
if (x_size > (plate_box.max.x() - plate_box.min.x()) * scale_factor)
{
return false;
}
coord_t y_size = polygon_box.max.y() - polygon_box.min.y();
if (y_size > (plate_box.max.y() - plate_box.min.y()) * scale_factor)
{
return false;
}
}
return true;
@ -951,6 +995,27 @@ bool check_PolygonPositionWithinPlate(const SolverConfiguration &solver_configur
if (y + polygon_box.min.y() < solver_configuration.plate_bounding_box.min.y() * scale_factor || y + polygon_box.max.y() > solver_configuration.plate_bounding_box.max.y() * scale_factor)
{
return false;
}
else
{
Polygon plate_polygon = solver_configuration.plate_bounding_polygon;
for (unsigned int i = 0; i < plate_polygon.points.size(); ++i)
{
plate_polygon.points[i] *= scale_factor;
}
if ( contains(plate_polygon, Point(x + polygon_box.min.x(), y + polygon_box.min.y()))
&& contains(plate_polygon, Point(x + polygon_box.max.x(), y + polygon_box.min.y()))
&& contains(plate_polygon, Point(x + polygon_box.max.x(), y + polygon_box.max.y()))
&& contains(plate_polygon, Point(x + polygon_box.min.x(), y + polygon_box.max.y())))
{
return true;
}
else
{
return false;
}
}
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -232,7 +232,6 @@ void assume_DecisionBox(const z3::expr &dec_var_X,
int box_size_y,
z3::expr_vector &box_constraints);
void introduce_BedBoundingBox(z3::solver &Solver,
const z3::expr &dec_var_X,
const z3::expr &dec_var_Y,
@ -254,8 +253,7 @@ void introduce_BedBoundingBox(z3::solver &Solver,
int box_min_x,
int box_min_y,
int box_max_x,
int box_max_y);
int box_max_y);
void assume_BedBoundingBox(const z3::expr &dec_var_X,
const z3::expr &dec_var_Y,
@ -266,6 +264,13 @@ void assume_BedBoundingBox(const z3::expr &dec_var_X,
int box_max_y,
z3::expr_vector &bounding_constraints);
void assume_BedBoundingPolygon(z3::context &Context,
const z3::expr &dec_var_X,
const z3::expr &dec_var_Y,
const Slic3r::Polygon &polygon,
const Slic3r::Polygon &bed_bounding_polygon,
z3::expr_vector &bounding_constraints);
void introduce_BedBoundingBox(z3::solver &Solver,
const z3::expr_vector &dec_vars_X,
const z3::expr_vector &dec_vars_Y,
@ -590,6 +595,12 @@ void introduce_PointInsidePolygon(z3::solver &Solver,
const z3::expr &dec_var_Y2,
const Slic3r::Polygon &polygon);
void assume_PointInsidePolygon(z3::context &Context,
const z3::expr &dec_var_X,
const z3::expr &dec_var_Y,
const Slic3r::Polygon &polygon,
z3::expr_vector &constraints);
void introduce_PointOutsidePolygon(z3::solver &Solver,
z3::context &Context,
const z3::expr &dec_var_X1,
@ -1454,6 +1465,12 @@ bool checkArea_SequentialWeakPolygonNonoverlapping(coord_t
const std::vector<Slic3r::Polygon> &polygons,
const std::vector<std::vector<Slic3r::Polygon> > &unreachable_polygons);
bool checkArea_SequentialWeakPolygonNonoverlapping(const Slic3r::Polygon &bounding_polygon,
const std::vector<int> &fixed,
const std::vector<int> &undecided,
const std::vector<Slic3r::Polygon> &polygons,
const std::vector<std::vector<Slic3r::Polygon> > &unreachable_polygons);
bool checkExtens_SequentialWeakPolygonNonoverlapping(coord_t box_min_x,
coord_t box_min_y,
coord_t box_max_x,
@ -1468,10 +1485,10 @@ bool checkExtens_SequentialWeakPolygonNonoverlapping(coord_t
bool optimize_SequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver &Solver,
z3::context &Context,
const SolverConfiguration &solver_configuration,
int &box_half_x_min,
int &box_half_y_min,
int &box_half_x_max,
int &box_half_y_max,
coord_t &box_half_x_min,
coord_t &box_half_y_min,
coord_t &box_half_x_max,
coord_t &box_half_y_max,
const z3::expr_vector &dec_vars_X,
const z3::expr_vector &dec_vars_Y,
const z3::expr_vector &dec_vars_T,
@ -1484,14 +1501,49 @@ bool optimize_SequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver
const std::vector<Slic3r::Polygon> &polygons,
const std::vector<std::vector<Slic3r::Polygon> > &unreachable_polygons);
bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver &Solver,
z3::context &Context,
const SolverConfiguration &solver_configuration,
coord_t &box_half_x_min,
coord_t &box_half_y_min,
coord_t &box_half_x_max,
coord_t &box_half_y_max,
const z3::expr_vector &dec_vars_X,
const z3::expr_vector &dec_vars_Y,
const z3::expr_vector &dec_vars_T,
std::vector<Rational> &dec_values_X,
std::vector<Rational> &dec_values_Y,
std::vector<Rational> &dec_values_T,
const std::vector<int> &fixed,
const std::vector<int> &undecided,
const string_map &dec_var_names_map,
const std::vector<Slic3r::Polygon> &polygons,
const std::vector<std::vector<Slic3r::Polygon> > &unreachable_polygons,
const ProgressRange &progress_range,
std::function<void(int)> progress_callback);
bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver &Solver,
z3::context &Context,
const SolverConfiguration &solver_configuration,
int &box_half_x_min,
int &box_half_y_min,
int &box_half_x_max,
int &box_half_y_max,
BoundingBox &inner_half_box,
const z3::expr_vector &dec_vars_X,
const z3::expr_vector &dec_vars_Y,
const z3::expr_vector &dec_vars_T,
std::vector<Rational> &dec_values_X,
std::vector<Rational> &dec_values_Y,
std::vector<Rational> &dec_values_T,
const std::vector<int> &fixed,
const std::vector<int> &undecided,
const string_map &dec_var_names_map,
const std::vector<Slic3r::Polygon> &polygons,
const std::vector<std::vector<Slic3r::Polygon> > &unreachable_polygons,
const ProgressRange &progress_range,
std::function<void(int)> progress_callback);
bool optimize_ConsequentialWeakPolygonNonoverlappingBinaryCentered(z3::solver &Solver,
z3::context &Context,
const SolverConfiguration &solver_configuration,
Polygon &inner_half_polygon,
const z3::expr_vector &dec_vars_X,
const z3::expr_vector &dec_vars_Y,
const z3::expr_vector &dec_vars_T,

View File

@ -105,6 +105,7 @@ static Sequential::PrinterGeometry get_printer_geometry(const ConfigBase& config
out.plate = { { scaled(min_x), scaled(min_y)},
{ scaled(max_x), scaled(min_y)},
// { 2 * scaled(max_x), (scaled(min_y) + scaled(max_y)) / 2}, /* for testing convex non-rectangular beds
{ scaled(max_x), scaled(max_y)},
{ scaled(min_x), scaled(max_y)}};