mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-18 05:55:56 +08:00
Fix --center, --dont-arrange, --export-* and other things
This commit is contained in:
parent
b17f623915
commit
945bbc030c
@ -119,6 +119,19 @@ int CLI::run(int argc, char **argv) {
|
|||||||
Model m;
|
Model m;
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
m.merge(model);
|
m.merge(model);
|
||||||
|
|
||||||
|
// Rearrange instances unless --dont-arrange is supplied
|
||||||
|
if (!this->config.getBool("dont_arrange")) {
|
||||||
|
m.add_default_instances();
|
||||||
|
const BoundingBoxf bb{ this->full_print_config.bed_shape.values };
|
||||||
|
m.arrange_objects(
|
||||||
|
this->full_print_config.min_object_distance(),
|
||||||
|
// if we are going to use the merged model for printing, honor
|
||||||
|
// the configured print bed for arranging, otherwise do it freely
|
||||||
|
this->has_print_action() ? &bb : nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this->models = {m};
|
this->models = {m};
|
||||||
} else if (opt_key == "duplicate") {
|
} else if (opt_key == "duplicate") {
|
||||||
const BoundingBoxf bb{ this->full_print_config.bed_shape.values };
|
const BoundingBoxf bb{ this->full_print_config.bed_shape.values };
|
||||||
@ -144,30 +157,38 @@ int CLI::run(int argc, char **argv) {
|
|||||||
model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
|
model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
|
||||||
} else if (opt_key == "center") {
|
} else if (opt_key == "center") {
|
||||||
for (auto &model : this->models) {
|
for (auto &model : this->models) {
|
||||||
|
model.add_default_instances();
|
||||||
|
// this affects instances:
|
||||||
model.center_instances_around_point(config.opt<ConfigOptionPoint>("center")->value);
|
model.center_instances_around_point(config.opt<ConfigOptionPoint>("center")->value);
|
||||||
|
// this affects volumes:
|
||||||
model.align_to_ground();
|
model.align_to_ground();
|
||||||
}
|
}
|
||||||
} else if (opt_key == "align_xy") {
|
} else if (opt_key == "align_xy") {
|
||||||
const Pointf p{ this->config.opt<ConfigOptionPoint>("align_xy")->value };
|
const Pointf p{ this->config.opt<ConfigOptionPoint>("align_xy")->value };
|
||||||
for (auto &model : this->models) {
|
for (auto &model : this->models) {
|
||||||
BoundingBoxf3 bb{ model.bounding_box() };
|
BoundingBoxf3 bb{ model.bounding_box() };
|
||||||
|
// this affects volumes:
|
||||||
model.translate(-(bb.min.x - p.x), -(bb.min.y - p.y), -bb.min.z);
|
model.translate(-(bb.min.x - p.x), -(bb.min.y - p.y), -bb.min.z);
|
||||||
}
|
}
|
||||||
} else if (opt_key == "rotate") {
|
} else if (opt_key == "rotate") {
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
for (auto &o : model.objects)
|
for (auto &o : model.objects)
|
||||||
|
// this affects volumes:
|
||||||
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), Z);
|
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), Z);
|
||||||
} else if (opt_key == "rotate_x") {
|
} else if (opt_key == "rotate_x") {
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
for (auto &o : model.objects)
|
for (auto &o : model.objects)
|
||||||
|
// this affects volumes:
|
||||||
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), X);
|
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), X);
|
||||||
} else if (opt_key == "rotate_y") {
|
} else if (opt_key == "rotate_y") {
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
for (auto &o : model.objects)
|
for (auto &o : model.objects)
|
||||||
|
// this affects volumes:
|
||||||
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), Y);
|
o->rotate(Geometry::deg2rad(config.getFloat(opt_key)), Y);
|
||||||
} else if (opt_key == "scale") {
|
} else if (opt_key == "scale") {
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
for (auto &o : model.objects)
|
for (auto &o : model.objects)
|
||||||
|
// this affects volumes:
|
||||||
o->scale(config.get_abs_value(opt_key, 1));
|
o->scale(config.get_abs_value(opt_key, 1));
|
||||||
} else if (opt_key == "scale_to_fit") {
|
} else if (opt_key == "scale_to_fit") {
|
||||||
const auto opt = config.opt<ConfigOptionPoint3>(opt_key);
|
const auto opt = config.opt<ConfigOptionPoint3>(opt_key);
|
||||||
@ -177,6 +198,7 @@ int CLI::run(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
for (auto &model : this->models)
|
for (auto &model : this->models)
|
||||||
for (auto &o : model.objects)
|
for (auto &o : model.objects)
|
||||||
|
// this affects volumes:
|
||||||
o->scale_to_fit(opt->value);
|
o->scale_to_fit(opt->value);
|
||||||
} else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
|
} else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
|
||||||
std::vector<Model> new_models;
|
std::vector<Model> new_models;
|
||||||
@ -253,13 +275,21 @@ int CLI::run(int argc, char **argv) {
|
|||||||
this->print_config.save(config.getString("save"));
|
this->print_config.save(config.getString("save"));
|
||||||
} else if (opt_key == "info") {
|
} else if (opt_key == "info") {
|
||||||
// --info works on unrepaired model
|
// --info works on unrepaired model
|
||||||
for (const Model &model : this->models)
|
for (Model &model : this->models) {
|
||||||
|
model.add_default_instances();
|
||||||
model.print_info();
|
model.print_info();
|
||||||
|
}
|
||||||
} else if (opt_key == "export_stl") {
|
} else if (opt_key == "export_stl") {
|
||||||
|
for (auto &model : this->models)
|
||||||
|
model.add_default_instances();
|
||||||
this->export_models(IO::STL);
|
this->export_models(IO::STL);
|
||||||
} else if (opt_key == "export_obj") {
|
} else if (opt_key == "export_obj") {
|
||||||
|
for (auto &model : this->models)
|
||||||
|
model.add_default_instances();
|
||||||
this->export_models(IO::OBJ);
|
this->export_models(IO::OBJ);
|
||||||
} else if (opt_key == "export_pov") {
|
} else if (opt_key == "export_pov") {
|
||||||
|
for (auto &model : this->models)
|
||||||
|
model.add_default_instances();
|
||||||
this->export_models(IO::POV);
|
this->export_models(IO::POV);
|
||||||
} else if (opt_key == "export_amf") {
|
} else if (opt_key == "export_amf") {
|
||||||
this->export_models(IO::AMF);
|
this->export_models(IO::AMF);
|
||||||
@ -278,11 +308,16 @@ int CLI::run(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
} else if (opt_key == "export_gcode") {
|
} else if (opt_key == "export_gcode") {
|
||||||
for (const Model &model : this->models) {
|
for (const Model &model : this->models) {
|
||||||
|
// If all objects have defined instances, their relative positions will be
|
||||||
|
// honored when printing (they will be only centered, unless --dont-arrange
|
||||||
|
// is supplied); if any object has no instances, it will get a default one
|
||||||
|
// and all instances will be rearranged (unless --dont-arrange is supplied).
|
||||||
SimplePrint print;
|
SimplePrint print;
|
||||||
print.status_cb = [](int ln, const std::string& msg) {
|
print.status_cb = [](int ln, const std::string& msg) {
|
||||||
boost::nowide::cout << msg << std::endl;
|
boost::nowide::cout << msg << std::endl;
|
||||||
};
|
};
|
||||||
print.apply_config(this->print_config);
|
print.apply_config(this->print_config);
|
||||||
|
print.arrange = !this->config.getBool("dont_arrange");
|
||||||
print.center = !this->config.has("center")
|
print.center = !this->config.has("center")
|
||||||
&& !this->config.has("align_xy")
|
&& !this->config.has("align_xy")
|
||||||
&& !this->config.getBool("dont_arrange");
|
&& !this->config.getBool("dont_arrange");
|
||||||
@ -365,8 +400,7 @@ CLI::print_help(bool include_print_options) const {
|
|||||||
|
|
||||||
void
|
void
|
||||||
CLI::export_models(IO::ExportFormat format) {
|
CLI::export_models(IO::ExportFormat format) {
|
||||||
for (size_t i = 0; i < this->models.size(); ++i) {
|
for (const Model& model : this->models) {
|
||||||
Model &model = this->models[i];
|
|
||||||
const std::string outfile = this->output_filepath(model, format);
|
const std::string outfile = this->output_filepath(model, format);
|
||||||
|
|
||||||
IO::write_model.at(format)(model, outfile);
|
IO::write_model.at(format)(model, outfile);
|
||||||
|
@ -27,6 +27,10 @@ class CLI {
|
|||||||
/// Exports loaded models to a file of the specified format, according to the options affecting output filename.
|
/// Exports loaded models to a file of the specified format, according to the options affecting output filename.
|
||||||
void export_models(IO::ExportFormat format);
|
void export_models(IO::ExportFormat format);
|
||||||
|
|
||||||
|
bool has_print_action() const {
|
||||||
|
return this->config.has("export_gcode") || this->config.has("export_sla_svg");
|
||||||
|
};
|
||||||
|
|
||||||
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
|
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,20 +170,17 @@ bool
|
|||||||
POV::write(const Model &model, std::string output_file)
|
POV::write(const Model &model, std::string output_file)
|
||||||
{
|
{
|
||||||
TriangleMesh mesh{ model.mesh() };
|
TriangleMesh mesh{ model.mesh() };
|
||||||
return STL::write(mesh, output_file);
|
return POV::write(mesh, output_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
POV::write(const TriangleMesh& mesh, std::string output_file)
|
POV::write(const TriangleMesh& mesh, std::string output_file)
|
||||||
{
|
{
|
||||||
TriangleMesh mesh2 = mesh;
|
|
||||||
mesh2.center_around_origin();
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
boost::nowide::ofstream pov;
|
boost::nowide::ofstream pov;
|
||||||
pov.open(output_file.c_str(), ios::out | ios::trunc);
|
pov.open(output_file.c_str(), ios::out | ios::trunc);
|
||||||
for (int i = 0; i < mesh2.stl.stats.number_of_facets; ++i) {
|
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||||
const stl_facet &f = mesh2.stl.facet_start[i];
|
const stl_facet &f = mesh.stl.facet_start[i];
|
||||||
pov << "triangle { ";
|
pov << "triangle { ";
|
||||||
pov << "<" << f.vertex[0].x << "," << f.vertex[0].y << "," << f.vertex[0].z << ">,";
|
pov << "<" << f.vertex[0].x << "," << f.vertex[0].y << "," << f.vertex[0].z << ">,";
|
||||||
pov << "<" << f.vertex[1].x << "," << f.vertex[1].y << "," << f.vertex[1].z << ">,";
|
pov << "<" << f.vertex[1].x << "," << f.vertex[1].y << "," << f.vertex[1].z << ">,";
|
||||||
|
@ -933,7 +933,7 @@ ModelObject::print_info() const
|
|||||||
cout << fixed;
|
cout << fixed;
|
||||||
cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
|
cout << "[" << boost::filesystem::path(this->input_file).filename().string() << "]" << endl;
|
||||||
|
|
||||||
TriangleMesh mesh = this->raw_mesh();
|
TriangleMesh mesh = this->mesh();
|
||||||
mesh.check_topology();
|
mesh.check_topology();
|
||||||
BoundingBoxf3 bb = mesh.bounding_box();
|
BoundingBoxf3 bb = mesh.bounding_box();
|
||||||
Sizef3 size = bb.size();
|
Sizef3 size = bb.size();
|
||||||
|
@ -2092,7 +2092,7 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||||||
def = this->add("output", coString);
|
def = this->add("output", coString);
|
||||||
def->label = __TRANS("Output File");
|
def->label = __TRANS("Output File");
|
||||||
def->tooltip = __TRANS("The file where the output will be written (if not specified, it will be based on the input file).");
|
def->tooltip = __TRANS("The file where the output will be written (if not specified, it will be based on the input file).");
|
||||||
def->cli = "output";
|
def->cli = "output|o";
|
||||||
|
|
||||||
#ifdef USE_WX
|
#ifdef USE_WX
|
||||||
def = this->add("autosave", coString);
|
def = this->add("autosave", coString);
|
||||||
|
@ -11,15 +11,19 @@ SimplePrint::set_model(const Model &model) {
|
|||||||
// make method idempotent so that the object is reusable
|
// make method idempotent so that the object is reusable
|
||||||
this->_print.clear_objects();
|
this->_print.clear_objects();
|
||||||
|
|
||||||
// make sure all objects have at least one defined instance
|
|
||||||
this->_model.add_default_instances();
|
|
||||||
|
|
||||||
// align to z = 0
|
// align to z = 0
|
||||||
for (ModelObject* o : this->_model.objects)
|
for (ModelObject* o : this->_model.objects)
|
||||||
o->translate(0, 0, -o->bounding_box().min.z);
|
o->translate(0, 0, -o->bounding_box().min.z);
|
||||||
|
|
||||||
|
// make sure all objects have at least one defined instance
|
||||||
|
if (this->_model.add_default_instances() && this->arrange) {
|
||||||
|
// if we added at least one default instance, we need to rearrange
|
||||||
|
const BoundingBoxf bb{ this->_print.config.bed_shape.values };
|
||||||
|
this->_model.arrange_objects(this->_print.config.min_object_distance(), &bb);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->center) {
|
if (this->center) {
|
||||||
Polygon bed_polygon{ scale(this->_print.config.bed_shape.values) };
|
const Polygon bed_polygon{ scale(this->_print.config.bed_shape.values) };
|
||||||
this->_model.center_instances_around_point(Slic3r::Pointf::new_unscale(bed_polygon.centroid()));
|
this->_model.center_instances_around_point(Slic3r::Pointf::new_unscale(bed_polygon.centroid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
class SimplePrint {
|
class SimplePrint {
|
||||||
public:
|
public:
|
||||||
|
bool arrange{true};
|
||||||
bool center{true};
|
bool center{true};
|
||||||
std::function<void(int, const std::string&)> status_cb {nullptr};
|
std::function<void(int, const std::string&)> status_cb {nullptr};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user