From 7ba08c90cff94d8e3e3c9c10e4076e9b3709db96 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 9 May 2014 14:24:35 +0200 Subject: [PATCH] Refactoring to Model API for making it stricter and safer --- lib/Slic3r/Format/AMF/Parser.pm | 2 +- lib/Slic3r/GUI/Plater.pm | 8 +- lib/Slic3r/Model.pm | 142 +++++++++++------------ lib/Slic3r/Test.pm | 23 +++- t/custom_gcode.t | 2 +- t/gcode.t | 2 +- t/multi.t | 2 +- t/perimeters.t | 4 +- t/print.t | 18 +-- t/retraction.t | 18 +-- t/support.t | 8 +- t/svg.t | 2 +- utils/dump-stl.pl | 2 +- xs/Build.PL | 3 +- xs/src/Model.cpp | 192 +++++++++++++++++--------------- xs/src/Model.hpp | 88 +++++++++------ xs/xsp/Model.xsp | 117 +++++++------------ 17 files changed, 316 insertions(+), 317 deletions(-) diff --git a/lib/Slic3r/Format/AMF/Parser.pm b/lib/Slic3r/Format/AMF/Parser.pm index 43dbf05a9..8f821cb2e 100644 --- a/lib/Slic3r/Format/AMF/Parser.pm +++ b/lib/Slic3r/Format/AMF/Parser.pm @@ -126,7 +126,7 @@ sub end_document { foreach my $instance (@{ $self->{_instances}{$object_id} }) { $self->{_model}->objects->[$new_object_id]->add_instance( rotation => $instance->{rz} || 0, - offset => [ $instance->{deltax} || 0, $instance->{deltay} || 0 ], + offset => Slic3r::Pointf->new($instance->{deltax} || 0, $instance->{deltay} || 0), ); } } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index dbe5e6f4b..aa6a521ed 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -409,7 +409,7 @@ sub load_model_objects { # add a default instance and center object around origin $o->center_around_origin; - $o->add_instance(offset => [ @{$self->{config}->print_center} ]); + $o->add_instance(offset => Slic3r::Pointf->new(@{$self->{config}->print_center})); } $self->{print}->auto_assign_extruders($o); @@ -487,7 +487,7 @@ sub increase { my $model_object = $self->{model}->objects->[$obj_idx]; my $last_instance = $model_object->instances->[-1]; my $i = $model_object->add_instance( - offset => [ map 10+$_, @{$last_instance->offset} ], + offset => Slic3r::Pointf->new(map 10+$_, @{$last_instance->offset}), scaling_factor => $last_instance->scaling_factor, rotation => $last_instance->rotation, ); @@ -654,10 +654,10 @@ sub split_object { for my $instance_idx (0..$#{ $current_model_object->instances }) { my $current_instance = $current_model_object->instances->[$instance_idx]; $model_object->add_instance( - offset => [ + offset => Slic3r::Pointf->new( $current_instance->offset->[X] + ($instance_idx * 10), $current_instance->offset->[Y] + ($instance_idx * 10), - ], + ), rotation => $current_instance->rotation, scaling_factor => $current_instance->scaling_factor, ); diff --git a/lib/Slic3r/Model.pm b/lib/Slic3r/Model.pm index 92dfa7245..e5cd02406 100644 --- a/lib/Slic3r/Model.pm +++ b/lib/Slic3r/Model.pm @@ -31,48 +31,34 @@ sub merge { sub add_object { my $self = shift; - my $new_object; if (@_ == 1) { # we have a Model::Object my ($object) = @_; - - $new_object = $self->add_object( - input_file => $object->input_file, - config => $object->config, - layer_height_ranges => $object->layer_height_ranges, # TODO: clone! - origin_translation => $object->origin_translation, - ); - - foreach my $volume (@{$object->volumes}) { - $new_object->add_volume($volume); - } - - $new_object->add_instance( - offset => [ @{$_->offset} ], - rotation => $_->rotation, - scaling_factor => $_->scaling_factor, - ) for @{ $object->instances // [] }; + return $self->_add_object_clone($object); } else { my (%args) = @_; - $new_object = $self->_add_object( - $args{input_file}, - $args{config} // Slic3r::Config->new, - $args{layer_height_ranges} // [], - $args{origin_translation} // Slic3r::Pointf->new, - ); + + my $new_object = $self->_add_object; + + $new_object->set_input_file($args{input_file}) + if defined $args{input_file}; + $new_object->config->apply($args{config}) + if defined $args{config}; + $new_object->set_layer_height_ranges($args{layer_height_ranges}) + if defined $args{layer_height_ranges}; + $new_object->set_origin_translation($args{origin_translation}) + if defined $args{origin_translation}; + + return $new_object; } - - return $new_object; } sub set_material { my $self = shift; my ($material_id, $attributes) = @_; - $attributes //= {}; - - my $material = $self->_set_material($material_id); - $material->set_attribute($_, $attributes->{$_}) for keys %$attributes; + my $material = $self->add_material($material_id); + $material->apply($attributes // {}); return $material; } @@ -89,10 +75,10 @@ sub duplicate_objects_grid { for my $x_copy (1..$grid->[X]) { for my $y_copy (1..$grid->[Y]) { $object->add_instance( - offset => [ + offset => Slic3r::Pointf->new( ($size->[X] + $distance) * ($x_copy-1), ($size->[Y] + $distance) * ($y_copy-1), - ], + ), ); } } @@ -106,12 +92,7 @@ sub duplicate_objects { foreach my $object (@{$self->objects}) { my @instances = @{$object->instances}; foreach my $instance (@instances) { - ### $object->add_instance($instance->clone); if we had clone() - $object->add_instance( - offset => [ @{$instance->offset} ], - rotation => $instance->rotation, - scaling_factor => $instance->scaling_factor, - ) for 2..$copies_num; + $object->add_instance($instance) for 2..$copies_num; } } @@ -151,9 +132,8 @@ sub duplicate { my @instances = @{$object->instances}; # store separately to avoid recursion from add_instance() below foreach my $instance (@instances) { foreach my $pos (@positions) { - ### $object->add_instance($instance->clone); if we had clone() $object->add_instance( - offset => [ $instance->offset->[X] + $pos->[X], $instance->offset->[Y] + $pos->[Y] ], + offset => Slic3r::Pointf->new($instance->offset->[X] + $pos->[X], $instance->offset->[Y] + $pos->[Y]), rotation => $instance->rotation, scaling_factor => $instance->scaling_factor, ); @@ -187,8 +167,8 @@ sub add_default_instances { # apply a default position to all objects not having one my $added = 0; foreach my $object (@{$self->objects}) { - if (!defined $object->instances) { - $object->add_instance(offset => [0,0]); + if ($object->instances_count == 0) { + $object->add_instance(offset => Slic3r::Pointf->new(0,0)); $added = 1; } } @@ -286,7 +266,7 @@ sub split_meshes { # add one instance per original instance $new_object->add_instance( - offset => [ @{$_->offset} ], + offset => Slic3r::Pointf->new(@{$_->offset}), rotation => $_->rotation, scaling_factor => $_->scaling_factor, ) for @{ $object->instances // [] }; @@ -314,6 +294,11 @@ sub get_material_name { package Slic3r::Model::Material; +sub apply { + my ($self, $attributes) = @_; + $self->set_attribute($_, $attributes{$_}) for keys %$attributes; +} + package Slic3r::Model::Object; use File::Basename qw(basename); @@ -328,8 +313,7 @@ sub add_volume { # we have a Model::Volume my ($volume) = @_; - $new_volume = $self->_add_volume( - $volume->material_id, $volume->mesh->clone, $volume->modifier); + $new_volume = $self->_add_volume_clone($volume); # TODO: material_id can't be undef. if (defined $volume->material_id) { @@ -345,10 +329,13 @@ sub add_volume { } } else { my %args = @_; - $new_volume = $self->_add_volume( - $args{material_id}, - $args{mesh}, - $args{modifier} // 0); + + $new_volume = $self->_add_volume($args{mesh}); + + $new_volume->set_material_id($args{material_id}) + if defined $args{material_id}; + $new_volume->set_modifier($args{modifier}) + if defined $args{modifier}; } if (defined $new_volume->material_id && !defined $self->model->get_material($new_volume->material_id)) { @@ -356,7 +343,7 @@ sub add_volume { $self->model->set_material($new_volume->material_id); } - $self->invalidate_bounding_box(); + $self->invalidate_bounding_box; return $new_volume; } @@ -364,16 +351,25 @@ sub add_volume { sub add_instance { my $self = shift; my %params = @_; - - return $self->_add_instance( - $params{rotation} // 0, - $params{scaling_factor} // 1, - $params{offset} // []); -} - -sub instances_count { - my $self = shift; - return scalar(@{ $self->instances // [] }); + + if (@_ == 1) { + # we have a Model::Instance + my ($instance) = @_; + return $self->_add_instance_clone($instance); + } else { + my (%args) = @_; + + my $new_instance = $self->_add_instance; + + $new_instance->set_rotation($args{rotation}) + if defined $args{rotation}; + $new_instance->set_scaling_factor($args{scaling_factor}) + if defined $args{scaling_factor}; + $new_instance->set_offset($args{offset}) + if defined $args{offset}; + + return $new_instance; + } } sub raw_mesh { @@ -446,11 +442,12 @@ sub center_around_origin { $self->translate(@shift); $self->origin_translation->translate(@shift[X,Y]); - if (defined $self->instances) { + 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])); + $instance->offset->y - $shift[Y], #-- + )); } $self->update_bounding_box; } @@ -538,23 +535,12 @@ sub cut { my ($self, $z) = @_; # clone this one - my $upper = Slic3r::Model::Object->new( - $self->model, - $self->input_file, - $self->config, # config is cloned by new() - $self->layer_height_ranges, - $self->origin_translation, - ); - my $lower = Slic3r::Model::Object->new( - $self->model, - $self->input_file, - $self->config, # config is cloned by new() - $self->layer_height_ranges, - $self->origin_translation, - ); + my $upper = $self->model->add_object($self); + my $lower = $self->model->add_object($self); + foreach my $instance (@{$self->instances}) { - $upper->add_instance(offset => [ @{$instance->offset} ]); - $lower->add_instance(offset => [ @{$instance->offset} ]); + $upper->add_instance(offset => Slic3r::Pointf->new(@{$instance->offset})); + $lower->add_instance(offset => Slic3r::Pointf->new(@{$instance->offset})); } foreach my $volume (@{$self->volumes}) { diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index 7d8ce6639..5531ae4f0 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -124,9 +124,9 @@ sub model { $model->set_material($model_name); $object->add_volume(mesh => mesh($model_name, %params), material_id => $model_name); $object->add_instance( - offset => [0,0], - rotation => $params{rotation} // 0, - scaling_factor => $params{scale} // 1, + offset => Slic3r::Pointf->new(0,0), + rotation => $params{rotation} // 0, + scaling_factor => $params{scale} // 1, ); return $model; } @@ -142,7 +142,8 @@ sub init_print { $print->apply_config($config); $models = [$models] if ref($models) ne 'ARRAY'; - for my $model (map { ref($_) ? $_ : model($_, %params) } @$models) { + $models = [ map { ref($_) ? $_ : model($_, %params) } @$models ]; + for my $model (@$models) { die "Unknown model in test" if !defined $model; if (defined $params{duplicate} && $params{duplicate} > 1) { $model->duplicate($params{duplicate} // 1, $print->config->min_object_distance); @@ -156,12 +157,18 @@ sub init_print { } $print->validate; - return $print; + # We return a proxy object in order to keep $models alive as required by the Print API. + return Slic3r::Test::Print->new( + print => $print, + models => $models, + ); } sub gcode { my ($print) = @_; + $print = $print->print if $print->isa('Slic3r::Test::Print'); + my $fh = IO::Scalar->new(\my $gcode); $print->process; $print->export_gcode(output_fh => $fh, quiet => 1); @@ -189,4 +196,10 @@ sub add_facet { } } +package Slic3r::Test::Print; +use Moo; + +has 'print' => (is => 'ro', required => 1); +has 'models' => (is => 'ro', required => 1); + 1; diff --git a/t/custom_gcode.t b/t/custom_gcode.t index 78610da1f..c693aecb9 100644 --- a/t/custom_gcode.t +++ b/t/custom_gcode.t @@ -57,7 +57,7 @@ use Slic3r::Test; $config->set('start_gcode', "TRAVEL:[travel_speed] HEIGHT:[layer_height]\n"); my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - my $output_file = $print->expanded_output_filepath; + my $output_file = $print->print->expanded_output_filepath; ok $output_file !~ /\[travel_speed\]/, 'print config options are replaced in output filename'; ok $output_file !~ /\[layer_height\]/, 'region config options are replaced in output filename'; diff --git a/t/gcode.t b/t/gcode.t index 9105082a9..a241bba27 100644 --- a/t/gcode.t +++ b/t/gcode.t @@ -78,7 +78,7 @@ use Slic3r::Test; }); - ok $print->total_used_filament > 0, 'final retraction is not considered in total used filament'; + ok $print->print->total_used_filament > 0, 'final retraction is not considered in total used filament'; } { diff --git a/t/multi.t b/t/multi.t index b15c261e5..fe1f81848 100644 --- a/t/multi.t +++ b/t/multi.t @@ -173,7 +173,7 @@ sub stacked_cubes { my $object = $model->add_object; $object->add_volume(mesh => Slic3r::Test::mesh('20mm_cube'), material_id => 'lower'); $object->add_volume(mesh => Slic3r::Test::mesh('20mm_cube', translate => [0,0,20]), material_id => 'upper'); - $object->add_instance(offset => [0,0]); + $object->add_instance(offset => Slic3r::Pointf->new(0,0)); return $model; } diff --git a/t/perimeters.t b/t/perimeters.t index b290615d1..b12b8f938 100644 --- a/t/perimeters.t +++ b/t/perimeters.t @@ -192,11 +192,11 @@ use Slic3r::Test; # we just need a pre-filled Print object my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - $print->init_extruders; + $print->print->init_extruders; # override a layer's slices my $expolygon = Slic3r::ExPolygon->new([[-71974463,-139999376],[-71731792,-139987456],[-71706544,-139985616],[-71682119,-139982639],[-71441248,-139946912],[-71417487,-139942895],[-71379384,-139933984],[-71141800,-139874480],[-71105247,-139862895],[-70873544,-139779984],[-70838592,-139765856],[-70614943,-139660064],[-70581783,-139643567],[-70368368,-139515680],[-70323751,-139487872],[-70122160,-139338352],[-70082399,-139306639],[-69894800,-139136624],[-69878679,-139121327],[-69707992,-138933008],[-69668575,-138887343],[-69518775,-138685359],[-69484336,-138631632],[-69356423,-138418207],[-69250040,-138193296],[-69220920,-138128976],[-69137992,-137897168],[-69126095,-137860255],[-69066568,-137622608],[-69057104,-137582511],[-69053079,-137558751],[-69017352,-137317872],[-69014392,-137293456],[-69012543,-137268207],[-68999369,-137000000],[-63999999,-137000000],[-63705947,-136985551],[-63654984,-136977984],[-63414731,-136942351],[-63364756,-136929840],[-63129151,-136870815],[-62851950,-136771631],[-62585807,-136645743],[-62377483,-136520895],[-62333291,-136494415],[-62291908,-136463728],[-62096819,-136319023],[-62058644,-136284432],[-61878676,-136121328],[-61680968,-135903184],[-61650275,-135861807],[-61505591,-135666719],[-61354239,-135414191],[-61332211,-135367615],[-61228359,-135148063],[-61129179,-134870847],[-61057639,-134585262],[-61014451,-134294047],[-61000000,-134000000],[-61000000,-107999999],[-61014451,-107705944],[-61057639,-107414736],[-61129179,-107129152],[-61228359,-106851953],[-61354239,-106585808],[-61505591,-106333288],[-61680967,-106096816],[-61878675,-105878680],[-62096820,-105680967],[-62138204,-105650279],[-62333292,-105505591],[-62585808,-105354239],[-62632384,-105332207],[-62851951,-105228360],[-62900463,-105211008],[-63129152,-105129183],[-63414731,-105057640],[-63705947,-105014448],[-63999999,-105000000],[-68999369,-105000000],[-69012543,-104731792],[-69014392,-104706544],[-69017352,-104682119],[-69053079,-104441248],[-69057104,-104417487],[-69066008,-104379383],[-69125528,-104141799],[-69137111,-104105248],[-69220007,-103873544],[-69234136,-103838591],[-69339920,-103614943],[-69356415,-103581784],[-69484328,-103368367],[-69512143,-103323752],[-69661647,-103122160],[-69693352,-103082399],[-69863383,-102894800],[-69878680,-102878679],[-70066999,-102707992],[-70112656,-102668576],[-70314648,-102518775],[-70368367,-102484336],[-70581783,-102356424],[-70806711,-102250040],[-70871040,-102220919],[-71102823,-102137992],[-71139752,-102126095],[-71377383,-102066568],[-71417487,-102057104],[-71441248,-102053079],[-71682119,-102017352],[-71706535,-102014392],[-71731784,-102012543],[-71974456,-102000624],[-71999999,-102000000],[-104000000,-102000000],[-104025536,-102000624],[-104268207,-102012543],[-104293455,-102014392],[-104317880,-102017352],[-104558751,-102053079],[-104582512,-102057104],[-104620616,-102066008],[-104858200,-102125528],[-104894751,-102137111],[-105126455,-102220007],[-105161408,-102234136],[-105385056,-102339920],[-105418215,-102356415],[-105631632,-102484328],[-105676247,-102512143],[-105877839,-102661647],[-105917600,-102693352],[-106105199,-102863383],[-106121320,-102878680],[-106292007,-103066999],[-106331424,-103112656],[-106481224,-103314648],[-106515663,-103368367],[-106643575,-103581783],[-106749959,-103806711],[-106779080,-103871040],[-106862007,-104102823],[-106873904,-104139752],[-106933431,-104377383],[-106942896,-104417487],[-106946920,-104441248],[-106982648,-104682119],[-106985607,-104706535],[-106987456,-104731784],[-107000630,-105000000],[-112000000,-105000000],[-112294056,-105014448],[-112585264,-105057640],[-112870848,-105129184],[-112919359,-105146535],[-113148048,-105228360],[-113194624,-105250392],[-113414191,-105354239],[-113666711,-105505591],[-113708095,-105536279],[-113903183,-105680967],[-114121320,-105878679],[-114319032,-106096816],[-114349720,-106138200],[-114494408,-106333288],[-114645760,-106585808],[-114667792,-106632384],[-114771640,-106851952],[-114788991,-106900463],[-114870815,-107129151],[-114942359,-107414735],[-114985551,-107705943],[-115000000,-107999999],[-115000000,-134000000],[-114985551,-134294048],[-114942359,-134585263],[-114870816,-134870847],[-114853464,-134919359],[-114771639,-135148064],[-114645759,-135414192],[-114494407,-135666720],[-114319031,-135903184],[-114121320,-136121327],[-114083144,-136155919],[-113903184,-136319023],[-113861799,-136349712],[-113666711,-136494416],[-113458383,-136619264],[-113414192,-136645743],[-113148049,-136771631],[-112870848,-136870815],[-112820872,-136883327],[-112585264,-136942351],[-112534303,-136949920],[-112294056,-136985551],[-112000000,-137000000],[-107000630,-137000000],[-106987456,-137268207],[-106985608,-137293440],[-106982647,-137317872],[-106946920,-137558751],[-106942896,-137582511],[-106933991,-137620624],[-106874471,-137858208],[-106862888,-137894751],[-106779992,-138126463],[-106765863,-138161424],[-106660080,-138385055],[-106643584,-138418223],[-106515671,-138631648],[-106487855,-138676256],[-106338352,-138877839],[-106306647,-138917600],[-106136616,-139105199],[-106121320,-139121328],[-105933000,-139291999],[-105887344,-139331407],[-105685351,-139481232],[-105631632,-139515663],[-105418216,-139643567],[-105193288,-139749951],[-105128959,-139779072],[-104897175,-139862016],[-104860247,-139873904],[-104622616,-139933423],[-104582511,-139942896],[-104558751,-139946912],[-104317880,-139982656],[-104293463,-139985616],[-104268216,-139987456],[-104025544,-139999376],[-104000000,-140000000],[-71999999,-140000000]],[[-105000000,-138000000],[-105000000,-104000000],[-71000000,-104000000],[-71000000,-138000000]],[[-69000000,-132000000],[-69000000,-110000000],[-64991180,-110000000],[-64991180,-132000000]],[[-111008824,-132000000],[-111008824,-110000000],[-107000000,-110000000],[-107000000,-132000000]]); - my $object = $print->objects->[0]; + my $object = $print->print->objects->[0]; $object->slice; my $layer = $object->layers->[1]; my $layerm = $layer->regions->[0]; diff --git a/t/print.t b/t/print.t index 863c17252..44317c637 100644 --- a/t/print.t +++ b/t/print.t @@ -38,21 +38,21 @@ use Slic3r::Test; my $print = Slic3r::Test::init_print(my $model = Slic3r::Test::model('20mm_cube'), config => $config); # user sets a per-region option - $print->objects->[0]->model_object->config->set('fill_density', 100); - $print->reload_object(0); + $print->print->objects->[0]->model_object->config->set('fill_density', 100); + $print->print->reload_object(0); # user exports G-code, thus the default config is reapplied - $print->apply_config($config); + $print->print->apply_config($config); - is $print->regions->[0]->config->fill_density, 100, 'apply_config() does not override per-object settings'; + is $print->print->regions->[0]->config->fill_density, 100, 'apply_config() does not override per-object settings'; # user assigns object extruders - $print->objects->[0]->model_object->config->set('extruder', 3); - $print->objects->[0]->model_object->config->set('perimeter_extruder', 2); - $print->reload_object(0); + $print->print->objects->[0]->model_object->config->set('extruder', 3); + $print->print->objects->[0]->model_object->config->set('perimeter_extruder', 2); + $print->print->reload_object(0); - is $print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded'; - is $print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders'; + is $print->print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded'; + is $print->print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders'; } __END__ diff --git a/t/retraction.t b/t/retraction.t index 186684c13..68a71569d 100644 --- a/t/retraction.t +++ b/t/retraction.t @@ -42,8 +42,8 @@ use Slic3r::Test qw(_eq); if ($info->{dist_Z}) { # lift move or lift + change layer - if (_eq($info->{dist_Z}, $print->config->get_at('retract_lift', $tool)) - || (_eq($info->{dist_Z}, $conf->layer_height + $print->config->get_at('retract_lift', $tool)) && $print->config->get_at('retract_lift', $tool) > 0)) { + if (_eq($info->{dist_Z}, $print->print->config->get_at('retract_lift', $tool)) + || (_eq($info->{dist_Z}, $conf->layer_height + $print->print->config->get_at('retract_lift', $tool)) && $print->print->config->get_at('retract_lift', $tool) > 0)) { fail 'only lifting while retracted' if !$retracted[$tool] && !($conf->g0 && $info->{retracting}); fail 'double lift' if $lifted; $lifted = 1; @@ -51,8 +51,8 @@ use Slic3r::Test qw(_eq); if ($info->{dist_Z} < 0) { fail 'going down only after lifting' if !$lifted; fail 'going down by the same amount of the lift or by the amount needed to get to next layer' - if !_eq($info->{dist_Z}, -$print->config->get_at('retract_lift', $tool)) - && !_eq($info->{dist_Z}, -$print->config->get_at('retract_lift', $tool) + $conf->layer_height); + if !_eq($info->{dist_Z}, -$print->print->config->get_at('retract_lift', $tool)) + && !_eq($info->{dist_Z}, -$print->print->config->get_at('retract_lift', $tool) + $conf->layer_height); $lifted = 0; } fail 'move Z at travel speed' if ($args->{F} // $self->F) != $conf->travel_speed * 60; @@ -60,9 +60,9 @@ use Slic3r::Test qw(_eq); if ($info->{retracting}) { $retracted[$tool] = 1; $retracted_length[$tool] += -$info->{dist_E}; - if (_eq($retracted_length[$tool], $print->config->get_at('retract_length', $tool))) { + if (_eq($retracted_length[$tool], $print->print->config->get_at('retract_length', $tool))) { # okay - } elsif (_eq($retracted_length[$tool], $print->config->get_at('retract_length_toolchange', $tool))) { + } elsif (_eq($retracted_length[$tool], $print->print->config->get_at('retract_length_toolchange', $tool))) { $wait_for_toolchange = 1; } else { fail 'retracted by the correct amount'; @@ -73,9 +73,9 @@ use Slic3r::Test qw(_eq); if ($info->{extruding}) { fail 'only extruding while not lifted' if $lifted; if ($retracted[$tool]) { - my $expected_amount = $retracted_length[$tool] + $print->config->get_at('retract_restart_extra', $tool); + my $expected_amount = $retracted_length[$tool] + $print->print->config->get_at('retract_restart_extra', $tool); if ($changed_tool && $toolchange_count[$tool] > 1) { - $expected_amount = $print->config->get_at('retract_length_toolchange', $tool) + $print->config->get_at('retract_restart_extra_toolchange', $tool); + $expected_amount = $print->print->config->get_at('retract_length_toolchange', $tool) + $print->print->config->get_at('retract_restart_extra_toolchange', $tool); $changed_tool = 0; } fail 'unretracted by the correct amount' @@ -84,7 +84,7 @@ use Slic3r::Test qw(_eq); $retracted_length[$tool] = 0; } } - if ($info->{travel} && $info->{dist_XY} >= $print->config->get_at('retract_before_travel', $tool)) { + if ($info->{travel} && $info->{dist_XY} >= $print->print->config->get_at('retract_before_travel', $tool)) { fail 'retracted before long travel move' if !$retracted[$tool]; } }); diff --git a/t/support.t b/t/support.t index 2f5ed2881..8186ec691 100644 --- a/t/support.t +++ b/t/support.t @@ -20,12 +20,12 @@ use Slic3r::Test; my $test = sub { my $print = Slic3r::Test::init_print('20mm_cube', config => $config); - $print->init_extruders; - my $flow = $print->objects->[0]->support_material_flow; + $print->print->init_extruders; + my $flow = $print->print->objects->[0]->support_material_flow; my $support_z = Slic3r::Print::SupportMaterial ->new( - object_config => $print->objects->[0]->config, - print_config => $print->config, + object_config => $print->print->objects->[0]->config, + print_config => $print->print->config, flow => $flow, interface_flow => $flow, first_layer_flow => $flow, diff --git a/t/svg.t b/t/svg.t index 9e2a8dcb1..eb274d59e 100644 --- a/t/svg.t +++ b/t/svg.t @@ -14,7 +14,7 @@ use Slic3r::Test; my $print = Slic3r::Test::init_print('20mm_cube'); eval { my $fh = IO::Scalar->new(\my $gcode); - $print->export_svg(output_fh => $fh, quiet => 1); + $print->print->export_svg(output_fh => $fh, quiet => 1); $fh->close; }; ok !$@, 'successful SVG export'; diff --git a/utils/dump-stl.pl b/utils/dump-stl.pl index 240f10b24..08b4d750a 100644 --- a/utils/dump-stl.pl +++ b/utils/dump-stl.pl @@ -18,7 +18,7 @@ $ARGV[0] or usage(1); if (-e $ARGV[0]) { my $model = Slic3r::Format::STL->read_file($ARGV[0]); - $model->objects->[0]->add_instance(offset => [0,0]); + $model->objects->[0]->add_instance(offset => Slic3r::Pointf->new(0,0)); my $mesh = $model->mesh; $mesh->repair; printf "VERTICES = %s\n", join ',', map "[$_->[0],$_->[1],$_->[2]]", @{$mesh->vertices}; diff --git a/xs/Build.PL b/xs/Build.PL index 915d6bca9..cf0f5bfa7 100644 --- a/xs/Build.PL +++ b/xs/Build.PL @@ -11,7 +11,8 @@ use Module::Build::WithXSpp; # NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace my @cflags = qw(-D_GLIBCXX_USE_C99 -DHAS_BOOL -DNOGDI -DSLIC3RXS); if ($ENV{SLIC3R_DEBUG}) { - push @cflags, qw(-DSLIC3R_DEBUG -g -ftemplate-backtrace-limit=0); + # only on newer GCCs: -ftemplate-backtrace-limit=0 + push @cflags, qw(-DSLIC3R_DEBUG -g); } if (ExtUtils::CppGuess->new->is_gcc) { # check whether we're dealing with a buggy GCC version diff --git a/xs/src/Model.cpp b/xs/src/Model.cpp index e5a04444d..35cf33792 100644 --- a/xs/src/Model.cpp +++ b/xs/src/Model.cpp @@ -6,24 +6,14 @@ Model::Model() {} Model::Model(const Model &other) { - objects.reserve(other.objects.size()); - - for (ModelMaterialMap::const_iterator i = other.materials.begin(); - i != other.materials.end(); ++i) - { - ModelMaterial *copy = new ModelMaterial(*i->second); - copy->model = this; - materials[i->first] = copy; - - } - - for (ModelObjectPtrs::const_iterator i = other.objects.begin(); - i != other.objects.end(); ++i) - { - ModelObject *copy = new ModelObject(**i); - copy->model = this; - objects.push_back(copy); - } + // copy materials + for (ModelMaterialMap::const_iterator i = other.materials.begin(); i != other.materials.end(); ++i) + this->add_material(i->first, *i->second); + + // copy objects + this->objects.reserve(other.objects.size()); + for (ModelObjectPtrs::const_iterator i = other.objects.begin(); i != other.objects.end(); ++i) + this->add_object(**i); } Model& Model::operator= (Model other) @@ -46,13 +36,19 @@ Model::~Model() } ModelObject* -Model::add_object(const std::string &input_file, const DynamicPrintConfig &config, - const t_layer_height_ranges &layer_height_ranges, const Pointf &origin_translation) +Model::add_object() { - ModelObject* object = new ModelObject(this, input_file, config, - layer_height_ranges, origin_translation); - this->objects.push_back(object); - return object; + ModelObject* new_object = new ModelObject(this); + this->objects.push_back(new_object); + return new_object; +} + +ModelObject* +Model::add_object(const ModelObject &other) +{ + ModelObject* new_object = new ModelObject(this, other); + this->objects.push_back(new_object); + return new_object; } void @@ -88,19 +84,40 @@ Model::clear_materials() this->delete_material( this->materials.begin()->first ); } -ModelMaterial * -Model::set_material(t_model_material_id material_id) +ModelMaterial* +Model::add_material(t_model_material_id material_id) { - ModelMaterialMap::iterator i = this->materials.find(material_id); - - ModelMaterial *mat; - if (i == this->materials.end()) { - mat = this->materials[material_id] = new ModelMaterial(this); - } else { - mat = i->second; + ModelMaterial* material = this->get_material(material_id); + if (material == NULL) { + material = this->materials[material_id] = new ModelMaterial(this); + } + return material; +} + +ModelMaterial* +Model::add_material(t_model_material_id material_id, const ModelMaterial &other) +{ + // delete existing material if any + ModelMaterial* material = this->get_material(material_id); + if (material != NULL) { + delete material; } - return mat; + // set new material + material = new ModelMaterial(this, other); + this->materials[material_id] = material; + return material; +} + +ModelMaterial* +Model::get_material(t_model_material_id material_id) +{ + ModelMaterialMap::iterator i = this->materials.find(material_id); + if (i == this->materials.end()) { + return NULL; + } else { + return i->second; + } } /* @@ -147,6 +164,9 @@ REGISTER_CLASS(Model, "Model"); ModelMaterial::ModelMaterial(Model *model) : model(model) {} +ModelMaterial::ModelMaterial(Model *model, const ModelMaterial &other) + : model(model), config(other.config), attributes(other.attributes) +{} void ModelMaterial::apply(const t_model_material_attributes &attributes) @@ -160,20 +180,12 @@ REGISTER_CLASS(ModelMaterial, "Model::Material"); #endif -ModelObject::ModelObject(Model *model, const std::string &input_file, - const DynamicPrintConfig &config, const t_layer_height_ranges &layer_height_ranges, - const Pointf &origin_translation) -: model(model), - input_file(input_file), - config(config), - layer_height_ranges(layer_height_ranges), - origin_translation(origin_translation), - _bounding_box_valid(false) -{ -} +ModelObject::ModelObject(Model *model) + : model(model) +{} -ModelObject::ModelObject(const ModelObject &other) -: model(other.model), +ModelObject::ModelObject(Model *model, const ModelObject &other) +: model(model), input_file(other.input_file), instances(), volumes(), @@ -183,25 +195,14 @@ ModelObject::ModelObject(const ModelObject &other) _bounding_box(other._bounding_box), _bounding_box_valid(other._bounding_box_valid) { - volumes.reserve(other.volumes.size()); - instances.reserve(other.instances.size()); - for (ModelVolumePtrs::const_iterator i = other.volumes.begin(); - i != other.volumes.end(); ++i) - { - ModelVolume *v = new ModelVolume(**i); - v->object = this; - volumes.push_back(v); + this->volumes.reserve(other.volumes.size()); + for (ModelVolumePtrs::const_iterator i = other.volumes.begin(); i != other.volumes.end(); ++i) + this->add_volume(**i); - } - - for (ModelInstancePtrs::const_iterator i = other.instances.begin(); - i != other.instances.end(); ++i) - { - ModelInstance *in = new ModelInstance(**i); - in->object = this; - instances.push_back(in); - } + this->instances.reserve(other.instances.size()); + for (ModelInstancePtrs::const_iterator i = other.instances.begin(); i != other.instances.end(); ++i) + this->add_instance(**i); } ModelObject& ModelObject::operator= (ModelObject other) @@ -229,11 +230,19 @@ ModelObject::~ModelObject() this->clear_instances(); } -ModelVolume * -ModelObject::add_volume(const t_model_material_id &material_id, - const TriangleMesh &mesh, bool modifier) +ModelVolume* +ModelObject::add_volume(const TriangleMesh &mesh) { - ModelVolume *v = new ModelVolume(this, material_id, mesh, modifier); + ModelVolume* v = new ModelVolume(this, mesh); + this->volumes.push_back(v); + this->invalidate_bounding_box(); + return v; +} + +ModelVolume* +ModelObject::add_volume(const ModelVolume &other) +{ + ModelVolume* v = new ModelVolume(this, other); this->volumes.push_back(v); this->invalidate_bounding_box(); return v; @@ -256,12 +265,19 @@ ModelObject::clear_volumes() this->delete_volume(i); } -ModelInstance * -ModelObject::add_instance(double rotation, double scaling_factor, - Pointf offset) +ModelInstance* +ModelObject::add_instance() { - ModelInstance *i = new ModelInstance( - this, rotation, scaling_factor, offset); + ModelInstance* i = new ModelInstance(this); + this->instances.push_back(i); + this->invalidate_bounding_box(); + return i; +} + +ModelInstance* +ModelObject::add_instance(const ModelInstance &other) +{ + ModelInstance* i = new ModelInstance(this, other); this->instances.push_back(i); this->invalidate_bounding_box(); return i; @@ -300,28 +316,26 @@ REGISTER_CLASS(ModelObject, "Model::Object"); #endif -ModelVolume::ModelVolume(ModelObject* object, const t_model_material_id &material_id, - const TriangleMesh &mesh, bool modifier) -: object(object), - material_id(material_id), - mesh(mesh), - modifier(modifier) -{ -} +ModelVolume::ModelVolume(ModelObject* object, const TriangleMesh &mesh) +: object(object), mesh(mesh), modifier(false) +{} + +ModelVolume::ModelVolume(ModelObject* object, const ModelVolume &other) +: object(object), material_id(other.material_id), mesh(other.mesh), modifier(other.modifier) +{} #ifdef SLIC3RXS REGISTER_CLASS(ModelVolume, "Model::Volume"); #endif -ModelInstance::ModelInstance(ModelObject *object, double rotation, - double scaling_factor, const Pointf &offset) -: object(object), - rotation(rotation), - scaling_factor(scaling_factor), - offset(offset) -{ -} +ModelInstance::ModelInstance(ModelObject *object) +: object(object), rotation(0), scaling_factor(1) +{} + +ModelInstance::ModelInstance(ModelObject *object, const ModelInstance &other) +: object(object), rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset) +{} #ifdef SLIC3RXS REGISTER_CLASS(ModelInstance, "Model::Instance"); diff --git a/xs/src/Model.hpp b/xs/src/Model.hpp index facbc3777..84c68ee61 100644 --- a/xs/src/Model.hpp +++ b/xs/src/Model.hpp @@ -38,13 +38,16 @@ class Model Model& operator= (Model other); void swap(Model &other); ~Model(); - ModelObject* add_object(const std::string &input_file, const DynamicPrintConfig &config, - const t_layer_height_ranges &layer_height_ranges, const Pointf &origin_translation); + ModelObject* add_object(); + ModelObject* add_object(const ModelObject &other); void delete_object(size_t idx); void clear_objects(); + + ModelMaterial* add_material(t_model_material_id material_id); + ModelMaterial* add_material(t_model_material_id material_id, const ModelMaterial &other); + ModelMaterial* get_material(t_model_material_id material_id); void delete_material(t_model_material_id material_id); void clear_materials(); - ModelMaterial *set_material(t_model_material_id material_id); // void duplicate_objects_grid(unsigned int x, unsigned int y, coordf_t distance); // void duplicate_objects(size_t copies_num, coordf_t distance, const BoundingBox &bb); // void arrange_objects(coordf_t distance, const BoundingBox &bb); @@ -65,19 +68,25 @@ class Model class ModelMaterial { + friend class Model; public: - Model* model; t_model_material_attributes attributes; DynamicPrintConfig config; - ModelMaterial(Model *model); + Model* get_model() const { return this->model; }; void apply(const t_model_material_attributes &attributes); + + private: + Model* model; + + ModelMaterial(Model *model); + ModelMaterial(Model *model, const ModelMaterial &other); }; class ModelObject { + friend class Model; public: - Model* model; std::string input_file; ModelInstancePtrs instances; ModelVolumePtrs volumes; @@ -89,65 +98,76 @@ class ModelObject BoundingBoxf3 _bounding_box; bool _bounding_box_valid; - ModelObject(Model *model, const std::string &input_file, const DynamicPrintConfig &config, - const t_layer_height_ranges &layer_height_ranges, const Pointf &origin_translation); - ModelObject(const ModelObject &other); - ModelObject& operator= (ModelObject other); - void swap(ModelObject &other); - ~ModelObject(); - - ModelVolume* add_volume(const t_model_material_id &material_id, - const TriangleMesh &mesh, bool modifier); + Model* get_model() const { return this->model; }; + + ModelVolume* add_volume(const TriangleMesh &mesh); + ModelVolume* add_volume(const ModelVolume &volume); void delete_volume(size_t idx); void clear_volumes(); - ModelInstance *add_instance(double rotation=0, double scaling_factor = 1, - Pointf offset = Pointf(0, 0)); + ModelInstance* add_instance(); + ModelInstance* add_instance(const ModelInstance &instance); void delete_instance(size_t idx); void delete_last_instance(); void clear_instances(); void invalidate_bounding_box(); - 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* materials) const; - size_t facets_count() const; - bool needed_repair() 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* materials) const; + //size_t facets_count() const; + //bool needed_repair() const; private: + Model* model; + + ModelObject(Model *model); + ModelObject(Model *model, const ModelObject &other); + ModelObject& operator= (ModelObject other); + void swap(ModelObject &other); + ~ModelObject(); void update_bounding_box(); }; class ModelVolume { + friend class ModelObject; public: - ModelObject* object; t_model_material_id material_id; TriangleMesh mesh; bool modifier; - - ModelVolume(ModelObject *object, const t_model_material_id &material_id, - const TriangleMesh &mesh, bool modifier); + + ModelObject* get_object() const { return this->object; }; + + private: + ModelObject* object; + + ModelVolume(ModelObject *object, const TriangleMesh &mesh); + ModelVolume(ModelObject *object, const ModelVolume &other); }; class ModelInstance { + friend class ModelObject; public: - ModelObject* object; double rotation; // around mesh center point double scaling_factor; Pointf offset; // in unscaled coordinates - - ModelInstance(ModelObject *object, double rotation, double scaling_factor, - const Pointf &offset); + ModelObject* get_object() const { return this->object; }; void transform_mesh(TriangleMesh* mesh, bool dont_translate) const; void transform_polygon(Polygon* polygon) const; + + private: + ModelObject* object; + + ModelInstance(ModelObject *object); + ModelInstance(ModelObject *object, const ModelInstance &other); }; } diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index ae4b9fc22..1dc8d010b 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -12,38 +12,30 @@ Clone clone() %code%{ RETVAL = THIS; %}; - - Ref _add_object(std::string input_file, - DynamicPrintConfig* config, - t_layer_height_ranges layer_height_ranges, - Pointf* origin_translation) - %code%{ - RETVAL = THIS->add_object(input_file, *config, layer_height_ranges, - *origin_translation); - %}; + %name{_add_object} Ref add_object(); + Ref _add_object_clone(ModelObject* other) + %code%{ RETVAL = THIS->add_object(*other); %}; void delete_object(size_t idx); void clear_objects(); - void delete_material(t_model_material_id material_id); - void clear_materials(); - - %name{_set_material} Ref set_material(t_model_material_id material_id) - %code%{ RETVAL = THIS->set_material(material_id); %}; Ref get_material(t_model_material_id material_id) %code%{ - ModelMaterialMap::iterator i = THIS->materials.find(material_id); - if (i == THIS->materials.end()) { + RETVAL = THIS->get_material(material_id); + if (RETVAL == NULL) { XSRETURN_UNDEF; } - - RETVAL = i->second; %}; + %name{add_material} Ref add_material(t_model_material_id material_id); + Ref add_material_clone(t_model_material_id material_id, ModelMaterial* other) + %code%{ RETVAL = THIS->add_material(material_id, *other); %}; bool has_material(t_model_material_id material_id) const %code%{ - RETVAL = (THIS->materials.find(material_id) != THIS->materials.end()); + RETVAL = (THIS->get_material(material_id) != NULL); %}; + void delete_material(t_model_material_id material_id); + void clear_materials(); std::vector material_names() const %code%{ @@ -70,22 +62,14 @@ // void split_meshes(); // std::string get_material_name(t_model_material_id material_id); - ModelObjectPtrs *objects() - %code%{ - if (THIS->objects.empty()) { - XSRETURN_UNDEF; - } - - RETVAL = &THIS->objects; - %}; + ModelObjectPtrs* objects() + %code%{ RETVAL = &THIS->objects; %}; }; %name{Slic3r::Model::Material} class ModelMaterial { - ~ModelMaterial(); - Ref model() - %code%{ RETVAL = THIS->model; %}; + %code%{ RETVAL = THIS->get_model(); %}; Ref config() %code%{ RETVAL = &THIS->config; %}; @@ -114,44 +98,21 @@ ModelMaterial::attributes() %name{Slic3r::Model::Object} class ModelObject { - ModelObject(Model* model, std::string input_file, - DynamicPrintConfig* config, t_layer_height_ranges layer_height_ranges, - Pointf* origin_translation) - %code%{ - RETVAL = new ModelObject(model, input_file, *config, - layer_height_ranges, *origin_translation); - %}; - - ~ModelObject(); - - ModelVolumePtrs *volumes() - %code%{ - if (THIS->volumes.empty()) { - XSRETURN_UNDEF; - } - - RETVAL = &THIS->volumes; - %}; - - ModelInstancePtrs *instances() - %code%{ - if (THIS->instances.empty()) { - XSRETURN_UNDEF; - } - - RETVAL = &THIS->instances; - %}; - + ModelVolumePtrs* volumes() + %code%{ RETVAL = &THIS->volumes; %}; + ModelInstancePtrs* instances() + %code%{ RETVAL = &THIS->instances; %}; + void invalidate_bounding_box(); - Ref _bounding_box(BoundingBoxf3 *new_bbox = NULL) + Ref _bounding_box(BoundingBoxf3* new_bbox = NULL) %code{% if (NULL != new_bbox) { THIS->_bounding_box = *new_bbox; THIS->_bounding_box_valid = true; } - + if (!THIS->_bounding_box_valid) { XSRETURN_UNDEF; } @@ -159,21 +120,21 @@ ModelMaterial::attributes() RETVAL = &THIS->_bounding_box; %}; - %name{_add_volume} Ref add_volume( - t_model_material_id material_id, TriangleMesh* mesh, bool modifier) - %code%{ RETVAL = THIS->add_volume(material_id, *mesh, modifier); %}; + %name{_add_volume} Ref add_volume(TriangleMesh* mesh) + %code%{ RETVAL = THIS->add_volume(*mesh); %}; + Ref _add_volume_clone(ModelVolume* other) + %code%{ RETVAL = THIS->add_volume(*other); %}; void delete_volume(size_t idx); void clear_volumes(); - %name{_add_instance} Ref add_instance( - double rotation, double scaling_factor, std::vector offset) - %code%{ - RETVAL = THIS->add_instance(rotation, scaling_factor, - Pointf(offset[0], offset[1])); - %}; + %name{_add_instance} Ref add_instance(); + Ref _add_instance_clone(ModelInstance* other) + %code%{ RETVAL = THIS->add_instance(*other); %}; void delete_last_instance(); void clear_instances(); + int instances_count() + %code%{ RETVAL = THIS->instances.size(); %}; std::string input_file() %code%{ RETVAL = THIS->input_file; %}; @@ -183,38 +144,42 @@ ModelMaterial::attributes() %code%{ RETVAL = &THIS->config; %}; Ref model() - %code%{ RETVAL = THIS->model; %}; + %code%{ RETVAL = THIS->get_model(); %}; t_layer_height_ranges layer_height_ranges() %code%{ RETVAL = THIS->layer_height_ranges; %}; + void set_layer_height_ranges(t_layer_height_ranges ranges) + %code%{ THIS->layer_height_ranges = ranges; %}; Clone origin_translation() %code%{ RETVAL = THIS->origin_translation; %}; + void set_origin_translation(Pointf* point) + %code%{ THIS->origin_translation = *point; %}; }; %name{Slic3r::Model::Volume} class ModelVolume { - ~ModelVolume(); - Ref object() - %code%{ RETVAL = THIS->object; %}; + %code%{ RETVAL = THIS->get_object(); %}; t_model_material_id material_id() %code%{ RETVAL = THIS->material_id; %}; + void set_material_id(t_model_material_id material_id) + %code%{ THIS->material_id = material_id; %}; Ref mesh() %code%{ RETVAL = &THIS->mesh; %}; bool modifier() %code%{ RETVAL = THIS->modifier; %}; + void set_modifier(bool modifier) + %code%{ THIS->modifier = modifier; %}; }; %name{Slic3r::Model::Instance} class ModelInstance { - ~ModelInstance(); - Ref object() - %code%{ RETVAL = THIS->object; %}; + %code%{ RETVAL = THIS->get_object(); %}; double rotation() %code%{ RETVAL = THIS->rotation; %};