Merge branch 'master' of github.com:alexrj/Slic3r
This commit is contained in:
commit
f3db284e2a
@ -71,7 +71,6 @@ use Slic3r::Print::Object;
|
||||
use Slic3r::Print::Simple;
|
||||
use Slic3r::Print::SupportMaterial;
|
||||
use Slic3r::Surface;
|
||||
use Slic3r::TriangleMesh;
|
||||
our $build = eval "use Slic3r::Build; 1";
|
||||
use Thread::Semaphore;
|
||||
|
||||
@ -178,6 +177,7 @@ sub thread_cleanup {
|
||||
*Slic3r::Flow::DESTROY = sub {};
|
||||
*Slic3r::GCode::PlaceholderParser::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBox::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBoxf::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBoxf3::DESTROY = sub {};
|
||||
*Slic3r::Line::DESTROY = sub {};
|
||||
*Slic3r::Model::DESTROY = sub {};
|
||||
|
@ -565,16 +565,20 @@ sub increase {
|
||||
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count);
|
||||
|
||||
# only autoarrange if user has autocentering enabled
|
||||
$self->stop_background_process;
|
||||
if ($Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
$self->arrange;
|
||||
} else {
|
||||
$self->update;
|
||||
}
|
||||
$self->schedule_background_process;
|
||||
}
|
||||
|
||||
sub decrease {
|
||||
my $self = shift;
|
||||
|
||||
$self->stop_background_process;
|
||||
|
||||
my ($obj_idx, $object) = $self->selected_object;
|
||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||
if ($model_object->instances_count >= 2) {
|
||||
@ -590,6 +594,7 @@ sub decrease {
|
||||
$self->{list}->Select($obj_idx, 1);
|
||||
}
|
||||
$self->update;
|
||||
$self->schedule_background_process;
|
||||
}
|
||||
|
||||
sub rotate {
|
||||
@ -695,7 +700,7 @@ sub changescale {
|
||||
|
||||
my $versor = [1,1,1];
|
||||
$versor->[$axis] = $scale/100;
|
||||
$model_object->scale_xyz($versor);
|
||||
$model_object->scale_xyz(Slic3r::Pointf3->new(@$versor));
|
||||
$self->make_thumbnail($obj_idx);
|
||||
} else {
|
||||
# max scale factor should be above 2540 to allow importing files exported in inches
|
||||
|
@ -148,13 +148,14 @@ sub perform_cut {
|
||||
# and cut dialog but ModelObject::cut() needs Z without any instance transformation
|
||||
my $z = $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor;
|
||||
|
||||
my ($new_model, $upper_object, $lower_object) = $self->{model_object}->cut($z);
|
||||
my ($new_model) = $self->{model_object}->cut($z);
|
||||
my ($upper_object, $lower_object) = @{$new_model->objects};
|
||||
$self->{new_model} = $new_model;
|
||||
$self->{new_model_objects} = [];
|
||||
if ($self->{cut_options}{keep_upper} && defined $upper_object) {
|
||||
if ($self->{cut_options}{keep_upper} && $upper_object->volumes_count > 0) {
|
||||
push @{$self->{new_model_objects}}, $upper_object;
|
||||
}
|
||||
if ($self->{cut_options}{keep_lower} && defined $lower_object) {
|
||||
if ($self->{cut_options}{keep_lower} && $lower_object->volumes_count > 0) {
|
||||
push @{$self->{new_model_objects}}, $lower_object;
|
||||
if ($self->{cut_options}{rotate_lower}) {
|
||||
$lower_object->rotate(PI, X);
|
||||
|
@ -158,91 +158,6 @@ sub _arrange {
|
||||
);
|
||||
}
|
||||
|
||||
# makes sure all objects have at least one instance
|
||||
sub add_default_instances {
|
||||
my ($self) = @_;
|
||||
|
||||
# apply a default position to all objects not having one
|
||||
my $added = 0;
|
||||
foreach my $object (@{$self->objects}) {
|
||||
if ($object->instances_count == 0) {
|
||||
$object->add_instance(offset => Slic3r::Pointf->new(0,0));
|
||||
$added = 1;
|
||||
}
|
||||
}
|
||||
return $added;
|
||||
}
|
||||
|
||||
# this returns the bounding box of the *transformed* instances
|
||||
sub bounding_box {
|
||||
my $self = shift;
|
||||
|
||||
return undef if !@{$self->objects};
|
||||
my $bb = $self->objects->[0]->bounding_box;
|
||||
$bb->merge($_->bounding_box) for @{$self->objects}[1..$#{$self->objects}];
|
||||
return $bb;
|
||||
}
|
||||
|
||||
# input point is expressed in unscaled coordinates
|
||||
sub center_instances_around_point {
|
||||
my ($self, $point) = @_;
|
||||
|
||||
my $bb = $self->bounding_box;
|
||||
return if !defined $bb;
|
||||
|
||||
my $size = $bb->size;
|
||||
my @shift = (
|
||||
-$bb->x_min + $point->[X] - $size->x/2,
|
||||
-$bb->y_min + $point->[Y] - $size->y/2, #//
|
||||
);
|
||||
|
||||
foreach my $object (@{$self->objects}) {
|
||||
foreach my $instance (@{$object->instances}) {
|
||||
$instance->set_offset(Slic3r::Pointf->new(
|
||||
$instance->offset->x + $shift[X],
|
||||
$instance->offset->y + $shift[Y], #++
|
||||
));
|
||||
}
|
||||
$object->update_bounding_box;
|
||||
}
|
||||
}
|
||||
|
||||
sub align_instances_to_origin {
|
||||
my ($self) = @_;
|
||||
|
||||
my $bb = $self->bounding_box;
|
||||
return if !defined $bb;
|
||||
|
||||
my $new_center = $bb->size;
|
||||
$new_center->translate(-$new_center->x/2, -$new_center->y/2); #//
|
||||
$self->center_instances_around_point($new_center);
|
||||
}
|
||||
|
||||
sub translate {
|
||||
my $self = shift;
|
||||
my @shift = @_;
|
||||
|
||||
$_->translate(@shift) for @{$self->objects};
|
||||
}
|
||||
|
||||
# flattens everything to a single mesh
|
||||
sub mesh {
|
||||
my $self = shift;
|
||||
|
||||
my $mesh = Slic3r::TriangleMesh->new;
|
||||
$mesh->merge($_->mesh) for @{$self->objects};
|
||||
return $mesh;
|
||||
}
|
||||
|
||||
# flattens everything to a single mesh
|
||||
sub raw_mesh {
|
||||
my $self = shift;
|
||||
|
||||
my $mesh = Slic3r::TriangleMesh->new;
|
||||
$mesh->merge($_->raw_mesh) for @{$self->objects};
|
||||
return $mesh;
|
||||
}
|
||||
|
||||
# this method splits objects into multiple distinct objects by walking their meshes
|
||||
sub split_meshes {
|
||||
my $self = shift;
|
||||
@ -384,105 +299,6 @@ sub add_instance {
|
||||
}
|
||||
}
|
||||
|
||||
sub raw_bounding_box {
|
||||
my $self = shift;
|
||||
|
||||
my @meshes = map $_->mesh->clone, grep !$_->modifier, @{ $self->volumes };
|
||||
die "No meshes found" if !@meshes;
|
||||
|
||||
my $instance = $self->instances->[0];
|
||||
$instance->transform_mesh($_, 1) for @meshes;
|
||||
|
||||
my $bb = (shift @meshes)->bounding_box;
|
||||
$bb->merge($_->bounding_box) for @meshes;
|
||||
return $bb;
|
||||
}
|
||||
|
||||
# flattens all volumes and instances into a single mesh
|
||||
sub mesh {
|
||||
my $self = shift;
|
||||
|
||||
my $mesh = $self->raw_mesh;
|
||||
|
||||
my @instance_meshes = ();
|
||||
foreach my $instance (@{ $self->instances }) {
|
||||
my $m = $mesh->clone;
|
||||
$instance->transform_mesh($m);
|
||||
push @instance_meshes, $m;
|
||||
}
|
||||
|
||||
my $full_mesh = Slic3r::TriangleMesh->new;
|
||||
$full_mesh->merge($_) for @instance_meshes;
|
||||
return $full_mesh;
|
||||
}
|
||||
|
||||
sub update_bounding_box {
|
||||
my ($self) = @_;
|
||||
$self->_bounding_box($self->mesh->bounding_box);
|
||||
}
|
||||
|
||||
# this returns the bounding box of the *transformed* instances
|
||||
sub bounding_box {
|
||||
my $self = shift;
|
||||
|
||||
$self->update_bounding_box if !defined $self->_bounding_box;
|
||||
return $self->_bounding_box->clone;
|
||||
}
|
||||
|
||||
# this returns the bounding box of the *transformed* given instance
|
||||
sub instance_bounding_box {
|
||||
my ($self, $instance_idx) = @_;
|
||||
|
||||
$instance_idx //= 0;
|
||||
|
||||
my $mesh = $self->raw_mesh;
|
||||
$self->instances->[$instance_idx]->transform_mesh($mesh);
|
||||
return $mesh->bounding_box;
|
||||
}
|
||||
|
||||
sub center_around_origin {
|
||||
my $self = shift;
|
||||
|
||||
# calculate the displacements needed to
|
||||
# center this object around the origin
|
||||
my $bb = $self->raw_mesh->bounding_box;
|
||||
|
||||
# first align to origin on XY
|
||||
my @shift = (
|
||||
-$bb->x_min,
|
||||
-$bb->y_min,
|
||||
0,
|
||||
);
|
||||
|
||||
# then center it on XY
|
||||
my $size = $bb->size;
|
||||
$shift[X] -= $size->x/2;
|
||||
$shift[Y] -= $size->y/2; #//
|
||||
|
||||
$self->translate(@shift);
|
||||
$self->origin_translation->translate(@shift[X,Y]);
|
||||
|
||||
if ($self->instances_count > 0) {
|
||||
foreach my $instance (@{ $self->instances }) {
|
||||
$instance->set_offset(Slic3r::Pointf->new(
|
||||
$instance->offset->x - $shift[X],
|
||||
$instance->offset->y - $shift[Y], #--
|
||||
));
|
||||
}
|
||||
$self->update_bounding_box;
|
||||
}
|
||||
|
||||
return @shift;
|
||||
}
|
||||
|
||||
sub translate {
|
||||
my $self = shift;
|
||||
my @shift = @_;
|
||||
|
||||
$_->mesh->translate(@shift) for @{$self->volumes};
|
||||
$self->_bounding_box->translate(@shift) if defined $self->_bounding_box;
|
||||
}
|
||||
|
||||
sub rotate {
|
||||
my ($self, $angle, $axis) = @_;
|
||||
|
||||
@ -512,39 +328,6 @@ sub flip {
|
||||
$self->invalidate_bounding_box;
|
||||
}
|
||||
|
||||
sub scale_xyz {
|
||||
my ($self, $versor) = @_;
|
||||
|
||||
$_->mesh->scale_xyz($versor) for @{$self->volumes};
|
||||
$self->invalidate_bounding_box;
|
||||
}
|
||||
|
||||
sub materials_count {
|
||||
my $self = shift;
|
||||
|
||||
my %materials = map { $_->material_id // '_default' => 1 } @{$self->volumes};
|
||||
return scalar keys %materials;
|
||||
}
|
||||
|
||||
sub unique_materials {
|
||||
my $self = shift;
|
||||
|
||||
my %materials = ();
|
||||
$materials{ $_->material_id } = 1
|
||||
for grep { defined $_->material_id } @{$self->volumes};
|
||||
return sort keys %materials;
|
||||
}
|
||||
|
||||
sub facets_count {
|
||||
my $self = shift;
|
||||
return sum(map $_->mesh->facets_count, grep !$_->modifier, @{$self->volumes});
|
||||
}
|
||||
|
||||
sub needed_repair {
|
||||
my $self = shift;
|
||||
return (first { !$_->mesh->needed_repair } grep !$_->modifier, @{$self->volumes}) ? 0 : 1;
|
||||
}
|
||||
|
||||
sub mesh_stats {
|
||||
my $self = shift;
|
||||
|
||||
@ -577,54 +360,4 @@ sub print_info {
|
||||
}
|
||||
}
|
||||
|
||||
sub cut {
|
||||
my ($self, $z) = @_;
|
||||
|
||||
# clone this one to duplicate instances, materials etc.
|
||||
my $model = Slic3r::Model->new;
|
||||
my $upper = $model->add_object($self);
|
||||
my $lower = $model->add_object($self);
|
||||
$upper->clear_volumes;
|
||||
$lower->clear_volumes;
|
||||
|
||||
foreach my $volume (@{$self->volumes}) {
|
||||
if ($volume->modifier) {
|
||||
# don't cut modifiers
|
||||
$upper->add_volume($volume);
|
||||
$lower->add_volume($volume);
|
||||
} else {
|
||||
my $upper_mesh = Slic3r::TriangleMesh->new;
|
||||
my $lower_mesh = Slic3r::TriangleMesh->new;
|
||||
$volume->mesh->cut($z + $volume->mesh->bounding_box->z_min, $upper_mesh, $lower_mesh);
|
||||
$upper_mesh->repair;
|
||||
$lower_mesh->repair;
|
||||
$upper_mesh->reset_repair_stats;
|
||||
$lower_mesh->reset_repair_stats;
|
||||
|
||||
if ($upper_mesh->facets_count > 0) {
|
||||
$upper->add_volume(
|
||||
name => $volume->name,
|
||||
material_id => $volume->material_id,
|
||||
mesh => $upper_mesh,
|
||||
modifier => $volume->modifier,
|
||||
config => $volume->config,
|
||||
);
|
||||
}
|
||||
if ($lower_mesh->facets_count > 0) {
|
||||
$lower->add_volume(
|
||||
name => $volume->name,
|
||||
material_id => $volume->material_id,
|
||||
mesh => $lower_mesh,
|
||||
modifier => $volume->modifier,
|
||||
config => $volume->config,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$upper = undef if !@{$upper->volumes};
|
||||
$lower = undef if !@{$lower->volumes};
|
||||
return ($model, $upper, $lower);
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -38,7 +38,7 @@ has 'status_cb' => (
|
||||
|
||||
has 'print_center' => (
|
||||
is => 'rw',
|
||||
default => sub { [100,100] },
|
||||
default => sub { Slic3r::Pointf->new(100,100) },
|
||||
);
|
||||
|
||||
has 'output_file' => (
|
||||
|
@ -156,7 +156,7 @@ sub init_print {
|
||||
$model->duplicate($params{duplicate} // 1, $print->config->min_object_distance);
|
||||
}
|
||||
$model->arrange_objects($print->config->min_object_distance);
|
||||
$model->center_instances_around_point($params{print_center} // [100,100]);
|
||||
$model->center_instances_around_point($params{print_center} // Slic3r::Pointf->new(100,100));
|
||||
foreach my $model_object (@{$model->objects}) {
|
||||
$print->auto_assign_extruders($model_object);
|
||||
$print->add_model_object($model_object);
|
||||
|
@ -1,22 +0,0 @@
|
||||
package Slic3r::TriangleMesh;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use List::Util qw(first);
|
||||
use Slic3r::Geometry qw(X Y);
|
||||
use Slic3r::Geometry::Clipper qw(union_ex offset);
|
||||
|
||||
sub needed_repair {
|
||||
my $self = shift;
|
||||
|
||||
my $stats = $self->stats;
|
||||
return (first { $stats->{$_} > 0 }
|
||||
qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)) ? 1 : 0;
|
||||
}
|
||||
|
||||
sub center {
|
||||
my $self = shift;
|
||||
return $self->bounding_box->center;
|
||||
}
|
||||
|
||||
1;
|
@ -178,7 +178,7 @@ if (@ARGV) { # slicing from command line
|
||||
$opt{duplicate_grid} = [ split /[,x]/, $opt{duplicate_grid}, 2 ];
|
||||
}
|
||||
if (defined $opt{print_center}) {
|
||||
$opt{print_center} = [ split /[,x]/, $opt{print_center}, 2 ];
|
||||
$opt{print_center} = Slic3r::Pointf->new(split /[,x]/, $opt{print_center}, 2);
|
||||
}
|
||||
|
||||
my $sprint = Slic3r::Print::Simple->new(
|
||||
@ -186,7 +186,7 @@ if (@ARGV) { # slicing from command line
|
||||
rotate => $opt{rotate} // 0,
|
||||
duplicate => $opt{duplicate} // 1,
|
||||
duplicate_grid => $opt{duplicate_grid} // [1,1],
|
||||
print_center => $opt{print_center} // [100,100],
|
||||
print_center => $opt{print_center} // Slic3r::Pointf->new(100,100),
|
||||
status_cb => sub {
|
||||
my ($percent, $message) = @_;
|
||||
printf "=> %s\n", $message;
|
||||
|
@ -16,6 +16,7 @@ BoundingBoxBase<PointClass>::BoundingBoxBase(const std::vector<PointClass> &poin
|
||||
this->max.x = std::max(it->x, this->max.x);
|
||||
this->max.y = std::max(it->y, this->max.y);
|
||||
}
|
||||
this->defined = true;
|
||||
}
|
||||
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
|
||||
template BoundingBoxBase<Pointf>::BoundingBoxBase(const std::vector<Pointf> &points);
|
||||
@ -80,10 +81,15 @@ template void BoundingBoxBase<Pointf3>::scale(double factor);
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::merge(const PointClass &point)
|
||||
{
|
||||
this->min.x = std::min(point.x, this->min.x);
|
||||
this->min.y = std::min(point.y, this->min.y);
|
||||
this->max.x = std::max(point.x, this->max.x);
|
||||
this->max.y = std::max(point.y, this->max.y);
|
||||
if (this->defined) {
|
||||
this->min.x = std::min(point.x, this->min.x);
|
||||
this->min.y = std::min(point.y, this->min.y);
|
||||
this->max.x = std::max(point.x, this->max.x);
|
||||
this->max.y = std::max(point.y, this->max.y);
|
||||
} else {
|
||||
this->min = this->max = point;
|
||||
this->defined = true;
|
||||
}
|
||||
}
|
||||
template void BoundingBoxBase<Point>::merge(const Point &point);
|
||||
template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
|
||||
@ -91,10 +97,16 @@ template void BoundingBoxBase<Pointf>::merge(const Pointf &point);
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
||||
{
|
||||
this->min.x = std::min(bb.min.x, this->min.x);
|
||||
this->min.y = std::min(bb.min.y, this->min.y);
|
||||
this->max.x = std::max(bb.max.x, this->max.x);
|
||||
this->max.y = std::max(bb.max.y, this->max.y);
|
||||
if (this->defined) {
|
||||
this->min.x = std::min(bb.min.x, this->min.x);
|
||||
this->min.y = std::min(bb.min.y, this->min.y);
|
||||
this->max.x = std::max(bb.max.x, this->max.x);
|
||||
this->max.y = std::max(bb.max.y, this->max.y);
|
||||
} else {
|
||||
this->min = bb.min;
|
||||
this->max = bb.max;
|
||||
this->defined = true;
|
||||
}
|
||||
}
|
||||
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
||||
template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
|
||||
@ -102,18 +114,22 @@ template void BoundingBoxBase<Pointf>::merge(const BoundingBoxBase<Pointf> &bb);
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
||||
{
|
||||
if (this->defined) {
|
||||
this->min.z = std::min(point.z, this->min.z);
|
||||
this->max.z = std::max(point.z, this->max.z);
|
||||
}
|
||||
BoundingBoxBase<PointClass>::merge(point);
|
||||
this->min.z = std::min(point.z, this->min.z);
|
||||
this->max.z = std::max(point.z, this->max.z);
|
||||
}
|
||||
template void BoundingBox3Base<Pointf3>::merge(const Pointf3 &point);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
|
||||
{
|
||||
if (this->defined) {
|
||||
this->min.z = std::min(bb.min.z, this->min.z);
|
||||
this->max.z = std::max(bb.max.z, this->max.z);
|
||||
}
|
||||
BoundingBoxBase<PointClass>::merge(bb);
|
||||
this->min.z = std::min(bb.min.z, this->min.z);
|
||||
this->max.z = std::max(bb.max.z, this->max.z);
|
||||
}
|
||||
template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb);
|
||||
|
||||
|
@ -18,8 +18,9 @@ class BoundingBoxBase
|
||||
public:
|
||||
PointClass min;
|
||||
PointClass max;
|
||||
bool defined;
|
||||
|
||||
BoundingBoxBase() {};
|
||||
BoundingBoxBase() : defined(false) {};
|
||||
BoundingBoxBase(const std::vector<PointClass> &points);
|
||||
void merge(const PointClass &point);
|
||||
void merge(const BoundingBoxBase<PointClass> &bb);
|
||||
@ -34,7 +35,7 @@ template <class PointClass>
|
||||
class BoundingBox3Base : public BoundingBoxBase<PointClass>
|
||||
{
|
||||
public:
|
||||
BoundingBox3Base() {};
|
||||
BoundingBox3Base() : BoundingBoxBase<PointClass>() {};
|
||||
BoundingBox3Base(const std::vector<PointClass> &points);
|
||||
void merge(const PointClass &point);
|
||||
void merge(const BoundingBox3Base<PointClass> &bb);
|
||||
@ -50,7 +51,7 @@ class BoundingBox : public BoundingBoxBase<Point>
|
||||
void polygon(Polygon* polygon) const;
|
||||
Polygon polygon() const;
|
||||
|
||||
BoundingBox() {};
|
||||
BoundingBox() : BoundingBoxBase<Point>() {};
|
||||
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {};
|
||||
BoundingBox(const Lines &lines);
|
||||
};
|
||||
@ -61,13 +62,13 @@ class BoundingBox3 : public BoundingBox3Base<Point3> {};
|
||||
|
||||
class BoundingBoxf : public BoundingBoxBase<Pointf> {
|
||||
public:
|
||||
BoundingBoxf() {};
|
||||
BoundingBoxf() : BoundingBoxBase<Pointf>() {};
|
||||
BoundingBoxf(const std::vector<Pointf> &points) : BoundingBoxBase<Pointf>(points) {};
|
||||
};
|
||||
|
||||
class BoundingBoxf3 : public BoundingBox3Base<Pointf3> {
|
||||
public:
|
||||
BoundingBoxf3() {};
|
||||
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
|
||||
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};
|
||||
};
|
||||
|
||||
|
@ -158,6 +158,91 @@ Model::has_objects_with_no_instances() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// makes sure all objects have at least one instance
|
||||
bool
|
||||
Model::add_default_instances()
|
||||
{
|
||||
bool added = false;
|
||||
// apply a default position to all objects not having one
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
if ((*o)->instances.empty()) {
|
||||
(*o)->add_instance();
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* instances
|
||||
void
|
||||
Model::bounding_box(BoundingBoxf3* bb)
|
||||
{
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
BoundingBoxf3 obb;
|
||||
(*o)->bounding_box(&obb);
|
||||
bb->merge(obb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Model::center_instances_around_point(const Pointf &point)
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
|
||||
Sizef3 size = bb.size();
|
||||
double shift_x = -bb.min.x + point.x - size.x/2;
|
||||
double shift_y = -bb.min.y + point.y - size.y/2;
|
||||
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
for (ModelInstancePtrs::const_iterator i = (*o)->instances.begin(); i != (*o)->instances.end(); ++i) {
|
||||
(*i)->offset.translate(shift_x, shift_y);
|
||||
}
|
||||
(*o)->update_bounding_box();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Model::align_instances_to_origin()
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
|
||||
Pointf new_center = (Pointf)bb.size();
|
||||
new_center.translate(-new_center.x/2, -new_center.y/2);
|
||||
this->center_instances_around_point(new_center);
|
||||
}
|
||||
|
||||
void
|
||||
Model::translate(coordf_t x, coordf_t y, coordf_t z)
|
||||
{
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
(*o)->translate(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
// flattens everything to a single mesh
|
||||
void
|
||||
Model::mesh(TriangleMesh* mesh) const
|
||||
{
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
TriangleMesh omesh;
|
||||
(*o)->mesh(&omesh);
|
||||
mesh->merge(omesh);
|
||||
}
|
||||
}
|
||||
|
||||
// flattens everything to a single mesh
|
||||
void
|
||||
Model::raw_mesh(TriangleMesh* mesh) const
|
||||
{
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
TriangleMesh omesh;
|
||||
(*o)->raw_mesh(&omesh);
|
||||
mesh->merge(omesh);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(Model, "Model");
|
||||
#endif
|
||||
@ -306,12 +391,45 @@ ModelObject::clear_instances()
|
||||
this->delete_instance(i);
|
||||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* instances
|
||||
void
|
||||
ModelObject::bounding_box(BoundingBoxf3* bb)
|
||||
{
|
||||
if (!this->_bounding_box_valid) this->update_bounding_box();
|
||||
*bb = this->_bounding_box;
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::invalidate_bounding_box()
|
||||
{
|
||||
this->_bounding_box_valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::update_bounding_box()
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->mesh(&mesh);
|
||||
|
||||
mesh.bounding_box(&this->_bounding_box);
|
||||
this->_bounding_box_valid = true;
|
||||
}
|
||||
|
||||
// flattens all volumes and instances into a single mesh
|
||||
void
|
||||
ModelObject::mesh(TriangleMesh* mesh) const
|
||||
{
|
||||
TriangleMesh raw_mesh;
|
||||
this->raw_mesh(&raw_mesh);
|
||||
|
||||
|
||||
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
|
||||
TriangleMesh m = raw_mesh;
|
||||
(*i)->transform_mesh(&m);
|
||||
mesh->merge(m);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::raw_mesh(TriangleMesh* mesh) const
|
||||
{
|
||||
@ -321,6 +439,156 @@ ModelObject::raw_mesh(TriangleMesh* mesh) const
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::raw_bounding_box(BoundingBoxf3* bb) const
|
||||
{
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
if ((*v)->modifier) continue;
|
||||
TriangleMesh mesh = (*v)->mesh;
|
||||
|
||||
if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
|
||||
this->instances.front()->transform_mesh(&mesh, true);
|
||||
|
||||
BoundingBoxf3 mbb;
|
||||
mesh.bounding_box(&mbb);
|
||||
bb->merge(mbb);
|
||||
}
|
||||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* given instance
|
||||
void
|
||||
ModelObject::instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->raw_mesh(&mesh);
|
||||
|
||||
this->instances[instance_idx]->transform_mesh(&mesh);
|
||||
|
||||
mesh.bounding_box(bb);
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::center_around_origin()
|
||||
{
|
||||
// calculate the displacements needed to
|
||||
// center this object around the origin
|
||||
BoundingBoxf3 bb;
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->raw_mesh(&mesh);
|
||||
mesh.bounding_box(&bb);
|
||||
}
|
||||
|
||||
// first align to origin on XY
|
||||
double shift_x = -bb.min.x;
|
||||
double shift_y = -bb.min.y;
|
||||
|
||||
// then center it on XY
|
||||
Sizef3 size = bb.size();
|
||||
shift_x -= size.x/2;
|
||||
shift_y -= size.y/2;
|
||||
|
||||
this->translate(shift_x, shift_y, 0);
|
||||
this->origin_translation.translate(shift_x, shift_y);
|
||||
|
||||
if (!this->instances.empty()) {
|
||||
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
|
||||
(*i)->offset.translate(-shift_x, -shift_y);
|
||||
}
|
||||
this->update_bounding_box();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
|
||||
{
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
(*v)->mesh.translate(x, y, z);
|
||||
}
|
||||
if (this->_bounding_box_valid) this->_bounding_box.translate(x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::scale(const Pointf3 &versor)
|
||||
{
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
(*v)->mesh.scale(versor);
|
||||
}
|
||||
this->invalidate_bounding_box();
|
||||
}
|
||||
|
||||
size_t
|
||||
ModelObject::materials_count() const
|
||||
{
|
||||
std::set<t_model_material_id> material_ids;
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
material_ids.insert((*v)->material_id());
|
||||
}
|
||||
return material_ids.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
ModelObject::facets_count() const
|
||||
{
|
||||
size_t num = 0;
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
if ((*v)->modifier) continue;
|
||||
num += (*v)->mesh.stl.stats.number_of_facets;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
bool
|
||||
ModelObject::needed_repair() const
|
||||
{
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
if ((*v)->modifier) continue;
|
||||
if ((*v)->mesh.needed_repair()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::cut(coordf_t z, Model* model) const
|
||||
{
|
||||
// clone this one to duplicate instances, materials etc.
|
||||
ModelObject* upper = model->add_object(*this);
|
||||
ModelObject* lower = model->add_object(*this);
|
||||
upper->clear_volumes();
|
||||
lower->clear_volumes();
|
||||
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
ModelVolume* volume = *v;
|
||||
if (volume->modifier) {
|
||||
// don't cut modifiers
|
||||
upper->add_volume(*volume);
|
||||
lower->add_volume(*volume);
|
||||
} else {
|
||||
TriangleMeshSlicer tms(&volume->mesh);
|
||||
TriangleMesh upper_mesh, lower_mesh;
|
||||
// TODO: shouldn't we use object bounding box instead of per-volume bb?
|
||||
tms.cut(z + volume->mesh.bounding_box().min.z, &upper_mesh, &lower_mesh);
|
||||
upper_mesh.repair();
|
||||
lower_mesh.repair();
|
||||
upper_mesh.reset_repair_stats();
|
||||
lower_mesh.reset_repair_stats();
|
||||
|
||||
if (upper_mesh.facets_count() > 0) {
|
||||
ModelVolume* vol = upper->add_volume(upper_mesh);
|
||||
vol->name = volume->name;
|
||||
vol->config = volume->config;
|
||||
vol->set_material(volume->material_id(), *volume->material());
|
||||
}
|
||||
if (lower_mesh.facets_count() > 0) {
|
||||
ModelVolume* vol = lower->add_volume(lower_mesh);
|
||||
vol->name = volume->name;
|
||||
vol->config = volume->config;
|
||||
vol->set_material(volume->material_id(), *volume->material());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(ModelObject, "Model::Object");
|
||||
#endif
|
||||
@ -358,6 +626,13 @@ ModelVolume::material() const
|
||||
return this->object->get_model()->get_material(this->_material_id);
|
||||
}
|
||||
|
||||
void
|
||||
ModelVolume::set_material(t_model_material_id material_id, const ModelMaterial &material)
|
||||
{
|
||||
this->_material_id = material_id;
|
||||
(void)this->object->get_model()->add_material(material_id, material);
|
||||
}
|
||||
|
||||
ModelMaterial*
|
||||
ModelVolume::assign_unique_material()
|
||||
{
|
||||
|
@ -53,11 +53,13 @@ class Model
|
||||
// void arrange_objects(coordf_t distance, const BoundingBox &bb);
|
||||
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
|
||||
bool has_objects_with_no_instances() const;
|
||||
// void bounding_box(BoundingBox* bb) const;
|
||||
// void align_to_origin();
|
||||
// void center_instances_around_point(const Pointf &point);
|
||||
// void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
// void mesh(TriangleMesh* mesh) const;
|
||||
bool add_default_instances();
|
||||
void bounding_box(BoundingBoxf3* bb);
|
||||
void center_instances_around_point(const Pointf &point);
|
||||
void align_instances_to_origin();
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
void mesh(TriangleMesh* mesh) const;
|
||||
void raw_mesh(TriangleMesh* mesh) const;
|
||||
// void split_meshes();
|
||||
// std::string get_material_name(t_model_material_id material_id);
|
||||
|
||||
@ -112,17 +114,21 @@ class ModelObject
|
||||
void delete_last_instance();
|
||||
void clear_instances();
|
||||
|
||||
void bounding_box(BoundingBoxf3* bb);
|
||||
void invalidate_bounding_box();
|
||||
|
||||
void mesh(TriangleMesh* mesh) const;
|
||||
void raw_mesh(TriangleMesh* mesh) const;
|
||||
//void mesh(TriangleMesh* mesh) const;
|
||||
//void instance_bounding_box(size_t instance_idx, BoundingBox* bb) const;
|
||||
//void center_around_origin();
|
||||
//void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
//size_t materials_count() const;
|
||||
//void unique_materials(std::vector<t_model_material_id>* materials) const;
|
||||
//size_t facets_count() const;
|
||||
//bool needed_repair() const;
|
||||
void raw_bounding_box(BoundingBoxf3* bb) const;
|
||||
void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const;
|
||||
void center_around_origin();
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
void scale(const Pointf3 &versor);
|
||||
size_t materials_count() const;
|
||||
size_t facets_count() const;
|
||||
bool needed_repair() const;
|
||||
void cut(coordf_t z, Model* model) const;
|
||||
void update_bounding_box(); // this is a private method but we expose it until we need to expose it via XS
|
||||
|
||||
private:
|
||||
Model* model;
|
||||
@ -132,7 +138,6 @@ class ModelObject
|
||||
ModelObject& operator= (ModelObject other);
|
||||
void swap(ModelObject &other);
|
||||
~ModelObject();
|
||||
void update_bounding_box();
|
||||
};
|
||||
|
||||
class ModelVolume
|
||||
@ -148,6 +153,7 @@ class ModelVolume
|
||||
t_model_material_id material_id() const;
|
||||
void material_id(t_model_material_id material_id);
|
||||
ModelMaterial* material() const;
|
||||
void set_material(t_model_material_id material_id, const ModelMaterial &material);
|
||||
|
||||
ModelMaterial* assign_unique_material();
|
||||
|
||||
|
@ -153,6 +153,23 @@ TriangleMesh::reset_repair_stats() {
|
||||
this->stl.stats.normals_fixed = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
TriangleMesh::needed_repair() const
|
||||
{
|
||||
return this->stl.stats.degenerate_facets > 0
|
||||
|| this->stl.stats.edges_fixed > 0
|
||||
|| this->stl.stats.facets_removed > 0
|
||||
|| this->stl.stats.facets_added > 0
|
||||
|| this->stl.stats.facets_reversed > 0
|
||||
|| this->stl.stats.backwards_edges > 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
TriangleMesh::facets_count() const
|
||||
{
|
||||
return this->stl.stats.number_of_facets;
|
||||
}
|
||||
|
||||
void
|
||||
TriangleMesh::WriteOBJFile(char* output_file) {
|
||||
stl_generate_shared_vertices(&stl);
|
||||
@ -164,12 +181,12 @@ void TriangleMesh::scale(float factor)
|
||||
stl_scale(&(this->stl), factor);
|
||||
}
|
||||
|
||||
void TriangleMesh::scale(std::vector<double> versor)
|
||||
void TriangleMesh::scale(const Pointf3 &versor)
|
||||
{
|
||||
float fversor[3];
|
||||
fversor[0] = versor[0];
|
||||
fversor[1] = versor[1];
|
||||
fversor[2] = versor[2];
|
||||
fversor[0] = versor.x;
|
||||
fversor[1] = versor.y;
|
||||
fversor[2] = versor.z;
|
||||
stl_scale_versor(&this->stl, fversor);
|
||||
}
|
||||
|
||||
@ -344,6 +361,14 @@ TriangleMesh::bounding_box(BoundingBoxf3* bb) const
|
||||
bb->max.z = this->stl.stats.max.z;
|
||||
}
|
||||
|
||||
BoundingBoxf3
|
||||
TriangleMesh::bounding_box() const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
return bb;
|
||||
}
|
||||
|
||||
void
|
||||
TriangleMesh::require_shared_vertices()
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ class TriangleMesh
|
||||
void repair();
|
||||
void WriteOBJFile(char* output_file);
|
||||
void scale(float factor);
|
||||
void scale(std::vector<double> versor);
|
||||
void scale(const Pointf3 &versor);
|
||||
void translate(float x, float y, float z);
|
||||
void rotate_x(float angle);
|
||||
void rotate_y(float angle);
|
||||
@ -44,7 +44,10 @@ class TriangleMesh
|
||||
void horizontal_projection(ExPolygons &retval) const;
|
||||
void convex_hull(Polygon* hull);
|
||||
void bounding_box(BoundingBoxf3* bb) const;
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
void reset_repair_stats();
|
||||
bool needed_repair() const;
|
||||
size_t facets_count() const;
|
||||
stl_file stl;
|
||||
bool repaired;
|
||||
|
||||
|
@ -40,7 +40,7 @@ my $cube = {
|
||||
$m->scale(2);
|
||||
ok abs($m->stats->{volume} - 40*40*40) < 1E-2, 'scale';
|
||||
|
||||
$m->scale_xyz([2,1,1]);
|
||||
$m->scale_xyz(Slic3r::Pointf3->new(2,1,1));
|
||||
ok abs($m->stats->{volume} - 2*40*40*40) < 1E-2, 'scale_xyz';
|
||||
|
||||
$m->translate(5,10,0);
|
||||
@ -51,7 +51,7 @@ my $cube = {
|
||||
|
||||
is_deeply $m->size, [80,40,40], 'size';
|
||||
|
||||
$m->scale_xyz([0.5,1,1]);
|
||||
$m->scale_xyz(Slic3r::Pointf3->new(0.5,1,1));
|
||||
$m->rotate(45, Slic3r::Point->new(20,20));
|
||||
ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate';
|
||||
|
||||
|
@ -4,7 +4,7 @@ use strict;
|
||||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 3;
|
||||
use Test::More tests => 5;
|
||||
|
||||
{
|
||||
my @points = (
|
||||
@ -17,4 +17,11 @@ use Test::More tests => 3;
|
||||
is_deeply $bb->max_point->pp, [500,200], 'max_point';
|
||||
}
|
||||
|
||||
{
|
||||
my $bb = Slic3r::Geometry::BoundingBox->new;
|
||||
$bb->merge_point(Slic3r::Point->new(10, 10));
|
||||
is_deeply $bb->min_point->pp, [10,10], 'min_point equals to the only defined point';
|
||||
is_deeply $bb->max_point->pp, [10,10], 'max_point equals to the only defined point';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
@ -7,6 +7,7 @@
|
||||
%}
|
||||
|
||||
%name{Slic3r::Geometry::BoundingBox} class BoundingBox {
|
||||
BoundingBox();
|
||||
~BoundingBox();
|
||||
Clone<BoundingBox> clone()
|
||||
%code{% RETVAL = THIS; %};
|
||||
@ -41,6 +42,7 @@ new_from_points(CLASS, points)
|
||||
};
|
||||
|
||||
%name{Slic3r::Geometry::BoundingBoxf} class BoundingBoxf {
|
||||
BoundingBoxf();
|
||||
~BoundingBoxf();
|
||||
Clone<BoundingBoxf> clone()
|
||||
%code{% RETVAL = THIS; %};
|
||||
@ -76,6 +78,7 @@ new_from_points(CLASS, points)
|
||||
};
|
||||
|
||||
%name{Slic3r::Geometry::BoundingBoxf3} class BoundingBoxf3 {
|
||||
BoundingBoxf3();
|
||||
~BoundingBoxf3();
|
||||
Clone<BoundingBoxf3> clone()
|
||||
%code{% RETVAL = THIS; %};
|
||||
|
@ -55,12 +55,21 @@
|
||||
// void duplicate_objects(size_t copies_num, coordf_t distance, const BoundingBox &bb);
|
||||
// void arrange_objects(coordf_t distance, const BoundingBox &bb);
|
||||
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
|
||||
bool has_objects_with_no_instances() const;
|
||||
// void bounding_box(BoundingBox* bb) const;
|
||||
// void center_instances_around_point(const Pointf &point);
|
||||
// void align_instances_to_origin();
|
||||
// void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
// void mesh(TriangleMesh* mesh) const;
|
||||
bool has_objects_with_no_instances();
|
||||
bool add_default_instances();
|
||||
BoundingBoxf3* bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
void center_instances_around_point(Pointf* point)
|
||||
%code%{ THIS->center_instances_around_point(*point); %};
|
||||
void align_instances_to_origin();
|
||||
void translate(double x, double y, double z);
|
||||
TriangleMesh* mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
|
||||
TriangleMesh* raw_mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
|
||||
// void split_meshes();
|
||||
// std::string get_material_name(t_model_material_id material_id);
|
||||
|
||||
@ -107,8 +116,21 @@ ModelMaterial::attributes()
|
||||
%code%{ RETVAL = &THIS->instances; %};
|
||||
|
||||
void invalidate_bounding_box();
|
||||
void update_bounding_box();
|
||||
TriangleMesh* mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
|
||||
TriangleMesh* raw_mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
|
||||
BoundingBoxf3* raw_bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->raw_bounding_box(RETVAL);
|
||||
%};
|
||||
BoundingBoxf3* instance_bounding_box(int idx)
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->instance_bounding_box(idx, RETVAL);
|
||||
%};
|
||||
|
||||
Ref<BoundingBoxf3> _bounding_box(BoundingBoxf3* new_bbox = NULL)
|
||||
%code{%
|
||||
@ -123,6 +145,11 @@ ModelMaterial::attributes()
|
||||
|
||||
RETVAL = &THIS->_bounding_box;
|
||||
%};
|
||||
BoundingBoxf3* bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
|
||||
%name{_add_volume} Ref<ModelVolume> add_volume(TriangleMesh* mesh)
|
||||
%code%{ RETVAL = THIS->add_volume(*mesh); %};
|
||||
@ -131,6 +158,8 @@ ModelMaterial::attributes()
|
||||
|
||||
void delete_volume(size_t idx);
|
||||
void clear_volumes();
|
||||
int volumes_count()
|
||||
%code%{ RETVAL = THIS->volumes.size(); %};
|
||||
|
||||
%name{_add_instance} Ref<ModelInstance> add_instance();
|
||||
Ref<ModelInstance> _add_instance_clone(ModelInstance* other)
|
||||
@ -163,6 +192,20 @@ ModelMaterial::attributes()
|
||||
%code%{ RETVAL = &THIS->origin_translation; %};
|
||||
void set_origin_translation(Pointf* point)
|
||||
%code%{ THIS->origin_translation = *point; %};
|
||||
|
||||
bool needed_repair() const;
|
||||
int materials_count() const;
|
||||
int facets_count();
|
||||
void center_around_origin();
|
||||
void translate(double x, double y, double z);
|
||||
void scale_xyz(Pointf3* versor)
|
||||
%code{% THIS->scale(*versor); %};
|
||||
|
||||
Model* cut(double z)
|
||||
%code%{
|
||||
RETVAL = new Model();
|
||||
THIS->cut(z, RETVAL);
|
||||
%};
|
||||
};
|
||||
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
void repair();
|
||||
void WriteOBJFile(char* output_file);
|
||||
void scale(float factor);
|
||||
void scale_xyz(std::vector<double> versor)
|
||||
%code{% THIS->scale(versor); %};
|
||||
void scale_xyz(Pointf3* versor)
|
||||
%code{% THIS->scale(*versor); %};
|
||||
void translate(float x, float y, float z);
|
||||
void rotate_x(float angle);
|
||||
void rotate_y(float angle);
|
||||
@ -38,8 +38,13 @@
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
int facets_count()
|
||||
%code{% RETVAL = THIS->stl.stats.number_of_facets; %};
|
||||
Pointf3* center()
|
||||
%code{%
|
||||
BoundingBoxf3 bb;
|
||||
THIS->bounding_box(&bb);
|
||||
RETVAL = new Pointf3(bb.center());
|
||||
%};
|
||||
int facets_count();
|
||||
void reset_repair_stats();
|
||||
%{
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user