void FffPolygonGenerator::processPlatformAdhesion(SliceDataStorage& storage) { switch(getSettingAsPlatformAdhesion("adhesion_type")) { case Adhesion_Skirt: if (getSettingInMicrons("draft_shield_height") == 0) { // draft screen replaces skirt generateSkirt(storage, getSettingInMicrons("skirt_gap"), getSettingInMicrons("skirt_line_width"), getSettingAsCount("skirt_line_count"), getSettingInMicrons("skirt_minimal_length")); } break; case Adhesion_Brim: generateSkirt(storage, 0, getSettingInMicrons("skirt_line_width"), getSettingAsCount("brim_line_count"), getSettingInMicrons("skirt_minimal_length")); break; case Adhesion_Raft: generateRaft(storage, getSettingInMicrons("raft_margin")); break; } sendPolygons(SkirtType, 0, storage.skirt, getSettingInMicrons("skirt_line_width")); }
std::vector<bool> SliceDataStorage::getExtrudersUsed() const { std::vector<bool> ret; ret.resize(meshgroup->getExtruderCount(), false); if (getSettingAsPlatformAdhesion("adhesion_type") != EPlatformAdhesion::NONE) { ret[getSettingAsIndex("adhesion_extruder_nr")] = true; { // process brim/skirt for (int extr_nr = 0; extr_nr < meshgroup->getExtruderCount(); extr_nr++) { if (skirt_brim[extr_nr].size() > 0) { ret[extr_nr] = true; continue; } } } } // TODO: ooze shield, draft shield ..? // support // support is presupposed to be present... ret[getSettingAsIndex("support_extruder_nr_layer_0")] = true; ret[getSettingAsIndex("support_infill_extruder_nr")] = true; ret[getSettingAsIndex("support_interface_extruder_nr")] = true; // all meshes are presupposed to actually have content for (const SliceMeshStorage& mesh : meshes) { if (!mesh.getSettingBoolean("anti_overhang_mesh") && !mesh.getSettingBoolean("support_mesh") ) { ret[mesh.getSettingAsIndex("extruder_nr")] = true; } } return ret; }
void FffPolygonGenerator::processPlatformAdhesion(SliceDataStorage& storage) { switch(getSettingAsPlatformAdhesion("adhesion_type")) { case EPlatformAdhesion::SKIRT: if (getSettingInMicrons("draft_shield_height") == 0) { // draft screen replaces skirt generateSkirt(storage, getSettingInMicrons("skirt_gap"), getSettingAsCount("skirt_line_count"), getSettingInMicrons("skirt_minimal_length")); } break; case EPlatformAdhesion::BRIM: generateSkirt(storage, 0, getSettingAsCount("brim_line_count"), getSettingInMicrons("skirt_minimal_length")); break; case EPlatformAdhesion::RAFT: generateRaft(storage, getSettingInMicrons("raft_margin")); break; } Polygons skirt_sent = storage.skirt[0]; for (int extruder = 1; extruder < storage.meshgroup->getExtruderCount(); extruder++) skirt_sent.add(storage.skirt[extruder]); }
bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeeper, SliceDataStorage& storage) /// slices the model { Progress::messageProgressStage(Progress::Stage::SLICING, &timeKeeper); storage.model_min = meshgroup->min(); storage.model_max = meshgroup->max(); storage.model_size = storage.model_max - storage.model_min; log("Slicing model...\n"); int initial_layer_thickness = getSettingInMicrons("layer_height_0"); if(initial_layer_thickness <= 0) //Initial layer height of 0 is not allowed. Negative layer height is nonsense. { logError("Initial layer height %i is disallowed.\n", initial_layer_thickness); return false; } int layer_thickness = getSettingInMicrons("layer_height"); if(layer_thickness <= 0) //Layer height of 0 is not allowed. Negative layer height is nonsense. { logError("Layer height %i is disallowed.\n", layer_thickness); return false; } int initial_slice_z = initial_layer_thickness - layer_thickness / 2; int layer_count = (storage.model_max.z - initial_slice_z) / layer_thickness + 1; if(layer_count <= 0) //Model is shallower than layer_height_0, so not even the first layer is sliced. Return an empty model then. { return true; //This is NOT an error state! } std::vector<Slicer*> slicerList; for(unsigned int mesh_idx = 0; mesh_idx < meshgroup->meshes.size(); mesh_idx++) { Mesh& mesh = meshgroup->meshes[mesh_idx]; Slicer* slicer = new Slicer(&mesh, initial_slice_z, layer_thickness, layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching")); slicerList.push_back(slicer); /* for(SlicerLayer& layer : slicer->layers) { //Reporting the outline here slows down the engine quite a bit, so only do so when debugging. sendPolygons("outline", layer_nr, layer.z, layer.polygonList); sendPolygons("openoutline", layer_nr, layer.openPolygonList); } */ Progress::messageProgress(Progress::Stage::SLICING, mesh_idx + 1, meshgroup->meshes.size()); } log("Layer count: %i\n", layer_count); meshgroup->clear();///Clear the mesh face and vertex data, it is no longer needed after this point, and it saves a lot of memory. Progress::messageProgressStage(Progress::Stage::PARTS, &timeKeeper); //carveMultipleVolumes(storage.meshes); generateMultipleVolumesOverlap(slicerList); // TODO!!! dont generate multi volume overlap with infill meshes! storage.meshes.reserve(slicerList.size()); // causes there to be no resize in meshes so that the pointers in sliceMeshStorage._config to retraction_config don't get invalidated. for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++) { storage.meshes.emplace_back(&meshgroup->meshes[meshIdx]); // new mesh in storage had settings from the Mesh SliceMeshStorage& meshStorage = storage.meshes.back(); Mesh& mesh = storage.meshgroup->meshes[meshIdx]; createLayerParts(meshStorage, slicerList[meshIdx], mesh.getSettingBoolean("meshfix_union_all"), mesh.getSettingBoolean("meshfix_union_all_remove_holes")); delete slicerList[meshIdx]; bool has_raft = getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::RAFT; //Add the raft offset to each layer. for(unsigned int layer_nr=0; layer_nr<meshStorage.layers.size(); layer_nr++) { SliceLayer& layer = meshStorage.layers[layer_nr]; meshStorage.layers[layer_nr].printZ += getSettingInMicrons("layer_height_0") - initial_slice_z; if (has_raft) { ExtruderTrain* train = storage.meshgroup->getExtruderTrain(getSettingAsIndex("adhesion_extruder_nr")); layer.printZ += train->getSettingInMicrons("raft_base_thickness") + train->getSettingInMicrons("raft_interface_thickness") + train->getSettingAsCount("raft_surface_layers") * train->getSettingInMicrons("raft_surface_thickness") + train->getSettingInMicrons("raft_airgap") - train->getSettingInMicrons("layer_0_z_overlap"); // shift all layers (except 0) down if (layer_nr == 0) { layer.printZ += train->getSettingInMicrons("layer_0_z_overlap"); // undo shifting down of first layer } } if (layer.parts.size() > 0 || (mesh.getSettingAsSurfaceMode("magic_mesh_surface_mode") != ESurfaceMode::NORMAL && layer.openPolyLines.size() > 0) ) { meshStorage.layer_nr_max_filled_layer = layer_nr; // last set by the highest non-empty layer } if (CommandSocket::isInstantiated()) { CommandSocket::getInstance()->sendLayerInfo(layer_nr, layer.printZ, layer_nr == 0? getSettingInMicrons("layer_height_0") : getSettingInMicrons("layer_height")); } } Progress::messageProgress(Progress::Stage::PARTS, meshIdx + 1, slicerList.size()); } return true; }
std::vector<bool> SliceDataStorage::getExtrudersUsed(int layer_nr) const { std::vector<bool> ret; ret.resize(meshgroup->getExtruderCount(), false); bool include_adhesion = true; bool include_helper_parts = true; bool include_models = true; if (layer_nr < 0) { include_models = false; if (layer_nr < -Raft::getFillerLayerCount(*this)) { include_helper_parts = false; } else { layer_nr = 0; // because the helper parts are copied from the initial layer in the filler layer include_adhesion = false; } } else if (layer_nr > 0 || getSettingAsPlatformAdhesion("adhesion_type") == EPlatformAdhesion::RAFT) { // only include adhesion only for layers where platform adhesion actually occurs // i.e. layers < 0 are for raft, layer 0 is for brim/skirt include_adhesion = false; } if (include_adhesion) { ret[getSettingAsIndex("adhesion_extruder_nr")] = true; { // process brim/skirt for (int extr_nr = 0; extr_nr < meshgroup->getExtruderCount(); extr_nr++) { if (skirt_brim[extr_nr].size() > 0) { ret[extr_nr] = true; continue; } } } } // TODO: ooze shield, draft shield ..? if (include_helper_parts) { // support if (layer_nr < int(support.supportLayers.size())) { const SupportLayer& support_layer = support.supportLayers[layer_nr]; if (layer_nr == 0) { if (support_layer.supportAreas.size() > 0) { ret[getSettingAsIndex("support_extruder_nr_layer_0")] = true; } } else { if (support_layer.supportAreas.size() > 0) { ret[getSettingAsIndex("support_infill_extruder_nr")] = true; } } if (support_layer.skin.size() > 0) { ret[getSettingAsIndex("support_interface_extruder_nr")] = true; } } } if (include_models) { for (const SliceMeshStorage& mesh : meshes) { if (layer_nr >= int(mesh.layers.size())) { continue; } const SliceLayer& layer = mesh.layers[layer_nr]; if (layer.parts.size() > 0) { ret[mesh.getSettingAsIndex("extruder_nr")] = true; } } } return ret; }
void MeshGroup::finalize() { extruder_count = getSettingAsCount("machine_extruder_count"); for (int extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++) { createExtruderTrain(extruder_nr); // create it if it didn't exist yet if (getSettingAsIndex("adhesion_extruder_nr") == extruder_nr && getSettingAsPlatformAdhesion("adhesion_type") != EPlatformAdhesion::NONE) { getExtruderTrain(extruder_nr)->setIsUsed(true); continue; } for (const Mesh& mesh : meshes) { if (mesh.getSettingBoolean("support_enable") && ( getSettingAsIndex("support_infill_extruder_nr") == extruder_nr || getSettingAsIndex("support_extruder_nr_layer_0") == extruder_nr || (getSettingBoolean("support_interface_enable") && getSettingAsIndex("support_interface_extruder_nr") == extruder_nr) ) ) { getExtruderTrain(extruder_nr)->setIsUsed(true); break; } } } for (const Mesh& mesh : meshes) { if (!mesh.getSettingBoolean("anti_overhang_mesh") && !mesh.getSettingBoolean("support_mesh") ) { getExtruderTrain(mesh.getSettingAsIndex("extruder_nr"))->setIsUsed(true); } } //If the machine settings have been supplied, offset the given position vertices to the center of vertices (0,0,0) is at the bed center. Point3 meshgroup_offset(0, 0, 0); if (!getSettingBoolean("machine_center_is_zero")) { meshgroup_offset.x = getSettingInMicrons("machine_width") / 2; meshgroup_offset.y = getSettingInMicrons("machine_depth") / 2; } // If a mesh position was given, put the mesh at this position in 3D space. for(Mesh& mesh : meshes) { Point3 mesh_offset(mesh.getSettingInMicrons("mesh_position_x"), mesh.getSettingInMicrons("mesh_position_y"), mesh.getSettingInMicrons("mesh_position_z")); if (mesh.getSettingBoolean("center_object")) { Point3 object_min = mesh.min(); Point3 object_max = mesh.max(); Point3 object_size = object_max - object_min; mesh_offset += Point3(-object_min.x - object_size.x / 2, -object_min.y - object_size.y / 2, -object_min.z); } mesh.offset(mesh_offset + meshgroup_offset); } }