mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 07:45:58 +08:00
update to arrange: a little bit more sane (but need more work)
also calibration can now use arrange if needed
This commit is contained in:
parent
0b94eee824
commit
29d393ec9c
@ -232,8 +232,6 @@ int CLI::run(int argc, char **argv)
|
||||
// Loop through transform options.
|
||||
bool user_center_specified = false;
|
||||
Points bed = get_bed_shape(m_print_config);
|
||||
ArrangeParams arrange_cfg;
|
||||
arrange_cfg.min_obj_distance = scaled(PrintConfig::min_object_distance(&m_print_config));
|
||||
int dups = 1;
|
||||
|
||||
for (auto const &opt_key : m_transforms) {
|
||||
@ -467,13 +465,13 @@ int CLI::run(int argc, char **argv)
|
||||
|
||||
PrintBase *print = (printer_technology == ptFFF) ? static_cast<PrintBase*>(&fff_print) : static_cast<PrintBase*>(&sla_print);
|
||||
|
||||
|
||||
if (! m_config.opt_bool("dont_arrange")) {
|
||||
print->apply(model, m_print_config); // arrange_objects needs that the print has the config
|
||||
ArrangeParams arrange_cfg;
|
||||
arrange_cfg.min_obj_distance = scaled(PrintConfig::min_object_distance(&m_print_config)) * 2;
|
||||
if (dups > 1) {
|
||||
try {
|
||||
// if all input objects have defined position(s) apply duplication to the whole model
|
||||
duplicate(print, model, size_t(dups), bed, arrange_cfg);
|
||||
duplicate(model, size_t(dups), bed, arrange_cfg);
|
||||
} catch (std::exception & ex) {
|
||||
boost::nowide::cerr << "error: " << ex.what() << std::endl;
|
||||
return 1;
|
||||
@ -481,9 +479,9 @@ int CLI::run(int argc, char **argv)
|
||||
}
|
||||
if (user_center_specified) {
|
||||
Vec2d c = m_config.option<ConfigOptionPoint>("center")->value;
|
||||
arrange_objects(print, model, InfiniteBed{scaled(c)}, arrange_cfg);
|
||||
arrange_objects(model, InfiniteBed{scaled(c)}, arrange_cfg);
|
||||
} else
|
||||
arrange_objects(print, model, bed, arrange_cfg);
|
||||
arrange_objects(model, bed, arrange_cfg);
|
||||
}
|
||||
if (printer_technology == ptFFF) {
|
||||
for (auto* mo : model.objects)
|
||||
|
@ -1855,15 +1855,16 @@ void ModelInstance::transform_polygon(Polygon* polygon) const
|
||||
polygon->scale(get_scaling_factor(X), get_scaling_factor(Y)); // scale around polygon origin
|
||||
}
|
||||
|
||||
arrangement::ArrangePolygon ModelInstance::get_arrange_polygon(const PrintBase *print_base) const
|
||||
|
||||
arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
||||
{
|
||||
static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||
|
||||
|
||||
Vec3d rotation = get_rotation();
|
||||
rotation.z() = 0.;
|
||||
rotation.z() = 0.;
|
||||
Transform3d trafo_instance =
|
||||
Geometry::assemble_transform(Vec3d::Zero(), rotation,
|
||||
get_scaling_factor(), get_mirror());
|
||||
get_scaling_factor(), get_mirror());
|
||||
|
||||
Polygon p = get_object()->convex_hull_2d(trafo_instance);
|
||||
|
||||
@ -1872,59 +1873,19 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon(const PrintBase *
|
||||
// this may happen for malformed models, see:
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||
if (!p.points.empty()) {
|
||||
Polygons pp{p};
|
||||
if (const Print* print = dynamic_cast<const Print*>(print_base))
|
||||
{
|
||||
//grow
|
||||
double dist = print->config().min_object_distance(&print->full_print_config());
|
||||
pp = offset(pp, scale_(dist));
|
||||
//simplify
|
||||
if (!pp.empty())
|
||||
pp = pp.front().simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||
}else
|
||||
pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||
Polygons pp{ p };
|
||||
pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||
if (!pp.empty()) p = pp.front();
|
||||
}
|
||||
|
||||
|
||||
arrangement::ArrangePolygon ret;
|
||||
ret.poly.contour = std::move(p);
|
||||
ret.translation = Vec2crd{scaled(get_offset(X)), scaled(get_offset(Y))};
|
||||
ret.rotation = get_rotation(Z);
|
||||
ret.translation = Vec2crd{ scaled(get_offset(X)), scaled(get_offset(Y)) };
|
||||
ret.rotation = get_rotation(Z);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
//arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
||||
//{
|
||||
// static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||
//
|
||||
// Vec3d rotation = get_rotation();
|
||||
// rotation.z() = 0.;
|
||||
// Transform3d trafo_instance =
|
||||
// Geometry::assemble_transform(Vec3d::Zero(), rotation,
|
||||
// get_scaling_factor(), get_mirror());
|
||||
//
|
||||
// Polygon p = get_object()->convex_hull_2d(trafo_instance);
|
||||
//
|
||||
// assert(!p.points.empty());
|
||||
//
|
||||
// // this may happen for malformed models, see:
|
||||
// // https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||
// if (!p.points.empty()) {
|
||||
// Polygons pp{ p };
|
||||
// pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||
// if (!pp.empty()) p = pp.front();
|
||||
// }
|
||||
//
|
||||
// arrangement::ArrangePolygon ret;
|
||||
// ret.poly.contour = std::move(p);
|
||||
// ret.translation = Vec2crd{ scaled(get_offset(X)), scaled(get_offset(Y)) };
|
||||
// ret.rotation = get_rotation(Z);
|
||||
//
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const
|
||||
{
|
||||
TriangleSelector selector(mv.mesh());
|
||||
|
@ -874,7 +874,7 @@ public:
|
||||
bool is_printable() const { return object->printable && printable && (print_volume_state == ModelInstancePVS_Inside); }
|
||||
|
||||
// Getting the input polygon for arrange
|
||||
arrangement::ArrangePolygon get_arrange_polygon(const PrintBase* print) const;
|
||||
arrangement::ArrangePolygon get_arrange_polygon() const;
|
||||
|
||||
// Apply the arrange result on the ModelInstance
|
||||
void apply_arrange_result(const Vec2d& offs, double rotation)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
arrangement::ArrangePolygons get_arrange_polys(const PrintBase* print, const Model &model, ModelInstancePtrs &instances)
|
||||
arrangement::ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (auto obj : model.objects) count += obj->instances.size();
|
||||
@ -15,7 +15,7 @@ arrangement::ArrangePolygons get_arrange_polys(const PrintBase* print, const Mod
|
||||
instances.clear(); instances.reserve(count);
|
||||
for (ModelObject *mo : model.objects)
|
||||
for (ModelInstance *minst : mo->instances) {
|
||||
input.emplace_back(minst->get_arrange_polygon(print));
|
||||
input.emplace_back(minst->get_arrange_polygon());
|
||||
instances.emplace_back(minst);
|
||||
}
|
||||
|
||||
@ -36,13 +36,13 @@ bool apply_arrange_polys(ArrangePolygons &input, ModelInstancePtrs &instances, V
|
||||
return ret;
|
||||
}
|
||||
|
||||
Slic3r::arrangement::ArrangePolygon get_arrange_poly(const PrintBase* print, const Model &model)
|
||||
Slic3r::arrangement::ArrangePolygon get_arrange_poly(const Model &model)
|
||||
{
|
||||
ArrangePolygon ap;
|
||||
Points &apts = ap.poly.contour.points;
|
||||
for (const ModelObject *mo : model.objects)
|
||||
for (const ModelInstance *minst : mo->instances) {
|
||||
ArrangePolygon obj_ap = minst->get_arrange_polygon(print);
|
||||
ArrangePolygon obj_ap = minst->get_arrange_polygon();
|
||||
ap.poly.contour.rotate(obj_ap.rotation);
|
||||
ap.poly.contour.translate(obj_ap.translation.x(), obj_ap.translation.y());
|
||||
const Points &pts = obj_ap.poly.contour.points;
|
||||
|
@ -24,50 +24,47 @@ using VirtualBedFn = std::function<void(arrangement::ArrangePolygon&)>;
|
||||
throw Slic3r::RuntimeError("Objects could not fit on the bed");
|
||||
}
|
||||
|
||||
ArrangePolygons get_arrange_polys(const PrintBase* print, const Model &model, ModelInstancePtrs &instances);
|
||||
ArrangePolygon get_arrange_poly(const PrintBase* print, const Model &model);
|
||||
ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances);
|
||||
ArrangePolygon get_arrange_poly(const Model &model);
|
||||
bool apply_arrange_polys(ArrangePolygons &polys, ModelInstancePtrs &instances, VirtualBedFn);
|
||||
|
||||
void duplicate(Model &model, ArrangePolygons &copies, VirtualBedFn);
|
||||
void duplicate_objects(Model &model, size_t copies_num);
|
||||
|
||||
template<class TBed>
|
||||
bool arrange_objects(PrintBase* print,
|
||||
Model & model,
|
||||
bool arrange_objects(Model & model,
|
||||
const TBed & bed,
|
||||
const ArrangeParams ¶ms,
|
||||
VirtualBedFn vfn = throw_if_out_of_bed)
|
||||
{
|
||||
ModelInstancePtrs instances;
|
||||
ArrangePolygons input = get_arrange_polys(print, model, instances);
|
||||
ArrangePolygons input = get_arrange_polys(model, instances);
|
||||
arrangement::arrange(input, bed, params);
|
||||
|
||||
return apply_arrange_polys(input, instances, vfn);
|
||||
}
|
||||
|
||||
template<class TBed>
|
||||
void duplicate(PrintBase* print,
|
||||
Model & model,
|
||||
void duplicate(Model & model,
|
||||
size_t copies_num,
|
||||
const TBed & bed,
|
||||
const ArrangeParams ¶ms,
|
||||
VirtualBedFn vfn = throw_if_out_of_bed)
|
||||
{
|
||||
ArrangePolygons copies(copies_num, get_arrange_poly(print, model));
|
||||
ArrangePolygons copies(copies_num, get_arrange_poly(model));
|
||||
arrangement::arrange(copies, bed, params);
|
||||
duplicate(model, copies, vfn);
|
||||
}
|
||||
|
||||
template<class TBed>
|
||||
void duplicate_objects(PrintBase* print,
|
||||
Model & model,
|
||||
void duplicate_objects(Model & model,
|
||||
size_t copies_num,
|
||||
const TBed & bed,
|
||||
const ArrangeParams ¶ms,
|
||||
VirtualBedFn vfn = throw_if_out_of_bed)
|
||||
{
|
||||
duplicate_objects(model, copies_num);
|
||||
arrange_objects(print, model, bed, params, vfn);
|
||||
arrange_objects(model, bed, params, vfn);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1259,35 +1259,49 @@ bool Print::has_skirt() const
|
||||
static inline bool sequential_print_horizontal_clearance_valid(const Print &print)
|
||||
{
|
||||
Polygons convex_hulls_other;
|
||||
//std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
|
||||
std::map<ObjectID, Polygon> map_model_object_to_convex_hull;
|
||||
for (const PrintObject *print_object : print.objects()) {
|
||||
double dist_grow = PrintConfig::min_object_distance(&print_object->config());
|
||||
assert(! print_object->model_object()->instances.empty());
|
||||
assert(! print_object->instances().empty());
|
||||
//ObjectID model_object_id = print_object->model_object()->id();
|
||||
//auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id);
|
||||
ObjectID model_object_id = print_object->model_object()->id();
|
||||
auto it_convex_hull = map_model_object_to_convex_hull.find(model_object_id);
|
||||
// Get convex hull of all printable volumes assigned to this print object.
|
||||
// ModelInstance *model_instance0 = print_object->model_object()->instances.front();
|
||||
// if (it_convex_hull == map_model_object_to_convex_hull.end()) {
|
||||
// // Calculate the convex hull of a printable object.
|
||||
// // Grow convex hull with the clearance margin.
|
||||
// // FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
|
||||
// // which causes that the warning will be showed after arrangement with the
|
||||
// // appropriate object distance. Even if I set this to jtMiter the warning still shows up.
|
||||
// it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id,
|
||||
// offset(print_object->model_object()->convex_hull_2d(
|
||||
// Geometry::assemble_transform(Vec3d::Zero(), model_instance0->get_rotation(), model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
|
||||
// // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
// float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
|
||||
// jtRound, float(scale_(0.1))).front());
|
||||
// }
|
||||
// // Make a copy, so it may be rotated for instances.
|
||||
// //FIXME seems like the rotation isn't taken into account
|
||||
// Polygon convex_hull0 = it_convex_hull->second;
|
||||
// //this can create bugs in macos, for reasons.
|
||||
//double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
|
||||
//if (std::abs(z_diff) > EPSILON)
|
||||
// convex_hull0.rotate(z_diff);
|
||||
ModelInstance *model_instance0 = print_object->model_object()->instances.front();
|
||||
if (it_convex_hull == map_model_object_to_convex_hull.end()) {
|
||||
// Calculate the convex hull of a printable object.
|
||||
// Grow convex hull with the clearance margin.
|
||||
// FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
|
||||
// which causes that the warning will be showed after arrangement with the
|
||||
// appropriate object distance. Even if I set this to jtMiter the warning still shows up.
|
||||
it_convex_hull = map_model_object_to_convex_hull.emplace_hint(it_convex_hull, model_object_id,
|
||||
offset(print_object->model_object()->convex_hull_2d(
|
||||
Geometry::assemble_transform(Vec3d::Zero(), model_instance0->get_rotation(), model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
|
||||
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
float(scale_(0.5 * dist_grow - EPSILON)),
|
||||
jtRound, float(scale_(0.1))).front());
|
||||
}
|
||||
// Make a copy, so it may be rotated for instances.
|
||||
//FIXME seems like the rotation isn't taken into account
|
||||
Polygon convex_hull0 = it_convex_hull->second;
|
||||
//this can create bugs in macos, for reasons.
|
||||
double z_diff = Geometry::rotation_diff_z(model_instance0->get_rotation(), print_object->instances().front().model_instance->get_rotation());
|
||||
if (std::abs(z_diff) > EPSILON)
|
||||
convex_hull0.rotate(z_diff);
|
||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||
for (const PrintInstance& instance : print_object->instances()) {
|
||||
Polygon convex_hull = convex_hull0;
|
||||
// instance.shift is a position of a centered object, while model object may not be centered.
|
||||
// Conver the shift from the PrintObject's coordinates into ModelObject's coordinates by removing the centering offset.
|
||||
convex_hull.translate(instance.shift - print_object->center_offset());
|
||||
if (!intersection(convex_hulls_other, convex_hull).empty())
|
||||
return false;
|
||||
polygons_append(convex_hulls_other, convex_hull);
|
||||
}
|
||||
|
||||
/*
|
||||
'old' superslicer sequential_print_horizontal_clearance_valid, that is better at skirts, but need some works, as the arrange has changed.
|
||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||
for (const PrintInstance &instance : print_object->instances()) {
|
||||
Polygons convex_hull = print_object->model_object()->convex_hull_2d(
|
||||
@ -1295,8 +1309,8 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin
|
||||
instance.model_instance->get_rotation(), instance.model_instance->get_scaling_factor(), instance.model_instance->get_mirror()));
|
||||
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
|
||||
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
|
||||
/*float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
|
||||
jtRound, float(scale_(0.1)));*/
|
||||
//float(scale_(0.5 * print.config().extruder_clearance_radius.value - EPSILON)),
|
||||
//jtRound, float(scale_(0.1)));
|
||||
if (convex_hull.empty())
|
||||
continue;
|
||||
// instance.shift is a position of a centered object, while model object may not be centered.
|
||||
@ -1305,13 +1319,14 @@ static inline bool sequential_print_horizontal_clearance_valid(const Print &prin
|
||||
poly.translate(instance.shift - print_object->center_offset());
|
||||
if (! intersection(
|
||||
convex_hulls_other,
|
||||
offset(convex_hull[0], double(scale_(print.config().min_object_distance(&instance.print_object->config(),0.)) - SCALED_EPSILON), jtRound, scale_(0.1))).empty())
|
||||
offset(convex_hull[0], double(scale_(PrintConfig::min_object_distance(&instance.print_object->config(),0.)) - SCALED_EPSILON), jtRound, scale_(0.1))).empty())
|
||||
return false;
|
||||
double extra_grow = print.config().min_object_distance(&instance.print_object->config(), 1.);
|
||||
double extra_grow = PrintConfig::min_object_distance(&instance.print_object->config(), 1.);
|
||||
if (extra_grow > 0)
|
||||
convex_hull = offset(convex_hull, scale_(extra_grow));
|
||||
polygons_append(convex_hulls_other, convex_hull);
|
||||
}
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -5205,8 +5205,9 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
|
||||
//test if called from usaslicer::l240 where it's called on an empty config...
|
||||
if (dd_opt == nullptr) return 0;
|
||||
|
||||
double duplicate_distance = dd_opt->value;
|
||||
double base_dist = duplicate_distance / 2;
|
||||
// /2 becasue we only count the grawing for the current object
|
||||
const double duplicate_distance = dd_opt->value / 2;
|
||||
double base_dist = duplicate_distance;
|
||||
//std::cout << "START min_object_distance =>" << base_dist << "\n";
|
||||
const ConfigOptionBool* co_opt = config->option<ConfigOptionBool>("complete_objects");
|
||||
if (co_opt && co_opt->value) {
|
||||
@ -5218,24 +5219,35 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
|
||||
for (double val : vals) max_nozzle_diam = std::fmax(max_nozzle_diam, val);
|
||||
|
||||
// min object distance is max(duplicate_distance, clearance_radius)
|
||||
// /2 becasue we only count the grawing for the current object
|
||||
//add 1 as safety offset.
|
||||
double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat();
|
||||
double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat() / 2 + 1;
|
||||
if (extruder_clearance_radius > base_dist) {
|
||||
base_dist = extruder_clearance_radius / 2;
|
||||
base_dist = extruder_clearance_radius;
|
||||
}
|
||||
|
||||
//std::cout << " min_object_distance add extruder_clearance_radius ("<< extruder_clearance_radius <<") =>" << base_dist << "\n";
|
||||
//FIXME: now brim can be per-object, so you ahve to get a different min_object_distance per object
|
||||
//add brim width
|
||||
const double first_layer_height = config->get_abs_value("first_layer_height");
|
||||
if (ref_height <= first_layer_height) {
|
||||
if (ref_height <= first_layer_height && ref_height != 0) {
|
||||
//FIXME: does not take into account object-defined brim !!! you can crash yoursefl with it
|
||||
if (config->option("brim_width")->getFloat() > 0) {
|
||||
brim_dist += config->option("brim_width")->getFloat();
|
||||
//std::cout << " Set brim=" << config->option("brim_width")->getFloat() << " => " << brim_dist << "\n";
|
||||
}
|
||||
} else if (config->option("brim_width")->getFloat() + 1 > base_dist) {
|
||||
base_dist = config->option("brim_width")->getFloat();
|
||||
}
|
||||
//add the skirt
|
||||
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) {
|
||||
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() == 1 && ref_height == 0) {
|
||||
skirt_dist = config->option("skirt_distance")->getFloat();
|
||||
const double first_layer_width = config->get_abs_value("first_layer_extrusion_width");
|
||||
Flow flow(first_layer_width, first_layer_height, max_nozzle_diam);
|
||||
skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
|
||||
base_dist = std::max(base_dist, skirt_dist + 1);
|
||||
skirt_dist = 0;
|
||||
}else if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) {
|
||||
double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height;
|
||||
if (ref_height <= skirt_height) {
|
||||
skirt_dist = config->option("skirt_distance")->getFloat();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Jobs/ProgressIndicator.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
@ -48,6 +49,18 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
class ProgressIndicatorStub : ProgressIndicator {
|
||||
public:
|
||||
|
||||
virtual ~ProgressIndicatorStub() override = default;
|
||||
|
||||
virtual void set_range(int range) override {}
|
||||
virtual void set_cancel_callback(CancelFn = CancelFn()) override {}
|
||||
virtual void set_progress(int pr) override {}
|
||||
virtual void set_status_text(const char*) override {}
|
||||
virtual int get_range() const override { return 0; }
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "Jobs/ArrangeJob.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "Plater.hpp"
|
||||
@ -98,6 +99,7 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
|
||||
}
|
||||
|
||||
/// --- translate ---;
|
||||
bool has_to_arrange = false;
|
||||
const float brim_width = std::max(print_config->option<ConfigOptionFloat>("brim_width")->value, nozzle_diameter * 5.);
|
||||
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
|
||||
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
|
||||
@ -108,7 +110,9 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
|
||||
for (int i = 1; i < nb_items; i++) {
|
||||
model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2 + (i % 2 == 0 ? -1 : 1) * offsety * ((i + 1) / 2), 0 });
|
||||
}
|
||||
//TODO: if not enough space, forget about complete_objects
|
||||
// if not enough space, forget about complete_objects
|
||||
if (bed_size.y() < offsety * (nb_items + 1))
|
||||
has_to_arrange = true;
|
||||
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
@ -141,6 +145,17 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
|
||||
ObjectList* obj = this->gui_app->obj_list();
|
||||
obj->update_after_undo_redo();
|
||||
|
||||
// arrange if needed, after new settings, to take them into account
|
||||
if (has_to_arrange) {
|
||||
//update print config (done at reslice but we need it here)
|
||||
if (plat->printer_technology() == ptFFF)
|
||||
plat->fff_print().apply(plat->model(), *plat->config());
|
||||
std::shared_ptr<ProgressIndicatorStub> fake_statusbar = std::make_shared<ProgressIndicatorStub>();
|
||||
ArrangeJob arranger(std::dynamic_pointer_cast<ProgressIndicator>(fake_statusbar), plat);
|
||||
arranger.prepare_all();
|
||||
arranger.process();
|
||||
arranger.finalize();
|
||||
}
|
||||
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "Jobs/ArrangeJob.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "Plater.hpp"
|
||||
@ -101,6 +102,7 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) {
|
||||
}
|
||||
|
||||
/// --- translate ---;
|
||||
bool has_to_arrange = false;
|
||||
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
|
||||
const ConfigOptionPoints* bed_shape = printerConfig->option<ConfigOptionPoints>("bed_shape");
|
||||
const double brim_width = nozzle_diameter * 3.5;
|
||||
@ -113,8 +115,10 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) {
|
||||
model.objects[objs_idx[2]]->translate({ bed_min.x() + bed_size.x() / 2 - offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 });
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 - offsety, 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 });
|
||||
//TODO: if not enough space, forget about complete_objects
|
||||
|
||||
// if not enough space, forget about complete_objects
|
||||
if (bed_size.y() < offsety * 2 + 25 * xyScale + brim_width || bed_size.x() < offsetx + 25 * xyScale + brim_width)
|
||||
has_to_arrange = true;
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *print_config; //make a copy
|
||||
@ -157,6 +161,17 @@ void CalibrationFlowDialog::create_geometry(float start, float delta) {
|
||||
ObjectList* obj = this->gui_app->obj_list();
|
||||
obj->update_after_undo_redo();
|
||||
|
||||
// arrange if needed, after new settings, to take them into account
|
||||
if (has_to_arrange) {
|
||||
//update print config (done at reslice but we need it here)
|
||||
if (plat->printer_technology() == ptFFF)
|
||||
plat->fff_print().apply(plat->model(), *plat->config());
|
||||
std::shared_ptr<ProgressIndicatorStub> fake_statusbar = std::make_shared<ProgressIndicatorStub>();
|
||||
ArrangeJob arranger(std::dynamic_pointer_cast<ProgressIndicator>(fake_statusbar), plat);
|
||||
arranger.prepare_all();
|
||||
arranger.process();
|
||||
arranger.finalize();
|
||||
}
|
||||
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "Jobs/ArrangeJob.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "Plater.hpp"
|
||||
@ -85,6 +86,7 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) {
|
||||
}
|
||||
|
||||
/// --- translate ---;
|
||||
bool has_to_arrange = false;
|
||||
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
|
||||
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
|
||||
const float brim_width = print_config->option<ConfigOptionFloat>("brim_width")->getFloat();
|
||||
@ -98,8 +100,10 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) {
|
||||
model.objects[objs_idx[3]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 - offsety, 0 });
|
||||
model.objects[objs_idx[4]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 , 0 });
|
||||
model.objects[objs_idx[5]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 });
|
||||
//TODO: if not enough space, forget about complete_objects
|
||||
|
||||
// if not enough space, forget about complete_objects
|
||||
if (bed_size.y() < offsety * 2 + 30 * xyz_scale + brim_width || bed_size.x() < offsetx + 35 * xyz_scale + brim_width)
|
||||
has_to_arrange = true;
|
||||
|
||||
/// --- main config, please modify object config when possible ---
|
||||
DynamicPrintConfig new_print_config = *print_config; //make a copy
|
||||
@ -136,6 +140,17 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) {
|
||||
ObjectList* obj = this->gui_app->obj_list();
|
||||
obj->update_after_undo_redo();
|
||||
|
||||
// arrange if needed, after new settings, to take them into account
|
||||
if (has_to_arrange) {
|
||||
//update print config (done at reslice but we need it here)
|
||||
if (plat->printer_technology() == ptFFF)
|
||||
plat->fff_print().apply(plat->model(), *plat->config());
|
||||
std::shared_ptr<ProgressIndicatorStub> fake_statusbar = std::make_shared<ProgressIndicatorStub>();
|
||||
ArrangeJob arranger(std::dynamic_pointer_cast<ProgressIndicator>(fake_statusbar), plat);
|
||||
arranger.prepare_all();
|
||||
arranger.process();
|
||||
arranger.finalize();
|
||||
}
|
||||
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "Jobs/ArrangeJob.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "Plater.hpp"
|
||||
@ -190,22 +191,20 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
}
|
||||
|
||||
/// --- translate ---;
|
||||
bool has_to_arrange = false;
|
||||
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
|
||||
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
|
||||
const float brim_width = std::max(print_config->option<ConfigOptionFloat>("brim_width")->value, nozzle_diameter * 5.);
|
||||
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
|
||||
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
|
||||
float offset = 4 + 26 * 1 + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0);
|
||||
float offset = 4 + 26 * scale * 1 + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0);
|
||||
if (nb_items == 1) {
|
||||
model.objects[objs_idx[0]]->translate({ bed_min.x() + bed_size.x() / 2, bed_min.y() + bed_size.y() / 2, 0 });
|
||||
} else {
|
||||
for (size_t i = 0; i < nb_items; i++) {
|
||||
model.objects[objs_idx[i]]->translate({ bed_min.x() + bed_size.x() / 2 + (i%2 ==0 ? -offset/2: offset/2), bed_min.y() + bed_size.y() / 2 + ( (i/2) % 2 == 0 ? -1 : 1) * offset * (((i / 2) + 1) / 2), 0 });
|
||||
}
|
||||
has_to_arrange = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// --- custom config ---
|
||||
for (size_t i = 0; i < nb_items; i++) {
|
||||
//speed
|
||||
@ -252,16 +251,29 @@ void CalibrationRetractionDialog::create_geometry(wxCommandEvent& event_args) {
|
||||
new_print_config.set_key_value("complete_objects_one_skirt", new ConfigOptionBool(true));
|
||||
}
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->load_config(new_print_config);
|
||||
plat->on_config_change(new_print_config);
|
||||
this->gui_app->get_tab(Preset::TYPE_PRINT)->update_dirty();
|
||||
plat->on_config_change(new_print_config);
|
||||
}
|
||||
|
||||
//update plater
|
||||
plat->changed_objects(objs_idx);
|
||||
//if (plat->printer_technology() == ptFFF)
|
||||
//plat->fff_print().full_print_config().apply(plat->config());
|
||||
//update everything, easier to code.
|
||||
ObjectList* obj = this->gui_app->obj_list();
|
||||
obj->update_after_undo_redo();
|
||||
|
||||
// arrange if needed, after new settings, to take them into account
|
||||
if (has_to_arrange) {
|
||||
//update print config (done at reslice but we need it here)
|
||||
if (plat->printer_technology() == ptFFF)
|
||||
plat->fff_print().apply(plat->model(), *plat->config());
|
||||
std::shared_ptr<ProgressIndicatorStub> fake_statusbar = std::make_shared<ProgressIndicatorStub>();
|
||||
ArrangeJob arranger(std::dynamic_pointer_cast<ProgressIndicator>(fake_statusbar), plat);
|
||||
arranger.prepare_all();
|
||||
arranger.process();
|
||||
arranger.finalize();
|
||||
}
|
||||
|
||||
plat->reslice();
|
||||
plat->select_view_3D("Preview");
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
apply_wipe_tower();
|
||||
}
|
||||
|
||||
ArrangePolygon get_arrange_polygon(const PrintBase* print_base) const
|
||||
ArrangePolygon get_arrange_polygon() const
|
||||
{
|
||||
Polygon ap({
|
||||
{coord_t(0), coord_t(0)},
|
||||
@ -80,11 +80,11 @@ void ArrangeJob::prepare_all() {
|
||||
for (ModelObject *obj: m_plater->model().objects)
|
||||
for (ModelInstance *mi : obj->instances) {
|
||||
ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable;
|
||||
cont.emplace_back(get_arrange_poly(m_plater->current_print(), mi));
|
||||
cont.emplace_back(get_arrange_poly(mi));
|
||||
}
|
||||
|
||||
if (auto wti = get_wipe_tower(*m_plater))
|
||||
m_selected.emplace_back(wti.get_arrange_polygon(m_plater->current_print()));
|
||||
m_selected.emplace_back(wti.get_arrange_polygon());
|
||||
}
|
||||
|
||||
void ArrangeJob::prepare_selected() {
|
||||
@ -112,7 +112,7 @@ void ArrangeJob::prepare_selected() {
|
||||
inst_sel[size_t(inst_id)] = true;
|
||||
|
||||
for (size_t i = 0; i < inst_sel.size(); ++i) {
|
||||
ArrangePolygon &&ap = get_arrange_poly(m_plater->current_print(), mo->instances[i]);
|
||||
ArrangePolygon &&ap = get_arrange_poly(mo->instances[i]);
|
||||
|
||||
ArrangePolygons &cont = mo->instances[i]->printable ?
|
||||
(inst_sel[i] ? m_selected :
|
||||
@ -124,7 +124,7 @@ void ArrangeJob::prepare_selected() {
|
||||
}
|
||||
|
||||
if (auto wti = get_wipe_tower(*m_plater)) {
|
||||
ArrangePolygon &&ap = get_arrange_poly(m_plater->current_print(), &wti);
|
||||
ArrangePolygon &&ap = get_arrange_poly(&wti);
|
||||
|
||||
m_plater->get_selection().is_wipe_tower() ?
|
||||
m_selected.emplace_back(std::move(ap)) :
|
||||
@ -149,10 +149,10 @@ void ArrangeJob::process()
|
||||
{
|
||||
static const auto arrangestr = _(L("Arranging"));
|
||||
|
||||
double dist = PrintConfig::min_object_distance(m_plater->config());
|
||||
double dist = PrintConfig::min_object_distance(&m_plater->current_print()->full_print_config());
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
params.min_obj_distance = scaled(dist);
|
||||
params.min_obj_distance = scaled(dist) * 2;
|
||||
|
||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||
Points bedpts = get_bed_shape(*m_plater->config());
|
||||
@ -214,7 +214,7 @@ void ArrangeJob::finalize() {
|
||||
|
||||
arrangement::ArrangePolygon get_wipe_tower_arrangepoly(Plater &plater)
|
||||
{
|
||||
return WipeTower{plater.canvas3D()->get_wipe_tower_info()}.get_arrange_polygon(plater.current_print());
|
||||
return WipeTower{plater.canvas3D()->get_wipe_tower_info()}.get_arrange_polygon();
|
||||
}
|
||||
|
||||
void apply_wipe_tower_arrangepoly(Plater &plater, const arrangement::ArrangePolygon &ap)
|
||||
|
@ -29,9 +29,9 @@ class ArrangeJob : public Job
|
||||
double bed_stride() const;
|
||||
|
||||
// Set up arrange polygon for a ModelInstance and Wipe tower
|
||||
template<class T> ArrangePolygon get_arrange_poly(const PrintBase* print_base, T *obj) const
|
||||
template<class T> ArrangePolygon get_arrange_poly(T *obj) const
|
||||
{
|
||||
ArrangePolygon ap = obj->get_arrange_polygon(print_base);
|
||||
ArrangePolygon ap = obj->get_arrange_polygon();
|
||||
ap.priority = 0;
|
||||
ap.bed_idx = ap.translation.x() / bed_stride();
|
||||
ap.setter = [obj, this](const ArrangePolygon &p) {
|
||||
@ -44,8 +44,6 @@ class ArrangeJob : public Job
|
||||
return ap;
|
||||
}
|
||||
|
||||
// Prepare all objects on the bed regardless of the selection
|
||||
void prepare_all();
|
||||
|
||||
// Prepare the selected and unselected items separately. If nothing is
|
||||
// selected, behaves as if everything would be selected.
|
||||
@ -56,6 +54,11 @@ protected:
|
||||
void prepare() override;
|
||||
|
||||
public:
|
||||
// Prepare all objects on the bed regardless of the selection
|
||||
//put on public to be accessed by calibrations
|
||||
void prepare_all();
|
||||
|
||||
|
||||
ArrangeJob(std::shared_ptr<ProgressIndicator> pri, Plater *plater)
|
||||
: Job{std::move(pri)}, m_plater{plater}
|
||||
{}
|
||||
|
@ -2775,7 +2775,7 @@ void Plater::find_new_position(const ModelInstancePtrs &instances,
|
||||
for (const ModelObject *mo : p->model.objects)
|
||||
for (const ModelInstance *inst : mo->instances) {
|
||||
auto it = std::find(instances.begin(), instances.end(), inst);
|
||||
arrangement::ArrangePolygon arrpoly = inst->get_arrange_polygon(this->current_print());
|
||||
arrangement::ArrangePolygon arrpoly = inst->get_arrange_polygon();
|
||||
|
||||
if (it == instances.end())
|
||||
fixed.emplace_back(std::move(arrpoly));
|
||||
|
Loading…
x
Reference in New Issue
Block a user