Arrange is accounting for the wipe tower now
This commit is contained in:
parent
5f226c5d7f
commit
e9a53e49db
@ -539,7 +539,7 @@ public:
|
||||
// 2D shape from top view.
|
||||
using ShapeData2D = std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
|
||||
|
||||
ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
ShapeData2D projectModelFromTop(const Slic3r::Model &model, const WipeTowerInfo& wti) {
|
||||
ShapeData2D ret;
|
||||
|
||||
// Count all the items on the bin (all the object's instances)
|
||||
@ -595,6 +595,28 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
}
|
||||
}
|
||||
|
||||
// The wipe tower is a separate case (in case there is one), let's duplicate the code
|
||||
if (wti.is_wipe_tower) {
|
||||
Points pts;
|
||||
pts.emplace_back(coord_t(scale_(0.)), coord_t(scale_(0.)));
|
||||
pts.emplace_back(coord_t(scale_(wti.bb_size(0))), coord_t(scale_(0.)));
|
||||
pts.emplace_back(coord_t(scale_(wti.bb_size(0))), coord_t(scale_(wti.bb_size(1))));
|
||||
pts.emplace_back(coord_t(scale_(-0.)), coord_t(scale_(wti.bb_size(1))));
|
||||
pts.emplace_back(coord_t(scale_(-0.)), coord_t(scale_(0.)));
|
||||
Polygon p(std::move(pts));
|
||||
ClipperLib::Path clpath = Slic3rMultiPoint_to_ClipperPath(p);
|
||||
ClipperLib::Polygon pn;
|
||||
pn.Contour = clpath;
|
||||
// Efficient conversion to item.
|
||||
Item item(std::move(pn));
|
||||
item.rotation(wti.rotation),
|
||||
item.translation({
|
||||
ClipperLib::cInt(wti.pos(0)/SCALING_FACTOR),
|
||||
ClipperLib::cInt(wti.pos(1)/SCALING_FACTOR)
|
||||
});
|
||||
ret.emplace_back(nullptr, item);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -603,7 +625,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
void applyResult(
|
||||
IndexedPackGroup::value_type& group,
|
||||
Coord batch_offset,
|
||||
ShapeData2D& shapemap)
|
||||
ShapeData2D& shapemap,
|
||||
WipeTowerInfo& wti)
|
||||
{
|
||||
for(auto& r : group) {
|
||||
auto idx = r.first; // get the original item index
|
||||
@ -612,18 +635,25 @@ void applyResult(
|
||||
// Get the model instance from the shapemap using the index
|
||||
ModelInstance *inst_ptr = shapemap[idx].first;
|
||||
|
||||
// Get the transformation data from the item object and scale it
|
||||
// appropriately
|
||||
auto off = item.translation();
|
||||
Radians rot = item.rotation();
|
||||
// Get the transformation data from the item object and scale it
|
||||
// appropriately
|
||||
auto off = item.translation();
|
||||
Radians rot = item.rotation();
|
||||
|
||||
Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
|
||||
off.Y*SCALING_FACTOR,
|
||||
inst_ptr->get_offset()(Z));
|
||||
Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
|
||||
off.Y*SCALING_FACTOR,
|
||||
inst_ptr ? inst_ptr->get_offset()(Z) : 0.);
|
||||
|
||||
// write the transformation data into the model instance
|
||||
inst_ptr->set_rotation(Z, rot);
|
||||
inst_ptr->set_offset(foff);
|
||||
if (inst_ptr) {
|
||||
// write the transformation data into the model instance
|
||||
inst_ptr->set_rotation(Z, rot);
|
||||
inst_ptr->set_offset(foff);
|
||||
}
|
||||
else { // this is the wipe tower - we will modify the struct with the info
|
||||
// and leave it up to the called to actually move the wipe tower
|
||||
wti.pos = Vec2d(foff(0), foff(1));
|
||||
wti.rotation = rot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,6 +739,7 @@ BedShapeHint bedShape(const Polyline &bed) {
|
||||
// The final client function to arrange the Model. A progress indicator and
|
||||
// a stop predicate can be also be passed to control the process.
|
||||
bool arrange(Model &model, // The model with the geometries
|
||||
WipeTowerInfo& wti, // Wipe tower info
|
||||
coord_t min_obj_distance, // Has to be in scaled (clipper) measure
|
||||
const Polyline &bed, // The bed geometry.
|
||||
BedShapeHint bedhint, // Hint about the bed geometry type.
|
||||
@ -721,7 +752,7 @@ bool arrange(Model &model, // The model with the geometries
|
||||
bool ret = true;
|
||||
|
||||
// Get the 2D projected shapes with their 3D model instance pointers
|
||||
auto shapemap = arr::projectModelFromTop(model);
|
||||
auto shapemap = arr::projectModelFromTop(model, wti);
|
||||
|
||||
// Copy the references for the shapes only as the arranger expects a
|
||||
// sequence of objects convertible to Item or ClipperPolygon
|
||||
@ -791,7 +822,7 @@ bool arrange(Model &model, // The model with the geometries
|
||||
if(result.empty() || stopcondition()) return false;
|
||||
|
||||
if(first_bin_only) {
|
||||
applyResult(result.front(), 0, shapemap);
|
||||
applyResult(result.front(), 0, shapemap, wti);
|
||||
} else {
|
||||
|
||||
const auto STRIDE_PADDING = 1.2;
|
||||
@ -801,7 +832,7 @@ bool arrange(Model &model, // The model with the geometries
|
||||
Coord batch_offset = 0;
|
||||
|
||||
for(auto& group : result) {
|
||||
applyResult(group, batch_offset, shapemap);
|
||||
applyResult(group, batch_offset, shapemap, wti);
|
||||
|
||||
// Only the first pack group can be placed onto the print bed. The
|
||||
// other objects which could not fit will be placed next to the
|
||||
@ -818,10 +849,11 @@ bool arrange(Model &model, // The model with the geometries
|
||||
void find_new_position(const Model &model,
|
||||
ModelInstancePtrs toadd,
|
||||
coord_t min_obj_distance,
|
||||
const Polyline &bed)
|
||||
const Polyline &bed,
|
||||
WipeTowerInfo& wti)
|
||||
{
|
||||
// Get the 2D projected shapes with their 3D model instance pointers
|
||||
auto shapemap = arr::projectModelFromTop(model);
|
||||
auto shapemap = arr::projectModelFromTop(model, wti);
|
||||
|
||||
// Copy the references for the shapes only as the arranger expects a
|
||||
// sequence of objects convertible to Item or ClipperPolygon
|
||||
|
@ -40,6 +40,13 @@ struct BedShapeHint {
|
||||
|
||||
BedShapeHint bedShape(const Polyline& bed);
|
||||
|
||||
struct WipeTowerInfo {
|
||||
bool is_wipe_tower = false;
|
||||
Vec2d pos;
|
||||
Vec2d bb_size;
|
||||
double rotation;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Arranges the model objects on the screen.
|
||||
*
|
||||
@ -66,7 +73,9 @@ BedShapeHint bedShape(const Polyline& bed);
|
||||
* packed. The unsigned argument is the number of items remaining to pack.
|
||||
* \param stopcondition A predicate returning true if abort is needed.
|
||||
*/
|
||||
bool arrange(Model &model, coord_t min_obj_distance,
|
||||
bool arrange(Model &model,
|
||||
WipeTowerInfo& wipe_tower_info,
|
||||
coord_t min_obj_distance,
|
||||
const Slic3r::Polyline& bed,
|
||||
BedShapeHint bedhint,
|
||||
bool first_bin_only,
|
||||
@ -78,7 +87,8 @@ bool arrange(Model &model, coord_t min_obj_distance,
|
||||
void find_new_position(const Model& model,
|
||||
ModelInstancePtrs instances_to_add,
|
||||
coord_t min_obj_distance,
|
||||
const Slic3r::Polyline& bed);
|
||||
const Slic3r::Polyline& bed,
|
||||
WipeTowerInfo& wti);
|
||||
|
||||
} // arr
|
||||
} // Slic3r
|
||||
|
@ -709,9 +709,6 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
brim_mesh.translate(-brim_width, -brim_width, 0.f);
|
||||
mesh.merge(brim_mesh);
|
||||
|
||||
//mesh.rotate(rotation_angle, &origin_of_rotation); // rotates the box according to the config rotation setting
|
||||
|
||||
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "slic3r/GUI/GLShader.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Tab.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "GUI_ObjectManipulation.hpp"
|
||||
@ -3291,6 +3292,38 @@ void GLCanvas3D::update_ui_from_settings()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
arr::WipeTowerInfo GLCanvas3D::get_wipe_tower_info() const
|
||||
{
|
||||
arr::WipeTowerInfo wti;
|
||||
for (const GLVolume* vol : m_volumes.volumes) {
|
||||
if (vol->is_wipe_tower) {
|
||||
wti.is_wipe_tower = true;
|
||||
wti.pos = Vec2d(m_config->opt_float("wipe_tower_x"),
|
||||
m_config->opt_float("wipe_tower_y"));
|
||||
wti.rotation = (M_PI/180.) * m_config->opt_float("wipe_tower_rotation_angle");
|
||||
const BoundingBoxf3& bb = vol->bounding_box;
|
||||
wti.bb_size = Vec2d(bb.size()(0), bb.size()(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return wti;
|
||||
}
|
||||
|
||||
|
||||
void GLCanvas3D::arrange_wipe_tower(const arr::WipeTowerInfo& wti) const
|
||||
{
|
||||
if (wti.is_wipe_tower) {
|
||||
DynamicPrintConfig cfg;
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = wti.pos(0);
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = wti.pos(1);
|
||||
cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = (180./M_PI) * wti.rotation;
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos)
|
||||
{
|
||||
float z0 = 0.0f;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
|
||||
#include "libslic3r/ModelArrange.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "GLToolbar.hpp"
|
||||
#include "Event.hpp"
|
||||
@ -608,6 +609,9 @@ public:
|
||||
int get_move_volume_id() const { return m_mouse.drag.move_volume_idx; }
|
||||
int get_first_hover_volume_idx() const { return m_hover_volume_idxs.empty() ? -1 : m_hover_volume_idxs.front(); }
|
||||
|
||||
arr::WipeTowerInfo get_wipe_tower_info() const;
|
||||
void arrange_wipe_tower(const arr::WipeTowerInfo& wti) const;
|
||||
|
||||
// Returns the view ray line, in world coordinate, at the given mouse position.
|
||||
Linef3 mouse_ray(const Point& mouse_pos);
|
||||
|
||||
|
@ -270,7 +270,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
|
||||
enable_grabber(Move, 2, !is_wipe_tower);
|
||||
enable_grabber(Rotate, 0, !is_wipe_tower);
|
||||
enable_grabber(Rotate, 1, !is_wipe_tower);
|
||||
|
||||
|
||||
bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
|
@ -1869,7 +1869,13 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
|
||||
Polyline bed; bed.points.reserve(bedpoints.size());
|
||||
for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
|
||||
|
||||
arr::find_new_position(model, new_instances, min_obj_distance, bed);
|
||||
arr::WipeTowerInfo wti = view3D->get_canvas3d()->get_wipe_tower_info();
|
||||
|
||||
arr::find_new_position(model, new_instances, min_obj_distance, bed, wti);
|
||||
|
||||
// it remains to move the wipe tower:
|
||||
view3D->get_canvas3d()->arrange_wipe_tower(wti);
|
||||
|
||||
#endif /* AUTOPLACEMENT_ON_LOAD */
|
||||
|
||||
if (scaled_down) {
|
||||
@ -2126,6 +2132,8 @@ void Plater::priv::arrange()
|
||||
|
||||
statusfn(0, arrangestr);
|
||||
|
||||
arr::WipeTowerInfo wti = view3D->get_canvas3d()->get_wipe_tower_info();
|
||||
|
||||
try {
|
||||
arr::BedShapeHint hint;
|
||||
|
||||
@ -2133,6 +2141,7 @@ void Plater::priv::arrange()
|
||||
hint.type = arr::BedShapeType::WHO_KNOWS;
|
||||
|
||||
arr::arrange(model,
|
||||
wti,
|
||||
min_obj_distance,
|
||||
bed,
|
||||
hint,
|
||||
@ -2144,6 +2153,9 @@ void Plater::priv::arrange()
|
||||
"Some geometries may be invalid."));
|
||||
}
|
||||
|
||||
// it remains to move the wipe tower:
|
||||
view3D->get_canvas3d()->arrange_wipe_tower(wti);
|
||||
|
||||
statusfn(0, L("Arranging done."));
|
||||
statusbar()->set_range(prev_range);
|
||||
statusbar()->set_cancel_callback(); // remove cancel button
|
||||
@ -2246,7 +2258,8 @@ void Plater::priv::sla_optimize_rotation() {
|
||||
oi->set_rotation(rt);
|
||||
}
|
||||
|
||||
arr::find_new_position(model, o->instances, coord_t(mindist/SCALING_FACTOR), bed);
|
||||
arr::WipeTowerInfo wti; // useless in SLA context
|
||||
arr::find_new_position(model, o->instances, coord_t(mindist/SCALING_FACTOR), bed, wti);
|
||||
|
||||
// Correct the z offset of the object which was corrupted be the rotation
|
||||
o->ensure_on_bed();
|
||||
|
Loading…
Reference in New Issue
Block a user