mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	More porting work
This commit is contained in:
		
							parent
							
								
									346c17d483
								
							
						
					
					
						commit
						5adb187dd2
					
				
					 5 changed files with 184 additions and 6 deletions
				
			
		|  | @ -414,10 +414,13 @@ sub intersect_facet { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|     my ($facet_id, $z) = @_; |     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_ids            = @{$self->facets_edges->[$facet_id]}; | ||||||
|     my @edge_vertices_ids   = $self->_facet_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) = (); |     my (@points, @intersection_points, @points_on_layer) = (); | ||||||
|          |          | ||||||
|  | @ -428,7 +431,7 @@ sub intersect_facet { | ||||||
|          |          | ||||||
|         if ($a->[Z] == $b->[Z] && $a->[Z] == $z) { |         if ($a->[Z] == $b->[Z] && $a->[Z] == $z) { | ||||||
|             # edge is horizontal and belongs to the current layer |             # 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) { |             if ($edge_type == FE_TOP) { | ||||||
|                 ($a, $b) = ($b, $a); |                 ($a, $b) = ($b, $a); | ||||||
|                 ($a_id, $b_id) = ($b_id, $a_id); |                 ($a_id, $b_id) = ($b_id, $a_id); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ my $build = Module::Build::WithXSpp->new( | ||||||
|     # _GLIBCXX_USE_C99 : to get the long long type for g++ |     # _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 |     # 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 |     # 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 |     # Provides extra C typemaps that are auto-merged | ||||||
|     extra_typemap_modules => { |     extra_typemap_modules => { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,10 @@ | ||||||
| #include "TriangleMesh.hpp" | #include "TriangleMesh.hpp" | ||||||
|  | #include <vector> | ||||||
|  | #include <map> | ||||||
|  | #include <utility> | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | #include <assert.h> | ||||||
| 
 | 
 | ||||||
| namespace Slic3r { | namespace Slic3r { | ||||||
| 
 | 
 | ||||||
|  | @ -160,12 +164,55 @@ TriangleMesh::slice(const std::vector<double> &z) | ||||||
|         FUTURE: parallelize slice_facet() and make_loops() |         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<int,int>              t_edge; | ||||||
|  |     typedef std::vector<t_edge>             t_edges;  // edge_idx => a_id,b_id
 | ||||||
|  |     typedef std::map<t_edge,int>            t_edges_map;  // a_id,b_id => edge_idx
 | ||||||
|  |     typedef std::vector< std::vector<int> > 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<IntersectionLines> lines(z.size()); | ||||||
|  |      | ||||||
|     for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { |     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
 |         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
 |         /* 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 |            this is needed to get all intersection lines in a consistent order | ||||||
|            (external on the right of the line) */ |            (external on the right of the line) */ | ||||||
|  |         /*
 | ||||||
|         float min_z; |         float min_z; | ||||||
|         if (facet.vertex[1].z < facet.vertex[0].z && facet.vertex[1].z < facet.vertex[2].z) { |         if (facet.vertex[1].z < facet.vertex[0].z && facet.vertex[1].z < facet.vertex[2].z) { | ||||||
|             // vertex 1 has lowest Z
 |             // vertex 1 has lowest Z
 | ||||||
|  | @ -184,6 +231,8 @@ TriangleMesh::slice(const std::vector<double> &z) | ||||||
|         } else { |         } else { | ||||||
|             min_z = facet.vertex[0].z; |             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)); |         float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z)); | ||||||
|          |          | ||||||
|         #ifdef SLIC3R_DEBUG |         #ifdef SLIC3R_DEBUG | ||||||
|  | @ -208,12 +257,114 @@ TriangleMesh::slice(const std::vector<double> &z) | ||||||
|         printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); |         printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); | ||||||
|         #endif |         #endif | ||||||
|          |          | ||||||
|         for (std::vector<double>::const_iterator it = z.begin(); it != z.end(); ++it) { |         for (std::vector<double>::const_iterator it = min_layer; it != max_layer + 1; ++it) { | ||||||
|  |             std::vector<double>::size_type layer_idx = it - z.begin(); | ||||||
|  |             double slice_z = *it; | ||||||
|  |             std::vector<IntersectionPoint> points; | ||||||
|  |             std::vector< std::vector<IntersectionPoint>::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<Polygons>* layers = new std::vector<Polygons>(z.size()); |     std::vector<Polygons>* layers = new std::vector<Polygons>(z.size()); | ||||||
|  |     for (std::vector<IntersectionLines>::const_iterator it = lines.begin(); it != lines.end(); ++it) { | ||||||
|  |          | ||||||
|  |     } | ||||||
|      |      | ||||||
|     // ...
 |     // ...
 | ||||||
|     // add a Polygon p to layer n:
 |     // add a Polygon p to layer n:
 | ||||||
|  |  | ||||||
|  | @ -26,6 +26,30 @@ class TriangleMesh | ||||||
|     stl_file stl; |     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<IntersectionLine> IntersectionLines; | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -48,7 +48,7 @@ my $cube = { | ||||||
|     my $m = Slic3r::TriangleMesh::XS->new; |     my $m = Slic3r::TriangleMesh::XS->new; | ||||||
|     $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); |     $m->ReadFromPerl($cube->{vertices}, $cube->{facets}); | ||||||
|     $m->Repair; |     $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__ | __END__ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci