diff --git a/CMakeLists.txt b/CMakeLists.txt index d3d1bfb3af..5815908865 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,8 +68,6 @@ set(engine_SRCS # Except main.cpp. src/TreeModelVolumes.cpp src/TreeSupport.cpp src/WallsComputation.cpp - src/Weaver.cpp - src/Wireframe2gcode.cpp src/WallToolPaths.cpp src/BeadingStrategy/BeadingStrategy.cpp diff --git a/include/FffGcodeWriter.h b/include/FffGcodeWriter.h index feb2ac46cb..87564ed7f4 100644 --- a/include/FffGcodeWriter.h +++ b/include/FffGcodeWriter.h @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Ultimaker B.V. +// Copyright (c) 2023 UltiMaker // CuraEngine is released under the terms of the AGPLv3 or higher. #ifndef GCODE_WRITER_H @@ -35,7 +35,6 @@ class TimeKeeper; */ class FffGcodeWriter : public NoCopy { - friend class Scene; // cause WireFrame2Gcode uses the member [gcode] (TODO) friend class FffProcessor; //Because FffProcessor exposes finalize (TODO) private: coord_t max_object_height; //!< The maximal height of all previously sliced meshgroups, used to avoid collision when moving to the next meshgroup to print. diff --git a/include/Weaver.h b/include/Weaver.h deleted file mode 100644 index e4c5d516d9..0000000000 --- a/include/Weaver.h +++ /dev/null @@ -1,117 +0,0 @@ -//Copyright (c) 2018 Ultimaker B.V. -//CuraEngine is released under the terms of the AGPLv3 or higher. - -#ifndef WEAVER_H -#define WEAVER_H - -#include "weaveDataStorage.h" -#include "utils/NoCopy.h" - -namespace cura -{ - -class MeshGroup; -class Polygons; - -/*! - * The main weaver / WirePrint / wireframe printing class, which computes the basic paths to be followed. - */ -class Weaver : public NoCopy -{ - friend class Wireframe2gcode; -private: - static const int HIGHER_BEND_NO_STRAIGHTEN = 0; - static const int MOVE_TO_STRAIGHTEN = 1; - static const int RETRACT_TO_STRAIGHTEN = 2; - -public: - /*! - * This is the main function for Neith / Weaving / WirePrinting / Webbed printing. - * Creates a wireframe for the model consisting of horizontal 'flat' parts and connections between consecutive flat parts consisting of UP moves and diagonally DOWN moves. - * - * \param objects The objects for which to create a wireframe print - */ - void weave(MeshGroup* objects); - -private: - WireFrame wireFrame; - - -/*! - * Connect two polygons, chainify the second and generate connections from it, supporting on the first polygon. - * - * \param supporting The polygons from which to start the connection - * \param z0 The height of the \p supporting - * \param supported The polygons to be supported by the connection from \p supporting to \p supported - * \param z1 the height of \p supported - */ - void connect(Polygons& parts0, int z0, Polygons& parts1, int z1, WeaveConnection& result); - -/*! - * Convert polygons, such that they consist of segments/links of uniform size, namely \p nozzle_top_diameter. - * - * \param parts1 The polygons to be chainified - * \param start_close_to The point from which to start the first link - */ - void chainify_polygons(Polygons& parts1, Point start_close_to, Polygons& result); - -/*! - * The main weaving function. - * Generate connections between two polygons. - * The connections consist of zig zags of which the zig is a line from a point in \p supported to the closest point in \p supporting - * and the zag is a diagonal line from the same point in \p supported to a point in \p supporting - * with a distance equal to Weaver::nozzle_top_diameter from the other point in \p supporting of the zig. - * - * \param supporting The polygons from which to start the connection - * \param z0 The height of the \p supporting - * \param supported The polygons to be supported by the connection from \p supporting to \p supported - * \param z1 the height of \p supported - * \param result The resulting connection - */ - void connect_polygons(Polygons& supporting, int z0, Polygons& supported, int z1, WeaveConnection& result); - -/*! - * Creates the roofs and floors which are laid down horizontally. - */ - void createHorizontalFill(WeaveLayer& layer, Polygons& layer_above); - -/*! - * Fill roofs starting from the outlines of \p supporting. - * The area to be filled in is difference( \p to_be_supported , \p supporting ). - * - * The basic algorithm performs insets on \p supported until the whole area of \p to_be_supported is filled. - * In order to not fill holes in the roof, the hole-areas are unioned with the insets, which results in connections where the UP move has close to zero length; - * pieces of the area between two consecutive insets have close to zero distance at these points. - * These parts of the horizontal infills are converted into moves by the function \p connections2moves. - * - * Note that the new inset is computed from the last inset, while the connections are between the last chainified inset and the new chainified inset. - * - */ - void fillRoofs(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& roofs); - -/*! - * Fill floors starting from the outlines of \p supporting. - * The area to be filled in is \p floors = difference( \p to_be_supported , \p supporting ). - * - * The basic algorithm performs outsets until the whole area of [to_be_supported] is filled. - * In order to not fill too much, the outsets are intersected with the [floors] area, which results in connections where the UP move has close to zero length. - * These parts of the horizontal infills are converted into moves by the function [connections2moves]. - * - * The first supporting polygons are \p supporting while the supporting polygons in consecutive iterations are sub-areas of \p floors. - * - * Note that the new outset is computed from the last outset, while the connections are between the last chainified outset and the new (chainified) outset. - * - */ - void fillFloors(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& roofs); - -/*! - * Filter out parts of connections with small distances; replace by moves. - * - */ - void connections2moves(WeaveRoofPart& inset); - -}; - -}//namespace cura - -#endif//WEAVER_H diff --git a/include/Wireframe2gcode.h b/include/Wireframe2gcode.h deleted file mode 100644 index c9c3173b34..0000000000 --- a/include/Wireframe2gcode.h +++ /dev/null @@ -1,159 +0,0 @@ -//Copyright (c) 2021 Ultimaker B.V. -//CuraEngine is released under the terms of the AGPLv3 or higher. - -#ifndef WIREFRAME2GCODE_H -#define WIREFRAME2GCODE_H - -#include // passing function pointer or lambda as argument to a function - -#include "RetractionConfig.h" -#include "settings/types/Angle.h" //For the nozzle expansion angle setting. -#include "utils/NoCopy.h" - -namespace cura -{ - -class Weaver; - -/*! - * Export class for exporting wireframe print gcode / weaver gcode / wireprint gcode. - */ -class Wireframe2gcode : public NoCopy -{ -private: - static const int STRATEGY_COMPENSATE = 0; - static const int STRATEGY_KNOT = 1; - static const int STRATEGY_RETRACT = 2; - - coord_t initial_layer_thickness; - coord_t filament_diameter; - coord_t line_width; - Ratio flowConnection; - Ratio flowFlat; - double extrusion_mm3_per_mm_connection; - double extrusion_mm3_per_mm_flat; - bool update_extrusion_offset; - coord_t nozzle_outer_diameter; - AngleRadians nozzle_expansion_angle; - coord_t nozzle_clearance; - coord_t nozzle_top_diameter; - Velocity moveSpeed; - Velocity speedBottom; - Velocity speedUp; - Velocity speedDown; - Velocity speedFlat; - coord_t connectionHeight; - coord_t roof_inset; - Duration flat_delay; - Duration bottom_delay; - Duration top_delay; - coord_t up_dist_half_speed; - coord_t top_jump_dist; - coord_t fall_down; - coord_t drag_along; - int strategy; - bool go_back_to_last_top; - Ratio straight_first_when_going_down; - coord_t roof_fall_down; - coord_t roof_drag_along; - Duration roof_outer_delay; - RetractionConfig standard_retraction_config; //!< The standard retraction settings used for moves between parts etc. - -public: - GCodeExport& gcode; //!< Where the result is 'stored' - - Wireframe2gcode(Weaver& weaver, GCodeExport& gcode); - - void writeGCode(); - - -private: - WireFrame& wireFrame; - - /*! - * Startup gcode: nozzle temp up, retraction settings, bed temp - */ - void processStartingCode(); - - /*! - * Lay down a skirt - */ - void processSkirt(); - - /*! - * End gcode: nozzle temp down - */ - void finalize(); - - void writeFill(std::vector& infill_insets, Polygons& outlines - , std::function connectionHandler - , std::function flatHandler); - - /*! - * Function for writing the gcode for a diagonally down movement of a connection. - * - * \param part The part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void go_down(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Function for writing the gcode of an upward move of a connection, which does a couple of small moves at the top. - * - * \param part The part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void strategy_knot(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Function for writing the gcode of an upward move of a connection, which does a retract at the top. - * - * \param part The part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void strategy_retract(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Function for writing the gcode of an upward move of a connection, which goes Wireframe2gcode::fall_down further up - * and Wireframe2gcode::drag_along back from the direction it will go to next. - * - * \param part The part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void strategy_compensate(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Function writing the gcode of a segment in the connection between two layers. - * - * \param part The part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void handle_segment(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Function for writing the gcode of a segment in the connection between two roof insets / floor outsets. - * - * \param part the part in which the segment is - * \param segment_idx The index of the segment in the \p part - */ - void handle_roof_segment(WeaveConnectionPart& part, unsigned int segment_idx); - - /*! - * Write a move action to gcode, inserting a retraction if neccesary. - * - * \param to The 3D destination of the move - */ - void writeMoveWithRetract(Point3 to); - - /*! - * Write a move action to gcode, inserting a retraction if neccesary. - * - * \param to The 2D destination of the move - */ - void writeMoveWithRetract(Point to); - -}; - -}//namespace cura - -#endif//WIREFRAME2GCODE_H diff --git a/include/weaveDataStorage.h b/include/weaveDataStorage.h deleted file mode 100644 index 1dcdb91dcd..0000000000 --- a/include/weaveDataStorage.h +++ /dev/null @@ -1,93 +0,0 @@ -//Copyright (c) 2018 Ultimaker B.V. -//CuraEngine is released under the terms of the AGPLv3 or higher. - -#ifndef WEAVE_DATA_STORAGE_H -#define WEAVE_DATA_STORAGE_H - -#include "utils/NoCopy.h" -#include "utils/IntPoint.h" -#include "utils/polygon.h" -#include "mesh.h" -#include "LayerPlan.h" -#include "MeshGroup.h" - - -namespace cura { - - -enum class WeaveSegmentType -{ - UP, - DOWN, - FLAT, - MOVE, - DOWN_AND_FLAT // DOWN_AND_FLAT is for parts of the roof which can either be viewed as flat or as down, since their [to] location is an up move with zero length -}; - - -struct WeaveConnectionSegment -{ - Point3 to; - WeaveSegmentType segmentType; - WeaveConnectionSegment(Point3 to, WeaveSegmentType dir) : to(to), segmentType(dir) {}; -}; - -struct PolyLine3 -{ - Point3 from; - std::vector segments; -}; - -struct WeaveConnectionPart -{ - PolyLine3 connection; - int supported_index;//!< index of corresponding supported polygon in WeaveConnection.supported (! last point in polygon is first point to start printing it!) - WeaveConnectionPart(int top_idx) : supported_index(top_idx) {}; -}; - -struct WeaveConnection -{ - int z0;//!< height of the supporting polygons (of the prev layer, roof inset, etc.) - int z1;//!< height of the \p supported polygons - std::vector connections; //!< for each polygon in \p supported the connection. - Polygons supported; //!< polygons to be supported by connections (from other polygons) -}; - -// Horizontal Fills: - -typedef std::vector WeaveInsetPart; //!< Polygon with extra information on each point -struct WeaveRoofPart : WeaveConnection -{ - // [supported] is an insets of the roof polygons (or of previous insets of it) - // [connections] are the connections between two consecutive roof polygon insets - std::vector supported_withMoves; //!< optimized inset polygons, with some parts of the polygons replaced by moves -}; - -struct WeaveRoof -{ - std::vector roof_insets; //!< connections between consecutive insets of the roof polygons - Polygons roof_outlines; //!< the area within which the horitonal connections are generated -}; - -// Layers - -struct WeaveLayer : WeaveConnection -{ - // [supported] are the outline polygons on the next layer which are (to be) connected, - // as well as the polygons supported by roofs (holes and boundaries of roofs) - // [connections] are the vertical connections - WeaveRoof roofs; //!< parts which are filled horizontally (both roofs and floors...) -}; -struct WireFrame : public NoCopy -{ - MeshGroup* meshgroup; - WeaveRoof bottom_infill; - Polygons bottom_outline; - int z_bottom; - std::vector layers; -}; - - -}//namespace cura - -#endif//WEAVE_DATA_STORAGE_H diff --git a/src/Scene.cpp b/src/Scene.cpp index 558a18bb4b..ff4baf9adc 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 Ultimaker B.V. +// Copyright (c) 2023 UltiMaker // CuraEngine is released under the terms of the AGPLv3 or higher #include @@ -6,8 +6,6 @@ #include "Application.h" #include "FffProcessor.h" //To start a slice. #include "Scene.h" -#include "Weaver.h" -#include "Wireframe2gcode.h" #include "communication/Communication.h" //To flush g-code and layer view when we're done. #include "progress/Progress.h" #include "sliceDataStorage.h" @@ -84,30 +82,14 @@ void Scene::processMeshGroup(MeshGroup& mesh_group) return; } - if (mesh_group.settings.get("wireframe_enabled")) + SliceDataStorage storage; + if (! fff_processor->polygon_generator.generateAreas(storage, &mesh_group, fff_processor->time_keeper)) { - spdlog::info("Starting Neith Weaver..."); - - Weaver weaver; - weaver.weave(&mesh_group); - - spdlog::info("Starting Neith Gcode generation..."); - Wireframe2gcode gcoder(weaver, fff_processor->gcode_writer.gcode); - gcoder.writeGCode(); - spdlog::info("Finished Neith Gcode generation..."); + return; } - else // Normal operation (not wireframe). - { - SliceDataStorage storage; - if (! fff_processor->polygon_generator.generateAreas(storage, &mesh_group, fff_processor->time_keeper)) - { - return; - } - - Progress::messageProgressStage(Progress::Stage::EXPORT, &fff_processor->time_keeper); - fff_processor->gcode_writer.writeGCode(storage, fff_processor->time_keeper); - } + Progress::messageProgressStage(Progress::Stage::EXPORT, &fff_processor->time_keeper); + fff_processor->gcode_writer.writeGCode(storage, fff_processor->time_keeper); Progress::messageProgress(Progress::Stage::FINISH, 1, 1); // 100% on this meshgroup Application::getInstance().communication->flushGCode(); diff --git a/src/Weaver.cpp b/src/Weaver.cpp deleted file mode 100644 index d84c24c42e..0000000000 --- a/src/Weaver.cpp +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright (c) 2022 Ultimaker B.V. -// CuraEngine is released under the terms of the AGPLv3 or higher - -#include // sqrt -#include // debug IO - -#include - -#include "Application.h" //To get the communication channel. -#include "PrintFeature.h" -#include "Slice.h" -#include "Weaver.h" -#include "communication/Communication.h" //To send layer view data. -#include "progress/Progress.h" -#include "settings/AdaptiveLayerHeights.h" -#include "settings/types/Angle.h" -#include "slicer.h" - -namespace cura -{ - -void Weaver::weave(MeshGroup* meshgroup) -{ - wireFrame.meshgroup = meshgroup; - - const coord_t maxz = meshgroup->max().z; - - const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings; - const coord_t initial_layer_thickness = mesh_group_settings.get("layer_height_0"); - const coord_t connection_height = mesh_group_settings.get("wireframe_height"); - const size_t layer_count = (maxz - initial_layer_thickness) / connection_height + 1; - std::vector layer_thicknesses; - - spdlog::info("Layer count: {}", layer_count); - - std::vector slicerList; - - for (Mesh& mesh : meshgroup->meshes) - { - constexpr bool variable_layer_heights = false; - cura::Slicer* slicer = new cura::Slicer(&mesh, connection_height, layer_count, variable_layer_heights, &layer_thicknesses); - slicerList.push_back(slicer); - } - - LayerIndex starting_layer_idx; - { // find first non-empty layer - for (starting_layer_idx = 0; starting_layer_idx < LayerIndex(layer_count); starting_layer_idx++) - { - Polygons parts; - for (cura::Slicer* slicer : slicerList) - parts.add(slicer->layers[starting_layer_idx].polygons); - - if (parts.size() > 0) - break; - } - if (starting_layer_idx > 0) - { - spdlog::warn("First {} layers are empty!", starting_layer_idx); - } - } - - spdlog::info("Chainifying layers..."); - { - int starting_z = -1; - for (cura::Slicer* slicer : slicerList) - wireFrame.bottom_outline.add(slicer->layers[starting_layer_idx].polygons); - - Application::getInstance().communication->sendPolygons(PrintFeatureType::OuterWall, wireFrame.bottom_outline, 1, 1, 1); - - if (slicerList.empty()) // Wait, there is nothing to slice. - { - wireFrame.z_bottom = 0; - } - else - { - wireFrame.z_bottom = slicerList[0]->layers[starting_layer_idx].z; - } - - Point starting_point_in_layer; - if (wireFrame.bottom_outline.size() > 0) - { - starting_point_in_layer = (wireFrame.bottom_outline.max() + wireFrame.bottom_outline.min()) / 2; - } - else - { - starting_point_in_layer = (Point(0, 0) + meshgroup->max() + meshgroup->min()) / 2; - } - - Progress::messageProgressStage(Progress::Stage::INSET_SKIN, nullptr); - for (LayerIndex layer_idx = starting_layer_idx + 1; layer_idx < LayerIndex(layer_count); layer_idx++) - { - Progress::messageProgress(Progress::Stage::INSET_SKIN, layer_idx + 1, layer_count); // abuse the progress system of the normal mode of CuraEngine - - Polygons parts1; - for (cura::Slicer* slicer : slicerList) - parts1.add(slicer->layers[layer_idx].polygons); - - - Polygons chainified; - - chainify_polygons(parts1, starting_point_in_layer, chainified); - - Application::getInstance().communication->sendPolygons(PrintFeatureType::OuterWall, chainified, 1, 1, 1); - - if (chainified.size() > 0) - { - if (starting_z == -1) - starting_z = slicerList[0]->layers[layer_idx - 1].z; - wireFrame.layers.emplace_back(); - WeaveLayer& layer = wireFrame.layers.back(); - - layer.z0 = slicerList[0]->layers[layer_idx - 1].z - starting_z; - layer.z1 = slicerList[0]->layers[layer_idx].z - starting_z; - - layer.supported = chainified; - - starting_point_in_layer = layer.supported.back().back(); - } - } - } - - spdlog::info("Finding horizontal parts..."); - { - Progress::messageProgressStage(Progress::Stage::SUPPORT, nullptr); - for (unsigned int layer_idx = 0; layer_idx < wireFrame.layers.size(); layer_idx++) - { - Progress::messageProgress(Progress::Stage::SUPPORT, layer_idx + 1, wireFrame.layers.size()); // abuse the progress system of the normal mode of CuraEngine - - WeaveLayer& layer = wireFrame.layers[layer_idx]; - - Polygons empty; - Polygons& layer_above = (layer_idx + 1 < wireFrame.layers.size()) ? wireFrame.layers[layer_idx + 1].supported : empty; - - createHorizontalFill(layer, layer_above); - } - } - // at this point layer.supported still only contains the polygons to be connected - // when connecting layers, we further add the supporting polygons created by the roofs - - spdlog::info("Connecting layers..."); - { - Polygons* lower_top_parts = &wireFrame.bottom_outline; - int last_z = wireFrame.z_bottom; - for (unsigned int layer_idx = 0; layer_idx < wireFrame.layers.size(); layer_idx++) // use top of every layer but the last - { - WeaveLayer& layer = wireFrame.layers[layer_idx]; - - connect_polygons(*lower_top_parts, last_z, layer.supported, layer.z1, layer); - layer.supported.add(layer.roofs.roof_outlines); - lower_top_parts = &layer.supported; - - last_z = layer.z1; - } - } - - - { // roofs: - if (! wireFrame.layers.empty()) // If there are no layers, create no roof. - { - WeaveLayer& top_layer = wireFrame.layers.back(); - Polygons to_be_supported; // empty for the top layer - fillRoofs(top_layer.supported, to_be_supported, -1, top_layer.z1, top_layer.roofs); - } - } - - - { // bottom: - if (! wireFrame.layers.empty()) // If there are no layers, create no bottom. - { - Polygons to_be_supported; // is empty for the bottom layer, cause the order of insets doesn't really matter (in a sense everything is to be supported) - fillRoofs(wireFrame.bottom_outline, to_be_supported, -1, wireFrame.layers.front().z0, wireFrame.bottom_infill); - } - } -} - - -void Weaver::createHorizontalFill(WeaveLayer& layer, Polygons& layer_above) -{ - const coord_t bridgable_dist = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("wireframe_height"); - - // Polygons& polys_below = lower_top_parts; - Polygons& polys_here = layer.supported; - Polygons& polys_above = layer_above; - - - { // roofs - Polygons to_be_supported = polys_above.offset(bridgable_dist); - fillRoofs(polys_here, to_be_supported, -1, layer.z1, layer.roofs); - } - - { // floors - Polygons to_be_supported = polys_above.offset(-bridgable_dist); - fillFloors(polys_here, to_be_supported, 1, layer.z1, layer.roofs); - } - - { // optimize away doubly printed regions (boundaries of holes in layer etc.) - for (WeaveRoofPart& inset : layer.roofs.roof_insets) - connections2moves(inset); - } -} - - -void Weaver::fillRoofs(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& horizontals) -{ - std::vector& insets = horizontals.roof_insets; - - if (supporting.size() == 0) - return; // no parts to start the roof from! - - Polygons roofs = supporting.difference(to_be_supported); - - const coord_t roof_inset = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("wireframe_roof_inset"); - roofs = roofs.offset(-roof_inset).offset(roof_inset); - - if (roofs.size() == 0) - return; - - - Polygons roof_outlines; - Polygons roof_holes; - { // split roofs into outlines and holes - std::vector roof_parts = roofs.splitIntoParts(); - for (PolygonsPart& roof_part : roof_parts) - { - roof_outlines.add(roof_part[0]); - for (unsigned int hole_idx = 1; hole_idx < roof_part.size(); hole_idx++) - { - roof_holes.add(roof_part[hole_idx]); - roof_holes.back().reverse(); - } - } - } - - - Polygons supporting_outlines; - - std::vector supporting_parts = supporting.splitIntoParts(); - for (PolygonsPart& supporting_part : supporting_parts) - supporting_outlines.add(supporting_part[0]); // only add outlines, not the holes - - - Polygons inset1; - Polygons last_inset; - Polygons last_supported = supporting; - for (Polygons inset0 = supporting_outlines; inset0.size() > 0; inset0 = last_inset) - { - last_inset = inset0.offset(direction * roof_inset, ClipperLib::jtRound); - inset1 = last_inset.intersection(roof_outlines); // stay within roof area - inset1 = inset1.unionPolygons(roof_holes); // make insets go around holes - - if (inset1.size() == 0) - break; - - insets.emplace_back(); - - connect(last_supported, z, inset1, z, insets.back()); - - inset1 = inset1.remove(roof_holes); // throw away holes which appear in every intersection - inset1 = inset1.remove(roof_outlines); // throw away fully filled regions - - last_supported = insets.back().supported; // chainified - } - - - horizontals.roof_outlines.add(roofs); // TODO just add the new lines, not the lines of the roofs which are already supported ==> make outlines into a connection from which we only print the top, not the connection -} - -void Weaver::fillFloors(Polygons& supporting, Polygons& to_be_supported, int direction, int z, WeaveRoof& horizontals) -{ - std::vector& outsets = horizontals.roof_insets; - - if (to_be_supported.size() == 0) - return; // no parts to start the floor from! - if (supporting.size() == 0) - return; // no parts to start the floor from! - - Polygons floors = to_be_supported.difference(supporting); - - const coord_t roof_inset = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("wireframe_roof_inset"); - floors = floors.offset(-roof_inset).offset(roof_inset); - - if (floors.size() == 0) - return; - - - std::vector floor_parts = floors.splitIntoParts(); - - Polygons floor_outlines; - Polygons floor_holes; - for (PolygonsPart& floor_part : floor_parts) - { - floor_outlines.add(floor_part[0]); - for (unsigned int hole_idx = 1; hole_idx < floor_part.size(); hole_idx++) - { - floor_holes.add(floor_part[hole_idx]); - // floor_holes.back().reverse(); - } - } - - - Polygons outset1; - - Polygons last_supported = supporting; - - for (Polygons outset0 = supporting; outset0.size() > 0; outset0 = outset1) - { - outset1 = outset0.offset(roof_inset * direction, ClipperLib::jtRound).intersection(floors); - outset1 = outset1.remove(floor_holes); // throw away holes which appear in every intersection - outset1 = outset1.remove(floor_outlines); // throw away holes which appear in every intersection - - - outsets.emplace_back(); - - connect(last_supported, z, outset1, z, outsets.back()); - - outset1 = outset1.remove(floor_outlines); // throw away fully filled regions - - last_supported = outsets.back().supported; // chainified - } - - - horizontals.roof_outlines.add(floors); -} - - -void Weaver::connections2moves(WeaveRoofPart& inset) -{ - const coord_t line_width = Application::getInstance().current_slice->scene.current_mesh_group->settings.get("wall_line_width_x"); - - constexpr bool include_half_of_last_down = true; - - for (WeaveConnectionPart& part : inset.connections) - { - std::vector& segments = part.connection.segments; - for (unsigned int idx = 0; idx < part.connection.segments.size(); idx += 2) - { - WeaveConnectionSegment& segment = segments[idx]; - assert(segment.segmentType == WeaveSegmentType::UP); - Point3 from = (idx == 0) ? part.connection.from : segments[idx - 1].to; - bool skipped = (segment.to - from).vSize2() < line_width * line_width; - if (skipped) - { - unsigned int begin = idx; - for (; idx < segments.size(); idx += 2) - { - WeaveConnectionSegment& segment = segments[idx]; - assert(segments[idx].segmentType == WeaveSegmentType::UP); - Point3 from = (idx == 0) ? part.connection.from : segments[idx - 1].to; - bool skipped = (segment.to - from).vSize2() < line_width * line_width; - if (! skipped) - { - break; - } - } - int end = idx - ((include_half_of_last_down) ? 2 : 1); - if (idx >= segments.size()) - segments.erase(segments.begin() + begin, segments.end()); - else - { - segments.erase(segments.begin() + begin, segments.begin() + end); - if (begin < segments.size()) - { - segments[begin].segmentType = WeaveSegmentType::MOVE; - if (include_half_of_last_down) - segments[begin + 1].segmentType = WeaveSegmentType::DOWN_AND_FLAT; - } - idx = begin + ((include_half_of_last_down) ? 2 : 1); - } - } - } - } -} - -void Weaver::connect(Polygons& parts0, int z0, Polygons& parts1, int z1, WeaveConnection& result) -{ - // TODO: convert polygons (with outset + difference) such that after printing the first polygon, we can't be in the way of the printed stuff - // something like: - // for (m > n) - // parts[m] = parts[m].difference(parts[n].offset(nozzle_top_diameter)) - // according to the printing order! - // - // OR! : - // - // unify different parts if gap is too small - - Polygons& supported = result.supported; - - if (parts1.size() == 0) - return; - - Point& start_close_to = (parts0.size() > 0) ? parts0.back().back() : parts1.back().back(); - - chainify_polygons(parts1, start_close_to, supported); - - if (parts0.size() == 0) - return; - - connect_polygons(parts0, z0, supported, z1, result); -} - - -void Weaver::chainify_polygons(Polygons& parts1, Point start_close_to, Polygons& result) -{ - const Settings& mesh_group_settings = Application::getInstance().current_slice->scene.current_mesh_group->settings; - const coord_t connection_height = mesh_group_settings.get("wireframe_height"); - const coord_t nozzle_outer_diameter = mesh_group_settings.get("machine_nozzle_tip_outer_diameter"); // ___ ___ - const AngleRadians nozzle_expansion_angle = mesh_group_settings.get("machine_nozzle_expansion_angle"); // \_U_/ - const coord_t nozzle_clearance = mesh_group_settings.get("wireframe_nozzle_clearance"); // at least line width - const coord_t nozzle_top_diameter = tan(nozzle_expansion_angle) * connection_height + nozzle_outer_diameter + nozzle_clearance; - - for (unsigned int prt = 0; prt < parts1.size(); prt++) - { - ConstPolygonRef upperPart = parts1[prt]; - - ClosestPolygonPoint closestInPoly = PolygonUtils::findClosest(start_close_to, upperPart); - - - PolygonRef part_top = result.newPoly(); - - GivenDistPoint next_upper; - bool found = true; - int idx = 0; - - for (Point upper_point = upperPart[closestInPoly.point_idx]; found; upper_point = next_upper.location) - { - found = PolygonUtils::getNextPointWithDistance(upper_point, nozzle_top_diameter, upperPart, idx, closestInPoly.point_idx, next_upper); - - - if (! found) - { - break; - } - - part_top.add(upper_point); - - idx = next_upper.pos; - } - if (part_top.size() > 0) - start_close_to = part_top.back(); - else - result.remove(result.size() - 1); - } -} - - -void Weaver::connect_polygons(Polygons& supporting, int z0, Polygons& supported, int z1, WeaveConnection& result) -{ - if (supporting.size() < 1) - { - std::cerr << "lower layer has zero parts!\n"; - return; - } - - result.z0 = z0; - result.z1 = z1; - - std::vector& parts = result.connections; - - for (unsigned int prt = 0; prt < supported.size(); prt++) - { - ConstPolygonRef upperPart(supported[prt]); - - - parts.emplace_back(prt); - WeaveConnectionPart& part = parts.back(); - PolyLine3& connection = part.connection; - - Point3 last_upper; - bool firstIter = true; - - for (const Point& upper_point : upperPart) - { - ClosestPolygonPoint lowerPolyPoint = PolygonUtils::findClosest(upper_point, supporting); - Point& lower = lowerPolyPoint.location; - - Point3 lower3 = Point3(lower.X, lower.Y, z0); - Point3 upper3 = Point3(upper_point.X, upper_point.Y, z1); - - - if (firstIter) - connection.from = lower3; - else - connection.segments.emplace_back<>(lower3, WeaveSegmentType::DOWN); - - connection.segments.emplace_back<>(upper3, WeaveSegmentType::UP); - last_upper = upper3; - - firstIter = false; - } - } -} - - -} // namespace cura diff --git a/src/Wireframe2gcode.cpp b/src/Wireframe2gcode.cpp deleted file mode 100644 index 9365dee414..0000000000 --- a/src/Wireframe2gcode.cpp +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright (c) 2022 Ultimaker B.V. -// CuraEngine is released under the terms of the AGPLv3 or higher - -#include // sqrt -#include // debug IO - -#include - -#include "Application.h" //To get the communication channel. -#include "ExtruderTrain.h" -#include "PathOrderOptimizer.h" //For skirt/brim. -#include "PrintFeature.h" -#include "Slice.h" -#include "Weaver.h" -#include "Wireframe2gcode.h" -#include "communication/Communication.h" //To write g-code output. -#include "progress/Progress.h" -#include "utils/math.h" -#include "weaveDataStorage.h" - -namespace cura -{ - - -void Wireframe2gcode::writeGCode() -{ - Settings& scene_settings = Application::getInstance().current_slice->scene.settings; - const size_t start_extruder_nr = scene_settings.get("skirt_brim_extruder_nr").extruder_nr; // TODO: figure out how Wireframe works with dual extrusion // TODO: what if the extruder is not overridden?! - gcode.preSetup(start_extruder_nr); - gcode.setInitialAndBuildVolumeTemps(start_extruder_nr); - - Application::getInstance().communication->beginGCode(); - - processStartingCode(); - - int maxObjectHeight; - if (wireFrame.layers.empty()) - { - maxObjectHeight = 0; - } - else - { - maxObjectHeight = wireFrame.layers.back().z1; - } - - gcode.setZ(initial_layer_thickness); - - processSkirt(); - - unsigned int total_layers = wireFrame.layers.size(); - gcode.writeLayerComment(0); - gcode.writeTypeComment(PrintFeatureType::SkirtBrim); - - for (PolygonRef bottom_part : wireFrame.bottom_infill.roof_outlines) - { - if (bottom_part.size() == 0) - continue; - writeMoveWithRetract(bottom_part[bottom_part.size() - 1]); - for (Point& segment_to : bottom_part) - { - gcode.writeExtrusion(segment_to, speedBottom, extrusion_mm3_per_mm_flat, PrintFeatureType::Skin); - } - } - - - // bottom: - Polygons empty_outlines; - writeFill( - wireFrame.bottom_infill.roof_insets, - empty_outlines, - [this](Wireframe2gcode&, WeaveConnectionPart& part, unsigned int segment_idx) - { - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - if (segment.segmentType == WeaveSegmentType::MOVE || segment.segmentType == WeaveSegmentType::DOWN_AND_FLAT) // this is the case when an inset overlaps with a hole - { - writeMoveWithRetract(segment.to); - } - else - { - gcode.writeExtrusion(segment.to, speedBottom, extrusion_mm3_per_mm_connection, PrintFeatureType::Skin); - } - }, - [this](Wireframe2gcode&, WeaveConnectionSegment& segment) - { - if (segment.segmentType == WeaveSegmentType::MOVE) - writeMoveWithRetract(segment.to); - else if (segment.segmentType == WeaveSegmentType::DOWN_AND_FLAT) - return; // do nothing - else - gcode.writeExtrusion(segment.to, speedBottom, extrusion_mm3_per_mm_flat, PrintFeatureType::Skin); - }); - Progress::messageProgressStage(Progress::Stage::EXPORT, nullptr); - for (LayerIndex layer_nr = 0; layer_nr < static_cast(wireFrame.layers.size()); layer_nr++) - { - Progress::messageProgress(Progress::Stage::EXPORT, layer_nr + 1, total_layers); // abuse the progress system of the normal mode of CuraEngine - - WeaveLayer& layer = wireFrame.layers[layer_nr]; - - gcode.writeLayerComment(layer_nr + 1); - - double fanSpeed = scene_settings.get("cool_fan_speed_max") * 100.0; - if (layer_nr == 0) - { - fanSpeed = scene_settings.get("cool_fan_speed_min") * 100.0; - } - gcode.writeFanCommand(fanSpeed); - - for (size_t part_nr = 0; part_nr < layer.connections.size(); part_nr++) - { - WeaveConnectionPart& part = layer.connections[part_nr]; - - if (part.connection.segments.size() == 0) - continue; - - gcode.writeTypeComment(PrintFeatureType::Support); // connection - { - if (vSize2(gcode.getPositionXY() - part.connection.from) > connectionHeight) - { - Point3 point_same_height(part.connection.from.x, part.connection.from.y, layer.z1 + MM2INT(0.1)); - writeMoveWithRetract(point_same_height); - } - writeMoveWithRetract(part.connection.from); - for (size_t segment_idx = 0; segment_idx < part.connection.segments.size(); segment_idx++) - { - handle_segment(part, segment_idx); - } - } - - - gcode.writeTypeComment(PrintFeatureType::OuterWall); // top - { - for (WeaveConnectionSegment& segment : part.connection.segments) - { - if (segment.segmentType == WeaveSegmentType::DOWN) - { - continue; - } - if (segment.segmentType == WeaveSegmentType::MOVE) - { - writeMoveWithRetract(segment.to); - } - else - { - gcode.writeExtrusion(segment.to, speedFlat, extrusion_mm3_per_mm_flat, PrintFeatureType::OuterWall); - gcode.writeDelay(flat_delay); - } - } - } - } - - // roofs: - gcode.setZ(layer.z1); - std::function handle_roof = &Wireframe2gcode::handle_roof_segment; - writeFill(layer.roofs.roof_insets, layer.roofs.roof_outlines, handle_roof, [this](Wireframe2gcode&, WeaveConnectionSegment& segment) { // handle flat segments - if (segment.segmentType == WeaveSegmentType::MOVE) - { - writeMoveWithRetract(segment.to); - } - else if (segment.segmentType == WeaveSegmentType::DOWN_AND_FLAT) - { - // do nothing - } - else - { - gcode.writeExtrusion(segment.to, speedFlat, extrusion_mm3_per_mm_flat, PrintFeatureType::Skin); - gcode.writeDelay(flat_delay); - } - }); - } - - gcode.setZ(maxObjectHeight); - - gcode.writeRetraction(standard_retraction_config); - - - gcode.updateTotalPrintTime(); - - gcode.writeDelay(0.3); - - gcode.writeFanCommand(0); - - finalize(); -} - - -void Wireframe2gcode::go_down(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - Point3 from = (segment_idx == 0) ? part.connection.from : part.connection.segments[segment_idx - 1].to; - if (go_back_to_last_top) - gcode.writeTravel(from, speedDown); - if (straight_first_when_going_down <= 0) - { - gcode.writeExtrusion(segment.to, speedDown, extrusion_mm3_per_mm_connection, PrintFeatureType::OuterWall); - } - else - { - Point3& to = segment.to; - Point3 from = gcode.getPosition(); // segment.from; - Point3 vec = to - from; - Point3 in_between = from + vec * static_cast(straight_first_when_going_down); - - Point3 up(in_between.x, in_between.y, from.z); - int64_t new_length = (up - from).vSize() + (to - up).vSize() + 5; - int64_t orr_length = vec.vSize(); - double enlargement = new_length / orr_length; - gcode.writeExtrusion(up, speedDown * enlargement, extrusion_mm3_per_mm_connection / enlargement, PrintFeatureType::OuterWall); - gcode.writeExtrusion(to, speedDown * enlargement, extrusion_mm3_per_mm_connection / enlargement, PrintFeatureType::OuterWall); - } - gcode.writeDelay(bottom_delay); - if (up_dist_half_speed > 0) - { - gcode.writeExtrusion(Point3(0, 0, up_dist_half_speed) + gcode.getPosition(), speedUp / 2, extrusion_mm3_per_mm_connection * 2, PrintFeatureType::OuterWall); - } -} - - -void Wireframe2gcode::strategy_knot(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - gcode.writeExtrusion(segment.to, speedUp, extrusion_mm3_per_mm_connection, PrintFeatureType::OuterWall); - Point3 next_vector; - if (segment_idx + 1 < part.connection.segments.size()) - { - WeaveConnectionSegment& next_segment = part.connection.segments[segment_idx + 1]; - next_vector = next_segment.to - segment.to; - } - else - { - next_vector = part.connection.segments[0].to - segment.to; - } - Point next_dir_2D(next_vector.x, next_vector.y); - next_dir_2D = next_dir_2D * top_jump_dist / vSize(next_dir_2D); - Point3 next_dir(next_dir_2D.X / 2, next_dir_2D.Y / 2, -top_jump_dist); - - Point3 current_pos = gcode.getPosition(); - - gcode.writeTravel(current_pos - next_dir, speedUp); - gcode.writeDelay(top_delay); - gcode.writeTravel(current_pos + next_dir_2D, speedUp); -} - -void Wireframe2gcode::strategy_retract(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - Point3 from = (segment_idx == 0) ? part.connection.from : part.connection.segments[segment_idx - 1].to; - - Settings& scene_settings = Application::getInstance().current_slice->scene.settings; - RetractionConfig retraction_config; - // TODO: get these from the settings! - retraction_config.distance = MM2INT(0.5); // INT2MM(getSettingInt("retraction_amount")) - retraction_config.prime_volume = 0; // INT2MM(getSettingInt("retractionPrime - retraction_config.speed = 20; // 40; - retraction_config.primeSpeed = 15; // 30; - retraction_config.zHop = 0; // getSettingInt("retraction_hop"); - retraction_config.retraction_count_max = scene_settings.get("retraction_count_max"); - retraction_config.retraction_extrusion_window = scene_settings.get("retraction_extrusion_window"); // Window in which to count retractions in mm of extruded filament. - retraction_config.retraction_min_travel_distance = scene_settings.get("retraction_min_travel"); - - double top_retract_pause = 2.0; - const coord_t retract_hop_dist = MM2INT(1); - bool after_retract_hop = false; - // bool go_horizontal_first = true; - bool lower_retract_start = true; - - Point3& to = segment.to; - if (lower_retract_start) - { - Point3 vec = to - from; - Point3 lowering = vec * retract_hop_dist / 2 / vec.vSize(); - Point3 lower = to - lowering; - gcode.writeExtrusion(lower, speedUp, extrusion_mm3_per_mm_connection, PrintFeatureType::OuterWall); - gcode.writeRetraction(retraction_config); - gcode.writeTravel(to + lowering, speedUp); - gcode.writeDelay(top_retract_pause); - if (after_retract_hop) - { - gcode.writeTravel(to + Point3(0, 0, retract_hop_dist), speedFlat); - } - } - else - { - gcode.writeExtrusion(to, speedUp, extrusion_mm3_per_mm_connection, PrintFeatureType::OuterWall); - gcode.writeRetraction(retraction_config); - gcode.writeTravel(to + Point3(0, 0, retract_hop_dist), speedFlat); - gcode.writeDelay(top_retract_pause); - if (after_retract_hop) - { - gcode.writeTravel(to + Point3(0, 0, retract_hop_dist * 3), speedFlat); - } - } -} - -void Wireframe2gcode::strategy_compensate(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - Point3 from = (segment_idx == 0) ? part.connection.from : part.connection.segments[segment_idx - 1].to; - Point3 to = segment.to + Point3(0, 0, fall_down * (segment.to - from).vSize() / connectionHeight); - Point3 vector = segment.to - from; - Point3 dir = vector * drag_along / vector.vSize(); - - Point3 next_point; - if (segment_idx + 1 < part.connection.segments.size()) - { - WeaveConnectionSegment& next_segment = part.connection.segments[segment_idx + 1]; - next_point = next_segment.to; - } - else - { - next_point = part.connection.segments[0].to; - } - Point3 next_vector = next_point - segment.to; - Point next_dir_2D(next_vector.x, next_vector.y); - int64_t next_dir_2D_size = vSize(next_dir_2D); - if (next_dir_2D_size > 0) - next_dir_2D = next_dir_2D * drag_along / next_dir_2D_size; - Point3 next_dir(next_dir_2D.X, next_dir_2D.Y, 0); - - Point3 newTop = to - next_dir + dir; - - int64_t orrLength = (segment.to - from).vSize() + next_vector.vSize() + 1; // + 1 in order to avoid division by zero - int64_t newLength = (newTop - from).vSize() + (next_point - newTop).vSize() + 1; // + 1 in order to avoid division by zero - - gcode.writeExtrusion(newTop, speedUp * newLength / orrLength, extrusion_mm3_per_mm_connection * orrLength / newLength, PrintFeatureType::OuterWall); -} -void Wireframe2gcode::handle_segment(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - - switch (segment.segmentType) - { - case WeaveSegmentType::MOVE: - writeMoveWithRetract(segment.to); - break; - case WeaveSegmentType::DOWN: - go_down(part, segment_idx); - break; - case WeaveSegmentType::FLAT: - spdlog::warn("Warning: flat piece in wire print connection."); - break; - case WeaveSegmentType::UP: - if (strategy == STRATEGY_KNOT) - { - strategy_knot(part, segment_idx); - } - else if (strategy == STRATEGY_RETRACT) - { - strategy_retract(part, segment_idx); - } - else if (strategy == STRATEGY_COMPENSATE) - { - strategy_compensate(part, segment_idx); - } - break; - case WeaveSegmentType::DOWN_AND_FLAT: - spdlog::error("Down and flat move in non-horizontal connection!"); - break; - } -} - - -void Wireframe2gcode::handle_roof_segment(WeaveConnectionPart& part, unsigned int segment_idx) -{ - WeaveConnectionSegment& segment = part.connection.segments[segment_idx]; - Point3 from = (segment_idx == 0) ? part.connection.from : part.connection.segments[segment_idx - 1].to; - WeaveConnectionSegment* next_segment = nullptr; - if (segment_idx + 1 < part.connection.segments.size()) - next_segment = &part.connection.segments[segment_idx + 1]; - switch (segment.segmentType) - { - case WeaveSegmentType::MOVE: - case WeaveSegmentType::DOWN_AND_FLAT: - if (next_segment && next_segment->segmentType != WeaveSegmentType::DOWN_AND_FLAT) - { - writeMoveWithRetract(segment.to); - } - break; - case WeaveSegmentType::UP: - { - Point3 to = segment.to + Point3(0, 0, roof_fall_down); - - Point3 vector = segment.to - from; - if (vector.vSize2() == 0) - return; - Point3 dir = vector * roof_drag_along / vector.vSize(); - - Point3 next_vector; - if (next_segment) - { - next_vector = next_segment->to - segment.to; - } - else - { - next_vector = part.connection.segments[0].to - segment.to; - } - Point next_dir_2D(next_vector.x, next_vector.y); - Point3 detoured = to + dir; - if (vSize2(next_dir_2D) > 0) - { - next_dir_2D = next_dir_2D * roof_drag_along / vSize(next_dir_2D); - Point3 next_dir(next_dir_2D.X, next_dir_2D.Y, 0); - detoured -= next_dir; - } - - gcode.writeExtrusion(detoured, speedUp, extrusion_mm3_per_mm_connection, PrintFeatureType::Skin); - } - break; - case WeaveSegmentType::DOWN: - gcode.writeExtrusion(segment.to, speedDown, extrusion_mm3_per_mm_connection, PrintFeatureType::Skin); - gcode.writeDelay(roof_outer_delay); - break; - case WeaveSegmentType::FLAT: - spdlog::error("Flat move in connection!"); - break; - } -} - - -void Wireframe2gcode::writeFill(std::vector& infill_insets, - Polygons& roof_outlines, - std::function connectionHandler, - std::function flatHandler) -{ - // bottom: - gcode.writeTypeComment(PrintFeatureType::Infill); - for (unsigned int inset_idx = 0; inset_idx < infill_insets.size(); inset_idx++) - { - WeaveRoofPart& inset = infill_insets[inset_idx]; - - - for (unsigned int inset_part_nr = 0; inset_part_nr < inset.connections.size(); inset_part_nr++) - { - WeaveConnectionPart& inset_part = inset.connections[inset_part_nr]; - std::vector& segments = inset_part.connection.segments; - - gcode.writeTypeComment(PrintFeatureType::Support); // connection - if (segments.size() == 0) - continue; - Point3 first_extrusion_from = inset_part.connection.from; - unsigned int first_segment_idx; - for (first_segment_idx = 0; first_segment_idx < segments.size() && segments[first_segment_idx].segmentType == WeaveSegmentType::MOVE; first_segment_idx++) - { // finds the first segment which is not a move - first_extrusion_from = segments[first_segment_idx].to; - } - if (first_segment_idx == segments.size()) - continue; - writeMoveWithRetract(first_extrusion_from); - for (unsigned int segment_idx = first_segment_idx; segment_idx < segments.size(); segment_idx++) - { - connectionHandler(*this, inset_part, segment_idx); - } - - gcode.writeTypeComment(PrintFeatureType::InnerWall); // top - for (unsigned int segment_idx = 0; segment_idx < segments.size(); segment_idx++) - { - WeaveConnectionSegment& segment = segments[segment_idx]; - - if (segment.segmentType == WeaveSegmentType::DOWN) - continue; - - flatHandler(*this, segment); - } - } - } - - gcode.writeTypeComment(PrintFeatureType::OuterWall); // outer perimeter of the flat parts - for (PolygonRef poly : roof_outlines) - { - writeMoveWithRetract(poly[poly.size() - 1]); - for (Point& p : poly) - { - Point3 to(p.X, p.Y, gcode.getPositionZ()); - WeaveConnectionSegment segment(to, WeaveSegmentType::FLAT); - flatHandler(*this, segment); - } - } -} - - -void Wireframe2gcode::writeMoveWithRetract(Point3 to) -{ - if ((gcode.getPosition() - to).vSize2() >= nozzle_top_diameter * nozzle_top_diameter * 2 * 2) - gcode.writeRetraction(standard_retraction_config); - gcode.writeTravel(to, moveSpeed); -} - -void Wireframe2gcode::writeMoveWithRetract(Point to) -{ - if (vSize2(gcode.getPositionXY() - to) >= nozzle_top_diameter * nozzle_top_diameter * 2 * 2) - gcode.writeRetraction(standard_retraction_config); - gcode.writeTravel(to, moveSpeed); -} - -Wireframe2gcode::Wireframe2gcode(Weaver& weaver, GCodeExport& gcode) : gcode(gcode), wireFrame(weaver.wireFrame) -{ - const Settings& scene_settings = Application::getInstance().current_slice->scene.settings; - initial_layer_thickness = scene_settings.get("layer_height_0"); - connectionHeight = scene_settings.get("wireframe_height"); - roof_inset = scene_settings.get("wireframe_roof_inset"); - - filament_diameter = scene_settings.get("material_diameter"); - line_width = scene_settings.get("wall_line_width_x"); - - flowConnection = scene_settings.get("wireframe_flow_connection"); - flowFlat = scene_settings.get("wireframe_flow_flat"); - - const double line_area = M_PI * square(INT2MM(line_width) / 2.0); - extrusion_mm3_per_mm_connection = line_area * flowConnection; - extrusion_mm3_per_mm_flat = line_area * flowFlat; - - update_extrusion_offset = false; - - nozzle_outer_diameter = scene_settings.get("machine_nozzle_tip_outer_diameter"); // ___ ___ . - // \ / . - nozzle_expansion_angle = scene_settings.get("machine_nozzle_expansion_angle"); // \_U_/ . - nozzle_clearance = scene_settings.get("wireframe_nozzle_clearance"); // at least line width - nozzle_top_diameter = tan(nozzle_expansion_angle) * connectionHeight + nozzle_outer_diameter + nozzle_clearance; - - moveSpeed = 40; - speedBottom = scene_settings.get("wireframe_printspeed_bottom"); - speedUp = scene_settings.get("wireframe_printspeed_up"); - speedDown = scene_settings.get("wireframe_printspeed_down"); - speedFlat = scene_settings.get("wireframe_printspeed_flat"); - - flat_delay = scene_settings.get("wireframe_flat_delay"); - bottom_delay = scene_settings.get("wireframe_bottom_delay"); - top_delay = scene_settings.get("wireframe_top_delay"); - - up_dist_half_speed = scene_settings.get("wireframe_up_half_speed"); - - top_jump_dist = scene_settings.get("wireframe_top_jump"); - - fall_down = scene_settings.get("wireframe_fall_down"); - drag_along = scene_settings.get("wireframe_drag_along"); - - strategy = STRATEGY_COMPENSATE; - if (scene_settings.get("wireframe_strategy") == "compensate") - strategy = STRATEGY_COMPENSATE; - if (scene_settings.get("wireframe_strategy") == "knot") - strategy = STRATEGY_KNOT; - if (scene_settings.get("wireframe_strategy") == "retract") - strategy = STRATEGY_RETRACT; - - go_back_to_last_top = false; - straight_first_when_going_down = scene_settings.get("wireframe_straight_before_down"); - - roof_fall_down = scene_settings.get("wireframe_roof_fall_down"); - roof_drag_along = scene_settings.get("wireframe_roof_drag_along"); - roof_outer_delay = scene_settings.get("wireframe_roof_outer_delay"); - - - standard_retraction_config.distance = scene_settings.get("retraction_amount"); // Retraction distance in mm. - standard_retraction_config.prime_volume = std::max(0.0, scene_settings.get("retraction_extra_prime_amount")); - standard_retraction_config.speed = scene_settings.get("retraction_retract_speed"); - standard_retraction_config.primeSpeed = scene_settings.get("retraction_prime_speed"); - standard_retraction_config.zHop = scene_settings.get("retraction_hop"); - standard_retraction_config.retraction_count_max = scene_settings.get("retraction_count_max"); - standard_retraction_config.retraction_extrusion_window = scene_settings.get("retraction_extrusion_window"); // Window in which to count retractions in mm of extruded filament. - standard_retraction_config.retraction_min_travel_distance = scene_settings.get("retraction_min_travel"); -} - -void Wireframe2gcode::processStartingCode() -{ - const Settings& scene_settings = Application::getInstance().current_slice->scene.settings; - const size_t extruder_count = Application::getInstance().current_slice->scene.extruders.size(); - size_t start_extruder_nr = scene_settings.get("skirt_brim_extruder_nr").extruder_nr; // TODO - - if (Application::getInstance().communication->isSequential()) - { - std::vector extruder_is_used; - extruder_is_used.resize(extruder_count, false); - extruder_is_used[start_extruder_nr] = true; - std::string prefix = gcode.getFileHeader(extruder_is_used); - gcode.writeCode(prefix.c_str()); - } - - gcode.writeComment("Generated with Cura_SteamEngine " CURA_ENGINE_VERSION); - - if (gcode.getFlavor() != EGCodeFlavor::ULTIGCODE && gcode.getFlavor() != EGCodeFlavor::GRIFFIN) - { - if (scene_settings.get("material_bed_temp_prepend")) - { - if (scene_settings.get("machine_heated_bed") && scene_settings.get("material_bed_temperature") != 0) - { - gcode.writeBedTemperatureCommand(scene_settings.get("material_bed_temperature"), scene_settings.get("material_bed_temp_wait")); - } - } - - if (scene_settings.get("material_print_temp_prepend")) - { - for (size_t extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++) - { - Temperature print_temp = scene_settings.get("material_print_temperature"); - gcode.writeTemperatureCommand(extruder_nr, print_temp); - } - if (scene_settings.get("material_print_temp_wait")) - { - for (size_t extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++) - { - const Temperature print_temp = scene_settings.get("material_print_temperature"); - gcode.writeTemperatureCommand(extruder_nr, print_temp, true); - } - } - } - } - - gcode.writeCode(scene_settings.get("machine_start_gcode").c_str()); - - if (gcode.getFlavor() == EGCodeFlavor::BFB) - { - gcode.writeComment("enable auto-retraction"); - std::ostringstream tmp; - tmp << "M227 S" << (scene_settings.get("retraction_amount") * 2560 / 1000) << " P" << (scene_settings.get("retraction_amount") * 2560 / 1000); - gcode.writeLine(tmp.str().c_str()); - } - else if (gcode.getFlavor() == EGCodeFlavor::GRIFFIN) - { // initialize extruder trains - gcode.writeCode("T0"); // Toolhead already assumed to be at T0, but writing it just to be safe... - Application::getInstance().communication->sendCurrentPosition(gcode.getPositionXY()); - gcode.startExtruder(start_extruder_nr); - constexpr bool wait = true; - gcode.writeTemperatureCommand(start_extruder_nr, scene_settings.get("material_print_temperature"), wait); - gcode.writePrimeTrain(scene_settings.get("speed_travel")); - gcode.writeRetraction(standard_retraction_config); - } -} - - -void Wireframe2gcode::processSkirt() -{ - if (wireFrame.bottom_outline.size() == 0) // If we have no layers, don't create a skirt either. - { - return; - } - Polygons skirt = wireFrame.bottom_outline.offset(MM2INT(100 + 5), ClipperLib::jtRound).offset(MM2INT(-100), ClipperLib::jtRound); - PathOrderOptimizer order(Point(INT32_MIN, INT32_MIN)); - for (PolygonRef skirt_path : skirt) - { - order.addPolygon(skirt_path); - } - order.optimize(); - - const Settings& scene_settings = Application::getInstance().current_slice->scene.settings; - for (const PathOrdering& path : order.paths) - { - gcode.writeTravel((*path.vertices)[path.start_vertex], scene_settings.get("speed_travel")); - for (size_t vertex_index = 0; vertex_index < path.vertices->size(); ++vertex_index) - { - Point vertex = (*path.vertices)[(vertex_index + path.start_vertex + 1) % path.vertices->size()]; - gcode.writeExtrusion(vertex, - scene_settings.get("skirt_brim_speed"), - scene_settings.get("skirt_brim_line_width") * scene_settings.get("initial_layer_line_width_factor") * INT2MM(initial_layer_thickness), - PrintFeatureType::SkirtBrim); - } - } -} - - -void Wireframe2gcode::finalize() -{ - gcode.finalize(Application::getInstance().current_slice->scene.settings.get("machine_end_gcode").c_str()); - for (size_t e = 0; e < Application::getInstance().current_slice->scene.extruders.size(); e++) - { - gcode.writeTemperatureCommand(e, 0, false); - } -} -} // namespace cura diff --git a/tests/test_global_settings.txt b/tests/test_global_settings.txt index c3ecdea57f..684e94a160 100644 --- a/tests/test_global_settings.txt +++ b/tests/test_global_settings.txt @@ -7,7 +7,6 @@ material_bed_temperature_layer_0=60 jerk_support_roof=5 roofing_pattern=lines gradual_support_infill_step_height=1 -wireframe_up_half_speed=0.3 support_angle=60 top_bottom_pattern_0=lines support_bottom_extruder_nr=0 @@ -30,11 +29,8 @@ print_sequence=all_at_once conical_overhang_angle=50 machine_show_variants=False raft_base_jerk=25 -wireframe_top_delay=0 -wireframe_flat_delay=0.1 machine_acceleration=3000 remove_empty_first_layers=True -wireframe_fall_down=0.5 bridge_skin_density_3=80 platform_adhesion=0 acceleration_wall_x=1000 @@ -51,7 +47,6 @@ support_bottom_stair_step_width=5.0 support_tree_branch_diameter_angle=5 jerk_topbottom=5 bridge_skin_speed_2=10.0 -wireframe_roof_fall_down=2 raft_smoothing=5 support=0 cutting_mesh=False @@ -84,9 +79,6 @@ support_conical_angle=30 speed_roofing=20 anti_overhang_mesh=False meshfix_union_all_remove_holes=False -wireframe_roof_inset=3 -wireframe_drag_along=0.6 -wireframe_flow_flat=100 support_interface_skip_height=0.3 draft_shield_height=10 top_thickness=1 @@ -163,7 +155,6 @@ cool_min_speed=5 magic_mesh_surface_mode=normal acceleration_roofing=500 infill_sparse_thickness=0.2 -wireframe_strategy=compensate cross_infill_density_image= z_seam_relative=False raft_surface_fan_speed=0 @@ -195,7 +186,6 @@ gantry_height=60 raft_interface_jerk=25 acceleration_topbottom=500 infill_sparse_density=100 -wireframe_printspeed_flat=5 speed_wall=30 skin_overlap=10 jerk_skirt_brim=5 @@ -208,7 +198,6 @@ draft_shield_height_limitation=full travel_retract_before_outer_wall=True date=30-08-2018 support_offset=0.2 -wireframe_enabled=False support_use_towers=True mold_angle=40 infill_line_width=0.42 @@ -226,10 +215,8 @@ raft_base_line_width=0.8 mesh_rotation_matrix=[[1,0,0], [0,1,0], [0,0,1]] support_pattern=zigzag cooling=0 -wireframe_printspeed_bottom=5 support_roof_line_width=0.35 skirt_gap=3 -wireframe_top_jump=0.6 speed_support=20 acceleration_print=4000 speed_wall_x=30 @@ -256,7 +243,6 @@ material_final_print_temperature=185 coasting_volume=0.064 skirt_line_count=1 machine_max_feedrate_e=45 -wireframe_height=3 acceleration_prime_tower=2000 machine_gcode_flavor=Griffin machine_height=200 @@ -276,7 +262,6 @@ acceleration_layer_0=500 coasting_min_volume=0.8 raft_margin=15 support_tower_diameter=3.0 -wireframe_roof_outer_delay=0.2 cool_fan_speed_max=100 machine_endstop_positive_direction_x=False speed_support_roof=23 @@ -288,8 +273,6 @@ support_zag_skip_count=0 initial_extruder_nr=0 roofing_angles=[ ] zig_zaggify_support=False -wireframe_nozzle_clearance=1 -wireframe_printspeed=5 jerk_print=25 infill_offset_x=0 machine_max_acceleration_e=10000 @@ -384,7 +367,6 @@ raft_base_speed=13.125 retraction_retract_speed=25 machine_end_gcode=G91 ;Relative movement\nG0 F15000 X8.0 Z0.5 E-4.5 ;Wiping+material retraction\nG0 F10000 Z1.5 E4.5 ;Compensation for the retraction\nG90 ;Disable relative movement support_tree_wall_count=1 -wireframe_roof_drag_along=0.8 material_shrinkage_percentage=100 machine_steps_per_mm_e=1600 xy_offset=0 @@ -409,7 +391,6 @@ material_print_temperature_layer_0=205 machine_minimum_feedrate=0.0 flow_rate_extrusion_offset_factor=100 acceleration_enabled=True -wireframe_straight_before_down=20 machine_nozzle_temp_enabled=True speed_infill=35 jerk_roofing=5 @@ -417,7 +398,6 @@ material=0 jerk_support_bottom=5 raft_interface_acceleration=4000 raft_jerk=25 -wireframe_flow=100 ooze_shield_enabled=True support_bottom_pattern=concentric gradual_infill_step_height=1.5 @@ -426,7 +406,6 @@ mesh_position_y=0 roofing_line_width=0.35 machine_nozzle_size=0.4 machine_head_polygon=[[-1, 1], [-1, -1], [1, -1], [1, 1]] -wireframe_flow_connection=100 adaptive_layer_height_variation=0.1 wall_0_inset=0 support_skip_some_zags=False @@ -436,7 +415,6 @@ acceleration_wall=1000 extruders_enabled_count=2 machine_depth=215 machine_firmware_retract=False -wireframe_printspeed_down=5 roofing_extruder_nr=-1 adaptive_layer_height_variation_step=0.01 jerk_wall_x=10 @@ -462,7 +440,6 @@ acceleration_travel=5000 cool_min_layer_time_fan_speed_max=10 infill_support_enabled=False material_initial_print_temperature=190 -wireframe_bottom_delay=0 bridge_wall_speed=10.0 mold_enabled=False bridge_wall_max_overhang=100 @@ -480,7 +457,6 @@ support_wall_count=0 ironing_pattern=zigzag top_layers=0 support_xy_distance=0.875 -wireframe_printspeed_up=5 machine_feeder_wheel_diameter=10.0 skin_no_small_gaps_heuristic=True speed_ironing=13.333333333333334