mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 03:16:00 +08:00
Fixed conflicts after merge with master
This commit is contained in:
commit
468f537121
6
deps/wxWidgets/wxWidgets.cmake
vendored
6
deps/wxWidgets/wxWidgets.cmake
vendored
@ -9,6 +9,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(_wx_toolkit "-DwxBUILD_TOOLKIT=gtk${_gtk_ver}")
|
||||
endif()
|
||||
|
||||
set(_unicode_utf8 OFF)
|
||||
if (UNIX) # wxWidgets will not use char as the underlying type for wxString unless its forced to.
|
||||
set (_unicode_utf8 ON)
|
||||
endif()
|
||||
|
||||
prusaslicer_add_cmake_project(wxWidgets
|
||||
# GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets"
|
||||
# GIT_TAG tm_cross_compile #${_wx_git_tag}
|
||||
@ -23,6 +28,7 @@ prusaslicer_add_cmake_project(wxWidgets
|
||||
-DwxUSE_MEDIACTRL=OFF
|
||||
-DwxUSE_DETECT_SM=OFF
|
||||
-DwxUSE_UNICODE=ON
|
||||
-DwxUSE_UNICODE_UTF8=${_unicode_utf8}
|
||||
-DwxUSE_OPENGL=ON
|
||||
-DwxUSE_LIBPNG=sys
|
||||
-DwxUSE_ZLIB=sys
|
||||
|
@ -42,7 +42,6 @@ use Slic3r::ExtrusionLoop;
|
||||
use Slic3r::ExtrusionPath;
|
||||
use Slic3r::Flow;
|
||||
use Slic3r::GCode::Reader;
|
||||
use Slic3r::Geometry::Clipper;
|
||||
use Slic3r::Layer;
|
||||
use Slic3r::Line;
|
||||
use Slic3r::Model;
|
||||
|
@ -4,19 +4,6 @@ use warnings;
|
||||
|
||||
# an ExPolygon is a polygon with holes
|
||||
|
||||
use List::Util qw(first);
|
||||
use Slic3r::Geometry::Clipper qw(union_ex diff_pl);
|
||||
|
||||
sub offset {
|
||||
my $self = shift;
|
||||
return Slic3r::Geometry::Clipper::offset(\@$self, @_);
|
||||
}
|
||||
|
||||
sub offset_ex {
|
||||
my $self = shift;
|
||||
return Slic3r::Geometry::Clipper::offset_ex(\@$self, @_);
|
||||
}
|
||||
|
||||
sub noncollapsing_offset_ex {
|
||||
my $self = shift;
|
||||
my ($distance, @params) = @_;
|
||||
|
@ -14,10 +14,8 @@ our @EXPORT_OK = qw(
|
||||
dot
|
||||
line_intersection
|
||||
normalize
|
||||
point_in_segment
|
||||
polyline_lines
|
||||
polygon_is_convex
|
||||
polygon_segment_having_point
|
||||
scale
|
||||
unscale
|
||||
scaled_epsilon
|
||||
@ -45,30 +43,6 @@ sub scaled_epsilon () { epsilon / &Slic3r::SCALING_FACTOR }
|
||||
sub scale ($) { $_[0] / &Slic3r::SCALING_FACTOR }
|
||||
sub unscale ($) { $_[0] * &Slic3r::SCALING_FACTOR }
|
||||
|
||||
# used by geometry.t, polygon_segment_having_point
|
||||
sub point_in_segment {
|
||||
my ($point, $line) = @_;
|
||||
|
||||
my ($x, $y) = @$point;
|
||||
my $line_p = $line->pp;
|
||||
my @line_x = sort { $a <=> $b } $line_p->[A][X], $line_p->[B][X];
|
||||
my @line_y = sort { $a <=> $b } $line_p->[A][Y], $line_p->[B][Y];
|
||||
|
||||
# check whether the point is in the segment bounding box
|
||||
return 0 unless $x >= ($line_x[0] - epsilon) && $x <= ($line_x[1] + epsilon)
|
||||
&& $y >= ($line_y[0] - epsilon) && $y <= ($line_y[1] + epsilon);
|
||||
|
||||
# if line is vertical, check whether point's X is the same as the line
|
||||
if ($line_p->[A][X] == $line_p->[B][X]) {
|
||||
return abs($x - $line_p->[A][X]) < epsilon ? 1 : 0;
|
||||
}
|
||||
|
||||
# calculate the Y in line at X of the point
|
||||
my $y3 = $line_p->[A][Y] + ($line_p->[B][Y] - $line_p->[A][Y])
|
||||
* ($x - $line_p->[A][X]) / ($line_p->[B][X] - $line_p->[A][X]);
|
||||
return abs($y3 - $y) < epsilon ? 1 : 0;
|
||||
}
|
||||
|
||||
# used by geometry.t
|
||||
sub polyline_lines {
|
||||
my ($polyline) = @_;
|
||||
@ -76,17 +50,6 @@ sub polyline_lines {
|
||||
return map Slic3r::Line->new(@points[$_, $_+1]), 0 .. $#points-1;
|
||||
}
|
||||
|
||||
# given a $polygon, return the (first) segment having $point
|
||||
# used by geometry.t
|
||||
sub polygon_segment_having_point {
|
||||
my ($polygon, $point) = @_;
|
||||
|
||||
foreach my $line (@{ $polygon->lines }) {
|
||||
return $line if point_in_segment($point, $line);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
# polygon must be simple (non complex) and ccw
|
||||
sub polygon_is_convex {
|
||||
my ($points) = @_;
|
||||
|
@ -6,9 +6,8 @@ require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT_OK = qw(
|
||||
offset
|
||||
offset_ex offset2_ex
|
||||
diff_ex diff union_ex intersection_ex
|
||||
JT_ROUND JT_MITER JT_SQUARE
|
||||
intersection intersection_pl diff_pl union);
|
||||
offset2_ex
|
||||
diff_ex diff union_ex
|
||||
union);
|
||||
|
||||
1;
|
||||
|
@ -5,12 +5,6 @@ use warnings;
|
||||
# a line is a two-points line
|
||||
use parent 'Slic3r::Polyline';
|
||||
|
||||
sub intersection {
|
||||
my $self = shift;
|
||||
my ($line, $require_crossing) = @_;
|
||||
return Slic3r::Geometry::line_intersection($self, $line, $require_crossing);
|
||||
}
|
||||
|
||||
sub grow {
|
||||
my $self = shift;
|
||||
return Slic3r::Polyline->new(@$self)->grow(@_);
|
||||
|
@ -5,9 +5,6 @@ use warnings;
|
||||
|
||||
use List::Util qw(min max sum first);
|
||||
use Slic3r::Flow ':roles';
|
||||
use Slic3r::Geometry qw(scale epsilon);
|
||||
use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
|
||||
offset offset_ex offset2_ex JT_MITER);
|
||||
use Slic3r::Print::State ':steps';
|
||||
use Slic3r::Surface ':types';
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
min_slic3r_version = 2.4.1-rc1
|
||||
1.0.1 Fix missing AzteQ Industrial ABS material for 0.6, 0.8 nozzle, enabled elefant foot compensation
|
||||
1.0.0 Added AzteQ Industrial profiles for 0.8 nozzle, updated spool weight and filament cost, some minor setting improvements
|
||||
min_slic3r_version = 2.3.2-alpha0
|
||||
0.0.9 Added AzteQ Industrial materials PC/ABS (Fillamentum), PC-Max (Polymaker), Nylon FX256 (Fillamentum), Added DeltiQ 2 materials Nylon PA12 (Fiberlogy), Nylon CF15 Carbon (Fillamentum), PEBA 90A - FlexFill (Fillamentum), MoldLay (Wax-Alike), disabled retract only when crossing perimeters, some minor setting improvements
|
||||
|
@ -6,7 +6,7 @@
|
||||
name = TriLAB
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the PrusaSlicer configuration to be downgraded.
|
||||
config_version = 1.0.0
|
||||
config_version = 1.0.1
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
|
||||
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||
@ -118,7 +118,7 @@ complete_objects = 0
|
||||
default_acceleration = 2000
|
||||
dont_support_bridges = 0
|
||||
draft_shield = 0
|
||||
elefant_foot_compensation = 0.0
|
||||
elefant_foot_compensation = 0.1
|
||||
ensure_vertical_shell_thickness = 0
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
external_perimeter_speed = 30
|
||||
@ -338,6 +338,7 @@ support_material_extrusion_width = 0.55
|
||||
support_material_interface_spacing = 0.6
|
||||
support_material_xy_spacing = 0.9
|
||||
top_infill_extrusion_width = 0.6
|
||||
elefant_foot_compensation = 0.2
|
||||
|
||||
[print:DeltiQ 0.30mm Strong @0.6 nozzle]
|
||||
inherits = DeltiQ 0.30mm Normal @0.6 nozzle
|
||||
@ -356,7 +357,7 @@ bottom_solid_min_thickness = 1.2
|
||||
bridge_flow_ratio = 0.90
|
||||
bridge_speed = 20
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_FAMILY_DQ.*/ and nozzle_diameter[0]==0.8
|
||||
elefant_foot_compensation = 0.0
|
||||
elefant_foot_compensation = 0.2
|
||||
external_perimeter_extrusion_width = 0.80
|
||||
external_perimeter_speed = 30
|
||||
extrusion_width = 0.80
|
||||
@ -415,7 +416,7 @@ complete_objects = 0
|
||||
default_acceleration = 2000
|
||||
dont_support_bridges = 0
|
||||
draft_shield = 0
|
||||
elefant_foot_compensation = 0
|
||||
elefant_foot_compensation = 0.1
|
||||
ensure_vertical_shell_thickness = 0
|
||||
external_perimeter_extrusion_width = 0.45
|
||||
external_perimeter_speed = 30
|
||||
@ -558,6 +559,7 @@ support_material_extrusion_width = 0.55
|
||||
support_material_interface_spacing = 0.6
|
||||
support_material_xy_spacing = 0.9
|
||||
top_infill_extrusion_width = 0.6
|
||||
elefant_foot_compensation = 0.2
|
||||
|
||||
[print:AzteQ Industrial 0.30mm Strong @0.6 nozzle]
|
||||
inherits = AzteQ Industrial 0.30mm Normal @0.6 nozzle
|
||||
@ -579,7 +581,7 @@ bottom_solid_min_thickness = 0.7
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 30
|
||||
dont_support_bridges = 0
|
||||
elefant_foot_compensation = 0
|
||||
elefant_foot_compensation = 0.2
|
||||
ensure_vertical_shell_thickness = 0
|
||||
external_perimeter_extrusion_width = 0.8
|
||||
external_perimeter_speed = 30
|
||||
@ -1413,9 +1415,11 @@ filament_spool_weight = 229
|
||||
|
||||
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.6 nozzle]
|
||||
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.6
|
||||
|
||||
[filament:AzteQ Industrial - ABS - ExtraFill (Fillamentum) @0.8 nozzle]
|
||||
inherits = AzteQ Industrial - ABS - ExtraFill (Fillamentum)
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_TRILAB.*/ and printer_notes=~/.*PRINTER_MODEL_AQI.*/ and nozzle_diameter[0]==0.8
|
||||
extrusion_multiplier = 0.95
|
||||
|
||||
[filament:AzteQ Industrial - PC/ABS - (Fillamentum)]
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "libslic3r.h"
|
||||
#include "clonable_ptr.hpp"
|
||||
@ -1989,6 +1990,7 @@ public:
|
||||
struct SetDeserializeItem {
|
||||
SetDeserializeItem(const char *opt_key, const char *opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
||||
SetDeserializeItem(const std::string &opt_key, const std::string &opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
||||
SetDeserializeItem(const std::string &opt_key, const std::string_view opt_value, bool append = false) : opt_key(opt_key), opt_value(opt_value), append(append) {}
|
||||
SetDeserializeItem(const char *opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
|
||||
SetDeserializeItem(const std::string &opt_key, const bool value, bool append = false) : opt_key(opt_key), opt_value(value ? "1" : "0"), append(append) {}
|
||||
SetDeserializeItem(const char *opt_key, const int value, bool append = false) : opt_key(opt_key), opt_value(std::to_string(value)), append(append) {}
|
||||
|
@ -324,10 +324,10 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E
|
||||
polylines.clear();
|
||||
}
|
||||
|
||||
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
|
||||
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, const Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height)
|
||||
{
|
||||
dst.reserve(dst.size() + polylines.size());
|
||||
for (Polyline &polyline : polylines)
|
||||
for (const Polyline &polyline : polylines)
|
||||
if (polyline.is_valid()) {
|
||||
ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height);
|
||||
dst.push_back(extrusion_path);
|
||||
|
@ -3661,42 +3661,44 @@ void GCodeProcessor::post_process()
|
||||
return std::tuple(!ret.empty(), (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1);
|
||||
};
|
||||
|
||||
struct FilamentData
|
||||
{
|
||||
double mm{ 0.0 };
|
||||
double cm3{ 0.0 };
|
||||
double g{ 0.0 };
|
||||
double cost{ 0.0 };
|
||||
};
|
||||
std::vector<double> filament_mm(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_cm3(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_g(m_result.extruders_count, 0.0);
|
||||
std::vector<double> filament_cost(m_result.extruders_count, 0.0);
|
||||
|
||||
double filament_total_g = 0.0;
|
||||
double filament_total_cost = 0.0;
|
||||
|
||||
FilamentData filament_data;
|
||||
for (const auto& [role, used] : m_result.print_statistics.used_filaments_per_role) {
|
||||
filament_data.mm += used.first;
|
||||
filament_data.g += used.second;
|
||||
}
|
||||
for (const auto& [id, volume] : m_result.print_statistics.volumes_per_extruder) {
|
||||
filament_data.cm3 += volume;
|
||||
filament_data.cost += volume * double(m_result.filament_densities[id]) * double(m_result.filament_cost[id]) * 0.000001;
|
||||
filament_mm[id] = volume / (static_cast<double>(M_PI) * sqr(0.5 * m_result.filament_diameters[id]));
|
||||
filament_cm3[id] = volume * 0.001;
|
||||
filament_g[id] = filament_cm3[id] * double(m_result.filament_densities[id]);
|
||||
filament_cost[id] = filament_g[id] * double(m_result.filament_cost[id]) * 0.001;
|
||||
filament_total_g += filament_g[id];
|
||||
filament_total_cost += filament_cost[id];
|
||||
}
|
||||
|
||||
auto process_used_filament = [&filament_data](std::string& gcode_line) {
|
||||
auto process_tag = [](std::string& gcode_line, const std::string& tag, double value) {
|
||||
auto process_used_filament = [&](std::string& gcode_line) {
|
||||
auto process_tag = [](std::string& gcode_line, const std::string& tag, const std::vector<double>& values) {
|
||||
if (boost::algorithm::istarts_with(gcode_line, tag)) {
|
||||
char buf[128];
|
||||
sprintf(buf, "%s %.2lf\n", tag.c_str(), value);
|
||||
gcode_line = buf;
|
||||
gcode_line = tag;
|
||||
char buf[1024];
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
sprintf(buf, i == values.size() - 1 ? " %.2lf\n" : " %.2lf,", values[i]);
|
||||
gcode_line += buf;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
bool ret = false;
|
||||
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_data.mm * 1000.0);
|
||||
ret |= process_tag(gcode_line, "; filament used [g] =", filament_data.g);
|
||||
ret |= process_tag(gcode_line, "; total filament used [g] =", filament_data.g);
|
||||
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_data.cm3 / 1000.0);
|
||||
ret |= process_tag(gcode_line, "; filament cost =", filament_data.cost);
|
||||
ret |= process_tag(gcode_line, "; total filament cost =", filament_data.cost);
|
||||
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_mm);
|
||||
ret |= process_tag(gcode_line, "; filament used [g] =", filament_g);
|
||||
ret |= process_tag(gcode_line, "; total filament used [g] =", { filament_total_g });
|
||||
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_cm3);
|
||||
ret |= process_tag(gcode_line, "; filament cost =", filament_cost);
|
||||
ret |= process_tag(gcode_line, "; total filament cost =", { filament_total_cost });
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
|
||||
float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
|
||||
float new_F(const GCodeReader &reader) const { return this->has(F) ? this->f() : reader.f(); }
|
||||
Point new_XY_scaled(const GCodeReader &reader) const
|
||||
{ return Point::new_scale(this->new_X(reader), this->new_Y(reader)); }
|
||||
float dist_X(const GCodeReader &reader) const { return this->has(X) ? (this->x() - reader.x()) : 0; }
|
||||
float dist_Y(const GCodeReader &reader) const { return this->has(Y) ? (this->y() - reader.y()) : 0; }
|
||||
float dist_Z(const GCodeReader &reader) const { return this->has(Z) ? (this->z() - reader.z()) : 0; }
|
||||
@ -134,6 +136,8 @@ public:
|
||||
float e() const { return m_position[E]; }
|
||||
float& f() { return m_position[F]; }
|
||||
float f() const { return m_position[F]; }
|
||||
Point xy_scaled() const { return Point::new_scale(this->x(), this->y()); }
|
||||
|
||||
|
||||
// Returns 0 for gcfNoExtrusion.
|
||||
char extrusion_axis() const { return m_extrusion_axis; }
|
||||
|
@ -1281,17 +1281,6 @@ PageMode::PageMode(ConfigWizard *parent)
|
||||
radio_advanced = new wxRadioButton(this, wxID_ANY, _L("Advanced mode"));
|
||||
radio_expert = new wxRadioButton(this, wxID_ANY, _L("Expert mode"));
|
||||
|
||||
append(radio_simple);
|
||||
append(radio_advanced);
|
||||
append(radio_expert);
|
||||
|
||||
append_text("\n" + _L("The size of the object can be specified in inches"));
|
||||
check_inch = new wxCheckBox(this, wxID_ANY, _L("Use inches"));
|
||||
append(check_inch);
|
||||
}
|
||||
|
||||
void PageMode::on_activate()
|
||||
{
|
||||
std::string mode { "simple" };
|
||||
wxGetApp().app_config->get("", "view_mode", mode);
|
||||
|
||||
@ -1299,7 +1288,16 @@ void PageMode::on_activate()
|
||||
else if (mode == "expert") { radio_expert->SetValue(true); }
|
||||
else { radio_simple->SetValue(true); }
|
||||
|
||||
append(radio_simple);
|
||||
append(radio_advanced);
|
||||
append(radio_expert);
|
||||
|
||||
append_text("\n" + _L("The size of the object can be specified in inches"));
|
||||
check_inch = new wxCheckBox(this, wxID_ANY, _L("Use inches"));
|
||||
check_inch->SetValue(wxGetApp().app_config->get("use_inches") == "1");
|
||||
append(check_inch);
|
||||
|
||||
on_activate();
|
||||
}
|
||||
|
||||
void PageMode::serialize_mode(AppConfig *app_config) const
|
||||
@ -1310,11 +1308,6 @@ void PageMode::serialize_mode(AppConfig *app_config) const
|
||||
if (radio_advanced->GetValue()) { mode = "advanced"; }
|
||||
if (radio_expert->GetValue()) { mode = "expert"; }
|
||||
|
||||
// If "Mode" page wasn't selected (no one radiobutton is checked),
|
||||
// we shouldn't to update a view_mode value in app_config
|
||||
if (mode.empty())
|
||||
return;
|
||||
|
||||
app_config->set("view_mode", mode);
|
||||
app_config->set("use_inches", check_inch->GetValue() ? "1" : "0");
|
||||
}
|
||||
|
@ -426,8 +426,6 @@ struct PageMode: ConfigWizardPage
|
||||
PageMode(ConfigWizard *parent);
|
||||
|
||||
void serialize_mode(AppConfig *app_config) const;
|
||||
|
||||
virtual void on_activate();
|
||||
};
|
||||
|
||||
struct PageVendors: ConfigWizardPage
|
||||
|
@ -3941,9 +3941,8 @@ void GCodeViewer::render_legend(float& legend_height)
|
||||
PartialTimes items;
|
||||
|
||||
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_custom_gcode_per_print_z;
|
||||
int extruders_count = wxGetApp().extruders_edited_cnt();
|
||||
std::vector<ColorRGBA> last_color(extruders_count);
|
||||
for (int i = 0; i < extruders_count; ++i) {
|
||||
std::vector<ColorRGBA> last_color(m_extruders_count);
|
||||
for (int i = 0; i < m_extruders_count; ++i) {
|
||||
last_color[i] = m_tool_colors[i];
|
||||
}
|
||||
int last_extruder_id = 1;
|
||||
|
@ -3465,7 +3465,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
// during the scene manipulation.
|
||||
|
||||
#if ENABLE_NEW_RECTANGLE_SELECTION
|
||||
if (m_picking_enabled && !any_gizmo_active && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && !rectangle_selection_dragging) {
|
||||
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && !rectangle_selection_dragging) {
|
||||
#else
|
||||
if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) {
|
||||
#endif // ENABLE_NEW_RECTANGLE_SELECTION
|
||||
|
@ -706,6 +706,10 @@ void MainFrame::init_tabpanel()
|
||||
// before the MainFrame is fully set up.
|
||||
tab->OnActivate();
|
||||
m_last_selected_tab = m_tabpanel->GetSelection();
|
||||
#ifdef _MSW_DARK_MODE
|
||||
if (wxGetApp().tabs_as_menu())
|
||||
tab->SetFocus();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
select_tab(size_t(0)); // select Plater
|
||||
@ -2018,8 +2022,13 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
|
||||
m_plater->SetFocus();
|
||||
Layout();
|
||||
}
|
||||
else
|
||||
else {
|
||||
select(false);
|
||||
#ifdef _MSW_DARK_MODE
|
||||
if (wxGetApp().tabs_as_menu() && tab == 0)
|
||||
m_plater->SetFocus();
|
||||
#endif
|
||||
}
|
||||
|
||||
// When we run application in ESettingsLayout::New or ESettingsLayout::Dlg mode, tabpanel is hidden from the very beginning
|
||||
// and as a result Tab::update_changed_tree_ui() function couldn't update m_is_nonsys_values values,
|
||||
|
@ -3872,6 +3872,9 @@ void Plater::priv::reload_from_disk()
|
||||
old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
|
||||
|
||||
sla::reproject_points_and_holes(old_model_object);
|
||||
|
||||
// Fix warning icon in object list
|
||||
wxGetApp().obj_list()->update_item_error_icon(obj_idx, vol_idx);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -490,8 +490,11 @@ bool PrintHostQueueDialog::load_user_data(int udt, std::vector<int>& vector)
|
||||
auto* app_config = wxGetApp().app_config;
|
||||
auto hasget = [app_config](const std::string& name, std::vector<int>& vector)->bool {
|
||||
if (app_config->has(name)) {
|
||||
vector.push_back(std::stoi(app_config->get(name)));
|
||||
return true;
|
||||
std::string val = app_config->get(name);
|
||||
if (!val.empty() || val[0]!='\0') {
|
||||
vector.push_back(std::stoi(val));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
318
t/fill.t
318
t/fill.t
@ -1,318 +0,0 @@
|
||||
use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
#plan tests => 43;
|
||||
# Test of a 100% coverage is off.
|
||||
plan tests => 19;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use local::lib "$FindBin::Bin/../local-lib";
|
||||
}
|
||||
|
||||
use List::Util qw(first sum);
|
||||
use Slic3r;
|
||||
use Slic3r::Geometry qw(X Y scale unscale convex_hull);
|
||||
use Slic3r::Geometry::Clipper qw(union diff diff_ex offset offset2_ex);
|
||||
use Slic3r::Surface qw(:types);
|
||||
use Slic3r::Test;
|
||||
|
||||
sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
||||
|
||||
{
|
||||
my $expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [50,0], [50,50], [0,50] ]);
|
||||
my $filler = Slic3r::Filler->new_from_type('rectilinear');
|
||||
$filler->set_bounding_box($expolygon->bounding_box);
|
||||
$filler->set_angle(0);
|
||||
my $surface = Slic3r::Surface->new(
|
||||
surface_type => S_TYPE_TOP,
|
||||
expolygon => $expolygon,
|
||||
);
|
||||
my $flow = Slic3r::Flow->new(
|
||||
width => 0.69,
|
||||
height => 0.4,
|
||||
nozzle_diameter => 0.50,
|
||||
);
|
||||
$filler->set_spacing($flow->spacing);
|
||||
foreach my $angle (0, 45) {
|
||||
$surface->expolygon->rotate(Slic3r::Geometry::deg2rad($angle), [0,0]);
|
||||
my $paths = $filler->fill_surface($surface, layer_height => 0.4, density => 0.4);
|
||||
is scalar @$paths, 1, 'one continuous path';
|
||||
}
|
||||
}
|
||||
|
||||
SKIP:
|
||||
{
|
||||
skip "The FillRectilinear2 does not fill the surface completely", 1;
|
||||
|
||||
my $test = sub {
|
||||
my ($expolygon, $flow_spacing, $angle, $density) = @_;
|
||||
|
||||
my $filler = Slic3r::Filler->new_from_type('rectilinear');
|
||||
$filler->set_bounding_box($expolygon->bounding_box);
|
||||
$filler->set_angle($angle // 0);
|
||||
# Adjust line spacing to fill the region.
|
||||
$filler->set_dont_adjust(0);
|
||||
$filler->set_link_max_length(scale(1.2*$flow_spacing));
|
||||
my $surface = Slic3r::Surface->new(
|
||||
surface_type => S_TYPE_BOTTOM,
|
||||
expolygon => $expolygon,
|
||||
);
|
||||
my $flow = Slic3r::Flow->new(
|
||||
width => $flow_spacing,
|
||||
height => 0.4,
|
||||
nozzle_diameter => $flow_spacing,
|
||||
);
|
||||
$filler->set_spacing($flow->spacing);
|
||||
my $paths = $filler->fill_surface(
|
||||
$surface,
|
||||
layer_height => $flow->height,
|
||||
density => $density // 1,
|
||||
);
|
||||
|
||||
# check whether any part was left uncovered
|
||||
my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $filler->spacing/2)}, @$paths;
|
||||
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
|
||||
|
||||
# ignore very small dots
|
||||
my $uncovered_filtered = [ grep $_->area > (scale $flow_spacing)**2, @$uncovered ];
|
||||
|
||||
is scalar(@$uncovered_filtered), 0, 'solid surface is fully filled';
|
||||
|
||||
if (0 && @$uncovered_filtered) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("uncovered.svg",
|
||||
no_arrows => 1,
|
||||
expolygons => [ $expolygon ],
|
||||
blue_expolygons => [ @$uncovered ],
|
||||
red_expolygons => [ @$uncovered_filtered ],
|
||||
polylines => [ @$paths ],
|
||||
);
|
||||
exit;
|
||||
}
|
||||
};
|
||||
|
||||
my $expolygon = Slic3r::ExPolygon->new([
|
||||
[6883102, 9598327.01296997],
|
||||
[6883102, 20327272.01297],
|
||||
[3116896, 20327272.01297],
|
||||
[3116896, 9598327.01296997],
|
||||
]);
|
||||
$test->($expolygon, 0.55);
|
||||
|
||||
for (1..20) {
|
||||
$expolygon->scale(1.05);
|
||||
$test->($expolygon, 0.55);
|
||||
}
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new(
|
||||
[[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]]
|
||||
);
|
||||
$test->($expolygon, 0.524341649025257);
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [98,0], [98,10], [0,10] ]);
|
||||
$test->($expolygon, 0.5, 45, 0.99); # non-solid infill
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::Polyline::Collection->new(
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[Y], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
|
||||
[20, 18, 15, 10, 8, 5],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::Polyline::Collection->new(
|
||||
Slic3r::Polyline->new([4,0], [10,0], [15,0]),
|
||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[X], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
|
||||
[reverse 4, 10, 15, 10, 15, 20],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[Y], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
|
||||
[20, 18, 15, 10, 8, 5],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
|
||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[X], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
|
||||
[reverse 4, 10, 15, 10, 15, 20],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) {
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]);
|
||||
$config->set('fill_pattern', $pattern);
|
||||
$config->set('top_fill_pattern', $pattern);
|
||||
$config->set('bottom_fill_pattern', $pattern);
|
||||
$config->set('perimeters', 1);
|
||||
$config->set('skirts', 0);
|
||||
$config->set('fill_density', 20);
|
||||
$config->set('layer_height', 0.05);
|
||||
$config->set('perimeter_extruder', 1);
|
||||
$config->set('infill_extruder', 2);
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2);
|
||||
ok my $gcode = Slic3r::Test::gcode($print), "successful $pattern infill generation";
|
||||
my $tool = undef;
|
||||
my @perimeter_points = my @infill_points = ();
|
||||
Slic3r::GCode::Reader->new->parse($gcode, sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->perimeter_extruder-1) {
|
||||
push @perimeter_points, Slic3r::Point->new_scale($args->{X}, $args->{Y});
|
||||
} elsif ($tool == $config->infill_extruder-1) {
|
||||
push @infill_points, Slic3r::Point->new_scale($args->{X}, $args->{Y});
|
||||
}
|
||||
}
|
||||
});
|
||||
my $convex_hull = convex_hull(\@perimeter_points);
|
||||
ok !(defined first { !$convex_hull->contains_point($_) } @infill_points), "infill does not exceed perimeters ($pattern)";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('nozzle_diameter', [0.4,0.4,0.4,0.4]);
|
||||
$config->set('infill_only_where_needed', 1);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('infill_extruder', 2);
|
||||
$config->set('infill_extrusion_width', 0.5);
|
||||
$config->set('wipe_into_infill', 0);
|
||||
$config->set('fill_density', 40);
|
||||
$config->set('cooling', [ 0 ]); # for preventing speeds from being altered
|
||||
$config->set('first_layer_speed', '100%'); # for preventing speeds from being altered
|
||||
|
||||
my $test = sub {
|
||||
my $print = Slic3r::Test::init_print('pyramid', config => $config);
|
||||
|
||||
my $tool = undef;
|
||||
my @infill_extrusions = (); # array of polylines
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->infill_extruder-1) {
|
||||
push @infill_extrusions, Slic3r::Line->new_scale(
|
||||
[ $self->X, $self->Y ],
|
||||
[ $info->{new_X}, $info->{new_Y} ],
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return 0 if !@infill_extrusions; # prevent calling convex_hull() with no points
|
||||
|
||||
my $convex_hull = convex_hull([ map $_->pp, map @$_, @infill_extrusions ]);
|
||||
return unscale unscale sum(map $_->area, @{offset([$convex_hull], scale(+$config->infill_extrusion_width/2))});
|
||||
};
|
||||
|
||||
my $tolerance = 5; # mm^2
|
||||
|
||||
$config->set('solid_infill_below_area', 0);
|
||||
ok $test->() < $tolerance,
|
||||
'no infill is generated when using infill_only_where_needed on a pyramid';
|
||||
|
||||
$config->set('solid_infill_below_area', 70);
|
||||
ok abs($test->() - $config->solid_infill_below_area) < $tolerance,
|
||||
'infill is only generated under the forced solid shells';
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 1);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('solid_infill_below_area', 20000000);
|
||||
$config->set('solid_infill_every_layers', 2);
|
||||
$config->set('perimeter_speed', 99);
|
||||
$config->set('external_perimeter_speed', 99);
|
||||
$config->set('cooling', [ 0 ]);
|
||||
$config->set('first_layer_speed', '100%');
|
||||
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
my %layers_with_extrusion = ();
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd eq 'G1' && $info->{dist_XY} > 0 && $info->{extruding}) {
|
||||
if (($args->{F} // $self->F) != $config->perimeter_speed*60) {
|
||||
$layers_with_extrusion{$self->Z} = ($args->{F} // $self->F);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ok !%layers_with_extrusion,
|
||||
"solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config::new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 3);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('layer_height', 0.2);
|
||||
$config->set('first_layer_height', 0.2);
|
||||
$config->set('nozzle_diameter', [0.35,0.35,0.35,0.35]);
|
||||
$config->set('infill_extruder', 2);
|
||||
$config->set('solid_infill_extruder', 2);
|
||||
$config->set('infill_extrusion_width', 0.52);
|
||||
$config->set('solid_infill_extrusion_width', 0.52);
|
||||
$config->set('first_layer_extrusion_width', 0);
|
||||
|
||||
my $print = Slic3r::Test::init_print('A', config => $config);
|
||||
my %infill = (); # Z => [ Line, Line ... ]
|
||||
my $tool = undef;
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->infill_extruder-1) {
|
||||
my $z = 1 * $self->Z;
|
||||
$infill{$z} ||= [];
|
||||
push @{$infill{$z}}, Slic3r::Line->new_scale(
|
||||
[ $self->X, $self->Y ],
|
||||
[ $info->{new_X}, $info->{new_Y} ],
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
my $grow_d = scale($config->infill_extrusion_width)/2;
|
||||
my $layer0_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.2} } ]);
|
||||
my $layer1_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.4} } ]);
|
||||
my $diff = diff($layer0_infill, $layer1_infill);
|
||||
$diff = offset2_ex($diff, -$grow_d, +$grow_d);
|
||||
$diff = [ grep { $_->area > 2*(($grow_d*2)**2) } @$diff ];
|
||||
is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0';
|
||||
}
|
||||
|
||||
__END__
|
40
t/geometry.t
40
t/geometry.t
@ -2,7 +2,7 @@ use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 30;
|
||||
plan tests => 27;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
@ -39,44 +39,6 @@ isnt Slic3r::Geometry::line_intersection($line1, $line2, 1), undef, 'line_inters
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $polygon = Slic3r::Polygon->new(
|
||||
[45919000, 515273900], [14726100, 461246400], [14726100, 348753500], [33988700, 315389800],
|
||||
[43749700, 343843000], [45422300, 352251500], [52362100, 362637800], [62748400, 369577600],
|
||||
[75000000, 372014700], [87251500, 369577600], [97637800, 362637800], [104577600, 352251500],
|
||||
[107014700, 340000000], [104577600, 327748400], [97637800, 317362100], [87251500, 310422300],
|
||||
[82789200, 309534700], [69846100, 294726100], [254081000, 294726100], [285273900, 348753500],
|
||||
[285273900, 461246400], [254081000, 515273900],
|
||||
);
|
||||
|
||||
# this points belongs to $polyline
|
||||
# note: it's actually a vertex, while we should better check an intermediate point
|
||||
my $point = Slic3r::Point->new(104577600, 327748400);
|
||||
|
||||
local $Slic3r::Geometry::epsilon = 1E-5;
|
||||
is_deeply Slic3r::Geometry::polygon_segment_having_point($polygon, $point)->pp,
|
||||
[ [107014700, 340000000], [104577600, 327748400] ],
|
||||
'polygon_segment_having_point';
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $point = Slic3r::Point->new(736310778.185108, 5017423926.8924);
|
||||
my $line = Slic3r::Line->new([627484000, 3695776000], [750000000, 3720147000]);
|
||||
is Slic3r::Geometry::point_in_segment($point, $line), 0, 'point_in_segment';
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $point = Slic3r::Point->new(736310778.185108, 5017423926.8924);
|
||||
my $line = Slic3r::Line->new([627484000, 3695776000], [750000000, 3720147000]);
|
||||
is Slic3r::Geometry::point_in_segment($point, $line), 0, 'point_in_segment';
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
my $polygons = [
|
||||
Slic3r::Polygon->new( # contour, ccw
|
||||
[45919000, 515273900], [14726100, 461246400], [14726100, 348753500], [33988700, 315389800],
|
||||
|
@ -14,7 +14,7 @@ use List::Util qw(first);
|
||||
use Slic3r;
|
||||
use Slic3r::Flow ':roles';
|
||||
use Slic3r::Geometry qw(PI scale unscale);
|
||||
use Slic3r::Geometry::Clipper qw(union_ex diff union offset);
|
||||
use Slic3r::Geometry::Clipper qw(union_ex diff);
|
||||
use Slic3r::Surface ':types';
|
||||
use Slic3r::Test;
|
||||
|
||||
|
121
t/polyclip.t
121
t/polyclip.t
@ -1,121 +0,0 @@
|
||||
use Test::More;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
plan tests => 18;
|
||||
|
||||
BEGIN {
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use local::lib "$FindBin::Bin/../local-lib";
|
||||
}
|
||||
|
||||
use Slic3r;
|
||||
use Slic3r::Geometry::Clipper qw(intersection_pl);
|
||||
|
||||
#==========================================================
|
||||
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(10, 10), Slic3r::Line->new([5, 10], [20, 10])), 1, 'point in horizontal segment';
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(30, 10), Slic3r::Line->new([5, 10], [20, 10])), 0, 'point not in horizontal segment';
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(10, 10), Slic3r::Line->new([10, 5], [10, 20])), 1, 'point in vertical segment';
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(10, 30), Slic3r::Line->new([10, 5], [10, 20])), 0, 'point not in vertical segment';
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(15, 15), Slic3r::Line->new([10, 10], [20, 20])), 1, 'point in diagonal segment';
|
||||
is Slic3r::Geometry::point_in_segment(Slic3r::Point->new(20, 15), Slic3r::Line->new([10, 10], [20, 20])), 0, 'point not in diagonal segment';
|
||||
|
||||
#==========================================================
|
||||
|
||||
my $square = Slic3r::Polygon->new( # ccw
|
||||
[100, 100],
|
||||
[200, 100],
|
||||
[200, 200],
|
||||
[100, 200],
|
||||
);
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $hole_in_square = [ # cw
|
||||
[140, 140],
|
||||
[140, 160],
|
||||
[160, 160],
|
||||
[160, 140],
|
||||
];
|
||||
my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
|
||||
#is $expolygon->contains_point(Slic3r::Point->new(100, 100)), 1, 'corner point is recognized';
|
||||
#is $expolygon->contains_point(Slic3r::Point->new(100, 180)), 1, 'point on contour is recognized';
|
||||
#is $expolygon->contains_point(Slic3r::Point->new(140, 150)), 1, 'point on hole contour is recognized';
|
||||
#is $expolygon->contains_point(Slic3r::Point->new(140, 140)), 1, 'point on hole corner is recognized';
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([150,180], [150,150])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([150, 180], [150, 160])->length,
|
||||
'line is clipped to square with hole';
|
||||
}
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([150,150], [150,120])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([150, 140], [150, 120])->length,
|
||||
'line is clipped to square with hole';
|
||||
}
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([120,180], [180,180])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([120,180], [180,180])->length,
|
||||
'line is clipped to square with hole';
|
||||
}
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([50, 150], [300, 150])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([100, 150], [140, 150])->length,
|
||||
'line is clipped to square with hole';
|
||||
is $intersection->[1]->length, Slic3r::Line->new([160, 150], [200, 150])->length,
|
||||
'line is clipped to square with hole';
|
||||
}
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([300, 150], [50, 150])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([200, 150], [160, 150])->length,
|
||||
'reverse line is clipped to square with hole';
|
||||
is $intersection->[1]->length, Slic3r::Line->new([140, 150], [100, 150])->length,
|
||||
'reverse line is clipped to square with hole';
|
||||
}
|
||||
{
|
||||
my $intersection = intersection_pl([Slic3r::Polyline->new([100,180], [200,180])], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([100,180], [200,180])->length,
|
||||
'tangent line is clipped to square with hole';
|
||||
}
|
||||
}
|
||||
|
||||
#==========================================================
|
||||
|
||||
{
|
||||
my $large_circle = Slic3r::Polygon->new_scale( # ccw
|
||||
[151.8639,288.1192], [133.2778,284.6011], [115.0091,279.6997], [98.2859,270.8606], [82.2734,260.7933],
|
||||
[68.8974,247.4181], [56.5622,233.0777], [47.7228,216.3558], [40.1617,199.0172], [36.6431,180.4328],
|
||||
[34.932,165.2312], [37.5567,165.1101], [41.0547,142.9903], [36.9056,141.4295], [40.199,124.1277],
|
||||
[47.7776,106.7972], [56.6335,90.084], [68.9831,75.7557], [82.3712,62.3948], [98.395,52.3429],
|
||||
[115.1281,43.5199], [133.4004,38.6374], [151.9884,35.1378], [170.8905,35.8571], [189.6847,37.991],
|
||||
[207.5349,44.2488], [224.8662,51.8273], [240.0786,63.067], [254.407,75.4169], [265.6311,90.6406],
|
||||
[275.6832,106.6636], [281.9225,124.52], [286.8064,142.795], [287.5061,161.696], [286.7874,180.5972],
|
||||
[281.8856,198.8664], [275.6283,216.7169], [265.5604,232.7294], [254.3211,247.942], [239.9802,260.2776],
|
||||
[224.757,271.5022], [207.4179,279.0635], [189.5605,285.3035], [170.7649,287.4188],
|
||||
);
|
||||
ok $large_circle->is_counter_clockwise, "contour is counter-clockwise";
|
||||
|
||||
my $small_circle = Slic3r::Polygon->new_scale( # cw
|
||||
[158.227,215.9007], [164.5136,215.9007], [175.15,214.5007], [184.5576,210.6044], [190.2268,207.8743],
|
||||
[199.1462,201.0306], [209.0146,188.346], [213.5135,177.4829], [214.6979,168.4866], [216.1025,162.3325],
|
||||
[214.6463,151.2703], [213.2471,145.1399], [209.0146,134.9203], [199.1462,122.2357], [189.8944,115.1366],
|
||||
[181.2504,111.5567], [175.5684,108.8205], [164.5136,107.3655], [158.2269,107.3655], [147.5907,108.7656],
|
||||
[138.183,112.6616], [132.5135,115.3919], [123.5943,122.2357], [113.7259,134.92], [109.2269,145.7834],
|
||||
[108.0426,154.7799], [106.638,160.9339], [108.0941,171.9957], [109.4933,178.1264], [113.7259,188.3463],
|
||||
[123.5943,201.0306], [132.8461,208.1296], [141.4901,211.7094], [147.172,214.4458],
|
||||
);
|
||||
ok $small_circle->is_clockwise, "hole is clockwise";
|
||||
|
||||
my $expolygon = Slic3r::ExPolygon->new($large_circle, $small_circle);
|
||||
my $line = Slic3r::Polyline->new_scale([152.742,288.086671142818], [152.742,34.166466971035]);
|
||||
|
||||
my $intersection = intersection_pl([$line], \@$expolygon);
|
||||
is $intersection->[0]->length, Slic3r::Line->new([152742000, 288086661], [152742000, 215178843])->length,
|
||||
'line is clipped to square with hole';
|
||||
is $intersection->[1]->length, Slic3r::Line->new([152742000, 108087507], [152742000, 35166477])->length,
|
||||
'line is clipped to square with hole';
|
||||
}
|
||||
|
||||
#==========================================================
|
@ -187,6 +187,19 @@ TriangleMesh mesh(TestMesh m)
|
||||
return mesh;
|
||||
}
|
||||
|
||||
TriangleMesh mesh(TestMesh min, Vec3d translate, Vec3d scale)
|
||||
{
|
||||
TriangleMesh m = mesh(min);
|
||||
m.translate(translate.cast<float>());
|
||||
m.scale(scale.cast<float>());
|
||||
return m;
|
||||
}
|
||||
|
||||
TriangleMesh mesh(TestMesh m, Vec3d translate, double scale)
|
||||
{
|
||||
return mesh(m, translate, Vec3d(scale, scale, scale));
|
||||
}
|
||||
|
||||
static bool verbose_gcode()
|
||||
{
|
||||
const char *v = std::getenv("SLIC3R_TESTS_GCODE");
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/ShortestPath.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include "test_data.hpp"
|
||||
@ -83,3 +84,60 @@ SCENARIO("ExtrusionEntityCollection: Polygon flattening", "[ExtrusionEntity]") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ExtrusionEntityCollection: Chained path", "[ExtrusionEntity]") {
|
||||
struct Test {
|
||||
Polylines unchained;
|
||||
Polylines chained;
|
||||
Point initial_point;
|
||||
};
|
||||
std::vector<Test> tests {
|
||||
{
|
||||
{
|
||||
{ {0,15}, {0,18}, {0,20} },
|
||||
{ {0,10}, {0,8}, {0,5} }
|
||||
},
|
||||
{
|
||||
{ {0,20}, {0,18}, {0,15} },
|
||||
{ {0,10}, {0,8}, {0,5} }
|
||||
},
|
||||
{ 0,30 }
|
||||
},
|
||||
{
|
||||
{
|
||||
{ {4,0}, {10,0}, {15,0} },
|
||||
{ {10,5}, {15,5}, {20,5} }
|
||||
},
|
||||
{
|
||||
{ {20,5}, {15,5}, {10,5} },
|
||||
{ {15,0}, {10,0}, {4,0} }
|
||||
},
|
||||
{ 30,0 }
|
||||
},
|
||||
{
|
||||
{
|
||||
{ {15,0}, {10,0}, {4,0} },
|
||||
{ {10,5}, {15,5}, {20,5} }
|
||||
},
|
||||
{
|
||||
{ {20,5}, {15,5}, {10,5} },
|
||||
{ {15,0}, {10,0}, {4,0} }
|
||||
},
|
||||
{ 30,0 }
|
||||
},
|
||||
};
|
||||
for (const Test &test : tests) {
|
||||
Polylines chained = chain_polylines(test.unchained, &test.initial_point);
|
||||
REQUIRE(chained == test.chained);
|
||||
ExtrusionEntityCollection unchained_extrusions;
|
||||
extrusion_entities_append_paths(unchained_extrusions.entities, test.unchained,
|
||||
erInternalInfill, 0., 0.4f, 0.3f);
|
||||
ExtrusionEntityCollection chained_extrusions = unchained_extrusions.chained_path_from(test.initial_point);
|
||||
REQUIRE(chained_extrusions.entities.size() == test.chained.size());
|
||||
for (size_t i = 0; i < chained_extrusions.entities.size(); ++ i) {
|
||||
const Points &p1 = test.chained[i].points;
|
||||
const Points &p2 = dynamic_cast<const ExtrusionPath*>(chained_extrusions.entities[i])->polyline.points;
|
||||
REQUIRE(p1 == p2);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
#include "libslic3r/Fill/Fill.hpp"
|
||||
#include "libslic3r/Flow.hpp"
|
||||
#include "libslic3r/Geometry.hpp"
|
||||
#include "libslic3r/Geometry/ConvexHull.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
@ -14,6 +15,7 @@
|
||||
#include "test_data.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace std::literals;
|
||||
|
||||
bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle = 0, double density = 1.0);
|
||||
|
||||
@ -43,7 +45,7 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") {
|
||||
SECTION("Square") {
|
||||
Slic3r::Points test_set;
|
||||
test_set.reserve(4);
|
||||
std::vector<Vec2d> points {Vec2d(0,0), Vec2d(100,0), Vec2d(100,100), Vec2d(0,100)};
|
||||
std::vector<Vec2d> points { {0,0}, {100,0}, {100,100}, {0,100} };
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
std::transform(points.cbegin()+i, points.cend(), std::back_inserter(test_set), [] (const Vec2d& a) -> Point { return Point::new_scale(a.x(), a.y()); } );
|
||||
std::transform(points.cbegin(), points.cbegin()+i, std::back_inserter(test_set), [] (const Vec2d& a) -> Point { return Point::new_scale(a.x(), a.y()); } );
|
||||
@ -118,24 +120,26 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") {
|
||||
REQUIRE(std::abs(paths[0].length() - static_cast<double>(scale_(3*100 + 2*50))) - SCALED_EPSILON > 0); // path has expected length
|
||||
}
|
||||
|
||||
SECTION("Rotated Square") {
|
||||
Slic3r::Points square { Point::new_scale(0,0), Point::new_scale(50,0), Point::new_scale(50,50), Point::new_scale(0,50)};
|
||||
Slic3r::ExPolygon expolygon(square);
|
||||
SECTION("Rotated Square produces one continuous path") {
|
||||
Slic3r::ExPolygon expolygon(Polygon::new_scale({ {0, 0}, {50, 0}, {50, 50}, {0, 50} }));
|
||||
std::unique_ptr<Slic3r::Fill> filler(Slic3r::Fill::new_from_type("rectilinear"));
|
||||
filler->bounding_box = get_extents(expolygon.contour);
|
||||
filler->bounding_box = get_extents(expolygon);
|
||||
filler->angle = 0;
|
||||
|
||||
Surface surface(stTop, expolygon);
|
||||
auto flow = Slic3r::Flow(0.69f, 0.4f, 0.50f);
|
||||
// width, height, nozzle_dmr
|
||||
auto flow = Slic3r::Flow(0.69f, 0.4f, 0.5f);
|
||||
|
||||
FillParams fill_params;
|
||||
fill_params.density = 1.0;
|
||||
filler->spacing = flow.spacing();
|
||||
|
||||
for (auto angle : { 0.0, 45.0}) {
|
||||
surface.expolygon.rotate(angle, Point(0,0));
|
||||
Polylines paths = filler->fill_surface(&surface, fill_params);
|
||||
REQUIRE(paths.size() == 1);
|
||||
for (auto density : { 0.4, 1.0 }) {
|
||||
fill_params.density = density;
|
||||
filler->spacing = flow.spacing();
|
||||
for (auto angle : { 0.0, 45.0}) {
|
||||
surface.expolygon.rotate(angle, Point(0,0));
|
||||
Polylines paths = filler->fill_surface(&surface, fill_params);
|
||||
// one continuous path
|
||||
REQUIRE(paths.size() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,202 +194,226 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") {
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Infill does not exceed perimeters", "[Fill]")
|
||||
{
|
||||
auto test = [](const std::string_view pattern) {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" },
|
||||
{ "fill_pattern", pattern },
|
||||
{ "top_fill_pattern", pattern },
|
||||
{ "bottom_fill_pattern", pattern },
|
||||
{ "perimeters", 1 },
|
||||
{ "skirts", 0 },
|
||||
{ "fill_density", 0.2 },
|
||||
{ "layer_height", 0.05 },
|
||||
{ "perimeter_extruder", 1 },
|
||||
{ "infill_extruder", 2 }
|
||||
});
|
||||
|
||||
WHEN("40mm cube sliced") {
|
||||
std::string gcode = Slic3r::Test::slice({ mesh(Slic3r::Test::TestMesh::cube_20x20x20, Vec3d::Zero(), 2.0) }, config);
|
||||
THEN("gcode not empty") {
|
||||
REQUIRE(! gcode.empty());
|
||||
}
|
||||
THEN("infill does not exceed perimeters") {
|
||||
GCodeReader parser;
|
||||
const int perimeter_extruder = config.opt_int("perimeter_extruder");
|
||||
const int infill_extruder = config.opt_int("infill_extruder");
|
||||
int tool = -1;
|
||||
Points perimeter_points;
|
||||
Points infill_points;
|
||||
parser.parse_buffer(gcode, [&tool, &perimeter_points, &infill_points, perimeter_extruder, infill_extruder]
|
||||
(Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
||||
{
|
||||
// if the command is a T command, set the the current tool
|
||||
if (boost::starts_with(line.cmd(), "T")) {
|
||||
tool = atoi(line.cmd().data() + 1) + 1;
|
||||
} else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
||||
if (tool == perimeter_extruder)
|
||||
perimeter_points.emplace_back(line.new_XY_scaled(self));
|
||||
else if (tool == infill_extruder)
|
||||
infill_points.emplace_back(line.new_XY_scaled(self));
|
||||
}
|
||||
});
|
||||
auto convex_hull = Geometry::convex_hull(perimeter_points);
|
||||
int num_inside = std::count_if(infill_points.begin(), infill_points.end(), [&convex_hull](const Point &pt){ return convex_hull.contains(pt); });
|
||||
REQUIRE(num_inside == infill_points.size());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GIVEN("Rectilinear") { test("rectilinear"sv); }
|
||||
GIVEN("Honeycomb") { test("honeycomb"sv); }
|
||||
GIVEN("HilbertCurve") { test("hilbertcurve"sv); }
|
||||
GIVEN("Concentric") { test("concentric"sv); }
|
||||
}
|
||||
|
||||
SCENARIO("Infill only where needed", "[Fill]")
|
||||
{
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" },
|
||||
{ "infill_only_where_needed", true },
|
||||
{ "bottom_solid_layers", 0 },
|
||||
{ "infill_extruder", 2 },
|
||||
{ "infill_extrusion_width", 0.5 },
|
||||
{ "wipe_into_infill", false },
|
||||
{ "fill_density", 0.4 },
|
||||
// for preventing speeds from being altered
|
||||
{ "cooling", "0, 0, 0, 0" },
|
||||
// for preventing speeds from being altered
|
||||
{ "first_layer_speed", "100%" }
|
||||
});
|
||||
|
||||
auto test = [&config]() -> double {
|
||||
std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::pyramid }, config);
|
||||
THEN("gcode not empty") {
|
||||
REQUIRE(! gcode.empty());
|
||||
}
|
||||
|
||||
GCodeReader parser;
|
||||
int tool = -1;
|
||||
const int infill_extruder = config.opt_int("infill_extruder");
|
||||
Points infill_points;
|
||||
parser.parse_buffer(gcode, [&tool, &infill_points, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line)
|
||||
{
|
||||
// if the command is a T command, set the the current tool
|
||||
if (boost::starts_with(line.cmd(), "T")) {
|
||||
tool = atoi(line.cmd().data() + 1) + 1;
|
||||
} else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
||||
if (tool == infill_extruder) {
|
||||
infill_points.emplace_back(self.xy_scaled());
|
||||
infill_points.emplace_back(line.new_XY_scaled(self));
|
||||
}
|
||||
}
|
||||
});
|
||||
// prevent calling convex_hull() with no points
|
||||
THEN("infill not empty") {
|
||||
REQUIRE(! infill_points.empty());
|
||||
}
|
||||
|
||||
auto opt_width = config.opt<ConfigOptionFloatOrPercent>("infill_extrusion_width");
|
||||
REQUIRE(! opt_width->percent);
|
||||
Polygons convex_hull = expand(Geometry::convex_hull(infill_points), scaled<float>(opt_width->value / 2));
|
||||
return SCALING_FACTOR * SCALING_FACTOR * std::accumulate(convex_hull.begin(), convex_hull.end(), 0., [](double acc, const Polygon &poly){ return acc + poly.area(); });
|
||||
};
|
||||
|
||||
double tolerance = 5; // mm^2
|
||||
|
||||
GIVEN("solid_infill_below_area == 0") {
|
||||
config.opt_float("solid_infill_below_area") = 0;
|
||||
WHEN("pyramid is sliced ") {
|
||||
auto area = test();
|
||||
THEN("no infill is generated when using infill_only_where_needed on a pyramid") {
|
||||
REQUIRE(area < tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
GIVEN("solid_infill_below_area == 70") {
|
||||
config.opt_float("solid_infill_below_area") = 70;
|
||||
WHEN("pyramid is sliced ") {
|
||||
auto area = test();
|
||||
THEN("infill is only generated under the forced solid shells") {
|
||||
REQUIRE(std::abs(area - 70) < tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SCENARIO("Infill density zero", "[Fill]")
|
||||
{
|
||||
WHEN("20mm cube is sliced") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "skirts", 0 },
|
||||
{ "perimeters", 1 },
|
||||
{ "fill_density", 0 },
|
||||
{ "top_solid_layers", 0 },
|
||||
{ "bottom_solid_layers", 0 },
|
||||
{ "solid_infill_below_area", 20000000 },
|
||||
{ "solid_infill_every_layers", 2 },
|
||||
{ "perimeter_speed", 99 },
|
||||
{ "external_perimeter_speed", 99 },
|
||||
{ "cooling", "0" },
|
||||
{ "first_layer_speed", "100%" }
|
||||
});
|
||||
|
||||
std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::cube_20x20x20 }, config);
|
||||
THEN("gcode not empty") {
|
||||
REQUIRE(! gcode.empty());
|
||||
}
|
||||
|
||||
THEN("solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0") {
|
||||
GCodeReader parser;
|
||||
const double perimeter_speed = config.opt_float("perimeter_speed");
|
||||
std::map<double, double> layers_with_extrusion;
|
||||
parser.parse_buffer(gcode, [&layers_with_extrusion, perimeter_speed](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) {
|
||||
if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
||||
double f = line.new_F(self);
|
||||
if (std::abs(f - perimeter_speed * 60.) > 0.01)
|
||||
// It is a perimeter.
|
||||
layers_with_extrusion[self.z()] = f;
|
||||
}
|
||||
});
|
||||
REQUIRE(layers_with_extrusion.empty());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("A is sliced") {
|
||||
DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "skirts", 0 },
|
||||
{ "perimeters", 3 },
|
||||
{ "fill_density", 0 },
|
||||
{ "layer_height", 0.2 },
|
||||
{ "first_layer_height", 0.2 },
|
||||
{ "nozzle_diameter", "0.35,0.35,0.35,0.35" },
|
||||
{ "infill_extruder", 2 },
|
||||
{ "solid_infill_extruder", 2 },
|
||||
{ "infill_extrusion_width", 0.52 },
|
||||
{ "solid_infill_extrusion_width", 0.52 },
|
||||
{ "first_layer_extrusion_width", 0 }
|
||||
});
|
||||
|
||||
std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::A }, config);
|
||||
THEN("gcode not empty") {
|
||||
REQUIRE(! gcode.empty());
|
||||
}
|
||||
|
||||
THEN("no missing parts in solid shell when fill_density is 0") {
|
||||
GCodeReader parser;
|
||||
int tool = -1;
|
||||
const int infill_extruder = config.opt_int("infill_extruder");
|
||||
std::map<coord_t, Lines> infill;
|
||||
parser.parse_buffer(gcode, [&tool, &infill, infill_extruder](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) {
|
||||
if (boost::starts_with(line.cmd(), "T")) {
|
||||
tool = atoi(line.cmd().data() + 1) + 1;
|
||||
} else if (line.cmd() == "G1" && line.extruding(self) && line.dist_XY(self) > 0) {
|
||||
if (tool == infill_extruder)
|
||||
infill[scaled<coord_t>(self.z())].emplace_back(self.xy_scaled(), line.new_XY_scaled(self));
|
||||
}
|
||||
});
|
||||
auto opt_width = config.opt<ConfigOptionFloatOrPercent>("infill_extrusion_width");
|
||||
REQUIRE(! opt_width->percent);
|
||||
auto grow_d = scaled<float>(opt_width->value / 2);
|
||||
auto inflate_lines = [grow_d](const Lines &lines) {
|
||||
Polygons out;
|
||||
for (const Line &line : lines)
|
||||
append(out, offset(Polyline{ line.a, line.b }, grow_d, Slic3r::ClipperLib::jtSquare, 3.));
|
||||
return union_(out);
|
||||
};
|
||||
Polygons layer0_infill = inflate_lines(infill[scaled<coord_t>(0.2)]);
|
||||
Polygons layer1_infill = inflate_lines(infill[scaled<coord_t>(0.4)]);
|
||||
ExPolygons poly = opening_ex(diff_ex(layer0_infill, layer1_infill), grow_d);
|
||||
const double threshold = 2. * sqr(grow_d * 2.);
|
||||
int missing_parts = std::count_if(poly.begin(), poly.end(), [threshold](const ExPolygon &poly){ return poly.area() > threshold; });
|
||||
REQUIRE(missing_parts == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
my $collection = Slic3r::Polyline::Collection->new(
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[Y], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
|
||||
[20, 18, 15, 10, 8, 5],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::Polyline::Collection->new(
|
||||
Slic3r::Polyline->new([4,0], [10,0], [15,0]),
|
||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[X], map @$_, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
|
||||
[reverse 4, 10, 15, 10, 15, 20],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([0,15], [0,18], [0,20]),
|
||||
Slic3r::Polyline->new([0,10], [0,8], [0,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[Y], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(0,30), 0)} ],
|
||||
[20, 18, 15, 10, 8, 5],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
{
|
||||
my $collection = Slic3r::ExtrusionPath::Collection->new(
|
||||
map Slic3r::ExtrusionPath->new(polyline => $_, role => 0, mm3_per_mm => 1),
|
||||
Slic3r::Polyline->new([15,0], [10,0], [4,0]),
|
||||
Slic3r::Polyline->new([10,5], [15,5], [20,5]),
|
||||
);
|
||||
is_deeply
|
||||
[ map $_->[X], map @{$_->polyline}, @{$collection->chained_path_from(Slic3r::Point->new(30,0), 0)} ],
|
||||
[reverse 4, 10, 15, 10, 15, 20],
|
||||
'chained path';
|
||||
}
|
||||
|
||||
for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) {
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('fill_pattern', $pattern);
|
||||
$config->set('external_fill_pattern', $pattern);
|
||||
$config->set('perimeters', 1);
|
||||
$config->set('skirts', 0);
|
||||
$config->set('fill_density', 20);
|
||||
$config->set('layer_height', 0.05);
|
||||
$config->set('perimeter_extruder', 1);
|
||||
$config->set('infill_extruder', 2);
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config, scale => 2);
|
||||
ok my $gcode = Slic3r::Test::gcode($print), "successful $pattern infill generation";
|
||||
my $tool = undef;
|
||||
my @perimeter_points = my @infill_points = ();
|
||||
Slic3r::GCode::Reader->new->parse($gcode, sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->perimeter_extruder-1) {
|
||||
push @perimeter_points, Slic3r::Point->new_scale($args->{X}, $args->{Y});
|
||||
} elsif ($tool == $config->infill_extruder-1) {
|
||||
push @infill_points, Slic3r::Point->new_scale($args->{X}, $args->{Y});
|
||||
}
|
||||
}
|
||||
});
|
||||
my $convex_hull = convex_hull(\@perimeter_points);
|
||||
ok !(defined first { !$convex_hull->contains_point($_) } @infill_points), "infill does not exceed perimeters ($pattern)";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('infill_only_where_needed', 1);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('infill_extruder', 2);
|
||||
$config->set('infill_extrusion_width', 0.5);
|
||||
$config->set('fill_density', 40);
|
||||
$config->set('cooling', 0); # for preventing speeds from being altered
|
||||
$config->set('first_layer_speed', '100%'); # for preventing speeds from being altered
|
||||
|
||||
my $test = sub {
|
||||
my $print = Slic3r::Test::init_print('pyramid', config => $config);
|
||||
|
||||
my $tool = undef;
|
||||
my @infill_extrusions = (); # array of polylines
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->infill_extruder-1) {
|
||||
push @infill_extrusions, Slic3r::Line->new_scale(
|
||||
[ $self->X, $self->Y ],
|
||||
[ $info->{new_X}, $info->{new_Y} ],
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return 0 if !@infill_extrusions; # prevent calling convex_hull() with no points
|
||||
|
||||
my $convex_hull = convex_hull([ map $_->pp, map @$_, @infill_extrusions ]);
|
||||
return unscale unscale sum(map $_->area, @{offset([$convex_hull], scale(+$config->infill_extrusion_width/2))});
|
||||
};
|
||||
|
||||
my $tolerance = 5; # mm^2
|
||||
|
||||
$config->set('solid_infill_below_area', 0);
|
||||
ok $test->() < $tolerance,
|
||||
'no infill is generated when using infill_only_where_needed on a pyramid';
|
||||
|
||||
$config->set('solid_infill_below_area', 70);
|
||||
ok abs($test->() - $config->solid_infill_below_area) < $tolerance,
|
||||
'infill is only generated under the forced solid shells';
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 1);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('solid_infill_below_area', 20000000);
|
||||
$config->set('solid_infill_every_layers', 2);
|
||||
$config->set('perimeter_speed', 99);
|
||||
$config->set('external_perimeter_speed', 99);
|
||||
$config->set('cooling', 0);
|
||||
$config->set('first_layer_speed', '100%');
|
||||
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
my %layers_with_extrusion = ();
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd eq 'G1' && $info->{dist_XY} > 0 && $info->{extruding}) {
|
||||
if (($args->{F} // $self->F) != $config->perimeter_speed*60) {
|
||||
$layers_with_extrusion{$self->Z} = ($args->{F} // $self->F);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ok !%layers_with_extrusion,
|
||||
"solid_infill_below_area and solid_infill_every_layers are ignored when fill_density is 0";
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 3);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('layer_height', 0.2);
|
||||
$config->set('first_layer_height', 0.2);
|
||||
$config->set('nozzle_diameter', [0.35]);
|
||||
$config->set('infill_extruder', 2);
|
||||
$config->set('solid_infill_extruder', 2);
|
||||
$config->set('infill_extrusion_width', 0.52);
|
||||
$config->set('solid_infill_extrusion_width', 0.52);
|
||||
$config->set('first_layer_extrusion_width', 0);
|
||||
|
||||
my $print = Slic3r::Test::init_print('A', config => $config);
|
||||
my %infill = (); # Z => [ Line, Line ... ]
|
||||
my $tool = undef;
|
||||
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
if ($cmd =~ /^T(\d+)/) {
|
||||
$tool = $1;
|
||||
} elsif ($cmd eq 'G1' && $info->{extruding} && $info->{dist_XY} > 0) {
|
||||
if ($tool == $config->infill_extruder-1) {
|
||||
my $z = 1 * $self->Z;
|
||||
$infill{$z} ||= [];
|
||||
push @{$infill{$z}}, Slic3r::Line->new_scale(
|
||||
[ $self->X, $self->Y ],
|
||||
[ $info->{new_X}, $info->{new_Y} ],
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
my $grow_d = scale($config->infill_extrusion_width)/2;
|
||||
my $layer0_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.2} } ]);
|
||||
my $layer1_infill = union([ map @{$_->grow($grow_d)}, @{ $infill{0.4} } ]);
|
||||
my $diff = diff($layer0_infill, $layer1_infill);
|
||||
$diff = offset2_ex($diff, -$grow_d, +$grow_d);
|
||||
$diff = [ grep { $_->area > 2*(($grow_d*2)**2) } @$diff ];
|
||||
is scalar(@$diff), 0, 'no missing parts in solid shell when fill_density is 0';
|
||||
}
|
||||
|
||||
{
|
||||
# GH: #2697
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
@ -427,6 +455,78 @@ for my $pattern (qw(rectilinear honeycomb hilbertcurve concentric)) {
|
||||
my @holes = map @{$_->holes}, @$covered;
|
||||
ok sum(map unscale unscale $_->area*-1, @holes) < 1, 'no gaps between top solid infill and perimeters';
|
||||
}
|
||||
|
||||
{
|
||||
skip "The FillRectilinear2 does not fill the surface completely", 1;
|
||||
|
||||
my $test = sub {
|
||||
my ($expolygon, $flow_spacing, $angle, $density) = @_;
|
||||
|
||||
my $filler = Slic3r::Filler->new_from_type('rectilinear');
|
||||
$filler->set_bounding_box($expolygon->bounding_box);
|
||||
$filler->set_angle($angle // 0);
|
||||
# Adjust line spacing to fill the region.
|
||||
$filler->set_dont_adjust(0);
|
||||
$filler->set_link_max_length(scale(1.2*$flow_spacing));
|
||||
my $surface = Slic3r::Surface->new(
|
||||
surface_type => S_TYPE_BOTTOM,
|
||||
expolygon => $expolygon,
|
||||
);
|
||||
my $flow = Slic3r::Flow->new(
|
||||
width => $flow_spacing,
|
||||
height => 0.4,
|
||||
nozzle_diameter => $flow_spacing,
|
||||
);
|
||||
$filler->set_spacing($flow->spacing);
|
||||
my $paths = $filler->fill_surface(
|
||||
$surface,
|
||||
layer_height => $flow->height,
|
||||
density => $density // 1,
|
||||
);
|
||||
|
||||
# check whether any part was left uncovered
|
||||
my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $filler->spacing/2)}, @$paths;
|
||||
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
|
||||
|
||||
# ignore very small dots
|
||||
my $uncovered_filtered = [ grep $_->area > (scale $flow_spacing)**2, @$uncovered ];
|
||||
|
||||
is scalar(@$uncovered_filtered), 0, 'solid surface is fully filled';
|
||||
|
||||
if (0 && @$uncovered_filtered) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output("uncovered.svg",
|
||||
no_arrows => 1,
|
||||
expolygons => [ $expolygon ],
|
||||
blue_expolygons => [ @$uncovered ],
|
||||
red_expolygons => [ @$uncovered_filtered ],
|
||||
polylines => [ @$paths ],
|
||||
);
|
||||
exit;
|
||||
}
|
||||
};
|
||||
|
||||
my $expolygon = Slic3r::ExPolygon->new([
|
||||
[6883102, 9598327.01296997],
|
||||
[6883102, 20327272.01297],
|
||||
[3116896, 20327272.01297],
|
||||
[3116896, 9598327.01296997],
|
||||
]);
|
||||
$test->($expolygon, 0.55);
|
||||
|
||||
for (1..20) {
|
||||
$expolygon->scale(1.05);
|
||||
$test->($expolygon, 0.55);
|
||||
}
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new(
|
||||
[[59515297,5422499],[59531249,5578697],[59695801,6123186],[59965713,6630228],[60328214,7070685],[60773285,7434379],[61274561,7702115],[61819378,7866770],[62390306,7924789],[62958700,7866744],[63503012,7702244],[64007365,7434357],[64449960,7070398],[64809327,6634999],[65082143,6123325],[65245005,5584454],[65266967,5422499],[66267307,5422499],[66269190,8310081],[66275379,17810072],[66277259,20697500],[65267237,20697500],[65245004,20533538],[65082082,19994444],[64811462,19488579],[64450624,19048208],[64012101,18686514],[63503122,18415781],[62959151,18251378],[62453416,18198442],[62390147,18197355],[62200087,18200576],[61813519,18252990],[61274433,18415918],[60768598,18686517],[60327567,19047892],[59963609,19493297],[59695865,19994587],[59531222,20539379],[59515153,20697500],[58502480,20697500],[58502480,5422499]]
|
||||
);
|
||||
$test->($expolygon, 0.524341649025257);
|
||||
|
||||
$expolygon = Slic3r::ExPolygon->new([ scale_points [0,0], [98,0], [98,10], [0,10] ]);
|
||||
$test->($expolygon, 0.5, 45, 0.99); # non-solid infill
|
||||
}
|
||||
*/
|
||||
|
||||
bool test_if_solid_surface_filled(const ExPolygon& expolygon, double flow_spacing, double angle, double density)
|
||||
|
@ -188,6 +188,46 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||
REQUIRE(intersection.front().area() == Approx(match.area()));
|
||||
}
|
||||
}
|
||||
|
||||
ExPolygons expolygons { ExPolygon { square, hole_in_square } };
|
||||
WHEN("Clipping line 1") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 15, 18 }, { 15, 15 } } }, expolygons);
|
||||
THEN("line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(15, 18) - Vec2f(15, 16)).norm() == Approx(intersection.front().length()));
|
||||
}
|
||||
}
|
||||
WHEN("Clipping line 2") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 15, 15 }, { 15, 12 } } }, expolygons);
|
||||
THEN("line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(15, 14) - Vec2f(15, 12)).norm() == Approx(intersection.front().length()));
|
||||
}
|
||||
}
|
||||
WHEN("Clipping line 3") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 12, 18 }, { 18, 18 } } }, expolygons);
|
||||
THEN("line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(18, 18) - Vec2f(12, 18)).norm() == Approx(intersection.front().length()));
|
||||
}
|
||||
}
|
||||
WHEN("Clipping line 4") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 5, 15 }, { 30, 15 } } }, expolygons);
|
||||
THEN("line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(14, 15) - Vec2f(10, 15)).norm() == Approx(intersection.front().length()));
|
||||
REQUIRE((Vec2f(20, 15) - Vec2f(16, 15)).norm() == Approx(intersection[1].length()));
|
||||
}
|
||||
}
|
||||
WHEN("Clipping line 5") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 30, 15 }, { 5, 15 } } }, expolygons);
|
||||
THEN("reverse line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(20, 15) - Vec2f(16, 15)).norm() == Approx(intersection.front().length()));
|
||||
REQUIRE((Vec2f(14, 15) - Vec2f(10, 15)).norm() == Approx(intersection[1].length()));
|
||||
}
|
||||
}
|
||||
WHEN("Clipping line 6") {
|
||||
Polylines intersection = intersection_pl({ Polyline { { 10, 18 }, { 20, 18 } } }, expolygons);
|
||||
THEN("tangent line is clipped to square with hole") {
|
||||
REQUIRE((Vec2f(20, 18) - Vec2f(10, 18)).norm() == Approx(intersection.front().length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
GIVEN("square with hole 2") {
|
||||
// CCW oriented contour
|
||||
@ -223,6 +263,44 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") {
|
||||
}
|
||||
}
|
||||
}
|
||||
GIVEN("circle") {
|
||||
Slic3r::ExPolygon circle_with_hole { Polygon::new_scale({
|
||||
{ 151.8639,288.1192 }, {133.2778,284.6011}, { 115.0091,279.6997 }, { 98.2859,270.8606 }, { 82.2734,260.7933 },
|
||||
{ 68.8974,247.4181 }, { 56.5622,233.0777 }, { 47.7228,216.3558 }, { 40.1617,199.0172 }, { 36.6431,180.4328 },
|
||||
{ 34.932,165.2312 }, { 37.5567,165.1101 }, { 41.0547,142.9903 }, { 36.9056,141.4295 }, { 40.199,124.1277 },
|
||||
{ 47.7776,106.7972 }, { 56.6335,90.084 }, { 68.9831,75.7557 }, { 82.3712,62.3948 }, { 98.395,52.3429 },
|
||||
{ 115.1281,43.5199 }, { 133.4004,38.6374 }, { 151.9884,35.1378 }, { 170.8905,35.8571 }, { 189.6847,37.991 },
|
||||
{ 207.5349,44.2488 }, { 224.8662,51.8273 }, { 240.0786,63.067 }, { 254.407,75.4169 }, { 265.6311,90.6406 },
|
||||
{ 275.6832,106.6636 }, { 281.9225,124.52 }, { 286.8064,142.795 }, { 287.5061,161.696 }, { 286.7874,180.5972 },
|
||||
{ 281.8856,198.8664 }, { 275.6283,216.7169 }, { 265.5604,232.7294 }, { 254.3211,247.942 }, { 239.9802,260.2776 },
|
||||
{ 224.757,271.5022 }, { 207.4179,279.0635 }, { 189.5605,285.3035 }, { 170.7649,287.4188 }
|
||||
}) };
|
||||
circle_with_hole.holes = { Polygon::new_scale({
|
||||
{ 158.227,215.9007 }, { 164.5136,215.9007 }, { 175.15,214.5007 }, { 184.5576,210.6044 }, { 190.2268,207.8743 },
|
||||
{ 199.1462,201.0306 }, { 209.0146,188.346 }, { 213.5135,177.4829 }, { 214.6979,168.4866 }, { 216.1025,162.3325 },
|
||||
{ 214.6463,151.2703 }, { 213.2471,145.1399 }, { 209.0146,134.9203 }, { 199.1462,122.2357 }, { 189.8944,115.1366 },
|
||||
{ 181.2504,111.5567 }, { 175.5684,108.8205 }, { 164.5136,107.3655 }, { 158.2269,107.3655 }, { 147.5907,108.7656 },
|
||||
{ 138.183,112.6616 }, { 132.5135,115.3919 }, { 123.5943,122.2357 }, { 113.7259,134.92 }, { 109.2269,145.7834 },
|
||||
{ 108.0426,154.7799 }, { 106.638,160.9339 }, { 108.0941,171.9957 }, { 109.4933,178.1264 }, { 113.7259,188.3463 },
|
||||
{ 123.5943,201.0306 }, { 132.8461,208.1296 }, { 141.4901,211.7094 }, { 147.172,214.4458 }
|
||||
}) };
|
||||
THEN("contour is counter-clockwise") {
|
||||
REQUIRE(circle_with_hole.contour.is_counter_clockwise());
|
||||
}
|
||||
THEN("hole is counter-clockwise") {
|
||||
REQUIRE(circle_with_hole.holes.size() == 1);
|
||||
REQUIRE(circle_with_hole.holes.front().is_clockwise());
|
||||
}
|
||||
|
||||
WHEN("clipping a line") {
|
||||
auto line = Polyline::new_scale({ { 152.742,288.086671142818 }, { 152.742,34.166466971035 } });
|
||||
Polylines intersection = intersection_pl({ line }, { circle_with_hole });
|
||||
THEN("clipped to two pieces") {
|
||||
REQUIRE(intersection.front().length() == Approx((Vec2d(152742000, 215178843) - Vec2d(152742000, 288086661)).norm()));
|
||||
REQUIRE(intersection[1].length() == Approx((Vec2d(152742000, 35166477) - Vec2d(152742000, 108087507)).norm()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<e_ordering o = e_ordering::OFF, class P, class Tree>
|
||||
|
@ -53,11 +53,8 @@ set(XS_XSP_FILES
|
||||
${XSP_DIR}/ExtrusionLoop.xsp
|
||||
${XSP_DIR}/ExtrusionMultiPath.xsp
|
||||
${XSP_DIR}/ExtrusionPath.xsp
|
||||
${XSP_DIR}/ExtrusionSimulator.xsp
|
||||
${XSP_DIR}/Filler.xsp
|
||||
${XSP_DIR}/Flow.xsp
|
||||
${XSP_DIR}/GCode.xsp
|
||||
# ${XSP_DIR}/GCodeSender.xsp
|
||||
${XSP_DIR}/Geometry.xsp
|
||||
${XSP_DIR}/Layer.xsp
|
||||
${XSP_DIR}/Line.xsp
|
||||
|
@ -133,23 +133,6 @@ sub clone {
|
||||
);
|
||||
}
|
||||
|
||||
package Slic3r::ExtrusionSimulator;
|
||||
|
||||
sub new {
|
||||
my ($class, %args) = @_;
|
||||
return $class->_new();
|
||||
}
|
||||
|
||||
package Slic3r::Filler;
|
||||
|
||||
sub fill_surface {
|
||||
my ($self, $surface, %args) = @_;
|
||||
$self->set_density($args{density}) if defined($args{density});
|
||||
$self->set_dont_adjust($args{dont_adjust}) if defined($args{dont_adjust});
|
||||
$self->set_complete($args{complete}) if defined($args{complete});
|
||||
return $self->_fill_surface($surface);
|
||||
}
|
||||
|
||||
package Slic3r::Flow;
|
||||
|
||||
sub new {
|
||||
@ -255,19 +238,12 @@ for my $class (qw(
|
||||
Slic3r::ExtrusionMultiPath
|
||||
Slic3r::ExtrusionPath
|
||||
Slic3r::ExtrusionPath::Collection
|
||||
Slic3r::ExtrusionSimulator
|
||||
Slic3r::Filler
|
||||
Slic3r::Flow
|
||||
Slic3r::GCode
|
||||
Slic3r::GCode::PlaceholderParser
|
||||
Slic3r::Geometry::BoundingBox
|
||||
Slic3r::Geometry::BoundingBoxf
|
||||
Slic3r::Geometry::BoundingBoxf3
|
||||
Slic3r::GUI::_3DScene::GLShader
|
||||
Slic3r::GUI::_3DScene::GLVolume
|
||||
Slic3r::GUI::Preset
|
||||
Slic3r::GUI::PresetCollection
|
||||
Slic3r::GUI::Tab
|
||||
Slic3r::Layer
|
||||
Slic3r::Layer::Region
|
||||
Slic3r::Layer::Support
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
// #include <libslic3r/GCodeSender.hpp>
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* extern "C" { */
|
||||
|
@ -9,8 +9,6 @@ REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath");
|
||||
REGISTER_CLASS(ExtrusionPath, "ExtrusionPath");
|
||||
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
|
||||
REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
|
||||
REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator");
|
||||
REGISTER_CLASS(Filler, "Filler");
|
||||
REGISTER_CLASS(Flow, "Flow");
|
||||
REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer");
|
||||
REGISTER_CLASS(GCode, "GCode");
|
||||
|
@ -9,16 +9,6 @@
|
||||
|
||||
%{
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
JT_MITER = jtMiter
|
||||
JT_ROUND = jtRound
|
||||
JT_SQUARE = jtSquare
|
||||
CODE:
|
||||
RETVAL = ix;
|
||||
OUTPUT: RETVAL
|
||||
|
||||
Polygons
|
||||
offset(polygons, delta, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
|
||||
Polygons polygons
|
||||
@ -30,17 +20,6 @@ offset(polygons, delta, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
ExPolygons
|
||||
offset_ex(polygons, delta, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
|
||||
Polygons polygons
|
||||
const float delta
|
||||
Slic3r::ClipperLib::JoinType joinType
|
||||
double miterLimit
|
||||
CODE:
|
||||
RETVAL = offset_ex(polygons, delta, joinType, miterLimit);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
ExPolygons
|
||||
offset2_ex(polygons, delta1, delta2, joinType = Slic3r::ClipperLib::jtMiter, miterLimit = 3)
|
||||
Polygons polygons
|
||||
@ -73,44 +52,6 @@ diff_ex(subject, clip, safety_offset = false)
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polylines
|
||||
diff_pl(subject, clip)
|
||||
Polylines subject
|
||||
Polygons clip
|
||||
CODE:
|
||||
RETVAL = diff_pl(subject, clip);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polygons
|
||||
intersection(subject, clip, safety_offset = false)
|
||||
Polygons subject
|
||||
Polygons clip
|
||||
bool safety_offset
|
||||
CODE:
|
||||
RETVAL = intersection(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
ExPolygons
|
||||
intersection_ex(subject, clip, safety_offset = false)
|
||||
Polygons subject
|
||||
Polygons clip
|
||||
bool safety_offset
|
||||
CODE:
|
||||
RETVAL = intersection_ex(subject, clip, safety_offset ? ApplySafetyOffset::Yes : ApplySafetyOffset::No);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polylines
|
||||
intersection_pl(subject, clip)
|
||||
Polylines subject
|
||||
Polygons clip
|
||||
CODE:
|
||||
RETVAL = intersection_pl(subject, clip);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polygons
|
||||
union(subject, safety_offset = false)
|
||||
Polygons subject
|
||||
|
@ -1,50 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/ExtrusionSimulator.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::ExtrusionSimulator} class ExtrusionSimulator {
|
||||
~ExtrusionSimulator();
|
||||
%name{_new} ExtrusionSimulator();
|
||||
|
||||
Clone<ExtrusionSimulator> clone()
|
||||
%code{% RETVAL = THIS; %};
|
||||
|
||||
void set_image_size(Point *image_size)
|
||||
%code{% THIS->set_image_size(*image_size); %};
|
||||
void set_viewport(BoundingBox *viewport)
|
||||
%code{% THIS->set_viewport(*viewport); %};
|
||||
void set_bounding_box(BoundingBox *bbox)
|
||||
%code{% THIS->set_bounding_box(*bbox); %};
|
||||
|
||||
void reset_accumulator();
|
||||
void extrude_to_accumulator(ExtrusionPath *path, Point *shift, ExtrusionSimulationType simulationType)
|
||||
%code{% THIS->extrude_to_accumulator(*path, *shift, simulationType); %};
|
||||
void evaluate_accumulator(ExtrusionSimulationType simulationType);
|
||||
void* image_ptr()
|
||||
%code{% RETVAL = const_cast<void*>(const_cast<Slic3r::ExtrusionSimulator*>(THIS)->image_ptr()); %};
|
||||
|
||||
%{
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
%package{Slic3r::ExtrusionSimulator};
|
||||
%{
|
||||
|
||||
IV
|
||||
_constant()
|
||||
ALIAS:
|
||||
EXTRSIM_SIMPLE = ExtrusionSimulationSimple
|
||||
EXTRSIM_DONT_SPREAD = ExtrusionSimulationDontSpread
|
||||
EXTRSIM_SPREAD_NFULL = ExtrisopmSimulationSpreadNotOverfilled
|
||||
EXTRSIM_SPREAD_FULL = ExtrusionSimulationSpreadFull
|
||||
EXTRSIM_SPREAD_EXCESS = ExtrusionSimulationSpreadExcess
|
||||
PROTOTYPE:
|
||||
CODE:
|
||||
RETVAL = ix;
|
||||
OUTPUT: RETVAL
|
||||
|
||||
%}
|
@ -1,65 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/Fill/Fill.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Filler} class Filler {
|
||||
~Filler();
|
||||
|
||||
void set_bounding_box(BoundingBox *bbox)
|
||||
%code{% THIS->fill->set_bounding_box(*bbox); %};
|
||||
void set_spacing(coordf_t spacing)
|
||||
%code{% THIS->fill->spacing = spacing; %};
|
||||
coordf_t spacing()
|
||||
%code{% RETVAL = THIS->fill->spacing; %};
|
||||
void set_layer_id(size_t layer_id)
|
||||
%code{% THIS->fill->layer_id = layer_id; %};
|
||||
void set_z(coordf_t z)
|
||||
%code{% THIS->fill->z = z; %};
|
||||
void set_angle(float angle)
|
||||
%code{% THIS->fill->angle = angle; %};
|
||||
void set_link_max_length(coordf_t len)
|
||||
%code{% THIS->fill->link_max_length = len; %};
|
||||
void set_loop_clipping(coordf_t clipping)
|
||||
%code{% THIS->fill->loop_clipping = clipping; %};
|
||||
|
||||
bool use_bridge_flow()
|
||||
%code{% RETVAL = THIS->fill->use_bridge_flow(); %};
|
||||
bool no_sort()
|
||||
%code{% RETVAL = THIS->fill->no_sort(); %};
|
||||
|
||||
void set_density(float density)
|
||||
%code{% THIS->params.density = density; %};
|
||||
void set_dont_adjust(bool dont_adjust)
|
||||
%code{% THIS->params.dont_adjust = dont_adjust; %};
|
||||
|
||||
PolylineCollection* _fill_surface(Surface *surface)
|
||||
%code{%
|
||||
PolylineCollection *pc = NULL;
|
||||
if (THIS->fill != NULL) {
|
||||
pc = new PolylineCollection();
|
||||
pc->polylines = THIS->fill->fill_surface(surface, THIS->params);
|
||||
}
|
||||
RETVAL = pc;
|
||||
%};
|
||||
|
||||
%{
|
||||
|
||||
Filler*
|
||||
new_from_type(CLASS, type)
|
||||
char* CLASS;
|
||||
std::string type;
|
||||
CODE:
|
||||
Filler *filler = new Filler();
|
||||
filler->fill = Fill::new_from_type(type);
|
||||
RETVAL = filler;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/GCodeSender.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::GCode::Sender} class GCodeSender {
|
||||
GCodeSender();
|
||||
~GCodeSender();
|
||||
|
||||
bool connect(std::string port, unsigned int baud_rate);
|
||||
void disconnect();
|
||||
bool is_connected();
|
||||
bool wait_connected(unsigned int timeout = 3);
|
||||
int queue_size();
|
||||
void send(std::string s, bool priority = false);
|
||||
void pause_queue();
|
||||
void resume_queue();
|
||||
void purge_queue(bool priority = false);
|
||||
std::vector<std::string> purge_log();
|
||||
std::string getT();
|
||||
std::string getB();
|
||||
};
|
@ -41,12 +41,6 @@
|
||||
Clone<BoundingBox> bounding_box();
|
||||
Clone<Point> point_projection(Point* point)
|
||||
%code{% RETVAL = THIS->point_projection(*point); %};
|
||||
Clone<Point> intersection(Line* line)
|
||||
%code{%
|
||||
Point p;
|
||||
(void)THIS->intersection(*line, &p);
|
||||
RETVAL = p;
|
||||
%};
|
||||
Clone<Point> first_intersection(Line* line)
|
||||
%code{%
|
||||
Point p;
|
||||
|
@ -82,16 +82,6 @@ Surface::polygons()
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Surfaces
|
||||
Surface::offset(delta, joinType = ClipperLib::jtMiter, miterLimit = 3)
|
||||
const float delta
|
||||
Slic3r::ClipperLib::JoinType joinType
|
||||
double miterLimit
|
||||
CODE:
|
||||
surfaces_append(RETVAL, offset_ex(THIS->expolygon, delta, joinType, miterLimit), *THIS);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
|
@ -118,14 +118,6 @@ ExtrusionLoop* O_OBJECT_SLIC3R
|
||||
Ref<ExtrusionLoop> O_OBJECT_SLIC3R_T
|
||||
Clone<ExtrusionLoop> O_OBJECT_SLIC3R_T
|
||||
|
||||
ExtrusionSimulator* O_OBJECT_SLIC3R
|
||||
Ref<ExtrusionSimulator> O_OBJECT_SLIC3R_T
|
||||
Clone<ExtrusionSimulator> O_OBJECT_SLIC3R_T
|
||||
|
||||
Filler* O_OBJECT_SLIC3R
|
||||
Ref<Filler> O_OBJECT_SLIC3R_T
|
||||
Clone<Filler> O_OBJECT_SLIC3R_T
|
||||
|
||||
Flow* O_OBJECT_SLIC3R
|
||||
Ref<Flow> O_OBJECT_SLIC3R_T
|
||||
Clone<Flow> O_OBJECT_SLIC3R_T
|
||||
|
@ -58,9 +58,6 @@
|
||||
%typemap{ExPolygonCollection*};
|
||||
%typemap{Ref<ExPolygonCollection>}{simple};
|
||||
%typemap{Clone<ExPolygonCollection>}{simple};
|
||||
%typemap{Filler*};
|
||||
%typemap{Ref<Filler>}{simple};
|
||||
%typemap{Clone<Filler>}{simple};
|
||||
%typemap{Flow*};
|
||||
%typemap{Ref<Flow>}{simple};
|
||||
%typemap{Clone<Flow>}{simple};
|
||||
@ -88,9 +85,6 @@
|
||||
%typemap{ExtrusionLoop*};
|
||||
%typemap{Ref<ExtrusionLoop>}{simple};
|
||||
%typemap{Clone<ExtrusionLoop>}{simple};
|
||||
%typemap{ExtrusionSimulator*};
|
||||
%typemap{Ref<ExtrusionSimulator>}{simple};
|
||||
%typemap{Clone<ExtrusionSimulator>}{simple};
|
||||
%typemap{TriangleMesh*};
|
||||
%typemap{Ref<TriangleMesh>}{simple};
|
||||
%typemap{Clone<TriangleMesh>}{simple};
|
||||
|
Loading…
x
Reference in New Issue
Block a user