void ModelObject::cut(Axis axis, coordf_t z, Model* model) const { // clone this one to duplicate instances, materials etc. ModelObject* upper = model->add_object(*this); ModelObject* lower = model->add_object(*this); upper->clear_volumes(); lower->clear_volumes(); upper->input_file = ""; lower->input_file = ""; for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) { ModelVolume* volume = *v; if (volume->modifier) { // don't cut modifiers upper->add_volume(*volume); lower->add_volume(*volume); } else { TriangleMesh upper_mesh, lower_mesh; if (axis == X) { TriangleMeshSlicer<X>(&volume->mesh).cut(z, &upper_mesh, &lower_mesh); } else if (axis == Y) { TriangleMeshSlicer<Y>(&volume->mesh).cut(z, &upper_mesh, &lower_mesh); } else if (axis == Z) { TriangleMeshSlicer<Z>(&volume->mesh).cut(z, &upper_mesh, &lower_mesh); } upper_mesh.repair(); lower_mesh.repair(); upper_mesh.reset_repair_stats(); lower_mesh.reset_repair_stats(); if (upper_mesh.facets_count() > 0) { ModelVolume* vol = upper->add_volume(upper_mesh); vol->name = volume->name; vol->config = volume->config; vol->set_material(volume->material_id(), *volume->material()); } if (lower_mesh.facets_count() > 0) { ModelVolume* vol = lower->add_volume(lower_mesh); vol->name = volume->name; vol->config = volume->config; vol->set_material(volume->material_id(), *volume->material()); } } } }
void ModelObject::cut(coordf_t z, Model* model) const { // clone this one to duplicate instances, materials etc. ModelObject* upper = model->add_object(*this); ModelObject* lower = model->add_object(*this); upper->clear_volumes(); lower->clear_volumes(); for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) { ModelVolume* volume = *v; if (volume->modifier) { // don't cut modifiers upper->add_volume(*volume); lower->add_volume(*volume); } else { TriangleMeshSlicer tms(&volume->mesh); TriangleMesh upper_mesh, lower_mesh; // TODO: shouldn't we use object bounding box instead of per-volume bb? tms.cut(z + volume->mesh.bounding_box().min.z, &upper_mesh, &lower_mesh); upper_mesh.repair(); lower_mesh.repair(); upper_mesh.reset_repair_stats(); lower_mesh.reset_repair_stats(); if (upper_mesh.facets_count() > 0) { ModelVolume* vol = upper->add_volume(upper_mesh); vol->name = volume->name; vol->config = volume->config; vol->set_material(volume->material_id(), *volume->material()); } if (lower_mesh.facets_count() > 0) { ModelVolume* vol = lower->add_volume(lower_mesh); vol->name = volume->name; vol->config = volume->config; vol->set_material(volume->material_id(), *volume->material()); } } } }
bool STL::read(std::string input_file, Model* model) { TriangleMesh mesh; if (!STL::read(input_file, &mesh)) return false; if (mesh.facets_count() == 0) throw std::runtime_error("This STL file couldn't be read because it's empty."); ModelObject* object = model->add_object(); object->name = boost::filesystem::path(input_file).filename().string(); object->input_file = input_file; ModelVolume* volume = object->add_volume(mesh); volume->name = object->name; return true; }
void Model::convert_multipart_object() { if (this->objects.empty()) return; ModelObject* object = this->add_object(); object->input_file = this->objects.front()->input_file; for (const ModelObject* o : this->objects) { for (const ModelVolume* v : o->volumes) { ModelVolume* v2 = object->add_volume(*v); v2->name = o->name; } } for (const ModelInstance* i : this->objects.front()->instances) object->add_instance(*i); while (this->objects.size() > 1) this->delete_object(0); }
bool STL::read(std::string input_file, Model* model) { // TODO: encode file name // TODO: check that file exists TriangleMesh mesh; if (!STL::read(input_file, &mesh)) return false; if (mesh.facets_count() == 0) throw std::runtime_error("This STL file couldn't be read because it's empty."); ModelObject* object = model->add_object(); object->name = input_file; // TODO: use basename() object->input_file = input_file; ModelVolume* volume = object->add_volume(mesh); volume->name = input_file; // TODO: use basename() return true; }
bool OBJ::read(std::string input_file, Model* model) { // TODO: encode file name // TODO: check that file exists tinyobj::attrib_t attrib; std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; std::string err; boost::nowide::ifstream ifs(input_file); bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &ifs); if (!err.empty()) { // `err` may contain warning message. std::cerr << err << std::endl; } if (!ret) throw std::runtime_error("Error while reading OBJ file"); ModelObject* object = model->add_object(); object->name = boost::filesystem::path(input_file).filename().string(); object->input_file = input_file; // Loop over shapes and add a volume for each one. for (std::vector<tinyobj::shape_t>::const_iterator shape = shapes.begin(); shape != shapes.end(); ++shape) { Pointf3s points; std::vector<Point3> facets; // Read vertices. assert((attrib.vertices.size() % 3) == 0); for (size_t v = 0; v < attrib.vertices.size(); v += 3) { points.push_back(Pointf3( attrib.vertices[v], attrib.vertices[v+1], attrib.vertices[v+2] )); } // Loop over facets of the current shape. for (size_t f = 0; f < shape->mesh.num_face_vertices.size(); ++f) { // tiny_obj_loader should triangulate any facet with more than 3 vertices assert((shape->mesh.num_face_vertices[f] % 3) == 0); facets.push_back(Point3( shape->mesh.indices[f*3+0].vertex_index, shape->mesh.indices[f*3+1].vertex_index, shape->mesh.indices[f*3+2].vertex_index )); } TriangleMesh mesh(points, facets); mesh.check_topology(); ModelVolume* volume = object->add_volume(mesh); volume->name = object->name; } return true; }