diff --git a/xs/src/libslic3r/SVG.cpp b/xs/src/libslic3r/SVG.cpp index 328d5421a..f196d4713 100644 --- a/xs/src/libslic3r/SVG.cpp +++ b/xs/src/libslic3r/SVG.cpp @@ -32,9 +32,17 @@ SVG::draw(const Line &line, std::string stroke) } void -SVG::AddLine(const IntersectionLine &line) +SVG::draw(const Lines &lines, std::string stroke) { - this->draw(Line(line.a, line.b)); + for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it) + this->draw(*it, stroke); +} + +void +SVG::draw(const IntersectionLines &lines, std::string stroke) +{ + for (IntersectionLines::const_iterator it = lines.begin(); it != lines.end(); ++it) + this->draw((Line)*it, stroke); } void @@ -50,11 +58,25 @@ SVG::draw(const ExPolygon &expolygon, std::string fill) this->path(d, true); } +void +SVG::draw(const ExPolygons &expolygons, std::string fill) +{ + for (ExPolygons::const_iterator it = expolygons.begin(); it != expolygons.end(); ++it) + this->draw(*it, fill); +} + void SVG::draw(const Polygon &polygon, std::string fill) { this->fill = fill; - this->path(this->get_path_d(polygon, true), true); + this->path(this->get_path_d(polygon, true), !fill.empty()); +} + +void +SVG::draw(const Polygons &polygons, std::string fill) +{ + for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) + this->draw(*it, fill); } void @@ -64,6 +86,13 @@ SVG::draw(const Polyline &polyline, std::string stroke) this->path(this->get_path_d(polyline, false), false); } +void +SVG::draw(const Polylines &polylines, std::string stroke) +{ + for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it) + this->draw(*it, fill); +} + void SVG::draw(const Point &point, std::string fill, unsigned int radius) { @@ -75,6 +104,13 @@ SVG::draw(const Point &point, std::string fill, unsigned int radius) fprintf(this->f, "%s\n", svg.str().c_str()); } +void +SVG::draw(const Points &points, std::string fill, unsigned int radius) +{ + for (Points::const_iterator it = points.begin(); it != points.end(); ++it) + this->draw(*it, fill, radius); +} + void SVG::path(const std::string &d, bool fill) { diff --git a/xs/src/libslic3r/SVG.hpp b/xs/src/libslic3r/SVG.hpp index bb0d5adcf..cbc546402 100644 --- a/xs/src/libslic3r/SVG.hpp +++ b/xs/src/libslic3r/SVG.hpp @@ -15,12 +15,17 @@ class SVG std::string fill, stroke; SVG(const char* filename); - void AddLine(const IntersectionLine &line); void draw(const Line &line, std::string stroke = "black"); + void draw(const Lines &lines, std::string stroke = "black"); + void draw(const IntersectionLines &lines, std::string stroke = "black"); void draw(const ExPolygon &expolygon, std::string fill = "grey"); + void draw(const ExPolygons &expolygons, std::string fill = "grey"); void draw(const Polygon &polygon, std::string fill = "grey"); + void draw(const Polygons &polygons, std::string fill = "grey"); void draw(const Polyline &polyline, std::string stroke = "black"); + void draw(const Polylines &polylines, std::string stroke = "black"); void draw(const Point &point, std::string fill = "black", unsigned int radius = 3); + void draw(const Points &points, std::string fill = "black", unsigned int radius = 3); void Close(); private: diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index 89116f17b..b25df7e0e 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -181,6 +181,7 @@ TriangleMesh::WriteOBJFile(char* output_file) { void TriangleMesh::scale(float factor) { stl_scale(&(this->stl), factor); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::scale(const Pointf3 &versor) @@ -190,41 +191,49 @@ void TriangleMesh::scale(const Pointf3 &versor) fversor[1] = versor.y; fversor[2] = versor.z; stl_scale_versor(&this->stl, fversor); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::translate(float x, float y, float z) { stl_translate_relative(&(this->stl), x, y, z); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::rotate_x(float angle) { stl_rotate_x(&(this->stl), angle); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::rotate_y(float angle) { stl_rotate_y(&(this->stl), angle); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::rotate_z(float angle) { stl_rotate_z(&(this->stl), angle); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::flip_x() { stl_mirror_yz(&this->stl); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::flip_y() { stl_mirror_xz(&this->stl); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::flip_z() { stl_mirror_xy(&this->stl); + stl_invalidate_shared_vertices(&this->stl); } void TriangleMesh::align_to_origin() @@ -507,7 +516,7 @@ TriangleMeshSlicer::slice(const std::vector &z, std::vector* for (std::vector::const_iterator loops = layers_p.begin(); loops != layers_p.end(); ++loops) { #ifdef SLIC3R_DEBUG size_t layer_id = loops - layers_p.begin(); - printf("Layer %zu (slice_z = %.2f): ", layer_id, z[layer_id]); + printf("Layer %zu (slice_z = %.2f):\n", layer_id, z[layer_id]); #endif this->make_expolygons(*loops, &(*layers)[ loops - layers_p.begin() ]); @@ -542,15 +551,19 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int if (a->z == b->z && a->z == slice_z) { // edge is horizontal and belongs to the current layer - /* We assume that this method is never being called for horizontal - facets, so no other edge is going to be on this layer. */ - stl_vertex* v0 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ]; - stl_vertex* v1 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ]; - stl_vertex* v2 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ]; + stl_vertex &v0 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ]; + stl_vertex &v1 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ]; + stl_vertex &v2 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ]; IntersectionLine line; if (min_z == max_z) { line.edge_type = feHorizontal; - } else if (v0->z < slice_z || v1->z < slice_z || v2->z < slice_z) { + if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) { + /* if normal points downwards this is a bottom horizontal facet so we reverse + its point order */ + std::swap(a, b); + std::swap(a_id, b_id); + } + } else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) { line.edge_type = feTop; std::swap(a, b); std::swap(a_id, b_id); @@ -624,12 +637,9 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int void TriangleMeshSlicer::make_loops(std::vector &lines, Polygons* loops) { - /* SVG svg("lines.svg"); - for (IntersectionLines::iterator line = lines.begin(); line != lines.end(); ++line) { - svg.AddLine(*line); - } + svg.draw(lines); svg.Close(); */ @@ -837,9 +847,9 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices) of the loops, since the Orientation() function provided by Clipper would do the same, thus repeating the calculation */ Polygons::const_iterator loop = loops.begin() + *loop_idx; - if (area[*loop_idx] >= 0) { + if (area[*loop_idx] > +EPSILON) { p_slices.push_back(*loop); - } else { + } else if (area[*loop_idx] < -EPSILON) { diff(p_slices, *loop, &p_slices); } } diff --git a/xs/t/01_trianglemesh.t b/xs/t/01_trianglemesh.t index b2f1d2849..cc140aa5a 100644 --- a/xs/t/01_trianglemesh.t +++ b/xs/t/01_trianglemesh.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 46; +use Test::More tests => 49; is Slic3r::TriangleMesh::hello_world(), 'Hello world!', 'hello world'; @@ -79,7 +79,7 @@ my $cube = { my $m = Slic3r::TriangleMesh->new; $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); $m->repair; - my @z = (2,4,8,6,8,10,12,14,16,18,20); + my @z = (0,2,4,8,6,8,10,12,14,16,18,20); my $result = $m->slice(\@z); my $SCALING_FACTOR = 0.000001; for my $i (0..$#z) { @@ -95,8 +95,19 @@ my $cube = { [ [0,1,2],[2,1,3],[1,0,4],[5,1,4],[0,2,4],[4,2,6],[7,6,8],[4,6,7],[9,4,7],[7,8,10],[2,3,6],[11,3,12],[7,12,9],[13,12,7],[6,3,11],[11,12,13],[3,1,5],[12,3,5],[5,4,9],[12,5,9],[13,7,10],[14,13,10],[8,15,10],[10,15,14],[6,11,8],[8,11,15],[15,11,13],[14,15,13] ], ); $m->repair; - my $slices = $m->slice([ 5, 10 ]); - is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a tangent plane includes its area'; + { + # at Z = 10 we have a top horizontal surface + my $slices = $m->slice([ 5, 10 ]); + is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a top tangent plane includes its area'; + } + $m->flip_z; + { + # this second test also checks that performing a second slice on a mesh after + # a transformation works properly (shared_vertices is correctly invalidated); + # at Z = -10 we have a bottom horizontal surface + my $slices = $m->slice([ -5, -10 ]); + is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a bottom tangent plane includes its area'; + } } {