1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
package Slic3r::Polygon;
use strict;
use warnings;
# a polygon is a closed polyline.
use parent 'Slic3r::Polyline';
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon);
use Slic3r::Geometry::Clipper qw(JT_MITER);
sub lines {
my $self = shift;
return polygon_lines($self);
}
sub boost_polygon {
my $self = shift;
return Boost::Geometry::Utils::polygon($self);
}
sub boost_linestring {
my $self = shift;
return Boost::Geometry::Utils::linestring([@$self, $self->[0]]);
}
sub wkt {
my $self = shift;
return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self;
}
sub is_counter_clockwise {
my $self = shift;
return Slic3r::Geometry::Clipper::is_counter_clockwise($self);
}
sub make_counter_clockwise {
my $self = shift;
if (!$self->is_counter_clockwise) {
$self->reverse;
return 1;
}
return 0;
}
sub make_clockwise {
my $self = shift;
if ($self->is_counter_clockwise) {
$self->reverse;
return 1;
}
return 0;
}
sub merge_continuous_lines {
my $self = shift;
polygon_remove_parallel_continuous_edges($self);
bless $_, 'Slic3r::Point' for @$self;
}
sub remove_acute_vertices {
my $self = shift;
polygon_remove_acute_vertices($self);
bless $_, 'Slic3r::Point' for @$self;
}
sub point_on_segment {
my $self = shift;
my ($point) = @_;
return polygon_segment_having_point($self, $point);
}
sub encloses_point {
my $self = shift;
my ($point) = @_;
return point_in_polygon($point, $self);
}
sub area {
my $self = shift;
return Slic3r::Geometry::Clipper::area($self);
}
sub safety_offset {
my $self = shift;
return (ref $self)->new(Slic3r::Geometry::Clipper::safety_offset([$self])->[0]);
}
sub offset {
my $self = shift;
return map Slic3r::Polygon->new($_), Slic3r::Geometry::Clipper::offset([$self], @_);
}
# this method subdivides the polygon segments to that no one of them
# is longer than the length provided
sub subdivide {
my $self = shift;
my ($max_length) = @_;
for (my $i = 0; $i <= $#$self; $i++) {
my $len = Slic3r::Geometry::line_length([ $self->[$i-1], $self->[$i] ]);
my $num_points = int($len / $max_length) - 1;
$num_points++ if $len % $max_length;
# $num_points is the number of points to add between $i-1 and $i
next if $num_points == -1;
my $spacing = $len / ($num_points + 1);
my @new_points = map Slic3r::Point->new($_),
map Slic3r::Geometry::point_along_segment($self->[$i-1], $self->[$i], $spacing * $_),
1..$num_points;
splice @$self, $i, 0, @new_points;
$i += @new_points;
}
}
# returns false if the polyline is too tight to be printed
sub is_printable {
my $self = shift;
my ($flow) = @_;
# try to get an inwards offset
# for a distance equal to half of the extrusion width;
# if no offset is possible, then polyline is not printable.
# we use flow_width here because this has to be consistent
# with the thin wall detection in Layer->make_surfaces,
# otherwise we could lose surfaces as that logic wouldn't
# detect them and we would be discarding them.
my $p = $self->clone;
$p->make_counter_clockwise;
return $p->offset(-$flow->scaled_width / 2) ? 1 : 0;
}
sub is_valid {
my $self = shift;
return @$self >= 3;
}
sub split_at_index {
my $self = shift;
my ($index) = @_;
return Slic3r::Polyline->new(
@$self[$index .. $#$self],
@$self[0 .. $index],
);
}
sub split_at {
my $self = shift;
my ($point) = @_;
# find index of point
my $i = -1;
for (my $n = 0; $n <= $#$self; $n++) {
if (Slic3r::Geometry::same_point($point, $self->[$n])) {
$i = $n;
last;
}
}
die "Point not found" if $i == -1;
return $self->split_at_index($i);
}
sub split_at_first_point {
my $self = shift;
return $self->split_at_index(0);
}
1;
|