mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Automatically repair any input STL file
This commit is contained in:
		
							parent
							
								
									d30b4f0310
								
							
						
					
					
						commit
						5975145426
					
				
					 2 changed files with 4 additions and 93 deletions
				
			
		| 
						 | 
				
			
			@ -7,37 +7,10 @@ sub read_file {
 | 
			
		|||
    my $self = shift;
 | 
			
		||||
    my ($file) = @_;
 | 
			
		||||
    
 | 
			
		||||
    Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n";
 | 
			
		||||
    
 | 
			
		||||
    # let's detect whether file is ASCII or binary
 | 
			
		||||
    my $mode;
 | 
			
		||||
    {
 | 
			
		||||
        my $size = +(stat $fh)[7];
 | 
			
		||||
        $mode = 'ascii' if $size < 80 + 4;
 | 
			
		||||
        
 | 
			
		||||
        # skip binary header
 | 
			
		||||
        seek $fh, 80, 0;
 | 
			
		||||
        read $fh, my $buf, 4;
 | 
			
		||||
        my $triangle_count = unpack 'L', $buf;
 | 
			
		||||
        die "STL file seems invalid, could not read facet count\n" if !defined $triangle_count;
 | 
			
		||||
        my $expected_size =
 | 
			
		||||
            + 80 # header
 | 
			
		||||
            +  4 # count
 | 
			
		||||
            + $triangle_count * (
 | 
			
		||||
                + 4   # normal, pt,pt,pt (vectors)
 | 
			
		||||
                  * 4   # bytes per value
 | 
			
		||||
                  * 3   # values per vector
 | 
			
		||||
                + 2 # the trailing 'short'
 | 
			
		||||
            );
 | 
			
		||||
        $mode = ($size == $expected_size) ? 'binary' : 'ascii';
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    my $facets = [];
 | 
			
		||||
    my $vertices = [];
 | 
			
		||||
    $mode eq 'ascii'
 | 
			
		||||
        ? _read_ascii($fh, $facets, $vertices)
 | 
			
		||||
        : _read_binary($fh, $facets, $vertices);
 | 
			
		||||
    close $fh;
 | 
			
		||||
    my $tmesh = Slic3r::TriangleMesh::XS->new;
 | 
			
		||||
    $tmesh->ReadSTLFile($file);
 | 
			
		||||
    $tmesh->Repair;
 | 
			
		||||
    my ($vertices, $facets) = @{$tmesh->ToPerl};
 | 
			
		||||
    
 | 
			
		||||
    my $model = Slic3r::Model->new;
 | 
			
		||||
    my $object = $model->add_object(vertices => $vertices);
 | 
			
		||||
| 
						 | 
				
			
			@ -45,64 +18,6 @@ sub read_file {
 | 
			
		|||
    return $model;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _read_ascii {
 | 
			
		||||
    my ($fh, $facets, $vertices) = @_;
 | 
			
		||||
    
 | 
			
		||||
    my $point_re = qr/(([^ ]+)\s+([^ ]+)\s+([^ ]+))/;
 | 
			
		||||
    
 | 
			
		||||
    my $facet;
 | 
			
		||||
    my %vertices_map = ();
 | 
			
		||||
    seek $fh, 0, 0;
 | 
			
		||||
    while (<$fh>) {
 | 
			
		||||
        if (!$facet) {
 | 
			
		||||
            /^\s*facet/ or next;  # be tolerant with malformed STL files not having the "normal" word
 | 
			
		||||
            $facet = [];  # ignore normal
 | 
			
		||||
        } else {
 | 
			
		||||
            if (/^\s*endfacet/) {
 | 
			
		||||
                push @$facets, $facet;
 | 
			
		||||
                undef $facet;
 | 
			
		||||
            } else {
 | 
			
		||||
                /^\s*vertex\s+$point_re/o or next;
 | 
			
		||||
                my $vertex_id = $1;
 | 
			
		||||
                my $vertex_idx;
 | 
			
		||||
                if (exists $vertices_map{$vertex_id}) {
 | 
			
		||||
                    $vertex_idx = $vertices_map{$vertex_id};
 | 
			
		||||
                } else {
 | 
			
		||||
                    push @$vertices, [map $_ * 1, $2, $3, $4];
 | 
			
		||||
                    $vertex_idx = $vertices_map{$vertex_id} = $#$vertices;
 | 
			
		||||
                }
 | 
			
		||||
                push @$facet, $vertex_idx;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if ($facet) {
 | 
			
		||||
        die "STL file seems invalid\n";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub _read_binary {
 | 
			
		||||
    my ($fh, $facets, $vertices) = @_;
 | 
			
		||||
    
 | 
			
		||||
    die "bigfloat" unless length(pack "f", 1) == 4;
 | 
			
		||||
    
 | 
			
		||||
    my %vertices_map = ();
 | 
			
		||||
    binmode $fh;
 | 
			
		||||
    seek $fh, 80 + 4, 0;
 | 
			
		||||
    while (read $fh, $_, 4*4*3+2) {
 | 
			
		||||
        push @$facets, my $facet = [];
 | 
			
		||||
        for (unpack 'x[f3](a[f3])3') {  # ignore normal
 | 
			
		||||
            my $vertex_idx;
 | 
			
		||||
            if (exists $vertices_map{$_}) {
 | 
			
		||||
                $vertex_idx = $vertices_map{$_};
 | 
			
		||||
            } else {
 | 
			
		||||
                push @$vertices, [ unpack 'f<3', $_ ];
 | 
			
		||||
                $vertex_idx = $vertices_map{$_} = $#$vertices;
 | 
			
		||||
            }
 | 
			
		||||
            push @$facet, $vertex_idx;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub write_file {
 | 
			
		||||
    my $self = shift;
 | 
			
		||||
    my ($file, $model, %params) = @_;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue