Fixed conflicts after merge with master

This commit is contained in:
enricoturri1966 2020-03-25 14:41:47 +01:00
commit f12b39be25
171 changed files with 23530 additions and 14236 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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.);

View file

@ -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));

View file

@ -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)));
}

View file

@ -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);
}

View file

@ -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();

View file

@ -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

View file

@ -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 &region : by_region) {
m_config.apply(print.regions()[&region - &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 &region : by_region)
if (! region.perimeters.empty()) {
m_config.apply(print.regions()[&region - &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 &region : by_region) {
m_config.apply(print.regions()[&region - &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 &region : by_region)
if (! region.infills.empty()) {
m_config.apply(print.regions()[&region - &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);
}
}

View file

@ -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);

View file

@ -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++;

View file

@ -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();

View file

@ -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();

View file

@ -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

View file

@ -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_

View file

@ -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
};

View file

@ -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;

View file

@ -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.

View file

@ -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

View file

@ -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]; }

View file

@ -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";
}

View file

@ -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(

View file

@ -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);
}

View file

@ -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); }

View file

@ -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

View file

@ -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);

View file

@ -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";

View file

@ -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 {

View file

@ -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(); }

View file

@ -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_

View file

@ -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)