New slicing algorithm based on a topological approach rather than numeric. It should be much more robust

This commit is contained in:
Alessandro Ranellucci 2012-02-18 20:36:14 +01:00
parent de88144649
commit a9e7204fc6
6 changed files with 339 additions and 271 deletions

View file

@ -42,15 +42,76 @@ sub read_file {
my $vertices = [];
{
my %vertices_map = ();
my %vertices_map = (); # given a vertex's coordinates, what's its index?
my @vertices_facets = (); # given a vertex index, what are the indexes of its tangent facets?
for (my $f = 0; $f <= $#$facets; $f++) {
for (1..3) {
my $point_id = join ',', @{$facets->[$f][$_]};
if (exists $vertices_map{$point_id}) {
$facets->[$f][$_] = $vertices_map{$point_id};
push @{$vertices_facets[$facets->[$f][$_]]}, $f;
} else {
push @$vertices, $facets->[$f][$_];
$facets->[$f][$_] = $vertices_map{$point_id} = $#$vertices;
$vertices_facets[$#$vertices] = [$f];
}
}
}
# The following loop checks that @vertices_facets only groups facets that
# are really connected together (i.e. neighbors or sharing neighbors);
# in other words it takes care of multiple vertices occupying the same
# point in space. It enforces topological correctness which is needed by
# the slicing algorithm.
# I'm keeping it disabled until I find a good test case.
if (0) {
my $vertices_count = $#$vertices; # store it to avoid processing newly created vertices
for (my $v = 0; $v <= $vertices_count; $v++) {
my $more_than_one_vertex_in_this_point = 0;
while (@{$vertices_facets[$v]}) {
my @facets_indexes = @{$vertices_facets[$v]};
@{$vertices_facets[$v]} = ();
my @this_f = shift @facets_indexes;
CYCLE: while (@facets_indexes && @this_f) {
# look for a facet that is connected to $this_f[-1] and whose common line contains $v
my @other_vertices_indexes = grep $_ != $v, @{$facets->[$this_f[-1]]}[1..3];
OTHER: for my $other_f (@facets_indexes) {
# facet is connected if it shares one more point
for (grep $_ != $v, @{$facets->[$other_f]}[1..3]) {
if ($_ ~~ @other_vertices_indexes) {
#printf "facet %d is connected to $other_f (sharing vertices $v and $_)\n", $this_f[-1];
# TODO: we should ensure that the common edge has a different orientation
# for each of the two adjacent facets
push @this_f, $other_f;
@facets_indexes = grep $_ != $other_f, @facets_indexes;
next CYCLE;
}
}
}
# if we're here, then we couldn't find any facet connected to $this_f[-1]
# so we should move this one to a different cluster (that is, a new vertex)
# (or ignore it if it turns to be a non-manifold facet)
if (@this_f > 1) {
push @{$vertices_facets[$v]}, $this_f[-1];
pop @this_f;
$more_than_one_vertex_in_this_point++;
} else {
last CYCLE;
}
}
if ($more_than_one_vertex_in_this_point) {
Slic3r::debugf " more than one vertex in the same point\n";
push @$vertices, $vertices->[$v];
for my $f (@this_f) {
$facets->[$f][$_] = $#$vertices for grep $facets->[$f][$_] == $v, 1..3;
}
}
}
}
}
@ -67,7 +128,7 @@ sub _read_ascii {
my $facet;
seek $fh, 0, 0;
while (<$fh>) {
chomp;
s/\R+$//;
if (!$facet) {
/^\s*facet\s+normal\s+$point_re/ or next;
$facet = [ [$1, $2, $3] ];
@ -77,7 +138,7 @@ sub _read_ascii {
undef $facet;
} else {
/^\s*vertex\s+$point_re/ or next;
push @$facet, [$1, $2, $3];
push @$facet, [map $_ * 1, $1, $2, $3];
}
}
}
@ -106,31 +167,33 @@ sub write_file {
open my $fh, '>', $file;
$binary
? _write_binary($fh, $mesh->facets)
: _write_ascii($fh, $mesh->facets);
? _write_binary($fh, $mesh)
: _write_ascii($fh, $mesh);
close $fh;
}
sub _write_binary {
my ($fh, $facets) = @_;
my ($fh, $mesh) = @_;
die "bigfloat" unless length(pack "f", 1) == 4;
binmode $fh;
print $fh pack 'x80';
print $fh pack 'L', ($#$facets + 1);
print $fh pack '(f<3)4S', (map @$_, @$_), 0 for @$facets;
print $fh pack 'L', scalar(@{$mesh->facets});
foreach my $facet (@{$mesh->facets}) {
print $fh pack '(f<3)4S', @{$facet->[0]}, (map @{$mesh->vertices->[$_]}, @$facet[1,2,3]), 0;
}
}
sub _write_ascii {
my ($fh, $facets) = @_;
my ($fh, $mesh) = @_;
printf $fh "solid\n";
foreach my $facet (@$facets) {
foreach my $facet (@{$mesh->facets}) {
printf $fh " facet normal %f %f %f\n", @{$facet->[0]};
printf $fh " outer loop\n";
printf $fh " vertex %f %f %f\n", @$_ for @$facet[1,2,3];
printf $fh " vertex %f %f %f\n", @{$mesh->vertices->[$_]} for @$facet[1,2,3];
printf $fh " endloop\n";
printf $fh " endfacet\n";
}