Merge branch 'master' into adaptive-slicing

This commit is contained in:
Florens Wasserfall 2016-11-09 19:01:27 +01:00
commit 38af2f2596
13 changed files with 155 additions and 13 deletions

View File

@ -63,6 +63,9 @@ main(const int argc, const char **argv)
// apply command line transform options
for (ModelObjectPtrs::iterator o = model.objects.begin(); o != model.objects.end(); ++o) {
if (cli_config.scale_to_fit.is_positive_volume())
(*o)->scale_to_fit(cli_config.scale_to_fit.value);
(*o)->scale(cli_config.scale.value);
(*o)->rotate(cli_config.rotate.value, Z);
}

View File

@ -486,6 +486,17 @@ void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType
}
template void diff<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_);
template <class ResultType>
void diff(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_)
{
Slic3r::Polygons pp;
for (Slic3r::ExPolygons::const_iterator ex = subject.begin(); ex != subject.end(); ++ex) {
Slic3r::Polygons ppp = *ex;
pp.insert(pp.end(), ppp.begin(), ppp.end());
}
diff(pp, clip, retval, safety_offset_);
}
Slic3r::Polygons
diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_)
{
@ -504,6 +515,7 @@ diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_)
}
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::Polygons>(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::Polygons, Slic3r::ExPolygons>(const Slic3r::Polygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template Slic3r::ExPolygons diff_ex<Slic3r::ExPolygons, Slic3r::ExPolygons>(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, bool safety_offset_);
template <class SubjectType, class ResultType>
void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_)
@ -596,6 +608,23 @@ void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2,
union_(pp, retval, safety_offset);
}
Slic3r::Polygons
union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset)
{
Polygons pp;
for (Slic3r::ExPolygons::const_iterator it = subject1.begin(); it != subject1.end(); ++it) {
Polygons spp = *it;
pp.insert(pp.end(), spp.begin(), spp.end());
}
for (Slic3r::ExPolygons::const_iterator it = subject2.begin(); it != subject2.end(); ++it) {
Polygons spp = *it;
pp.insert(pp.end(), spp.begin(), spp.end());
}
Polygons retval;
union_(pp, &retval, safety_offset);
return retval;
}
void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_)
{
Slic3r::Polygons clip;

View File

@ -129,6 +129,7 @@ Slic3r::ExPolygons union_ex(const Slic3r::Polygons &subject, bool safety_offset
Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject, bool safety_offset = false);
void union_(const Slic3r::Polygons &subject1, const Slic3r::Polygons &subject2, Slic3r::Polygons* retval, bool safety_offset = false);
Slic3r::Polygons union_(const Slic3r::ExPolygons &subject1, const Slic3r::ExPolygons &subject2, bool safety_offset = false);
void union_pt(const Slic3r::Polygons &subject, ClipperLib::PolyTree* retval, bool safety_offset_ = false);
void union_pt_chained(const Slic3r::Polygons &subject, Slic3r::Polygons* retval, bool safety_offset_ = false);

View File

@ -283,6 +283,8 @@ DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
opt = new ConfigOptionFloatOrPercent ();
} else if (optdef->type == coPoint) {
opt = new ConfigOptionPoint ();
} else if (optdef->type == coPoint3) {
opt = new ConfigOptionPoint3 ();
} else if (optdef->type == coPoints) {
opt = new ConfigOptionPoints ();
} else if (optdef->type == coBool) {

View File

@ -10,6 +10,8 @@
#include <stdexcept>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include "libslic3r.h"
#include "Point.hpp"
@ -352,15 +354,55 @@ class ConfigOptionPoint : public ConfigOptionSingle<Pointf>
};
bool deserialize(std::string str, bool append = false) {
std::istringstream iss(str);
iss >> this->value.x;
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
iss.ignore(std::numeric_limits<std::streamsize>::max(), 'x');
iss >> this->value.y;
std::vector<std::string> tokens(2);
boost::split(tokens, str, boost::is_any_of(",x"));
try {
this->value.x = boost::lexical_cast<coordf_t>(tokens[0]);
this->value.y = boost::lexical_cast<coordf_t>(tokens[1]);
} catch (boost::bad_lexical_cast &e){
std::cout << "Exception caught : " << e.what() << std::endl;
return false;
}
return true;
};
};
class ConfigOptionPoint3 : public ConfigOptionSingle<Pointf3>
{
public:
ConfigOptionPoint3() : ConfigOptionSingle<Pointf3>(Pointf3(0,0,0)) {};
ConfigOptionPoint3(Pointf3 _value) : ConfigOptionSingle<Pointf3>(_value) {};
ConfigOptionPoint3* clone() const { return new ConfigOptionPoint3(this->value); };
std::string serialize() const {
std::ostringstream ss;
ss << this->value.x;
ss << ",";
ss << this->value.y;
ss << ",";
ss << this->value.z;
return ss.str();
};
bool deserialize(std::string str, bool append = false) {
std::vector<std::string> tokens(3);
boost::split(tokens, str, boost::is_any_of(",x"));
try {
this->value.x = boost::lexical_cast<coordf_t>(tokens[0]);
this->value.y = boost::lexical_cast<coordf_t>(tokens[1]);
this->value.z = boost::lexical_cast<coordf_t>(tokens[2]);
} catch (boost::bad_lexical_cast &e){
std::cout << "Exception caught : " << e.what() << std::endl;
return false;
}
return true;
};
bool is_positive_volume () {
return this->value.x > 0 && this->value.y > 0 && this->value.z > 0;
};
};
class ConfigOptionPoints : public ConfigOptionVector<Pointf>
{
public:
@ -526,6 +568,7 @@ enum ConfigOptionType {
coPercent,
coFloatOrPercent,
coPoint,
coPoint3,
coPoints,
coBool,
coBools,

View File

@ -58,11 +58,6 @@ POV::write(TriangleMesh& mesh, std::string output_file)
{
TriangleMesh mesh2 = mesh;
mesh2.center_around_origin();
{
Sizef3 size = mesh2.bounding_box().size();
coordf_t maxdim = fmax(size.x, fmax(size.y, size.y));
mesh2.scale(10.0/maxdim);
}
using namespace std;
ofstream pov;

View File

@ -609,6 +609,20 @@ ModelObject::scale(const Pointf3 &versor)
this->invalidate_bounding_box();
}
void
ModelObject::scale_to_fit(const Sizef3 &size)
{
Sizef3 orig_size = this->bounding_box().size();
float factor = fminf(
size.x / orig_size.x,
fminf(
size.y / orig_size.y,
size.z / orig_size.z
)
);
this->scale(factor);
}
void
ModelObject::rotate(float angle, const Axis &axis)
{

View File

@ -2,6 +2,7 @@
#define slic3r_Model_hpp_
#include "libslic3r.h"
#include "BoundingBox.hpp"
#include "PrintConfig.hpp"
#include "Layer.hpp"
#include "Point.hpp"
@ -129,6 +130,7 @@ class ModelObject
void translate(coordf_t x, coordf_t y, coordf_t z);
void scale(float factor);
void scale(const Pointf3 &versor);
void scale_to_fit(const Sizef3 &size);
void rotate(float angle, const Axis &axis);
void mirror(const Axis &axis);
size_t materials_count() const;

View File

@ -1457,6 +1457,12 @@ CLIConfigDef::CLIConfigDef()
def->tooltip = "Scaling factor (default: 1).";
def->cli = "scale";
def->default_value = new ConfigOptionFloat(1);
def = this->add("scale_to_fit", coPoint3);
def->label = "Scale to Fit";
def->tooltip = "Scale to fit the given volume.";
def->cli = "scale-to-fit";
def->default_value = new ConfigOptionPoint3(Pointf3(0,0,0));
}
CLIConfigDef cli_config_def;

View File

@ -500,6 +500,9 @@ class SVGExportConfig
ConfigOptionFloat layer_height;
ConfigOptionInt raft_layers;
ConfigOptionFloat raft_offset;
ConfigOptionBool support_material;
ConfigOptionFloatOrPercent support_material_extrusion_width;
ConfigOptionFloat support_material_spacing;
SVGExportConfig() : StaticPrintConfig() {
this->set_defaults();
@ -510,6 +513,9 @@ class SVGExportConfig
OPT_PTR(layer_height);
OPT_PTR(raft_layers);
OPT_PTR(raft_offset);
OPT_PTR(support_material);
OPT_PTR(support_material_extrusion_width);
OPT_PTR(support_material_spacing);
return NULL;
};
@ -536,6 +542,7 @@ class CLIConfig
ConfigOptionFloat rotate;
ConfigOptionString save;
ConfigOptionFloat scale;
ConfigOptionPoint3 scale_to_fit;
CLIConfig() : ConfigBase(), StaticConfig() {
this->def = &cli_config_def;
@ -552,6 +559,7 @@ class CLIConfig
OPT_PTR(rotate);
OPT_PTR(save);
OPT_PTR(scale);
OPT_PTR(scale_to_fit);
return NULL;
};

View File

@ -17,6 +17,7 @@ SVGExport::writeSVG(const std::string &outputfile)
bb.max.y += this->config.raft_offset.value;
}
this->mesh.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin
bb.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin
const Sizef3 size = bb.size();
// if we are generating a raft, first_layer_height will not affect mesh slicing
@ -53,17 +54,47 @@ SVGExport::writeSVG(const std::string &outputfile)
layer_z[i] += first_lh + lh * (this->config.raft_layers-1);
}
// generate support material
std::vector<Points> support_material(layers.size());
if (this->config.support_material) {
// generate a grid of points according to the configured spacing,
// covering the entire object bounding box
Points support_material_points;
for (coordf_t x = bb.min.x; x <= bb.max.x; x += this->config.support_material_spacing) {
for (coordf_t y = bb.min.y; y <= bb.max.y; y += this->config.support_material_spacing) {
support_material_points.push_back(Point(scale_(x), scale_(y)));
}
}
// check overhangs, starting from the upper layer, and detect which points apply
// to each layer
ExPolygons overhangs;
for (int i = layer_z.size()-1; i >= 0; --i) {
overhangs = diff_ex(union_(overhangs, layers[i+1]), layers[i]);
for (Points::const_iterator it = support_material_points.begin(); it != support_material_points.end(); ++it) {
for (ExPolygons::const_iterator e = overhangs.begin(); e != overhangs.end(); ++e) {
if (e->contains(*it)) {
support_material[i].push_back(*it);
break;
}
}
}
}
}
double support_material_radius = this->config.support_material_extrusion_width.get_abs_value(this->config.layer_height)/2;
FILE* f = fopen(outputfile.c_str(), "w");
fprintf(f,
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
"<svg width=\"%f\" height=\"%f\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:slic3r=\"http://slic3r.org/namespaces/slic3r\">\n"
"<svg width=\"%f\" height=\"%f\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:slic3r=\"http://slic3r.org/namespaces/slic3r\" viewport-fill=\"black\">\n"
"<!-- Generated using Slic3r %s http://slic3r.org/ -->\n"
, size.x, size.y, SLIC3R_VERSION);
for (size_t i = 0; i < layer_z.size(); ++i) {
fprintf(f, "\t<g id=\"layer%zu\" slic3r:z=\"%0.4f\">\n", i, layer_z[i]);
for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it){
for (ExPolygons::const_iterator it = layers[i].begin(); it != layers[i].end(); ++it) {
std::string pd;
Polygons pp = *it;
for (Polygons::const_iterator mp = pp.begin(); mp != pp.end(); ++mp) {
@ -80,6 +111,11 @@ SVGExport::writeSVG(const std::string &outputfile)
pd.c_str(), "white", "black", "0", unscale(unscale(it->area()))
);
}
for (Points::const_iterator it = support_material[i].begin(); it != support_material[i].end(); ++it) {
fprintf(f,"\t\t<circle cx=\"%f\" cy=\"%f\" r=\"%f\" stroke-width=\"0\" fill=\"white\" slic3r:type=\"support\" />\n",
unscale(it->x), unscale(it->y), support_material_radius
);
}
fprintf(f,"\t</g>\n");
}
fprintf(f,"</svg>\n");

View File

@ -115,6 +115,9 @@ ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) {
} else if (def.type == coPoint) {
const ConfigOptionPoint* optv = dynamic_cast<const ConfigOptionPoint*>(&opt);
return perl_to_SV_clone_ref(optv->value);
} else if (def.type == coPoint3) {
const ConfigOptionPoint3* optv = dynamic_cast<const ConfigOptionPoint3*>(&opt);
return perl_to_SV_clone_ref(optv->value);
} else if (def.type == coPoints) {
const ConfigOptionPoints* optv = dynamic_cast<const ConfigOptionPoints*>(&opt);
AV* av = newAV();

View File

@ -118,7 +118,7 @@ print_config_def()
opt_type = "s";
} else if (optdef->type == coStrings) {
opt_type = "s@";
} else if (optdef->type == coPoint || optdef->type == coPoints) {
} else if (optdef->type == coPoint || optdef->type == coPoint3 || optdef->type == coPoints) {
opt_type = "point";
} else if (optdef->type == coBool || optdef->type == coBools) {
opt_type = "bool";