#!/usr/bin/perl
# Read an ASCII format STL file
# Report if it is not a solid.
# Report issues with the facet normals.
# solid 1170Handle
# facet normal -0.000148266570749099 -0.00460401291523558 0.999989390484769
# outer loop
# vertex 0.000140744572064588 1.4493726055151 0.146
# vertex -0.0370754460367823 1.67815054731263 0.146999999999999
# vertex -0.0413711642044813 1.68852132837323 0.146999999999999
# endloop
# endfacet
# endsolid 1170Handle
# That normal isn't a proper unit normal. Should be:
# facet normal 0.0 0.0 1.0
#
# Sort two points into an appropriately ordered edge with
# standardized precision.
sub mkedge {
local($p, $t) = @_;
($x1, $y1, $z1) = split(/\s+/, $p);
($x2, $y2, $z2) = split(/\s+/, $t);
# # Round each coordinate to the desired resolution.
# $resolution = 1000;
# $x1 = int($x1*$resolution+0.5);
# $y1 = int($y1*$resolution+0.5);
# $z1 = int($z1*$resolution+0.5);
# $x2 = int($x2*$resolution+0.5);
# $y2 = int($y2*$resolution+0.5);
# $z2 = int($z2*$resolution+0.5);
$cmp = $x1 <=> $x2;
$cmp = $y1 <=> $y2 unless $cmp;
$cmp = $z1 <=> $z2 unless $cmp;
if ($cmp > 0) {
# Swap them
($p, $t) = ($t, $p);
($x1, $y1, $z1, $x2, $y2, $z2) = ($x2, $y2, $z2, $x1, $y1, $z1);
}
# return "($x1 $y1 $z1) ($x2, $y2, $z2)";
return "$p $t";
}
# Check that every line segment joins two faces.
$badfiles = 0;
foreach $f (@ARGV) {
open(INPUT, $f) || die "$f: $!";
$_ = ;
unless (/^solid /) {
warn "$f: Not an ASCII STL file\n";
$badfiles++;
next;
}
$previous = undef;
%edge = ();
$bad = 0;
while () {
s/\r$//; chop;
last if /^\s*endsolid /;
if (/^\s*facet /) {
next unless /-0[.]0 /;
warn "$f: bad normal: $_\n";
$bad++;
next;
}
next if /^\s*endloop/;
next if /^\s*outer loop/;
if (/^\s*endfacet/) {
$edge = &mkedge($first, $this);
$edge{$edge} = 0 unless defined $edge{$edge};
$edge{$edge}++;
$edges++;
$previous = undef;
next;
}
die "syntax error: $_" unless /\s*vertex ([-e\d.\s]+)$/i;
$this = $1;
if (defined $previous) {
$edge = &mkedge($previous, $this);
$edge{$edge} = 0 unless defined $edge{$edge};
$edge{$edge}++;
$edges++;
} else {
$first = $this;
}
$previous = $this;
}
foreach $edge (keys %edge) {
if ($edge{$edge} != 2) {
print "$edge occurs $edge{$edge} times\n";
$bad++;
}
}
if ($bad) {
print "$f: $bad out of $edges edges were open\n";
$badfiles++;
}
}
exit $badfiles;