diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp index 6b5991acd..5cc143540 100644 --- a/xs/src/libslic3r/ClipperUtils.cpp +++ b/xs/src/libslic3r/ClipperUtils.cpp @@ -709,7 +709,7 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, PolyTreeToExPolygons(polytree, retval); } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, +void _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_) { PROFILE_FUNC(); @@ -723,7 +723,7 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, ClipperPaths_to_Slic3rMultiPoints(output, retval); } -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, +void _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_) { // convert Lines to Polylines @@ -733,7 +733,7 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, polylines.push_back(*line); // perform operation - _clipper(clipType, polylines, clip, &polylines, safety_offset_); + _clipper_pl(clipType, polylines, clip, &polylines, safety_offset_); // convert Polylines to Lines for (Slic3r::Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) @@ -750,7 +750,7 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, polylines.push_back(*polygon); // implicit call to split_at_first_point() // perform clipping - _clipper(clipType, polylines, clip, retval, safety_offset_); + _clipper_pl(clipType, polylines, clip, retval, safety_offset_); /* If the split_at_first_point() call above happens to split the polygon inside the clipping area we would get two consecutive polylines instead of a single one, so we go through them in order @@ -796,8 +796,6 @@ void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); template void diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void diff(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_); template void diff(const SubjectType &subject, const Slic3r::ExPolygons &clip, ResultType* retval, bool safety_offset_) @@ -850,8 +848,6 @@ void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, Resu template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); template void intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); -template void intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_); template SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_) diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/xs/src/libslic3r/ClipperUtils.hpp index 783453807..8efebdfad 100644 --- a/xs/src/libslic3r/ClipperUtils.hpp +++ b/xs/src/libslic3r/ClipperUtils.hpp @@ -105,10 +105,10 @@ void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::Polygons* retval, bool safety_offset_); void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_); -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, - const Slic3r::Polygons &clip, Slic3r::Polylines* retval); -void _clipper(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, - const Slic3r::Polygons &clip, Slic3r::Lines* retval); +void _clipper_pl(ClipperLib::ClipType clipType, const Slic3r::Polylines &subject, + const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_); +void _clipper_ln(ClipperLib::ClipType clipType, const Slic3r::Lines &subject, + const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_); template void diff(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); @@ -121,9 +121,29 @@ Slic3r::Polygons diff(const Slic3r::Polygons &subject, const Slic3r::Polygons &c template Slic3r::ExPolygons diff_ex(const SubjectType &subject, const ClipType &clip, bool safety_offset_ = false); +inline void diff(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false) +{ + _clipper_pl(ClipperLib::ctDifference, subject, clip, retval, safety_offset_); +} + +inline void diff(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false) +{ + _clipper_ln(ClipperLib::ctDifference, subject, clip, retval, safety_offset_); +} + template void intersection(const SubjectType &subject, const Slic3r::Polygons &clip, ResultType* retval, bool safety_offset_ = false); +inline void intersection(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, Slic3r::Polylines* retval, bool safety_offset_ = false) +{ + _clipper_pl(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_); +} + +inline void intersection(const Slic3r::Lines &subject, const Slic3r::Polygons &clip, Slic3r::Lines* retval, bool safety_offset_ = false) +{ + _clipper_ln(ClipperLib::ctIntersection, subject, clip, retval, safety_offset_); +} + template SubjectType intersection(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); @@ -133,6 +153,14 @@ intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, b template bool intersects(const SubjectType &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false); +inline Slic3r::Polylines +intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip, bool safety_offset_ = false) +{ + Slic3r::Polylines polylines_out; + _clipper_pl(ClipperLib::ctIntersection, subject, clip, &polylines_out, safety_offset_); + return polylines_out; +} + void xor_(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, Slic3r::ExPolygons* retval, bool safety_offset_ = false); diff --git a/xs/src/libslic3r/ExtrusionSimulator.cpp b/xs/src/libslic3r/ExtrusionSimulator.cpp index 0c86f073e..3752caed4 100644 --- a/xs/src/libslic3r/ExtrusionSimulator.cpp +++ b/xs/src/libslic3r/ExtrusionSimulator.cpp @@ -803,7 +803,7 @@ void gcode_spread_points( const Cell &cell = cells[i]; acc[cell.idx.y()][cell.idx.x()] = (1.f - cell.fraction_covered) * cell.volume + cell.fraction_covered * cell.area * height_avg; } - } else if (simulationType == ExtrusionSimulationSpreadExcess) { + } else if (simulationType == Slic3r::ExtrusionSimulationSpreadExcess) { // The volume under the circle does not fit. // 1) Fill the underfilled cells and remove them from the list. float volume_borrowed_total = 0.; diff --git a/xs/src/libslic3r/ExtrusionSimulator.hpp b/xs/src/libslic3r/ExtrusionSimulator.hpp index 8b956ec11..040406766 100644 --- a/xs/src/libslic3r/ExtrusionSimulator.hpp +++ b/xs/src/libslic3r/ExtrusionSimulator.hpp @@ -13,7 +13,7 @@ enum ExtrusionSimulationType ExtrusionSimulationDontSpread, ExtrisopmSimulationSpreadNotOverfilled, ExtrusionSimulationSpreadFull, - ExtrusionSimulationSpreadExcess, + ExtrusionSimulationSpreadExcess }; // An opaque class, to keep the boost stuff away from the header. diff --git a/xs/src/libslic3r/Layer.hpp b/xs/src/libslic3r/Layer.hpp index e59f0c9e1..a5ba3f804 100644 --- a/xs/src/libslic3r/Layer.hpp +++ b/xs/src/libslic3r/Layer.hpp @@ -11,9 +11,6 @@ namespace Slic3r { -typedef std::pair t_layer_height_range; -typedef std::map t_layer_height_ranges; - class Layer; class PrintRegion; class PrintObject; diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index b2a9d0b53..963bd7c85 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -6,6 +6,7 @@ #include "Layer.hpp" #include "Point.hpp" #include "TriangleMesh.hpp" +#include "Slicing.hpp" #include #include #include diff --git a/xs/src/libslic3r/Polygon.hpp b/xs/src/libslic3r/Polygon.hpp index c2ffa959c..b0a7ea40a 100644 --- a/xs/src/libslic3r/Polygon.hpp +++ b/xs/src/libslic3r/Polygon.hpp @@ -178,7 +178,7 @@ namespace boost { namespace polygon { static inline Slic3r::Polygon& set_points(Slic3r::Polygon& polygon, iT input_begin, iT input_end) { polygon.points.clear(); while (input_begin != input_end) { - polygon.points.push_back(Point()); + polygon.points.push_back(Slic3r::Point()); boost::polygon::assign(polygon.points.back(), *input_begin); ++input_begin; } diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 132e7d0df..3a5d38ec3 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -154,7 +154,7 @@ private: // TODO: call model_object->get_bounding_box() instead of accepting // parameter PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox); - ~PrintObject(); + ~PrintObject() {} }; typedef std::vector PrintObjectPtrs; diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index b276744c4..7b5014414 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -974,7 +974,7 @@ PrintObject::_make_perimeters() // check whether a portion of the upper slices falls inside the critical area const Polylines intersection = intersection_pl( - upper_layerm_polygons, + to_polylines(upper_layerm_polygons), critical_area ); diff --git a/xs/src/libslic3r/Slicing.hpp b/xs/src/libslic3r/Slicing.hpp new file mode 100644 index 000000000..5e910c672 --- /dev/null +++ b/xs/src/libslic3r/Slicing.hpp @@ -0,0 +1,44 @@ +// Based on implementation by @platsch + +#ifndef slic3r_Slicing_hpp_ +#define slic3r_Slicing_hpp_ + +#include "libslic3r.h" + +namespace Slic3r +{ + +struct SlicingParameters +{ + SlicingParameters() { memset(this, 0, sizeof(SlicingParameters)); } + + // The regular layer height, applied for all but the first layer, if not overridden by layer ranges + // or by the variable layer thickness table. + coordf_t layer_height; + + // Thickness of the first layer. This is either the first print layer thickness if printed without a raft, + // or a bridging flow thickness if printed over a non-soluble raft, + // or a normal layer height if printed over a soluble raft. + coordf_t first_layer_height; + + // If the object is printed over a non-soluble raft, the first layer may be printed with a briding flow. + bool first_layer_bridging; + + // Minimum / maximum layer height, to be used for the automatic adaptive layer height algorithm, + // or by an interactive layer height editor. + coordf_t min_layer_height; + coordf_t max_layer_height; + + // Bottom and top of the printed object. + // If printed without a raft, object_print_z_min = 0 and object_print_z_max = object height. + // Otherwise object_print_z_min is equal to the raft height. + coordf_t object_print_z_min; + coordf_t object_print_z_max; +}; + +typedef std::pair t_layer_height_range; +typedef std::map t_layer_height_ranges; + +}; // namespace Slic3r + +#endif /* slic3r_Slicing_hpp_ */ diff --git a/xs/src/libslic3r/SlicingAdaptive.cpp b/xs/src/libslic3r/SlicingAdaptive.cpp new file mode 100644 index 000000000..b7f116770 --- /dev/null +++ b/xs/src/libslic3r/SlicingAdaptive.cpp @@ -0,0 +1,149 @@ +#include "libslic3r.h" +#include "TriangleMesh.hpp" +#include "SlicingAdaptive.hpp" + +namespace Slic3r +{ + +void SlicingAdaptive::clear() +{ + m_meshes.clear(); + m_faces.clear(); + m_face_normal_z.clear(); +} + +std::pair face_z_span(const stl_facet *f) +{ + return std::pair( + std::min(std::min(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z), + std::max(std::max(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z)); +} + +void SlicingAdaptive::prepare() +{ + // 1) Collect faces of all meshes. + { + int nfaces_total = 0; + for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) + nfaces_total += (*it_mesh)->stl.stats.number_of_facets; + m_faces.reserve(nfaces_total); + } + m_max_z = 0; + for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) { + const stl_facet *faces = (*it_mesh)->stl.facet_start; + int nfaces = (*it_mesh)->stl.stats.number_of_facets; + for (int i = 0; i < nfaces; ++ i) { + const stl_facet *facet = faces + i; + m_faces.push_back(facet); + m_max_z = std::max(std::max(m_max_z, facet->vertex[0].z), std::max(facet->vertex[1].z, facet->vertex[2].z)); + } + } + + // 2) Sort faces lexicographically by their Z span. + std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { + std::pair span1 = face_z_span(f1); + std::pair span2 = face_z_span(f2); + return span1 < span2; + }); + + // 3) Generate Z components of the facet normals. + m_face_normal_z.assign(m_faces.size(), 0.f); + for (size_t iface = 0; iface < m_faces.size(); ++ iface) + m_face_normal_z[iface] = m_faces[iface]->normal.z; +} + +float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet) +{ + float height = m_layer_height_max; + bool first_hit = false; + + // find all facets intersecting the slice-layer + int ordered_id = current_facet; + for (; ordered_id < int(m_faces.size()); ++ ordered_id) { + std::pair zspan = face_z_span(m_faces[ordered_id]); + // facet's minimum is higher than slice_z -> end loop + if (zspan.first >= z) + break; + // facet's maximum is higher than slice_z -> store the first event for next cusp_height call to begin at this point + if (zspan.second > z) { + // first event? + if (! first_hit) { + first_hit = true; + current_facet = ordered_id; + } + // skip touching facets which could otherwise cause small cusp values + if (zspan.second <= z + EPSILON) + continue; + // compute cusp-height for this facet and store minimum of all heights + float normal_z = m_face_normal_z[ordered_id]; + height = std::min(height, (normal_z == 0) ? 9999 : abs(cusp_value / normal_z)); + } + } + + // lower height limit due to printer capabilities + height = std::max(height, m_layer_height_min); + + // check for sloped facets inside the determined layer and correct height if necessary + if (height > m_layer_height_min) { + for (; ordered_id < int(m_faces.size()); ++ ordered_id) { + std::pair zspan = face_z_span(m_faces[ordered_id]); + // facet's minimum is higher than slice_z + height -> end loop + if (zspan.first >= z + height) + break; + + // skip touching facets which could otherwise cause small cusp values + if (zspan.second <= z + EPSILON) + continue; + + // Compute cusp-height for this facet and check against height. + float normal_z = m_face_normal_z[ordered_id]; + float cusp = (normal_z == 0) ? 9999 : abs(cusp_value / normal_z); + + float z_diff = zspan.first - z; + + // handle horizontal facets + if (m_face_normal_z[ordered_id] > 0.999) { + // Slic3r::debugf "cusp computation, height is reduced from %f", $height; + height = z_diff; + // Slic3r::debugf "to %f due to near horizontal facet\n", $height; + } else if (cusp > z_diff) { + if (cusp < height) { + // Slic3r::debugf "cusp computation, height is reduced from %f", $height; + height = cusp; + // Slic3r::debugf "to %f due to new cusp height\n", $height; + } + } else { + // Slic3r::debugf "cusp computation, height is reduced from %f", $height; + height = z_diff; + // Slic3r::debugf "to z-diff: %f\n", $height; + } + } + // lower height limit due to printer capabilities again + height = std::max(height, m_layer_height_min); + } + +// Slic3r::debugf "cusp computation, layer-bottom at z:%f, cusp_value:%f, resulting layer height:%f\n", unscale $z, $cusp_value, $height; + return height; +} + +// Returns the distance to the next horizontal facet in Z-dir +// to consider horizontal object features in slice thickness +float SlicingAdaptive::horizontal_facet_distance(float z) +{ + for (size_t i = 0; i < m_faces.size(); ++ i) { + std::pair zspan = face_z_span(m_faces[i]); + // facet's minimum is higher than max forward distance -> end loop + if (zspan.first > z + m_layer_height_max) + break; + // min_z == max_z -> horizontal facet + if (zspan.first > z && zspan.first == zspan.second) + return zspan.first - z; + } + + // objects maximum? + return (z + m_layer_height_max > m_max_z) ? + std::max(m_max_z - z, 0.f) : + m_layer_height_max; +} + +}; // namespace Slic3r diff --git a/xs/src/libslic3r/SlicingAdaptive.hpp b/xs/src/libslic3r/SlicingAdaptive.hpp new file mode 100644 index 000000000..23e8f4b62 --- /dev/null +++ b/xs/src/libslic3r/SlicingAdaptive.hpp @@ -0,0 +1,38 @@ +// Based on implementation by @platsch + +#ifndef slic3r_SlicingAdaptive_hpp_ +#define slic3r_SlicingAdaptive_hpp_ + +#include "Slicing.hpp" +#include "admesh/stl.h" + +namespace Slic3r +{ + +class TriangleMesh; + +class SlicingAdaptive +{ +public: + void clear(); + void set_layer_height_range(float min, float max) { m_layer_height_min = min; m_layer_height_max = max; } + void add_mesh(const TriangleMesh *mesh) { m_meshes.push_back(mesh); } + void prepare(); + float cusp_height(float z, float cusp_value, int ¤t_facet); + float horizontal_facet_distance(float z); + +protected: + float m_layer_height_min; + float m_layer_height_max; + float m_max_z; + + std::vector m_meshes; + // Collected faces of all meshes, sorted by raising Z of the bottom most face. + std::vector m_faces; + // Z component of face normals, normalized. + std::vector m_face_normal_z; +}; + +}; // namespace Slic3r + +#endif /* slic3r_SlicingAdaptive_hpp_ */ diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp index 835dea79d..47ce5d6db 100644 --- a/xs/src/libslic3r/SupportMaterial.cpp +++ b/xs/src/libslic3r/SupportMaterial.cpp @@ -8,7 +8,6 @@ #include "EdgeGrid.hpp" #include -#include #include #include #include @@ -21,6 +20,8 @@ #include "SVG.hpp" #endif +#include + namespace Slic3r { // Increment used to reach MARGIN in steps to avoid trespassing thin objects diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index b7c729406..eafdf1522 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -163,4 +163,6 @@ SV* polynode2perl(const ClipperLib::PolyNode& node); #endif #endif +using namespace Slic3r; + #endif