Cut by Grid also in GUI

This commit is contained in:
Alessandro Ranellucci 2016-12-18 13:10:25 +01:00
parent 54f782c121
commit 5cbdb7865d
6 changed files with 117 additions and 49 deletions

View File

@ -618,7 +618,7 @@ sub load_model_objects {
$o->repair;
push @{ $self->{objects} }, Slic3r::GUI::Plater::Object->new(
name => basename($model_object->input_file),
name => $model_object->name || basename($model_object->input_file),
);
push @obj_idx, $#{ $self->{objects} };
@ -1649,9 +1649,14 @@ sub object_cut_dialog {
return unless $dlg->ShowModal == wxID_OK;
if (my @new_objects = $dlg->NewModelObjects) {
my $process_dialog = Wx::ProgressDialog->new('Loading…', "Loading new objects…", 100, $self, 0);
$process_dialog->Pulse;
$self->remove($obj_idx);
$self->load_model_objects(grep defined($_), @new_objects);
$self->arrange;
$self->arrange if @new_objects <= 2; # don't arrange for grid cuts
$process_dialog->Destroy;
}
}

View File

@ -6,6 +6,8 @@ use strict;
use warnings;
use utf8;
use POSIX qw(ceil);
use Scalar::Util qw(looks_like_number);
use Slic3r::Geometry qw(PI X Y Z);
use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
@ -109,8 +111,14 @@ sub new {
));
{
my $cut_button_sizer = Wx::BoxSizer->new(wxVERTICAL);
$self->{btn_cut} = Wx::Button->new($self, -1, "Perform cut", wxDefaultPosition, wxDefaultSize);
$self->{btn_cut}->SetDefault;
$cut_button_sizer->Add($self->{btn_cut}, 0, wxALIGN_RIGHT | wxALL, 10);
$self->{btn_cut_grid} = Wx::Button->new($self, -1, "Cut by grid…", wxDefaultPosition, wxDefaultSize);
$cut_button_sizer->Add($self->{btn_cut_grid}, 0, wxALIGN_RIGHT | wxALL, 10);
$optgroup->append_line(Slic3r::GUI::OptionsGroup::Line->new(
sizer => $cut_button_sizer,
));
@ -144,14 +152,14 @@ sub new {
$self->_perform_cut() unless $self->{mesh_cut_valid};
# Adjust position / orientation of the split object halves.
if ($self->{new_model_objects}{lower}) {
if (my $lower = $self->{new_model_objects}[0]) {
if ($self->{cut_options}{rotate_lower} && $self->{cut_options}{axis} == Z) {
$self->{new_model_objects}{lower}->rotate(PI, X);
$lower->rotate(PI, X);
}
$self->{new_model_objects}{lower}->center_around_origin; # align to Z = 0
$lower->center_around_origin; # align to Z = 0
}
if ($self->{new_model_objects}{upper}) {
$self->{new_model_objects}{upper}->center_around_origin; # align to Z = 0
if (my $upper = $self->{new_model_objects}[1]) {
$upper->center_around_origin; # align to Z = 0
}
# Note that the window was already closed, so a pending update will not be executed.
@ -160,6 +168,48 @@ sub new {
$self->Destroy();
});
EVT_BUTTON($self, $self->{btn_cut_grid}, sub {
my $grid_x = Wx::GetTextFromUser("Enter the width of the desired tiles along the X axis:",
"Cut by Grid", 100, $self);
return if !looks_like_number($grid_x) || $grid_x <= 0;
my $grid_y = Wx::GetTextFromUser("Enter the width of the desired tiles along the Y axis:",
"Cut by Grid", 100, $self);
return if !looks_like_number($grid_y) || $grid_y <= 0;
my $process_dialog = Wx::ProgressDialog->new('Cutting…', "Cutting model by grid…", 100, $self, 0);
$process_dialog->Pulse;
my $meshes = $self->{model_object}->mesh->cut_by_grid(Slic3r::Pointf->new($grid_x, $grid_y));
$self->{new_model_objects} = [];
my $bb = $self->{model_object}->bounding_box;
$self->{new_model} = my $model = Slic3r::Model->new;
for my $i (0..$#$meshes) {
push @{$self->{new_model_objects}}, my $o = $model->add_object(
name => sprintf('%s (%d)', $self->{model_object}->name, $i+1),
);
my $v = $o->add_volume(
mesh => $meshes->[$i],
name => $o->name,
);
my $min = $v->mesh->bounding_box->min_point->clone;
$o->center_around_origin;
my $i = $o->add_instance(offset => Slic3r::Pointf->new(@{$min}[X,Y]));
$i->offset->translate(
5 * ceil(($i->offset->x - $bb->center->x) / $grid_x),
5 * ceil(($i->offset->y - $bb->center->y) / $grid_y),
);
}
$process_dialog->Destroy;
# Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1;
$self->EndModal(wxID_OK);
$self->Destroy();
});
EVT_CLOSE($self, sub {
# Note that the window was already closed, so a pending update will not be executed.
$self->{already_closed} = 1;
@ -208,12 +258,12 @@ sub _perform_cut
my ($new_model) = $self->{model_object}->cut($self->{cut_options}{axis}, $z);
my ($upper_object, $lower_object) = @{$new_model->objects};
$self->{new_model} = $new_model;
$self->{new_model_objects} = {};
$self->{new_model_objects} = [];
if ($self->{cut_options}{keep_upper} && $upper_object->volumes_count > 0) {
$self->{new_model_objects}{upper} = $upper_object;
$self->{new_model_objects}[1] = $upper_object;
}
if ($self->{cut_options}{keep_lower} && $lower_object->volumes_count > 0) {
$self->{new_model_objects}{lower} = $lower_object;
$self->{new_model_objects}[0] = $lower_object;
}
$self->{mesh_cut_valid} = 1;
@ -241,7 +291,7 @@ sub _update {
# get volumes to render
my @objects = ();
if ($life_preview_active) {
push @objects, values %{$self->{new_model_objects}};
push @objects, grep defined, @{$self->{new_model_objects}};
} else {
push @objects, $self->{model_object};
}
@ -311,7 +361,7 @@ sub _update {
sub NewModelObjects {
my ($self) = @_;
return values %{ $self->{new_model_objects} };
return grep defined, @{ $self->{new_model_objects} };
}
1;

View File

@ -160,41 +160,12 @@ main(const int argc, const char **argv)
TriangleMesh mesh = model->mesh();
mesh.repair();
const BoundingBoxf3 bb = mesh.bounding_box();
mesh.translate(0, 0, -bb.min.z);
const Sizef3 size = bb.size();
const size_t x_parts = ceil((size.x - EPSILON)/cli_config.cut_grid.value.x);
const size_t y_parts = ceil((size.y - EPSILON)/cli_config.cut_grid.value.y);
for (size_t i = 1; i <= x_parts; ++i) {
TriangleMesh curr;
if (i == x_parts) {
curr = mesh;
} else {
TriangleMesh next;
TriangleMeshSlicer<X>(&mesh).cut(bb.min.x + (cli_config.cut_grid.value.x * i), &next, &curr);
curr.repair();
next.repair();
mesh = next;
}
for (size_t j = 1; j <= y_parts; ++j) {
TriangleMesh tile;
if (j == y_parts) {
tile = curr;
} else {
TriangleMesh next;
TriangleMeshSlicer<Y>(&curr).cut(bb.min.y + (cli_config.cut_grid.value.y * j), &next, &tile);
tile.repair();
next.repair();
curr = next;
}
TriangleMeshPtrs meshes = mesh.cut_by_grid(cli_config.cut_grid.value);
for (TriangleMeshPtrs::iterator m = meshes.begin(); m != meshes.end(); ++m) {
std::ostringstream ss;
ss << model->objects.front()->input_file << "_" << i << "_" << j << ".stl";
IO::STL::write(tile, ss.str());
}
ss << model->objects.front()->input_file << "_" << (m - meshes.begin()) << ".stl";
IO::STL::write(**m, ss.str());
delete *m;
}
} else {
std::cerr << "error: command not supported" << std::endl;

View File

@ -395,6 +395,47 @@ TriangleMesh::split() const
return meshes;
}
TriangleMeshPtrs
TriangleMesh::cut_by_grid(const Pointf &grid) const
{
TriangleMesh mesh = *this;
const BoundingBoxf3 bb = mesh.bounding_box();
const Sizef3 size = bb.size();
const size_t x_parts = ceil((size.x - EPSILON)/grid.x);
const size_t y_parts = ceil((size.y - EPSILON)/grid.y);
TriangleMeshPtrs meshes;
for (size_t i = 1; i <= x_parts; ++i) {
TriangleMesh curr;
if (i == x_parts) {
curr = mesh;
} else {
TriangleMesh next;
TriangleMeshSlicer<X>(&mesh).cut(bb.min.x + (grid.x * i), &next, &curr);
curr.repair();
next.repair();
mesh = next;
}
for (size_t j = 1; j <= y_parts; ++j) {
TriangleMesh* tile;
if (j == y_parts) {
tile = new TriangleMesh(curr);
} else {
TriangleMesh next;
tile = new TriangleMesh;
TriangleMeshSlicer<Y>(&curr).cut(bb.min.y + (grid.y * j), &next, tile);
tile->repair();
next.repair();
curr = next;
}
meshes.push_back(tile);
}
}
return meshes;
}
void
TriangleMesh::merge(const TriangleMesh &mesh)
{

View File

@ -49,6 +49,7 @@ class TriangleMesh
void center_around_origin();
void rotate(double angle, Point* center);
TriangleMeshPtrs split() const;
TriangleMeshPtrs cut_by_grid(const Pointf &grid) const;
void merge(const TriangleMesh &mesh);
ExPolygons horizontal_projection() const;
Polygon convex_hull();
@ -112,8 +113,6 @@ class TriangleMeshSlicer
void cut(float z, TriangleMesh* upper, TriangleMesh* lower) const;
static void cut(TriangleMesh* mesh, Axis axis, float z, TriangleMesh* upper, TriangleMesh* lower);
private:
typedef std::vector< std::vector<int> > t_facets_edges;
t_facets_edges facets_edges;

View File

@ -30,6 +30,8 @@
void align_to_origin();
void rotate(double angle, Point* center);
TriangleMeshPtrs split();
TriangleMeshPtrs cut_by_grid(Pointf* grid)
%code{% RETVAL = THIS->cut_by_grid(*grid); %};
void merge(TriangleMesh* mesh)
%code{% THIS->merge(*mesh); %};
ExPolygons horizontal_projection();