Comparar commits
13 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| d36934e35b | |||
| 41f7258e25 | |||
| 24cb4fbb36 | |||
| 6fa022013d | |||
| 9274846970 | |||
| 9050f8da53 | |||
| f7039848c2 | |||
| d4e27d8bbb | |||
| 13f5ebe9d7 | |||
| db787c7cab | |||
| 21a04beb25 | |||
| 1565e979ec | |||
| 927395630b |
@@ -13,6 +13,12 @@ endif()
|
||||
# Add warnings
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
|
||||
if(NOT APPLE AND NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} libs)
|
||||
|
||||
add_library(clipper STATIC libs/clipper/clipper.cpp)
|
||||
@@ -54,6 +60,9 @@ protobuf_generate_cpp(engine_PB_SRCS engine_PB_HEADERS Cura.proto)
|
||||
add_executable(CuraEngine ${engine_SRCS} ${engine_PB_SRCS})
|
||||
target_link_libraries(CuraEngine clipper Arcus)
|
||||
|
||||
add_executable(Test src/test.cpp)
|
||||
target_link_libraries(Test clipper)
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(CuraEngine pthread)
|
||||
endif()
|
||||
|
||||
@@ -167,6 +167,9 @@ void CommandSocket::sendPolygons(PolygonType type, int layer_nr, Polygons& polyg
|
||||
{
|
||||
if(!d->currentSlicedObject)
|
||||
return;
|
||||
|
||||
if (polygons.size() == 0)
|
||||
return;
|
||||
|
||||
Cura::Layer* layer = d->getLayerById(layer_nr);
|
||||
|
||||
|
||||
+63
-35
@@ -183,7 +183,7 @@ private:
|
||||
}
|
||||
|
||||
gcode.setFlavor(getSettingAsGCodeFlavor("machine_gcode_flavor"));
|
||||
gcode.setRetractionSettings(getSettingInMicrons("machine_switch_extruder_retraction_amount"), getSettingInMillimetersPerSecond("material_switch_extruder_retraction_speed"), getSettingInMillimetersPerSecond("material_switch_extruder_prime_speed"), getSettingInMicrons("retraction_extrusion_window"), getSettingInMicrons("retraction_count_max"));
|
||||
gcode.setRetractionSettings(getSettingInMicrons("machine_switch_extruder_retraction_amount"), getSettingInMillimetersPerSecond("material_switch_extruder_retraction_speed"), getSettingInMillimetersPerSecond("material_switch_extruder_prime_speed"), getSettingInMicrons("retraction_extrusion_window"), getSettingAsCount("retraction_count_max"));
|
||||
}
|
||||
|
||||
bool prepareModel(SliceDataStorage& storage, PrintObject* object) /// slices the model
|
||||
@@ -195,11 +195,16 @@ private:
|
||||
log("Slicing model...\n");
|
||||
int initial_layer_thickness = object->getSettingInMicrons("layer_height_0");
|
||||
int layer_thickness = object->getSettingInMicrons("layer_height");
|
||||
int layer_count = (storage.model_max.z - (initial_layer_thickness - layer_thickness / 2)) / layer_thickness + 1;
|
||||
if (object->getSettingAsPlatformAdhesion("adhesion_type") == Adhesion_Raft)
|
||||
{
|
||||
initial_layer_thickness = layer_thickness;
|
||||
}
|
||||
int initial_slice_z = (initial_layer_thickness - layer_thickness / 2);
|
||||
int layer_count = (storage.model_max.z - initial_slice_z) / layer_thickness + 1;
|
||||
std::vector<Slicer*> slicerList;
|
||||
for(Mesh& mesh : object->meshes)
|
||||
{
|
||||
Slicer* slicer = new Slicer(&mesh, initial_layer_thickness - layer_thickness / 2, layer_thickness, layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching"));
|
||||
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)
|
||||
@@ -255,6 +260,7 @@ private:
|
||||
object->clear();///Clear the mesh data, it is no longer needed after this point, and it saves a lot of memory.
|
||||
|
||||
log("Generating layer parts...\n");
|
||||
storage.meshes.reserve(slicerList.size());
|
||||
for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++)
|
||||
{
|
||||
storage.meshes.emplace_back(&object->meshes[meshIdx]);
|
||||
@@ -263,11 +269,24 @@ private:
|
||||
delete slicerList[meshIdx];
|
||||
|
||||
bool has_raft = meshStorage.settings->getSettingAsPlatformAdhesion("adhesion_type") == Adhesion_Raft;
|
||||
//Add the raft offset to each layer.
|
||||
for(unsigned int layer_nr=0; layer_nr<meshStorage.layers.size(); layer_nr++)
|
||||
{
|
||||
//Add the raft offset to each layer.
|
||||
if (has_raft)
|
||||
meshStorage.layers[layer_nr].printZ += meshStorage.settings->getSettingInMicrons("raft_base_thickness") + meshStorage.settings->getSettingInMicrons("raft_interface_thickness") + getSettingAsCount("raft_surface_layers") * getSettingInMicrons("raft_surface_thickness");
|
||||
{
|
||||
meshStorage.layers[layer_nr].printZ +=
|
||||
meshStorage.settings->getSettingInMicrons("raft_base_thickness")
|
||||
+ meshStorage.settings->getSettingInMicrons("raft_interface_thickness")
|
||||
+ meshStorage.settings->getSettingAsCount("raft_surface_layers") * getSettingInMicrons("layer_height") //raft_surface_thickness")
|
||||
+ meshStorage.settings->getSettingInMicrons("raft_airgap")
|
||||
- initial_slice_z;
|
||||
}
|
||||
else
|
||||
{
|
||||
meshStorage.layers[layer_nr].printZ +=
|
||||
meshStorage.settings->getSettingInMicrons("layer_height_0")
|
||||
- initial_slice_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
log("Generated layer parts in %5.3fs\n", timeKeeper.restart());
|
||||
@@ -309,26 +328,33 @@ private:
|
||||
{
|
||||
if(commandSocket)
|
||||
{
|
||||
commandSocket->sendLayerInfo(layer_nr, mesh.layers[layer_nr].printZ, layer_nr == 0 ? mesh.settings->getSettingInMicrons("layer_height_0") : mesh.settings->getSettingInMicrons("layer_height"));
|
||||
int initial_layer_thickness = mesh.settings->getSettingInMicrons("layer_height_0");
|
||||
int layer_thickness = mesh.settings->getSettingInMicrons("layer_height");
|
||||
if (mesh.settings->getSettingAsPlatformAdhesion("adhesion_type") == Adhesion_Raft)
|
||||
{
|
||||
initial_layer_thickness = layer_thickness;
|
||||
}
|
||||
commandSocket->sendLayerInfo(layer_nr, mesh.layers[layer_nr].printZ, layer_nr == 0 ? initial_layer_thickness : layer_thickness);
|
||||
}
|
||||
|
||||
int insetCount = mesh.settings->getSettingAsCount("wall_line_count");
|
||||
if (mesh.settings->getSettingBoolean("magic_spiralize") && static_cast<int>(layer_nr) < mesh.settings->getSettingAsCount("bottom_layers") && layer_nr % 2 == 1)//Add extra insets every 2 layers when spiralizing, this makes bottoms of cups watertight.
|
||||
insetCount += 5;
|
||||
SliceLayer* layer = &mesh.layers[layer_nr];
|
||||
int extrusionWidth = mesh.settings->getSettingInMicrons("wall_line_width_x");
|
||||
int wall_line_width_0 = mesh.settings->getSettingInMicrons("wall_line_width_0");
|
||||
int wall_line_width_x = mesh.settings->getSettingInMicrons("wall_line_width_x");
|
||||
int inset_count = insetCount;
|
||||
if (mesh.settings->getSettingBoolean("alternate_extra_perimeter"))
|
||||
inset_count += layer_nr % 2;
|
||||
generateInsets(layer, extrusionWidth, inset_count, mesh.settings->getSettingBoolean("wall_overlap_avoid_enabled"));
|
||||
generateInsets(layer, wall_line_width_0, wall_line_width_x, inset_count, mesh.settings->getSettingBoolean("wall_overlap_avoid_enabled"));
|
||||
|
||||
for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++)
|
||||
{
|
||||
if (layer->parts[partNr].insets.size() > 0)
|
||||
{
|
||||
sendPolygons(Inset0Type, layer_nr, layer->parts[partNr].insets[0], extrusionWidth);
|
||||
sendPolygons(Inset0Type, layer_nr, layer->parts[partNr].insets[0], wall_line_width_x);
|
||||
for(unsigned int inset=1; inset<layer->parts[partNr].insets.size(); inset++)
|
||||
sendPolygons(InsetXType, layer_nr, layer->parts[partNr].insets[inset], extrusionWidth);
|
||||
sendPolygons(InsetXType, layer_nr, layer->parts[partNr].insets[inset], wall_line_width_x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,7 +451,12 @@ private:
|
||||
generateSkins(layer_nr, mesh, extrusionWidth, mesh.settings->getSettingAsCount("bottom_layers"), mesh.settings->getSettingAsCount("top_layers"), mesh.settings->getSettingAsCount("skin_outline_count"), mesh.settings->getSettingBoolean("wall_overlap_avoid_enabled"));
|
||||
if (mesh.settings->getSettingInMicrons("infill_line_distance") > 0)
|
||||
{
|
||||
generateSparse(layer_nr, mesh, extrusionWidth, mesh.settings->getSettingAsCount("bottom_layers"), mesh.settings->getSettingAsCount("top_layers"));
|
||||
int infill_skin_overlap = 0;
|
||||
if (mesh.settings->getSettingInMicrons("infill_line_distance") > mesh.settings->getSettingInMicrons("infill_line_width") + 10)
|
||||
{
|
||||
infill_skin_overlap = extrusionWidth / 2;
|
||||
}
|
||||
generateSparse(layer_nr, mesh, extrusionWidth, infill_skin_overlap);
|
||||
if (mesh.settings->getSettingString("fill_perimeter_gaps") == "Skin")
|
||||
{
|
||||
generatePerimeterGaps(layer_nr, mesh, extrusionWidth, mesh.settings->getSettingAsCount("bottom_layers"), mesh.settings->getSettingAsCount("top_layers"));
|
||||
@@ -556,18 +587,18 @@ private:
|
||||
raft_base_config.setLayerHeight(getSettingInMicrons("raft_base_thickness"));
|
||||
raft_base_config.setFlow(getSettingInPercentage("material_flow"));
|
||||
GCodePathConfig raft_interface_config(&storage.retraction_config, "SUPPORT");
|
||||
raft_interface_config.setSpeed(getSettingInMillimetersPerSecond("raft_interface_speed"));
|
||||
raft_interface_config.setLineWidth(getSettingInMicrons("raft_interface_linewidth"));
|
||||
raft_interface_config.setSpeed(getSettingInMillimetersPerSecond("raft_base_speed"));
|
||||
raft_interface_config.setLineWidth(getSettingInMicrons("raft_base_linewidth"));
|
||||
raft_interface_config.setLayerHeight(getSettingInMicrons("raft_base_thickness"));
|
||||
raft_interface_config.setFlow(getSettingInPercentage("material_flow"));
|
||||
GCodePathConfig raft_surface_config(&storage.retraction_config, "SUPPORT");
|
||||
raft_surface_config.setSpeed(getSettingInMillimetersPerSecond("raft_surface_speed"));
|
||||
raft_surface_config.setLineWidth(getSettingInMicrons("raft_surface_line_width"));
|
||||
raft_surface_config.setSpeed(getSettingInMillimetersPerSecond("raft_base_speed"));
|
||||
raft_surface_config.setLineWidth(getSettingInMicrons("raft_base_linewidth"));
|
||||
raft_surface_config.setLayerHeight(getSettingInMicrons("raft_base_thickness"));
|
||||
raft_surface_config.setFlow(getSettingInPercentage("material_flow"));
|
||||
|
||||
{
|
||||
gcode.writeLayerComment(-2);
|
||||
gcode.writeLayerComment(-3);
|
||||
gcode.writeComment("RAFT");
|
||||
GCodePlanner gcodeLayer(gcode, &storage.retraction_config, getSettingInMillimetersPerSecond("speed_travel"), getSettingInMicrons("retraction_min_travel"));
|
||||
if (getSettingAsIndex("support_extruder_nr") > 0)
|
||||
@@ -580,19 +611,21 @@ private:
|
||||
generateLineInfill(storage.raftOutline, offset_from_poly_outline, raftLines, getSettingInMicrons("raft_base_linewidth"), getSettingInMicrons("raft_line_spacing"), getSettingInPercentage("fill_overlap"), 0);
|
||||
gcodeLayer.addLinesByOptimizer(raftLines, &raft_base_config);
|
||||
|
||||
gcode.writeFanCommand(getSettingInPercentage("raft_base_fan_speed"));
|
||||
gcode.writeFanCommand(getSettingInPercentage("cool_fan_speed_max"));
|
||||
gcodeLayer.writeGCode(false, getSettingInMicrons("raft_base_thickness"));
|
||||
}
|
||||
|
||||
{ /// this code block is about something which is of yet unknown
|
||||
gcode.writeLayerComment(-1);
|
||||
{
|
||||
gcode.writeLayerComment(-2);
|
||||
gcode.writeComment("RAFT");
|
||||
GCodePlanner gcodeLayer(gcode, &storage.retraction_config, getSettingInMillimetersPerSecond("speed_travel"), getSettingInMicrons("retraction_min_travel"));
|
||||
gcode.setZ(getSettingInMicrons("raft_base_thickness") + getSettingInMicrons("raft_interface_thickness"));
|
||||
|
||||
Polygons raftLines;
|
||||
int offset_from_poly_outline = 0;
|
||||
generateLineInfill(storage.raftOutline, offset_from_poly_outline, raftLines, getSettingInMicrons("raft_interface_line_width"), getSettingInMicrons("raft_interface_line_spacing"), getSettingInPercentage("fill_overlap"), getSettingAsCount("raft_surface_layers") > 0 ? 45 : 90);
|
||||
int raft_interface_line_width = getSettingInMicrons("wall_line_width_x"); // getSettingInMicrons("raft_interface_line_width")
|
||||
int raft_interface_line_spacing = getSettingInMicrons("raft_line_spacing"); // getSettingInMicrons("raft_interface_line_spacing")
|
||||
generateLineInfill(storage.raftOutline, offset_from_poly_outline, raftLines, raft_interface_line_width, raft_interface_line_spacing, getSettingInPercentage("fill_overlap"), getSettingAsCount("raft_surface_layers") > 0 ? 45 : 90);
|
||||
gcodeLayer.addLinesByOptimizer(raftLines, &raft_interface_config);
|
||||
|
||||
gcodeLayer.writeGCode(false, getSettingInMicrons("raft_interface_thickness"));
|
||||
@@ -602,12 +635,15 @@ private:
|
||||
{
|
||||
gcode.writeLayerComment(-1);
|
||||
gcode.writeComment("RAFT");
|
||||
int raft_surface_thickness = getSettingInMicrons("layer_height"); // getSettingInMicrons("raft_surface_thickness")
|
||||
GCodePlanner gcodeLayer(gcode, &storage.retraction_config, getSettingInMillimetersPerSecond("speed_travel"), getSettingInMicrons("retraction_min_travel"));
|
||||
gcode.setZ(getSettingInMicrons("raft_base_thickness") + getSettingInMicrons("raft_interface_thickness") + getSettingInMicrons("raft_surface_thickness")*raftSurfaceLayer);
|
||||
gcode.setZ(getSettingInMicrons("raft_base_thickness") + getSettingInMicrons("raft_interface_thickness") + raft_surface_thickness*raftSurfaceLayer);
|
||||
|
||||
Polygons raftLines;
|
||||
int offset_from_poly_outline = 0;
|
||||
generateLineInfill(storage.raftOutline, offset_from_poly_outline, raftLines, getSettingInMicrons("raft_surface_line_width"), getSettingInMicrons("raft_surface_line_spacing"), getSettingInPercentage("fill_overlap"), 90 * raftSurfaceLayer);
|
||||
int raft_surface_line_width = getSettingInMicrons("wall_line_width_0"); // getSettingInMicrons("raft_surface_line_width")
|
||||
int raft_surface_line_spacing = raft_surface_line_width; // getSettingInMicrons("raft_surface_line_spacing")
|
||||
generateLineInfill(storage.raftOutline, offset_from_poly_outline, raftLines, raft_surface_line_width, raft_surface_line_spacing, getSettingInPercentage("fill_overlap"), (raftSurfaceLayer % 2 == 0)? 0 : 90);
|
||||
gcodeLayer.addLinesByOptimizer(raftLines, &raft_surface_config);
|
||||
|
||||
gcodeLayer.writeGCode(false, getSettingInMicrons("raft_interface_thickness"));
|
||||
@@ -620,7 +656,7 @@ private:
|
||||
if (commandSocket) commandSocket->sendProgress(2.0/3.0 + 1.0/3.0 * float(layer_nr) / float(totalLayers));
|
||||
|
||||
int layer_thickness = getSettingInMicrons("layer_height");
|
||||
if (layer_nr == 0)
|
||||
if (layer_nr == 0 && !has_raft)
|
||||
{
|
||||
layer_thickness = getSettingInMicrons("layer_height_0");
|
||||
}
|
||||
@@ -680,17 +716,9 @@ private:
|
||||
gcode.writeLayerComment(layer_nr);
|
||||
|
||||
GCodePlanner gcodeLayer(gcode, &storage.retraction_config, getSettingInMillimetersPerSecond("speed_travel"), getSettingInMicrons("retraction_min_travel"));
|
||||
int32_t z = getSettingInMicrons("layer_height_0") + layer_nr * getSettingInMicrons("layer_height");
|
||||
if (has_raft)
|
||||
{
|
||||
z += getSettingInMicrons("raft_base_thickness") + getSettingInMicrons("raft_interface_thickness") + getSettingAsCount("raft_surface_layers")*getSettingInMicrons("raft_surface_thickness");
|
||||
if (layer_nr == 0)
|
||||
{
|
||||
z += getSettingInMicrons("raft_airgap_layer_0");
|
||||
} else {
|
||||
z += getSettingInMicrons("raft_airgap");
|
||||
}
|
||||
}
|
||||
|
||||
int z = storage.meshes[0].layers[layer_nr].printZ;
|
||||
|
||||
gcode.setZ(z);
|
||||
gcode.resetStartPosition();
|
||||
|
||||
@@ -751,7 +779,7 @@ private:
|
||||
gcode.writeFanCommand(fanSpeed);
|
||||
}
|
||||
|
||||
gcodeLayer.writeGCode(getSettingBoolean("cool_lift_head"), layer_nr > 0 ? getSettingInMicrons("layer_height") : getSettingInMicrons("layer_height_0"));
|
||||
gcodeLayer.writeGCode(getSettingBoolean("cool_lift_head"), layer_nr > 0 || getSettingAsPlatformAdhesion("adhesion_type") == Adhesion_Raft? getSettingInMicrons("layer_height") : getSettingInMicrons("layer_height_0"));
|
||||
if (commandSocket)
|
||||
commandSocket->sendGCodeLayer();
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ void GCodeExport::setRetractionSettings(int extruderSwitchRetraction, int extrud
|
||||
this->extruderSwitchRetractionSpeed = extruderSwitchRetractionSpeed;
|
||||
this->extruderSwitchPrimeSpeed = extruderSwitchPrimeSpeed;
|
||||
this->retraction_extrusion_window = INT2MM(retraction_extrusion_window);
|
||||
this->retraction_count_max = INT2MM(retraction_count_max);
|
||||
this->retraction_count_max = retraction_count_max;
|
||||
}
|
||||
|
||||
void GCodeExport::setZ(int z)
|
||||
@@ -337,7 +337,7 @@ void GCodeExport::writeRetraction(RetractionConfig* config, bool force)
|
||||
if (config->amount <= 0)
|
||||
return;
|
||||
|
||||
if (!force && retraction_count_max > 0 && extrusion_amount_at_previous_n_retractions.size() == retraction_count_max - 1
|
||||
if (!force && retraction_count_max > 0 && int(extrusion_amount_at_previous_n_retractions.size()) == retraction_count_max - 1
|
||||
&& extrusion_amount < extrusion_amount_at_previous_n_retractions.back() + retraction_extrusion_window)
|
||||
return;
|
||||
|
||||
@@ -362,7 +362,7 @@ void GCodeExport::writeRetraction(RetractionConfig* config, bool force)
|
||||
isZHopped = true;
|
||||
}
|
||||
extrusion_amount_at_previous_n_retractions.push_front(extrusion_amount);
|
||||
if (extrusion_amount_at_previous_n_retractions.size() == retraction_count_max)
|
||||
if (int(extrusion_amount_at_previous_n_retractions.size()) == retraction_count_max)
|
||||
{
|
||||
extrusion_amount_at_previous_n_retractions.pop_back();
|
||||
}
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ private:
|
||||
int extruderSwitchRetractionSpeed;
|
||||
int extruderSwitchPrimeSpeed;
|
||||
double retraction_extrusion_window;
|
||||
double retraction_count_max;
|
||||
int retraction_count_max;
|
||||
std::deque<double> extrusion_amount_at_previous_n_retractions; // in mm or mm^3
|
||||
Point3 currentPosition;
|
||||
Point3 startPosition;
|
||||
|
||||
@@ -238,13 +238,13 @@ void GCodePlanner::writeGCode(bool liftHeadIfNeeded, int layerThickness)
|
||||
p0 = gcode.getPositionXY();
|
||||
for(unsigned int x=n; x<i-1; x+=2)
|
||||
{
|
||||
int64_t oldLen = vSize(p0 - paths[x].points[0]);
|
||||
int64_t new_width = vSize(p0 - paths[x].points[0]); // = old_length
|
||||
Point newPoint = (paths[x].points[0] + paths[x+1].points[0]) / 2;
|
||||
int64_t newLen = vSize(gcode.getPositionXY() - newPoint);
|
||||
if (newLen > 0)
|
||||
int64_t old_width = path->config->getLineWidth();
|
||||
if (old_width > 0)
|
||||
{
|
||||
if (oldLen > 0)
|
||||
gcode.writeMove(newPoint, speed * newLen / oldLen, path->config->getExtrusionMM3perMM());
|
||||
if (new_width > 0)
|
||||
gcode.writeMove(newPoint, speed * old_width / new_width, path->config->getExtrusionMM3perMM() * new_width / old_width);
|
||||
else
|
||||
gcode.writeMove(newPoint, speed, path->config->getExtrusionMM3perMM());
|
||||
}
|
||||
|
||||
+9
-6
@@ -4,9 +4,9 @@
|
||||
#include "utils/polygonUtils.h"
|
||||
namespace cura {
|
||||
|
||||
void generateInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters)
|
||||
void generateInsets(SliceLayerPart* part, int line_width_0, int line_width_x, int insetCount, bool avoidOverlappingPerimeters)
|
||||
{
|
||||
int combBoundaryInset = extrusionWidth/2; // hard coded value
|
||||
int combBoundaryInset = line_width_x/2; // hard coded value
|
||||
part->combBoundery = part->outline.offset(-combBoundaryInset);
|
||||
if (insetCount == 0)
|
||||
{
|
||||
@@ -19,10 +19,13 @@ void generateInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bo
|
||||
part->insets.push_back(Polygons());
|
||||
if (i == 0)
|
||||
{
|
||||
offsetSafe(part->outline, - extrusionWidth/2, extrusionWidth, part->insets[i], avoidOverlappingPerimeters);
|
||||
offsetSafe(part->outline, - line_width_x/2, line_width_x, part->insets[i], avoidOverlappingPerimeters);
|
||||
} else if (i == 1)
|
||||
{
|
||||
offsetExtrusionWidth(part->insets[i-1], true, line_width_0, part->insets[i], &part->perimeterGaps, avoidOverlappingPerimeters);
|
||||
} else
|
||||
{
|
||||
offsetExtrusionWidth(part->insets[i-1], true, extrusionWidth, part->insets[i], &part->perimeterGaps, avoidOverlappingPerimeters);
|
||||
offsetExtrusionWidth(part->insets[i-1], true, line_width_x, part->insets[i], &part->perimeterGaps, avoidOverlappingPerimeters);
|
||||
}
|
||||
|
||||
optimizePolygons(part->insets[i]);
|
||||
@@ -35,11 +38,11 @@ void generateInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bo
|
||||
}
|
||||
|
||||
|
||||
void generateInsets(SliceLayer* layer, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters)
|
||||
void generateInsets(SliceLayer* layer, int line_width_0, int line_width_x, int insetCount, bool avoidOverlappingPerimeters)
|
||||
{
|
||||
for(unsigned int partNr = 0; partNr < layer->parts.size(); partNr++)
|
||||
{
|
||||
generateInsets(&layer->parts[partNr], extrusionWidth, insetCount, avoidOverlappingPerimeters);
|
||||
generateInsets(&layer->parts[partNr], line_width_0, line_width_x, insetCount, avoidOverlappingPerimeters);
|
||||
}
|
||||
|
||||
//Remove the parts which did not generate an inset. As these parts are too small to print,
|
||||
|
||||
+6
-4
@@ -11,21 +11,23 @@ namespace cura
|
||||
* Generates the insets / perimeters for a single layer part.
|
||||
*
|
||||
* \param part The part for which to generate the insets.
|
||||
* \param extrusionWidth extrusionWidth
|
||||
* \param line_width_0 Line width of the outer wall
|
||||
* \param line_width_x Line width of other walls
|
||||
* \param insetCount The number of insets to to generate
|
||||
* \param avoidOverlappingPerimeters Whether to remove the parts of two consecutive perimeters where they have overlap (and store the gaps thus created in the \p part)
|
||||
*/
|
||||
void generateInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters);
|
||||
void generateInsets(SliceLayerPart* part, int line_width_0, int line_width_x, int insetCount, bool avoidOverlappingPerimeters);
|
||||
|
||||
/*!
|
||||
* Generates the insets / perimeters for all parts in a layer.
|
||||
*
|
||||
* \param layer The layer for which to generate the insets.
|
||||
* \param extrusionWidth extrusionWidth
|
||||
* \param line_width_0 Line width of the outer wall
|
||||
* \param line_width_x Line width of other walls
|
||||
* \param insetCount The number of insets to to generate
|
||||
* \param avoidOverlappingPerimeters Whether to remove the parts of two consecutive perimeters where they have overlap (and store the gaps thus created in the \p part)
|
||||
*/
|
||||
void generateInsets(SliceLayer* layer, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters);
|
||||
void generateInsets(SliceLayer* layer, int line_width_0, int line_width_x, int insetCount, bool avoidOverlappingPerimeters);
|
||||
|
||||
}//namespace cura
|
||||
|
||||
|
||||
+3
-4
@@ -95,14 +95,13 @@ void generateSkinInsets(SliceLayerPart* part, int extrusionWidth, int insetCount
|
||||
}
|
||||
}
|
||||
|
||||
void generateSparse(int layerNr, SliceMeshStorage& storage, int extrusionWidth, int downSkinCount, int upSkinCount)
|
||||
void generateSparse(int layerNr, SliceMeshStorage& storage, int extrusionWidth, int infill_skin_overlap)
|
||||
{
|
||||
int extra_sparse_inset_during_clipping = extrusionWidth / 2;
|
||||
SliceLayer& layer = storage.layers[layerNr];
|
||||
|
||||
for(SliceLayerPart& part : layer.parts)
|
||||
{
|
||||
Polygons sparse = part.insets.back().offset(-extrusionWidth / 2 - extra_sparse_inset_during_clipping);
|
||||
Polygons sparse = part.insets.back().offset(-extrusionWidth / 2 - infill_skin_overlap);
|
||||
|
||||
for(SliceLayerPart& part2 : layer.parts)
|
||||
{
|
||||
@@ -116,7 +115,7 @@ void generateSparse(int layerNr, SliceMeshStorage& storage, int extrusionWidth,
|
||||
}
|
||||
sparse.removeSmallAreas(3.0);//(2 * M_PI * INT2MM(config.extrusionWidth) * INT2MM(config.extrusionWidth)) * 3;
|
||||
|
||||
part.sparse_outline.push_back(sparse.offset(extra_sparse_inset_during_clipping));
|
||||
part.sparse_outline.push_back(sparse.offset(infill_skin_overlap));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -53,8 +53,14 @@ void generateSkinAreas(int layerNr, SliceMeshStorage& storage, int extrusionWidt
|
||||
*/
|
||||
void generateSkinInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters);
|
||||
|
||||
|
||||
void generateSparse(int layerNr, SliceMeshStorage& storage, int extrusionWidth, int downSkinCount, int upSkinCount);
|
||||
/*!
|
||||
* Generate Infill
|
||||
* \param layerNr The index of the layer for which to generate the infill
|
||||
* \param part The part where the insets (input) are stored and where the infill (output) is stored.
|
||||
* \param extrusionWidth width of the wall lines
|
||||
* \param infill_skin_overlap overlap distance between infill and skin
|
||||
*/
|
||||
void generateSparse(int layerNr, SliceMeshStorage& storage, int extrusionWidth, int infill_skin_overlap);
|
||||
void combineSparseLayers(int layerNr, SliceMeshStorage& storage, int amount);
|
||||
|
||||
}//namespace cura
|
||||
|
||||
+4
-1
@@ -271,6 +271,7 @@ void SlicerLayer::makePolygons(Mesh* mesh, bool keep_none_closed, bool extensive
|
||||
polygonList.add(openPolygonList[n]);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i=0;i<openPolygonList.size();i++)
|
||||
{
|
||||
if (openPolygonList[i].size() > 0)
|
||||
@@ -298,7 +299,9 @@ void SlicerLayer::makePolygons(Mesh* mesh, bool keep_none_closed, bool extensive
|
||||
|
||||
//Finally optimize all the polygons. Every point removed saves time in the long run.
|
||||
optimizePolygons(polygonList);
|
||||
|
||||
|
||||
polygonList = polygonList.removeDegenerateVerts(); // remove verts connected to overlapping line segments
|
||||
|
||||
int xy_offset = mesh->getSettingInMicrons("xy_offset");
|
||||
if (xy_offset != 0)
|
||||
{
|
||||
|
||||
+1
-2
@@ -31,7 +31,6 @@ void generateSupportAreas(SliceDataStorage& storage, SliceMeshStorage* object, i
|
||||
|
||||
double supportAngle = object->settings->getSettingInAngleRadians("support_angle");
|
||||
bool supportOnBuildplateOnly = support_type == Support_PlatformOnly;
|
||||
int supportXYDistance = object->settings->getSettingInMicrons("support_xy_distance");
|
||||
int supportZDistance = object->settings->getSettingInMicrons("support_z_distance");
|
||||
int supportZDistanceBottom = object->settings->getSettingInMicrons("support_bottom_distance");
|
||||
int supportZDistanceTop = object->settings->getSettingInMicrons("support_top_distance");
|
||||
@@ -50,7 +49,7 @@ void generateSupportAreas(SliceDataStorage& storage, SliceMeshStorage* object, i
|
||||
|
||||
int layerThickness = object->settings->getSettingInMicrons("layer_height");
|
||||
int extrusionWidth = object->settings->getSettingInMicrons("wall_line_width_x"); // TODO check for layer0extrusionWidth!
|
||||
|
||||
int supportXYDistance = object->settings->getSettingInMicrons("support_xy_distance") + extrusionWidth / 2;
|
||||
|
||||
|
||||
|
||||
|
||||
+42
-1
@@ -163,6 +163,7 @@ void test_BucketGrid2D()
|
||||
//bg.debug();
|
||||
}*/
|
||||
|
||||
/*
|
||||
#include <math.h>
|
||||
#include "utils/gettime.h"
|
||||
void test_findClosestConnection()
|
||||
@@ -264,8 +265,48 @@ void test_findClosestConnection()
|
||||
std::cerr << "evalTime : " << evalTime << std::endl;
|
||||
std::cerr << "totalLength : " << totalLength << std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
void test_clipper()
|
||||
{
|
||||
Polygon p;
|
||||
p.emplace_back(0, 11004);
|
||||
p.emplace_back(0, 10129);
|
||||
p.emplace_back(0, 9185);
|
||||
p.emplace_back(0, 8477);
|
||||
p.emplace_back(1, 8491);
|
||||
p.emplace_back(418, 8861);
|
||||
p.emplace_back(1080, 9389);
|
||||
p.emplace_back(2106, 10142);
|
||||
p.emplace_back(3000, 10757);
|
||||
p.emplace_back(3000, 12010);
|
||||
p.emplace_back(3000, 12790);
|
||||
p.emplace_back(3000, 13485);
|
||||
p.emplace_back(3000, 14088);
|
||||
p.emplace_back(3000, 14601);
|
||||
p.emplace_back(3000, 15354);
|
||||
p.emplace_back(3000, 24867);
|
||||
p.emplace_back(3000, 25469);
|
||||
p.emplace_back(3000, 26303);
|
||||
p.emplace_back(3000, 27421);
|
||||
p.emplace_back(3000, 28242);
|
||||
p.emplace_back(2107, 28856);
|
||||
p.emplace_back(1080, 29610);
|
||||
p.emplace_back(608, 29986);
|
||||
p.emplace_back(1, 30508);
|
||||
p.emplace_back(1, 30522);
|
||||
p.emplace_back(0, 11772);
|
||||
|
||||
Polygons polys;
|
||||
polys.add(p);
|
||||
|
||||
polys.debugOutputHTML("output/problem_test.html", true);
|
||||
polys.offset(-400).debugOutputHTML("output/problem_test_offset.html", true);
|
||||
polys = polys.removeDegenerateVerts();
|
||||
polys.offset(-400).debugOutputHTML("output/problem_test_offset_solved.html", true);
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_findClosestConnection();
|
||||
// test_findClosestConnection();
|
||||
test_clipper();
|
||||
}
|
||||
+88
-1
@@ -66,6 +66,12 @@ public:
|
||||
{
|
||||
polygon->push_back(p);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void emplace_back(Args... args)
|
||||
{
|
||||
polygon->emplace_back(args...);
|
||||
}
|
||||
|
||||
void remove(unsigned int index)
|
||||
{
|
||||
@@ -344,11 +350,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
polygon->pop_back();
|
||||
}
|
||||
|
||||
ClipperLib::Path::reference back() const
|
||||
{
|
||||
return polygon->back();
|
||||
}
|
||||
|
||||
|
||||
ClipperLib::Path::iterator begin()
|
||||
{
|
||||
return polygon->begin();
|
||||
@@ -559,6 +570,47 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!
|
||||
* Removes overlapping consecutive line segments which don't delimit a positive area.
|
||||
*/
|
||||
Polygons removeDegenerateVerts()
|
||||
{
|
||||
Polygons ret;
|
||||
for (PolygonRef poly : *this)
|
||||
{
|
||||
Polygon result;
|
||||
|
||||
auto isDegenerate = [](Point& last, Point& now, Point& next)
|
||||
{
|
||||
Point last_line = now - last;
|
||||
Point next_line = next - now;
|
||||
return dot(last_line, next_line) == -1 * vSize(last_line) * vSize(next_line);
|
||||
};
|
||||
|
||||
for (unsigned int idx = 0; idx < poly.size(); idx++)
|
||||
{
|
||||
Point& last = (result.size() == 0) ? poly.back() : result.back();
|
||||
if (idx+1 == poly.size() && result.size() == 0) { break; }
|
||||
Point& next = (idx+1 == poly.size())? result[0] : poly[idx+1];
|
||||
if ( isDegenerate(last, poly[idx], next) )
|
||||
{ // lines are in the opposite direction
|
||||
// don't add vert to the result
|
||||
while (result.size() > 1 && isDegenerate(result[result.size()-2], result.back(), next) )
|
||||
{
|
||||
result.pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.add(poly[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.size() > 2) { ret.add(result); }
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*!
|
||||
* Removes the same polygons from this set (and also empty polygons).
|
||||
* Polygons are considered the same if all points lie within [same_distance] of their counterparts.
|
||||
@@ -709,6 +761,41 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void debugOutputHTML(const char* filename, bool dotTheVertices = false)
|
||||
{
|
||||
FILE* out = fopen(filename, "w");
|
||||
fprintf(out, "<!DOCTYPE html><html><body>");
|
||||
Point modelSize = max() - min();
|
||||
modelSize.X = std::max(modelSize.X, modelSize.Y);
|
||||
modelSize.Y = std::max(modelSize.X, modelSize.Y);
|
||||
Point modelMin = min();
|
||||
|
||||
fprintf(out, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"width: 500px; height:500px\">\n");
|
||||
for(Polygons& parts : splitIntoParts())
|
||||
{
|
||||
for(unsigned int j=0;j<parts.size();j++)
|
||||
{
|
||||
Polygon poly = parts[j];
|
||||
fprintf(out, "<polygon points=\"");
|
||||
for(Point& p : poly)
|
||||
{
|
||||
fprintf(out, "%f,%f ", float(p.X - modelMin.X)/modelSize.X*500, float(p.Y - modelMin.Y)/modelSize.Y*500);
|
||||
}
|
||||
if (j == 0)
|
||||
fprintf(out, "\" style=\"fill:gray; stroke:black;stroke-width:1\" />\n");
|
||||
else
|
||||
fprintf(out, "\" style=\"fill:red; stroke:black;stroke-width:1\" />\n");
|
||||
|
||||
if (dotTheVertices)
|
||||
for(Point& p : poly)
|
||||
fprintf(out, "<circle cx=\"%f\" cy=\"%f\" r=\"2\" stroke=\"black\" stroke-width=\"3\" fill=\"black\" />", float(p.X - modelMin.X)/modelSize.X*500, float(p.Y - modelMin.Y)/modelSize.Y*500);
|
||||
}
|
||||
}
|
||||
fprintf(out, "</svg>\n");
|
||||
fprintf(out, "</body></html>");
|
||||
fclose(out);
|
||||
}
|
||||
};
|
||||
|
||||
/* Axis aligned boundary box */
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário