mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-05 17:40:44 +08:00
implemented quadratic control and interpolation
This commit is contained in:
parent
c3018d600a
commit
747d2dfca4
@ -19,6 +19,8 @@ sub new {
|
|||||||
$self->SetBackgroundColour(Wx::wxWHITE);
|
$self->SetBackgroundColour(Wx::wxWHITE);
|
||||||
|
|
||||||
$self->{line_pen} = Wx::Pen->new(Wx::Colour->new(50,50,50), 1, wxSOLID);
|
$self->{line_pen} = Wx::Pen->new(Wx::Colour->new(50,50,50), 1, wxSOLID);
|
||||||
|
$self->{interactive_pen} = Wx::Pen->new(Wx::Colour->new(255,0,0), 1, wxSOLID);
|
||||||
|
$self->{resulting_pen} = Wx::Pen->new(Wx::Colour->new(0,255,0), 1, wxSOLID);
|
||||||
|
|
||||||
$self->{user_drawn_background} = $^O ne 'darwin';
|
$self->{user_drawn_background} = $^O ne 'darwin';
|
||||||
|
|
||||||
@ -29,6 +31,8 @@ sub new {
|
|||||||
$self->{max_layer_height} = 0.4;
|
$self->{max_layer_height} = 0.4;
|
||||||
$self->{object_height} = 1.0;
|
$self->{object_height} = 1.0;
|
||||||
$self->{layer_points} = ();
|
$self->{layer_points} = ();
|
||||||
|
$self->{interactive_points} = ();
|
||||||
|
$self->{resulting_points} = ();
|
||||||
|
|
||||||
|
|
||||||
EVT_PAINT($self, \&repaint);
|
EVT_PAINT($self, \&repaint);
|
||||||
@ -48,8 +52,6 @@ sub repaint {
|
|||||||
my $dc = Wx::AutoBufferedPaintDC->new($self);
|
my $dc = Wx::AutoBufferedPaintDC->new($self);
|
||||||
my $size = $self->GetSize;
|
my $size = $self->GetSize;
|
||||||
my @size = ($size->GetWidth, $size->GetHeight);
|
my @size = ($size->GetWidth, $size->GetHeight);
|
||||||
|
|
||||||
print "repaint\n";
|
|
||||||
|
|
||||||
|
|
||||||
if ($self->{user_drawn_background}) {
|
if ($self->{user_drawn_background}) {
|
||||||
@ -70,9 +72,25 @@ sub repaint {
|
|||||||
$dc->DrawLabel(sprintf('%.4g', $self->{min_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_LEFT | wxALIGN_BOTTOM);
|
$dc->DrawLabel(sprintf('%.4g', $self->{min_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_LEFT | wxALIGN_BOTTOM);
|
||||||
$dc->DrawLabel(sprintf('%.4g', $self->{max_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_RIGHT | wxALIGN_BOTTOM);
|
$dc->DrawLabel(sprintf('%.4g', $self->{max_layer_height}), Wx::Rect->new(0, $size[1]/2, $size[0], $size[1]/2), wxALIGN_RIGHT | wxALIGN_BOTTOM);
|
||||||
|
|
||||||
# draw current layers as lines
|
|
||||||
|
# draw interpolated (user modified) layers as lines
|
||||||
my $last_z = 0.0;
|
my $last_z = 0.0;
|
||||||
my @points = ();
|
my @points = ();
|
||||||
|
foreach my $z (@{$self->{interactive_points}}) {
|
||||||
|
my $layer_h = $z - $last_z;
|
||||||
|
$dc->SetPen($self->{interactive_pen});
|
||||||
|
my $pl = $self->point_to_pixel(0, $z);
|
||||||
|
my $pr = $self->point_to_pixel($layer_h, $z);
|
||||||
|
$dc->DrawLine($pl->x, $pl->y, $pr->x, $pr->y);
|
||||||
|
push (@points, $pr);
|
||||||
|
$last_z = $z;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dc->DrawSpline(\@points);
|
||||||
|
|
||||||
|
# draw current layers as lines
|
||||||
|
$last_z = 0.0;
|
||||||
|
@points = ();
|
||||||
foreach my $z (@{$self->{layer_points}}) {
|
foreach my $z (@{$self->{layer_points}}) {
|
||||||
my $layer_h = $z - $last_z;
|
my $layer_h = $z - $last_z;
|
||||||
$dc->SetPen($self->{line_pen});
|
$dc->SetPen($self->{line_pen});
|
||||||
@ -85,6 +103,21 @@ sub repaint {
|
|||||||
|
|
||||||
$dc->DrawSpline(\@points);
|
$dc->DrawSpline(\@points);
|
||||||
|
|
||||||
|
# draw resulting layers as lines
|
||||||
|
$last_z = 0.0;
|
||||||
|
@points = ();
|
||||||
|
foreach my $z (@{$self->{resulting_points}}) {
|
||||||
|
my $layer_h = $z - $last_z;
|
||||||
|
$dc->SetPen($self->{resulting_pen});
|
||||||
|
my $pl = $self->point_to_pixel(0, $z);
|
||||||
|
my $pr = $self->point_to_pixel($layer_h, $z);
|
||||||
|
$dc->DrawLine($pl->x, $pl->y, $pr->x, $pr->y);
|
||||||
|
push (@points, $pr);
|
||||||
|
$last_z = $z;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dc->DrawSpline(\@points);
|
||||||
|
|
||||||
$event->Skip;
|
$event->Skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,61 +126,29 @@ sub mouse_event {
|
|||||||
|
|
||||||
my $pos = $event->GetPosition;
|
my $pos = $event->GetPosition;
|
||||||
my @obj_pos = $self->pixel_to_point($pos);
|
my @obj_pos = $self->pixel_to_point($pos);
|
||||||
#$pos->y = $self->GetSize->GetHeight - $pos->y;
|
|
||||||
# my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]]
|
|
||||||
if ($event->ButtonDown) {
|
if ($event->ButtonDown) {
|
||||||
if ($event->LeftDown) {
|
if ($event->LeftDown) {
|
||||||
# start dragging
|
# start dragging
|
||||||
$self->{drag_start_pos} = [$pos->x, $pos->y];
|
$self->{drag_start_pos} = $pos;
|
||||||
}
|
}
|
||||||
# $self->{on_select_object}->(undef);
|
} elsif ($event->LeftUp) {
|
||||||
# # traverse objects and instances in reverse order, so that if they're overlapping
|
if($self->{drag_start_pos}) {
|
||||||
# # we get the one that gets drawn last, thus on top (as user expects that to move)
|
$self->{resulting_points} = $self->{interactive_points};
|
||||||
# OBJECTS: for my $obj_idx (reverse 0 .. $#{$self->{objects}}) {
|
$self->Refresh;
|
||||||
# my $object = $self->{objects}->[$obj_idx];
|
}
|
||||||
# for my $instance_idx (reverse 0 .. $#{ $object->instance_thumbnails }) {
|
$self->{drag_start_pos} = undef;
|
||||||
# my $thumbnail = $object->instance_thumbnails->[$instance_idx];
|
|
||||||
# if (defined first { $_->contour->contains_point($point) } @$thumbnail) {
|
|
||||||
# $self->{on_select_object}->($obj_idx);
|
|
||||||
#
|
|
||||||
# if ($event->LeftDown) {
|
|
||||||
# # start dragging
|
|
||||||
# my $instance = $self->{model}->objects->[$obj_idx]->instances->[$instance_idx];
|
|
||||||
# my $instance_origin = [ map scale($_), @{$instance->offset} ];
|
|
||||||
# $self->{drag_start_pos} = [ # displacement between the click and the instance origin in scaled model units
|
|
||||||
# $point->x - $instance_origin->[X],
|
|
||||||
# $point->y - $instance_origin->[Y], #-
|
|
||||||
# ];
|
|
||||||
# $self->{drag_object} = [ $obj_idx, $instance_idx ];
|
|
||||||
# } elsif ($event->RightDown) {
|
|
||||||
# $self->{on_right_click}->($pos);
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# last OBJECTS;
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# $self->Refresh;
|
|
||||||
# } elsif ($event->LeftUp) {
|
|
||||||
# $self->{on_instances_moved}->()
|
|
||||||
# if $self->{drag_object};
|
|
||||||
# $self->{drag_start_pos} = undef;
|
|
||||||
# $self->{drag_object} = undef;
|
|
||||||
# $self->SetCursor(wxSTANDARD_CURSOR);
|
|
||||||
# } elsif ($event->LeftDClick) {
|
|
||||||
# $self->{on_double_click}->();
|
|
||||||
} elsif ($event->Dragging) {
|
} elsif ($event->Dragging) {
|
||||||
print "dragging, pos: " . $pos->x . ":" . $pos->y . "\n";
|
print "dragging, pos: " . $pos->x . ":" . $pos->y . "\n";
|
||||||
# return if !$self->{drag_start_pos}; # concurrency problems
|
return if !$self->{drag_start_pos}; # concurrency problems
|
||||||
# my ($obj_idx, $instance_idx) = @{ $self->{drag_object} };
|
|
||||||
# my $model_object = $self->{model}->objects->[$obj_idx];
|
my @start_pos = $self->pixel_to_point($self->{drag_start_pos});
|
||||||
# $model_object->instances->[$instance_idx]->set_offset(
|
my $range = abs($start_pos[1] - $obj_pos[1]);
|
||||||
# Slic3r::Pointf->new(
|
|
||||||
# unscale($point->[X] - $self->{drag_start_pos}[X]),
|
# compute updated interactive layer heights
|
||||||
# unscale($point->[Y] - $self->{drag_start_pos}[Y]),
|
$self->interactive_curve($start_pos[1], $obj_pos[0], $range);
|
||||||
# ));
|
$self->Refresh;
|
||||||
# $model_object->update_bounding_box;
|
|
||||||
# $self->Refresh;
|
|
||||||
}# elsif ($event->Moving) {
|
}# elsif ($event->Moving) {
|
||||||
# my $cursor = wxSTANDARD_CURSOR;
|
# my $cursor = wxSTANDARD_CURSOR;
|
||||||
# if (defined first { $_->contour->contains_point($point) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) {
|
# if (defined first { $_->contour->contains_point($point) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) {
|
||||||
@ -157,6 +158,7 @@ sub mouse_event {
|
|||||||
# }
|
# }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Internal function to cache scaling factors
|
||||||
sub update_canvas_size {
|
sub update_canvas_size {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
@ -191,9 +193,86 @@ sub set_layer_points {
|
|||||||
my ($self, @layer_points) = @_;
|
my ($self, @layer_points) = @_;
|
||||||
|
|
||||||
$self->{layer_points} = [@layer_points];
|
$self->{layer_points} = [@layer_points];
|
||||||
|
$self->{interactive_points} = [@layer_points]; # Initialize to current values
|
||||||
|
$self->{resulting_points} = [@layer_points]; # Initialize to current values
|
||||||
$self->Refresh;
|
$self->Refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub interactive_curve {
|
||||||
|
my ($self, $mod_z, $target_layer_height, $range) = @_;
|
||||||
|
|
||||||
|
$self->{interactive_points} = (); # reset interactive curve
|
||||||
|
|
||||||
|
my $z = 0.0;
|
||||||
|
my $layer_h = $self->{resulting_points}[0];
|
||||||
|
my $i = 0;
|
||||||
|
# copy points which are not going to be modified
|
||||||
|
while(($z+$self->{resulting_points}[$i] < $mod_z-$range) && ($i < @{$self->{resulting_points}})) {
|
||||||
|
$layer_h = $self->{resulting_points}[$i] - $z;
|
||||||
|
$z = $self->{resulting_points}[$i];
|
||||||
|
push (@{$self->{interactive_points}}, $z);
|
||||||
|
$i +=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print "last original z: " . $z . "\n";
|
||||||
|
# interpolate next points
|
||||||
|
while($z < $self->{object_height}) {
|
||||||
|
$layer_h = $self->_interpolate_next_layer_h($z);
|
||||||
|
my $diff = $target_layer_height - $layer_h;
|
||||||
|
my $quadratic_factor = $self->_quadratic_factor($mod_z, $range, $z+$layer_h);
|
||||||
|
$layer_h += $diff * $quadratic_factor;
|
||||||
|
$z += $layer_h;
|
||||||
|
push (@{$self->{interactive_points}}, $z);
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove top layer if n-1 is higher than object_height!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _interpolate_next_layer_h {
|
||||||
|
my ($self, $z) = @_;
|
||||||
|
my $layer_h = $self->{resulting_points}[0];
|
||||||
|
my $array_size = @{$self->{resulting_points}};
|
||||||
|
my $i = 1;
|
||||||
|
# find current layer
|
||||||
|
while(($self->{resulting_points}[$i] <= $z) && ($array_size-1 > $i)) {
|
||||||
|
$i += 1;
|
||||||
|
}
|
||||||
|
if($i == 1) {return $layer_h}; # first layer, nothing to interpolate
|
||||||
|
|
||||||
|
$layer_h = $self->{resulting_points}[$i] - $self->{resulting_points}[$i-1];
|
||||||
|
my $tmp = $layer_h;
|
||||||
|
# interpolate
|
||||||
|
if($array_size-1 > $i) {
|
||||||
|
my $next_layer_h = $self->{resulting_points}[$i+1] - $self->{resulting_points}[$i];
|
||||||
|
$layer_h = $layer_h * ($self->{resulting_points}[$i] - $z)/$layer_h + $next_layer_h * min(1, ($z+$layer_h-$self->{resulting_points}[$i])/$next_layer_h);
|
||||||
|
}
|
||||||
|
# if(abs($layer_h - $tmp) > 0.001) {
|
||||||
|
# print "z: " . $z . "\n";
|
||||||
|
# my $layer_i = $self->{resulting_points}[$i] - $self->{resulting_points}[$i-1];
|
||||||
|
# my $layer_i1 = $self->{resulting_points}[$i+1] - $self->{resulting_points}[$i];
|
||||||
|
# print "layer i: " . $layer_i . " -> " . $self->{resulting_points}[$i] . "\n";
|
||||||
|
# print "layer i+1: " . $layer_i1 . " -> " . $self->{resulting_points}[$i+1] . "\n";
|
||||||
|
# print "layer_h_1: " . $tmp . " layer_h_2: " . $layer_h . "\n\n";
|
||||||
|
# }
|
||||||
|
return $layer_h;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _quadratic_factor {
|
||||||
|
my ($self, $fixpoint, $range, $value) = @_;
|
||||||
|
|
||||||
|
# avoid division by zero
|
||||||
|
$range = 0.00001 if $range <= 0;
|
||||||
|
|
||||||
|
my $dist = abs($fixpoint - $value);
|
||||||
|
my $x = $dist/$range; # normalize
|
||||||
|
my $result = 1-($x*$x);
|
||||||
|
|
||||||
|
print "fixpoint: " . $fixpoint . " range: " . $range . " value: " . $value . " result: " . $result . "\n";
|
||||||
|
|
||||||
|
return max(0, $result);
|
||||||
|
}
|
||||||
|
|
||||||
# Takes a 2-tupel [layer_height (x), height(y)] and converts it
|
# Takes a 2-tupel [layer_height (x), height(y)] and converts it
|
||||||
# into a Wx::Point in scaled canvas coordinates
|
# into a Wx::Point in scaled canvas coordinates
|
||||||
sub point_to_pixel {
|
sub point_to_pixel {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user