diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 162c3a3d1..789fbc373 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -104,32 +104,13 @@ sub duplicate_objects { $self->arrange_objects($distance, $bb); } -# arrange objects preserving their instance count -# but altering their instance positions -sub arrange_objects { - my ($self, $distance, $bb) = @_; - - # get the (transformed) size of each instance so that we take - # into account their different transformations when packing - my @instance_sizes = (); - foreach my $object (@{$self->objects}) { - push @instance_sizes, map $object->instance_bounding_box($_)->size, 0..$#{$object->instances}; - } - - my @positions = $self->_arrange(\@instance_sizes, $distance, $bb); - - foreach my $object (@{$self->objects}) { - $_->set_offset(Slic3r::Pointf->new(@{shift @positions})) for @{$object->instances}; - $object->update_bounding_box; - } -} - # duplicate the entire model preserving instance relative positions sub duplicate { my ($self, $copies_num, $distance, $bb) = @_; - my $model_size = $self->bounding_box->size; - my @positions = $self->_arrange([ map $model_size, 2..$copies_num ], $distance, $bb); + my $model_size = Slic3r::Pointf->new(@{$self->bounding_box->size}[X,Y]); + $bb //= Slic3r::Geometry::BoundingBoxf->new; + my @positions = @{$self->_arrange([ map $model_size, 2..$copies_num ], $distance, $bb)}; # note that this will leave the object count unaltered @@ -148,23 +129,6 @@ sub duplicate { } } -sub _arrange { - my ($self, $sizes, $distance, $bb) = @_; - - $bb //= Slic3r::Geometry::BoundingBoxf->new; - - # we supply unscaled data to arrange() - return @{Slic3r::Geometry::arrange( - scalar(@$sizes), # number of parts - Slic3r::Pointf->new( - max(map $_->x, @$sizes), # cell width - max(map $_->y, @$sizes), # cell height , - ), - $distance, # distance between cells - $bb, # bounding box of the area to fill (can be undef) - )}; -} - sub print_info { my $self = shift; $_->print_info for @{$self->objects}; diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 827029aa0..62a6d8f7c 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -186,7 +186,6 @@ arrange(size_t total_parts, Pointf part, coordf_t dist, const BoundingBoxf &bb) // this is how many cells we have available into which to put parts size_t cellw = floor((area.x + dist) / part.x); size_t cellh = floor((area.x + dist) / part.x); - if (total_parts > (cellw * cellh)) CONFESS("%zu parts won't fit in your print area!\n", total_parts); diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 01c907fad..851a3b08b 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -239,6 +239,42 @@ Model::raw_mesh() const return mesh; } +Pointfs +Model::_arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf &bb) 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 + ); +} + +/* arrange objects preserving their instance count + but altering their instance positions */ +void +Model::arrange_objects(coordf_t dist, BoundingBoxf bb) +{ + // get the (transformed) size of each instance so that we take + // into account their different transformations when packing + Pointfs instance_sizes; + for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) { + for (size_t i = 0; i < (*o)->instances.size(); ++i) { + instance_sizes.push_back((*o)->instance_bounding_box(i).size()); + } + } + + Pointfs positions = this->_arrange(instance_sizes, dist, bb); + + 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) { + (*i)->offset = positions.back(); + positions.pop_back(); + } + } +} + #ifdef SLIC3RXS REGISTER_CLASS(Model, "Model"); #endif diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index d802ae8e7..64b22d837 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -61,10 +61,8 @@ class Model TriangleMesh mesh() const; TriangleMesh raw_mesh() const; // std::string get_material_name(t_model_material_id material_id); - - - private: - void _arrange(const std::vector &sizes, coordf_t distance, const BoundingBox &bb) const; + Pointfs _arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf &bb) const; + void arrange_objects(coordf_t dist, BoundingBoxf bb = BoundingBoxf()); }; class ModelMaterial diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 183890967..ee54dbcb6 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -55,7 +55,6 @@ // void duplicate_objects_grid(coordf_t x, coordf_t y, coordf_t distance); // void duplicate_objects(size_t copies_num, coordf_t distance, const BoundingBox &bb); - // void arrange_objects(coordf_t distance, const BoundingBox &bb); // void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb); bool has_objects_with_no_instances(); bool add_default_instances(); @@ -71,6 +70,12 @@ ModelObjectPtrs* objects() %code%{ RETVAL = &THIS->objects; %}; + + Pointfs _arrange(Pointfs sizes, double dist, BoundingBoxf* bb) + %code%{ RETVAL = THIS->_arrange(sizes, dist, *bb); %}; + + void arrange_objects(double dist, BoundingBoxf* bb) + %code%{ THIS->arrange_objects(dist, *bb); %}; };