bool Model::_arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb, Pointfs &out) const { // we supply unscaled data to arrange() bool result = 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 out // output positions ); if (!result && bb != NULL) { // Try to arrange again ignoring bb result = Slic3r::Geometry::arrange( sizes.size(), // number of parts BoundingBoxf(sizes).max, // width and height of a single cell dist, // distance between cells NULL, // bounding box of the area to fill out // output positions ); } return result; }
/* arrange objects preserving their instance count but altering their instance positions */ bool Model::arrange_objects(coordf_t dist, const 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; 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) { (*i)->offset = positions.back(); positions.pop_back(); } (*o)->invalidate_bounding_box(); } return true; }
/* duplicate the entire model preserving instance relative positions */ 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); // note that this will leave the object count unaltered for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) { // make a copy of the pointers in order to avoid recursion when appending their copies ModelInstancePtrs instances = (*o)->instances; for (ModelInstancePtrs::const_iterator i = instances.begin(); i != instances.end(); ++i) { for (Pointfs::const_iterator pos = positions.begin(); pos != positions.end(); ++pos) { ModelInstance* instance = (*o)->add_instance(**i); instance->offset.translate(*pos); } } (*o)->invalidate_bounding_box(); } }
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 ); }
// Follow an Archimedean spiral, in polar coordinates: r=a+b\theta Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) { // Radius to achieve. coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5; // Now unwind the spiral. coordf_t a = 1.; coordf_t b = 1./(2.*M_PI); coordf_t theta = 0.; coordf_t r = 1; Pointfs out; //FIXME Vojtech: If used as a solid infill, there is a gap left at the center. out.push_back(Pointf(0, 0)); out.push_back(Pointf(1, 0)); while (r < rmax) { theta += 1. / r; r = a + b * theta; out.push_back(Pointf(r * cos(theta), r * sin(theta))); } return out; }
Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) { // Minimum power of two square to fit the domain. size_t sz = 2; size_t pw = 1; { size_t sz0 = std::max(max_x + 1 - min_x, max_y + 1 - min_y); while (sz < sz0) { sz = sz << 1; ++ pw; } } size_t sz2 = sz * sz; Pointfs line; line.reserve(sz2); for (size_t i = 0; i < sz2; ++ i) { Point p = hilbert_n_to_xy(i); line.push_back(Pointf(p.x + min_x, p.y + min_y)); } return line; }
Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) { // Radius to achieve. coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5; // Now unwind the spiral. coordf_t r = 0; coordf_t r_inc = sqrt(2.); Pointfs out; out.push_back(Pointf(0, 0)); while (r < rmax) { r += r_inc; coordf_t rx = r / sqrt(2.); coordf_t r2 = r + rx; out.push_back(Pointf( r, 0.)); out.push_back(Pointf( r2, rx)); out.push_back(Pointf( rx, rx)); out.push_back(Pointf( rx, r2)); out.push_back(Pointf(0., r)); out.push_back(Pointf(-rx, r2)); out.push_back(Pointf(-rx, rx)); out.push_back(Pointf(-r2, rx)); out.push_back(Pointf(-r, 0.)); out.push_back(Pointf(-r2, -rx)); out.push_back(Pointf(-rx, -rx)); out.push_back(Pointf(-rx, -r2)); out.push_back(Pointf(0., -r)); out.push_back(Pointf( rx, -r2)); out.push_back(Pointf( rx, -rx)); out.push_back(Pointf( r2+r_inc, -rx)); } return out; }