Ported some methods including add_model_object() and apply_config() to XS
This commit is contained in:
parent
6b4015f9ac
commit
3e4c572164
14 changed files with 312 additions and 254 deletions
|
@ -174,19 +174,6 @@ sub _handle_legacy {
|
|||
return ($opt_key, $value);
|
||||
}
|
||||
|
||||
sub set_ifndef {
|
||||
my $self = shift;
|
||||
my ($opt_key, $value, $deserialize) = @_;
|
||||
|
||||
if (!$self->has($opt_key)) {
|
||||
if ($deserialize) {
|
||||
$self->set_deserialize($opt_key, $value);
|
||||
} else {
|
||||
$self->set($opt_key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub as_ini {
|
||||
my ($self) = @_;
|
||||
|
||||
|
@ -213,23 +200,6 @@ sub setenv {
|
|||
}
|
||||
}
|
||||
|
||||
sub equals {
|
||||
my ($self, $other) = @_;
|
||||
return @{ $self->diff($other) } == 0;
|
||||
}
|
||||
|
||||
# this will *ignore* options not present in both configs
|
||||
sub diff {
|
||||
my ($self, $other) = @_;
|
||||
|
||||
my @diff = ();
|
||||
foreach my $opt_key (sort @{$self->get_keys}) {
|
||||
push @diff, $opt_key
|
||||
if $other->has($opt_key) && $other->serialize($opt_key) ne $self->serialize($opt_key);
|
||||
}
|
||||
return [@diff];
|
||||
}
|
||||
|
||||
# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
|
||||
# objects because it performs cross checks
|
||||
sub validate {
|
||||
|
|
|
@ -34,189 +34,6 @@ sub status_cb {
|
|||
return $status_cb // sub {};
|
||||
}
|
||||
|
||||
sub apply_config {
|
||||
my ($self, $config) = @_;
|
||||
|
||||
$config = $config->clone;
|
||||
$config->normalize;
|
||||
|
||||
# apply variables to placeholder parser
|
||||
$self->placeholder_parser->apply_config($config);
|
||||
|
||||
my $invalidated = 0;
|
||||
|
||||
# handle changes to print config
|
||||
my $print_diff = $self->config->diff($config);
|
||||
if (@$print_diff) {
|
||||
$self->config->apply_dynamic($config);
|
||||
|
||||
$invalidated = 1
|
||||
if $self->invalidate_state_by_config_options($print_diff);
|
||||
}
|
||||
|
||||
# handle changes to object config defaults
|
||||
$self->default_object_config->apply_dynamic($config);
|
||||
foreach my $object (@{$self->objects}) {
|
||||
# we don't assume that $config contains a full ObjectConfig,
|
||||
# so we base it on the current print-wise default
|
||||
my $new = $self->default_object_config->clone;
|
||||
$new->apply_dynamic($config);
|
||||
|
||||
# we override the new config with object-specific options
|
||||
my $model_object_config = $object->model_object->config->clone;
|
||||
$model_object_config->normalize;
|
||||
$new->apply_dynamic($model_object_config);
|
||||
|
||||
# check whether the new config is different from the current one
|
||||
my $diff = $object->config->diff($new);
|
||||
if (@$diff) {
|
||||
$object->config->apply($new);
|
||||
|
||||
$invalidated = 1
|
||||
if $object->invalidate_state_by_config_options($diff);
|
||||
}
|
||||
}
|
||||
|
||||
# handle changes to regions config defaults
|
||||
$self->default_region_config->apply_dynamic($config);
|
||||
|
||||
# All regions now have distinct settings.
|
||||
# Check whether applying the new region config defaults we'd get different regions.
|
||||
my $rearrange_regions = 0;
|
||||
my @other_region_configs = ();
|
||||
REGION: foreach my $region_id (0..($self->region_count - 1)) {
|
||||
my $region = $self->regions->[$region_id];
|
||||
my @this_region_configs = ();
|
||||
foreach my $object (@{$self->objects}) {
|
||||
foreach my $volume_id (@{ $object->get_region_volumes($region_id) }) {
|
||||
my $volume = $object->model_object->volumes->[$volume_id];
|
||||
|
||||
my $new = $self->default_region_config->clone;
|
||||
foreach my $other_config ($object->model_object->config, $volume->config) {
|
||||
my $other_config = $other_config->clone;
|
||||
$other_config->normalize;
|
||||
$new->apply_dynamic($other_config);
|
||||
}
|
||||
if ($volume->material_id ne '') {
|
||||
my $material_config = $object->model_object->model->get_material($volume->material_id)->config->clone;
|
||||
$material_config->normalize;
|
||||
$new->apply_dynamic($material_config);
|
||||
}
|
||||
if (defined first { !$_->equals($new) } @this_region_configs) {
|
||||
# if the new config for this volume differs from the other
|
||||
# volume configs currently associated to this region, it means
|
||||
# the region subdivision does not make sense anymore
|
||||
$rearrange_regions = 1;
|
||||
last REGION;
|
||||
}
|
||||
push @this_region_configs, $new;
|
||||
|
||||
if (defined first { $_->equals($new) } @other_region_configs) {
|
||||
# if the new config for this volume equals any of the other
|
||||
# volume configs that are not currently associated to this
|
||||
# region, it means the region subdivision does not make
|
||||
# sense anymore
|
||||
$rearrange_regions = 1;
|
||||
last REGION;
|
||||
}
|
||||
|
||||
# if we're here and the new region config is different from the old
|
||||
# one, we need to apply the new config and invalidate all objects
|
||||
# (possible optimization: only invalidate objects using this region)
|
||||
my $region_config_diff = $region->config->diff($new);
|
||||
if (@$region_config_diff) {
|
||||
$region->config->apply($new);
|
||||
foreach my $o (@{$self->objects}) {
|
||||
$invalidated = 1
|
||||
if $o->invalidate_state_by_config_options($region_config_diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
push @other_region_configs, @this_region_configs;
|
||||
}
|
||||
|
||||
if ($rearrange_regions) {
|
||||
# the current subdivision of regions does not make sense anymore.
|
||||
# we need to remove all objects and re-add them
|
||||
my @model_objects = map $_->model_object, @{$self->objects};
|
||||
$self->clear_objects;
|
||||
$self->add_model_object($_) for @model_objects;
|
||||
$invalidated = 1;
|
||||
}
|
||||
|
||||
return $invalidated;
|
||||
}
|
||||
|
||||
# caller is responsible for supplying models whose objects don't collide
|
||||
# and have explicit instance positions
|
||||
sub add_model_object {
|
||||
my $self = shift;
|
||||
my ($object, $obj_idx) = @_;
|
||||
|
||||
my $object_config = $object->config->clone;
|
||||
$object_config->normalize;
|
||||
|
||||
# initialize print object and store it at the given position
|
||||
my $o;
|
||||
if (defined $obj_idx) {
|
||||
$o = $self->set_new_object($obj_idx, $object, $object->raw_bounding_box);
|
||||
} else {
|
||||
$o = $self->add_object($object, $object->raw_bounding_box);
|
||||
}
|
||||
|
||||
$o->set_copies([ map Slic3r::Point->new_scale(@{ $_->offset }), @{ $object->instances } ]);
|
||||
$o->set_layer_height_ranges($object->layer_height_ranges);
|
||||
|
||||
# TODO: translate _trigger_copies to C++, then this can be done by
|
||||
# PrintObject constructor
|
||||
$o->_trigger_copies;
|
||||
|
||||
foreach my $volume_id (0..$#{$object->volumes}) {
|
||||
my $volume = $object->volumes->[$volume_id];
|
||||
|
||||
# get the config applied to this volume: start from our global defaults
|
||||
my $config = Slic3r::Config::PrintRegion->new;
|
||||
$config->apply($self->default_region_config);
|
||||
|
||||
# override the defaults with per-object config and then with per-volume and per-material configs
|
||||
foreach my $other_config ($object_config, $volume->config) {
|
||||
my $other_config = $other_config->clone;
|
||||
$other_config->normalize;
|
||||
$config->apply_dynamic($other_config);
|
||||
}
|
||||
if ($volume->material_id ne '') {
|
||||
my $material_config = $volume->material->config->clone;
|
||||
$material_config->normalize;
|
||||
$config->apply_dynamic($material_config);
|
||||
}
|
||||
|
||||
# find an existing print region with the same config
|
||||
my $region_id;
|
||||
foreach my $i (0..($self->region_count - 1)) {
|
||||
my $region = $self->regions->[$i];
|
||||
if ($config->equals($region->config)) {
|
||||
$region_id = $i;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# if no region exists with the same config, create a new one
|
||||
if (!defined $region_id) {
|
||||
my $r = $self->add_region();
|
||||
$r->config->apply($config);
|
||||
$region_id = $self->region_count - 1;
|
||||
}
|
||||
|
||||
# assign volume to region
|
||||
$o->add_region_volume($region_id, $volume_id);
|
||||
}
|
||||
|
||||
# apply config to print object
|
||||
$o->config->apply($self->default_object_config);
|
||||
$o->config->apply_dynamic($object_config);
|
||||
}
|
||||
|
||||
sub reload_object {
|
||||
my ($self, $obj_idx) = @_;
|
||||
|
||||
|
|
|
@ -32,34 +32,12 @@ sub support_layers {
|
|||
return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ];
|
||||
}
|
||||
|
||||
# TODO: translate to C++, then call it from constructor (see also
|
||||
# Print->add_model_object)
|
||||
sub _trigger_copies {
|
||||
my $self = shift;
|
||||
|
||||
# TODO: should this mean point is 0,0?
|
||||
return if !defined $self->_copies_shift;
|
||||
|
||||
# order copies with a nearest neighbor search and translate them by _copies_shift
|
||||
$self->set_shifted_copies([
|
||||
map {
|
||||
my $c = $_->clone;
|
||||
$c->translate(@{ $self->_copies_shift });
|
||||
$c;
|
||||
} @{$self->copies}[@{chained_path($self->copies)}]
|
||||
]);
|
||||
|
||||
$self->print->invalidate_step(STEP_SKIRT);
|
||||
$self->print->invalidate_step(STEP_BRIM);
|
||||
}
|
||||
|
||||
# in unscaled coordinates
|
||||
sub add_copy {
|
||||
my ($self, $x, $y) = @_;
|
||||
my @copies = @{$self->copies};
|
||||
push @copies, Slic3r::Point->new_scale($x, $y);
|
||||
$self->set_copies(\@copies);
|
||||
$self->_trigger_copies;
|
||||
}
|
||||
|
||||
sub delete_last_copy {
|
||||
|
@ -67,13 +45,11 @@ sub delete_last_copy {
|
|||
my @copies = $self->copies;
|
||||
pop @copies;
|
||||
$self->set_copies(\@copies);
|
||||
$self->_trigger_copies;
|
||||
}
|
||||
|
||||
sub delete_all_copies {
|
||||
my ($self) = @_;
|
||||
$self->set_copies([]);
|
||||
$self->_trigger_copies;
|
||||
}
|
||||
|
||||
# this is the *total* layer count (including support layers)
|
||||
|
|
|
@ -27,6 +27,27 @@ ConfigBase::apply(const ConfigBase &other, bool ignore_nonexistent) {
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ConfigBase::equals(ConfigBase &other) {
|
||||
return this->diff(other).empty();
|
||||
}
|
||||
|
||||
// this will *ignore* options not present in both configs
|
||||
t_config_option_keys
|
||||
ConfigBase::diff(ConfigBase &other) {
|
||||
t_config_option_keys diff;
|
||||
|
||||
t_config_option_keys my_keys;
|
||||
this->keys(&my_keys);
|
||||
for (t_config_option_keys::const_iterator opt_key = my_keys.begin(); opt_key != my_keys.end(); ++opt_key) {
|
||||
if (other.has(*opt_key) && other.serialize(*opt_key) != this->serialize(*opt_key)) {
|
||||
diff.push_back(*opt_key);
|
||||
}
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
std::string
|
||||
ConfigBase::serialize(const t_config_option_key opt_key) {
|
||||
ConfigOption* opt = this->option(opt_key);
|
||||
|
@ -248,6 +269,18 @@ ConfigBase::set_deserialize(const t_config_option_key opt_key, SV* str) {
|
|||
|
||||
return this->set_deserialize(opt_key, value);
|
||||
}
|
||||
|
||||
void
|
||||
ConfigBase::set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize)
|
||||
{
|
||||
if (!this->has(opt_key)) {
|
||||
if (deserialize) {
|
||||
this->set_deserialize(opt_key, value);
|
||||
} else {
|
||||
this->set(opt_key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
|
||||
|
|
|
@ -464,8 +464,11 @@ class ConfigBase
|
|||
virtual const ConfigOption* option(const t_config_option_key opt_key) const = 0;
|
||||
virtual void keys(t_config_option_keys *keys) const = 0;
|
||||
void apply(const ConfigBase &other, bool ignore_nonexistent = false);
|
||||
bool equals(ConfigBase &other);
|
||||
t_config_option_keys diff(ConfigBase &other);
|
||||
std::string serialize(const t_config_option_key opt_key);
|
||||
bool set_deserialize(const t_config_option_key opt_key, std::string str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
double get_abs_value(const t_config_option_key opt_key);
|
||||
double get_abs_value(const t_config_option_key opt_key, double ratio_over);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ sort_points (Point a, Point b)
|
|||
|
||||
/* This implementation is based on Andrew's monotone chain 2D convex hull algorithm */
|
||||
void
|
||||
convex_hull(Points &points, Polygon* hull)
|
||||
convex_hull(Points points, Polygon* hull)
|
||||
{
|
||||
assert(points.size() >= 3);
|
||||
// sort input points
|
||||
|
@ -55,12 +55,12 @@ convex_hull(Points &points, Polygon* hull)
|
|||
/* accepts an arrayref of points and returns a list of indices
|
||||
according to a nearest-neighbor walk */
|
||||
void
|
||||
chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near)
|
||||
chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near)
|
||||
{
|
||||
PointPtrs my_points;
|
||||
std::map<Point*,Points::size_type> indices;
|
||||
PointConstPtrs my_points;
|
||||
std::map<const Point*,Points::size_type> indices;
|
||||
my_points.reserve(points.size());
|
||||
for (Points::iterator it = points.begin(); it != points.end(); ++it) {
|
||||
for (Points::const_iterator it = points.begin(); it != points.end(); ++it) {
|
||||
my_points.push_back(&*it);
|
||||
indices[&*it] = it - points.begin();
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ chained_path(Points &points, std::vector<Points::size_type> &retval, Point start
|
|||
}
|
||||
|
||||
void
|
||||
chained_path(Points &points, std::vector<Points::size_type> &retval)
|
||||
chained_path(const Points &points, std::vector<Points::size_type> &retval)
|
||||
{
|
||||
if (points.empty()) return; // can't call front() on empty vector
|
||||
chained_path(points, retval, points.front());
|
||||
|
|
|
@ -11,9 +11,9 @@ using boost::polygon::voronoi_diagram;
|
|||
|
||||
namespace Slic3r { namespace Geometry {
|
||||
|
||||
void convex_hull(Points &points, Polygon* hull);
|
||||
void chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near);
|
||||
void chained_path(Points &points, std::vector<Points::size_type> &retval);
|
||||
void convex_hull(Points points, Polygon* hull);
|
||||
void chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near);
|
||||
void chained_path(const Points &points, std::vector<Points::size_type> &retval);
|
||||
template<class T> void chained_path_items(Points &points, T &items, T &retval);
|
||||
bool directions_parallel(double angle1, double angle2, double max_diff = 0);
|
||||
|
||||
|
|
|
@ -40,6 +40,12 @@ Point::translate(double x, double y)
|
|||
this->y += y;
|
||||
}
|
||||
|
||||
void
|
||||
Point::translate(const Point &vector)
|
||||
{
|
||||
this->translate(vector.x, vector.y);
|
||||
}
|
||||
|
||||
void
|
||||
Point::rotate(double angle, const Point ¢er)
|
||||
{
|
||||
|
|
|
@ -27,10 +27,14 @@ class Point
|
|||
Point(int _x, int _y): x(_x), y(_y) {};
|
||||
Point(long long _x, long long _y): x(_x), y(_y) {}; // for Clipper
|
||||
Point(double x, double y);
|
||||
static Point new_scale(coordf_t x, coordf_t y) {
|
||||
return Point(scale_(x), scale_(y));
|
||||
};
|
||||
bool operator==(const Point& rhs) const;
|
||||
std::string wkt() const;
|
||||
void scale(double factor);
|
||||
void translate(double x, double y);
|
||||
void translate(const Point &vector);
|
||||
void rotate(double angle, const Point ¢er);
|
||||
bool coincides_with(const Point &point) const;
|
||||
bool coincides_with_epsilon(const Point &point) const;
|
||||
|
|
|
@ -308,6 +308,189 @@ Print::max_allowed_layer_height() const
|
|||
return *std::max_element(nozzle_diameter.begin(), nozzle_diameter.end());
|
||||
}
|
||||
|
||||
/* Caller is responsible for supplying models whose objects don't collide
|
||||
and have explicit instance positions */
|
||||
void
|
||||
Print::add_model_object(ModelObject* model_object, int idx)
|
||||
{
|
||||
DynamicPrintConfig object_config = model_object->config; // clone
|
||||
object_config.normalize();
|
||||
|
||||
// initialize print object and store it at the given position
|
||||
PrintObject* o;
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
model_object->raw_bounding_box(&bb);
|
||||
o = (idx != -1)
|
||||
? this->set_new_object(idx, model_object, bb)
|
||||
: this->add_object(model_object, bb);
|
||||
}
|
||||
|
||||
{
|
||||
Points copies;
|
||||
for (ModelInstancePtrs::const_iterator i = model_object->instances.begin(); i != model_object->instances.end(); ++i) {
|
||||
copies.push_back(Point::new_scale((*i)->offset.x, (*i)->offset.y));
|
||||
}
|
||||
o->set_copies(copies);
|
||||
}
|
||||
o->layer_height_ranges = model_object->layer_height_ranges;
|
||||
|
||||
for (ModelVolumePtrs::const_iterator v_i = model_object->volumes.begin(); v_i != model_object->volumes.end(); ++v_i) {
|
||||
size_t volume_id = v_i - model_object->volumes.begin();
|
||||
ModelVolume* volume = *v_i;
|
||||
|
||||
// get the config applied to this volume
|
||||
PrintRegionConfig config = this->_region_config_from_model_volume(*volume);
|
||||
|
||||
// find an existing print region with the same config
|
||||
int region_id = -1;
|
||||
for (PrintRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region) {
|
||||
if (config.equals((*region)->config)) {
|
||||
region_id = region - this->regions.begin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if no region exists with the same config, create a new one
|
||||
if (region_id == -1) {
|
||||
PrintRegion* r = this->add_region();
|
||||
r->config.apply(config);
|
||||
region_id = this->regions.size() - 1;
|
||||
}
|
||||
|
||||
// assign volume to region
|
||||
o->add_region_volume(region_id, volume_id);
|
||||
}
|
||||
|
||||
// apply config to print object
|
||||
o->config.apply(this->default_object_config);
|
||||
o->config.apply(object_config, true);
|
||||
}
|
||||
|
||||
bool
|
||||
Print::apply_config(DynamicPrintConfig config)
|
||||
{
|
||||
// we get a copy of the config object so we can modify it safely
|
||||
config.normalize();
|
||||
|
||||
// apply variables to placeholder parser
|
||||
this->placeholder_parser.apply_config(config);
|
||||
|
||||
bool invalidated = false;
|
||||
|
||||
// handle changes to print config
|
||||
t_config_option_keys print_diff = this->config.diff(config);
|
||||
if (!print_diff.empty()) {
|
||||
this->config.apply(config, true);
|
||||
|
||||
if (this->invalidate_state_by_config_options(print_diff))
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
// handle changes to object config defaults
|
||||
this->default_object_config.apply(config, true);
|
||||
FOREACH_OBJECT(this, obj_ptr) {
|
||||
// we don't assume that config contains a full ObjectConfig,
|
||||
// so we base it on the current print-wise default
|
||||
PrintObjectConfig new_config = this->default_object_config;
|
||||
new_config.apply(config, true);
|
||||
|
||||
// we override the new config with object-specific options
|
||||
{
|
||||
DynamicPrintConfig model_object_config = (*obj_ptr)->model_object()->config;
|
||||
model_object_config.normalize();
|
||||
new_config.apply(model_object_config, true);
|
||||
}
|
||||
|
||||
// check whether the new config is different from the current one
|
||||
t_config_option_keys diff = (*obj_ptr)->config.diff(new_config);
|
||||
if (!diff.empty()) {
|
||||
(*obj_ptr)->config.apply(new_config, true);
|
||||
|
||||
if ((*obj_ptr)->invalidate_state_by_config_options(diff))
|
||||
invalidated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// handle changes to regions config defaults
|
||||
this->default_region_config.apply(config, true);
|
||||
|
||||
// All regions now have distinct settings.
|
||||
// Check whether applying the new region config defaults we'd get different regions.
|
||||
bool rearrange_regions = false;
|
||||
std::vector<PrintRegionConfig> other_region_configs;
|
||||
FOREACH_REGION(this, it_r) {
|
||||
size_t region_id = it_r - this->regions.begin();
|
||||
PrintRegion* region = *it_r;
|
||||
|
||||
std::vector<PrintRegionConfig> this_region_configs;
|
||||
FOREACH_OBJECT(this, it_o) {
|
||||
PrintObject* object = *it_o;
|
||||
|
||||
std::vector<int> ®ion_volumes = object->region_volumes[region_id];
|
||||
for (std::vector<int>::const_iterator volume_id = region_volumes.begin(); volume_id != region_volumes.end(); ++volume_id) {
|
||||
ModelVolume* volume = object->model_object()->volumes[*volume_id];
|
||||
|
||||
PrintRegionConfig new_config = this->_region_config_from_model_volume(*volume);
|
||||
|
||||
for (std::vector<PrintRegionConfig>::iterator it = this_region_configs.begin(); it != this_region_configs.end(); ++it) {
|
||||
// if the new config for this volume differs from the other
|
||||
// volume configs currently associated to this region, it means
|
||||
// the region subdivision does not make sense anymore
|
||||
if (!it->equals(new_config)) {
|
||||
rearrange_regions = true;
|
||||
goto NEXT_REGION;
|
||||
}
|
||||
}
|
||||
this_region_configs.push_back(new_config);
|
||||
|
||||
for (std::vector<PrintRegionConfig>::iterator it = other_region_configs.begin(); it != other_region_configs.end(); ++it) {
|
||||
// if the new config for this volume equals any of the other
|
||||
// volume configs that are not currently associated to this
|
||||
// region, it means the region subdivision does not make
|
||||
// sense anymore
|
||||
if (it->equals(new_config)) {
|
||||
rearrange_regions = true;
|
||||
goto NEXT_REGION;
|
||||
}
|
||||
}
|
||||
|
||||
// if we're here and the new region config is different from the old
|
||||
// one, we need to apply the new config and invalidate all objects
|
||||
// (possible optimization: only invalidate objects using this region)
|
||||
t_config_option_keys region_config_diff = region->config.diff(new_config);
|
||||
if (!region_config_diff.empty()) {
|
||||
region->config.apply(new_config);
|
||||
FOREACH_OBJECT(this, o) {
|
||||
if ((*o)->invalidate_state_by_config_options(region_config_diff))
|
||||
invalidated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
other_region_configs.insert(other_region_configs.end(), this_region_configs.begin(), this_region_configs.end());
|
||||
|
||||
NEXT_REGION:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rearrange_regions) {
|
||||
// the current subdivision of regions does not make sense anymore.
|
||||
// we need to remove all objects and re-add them
|
||||
ModelObjectPtrs model_objects;
|
||||
FOREACH_OBJECT(this, o) {
|
||||
model_objects.push_back((*o)->model_object());
|
||||
}
|
||||
this->clear_objects();
|
||||
for (ModelObjectPtrs::iterator it = model_objects.begin(); it != model_objects.end(); ++it) {
|
||||
this->add_model_object(*it);
|
||||
}
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
void
|
||||
Print::init_extruders()
|
||||
{
|
||||
|
@ -324,6 +507,28 @@ Print::init_extruders()
|
|||
this->state.set_done(psInitExtruders);
|
||||
}
|
||||
|
||||
PrintRegionConfig
|
||||
Print::_region_config_from_model_volume(const ModelVolume &volume)
|
||||
{
|
||||
PrintRegionConfig config = this->default_region_config;
|
||||
{
|
||||
DynamicPrintConfig other_config = volume.get_object()->config;
|
||||
other_config.normalize();
|
||||
config.apply(other_config, true);
|
||||
}
|
||||
{
|
||||
DynamicPrintConfig other_config = volume.config;
|
||||
other_config.normalize();
|
||||
config.apply(other_config, true);
|
||||
}
|
||||
if (!volume.material_id().empty()) {
|
||||
DynamicPrintConfig material_config = volume.material()->config;
|
||||
material_config.normalize();
|
||||
config.apply(material_config, true);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
bool
|
||||
Print::has_support_material() const
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "PrintConfig.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "Layer.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "PlaceholderParser.hpp"
|
||||
|
||||
|
||||
|
@ -70,7 +71,6 @@ class PrintObject
|
|||
public:
|
||||
// vector of (vectors of volume ids), indexed by region_id
|
||||
std::vector<std::vector<int> > region_volumes;
|
||||
Points copies; // Slic3r::Point objects in scaled G-code coordinates
|
||||
PrintObjectConfig config;
|
||||
t_layer_height_ranges layer_height_ranges;
|
||||
|
||||
|
@ -95,7 +95,10 @@ class PrintObject
|
|||
|
||||
Print* print();
|
||||
ModelObject* model_object();
|
||||
|
||||
|
||||
Points copies() const;
|
||||
void set_copies(const Points &points);
|
||||
|
||||
// adds region_id, too, if necessary
|
||||
void add_region_volume(int region_id, int volume_id);
|
||||
|
||||
|
@ -119,6 +122,7 @@ class PrintObject
|
|||
private:
|
||||
Print* _print;
|
||||
ModelObject* _model_object;
|
||||
Points _copies; // Slic3r::Point objects in scaled G-code coordinates
|
||||
|
||||
// TODO: call model_object->get_bounding_box() instead of accepting
|
||||
// parameter
|
||||
|
@ -164,6 +168,8 @@ class Print
|
|||
bool invalidate_step(PrintStep step);
|
||||
bool invalidate_all_steps();
|
||||
|
||||
void add_model_object(ModelObject* model_object, int idx = -1);
|
||||
bool apply_config(DynamicPrintConfig config);
|
||||
void init_extruders();
|
||||
|
||||
std::set<size_t> extruders() const;
|
||||
|
@ -174,6 +180,7 @@ class Print
|
|||
private:
|
||||
void clear_regions();
|
||||
void delete_region(size_t idx);
|
||||
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
|
||||
};
|
||||
|
||||
#define FOREACH_BASE(type, container, iterator) for (type::const_iterator iterator = (container).begin(); iterator != (container).end(); ++iterator)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "Print.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "Geometry.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -21,8 +22,6 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
|
|||
this->_copies_shift = Point(
|
||||
scale_(modobj_bbox.min.x), scale_(modobj_bbox.min.y));
|
||||
|
||||
// TODO: $self->_trigger_copies;
|
||||
|
||||
// Scale the object size and store it
|
||||
Pointf3 size = modobj_bbox.size();
|
||||
this->size = Point3(scale_(size.x), scale_(size.y), scale_(size.z));
|
||||
|
@ -45,6 +44,35 @@ PrintObject::model_object()
|
|||
return this->_model_object;
|
||||
}
|
||||
|
||||
Points
|
||||
PrintObject::copies() const
|
||||
{
|
||||
return this->_copies;
|
||||
}
|
||||
|
||||
void
|
||||
PrintObject::set_copies(const Points &points)
|
||||
{
|
||||
this->_copies = points;
|
||||
|
||||
// order copies with a nearest neighbor search and translate them by _copies_shift
|
||||
this->_shifted_copies.clear();
|
||||
this->_shifted_copies.reserve(points.size());
|
||||
|
||||
// order copies with a nearest-neighbor search
|
||||
std::vector<Points::size_type> ordered_copies;
|
||||
Slic3r::Geometry::chained_path(points, ordered_copies);
|
||||
|
||||
for (std::vector<Points::size_type>::const_iterator it = ordered_copies.begin(); it != ordered_copies.end(); ++it) {
|
||||
Point copy = points[*it];
|
||||
copy.translate(this->_copies_shift);
|
||||
this->_shifted_copies.push_back(copy);
|
||||
}
|
||||
|
||||
this->_print->invalidate_step(psSkirt);
|
||||
this->_print->invalidate_step(psBrim);
|
||||
}
|
||||
|
||||
void
|
||||
PrintObject::add_region_volume(int region_id, int volume_id)
|
||||
{
|
||||
|
|
|
@ -14,12 +14,15 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
double get_abs_value(t_config_option_key opt_key, double ratio_over);
|
||||
void apply(DynamicPrintConfig* other)
|
||||
%code{% THIS->apply(*other, true); %};
|
||||
std::vector<std::string> diff(DynamicPrintConfig* other)
|
||||
%code{% RETVAL = THIS->diff(*other); %};
|
||||
void apply_static(FullPrintConfig* other)
|
||||
%code{% THIS->apply(*other, true); %};
|
||||
std::vector<std::string> get_keys()
|
||||
|
@ -37,6 +40,7 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
|
@ -58,6 +62,7 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
|
@ -77,6 +82,7 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
|
@ -98,6 +104,7 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
|
@ -119,6 +126,7 @@
|
|||
SV* get_at(t_config_option_key opt_key, int i);
|
||||
bool set(t_config_option_key opt_key, SV* value);
|
||||
bool set_deserialize(t_config_option_key opt_key, SV* str);
|
||||
void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false);
|
||||
std::string serialize(t_config_option_key opt_key);
|
||||
double get_abs_value(t_config_option_key opt_key);
|
||||
%name{get_abs_value_over}
|
||||
|
|
|
@ -56,8 +56,7 @@ _constant()
|
|||
Ref<ModelObject> model_object();
|
||||
Ref<PrintObjectConfig> config()
|
||||
%code%{ RETVAL = &THIS->config; %};
|
||||
Points copies()
|
||||
%code%{ RETVAL = THIS->copies; %};
|
||||
Points copies();
|
||||
t_layer_height_ranges layer_height_ranges()
|
||||
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
||||
Ref<Point3> size()
|
||||
|
@ -75,8 +74,7 @@ _constant()
|
|||
void set_shifted_copies(Points value)
|
||||
%code%{ THIS->_shifted_copies = value; %};
|
||||
|
||||
void set_copies(Points copies)
|
||||
%code%{ THIS->copies = copies; %};
|
||||
void set_copies(Points copies);
|
||||
void set_layer_height_ranges(t_layer_height_ranges layer_height_ranges)
|
||||
%code%{ THIS->layer_height_ranges = layer_height_ranges; %};
|
||||
|
||||
|
@ -169,6 +167,9 @@ _constant()
|
|||
double max_allowed_layer_height() const;
|
||||
bool has_support_material() const;
|
||||
|
||||
void add_model_object(ModelObject* model_object, int idx = -1);
|
||||
bool apply_config(DynamicPrintConfig* config)
|
||||
%code%{ RETVAL = THIS->apply_config(*config); %};
|
||||
void init_extruders();
|
||||
%{
|
||||
|
||||
|
|
Loading…
Reference in a new issue