From 5adb187dd22cfbfc549c1fba8ec1422dbbd5c8f4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 7 Sep 2013 21:08:53 +0200 Subject: [PATCH] More porting work --- lib/Slic3r/TriangleMesh.pm | 9 ++- xs/Build.PL | 2 +- xs/src/TriangleMesh.cpp | 153 ++++++++++++++++++++++++++++++++++++- xs/src/TriangleMesh.hpp | 24 ++++++ xs/t/01_trianglemesh.t | 2 +- 5 files changed, 184 insertions(+), 6 deletions(-) diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index d254a6c5a..1d721babb 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -414,10 +414,13 @@ sub intersect_facet { my $self = shift; my ($facet_id, $z) = @_; - my @vertices_ids = @{$self->facets->[$facet_id]}[-3..-1]; - my %vertices = map { $_ => $self->vertices->[$_] } @vertices_ids; # cache vertices my @edge_ids = @{$self->facets_edges->[$facet_id]}; my @edge_vertices_ids = $self->_facet_edges($facet_id); + my %vertices; + { + my @vertices_ids = @{$self->facets->[$facet_id]}[-3..-1]; + %vertices = map { $_ => $self->vertices->[$_] } @vertices_ids; # cache vertices + } my (@points, @intersection_points, @points_on_layer) = (); @@ -428,7 +431,7 @@ sub intersect_facet { if ($a->[Z] == $b->[Z] && $a->[Z] == $z) { # edge is horizontal and belongs to the current layer - my $edge_type = (grep $vertices{$_}[Z] < $z, @vertices_ids) ? FE_TOP : FE_BOTTOM; + my $edge_type = (grep $_->[Z] < $z, values %vertices) ? FE_TOP : FE_BOTTOM; if ($edge_type == FE_TOP) { ($a, $b) = ($b, $a); ($a_id, $b_id) = ($b_id, $a_id); diff --git a/xs/Build.PL b/xs/Build.PL index 2a7dc4fa1..edc66fd70 100644 --- a/xs/Build.PL +++ b/xs/Build.PL @@ -24,7 +24,7 @@ my $build = Module::Build::WithXSpp->new( # _GLIBCXX_USE_C99 : to get the long long type for g++ # HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC # NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace - extra_compiler_flags => [qw(-D_GLIBCXX_USE_C99 -DHAS_BOOL -DNOGDI), ($ENV{SLIC3R_DEBUG} ? ' -DSLIC3R_DEBUG' : '')], + extra_compiler_flags => [qw(-D_GLIBCXX_USE_C99 -DHAS_BOOL -DNOGDI), ($ENV{SLIC3R_DEBUG} ? ' -DSLIC3R_DEBUG -g' : '')], # Provides extra C typemaps that are auto-merged extra_typemap_modules => { diff --git a/xs/src/TriangleMesh.cpp b/xs/src/TriangleMesh.cpp index 165c32af4..085518f6b 100644 --- a/xs/src/TriangleMesh.cpp +++ b/xs/src/TriangleMesh.cpp @@ -1,6 +1,10 @@ #include "TriangleMesh.hpp" +#include +#include +#include #include #include +#include namespace Slic3r { @@ -160,12 +164,55 @@ TriangleMesh::slice(const std::vector &z) FUTURE: parallelize slice_facet() and make_loops() */ + // build a table to map a facet_idx to its three edge indices + if (this->stl.v_shared == NULL) stl_generate_shared_vertices(&(this->stl)); + typedef std::pair t_edge; + 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_map edges_map; + for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { + facets_edges[facet_idx].resize(3); + for (int i = 0; i <= 2; i++) { + int a_id = this->stl.v_indices[facet_idx].vertex[i]; + int b_id = this->stl.v_indices[facet_idx].vertex[(i+1) % 3]; + + int edge_idx; + t_edges_map::const_iterator my_edge = edges_map.find(std::make_pair(b_id,a_id)); + if (my_edge == edges_map.end()) { + // edge isn't listed in table, so we insert it + edge_idx = edges.size(); + edges.push_back(std::make_pair(a_id,b_id)); + edges_map[ edges[edge_idx] ] = edge_idx; + } else { + edge_idx = my_edge->second; + } + facets_edges[facet_idx][i] = edge_idx; + + #ifdef SLIC3R_DEBUG + printf(" [facet %d, edge %d] a_id = %d, b_id = %d --> edge %d\n", facet_idx, i, a_id, b_id, edge_idx); + #endif + } + } + } + + std::vector lines(z.size()); + for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { stl_facet facet = this->stl.facet_start[facet_idx]; // this is a copy /* 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 (external on the right of the line) */ + /* float min_z; if (facet.vertex[1].z < facet.vertex[0].z && facet.vertex[1].z < facet.vertex[2].z) { // vertex 1 has lowest Z @@ -184,6 +231,8 @@ TriangleMesh::slice(const std::vector &z) } else { min_z = facet.vertex[0].z; } + */ + float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z)); float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z)); #ifdef SLIC3R_DEBUG @@ -208,12 +257,114 @@ TriangleMesh::slice(const std::vector &z) printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); #endif - for (std::vector::const_iterator it = z.begin(); it != z.end(); ++it) { + for (std::vector::const_iterator it = min_layer; it != max_layer + 1; ++it) { + std::vector::size_type layer_idx = it - z.begin(); + double slice_z = *it; + std::vector points; + std::vector< std::vector::size_type > points_on_layer, intersection_points; + for (int i = 0; i <= 2; i++) { // loop through facet edges + int edge_id = facets_edges[facet_idx][i]; + t_edge edge = edges[edge_id]; + + stl_vertex* a = &(this->stl.v_shared[edge.first]); + stl_vertex* b = &(this->stl.v_shared[edge.second]); + + #ifdef SLIC3R_DEBUG + printf(" a = %f, b = %f, slice_z = %f\n", a->z, b->z, slice_z); + #endif + + if (a->z == b->z && a->z == slice_z) { + // edge is horizontal and belongs to the current layer + #ifdef SLIC3R_DEBUG + printf("Edge is horizontal!\n"); + #endif + + /* 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; + } else { + line.edge_type = feBottom; + } + lines[layer_idx].push_back(line); + } else if (a->z == slice_z) { + #ifdef SLIC3R_DEBUG + printf("A point on plane!\n"); + #endif + + IntersectionPoint point; + point.x = a->x; + point.y = a->y; + point.point_id = edge.first; + points.push_back(point); + points_on_layer.push_back(points.size()-1); + } else if (b->z == slice_z) { + #ifdef SLIC3R_DEBUG + printf("B point on plane!\n"); + #endif + + IntersectionPoint point; + point.x = b->x; + point.y = b->y; + point.point_id = edge.second; + 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)) { + // edge intersects the current layer; calculate intersection + #ifdef SLIC3R_DEBUG + printf("Intersects!\n"); + #endif + + IntersectionPoint point; + point.x = b->x + (a->x - b->x) * (slice_z - b->z) / (a->z - b->z); + point.y = b->y + (a->y - b->y) * (slice_z - b->z) / (a->z - b->z); + point.edge_id = edge_id; + points.push_back(point); + intersection_points.push_back(points.size()-1); + } + } + + if (points_on_layer.size() == 2) { + if (intersection_points.size() == 1) { + + } else if (intersection_points.empty()) { + 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; + line.b.x = points[0].x; + line.b.y = points[0].y; + line.a_id = points[1].point_id; + line.b_id = points[0].point_id; + line.edge_a_id = points[1].edge_id; + line.edge_b_id = points[0].edge_id; + lines[layer_idx].push_back(line); + } } } + // build loops std::vector* layers = new std::vector(z.size()); + for (std::vector::const_iterator it = lines.begin(); it != lines.end(); ++it) { + + } // ... // add a Polygon p to layer n: diff --git a/xs/src/TriangleMesh.hpp b/xs/src/TriangleMesh.hpp index e6ed3fa0c..7ba9157d1 100644 --- a/xs/src/TriangleMesh.hpp +++ b/xs/src/TriangleMesh.hpp @@ -26,6 +26,30 @@ class TriangleMesh stl_file stl; }; +enum FacetEdgeType { feNone, feTop, feBottom }; + +class IntersectionPoint : public Point +{ + public: + int point_id; + int edge_id; + IntersectionPoint() : point_id(-1), edge_id(-1) {}; +}; + +class IntersectionLine +{ + public: + Point a; + Point b; + int a_id; + int b_id; + int edge_a_id; + int edge_b_id; + FacetEdgeType edge_type; + IntersectionLine() : a_id(-1), b_id(-1), edge_a_id(-1), edge_b_id(-1), edge_type(feNone) {}; +}; +typedef std::vector IntersectionLines; + } #endif diff --git a/xs/t/01_trianglemesh.t b/xs/t/01_trianglemesh.t index 1948d0be5..09b47e68b 100644 --- a/xs/t/01_trianglemesh.t +++ b/xs/t/01_trianglemesh.t @@ -48,7 +48,7 @@ my $cube = { my $m = Slic3r::TriangleMesh::XS->new; $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); $m->Repair; - my $result = $m->slice([2,4,8,6,8,10,12,14,16,18]); + my $result = $m->slice([2,4,8,6,8,10,12,14,16,18,20]); } __END__