mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-24 09:11:23 -06:00
Fixed conflicts after merge with master
This commit is contained in:
commit
f12b39be25
171 changed files with 23530 additions and 14236 deletions
|
|
@ -577,7 +577,7 @@ void _arrange(
|
|||
std::function<bool()> stopfn)
|
||||
{
|
||||
// Integer ceiling the min distance from the bed perimeters
|
||||
coord_t md = minobjd - 2 * scaled(0.1 + EPSILON);
|
||||
coord_t md = minobjd;
|
||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||
|
||||
auto corrected_bin = bin;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ std::vector<std::pair<double, unsigned int>> custom_tool_changes(const Info& cus
|
|||
for (const Item& custom_gcode : custom_gcode_per_print_z.gcodes)
|
||||
if (custom_gcode.gcode == ToolChangeCode) {
|
||||
// If extruder count in PrinterSettings was changed, use default (0) extruder for extruders, more than num_extruders
|
||||
custom_tool_changes.emplace_back(custom_gcode.print_z, static_cast<unsigned int>(custom_gcode.extruder > num_extruders ? 1 : custom_gcode.extruder));
|
||||
assert(custom_gcode.extruder >= 0);
|
||||
custom_tool_changes.emplace_back(custom_gcode.print_z, static_cast<unsigned int>(size_t(custom_gcode.extruder) > num_extruders ? 1 : custom_gcode.extruder));
|
||||
}
|
||||
return custom_tool_changes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,7 @@ EdgeGrid::Grid::ClosestPointResult EdgeGrid::Grid::closest_point(const Point &pt
|
|||
}
|
||||
}
|
||||
}
|
||||
if (result.contour_idx != -1 && d_min <= double(search_radius)) {
|
||||
if (result.contour_idx != size_t(-1) && d_min <= double(search_radius)) {
|
||||
result.distance = d_min * sign_min;
|
||||
result.t /= l2_seg_min;
|
||||
assert(result.t >= 0. && result.t < 1.);
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
if (surface.surface_type == stInternalVoid)
|
||||
has_internal_voids = true;
|
||||
else {
|
||||
FlowRole extrusion_role = (surface.surface_type == stTop) ? frTopSolidInfill : (surface.is_solid() ? frSolidInfill : frInfill);
|
||||
FlowRole extrusion_role = surface.is_top() ? frTopSolidInfill : (surface.is_solid() ? frSolidInfill : frInfill);
|
||||
bool is_bridge = layer.id() > 0 && surface.is_bridge();
|
||||
params.extruder = layerm.region()->extruder(extrusion_role);
|
||||
params.pattern = layerm.region()->config().fill_pattern.value;
|
||||
|
|
@ -132,7 +132,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||
is_bridge ?
|
||||
erBridgeInfill :
|
||||
(surface.is_solid() ?
|
||||
((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
|
||||
(surface.is_top() ? erTopSolidInfill : erSolidInfill) :
|
||||
erInternalInfill);
|
||||
params.bridge_angle = float(surface.bridge_angle);
|
||||
params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
||||
|
|
|
|||
|
|
@ -611,7 +611,7 @@ static inline SegmentPoint clip_start_segment_and_point(const Points &polyline,
|
|||
SegmentPoint out;
|
||||
if (polyline.size() >= 2) {
|
||||
Vec2d pt_prev = polyline.front().cast<double>();
|
||||
for (int i = 1; i < polyline.size(); ++ i) {
|
||||
for (size_t i = 1; i < polyline.size(); ++ i) {
|
||||
Vec2d pt = polyline[i].cast<double>();
|
||||
Vec2d v = pt - pt_prev;
|
||||
double l2 = v.squaredNorm();
|
||||
|
|
@ -674,7 +674,7 @@ static inline double segment_point_distance_squared(const Vec2d &p1a, const Vec2
|
|||
if (l2 < EPSILON)
|
||||
// p1a == p1b
|
||||
return (p2 - p1a).squaredNorm();
|
||||
return segment_point_distance_squared(p1a, p1b, v, v.squaredNorm(), p2);
|
||||
return segment_point_distance_squared(p1a, p1b, v, v.squaredNorm(), p2);
|
||||
}
|
||||
|
||||
// Distance to the closest point of line.
|
||||
|
|
@ -692,7 +692,7 @@ static inline double min_distance_of_segments(const Vec2d &p1a, const Vec2d &p1b
|
|||
// p2a == p2b: Return distance of p2a from the (p1a, p1b) segment.
|
||||
return segment_point_distance_squared(p1a, p1b, v1, l1_2, p2a);
|
||||
|
||||
return std::min(
|
||||
return std::min(
|
||||
std::min(segment_point_distance_squared(p1a, p1b, v1, l1_2, p2a), segment_point_distance_squared(p1a, p1b, v1, l1_2, p2b)),
|
||||
std::min(segment_point_distance_squared(p2a, p2b, v2, l2_2, p1a), segment_point_distance_squared(p2a, p2b, v2, l2_2, p1b)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ void FillGyroid::_fill_surface_single(
|
|||
Polylines &polylines_out)
|
||||
{
|
||||
float infill_angle = this->angle + (CorrectionAngle * 2*M_PI) / 360.;
|
||||
if(abs(infill_angle) >= EPSILON)
|
||||
if(std::abs(infill_angle) >= EPSILON)
|
||||
expolygon.rotate(-infill_angle);
|
||||
|
||||
BoundingBox bb = expolygon.contour.bounding_box();
|
||||
|
|
@ -197,8 +197,9 @@ void FillGyroid::_fill_surface_single(
|
|||
append(polylines_out, std::move(polylines));
|
||||
else
|
||||
this->connect_infill(std::move(polylines), expolygon, polylines_out, this->spacing, params);
|
||||
|
||||
// new paths must be rotated back
|
||||
if (abs(infill_angle) >= EPSILON) {
|
||||
if (std::abs(infill_angle) >= EPSILON) {
|
||||
for (auto it = polylines_out.begin() + polylines_out_first_idx; it != polylines_out.end(); ++ it)
|
||||
it->rotate(infill_angle);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
#include "../Utils.hpp"
|
||||
#include "../GCode.hpp"
|
||||
#include "../Geometry.hpp"
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#include "../GCode/ThumbnailData.hpp"
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#include "../I18N.hpp"
|
||||
|
||||
|
|
@ -47,9 +45,7 @@ const std::string MODEL_EXTENSION = ".model";
|
|||
const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA
|
||||
const std::string CONTENT_TYPES_FILE = "[Content_Types].xml";
|
||||
const std::string RELATIONSHIPS_FILE = "_rels/.rels";
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
const std::string THUMBNAIL_FILE = "Metadata/thumbnail.png";
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config";
|
||||
const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config";
|
||||
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
||||
|
|
@ -1722,7 +1718,7 @@ namespace Slic3r {
|
|||
}
|
||||
|
||||
// Added because of github #3435, currently not used by PrusaSlicer
|
||||
int instances_count_id = get_attribute_value_int(attributes, num_attributes, INSTANCESCOUNT_ATTR);
|
||||
// int instances_count_id = get_attribute_value_int(attributes, num_attributes, INSTANCESCOUNT_ATTR);
|
||||
|
||||
m_objects_metadata.insert(IdToMetadataMap::value_type(object_id, ObjectMetadata()));
|
||||
m_curr_config.object_id = object_id;
|
||||
|
|
@ -1969,22 +1965,12 @@ namespace Slic3r {
|
|||
bool m_fullpath_sources{ true };
|
||||
|
||||
public:
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data = nullptr);
|
||||
#else
|
||||
bool save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
private:
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data);
|
||||
#else
|
||||
bool _save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
|
||||
bool _add_model_file_to_archive(mz_zip_archive& archive, const Model& model, IdToObjectDataMap &objects_data);
|
||||
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
|
||||
|
|
@ -1999,26 +1985,14 @@ namespace Slic3r {
|
|||
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
};
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data)
|
||||
{
|
||||
clear_errors();
|
||||
m_fullpath_sources = fullpath_sources;
|
||||
return _save_model_to_file(filename, model, config, thumbnail_data);
|
||||
}
|
||||
#else
|
||||
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources)
|
||||
{
|
||||
clear_errors();
|
||||
return _save_model_to_file(filename, model, config);
|
||||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, const ThumbnailData* thumbnail_data)
|
||||
#else
|
||||
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
|
@ -2037,7 +2011,6 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
if ((thumbnail_data != nullptr) && thumbnail_data->is_valid())
|
||||
{
|
||||
// Adds the file Metadata/thumbnail.png.
|
||||
|
|
@ -2048,7 +2021,6 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
// Adds relationships file ("_rels/.rels").
|
||||
// The content of this file is the same for each PrusaSlicer 3mf.
|
||||
|
|
@ -2160,9 +2132,7 @@ namespace Slic3r {
|
|||
stream << "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n";
|
||||
stream << " <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" />\n";
|
||||
stream << " <Default Extension=\"model\" ContentType=\"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />\n";
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
stream << " <Default Extension=\"png\" ContentType=\"image/png\" />\n";
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
stream << "</Types>";
|
||||
|
||||
std::string out = stream.str();
|
||||
|
|
@ -2176,7 +2146,6 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool _3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data)
|
||||
{
|
||||
bool res = false;
|
||||
|
|
@ -2194,7 +2163,6 @@ namespace Slic3r {
|
|||
|
||||
return res;
|
||||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
bool _3MF_Exporter::_add_relationships_file_to_archive(mz_zip_archive& archive)
|
||||
{
|
||||
|
|
@ -2202,9 +2170,7 @@ namespace Slic3r {
|
|||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n";
|
||||
stream << " <Relationship Target=\"/" << MODEL_FILE << "\" Id=\"rel-1\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\" />\n";
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
stream << " <Relationship Target=\"/" << THUMBNAIL_FILE << "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\" />\n";
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
stream << "</Relationships>";
|
||||
|
||||
std::string out = stream.str();
|
||||
|
|
@ -2795,22 +2761,13 @@ bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool c
|
|||
return res;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data)
|
||||
#else
|
||||
bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
if ((path == nullptr) || (model == nullptr))
|
||||
return false;
|
||||
|
||||
_3MF_Exporter exporter;
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
bool res = exporter.save_model_to_file(path, *model, config, fullpath_sources, thumbnail_data);
|
||||
#else
|
||||
bool res = exporter.save_model_to_file(path, *model, config, fullpath_sources);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
if (!res)
|
||||
exporter.log_errors();
|
||||
|
||||
|
|
|
|||
|
|
@ -26,20 +26,14 @@ namespace Slic3r {
|
|||
|
||||
class Model;
|
||||
class DynamicPrintConfig;
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
struct ThumbnailData;
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
// Load the content of a 3mf file into the given model and preset bundle.
|
||||
extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model, bool check_version);
|
||||
|
||||
// Save the given model and the config data contained in the given Print into a 3mf file.
|
||||
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data = nullptr);
|
||||
#else
|
||||
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
|
@ -291,7 +289,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||
|
||||
std::string gcode;
|
||||
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines)
|
||||
// We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
|
||||
float alpha = m_wipe_tower_rotation/180.f * float(M_PI);
|
||||
Vec2f start_pos = tcr.start_pos;
|
||||
|
|
@ -431,7 +429,6 @@ std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower:
|
|||
Vec2f pos = tcr.start_pos;
|
||||
Vec2f transformed_pos = pos;
|
||||
Vec2f old_pos(-1000.1f, -1000.1f);
|
||||
std::string never_skip_tag = WipeTower::never_skip_tag();
|
||||
|
||||
while (gcode_str) {
|
||||
std::getline(gcode_str, line); // we read the gcode line by line
|
||||
|
|
@ -441,11 +438,11 @@ std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower:
|
|||
// WT generator can override this by appending the never_skip_tag
|
||||
if (line.find("G1 ") == 0) {
|
||||
bool never_skip = false;
|
||||
auto it = line.find(never_skip_tag);
|
||||
auto it = line.find(WipeTower::never_skip_tag());
|
||||
if (it != std::string::npos) {
|
||||
// remove the tag and remember we saw it
|
||||
never_skip = true;
|
||||
line.erase(it, it+never_skip_tag.size());
|
||||
line.erase(it, it+WipeTower::never_skip_tag().size());
|
||||
}
|
||||
std::ostringstream line_out;
|
||||
std::istringstream line_str(line);
|
||||
|
|
@ -701,11 +698,7 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
|||
return layers_to_print;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#else
|
||||
void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_data)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
PROFILE_CLEAR();
|
||||
|
||||
|
|
@ -731,11 +724,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
|||
|
||||
try {
|
||||
m_placeholder_parser_failed_templates.clear();
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
this->_do_export(*print, file, thumbnail_cb);
|
||||
#else
|
||||
this->_do_export(*print, file);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
fflush(file);
|
||||
if (ferror(file)) {
|
||||
fclose(file);
|
||||
|
|
@ -975,7 +964,6 @@ namespace DoExport {
|
|||
}
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
template<typename WriteToOutput, typename ThrowIfCanceledCallback>
|
||||
static void export_thumbnails_to_file(ThumbnailsGeneratorCallback &thumbnail_cb, const std::vector<Vec2d> &sizes, WriteToOutput output, ThrowIfCanceledCallback throw_if_canceled)
|
||||
{
|
||||
|
|
@ -1019,7 +1007,6 @@ namespace DoExport {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
// Fill in print_statistics and return formatted string containing filament statistics to be inserted into G-code comment section.
|
||||
static std::string update_print_stats_and_format_filament_stats(
|
||||
|
|
@ -1125,11 +1112,7 @@ std::vector<const PrintInstance*> sort_object_instances_by_model_order(const Pri
|
|||
return instances;
|
||||
}
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#else
|
||||
void GCode::_do_export(Print& print, FILE* file)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
PROFILE_FUNC();
|
||||
|
||||
|
|
@ -1752,7 +1735,6 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
|||
std::sort(sorted.begin(), sorted.end());
|
||||
|
||||
if (! sorted.empty()) {
|
||||
const Print &print = *sorted.front().first->print();
|
||||
out.reserve(sorted.size());
|
||||
for (const PrintInstance *instance : *ordering) {
|
||||
const PrintObject &print_object = *instance->print_object;
|
||||
|
|
@ -1798,13 +1780,14 @@ namespace ProcessLayer
|
|||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||
if (color_change || tool_change)
|
||||
{
|
||||
assert(m600_extruder_before_layer >= 0);
|
||||
// Color Change or Tool Change as Color Change.
|
||||
// add tag for analyzer
|
||||
gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
|
||||
// add tag for time estimator
|
||||
gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n";
|
||||
|
||||
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != m600_extruder_before_layer
|
||||
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
|
||||
// && !MMU1
|
||||
) {
|
||||
//! FIXME_in_fw show message during print pause
|
||||
|
|
@ -2880,11 +2863,12 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
|
|||
std::string GCode::extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid)
|
||||
{
|
||||
std::string gcode;
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
for (const ExtrusionEntity *ee : region.perimeters)
|
||||
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
|
||||
}
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||
if (! region.perimeters.empty()) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
for (const ExtrusionEntity *ee : region.perimeters)
|
||||
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
|
@ -2892,19 +2876,20 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
|
|||
std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region)
|
||||
{
|
||||
std::string gcode;
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
ExtrusionEntitiesPtr extrusions { region.infills };
|
||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||
for (const ExtrusionEntity *fill : extrusions) {
|
||||
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
||||
if (eec) {
|
||||
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
||||
gcode += this->extrude_entity(*ee, "infill");
|
||||
} else
|
||||
gcode += this->extrude_entity(*fill, "infill");
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||
if (! region.infills.empty()) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
ExtrusionEntitiesPtr extrusions { region.infills };
|
||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||
for (const ExtrusionEntity *fill : extrusions) {
|
||||
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
||||
if (eec) {
|
||||
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
||||
gcode += this->extrude_entity(*ee, "infill");
|
||||
} else
|
||||
gcode += this->extrude_entity(*fill, "infill");
|
||||
}
|
||||
}
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
|
@ -3370,17 +3355,18 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
|||
has_overrides = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Data is cleared, but the memory is not.
|
||||
by_region_per_copy_cache.clear();
|
||||
|
||||
if (! has_overrides)
|
||||
// Simple case. No need to copy the regions.
|
||||
return this->by_region;
|
||||
return wiping_entities ? by_region_per_copy_cache : this->by_region;
|
||||
|
||||
// Complex case. Some of the extrusions of some object instances are to be printed first - those are the wiping extrusions.
|
||||
// Some of the extrusions of some object instances are printed later - those are the clean print extrusions.
|
||||
// Filter out the extrusions based on the infill_overrides / perimeter_overrides:
|
||||
|
||||
// Data is cleared, but the memory is not.
|
||||
by_region_per_copy_cache.clear();
|
||||
|
||||
for (const auto& reg : by_region) {
|
||||
by_region_per_copy_cache.emplace_back(); // creates a region in the newly created Island
|
||||
|
||||
|
|
@ -3441,15 +3427,17 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
|
|||
|
||||
// First we append the entities, there are eec->entities.size() of them:
|
||||
size_t old_size = perimeters_or_infills->size();
|
||||
perimeters_or_infills->reserve(perimeters_or_infills->size() + eec->entities.size());
|
||||
size_t new_size = old_size + eec->entities.size();
|
||||
perimeters_or_infills->reserve(new_size);
|
||||
for (auto* ee : eec->entities)
|
||||
perimeters_or_infills->emplace_back(ee);
|
||||
|
||||
if (copies_extruder != nullptr) {
|
||||
perimeters_or_infills_overrides->reserve(old_size + eec->entities.size());
|
||||
perimeters_or_infills_overrides->resize(old_size, nullptr);
|
||||
for (unsigned int i = 0; i < eec->entities.size(); ++ i)
|
||||
perimeters_or_infills_overrides->emplace_back(copies_extruder);
|
||||
// Don't reallocate overrides if not needed.
|
||||
// Missing overrides are implicitely considered non-overridden.
|
||||
perimeters_or_infills_overrides->reserve(new_size);
|
||||
perimeters_or_infills_overrides->resize(old_size, nullptr);
|
||||
perimeters_or_infills_overrides->resize(new_size, copies_extruder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@
|
|||
#include "GCodeTimeEstimator.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
#include "GCode/Analyzer.hpp"
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
@ -166,11 +164,7 @@ public:
|
|||
|
||||
// throws std::runtime_exception on error,
|
||||
// throws CanceledException through print->throw_if_canceled().
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
void do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#else
|
||||
void do_export(Print *print, const char *path, GCodePreviewData *preview_data = nullptr);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
// Exported for the helper classes (OozePrevention, Wipe) and for the Perl binding for unit tests.
|
||||
const Vec2d& origin() const { return m_origin; }
|
||||
|
|
@ -210,11 +204,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
void _do_export(Print &print, FILE *file, ThumbnailsGeneratorCallback thumbnail_cb);
|
||||
#else
|
||||
void _do_export(Print &print, FILE *file);
|
||||
#endif //ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
static std::vector<LayerToPrint> collect_layers_to_print(const PrintObject &object);
|
||||
static std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> collect_layers_to_print(const Print &print);
|
||||
|
|
|
|||
|
|
@ -444,8 +444,10 @@ void GCodeAnalyzer::_processG92(const GCodeReader::GCodeLine& line)
|
|||
anyFound = true;
|
||||
}
|
||||
|
||||
if (!anyFound)
|
||||
if (!anyFound && ! line.has_unknown_axis())
|
||||
{
|
||||
// The G92 may be called for axes that PrusaSlicer does not recognize, for example see GH issue #3510,
|
||||
// where G92 A0 B0 is called although the extruder axis is till E.
|
||||
for (unsigned char a = X; a < Num_Axis; ++a)
|
||||
{
|
||||
_set_axis_origin((EAxis)a, _get_axis_position((EAxis)a));
|
||||
|
|
@ -470,7 +472,7 @@ void GCodeAnalyzer::_processM106(const GCodeReader::GCodeLine& line)
|
|||
// The absence of P means the print cooling fan, so ignore anything else.
|
||||
float new_fan_speed;
|
||||
if (line.has_value('S', new_fan_speed))
|
||||
_set_fan_speed((100.0f / 256.0f) * new_fan_speed);
|
||||
_set_fan_speed((100.0f / 255.0f) * new_fan_speed);
|
||||
else
|
||||
_set_fan_speed(100.0f);
|
||||
}
|
||||
|
|
@ -644,7 +646,7 @@ bool GCodeAnalyzer::_process_tags(const GCodeReader::GCodeLine& line)
|
|||
if (pos != comment.npos)
|
||||
{
|
||||
pos = comment.find_last_of(",T");
|
||||
int extruder = pos == comment.npos ? 0 : std::atoi(comment.substr(pos + 1, comment.npos).c_str());
|
||||
unsigned extruder = pos == comment.npos ? 0 : std::stoi(comment.substr(pos + 1, comment.npos));
|
||||
_process_color_change_tag(extruder);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -702,7 +704,7 @@ void GCodeAnalyzer::_process_height_tag(const std::string& comment, size_t pos)
|
|||
_set_height((float)::strtod(comment.substr(pos + Height_Tag.length()).c_str(), nullptr));
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_process_color_change_tag(int extruder)
|
||||
void GCodeAnalyzer::_process_color_change_tag(unsigned extruder)
|
||||
{
|
||||
m_extruder_color[extruder] = m_extruders_count + m_state.cp_color_counter; // color_change position in list of color for preview
|
||||
m_state.cp_color_counter++;
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ private:
|
|||
void _process_height_tag(const std::string& comment, size_t pos);
|
||||
|
||||
// Processes color change tag
|
||||
void _process_color_change_tag(int extruder);
|
||||
void _process_color_change_tag(unsigned extruder);
|
||||
|
||||
// Processes pause print and custom gcode tag
|
||||
void _process_pause_print_or_custom_code_tag();
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ Color GCodePreviewData::RangeBase::get_color_at(float value) const
|
|||
{
|
||||
// Input value scaled to the color range
|
||||
float step = step_size();
|
||||
const float global_t = (step != 0.0f) ? std::max(0.0f, value - min()) / step_size() : 0.0f; // lower limit of 0.0f
|
||||
const float global_t = (step != 0.0f) ? std::max(0.0f, value - min()) / step : 0.0f; // lower limit of 0.0f
|
||||
|
||||
constexpr std::size_t color_max_idx = range_rainbow_colors.size() - 1;
|
||||
|
||||
|
|
@ -241,6 +241,7 @@ void GCodePreviewData::reset()
|
|||
ranges.width.reset();
|
||||
ranges.height.reset();
|
||||
ranges.feedrate.reset();
|
||||
ranges.fan_speed.reset();
|
||||
ranges.volumetric_rate.reset();
|
||||
extrusion.layers.clear();
|
||||
travel.polylines.clear();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#include "ThumbnailData.hpp"
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void ThumbnailData::set(unsigned int w, unsigned int h)
|
||||
|
|
@ -32,5 +30,3 @@ bool ThumbnailData::is_valid() const
|
|||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef slic3r_ThumbnailData_hpp_
|
||||
#define slic3r_ThumbnailData_hpp_
|
||||
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#include <vector>
|
||||
#include "libslic3r/Point.hpp"
|
||||
|
||||
|
|
@ -26,6 +24,4 @@ typedef std::function<void(ThumbnailsList & thumbnails, const Vec2ds & sizes, bo
|
|||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#endif // slic3r_ThumbnailData_hpp_
|
||||
|
|
@ -64,7 +64,7 @@ private:
|
|||
std::map<const ExtrusionEntity*, ExtruderPerCopy> entity_map; // to keep track of who prints what
|
||||
bool something_overridable = false;
|
||||
bool something_overridden = false;
|
||||
const LayerTools* m_layer_tools; // so we know which LayerTools object this belongs to
|
||||
const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -492,6 +492,9 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
|
|||
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
|
||||
m_bed_shape = (bed_points.size() == 4 ? RectangularBed : CircularBed);
|
||||
m_bed_width = float(BoundingBoxf(bed_points).size().x());
|
||||
m_bed_bottom_left = m_bed_shape == RectangularBed
|
||||
? Vec2f(bed_points.front().x(), bed_points.front().y())
|
||||
: Vec2f::Zero();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -566,6 +569,8 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
|||
// In case of a circular bed, place it so it goes across the diameter and hope it will fit
|
||||
if (m_bed_shape == CircularBed)
|
||||
cleaning_box.translate(-m_bed_width/2 + m_bed_width * 0.03f, -m_bed_width * 0.12f);
|
||||
if (m_bed_shape == RectangularBed)
|
||||
cleaning_box.translate(m_bed_bottom_left);
|
||||
|
||||
std::vector<ToolChangeResult> results;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ enum GCodeFlavor : unsigned char;
|
|||
class WipeTower
|
||||
{
|
||||
public:
|
||||
static char const* never_skip_tag() { return "_GCODE_WIPE_TOWER_NEVER_SKIP_TAG"; }
|
||||
static const std::string never_skip_tag() { return "_GCODE_WIPE_TOWER_NEVER_SKIP_TAG"; }
|
||||
|
||||
struct Extrusion
|
||||
{
|
||||
|
|
@ -189,8 +189,6 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
WipeTower();
|
||||
|
||||
enum wipe_shape // A fill-in direction
|
||||
{
|
||||
SHAPE_NORMAL = 1,
|
||||
|
|
@ -236,6 +234,7 @@ private:
|
|||
CircularBed
|
||||
} m_bed_shape;
|
||||
float m_bed_width; // width of the bed bounding box
|
||||
Vec2f m_bed_bottom_left; // bottom-left corner coordinates (for rectangular beds)
|
||||
|
||||
float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill.
|
||||
float m_extrusion_flow = 0.038f; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline,
|
|||
if (is_end_of_gcode_line(*c))
|
||||
break;
|
||||
// Check the name of the axis.
|
||||
Axis axis = NUM_AXES;
|
||||
Axis axis = NUM_AXES_WITH_UNKNOWN;
|
||||
switch (*c) {
|
||||
case 'X': axis = X; break;
|
||||
case 'Y': axis = Y; break;
|
||||
|
|
@ -49,15 +49,19 @@ const char* GCodeReader::parse_line_internal(const char *ptr, GCodeLine &gline,
|
|||
default:
|
||||
if (*c == m_extrusion_axis)
|
||||
axis = E;
|
||||
else if (*c >= 'A' && *c <= 'Z')
|
||||
// Unknown axis, but we still want to remember that such a axis was seen.
|
||||
axis = UNKNOWN_AXIS;
|
||||
break;
|
||||
}
|
||||
if (axis != NUM_AXES) {
|
||||
if (axis != NUM_AXES_WITH_UNKNOWN) {
|
||||
// Try to parse the numeric value.
|
||||
char *pend = nullptr;
|
||||
double v = strtod(++ c, &pend);
|
||||
if (pend != nullptr && is_end_of_word(*pend)) {
|
||||
// The axis value has been parsed correctly.
|
||||
gline.m_axis[int(axis)] = float(v);
|
||||
if (axis != UNKNOWN_AXIS)
|
||||
gline.m_axis[int(axis)] = float(v);
|
||||
gline.m_mask |= 1 << int(axis);
|
||||
c = pend;
|
||||
} else
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public:
|
|||
bool has_z() const { return this->has(Z); }
|
||||
bool has_e() const { return this->has(E); }
|
||||
bool has_f() const { return this->has(F); }
|
||||
bool has_unknown_axis() const { return this->has(UNKNOWN_AXIS); }
|
||||
float x() const { return m_axis[X]; }
|
||||
float y() const { return m_axis[Y]; }
|
||||
float z() const { return m_axis[Z]; }
|
||||
|
|
|
|||
|
|
@ -112,72 +112,82 @@ void Layer::make_perimeters()
|
|||
// keep track of regions whose perimeters we have already generated
|
||||
std::vector<unsigned char> done(m_regions.size(), false);
|
||||
|
||||
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) {
|
||||
size_t region_id = layerm - m_regions.begin();
|
||||
if (done[region_id])
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||
done[region_id] = true;
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||
|
||||
// find compatible regions
|
||||
LayerRegionPtrs layerms;
|
||||
layerms.push_back(*layerm);
|
||||
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) {
|
||||
LayerRegion* other_layerm = *it;
|
||||
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||
&& config.perimeters == other_config.perimeters
|
||||
&& config.perimeter_speed == other_config.perimeter_speed
|
||||
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
||||
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||
&& config.overhangs == other_config.overhangs
|
||||
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
|
||||
&& config.thin_walls == other_config.thin_walls
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||
&& config.infill_overlap == other_config.infill_overlap) {
|
||||
layerms.push_back(other_layerm);
|
||||
done[it - m_regions.begin()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (layerms.size() == 1) { // optimization
|
||||
(*layerm)->fill_surfaces.surfaces.clear();
|
||||
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
|
||||
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
|
||||
} else {
|
||||
SurfaceCollection new_slices;
|
||||
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
|
||||
LayerRegion *layerm_config = layerms.front();
|
||||
{
|
||||
// group slices (surfaces) according to number of extra perimeters
|
||||
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegion *layerm : layerms) {
|
||||
for (Surface &surface : layerm->slices.surfaces)
|
||||
slices[surface.extra_perimeters].emplace_back(surface);
|
||||
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
|
||||
layerm_config = layerm;
|
||||
}
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||
}
|
||||
|
||||
// make perimeters
|
||||
SurfaceCollection fill_surfaces;
|
||||
layerm_config->make_perimeters(new_slices, &fill_surfaces);
|
||||
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm)
|
||||
if ((*layerm)->slices.empty()) {
|
||||
(*layerm)->perimeters.clear();
|
||||
(*layerm)->fills.clear();
|
||||
(*layerm)->thin_fills.clear();
|
||||
} else {
|
||||
size_t region_id = layerm - m_regions.begin();
|
||||
if (done[region_id])
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||
done[region_id] = true;
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||
|
||||
// find compatible regions
|
||||
LayerRegionPtrs layerms;
|
||||
layerms.push_back(*layerm);
|
||||
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it)
|
||||
if (! (*it)->slices.empty()) {
|
||||
LayerRegion* other_layerm = *it;
|
||||
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||
&& config.perimeters == other_config.perimeters
|
||||
&& config.perimeter_speed == other_config.perimeter_speed
|
||||
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
||||
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||
&& config.overhangs == other_config.overhangs
|
||||
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
|
||||
&& config.thin_walls == other_config.thin_walls
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||
&& config.infill_overlap == other_config.infill_overlap)
|
||||
{
|
||||
other_layerm->perimeters.clear();
|
||||
other_layerm->fills.clear();
|
||||
other_layerm->thin_fills.clear();
|
||||
layerms.push_back(other_layerm);
|
||||
done[it - m_regions.begin()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (layerms.size() == 1) { // optimization
|
||||
(*layerm)->fill_surfaces.surfaces.clear();
|
||||
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
|
||||
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
|
||||
} else {
|
||||
SurfaceCollection new_slices;
|
||||
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
|
||||
LayerRegion *layerm_config = layerms.front();
|
||||
{
|
||||
// group slices (surfaces) according to number of extra perimeters
|
||||
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegion *layerm : layerms) {
|
||||
for (Surface &surface : layerm->slices.surfaces)
|
||||
slices[surface.extra_perimeters].emplace_back(surface);
|
||||
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
|
||||
layerm_config = layerm;
|
||||
}
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||
}
|
||||
|
||||
// make perimeters
|
||||
SurfaceCollection fill_surfaces;
|
||||
layerm_config->make_perimeters(new_slices, &fill_surfaces);
|
||||
|
||||
// assign fill_surfaces to each layer
|
||||
if (!fill_surfaces.surfaces.empty()) {
|
||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||
// Separate the fill surfaces.
|
||||
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
|
||||
(*l)->fill_expolygons = expp;
|
||||
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// assign fill_surfaces to each layer
|
||||
if (!fill_surfaces.surfaces.empty()) {
|
||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||
// Separate the fill surfaces.
|
||||
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
|
||||
(*l)->fill_expolygons = expp;
|
||||
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||
// Voids are sparse infills if infill rate is zero.
|
||||
Polygons voids;
|
||||
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
||||
if (surface.surface_type == stTop) {
|
||||
if (surface.is_top()) {
|
||||
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
||||
// This gives the priority to bottom surfaces.
|
||||
surfaces_append(top, offset_ex(surface.expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
|
||||
|
|
@ -313,7 +313,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||
s2.clear();
|
||||
}
|
||||
}
|
||||
if (s1.surface_type == stTop)
|
||||
if (s1.is_top())
|
||||
// Trim the top surfaces by the bottom surfaces. This gives the priority to the bottom surfaces.
|
||||
polys = diff(polys, bottom_polygons);
|
||||
surfaces_append(
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||
} else if (
|
||||
opt_key == "skirts"
|
||||
|| opt_key == "skirt_height"
|
||||
|| opt_key == "draft_shield"
|
||||
|| opt_key == "skirt_distance"
|
||||
|| opt_key == "min_skirt_length"
|
||||
|| opt_key == "ooze_prevention"
|
||||
|
|
@ -1146,14 +1147,12 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||
|
||||
bool Print::has_infinite_skirt() const
|
||||
{
|
||||
return (m_config.skirt_height == -1 && m_config.skirts > 0)
|
||||
|| (m_config.ooze_prevention && this->extruders().size() > 1);
|
||||
return (m_config.draft_shield && m_config.skirts > 0) || (m_config.ooze_prevention && this->extruders().size() > 1);
|
||||
}
|
||||
|
||||
bool Print::has_skirt() const
|
||||
{
|
||||
return (m_config.skirt_height > 0 && m_config.skirts > 0)
|
||||
|| this->has_infinite_skirt();
|
||||
return (m_config.skirt_height > 0 && m_config.skirts > 0) || this->has_infinite_skirt();
|
||||
}
|
||||
|
||||
static inline bool sequential_print_horizontal_clearance_valid(const Print &print)
|
||||
|
|
@ -1623,11 +1622,7 @@ void Print::process()
|
|||
// The export_gcode may die for various reasons (fails to process output_filename_format,
|
||||
// write error into the G-code, cannot execute post-processing scripts).
|
||||
// It is up to the caller to show an error message.
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
|
||||
#else
|
||||
std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data)
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
{
|
||||
// output everything to a G-code file
|
||||
// The following call may die if the output_filename_format template substitution fails.
|
||||
|
|
@ -1644,11 +1639,7 @@ std::string Print::export_gcode(const std::string &path_template, GCodePreviewDa
|
|||
|
||||
// The following line may die for multiple reasons.
|
||||
GCode gcode;
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
gcode.do_export(this, path.c_str(), preview_data, thumbnail_cb);
|
||||
#else
|
||||
gcode.do_export(this, path.c_str(), preview_data);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
|
|
@ -1936,7 +1927,7 @@ void Print::_make_brim()
|
|||
// Find all pieces that the initial loop was split into.
|
||||
size_t j = i + 1;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
|
||||
auto *loop = new ExtrusionLoop();
|
||||
m_brim.entities.emplace_back(loop);
|
||||
|
|
@ -2138,6 +2129,7 @@ std::string Print::output_filename(const std::string &filename_base) const
|
|||
// Set the placeholders for the data know first after the G-code export is finished.
|
||||
// These values will be just propagated into the output file name.
|
||||
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
|
||||
config.set_key_value("num_extruders", new ConfigOptionInt((int)m_config.nozzle_diameter.size()));
|
||||
return this->PrintBase::output_filename(m_config.output_filename_format.value, ".gcode", filename_base, &config);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@
|
|||
#include "Slicing.hpp"
|
||||
#include "GCode/ToolOrdering.hpp"
|
||||
#include "GCode/WipeTower.hpp"
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
#include "GCode/ThumbnailData.hpp"
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
#include "libslic3r.h"
|
||||
|
||||
|
|
@ -364,11 +362,7 @@ public:
|
|||
void process() override;
|
||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
||||
#if ENABLE_THUMBNAIL_GENERATOR
|
||||
std::string export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
|
||||
#else
|
||||
std::string export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||
#endif // ENABLE_THUMBNAIL_GENERATOR
|
||||
|
||||
// methods for handling state
|
||||
bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ void PrintConfigDef::init_fff_params()
|
|||
"to clip the overlapping object parts one by the other "
|
||||
"(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("colorprint_heights", coFloats);
|
||||
def->label = L("Colorprint height");
|
||||
|
|
@ -1691,6 +1691,13 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
def = this->add("draft_shield", coBool);
|
||||
def->label = L("Draft shield");
|
||||
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. "
|
||||
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("skirts", coInt);
|
||||
def->label = L("Loops (minimum)");
|
||||
def->full_label = L("Skirt Loops");
|
||||
|
|
@ -2998,6 +3005,11 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
} else if (opt_key == "support_material_pattern" && value == "pillars") {
|
||||
// Slic3r PE does not support the pillars. They never worked well.
|
||||
value = "rectilinear";
|
||||
} else if (opt_key == "skirt_height" && value == "-1") {
|
||||
// PrusaSlicer no more accepts skirt_height == -1 to print a draft shield to the top of the highest object.
|
||||
// A new "draft_shield" boolean config value is used instead.
|
||||
opt_key = "draft_shield";
|
||||
value = "1";
|
||||
} else if (opt_key == "octoprint_host") {
|
||||
opt_key = "print_host";
|
||||
} else if (opt_key == "octoprint_cafile") {
|
||||
|
|
@ -3206,7 +3218,7 @@ std::string FullPrintConfig::validate()
|
|||
return "Invalid value for --infill-every-layers";
|
||||
|
||||
// --skirt-height
|
||||
if (this->skirt_height < -1) // -1 means as tall as the object
|
||||
if (this->skirt_height < 0)
|
||||
return "Invalid value for --skirt-height";
|
||||
|
||||
// --bridge-flow-ratio
|
||||
|
|
|
|||
|
|
@ -800,6 +800,7 @@ public:
|
|||
ConfigOptionBools retract_layer_change;
|
||||
ConfigOptionFloat skirt_distance;
|
||||
ConfigOptionInt skirt_height;
|
||||
ConfigOptionBool draft_shield;
|
||||
ConfigOptionInt skirts;
|
||||
ConfigOptionInts slowdown_below_layer_time;
|
||||
ConfigOptionBool spiral_vase;
|
||||
|
|
@ -872,6 +873,7 @@ protected:
|
|||
OPT_PTR(retract_layer_change);
|
||||
OPT_PTR(skirt_distance);
|
||||
OPT_PTR(skirt_height);
|
||||
OPT_PTR(draft_shield);
|
||||
OPT_PTR(skirts);
|
||||
OPT_PTR(slowdown_below_layer_time);
|
||||
OPT_PTR(spiral_vase);
|
||||
|
|
|
|||
|
|
@ -817,11 +817,12 @@ void PrintObject::detect_surfaces_type()
|
|||
m_layers[idx_layer]->m_regions[idx_region]->slices.surfaces = std::move(surfaces_new[idx_layer]);
|
||||
}
|
||||
|
||||
if (spiral_vase && num_layers > 1) {
|
||||
// Turn the last bottom layer infill to a top infill, so it will be extruded with a proper pattern.
|
||||
Surfaces &surfaces = m_layers[num_layers - 1]->m_regions[idx_region]->slices.surfaces;
|
||||
for (Surface &surface : surfaces)
|
||||
surface.surface_type = stTop;
|
||||
if (spiral_vase) {
|
||||
if (num_layers > 1)
|
||||
// Turn the last bottom layer infill to a top infill, so it will be extruded with a proper pattern.
|
||||
m_layers[num_layers - 1]->m_regions[idx_region]->slices.set_type(stTop);
|
||||
for (size_t i = num_layers; i < m_layers.size(); ++ i)
|
||||
m_layers[i]->m_regions[idx_region]->slices.set_type(stInternal);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - start";
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ public:
|
|||
|
||||
// Iterates over hits and holes and returns the true hit, possibly
|
||||
// on the inside of a hole.
|
||||
// This function is currently not used anywhere, it was written when the
|
||||
// holes were subtracted on slices, that is, before we started using CGAL
|
||||
// to actually cut the holes into the mesh.
|
||||
hit_result filter_hits(const std::vector<EigenMesh3D::hit_result>& obj_hits) const;
|
||||
|
||||
class si_result {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ public:
|
|||
void remove_type(const SurfaceType type);
|
||||
void remove_types(const SurfaceType *types, int ntypes);
|
||||
void filter_by_type(SurfaceType type, Polygons* polygons);
|
||||
void set_type(SurfaceType type) {
|
||||
for (Surface &surface : this->surfaces)
|
||||
surface.surface_type = type;
|
||||
}
|
||||
|
||||
void clear() { surfaces.clear(); }
|
||||
bool empty() const { return surfaces.empty(); }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _technologies_h_
|
||||
#define _technologies_h_
|
||||
#ifndef _prusaslicer_technologies_h_
|
||||
#define _prusaslicer_technologies_h_
|
||||
|
||||
//============
|
||||
// debug techs
|
||||
|
|
@ -17,37 +17,20 @@
|
|||
#define ENABLE_CAMERA_STATISTICS 0
|
||||
// Render the picking pass instead of the main scene (use [T] key to toggle between regular rendering and picking pass only rendering)
|
||||
#define ENABLE_RENDER_PICKING_PASS 0
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha1 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA1 1
|
||||
|
||||
// Enable extracting thumbnails from selected gcode and save them as png files
|
||||
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG 0
|
||||
// Disable synchronization of unselected instances
|
||||
#define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1)
|
||||
#define DISABLE_INSTANCES_SYNCH 0
|
||||
// Use wxDataViewRender instead of wxDataViewCustomRenderer
|
||||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
||||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING 0
|
||||
|
||||
|
||||
//====================
|
||||
// 2.2.0.alpha1 techs
|
||||
//====================
|
||||
#define ENABLE_2_2_0_ALPHA1 1
|
||||
|
||||
// Enable thumbnail generator
|
||||
// When removing this technology, remove it also from stable branch,
|
||||
// where it has been partially copied for patch 2.1.1
|
||||
#define ENABLE_THUMBNAIL_GENERATOR (1 && ENABLE_2_2_0_ALPHA1)
|
||||
#define ENABLE_THUMBNAIL_GENERATOR_DEBUG (0 && ENABLE_THUMBNAIL_GENERATOR)
|
||||
|
||||
|
||||
//==================
|
||||
//================
|
||||
// 2.2.0.rc1 techs
|
||||
//==================
|
||||
//================
|
||||
#define ENABLE_2_2_0_RC1 1
|
||||
|
||||
// Enable hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets
|
||||
// Enable hack to remove crash when closing on OSX 10.9.5
|
||||
#define ENABLE_HACK_CLOSING_ON_OSX_10_9_5 (1 && ENABLE_2_2_0_RC1)
|
||||
|
||||
|
||||
|
|
@ -56,8 +39,19 @@
|
|||
//==================
|
||||
#define ENABLE_2_2_0_FINAL 1
|
||||
|
||||
// Enable tooltips for GLCanvas3D using ImGUI
|
||||
#define ENABLE_CANVAS_TOOLTIP_USING_IMGUI (1 && ENABLE_2_2_0_FINAL)
|
||||
// Enable fix for dragging mouse event handling for gizmobar
|
||||
#define ENABLE_GIZMO_TOOLBAR_DRAGGING_FIX (1 && ENABLE_2_2_0_FINAL)
|
||||
|
||||
|
||||
//===================
|
||||
// 2.3.0.alpha1 techs
|
||||
//===================
|
||||
#define ENABLE_2_3_0_ALPHA1 1
|
||||
|
||||
// Moves GLCanvas3DManager from being a static member of _3DScene to be a normal member of GUI_App
|
||||
#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_2_0_FINAL)
|
||||
#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_3_0_ALPHA1)
|
||||
|
||||
|
||||
#endif // _technologies_h_
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
|
|
|||
|
|
@ -98,7 +98,17 @@ extern Semver SEMVER;
|
|||
template<typename T, typename Q>
|
||||
inline T unscale(Q v) { return T(v) * T(SCALING_FACTOR); }
|
||||
|
||||
enum Axis { X=0, Y, Z, E, F, NUM_AXES };
|
||||
enum Axis {
|
||||
X=0,
|
||||
Y,
|
||||
Z,
|
||||
E,
|
||||
F,
|
||||
NUM_AXES,
|
||||
// For the GCodeReader to mark a parsed axis, which is not in "XYZEF", it was parsed correctly.
|
||||
UNKNOWN_AXIS = NUM_AXES,
|
||||
NUM_AXES_WITH_UNKNOWN,
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void append_to(std::vector<T> &dst, const std::vector<T> &src)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue