Merge branch 'master' into fs_QuadricEdgeCollapse

This commit is contained in:
Filip Sykala 2021-08-18 10:37:21 +02:00
commit cc88b1e86b
18 changed files with 269 additions and 137 deletions

View file

@ -45,16 +45,38 @@ static float max_brim_width(const ConstPrintObjectPtrsAdaptor &objects)
}));
}
static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
// Returns ExPolygons of the bottom layer of the print object after elephant foot compensation.
static ExPolygons get_print_object_bottom_layer_expolygons(const PrintObject &print_object)
{
ExPolygons ex_polygons;
for (LayerRegion *region : print_object.layers().front()->regions())
Slic3r::append(ex_polygons, offset_ex(offset_ex(region->slices.surfaces, float(SCALED_EPSILON)), -float(SCALED_EPSILON)));
return ex_polygons;
}
// Returns ExPolygons of bottom layer for every print object in Print after elephant foot compensation.
static std::vector<ExPolygons> get_print_bottom_layers_expolygons(const Print &print)
{
std::vector<ExPolygons> bottom_layers_expolygons;
bottom_layers_expolygons.reserve(print.objects().size());
for (const PrintObject *object : print.objects())
bottom_layers_expolygons.emplace_back(get_print_object_bottom_layer_expolygons(*object));
return bottom_layers_expolygons;
}
static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print, const std::vector<ExPolygons> &bottom_layers_expolygons)
{
assert(print.objects().size() == bottom_layers_expolygons.size());
Polygons islands;
ConstPrintObjectPtrs island_to_object;
for (const PrintObject *object : print.objects()) {
for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) {
Polygons islands_object;
islands_object.reserve(object->layers().front()->lslices.size());
for (const ExPolygon &ex_poly : object->layers().front()->lslices)
islands_object.reserve(bottom_layers_expolygons[print_object_idx].size());
for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx])
islands_object.emplace_back(ex_poly.contour);
const PrintObject *object = print.objects()[print_object_idx];
islands.reserve(islands.size() + object->instances().size() * islands_object.size());
for (const PrintInstance &instance : object->instances())
for (Polygon &poly : islands_object) {
@ -110,7 +132,7 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev
//FIXME how about the brim type?
auto brim_offset = float(scale_(object->config().brim_offset.value));
Polygons islands_object;
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) {
Polygons contour_offset = offset(ex_poly.contour, brim_offset);
for (Polygon &poly : contour_offset)
poly.douglas_peucker(SCALED_RESOLUTION);
@ -124,8 +146,12 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev
return islands;
}
static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
static ExPolygons top_level_outer_brim_area(const Print &print,
const ConstPrintObjectPtrs &top_level_objects_with_brim,
const std::vector<ExPolygons> &bottom_layers_expolygons,
const float no_brim_offset)
{
assert(print.objects().size() == bottom_layers_expolygons.size());
std::unordered_set<size_t> top_level_objects_idx;
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
for (const PrintObject *object : top_level_objects_with_brim)
@ -133,15 +159,16 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
ExPolygons brim_area;
ExPolygons no_brim_area;
for (const PrintObject *object : print.objects()) {
const BrimType brim_type = object->config().brim_type.value;
const float brim_offset = scale_(object->config().brim_offset.value);
const float brim_width = scale_(object->config().brim_width.value);
const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) {
const PrintObject *object = print.objects()[print_object_idx];
const BrimType brim_type = object->config().brim_type.value;
const float brim_offset = scale_(object->config().brim_offset.value);
const float brim_width = scale_(object->config().brim_width.value);
const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
ExPolygons brim_area_object;
ExPolygons no_brim_area_object;
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) {
if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim)
append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset)));
@ -166,8 +193,12 @@ static ExPolygons top_level_outer_brim_area(const Print &print, const ConstPrint
return diff_ex(brim_area, no_brim_area);
}
static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, const float no_brim_offset)
static ExPolygons inner_brim_area(const Print &print,
const ConstPrintObjectPtrs &top_level_objects_with_brim,
const std::vector<ExPolygons> &bottom_layers_expolygons,
const float no_brim_offset)
{
assert(print.objects().size() == bottom_layers_expolygons.size());
std::unordered_set<size_t> top_level_objects_idx;
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
for (const PrintObject *object : top_level_objects_with_brim)
@ -176,16 +207,17 @@ static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs
ExPolygons brim_area;
ExPolygons no_brim_area;
Polygons holes;
for (const PrintObject *object : print.objects()) {
const BrimType brim_type = object->config().brim_type.value;
const float brim_offset = scale_(object->config().brim_offset.value);
const float brim_width = scale_(object->config().brim_width.value);
const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) {
const PrintObject *object = print.objects()[print_object_idx];
const BrimType brim_type = object->config().brim_type.value;
const float brim_offset = scale_(object->config().brim_offset.value);
const float brim_width = scale_(object->config().brim_width.value);
const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
ExPolygons brim_area_object;
ExPolygons no_brim_area_object;
Polygons holes_object;
for (const ExPolygon &ex_poly : object->layers().front()->lslices) {
for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) {
if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) {
if (top_outer_brim)
no_brim_area_object.emplace_back(ex_poly);
@ -204,7 +236,7 @@ static ExPolygons inner_brim_area(const Print &print, const ConstPrintObjectPtrs
append(holes_object, ex_poly.holes);
}
append(no_brim_area_object, offset_ex(object->layers().front()->lslices, brim_offset));
append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_offset));
for (const PrintInstance &instance : object->instances()) {
append_and_translate(brim_area, brim_area_object, instance);
@ -236,7 +268,7 @@ static void optimize_polylines_by_reversing(Polylines *polylines)
static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_area, float max_connection_length)
{
if (polylines.empty())
return Polylines();
return {};
BoundingBox bbox = get_extents(polylines);
bbox.merge(get_extents(brim_area));
@ -305,16 +337,20 @@ static Polylines connect_brim_lines(Polylines &&polylines, const Polygons &brim_
}
}
if (end < polylines.size())
polylines.erase(polylines.begin() + end, polylines.end());
polylines.erase(polylines.begin() + int(end), polylines.end());
}
return std::move(polylines);
}
static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_level_objects_with_brim, ExtrusionEntityCollection &brim)
static void make_inner_brim(const Print &print,
const ConstPrintObjectPtrs &top_level_objects_with_brim,
const std::vector<ExPolygons> &bottom_layers_expolygons,
ExtrusionEntityCollection &brim)
{
assert(print.objects().size() == bottom_layers_expolygons.size());
Flow flow = print.brim_flow();
ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, float(flow.scaled_spacing()));
ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing()));
Polygons loops;
islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), jtSquare);
for (size_t i = 0; !islands_ex.empty(); ++i) {
@ -334,11 +370,12 @@ static void make_inner_brim(const Print &print, const ConstPrintObjectPtrs &top_
// Collect islands_area to be merged into the final 1st layer convex hull.
ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area)
{
Flow flow = print.brim_flow();
ConstPrintObjectPtrs top_level_objects_with_brim = get_top_level_objects_with_brim(print);
Polygons islands = top_level_outer_brim_islands(top_level_objects_with_brim);
ExPolygons islands_area_ex = top_level_outer_brim_area(print, top_level_objects_with_brim, float(flow.scaled_spacing()));
islands_area = to_polygons(islands_area_ex);
Flow flow = print.brim_flow();
std::vector<ExPolygons> bottom_layers_expolygons = get_print_bottom_layers_expolygons(print);
ConstPrintObjectPtrs top_level_objects_with_brim = get_top_level_objects_with_brim(print, bottom_layers_expolygons);
Polygons islands = top_level_outer_brim_islands(top_level_objects_with_brim);
ExPolygons islands_area_ex = top_level_outer_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing()));
islands_area = to_polygons(islands_area_ex);
Polygons loops;
size_t num_loops = size_t(floor(max_brim_width(print.objects()) / flow.spacing()));
@ -536,7 +573,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
extrusion_entities_append_loops_and_paths(brim.entities, std::move(all_loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
}
make_inner_brim(print, top_level_objects_with_brim, brim);
make_inner_brim(print, top_level_objects_with_brim, bottom_layers_expolygons, brim);
return brim;
}

View file

@ -295,7 +295,7 @@ void PrintConfigDef::init_common_params()
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.2));
def->set_default_value(new ConfigOptionFloat(0.));
// Options used by physical printers
@ -491,10 +491,11 @@ void PrintConfigDef::init_fff_params()
def = this->add("brim_offset", coFloat);
def->label = L("Brim offset");
def->category = L("Skirt and brim");
def->tooltip = L("The offset of the brim from the printed object.");
def->tooltip = L("The offset of the brim from the printed object. The offset is applied after the elephant foot compensation.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0));
def->set_default_value(new ConfigOptionFloat(0.f));
def = this->add("clip_multipart_objects", coBool);
def->label = L("Clip multi-part objects");

View file

@ -58,29 +58,6 @@ T sum_score(AccessFn &&accessfn, size_t facecount, size_t Nthreads)
return execution::reduce(ex_tbb, from, to, initv, mergefn, accessfn, grainsize);
}
// Try to guess the number of support points needed to support a mesh
double get_misalginment_score(const TriangleMesh &mesh, const Transform3f &tr)
{
if (mesh.its.vertices.empty()) return std::nan("");
auto accessfn = [&mesh, &tr](size_t fi) {
auto triangle = get_transformed_triangle(mesh, tr, fi);
Vec3f U = triangle[1] - triangle[0];
Vec3f V = triangle[2] - triangle[0];
Vec3f C = U.cross(V);
// We should score against the alignment with the reference planes
return scaled<int_fast64_t>(std::abs(C.dot(Vec3f::UnitX())) +
std::abs(C.dot(Vec3f::UnitY())));
};
size_t facecount = mesh.its.indices.size();
size_t Nthreads = std::thread::hardware_concurrency();
double S = unscaled(sum_score<int_fast64_t>(accessfn, facecount, Nthreads));
return S / facecount;
}
// Get area and normal of a triangle
struct Facestats {
Vec3f normal;
@ -96,21 +73,45 @@ struct Facestats {
}
};
// Try to guess the number of support points needed to support a mesh
double get_misalginment_score(const TriangleMesh &mesh, const Transform3f &tr)
{
if (mesh.its.vertices.empty()) return std::nan("");
auto accessfn = [&mesh, &tr](size_t fi) {
Facestats fc{get_transformed_triangle(mesh, tr, fi)};
float score = fc.area
* (std::abs(fc.normal.dot(Vec3f::UnitX()))
+ std::abs(fc.normal.dot(Vec3f::UnitY()))
+ std::abs(fc.normal.dot(Vec3f::UnitZ())));
// We should score against the alignment with the reference planes
return scaled<int_fast64_t>(score);
};
size_t facecount = mesh.its.indices.size();
size_t Nthreads = std::thread::hardware_concurrency();
double S = unscaled(sum_score<int_fast64_t>(accessfn, facecount, Nthreads));
return S / facecount;
}
// The score function for a particular face
inline double get_supportedness_score(const Facestats &fc)
{
// Simply get the angle (acos of dot product) between the face normal and
// the DOWN vector.
float phi = 1. - std::acos(fc.normal.dot(DOWN)) / float(PI);
// Only consider faces that have slopes below 90 deg:
phi = phi * (phi >= 0.5f);
float cosphi = fc.normal.dot(DOWN);
float phi = 1.f - std::acos(cosphi) / float(PI);
// Make the huge slopes more significant than the smaller slopes
phi = phi * phi * phi;
// Multiply with the area of the current face
return fc.area * POINTS_PER_UNIT_AREA * phi;
// Multiply with the square root of face area of the current face,
// the area is less important as it grows.
// This makes many smaller overhangs a bigger impact.
return std::sqrt(fc.area) * POINTS_PER_UNIT_AREA * phi;
}
// Try to guess the number of support points needed to support a mesh
@ -120,8 +121,7 @@ double get_supportedness_score(const TriangleMesh &mesh, const Transform3f &tr)
auto accessfn = [&mesh, &tr](size_t fi) {
Facestats fc{get_transformed_triangle(mesh, tr, fi)};
return get_supportedness_score(fc);
return scaled<int_fast64_t>(get_supportedness_score(fc));
};
size_t facecount = mesh.its.indices.size();
@ -164,7 +164,7 @@ float get_supportedness_onfloor_score(const TriangleMesh &mesh,
Facestats fc{tri};
if (tri[0].z() <= zlvl && tri[1].z() <= zlvl && tri[2].z() <= zlvl)
return -fc.area * POINTS_PER_UNIT_AREA;
return -2 * fc.area * POINTS_PER_UNIT_AREA;
return get_supportedness_score(fc);
};
@ -283,6 +283,26 @@ std::array<double, N> find_min_score(Fn &&fn, It from, It to, StopCond &&stopfn)
} // namespace
// Assemble the mesh with the correct transformation to be used in rotation
// optimization.
TriangleMesh get_mesh_to_rotate(const ModelObject &mo)
{
TriangleMesh mesh = mo.raw_mesh();
mesh.require_shared_vertices();
ModelInstance *mi = mo.instances[0];
auto rotation = Vec3d::Zero();
auto offset = Vec3d::Zero();
Transform3d trafo_instance = Geometry::assemble_transform(offset,
rotation,
mi->get_scaling_factor(),
mi->get_mirror());
mesh.transform(trafo_instance);
return mesh;
}
Vec2d find_best_misalignment_rotation(const ModelObject & mo,
const RotOptimizeParams &params)
{
@ -293,8 +313,7 @@ Vec2d find_best_misalignment_rotation(const ModelObject & mo,
// We will use only one instance of this converted mesh to examine different
// rotations
TriangleMesh mesh = mo.raw_mesh();
mesh.require_shared_vertices();
TriangleMesh mesh = get_mesh_to_rotate(mo);
// To keep track of the number of iterations
int status = 0;
@ -326,7 +345,7 @@ Vec2d find_best_misalignment_rotation(const ModelObject & mo,
// We are searching rotations around only two axes x, y. Thus the
// problem becomes a 2 dimensional optimization task.
// We can specify the bounds for a dimension in the following way:
auto bounds = opt::bounds({ {-PI/2, PI/2}, {-PI/2, PI/2} });
auto bounds = opt::bounds({ {-PI, PI}, {-PI, PI} });
auto result = solver.to_max().optimize(
[&mesh, &statusfn] (const XYRotation &rot)
@ -350,8 +369,7 @@ Vec2d find_least_supports_rotation(const ModelObject & mo,
// We will use only one instance of this converted mesh to examine different
// rotations
TriangleMesh mesh = mo.raw_mesh();
mesh.require_shared_vertices();
TriangleMesh mesh = get_mesh_to_rotate(mo);
// To keep track of the number of iterations
unsigned status = 0;

View file

@ -519,7 +519,7 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &hjp,
auto [polar, azimuth] = dir_to_spheric(dir);
polar = PI - m_cfg.bridge_slope;
Vec3d d = spheric_to_dir(polar, azimuth).normalized();
double t = bridge_mesh_distance(endp, dir, radius);
double t = bridge_mesh_distance(endp, d, radius);
double tmax = std::min(m_cfg.max_bridge_length_mm, t);
t = 0.;