New feature: Splitting an object into a multi-part volume.
This commit is contained in:
parent
a1f6403463
commit
b724d789fd
@ -56,13 +56,15 @@ sub new {
|
|||||||
$self->{btn_load_modifier} = Wx::Button->new($self, -1, "Load modifier…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
$self->{btn_load_modifier} = Wx::Button->new($self, -1, "Load modifier…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||||
$self->{btn_load_lambda_modifier} = Wx::Button->new($self, -1, "Load generic…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
$self->{btn_load_lambda_modifier} = Wx::Button->new($self, -1, "Load generic…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||||
$self->{btn_delete} = Wx::Button->new($self, -1, "Delete part", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
$self->{btn_delete} = Wx::Button->new($self, -1, "Delete part", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||||
$self->{btn_move_up} = Wx::Button->new($self, -1, $Slic3r::GUI::have_button_icons ? "" : "Up", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
$self->{btn_split} = Wx::Button->new($self, -1, "Split part", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||||
$self->{btn_move_down} = Wx::Button->new($self, -1, $Slic3r::GUI::have_button_icons ? "" : "Down", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
$self->{btn_move_up} = Wx::Button->new($self, -1, $Slic3r::GUI::have_button_icons ? "" : "Up", wxDefaultPosition, [40, -1], wxBU_LEFT);
|
||||||
|
$self->{btn_move_down} = Wx::Button->new($self, -1, $Slic3r::GUI::have_button_icons ? "" : "Down", wxDefaultPosition, [40, -1], wxBU_LEFT);
|
||||||
if ($Slic3r::GUI::have_button_icons) {
|
if ($Slic3r::GUI::have_button_icons) {
|
||||||
$self->{btn_load_part}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_load_part}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
||||||
$self->{btn_load_modifier}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_load_modifier}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
||||||
$self->{btn_load_lambda_modifier}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_load_lambda_modifier}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG));
|
||||||
$self->{btn_delete}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_delete.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_delete}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("brick_delete.png"), wxBITMAP_TYPE_PNG));
|
||||||
|
$self->{btn_split}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("shape_ungroup.png"), wxBITMAP_TYPE_PNG));
|
||||||
$self->{btn_move_up}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("bullet_arrow_up.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_move_up}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("bullet_arrow_up.png"), wxBITMAP_TYPE_PNG));
|
||||||
$self->{btn_move_down}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("bullet_arrow_down.png"), wxBITMAP_TYPE_PNG));
|
$self->{btn_move_down}->SetBitmap(Wx::Bitmap->new($Slic3r::var->("bullet_arrow_down.png"), wxBITMAP_TYPE_PNG));
|
||||||
}
|
}
|
||||||
@ -73,12 +75,18 @@ sub new {
|
|||||||
$buttons_sizer->Add($self->{btn_load_modifier}, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5);
|
$buttons_sizer->Add($self->{btn_load_modifier}, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5);
|
||||||
$buttons_sizer->Add($self->{btn_load_lambda_modifier}, 0, wxEXPAND | wxBOTTOM, 5);
|
$buttons_sizer->Add($self->{btn_load_lambda_modifier}, 0, wxEXPAND | wxBOTTOM, 5);
|
||||||
$buttons_sizer->Add($self->{btn_delete}, 0, wxEXPAND | wxRIGHT, 5);
|
$buttons_sizer->Add($self->{btn_delete}, 0, wxEXPAND | wxRIGHT, 5);
|
||||||
$buttons_sizer->Add($self->{btn_move_up}, 0, wxEXPAND | wxRIGHT, 5);
|
$buttons_sizer->Add($self->{btn_split}, 0, wxEXPAND | wxRIGHT, 5);
|
||||||
$buttons_sizer->Add($self->{btn_move_down}, 0, wxEXPAND, 5);
|
{
|
||||||
|
my $up_down_sizer = Wx::GridSizer->new(1, 2);
|
||||||
|
$up_down_sizer->Add($self->{btn_move_up}, 0, wxEXPAND | wxRIGHT, 5);
|
||||||
|
$up_down_sizer->Add($self->{btn_move_down}, 0, wxEXPAND, 5);
|
||||||
|
$buttons_sizer->Add($up_down_sizer, 0, wxEXPAND, 5);
|
||||||
|
}
|
||||||
$self->{btn_load_part}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_load_part}->SetFont($Slic3r::GUI::small_font);
|
||||||
$self->{btn_load_modifier}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_load_modifier}->SetFont($Slic3r::GUI::small_font);
|
||||||
$self->{btn_load_lambda_modifier}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_load_lambda_modifier}->SetFont($Slic3r::GUI::small_font);
|
||||||
$self->{btn_delete}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_delete}->SetFont($Slic3r::GUI::small_font);
|
||||||
|
$self->{btn_split}->SetFont($Slic3r::GUI::small_font);
|
||||||
$self->{btn_move_up}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_move_up}->SetFont($Slic3r::GUI::small_font);
|
||||||
$self->{btn_move_down}->SetFont($Slic3r::GUI::small_font);
|
$self->{btn_move_down}->SetFont($Slic3r::GUI::small_font);
|
||||||
|
|
||||||
@ -182,6 +190,7 @@ sub new {
|
|||||||
EVT_BUTTON($self, $self->{btn_load_modifier}, sub { $self->on_btn_load(1) });
|
EVT_BUTTON($self, $self->{btn_load_modifier}, sub { $self->on_btn_load(1) });
|
||||||
EVT_BUTTON($self, $self->{btn_load_lambda_modifier}, sub { $self->on_btn_lambda(1) });
|
EVT_BUTTON($self, $self->{btn_load_lambda_modifier}, sub { $self->on_btn_lambda(1) });
|
||||||
EVT_BUTTON($self, $self->{btn_delete}, \&on_btn_delete);
|
EVT_BUTTON($self, $self->{btn_delete}, \&on_btn_delete);
|
||||||
|
EVT_BUTTON($self, $self->{btn_split}, \&on_btn_split);
|
||||||
EVT_BUTTON($self, $self->{btn_move_up}, \&on_btn_move_up);
|
EVT_BUTTON($self, $self->{btn_move_up}, \&on_btn_move_up);
|
||||||
EVT_BUTTON($self, $self->{btn_move_down}, \&on_btn_move_down);
|
EVT_BUTTON($self, $self->{btn_move_down}, \&on_btn_move_down);
|
||||||
|
|
||||||
@ -279,6 +288,7 @@ sub selection_changed {
|
|||||||
$self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1);
|
$self->{canvas}->volumes->[ $itemData->{volume_id} ]->set_selected(1);
|
||||||
}
|
}
|
||||||
$self->{btn_delete}->Enable;
|
$self->{btn_delete}->Enable;
|
||||||
|
$self->{btn_split}->Enable;
|
||||||
$self->{btn_move_up}->Enable if $itemData->{volume_id} > 0;
|
$self->{btn_move_up}->Enable if $itemData->{volume_id} > 0;
|
||||||
$self->{btn_move_down}->Enable if $itemData->{volume_id} + 1 < $self->{model_object}->volumes_count;
|
$self->{btn_move_down}->Enable if $itemData->{volume_id} + 1 < $self->{model_object}->volumes_count;
|
||||||
|
|
||||||
@ -449,6 +459,18 @@ sub on_btn_delete {
|
|||||||
$self->_parts_changed;
|
$self->_parts_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub on_btn_split {
|
||||||
|
my ($self) = @_;
|
||||||
|
|
||||||
|
my $itemData = $self->get_selection;
|
||||||
|
if ($itemData && $itemData->{type} eq 'volume') {
|
||||||
|
my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}];
|
||||||
|
$self->{parts_changed} = 1 if $volume->split > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->_parts_changed;
|
||||||
|
}
|
||||||
|
|
||||||
sub _parts_changed {
|
sub _parts_changed {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
|
@ -685,6 +685,36 @@ ModelMaterial* ModelVolume::assign_unique_material()
|
|||||||
return model->add_material(this->_material_id);
|
return model->add_material(this->_material_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split this volume, append the result to the object owning this volume.
|
||||||
|
// Return the number of volumes created from this one.
|
||||||
|
// This is useful to assign different materials to different volumes of an object.
|
||||||
|
size_t ModelVolume::split()
|
||||||
|
{
|
||||||
|
TriangleMeshPtrs meshptrs = this->mesh.split();
|
||||||
|
if (meshptrs.size() <= 1) {
|
||||||
|
delete meshptrs.front();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t idx = 0;
|
||||||
|
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
||||||
|
std::string name = this->name;
|
||||||
|
for (TriangleMesh *mesh : meshptrs) {
|
||||||
|
mesh->repair();
|
||||||
|
if (idx == 0)
|
||||||
|
this->mesh = std::move(*mesh);
|
||||||
|
else
|
||||||
|
this->object->volumes.insert(this->object->volumes.begin() + (++ ivolume), new ModelVolume(object, *this, std::move(*mesh)));
|
||||||
|
char str_idx[64];
|
||||||
|
sprintf(str_idx, "_%d", idx + 1);
|
||||||
|
this->object->volumes[ivolume]->name = name + str_idx;
|
||||||
|
delete mesh;
|
||||||
|
++ idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
|
||||||
{
|
{
|
||||||
mesh->rotate_z(this->rotation); // rotate around mesh origin
|
mesh->rotate_z(this->rotation); // rotate around mesh origin
|
||||||
|
@ -161,6 +161,10 @@ public:
|
|||||||
void material_id(t_model_material_id material_id);
|
void material_id(t_model_material_id material_id);
|
||||||
ModelMaterial* material() const;
|
ModelMaterial* material() const;
|
||||||
void set_material(t_model_material_id material_id, const ModelMaterial &material);
|
void set_material(t_model_material_id material_id, const ModelMaterial &material);
|
||||||
|
// Split this volume, append the result to the object owning this volume.
|
||||||
|
// Return the number of volumes created from this one.
|
||||||
|
// This is useful to assign different materials to different volumes of an object.
|
||||||
|
size_t split();
|
||||||
|
|
||||||
ModelMaterial* assign_unique_material();
|
ModelMaterial* assign_unique_material();
|
||||||
|
|
||||||
@ -174,6 +178,9 @@ private:
|
|||||||
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
||||||
name(other.name), mesh(other.mesh), config(other.config), modifier(other.modifier), object(object)
|
name(other.name), mesh(other.mesh), config(other.config), modifier(other.modifier), object(object)
|
||||||
{ this->material_id(other.material_id()); }
|
{ this->material_id(other.material_id()); }
|
||||||
|
ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) :
|
||||||
|
name(other.name), mesh(std::move(mesh)), config(other.config), modifier(other.modifier), object(object)
|
||||||
|
{ this->material_id(other.material_id()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// A single instance of a ModelObject.
|
// A single instance of a ModelObject.
|
||||||
|
@ -78,28 +78,11 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Point3>& fa
|
|||||||
stl_get_size(&stl);
|
stl_get_size(&stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
TriangleMesh::TriangleMesh(const TriangleMesh &other)
|
TriangleMesh::TriangleMesh(const TriangleMesh &other) :
|
||||||
: stl(other.stl), repaired(other.repaired)
|
repaired(false)
|
||||||
{
|
{
|
||||||
this->stl.heads = NULL;
|
stl_initialize(&this->stl);
|
||||||
this->stl.tail = NULL;
|
*this = other;
|
||||||
this->stl.error = other.stl.error;
|
|
||||||
if (other.stl.facet_start != NULL) {
|
|
||||||
this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet));
|
|
||||||
std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start);
|
|
||||||
}
|
|
||||||
if (other.stl.neighbors_start != NULL) {
|
|
||||||
this->stl.neighbors_start = (stl_neighbors*)calloc(other.stl.stats.number_of_facets, sizeof(stl_neighbors));
|
|
||||||
std::copy(other.stl.neighbors_start, other.stl.neighbors_start + other.stl.stats.number_of_facets, this->stl.neighbors_start);
|
|
||||||
}
|
|
||||||
if (other.stl.v_indices != NULL) {
|
|
||||||
this->stl.v_indices = (v_indices_struct*)calloc(other.stl.stats.number_of_facets, sizeof(v_indices_struct));
|
|
||||||
std::copy(other.stl.v_indices, other.stl.v_indices + other.stl.stats.number_of_facets, this->stl.v_indices);
|
|
||||||
}
|
|
||||||
if (other.stl.v_shared != NULL) {
|
|
||||||
this->stl.v_shared = (stl_vertex*)calloc(other.stl.stats.shared_vertices, sizeof(stl_vertex));
|
|
||||||
std::copy(other.stl.v_shared, other.stl.v_shared + other.stl.stats.shared_vertices, this->stl.v_shared);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TriangleMesh::TriangleMesh(TriangleMesh &&other) :
|
TriangleMesh::TriangleMesh(TriangleMesh &&other) :
|
||||||
@ -109,9 +92,30 @@ TriangleMesh::TriangleMesh(TriangleMesh &&other) :
|
|||||||
this->swap(other);
|
this->swap(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
TriangleMesh& TriangleMesh::operator= (TriangleMesh other)
|
TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
|
||||||
{
|
{
|
||||||
this->swap(other);
|
stl_close(&this->stl);
|
||||||
|
this->stl = other.stl;
|
||||||
|
this->repaired = other.repaired;
|
||||||
|
this->stl.heads = nullptr;
|
||||||
|
this->stl.tail = nullptr;
|
||||||
|
this->stl.error = other.stl.error;
|
||||||
|
if (other.stl.facet_start != nullptr) {
|
||||||
|
this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet));
|
||||||
|
std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start);
|
||||||
|
}
|
||||||
|
if (other.stl.neighbors_start != nullptr) {
|
||||||
|
this->stl.neighbors_start = (stl_neighbors*)calloc(other.stl.stats.number_of_facets, sizeof(stl_neighbors));
|
||||||
|
std::copy(other.stl.neighbors_start, other.stl.neighbors_start + other.stl.stats.number_of_facets, this->stl.neighbors_start);
|
||||||
|
}
|
||||||
|
if (other.stl.v_indices != nullptr) {
|
||||||
|
this->stl.v_indices = (v_indices_struct*)calloc(other.stl.stats.number_of_facets, sizeof(v_indices_struct));
|
||||||
|
std::copy(other.stl.v_indices, other.stl.v_indices + other.stl.stats.number_of_facets, this->stl.v_indices);
|
||||||
|
}
|
||||||
|
if (other.stl.v_shared != nullptr) {
|
||||||
|
this->stl.v_shared = (stl_vertex*)calloc(other.stl.stats.shared_vertices, sizeof(stl_vertex));
|
||||||
|
std::copy(other.stl.v_shared, other.stl.v_shared + other.stl.stats.shared_vertices, this->stl.v_shared);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +431,7 @@ TriangleMesh::split() const
|
|||||||
if (!this->repaired) CONFESS("split() requires repair()");
|
if (!this->repaired) CONFESS("split() requires repair()");
|
||||||
|
|
||||||
// loop while we have remaining facets
|
// loop while we have remaining facets
|
||||||
while (1) {
|
for (;;) {
|
||||||
// get the first facet
|
// get the first facet
|
||||||
std::queue<int> facet_queue;
|
std::queue<int> facet_queue;
|
||||||
std::deque<int> facets;
|
std::deque<int> facets;
|
||||||
|
@ -24,8 +24,8 @@ public:
|
|||||||
TriangleMesh(const Pointf3s &points, const std::vector<Point3> &facets);
|
TriangleMesh(const Pointf3s &points, const std::vector<Point3> &facets);
|
||||||
TriangleMesh(const TriangleMesh &other);
|
TriangleMesh(const TriangleMesh &other);
|
||||||
TriangleMesh(TriangleMesh &&other);
|
TriangleMesh(TriangleMesh &&other);
|
||||||
TriangleMesh& operator= (TriangleMesh other);
|
TriangleMesh& operator=(const TriangleMesh &other);
|
||||||
TriangleMesh& operator= (TriangleMesh &&other);
|
TriangleMesh& operator=(TriangleMesh &&other);
|
||||||
void swap(TriangleMesh &other);
|
void swap(TriangleMesh &other);
|
||||||
~TriangleMesh();
|
~TriangleMesh();
|
||||||
void ReadSTLFile(const char* input_file);
|
void ReadSTLFile(const char* input_file);
|
||||||
|
@ -297,6 +297,8 @@ ModelMaterial::attributes()
|
|||||||
%code%{ RETVAL = THIS->modifier; %};
|
%code%{ RETVAL = THIS->modifier; %};
|
||||||
void set_modifier(bool modifier)
|
void set_modifier(bool modifier)
|
||||||
%code%{ THIS->modifier = modifier; %};
|
%code%{ THIS->modifier = modifier; %};
|
||||||
|
|
||||||
|
size_t split();
|
||||||
|
|
||||||
ModelMaterial* assign_unique_material();
|
ModelMaterial* assign_unique_material();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user