mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 23:31:19 +00:00
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes. clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer. * Remove Unused Project Includes From Files With Platform-Specific Code A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block. * Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass The platform-file pass treated pchheader.hpp as an ordinary header and emptied it, and left GUI_Preview.hpp and 14 other files relying on headers they no longer reached directly. * Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call * Include Headers That Files Reached Through Ones the Cleanup Removed * Drop Includes Duplicated by the Cleanup or by Main's Own Additions * Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
202 lines
7.5 KiB
C++
202 lines
7.5 KiB
C++
#include "ModelArrange.hpp"
|
|
|
|
#include <cstddef>
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <libslic3r/Model.hpp>
|
|
#include <libslic3r/Geometry/ConvexHull.hpp>
|
|
#include <libslic3r/Print.hpp>
|
|
#include "Arrange.hpp"
|
|
#include <utility>
|
|
#include "Config.hpp"
|
|
#include <set>
|
|
#include <string>
|
|
#include "Point.hpp"
|
|
#include "PrintConfig.hpp"
|
|
#include "BoundingBox.hpp"
|
|
#include "ExPolygon.hpp"
|
|
#include "Polygon.hpp"
|
|
|
|
namespace Slic3r {
|
|
|
|
arrangement::ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances)
|
|
{
|
|
size_t count = 0;
|
|
for (auto obj : model.objects) count += obj->instances.size();
|
|
|
|
ArrangePolygons input;
|
|
input.reserve(count);
|
|
instances.clear(); instances.reserve(count);
|
|
ArrangePolygon ap;
|
|
for (ModelObject *mo : model.objects)
|
|
for (ModelInstance *minst : mo->instances) {
|
|
minst->get_arrange_polygon(&ap);
|
|
// ModelInstance::get_arrange_polygon leaves bed_idx at its UNARRANGED
|
|
// default; seed it to bed 0 (as get_instance_arrange_poly does) so the
|
|
// nester treats the item as placeable instead of returning it unplaced.
|
|
ap.bed_idx = 0;
|
|
input.emplace_back(ap);
|
|
instances.emplace_back(minst);
|
|
}
|
|
|
|
return input;
|
|
}
|
|
|
|
bool apply_arrange_polys(ArrangePolygons &input, ModelInstancePtrs &instances, VirtualBedFn vfn)
|
|
{
|
|
bool ret = true;
|
|
|
|
for(size_t i = 0; i < input.size(); ++i) {
|
|
if (input[i].bed_idx != 0) { ret = false; if (vfn) vfn(input[i]); }
|
|
if (input[i].bed_idx >= 0)
|
|
instances[i]->apply_arrange_result(input[i].translation.cast<double>(),
|
|
input[i].rotation);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
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(&obj_ap);
|
|
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;
|
|
std::copy(pts.begin(), pts.end(), std::back_inserter(apts));
|
|
}
|
|
|
|
apts = std::move(Geometry::convex_hull(apts).points);
|
|
return ap;
|
|
}
|
|
|
|
void duplicate(Model &model, Slic3r::arrangement::ArrangePolygons &copies, VirtualBedFn vfn)
|
|
{
|
|
for (ModelObject *o : model.objects) {
|
|
// make a copy of the pointers in order to avoid recursion when appending their copies
|
|
ModelInstancePtrs instances = o->instances;
|
|
o->instances.clear();
|
|
for (const ModelInstance *i : instances) {
|
|
for (arrangement::ArrangePolygon &ap : copies) {
|
|
if (ap.bed_idx != 0) vfn(ap);
|
|
ModelInstance *instance = o->add_instance(*i);
|
|
Vec2d pos = unscale(ap.translation);
|
|
instance->set_offset(instance->get_offset() + to_3d(pos, 0.));
|
|
}
|
|
}
|
|
o->invalidate_bounding_box();
|
|
}
|
|
}
|
|
|
|
void duplicate_objects(Model &model, size_t copies_num)
|
|
{
|
|
for (ModelObject *o : model.objects) {
|
|
// make a copy of the pointers in order to avoid recursion when appending their copies
|
|
ModelInstancePtrs instances = o->instances;
|
|
for (const ModelInstance *i : instances)
|
|
for (size_t k = 2; k <= copies_num; ++ k)
|
|
o->add_instance(*i);
|
|
}
|
|
}
|
|
|
|
// Set up arrange polygon for a ModelInstance and Wipe tower
|
|
template<class T>
|
|
arrangement::ArrangePolygon get_arrange_poly(T obj, const Slic3r::DynamicPrintConfig& config)
|
|
{
|
|
ArrangePolygon ap = obj.get_arrange_polygon(config);
|
|
//BBS: always set bed_idx to 0 to use original transforms with no bed_idx
|
|
//if this object is not arranged, it can keep the original transforms
|
|
//ap.bed_idx = ap.translation.x() / bed_stride_x(plater);
|
|
ap.bed_idx = 0;
|
|
ap.setter = [obj](const ArrangePolygon& p) {
|
|
if (p.is_arranged()) {
|
|
Vec2d t = p.translation.cast<double>();
|
|
//BBS: change to sudoku-style computation, do it in partplate list
|
|
//t.x() += p.bed_idx * bed_stride(plater);
|
|
//t.x() += col * bed_stride_x(plater);
|
|
//t.y() -= row * bed_stride_y(plater);
|
|
T{ obj }.apply_arrange_result(t, p.rotation, p.itemid);
|
|
}
|
|
};
|
|
|
|
return ap;
|
|
}
|
|
|
|
template<>
|
|
arrangement::ArrangePolygon get_arrange_poly(ModelInstance* inst, const Slic3r::DynamicPrintConfig& config)
|
|
{
|
|
return get_arrange_poly(PtrWrapper{ inst },config);
|
|
}
|
|
|
|
ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::DynamicPrintConfig& config)
|
|
{
|
|
ArrangePolygon ap = get_arrange_poly(PtrWrapper{ instance }, config);
|
|
|
|
//BBS: add temperature information
|
|
if (config.has("curr_bed_type")) {
|
|
ap.bed_temp = 0;
|
|
ap.first_bed_temp = 0;
|
|
BedType curr_bed_type = config.opt_enum<BedType>("curr_bed_type");
|
|
|
|
const ConfigOptionInts* bed_opt = config.option<ConfigOptionInts>(get_bed_temp_key(curr_bed_type));
|
|
if (bed_opt != nullptr)
|
|
ap.bed_temp = bed_opt->get_at(ap.extrude_ids.front()-1);
|
|
|
|
const ConfigOptionInts* bed_opt_1st_layer = config.option<ConfigOptionInts>(get_bed_temp_1st_layer_key(curr_bed_type));
|
|
if (bed_opt_1st_layer != nullptr)
|
|
ap.first_bed_temp = bed_opt_1st_layer->get_at(ap.extrude_ids.front()-1);
|
|
}
|
|
|
|
if (config.has("nozzle_temperature")) //get the print temperature
|
|
ap.print_temp = config.opt_int("nozzle_temperature", ap.extrude_ids.front() - 1);
|
|
if (config.has("nozzle_temperature_initial_layer")) //get the nozzle_temperature_initial_layer
|
|
ap.first_print_temp = config.opt_int("nozzle_temperature_initial_layer", ap.extrude_ids.front() - 1);
|
|
|
|
if (config.has("temperature_vitrification")) {
|
|
ap.vitrify_temp = config.opt_int("temperature_vitrification", ap.extrude_ids.front() - 1);
|
|
}
|
|
|
|
// get filament temp types
|
|
auto* filament_types_opt = dynamic_cast<const ConfigOptionStrings*>(config.option("filament_type"));
|
|
if (filament_types_opt) {
|
|
std::set<int> filament_temp_types;
|
|
for (auto i : ap.extrude_ids) {
|
|
std::string type_str = filament_types_opt->get_at(i-1);
|
|
int temp_type = Print::get_filament_temp_type(type_str);
|
|
filament_temp_types.insert(temp_type);
|
|
}
|
|
ap.filament_temp_type = Print::get_compatible_filament_type(filament_temp_types);
|
|
}
|
|
|
|
// get brim width
|
|
auto obj = instance->get_object();
|
|
|
|
ap.brim_width = 1.0;
|
|
// For by-layer printing, need to shrink bed a little, so the support won't go outside bed.
|
|
// We set it to 5mm because that's how much a normal support will grow by default.
|
|
// normal support 5mm, other support 22mm, no support 0mm
|
|
auto supp_type_ptr = obj->get_config_value<ConfigOptionBool>(config, "enable_support");
|
|
auto support_type_ptr = obj->get_config_value<ConfigOptionEnum<SupportType>>(config, "support_type");
|
|
auto support_type = support_type_ptr->value;
|
|
auto enable_support = supp_type_ptr->getBool();
|
|
int support_int = support_type_ptr->getInt();
|
|
|
|
if (enable_support && (support_type == stNormalAuto || support_type == stNormal))
|
|
ap.brim_width = 6.0;
|
|
else if (enable_support) {
|
|
ap.brim_width = 24.0; // 2*MAX_BRANCH_RADIUS_FIRST_LAYER
|
|
ap.has_tree_support = true;
|
|
}
|
|
|
|
auto size = obj->instance_convex_hull_bounding_box(instance).size();
|
|
ap.height = size.z();
|
|
ap.name = obj->name;
|
|
return ap;
|
|
}
|
|
|
|
} // namespace Slic3r
|