2017-09-12 07:01:48 +00:00
|
|
|
// Calculate extents of the extrusions assigned to Print / PrintObject.
|
|
|
|
// The extents are used for assessing collisions of the print with the priming towers,
|
|
|
|
// to decide whether to pause the print after the priming towers are extruded
|
|
|
|
// to let the operator remove them from the print bed.
|
|
|
|
|
|
|
|
#include "../BoundingBox.hpp"
|
|
|
|
#include "../ExtrusionEntity.hpp"
|
|
|
|
#include "../ExtrusionEntityCollection.hpp"
|
2020-05-26 09:09:38 +00:00
|
|
|
#include "../Layer.hpp"
|
2017-09-12 07:01:48 +00:00
|
|
|
#include "../Print.hpp"
|
|
|
|
|
|
|
|
#include "PrintExtents.hpp"
|
|
|
|
#include "WipeTower.hpp"
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
|
|
|
static inline BoundingBox extrusion_polyline_extents(const Polyline &polyline, const coord_t radius)
|
|
|
|
{
|
|
|
|
BoundingBox bbox;
|
|
|
|
if (! polyline.points.empty())
|
|
|
|
bbox.merge(polyline.points.front());
|
|
|
|
for (const Point &pt : polyline.points) {
|
2018-08-17 13:53:43 +00:00
|
|
|
bbox.min(0) = std::min(bbox.min(0), pt(0) - radius);
|
|
|
|
bbox.min(1) = std::min(bbox.min(1), pt(1) - radius);
|
|
|
|
bbox.max(0) = std::max(bbox.max(0), pt(0) + radius);
|
|
|
|
bbox.max(1) = std::max(bbox.max(1), pt(1) + radius);
|
2017-09-12 07:01:48 +00:00
|
|
|
}
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BoundingBoxf extrusionentity_extents(const ExtrusionPath &extrusion_path)
|
|
|
|
{
|
2020-01-14 10:54:09 +00:00
|
|
|
BoundingBox bbox = extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width)));
|
2017-09-12 07:01:48 +00:00
|
|
|
BoundingBoxf bboxf;
|
|
|
|
if (! empty(bbox)) {
|
2018-08-21 15:43:05 +00:00
|
|
|
bboxf.min = unscale(bbox.min);
|
|
|
|
bboxf.max = unscale(bbox.max);
|
2017-09-13 13:52:51 +00:00
|
|
|
bboxf.defined = true;
|
2017-09-12 07:01:48 +00:00
|
|
|
}
|
|
|
|
return bboxf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BoundingBoxf extrusionentity_extents(const ExtrusionLoop &extrusion_loop)
|
|
|
|
{
|
|
|
|
BoundingBox bbox;
|
|
|
|
for (const ExtrusionPath &extrusion_path : extrusion_loop.paths)
|
2020-01-14 10:54:09 +00:00
|
|
|
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
|
2017-09-12 07:01:48 +00:00
|
|
|
BoundingBoxf bboxf;
|
|
|
|
if (! empty(bbox)) {
|
2018-08-21 15:43:05 +00:00
|
|
|
bboxf.min = unscale(bbox.min);
|
|
|
|
bboxf.max = unscale(bbox.max);
|
2017-09-13 13:52:51 +00:00
|
|
|
bboxf.defined = true;
|
|
|
|
}
|
2017-09-12 07:01:48 +00:00
|
|
|
return bboxf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BoundingBoxf extrusionentity_extents(const ExtrusionMultiPath &extrusion_multi_path)
|
|
|
|
{
|
|
|
|
BoundingBox bbox;
|
|
|
|
for (const ExtrusionPath &extrusion_path : extrusion_multi_path.paths)
|
2020-01-14 10:54:09 +00:00
|
|
|
bbox.merge(extrusion_polyline_extents(extrusion_path.polyline, coord_t(scale_(0.5 * extrusion_path.width))));
|
2017-09-12 07:01:48 +00:00
|
|
|
BoundingBoxf bboxf;
|
|
|
|
if (! empty(bbox)) {
|
2018-08-21 15:43:05 +00:00
|
|
|
bboxf.min = unscale(bbox.min);
|
|
|
|
bboxf.max = unscale(bbox.max);
|
2017-09-13 13:52:51 +00:00
|
|
|
bboxf.defined = true;
|
|
|
|
}
|
2017-09-12 07:01:48 +00:00
|
|
|
return bboxf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_entity);
|
|
|
|
|
|
|
|
static inline BoundingBoxf extrusionentity_extents(const ExtrusionEntityCollection &extrusion_entity_collection)
|
|
|
|
{
|
|
|
|
BoundingBoxf bbox;
|
|
|
|
for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities)
|
|
|
|
bbox.merge(extrusionentity_extents(extrusion_entity));
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_entity)
|
|
|
|
{
|
|
|
|
if (extrusion_entity == nullptr)
|
|
|
|
return BoundingBoxf();
|
|
|
|
auto *extrusion_path = dynamic_cast<const ExtrusionPath*>(extrusion_entity);
|
|
|
|
if (extrusion_path != nullptr)
|
|
|
|
return extrusionentity_extents(*extrusion_path);
|
|
|
|
auto *extrusion_loop = dynamic_cast<const ExtrusionLoop*>(extrusion_entity);
|
|
|
|
if (extrusion_loop != nullptr)
|
|
|
|
return extrusionentity_extents(*extrusion_loop);
|
|
|
|
auto *extrusion_multi_path = dynamic_cast<const ExtrusionMultiPath*>(extrusion_entity);
|
|
|
|
if (extrusion_multi_path != nullptr)
|
|
|
|
return extrusionentity_extents(*extrusion_multi_path);
|
|
|
|
auto *extrusion_entity_collection = dynamic_cast<const ExtrusionEntityCollection*>(extrusion_entity);
|
|
|
|
if (extrusion_entity_collection != nullptr)
|
|
|
|
return extrusionentity_extents(*extrusion_entity_collection);
|
2018-09-18 08:09:58 +00:00
|
|
|
throw std::runtime_error("Unexpected extrusion_entity type in extrusionentity_extents()");
|
2017-09-12 07:01:48 +00:00
|
|
|
return BoundingBoxf();
|
|
|
|
}
|
|
|
|
|
|
|
|
BoundingBoxf get_print_extrusions_extents(const Print &print)
|
|
|
|
{
|
2018-09-11 12:04:47 +00:00
|
|
|
BoundingBoxf bbox(extrusionentity_extents(print.brim()));
|
|
|
|
bbox.merge(extrusionentity_extents(print.skirt()));
|
2017-09-12 07:01:48 +00:00
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
2017-09-12 13:55:38 +00:00
|
|
|
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z)
|
2017-09-12 07:01:48 +00:00
|
|
|
{
|
|
|
|
BoundingBoxf bbox;
|
2018-09-11 12:04:47 +00:00
|
|
|
for (const Layer *layer : print_object.layers()) {
|
2017-09-12 07:01:48 +00:00
|
|
|
if (layer->print_z > max_print_z)
|
|
|
|
break;
|
|
|
|
BoundingBoxf bbox_this;
|
2018-09-11 12:04:47 +00:00
|
|
|
for (const LayerRegion *layerm : layer->regions()) {
|
2017-09-12 07:01:48 +00:00
|
|
|
bbox_this.merge(extrusionentity_extents(layerm->perimeters));
|
|
|
|
for (const ExtrusionEntity *ee : layerm->fills.entities)
|
|
|
|
// fill represents infill extrusions of a single island.
|
|
|
|
bbox_this.merge(extrusionentity_extents(*dynamic_cast<const ExtrusionEntityCollection*>(ee)));
|
|
|
|
}
|
|
|
|
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
|
|
|
if (support_layer)
|
|
|
|
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
|
|
|
bbox_this.merge(extrusionentity_extents(extrusion_entity));
|
2020-01-23 08:53:06 +00:00
|
|
|
for (const PrintInstance &instance : print_object.instances()) {
|
2017-09-12 07:01:48 +00:00
|
|
|
BoundingBoxf bbox_translated(bbox_this);
|
2020-01-23 08:53:06 +00:00
|
|
|
bbox_translated.translate(unscale(instance.shift));
|
2017-09-12 07:01:48 +00:00
|
|
|
bbox.merge(bbox_translated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z.
|
|
|
|
// The projection does not contain the priming regions.
|
2017-09-12 13:55:38 +00:00
|
|
|
BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z)
|
2017-09-12 07:01:48 +00:00
|
|
|
{
|
2018-07-27 13:56:27 +00:00
|
|
|
// Wipe tower extrusions are saved as if the tower was at the origin with no rotation
|
|
|
|
// We need to get position and angle of the wipe tower to transform them to actual position.
|
2018-08-21 18:34:45 +00:00
|
|
|
Transform2d trafo =
|
2018-09-12 09:59:02 +00:00
|
|
|
Eigen::Translation2d(print.config().wipe_tower_x.value, print.config().wipe_tower_y.value) *
|
2019-05-07 03:33:09 +00:00
|
|
|
Eigen::Rotation2Dd(Geometry::deg2rad(print.config().wipe_tower_rotation_angle.value));
|
2018-07-27 13:56:27 +00:00
|
|
|
|
2017-09-12 07:01:48 +00:00
|
|
|
BoundingBoxf bbox;
|
2018-09-11 12:04:47 +00:00
|
|
|
for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.wipe_tower_data().tool_changes) {
|
2017-09-12 07:01:48 +00:00
|
|
|
if (! tool_changes.empty() && tool_changes.front().print_z > max_print_z)
|
|
|
|
break;
|
|
|
|
for (const WipeTower::ToolChangeResult &tcr : tool_changes) {
|
|
|
|
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
|
|
|
|
const WipeTower::Extrusion &e = tcr.extrusions[i];
|
|
|
|
if (e.width > 0) {
|
2018-08-21 19:05:24 +00:00
|
|
|
Vec2d delta = 0.5 * Vec2d(e.width, e.width);
|
2019-06-17 08:16:07 +00:00
|
|
|
Vec2d p1 = trafo * (&e - 1)->pos.cast<double>();
|
|
|
|
Vec2d p2 = trafo * e.pos.cast<double>();
|
2018-08-21 18:34:45 +00:00
|
|
|
bbox.merge(p1.cwiseMin(p2) - delta);
|
|
|
|
bbox.merge(p1.cwiseMax(p2) + delta);
|
2017-09-12 07:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a bounding box of the wipe tower priming extrusions.
|
|
|
|
BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print)
|
|
|
|
{
|
|
|
|
BoundingBoxf bbox;
|
2018-09-11 12:04:47 +00:00
|
|
|
if (print.wipe_tower_data().priming != nullptr) {
|
2019-06-14 10:28:24 +00:00
|
|
|
for (const WipeTower::ToolChangeResult &tcr : *print.wipe_tower_data().priming) {
|
|
|
|
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
|
|
|
|
const WipeTower::Extrusion &e = tcr.extrusions[i];
|
|
|
|
if (e.width > 0) {
|
2019-06-17 08:16:07 +00:00
|
|
|
const Vec2d& p1 = (&e - 1)->pos.cast<double>();
|
|
|
|
const Vec2d& p2 = e.pos.cast<double>();
|
2019-06-14 10:28:24 +00:00
|
|
|
bbox.merge(p1);
|
|
|
|
coordf_t radius = 0.5 * e.width;
|
|
|
|
bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius);
|
|
|
|
bbox.min(1) = std::min(bbox.min(1), std::min(p1(1), p2(1)) - radius);
|
|
|
|
bbox.max(0) = std::max(bbox.max(0), std::max(p1(0), p2(0)) + radius);
|
|
|
|
bbox.max(1) = std::max(bbox.max(1), std::max(p1(1), p2(1)) + radius);
|
|
|
|
}
|
2017-09-12 07:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|