Ported union_pt() to XS
This commit is contained in:
parent
443d4e52cb
commit
9cf831b9c5
7 changed files with 78 additions and 42 deletions
|
@ -37,7 +37,7 @@ sub fill_surface {
|
||||||
# generate paths from the outermost to the innermost, to avoid
|
# generate paths from the outermost to the innermost, to avoid
|
||||||
# adhesion problems of the first central tiny loops
|
# adhesion problems of the first central tiny loops
|
||||||
@loops = map Slic3r::Polygon->new(@$_),
|
@loops = map Slic3r::Polygon->new(@$_),
|
||||||
reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) );
|
reverse traverse_pt( union_pt(\@loops) );
|
||||||
|
|
||||||
# order paths using a nearest neighbor search
|
# order paths using a nearest neighbor search
|
||||||
my @paths = ();
|
my @paths = ();
|
||||||
|
|
|
@ -13,20 +13,6 @@ use Math::Clipper 1.22 qw(:cliptypes :polyfilltypes :jointypes is_counter_clockw
|
||||||
use Slic3r::Geometry qw(scale);
|
use Slic3r::Geometry qw(scale);
|
||||||
our $clipper = Math::Clipper->new;
|
our $clipper = Math::Clipper->new;
|
||||||
|
|
||||||
sub _safety_offset {
|
|
||||||
my ($polygons, $factor) = @_;
|
|
||||||
return [ map Slic3r::Polygon->new(@$_),
|
|
||||||
@{Math::Clipper::int_offset(_convert($polygons), $factor // (scale 1e-05), 100000, JT_MITER, 2)} ];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub union_pt {
|
|
||||||
my ($polygons, $jointype, $safety_offset) = @_;
|
|
||||||
$jointype = PFT_NONZERO unless defined $jointype;
|
|
||||||
$clipper->clear;
|
|
||||||
$clipper->add_subject_polygons($safety_offset ? _convert(_safety_offset($polygons)) : _convert($polygons));
|
|
||||||
return $clipper->pt_execute(CT_UNION, $jointype, $jointype);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub traverse_pt {
|
sub traverse_pt {
|
||||||
my ($polynodes) = @_;
|
my ($polynodes) = @_;
|
||||||
|
|
||||||
|
@ -45,10 +31,4 @@ sub traverse_pt {
|
||||||
return @polygons;
|
return @polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _convert {
|
|
||||||
my $p = shift;
|
|
||||||
$p = $p->pp if ref($p) ne 'ARRAY' && $p->can('pp');
|
|
||||||
return [ map { (ref($_) ne 'ARRAY' && $_->can('pp')) ? $_->pp : $_ } @$p ];
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -239,8 +239,8 @@ sub make_perimeters {
|
||||||
$self->_fill_gaps(\@gaps);
|
$self->_fill_gaps(\@gaps);
|
||||||
|
|
||||||
# find nesting hierarchies separately for contours and holes
|
# find nesting hierarchies separately for contours and holes
|
||||||
my $contours_pt = union_pt(\@contours, PFT_EVENODD);
|
my $contours_pt = union_pt(\@contours);
|
||||||
my $holes_pt = union_pt(\@holes, PFT_EVENODD);
|
my $holes_pt = union_pt(\@holes);
|
||||||
|
|
||||||
# prepare a coderef for traversing the PolyTree object
|
# prepare a coderef for traversing the PolyTree object
|
||||||
# external contours are root items of $contours_pt
|
# external contours are root items of $contours_pt
|
||||||
|
|
|
@ -681,7 +681,7 @@ sub make_brim {
|
||||||
polygon => Slic3r::Polygon->new(@$_),
|
polygon => Slic3r::Polygon->new(@$_),
|
||||||
role => EXTR_ROLE_SKIRT,
|
role => EXTR_ROLE_SKIRT,
|
||||||
flow_spacing => $flow->spacing,
|
flow_spacing => $flow->spacing,
|
||||||
), reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) );
|
), reverse traverse_pt( union_pt(\@loops) );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub write_gcode {
|
sub write_gcode {
|
||||||
|
|
|
@ -28,19 +28,19 @@ void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& ex
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
ClipperPolygon_to_Slic3rPolygon(ClipperLib::Polygon &input, Slic3r::Polygon &output)
|
ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output)
|
||||||
{
|
{
|
||||||
output.points.clear();
|
output.points.clear();
|
||||||
for (ClipperLib::Polygon::iterator pit = input.begin(); pit != input.end(); ++pit) {
|
for (ClipperLib::Polygon::const_iterator pit = input.begin(); pit != input.end(); ++pit) {
|
||||||
output.points.push_back(Slic3r::Point( (*pit).X, (*pit).Y ));
|
output.points.push_back(Slic3r::Point( (*pit).X, (*pit).Y ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClipperPolygons_to_Slic3rPolygons(ClipperLib::Polygons &input, Slic3r::Polygons &output)
|
ClipperPolygons_to_Slic3rPolygons(const ClipperLib::Polygons &input, Slic3r::Polygons &output)
|
||||||
{
|
{
|
||||||
output.clear();
|
output.clear();
|
||||||
for (ClipperLib::Polygons::iterator it = input.begin(); it != input.end(); ++it) {
|
for (ClipperLib::Polygons::const_iterator it = input.begin(); it != input.end(); ++it) {
|
||||||
Slic3r::Polygon p;
|
Slic3r::Polygon p;
|
||||||
ClipperPolygon_to_Slic3rPolygon(*it, p);
|
ClipperPolygon_to_Slic3rPolygon(*it, p);
|
||||||
output.push_back(p);
|
output.push_back(p);
|
||||||
|
@ -48,7 +48,7 @@ ClipperPolygons_to_Slic3rPolygons(ClipperLib::Polygons &input, Slic3r::Polygons
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolygons &output)
|
ClipperPolygons_to_Slic3rExPolygons(const ClipperLib::Polygons &input, Slic3r::ExPolygons &output)
|
||||||
{
|
{
|
||||||
// init Clipper
|
// init Clipper
|
||||||
ClipperLib::Clipper clipper;
|
ClipperLib::Clipper clipper;
|
||||||
|
@ -67,19 +67,19 @@ ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolyg
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Slic3rPolygon_to_ClipperPolygon(Slic3r::Polygon &input, ClipperLib::Polygon &output)
|
Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output)
|
||||||
{
|
{
|
||||||
output.clear();
|
output.clear();
|
||||||
for (Slic3r::Points::iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
|
for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
|
||||||
output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y ));
|
output.push_back(ClipperLib::IntPoint( (*pit).x, (*pit).y ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Slic3rPolygons_to_ClipperPolygons(Slic3r::Polygons &input, ClipperLib::Polygons &output)
|
Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output)
|
||||||
{
|
{
|
||||||
output.clear();
|
output.clear();
|
||||||
for (Slic3r::Polygons::iterator it = input.begin(); it != input.end(); ++it) {
|
for (Slic3r::Polygons::const_iterator it = input.begin(); it != input.end(); ++it) {
|
||||||
ClipperLib::Polygon p;
|
ClipperLib::Polygon p;
|
||||||
Slic3rPolygon_to_ClipperPolygon(*it, p);
|
Slic3rPolygon_to_ClipperPolygon(*it, p);
|
||||||
output.push_back(p);
|
output.push_back(p);
|
||||||
|
@ -194,7 +194,7 @@ offset2_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float d
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void _clipper_do(const ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
void _clipper_do(const ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
||||||
Slic3r::Polygons &clip, T &retval, const bool safety_offset_)
|
Slic3r::Polygons &clip, T &retval, const ClipperLib::PolyFillType fillType, const bool safety_offset_)
|
||||||
{
|
{
|
||||||
// read input
|
// read input
|
||||||
ClipperLib::Polygons* input_subject = new ClipperLib::Polygons();
|
ClipperLib::Polygons* input_subject = new ClipperLib::Polygons();
|
||||||
|
@ -222,7 +222,7 @@ void _clipper_do(const ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
||||||
delete input_clip;
|
delete input_clip;
|
||||||
|
|
||||||
// perform operation
|
// perform operation
|
||||||
clipper.Execute(clipType, retval, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
clipper.Execute(clipType, retval, fillType, fillType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _clipper(ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
void _clipper(ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
||||||
|
@ -230,7 +230,7 @@ void _clipper(ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
||||||
{
|
{
|
||||||
// perform operation
|
// perform operation
|
||||||
ClipperLib::Polygons* output = new ClipperLib::Polygons();
|
ClipperLib::Polygons* output = new ClipperLib::Polygons();
|
||||||
_clipper_do<ClipperLib::Polygons>(clipType, subject, clip, *output, safety_offset_);
|
_clipper_do<ClipperLib::Polygons>(clipType, subject, clip, *output, ClipperLib::pftNonZero, safety_offset_);
|
||||||
|
|
||||||
// convert into Polygons
|
// convert into Polygons
|
||||||
ClipperPolygons_to_Slic3rPolygons(*output, retval);
|
ClipperPolygons_to_Slic3rPolygons(*output, retval);
|
||||||
|
@ -242,7 +242,7 @@ void _clipper(ClipperLib::ClipType clipType, Slic3r::Polygons &subject,
|
||||||
{
|
{
|
||||||
// perform operation
|
// perform operation
|
||||||
ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree();
|
ClipperLib::PolyTree* polytree = new ClipperLib::PolyTree();
|
||||||
_clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, *polytree, safety_offset_);
|
_clipper_do<ClipperLib::PolyTree>(clipType, subject, clip, *polytree, ClipperLib::pftNonZero, safety_offset_);
|
||||||
|
|
||||||
// convert into ExPolygons
|
// convert into ExPolygons
|
||||||
PolyTreeToExPolygons(*polytree, retval);
|
PolyTreeToExPolygons(*polytree, retval);
|
||||||
|
@ -280,6 +280,12 @@ void union_(Slic3r::Polygons &subject, T &retval, bool safety_offset_)
|
||||||
template void union_<Slic3r::ExPolygons>(Slic3r::Polygons &subject, Slic3r::ExPolygons &retval, bool safety_offset_);
|
template void union_<Slic3r::ExPolygons>(Slic3r::Polygons &subject, Slic3r::ExPolygons &retval, bool safety_offset_);
|
||||||
template void union_<Slic3r::Polygons>(Slic3r::Polygons &subject, Slic3r::Polygons &retval, bool safety_offset_);
|
template void union_<Slic3r::Polygons>(Slic3r::Polygons &subject, Slic3r::Polygons &retval, bool safety_offset_);
|
||||||
|
|
||||||
|
void union_pt(Slic3r::Polygons &subject, ClipperLib::PolyTree &retval, bool safety_offset_)
|
||||||
|
{
|
||||||
|
Slic3r::Polygons clip;
|
||||||
|
_clipper_do<ClipperLib::PolyTree>(ClipperLib::ctUnion, subject, clip, retval, ClipperLib::pftEvenOdd, safety_offset_);
|
||||||
|
}
|
||||||
|
|
||||||
void simplify_polygons(Slic3r::Polygons &subject, Slic3r::Polygons &retval)
|
void simplify_polygons(Slic3r::Polygons &subject, Slic3r::Polygons &retval)
|
||||||
{
|
{
|
||||||
// convert into Clipper polygons
|
// convert into Clipper polygons
|
||||||
|
@ -312,4 +318,33 @@ void safety_offset(ClipperLib::Polygons* &subject)
|
||||||
subject = retval;
|
subject = retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
|
||||||
|
SV*
|
||||||
|
polynode_children_2_perl(const ClipperLib::PolyNode& node)
|
||||||
|
{
|
||||||
|
AV* av = newAV();
|
||||||
|
const unsigned int len = node.ChildCount();
|
||||||
|
av_extend(av, len-1);
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
av_store(av, i, polynode2perl(*node.Childs[i]));
|
||||||
|
}
|
||||||
|
return (SV*)newRV_noinc((SV*)av);
|
||||||
|
}
|
||||||
|
|
||||||
|
SV*
|
||||||
|
polynode2perl(const ClipperLib::PolyNode& node)
|
||||||
|
{
|
||||||
|
HV* hv = newHV();
|
||||||
|
Slic3r::Polygon p;
|
||||||
|
ClipperPolygon_to_Slic3rPolygon(node.Contour, p);
|
||||||
|
if (node.IsHole()) {
|
||||||
|
(void)hv_stores( hv, "hole", p.to_SV() );
|
||||||
|
} else {
|
||||||
|
(void)hv_stores( hv, "outer", p.to_SV() );
|
||||||
|
}
|
||||||
|
(void)hv_stores( hv, "children", polynode_children_2_perl(node) );
|
||||||
|
return (SV*)newRV_noinc((SV*)hv);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,11 @@ void AddOuterPolyNodeToExPolygons(ClipperLib::PolyNode& polynode, Slic3r::ExPoly
|
||||||
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
|
void PolyTreeToExPolygons(ClipperLib::PolyTree& polytree, Slic3r::ExPolygons& expolygons);
|
||||||
//-----------------------------------------------------------
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
void Slic3rPolygon_to_ClipperPolygon(Slic3r::Polygon &input, ClipperLib::Polygon &output);
|
void Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output);
|
||||||
void Slic3rPolygons_to_ClipperPolygons(Slic3r::Polygons &input, ClipperLib::Polygons &output);
|
void Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output);
|
||||||
void ClipperPolygon_to_Slic3rPolygon(ClipperLib::Polygon &input, Slic3r::Polygon &output);
|
void ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output);
|
||||||
void ClipperPolygons_to_Slic3rPolygons(ClipperLib::Polygons &input, Slic3r::Polygons &output);
|
void ClipperPolygons_to_Slic3rPolygons(const ClipperLib::Polygons &input, Slic3r::Polygons &output);
|
||||||
void ClipperPolygons_to_Slic3rExPolygons(ClipperLib::Polygons &input, Slic3r::ExPolygons &output);
|
void ClipperPolygons_to_Slic3rExPolygons(const ClipperLib::Polygons &input, Slic3r::ExPolygons &output);
|
||||||
|
|
||||||
void scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale);
|
void scaleClipperPolygons(ClipperLib::Polygons &polygons, const double scale);
|
||||||
|
|
||||||
|
@ -64,10 +64,18 @@ void xor_ex(Slic3r::Polygons &subject, Slic3r::Polygons &clip, Slic3r::ExPolygon
|
||||||
template <class T>
|
template <class T>
|
||||||
void union_(Slic3r::Polygons &subject, T &retval, bool safety_offset_ = false);
|
void union_(Slic3r::Polygons &subject, T &retval, bool safety_offset_ = false);
|
||||||
|
|
||||||
|
void union_pt(Slic3r::Polygons &subject, ClipperLib::PolyTree &retval, bool safety_offset_ = false);
|
||||||
|
|
||||||
void simplify_polygons(Slic3r::Polygons &subject, Slic3r::Polygons &retval);
|
void simplify_polygons(Slic3r::Polygons &subject, Slic3r::Polygons &retval);
|
||||||
|
|
||||||
void safety_offset(ClipperLib::Polygons* &subject);
|
void safety_offset(ClipperLib::Polygons* &subject);
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
|
||||||
|
SV* polynode_children_2_perl(const ClipperLib::PolyNode& node);
|
||||||
|
SV* polynode2perl(const ClipperLib::PolyNode& node);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -128,6 +128,19 @@ union_ex(subject, safety_offset = false)
|
||||||
OUTPUT:
|
OUTPUT:
|
||||||
RETVAL
|
RETVAL
|
||||||
|
|
||||||
|
SV*
|
||||||
|
union_pt(subject, safety_offset = false)
|
||||||
|
Polygons subject
|
||||||
|
bool safety_offset
|
||||||
|
CODE:
|
||||||
|
// perform operation
|
||||||
|
ClipperLib::PolyTree polytree;
|
||||||
|
union_pt(subject, polytree, safety_offset);
|
||||||
|
|
||||||
|
RETVAL = polynode_children_2_perl(polytree);
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
Polygons
|
Polygons
|
||||||
simplify_polygons(subject)
|
simplify_polygons(subject)
|
||||||
Polygons subject
|
Polygons subject
|
||||||
|
|
Loading…
Reference in a new issue