diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index 9dc3235db..ff135adf8 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -170,14 +170,14 @@ TriangleMesh::slice(const std::vector &z) typedef std::vector t_edges; // edge_idx => a_id,b_id typedef std::map t_edges_map; // a_id,b_id => edge_idx typedef std::vector< std::vector > t_facets_edges; - t_edges edges; t_facets_edges facets_edges; - // reserve() instad of resize() because otherwise we couldn't read .size() below to assign edge_idx - edges.reserve(this->stl.stats.number_of_facets * 3); // number of edges = number of facets * 3 facets_edges.resize(this->stl.stats.number_of_facets); { + t_edges edges; + // reserve() instad of resize() because otherwise we couldn't read .size() below to assign edge_idx + edges.reserve(this->stl.stats.number_of_facets * 3); // number of edges = number of facets * 3 t_edges_map edges_map; for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { facets_edges[facet_idx].resize(3); @@ -238,6 +238,7 @@ TriangleMesh::slice(const std::vector &z) double slice_z = *it; std::vector points; std::vector< std::vector::size_type > points_on_layer, intersection_points; + bool found_horizontal_edge = false; /* reorder vertices so that the first one is the one with lowest Z this is needed to get all intersection lines in a consistent order @@ -252,10 +253,10 @@ TriangleMesh::slice(const std::vector &z) } for (int j = i; (j-i) < 3; j++) { // loop through facet edges int edge_id = facets_edges[facet_idx][j % 3]; - t_edge edge = edges[edge_id]; - - stl_vertex* a = &(this->stl.v_shared[edge.first]); - stl_vertex* b = &(this->stl.v_shared[edge.second]); + int a_id = this->stl.v_indices[facet_idx].vertex[j % 3]; + int b_id = this->stl.v_indices[facet_idx].vertex[(j+1) % 3]; + stl_vertex* a = &(this->stl.v_shared[a_id]); + stl_vertex* b = &(this->stl.v_shared[b_id]); if (a->z == b->z && a->z == slice_z) { // edge is horizontal and belongs to the current layer @@ -266,21 +267,25 @@ TriangleMesh::slice(const std::vector &z) /* We assume that this method is never being called for horizontal facets, so no other edge is going to be on this layer. */ IntersectionLine line; - line.a.x = a->x; - line.a.y = a->y; - line.b.x = b->x; - line.b.y = b->y; - line.a_id = edge.first; - line.b_id = edge.second; - if (this->stl.v_indices[facet_idx].vertex[0] < slice_z || this->stl.v_indices[facet_idx].vertex[1] < slice_z || this->stl.v_indices[facet_idx].vertex[2] < slice_z) { line.edge_type = feTop; + std::swap(a, b); + std::swap(a_id, b_id); } else { line.edge_type = feBottom; } + line.a.x = a->x; + line.a.y = a->y; + line.b.x = b->x; + line.b.y = b->y; + line.a_id = a_id; + line.b_id = b_id; + lines[layer_idx].push_back(line); + found_horizontal_edge = true; + break; } else if (a->z == slice_z) { #ifdef SLIC3R_DEBUG printf("A point on plane!\n"); @@ -289,7 +294,7 @@ TriangleMesh::slice(const std::vector &z) IntersectionPoint point; point.x = a->x; point.y = a->y; - point.point_id = edge.first; + point.point_id = a_id; points.push_back(point); points_on_layer.push_back(points.size()-1); } else if (b->z == slice_z) { @@ -300,7 +305,7 @@ TriangleMesh::slice(const std::vector &z) IntersectionPoint point; point.x = b->x; point.y = b->y; - point.point_id = edge.second; + point.point_id = b_id; points.push_back(point); points_on_layer.push_back(points.size()-1); } else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) { @@ -317,18 +322,20 @@ TriangleMesh::slice(const std::vector &z) intersection_points.push_back(points.size()-1); } } + if (found_horizontal_edge) continue; if (points_on_layer.size() == 2) { if (intersection_points.size() == 1) { points.erase( points.begin() + points_on_layer[1] ); } else if (intersection_points.empty()) { - if (points[ points_on_layer[0] ].coincides_with(&points[ points_on_layer[1] ])) continue; + if (points[ points_on_layer[0] ].coincides_with(&points[ points_on_layer[1] ])) { + continue; + } } } if (!points.empty()) { assert(points.size() == 2); // facets must intersect each plane 0 or 2 times - IntersectionLine line; line.a.x = points[1].x; line.a.y = points[1].y; @@ -349,12 +356,12 @@ TriangleMesh::slice(const std::vector &z) int layer_idx = it - lines.begin(); // remove tangent edges - for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { + for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) { if (line->skip || line->edge_type == feNone) continue; /* if the line is a facet edge, find another facet edge having the same endpoints but in reverse order */ - for (IntersectionLines::iterator line2 = line + 1; line2 != (*it).end(); ++line2) { + for (IntersectionLines::iterator line2 = line + 1; line2 != it->end(); ++line2) { if (line2->skip || line2->edge_type == feNone) continue; // are these facets adjacent? (sharing a common edge on this layer) @@ -377,9 +384,9 @@ TriangleMesh::slice(const std::vector &z) // build a map of lines by edge_a_id and a_id std::vector by_edge_a_id, by_a_id; - by_edge_a_id.resize(edges.size()); + by_edge_a_id.resize(this->stl.stats.number_of_facets * 3); by_a_id.resize(this->stl.stats.shared_vertices); - for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { + for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) { if (line->skip) continue; if (line->edge_a_id != -1) by_edge_a_id[line->edge_a_id].push_back(&(*line)); if (line->a_id != -1) by_a_id[line->a_id].push_back(&(*line)); @@ -388,7 +395,7 @@ TriangleMesh::slice(const std::vector &z) CYCLE: while (1) { // take first spare line and start a new loop IntersectionLine* first_line = NULL; - for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { + for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) { if (line->skip) continue; first_line = &(*line); break; @@ -398,6 +405,12 @@ TriangleMesh::slice(const std::vector &z) IntersectionLinePtrs loop; loop.push_back(first_line); + /* + printf("first_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n", + first_line->edge_a_id, first_line->edge_b_id, first_line->a_id, first_line->b_id, + first_line->a.x, first_line->a.y, first_line->b.x, first_line->b.y); + */ + while (1) { // find a line starting where last one finishes IntersectionLine* next_line = NULL; @@ -441,6 +454,11 @@ TriangleMesh::slice(const std::vector &z) //// push @failed_loops, [@loop]; goto CYCLE; } + /* + printf("next_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n", + next_line->edge_a_id, next_line->edge_b_id, next_line->a_id, next_line->b_id, + next_line->a.x, next_line->a.y, next_line->b.x, next_line->b.y); + */ loop.push_back(next_line); next_line->skip = true; } diff --git a/xs/t/01_trianglemesh.t b/xs/t/01_trianglemesh.t index 42c42ad98..32d189826 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 => 10; +use Test::More tests => 43; is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!', 'hello world'; @@ -44,7 +44,7 @@ my $cube = { ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate'; } -if (0) { +{ my $m = Slic3r::TriangleMesh::XS->new; $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); $m->Repair;