Fix --center, --dont-arrange, --export-* and other things

This commit is contained in:
Alessandro Ranellucci 2018-11-25 14:56:33 +01:00 committed by Joseph Lenox
parent b17f623915
commit 945bbc030c
7 changed files with 55 additions and 15 deletions

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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 << ">,";

View File

@ -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();

View File

@ -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);

View File

@ -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()));
} }

View File

@ -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};