Show vertical projection instead of convex hull for objects with <= 2000 facets. #780

This commit is contained in:
Alessandro Ranellucci 2012-11-24 00:13:04 +01:00
parent e6afebb982
commit 116ab446e3
3 changed files with 76 additions and 16 deletions

View File

@ -164,6 +164,11 @@ sub simplify {
$_->simplify(@_) for @$self;
}
sub scale {
my $self = shift;
$_->scale(@_) for @$self;
}
sub translate {
my $self = shift;
$_->translate(@_) for @$self;
@ -300,4 +305,34 @@ sub medial_axis {
return @result;
}
package Slic3r::ExPolygon::Collection;
use Moo;
use Slic3r::Geometry qw(X1 Y1);
has 'expolygons' => (is => 'ro', default => sub { [] });
sub clone {
my $self = shift;
return (ref $self)->new(
expolygons => [ map $_->clone, @{$self->expolygons} ],
);
}
sub align_to_origin {
my $self = shift;
my @bb = Slic3r::Geometry::bounding_box([ map @$_, map @$_, @{$self->expolygons} ]);
$_->translate(-$bb[X1], -$bb[Y1]) for @{$self->expolygons};
}
sub rotate {
my $self = shift;
$_->rotate(@_) for @{$self->expolygons};
}
sub size {
my $self = shift;
return [ Slic3r::Geometry::size_2D([ map @$_, map @$_, @{$self->expolygons} ]) ];
}
1;

View File

@ -727,6 +727,7 @@ sub make_thumbnail {
my $object = $self->{objects}[$obj_idx];
$object->thumbnail_scaling_factor($self->{scaling_factor});
my $cb = sub {
$Slic3r::Geometry::Clipper::clipper = Math::Clipper->new if $Slic3r::have_threads;
my $thumbnail = $object->make_thumbnail;
if ($Slic3r::have_threads) {
@ -857,7 +858,8 @@ sub repaint {
for my $instance_idx (0 .. $#{$object->instances}) {
my $instance = $object->instances->[$instance_idx];
push @{$parent->{object_previews}}, [ $obj_idx, $instance_idx, $object->thumbnail->clone ];
$parent->{object_previews}->[-1][2]->translate(map $parent->to_pixel($instance->[$_]) + $parent->{shift}[$_], (X,Y));
$_->translate(map $parent->to_pixel($instance->[$_]) + $parent->{shift}[$_], (X,Y))
for @{$parent->{object_previews}->[-1][2]->expolygons};
my $drag_object = $self->{drag_object};
if (defined $drag_object && $obj_idx == $drag_object->[0] && $instance_idx == $drag_object->[1]) {
@ -867,11 +869,12 @@ sub repaint {
} else {
$dc->SetBrush($parent->{objects_brush});
}
$dc->DrawPolygon($parent->_y($parent->{object_previews}->[-1][2]), 0, 0);
$dc->DrawPolygon($parent->_y($_), 0, 0) for map $_->contour, @{ $parent->{object_previews}->[-1][2]->expolygons };
# if sequential printing is enabled and we have more than one object
if ($parent->{config}->complete_objects && (map @{$_->instances}, @{$parent->{objects}}) > 1) {
my $clearance = +($parent->{object_previews}->[-1][2]->offset($parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0];
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ]));
my $clearance = +($convex_hull->offset($parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0];
$dc->SetPen($parent->{clearance_pen});
$dc->SetBrush($parent->{transparent_brush});
$dc->DrawPolygon($parent->_y($clearance), 0, 0);
@ -881,7 +884,7 @@ sub repaint {
# draw skirt
if (@{$parent->{object_previews}} && $parent->{config}->skirts) {
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->[2]}, @{$parent->{object_previews}} ]));
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ]));
$convex_hull = +($convex_hull->offset($parent->{config}->skirt_distance * $parent->{scaling_factor}, 1, JT_ROUND))[0];
$dc->SetPen($parent->{skirt_pen});
$dc->SetBrush($parent->{transparent_brush});
@ -903,7 +906,7 @@ sub mouse_event {
$parent->selection_changed(0);
for my $preview (@{$parent->{object_previews}}) {
my ($obj_idx, $instance_idx, $thumbnail) = @$preview;
if ($thumbnail->encloses_point($pos)) {
if (first { $_->contour->encloses_point($pos) } @{$thumbnail->expolygons}) {
$parent->{selected_objects} = [ [$obj_idx, $instance_idx] ];
$parent->{list}->Select($obj_idx, 1);
$parent->selection_changed(1);
@ -934,7 +937,7 @@ sub mouse_event {
} elsif ($event->Moving) {
my $cursor = wxSTANDARD_CURSOR;
for my $preview (@{$parent->{object_previews}}) {
if ($preview->[2]->encloses_point($pos)) {
if (first { $_->contour->encloses_point($pos) } @{ $preview->[2]->expolygons }) {
$cursor = Wx::Cursor->new(wxCURSOR_HAND);
last;
}
@ -1114,19 +1117,26 @@ sub make_thumbnail {
my $self = shift;
my @points = map [ @$_[X,Y] ], @{$self->model_object->mesh->vertices};
my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points));
for (@$convex_hull) {
my $mesh = $self->model_object->mesh;
my $thumbnail = Slic3r::ExPolygon::Collection->new(
expolygons => (@{$mesh->facets} <= 2000)
? $mesh->horizontal_projection
: [ Slic3r::ExPolygon->new(convex_hull($mesh->vertices)) ],
);
for (map @$_, map @$_, @{$thumbnail->expolygons}) {
@$_ = map $_ * $self->thumbnail_scaling_factor, @$_;
}
$convex_hull->simplify(0.3);
$convex_hull->rotate(Slic3r::Geometry::deg2rad($self->rotate));
$convex_hull->scale($self->scale);
$convex_hull->align_to_origin;
for (@{$thumbnail->expolygons}) {
$_->simplify(0.3);
$_->rotate(Slic3r::Geometry::deg2rad($self->rotate));
$_->scale($self->scale);
}
$thumbnail->align_to_origin;
$self->thumbnail($convex_hull); # ignored in multi-threaded environments
$self->thumbnail($thumbnail); # ignored in multi-threaded environments
$self->free_model_object;
return $convex_hull;
return $thumbnail;
}
sub set_rotation {
@ -1150,7 +1160,7 @@ sub set_scale {
return if $factor == 1;
$self->size->[$_] *= $factor for X,Y,Z;
if ($self->thumbnail) {
$self->thumbnail->scale($factor);
$_->scale($factor) for @{$self->thumbnail->expolygons};
$self->thumbnail->align_to_origin;
}
$self->scale($scale);

View File

@ -2,6 +2,7 @@ package Slic3r::TriangleMesh;
use Moo;
use Slic3r::Geometry qw(X Y Z A B unscale same_point);
use Slic3r::Geometry::Clipper qw(union_ex);
# public
has 'vertices' => (is => 'ro', required => 1); # id => [$x,$y,$z]
@ -578,4 +579,18 @@ sub split_mesh {
return @meshes;
}
sub horizontal_projection {
my $self = shift;
my @f = ();
foreach my $facet (@{$self->facets}) {
push @f, [ map [ @{$self->vertices->[$_]}[X,Y] ], @$facet ];
}
my $scale_vector = Math::Clipper::integerize_coordinate_sets({ bits => 32 }, @f);
my $union = union_ex([ Slic3r::Geometry::Clipper::offset(\@f, 1) ]);
Math::Clipper::unscale_coordinate_sets($scale_vector, $_) for @$union;
return $union;
}
1;