Exemple #1
0
void
ModelObject::center_around_origin()
{
    // calculate the displacements needed to 
    // center this object around the origin
    BoundingBoxf3 bb;
    {
        TriangleMesh mesh;
        this->raw_mesh(&mesh);
        mesh.bounding_box(&bb);
    }
    
    // first align to origin on XYZ
    Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
    
    // then center it on XY
    Sizef3 size = bb.size();
    vector.x -= size.x/2;
    vector.y -= size.y/2;
    
    this->translate(vector);
    this->origin_translation.translate(vector);
    
    if (!this->instances.empty()) {
        for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
            (*i)->offset.translate(-vector.x, -vector.y);
        }
        this->update_bounding_box();
    }
}
Exemple #2
0
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const
{
    // rotate around mesh origin
    double c = cos(this->rotation);
    double s = sin(this->rotation);
    BoundingBoxf3 bbox;
    for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) {
        const stl_facet &facet = mesh->stl.facet_start[i];
        for (int j = 0; j < 3; ++ j) {
            stl_vertex v = facet.vertex[j];
            double xold = v.x;
            double yold = v.y;
            v.x = float(c * xold - s * yold);
            v.y = float(s * xold + c * yold);
            v.x *= float(this->scaling_factor);
            v.y *= float(this->scaling_factor);
            v.z *= float(this->scaling_factor);
            if (!dont_translate) {
                v.x += this->offset.x;
                v.y += this->offset.y;
            }
            bbox.merge(Pointf3(v.x, v.y, v.z));
        }
    }
    return bbox;
}
Exemple #3
0
void
ModelObject::center_around_origin()
{
    // calculate the displacements needed to 
    // center this object around the origin
	BoundingBoxf3 bb;
	for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v)
		if (! (*v)->modifier)
			bb.merge((*v)->mesh.bounding_box());
    
    // first align to origin on XYZ
    Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
    
    // then center it on XY
    Sizef3 size = bb.size();
    vector.x -= size.x/2;
    vector.y -= size.y/2;
    
    this->translate(vector);
    this->origin_translation.translate(vector);
    
    if (!this->instances.empty()) {
        for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
            // apply rotation and scaling to vector as well before translating instance,
            // in order to leave final position unaltered
            Vectorf3 v = vector.negative();
            v.rotate((*i)->rotation, (*i)->offset);
            v.scale((*i)->scaling_factor);
            (*i)->offset.translate(v.x, v.y);
        }
        this->invalidate_bounding_box();
    }
}
Exemple #4
0
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
{
    // rotate around mesh origin
    double c = cos(this->rotation);
    double s = sin(this->rotation);
    Pointf3 pts[4] = {
        bbox.min,
        bbox.max,
        Pointf3(bbox.min.x, bbox.max.y, bbox.min.z),
        Pointf3(bbox.max.x, bbox.min.y, bbox.max.z)
    };
    BoundingBoxf3 out;
    for (int i = 0; i < 4; ++ i) {
        Pointf3 &v = pts[i];
        double xold = v.x;
        double yold = v.y;
        v.x = float(c * xold - s * yold);
        v.y = float(s * xold + c * yold);
        v.x *= this->scaling_factor;
        v.y *= this->scaling_factor;
        v.z *= this->scaling_factor;
        if (!dont_translate) {
            v.x += this->offset.x;
            v.y += this->offset.y;
        }
        out.merge(v);
    }
    return out;
}
Exemple #5
0
void
Model::align_instances_to_origin()
{
    BoundingBoxf3 bb = this->bounding_box();
    
    Pointf new_center = (Pointf)bb.size();
    new_center.translate(-new_center.x/2, -new_center.y/2);
    this->center_instances_around_point(new_center);
}
Exemple #6
0
// this returns the bounding box of the *transformed* instances
BoundingBoxf3
Model::bounding_box() const
{
    BoundingBoxf3 bb;
    for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
        bb.merge((*o)->bounding_box());
    }
    return bb;
}
Exemple #7
0
// this returns the bounding box of the *transformed* given instance
BoundingBoxf3
ModelObject::instance_bounding_box(size_t instance_idx) const
{
    BoundingBoxf3 bb;
    for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
        if ((*v)->modifier) continue;
        bb.merge(this->instances[instance_idx]->transform_mesh_bounding_box(&(*v)->mesh, true));
    }
    return bb;
}
Exemple #8
0
BoundingBoxf3
ModelObject::raw_bounding_box() const
{
    BoundingBoxf3 bb;
    for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
        if ((*v)->modifier) continue;
        if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
        bb.merge(this->instances.front()->transform_mesh_bounding_box(&(*v)->mesh, true));
    }
    return bb;
}
Exemple #9
0
void
ModelObject::align_to_ground()
{
    // calculate the displacements needed to 
    // center this object around the origin
	BoundingBoxf3 bb;
	for (const ModelVolume* v : this->volumes)
		if (!v->modifier)
			bb.merge(v->mesh.bounding_box());
    
    this->translate(0, 0, -bb.min.z);
    this->origin_translation.translate(0, 0, -bb.min.z);
}
Exemple #10
0
void
ModelObject::update_bounding_box()
{
//    this->_bounding_box = this->mesh().bounding_box();
    BoundingBoxf3 raw_bbox;
    for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
        if ((*v)->modifier) continue;
        raw_bbox.merge((*v)->mesh.bounding_box());
    }
    BoundingBoxf3 bb;
    for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i)
        bb.merge((*i)->transform_bounding_box(raw_bbox));
    this->_bounding_box = bb;
    this->_bounding_box_valid = true;
}
Exemple #11
0
void
Model::center_instances_around_point(const Pointf &point)
{
    BoundingBoxf3 bb = this->bounding_box();
    
    Sizef3 size = bb.size();
    coordf_t shift_x = -bb.min.x + point.x - size.x/2;
    coordf_t shift_y = -bb.min.y + point.y - size.y/2;
    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.translate(shift_x, shift_y);
        }
        (*o)->invalidate_bounding_box();
    }
}
Exemple #12
0
PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox)
:   _print(print),
    _model_object(model_object),
    typed_slices(false)
{
    region_volumes.resize(this->_print->regions.size());

    // Compute the translation to be applied to our meshes so that we work with smaller coordinates
    {
        // Translate meshes so that our toolpath generation algorithms work with smaller
        // XY coordinates; this translation is an optimization and not strictly required.
        // A cloned mesh will be aligned to 0 before slicing in _slice_region() since we
        // don't assume it's already aligned and we don't alter the original position in model.
        // We store the XY translation so that we can place copies correctly in the output G-code
        // (copies are expressed in G-code coordinates and this translation is not publicly exposed).
        this->_copies_shift = Point(
            scale_(modobj_bbox.min.x), scale_(modobj_bbox.min.y));

        // Scale the object size and store it
        Pointf3 size = modobj_bbox.size();
        this->size = Point3(scale_(size.x), scale_(size.y), scale_(size.z));
    }
    
    this->reload_model_instances();
    this->layer_height_ranges = model_object->layer_height_ranges;
}
Exemple #13
0
void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const
{
    if (m_quadric == nullptr)
        return;

    float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
    double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size);

    float color[3];
    ::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float));
    if (!picking && (m_hover_id != -1))
    {
        color[0] = 1.0f - color[0];
        color[1] = 1.0f - color[1];
        color[2] = 1.0f - color[2];
    }

    if (!picking)
        glsafe(::glEnable(GL_LIGHTING));

    glsafe(::glColor3fv(color));
    glsafe(::glPushMatrix());
    glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)));
    glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
    glsafe(::glRotated(90.0, 1.0, 0.0, 0.0));
    glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
    ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
    ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
    ::gluQuadricOrientation(m_quadric, GLU_INSIDE);
    ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
    glsafe(::glPopMatrix());
    glsafe(::glPushMatrix());
    glsafe(::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)));
    glsafe(::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0));
    glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
    glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
    ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE);
    ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1);
    ::gluQuadricOrientation(m_quadric, GLU_INSIDE);
    ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1);
    glsafe(::glPopMatrix());

    if (!picking)
        glsafe(::glDisable(GL_LIGHTING));
}
Exemple #14
0
BoundingBoxf3 ModelInstance::transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate) const
{
    // rotate around mesh origin
    double c = cos(this->rotation);
    double s = sin(this->rotation);
    double cx = cos(this->x_rotation);
    double sx = sin(this->x_rotation);
    double cy = cos(this->y_rotation);
    double sy = sin(this->y_rotation);
    Pointf3 pts[4] = {
        bbox.min,
        bbox.max,
        Pointf3(bbox.min.x, bbox.max.y, bbox.min.z),
        Pointf3(bbox.max.x, bbox.min.y, bbox.max.z)
    };
    BoundingBoxf3 out;
    for (int i = 0; i < 4; ++ i) {
        Pointf3 &v = pts[i];
        double xold = v.x;
        double yold = v.y;
        double zold = v.z;
        // Rotation around x axis.
        v.z = float(sx * yold + cx * zold);
        yold = v.y = float(cx * yold - sx * zold);
        zold = v.z;
        // Rotation around y axis.
        v.x = float(cy * xold + sy * zold);
        v.z = float(-sy * xold + cy * zold);
        xold = v.x;
        // Rotation around z axis.
        v.x = float(c * xold - s * yold);
        v.y = float(s * xold + c * yold);
        v.x *= this->scaling_factor * this->scaling_vector.x;
        v.y *= this->scaling_factor * this->scaling_vector.y;
        v.z *= this->scaling_factor * this->scaling_vector.z;
        if (!dont_translate) {
            v.x += this->offset.x;
            v.y += this->offset.y;
        }
        out.merge(v);
    }
    return out;
}
Exemple #15
0
void
ModelObject::print_info() const
{
    using namespace std;
    cout << fixed;
    cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
    
    TriangleMesh mesh = this->raw_mesh();
    mesh.check_topology();
    BoundingBoxf3 bb = mesh.bounding_box();
    Sizef3 size = bb.size();
    cout << "size_x = " << size.x << endl;
    cout << "size_y = " << size.y << endl;
    cout << "size_z = " << size.z << endl;
    cout << "min_x = " << bb.min.x << endl;
    cout << "min_y = " << bb.min.y << endl;
    cout << "min_z = " << bb.min.z << endl;
    cout << "max_x = " << bb.max.x << endl;
    cout << "max_y = " << bb.max.y << endl;
    cout << "max_z = " << bb.max.z << endl;
    cout << "number_of_facets = " << mesh.stl.stats.number_of_facets  << endl;
    cout << "manifold = "   << (mesh.is_manifold() ? "yes" : "no") << endl;
    
    mesh.repair();  // this calculates number_of_parts
    if (mesh.needed_repair()) {
        mesh.repair();
        if (mesh.stl.stats.degenerate_facets > 0)
            cout << "degenerate_facets = "  << mesh.stl.stats.degenerate_facets << endl;
        if (mesh.stl.stats.edges_fixed > 0)
            cout << "edges_fixed = "        << mesh.stl.stats.edges_fixed       << endl;
        if (mesh.stl.stats.facets_removed > 0)
            cout << "facets_removed = "     << mesh.stl.stats.facets_removed    << endl;
        if (mesh.stl.stats.facets_added > 0)
            cout << "facets_added = "       << mesh.stl.stats.facets_added      << endl;
        if (mesh.stl.stats.facets_reversed > 0)
            cout << "facets_reversed = "    << mesh.stl.stats.facets_reversed   << endl;
        if (mesh.stl.stats.backwards_edges > 0)
            cout << "backwards_edges = "    << mesh.stl.stats.backwards_edges   << endl;
    }
    cout << "number_of_parts =  " << mesh.stl.stats.number_of_parts << endl;
    cout << "volume = "           << mesh.volume()                  << endl;
}
Exemple #16
0
BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mesh, bool dont_translate) const
{
    // rotate around mesh origin
    double c = cos(this->rotation);
    double s = sin(this->rotation);
    double cx = cos(this->x_rotation);
    double sx = sin(this->x_rotation);
    double cy = cos(this->y_rotation);
    double sy = sin(this->y_rotation);
    BoundingBoxf3 bbox;
    for (int i = 0; i < mesh->stl.stats.number_of_facets; ++ i) {
        const stl_facet &facet = mesh->stl.facet_start[i];
        for (int j = 0; j < 3; ++ j) {
            stl_vertex v = facet.vertex[j];
            double xold = v.x;
            double yold = v.y;
            double zold = v.z;
            // Rotation around x axis.
            v.z = float(sx * yold + cx * zold);
            yold = v.y = float(cx * yold - sx * zold);
            zold = v.z;
            // Rotation around y axis.
            v.x = float(cy * xold + sy * zold);
            v.z = float(-sy * xold + cy * zold);
            xold = v.x;
            // Rotation around z axis.
            v.x = float(c * xold - s * yold);
            v.y = float(s * xold + c * yold);
            v.x *= float(this->scaling_factor * this->scaling_vector.x);
            v.y *= float(this->scaling_factor * this->scaling_vector.y);
            v.z *= float(this->scaling_factor * this->scaling_vector.z);
            if (!dont_translate) {
                v.x += this->offset.x;
                v.y += this->offset.y;
                if (this->y_rotation || this->x_rotation)
                    v.z += -(mesh->stl.stats.min.z);
            }
            bbox.merge(Pointf3(v.x, v.y, v.z));
        }
    }
    return bbox;
}
Exemple #17
0
void
SVGExport::writeSVG(const std::string &outputfile)
{
    // align to origin taking raft into account
    BoundingBoxf3 bb = this->mesh.bounding_box();
    if (this->config.raft_layers > 0) {
        bb.min.x -= this->config.raft_offset.value;
        bb.min.y -= this->config.raft_offset.value;
        bb.max.x += this->config.raft_offset.value;
        bb.max.y += this->config.raft_offset.value;
    }
    this->mesh.translate(-bb.min.x, -bb.min.y, -bb.min.z);  // align to origin
    bb.translate(-bb.min.x, -bb.min.y, -bb.min.z);          // align to origin
    const Sizef3 size = bb.size();
    
    // if we are generating a raft, first_layer_height will not affect mesh slicing
    const float lh = this->config.layer_height.value;
    const float first_lh = this->config.first_layer_height.value;
    
    // generate the list of Z coordinates for mesh slicing
    // (we slice each layer at half of its thickness)
    std::vector<float> slice_z, layer_z;
    {
        const float first_slice_lh = (this->config.raft_layers > 0) ? lh : first_lh;
        slice_z.push_back(first_slice_lh/2);
        layer_z.push_back(first_slice_lh);
    }
    while (layer_z.back() + lh/2 <= this->mesh.stl.stats.max.z) {
        slice_z.push_back(layer_z.back() + lh/2);
        layer_z.push_back(layer_z.back() + lh);
    }
    
    // perform the slicing
    std::vector<ExPolygons> layers;
    TriangleMeshSlicer(&this->mesh).slice(slice_z, &layers);
    
    // generate a solid raft if requested
    if (this->config.raft_layers > 0) {
        ExPolygons raft = offset_ex(layers.front(), scale_(this->config.raft_offset));
        for (int i = this->config.raft_layers; i >= 1; --i) {
            layer_z.insert(layer_z.begin(), first_lh + lh * (i-1));
            layers.insert(layers.begin(), raft);
        }
        
        // prepend total raft height to all sliced layers
        for (int i = this->config.raft_layers; i < layer_z.size(); ++i)
            layer_z[i] += first_lh + lh * (this->config.raft_layers-1);
    }
    
    // generate support material
    std::vector<Points> support_material(layers.size());
    if (this->config.support_material) {
        // generate a grid of points according to the configured spacing,
        // covering the entire object bounding box
        Points support_material_points;
        for (coordf_t x = bb.min.x; x <= bb.max.x; x += this->config.support_material_spacing) {
            for (coordf_t y = bb.min.y; y <= bb.max.y; y += this->config.support_material_spacing) {
                support_material_points.push_back(Point(scale_(x), scale_(y)));
            }
        }
        
        // check overhangs, starting from the upper layer, and detect which points apply 
        // to each layer
        ExPolygons overhangs;
        for (int i = layer_z.size()-1; i >= 0; --i) {
            overhangs = diff_ex(union_(overhangs, layers[i+1]), layers[i]);
            for (Points::const_iterator it = support_material_points.begin(); it != support_material_points.end(); ++it) {
                for (ExPolygons::const_iterator e = overhangs.begin(); e != overhangs.end(); ++e) {
                    if (e->contains(*it)) {
                        support_material[i].push_back(*it);
                        break;
                    }
                }
            }
        }
    }
    
    double support_material_radius = this->config.support_material_extrusion_width.get_abs_value(this->config.layer_height)/2;
    
    FILE* f = fopen(outputfile.c_str(), "w");
    fprintf(f,
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
        "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
        "<svg width=\"%f\" height=\"%f\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:slic3r=\"http://slic3r.org/namespaces/slic3r\" viewport-fill=\"black\">\n"
        "<!-- Generated using Slic3r %s http://slic3r.org/ -->\n"
        , size.x, size.y, SLIC3R_VERSION);
    
    for (size_t i = 0; i < layer_z.size(); ++i) {
        fprintf(f, "\t<g id=\"layer%zu\" slic3r:z=\"%0.4f\">\n", i, layer_z[i]);
        for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it) {
            std::string pd;
            Polygons pp = *it;
            for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp) {
                std::ostringstream d;
                d << "M ";
                for (Points::const_iterator p = mp->points.begin(); p != mp->points.end(); ++p) {
                    d << unscale(p->x) << " ";
                    d << unscale(p->y) << " ";
                }
                d << "z";
                pd += d.str() + " ";
            }
            fprintf(f,"\t\t<path d=\"%s\" style=\"fill: %s; stroke: %s; stroke-width: %s; fill-type: evenodd\" slic3r:area=\"%0.4f\" />\n",
                pd.c_str(), "white", "black", "0", unscale(unscale(it->area()))
            );
        }
        for (Points::const_iterator it = support_material[i].begin(); it != support_material[i].end(); ++it) {
            fprintf(f,"\t\t<circle cx=\"%f\" cy=\"%f\" r=\"%f\" stroke-width=\"0\" fill=\"white\" slic3r:type=\"support\" />\n",
                unscale(it->x), unscale(it->y), support_material_radius
            );
        }
        fprintf(f,"\t</g>\n");
    }
    fprintf(f,"</svg>\n");
}