From 6217622865eac20a00b0a1a55dfddd2dffd51ceb Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 4 Nov 2016 15:03:51 +0100 Subject: [PATCH] Hopefully a fix of https://github.com/prusa3d/Slic3r/issues/11 Replaced eval { die } construct with a bool return value indicating success or failure of an automatic arrangement of parts on the print bed. Don't know exactly what is happening here, but throwing a "die" inside a XS function and then catching it inside an eval {} block is suspcious. --- lib/Slic3r/GUI/Plater.pm | 4 +--- xs/src/libslic3r/Geometry.cpp | 12 +++++++----- xs/src/libslic3r/Geometry.hpp | 6 +++++- xs/src/libslic3r/Model.cpp | 18 ++++++++++++------ xs/src/libslic3r/Model.hpp | 5 +++-- xs/xsp/Geometry.xsp | 7 ++++++- xs/xsp/Model.xsp | 3 +-- 7 files changed, 35 insertions(+), 20 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 5069f3e4a..54f66e221 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -965,9 +965,7 @@ sub arrange { $self->pause_background_process; my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($self->{config}->bed_shape); - eval { - $self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb); - }; + my $success = $self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb); # ignore arrange failures on purpose: user has visual feedback and we don't need to warn him # when parts don't fit in print bed diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 15b68e96a..31a6dfb22 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -424,9 +424,12 @@ class ArrangeItemIndex { ArrangeItem item; ArrangeItemIndex(coordf_t _index, ArrangeItem _item) : index(_index), item(_item) {}; }; -Pointfs -arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const BoundingBoxf* bb) + +bool +arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const BoundingBoxf* bb, Pointfs &positions) { + positions.clear(); + Pointf part = part_size; // use actual part size (the largest) plus separation distance (half on each side) in spacing algorithm @@ -446,7 +449,7 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi size_t cellw = floor((area.x + dist) / part.x); size_t cellh = floor((area.y + dist) / part.y); if (total_parts > (cellw * cellh)) - CONFESS(PRINTF_ZU " parts won't fit in your print area!\n", total_parts); + return false; // total space used by cells Pointf cells(cellw * part.x, cellh * part.y); @@ -527,7 +530,6 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi } } // now we actually place objects into cells, positioned such that the left and bottom borders are at 0 - Pointfs positions; for (size_t i = 1; i <= total_parts; ++i) { ArrangeItemIndex c = cellsorder.front(); cellsorder.erase(cellsorder.begin()); @@ -544,7 +546,7 @@ arrange(size_t total_parts, const Pointf &part_size, coordf_t dist, const Boundi } } - return positions; + return true; } #endif diff --git a/xs/src/libslic3r/Geometry.hpp b/xs/src/libslic3r/Geometry.hpp index 2c05c1e38..30582fdfd 100644 --- a/xs/src/libslic3r/Geometry.hpp +++ b/xs/src/libslic3r/Geometry.hpp @@ -26,7 +26,11 @@ double deg2rad(double angle); void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval); double linint(double value, double oldmin, double oldmax, double newmin, double newmax); -Pointfs arrange(size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box); +bool arrange( + // input + size_t num_parts, const Pointf &part_size, coordf_t gap, const BoundingBoxf* bed_bounding_box, + // output + Pointfs &positions); class MedialAxis { public: diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index adc464bf7..5db9066a6 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -215,21 +215,22 @@ Model::raw_mesh() const return mesh; } -Pointfs -Model::_arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb) const +bool +Model::_arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb, Pointfs &out) const { // we supply unscaled data to arrange() return Slic3r::Geometry::arrange( sizes.size(), // number of parts BoundingBoxf(sizes).max, // width and height of a single cell dist, // distance between cells - bb // bounding box of the area to fill + bb, // bounding box of the area to fill + out // output positions ); } /* arrange objects preserving their instance count but altering their instance positions */ -void +bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) { // get the (transformed) size of each instance so that we take @@ -241,7 +242,9 @@ Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) } } - Pointfs positions = this->_arrange(instance_sizes, dist, bb); + Pointfs positions; + if (! this->_arrange(instance_sizes, dist, bb, positions)) + return false; for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) { for (ModelInstancePtrs::const_iterator i = (*o)->instances.begin(); i != (*o)->instances.end(); ++i) { @@ -250,6 +253,7 @@ Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) } (*o)->invalidate_bounding_box(); } + return true; } /* duplicate the entire model preserving instance relative positions */ @@ -257,7 +261,9 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb) { Pointfs model_sizes(copies_num-1, this->bounding_box().size()); - Pointfs positions = this->_arrange(model_sizes, dist, bb); + Pointfs positions; + if (! this->_arrange(model_sizes, dist, bb, positions)) + CONFESS("Cannot duplicate part as the resulting objects would not fit on the print bed.\n"); // note that this will leave the object count unaltered diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index cb0ab05f2..60405f6f6 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -64,8 +64,9 @@ public: void translate(coordf_t x, coordf_t y, coordf_t z); TriangleMesh mesh() const; TriangleMesh raw_mesh() const; - Pointfs _arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb = NULL) const; - void arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL); + bool _arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb, Pointfs &out) const; + bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL); + // Croaks if the duplicated objects do not fit the print bed. void duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL); void duplicate_objects(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL); void duplicate_objects_grid(size_t x, size_t y, coordf_t dist); diff --git a/xs/xsp/Geometry.xsp b/xs/xsp/Geometry.xsp index 718ce5bdf..b23bbeffa 100644 --- a/xs/xsp/Geometry.xsp +++ b/xs/xsp/Geometry.xsp @@ -9,7 +9,12 @@ %package{Slic3r::Geometry}; Pointfs arrange(size_t total_parts, Pointf* part, coordf_t dist, BoundingBoxf* bb = NULL) - %code{% RETVAL = Slic3r::Geometry::arrange(total_parts, *part, dist, bb); %}; + %code{% + Pointfs points; + if (! Slic3r::Geometry::arrange(total_parts, *part, dist, bb, points)) + CONFESS(PRINTF_ZU " parts won't fit in your print area!\n", total_parts); + RETVAL = points; + %}; %{ diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 3cc0f5e3b..aedc1f7dc 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -66,8 +66,7 @@ ModelObjectPtrs* objects() %code%{ RETVAL = &THIS->objects; %}; - Pointfs _arrange(Pointfs sizes, double dist, BoundingBoxf* bb = NULL); - void arrange_objects(double dist, BoundingBoxf* bb = NULL); + bool arrange_objects(double dist, BoundingBoxf* bb = NULL); void duplicate(unsigned int copies_num, double dist, BoundingBoxf* bb = NULL); void duplicate_objects(unsigned int copies_num, double dist, BoundingBoxf* bb = NULL); void duplicate_objects_grid(unsigned int x, unsigned int y, double dist);