diff --git a/xs/src/libslic3r/Surface.cpp b/xs/src/libslic3r/Surface.cpp index 5df2dd99ae..384540d87b 100644 --- a/xs/src/libslic3r/Surface.cpp +++ b/xs/src/libslic3r/Surface.cpp @@ -1,5 +1,6 @@ #include "BoundingBox.hpp" #include "Surface.hpp" +#include "SVG.hpp" namespace Slic3r { @@ -82,4 +83,65 @@ BoundingBox get_extents(const SurfacesPtr &surfaces) return bbox; } +const char* surface_type_to_color_name(const SurfaceType surface_type) +{ + switch (surface_type) { + case stTop: return "rgb(255,0,0)"; // "red"; + case stBottom: return "rgb(0,255,0)"; // "green"; + case stBottomBridge: return "rgb(0,0,255)"; // "blue"; + case stInternal: return "rgb(255,255,128)"; // yellow + case stInternalSolid: return "rgb(255,0,255)"; // magenta + case stInternalBridge: return "rgb(0,255,255)"; + case stInternalVoid: return "rgb(128,128,128)"; + case stPerimeter: return "rgb(128,0,0)"; // maroon + default: return "rgb(64,64,64)"; + }; +} + +Point export_surface_type_legend_to_svg_box_size() +{ + return Point(scale_(1.+10.*8.), scale_(3.)); +} + +void export_surface_type_legend_to_svg(SVG &svg, const Point &pos) +{ + // 1st row + coord_t pos_x0 = pos.x + scale_(1.); + coord_t pos_x = pos_x0; + coord_t pos_y = pos.y + scale_(1.5); + coord_t step_x = scale_(10.); + svg.draw_legend(Point(pos_x, pos_y), "perimeter" , surface_type_to_color_name(stPerimeter)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "top" , surface_type_to_color_name(stTop)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "bottom" , surface_type_to_color_name(stBottom)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "bottom bridge" , surface_type_to_color_name(stBottomBridge)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "invalid" , surface_type_to_color_name(SurfaceType(-1))); + // 2nd row + pos_x = pos_x0; + pos_y = pos.y+scale_(2.8); + svg.draw_legend(Point(pos_x, pos_y), "internal" , surface_type_to_color_name(stInternal)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "internal solid" , surface_type_to_color_name(stInternalSolid)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "internal bridge", surface_type_to_color_name(stInternalBridge)); + pos_x += step_x; + svg.draw_legend(Point(pos_x, pos_y), "internal void" , surface_type_to_color_name(stInternalVoid)); +} + +bool export_to_svg(const char *path, const Surfaces &surfaces, const float transparency) +{ + BoundingBox bbox; + for (Surfaces::const_iterator surface = surfaces.begin(); surface != surfaces.end(); ++surface) + bbox.merge(get_extents(surface->expolygon)); + + SVG svg(path, bbox); + for (Surfaces::const_iterator surface = surfaces.begin(); surface != surfaces.end(); ++surface) + svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency); + svg.Close(); + return true; +} + } diff --git a/xs/src/libslic3r/Surface.hpp b/xs/src/libslic3r/Surface.hpp index 00286c2075..7f2c09dabf 100644 --- a/xs/src/libslic3r/Surface.hpp +++ b/xs/src/libslic3r/Surface.hpp @@ -6,7 +6,7 @@ namespace Slic3r { -enum SurfaceType { stTop, stBottom, stBottomBridge, stInternal, stInternalSolid, stInternalBridge, stInternalVoid }; +enum SurfaceType { stTop, stBottom, stBottomBridge, stInternal, stInternalSolid, stInternalBridge, stInternalVoid, stPerimeter }; class Surface { @@ -34,10 +34,43 @@ class Surface typedef std::vector Surfaces; typedef std::vector SurfacesPtr; +inline Polygons to_polygons(const SurfacesPtr &src) +{ + Polygons polygons; + for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it) { + polygons.push_back((*it)->expolygon.contour); + for (Polygons::const_iterator ith = (*it)->expolygon.holes.begin(); ith != (*it)->expolygon.holes.end(); ++ith) { + polygons.push_back(*ith); + } + } + return polygons; +} + +#if SLIC3R_CPPVER > 11 +inline Polygons to_polygons(SurfacesPtr &&src) +{ + Polygons polygons; + for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++it) { + polygons.push_back(std::move((*it)->expolygon.contour)); + for (Polygons::const_iterator ith = (*it)->expolygon.holes.begin(); ith != (*it)->expolygon.holes.end(); ++ith) { + polygons.push_back(std::move(*ith)); + } + } + return polygons; +} +#endif + extern BoundingBox get_extents(const Surface &surface); extern BoundingBox get_extents(const Surfaces &surfaces); extern BoundingBox get_extents(const SurfacesPtr &surfaces); +class SVG; + +extern const char* surface_type_to_color_name(const SurfaceType surface_type); +extern void export_surface_type_legend_to_svg(SVG &svg, const Point &pos); +extern Point export_surface_type_legend_to_svg_box_size(); +extern bool export_to_svg(const char *path, const Surfaces &surfaces, const float transparency = 1.f); + } #endif diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp index 21e6eb0cc4..5fbb913b1b 100644 --- a/xs/src/libslic3r/SurfaceCollection.cpp +++ b/xs/src/libslic3r/SurfaceCollection.cpp @@ -91,7 +91,7 @@ SurfaceCollection::any_bottom_contains(const T &item) const template bool SurfaceCollection::any_bottom_contains(const Polyline &item) const; SurfacesPtr -SurfaceCollection::filter_by_type(SurfaceType type) +SurfaceCollection::filter_by_type(const SurfaceType type) { SurfacesPtr ss; for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { @@ -100,6 +100,21 @@ SurfaceCollection::filter_by_type(SurfaceType type) return ss; } +SurfacesPtr +SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) +{ + SurfacesPtr ss; + for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { + for (int i = 0; i < ntypes; ++ i) { + if (surface->surface_type == types[i]) { + ss.push_back(&*surface); + break; + } + } + } + return ss; +} + void SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons) { @@ -111,10 +126,91 @@ SurfaceCollection::filter_by_type(SurfaceType type, Polygons* polygons) } } +void +SurfaceCollection::keep_type(const SurfaceType type) +{ + size_t j = 0; + for (size_t i = 0; i < surfaces.size(); ++ i) { + if (surfaces[i].surface_type == type) { + if (j < i) + std::swap(surfaces[i], surfaces[j]); + ++ j; + } + } + if (j < surfaces.size()) + surfaces.erase(surfaces.begin() + j, surfaces.end()); +} + +void +SurfaceCollection::keep_types(const SurfaceType *types, int ntypes) +{ + size_t j = 0; + for (size_t i = 0; i < surfaces.size(); ++ i) { + bool keep = false; + for (int k = 0; k < ntypes; ++ k) { + if (surfaces[i].surface_type == types[k]) { + keep = true; + break; + } + } + if (keep) { + if (j < i) + std::swap(surfaces[i], surfaces[j]); + ++ j; + } + } + if (j < surfaces.size()) + surfaces.erase(surfaces.begin() + j, surfaces.end()); +} + +void +SurfaceCollection::remove_type(const SurfaceType type) +{ + size_t j = 0; + for (size_t i = 0; i < surfaces.size(); ++ i) { + if (surfaces[i].surface_type != type) { + if (j < i) + std::swap(surfaces[i], surfaces[j]); + ++ j; + } + } + if (j < surfaces.size()) + surfaces.erase(surfaces.begin() + j, surfaces.end()); +} + +void +SurfaceCollection::remove_types(const SurfaceType *types, int ntypes) +{ + size_t j = 0; + for (size_t i = 0; i < surfaces.size(); ++ i) { + bool remove = false; + for (int k = 0; k < ntypes; ++ k) { + if (surfaces[i].surface_type == types[k]) { + remove = true; + break; + } + } + if (! remove) { + if (j < i) + std::swap(surfaces[i], surfaces[j]); + ++ j; + } + } + if (j < surfaces.size()) + surfaces.erase(surfaces.begin() + j, surfaces.end()); +} + void SurfaceCollection::append(const SurfaceCollection &coll) { this->surfaces.insert(this->surfaces.end(), coll.surfaces.begin(), coll.surfaces.end()); } +void +SurfaceCollection::append(const SurfaceType surfaceType, const Slic3r::ExPolygons &expoly) +{ + for (Slic3r::ExPolygons::const_iterator it = expoly.begin(); it != expoly.end(); ++ it) + this->surfaces.push_back(Slic3r::Surface(surfaceType, *it)); +} + } diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/xs/src/libslic3r/SurfaceCollection.hpp index a4a3a7e5d4..07d0b00299 100644 --- a/xs/src/libslic3r/SurfaceCollection.hpp +++ b/xs/src/libslic3r/SurfaceCollection.hpp @@ -21,9 +21,15 @@ class SurfaceCollection void group(std::vector *retval); template bool any_internal_contains(const T &item) const; template bool any_bottom_contains(const T &item) const; - SurfacesPtr filter_by_type(SurfaceType type); + SurfacesPtr filter_by_type(const SurfaceType type); + SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes); + void keep_type(const SurfaceType type); + void keep_types(const SurfaceType *types, int ntypes); + void remove_type(const SurfaceType type); + void remove_types(const SurfaceType *types, int ntypes); void filter_by_type(SurfaceType type, Polygons* polygons); void append(const SurfaceCollection &coll); + void append(const SurfaceType surfaceType, const Slic3r::ExPolygons &expoly); }; } diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h index 680716bb8d..00e4ef90dd 100644 --- a/xs/src/libslic3r/libslic3r.h +++ b/xs/src/libslic3r/libslic3r.h @@ -5,6 +5,7 @@ #include #include #include +#include #define SLIC3R_VERSION "1.3.0-dev" @@ -26,7 +27,9 @@ // Maximum perimeter length for the loop to apply the small perimeter speed. #define SMALL_PERIMETER_LENGTH (6.5 / SCALING_FACTOR) * 2 * PI #define INSET_OVERLAP_TOLERANCE 0.4 -#define EXTERNAL_INFILL_MARGIN 3 +// 3mm ring around the top / bottom / bridging areas. +//FIXME This is quite a lot. +#define EXTERNAL_INFILL_MARGIN 3. #define scale_(val) ((val) / SCALING_FACTOR) #define unscale(val) ((val) * SCALING_FACTOR) #define SCALED_EPSILON scale_(EPSILON)