More work on the clipping method for medial axis. Includes Polyline->is_valid()
This commit is contained in:
parent
7e8c535f6a
commit
b5aaeb9b12
@ -7,7 +7,7 @@ use warnings;
|
|||||||
use Boost::Geometry::Utils;
|
use Boost::Geometry::Utils;
|
||||||
use List::Util qw(first);
|
use List::Util qw(first);
|
||||||
use Math::Geometry::Voronoi;
|
use Math::Geometry::Voronoi;
|
||||||
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon);
|
use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon scaled_epsilon);
|
||||||
use Slic3r::Geometry::Clipper qw(union_ex);
|
use Slic3r::Geometry::Clipper qw(union_ex);
|
||||||
|
|
||||||
sub wkt {
|
sub wkt {
|
||||||
@ -111,7 +111,14 @@ sub _medial_axis_clip {
|
|||||||
|
|
||||||
my $grow = sub {
|
my $grow = sub {
|
||||||
my ($line, $distance) = @_;
|
my ($line, $distance) = @_;
|
||||||
my ($a, $b) = @$line;
|
|
||||||
|
my $line_clone = $line->clone;
|
||||||
|
$line_clone->clip_start(scaled_epsilon);
|
||||||
|
return () if !$line_clone->is_valid;
|
||||||
|
$line_clone->clip_end(scaled_epsilon);
|
||||||
|
return () if !$line_clone->is_valid;
|
||||||
|
|
||||||
|
my ($a, $b) = @$line_clone;
|
||||||
my $dx = $a->x - $b->x;
|
my $dx = $a->x - $b->x;
|
||||||
my $dy = $a->y - $b->y; #-
|
my $dy = $a->y - $b->y; #-
|
||||||
my $dist = sqrt($dx*$dx + $dy*$dy);
|
my $dist = sqrt($dx*$dx + $dy*$dy);
|
||||||
@ -130,9 +137,18 @@ sub _medial_axis_clip {
|
|||||||
foreach my $polygon (@$self) {
|
foreach my $polygon (@$self) {
|
||||||
my @polylines = ();
|
my @polylines = ();
|
||||||
foreach my $line (@{$polygon->lines}) {
|
foreach my $line (@{$polygon->lines}) {
|
||||||
|
# remove the areas that are already covered from this line
|
||||||
my $clipped = Boost::Geometry::Utils::multi_linestring_multi_polygon_difference([$line->pp], [ map $_->pp, @{union_ex($covered)} ]);
|
my $clipped = Boost::Geometry::Utils::multi_linestring_multi_polygon_difference([$line->pp], [ map $_->pp, @{union_ex($covered)} ]);
|
||||||
|
|
||||||
|
# skip very short segments/dots
|
||||||
@$clipped = grep $_->length > $width/10, map Slic3r::Polyline->new(@$_), @$clipped;
|
@$clipped = grep $_->length > $width/10, map Slic3r::Polyline->new(@$_), @$clipped;
|
||||||
|
|
||||||
|
# grow the remaining lines and add them to the covered areas
|
||||||
push @$covered, map $grow->($_, $width*1.1), @$clipped;
|
push @$covered, map $grow->($_, $width*1.1), @$clipped;
|
||||||
|
|
||||||
|
# if the first remaining segment is connected to the last polyline, append it
|
||||||
|
# to that -- NOTE: this assumes that multi_linestring_multi_polygon_difference()
|
||||||
|
# preserved the orientation of the input linestring
|
||||||
if (@polylines && @$clipped && $clipped->[0]->first_point->distance_to($polylines[-1]->last_point) <= $width/10) {
|
if (@polylines && @$clipped && $clipped->[0]->first_point->distance_to($polylines[-1]->last_point) <= $width/10) {
|
||||||
$polylines[-1]->append_polyline(shift @$clipped);
|
$polylines[-1]->append_polyline(shift @$clipped);
|
||||||
}
|
}
|
||||||
@ -140,7 +156,7 @@ sub _medial_axis_clip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach my $polyline (@polylines) {
|
foreach my $polyline (@polylines) {
|
||||||
next if $polyline->length <= $width/10;
|
# if this polyline looks like a closed loop, return it as a polygon
|
||||||
if ($polyline->first_point->coincides_with($polyline->last_point)) {
|
if ($polyline->first_point->coincides_with($polyline->last_point)) {
|
||||||
next if @$polyline == 2;
|
next if @$polyline == 2;
|
||||||
$polyline->pop_back;
|
$polyline->pop_back;
|
||||||
|
@ -49,6 +49,12 @@ MultiPoint::length() const
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MultiPoint::is_valid() const
|
||||||
|
{
|
||||||
|
return this->points.size() >= 2;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
void
|
void
|
||||||
MultiPoint::from_SV(SV* poly_sv)
|
MultiPoint::from_SV(SV* poly_sv)
|
||||||
|
@ -20,6 +20,7 @@ class MultiPoint
|
|||||||
virtual Point* last_point() const = 0;
|
virtual Point* last_point() const = 0;
|
||||||
virtual Lines lines() const = 0;
|
virtual Lines lines() const = 0;
|
||||||
double length() const;
|
double length() const;
|
||||||
|
bool is_valid() const;
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
void from_SV(SV* poly_sv);
|
void from_SV(SV* poly_sv);
|
||||||
|
@ -40,6 +40,15 @@ Polyline::clip_end(double distance)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removes the given distance from the start of the polyline
|
||||||
|
void
|
||||||
|
Polyline::clip_start(double distance)
|
||||||
|
{
|
||||||
|
this->reverse();
|
||||||
|
this->clip_end(distance);
|
||||||
|
if (this->points.size() >= 2) this->reverse();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
SV*
|
SV*
|
||||||
Polyline::to_SV_ref()
|
Polyline::to_SV_ref()
|
||||||
|
@ -11,6 +11,7 @@ class Polyline : public MultiPoint {
|
|||||||
Point* last_point() const;
|
Point* last_point() const;
|
||||||
Lines lines() const;
|
Lines lines() const;
|
||||||
void clip_end(double distance);
|
void clip_end(double distance);
|
||||||
|
void clip_start(double distance);
|
||||||
|
|
||||||
#ifdef SLIC3RXS
|
#ifdef SLIC3RXS
|
||||||
SV* to_SV_ref();
|
SV* to_SV_ref();
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
Point* last_point()
|
Point* last_point()
|
||||||
%code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->last_point(); %};
|
%code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->last_point(); %};
|
||||||
double length();
|
double length();
|
||||||
|
bool is_valid();
|
||||||
void clip_end(double distance);
|
void clip_end(double distance);
|
||||||
|
void clip_start(double distance);
|
||||||
%{
|
%{
|
||||||
|
|
||||||
Polyline*
|
Polyline*
|
||||||
|
Loading…
Reference in New Issue
Block a user