Comparar commits

..

64 Commits

Autor SHA1 Mensagem Data
Mark Burton 85ac4e69bd Fix spiralize args bug - untested but this just looked wrong to me. 2017-02-02 14:00:48 +01:00
Ghostkeeper 45bb64a0c1 Always initialise distance2
It was possibly using uninitialised memory there.

Probably not contributing to CURA-3274, but I'm still committing it under there because I found it while searching for a fix.
2017-01-27 16:02:26 +01:00
Ghostkeeper c2ffb7c81d Remove 'l' formatting character and simplify+speed-up int2mm formatting
The 'l' formatting character in combination with 'd' was not allowed with MinGW on Windows. Simply formatting with 'd' is sufficient since our coordinates are allowed to be cast to integers at this stage: We won't need to square them any more or anything.

Contributes to issue CURA-3274.
2017-01-27 15:19:07 +01:00
Ghostkeeper 9c3170b277 Print debug message upon sending layer data
This should help a bit with debugging the slice loop. I hope.

Contributes to issue CURA-3274.
2017-01-25 17:45:34 +01:00
Ghostkeeper e2f89778e2 Remove p1 after inserting point next to it
Because this insertion requires dereferencing p1. If it has been removed from the list, dereferencing it would remove it from memory so that would be an invalid pointer reference.

Contributes to debugging issue CURA-3274.
2017-01-25 14:40:11 +01:00
Ghostkeeper 8f74952aca Replace last long in gcodeExport with int64_t
Previously we had a crash only on windows because the long was not long enough. Perhaps this fixes something with the slicing loop.

Contributes to issue CURA-3274.
2017-01-25 13:36:14 +01:00
Tim Kuipers 17463e1139 quick fix: accidental const (CURA-3309) 2017-01-23 17:37:17 +01:00
Tim Kuipers 8df26ae916 fix: equalize flow still equalizes after halving the line width for perimeter gaps (CURA-3309) 2017-01-23 17:36:24 +01:00
Tim Kuipers c2aa1d59bc fix: add perimeter_gaps config with line width of half the inner wall line width (CURA-3309)
also the perimeter gaps of the skin walls now have to be generated separately
2017-01-23 14:53:57 +01:00
Tim Kuipers 113202cd34 fix: types in CubicSubdiv were wrong (CURA-3196)
the sphere_slice_radius2 was a long rather than a coord_t (long long)
2017-01-20 15:23:34 +01:00
Tim Kuipers 4bc706d618 fix: perimeter gaps were introduced for the overlap between infill and skin (CURA-3179)
this caused extra overextrusion where infill and skin meet
2017-01-20 15:01:51 +01:00
Tim Kuipers 5766e2db11 fix: don't fill gaps for outer wall when spiralize is enabled (CURA-3152) 2017-01-20 14:21:14 +01:00
Tim Kuipers 671ebccdbb fix: indentation only (CURA-3271) 2017-01-20 14:08:56 +01:00
Tim Kuipers 2516165c86 fix: there were no support bottoms on top of the first model in support of the second model (CURA-3271)
All support areas are now generated before generating the interface. They are stored in supportLayer.supportAreas right after generation of the areas.
generateSupportInterface then operates on the merged supportAreas.

Note that this has a performace impact: while evaluating support interface, the support of all models is considered, rather than only the support it introduced itself.
2017-01-20 14:08:29 +01:00
Tim Kuipers 0315aaf404 fix: support top distance was one layer too high (CURA-3269) 2017-01-20 13:26:39 +01:00
Tim Kuipers 49f09ed204 fix: (anti) support meshes could f*ck up the printZ of each layer (CURA-3198)
those meshes didn't call createLayerParts and so their printZ was never set.
To determine the print height of a layer an arbitrary mesh was used to see the printZ.
2017-01-02 23:03:40 +01:00
Ghostkeeper 3e7d623c86 Make total bounding box use head coordinates
Instead of nozzle coordinates.
2016-12-20 15:49:37 +01:00
Ghostkeeper d694bff227 Remove superfluous comment
A bit witty, perhaps, but unnecessary.

Contributes to issue CURA-3137.
2016-12-15 12:03:28 +01:00
Ghostkeeper 05be030c45 Document range check for pre-computed cubes
Contributes to issue CURA-3137.
2016-12-14 15:15:20 +01:00
Ghostkeeper 3c5e745f83 Reintroduce assert for coordinates exceeding maximum int
Because we might still test with models of 2km size.

Contributes to issue CURA-3137.
2016-12-14 14:09:16 +01:00
Ghostkeeper 2e6cd36f20 Make unused parameters unnamed
This way they cannot be used any more.

Shuts the compiler up for issue CURA-3137.
2016-12-14 12:02:00 +01:00
Ghostkeeper 9fc4a427cd Removed checks of unsigned ints being >= 0
Because that's always true. Even the compiler says that.

Contributes sorta to issue CURA-3137.
2016-12-14 12:00:39 +01:00
Ghostkeeper 5729908023 Remove unused path parameter
According to the compiler, the path parameter of handleChildren was not unused, but that was only because it went recursively to subcalls to handleChildren, so it was actually also unused.

Contributes to issue CURA-3137.
2016-12-14 11:55:40 +01:00
Ghostkeeper c5b90b0ad9 Put check for empty extruder trains before size check
Could save a miniscule amount of time.

Contributes to issue CURA-3137.
2016-12-14 11:50:45 +01:00
Ghostkeeper 382343e558 Make recursion depth unsigned
It can't be negative anyway. And it helps with the signed-unsigned comparison checks.

Contributes to issue CURA-3137.
2016-12-14 11:48:46 +01:00
Ghostkeeper 68b293b880 Make subdivided cubic infill robust to 0% infill
Otherwise it would crash or loop forever.

Contributes to issue CURA-3137.
2016-12-14 11:44:34 +01:00
Ghostkeeper f867c0f53a Prevent crashing when given no extruder trains
Instead we return -1. A bit more robust.

Contributes to issue CURA-3137.
2016-12-14 11:05:05 +01:00
Ghostkeeper ee7e83d138 Merge branch 'mb-layer-height-comment' of https://github.com/smartavionics/CuraEngine into smartavionics-mb-layer-height-comment 2016-12-14 09:29:53 +01:00
Ghostkeeper 50df40c6c6 Revert "Re-use extruder train variable"
This reverts commit c9217d4738.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper 4d924fd33d Revert "Add park distance information to retraction config"
This reverts commit 23ef513cce.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper c953a726cb Revert "Add function to move filament to park position"
This reverts commit ae00cbe497.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper 7c8c0b2417 Revert "Correct speed of retraction"
This reverts commit 6925f39426.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper a834754d64 Revert "Remove some annoying compile warnings"
This reverts commit d75882a707.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper 9957a0c733 Revert "Fix updating current E value"
This reverts commit 80f8760f68.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper f6ce0b4141 Revert "Put filament in parking position when we never use it any more"
This reverts commit 3cb3e5de45.

Contributes to issue CURA-2795.
2016-12-13 15:35:47 +01:00
Ghostkeeper 120a9c440c Revert "Park filament even if printer doesn't support retraction"
This reverts commit 837f992f69.

Contributes to issue CURA-2795.
2016-12-13 15:35:46 +01:00
Ghostkeeper 59f72bdd98 Revert "Expand documentation of writePark"
This reverts commit 4f3b4f429d.

Contributes to issue CURA-2795.
2016-12-13 15:35:46 +01:00
Ghostkeeper abc43302ac Revert "Correct retraction speed"
This reverts commit 36eb3471df.

Contributes to issue CURA-2795.
2016-12-13 15:35:46 +01:00
Mark Burton c2725bdf83 Move layer_height out of the GCodeExport class - it doesn't need to be a member. 2016-12-13 13:47:39 +00:00
Tim Kuipers fb761dfd9d fix: don't generate perimeter_gaps between inner wall and infill/skin when there is no infill (CURA-3108) 2016-12-13 13:53:05 +01:00
Mark Burton 90727a0578 Merge branch 'master' into mb-layer-height-comment 2016-12-13 08:05:31 +00:00
Mark Burton fd7d1a4bd4 Add comment that reports layer height in RepRap flavour gcode. 2016-12-12 16:54:13 +00:00
Ghostkeeper 2b1266c647 Move implementation to CPP file
Contributes to issue CURA-3006.
2016-12-12 14:04:32 +01:00
Ghostkeeper 901bf47610 Move implementation to CPP file
Contributes to issue CURA-3006.
2016-12-12 13:55:47 +01:00
Ghostkeeper 80a6115537 Move implementation to CPP file
Contributes to issue CURA-3006.
2016-12-12 13:44:23 +01:00
Ghostkeeper f94ca645bd Make writeRetraction accept const ref instead of const pointer
This change was already made for CURA-2795, and upon this change was built by other commits for other issues. I had to revert CURA-2795, so that would undo the changes that the other commits depend on. Instead though, I un-reverted the change because it's nice and doesn't have anything inherently to do with CURA-2795.

Contributes to issue CURA-2795.
2016-12-12 13:11:03 +01:00
Ghostkeeper 2067644d30 Revert "Update prime speed corresponding to park retraction"
This reverts commit 6c986e6cfe.

Contributes to issue CURA-2795.
2016-12-12 12:57:15 +01:00
Ghostkeeper 0285e2f025 Revert "Add additional safety check for extruder switching off in later layers"
This reverts commit bc82fd98c9.

Contributes to issue CURA-2795.
2016-12-12 12:57:15 +01:00
Ghostkeeper 38a1ee4270 Revert "Allow going to stand-by temperature if nozzle is later used"
This reverts commit 3c0d3f1b2d.

Contributes to issue CURA-2795.
2016-12-12 12:57:15 +01:00
Ghostkeeper 63459d5cd4 Revert "Correct documentation on why the temperature is switched off later"
This reverts commit 6972101d7e.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 138691436e Revert "Correct technicality in documentation"
This reverts commit ab2c2eed4b.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper b9c5b4593b Revert "Remove unused parameter"
This reverts commit b7e9f72023.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper a0a3a24dc1 Revert "Restore park distance exception for BFB g-code"
This reverts commit b6355b69e7.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 5959b41132 Revert "Use filament park distance setting instead of direct heat & cool zones"
This reverts commit b0487fa4c7.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 3d7229c9f2 Revert "Turn extruder temperature off only if it parked the filament"
This reverts commit 84d3381be6.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper e1cfc3d93b Revert "Break retraction in two"
This reverts commit a0625aa735.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 5834540bec Revert "Rename writeRetractionMove to writeMoveFilament"
This reverts commit 7c39b6b26a.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper f191d23e17 Revert "Pass retraction configs by reference instead of pointer"
This reverts commit 7a8be50b8f.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 5114ab4218 Revert "Use writeMoveFilament to retract to parking distance"
This reverts commit cb7b7bf22a.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 9f5645ecac Revert "Protect writeMoveFilament"
This reverts commit 52220ccab8.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper 66befe5827 Revert "Correct documentation of extruder_switch parameter"
This reverts commit 4263801d16.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper c9de64f946 Revert "Use optional to denote uninitiated previous extruder temperature"
This reverts commit 460c52ea6c.

Contributes to issue CURA-2795.
2016-12-12 12:57:14 +01:00
Ghostkeeper dbfa3a0f4b Revert "Move park distance data to ExtruderTrainAttributes"
This reverts commit 7777668b86.

Contributes to issue CURA-2795.
2016-12-12 12:54:56 +01:00
Ghostkeeper 02268eb7e8 Revert "Park via E-moves instead of via a retraction"
This reverts commit 6350f47cd6.

Contributes to issue CURA-2795.
2016-12-12 12:54:56 +01:00
60 arquivos alterados com 632 adições e 8832 exclusões
+5 -9
Ver Arquivo
@@ -59,12 +59,12 @@ set(engine_SRCS # Except main.cpp.
src/gcodePlanner.cpp
src/infill.cpp
src/WallsComputation.cpp
src/layerPart.cpp
src/LayerPlanBuffer.cpp
src/Material.cpp
src/MaterialBase.cpp
src/MergeInfillLines.cpp
src/mesh.cpp
src/MeshGroup.cpp
src/multiVolumes.cpp
src/pathOrderOptimizer.cpp
src/Preheat.cpp
src/PrimeTower.cpp
@@ -72,10 +72,9 @@ set(engine_SRCS # Except main.cpp.
src/skin.cpp
src/SkirtBrim.cpp
src/sliceDataStorage.cpp
src/slicer.cpp
src/support.cpp
src/timeEstimate.cpp
src/TexturedMesh.cpp
src/TextureProcessor.cpp
src/WallsComputation.cpp
src/wallOverlap.cpp
src/Weaver.cpp
@@ -88,13 +87,10 @@ set(engine_SRCS # Except main.cpp.
src/infill/ZigzagConnectorProcessorNoEndPieces.cpp
src/infill/SubDivCube.cpp
src/slicer/LayerPart.cpp
src/slicer/MultiVolumes.cpp
src/slicer/SlicerLayer.cpp
src/slicer/Slicer.cpp
src/pathPlanning/Comb.cpp
src/pathPlanning/GCodePath.cpp
src/pathPlanning/LinePolygonsCrossings.cpp
src/pathPlanning/NozzleTempInsert.cpp
src/pathPlanning/TimeMaterialEstimates.cpp
src/progress/Progress.cpp
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1 -1
Ver Arquivo
@@ -2,7 +2,7 @@
#ifndef CONICAL_OVERHANG_H
#define CONICAL_OVERHANG_H
#include "slicer/Slicer.h"
#include "slicer.h"
namespace cura {
+46 -27
Ver Arquivo
@@ -1,5 +1,3 @@
//Copyright (c) 2016 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include <list>
@@ -196,7 +194,17 @@ void FffGcodeWriter::initConfigs(SliceDataStorage& storage)
mesh.inset0_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_0"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_0"), mesh.getSettingInMillimetersPerSecond("jerk_wall_0"), mesh.getSettingInMicrons("wall_line_width_0"), mesh.getSettingInPercentage("material_flow"));
mesh.insetX_config.init(mesh.getSettingInMillimetersPerSecond("speed_wall_x"), mesh.getSettingInMillimetersPerSecond("acceleration_wall_x"), mesh.getSettingInMillimetersPerSecond("jerk_wall_x"), mesh.getSettingInMicrons("wall_line_width_x"), mesh.getSettingInPercentage("material_flow"));
mesh.skin_config.init(mesh.getSettingInMillimetersPerSecond("speed_topbottom"), mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), mesh.getSettingInMicrons("skin_line_width"), mesh.getSettingInPercentage("material_flow"));
// The perimeter gap config follows the skin config, but has a different line width:
// wall_line_width_x divided by two because the gaps are between 0 and 1 times the wall line width
const int perimeter_gaps_line_width = mesh.getSettingInMicrons("wall_line_width_x") / 2;
double perimeter_gaps_speed = mesh.getSettingInMillimetersPerSecond("speed_topbottom");
if (mesh.getSettingBoolean("speed_equalize_flow_enabled"))
{
perimeter_gaps_speed = perimeter_gaps_speed * mesh.getSettingInMicrons("skin_line_width") / perimeter_gaps_line_width;
}
mesh.perimeter_gap_config.init(perimeter_gaps_speed, mesh.getSettingInMillimetersPerSecond("acceleration_topbottom"), mesh.getSettingInMillimetersPerSecond("jerk_topbottom"), perimeter_gaps_line_width, mesh.getSettingInPercentage("material_flow"));
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].init(mesh.getSettingInMillimetersPerSecond("speed_infill"), mesh.getSettingInMillimetersPerSecond("acceleration_infill"), mesh.getSettingInMillimetersPerSecond("jerk_infill"), mesh.getSettingInMicrons("infill_line_width") * (idx + 1), mesh.getSettingInPercentage("material_flow"));
@@ -698,7 +706,7 @@ std::vector<unsigned int> FffGcodeWriter::calculateMeshOrder(SliceDataStorage& s
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingAsIndex("extruder_nr") == extruder_nr)
{
Mesh& mesh_data = *storage.meshgroup->meshes[mesh_idx];
Mesh& mesh_data = storage.meshgroup->meshes[mesh_idx];
Point3 middle = (mesh_data.getAABB().min + mesh_data.getAABB().max) / 2;
mesh_idx_order_optimizer.addItem(Point(middle.x, middle.y), mesh_idx);
}
@@ -999,7 +1007,7 @@ void FffGcodeWriter::processInsets(GCodePlanner& gcode_layer, SliceMeshStorage*
{ // on the last normal layer first make the outer wall normally and then start a second outer wall from the same hight, but gradually moving upward
WallOverlapComputation* wall_overlap_computation(nullptr);
int wall_0_wipe_dist(0);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, mesh->getSettingInMicrons("wall_0_wipe_dist"), wall_0_wipe_dist);
gcode_layer.addPolygonsByOptimizer(part.insets[0], &mesh->insetX_config, wall_overlap_computation, EZSeamType::SHORTEST, z_seam_pos, wall_0_wipe_dist, spiralize);
}
}
int processed_inset_number = -1;
@@ -1046,9 +1054,11 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
{
int64_t z = layer_nr * getSettingInMicrons("layer_height");
const unsigned int skin_line_width = mesh->skin_config.getLineWidth();
const unsigned int perimeter_gaps_line_width = mesh->perimeter_gap_config.getLineWidth();
constexpr int perimeter_gaps_extra_offset = 15; // extra offset so that the perimeter gaps aren't created everywhere due to rounding errors
bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE;
bool fill_perimeter_gaps = mesh->getSettingAsFillPerimeterGapMode("fill_perimeter_gaps") != FillPerimeterGapMode::NOWHERE
&& !mesh->getSettingBoolean("magic_spiralize");
Point z_seam_pos(0, 0); // not used
PathOrderOptimizer part_order_optimizer(gcode_layer.getLastPosition(), z_seam_pos, EZSeamType::SHORTEST);
@@ -1118,13 +1128,6 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
Infill infill_comp(pattern, *inner_skin_outline, offset_from_inner_skin_outline, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift, perimeter_gaps_output);
infill_comp.generate(skin_polygons, skin_lines);
if (fill_perimeter_gaps)
{ // handle perimeter_gaps of skin insets
int offset = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(skin_polygons, skin_lines);
}
gcode_layer.addPolygonsByOptimizer(skin_polygons, &mesh->skin_config);
if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES)
@@ -1135,40 +1138,56 @@ void FffGcodeWriter::processSkinAndPerimeterGaps(GCodePlanner& gcode_layer, Slic
{
gcode_layer.addLinesByOptimizer(skin_lines, &mesh->skin_config, (pattern == EFillMethod::ZIG_ZAG)? SpaceFillType::PolyLines : SpaceFillType::Lines);
}
if (fill_perimeter_gaps)
{ // handle perimeter_gaps of skin insets
Polygons gap_polygons; // will remain empty
Polygons gap_lines;
int offset = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(gap_polygons, gap_lines);
gcode_layer.addLinesByOptimizer(gap_lines, &mesh->perimeter_gap_config, SpaceFillType::Lines);
}
}
if (fill_perimeter_gaps)
{ // handle perimeter gaps of normal insets
Polygons perimeter_gaps;
int line_width = mesh->inset0_config.getLineWidth();
for (unsigned int inset_idx = 0; inset_idx < part.insets.size(); inset_idx++)
for (unsigned int inset_idx = 0; inset_idx < part.insets.size() - 1; inset_idx++)
{
const Polygons outer = part.insets[inset_idx].offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
line_width = mesh->insetX_config.getLineWidth();
Polygons inner;
if (inset_idx + 1 < part.insets.size())
Polygons inner = part.insets[inset_idx + 1].offset(line_width / 2);
perimeter_gaps.add(outer.difference(inner));
}
{ // gap between inner wall and skin/infill
if (mesh->getSettingInMicrons("infill_line_distance") > 0
&& !mesh->getSettingBoolean("infill_hollow")
&& mesh->getSettingInMicrons("infill_overlap_mm") >= 0
)
{
inner = part.insets[inset_idx + 1].offset(line_width / 2);
}
else
{
inner = part.infill_area;
const Polygons outer = part.insets.back().offset(-1 * line_width / 2 - perimeter_gaps_extra_offset);
Polygons inner = part.infill_area;
for (SkinPart& skin_part : part.skin_parts)
{
inner.add(skin_part.outline);
}
inner = inner.unionPolygons();
perimeter_gaps.add(outer.difference(inner));
}
perimeter_gaps.add(outer.difference(inner));
}
Polygons skin_polygons; // unused
Polygons skin_lines; // soon to be generated gap filler lines
Polygons gap_polygons; // unused
Polygons gap_lines; // soon to be generated gap filler lines
int offset = 0;
int extra_infill_shift = 0;
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, skin_line_width, skin_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(skin_polygons, skin_lines);
Infill infill_comp(EFillMethod::LINES, perimeter_gaps, offset, perimeter_gaps_line_width, perimeter_gaps_line_width, skin_overlap, skin_angle, z, extra_infill_shift);
infill_comp.generate(gap_polygons, gap_lines);
gcode_layer.addLinesByOptimizer(skin_lines, &mesh->skin_config, SpaceFillType::Lines);
gcode_layer.addLinesByOptimizer(gap_lines, &mesh->perimeter_gap_config, SpaceFillType::Lines);
}
}
+18 -12
Ver Arquivo
@@ -4,15 +4,14 @@
#include <map> // multimap (ordered map allowing duplicate keys)
#include "utils/math.h"
#include "slicer/Slicer.h"
#include "utils/algorithm.h"
#include "slicer.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "MeshGroup.h"
#include "support.h"
#include "slicer/MultiVolumes.h"
#include "slicer/LayerPart.h"
#include "TextureProcessor.h"
#include "multiVolumes.h"
#include "layerPart.h"
#include "WallsComputation.h"
#include "SkirtBrim.h"
#include "skin.h"
@@ -89,7 +88,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
std::vector<Slicer*> slicerList;
for(unsigned int mesh_idx = 0; mesh_idx < meshgroup->meshes.size(); mesh_idx++)
{
Mesh& mesh = *meshgroup->meshes[mesh_idx];
Mesh& mesh = meshgroup->meshes[mesh_idx];
Slicer* slicer = new Slicer(&mesh, initial_slice_z, layer_thickness, slice_layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching"));
slicerList.push_back(slicer);
/*
@@ -108,7 +107,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
for(unsigned int meshIdx=0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = *storage.meshgroup->meshes[meshIdx];
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
if (mesh.getSettingBoolean("conical_overhang_enabled") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
ConicalOverhang::apply(slicerList[meshIdx], mesh.getSettingInAngleRadians("conical_overhang_angle"), layer_thickness);
@@ -117,7 +116,6 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
Progress::messageProgressStage(Progress::Stage::PARTS, &timeKeeper);
if (storage.getSettingBoolean("carve_multiple_volumes"))
{
carveMultipleVolumes(slicerList, storage.getSettingBoolean("alternate_carve_order"));
@@ -127,7 +125,7 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
storage.print_layer_count = 0;
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Mesh& mesh = *storage.meshgroup->meshes[meshIdx];
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
Slicer* slicer = slicerList[meshIdx];
if (!mesh.getSettingBoolean("anti_overhang_mesh") && !mesh.getSettingBoolean("infill_mesh"))
{
@@ -140,10 +138,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
for (unsigned int meshIdx = 0; meshIdx < slicerList.size(); meshIdx++)
{
Slicer* slicer = slicerList[meshIdx];
Mesh& mesh = *storage.meshgroup->meshes[meshIdx];
Mesh& mesh = storage.meshgroup->meshes[meshIdx];
// always make a new SliceMeshStorage, so that they have the same ordering / indexing as meshgroup.meshes
storage.meshes.emplace_back(meshgroup->meshes[meshIdx], slicer->layers.size()); // new mesh in storage had settings from the Mesh
storage.meshes.emplace_back(&meshgroup->meshes[meshIdx], slicer->layers.size()); // new mesh in storage had settings from the Mesh
SliceMeshStorage& meshStorage = storage.meshes.back();
if (mesh.getSettingBoolean("anti_overhang_mesh"))
@@ -153,6 +151,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.anti_overhang = support_layer.anti_overhang.unionPolygons(slicer_layer.polygons);
meshStorage.layers[layer_nr].printZ =
slicer_layer.z
+ getSettingInMicrons("layer_height_0")
- initial_slice_z;
}
continue;
}
@@ -163,6 +165,10 @@ bool FffPolygonGenerator::sliceModel(MeshGroup* meshgroup, TimeKeeper& timeKeepe
SupportLayer& support_layer = storage.support.supportLayers[layer_nr];
SlicerLayer& slicer_layer = slicer->layers[layer_nr];
support_layer.support_mesh.add(slicer_layer.polygons);
meshStorage.layers[layer_nr].printZ =
slicer_layer.z
+ getSettingInMicrons("layer_height_0")
- initial_slice_z;
}
continue;
}
@@ -359,8 +365,8 @@ void FffPolygonGenerator::processBasicWallsSkinInfill(SliceDataStorage& storage,
SliceMeshStorage& other_mesh = storage.meshes[other_mesh_idx];
if (other_mesh.getSettingBoolean("infill_mesh"))
{
AABB3D aabb = storage.meshgroup->meshes[mesh_idx]->getAABB();
AABB3D other_aabb = storage.meshgroup->meshes[other_mesh_idx]->getAABB();
AABB3D aabb = storage.meshgroup->meshes[mesh_idx].getAABB();
AABB3D other_aabb = storage.meshgroup->meshes[other_mesh_idx].getAABB();
if (aabb.hit(other_aabb))
{
process_infill = true;
+3 -3
Ver Arquivo
@@ -38,7 +38,7 @@ std::string FffProcessor::getAllSettingsString(MeshGroup& meshgroup, bool first_
}
for (unsigned int mesh_idx = 0; mesh_idx < meshgroup.meshes.size(); mesh_idx++)
{
Mesh& mesh = *meshgroup.meshes[mesh_idx];
Mesh& mesh = meshgroup.meshes[mesh_idx];
sstream << " -e" << mesh.getSettingAsIndex("extruder_nr") << " -l \"" << mesh_idx << "\"" << mesh.getAllLocalSettingsString();
}
sstream << "\n";
@@ -58,9 +58,9 @@ bool FffProcessor::processMeshGroup(MeshGroup* meshgroup)
gcode_writer.setParent(meshgroup);
bool empty = true;
for (Mesh* mesh : meshgroup->meshes)
for (Mesh& mesh : meshgroup->meshes)
{
if (!mesh->getSettingBoolean("infill_mesh") && !mesh->getSettingBoolean("anti_overhang_mesh"))
if (!mesh.getSettingBoolean("infill_mesh") && !mesh.getSettingBoolean("anti_overhang_mesh"))
{
empty = false;
}
-27
Ver Arquivo
@@ -1,27 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MAT_COORD_H
#define MAT_COORD_H
#include "utils/FPoint.h"
namespace cura
{
/*!
* Coordinates in a specific texture bitmap
*/
struct MatCoord
{
FPoint coords;
int mat_id; //!< Material id
MatCoord() //!< non-initializing constructor
{}
MatCoord(FPoint coords, int mat_id) //!< constructor
: coords(coords)
, mat_id(mat_id)
{}
};
} // namespace cura
#endif // MAT_COORD_H
-27
Ver Arquivo
@@ -1,27 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MAT_SEGMENT_H
#define MAT_SEGMENT_H
#include "MatCoord.h"
namespace cura
{
/*!
* Coordinates in a specific texture bitmap
*/
struct MatSegment
{
MatCoord start;
MatCoord end;
MatSegment() //!< non-initializing constructor
{}
MatSegment(MatCoord start, MatCoord end)
: start(start)
, end(end)
{}
};
} // namespace cura
#endif // MAT_SEGMENT_H
-143
Ver Arquivo
@@ -1,143 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include <limits> // numeric limits
#include <algorithm> // min max
#include <iostream>
#include <cassert>
#include "Material.h"
namespace cura
{
Material::Material()
: data(nullptr)
, width(0)
, height(0)
, depth(0)
{
}
void Material::setData(unsigned char* data)
{
this->data = data;
}
void Material::setDimensions(unsigned int width, unsigned int height, unsigned int depth)
{
this->width = width;
this->height = height;
this->depth = depth;
}
float Material::getColor(float x, float y, ColourUsage color) const
{
assert(x >= 0.0f && x <= 1.0f);
assert(y >= 0.0f && y <= 1.0f);
switch (color)
{
case ColourUsage::RED:
case ColourUsage::GREEN:
case ColourUsage::BLUE:
case ColourUsage::ALPHA:
{
assert((int)color >= 0 && (unsigned int)color < depth && "Z out of bounds!");
return getColorData(x, y, (unsigned int) color);
}
case ColourUsage::GREY:
default:
{
float r = getColorData(x, y, (unsigned int) ColourUsage::RED);
float g = getColorData(x, y, (unsigned int) ColourUsage::GREEN);
float b = getColorData(x, y, (unsigned int) ColourUsage::BLUE);
return (r + g + b) / 3.0;
}
}
}
float Material::getColorData(float x, float y, unsigned int z) const
{
unsigned int x_idx = (unsigned int) (x * (width - 1) + 0.5);
assert(x_idx >= 0 && x_idx < width && "requested X is out of bounds!");
unsigned int y_idx = (unsigned int) (y * (height - 1) + 0.5);
assert(y_idx >= 0 && y_idx < height && "requested Y is out of bounds!");
unsigned char col = data[(y_idx * width + x_idx) * depth + z];
return (float) col / std::numeric_limits<unsigned char>::max();
}
void Material::debugOutput(bool dw) const
{
std::cerr << "\nImage size: " << width << " x " << height << " (" << depth << "channels)\n";
std::cerr << '+';
for (unsigned int i = 0; i < width; i++)
{
std::cerr << ((dw)? "--" : "-");
}
std::cerr << "+\n";
for (unsigned int y = 0; y < height; y++)
{
std::cerr << "|";
for (unsigned int x = 0; x < width; x++)
{
int val = (data[(y*width+x)*depth] * 10 / 256);
switch (val)
{
case 0:
std::cerr << ((dw)? " " : " ");
break;
case 1:
std::cerr << ((dw)? ".." : ".");
break;
case 2:
std::cerr << ((dw)? ",," : ",");
break;
case 3:
std::cerr << ((dw)? "::" : ":");
break;
case 4:
std::cerr << ((dw)? ";;" : ";");
break;
case 5:
std::cerr << ((dw)? "++" : "+");
break;
case 6:
std::cerr << ((dw)? "░░" : "");
break;
case 7:
std::cerr << ((dw)? "▒▒" : "");
break;
case 8:
std::cerr << ((dw)? "▓▓" : "");
break;
default:
if (val > 8)
{
std::cerr << ((dw)? "██" : "");
}
else
{
std::cerr << ((dw)? " " : " ");
}
}
}
std::cerr << "|\n";
}
std::cerr << '+';
for (unsigned int i = 0; i < width; i++)
{
std::cerr << ((dw)? "--" : "-");
}
std::cerr << "+\n";
}
} // namespace cura
-67
Ver Arquivo
@@ -1,67 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MATERIAL_H
#define MATERIAL_H
#include "settings/settings.h" // ColourUsage
namespace cura
{
/*!
* The material used in a texture.
*
* This class just holds the image data and has some nice utility functions.
*/
class Material
{
public:
/*!
* non-initializing constructor
*/
Material();
/*!
* Set the pixel data of the image
* \param data pointer to the array of data in RGBA, left-to-right, top-to-bottom
*/
void setData(unsigned char* data);
/*!
* Set the dimensions of the image
* \param width The horizontal length of the imnage
* \param height The vertical length of the imnage
* \param depth The number of color channels
*/
void setDimensions(unsigned int width, unsigned int height, unsigned int depth);
/*!
* get the color value at a particular place in the image
*
* \param x place in the horizontal direction left to right (value between zero and one)
* \param y place in the vertical direction top to bottom (value between zero and one)
* \param color The color channel to check
* \return a value between zero and one
*/
float getColor(float x, float y, ColourUsage color) const;
/*!
* print out something which looks like the picture through std::cerr
* \param double_width Whether to double each character being written, so that the width is visually similar to the height of each pixel.
*/
void debugOutput(bool double_width = true) const;
protected:
unsigned char* data; //!< pixel data in rgb-row-first (or bgr-row first ?)
unsigned int width, height, depth; //!< image dimensions
/*!
* Get a color value from the data
* \param x place in the horizontal direction left to right (value between zero and one)
* \param y place in the vertical direction top to bottom (value between zero and one)
* \return the color data (0-256)
*/
float getColorData(float x, float y, unsigned int z) const;
};
} // namespace cura
#endif // MATERIAL_H
-42
Ver Arquivo
@@ -1,42 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "MaterialBase.h"
namespace cura
{
Material* MaterialBase::add(std::string name)
{
name_to_mat_idx[name] = materials.size();
materials.emplace_back();
return &materials.back();
}
const Material* MaterialBase::getMat(unsigned int id) const
{
if (id < materials.size())
{
return &materials[id];
}
else
{
return nullptr;
}
}
int MaterialBase::getMatId(std::string name) const
{
auto it = name_to_mat_idx.find(name);
if (it == name_to_mat_idx.end())
{
return -1;
}
else
{
return it->second;
}
}
} // namespace cura
-27
Ver Arquivo
@@ -1,27 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef MATERIAL_BASE_H
#define MATERIAL_BASE_H
#include <unordered_map>
#include <string>
#include <vector>
#include "Material.h"
namespace cura
{
class MaterialBase
{
public:
int getMatId(std::string name) const;
Material* add(std::string name);
const Material* getMat(unsigned int id) const;
protected:
std::unordered_map<std::string, int> name_to_mat_idx;
std::vector<Material> materials;
};
} // namespace cura
#endif // MATERIAL_BASE_H
+22 -183
Ver Arquivo
@@ -3,9 +3,6 @@
#include <strings.h>
#include <stdio.h>
#define STB_IMAGE_IMPLEMENTATION // needed in order to enable the implementation of libs/std_image.h
#include "stb/stb_image.h"
#include "MeshGroup.h"
#include "utils/gettime.h"
#include "utils/logoutput.h"
@@ -28,10 +25,6 @@ void* fgets_(char* ptr, size_t len, FILE* f)
*ptr = '\0';
return ptr;
}
else if (*ptr =='\0')
{
return ptr;
}
ptr++;
len--;
}
@@ -52,10 +45,6 @@ MeshGroup::~MeshGroup()
delete extruders[extruder];
}
}
for (Mesh* mesh : meshes)
{
delete mesh;
}
}
int MeshGroup::getExtruderCount() const
@@ -101,10 +90,10 @@ Point3 MeshGroup::min() const
{
return Point3(0, 0, 0);
}
Point3 ret = meshes[0]->min();
for (unsigned int i = 1; i < meshes.size(); i++)
Point3 ret = meshes[0].min();
for(unsigned int i=1; i<meshes.size(); i++)
{
Point3 v = meshes[i]->min();
Point3 v = meshes[i].min();
ret.x = std::min(ret.x, v.x);
ret.y = std::min(ret.y, v.y);
ret.z = std::min(ret.z, v.z);
@@ -118,10 +107,10 @@ Point3 MeshGroup::max() const
{
return Point3(0, 0, 0);
}
Point3 ret = meshes[0]->max();
for (unsigned int i = 1; i < meshes.size(); i++)
Point3 ret = meshes[0].max();
for(unsigned int i=1; i<meshes.size(); i++)
{
Point3 v = meshes[i]->max();
Point3 v = meshes[i].max();
ret.x = std::max(ret.x, v.x);
ret.y = std::max(ret.y, v.y);
ret.z = std::max(ret.z, v.z);
@@ -131,9 +120,9 @@ Point3 MeshGroup::max() const
void MeshGroup::clear()
{
for (Mesh* m : meshes)
for(Mesh& m : meshes)
{
m->clear();
m.clear();
}
}
@@ -151,9 +140,9 @@ void MeshGroup::finalize()
continue;
}
for (const Mesh* mesh : meshes)
for (const Mesh& mesh : meshes)
{
if (mesh->getSettingBoolean("support_enable")
if (mesh.getSettingBoolean("support_enable")
&& (
getSettingAsIndex("support_infill_extruder_nr") == extruder_nr
|| getSettingAsIndex("support_extruder_nr_layer_0") == extruder_nr
@@ -167,13 +156,13 @@ void MeshGroup::finalize()
}
}
for (const Mesh* mesh : meshes)
for (const Mesh& mesh : meshes)
{
if (!mesh->getSettingBoolean("anti_overhang_mesh")
&& !mesh->getSettingBoolean("support_mesh")
if (!mesh.getSettingBoolean("anti_overhang_mesh")
&& !mesh.getSettingBoolean("support_mesh")
)
{
getExtruderTrain(mesh->getSettingAsIndex("extruder_nr"))->setIsUsed(true);
getExtruderTrain(mesh.getSettingAsIndex("extruder_nr"))->setIsUsed(true);
}
}
@@ -186,17 +175,17 @@ void MeshGroup::finalize()
}
// If a mesh position was given, put the mesh at this position in 3D space.
for (Mesh* mesh : meshes)
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 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_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);
mesh.offset(mesh_offset + meshgroup_offset);
}
}
@@ -340,138 +329,6 @@ bool loadMeshSTL(Mesh* mesh, const char* filename, const FMatrix3x3& matrix)
return loadMeshSTL_binary(mesh, filename, matrix);
}
void loadMatImage(Material* mat, const char* filename)
{
int width;
int height;
int depth;
// in RGBA order
unsigned char* data = stbi_load(filename, &width, &height, &depth, 0);
if (data)
{
mat->setData(data);
mat->setDimensions(width, height, depth);
}
else
{
logError("Cannot load image %s.", filename);
}
}
void loadMaterialBase(TexturedMesh* mesh, const char* filename)
{
FILE* f = fopen(filename, "rt");
if (f == nullptr)
{
logError("ERROR: Couldn't load MTL file %s.\n", filename);
return;
}
char buffer[1024];
char mat_name [100];
char mat_file [100];
char map_type [10];
Material* last_mat = nullptr;
while(fgets_(buffer, sizeof(buffer), f))
{
if (buffer[0] == '#')
{
continue;
}
if (sscanf(buffer, "map_%s %s", map_type, mat_file) == 2 // we don't care what type of map it specifies (currently)
|| sscanf(buffer, "bump %s", mat_file) == 1
|| sscanf(buffer, "disp %s", mat_file) == 1
|| sscanf(buffer, "decal %s", mat_file) == 1
|| sscanf(buffer, "refl %s", mat_file) == 1
)
{
std::string parent_dir = std::string(filename).substr(0, std::string(filename).find_last_of("/\\"));
std::string mtl_file = parent_dir + "/" + mat_file;
if (last_mat)
{
loadMatImage(last_mat, mtl_file.c_str());
}
}
else if (sscanf(buffer, "newmtl %s", mat_name) == 1)
{
last_mat = mesh->addMaterial(mat_name);
}
}
fclose(f);
}
bool loadMeshOBJ(TexturedMesh* mesh, const char* filename, const FMatrix3x3& matrix)
{
FILE* f = fopen(filename, "rt");
if (f == nullptr)
{
return false;
}
char buffer[1024];
FPoint3 vertex;
Point3 vertex_indices;
float texture_x;
float texture_y;
float temp;
char face_index_buffer_1 [100];
char face_index_buffer_2 [100];
char face_index_buffer_3 [100];
char str_buffer [100];
while(fgets_(buffer, sizeof(buffer), f))
{
if (buffer[0] == '#')
{
continue;
}
if (sscanf(buffer, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
{
Point3 v = matrix.apply(vertex);
mesh->addVertex(v);
}
else if (sscanf(buffer, "vt %f %f", &texture_x, &texture_y) == 2)
{
mesh->addTextureCoord(texture_x, texture_y);
}
else if (sscanf(buffer, "f %s %s %s", face_index_buffer_1, face_index_buffer_2, face_index_buffer_3) == 3)
{
int normal_vector_index; // unused
Point3 texture_indices(0, 0, 0); // becomes -1 if no texture data supplied
int n_scanned_1 = sscanf(face_index_buffer_1, "%d/%d/%d", &vertex_indices.x, &texture_indices.x, &normal_vector_index);
int n_scanned_2 = sscanf(face_index_buffer_2, "%d/%d/%d", &vertex_indices.y, &texture_indices.y, &normal_vector_index);
int n_scanned_3 = sscanf(face_index_buffer_3, "%d/%d/%d", &vertex_indices.z, &texture_indices.z, &normal_vector_index);
if (n_scanned_1 > 0 && n_scanned_2 > 0 && n_scanned_3 > 0)
{
mesh->addFace(vertex_indices.x - 1, vertex_indices.y - 1, vertex_indices.z - 1, texture_indices.x - 1, texture_indices.y - 1, texture_indices.z - 1);
// obj files count vertex indices starting from 1!
}
}
else if (sscanf(buffer, "mtllib %s", str_buffer) == 1)
{
std::string parent_dir = std::string(filename).substr(0, std::string(filename).find_last_of("/\\"));
std::string mtl_file = parent_dir + "/" + str_buffer;
loadMaterialBase(mesh, mtl_file.c_str());
}
else if (sscanf(buffer, "usemtl %s", str_buffer) == 1)
{
mesh->setMaterial(str_buffer);
}
else if (sscanf(buffer, "vn %f %f %f", &temp, &temp, &temp) == 3)
{
// do nothing
}
else if (buffer[0] == '\0')
{
// empty line, do nothing
}
else
{
logError("Cannot parse line \"%s\"\n", buffer);
}
}
fclose(f);
mesh->finish();
return true;
}
bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMatrix3x3& transformation, SettingsBaseVirtual* object_parent_settings)
{
TimeKeeper load_timer;
@@ -479,32 +336,14 @@ bool loadMeshIntoMeshGroup(MeshGroup* meshgroup, const char* filename, const FMa
const char* ext = strrchr(filename, '.');
if (ext && (strcmp(ext, ".stl") == 0 || strcmp(ext, ".STL") == 0))
{
Mesh* mesh = new Mesh(object_parent_settings ? object_parent_settings : meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if (loadMeshSTL(mesh,filename,transformation)) //Load it! If successful...
Mesh mesh = object_parent_settings ? Mesh(object_parent_settings) : Mesh(meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if(loadMeshSTL(&mesh,filename,transformation)) //Load it! If successful...
{
meshgroup->meshes.push_back(mesh);
log("loading '%s' took %.3f seconds\n",filename,load_timer.restart());
return true;
}
else
{
delete mesh;
}
}
else if (ext && (strcmp(ext, ".obj") == 0 || strcmp(ext, ".OBJ") == 0))
{
TexturedMesh* mesh = new TexturedMesh(object_parent_settings ? object_parent_settings : meshgroup); //If we have object_parent_settings, use them as parent settings. Otherwise, just use meshgroup.
if (loadMeshOBJ(mesh,filename,transformation)) //Load it! If successful...
{
meshgroup->meshes.push_back(mesh);
return true;
}
else
{
delete mesh;
}
}
return false;
}
+1 -2
Ver Arquivo
@@ -4,7 +4,6 @@
#include "utils/NoCopy.h"
#include "mesh.h"
#include "TexturedMesh.h"
#include "ExtruderTrain.h"
namespace cura
@@ -36,7 +35,7 @@ public:
const ExtruderTrain* getExtruderTrain(unsigned int extruder_nr) const;
std::vector<Mesh*> meshes;
std::vector<Mesh> meshes;
Point3 min() const; //! minimal corner of bounding box
Point3 max() const; //! maximal corner of bounding box
-141
Ver Arquivo
@@ -1,141 +0,0 @@
#include "TextureProcessor.h"
#include <algorithm> // swap
#include "utils/optional.h"
#include "slicer/SlicerSegment.h"
namespace cura
{
#define POINT_DIST 400
#define AMPLITUDE 3000
#define EXTRA_OFFSET 3000
/*
void TextureProcessor::process(std::vector< Slicer* >& slicer_list)
{
for (Slicer* slicer : slicer_list)
{
for (SlicerLayer& layer : slicer->layers)
{
process(slicer->mesh, layer);
}
}
}
*/
void TextureProcessor::processSegmentBumpMap(const Mesh* mesh, const SlicerSegment& slicer_segment, const MatSegment& mat, const Point p0, const Point p1, coord_t& dist_left_over, PolygonRef result)
{
MatCoord mat_start = mat.start;
MatCoord mat_end = mat.end;
if (vSize2(slicer_segment.start - p0) > vSize2(slicer_segment.start - p1))
{
std::swap(mat_start, mat_end);
}
Point p0p1 = p1 - p0;
int64_t p0p1_size = vSize(p0p1);
if (dist_left_over >= p0p1_size)
{
dist_left_over -= p0p1_size;
return;
}
Point perp_to_p0p1 = turn90CCW(p0p1);
int64_t dist_last_point = -1; // p0p1_size * 2 - dist_left_over; // so that p0p1_size - dist_last_point evaulates to dist_left_over - p0p1_size
// TODO: move start point (which was already moved last iteration
for (int64_t p0pa_dist = dist_left_over; p0pa_dist < p0p1_size; p0pa_dist += POINT_DIST)
{
assert(p0pa_dist >= 0);
assert(p0pa_dist <= p0p1_size);
MatCoord mat_coord_now = mat_start;
mat_coord_now.coords = mat_start.coords + (mat_end.coords - mat_start.coords) * p0pa_dist / p0p1_size;
float val = mesh->getColor(mat_coord_now, ColourUsage::GREY);
int offset = val * (AMPLITUDE * 2) - AMPLITUDE + EXTRA_OFFSET;
Point fuzz = normal(perp_to_p0p1, offset);
Point pa = p0 + normal(p0p1, p0pa_dist) - fuzz;
result.add(pa);
dist_last_point = p0pa_dist;
}
// TODO: move end point as well
float val = mesh->getColor(mat_end, ColourUsage::GREY);
int r = val * (AMPLITUDE * 2) - AMPLITUDE + EXTRA_OFFSET;
Point fuzz = normal(perp_to_p0p1, r);
result.emplace_back(p1 - fuzz);
assert(dist_last_point >= 0 && "above loop should have run at least once!");
assert(p0p1_size > dist_last_point);
dist_left_over = p0p1_size - dist_last_point;
assert(dist_left_over <= POINT_DIST);
}
void TextureProcessor::processBumpMap(const Mesh* mesh, SlicerLayer& layer)
{
Polygons results;
for (PolygonRef poly : layer.polygons)
{
// generate points in between p0 and p1
PolygonRef result = results.newPoly();
coord_t dist_left_over = (POINT_DIST / 2); // the distance to be traversed on the line before making the first new point
Point* p0 = &poly.back();
for (Point& p1 : poly)
{ // 'a' is the (next) new point between p0 and p1
if (*p0 == p1)
{
continue;
}
SlicerSegment segment(*p0, p1);
std::optional<std::pair<SlicerSegment, MatSegment>> best_mat_segment_it;
coord_t best_dist_score = std::numeric_limits<coord_t>::max();
for (std::unordered_map<SlicerSegment, MatSegment>::iterator it = layer.segment_to_material_segment.begin(); it != layer.segment_to_material_segment.end(); ++it)
{
const SlicerSegment& sliced_segment = it->first;
coord_t dist_score = std::min(
vSize2(sliced_segment.start - segment.start) + vSize2(sliced_segment.end - segment.end)
, vSize2(sliced_segment.end - segment.start) + vSize2(sliced_segment.start - segment.end)
);
if (dist_score < best_dist_score)
{
best_dist_score = dist_score;
best_mat_segment_it = *it;
}
}
if (best_dist_score < 30 * 30) // TODO: magic value of 0.03mm for total stitching distance > should be something like SlicerLayer.cpp::largest_neglected_gap_second_phase (?)
{
assert(best_mat_segment_it);
processSegmentBumpMap(mesh, best_mat_segment_it->first, best_mat_segment_it->second, *p0, p1, dist_left_over, result);
}
else
{
result.emplace_back(p1);
}
p0 = &p1;
}
while (result.size() < 3 )
{
unsigned int point_idx = poly.size() - 2;
result.add(poly[point_idx]);
if (point_idx == 0) { break; }
point_idx--;
}
if (result.size() < 3)
{
result.clear();
for (Point& p : poly)
result.add(p);
}
}
// a negative offset on two sides of a corner, may introduce complexities in the model which should be removed:
// ^↘
// ^ ↘
// <<<<<<<<^<<<< should become <<<<<<<<
// ^ ^
// ^ ^
// ^ ^
layer.polygons = results.removeComplexParts();
}
}//namespace cura
-25
Ver Arquivo
@@ -1,25 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef TEXTURE_PROCESSOR_H
#define TEXTURE_PROCESSOR_H
#include <vector>
#include "slicer/Slicer.h"
#include "mesh.h"
namespace cura
{
class TextureProcessor
{
public:
// static void process(std::vector<Slicer*>& slicer_list);
static void processBumpMap(const Mesh* mesh, SlicerLayer& layer);
protected:
static void processSegmentBumpMap(const Mesh* mesh, const SlicerSegment& slicer_segment, const MatSegment& mat, const Point p0, const Point p1, coord_t& dist_left_over, PolygonRef result);
};
} // namespace cura
#endif // TEXTURE_PROCESSOR_H
-137
Ver Arquivo
@@ -1,137 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#include "TexturedMesh.h"
#include <cassert>
#include "utils/logoutput.h"
namespace cura
{
TexturedMesh::TexturedMesh(SettingsBaseVirtual* sb)
: Mesh(sb)
, current_mat(-1) // not set yet
{
}
void TexturedMesh::addTextureCoord(float x, float y)
{
texture_coords.emplace_back(x, y);
}
void TexturedMesh::addFace(int vi0, int vi1, int vi2, int ti0, int ti1, int ti2)
{
if (vi0 < -1)
{
vi0 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (vi1 < -1)
{
vi1 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (vi2 < -1)
{
vi2 = Mesh::faces.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti0 < -1)
{
ti0 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti1 < -1)
{
ti1 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
if (ti2 < -1)
{
ti2 = texture_coords.size() + vi0 + 1; // + 1 because of relative indexing doesn't start counting from 1
}
bool made_new_face = Mesh::addFace(vi0, vi1, vi2);
if (made_new_face)
{
face_texture_indices.emplace_back(ti0, ti1, ti2, current_mat);
assert(Mesh::faces.size() == face_texture_indices.size());
}
}
bool TexturedMesh::setMaterial(std::string name)
{
current_mat = material_base.getMatId(name);
return current_mat >= 0;
}
Material* TexturedMesh::addMaterial(std::__cxx11::string name)
{
return material_base.add(name);
}
bool TexturedMesh::getFaceEdgeMatCoord(unsigned int face_idx, int64_t z, unsigned int p0_idx, unsigned int p1_idx, MatCoord& result) const
{
if (face_idx >= face_texture_indices.size() || face_idx >= faces.size())
{
return false;
}
FaceTextureCoordIndices texture_idxs = face_texture_indices[face_idx];
if (texture_idxs.index[0] < 0 || texture_idxs.index[1] < 0 || texture_idxs.index[2] < 0 || texture_idxs.mat_id < 0)
{
return false;
}
const MeshFace& face = faces[face_idx];
Point3 p0(vertices[face.vertex_index[p0_idx]].p);
Point3 p1(vertices[face.vertex_index[p1_idx]].p);
float dzp0 = z - p0.z;
float dp0p1 = p1.z - p0.z;
if (dzp0 * dp0p1 < 0)
{ // z doesn't lie between p0 and p1
return false;
}
if (dzp0 == 0)
{ // edge is not cut by horizontal plane!
return false;
}
float ratio = INT2MM(dzp0) / INT2MM(dp0p1);
FPoint t0 = texture_coords[texture_idxs.index[p0_idx]];
FPoint t1 = texture_coords[texture_idxs.index[p1_idx]];
result.mat_id = texture_idxs.mat_id;
result.coords.x = t0.x + (t1.x - t0.x) * ratio;
result.coords.y = t0.y + (t1.y - t0.y) * ratio;
if (result.coords.x > 1.001 || result.coords.x < -0.001 || result.coords.y > 1.001 || result.coords.y < -0.001)
{
logError("WARNING: wapping material to outside image!");
}
return true;
}
bool TexturedMesh::registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const
{
if (!getFaceEdgeMatCoord(face_idx, z, idx_shared, idx_first, result.start))
{
return false;
}
if (!getFaceEdgeMatCoord(face_idx, z, idx_shared, idx_second, result.end))
{
return false;
}
return true;
}
float TexturedMesh::getColor(MatCoord bitmap_coord, ColourUsage color) const
{
const Material* mat = material_base.getMat(bitmap_coord.mat_id);
if (mat)
{
return mat->getColor(bitmap_coord.coords.x, bitmap_coord.coords.y, color);
}
else
{
return 0.0f;
}
}
} // namespace cura
-78
Ver Arquivo
@@ -1,78 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef TEXTURED_MESH_H
#define TEXTURED_MESH_H
#include <vector>
#include <string>
#include "MaterialBase.h"
#include "mesh.h"
#include "utils/intpoint.h"
#include "MatSegment.h"
namespace cura
{
/*!
* A mesh with bitmap textures to it.
*
* material coordinates are defined separately, and can be reused for different bitmap textures
*/
class TexturedMesh : public Mesh
{
public:
TexturedMesh(SettingsBaseVirtual* sb);
/*!
*
*/
struct FaceTextureCoordIndices
{
int index[3]; //!< indices into texture_coords or -1 if no texture data available
int mat_id; //!< Material id
FaceTextureCoordIndices(int i1, int i2, int i3, int mat_id)
: mat_id(mat_id)
{
index[0] = i1;
index[1] = i2;
index[2] = i3;
}
};
void addTextureCoord(float x, float y);
void addFace(int vi0, int vi1, int vi2, int ti0, int ti1, int ti2);
using Mesh::addFace; // otherwise above addFace would shadow the parent addFace
bool setMaterial(std::string name); //!< set the material to be used in the comming data to be loaded
Material* addMaterial(std::string name);
virtual bool registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const;
protected:
std::vector<FPoint> texture_coords; //!< all texture coordinates by all faces
std::vector<FaceTextureCoordIndices> face_texture_indices; //!< for each face the corresponding texture coordinates in TexturedMesh::texture_coords
// TODO clean up above lists when super class clear() is called
// TODO when to clean up below material base?
MaterialBase material_base;
/*!
* Get the material coordinate corresponding to the point on a plane cutting a given edge of the face.
* \param face_idx The face for which to get the material coord
* \param z The z of the horizontal plane cutting the face
* \param p0_idx The index into the first vert of the edge
* \param p1_idx The index into the second vert of the edge
* \param result The resulting material Coordinates
* \return Whether a Material coordinate is defined at the given location
*/
bool getFaceEdgeMatCoord(unsigned int face_idx, int64_t z, unsigned int p0_idx, unsigned int p1_idx, MatCoord& result) const;
virtual float getColor(MatCoord bitmap_coord, ColourUsage color) const;
private:
int current_mat; //!< material currently used in loading the face material info
};
} // namespace cura
#endif // TEXTURED_MESH_H
+2 -2
Ver Arquivo
@@ -23,9 +23,9 @@ void Weaver::weave(MeshGroup* meshgroup)
std::vector<cura::Slicer*> slicerList;
for (Mesh* mesh : meshgroup->meshes)
for(Mesh& mesh : meshgroup->meshes)
{
cura::Slicer* slicer = new cura::Slicer(mesh, initial_layer_thickness, connectionHeight, layer_count, mesh->getSettingBoolean("meshfix_keep_open_polygons"), mesh->getSettingBoolean("meshfix_extensive_stitching"));
cura::Slicer* slicer = new cura::Slicer(&mesh, initial_layer_thickness, connectionHeight, layer_count, mesh.getSettingBoolean("meshfix_keep_open_polygons"), mesh.getSettingBoolean("meshfix_extensive_stitching"));
slicerList.push_back(slicer);
}
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@
#include "settings/settings.h"
#include "MeshGroup.h"
#include "slicer/Slicer.h"
#include "slicer.h"
#include "utils/NoCopy.h"
#include "utils/polygon.h"
+1 -1
Ver Arquivo
@@ -11,7 +11,7 @@
#include "settings/settings.h"
#include "MeshGroup.h"
#include "slicer/Slicer.h"
#include "slicer.h"
#include "utils/polygon.h"
#include "Weaver.h"
+6 -4
Ver Arquivo
@@ -346,9 +346,9 @@ void CommandSocket::connect(const std::string& ip, int port)
continue;
}
const ExtruderTrain* settings_base = meshgroup->getExtruderTrain(extruder_nr); //The extruder train that the setting should fall back to.
for (Mesh* mesh : meshgroup->meshes)
for (Mesh& mesh : meshgroup->meshes)
{
mesh->setSettingInheritBase(setting_extruder.name(), *settings_base);
mesh.setSettingInheritBase(setting_extruder.name(), *settings_base);
}
}
}
@@ -455,8 +455,8 @@ void CommandSocket::handleObjectList(cura::proto::ObjectList* list, const google
}
SettingsBase* extruder_train = meshgroup->getExtruderTrain(extruder_train_nr);
meshgroup->meshes.push_back(new Mesh(extruder_train)); //Construct a new mesh (with the corresponding extruder train as settings parent object) and put it into MeshGroup's mesh list.
Mesh& mesh = *meshgroup->meshes.back();
meshgroup->meshes.push_back(extruder_train); //Construct a new mesh (with the corresponding extruder train as settings parent object) and put it into MeshGroup's mesh list.
Mesh& mesh = meshgroup->meshes.back();
for (int i = 0; i < face_count; ++i)
{
@@ -642,6 +642,7 @@ void CommandSocket::sendLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::Layer>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
@@ -667,6 +668,7 @@ void CommandSocket::sendOptimizedLayerData()
{
for (std::pair<const int, std::shared_ptr<cura::proto::LayerOptimized>> entry : data.slice_data) //Note: This is in no particular order!
{
logDebug("Sending layer data for layer %i of %i.\n", entry.first, data.slice_data.size());
private_data->socket->sendMessage(entry.second); //Send the actual layers.
}
data.sliced_objects = 0;
+25 -44
Ver Arquivo
@@ -1,7 +1,4 @@
//Copyright (c) 2013 David Braam
//Copyright (c) 2016 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <stdarg.h>
#include <iomanip>
#include <cmath>
@@ -14,6 +11,8 @@
namespace cura {
double layer_height; //!< report basic layer height in RepRap gcode file.
GCodeExport::GCodeExport()
: output_stream(&std::cout)
, currentPosition(0,0,MM2INT(20))
@@ -52,13 +51,13 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
extruder_count = meshgroup->getSettingAsCount("machine_extruder_count");
for (const Mesh* mesh : meshgroup->meshes)
for (const Mesh& mesh : meshgroup->meshes)
{
if (!mesh->getSettingBoolean("anti_overhang_mesh")
&& !mesh->getSettingBoolean("support_mesh")
if (!mesh.getSettingBoolean("anti_overhang_mesh")
&& !mesh.getSettingBoolean("support_mesh")
)
{
extruder_attr[mesh->getSettingAsIndex("extruder_nr")].is_used = true;
extruder_attr[mesh.getSettingAsIndex("extruder_nr")].is_used = true;
}
}
@@ -70,11 +69,11 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
{
extruder_attr[extruder_nr].is_used = true;
}
for (const Mesh* mesh : meshgroup->meshes)
for (const Mesh& mesh : meshgroup->meshes)
{
if ((mesh->getSettingBoolean("support_enable") && mesh->getSettingBoolean("support_interface_enable") && meshgroup->getSettingAsIndex("support_interface_extruder_nr") == int(extruder_nr))
|| (mesh->getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_infill_extruder_nr") == int(extruder_nr))
|| (mesh->getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_extruder_nr_layer_0") == int(extruder_nr))
if ((mesh.getSettingBoolean("support_enable") && mesh.getSettingBoolean("support_interface_enable") && meshgroup->getSettingAsIndex("support_interface_extruder_nr") == int(extruder_nr))
|| (mesh.getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_infill_extruder_nr") == int(extruder_nr))
|| (mesh.getSettingBoolean("support_enable") && meshgroup->getSettingAsIndex("support_extruder_nr_layer_0") == int(extruder_nr))
)
{
extruder_attr[extruder_nr].is_used = true;
@@ -84,7 +83,7 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
extruder_attr[extruder_nr].prime_pos = Point3(train->getSettingInMicrons("extruder_prime_pos_x"), train->getSettingInMicrons("extruder_prime_pos_y"), train->getSettingInMicrons("extruder_prime_pos_z"));
extruder_attr[extruder_nr].prime_pos_is_abs = train->getSettingBoolean("extruder_prime_pos_abs");
extruder_attr[extruder_nr].park_distance = train->getSettingInMillimeters("machine_filament_park_distance");
extruder_attr[extruder_nr].nozzle_size = train->getSettingInMicrons("machine_nozzle_size");
extruder_attr[extruder_nr].nozzle_offset = Point(train->getSettingInMicrons("machine_nozzle_offset_x"), train->getSettingInMicrons("machine_nozzle_offset_y"));
extruder_attr[extruder_nr].material_guid = train->getSettingString("material_guid");
@@ -100,6 +99,8 @@ void GCodeExport::preSetup(const MeshGroup* meshgroup)
machine_name = meshgroup->getSettingString("machine_name");
layer_height = meshgroup->getSettingInMillimeters("layer_height");
if (flavor == EGCodeFlavor::BFB)
{
new_line = "\r\n";
@@ -197,6 +198,7 @@ std::string GCodeExport::getFileHeader(const double* print_time, const std::vect
else if (flavor == EGCodeFlavor::REPRAP)
{
prefix << ";Filament used: " << ((filament_used.size() >= 1)? filament_used[0] / (1000 * extruder_attr[0].filament_area) : 0) << "m" << new_line;
prefix << ";Layer height: " << layer_height << new_line;
}
return prefix.str();
}
@@ -554,8 +556,6 @@ void GCodeExport::writeMove(int x, int y, int z, double speed, double extrusion_
assert((Point3(x,y,z) - currentPosition).vSize() < MM2INT(300)); // no crazy positions (this code should not be compiled for release)
#endif //ASSERT_INSANE_OUTPUT
total_bounding_box.include(Point3(x, y, z));
if (extrusion_mm3_per_mm < 0)
logWarning("Warning! Negative extrusion move!");
@@ -568,6 +568,7 @@ void GCodeExport::writeMove(int x, int y, int z, double speed, double extrusion_
double extrusion_per_mm = mm3ToE(extrusion_mm3_per_mm);
Point gcode_pos = getGcodePos(x,y, current_extruder);
total_bounding_box.include(Point3(gcode_pos.X, gcode_pos.Y, z));
if (extrusion_mm3_per_mm > 0.000001)
{
@@ -689,11 +690,12 @@ void GCodeExport::writeRetraction(const RetractionConfig& config, bool force, bo
extruded_volume_at_previous_n_retractions.pop_back();
}
}
if (firmware_retract)
{
if (extruder_switch && extr_attr.retraction_e_amount_current)
if (extruder_switch && extr_attr.retraction_e_amount_current)
{
return;
return;
}
*output_stream << "G10";
if (extruder_switch)
@@ -704,20 +706,6 @@ void GCodeExport::writeRetraction(const RetractionConfig& config, bool force, bo
//Assume default UM2 retraction settings.
estimateCalculator.plan(TimeEstimateCalculator::Position(INT2MM(currentPosition.x), INT2MM(currentPosition.y), INT2MM(currentPosition.z), eToMm(current_e_value + retraction_diff_e_amount)), 25); // TODO: hardcoded values!
}
writeMoveFilament(config, config.distance);
}
void GCodeExport::writeMoveFilament(const RetractionConfig& config, const double new_retraction_distance)
{
ExtruderTrainAttributes& extr_attr = extruder_attr[current_extruder];
const double old_retraction_e_amount = extr_attr.retraction_e_amount_current;
const double new_retraction_e_amount = mmToE(new_retraction_distance);
const double retraction_diff_e_amount = old_retraction_e_amount - new_retraction_e_amount;
if (std::abs(retraction_diff_e_amount) < 0.000001)
{
return; //No need to have detailed extrusion moves this small.
}
else
{
double speed = ((retraction_diff_e_amount < 0.0)? config.speed : extr_attr.last_retraction_prime_speed) * 60;
@@ -740,7 +728,7 @@ void GCodeExport::writeZhopStart(int hop_height)
{
isZHopped = hop_height;
*output_stream << "G1 Z" << MMtoStream{currentPosition.z + isZHopped} << new_line;
total_bounding_box.include(currentPosition + Point3(0, 0, isZHopped));
total_bounding_box.includeZ(currentPosition.z + isZHopped);
}
}
@@ -780,21 +768,14 @@ void GCodeExport::startExtruder(int new_extruder)
currentPosition.z += 1;
}
void GCodeExport::switchExtruder(int new_extruder, const RetractionConfig& retraction_config_old_extruder, const bool turn_off_extruder)
void GCodeExport::switchExtruder(int new_extruder, const RetractionConfig& retraction_config_old_extruder)
{
if (current_extruder == new_extruder)
return;
if (turn_off_extruder)
{
writeMoveFilament(retraction_config_old_extruder, extruder_attr[current_extruder].park_distance);
}
else
{
bool force = true;
bool extruder_switch = true;
writeRetraction(const_cast<RetractionConfig&>(retraction_config_old_extruder), force, extruder_switch);
}
bool force = true;
bool extruder_switch = true;
writeRetraction(const_cast<RetractionConfig&>(retraction_config_old_extruder), force, extruder_switch);
resetExtrusionValue(); // zero the E value on the old extruder, so that the current_e_value is registered on the old extruder
@@ -941,7 +922,7 @@ void GCodeExport::finalize(const char* endCode)
{
writeFanCommand(0);
writeCode(endCode);
long print_time = getTotalPrintTime();
int64_t print_time = getTotalPrintTime();
int mat_0 = getTotalFilamentUsed(0);
log("Print time: %d\n", print_time);
log("Print time (readable): %dh %dm %ds\n", print_time / 60 / 60, (print_time / 60) % 60, print_time % 60);
+2 -21
Ver Arquivo
@@ -1,7 +1,4 @@
//Copyright (c) 2013 David Braam
//Copyright (c) 2016 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef GCODEEXPORT_H
#define GCODEEXPORT_H
@@ -62,7 +59,6 @@ private:
double retraction_e_amount_current; //!< The current retracted amount (in mm or mm^3), or zero(i.e. false) if it is not currently retracted (positive values mean retracted amount, so negative impact on E values)
double retraction_e_amount_at_e_start; //!< The ExtruderTrainAttributes::retraction_amount_current value at E0, i.e. the offset (in mm or mm^3) from E0 to the situation where the filament is at the tip of the nozzle.
double park_distance; //!< The distance from the nozzle at which to park filament after having completed printing with it.
double prime_volume; //!< Amount of material (in mm^3) to be primed after an unretration (due to oozing and/or coasting)
double last_retraction_prime_speed; //!< The last prime speed (in mm/s) of the to-be-primed amount
@@ -83,7 +79,6 @@ private:
, initial_temp(0)
, retraction_e_amount_current(0.0)
, retraction_e_amount_at_e_start(0.0)
, park_distance(0.0)
, prime_volume(0.0)
, last_retraction_prime_speed(0.0)
{ }
@@ -163,18 +158,6 @@ protected:
*/
double mmToE(double mm);
/*!
* \brief Write a move in the E-direction such that the filament is
* retracted or unretracted to the specified distance.
*
* No checks are made for the maximum number of retractions.
*
* \param config The configuration from which to get the distance and speed.
* \param new_retraction_distance The distance from the tip of the nozzle
* where the filament is supposed to end up.
*/
void writeMoveFilament(const RetractionConfig& config, const double new_retraction_distance);
public:
GCodeExport();
@@ -313,10 +296,8 @@ public:
*
* \param new_extruder The extruder to switch to
* \param retraction_config_old_extruder The extruder switch retraction config of the old extruder, to perform the extruder switch retraction with.
* \param turn_off_extruder Should the old extruder be turned off
* completely?
*/
void switchExtruder(int new_extruder, const RetractionConfig& retraction_config_old_extruder, const bool turn_off_extruder = false);
void switchExtruder(int new_extruder, const RetractionConfig& retraction_config_old_extruder);
void writeCode(const char* str);
+21 -19
Ver Arquivo
@@ -663,17 +663,14 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
{
ExtruderPlan& extruder_plan = extruder_plans[extruder_plan_idx];
RetractionConfig& retraction_config = storage.retraction_config_per_extruder[extruder_plan.extruder];
const ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder);
if (extruder != extruder_plan.extruder)
{
int prev_extruder = extruder;
extruder = extruder_plan.extruder;
gcode.switchExtruder(extruder, storage.extruder_switch_retraction_config_per_extruder[prev_extruder]);
const int prev_layer_nr = (extruder_plan_idx == 0) ? layer_nr - 1 : layer_nr;
const bool turn_off_extruder = prev_layer_nr >= storage.max_print_height_per_extruder[prev_extruder]; //Previous extruder is not used any more in this mesh group.
gcode.switchExtruder(extruder, storage.extruder_switch_retraction_config_per_extruder[prev_extruder], turn_off_extruder);
const ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder);
if (train->getSettingInMillimetersPerSecond("max_feedrate_z_override") > 0)
{
gcode.writeMaxZFeedrate(train->getSettingInMillimetersPerSecond("max_feedrate_z_override"));
@@ -684,22 +681,23 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
gcode.writeTemperatureCommand(extruder, extruder_plan.initial_printing_temperature, wait);
}
std::optional<double> prev_extruder_temp = std::optional<double>();
if (turn_off_extruder)
{
prev_extruder_temp = 0; //Turn previous extruder off entirely. TODO: Should there be a setting for the temperature to turn an extruder off?
}
else if (extruder_plan.prev_extruder_standby_temp)
{
prev_extruder_temp = *extruder_plan.prev_extruder_standby_temp; //Not entirely, but just to stand-by temperature.
}
if (prev_extruder_temp) //One of the if-statements above went through.
{
// prime extruder if it hadn't been used yet
gcode.writePrimeTrain(storage.meshgroup->getExtruderTrain(extruder)->getSettingInMillimetersPerSecond("speed_travel"));
gcode.writeRetraction(retraction_config);
if (extruder_plan.prev_extruder_standby_temp)
{ // turn off previous extruder
constexpr bool wait = false;
gcode.writeTemperatureCommand(prev_extruder, *prev_extruder_temp, wait);
double prev_extruder_temp = *extruder_plan.prev_extruder_standby_temp;
int prev_layer_nr = (extruder_plan_idx == 0)? layer_nr - 1 : layer_nr;
if (prev_layer_nr == storage.max_print_height_per_extruder[prev_extruder])
{
prev_extruder_temp = 0; // TODO ? should there be a setting for extruder_off_temperature ?
}
gcode.writeTemperatureCommand(prev_extruder, prev_extruder_temp, wait);
}
}
else if (extruder_plan_idx == 0 && layer_nr != 0 && train->getSettingBoolean("retract_at_layer_change"))
else if (extruder_plan_idx == 0 && layer_nr != 0 && storage.meshgroup->getExtruderTrain(extruder)->getSettingBoolean("retract_at_layer_change"))
{
gcode.writeRetraction(retraction_config);
}
@@ -710,6 +708,7 @@ void GCodePlanner::writeGCode(GCodeExport& gcode)
return a.path_idx < b.path_idx;
} );
const ExtruderTrain* train = storage.meshgroup->getExtruderTrain(extruder);
if (train->getSettingInMillimetersPerSecond("max_feedrate_z_override") > 0)
{
gcode.writeMaxZFeedrate(train->getSettingInMillimetersPerSecond("max_feedrate_z_override"));
@@ -898,6 +897,7 @@ void GCodePlanner::completeConfigs()
mesh.insetX_config.setLayerHeight(layer_thickness);
mesh.skin_config.setLayerHeight(layer_thickness);
mesh.perimeter_gap_config.setLayerHeight(layer_thickness);
for(unsigned int idx=0; idx<MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].setLayerHeight(layer_thickness);
@@ -956,6 +956,7 @@ void GCodePlanner::processInitialLayersSpeedup()
//Skin speed (per mesh).
mesh.skin_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
mesh.perimeter_gap_config.smoothSpeed(initial_layer_speed_config, layer_nr, initial_speedup_layers);
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
@@ -977,6 +978,7 @@ void GCodePlanner::processInitialLayersSpeedup()
mesh.inset0_config.setSpeedIconic();
mesh.insetX_config.setSpeedIconic();
mesh.skin_config.setSpeedIconic();
mesh.perimeter_gap_config.setSpeedIconic();
for (unsigned int idx = 0; idx < MAX_INFILL_COMBINE; idx++)
{
mesh.infill_config[idx].setSpeedIconic();
@@ -987,7 +989,7 @@ void GCodePlanner::processInitialLayersSpeedup()
bool GCodePlanner::makeRetractSwitchRetract(unsigned int extruder_plan_idx, unsigned int path_idx)
bool GCodePlanner::makeRetractSwitchRetract(GCodeExport& gcode, unsigned int extruder_plan_idx, unsigned int path_idx)
{
std::vector<GCodePath>& paths = extruder_plans[extruder_plan_idx].paths;
for (unsigned int path_idx2 = path_idx + 1; path_idx2 < paths.size(); path_idx2++)
+3 -2
Ver Arquivo
@@ -451,12 +451,13 @@ public:
/*!
* Whether the current retracted path is to be an extruder switch retraction.
* This function is used to avoid a G10 S1 after a G10.
*
*
* \param gcode The gcode to write the planned paths to
* \param extruder_plan_idx The index of the current extruder plan
* \param path_idx The index of the current retracted path
* \return Whether the path should be an extgruder switch retracted path
*/
bool makeRetractSwitchRetract(unsigned int extruder_plan_idx, unsigned int path_idx);
bool makeRetractSwitchRetract(GCodeExport& gcode, unsigned int extruder_plan_idx, unsigned int path_idx);
/*!
* Writes a path to GCode and performs coasting, or returns false if it did nothing.
+32 -19
Ver Arquivo
@@ -41,16 +41,20 @@ void SubDivCube::precomputeOctree(SliceMeshStorage& mesh)
coord_t max_side_length = furthest_dist_from_origin * 2;
int curr_recursion_depth = 0;
for (int64_t curr_side_length = mesh.getSettingInMicrons("infill_line_distance") * 2; curr_side_length < max_side_length * 2; curr_side_length *= 2)
const int64_t infill_line_distance = mesh.getSettingInMicrons("infill_line_distance");
if (infill_line_distance > 0)
{
cube_properties_per_recursion_step.emplace_back();
CubeProperties& cube_properties_here = cube_properties_per_recursion_step.back();
cube_properties_here.side_length = curr_side_length;
cube_properties_here.height = sqrt(3) * curr_side_length;
cube_properties_here.square_height = sqrt(2) * curr_side_length;
cube_properties_here.max_draw_z_diff = ONE_OVER_SQRT_3 * curr_side_length;
cube_properties_here.max_line_offset = ONE_OVER_SQRT_6 * curr_side_length;
curr_recursion_depth++;
for (int64_t curr_side_length = infill_line_distance * 2; curr_side_length < max_side_length * 2; curr_side_length *= 2)
{
cube_properties_per_recursion_step.emplace_back();
CubeProperties& cube_properties_here = cube_properties_per_recursion_step.back();
cube_properties_here.side_length = curr_side_length;
cube_properties_here.height = sqrt(3) * curr_side_length;
cube_properties_here.square_height = sqrt(2) * curr_side_length;
cube_properties_here.max_draw_z_diff = ONE_OVER_SQRT_3 * curr_side_length;
cube_properties_here.max_line_offset = ONE_OVER_SQRT_6 * curr_side_length;
curr_recursion_depth++;
}
}
Point3 center(0, 0, 0);
@@ -80,6 +84,10 @@ void SubDivCube::precomputeOctree(SliceMeshStorage& mesh)
void SubDivCube::generateSubdivisionLines(int64_t z, Polygons& result)
{
if (cube_properties_per_recursion_step.empty()) //Infill is set to 0%.
{
return;
}
Polygons directional_line_groups[3];
generateSubdivisionLines(z, result, directional_line_groups);
@@ -136,17 +144,21 @@ void SubDivCube::generateSubdivisionLines(int64_t z, Polygons& result, Polygons
}
}
SubDivCube::SubDivCube(SliceMeshStorage& mesh, Point3& center, int depth)
SubDivCube::SubDivCube(SliceMeshStorage& mesh, Point3& center, unsigned int depth)
{
this->depth = depth;
this->center = center;
CubeProperties cube_properties = cube_properties_per_recursion_step[depth];
if (depth == 0) // lowest layer, no need for subdivision, exit.
{
return;
}
if (depth >= cube_properties_per_recursion_step.size()) //Depth is out of bounds of what we pre-computed.
{
return;
}
CubeProperties cube_properties = cube_properties_per_recursion_step[depth];
Point3 child_center;
coord_t radius = double(radius_multiplier * double(cube_properties.height)) / 4.0 + radius_addition;
@@ -174,15 +186,15 @@ SubDivCube::SubDivCube(SliceMeshStorage& mesh, Point3& center, int depth)
bool SubDivCube::isValidSubdivision(SliceMeshStorage& mesh, Point3& center, int64_t radius)
{
int64_t distance2;
long int sphere_slice_radius2;//!< squared radius of bounding sphere slice on target layer
coord_t sphere_slice_radius2;//!< squared radius of bounding sphere slice on target layer
bool inside_somewhere = false;
bool outside_somewhere = false;
int inside;
double part_dist;//what percentage of the radius the target layer is away from the center along the z axis. 0 - 1
const long int layer_height = mesh.getSettingInMicrons("layer_height");
long int bottom_layer = (center.z - radius) / layer_height;
long int top_layer = (center.z + radius) / layer_height;
for (long int test_layer = bottom_layer; test_layer <= top_layer; test_layer += 3) // steps of three. Low-hanging speed gain.
const coord_t layer_height = mesh.getSettingInMicrons("layer_height");
int bottom_layer = (center.z - radius) / layer_height;
int top_layer = (center.z + radius) / layer_height;
for (int test_layer = bottom_layer; test_layer <= top_layer; test_layer += 3) // steps of three. Low-hanging speed gain.
{
part_dist = (double)(test_layer * layer_height - center.z) / radius;
sphere_slice_radius2 = radius * radius * (1.0 - (part_dist * part_dist));
@@ -209,11 +221,12 @@ bool SubDivCube::isValidSubdivision(SliceMeshStorage& mesh, Point3& center, int6
return false;
}
int SubDivCube::distanceFromPointToMesh(SliceMeshStorage& mesh, long int layer_nr, Point& location, int64_t* distance2)
int SubDivCube::distanceFromPointToMesh(SliceMeshStorage& mesh, int layer_nr, Point& location, int64_t* distance2)
{
if (layer_nr < 0 || (unsigned long int)layer_nr >= mesh.layers.size()) //!< this layer is outside of valid range
if (layer_nr < 0 || (unsigned int)layer_nr >= mesh.layers.size()) //!< this layer is outside of valid range
{
return 2;
*distance2 = 0;
}
Polygons collide;
mesh.layers[layer_nr].getSecondOrInnermostWalls(collide);
+3 -3
Ver Arquivo
@@ -17,7 +17,7 @@ public:
* \param my_center the center of the cube
* \param depth the recursion depth of the cube (0 is most recursed)
*/
SubDivCube(SliceMeshStorage& mesh, Point3& center, int depth);
SubDivCube(SliceMeshStorage& mesh, Point3& center, unsigned int depth);
~SubDivCube(); //!< destructor (also destroys children
@@ -74,7 +74,7 @@ private:
* \param[out] distance2 the squared distance to the infill border
* \return Code 0: outside, 1: inside, 2: boundary does not exist at specified layer
*/
static int distanceFromPointToMesh(SliceMeshStorage& mesh, long int layer_nr, Point& location, int64_t* distance2);
static int distanceFromPointToMesh(SliceMeshStorage& mesh, int layer_nr, Point& location, int64_t* distance2);
/*!
* Adds the defined line to the specified polygons. It assumes that the specified polygons are all parallel lines. Combines line segments with touching ends closer than epsilon.
@@ -84,7 +84,7 @@ private:
*/
void addLineAndCombine(Polygons& group, Point from, Point to);
int depth; //!< the recursion depth of the cube (0 is most recursed)
unsigned int depth; //!< the recursion depth of the cube (0 is most recursed)
Point3 center; //!< center location of the cube in absolute coordinates
SubDivCube* children[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; //!< pointers to this cube's eight octree children
static std::vector<CubeProperties> cube_properties_per_recursion_step; //!< precomputed array of basic properties of cubes based on recursion depth.
+4 -4
Ver Arquivo
@@ -1,10 +1,10 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include "LayerPart.h"
#include "../settings/settings.h"
#include "../progress/Progress.h"
#include "layerPart.h"
#include "settings/settings.h"
#include "progress/Progress.h"
#include "../utils/SVG.h" // debug output
#include "utils/SVG.h" // debug output
/*
The layer-part creation step is the first step in creating actual useful data for 3D printing.
+6 -6
Ver Arquivo
@@ -1,10 +1,10 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef SLICER_LAYERPART_H
#define SLICER_LAYERPART_H
#ifndef LAYERPART_H
#define LAYERPART_H
#include "../sliceDataStorage.h"
#include "Slicer.h"
#include "../commandSocket.h"
#include "sliceDataStorage.h"
#include "slicer.h"
#include "commandSocket.h"
/*
The layer-part creation step is the first step in creating actual useful data for 3D printing.
@@ -28,4 +28,4 @@ void layerparts2HTML(SliceDataStorage& mesh, const char* filename, bool all_laye
}//namespace cura
#endif//SLICER_LAYERPART_H
#endif//LAYERPART_H
+1 -1
Ver Arquivo
@@ -210,7 +210,7 @@ void slice(int argc, char **argv)
}
else
{
last_settings_object = meshgroup->meshes.back();
last_settings_object = &(meshgroup->meshes.back()); // pointer is valid until a new object is added, so this is OK
}
break;
case 'o':
+2 -33
Ver Arquivo
@@ -19,21 +19,12 @@ Mesh::Mesh(SettingsBaseVirtual* parent)
{
}
bool Mesh::addFace(Point3& v0, Point3& v1, Point3& v2)
void Mesh::addFace(Point3& v0, Point3& v1, Point3& v2)
{
int vi0 = findIndexOfVertex(v0);
int vi1 = findIndexOfVertex(v1);
int vi2 = findIndexOfVertex(v2);
return addFace(vi0, vi1, vi2);
}
bool Mesh::addFace(int vi0, int vi1, int vi2)
{
if (vi0 == vi1 || vi1 == vi2 || vi0 == vi2)
{
// the face has two vertices which get assigned the same location. Don't add the face.
return false;
}
if (vi0 == vi1 || vi1 == vi2 || vi0 == vi2) return; // the face has two vertices which get assigned the same location. Don't add the face.
int idx = faces.size(); // index of face to be added
faces.emplace_back();
@@ -44,8 +35,6 @@ bool Mesh::addFace(int vi0, int vi1, int vi2)
vertices[face.vertex_index[0]].connected_faces.push_back(idx);
vertices[face.vertex_index[1]].connected_faces.push_back(idx);
vertices[face.vertex_index[2]].connected_faces.push_back(idx);
return true;
}
void Mesh::clear()
@@ -92,14 +81,6 @@ void Mesh::expandXY(int64_t offset)
}
void Mesh::addVertex(const Point3& v)
{
uint32_t hash = pointHash(v);
vertex_hash_map[hash].push_back(vertices.size());
vertices.emplace_back(v);
aabb.include(v);
}
int Mesh::findIndexOfVertex(const Point3& v)
{
uint32_t hash = pointHash(v);
@@ -208,16 +189,4 @@ int Mesh::getFaceIdxWithPoints(int idx0, int idx1, int notFaceIdx, int notFaceVe
return bestIdx;
}
bool Mesh::registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const
{
// do nothing for a non-textured mesh
return false;
}
float Mesh::getColor(MatCoord, ColourUsage) const
{
return 0.0f;
}
}//namespace cura
+1 -28
Ver Arquivo
@@ -3,7 +3,6 @@
#include "settings/settings.h"
#include "utils/AABB3D.h"
#include "MatSegment.h"
namespace cura
{
@@ -66,26 +65,7 @@ public:
Mesh(SettingsBaseVirtual* parent); //!< initializes the settings
virtual ~Mesh() {} //!< Destructor
/*!
* add a face to the mesh without settings it's connected_faces.
*
* Don't add a face when the surface is zero mm^2
*
* \return whether a face has been added
*/
bool addFace(Point3& v0, Point3& v1, Point3& v2);
/*!
* add a face to the mesh without settings it's connected_faces.
*
* Don't add a face when the surface is zero mm^2
*
* \return whether a face has been added
*/
bool addFace(int vi0, int vi1, int vi2);
void addVertex(const Point3& v);
void addFace(Point3& v0, Point3& v1, Point3& v2); //!< add a face to the mesh without settings it's connected_faces.
void clear(); //!< clears all data
void finish(); //!< complete the model : set the connected_face_index fields of the faces.
@@ -106,13 +86,6 @@ public:
aabb.offset(offset);
}
/*!
* \return Whether a texture line segment has been created
*/
virtual bool registerFaceSlice(unsigned int face_idx, unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, Point segment_start, Point segment_end, MatSegment& result) const;
virtual float getColor(MatCoord bitmap_coord, ColourUsage color) const;
private:
int findIndexOfVertex(const Point3& v); //!< find index of vertex close to the given point, or create a new vertex and return its index.
@@ -1,4 +1,4 @@
#include "MultiVolumes.h"
#include "multiVolumes.h"
namespace cura
{
@@ -1,8 +1,8 @@
#ifndef SLICER_MULTIVOLUMES_H
#define SLICER_MULTIVOLUMES_H
#ifndef MULTIVOLUMES_H
#define MULTIVOLUMES_H
#include "../sliceDataStorage.h"
#include "Slicer.h"
#include "sliceDataStorage.h"
#include "slicer.h"
/* This file contains code to help fixing up and changing layers that are build from multiple volumes. */
namespace cura {
@@ -21,4 +21,4 @@ void generateMultipleVolumesOverlap(std::vector<Slicer*> &meshes);
}//namespace cura
#endif//SLICER_MULTIVOLUMES_H
#endif//MULTIVOLUMES_H
+24
Ver Arquivo
@@ -0,0 +1,24 @@
//Copyright (C) 2016 Ultimaker
//Released under terms of the AGPLv3 License
#include "GCodePath.h"
namespace cura
{
bool GCodePath::isTravelPath()
{
return config->isTravelPath();
}
double GCodePath::getExtrusionMM3perMM()
{
return flow * config->getExtrusionMM3perMM();
}
int GCodePath::getLineWidth()
{
return flow * config->getLineWidth() * config->getFlowPercentage() / 100.0;
}
}
+3 -12
Ver Arquivo
@@ -41,10 +41,7 @@ public:
*
* \return Whether this config is the config of a travel path.
*/
bool isTravelPath()
{
return config->isTravelPath();
}
bool isTravelPath();
/*!
* Get the material flow in mm^3 per mm traversed.
@@ -53,19 +50,13 @@ public:
*
* \return The flow
*/
double getExtrusionMM3perMM()
{
return flow * config->getExtrusionMM3perMM();
}
double getExtrusionMM3perMM();
/*!
* Get the actual line width (modulated by the flow)
* \return the actual line width as shown in layer view
*/
int getLineWidth()
{
return flow * config->getLineWidth() * config->getFlowPercentage() / 100.0;
}
int getLineWidth();
};
}//namespace cura
+24
Ver Arquivo
@@ -0,0 +1,24 @@
//Copyright (C) 2016 Ultimaker
//Released under terms of the AGPLv3 License
#include "NozzleTempInsert.h"
namespace cura
{
NozzleTempInsert::NozzleTempInsert(unsigned int path_idx, int extruder, double temperature, bool wait, double time_after_path_start)
: path_idx(path_idx)
, time_after_path_start(time_after_path_start)
, extruder(extruder)
, temperature(temperature)
, wait(wait)
{
assert(temperature != 0 && temperature != -1 && "Temperature command must be set!");
}
void NozzleTempInsert::write(GCodeExport& gcode)
{
gcode.writeTemperatureCommand(extruder, temperature, wait);
}
}
+2 -13
Ver Arquivo
@@ -19,24 +19,13 @@ struct NozzleTempInsert
int extruder; //!< The extruder for which to set the temp
double temperature; //!< The temperature of the temperature command to insert
bool wait; //!< Whether to wait for the temperature to be reached
NozzleTempInsert(unsigned int path_idx, int extruder, double temperature, bool wait, double time_after_path_start = 0.0)
: path_idx(path_idx)
, time_after_path_start(time_after_path_start)
, extruder(extruder)
, temperature(temperature)
, wait(wait)
{
assert(temperature != 0 && temperature != -1 && "Temperature command must be set!");
}
NozzleTempInsert(unsigned int path_idx, int extruder, double temperature, bool wait, double time_after_path_start = 0.0);
/*!
* Write the temperature command at the current position in the gcode.
* \param gcode The actual gcode writer
*/
void write(GCodeExport& gcode)
{
gcode.writeTemperatureCommand(extruder, temperature, wait);
}
void write(GCodeExport& gcode);
};
}//namespace cura
+63
Ver Arquivo
@@ -4,6 +4,22 @@
namespace cura
{
TimeMaterialEstimates::TimeMaterialEstimates(double extrude_time, double unretracted_travel_time, double retracted_travel_time, double material)
: extrude_time(extrude_time)
, unretracted_travel_time(unretracted_travel_time)
, retracted_travel_time(retracted_travel_time)
, material(material)
{
}
TimeMaterialEstimates::TimeMaterialEstimates()
: extrude_time(0.0)
, unretracted_travel_time(0.0)
, retracted_travel_time(0.0)
, material(0.0)
{
}
TimeMaterialEstimates TimeMaterialEstimates::operator-(const TimeMaterialEstimates& other)
{
return TimeMaterialEstimates(extrude_time - other.extrude_time,unretracted_travel_time - other.unretracted_travel_time,retracted_travel_time - other.retracted_travel_time,material - other.material);
@@ -18,4 +34,51 @@ TimeMaterialEstimates& TimeMaterialEstimates::operator-=(const TimeMaterialEstim
return *this;
}
TimeMaterialEstimates TimeMaterialEstimates::operator+(const TimeMaterialEstimates& other)
{
return TimeMaterialEstimates(extrude_time+other.extrude_time, unretracted_travel_time+other.unretracted_travel_time, retracted_travel_time+other.retracted_travel_time, material+other.material);
}
TimeMaterialEstimates& TimeMaterialEstimates::operator+=(const TimeMaterialEstimates& other)
{
extrude_time += other.extrude_time;
unretracted_travel_time += other.unretracted_travel_time;
retracted_travel_time += other.retracted_travel_time;
material += other.material;
return *this;
}
double TimeMaterialEstimates::getExtrudeTime() const
{
return extrude_time;
}
double TimeMaterialEstimates::getMaterial() const
{
return material;
}
double TimeMaterialEstimates::getTotalTime() const
{
return extrude_time + unretracted_travel_time + retracted_travel_time;
}
double TimeMaterialEstimates::getTotalUnretractedTime() const
{
return extrude_time + unretracted_travel_time;
}
double TimeMaterialEstimates::getTravelTime() const
{
return retracted_travel_time + unretracted_travel_time;
}
void TimeMaterialEstimates::reset()
{
extrude_time = 0.0;
unretracted_travel_time = 0.0;
retracted_travel_time = 0.0;
material = 0.0;
}
}//namespace cura
+10 -53
Ver Arquivo
@@ -29,35 +29,17 @@ public:
* \param retracted_travel_time Time in seconds occupied by retracted travel (non-extrusion)
* \param material Material used (in mm^3)
*/
TimeMaterialEstimates(double extrude_time, double unretracted_travel_time, double retracted_travel_time, double material)
: extrude_time(extrude_time)
, unretracted_travel_time(unretracted_travel_time)
, retracted_travel_time(retracted_travel_time)
, material(material)
{
}
TimeMaterialEstimates(double extrude_time, double unretracted_travel_time, double retracted_travel_time, double material);
/*!
* Basic constructor initializing all estimates to zero.
*/
TimeMaterialEstimates()
: extrude_time(0.0)
, unretracted_travel_time(0.0)
, retracted_travel_time(0.0)
, material(0.0)
{
}
TimeMaterialEstimates();
/*!
* Set all estimates to zero.
*/
void reset()
{
extrude_time = 0.0;
unretracted_travel_time = 0.0;
retracted_travel_time = 0.0;
material = 0.0;
}
void reset();
/*!
* Pointwise addition of estimate stats
@@ -65,10 +47,7 @@ public:
* \param other The estimates to add to these estimates.
* \return The resulting estimates
*/
TimeMaterialEstimates operator+(const TimeMaterialEstimates& other)
{
return TimeMaterialEstimates(extrude_time+other.extrude_time, unretracted_travel_time+other.unretracted_travel_time, retracted_travel_time+other.retracted_travel_time, material+other.material);
}
TimeMaterialEstimates operator+(const TimeMaterialEstimates& other);
/*!
* In place pointwise addition of estimate stats
@@ -76,14 +55,7 @@ public:
* \param other The estimates to add to these estimates.
* \return These estimates
*/
TimeMaterialEstimates& operator+=(const TimeMaterialEstimates& other)
{
extrude_time += other.extrude_time;
unretracted_travel_time += other.unretracted_travel_time;
retracted_travel_time += other.retracted_travel_time;
material += other.material;
return *this;
}
TimeMaterialEstimates& operator+=(const TimeMaterialEstimates& other);
/*!
* \brief Subtracts the specified estimates from these estimates and returns
@@ -112,10 +84,7 @@ public:
*
* \return the total of all different time estimate values
*/
double getTotalTime() const
{
return extrude_time + unretracted_travel_time + retracted_travel_time;
}
double getTotalTime() const;
/*!
* Get the total time during which the head is not retracted.
@@ -124,10 +93,7 @@ public:
*
* \return the total time during which the head is not retracted.
*/
double getTotalUnretractedTime() const
{
return extrude_time + unretracted_travel_time;
}
double getTotalUnretractedTime() const;
/*!
* Get the total travel time.
@@ -136,30 +102,21 @@ public:
*
* \return the total travel time.
*/
double getTravelTime() const
{
return retracted_travel_time + unretracted_travel_time;
}
double getTravelTime() const;
/*!
* Get the extrusion time.
*
* \return extrusion time.
*/
double getExtrudeTime() const
{
return extrude_time;
}
double getExtrudeTime() const;
/*!
* Get the amount of material used in mm^3.
*
* \return amount of material
*/
double getMaterial() const
{
return material;
}
double getMaterial() const;
};
}//namespace cura
+10 -8
Ver Arquivo
@@ -125,6 +125,11 @@ bool SettingRegistry::getDefinitionFile(const std::string machine_id, std::strin
int SettingRegistry::loadExtruderJSONsettings(unsigned int extruder_nr, SettingsBase* settings_base)
{
if (extruder_train_ids.empty())
{
logError("Couldn't find any extruder trains!\n");
return -1;
}
if (extruder_nr >= extruder_train_ids.size())
{
logWarning("Couldn't load extruder.def.json file for extruder %i. Index out of bounds.\n Loading first extruder definition instead.\n", extruder_nr);
@@ -220,8 +225,7 @@ int SettingRegistry::loadJSONsettingsFromDoc(rapidjson::Document& json_document,
if (json_document.HasMember("settings"))
{
std::list<std::string> path;
handleChildren(json_document["settings"], path, settings_base, warn_duplicates);
handleChildren(json_document["settings"], settings_base, warn_duplicates);
}
if (json_document.HasMember("overrides"))
@@ -243,7 +247,7 @@ int SettingRegistry::loadJSONsettingsFromDoc(rapidjson::Document& json_document,
return 0;
}
void SettingRegistry::handleChildren(const rapidjson::Value& settings_list, std::list<std::string>& path, SettingsBase* settings_base, bool warn_duplicates)
void SettingRegistry::handleChildren(const rapidjson::Value& settings_list, SettingsBase* settings_base, bool warn_duplicates)
{
if (!settings_list.IsObject())
{
@@ -252,12 +256,10 @@ void SettingRegistry::handleChildren(const rapidjson::Value& settings_list, std:
}
for (rapidjson::Value::ConstMemberIterator setting_iterator = settings_list.MemberBegin(); setting_iterator != settings_list.MemberEnd(); ++setting_iterator)
{
handleSetting(setting_iterator, path, settings_base, warn_duplicates);
handleSetting(setting_iterator, settings_base, warn_duplicates);
if (setting_iterator->value.HasMember("children"))
{
std::list<std::string> path_here = path;
path_here.push_back(setting_iterator->name.GetString());
handleChildren(setting_iterator->value["children"], path_here, settings_base, warn_duplicates);
handleChildren(setting_iterator->value["children"], settings_base, warn_duplicates);
}
}
}
@@ -275,7 +277,7 @@ bool SettingRegistry::settingIsUsedByEngine(const rapidjson::Value& setting)
}
void SettingRegistry::handleSetting(const rapidjson::Value::ConstMemberIterator& json_setting_it, std::list<std::string>& path, SettingsBase* settings_base, bool warn_duplicates)
void SettingRegistry::handleSetting(const rapidjson::Value::ConstMemberIterator& json_setting_it, SettingsBase* settings_base, bool warn_duplicates)
{
const rapidjson::Value& json_setting = json_setting_it->value;
if (!json_setting.IsObject())
+2 -3
Ver Arquivo
@@ -174,17 +174,16 @@ private:
* \param settings_base The settings base where to store the default values.
* \param warn_duplicates whether to warn for duplicate setting definitions
*/
void handleChildren(const rapidjson::Value& settings_list, std::list<std::string>& path, SettingsBase* settings_base, bool warn_duplicates);
void handleChildren(const rapidjson::Value& settings_list, SettingsBase* settings_base, bool warn_duplicates);
/*!
* Handle a json object for a setting.
*
* \param json_setting_it Iterator for the setting which contains the key (setting name) and attributes info
* \param path The path of (internal) setting names traversed to get to this object
* \param settings_base The settings base where to store the default values.
* \param warn_duplicates whether to warn for duplicate setting definitions
*/
void handleSetting(const rapidjson::Value::ConstMemberIterator& json_setting_it, std::list<std::string>& path, SettingsBase* settings_base, bool warn_duplicates);
void handleSetting(const rapidjson::Value::ConstMemberIterator& json_setting_it, SettingsBase* settings_base, bool warn_duplicates);
};
}//namespace cura
-12
Ver Arquivo
@@ -177,18 +177,6 @@ enum class SupportDistPriority
Z_OVERRIDES_XY
};
/*!
* Which color(s) of a texture to use
*/
enum class ColourUsage
{
RED = 0,
GREEN = 1,
BLUE = 2,
ALPHA = 3,
GREY // use red, green and blue channels
};
#define MAX_EXTRUDERS 16
//Maximum number of infill layers that can be combined into a single infill extrusion area.
+2
Ver Arquivo
@@ -155,6 +155,7 @@ public:
GCodePathConfig inset0_config;
GCodePathConfig insetX_config;
GCodePathConfig skin_config;
GCodePathConfig perimeter_gap_config;
std::vector<GCodePathConfig> infill_config;
SubDivCube* base_subdiv_cube;
@@ -165,6 +166,7 @@ public:
, inset0_config(PrintFeatureType::OuterWall)
, insetX_config(PrintFeatureType::InnerWall)
, skin_config(PrintFeatureType::Skin)
, perimeter_gap_config(PrintFeatureType::Skin)
, base_subdiv_cube(nullptr)
{
layers.resize(slice_layer_count);
+121 -9
Ver Arquivo
@@ -1,11 +1,16 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <stdio.h>
#include "SlicerLayer.h"
#include "../TextureProcessor.h"
#include "../utils/SparsePointGridInclusive.h"
#include <algorithm> // remove_if
namespace cura
{
#include "utils/gettime.h"
#include "utils/logoutput.h"
#include "utils/SparsePointGridInclusive.h"
#include "slicer.h"
namespace cura {
int largest_neglected_gap_first_phase = MM2INT(0.01); //!< distance between two line segments regarded as connected
int largest_neglected_gap_second_phase = MM2INT(0.02); //!< distance between two line segments regarded as connected
@@ -769,8 +774,6 @@ void SlicerLayer::makePolygons(const Mesh* mesh, bool keep_none_closed, bool ext
auto it = std::remove_if(polygons.begin(), polygons.end(), [snapDistance](PolygonRef poly) { return poly.shorterThan(snapDistance); });
polygons.erase(it, polygons.end());
TextureProcessor::processBumpMap(mesh, *this);
//Finally optimize all the polygons. Every point removed saves time in the long run.
polygons.simplify();
@@ -783,4 +786,113 @@ void SlicerLayer::makePolygons(const Mesh* mesh, bool keep_none_closed, bool ext
}
}
} // namespace cura
Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keep_none_closed, bool extensive_stitching)
: mesh(mesh)
{
assert(slice_layer_count > 0);
TimeKeeper slice_timer;
layers.resize(slice_layer_count);
for(int32_t layer_nr = 0; layer_nr < slice_layer_count; layer_nr++)
{
layers[layer_nr].z = initial + thickness * layer_nr;
}
for(unsigned int mesh_idx = 0; mesh_idx < mesh->faces.size(); mesh_idx++)
{
const MeshFace& face = mesh->faces[mesh_idx];
const MeshVertex& v0 = mesh->vertices[face.vertex_index[0]];
const MeshVertex& v1 = mesh->vertices[face.vertex_index[1]];
const MeshVertex& v2 = mesh->vertices[face.vertex_index[2]];
Point3 p0 = v0.p;
Point3 p1 = v1.p;
Point3 p2 = v2.p;
int32_t minZ = p0.z;
int32_t maxZ = p0.z;
if (p1.z < minZ) minZ = p1.z;
if (p2.z < minZ) minZ = p2.z;
if (p1.z > maxZ) maxZ = p1.z;
if (p2.z > maxZ) maxZ = p2.z;
int32_t layer_max = (maxZ - initial) / thickness;
for(int32_t layer_nr = (minZ - initial) / thickness; layer_nr <= layer_max; layer_nr++)
{
int32_t z = layer_nr * thickness + initial;
if (z < minZ) continue;
if (layer_nr < 0) continue;
SlicerSegment s;
s.endVertex = nullptr;
int end_edge_idx = -1;
if (p0.z < z && p1.z >= z && p2.z >= z)
{
s = project2D(p0, p2, p1, z);
end_edge_idx = 0;
if (p1.z == z)
{
s.endVertex = &v1;
}
}
else if (p0.z > z && p1.z < z && p2.z < z)
{
s = project2D(p0, p1, p2, z);
end_edge_idx = 2;
}
else if (p1.z < z && p0.z >= z && p2.z >= z)
{
s = project2D(p1, p0, p2, z);
end_edge_idx = 1;
if (p2.z == z)
{
s.endVertex = &v2;
}
}
else if (p1.z > z && p0.z < z && p2.z < z)
{
s = project2D(p1, p2, p0, z);
end_edge_idx = 0;
}
else if (p2.z < z && p1.z >= z && p0.z >= z)
{
s = project2D(p2, p1, p0, z);
end_edge_idx = 2;
if (p0.z == z)
{
s.endVertex = &v0;
}
}
else if (p2.z > z && p1.z < z && p0.z < z)
{
s = project2D(p2, p0, p1, z);
end_edge_idx = 1;
}
else
{
//Not all cases create a segment, because a point of a face could create just a dot, and two touching faces
// on the slice would create two segments
continue;
}
layers[layer_nr].face_idx_to_segment_idx.insert(std::make_pair(mesh_idx, layers[layer_nr].segments.size()));
s.faceIndex = mesh_idx;
s.endOtherFaceIdx = face.connected_face_index[end_edge_idx];
s.addedToPolygon = false;
layers[layer_nr].segments.push_back(s);
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
}//namespace cura
+80 -18
Ver Arquivo
@@ -1,21 +1,47 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_LAYER_H
#define SLICER_SLICER_LAYER_H
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef SLICER_H
#define SLICER_H
#include <unordered_map>
#include <queue>
#include "../mesh.h"
#include "../utils/intpoint.h"
#include "../utils/polygon.h"
#include "mesh.h"
#include "utils/polygon.h"
/*
The Slicer creates layers of polygons from an optimized 3D model.
The result of the Slicer is a list of polygons without any order or structure.
*/
namespace cura {
#include "SlicerSegment.h"
#include "GapCloserResult.h"
#include "ClosePolygonResult.h"
#include "../MatSegment.h"
namespace cura
class SlicerSegment
{
public:
Point start, end;
int faceIndex = -1;
// The index of the other face connected via the edge that created end
int endOtherFaceIdx = -1;
// If end corresponds to a vertex of the mesh, then this is populated
// with the vertex that it ended on.
const MeshVertex *endVertex = nullptr;
bool addedToPolygon = false;
};
class ClosePolygonResult
{ //The result of trying to find a point on a closed polygon line. This gives back the point index, the polygon index, and the point of the connection.
//The line on which the point lays is between pointIdx-1 and pointIdx
public:
Point intersectionPoint;
int polygonIdx = -1;
unsigned int pointIdx = -1;
};
class GapCloserResult
{
public:
int64_t len = -1;
int polygonIdx = -1;
unsigned int pointIdxA = -1;
unsigned int pointIdxB = -1;
bool AtoB = false;
};
class SlicerLayer
{
@@ -26,8 +52,6 @@ public:
int z = -1;
Polygons polygons;
Polygons openPolylines;
std::unordered_map<SlicerSegment, MatSegment> segment_to_material_segment;
/*!
* Connect the segments into polygons for this layer of this \p mesh
@@ -459,6 +483,44 @@ private:
bool allow_reverse);
};
} // namespace cura
class Slicer
{
public:
std::vector<SlicerLayer> layers;
#endif // SLICER_SLICER_LAYER_H
const Mesh* mesh = nullptr; //!< The sliced mesh
Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keepNoneClosed, bool extensiveStitching);
/*!
* Linear interpolation
*
* Get the Y of a point with X \p x in the line through (\p x0, \p y0) and (\p x1, \p y1)
*/
int64_t interpolate(int64_t x, int64_t x0, int64_t x1, int64_t y0, int64_t y1) const
{
int64_t dx_01 = x1 - x0;
int64_t num = (y1 - y0) * (x - x0);
num += num > 0 ? dx_01/2 : -dx_01/2; // add in offset to round result
int64_t y = y0 + num / dx_01;
return y;
}
SlicerSegment project2D(Point3& p0, Point3& p1, Point3& p2, int32_t z) const
{
SlicerSegment seg;
seg.start.X = interpolate(z, p0.z, p1.z, p0.x, p1.x);
seg.start.Y = interpolate(z, p0.z, p1.z, p0.y, p1.y);
seg.end .X = interpolate(z, p0.z, p2.z, p0.x, p2.x);
seg.end .Y = interpolate(z, p0.z, p2.z, p0.y, p2.y);
return seg;
}
void dumpSegmentsToHTML(const char* filename);
};
}//namespace cura
#endif//SLICER_H
-21
Ver Arquivo
@@ -1,21 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_CLOSE_POLYGON_RESULT_H
#define SLICER_CLOSE_POLYGON_RESULT_H
#include "../utils/intpoint.h"
namespace cura
{
class ClosePolygonResult
{ //The result of trying to find a point on a closed polygon line. This gives back the point index, the polygon index, and the point of the connection.
//The line on which the point lays is between pointIdx-1 and pointIdx
public:
Point intersectionPoint;
int polygonIdx = -1;
unsigned int pointIdx = -1;
};
} // namespace cura
#endif // SLICER_CLOSE_POLYGON_RESULT_H
-22
Ver Arquivo
@@ -1,22 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_GAP_CLOSER_RESULT_H
#define SLICER_GAP_CLOSER_RESULT_H
#include "../utils/intpoint.h"
namespace cura
{
class GapCloserResult
{
public:
int64_t len = -1;
int polygonIdx = -1;
unsigned int pointIdxA = -1;
unsigned int pointIdxB = -1;
bool AtoB = false;
};
} // namespace cura
#endif // SLICER_GAP_CLOSER_RESULT_H
-147
Ver Arquivo
@@ -1,147 +0,0 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#include <stdio.h>
#include "../utils/gettime.h"
#include "../utils/logoutput.h"
#include "../MatCoord.h"
#include "Slicer.h"
namespace cura {
SlicerSegment Slicer::project2D(unsigned int face_idx, const Point3 p[3], unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, int32_t layer_nr)
{
const Point3& p0 = p[idx_shared];
const Point3& p1 = p[idx_first];
const Point3& p2 = p[idx_second];
SlicerSegment seg;
seg.start.X = interpolate(z, p0.z, p1.z, p0.x, p1.x);
seg.start.Y = interpolate(z, p0.z, p1.z, p0.y, p1.y);
seg.end .X = interpolate(z, p0.z, p2.z, p0.x, p2.x);
seg.end .Y = interpolate(z, p0.z, p2.z, p0.y, p2.y);
MatSegment mat_segment;
bool got_texture_coords = mesh->registerFaceSlice(face_idx, idx_shared, idx_first, idx_second, z, seg.start, seg.end, mat_segment);
if (got_texture_coords)
{
SlicerLayer& layer = layers[layer_nr];
layer.segment_to_material_segment.emplace(seg, mat_segment);
}
return seg;
}
Slicer::Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keep_none_closed, bool extensive_stitching)
: mesh(mesh)
{
assert(slice_layer_count > 0);
TimeKeeper slice_timer;
layers.resize(slice_layer_count);
for(int32_t layer_nr = 0; layer_nr < slice_layer_count; layer_nr++)
{
layers[layer_nr].z = initial + thickness * layer_nr;
}
for(unsigned int face_idx = 0; face_idx < mesh->faces.size(); face_idx++)
{
const MeshFace& face = mesh->faces[face_idx];
const MeshVertex& v0 = mesh->vertices[face.vertex_index[0]];
const MeshVertex& v1 = mesh->vertices[face.vertex_index[1]];
const MeshVertex& v2 = mesh->vertices[face.vertex_index[2]];
Point3 p[3] =
{ mesh->vertices[face.vertex_index[0]].p
, mesh->vertices[face.vertex_index[1]].p
, mesh->vertices[face.vertex_index[2]].p };
Point3& p0 = p[0];
Point3& p1 = p[1];
Point3& p2 = p[2];
int32_t minZ = p0.z;
int32_t maxZ = p0.z;
if (p1.z < minZ) minZ = p1.z;
if (p2.z < minZ) minZ = p2.z;
if (p1.z > maxZ) maxZ = p1.z;
if (p2.z > maxZ) maxZ = p2.z;
int32_t layer_max = (maxZ - initial) / thickness;
int32_t z = 0;
for (int32_t layer_nr = (minZ - initial + thickness - 1) / thickness; layer_nr < layer_max; layer_nr++) // + thickness - 1 to get the first layer above or at minZ
{
z = layer_nr * thickness + initial;
if (z < minZ) continue;
if (layer_nr < 0) continue;
SlicerSegment s;
s.endVertex = nullptr;
int end_edge_idx = -1;
if (p0.z < z && p1.z >= z && p2.z >= z)
{
s = project2D(face_idx, p, 0, 2, 1, z, layer_nr);
end_edge_idx = 0;
if (p1.z == z)
{
s.endVertex = &v1;
}
}
else if (p0.z > z && p1.z < z && p2.z < z)
{
s = project2D(face_idx, p, 0, 1, 2, z, layer_nr);
end_edge_idx = 2;
}
else if (p1.z < z && p0.z >= z && p2.z >= z)
{
s = project2D(face_idx, p, 1, 0, 2, z, layer_nr);
end_edge_idx = 1;
if (p2.z == z)
{
s.endVertex = &v2;
}
}
else if (p1.z > z && p0.z < z && p2.z < z)
{
s = project2D(face_idx, p, 1, 2, 0, z, layer_nr);
end_edge_idx = 0;
}
else if (p2.z < z && p1.z >= z && p0.z >= z)
{
s = project2D(face_idx, p, 2, 1, 0, z, layer_nr);
end_edge_idx = 2;
if (p0.z == z)
{
s.endVertex = &v0;
}
}
else if (p2.z > z && p1.z < z && p0.z < z)
{
s = project2D(face_idx, p, 2, 0, 1, z, layer_nr);
end_edge_idx = 1;
}
else
{
//Not all cases create a segment, because a point of a face could create just a dot, and two touching faces
// on the slice would create two segments
continue;
}
layers[layer_nr].face_idx_to_segment_idx.insert(std::make_pair(face_idx, layers[layer_nr].segments.size()));
s.faceIndex = face_idx;
s.endOtherFaceIdx = face.connected_face_index[end_edge_idx];
s.addedToPolygon = false;
layers[layer_nr].segments.push_back(s);
}
}
log("slice of mesh took %.3f seconds\n",slice_timer.restart());
for(unsigned int layer_nr=0; layer_nr<layers.size(); layer_nr++)
{
layers[layer_nr].makePolygons(mesh, keep_none_closed, extensive_stitching);
}
mesh->expandXY(mesh->getSettingInMicrons("xy_offset"));
log("slice make polygons took %.3f seconds\n",slice_timer.restart());
}
}//namespace cura
-60
Ver Arquivo
@@ -1,60 +0,0 @@
/** Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_H
#define SLICER_SLICER_H
#include <queue>
#include "../mesh.h"
#include "../utils/polygon.h"
#include "SlicerSegment.h"
#include "ClosePolygonResult.h"
#include "SlicerLayer.h"
#include "../MatSegment.h"
/*
The Slicer creates layers of polygons from an optimized 3D model.
The result of the Slicer is a list of polygons without any order or structure.
*/
namespace cura {
class Slicer
{
public:
std::vector<SlicerLayer> layers;
const Mesh* mesh = nullptr; //!< The sliced mesh
Slicer(Mesh* mesh, int initial, int thickness, int slice_layer_count, bool keepNoneClosed, bool extensiveStitching);
/*!
* Linear interpolation
*
* Get the Y of a point with X \p x in the line through (\p x0, \p y0) and (\p x1, \p y1)
*
* \param p The face vertice locations in the order the vertices are given in the face
*/
int64_t interpolate(int64_t x, int64_t x0, int64_t x1, int64_t y0, int64_t y1) const
{
int64_t dx_01 = x1 - x0;
int64_t num = (y1 - y0) * (x - x0);
num += num > 0 ? dx_01/2 : -dx_01/2; // add in offset to round result
int64_t y = y0 + num / dx_01;
return y;
}
SlicerSegment project2D(unsigned int face_idx, const Point3 p[3], unsigned int idx_shared, unsigned int idx_first, unsigned int idx_second, int32_t z, int32_t layer_nr);
void dumpSegmentsToHTML(const char* filename);
};
}//namespace cura
#endif//SLICER_SLICER_H
-57
Ver Arquivo
@@ -1,57 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef SLICER_SLICER_SEGMENT_H
#define SLICER_SLICER_SEGMENT_H
#include <functional>
#include "../utils/intpoint.h"
namespace cura
{
class SlicerSegment
{
public:
Point start, end;
int faceIndex = -1;
// The index of the other face connected via the edge that created end
int endOtherFaceIdx = -1;
// If end corresponds to a vertex of the mesh, then this is populated
// with the vertex that it ended on.
const MeshVertex *endVertex = nullptr;
bool addedToPolygon = false;
SlicerSegment() //!< non-initializing constructor
{}
SlicerSegment(Point start, Point end) //!< partially initializing constructor
: start(start)
, end(end)
{}
/*!
* equivalence testing irrespective of start/end order
*/
bool operator==(const SlicerSegment& b) const
{
return (start == b.start && end == b.end) || (start == b.end && end == b.start);
}
};
} // namespace cura
namespace std
{
/*!
* hash function irrespective of start/end order
*/
template<> struct hash<cura::SlicerSegment>
{
typedef std::size_t result_type;
result_type operator()(cura::SlicerSegment const& s) const
{
return std::hash<cura::Point>()(cura::operator+(s.start, s.end));
}
};
} // namespace std
#endif // SLICER_SLICER_SEGMENT_H
+55 -49
Ver Arquivo
@@ -90,6 +90,7 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int l
storage.support.supportLayers.resize(layer_count);
}
// generate support areas
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
@@ -100,25 +101,33 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int l
std::vector<Polygons> supportAreas;
supportAreas.resize(layer_count, Polygons());
generateSupportAreas(storage, mesh_idx, layer_count, supportAreas);
if (mesh.getSettingBoolean("support_interface_enable"))
for (unsigned int layer_idx = 0; layer_idx < layer_count; layer_idx++)
{
generateSupportInterface(storage, mesh, supportAreas, layer_count);
}
else
{
for (unsigned int layer_idx = 0; layer_idx < layer_count ; layer_idx++)
{
storage.support.supportLayers[layer_idx].supportAreas.add(supportAreas[layer_idx]);
}
storage.support.supportLayers[layer_idx].supportAreas.add(supportAreas[layer_idx]);
}
}
for (unsigned int layer_idx = 0; layer_idx < layer_count ; layer_idx++)
{
Polygons& support_areas = storage.support.supportLayers[layer_idx].supportAreas;
support_areas = support_areas.unionPolygons();
}
// handle support interface
for (unsigned int mesh_idx = 0; mesh_idx < storage.meshes.size(); mesh_idx++)
{
SliceMeshStorage& mesh = storage.meshes[mesh_idx];
if (mesh.getSettingBoolean("infill_mesh") || mesh.getSettingBoolean("anti_overhang_mesh"))
{
continue;
}
if (mesh.getSettingBoolean("support_interface_enable"))
{
generateSupportInterface(storage, mesh, layer_count);
}
}
}
/*
@@ -342,14 +351,14 @@ void AreaSupport::generateSupportAreas(SliceDataStorage& storage, unsigned int m
}
//Enforce top Z distance.
if (layerZdistanceTop > 0)
if (layerZdistanceTop > 1)
{
// this is performed after the main support generation loop above, because it affects the joining of polygons
// if this would be performed in the main loop then some support would not have been generated under the overhangs and consequently no support is generated for that,
// meaning almost no support would be generated in some cases which definitely need support.
for (size_t layer_idx = 0; layer_idx < storage.support.supportLayers.size() && layer_idx < support_layer_count - layerZdistanceTop; layer_idx++)
for (size_t layer_idx = 0; layer_idx < storage.support.supportLayers.size() && layer_idx < support_layer_count - (layerZdistanceTop - 1); layer_idx++)
{
supportAreas[layer_idx] = supportAreas[layer_idx].difference(storage.getLayerOutlines(layer_idx + layerZdistanceTop, false));
supportAreas[layer_idx] = supportAreas[layer_idx].difference(storage.getLayerOutlines(layer_idx + layerZdistanceTop - 1, false));
}
}
@@ -559,7 +568,7 @@ void AreaSupport::handleWallStruts(
}
void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, std::vector<Polygons>& support_areas, const unsigned int layer_count)
void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, const unsigned int layer_count)
{
const unsigned int roof_layer_count = round_divide(mesh.getSettingInMicrons("support_roof_height"), storage.getSettingInMicrons("layer_height"));
const unsigned int bottom_layer_count = round_divide(mesh.getSettingInMicrons("support_bottom_height"), storage.getSettingInMicrons("layer_height"));
@@ -576,44 +585,41 @@ void AreaSupport::generateSupportInterface(SliceDataStorage& storage, const Slic
const unsigned int top_layer_idx_above = layer_idx + roof_layer_count + z_distance_top;
const unsigned int bottom_layer_idx_below = std::max(0, int(layer_idx) - int(bottom_layer_count) - int(z_distance_bottom));
if (top_layer_idx_above < supportLayers.size())
if (top_layer_idx_above >= supportLayers.size())
{
Polygons roofs;
if (roof_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (roof_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(roof_layer_count - 1) / float(n_scans));
for (float layer_idx_above = top_layer_idx_above; layer_idx_above > layer_idx + z_distance_top; layer_idx_above -= z_skip)
{
const Polygons outlines_above = mesh.layers[std::round(layer_idx_above)].getOutlines();
model = model.unionPolygons(outlines_above);
}
roofs = support_areas[layer_idx].intersection(model);
}
Polygons bottoms;
if (bottom_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (bottom_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(bottom_layer_count - 1) / float(n_scans));
for (float layer_idx_below = bottom_layer_idx_below; std::round(layer_idx_below) < (int)(layer_idx - z_distance_bottom); layer_idx_below += z_skip)
{
const Polygons outlines_below = mesh.layers[std::round(layer_idx_below)].getOutlines();
model = model.unionPolygons(outlines_below);
}
bottoms = support_areas[layer_idx].intersection(model);
}
// expand skin a bit so that we're sure it's not too thin to be printed.
Polygons skin = roofs.unionPolygons(bottoms).offset(interface_line_width).intersection(support_areas[layer_idx]);
skin.removeSmallAreas(1.0);
layer.skin.add(skin);
layer.supportAreas.add(support_areas[layer_idx].difference(layer.skin));
continue;
}
else
Polygons roofs;
if (roof_layer_count > 0)
{
layer.skin.add(support_areas[layer_idx]);
Polygons model;
const unsigned int n_scans = std::max(1u, (roof_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(roof_layer_count - 1) / float(n_scans));
for (float layer_idx_above = top_layer_idx_above; layer_idx_above > layer_idx + z_distance_top; layer_idx_above -= z_skip)
{
const Polygons outlines_above = mesh.layers[std::round(layer_idx_above)].getOutlines();
model = model.unionPolygons(outlines_above);
}
roofs = layer.supportAreas.intersection(model);
}
Polygons bottoms;
if (bottom_layer_count > 0)
{
Polygons model;
const unsigned int n_scans = std::max(1u, (bottom_layer_count - 1) / skip_layer_count);
const float z_skip = std::max(1.0f, float(bottom_layer_count - 1) / float(n_scans));
for (float layer_idx_below = bottom_layer_idx_below; std::round(layer_idx_below) < (int)(layer_idx - z_distance_bottom); layer_idx_below += z_skip)
{
const Polygons outlines_below = mesh.layers[std::round(layer_idx_below)].getOutlines();
model = model.unionPolygons(outlines_below);
}
bottoms = layer.supportAreas.intersection(model);
}
// expand skin a bit so that we're sure it's not too thin to be printed.
Polygons skin = roofs.unionPolygons(bottoms).offset(interface_line_width).intersection(layer.supportAreas);
skin.removeSmallAreas(1.0);
layer.skin.add(skin);
layer.supportAreas = layer.supportAreas.difference(layer.skin);
}
}
+1 -2
Ver Arquivo
@@ -36,10 +36,9 @@ private:
*
* \param storage Output storage: support area + support skin area output
* \param mesh The mesh to generate support skins for.
* \param support_areas The basic support areas for the current mesh
* \param layer_count The number of layers in this mesh group.
*/
static void generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, std::vector<Polygons>& support_areas, const unsigned int layer_count);
static void generateSupportInterface(SliceDataStorage& storage, const SliceMeshStorage& mesh, const unsigned int layer_count);
/*!
* Join current support layer with the support of the layer above, (make support conical) and perform smoothing etc operations.
+6
Ver Arquivo
@@ -37,6 +37,12 @@ void AABB3D::include(Point3 p)
max.z = std::max(max.z, p.z);
}
void AABB3D::includeZ(int32_t z)
{
min.z = std::min(min.z, z);
max.z = std::max(max.z, z);
}
void AABB3D::offset(Point3 offset)
{
min += offset;
+8
Ver Arquivo
@@ -38,6 +38,14 @@ struct AABB3D
*/
void include(Point3 p);
/*!
* Expand the AABB3D to include a z-coordinate.
*
* This is for including a point of which the X and Y coordinates are
* unknown but known to already be included in the bounding box.
*/
void includeZ(int32_t z);
/*!
* Offset the coordinates of the bounding box.
* \param offset The offset with which to offset the AABB3D.
-74
Ver Arquivo
@@ -1,74 +0,0 @@
/** Copyright (C) 2016 Tim Kuipers - Released under terms of the AGPLv3 License */
#ifndef UTILS_F_POINT_H
#define UTILS_F_POINT_H
#include <cmath> // sqrt
#include <iostream> // auto-serialization / auto-toString() '<<'
namespace cura
{
/*!
* 2D coordinates represented by floats
*/
class FPoint
{
public:
float x, y; //!< Coordinates
FPoint() //!< non-initializing constructor
{}
FPoint(float x, float y) //!< constructor
: x(x)
, y(y)
{}
FPoint operator+(const FPoint& p) const { return FPoint(x+p.x, y+p.y); }
FPoint operator-(const FPoint& p) const { return FPoint(x-p.x, y-p.y); }
FPoint operator/(const float i) const { return FPoint(x/i, y/i); }
FPoint operator*(const float i) const { return FPoint(x*i, y*i); }
FPoint& operator += (const FPoint& p) { x += p.x; y += p.y; return *this; }
FPoint& operator -= (const FPoint& p) { x -= p.x; y -= p.y; return *this; }
bool operator==(const FPoint& p) const { return x == p.x && y == p.y; }
bool operator!=(const FPoint& p) const { return x != p.x || y != p.y; }
/*!
* output to string stream in standard format
*/
template<class CharT, class TraitsT>
friend
std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT, TraitsT>& os, const FPoint& p)
{
return os << "(" << p.x << ", " << p.y << ")";
}
/*!
* squared vector size
*/
float vSize2() const
{
return x * x + y * y;
}
/*!
* vector size
*/
float vSize() const
{
return sqrt(vSize2());
}
/*!
* dot product
*/
float dot(const FPoint& p) const
{
return x * p.x + y * p.y;
}
};
} // namespace cura
#endif // UTILS_F_POINT_H
+1 -11
Ver Arquivo
@@ -190,16 +190,6 @@ unsigned int Polygons::findInside(Point p, bool border_result)
return ret;
}
Polygons Polygons::removeComplexParts() const
{
Polygons ret;
ClipperLib::Clipper clipper(clipper_init);
clipper.AddPaths(paths, ClipperLib::ptSubject, true);
clipper.Execute(ClipperLib::ctUnion, ret.paths, ClipperLib::pftPositive);
return ret;
}
Polygons Polygons::offset(int distance, ClipperLib::JoinType join_type, double miter_limit) const
{
Polygons ret;
@@ -847,7 +837,6 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
Point b;
bool success = LinearAlg2D::getPointOnLineWithDist(a, p1, p2, shortcut_length, b);
// v02 has to be longer than ab!
p1_it.remove();
if (success)
{ // if not success then assume b is negligibly close to 2, but rounding errors caused a problem
#ifdef ASSERT_INSANE_OUTPUT
@@ -855,6 +844,7 @@ void PolygonRef::smooth_corner_simple(ListPolygon& poly, const Point p0, const P
#endif // #ifdef ASSERT_INSANE_OUTPUT
ListPolyIt::insertPointNonDuplicate(p1_it, p2_it, b);
}
p1_it.remove();
}
}
}
+4 -16
Ver Arquivo
@@ -54,7 +54,7 @@ public:
Point& operator[] (unsigned int index) const
{
POLY_ASSERT(index < size() && index >= 0);
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
return (*path)[index];
}
@@ -87,7 +87,7 @@ public:
void remove(unsigned int index)
{
POLY_ASSERT(index < size() && index >= 0);
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
path->erase(path->begin() + index);
}
@@ -409,7 +409,7 @@ public:
PolygonRef operator[] (unsigned int index)
{
POLY_ASSERT(index < size() && index >= 0);
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
return PolygonRef(paths[index]);
}
const PolygonRef operator[] (unsigned int index) const
@@ -439,7 +439,7 @@ public:
*/
void remove(unsigned int index)
{
POLY_ASSERT(index < size() && index >= 0);
POLY_ASSERT(index < size() && index <= std::numeric_limits<int>::max());
if (index < paths.size() - 1)
{
paths[index] = std::move(paths.back());
@@ -859,18 +859,6 @@ public:
return ret;
}
/*!
* Remove holes which are lying outside of parts, and outlines inside of parts
*
* ^↘
* ^ ↘
* <<<<<<<<^<<<< should become <<<<<<<<
* ^ ^
* ^ ^
* ^ ^
*/
Polygons removeComplexParts() const;
int64_t polygonLength() const
{
int64_t length = 0;
+4 -1
Ver Arquivo
@@ -1,3 +1,6 @@
//Copyright (c) 2017 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
@@ -35,7 +38,7 @@ static inline void writeInt2mm(const int64_t coord, std::ostream& ss)
{
constexpr size_t buffer_size = 24;
char buffer[buffer_size];
int char_count = sprintf(buffer, "%" PRId64, coord); // convert int to string
int char_count = sprintf(buffer, "%d", int(coord)); // convert int to string
#ifdef DEBUG
if (char_count + 1 >= int(buffer_size)) // + 1 for the null character
{