mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-24 15:13:58 -06:00
Collect undetected lines (caused by dirty or non-manifold models), warn the user, post debug info. Includes some further ExPolygon refactoring.
This commit is contained in:
parent
91e250a2fd
commit
fec816b065
9 changed files with 92 additions and 34 deletions
|
@ -4,7 +4,7 @@ use Moo;
|
|||
use Math::Clipper ':all';
|
||||
use Slic3r::Geometry qw(polygon_lines points_coincide angle3points polyline_lines nearest_point
|
||||
line_length);
|
||||
use Slic3r::Geometry::Clipper qw(safety_offset union_ex);
|
||||
use Slic3r::Geometry::Clipper qw(safety_offset union_ex PFT_EVENODD);
|
||||
use XXX;
|
||||
|
||||
use constant PI => 4 * atan2(1, 1);
|
||||
|
@ -132,13 +132,6 @@ sub remove_surface {
|
|||
sub make_surfaces {
|
||||
my $self = shift;
|
||||
|
||||
# this algorithm can be further simplified:
|
||||
# first remove all facetedges that are not connected to any other edge
|
||||
# or that are connected to more than one edge: those are the edges
|
||||
# tangent to our plane, that we don't care about;
|
||||
# then we would have all points connecting two and only two lines,
|
||||
# so a simple head-to-tail algorithm would work
|
||||
|
||||
my @lines = ();
|
||||
push @lines, @{$self->lines};
|
||||
#@lines = grep line_length($_) > xx, @lines;
|
||||
|
@ -162,9 +155,12 @@ sub make_surfaces {
|
|||
}
|
||||
|
||||
my $n = 0;
|
||||
my @polygons = ();
|
||||
my (@polygons, %visited_lines, @discarded_lines, @discarded_polylines) = ();
|
||||
while (my $first_line = shift @lines) {
|
||||
next if $visited_lines{ $first_line->id };
|
||||
my @points = @$first_line;
|
||||
|
||||
my @seen_lines = ($first_line);
|
||||
my %seen_points = map { $get_point_id->($points[$_]) => $_ } 0..1;
|
||||
|
||||
CYCLE: while (1) {
|
||||
|
@ -207,7 +203,7 @@ sub make_surfaces {
|
|||
#}
|
||||
|
||||
my ($next_line) = splice @$next_lines, $ordered_next_lines[0], 1;
|
||||
|
||||
push @seen_lines, $next_line;
|
||||
|
||||
push @points, $next_line->[B];
|
||||
|
||||
|
@ -221,21 +217,60 @@ sub make_surfaces {
|
|||
}
|
||||
|
||||
if (@points < 4 || !points_coincide($points[0], $points[-1])) {
|
||||
# discarding polyline
|
||||
if (@points == 2) {
|
||||
push @discarded_lines, [@points];
|
||||
} else {
|
||||
push @discarded_polylines, [@points];
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
$visited_lines{ $_->id } = 1 for @seen_lines;
|
||||
pop @points;
|
||||
Slic3r::debugf "Discovered polygon of %d points\n", scalar(@points);
|
||||
push @polygons, Slic3r::Polygon->new(@points);
|
||||
$polygons[-1]->cleanup;
|
||||
}
|
||||
|
||||
{
|
||||
my $expolygons = union_ex([ @polygons ]);
|
||||
Slic3r::debugf " %d surface(s) detected from %d polylines\n",
|
||||
scalar(@$expolygons), scalar(@polygons);
|
||||
# Now, if we got a clean and manifold model then @polygons would contain everything
|
||||
# we need to draw our layer. In real life, sadly, things are different and it is likely
|
||||
# that the above algorithm wasn't able to detect every polygon. This may happen because
|
||||
# of non-manifoldness or because of many close lines, often overlapping; both situations
|
||||
# make a head-to-tail search difficult.
|
||||
# On the other hand, we can safely assume that every polygon we detected is correct, as
|
||||
# the above algorithm is quite strict. We can take a brute force approach to connect any
|
||||
# other line.
|
||||
|
||||
# So, let's first check what lines were not detected as part of polygons.
|
||||
if (@discarded_lines || @discarded_polylines) {
|
||||
print " Warning: errors while parsing this layer (dirty or non-manifold model)\n";
|
||||
Slic3r::debugf " %d lines out of %d were discarded and %d polylines were not closed\n",
|
||||
scalar(@discarded_lines), scalar(@{$self->lines}), scalar(@discarded_polylines);
|
||||
|
||||
push @{$self->surfaces}, map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'), @$expolygons;
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output(undef, "layer" . $self->id . "_detected.svg",
|
||||
white_polygons => \@polygons,
|
||||
);
|
||||
Slic3r::SVG::output(undef, "layer" . $self->id . "_discarded_lines.svg",
|
||||
red_lines => \@discarded_lines,
|
||||
);
|
||||
Slic3r::SVG::output(undef, "layer" . $self->id . "_discarded_polylines.svg",
|
||||
polylines => \@discarded_polylines,
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $expolygons = union_ex([ @polygons ], PFT_EVENODD);
|
||||
Slic3r::debugf " %d surface(s) having %d holes detected from %d polylines\n",
|
||||
scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@polygons);
|
||||
|
||||
push @{$self->surfaces},
|
||||
map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'),
|
||||
@$expolygons;
|
||||
}
|
||||
|
||||
#use Slic3r::SVG;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue