86 lines
2.1 KiB
Perl
86 lines
2.1 KiB
Perl
package Slic3r::STL;
|
|
use Moo;
|
|
|
|
use Math::Clipper qw(integerize_coordinate_sets is_counter_clockwise);
|
|
use Slic3r::Geometry qw(X Y Z three_points_aligned longest_segment);
|
|
use XXX;
|
|
|
|
sub read_file {
|
|
my $self = shift;
|
|
my ($file) = @_;
|
|
|
|
open my $fh, '<', $file or die "Failed to open $file\n";
|
|
my $facets = [];
|
|
|
|
# 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;
|
|
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';
|
|
}
|
|
|
|
$mode eq 'ascii'
|
|
? _read_ascii($fh, $facets)
|
|
: _read_binary($fh, $facets);
|
|
|
|
close $fh;
|
|
return Slic3r::TriangleMesh->new(facets => $facets);
|
|
}
|
|
|
|
sub _read_ascii {
|
|
my ($fh, $facets) = @_;
|
|
|
|
my $point_re = qr/([^ ]+)\s+([^ ]+)\s+([^ ]+)$/;
|
|
|
|
my $facet;
|
|
seek $fh, 0, 0;
|
|
while (<$fh>) {
|
|
chomp;
|
|
if (!$facet) {
|
|
/^\s*facet\s+normal\s+$point_re/ or next;
|
|
$facet = [ [$1, $2, $3] ];
|
|
} else {
|
|
if (/^\s*endfacet/) {
|
|
push @$facets, $facet;
|
|
undef $facet;
|
|
} else {
|
|
/^\s*vertex\s+$point_re/ or next;
|
|
push @$facet, [$1, $2, $3];
|
|
}
|
|
}
|
|
}
|
|
if ($facet) {
|
|
die "STL file seems invalid\n";
|
|
}
|
|
}
|
|
|
|
sub _read_binary {
|
|
my ($fh, $facets) = @_;
|
|
|
|
die "bigfloat" unless length(pack "f", 1) == 4;
|
|
|
|
binmode $fh;
|
|
seek $fh, 80 + 4, 0;
|
|
while (read $fh, $_, 4*4*3+2) {
|
|
my @v = unpack '(f<3)4';
|
|
push @$facets, [ [@v[0..2]], [@v[3..5]], [@v[6..8]], [@v[9..11]] ];
|
|
}
|
|
}
|
|
|
|
1;
|