Merge branch 'master' into xsdata
Conflicts: lib/Slic3r/GCode.pm xs/src/Point.hpp
This commit is contained in:
commit
31809d473f
@ -13,7 +13,7 @@ sub read_file {
|
|||||||
my ($vertices, $facets) = @{$tmesh->ToPerl};
|
my ($vertices, $facets) = @{$tmesh->ToPerl};
|
||||||
|
|
||||||
my $model = Slic3r::Model->new;
|
my $model = Slic3r::Model->new;
|
||||||
my $object = $model->add_object(vertices => $vertices);
|
my $object = $model->add_object(vertices => $vertices, mesh_stats => $tmesh->stats);
|
||||||
my $volume = $object->add_volume(facets => $facets);
|
my $volume = $object->add_volume(facets => $facets);
|
||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
@ -96,9 +96,13 @@ sub change_layer {
|
|||||||
my ($layer) = @_;
|
my ($layer) = @_;
|
||||||
|
|
||||||
$self->layer($layer);
|
$self->layer($layer);
|
||||||
|
|
||||||
|
# avoid computing overhangs if they're not needed
|
||||||
$self->_layer_overhangs(
|
$self->_layer_overhangs(
|
||||||
$layer->id > 0
|
$layer->id > 0 && ($Slic3r::Config->overhangs || $Slic3r::Config->start_perimeters_at_non_overhang)
|
||||||
? [ map $_->expolygon->arrayref, grep $_->surface_type == S_TYPE_BOTTOM, map @{$_->slices}, @{$layer->regions} ]
|
? [ map $_->expolygon->arrayref, grep $_->surface_type == S_TYPE_BOTTOM, map @{$_->slices}, @{$layer->regions} ]
|
||||||
|
$layer->id > 0 && ($Slic3r::Config->overhangs || $Slic3r::Config->start_perimeters_at_non_overhang)
|
||||||
|
? [ map $_->expolygon, grep $_->surface_type == S_TYPE_BOTTOM, map @{$_->slices}, @{$layer->regions} ]
|
||||||
: []
|
: []
|
||||||
);
|
);
|
||||||
if ($self->config->avoid_crossing_perimeters) {
|
if ($self->config->avoid_crossing_perimeters) {
|
||||||
@ -168,8 +172,9 @@ sub extrude_loop {
|
|||||||
@candidates = @concave;
|
@candidates = @concave;
|
||||||
if (!@candidates) {
|
if (!@candidates) {
|
||||||
# if none, look for any non-overhang vertex
|
# if none, look for any non-overhang vertex
|
||||||
@candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs),
|
if ($Slic3r::Config->start_perimeters_at_non_overhang) {
|
||||||
@{$loop->polygon};
|
@candidates = grep !Boost::Geometry::Utils::point_covered_by_multi_polygon($_, $self->_layer_overhangs), @{$loop->polygon};
|
||||||
|
}
|
||||||
if (!@candidates) {
|
if (!@candidates) {
|
||||||
# if none, all points are valid candidates
|
# if none, all points are valid candidates
|
||||||
@candidates = @{$loop->polygon};
|
@candidates = @{$loop->polygon};
|
||||||
|
@ -317,6 +317,7 @@ sub load_file {
|
|||||||
input_file => $input_file,
|
input_file => $input_file,
|
||||||
input_file_object_id => $i,
|
input_file_object_id => $i,
|
||||||
model_object => $model->objects->[$i],
|
model_object => $model->objects->[$i],
|
||||||
|
mesh_stats => $model->objects->[$i]->mesh_stats, # so that we can free model_object
|
||||||
instances => [
|
instances => [
|
||||||
$model->objects->[$i]->instances
|
$model->objects->[$i]->instances
|
||||||
? (map $_->offset, @{$model->objects->[$i]->instances})
|
? (map $_->offset, @{$model->objects->[$i]->instances})
|
||||||
@ -1070,6 +1071,7 @@ sub OnDropFiles {
|
|||||||
package Slic3r::GUI::Plater::Object;
|
package Slic3r::GUI::Plater::Object;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
|
use List::Util qw(first);
|
||||||
use Math::ConvexHull::MonotoneChain qw();
|
use Math::ConvexHull::MonotoneChain qw();
|
||||||
use Slic3r::Geometry qw(X Y Z MIN MAX deg2rad);
|
use Slic3r::Geometry qw(X Y Z MIN MAX deg2rad);
|
||||||
|
|
||||||
@ -1086,6 +1088,7 @@ has 'thumbnail' => (is => 'rw', trigger => \&_transform_thumbnail);
|
|||||||
has 'transformed_thumbnail' => (is => 'rw');
|
has 'transformed_thumbnail' => (is => 'rw');
|
||||||
has 'thumbnail_scaling_factor' => (is => 'rw', trigger => \&_transform_thumbnail);
|
has 'thumbnail_scaling_factor' => (is => 'rw', trigger => \&_transform_thumbnail);
|
||||||
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
|
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
|
||||||
|
has 'mesh_stats' => (is => 'rw');
|
||||||
|
|
||||||
# statistics
|
# statistics
|
||||||
has 'facets' => (is => 'rw');
|
has 'facets' => (is => 'rw');
|
||||||
@ -1111,7 +1114,18 @@ sub _trigger_model_object {
|
|||||||
sub check_manifoldness {
|
sub check_manifoldness {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
if ($self->mesh_stats) {
|
||||||
|
if (first { $self->mesh_stats->{$_} > 0 } qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)) {
|
||||||
|
warn "Warning: the input file contains manifoldness errors. "
|
||||||
|
. "Slic3r repaired it successfully by guessing what the correct shape should be, "
|
||||||
|
. "but you might still want to inspect the G-code before printing.\n";
|
||||||
|
$self->is_manifold(0);
|
||||||
|
} else {
|
||||||
|
$self->is_manifold(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
$self->is_manifold($self->get_model_object->check_manifoldness);
|
$self->is_manifold($self->get_model_object->check_manifoldness);
|
||||||
|
}
|
||||||
return $self->is_manifold;
|
return $self->is_manifold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use base 'Wx::Dialog';
|
|||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my ($parent, %params) = @_;
|
my ($parent, %params) = @_;
|
||||||
my $self = $class->SUPER::new($parent, -1, "Object", wxDefaultPosition, [500,350], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
my $self = $class->SUPER::new($parent, -1, "Object", wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||||
$self->{object} = $params{object};
|
$self->{object} = $params{object};
|
||||||
|
|
||||||
$self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
$self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
||||||
@ -50,7 +50,7 @@ sub new {
|
|||||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
|
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
|
||||||
$self->{object} = $params{object};
|
$self->{object} = $params{object};
|
||||||
|
|
||||||
my $grid_sizer = Wx::FlexGridSizer->new(3, 2, 10, 5);
|
my $grid_sizer = Wx::FlexGridSizer->new(3, 2, 5, 5);
|
||||||
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
|
||||||
$grid_sizer->AddGrowableCol(1);
|
$grid_sizer->AddGrowableCol(1);
|
||||||
|
|
||||||
@ -76,14 +76,34 @@ sub get_properties {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
my $object = $self->{object};
|
my $object = $self->{object};
|
||||||
return [
|
my $properties = [
|
||||||
['Name' => $object->name],
|
['Name' => $object->name],
|
||||||
['Size' => sprintf "%.2f x %.2f x %.2f", @{$object->transformed_size}],
|
['Size' => sprintf "%.2f x %.2f x %.2f", @{$object->transformed_size}],
|
||||||
['Facets' => $object->facets],
|
['Facets' => $object->facets],
|
||||||
['Vertices' => $object->vertices],
|
['Vertices' => $object->vertices],
|
||||||
['Materials' => $object->materials],
|
['Materials' => $object->materials],
|
||||||
['Two-Manifold' => $object->is_manifold ? 'Yes' : 'No'],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (my $stats = $object->mesh_stats) {
|
||||||
|
push @$properties,
|
||||||
|
[ 'Shells' => $stats->{number_of_parts} ],
|
||||||
|
[ 'Volume' => sprintf('%.2f', $stats->{volume} * ($object->scale**3)) ],
|
||||||
|
[ 'Degenerate facets' => $stats->{degenerate_facets} ],
|
||||||
|
[ 'Edges fixed' => $stats->{edges_fixed} ],
|
||||||
|
[ 'Facets removed' => $stats->{facets_removed} ],
|
||||||
|
[ 'Facets added' => $stats->{facets_added} ],
|
||||||
|
[ 'Facets reversed' => $stats->{facets_reversed} ],
|
||||||
|
[ 'Backwards edges' => $stats->{backwards_edges} ],
|
||||||
|
# we don't show normals_fixed because we never provide normals
|
||||||
|
# to admesh, so it generates normals for all facets
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
push @$properties,
|
||||||
|
['Two-Manifold' => $object->is_manifold ? 'Yes' : 'No'],
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
package Slic3r::GUI::Plater::ObjectDialog::PreviewTab;
|
package Slic3r::GUI::Plater::ObjectDialog::PreviewTab;
|
||||||
|
@ -297,6 +297,7 @@ has 'vertices' => (is => 'ro', default => sub { [] });
|
|||||||
has 'volumes' => (is => 'ro', default => sub { [] });
|
has 'volumes' => (is => 'ro', default => sub { [] });
|
||||||
has 'instances' => (is => 'rw');
|
has 'instances' => (is => 'rw');
|
||||||
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
|
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
|
||||||
|
has 'mesh_stats' => (is => 'rw');
|
||||||
has '_bounding_box' => (is => 'rw');
|
has '_bounding_box' => (is => 'rw');
|
||||||
|
|
||||||
sub add_volume {
|
sub add_volume {
|
||||||
|
@ -215,17 +215,34 @@ sub make_loops {
|
|||||||
}
|
}
|
||||||
@lines = grep $_, @lines;
|
@lines = grep $_, @lines;
|
||||||
|
|
||||||
|
# build a map of lines by EDGE_A_ID and A_ID
|
||||||
|
my %by_edge_a_id = my %by_a_id = ();
|
||||||
|
for (0..$#lines) {
|
||||||
|
if (defined(my $edge_a_id = $lines[$_][I_EDGE_A_ID])) {
|
||||||
|
$by_edge_a_id{$edge_a_id} //= [];
|
||||||
|
push @{ $by_edge_a_id{$edge_a_id} }, $_;
|
||||||
|
}
|
||||||
|
if (defined(my $a_id = $lines[$_][I_A_ID])) {
|
||||||
|
$by_a_id{$a_id} //= [];
|
||||||
|
push @{ $by_a_id{$a_id} }, $_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
my (@polygons, @failed_loops) = ();
|
my (@polygons, @failed_loops) = ();
|
||||||
CYCLE: while (@lines) {
|
my %used_lines = ();
|
||||||
|
CYCLE: while (1) {
|
||||||
# take first spare line and start a new loop
|
# take first spare line and start a new loop
|
||||||
my @loop = (shift @lines);
|
my $first_idx = first { !exists $used_lines{$_} } 0..$#lines;
|
||||||
|
last if !defined $first_idx;
|
||||||
|
$used_lines{$first_idx} = 1;
|
||||||
|
my @loop = ($lines[$first_idx]);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
# find a line starting where last one finishes
|
# find a line starting where last one finishes
|
||||||
my $line_idx;
|
my $line_idx;
|
||||||
$line_idx = first { defined $lines[$_][I_EDGE_A_ID] && $lines[$_][I_EDGE_A_ID] == $loop[-1][I_EDGE_B_ID] } 0..$#lines
|
$line_idx = first { !exists $used_lines{$_} } @{ $by_edge_a_id{$loop[-1][I_EDGE_B_ID]} // [] }
|
||||||
if defined $loop[-1][I_EDGE_B_ID];
|
if defined $loop[-1][I_EDGE_B_ID];
|
||||||
$line_idx ||= first { defined $lines[$_][I_A_ID] && $lines[$_][I_A_ID] == $loop[-1][I_B_ID] } 0..$#lines
|
$line_idx //= first { !exists $used_lines{$_} } @{ $by_a_id{$loop[-1][I_B_ID]} // [] }
|
||||||
if defined $loop[-1][I_B_ID];
|
if defined $loop[-1][I_B_ID];
|
||||||
|
|
||||||
if (!defined $line_idx) {
|
if (!defined $line_idx) {
|
||||||
@ -244,7 +261,8 @@ sub make_loops {
|
|||||||
push @failed_loops, [@loop];
|
push @failed_loops, [@loop];
|
||||||
next CYCLE;
|
next CYCLE;
|
||||||
}
|
}
|
||||||
push @loop, splice @lines, $line_idx, 1;
|
push @loop, $lines[$line_idx];
|
||||||
|
$used_lines{$line_idx} = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ extern "C" {
|
|||||||
|
|
||||||
#include "Point.hpp"
|
#include "Point.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
typedef std::vector<Point> Polygon;
|
typedef std::vector<Point> Polygon;
|
||||||
typedef std::vector<Polygon> Polygons;
|
typedef std::vector<Polygon> Polygons;
|
||||||
|
|
||||||
@ -98,4 +100,6 @@ polygon2perl(Polygon& poly) {
|
|||||||
return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Polygon", GV_ADD));
|
return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Polygon", GV_ADD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,6 +10,8 @@ extern "C" {
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
class Point
|
class Point
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -36,4 +38,6 @@ point2perl(Point& point) {
|
|||||||
return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Point", GV_ADD));
|
return sv_bless(newRV_noinc((SV*)av), gv_stashpv("Slic3r::Point", GV_ADD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "TriangleMesh.hpp"
|
#include "TriangleMesh.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
TriangleMesh::TriangleMesh() {}
|
TriangleMesh::TriangleMesh() {}
|
||||||
TriangleMesh::~TriangleMesh() {
|
TriangleMesh::~TriangleMesh() {
|
||||||
stl_close(&stl);
|
stl_close(&stl);
|
||||||
@ -86,6 +88,12 @@ TriangleMesh::Repair() {
|
|||||||
|
|
||||||
// normal_values
|
// normal_values
|
||||||
stl_fix_normal_values(&stl);
|
stl_fix_normal_values(&stl);
|
||||||
|
|
||||||
|
// always calculate the volume and reverse all normals if volume is negative
|
||||||
|
stl_calculate_volume(&stl);
|
||||||
|
|
||||||
|
// neighbors
|
||||||
|
stl_verify_neighbors(&stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -130,3 +138,5 @@ TriangleMesh::ToPerl() {
|
|||||||
av_store(result, 1, newRV_noinc((SV*)facets));
|
av_store(result, 1, newRV_noinc((SV*)facets));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -10,6 +10,8 @@ extern "C" {
|
|||||||
#include "ppport.h"
|
#include "ppport.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
class TriangleMesh
|
class TriangleMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -20,8 +22,9 @@ class TriangleMesh
|
|||||||
void Repair();
|
void Repair();
|
||||||
void WriteOBJFile(char* output_file);
|
void WriteOBJFile(char* output_file);
|
||||||
AV* ToPerl();
|
AV* ToPerl();
|
||||||
private:
|
|
||||||
stl_file stl;
|
stl_file stl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,8 @@ extern "C" {
|
|||||||
#include "ppport.h"
|
#include "ppport.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
class ZTable
|
class ZTable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -21,4 +23,6 @@ ZTable::ZTable(std::vector<unsigned int>* ztable) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Slic3r {}
|
||||||
|
using namespace Slic3r;
|
||||||
|
|
||||||
#define av_store_point_xy(AV, X, Y) \
|
#define av_store_point_xy(AV, X, Y) \
|
||||||
av_store(AV, 0, newSViv(X)); \
|
av_store(AV, 0, newSViv(X)); \
|
||||||
av_store(AV, 1, newSViv(Y))
|
av_store(AV, 1, newSViv(Y))
|
||||||
|
@ -4,7 +4,7 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use Slic3r::XS;
|
use Slic3r::XS;
|
||||||
use Test::More tests => 3;
|
use Test::More tests => 5;
|
||||||
|
|
||||||
is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!',
|
is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!',
|
||||||
'hello world';
|
'hello world';
|
||||||
@ -21,6 +21,10 @@ my $cube = {
|
|||||||
my ($vertices, $facets) = @{$m->ToPerl};
|
my ($vertices, $facets) = @{$m->ToPerl};
|
||||||
is_deeply $vertices, $cube->{vertices}, 'vertices arrayref roundtrip';
|
is_deeply $vertices, $cube->{vertices}, 'vertices arrayref roundtrip';
|
||||||
is_deeply $facets, $cube->{facets}, 'facets arrayref roundtrip';
|
is_deeply $facets, $cube->{facets}, 'facets arrayref roundtrip';
|
||||||
|
|
||||||
|
my $stats = $m->stats;
|
||||||
|
is $stats->{number_of_facets}, scalar(@{ $cube->{facets} }), 'stats.number_of_facets';
|
||||||
|
ok abs($stats->{volume} - 20*20*20) < 1E-3, 'stats.volume';
|
||||||
}
|
}
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
@ -13,6 +13,27 @@
|
|||||||
void Repair();
|
void Repair();
|
||||||
void WriteOBJFile(char* output_file);
|
void WriteOBJFile(char* output_file);
|
||||||
AV* ToPerl();
|
AV* ToPerl();
|
||||||
|
%{
|
||||||
|
|
||||||
|
SV*
|
||||||
|
TriangleMesh::stats()
|
||||||
|
CODE:
|
||||||
|
HV* hv = newHV();
|
||||||
|
(void)hv_stores( hv, "number_of_facets", newSViv(THIS->stl.stats.number_of_facets) );
|
||||||
|
(void)hv_stores( hv, "number_of_parts", newSViv(THIS->stl.stats.number_of_parts) );
|
||||||
|
(void)hv_stores( hv, "volume", newSVnv(THIS->stl.stats.volume) );
|
||||||
|
(void)hv_stores( hv, "degenerate_facets", newSViv(THIS->stl.stats.degenerate_facets) );
|
||||||
|
(void)hv_stores( hv, "edges_fixed", newSViv(THIS->stl.stats.edges_fixed) );
|
||||||
|
(void)hv_stores( hv, "facets_removed", newSViv(THIS->stl.stats.facets_removed) );
|
||||||
|
(void)hv_stores( hv, "facets_added", newSViv(THIS->stl.stats.facets_added) );
|
||||||
|
(void)hv_stores( hv, "facets_reversed", newSViv(THIS->stl.stats.facets_reversed) );
|
||||||
|
(void)hv_stores( hv, "backwards_edges", newSViv(THIS->stl.stats.backwards_edges) );
|
||||||
|
(void)hv_stores( hv, "normals_fixed", newSViv(THIS->stl.stats.normals_fixed) );
|
||||||
|
RETVAL = (SV*)newRV_noinc((SV*)hv);
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
|
%}
|
||||||
};
|
};
|
||||||
|
|
||||||
%package{Slic3r::TriangleMesh::XS};
|
%package{Slic3r::TriangleMesh::XS};
|
||||||
|
Loading…
Reference in New Issue
Block a user