Update Clipper to 6.0.0
This commit is contained in:
parent
d49052779f
commit
50c0081d25
@ -293,6 +293,7 @@ sub make_perimeters {
|
|||||||
my @p = map $_->medial_axis($pspacing), @thin_walls;
|
my @p = map $_->medial_axis($pspacing), @thin_walls;
|
||||||
my @paths = ();
|
my @paths = ();
|
||||||
for my $p (@p) {
|
for my $p (@p) {
|
||||||
|
next if $p->length <= $pspacing * 2;
|
||||||
my %params = (
|
my %params = (
|
||||||
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
role => EXTR_ROLE_EXTERNAL_PERIMETER,
|
||||||
flow_spacing => $self->perimeter_flow->spacing,
|
flow_spacing => $self->perimeter_flow->spacing,
|
||||||
|
@ -31,7 +31,7 @@ sub point_on_left {
|
|||||||
|
|
||||||
sub grow {
|
sub grow {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return Slic3r::Polyline->new(@$self[0,1,0])->grow(@_);
|
return Slic3r::Polyline->new(@$self)->grow(@_);
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -35,20 +35,6 @@ sub simplify {
|
|||||||
return __PACKAGE__->new(@$simplified);
|
return __PACKAGE__->new(@$simplified);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub grow {
|
|
||||||
my $self = shift;
|
|
||||||
my ($distance, $scale, $joinType, $miterLimit) = @_;
|
|
||||||
$joinType //= JT_SQUARE; # we override this one
|
|
||||||
$scale //= 100000; # we init these because we can't pass undef
|
|
||||||
$miterLimit //= 3;
|
|
||||||
|
|
||||||
my @points = @$self;
|
|
||||||
return @{Slic3r::Geometry::Clipper::offset(
|
|
||||||
[ Slic3r::Polygon->new(@points, CORE::reverse @points[1..($#points-1)]) ],
|
|
||||||
$distance, $scale, $joinType, $miterLimit,
|
|
||||||
)};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub clip_with_polygon {
|
sub clip_with_polygon {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($polygon) = @_;
|
my ($polygon) = @_;
|
||||||
|
@ -652,10 +652,10 @@ sub make_brim {
|
|||||||
if (@{ $object->support_layers }) {
|
if (@{ $object->support_layers }) {
|
||||||
my $support_layer0 = $object->support_layers->[0];
|
my $support_layer0 = $object->support_layers->[0];
|
||||||
push @object_islands,
|
push @object_islands,
|
||||||
(map $_->polyline->grow($grow_distance), @{$support_layer0->support_fills})
|
(map @{$_->polyline->grow($grow_distance)}, @{$support_layer0->support_fills})
|
||||||
if $support_layer0->support_fills;
|
if $support_layer0->support_fills;
|
||||||
push @object_islands,
|
push @object_islands,
|
||||||
(map $_->polyline->grow($grow_distance), @{$support_layer0->support_interface_fills})
|
(map @{$_->polyline->grow($grow_distance)}, @{$support_layer0->support_interface_fills})
|
||||||
if $support_layer0->support_interface_fills;
|
if $support_layer0->support_interface_fills;
|
||||||
}
|
}
|
||||||
foreach my $copy (@{$object->copies}) {
|
foreach my $copy (@{$object->copies}) {
|
||||||
@ -666,7 +666,7 @@ sub make_brim {
|
|||||||
# if brim touches skirt, make it around skirt too
|
# if brim touches skirt, make it around skirt too
|
||||||
# TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups)
|
# TODO: calculate actual skirt width (using each extruder's flow in multi-extruder setups)
|
||||||
if ($Slic3r::Config->skirt_distance + (($Slic3r::Config->skirts - 1) * $flow->spacing) <= $Slic3r::Config->brim_width) {
|
if ($Slic3r::Config->skirt_distance + (($Slic3r::Config->skirts - 1) * $flow->spacing) <= $Slic3r::Config->brim_width) {
|
||||||
push @islands, map $_->split_at_first_point->polyline->grow($grow_distance), @{$self->skirt};
|
push @islands, map @{$_->split_at_first_point->polyline->grow($grow_distance)}, @{$self->skirt};
|
||||||
}
|
}
|
||||||
|
|
||||||
my @loops = ();
|
my @loops = ();
|
||||||
|
@ -258,6 +258,10 @@ sub make_perimeters {
|
|||||||
|
|
||||||
# only add the perimeter if there's an intersection with the collapsed area
|
# only add the perimeter if there's an intersection with the collapsed area
|
||||||
last CYCLE if !@{ intersection($diff, $hypothetical_perimeter) };
|
last CYCLE if !@{ intersection($diff, $hypothetical_perimeter) };
|
||||||
|
use Slic3r::SVG;
|
||||||
|
Slic3r::SVG::output("extra.svg",
|
||||||
|
expolygons => union_ex(intersection($diff, $hypothetical_perimeter)),
|
||||||
|
);exit;
|
||||||
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
|
Slic3r::debugf " adding one more perimeter at layer %d\n", $layer_id;
|
||||||
$slice->extra_perimeters($extra_perimeters);
|
$slice->extra_perimeters($extra_perimeters);
|
||||||
}
|
}
|
||||||
|
@ -480,7 +480,7 @@ sub generate_toolpaths {
|
|||||||
# solution should be found to achieve both goals
|
# solution should be found to achieve both goals
|
||||||
$contact_infill = diff(
|
$contact_infill = diff(
|
||||||
$contact,
|
$contact,
|
||||||
[ map $_->grow($circle_radius*1.1), @loops ],
|
[ map @{$_->grow($circle_radius*1.1)}, @loops ],
|
||||||
);
|
);
|
||||||
|
|
||||||
# transform loops into ExtrusionPath objects
|
# transform loops into ExtrusionPath objects
|
||||||
|
@ -92,7 +92,7 @@ sub _plot {
|
|||||||
foreach my $path (@paths) {
|
foreach my $path (@paths) {
|
||||||
foreach my $line (@{$path->lines}) {
|
foreach my $line (@{$path->lines}) {
|
||||||
my @intersections = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
|
my @intersections = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
|
||||||
Slic3r::ExPolygon->new($line->grow(Slic3r::Geometry::scale $path->flow_spacing/2))->pp,
|
Slic3r::ExPolygon->new(@{$line->grow(Slic3r::Geometry::scale $path->flow_spacing/2)})->pp,
|
||||||
[ $self->line ],
|
[ $self->line ],
|
||||||
) };
|
) };
|
||||||
die "Intersection has more than two points!\n" if first { @$_ > 2 } @intersections;
|
die "Intersection has more than two points!\n" if first { @$_ > 2 } @intersections;
|
||||||
|
@ -35,16 +35,16 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
|
|||||||
|
|
||||||
is_deeply [ map $_->pp, @$intersection ], [[
|
is_deeply [ map $_->pp, @$intersection ], [[
|
||||||
[
|
[
|
||||||
[20, 12],
|
|
||||||
[20, 18],
|
[20, 18],
|
||||||
[10, 18],
|
[10, 18],
|
||||||
[10, 12],
|
[10, 12],
|
||||||
|
[20, 12],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
[14, 14],
|
|
||||||
[14, 16],
|
[14, 16],
|
||||||
[16, 16],
|
[16, 16],
|
||||||
[16, 14],
|
[16, 14],
|
||||||
|
[14, 14],
|
||||||
],
|
],
|
||||||
]], 'hole is preserved after intersection';
|
]], 'hole is preserved after intersection';
|
||||||
}
|
}
|
||||||
@ -58,11 +58,11 @@ use Slic3r::Geometry::Clipper qw(intersection_ex union_ex diff_ex);
|
|||||||
|
|
||||||
my $union = union_ex([ $contour1, $contour2, $hole ]);
|
my $union = union_ex([ $contour1, $contour2, $hole ]);
|
||||||
|
|
||||||
is_deeply [ map $_->pp, @$union ], [[ [ [40,0], [40,40], [0,40], [0,0] ] ]],
|
is_deeply [ map $_->pp, @$union ], [[ [ [40,40], [0,40], [0,0], [40,0] ] ]],
|
||||||
'union of two ccw and one cw is a contour with no holes';
|
'union of two ccw and one cw is a contour with no holes';
|
||||||
|
|
||||||
my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]);
|
my $diff = diff_ex([ $contour1, $contour2 ], [ $hole ]);
|
||||||
is_deeply [ map $_->pp, @$diff ], [[ [ [40,0], [40,40], [0,40], [0,0] ], [ [15,15], [15,25], [25,25], [25,15] ] ]],
|
is_deeply [ map $_->pp, @$diff ], [[ [ [40,40], [0,40], [0,0], [40,0] ], [ [15,25], [25,25], [25,15], [15,15] ] ]],
|
||||||
'difference of a cw from two ccw is a contour with one hole';
|
'difference of a cw from two ccw is a contour with one hole';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
t/fill.t
2
t/fill.t
@ -68,7 +68,7 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||||||
);
|
);
|
||||||
|
|
||||||
# check whether any part was left uncovered
|
# check whether any part was left uncovered
|
||||||
my @grown_paths = map Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2), @paths;
|
my @grown_paths = map @{Slic3r::Polyline->new(@$_)->grow(scale $params->{flow_spacing}/2)}, @paths;
|
||||||
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
|
my $uncovered = diff_ex([ @$expolygon ], [ @grown_paths ], 1);
|
||||||
|
|
||||||
# ignore very small dots
|
# ignore very small dots
|
||||||
|
@ -187,7 +187,7 @@ is Slic3r::Geometry::can_connect_points(@$points, $polygons), 0, 'can_connect_po
|
|||||||
|
|
||||||
{
|
{
|
||||||
my $line = Slic3r::Line->new([10,10], [20,10]);
|
my $line = Slic3r::Line->new([10,10], [20,10]);
|
||||||
is +($line->grow(5))[0]->area, Slic3r::Polygon->new([5,5], [25,5], [25,15], [5,15])->area, 'grow line';
|
is $line->grow(5)->[0]->area, Slic3r::Polygon->new([10,5], [20,5], [20,15], [10,15])->area, 'grow line';
|
||||||
}
|
}
|
||||||
|
|
||||||
#==========================================================
|
#==========================================================
|
||||||
|
@ -67,7 +67,7 @@ ClipperPolygons_to_Slic3rExPolygons(const ClipperLib::Polygons &input, Slic3r::E
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygon &output)
|
Slic3rPolygon_to_ClipperPolygon(const Slic3r::MultiPoint &input, ClipperLib::Polygon &output)
|
||||||
{
|
{
|
||||||
output.clear();
|
output.clear();
|
||||||
for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
|
for (Slic3r::Points::const_iterator pit = input.points.begin(); pit != input.points.end(); ++pit) {
|
||||||
@ -75,11 +75,12 @@ Slic3rPolygon_to_ClipperPolygon(const Slic3r::Polygon &input, ClipperLib::Polygo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
void
|
void
|
||||||
Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output)
|
Slic3rPolygons_to_ClipperPolygons(const T &input, ClipperLib::Polygons &output)
|
||||||
{
|
{
|
||||||
output.clear();
|
output.clear();
|
||||||
for (Slic3r::Polygons::const_iterator it = input.begin(); it != input.end(); ++it) {
|
for (typename T::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);
|
||||||
@ -129,6 +130,38 @@ offset(Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float delta,
|
|||||||
delete output;
|
delete output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
offset(Slic3r::Polylines &polylines, ClipperLib::Polygons &retval, const float delta,
|
||||||
|
double scale, ClipperLib::JoinType joinType, double miterLimit)
|
||||||
|
{
|
||||||
|
// read input
|
||||||
|
ClipperLib::Polygons* input = new ClipperLib::Polygons();
|
||||||
|
Slic3rPolygons_to_ClipperPolygons(polylines, *input);
|
||||||
|
|
||||||
|
// scale input
|
||||||
|
scaleClipperPolygons(*input, scale);
|
||||||
|
|
||||||
|
// perform offset
|
||||||
|
ClipperLib::OffsetPaths(*input, retval, (delta*scale), joinType, ClipperLib::etButt, miterLimit);
|
||||||
|
delete input;
|
||||||
|
|
||||||
|
// unscale output
|
||||||
|
scaleClipperPolygons(retval, 1/scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
offset(Slic3r::Polylines &polylines, Slic3r::Polygons &retval, const float delta,
|
||||||
|
double scale, ClipperLib::JoinType joinType, double miterLimit)
|
||||||
|
{
|
||||||
|
// perform offset
|
||||||
|
ClipperLib::Polygons* output = new ClipperLib::Polygons();
|
||||||
|
offset(polylines, *output, delta, scale, joinType, miterLimit);
|
||||||
|
|
||||||
|
// convert into ExPolygons
|
||||||
|
ClipperPolygons_to_Slic3rPolygons(*output, retval);
|
||||||
|
delete output;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
|
offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
|
||||||
double scale, ClipperLib::JoinType joinType, double miterLimit)
|
double scale, ClipperLib::JoinType joinType, double miterLimit)
|
||||||
|
@ -21,20 +21,31 @@ 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(const Slic3r::Polygon &input, ClipperLib::Polygon &output);
|
void Slic3rPolygon_to_ClipperPolygon(const Slic3r::MultiPoint &input, ClipperLib::Polygon &output);
|
||||||
void Slic3rPolygons_to_ClipperPolygons(const Slic3r::Polygons &input, ClipperLib::Polygons &output);
|
template <class T>
|
||||||
|
void Slic3rPolygons_to_ClipperPolygons(const T &input, ClipperLib::Polygons &output);
|
||||||
void ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output);
|
void ClipperPolygon_to_Slic3rPolygon(const ClipperLib::Polygon &input, Slic3r::Polygon &output);
|
||||||
void ClipperPolygons_to_Slic3rPolygons(const ClipperLib::Polygons &input, Slic3r::Polygons &output);
|
void ClipperPolygons_to_Slic3rPolygons(const ClipperLib::Polygons &input, Slic3r::Polygons &output);
|
||||||
void ClipperPolygons_to_Slic3rExPolygons(const 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);
|
||||||
|
|
||||||
|
// offset Polygons
|
||||||
void offset(Slic3r::Polygons &polygons, ClipperLib::Polygons &retval, const float delta,
|
void offset(Slic3r::Polygons &polygons, ClipperLib::Polygons &retval, const float delta,
|
||||||
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||||
double miterLimit = 3);
|
double miterLimit = 3);
|
||||||
void offset(Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float delta,
|
void offset(Slic3r::Polygons &polygons, Slic3r::Polygons &retval, const float delta,
|
||||||
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||||
double miterLimit = 3);
|
double miterLimit = 3);
|
||||||
|
|
||||||
|
// offset Polylines
|
||||||
|
void offset(Slic3r::Polylines &polylines, ClipperLib::Polygons &retval, const float delta,
|
||||||
|
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
|
||||||
|
double miterLimit = 3);
|
||||||
|
void offset(Slic3r::Polylines &polylines, Slic3r::Polygons &retval, const float delta,
|
||||||
|
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtSquare,
|
||||||
|
double miterLimit = 3);
|
||||||
|
|
||||||
void offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
|
void offset_ex(Slic3r::Polygons &polygons, Slic3r::ExPolygons &retval, const float delta,
|
||||||
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
double scale = 100000, ClipperLib::JoinType joinType = ClipperLib::jtMiter,
|
||||||
double miterLimit = 3);
|
double miterLimit = 3);
|
||||||
|
4218
xs/src/clipper.cpp
4218
xs/src/clipper.cpp
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* Author : Angus Johnson *
|
* Author : Angus Johnson *
|
||||||
* Version : 5.1.5 *
|
* Version : 6.0.0 *
|
||||||
* Date : 4 May 2013 *
|
* Date : 30 October 2013 *
|
||||||
* Website : http://www.angusj.com *
|
* Website : http://www.angusj.com *
|
||||||
* Copyright : Angus Johnson 2010-2013 *
|
* Copyright : Angus Johnson 2010-2013 *
|
||||||
* *
|
* *
|
||||||
@ -34,11 +34,30 @@
|
|||||||
#ifndef clipper_hpp
|
#ifndef clipper_hpp
|
||||||
#define clipper_hpp
|
#define clipper_hpp
|
||||||
|
|
||||||
|
#define CLIPPER_VERSION "6.0.0"
|
||||||
|
|
||||||
|
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
||||||
|
//improve performance but coordinate values are limited to the range +/- 46340
|
||||||
|
//#define use_int32
|
||||||
|
|
||||||
|
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
|
||||||
|
//#define use_xyz
|
||||||
|
|
||||||
|
//use_lines: Enables line clipping. Adds a very minor cost to performance.
|
||||||
|
//#define use_lines
|
||||||
|
|
||||||
|
//When enabled, code developed with earlier versions of Clipper
|
||||||
|
//(ie prior to ver 6) should compile without changes.
|
||||||
|
//In a future update, this compatability code will be removed.
|
||||||
|
#define use_deprecated
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace ClipperLib {
|
namespace ClipperLib {
|
||||||
|
|
||||||
@ -50,23 +69,63 @@ enum PolyType { ptSubject, ptClip };
|
|||||||
//see http://glprogramming.com/red/chapter11.html
|
//see http://glprogramming.com/red/chapter11.html
|
||||||
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||||
|
|
||||||
typedef signed long long long64;
|
#ifdef use_int32
|
||||||
typedef unsigned long long ulong64;
|
typedef int cInt;
|
||||||
|
typedef unsigned int cUInt;
|
||||||
|
#else
|
||||||
|
typedef signed long long cInt;
|
||||||
|
typedef unsigned long long cUInt;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct IntPoint {
|
struct IntPoint {
|
||||||
public:
|
cInt X;
|
||||||
long64 X;
|
cInt Y;
|
||||||
long64 Y;
|
#ifdef use_xyz
|
||||||
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
|
cInt Z;
|
||||||
friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
|
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
|
||||||
|
#else
|
||||||
|
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
|
||||||
|
{
|
||||||
|
return a.X == b.X && a.Y == b.Y;
|
||||||
|
}
|
||||||
|
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
|
||||||
|
{
|
||||||
|
return a.X != b.X || a.Y != b.Y;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef std::vector< IntPoint > Polygon;
|
typedef std::vector< IntPoint > Path;
|
||||||
typedef std::vector< Polygon > Polygons;
|
typedef std::vector< Path > Paths;
|
||||||
|
|
||||||
|
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
|
||||||
|
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
|
||||||
|
|
||||||
std::ostream& operator <<(std::ostream &s, Polygon &p);
|
std::ostream& operator <<(std::ostream &s, const IntPoint &p);
|
||||||
std::ostream& operator <<(std::ostream &s, Polygons &p);
|
std::ostream& operator <<(std::ostream &s, const Path &p);
|
||||||
|
std::ostream& operator <<(std::ostream &s, const Paths &p);
|
||||||
|
|
||||||
|
#ifdef use_deprecated
|
||||||
|
typedef signed long long long64; //backward compatibility only
|
||||||
|
typedef Path Polygon;
|
||||||
|
typedef Paths Polygons;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct DoublePoint
|
||||||
|
{
|
||||||
|
double X;
|
||||||
|
double Y;
|
||||||
|
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
|
||||||
|
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
|
||||||
|
};
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef use_xyz
|
||||||
|
typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
|
||||||
|
#endif
|
||||||
|
|
||||||
class PolyNode;
|
class PolyNode;
|
||||||
typedef std::vector< PolyNode* > PolyNodes;
|
typedef std::vector< PolyNode* > PolyNodes;
|
||||||
@ -75,13 +134,15 @@ class PolyNode
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PolyNode();
|
PolyNode();
|
||||||
Polygon Contour;
|
Path Contour;
|
||||||
PolyNodes Childs;
|
PolyNodes Childs;
|
||||||
PolyNode* Parent;
|
PolyNode* Parent;
|
||||||
PolyNode* GetNext() const;
|
PolyNode* GetNext() const;
|
||||||
bool IsHole() const;
|
bool IsHole() const;
|
||||||
|
bool IsOpen() const;
|
||||||
int ChildCount() const;
|
int ChildCount() const;
|
||||||
private:
|
private:
|
||||||
|
bool m_IsOpen;
|
||||||
PolyNode* GetNextSiblingUp() const;
|
PolyNode* GetNextSiblingUp() const;
|
||||||
unsigned Index; //node index in Parent.Childs
|
unsigned Index; //node index in Parent.Childs
|
||||||
void AddChild(PolyNode& child);
|
void AddChild(PolyNode& child);
|
||||||
@ -100,112 +161,62 @@ private:
|
|||||||
friend class Clipper; //to access AllNodes
|
friend class Clipper; //to access AllNodes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
||||||
enum JoinType {jtSquare, jtRound, jtMiter};
|
enum JoinType {jtSquare, jtRound, jtMiter};
|
||||||
|
enum EndType {etClosed, etButt, etSquare, etRound};
|
||||||
|
|
||||||
bool Orientation(const Polygon &poly);
|
bool Orientation(const Path &poly);
|
||||||
double Area(const Polygon &poly);
|
double Area(const Path &poly);
|
||||||
|
|
||||||
|
#ifdef use_deprecated
|
||||||
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
|
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
|
||||||
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
|
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
|
||||||
|
void PolyTreeToPolygons(const PolyTree& polytree, Paths& paths);
|
||||||
|
void ReversePolygon(Path& p);
|
||||||
|
void ReversePolygons(Paths& p);
|
||||||
|
#endif
|
||||||
|
|
||||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
|
||||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
double delta, JoinType jointype, EndType endtype, double limit = 0);
|
||||||
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
|
|
||||||
|
|
||||||
void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance = 1.415);
|
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||||
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance = 1.415);
|
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||||
|
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
||||||
|
|
||||||
void PolyTreeToPolygons(PolyTree& polytree, Polygons& polygons);
|
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
||||||
|
void CleanPolygon(Path& poly, double distance = 1.415);
|
||||||
|
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
|
||||||
|
void CleanPolygons(Paths& polys, double distance = 1.415);
|
||||||
|
|
||||||
void ReversePolygon(Polygon& p);
|
void MinkowkiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
|
||||||
void ReversePolygons(Polygons& p);
|
void MinkowkiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
|
||||||
|
|
||||||
//used internally ...
|
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
|
||||||
|
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
|
||||||
|
void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
|
||||||
|
|
||||||
|
void ReversePath(Path& p);
|
||||||
|
void ReversePaths(Paths& p);
|
||||||
|
|
||||||
|
struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
|
||||||
|
|
||||||
|
//enums that are used internally ...
|
||||||
enum EdgeSide { esLeft = 1, esRight = 2};
|
enum EdgeSide { esLeft = 1, esRight = 2};
|
||||||
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
|
|
||||||
|
|
||||||
struct TEdge {
|
//forward declarations (for stuff used internally) ...
|
||||||
long64 xbot;
|
struct TEdge;
|
||||||
long64 ybot;
|
struct IntersectNode;
|
||||||
long64 xcurr;
|
struct LocalMinima;
|
||||||
long64 ycurr;
|
struct Scanbeam;
|
||||||
long64 xtop;
|
struct OutPt;
|
||||||
long64 ytop;
|
struct OutRec;
|
||||||
double dx;
|
struct Join;
|
||||||
long64 deltaX;
|
|
||||||
long64 deltaY;
|
|
||||||
PolyType polyType;
|
|
||||||
EdgeSide side;
|
|
||||||
int windDelta; //1 or -1 depending on winding direction
|
|
||||||
int windCnt;
|
|
||||||
int windCnt2; //winding count of the opposite polytype
|
|
||||||
int outIdx;
|
|
||||||
TEdge *next;
|
|
||||||
TEdge *prev;
|
|
||||||
TEdge *nextInLML;
|
|
||||||
TEdge *nextInAEL;
|
|
||||||
TEdge *prevInAEL;
|
|
||||||
TEdge *nextInSEL;
|
|
||||||
TEdge *prevInSEL;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IntersectNode {
|
|
||||||
TEdge *edge1;
|
|
||||||
TEdge *edge2;
|
|
||||||
IntPoint pt;
|
|
||||||
IntersectNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LocalMinima {
|
|
||||||
long64 Y;
|
|
||||||
TEdge *leftBound;
|
|
||||||
TEdge *rightBound;
|
|
||||||
LocalMinima *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Scanbeam {
|
|
||||||
long64 Y;
|
|
||||||
Scanbeam *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OutPt; //forward declaration
|
|
||||||
|
|
||||||
struct OutRec {
|
|
||||||
int idx;
|
|
||||||
bool isHole;
|
|
||||||
OutRec *FirstLeft; //see comments in clipper.pas
|
|
||||||
PolyNode *polyNode;
|
|
||||||
OutPt *pts;
|
|
||||||
OutPt *bottomPt;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OutPt {
|
|
||||||
int idx;
|
|
||||||
IntPoint pt;
|
|
||||||
OutPt *next;
|
|
||||||
OutPt *prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JoinRec {
|
|
||||||
IntPoint pt1a;
|
|
||||||
IntPoint pt1b;
|
|
||||||
int poly1Idx;
|
|
||||||
IntPoint pt2a;
|
|
||||||
IntPoint pt2b;
|
|
||||||
int poly2Idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HorzJoinRec {
|
|
||||||
TEdge *edge;
|
|
||||||
int savedIdx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
|
|
||||||
|
|
||||||
typedef std::vector < OutRec* > PolyOutList;
|
typedef std::vector < OutRec* > PolyOutList;
|
||||||
typedef std::vector < TEdge* > EdgeList;
|
typedef std::vector < TEdge* > EdgeList;
|
||||||
typedef std::vector < JoinRec* > JoinList;
|
typedef std::vector < Join* > JoinList;
|
||||||
typedef std::vector < HorzJoinRec* > HorzJoinList;
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
//ClipperBase is the ancestor to the Clipper class. It should not be
|
//ClipperBase is the ancestor to the Clipper class. It should not be
|
||||||
//instantiated directly. This class simply abstracts the conversion of sets of
|
//instantiated directly. This class simply abstracts the conversion of sets of
|
||||||
@ -215,29 +226,43 @@ class ClipperBase
|
|||||||
public:
|
public:
|
||||||
ClipperBase();
|
ClipperBase();
|
||||||
virtual ~ClipperBase();
|
virtual ~ClipperBase();
|
||||||
bool AddPolygon(const Polygon &pg, PolyType polyType);
|
bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
|
||||||
bool AddPolygons( const Polygons &ppg, PolyType polyType);
|
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
||||||
|
|
||||||
|
#ifdef use_deprecated
|
||||||
|
bool AddPolygon(const Path &pg, PolyType PolyTyp);
|
||||||
|
bool AddPolygons(const Paths &ppg, PolyType PolyTyp);
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void Clear();
|
virtual void Clear();
|
||||||
IntRect GetBounds();
|
IntRect GetBounds();
|
||||||
|
bool PreserveCollinear() {return m_PreserveCollinear;};
|
||||||
|
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
|
||||||
protected:
|
protected:
|
||||||
void DisposeLocalMinimaList();
|
void DisposeLocalMinimaList();
|
||||||
TEdge* AddBoundsToLML(TEdge *e);
|
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
|
||||||
void PopLocalMinima();
|
void PopLocalMinima();
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
void InsertLocalMinima(LocalMinima *newLm);
|
void InsertLocalMinima(LocalMinima *newLm);
|
||||||
|
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
|
||||||
|
TEdge* DescendToMin(TEdge *&E);
|
||||||
|
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
|
||||||
LocalMinima *m_CurrentLM;
|
LocalMinima *m_CurrentLM;
|
||||||
LocalMinima *m_MinimaList;
|
LocalMinima *m_MinimaList;
|
||||||
bool m_UseFullRange;
|
bool m_UseFullRange;
|
||||||
EdgeList m_edges;
|
EdgeList m_edges;
|
||||||
|
bool m_PreserveCollinear;
|
||||||
|
bool m_HasOpenPaths;
|
||||||
};
|
};
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Clipper : public virtual ClipperBase
|
class Clipper : public virtual ClipperBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Clipper();
|
Clipper(int initOptions = 0);
|
||||||
~Clipper();
|
~Clipper();
|
||||||
bool Execute(ClipType clipType,
|
bool Execute(ClipType clipType,
|
||||||
Polygons &solution,
|
Paths &solution,
|
||||||
PolyFillType subjFillType = pftEvenOdd,
|
PolyFillType subjFillType = pftEvenOdd,
|
||||||
PolyFillType clipFillType = pftEvenOdd);
|
PolyFillType clipFillType = pftEvenOdd);
|
||||||
bool Execute(ClipType clipType,
|
bool Execute(ClipType clipType,
|
||||||
@ -247,17 +272,21 @@ public:
|
|||||||
void Clear();
|
void Clear();
|
||||||
bool ReverseSolution() {return m_ReverseOutput;};
|
bool ReverseSolution() {return m_ReverseOutput;};
|
||||||
void ReverseSolution(bool value) {m_ReverseOutput = value;};
|
void ReverseSolution(bool value) {m_ReverseOutput = value;};
|
||||||
bool ForceSimple() {return m_ForceSimple;};
|
bool StrictlySimple() {return m_StrictSimple;};
|
||||||
void ForceSimple(bool value) {m_ForceSimple = value;};
|
void StrictlySimple(bool value) {m_StrictSimple = value;};
|
||||||
|
//set the callback function for z value filling on intersections (otherwise Z is 0)
|
||||||
|
#ifdef use_xyz
|
||||||
|
void ZFillFunction(TZFillCallback zFillFunc);
|
||||||
|
#endif
|
||||||
protected:
|
protected:
|
||||||
void Reset();
|
void Reset();
|
||||||
virtual bool ExecuteInternal();
|
virtual bool ExecuteInternal();
|
||||||
private:
|
private:
|
||||||
PolyOutList m_PolyOuts;
|
PolyOutList m_PolyOuts;
|
||||||
JoinList m_Joins;
|
JoinList m_Joins;
|
||||||
HorzJoinList m_HorizJoins;
|
JoinList m_GhostJoins;
|
||||||
ClipType m_ClipType;
|
ClipType m_ClipType;
|
||||||
Scanbeam *m_Scanbeam;
|
std::set< cInt, std::greater<cInt> > m_Scanbeam;
|
||||||
TEdge *m_ActiveEdges;
|
TEdge *m_ActiveEdges;
|
||||||
TEdge *m_SortedEdges;
|
TEdge *m_SortedEdges;
|
||||||
IntersectNode *m_IntersectNodes;
|
IntersectNode *m_IntersectNodes;
|
||||||
@ -266,15 +295,17 @@ private:
|
|||||||
PolyFillType m_SubjFillType;
|
PolyFillType m_SubjFillType;
|
||||||
bool m_ReverseOutput;
|
bool m_ReverseOutput;
|
||||||
bool m_UsingPolyTree;
|
bool m_UsingPolyTree;
|
||||||
bool m_ForceSimple;
|
bool m_StrictSimple;
|
||||||
void DisposeScanbeamList();
|
#ifdef use_xyz
|
||||||
|
TZFillCallback m_ZFill; //custom callback
|
||||||
|
#endif
|
||||||
void SetWindingCount(TEdge& edge);
|
void SetWindingCount(TEdge& edge);
|
||||||
bool IsEvenOddFillType(const TEdge& edge) const;
|
bool IsEvenOddFillType(const TEdge& edge) const;
|
||||||
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
||||||
void InsertScanbeam(const long64 Y);
|
void InsertScanbeam(const cInt Y);
|
||||||
long64 PopScanbeam();
|
cInt PopScanbeam();
|
||||||
void InsertLocalMinimaIntoAEL(const long64 botY);
|
void InsertLocalMinimaIntoAEL(const cInt botY);
|
||||||
void InsertEdgeIntoAEL(TEdge *edge);
|
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
|
||||||
void AddEdgeToSEL(TEdge *edge);
|
void AddEdgeToSEL(TEdge *edge);
|
||||||
void CopyAELToSEL();
|
void CopyAELToSEL();
|
||||||
void DeleteFromSEL(TEdge *e);
|
void DeleteFromSEL(TEdge *e);
|
||||||
@ -282,27 +313,28 @@ private:
|
|||||||
void UpdateEdgeIntoAEL(TEdge *&e);
|
void UpdateEdgeIntoAEL(TEdge *&e);
|
||||||
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
|
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
|
||||||
bool IsContributing(const TEdge& edge) const;
|
bool IsContributing(const TEdge& edge) const;
|
||||||
bool IsTopHorz(const long64 XPos);
|
bool IsTopHorz(const cInt XPos);
|
||||||
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
|
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
|
||||||
void DoMaxima(TEdge *e, long64 topY);
|
void DoMaxima(TEdge *e);
|
||||||
void ProcessHorizontals();
|
void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
|
||||||
void ProcessHorizontal(TEdge *horzEdge);
|
void ProcessHorizontals(bool IsTopOfScanbeam);
|
||||||
|
void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
|
||||||
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||||
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||||
OutRec* GetOutRec(int idx);
|
OutRec* GetOutRec(int idx);
|
||||||
void AppendPolygon(TEdge *e1, TEdge *e2);
|
void AppendPolygon(TEdge *e1, TEdge *e2);
|
||||||
void IntersectEdges(TEdge *e1, TEdge *e2,
|
void IntersectEdges(TEdge *e1, TEdge *e2,
|
||||||
const IntPoint &pt, const IntersectProtects protects);
|
const IntPoint &pt, bool protect = false);
|
||||||
OutRec* CreateOutRec();
|
OutRec* CreateOutRec();
|
||||||
void AddOutPt(TEdge *e, const IntPoint &pt);
|
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
||||||
void DisposeAllPolyPts();
|
void DisposeAllOutRecs();
|
||||||
void DisposeOutRec(PolyOutList::size_type index);
|
void DisposeOutRec(PolyOutList::size_type index);
|
||||||
bool ProcessIntersections(const long64 botY, const long64 topY);
|
bool ProcessIntersections(const cInt botY, const cInt topY);
|
||||||
void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
void InsertIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||||
void BuildIntersectList(const long64 botY, const long64 topY);
|
void BuildIntersectList(const cInt botY, const cInt topY);
|
||||||
void ProcessIntersectList();
|
void ProcessIntersectList();
|
||||||
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
|
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
||||||
void BuildResult(Polygons& polys);
|
void BuildResult(Paths& polys);
|
||||||
void BuildResult2(PolyTree& polytree);
|
void BuildResult2(PolyTree& polytree);
|
||||||
void SetHoleState(TEdge *e, OutRec *outrec);
|
void SetHoleState(TEdge *e, OutRec *outrec);
|
||||||
void DisposeIntersectNodes();
|
void DisposeIntersectNodes();
|
||||||
@ -310,19 +342,19 @@ private:
|
|||||||
void FixupOutPolygon(OutRec &outrec);
|
void FixupOutPolygon(OutRec &outrec);
|
||||||
bool IsHole(TEdge *e);
|
bool IsHole(TEdge *e);
|
||||||
void FixHoleLinkage(OutRec &outrec);
|
void FixHoleLinkage(OutRec &outrec);
|
||||||
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
|
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
|
||||||
void ClearJoins();
|
void ClearJoins();
|
||||||
void AddHorzJoin(TEdge *e, int idx);
|
void ClearGhostJoins();
|
||||||
void ClearHorzJoins();
|
void AddGhostJoin(OutPt *op, const IntPoint offPt);
|
||||||
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
|
bool JoinPoints(const Join *j, OutPt *&p1, OutPt *&p2);
|
||||||
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
|
|
||||||
void JoinCommonEdges();
|
void JoinCommonEdges();
|
||||||
void DoSimplePolygons();
|
void DoSimplePolygons();
|
||||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||||
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
|
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||||
|
#ifdef use_xyz
|
||||||
|
void SetZ(IntPoint& pt, TEdge& e);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
class clipperException : public std::exception
|
class clipperException : public std::exception
|
||||||
|
@ -23,59 +23,59 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
|
|||||||
{
|
{
|
||||||
my $result = Slic3r::Geometry::Clipper::offset([ $square, $hole_in_square ], 5);
|
my $result = Slic3r::Geometry::Clipper::offset([ $square, $hole_in_square ], 5);
|
||||||
is_deeply [ map $_->pp, @$result ], [ [
|
is_deeply [ map $_->pp, @$result ], [ [
|
||||||
[205, 95],
|
|
||||||
[205, 205],
|
[205, 205],
|
||||||
[95, 205],
|
[95, 205],
|
||||||
[95, 95],
|
[95, 95],
|
||||||
|
[205, 95],
|
||||||
], [
|
], [
|
||||||
[155, 145],
|
|
||||||
[145, 145],
|
[145, 145],
|
||||||
[145, 155],
|
[145, 155],
|
||||||
[155, 155],
|
[155, 155],
|
||||||
|
[155, 145],
|
||||||
] ], 'offset';
|
] ], 'offset';
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $result = Slic3r::Geometry::Clipper::offset_ex([ @$expolygon ], 5);
|
my $result = Slic3r::Geometry::Clipper::offset_ex([ @$expolygon ], 5);
|
||||||
is_deeply $result->[0]->pp, [ [
|
is_deeply $result->[0]->pp, [ [
|
||||||
[205, 95],
|
|
||||||
[205, 205],
|
[205, 205],
|
||||||
[95, 205],
|
[95, 205],
|
||||||
[95, 95],
|
[95, 95],
|
||||||
|
[205, 95],
|
||||||
], [
|
], [
|
||||||
[145, 145],
|
|
||||||
[145, 155],
|
[145, 155],
|
||||||
[155, 155],
|
[155, 155],
|
||||||
[155, 145],
|
[155, 145],
|
||||||
|
[145, 145],
|
||||||
] ], 'offset_ex';
|
] ], 'offset_ex';
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon ], 5, -2);
|
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon ], 5, -2);
|
||||||
is_deeply $result->[0]->pp, [ [
|
is_deeply $result->[0]->pp, [ [
|
||||||
[203, 97],
|
|
||||||
[203, 203],
|
[203, 203],
|
||||||
[97, 203],
|
[97, 203],
|
||||||
[97, 97],
|
[97, 97],
|
||||||
|
[203, 97],
|
||||||
], [
|
], [
|
||||||
[143, 143],
|
|
||||||
[143, 157],
|
[143, 157],
|
||||||
[157, 157],
|
[157, 157],
|
||||||
[157, 143],
|
[157, 143],
|
||||||
|
[143, 143],
|
||||||
] ], 'offset2_ex';
|
] ], 'offset2_ex';
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $expolygon2 = Slic3r::ExPolygon->new([
|
my $expolygon2 = Slic3r::ExPolygon->new([
|
||||||
[20000000, 0],
|
|
||||||
[20000000, 20000000],
|
[20000000, 20000000],
|
||||||
[0, 20000000],
|
[0, 20000000],
|
||||||
[0, 0],
|
[0, 0],
|
||||||
|
[20000000, 0],
|
||||||
], [
|
], [
|
||||||
[5000000, 5000000],
|
|
||||||
[5000000, 15000000],
|
[5000000, 15000000],
|
||||||
[15000000, 15000000],
|
[15000000, 15000000],
|
||||||
[15000000, 5000000],
|
[15000000, 5000000],
|
||||||
|
[5000000, 5000000],
|
||||||
]);
|
]);
|
||||||
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon2 ], -1, +1);
|
my $result = Slic3r::Geometry::Clipper::offset2_ex([ @$expolygon2 ], -1, +1);
|
||||||
is_deeply $result->[0]->pp, $expolygon2->pp, 'offset2_ex';
|
is_deeply $result->[0]->pp, $expolygon2->pp, 'offset2_ex';
|
||||||
@ -85,7 +85,7 @@ my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square);
|
|||||||
my $polygon1 = Slic3r::Polygon->new(@$square);
|
my $polygon1 = Slic3r::Polygon->new(@$square);
|
||||||
my $polygon2 = Slic3r::Polygon->new(reverse @$hole_in_square);
|
my $polygon2 = Slic3r::Polygon->new(reverse @$hole_in_square);
|
||||||
my $result = Slic3r::Geometry::Clipper::diff_ex([$polygon1], [$polygon2]);
|
my $result = Slic3r::Geometry::Clipper::diff_ex([$polygon1], [$polygon2]);
|
||||||
is_deeply $result->[0]->pp, $expolygon->pp, 'diff_ex';
|
is $result->[0]->area, $expolygon->area, 'diff_ex';
|
||||||
}
|
}
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
#include <myinit.h>
|
#include <myinit.h>
|
||||||
|
#include "ClipperUtils.hpp"
|
||||||
#include "Polyline.hpp"
|
#include "Polyline.hpp"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
@ -68,5 +69,18 @@ Polyline::rotate(angle, center_sv)
|
|||||||
center.from_SV_check(center_sv);
|
center.from_SV_check(center_sv);
|
||||||
THIS->rotate(angle, ¢er);
|
THIS->rotate(angle, ¢er);
|
||||||
|
|
||||||
|
Polygons
|
||||||
|
Polyline::grow(delta, scale = CLIPPER_OFFSET_SCALE, joinType = ClipperLib::jtSquare, miterLimit = 3)
|
||||||
|
const float delta
|
||||||
|
double scale
|
||||||
|
ClipperLib::JoinType joinType
|
||||||
|
double miterLimit
|
||||||
|
CODE:
|
||||||
|
Polylines polylines;
|
||||||
|
polylines.push_back(*THIS);
|
||||||
|
offset(polylines, RETVAL, delta, scale, joinType, miterLimit);
|
||||||
|
OUTPUT:
|
||||||
|
RETVAL
|
||||||
|
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user