mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 00:31:11 -06:00
Merge branch 'master' into wipe_tower_improvements
This commit is contained in:
commit
1c6fa6660e
79 changed files with 34645 additions and 10116 deletions
|
@ -26,6 +26,7 @@ enum ExtrusionRole {
|
|||
erSupportMaterial,
|
||||
erSupportMaterialInterface,
|
||||
erWipeTower,
|
||||
erCustom,
|
||||
// Extrusion role for a collection with multiple extrusion roles.
|
||||
erMixed,
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "FillConcentric.hpp"
|
||||
#include "FillHoneycomb.hpp"
|
||||
#include "Fill3DHoneycomb.hpp"
|
||||
#include "FillGyroid.hpp"
|
||||
#include "FillPlanePath.hpp"
|
||||
#include "FillRectilinear.hpp"
|
||||
#include "FillRectilinear2.hpp"
|
||||
|
@ -21,6 +22,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||
case ipConcentric: return new FillConcentric();
|
||||
case ipHoneycomb: return new FillHoneycomb();
|
||||
case ip3DHoneycomb: return new Fill3DHoneycomb();
|
||||
case ipGyroid: return new FillGyroid();
|
||||
case ipRectilinear: return new FillRectilinear2();
|
||||
// case ipRectilinear: return new FillRectilinear();
|
||||
case ipLine: return new FillLine();
|
||||
|
|
150
xs/src/libslic3r/Fill/FillGyroid.cpp
Normal file
150
xs/src/libslic3r/Fill/FillGyroid.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
#include "../ClipperUtils.hpp"
|
||||
#include "../PolylineCollection.hpp"
|
||||
#include "../Surface.hpp"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "FillGyroid.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static inline Polyline make_wave_vertical(
|
||||
double width, double height, double x0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(coord_t(clamp(0., width, x0) * scaleFactor), 0));
|
||||
double phase_offset_sin = (z_cos < 0 ? M_PI : 0) + M_PI;
|
||||
double phase_offset_cos = (z_cos < 0 ? M_PI : 0) + M_PI + (flip ? M_PI : 0.);
|
||||
for (double y = 0.; y < height + segmentSize; y += segmentSize) {
|
||||
y = std::min(y, height);
|
||||
double a = sin(y + phase_offset_sin);
|
||||
double b = - z_cos;
|
||||
double res = z_sin * cos(y + phase_offset_cos);
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double x = clamp(0., width, asin(a/r) + asin(res/r) + M_PI + x0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
return polyline;
|
||||
}
|
||||
|
||||
static inline Polyline make_wave_horizontal(
|
||||
double width, double height, double y0,
|
||||
double segmentSize, double scaleFactor,
|
||||
double z_cos, double z_sin, bool flip)
|
||||
{
|
||||
Polyline polyline;
|
||||
polyline.points.emplace_back(Point(0, coord_t(clamp(0., height, y0) * scaleFactor)));
|
||||
double phase_offset_sin = (z_sin < 0 ? M_PI : 0) + (flip ? 0 : M_PI);
|
||||
double phase_offset_cos = z_sin < 0 ? M_PI : 0.;
|
||||
for (double x=0.; x < width + segmentSize; x += segmentSize) {
|
||||
x = std::min(x, width);
|
||||
double a = cos(x + phase_offset_cos);
|
||||
double b = - z_sin;
|
||||
double res = z_cos * sin(x + phase_offset_sin);
|
||||
double r = sqrt(sqr(a) + sqr(b));
|
||||
double y = clamp(0., height, asin(a/r) + asin(res/r) + 0.5 * M_PI + y0);
|
||||
polyline.points.emplace_back(convert_to<Point>(Pointf(x, y) * scaleFactor));
|
||||
}
|
||||
if (flip)
|
||||
std::reverse(polyline.points.begin(), polyline.points.end());
|
||||
return polyline;
|
||||
}
|
||||
|
||||
static Polylines make_gyroid_waves(double gridZ, double density, double layer_width, double width, double height)
|
||||
{
|
||||
double scaleFactor = scale_(layer_width) / density;
|
||||
double segmentSize = 0.5 * density;
|
||||
//scale factor for 5% : 8 712 388
|
||||
// 1z = 10^-6 mm ?
|
||||
double z = gridZ / scaleFactor;
|
||||
double z_sin = sin(z);
|
||||
double z_cos = cos(z);
|
||||
Polylines result;
|
||||
if (abs(z_sin) <= abs(z_cos)) {
|
||||
// Vertical wave
|
||||
double x0 = M_PI * (int)((- 0.5 * M_PI) / M_PI - 1.);
|
||||
bool flip = ((int)(x0 / M_PI + 1.) & 1) != 0;
|
||||
for (; x0 < width - 0.5 * M_PI; x0 += M_PI, flip = ! flip)
|
||||
result.emplace_back(make_wave_vertical(width, height, x0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
} else {
|
||||
// Horizontal wave
|
||||
bool flip = true;
|
||||
for (double y0 = 0.; y0 < width; y0 += M_PI, flip = !flip)
|
||||
result.emplace_back(make_wave_horizontal(width, height, y0, segmentSize, scaleFactor, z_cos, z_sin, flip));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FillGyroid::_fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out)
|
||||
{
|
||||
// no rotation is supported for this infill pattern
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
coord_t distance = coord_t(scale_(this->spacing) / (params.density*this->scaling));
|
||||
|
||||
// align bounding box to a multiple of our grid module
|
||||
bb.merge(_align_to_grid(bb.min, Point(2*M_PI*distance, 2*M_PI*distance)));
|
||||
|
||||
// generate pattern
|
||||
Polylines polylines = make_gyroid_waves(
|
||||
scale_(this->z),
|
||||
params.density*this->scaling,
|
||||
this->spacing,
|
||||
ceil(bb.size().x / distance) + 1.,
|
||||
ceil(bb.size().y / distance) + 1.);
|
||||
|
||||
// move pattern in place
|
||||
for (Polyline &polyline : polylines)
|
||||
polyline.translate(bb.min.x, bb.min.y);
|
||||
|
||||
// clip pattern to boundaries
|
||||
polylines = intersection_pl(polylines, (Polygons)expolygon);
|
||||
|
||||
// connect lines
|
||||
if (! params.dont_connect && ! polylines.empty()) { // prevent calling leftmost_point() on empty collections
|
||||
ExPolygon expolygon_off;
|
||||
{
|
||||
ExPolygons expolygons_off = offset_ex(expolygon, (float)SCALED_EPSILON);
|
||||
if (! expolygons_off.empty()) {
|
||||
// When expanding a polygon, the number of islands could only shrink. Therefore the offset_ex shall generate exactly one expanded island for one input island.
|
||||
assert(expolygons_off.size() == 1);
|
||||
std::swap(expolygon_off, expolygons_off.front());
|
||||
}
|
||||
}
|
||||
Polylines chained = PolylineCollection::chained_path_from(
|
||||
std::move(polylines),
|
||||
PolylineCollection::leftmost_point(polylines), false); // reverse allowed
|
||||
bool first = true;
|
||||
for (Polyline &polyline : chained) {
|
||||
if (! first) {
|
||||
// Try to connect the lines.
|
||||
Points &pts_end = polylines_out.back().points;
|
||||
const Point &first_point = polyline.points.front();
|
||||
const Point &last_point = pts_end.back();
|
||||
// TODO: we should also check that both points are on a fill_boundary to avoid
|
||||
// connecting paths on the boundaries of internal regions
|
||||
// TODO: avoid crossing current infill path
|
||||
if (first_point.distance_to(last_point) <= 5 * distance &&
|
||||
expolygon_off.contains(Line(last_point, first_point))) {
|
||||
// Append the polyline.
|
||||
pts_end.insert(pts_end.end(), polyline.points.begin(), polyline.points.end());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// The lines cannot be connected.
|
||||
polylines_out.emplace_back(std::move(polyline));
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
34
xs/src/libslic3r/Fill/FillGyroid.hpp
Normal file
34
xs/src/libslic3r/Fill/FillGyroid.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef slic3r_FillGyroid_hpp_
|
||||
#define slic3r_FillGyroid_hpp_
|
||||
|
||||
#include "../libslic3r.h"
|
||||
|
||||
#include "FillBase.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class FillGyroid : public Fill
|
||||
{
|
||||
public:
|
||||
FillGyroid() {}
|
||||
virtual Fill* clone() const { return new FillGyroid(*this); }
|
||||
|
||||
// require bridge flow since most of this pattern hangs in air
|
||||
virtual bool use_bridge_flow() const { return true; }
|
||||
|
||||
protected:
|
||||
|
||||
// mult of density, to have a good %of weight for each density parameter
|
||||
float scaling = 1.75;
|
||||
|
||||
virtual void _fill_surface_single(
|
||||
const FillParams ¶ms,
|
||||
unsigned int thickness_layers,
|
||||
const std::pair<float, Point> &direction,
|
||||
ExPolygon &expolygon,
|
||||
Polylines &polylines_out);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_FillGyroid_hpp_
|
|
@ -587,6 +587,15 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
|||
this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true);
|
||||
// Set extruder(s) temperature before and after start G-code.
|
||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false);
|
||||
|
||||
if (m_enable_analyzer)
|
||||
{
|
||||
// adds tag for analyzer
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
_writeln(file, buf);
|
||||
}
|
||||
|
||||
// Write the custom start G-code
|
||||
_writeln(file, start_gcode);
|
||||
// Process filament-specific gcode in extruder order.
|
||||
|
@ -770,6 +779,15 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
|||
// Write end commands to file.
|
||||
_write(file, this->retract());
|
||||
_write(file, m_writer.set_fan(false));
|
||||
|
||||
if (m_enable_analyzer)
|
||||
{
|
||||
// adds tag for analyzer
|
||||
char buf[32];
|
||||
sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
|
||||
_writeln(file, buf);
|
||||
}
|
||||
|
||||
// Process filament-specific gcode in extruder order.
|
||||
if (print.config.single_extruder_multi_material) {
|
||||
// Process the end_filament_gcode for the active filament only.
|
||||
|
@ -1384,18 +1402,13 @@ void GCode::apply_print_config(const PrintConfig &print_config)
|
|||
|
||||
void GCode::append_full_config(const Print& print, std::string& str)
|
||||
{
|
||||
char buff[4096];
|
||||
|
||||
const StaticPrintConfig *configs[] = { &print.config, &print.default_object_config, &print.default_region_config };
|
||||
for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) {
|
||||
const StaticPrintConfig *cfg = configs[i];
|
||||
for (const std::string &key : cfg->keys())
|
||||
{
|
||||
if (key != "compatible_printers")
|
||||
{
|
||||
sprintf(buff, "; %s = %s\n", key.c_str(), cfg->serialize(key).c_str());
|
||||
str += buff;
|
||||
}
|
||||
str += "; " + key + " = " + cfg->serialize(key) + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,13 @@ void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLi
|
|||
{
|
||||
// processes 'special' comments contained in line
|
||||
if (_process_tags(line))
|
||||
{
|
||||
#if 0
|
||||
// DEBUG ONLY: puts the line back into the gcode
|
||||
m_process_output += line.raw() + "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// sets new start position/extrusion
|
||||
_set_start_position(_get_end_position());
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "Analyzer.hpp"
|
||||
#include "PreviewData.hpp"
|
||||
#include <float.h>
|
||||
#include <wx/intl.h>
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -125,26 +127,28 @@ const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Rol
|
|||
Color(0.0f, 0.5f, 0.0f, 1.0f), // erSupportMaterial
|
||||
Color(0.0f, 0.0f, 0.5f, 1.0f), // erSupportMaterialInterface
|
||||
Color(0.7f, 0.89f, 0.67f, 1.0f), // erWipeTower
|
||||
Color(1.0f, 1.0f, 0.0f, 1.0f), // erCustom
|
||||
Color(0.0f, 0.0f, 0.0f, 1.0f) // erMixed
|
||||
};
|
||||
|
||||
// todo: merge with Slic3r::ExtrusionRole2String() from GCode.cpp
|
||||
const std::string GCodePreviewData::Extrusion::Default_Extrusion_Role_Names[Num_Extrusion_Roles]
|
||||
{
|
||||
"None",
|
||||
"Perimeter",
|
||||
"External perimeter",
|
||||
"Overhang perimeter",
|
||||
"Internal infill",
|
||||
"Solid infill",
|
||||
"Top solid infill",
|
||||
"Bridge infill",
|
||||
"Gap fill",
|
||||
"Skirt",
|
||||
"Support material",
|
||||
"Support material interface",
|
||||
"Wipe tower",
|
||||
"Mixed"
|
||||
L("None"),
|
||||
L("Perimeter"),
|
||||
L("External perimeter"),
|
||||
L("Overhang perimeter"),
|
||||
L("Internal infill"),
|
||||
L("Solid infill"),
|
||||
L("Top solid infill"),
|
||||
L("Bridge infill"),
|
||||
L("Gap fill"),
|
||||
L("Skirt"),
|
||||
L("Support material"),
|
||||
L("Support material interface"),
|
||||
L("Wipe tower"),
|
||||
L("Custom"),
|
||||
L("Mixed")
|
||||
};
|
||||
|
||||
const GCodePreviewData::Extrusion::EViewType GCodePreviewData::Extrusion::Default_View_Type = GCodePreviewData::Extrusion::FeatureType;
|
||||
|
@ -323,15 +327,15 @@ std::string GCodePreviewData::get_legend_title() const
|
|||
switch (extrusion.view_type)
|
||||
{
|
||||
case Extrusion::FeatureType:
|
||||
return "Feature type";
|
||||
return L("Feature type");
|
||||
case Extrusion::Height:
|
||||
return "Height (mm)";
|
||||
return L("Height (mm)");
|
||||
case Extrusion::Width:
|
||||
return "Width (mm)";
|
||||
return L("Width (mm)");
|
||||
case Extrusion::Feedrate:
|
||||
return "Speed (mm/s)";
|
||||
return L("Speed (mm/s)");
|
||||
case Extrusion::Tool:
|
||||
return "Tool";
|
||||
return L("Tool");
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -360,10 +364,13 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||
{
|
||||
case Extrusion::FeatureType:
|
||||
{
|
||||
items.reserve(erMixed - erPerimeter + 1);
|
||||
for (unsigned int i = (unsigned int)erPerimeter; i < (unsigned int)erMixed; ++i)
|
||||
ExtrusionRole first_valid = erPerimeter;
|
||||
ExtrusionRole last_valid = erCustom;
|
||||
|
||||
items.reserve(last_valid - first_valid + 1);
|
||||
for (unsigned int i = (unsigned int)first_valid; i <= (unsigned int)last_valid; ++i)
|
||||
{
|
||||
items.emplace_back(extrusion.role_names[i], extrusion.role_colors[i]);
|
||||
items.emplace_back(_CHB(extrusion.role_names[i].c_str()).data(), extrusion.role_colors[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -389,8 +396,8 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||
items.reserve(tools_colors_count);
|
||||
for (unsigned int i = 0; i < tools_colors_count; ++i)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf(buf, "Extruder %d", i + 1);
|
||||
char buf[MIN_BUF_LENGTH_FOR_L];
|
||||
sprintf(buf, _CHB(L("Extruder %d")), i + 1);
|
||||
|
||||
GCodePreviewData::Color color;
|
||||
::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float));
|
||||
|
|
|
@ -19,6 +19,18 @@ static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 per
|
|||
|
||||
static const float PREVIOUS_FEEDRATE_THRESHOLD = 0.0001f;
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
static const std::string MOVE_TYPE_STR[Slic3r::GCodeTimeEstimator::Block::Num_Types] =
|
||||
{
|
||||
"Noop",
|
||||
"Retract",
|
||||
"Unretract",
|
||||
"Tool_change",
|
||||
"Move",
|
||||
"Extrude"
|
||||
};
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void GCodeTimeEstimator::Feedrates::reset()
|
||||
|
@ -139,6 +151,14 @@ namespace Slic3r {
|
|||
return (acceleration == 0.0f) ? 0.0f : (2.0f * acceleration * distance - sqr(initial_rate) + sqr(final_rate)) / (4.0f * acceleration);
|
||||
}
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
GCodeTimeEstimator::MoveStats::MoveStats()
|
||||
: count(0)
|
||||
, time(0.0f)
|
||||
{
|
||||
}
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
GCodeTimeEstimator::GCodeTimeEstimator()
|
||||
{
|
||||
reset();
|
||||
|
@ -155,6 +175,10 @@ namespace Slic3r {
|
|||
|
||||
_calculate_time();
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
_reset_blocks();
|
||||
_reset();
|
||||
}
|
||||
|
@ -166,6 +190,10 @@ namespace Slic3r {
|
|||
_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
|
||||
_calculate_time();
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
_reset_blocks();
|
||||
_reset();
|
||||
}
|
||||
|
@ -180,6 +208,10 @@ namespace Slic3r {
|
|||
_parser.parse_line(line, action);
|
||||
_calculate_time();
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
_reset_blocks();
|
||||
_reset();
|
||||
}
|
||||
|
@ -208,6 +240,11 @@ namespace Slic3r {
|
|||
{
|
||||
PROFILE_FUNC();
|
||||
_calculate_time();
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
_log_moves_stats();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
_reset_blocks();
|
||||
_reset();
|
||||
}
|
||||
|
@ -393,6 +430,9 @@ namespace Slic3r {
|
|||
void GCodeTimeEstimator::reset()
|
||||
{
|
||||
_time = 0.0f;
|
||||
#if ENABLE_MOVE_STATS
|
||||
_moves_stats.clear();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
_reset_blocks();
|
||||
_reset();
|
||||
}
|
||||
|
@ -448,9 +488,24 @@ namespace Slic3r {
|
|||
|
||||
for (const Block& block : _blocks)
|
||||
{
|
||||
#if ENABLE_MOVE_STATS
|
||||
float block_time = 0.0f;
|
||||
block_time += block.acceleration_time();
|
||||
block_time += block.cruise_time();
|
||||
block_time += block.deceleration_time();
|
||||
_time += block_time;
|
||||
|
||||
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
|
||||
if (it == _moves_stats.end())
|
||||
it = _moves_stats.insert(MovesStatsMap::value_type(block.move_type, MoveStats())).first;
|
||||
|
||||
it->second.count += 1;
|
||||
it->second.time += block_time;
|
||||
#else
|
||||
_time += block.acceleration_time();
|
||||
_time += block.cruise_time();
|
||||
_time += block.deceleration_time();
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -746,6 +801,28 @@ namespace Slic3r {
|
|||
set_axis_position((EAxis)a, new_pos[a]);
|
||||
}
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
// detects block move type
|
||||
block.move_type = Block::Noop;
|
||||
|
||||
if (block.delta_pos[E] < 0.0f)
|
||||
{
|
||||
if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f) || (block.delta_pos[Z] != 0.0f))
|
||||
block.move_type = Block::Move;
|
||||
else
|
||||
block.move_type = Block::Retract;
|
||||
}
|
||||
else if (block.delta_pos[E] > 0.0f)
|
||||
{
|
||||
if ((block.delta_pos[X] == 0.0f) && (block.delta_pos[Y] == 0.0f) && (block.delta_pos[Z] == 0.0f))
|
||||
block.move_type = Block::Unretract;
|
||||
else if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f))
|
||||
block.move_type = Block::Extrude;
|
||||
}
|
||||
else if ((block.delta_pos[X] != 0.0f) || (block.delta_pos[Y] != 0.0f) || (block.delta_pos[Z] != 0.0f))
|
||||
block.move_type = Block::Move;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
// adds block to blocks list
|
||||
_blocks.emplace_back(block);
|
||||
}
|
||||
|
@ -1064,4 +1141,24 @@ namespace Slic3r {
|
|||
next->flags.recalculate = false;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
void GCodeTimeEstimator::_log_moves_stats() const
|
||||
{
|
||||
float moves_count = 0.0f;
|
||||
for (const MovesStatsMap::value_type& move : _moves_stats)
|
||||
{
|
||||
moves_count += (float)move.second.count;
|
||||
}
|
||||
|
||||
for (const MovesStatsMap::value_type& move : _moves_stats)
|
||||
{
|
||||
std::cout << MOVE_TYPE_STR[move.first];
|
||||
std::cout << ": count " << move.second.count << " (" << 100.0f * (float)move.second.count / moves_count << "%)";
|
||||
std::cout << " - time: " << move.second.time << "s (" << 100.0f * move.second.time / _time << "%)";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "PrintConfig.hpp"
|
||||
#include "GCodeReader.hpp"
|
||||
|
||||
#define ENABLE_MOVE_STATS 0
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//
|
||||
|
@ -74,6 +76,19 @@ namespace Slic3r {
|
|||
public:
|
||||
struct Block
|
||||
{
|
||||
#if ENABLE_MOVE_STATS
|
||||
enum EMoveType : unsigned char
|
||||
{
|
||||
Noop,
|
||||
Retract,
|
||||
Unretract,
|
||||
Tool_change,
|
||||
Move,
|
||||
Extrude,
|
||||
Num_Types
|
||||
};
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
struct FeedrateProfile
|
||||
{
|
||||
float entry; // mm/s
|
||||
|
@ -106,6 +121,10 @@ namespace Slic3r {
|
|||
bool nominal_length;
|
||||
};
|
||||
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
EMoveType move_type;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
Flags flags;
|
||||
|
||||
float delta_pos[Num_Axis]; // mm
|
||||
|
@ -156,6 +175,18 @@ namespace Slic3r {
|
|||
|
||||
typedef std::vector<Block> BlocksList;
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
struct MoveStats
|
||||
{
|
||||
unsigned int count;
|
||||
float time;
|
||||
|
||||
MoveStats();
|
||||
};
|
||||
|
||||
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
private:
|
||||
GCodeReader _parser;
|
||||
State _state;
|
||||
|
@ -163,6 +194,9 @@ namespace Slic3r {
|
|||
Feedrates _prev;
|
||||
BlocksList _blocks;
|
||||
float _time; // s
|
||||
#if ENABLE_MOVE_STATS
|
||||
MovesStatsMap _moves_stats;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
|
||||
public:
|
||||
GCodeTimeEstimator();
|
||||
|
@ -318,6 +352,10 @@ namespace Slic3r {
|
|||
void _planner_reverse_pass_kernel(Block& curr, Block& next);
|
||||
|
||||
void _recalculate_trapezoids();
|
||||
|
||||
#if ENABLE_MOVE_STATS
|
||||
void _log_moves_stats() const;
|
||||
#endif // ENABLE_MOVE_STATS
|
||||
};
|
||||
|
||||
} /* namespace Slic3r */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -91,7 +92,15 @@ Model Model::read_from_archive(const std::string &input_file, PresetBundle* bund
|
|||
throw std::runtime_error("The supplied file couldn't be read because it's empty");
|
||||
|
||||
for (ModelObject *o : model.objects)
|
||||
o->input_file = input_file;
|
||||
{
|
||||
if (boost::algorithm::iends_with(input_file, ".zip.amf"))
|
||||
{
|
||||
// we remove the .zip part of the extension to avoid it be added to filenames when exporting
|
||||
o->input_file = boost::ireplace_last_copy(input_file, ".zip.", ".");
|
||||
}
|
||||
else
|
||||
o->input_file = input_file;
|
||||
}
|
||||
|
||||
if (add_default_instances)
|
||||
model.add_default_instances();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,7 +29,7 @@ enum GCodeFlavor {
|
|||
|
||||
enum InfillPattern {
|
||||
ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
|
||||
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral,
|
||||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral,
|
||||
};
|
||||
|
||||
enum SupportMaterialPattern {
|
||||
|
@ -73,6 +73,7 @@ template<> inline t_config_enum_values& ConfigOptionEnum<InfillPattern>::get_enu
|
|||
keys_map["concentric"] = ipConcentric;
|
||||
keys_map["honeycomb"] = ipHoneycomb;
|
||||
keys_map["3dhoneycomb"] = ip3DHoneycomb;
|
||||
keys_map["gyroid"] = ipGyroid;
|
||||
keys_map["hilbertcurve"] = ipHilbertCurve;
|
||||
keys_map["archimedeanchords"] = ipArchimedeanChords;
|
||||
keys_map["octagramspiral"] = ipOctagramSpiral;
|
||||
|
@ -699,6 +700,7 @@ class HostConfig : public StaticPrintConfig
|
|||
public:
|
||||
ConfigOptionString octoprint_host;
|
||||
ConfigOptionString octoprint_apikey;
|
||||
ConfigOptionString octoprint_cafile;
|
||||
ConfigOptionString serial_port;
|
||||
ConfigOptionInt serial_speed;
|
||||
|
||||
|
@ -707,6 +709,7 @@ protected:
|
|||
{
|
||||
OPT_PTR(octoprint_host);
|
||||
OPT_PTR(octoprint_apikey);
|
||||
OPT_PTR(octoprint_cafile);
|
||||
OPT_PTR(serial_port);
|
||||
OPT_PTR(serial_speed);
|
||||
}
|
||||
|
|
|
@ -198,9 +198,8 @@ TriangleMesh::repair() {
|
|||
stl_clear_error(&stl);
|
||||
}
|
||||
|
||||
// commenting out the following call fixes: #574, #413, #269, #262, #259, #230, #228, #206
|
||||
// // normal_directions
|
||||
// stl_fix_normal_directions(&stl);
|
||||
// normal_directions
|
||||
stl_fix_normal_directions(&stl);
|
||||
|
||||
// normal_values
|
||||
stl_fix_normal_values(&stl);
|
||||
|
@ -210,7 +209,7 @@ TriangleMesh::repair() {
|
|||
|
||||
// neighbors
|
||||
stl_verify_neighbors(&stl);
|
||||
|
||||
|
||||
this->repaired = true;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() finished";
|
||||
|
@ -1187,40 +1186,46 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
|||
loops correctly in some edge cases when original model had overlapping facets
|
||||
*/
|
||||
|
||||
std::vector<double> area;
|
||||
std::vector<size_t> sorted_area; // vector of indices
|
||||
for (Polygons::const_iterator loop = loops.begin(); loop != loops.end(); ++ loop) {
|
||||
area.push_back(loop->area());
|
||||
sorted_area.push_back(loop - loops.begin());
|
||||
}
|
||||
|
||||
// outer first
|
||||
std::sort(sorted_area.begin(), sorted_area.end(),
|
||||
[&area](size_t a, size_t b) { return std::abs(area[a]) > std::abs(area[b]); });
|
||||
/* The following lines are commented out because they can generate wrong polygons,
|
||||
see for example issue #661 */
|
||||
|
||||
// we don't perform a safety offset now because it might reverse cw loops
|
||||
Polygons p_slices;
|
||||
for (std::vector<size_t>::const_iterator loop_idx = sorted_area.begin(); loop_idx != sorted_area.end(); ++ loop_idx) {
|
||||
/* we rely on the already computed area to determine the winding order
|
||||
of the loops, since the Orientation() function provided by Clipper
|
||||
would do the same, thus repeating the calculation */
|
||||
Polygons::const_iterator loop = loops.begin() + *loop_idx;
|
||||
if (area[*loop_idx] > +EPSILON)
|
||||
p_slices.push_back(*loop);
|
||||
else if (area[*loop_idx] < -EPSILON)
|
||||
//FIXME This is arbitrary and possibly very slow.
|
||||
// If the hole is inside a polygon, then there is no need to diff.
|
||||
// If the hole intersects a polygon boundary, then diff it, but then
|
||||
// there is no guarantee of an ordering of the loops.
|
||||
// Maybe we can test for the intersection before running the expensive diff algorithm?
|
||||
p_slices = diff(p_slices, *loop);
|
||||
}
|
||||
//std::vector<double> area;
|
||||
//std::vector<size_t> sorted_area; // vector of indices
|
||||
//for (Polygons::const_iterator loop = loops.begin(); loop != loops.end(); ++ loop) {
|
||||
// area.push_back(loop->area());
|
||||
// sorted_area.push_back(loop - loops.begin());
|
||||
//}
|
||||
//
|
||||
//// outer first
|
||||
//std::sort(sorted_area.begin(), sorted_area.end(),
|
||||
// [&area](size_t a, size_t b) { return std::abs(area[a]) > std::abs(area[b]); });
|
||||
|
||||
//// we don't perform a safety offset now because it might reverse cw loops
|
||||
//Polygons p_slices;
|
||||
//for (std::vector<size_t>::const_iterator loop_idx = sorted_area.begin(); loop_idx != sorted_area.end(); ++ loop_idx) {
|
||||
// /* we rely on the already computed area to determine the winding order
|
||||
// of the loops, since the Orientation() function provided by Clipper
|
||||
// would do the same, thus repeating the calculation */
|
||||
// Polygons::const_iterator loop = loops.begin() + *loop_idx;
|
||||
// if (area[*loop_idx] > +EPSILON)
|
||||
// p_slices.push_back(*loop);
|
||||
// else if (area[*loop_idx] < -EPSILON)
|
||||
// //FIXME This is arbitrary and possibly very slow.
|
||||
// // If the hole is inside a polygon, then there is no need to diff.
|
||||
// // If the hole intersects a polygon boundary, then diff it, but then
|
||||
// // there is no guarantee of an ordering of the loops.
|
||||
// // Maybe we can test for the intersection before running the expensive diff algorithm?
|
||||
// p_slices = diff(p_slices, *loop);
|
||||
//}
|
||||
|
||||
// perform a safety offset to merge very close facets (TODO: find test case for this)
|
||||
double safety_offset = scale_(0.0499);
|
||||
//FIXME see https://github.com/prusa3d/Slic3r/issues/520
|
||||
// double safety_offset = scale_(0.0001);
|
||||
ExPolygons ex_slices = offset2_ex(p_slices, +safety_offset, -safety_offset);
|
||||
|
||||
/* The following line is commented out because it can generate wrong polygons,
|
||||
see for example issue #661 */
|
||||
//ExPolygons ex_slices = offset2_ex(p_slices, +safety_offset, -safety_offset);
|
||||
|
||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
||||
size_t holes_count = 0;
|
||||
|
@ -1231,7 +1236,10 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slic
|
|||
#endif
|
||||
|
||||
// append to the supplied collection
|
||||
expolygons_append(*slices, ex_slices);
|
||||
/* Fix for issue #661 { */
|
||||
expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
|
||||
//expolygons_append(*slices, ex_slices);
|
||||
/* } */
|
||||
}
|
||||
|
||||
void TriangleMeshSlicer::make_expolygons(std::vector<IntersectionLine> &lines, ExPolygons* slices) const
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue