From 576c167bd52ea4f377a83c093be9d927a7cd2c75 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 4 May 2022 18:21:08 +0200 Subject: [PATCH] Ported "avoid crossing perimeters" and bridging unit tests from Perl to C++. Further reduced Perl bindings. Got rid of the ExPolygonCollection wrapper, replaced with ExPolygons. --- lib/Slic3r/ExPolygon.pm | 7 - lib/Slic3r/Geometry.pm | 170 ------------------ src/libslic3r/CMakeLists.txt | 2 - src/libslic3r/ClipperUtils.cpp | 6 +- src/libslic3r/ClipperUtils.hpp | 16 +- src/libslic3r/EdgeGrid.cpp | 5 - src/libslic3r/EdgeGrid.hpp | 5 +- src/libslic3r/ExPolygon.hpp | 2 +- src/libslic3r/ExPolygonCollection.cpp | 136 -------------- src/libslic3r/ExPolygonCollection.hpp | 41 ----- src/libslic3r/ExtrusionEntity.cpp | 10 +- src/libslic3r/ExtrusionEntity.hpp | 11 +- src/libslic3r/GCode.cpp | 2 +- src/libslic3r/Geometry.cpp | 7 - src/libslic3r/Geometry.hpp | 1 - src/libslic3r/Geometry/ConvexHull.cpp | 11 ++ src/libslic3r/Geometry/ConvexHull.hpp | 1 + src/libslic3r/Layer.hpp | 5 +- src/libslic3r/Polyline.cpp | 1 - src/libslic3r/SLA/SupportPointGenerator.cpp | 7 +- src/libslic3r/SupportMaterial.cpp | 2 +- t/angles.t | 93 ---------- t/avoid_crossing_perimeters.t | 22 --- t/bridges.t | 137 -------------- t/collinear.t | 87 --------- t/geometry.t | 64 +------ tests/fff_print/CMakeLists.txt | 2 + .../test_avoid_crossing_perimeters.cpp | 16 ++ tests/fff_print/test_bridges.cpp | 133 ++++++++++++++ tests/fff_print/test_fill.cpp | 3 +- tests/libslic3r/test_clipper_utils.cpp | 2 +- xs/CMakeLists.txt | 2 - xs/lib/Slic3r/XS.pm | 7 - xs/src/perlglue.cpp | 2 - xs/t/04_expolygon.t | 26 +-- xs/xsp/BridgeDetector.xsp | 43 ----- xs/xsp/ExPolygonCollection.xsp | 81 --------- xs/xsp/ExtrusionPath.xsp | 16 -- xs/xsp/Geometry.xsp | 8 - xs/xsp/Layer.xsp | 4 - xs/xsp/my.map | 8 - xs/xsp/typemap.xspt | 6 - 42 files changed, 204 insertions(+), 1006 deletions(-) delete mode 100644 src/libslic3r/ExPolygonCollection.cpp delete mode 100644 src/libslic3r/ExPolygonCollection.hpp delete mode 100644 t/angles.t delete mode 100644 t/avoid_crossing_perimeters.t delete mode 100644 t/bridges.t delete mode 100644 t/collinear.t create mode 100644 tests/fff_print/test_avoid_crossing_perimeters.cpp create mode 100644 tests/fff_print/test_bridges.cpp delete mode 100644 xs/xsp/BridgeDetector.xsp delete mode 100644 xs/xsp/ExPolygonCollection.xsp diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 6090a073b..1b55849eb 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -9,11 +9,4 @@ sub bounding_box { return $self->contour->bounding_box; } -package Slic3r::ExPolygon::Collection; - -sub size { - my $self = shift; - return [ Slic3r::Geometry::size_2D([ map @$_, map @$_, @$self ]) ]; -} - 1; diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index ca262fc76..b3c57fcd0 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -9,13 +9,6 @@ our @ISA = qw(Exporter); our @EXPORT_OK = qw( PI epsilon - angle3points - collinear - dot - line_intersection - normalize - polyline_lines - polygon_is_convex scale unscale scaled_epsilon @@ -26,7 +19,6 @@ our @EXPORT_OK = qw( chained_path_from deg2rad rad2deg - rad2deg_dir ); use constant PI => 4 * atan2(1, 1); @@ -43,136 +35,6 @@ sub scaled_epsilon () { epsilon / &Slic3r::SCALING_FACTOR } sub scale ($) { $_[0] / &Slic3r::SCALING_FACTOR } sub unscale ($) { $_[0] * &Slic3r::SCALING_FACTOR } -# used by geometry.t -sub polyline_lines { - my ($polyline) = @_; - my @points = @$polyline; - return map Slic3r::Line->new(@points[$_, $_+1]), 0 .. $#points-1; -} - -# polygon must be simple (non complex) and ccw -sub polygon_is_convex { - my ($points) = @_; - for (my $i = 0; $i <= $#$points; $i++) { - my $angle = angle3points($points->[$i-1], $points->[$i-2], $points->[$i]); - return 0 if $angle < PI; - } - return 1; -} - -sub normalize { - my ($line) = @_; - - my $len = sqrt( ($line->[X]**2) + ($line->[Y]**2) + ($line->[Z]**2) ) - or return [0, 0, 0]; # to avoid illegal division by zero - return [ map $_ / $len, @$line ]; -} - -# 2D dot product -# used by 3DScene.pm -sub dot { - my ($u, $v) = @_; - return $u->[X] * $v->[X] + $u->[Y] * $v->[Y]; -} - -sub line_intersection { - my ($line1, $line2, $require_crossing) = @_; - $require_crossing ||= 0; - - my $intersection = _line_intersection(map @$_, @$line1, @$line2); - return (ref $intersection && $intersection->[1] == $require_crossing) - ? $intersection->[0] - : undef; -} - -# Used by test cases. -sub collinear { - my ($line1, $line2, $require_overlapping) = @_; - my $intersection = _line_intersection(map @$_, @$line1, @$line2); - return 0 unless !ref($intersection) - && ($intersection eq 'parallel collinear' - || ($intersection eq 'parallel vertical' && abs($line1->[A][X] - $line2->[A][X]) < epsilon)); - - if ($require_overlapping) { - my @box_a = bounding_box([ $line1->[0], $line1->[1] ]); - my @box_b = bounding_box([ $line2->[0], $line2->[1] ]); - return 0 unless bounding_box_intersect( 2, @box_a, @box_b ); - } - - return 1; -} - -sub _line_intersection { - my ( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 ) = @_; - - my ($x, $y); # The as-yet-undetermined intersection point. - - my $dy10 = $y1 - $y0; # dyPQ, dxPQ are the coordinate differences - my $dx10 = $x1 - $x0; # between the points P and Q. - my $dy32 = $y3 - $y2; - my $dx32 = $x3 - $x2; - - my $dy10z = abs( $dy10 ) < epsilon; # Is the difference $dy10 "zero"? - my $dx10z = abs( $dx10 ) < epsilon; - my $dy32z = abs( $dy32 ) < epsilon; - my $dx32z = abs( $dx32 ) < epsilon; - - my $dyx10; # The slopes. - my $dyx32; - - $dyx10 = $dy10 / $dx10 unless $dx10z; - $dyx32 = $dy32 / $dx32 unless $dx32z; - - # Now we know all differences and the slopes; - # we can detect horizontal/vertical special cases. - # E.g., slope = 0 means a horizontal line. - - unless ( defined $dyx10 or defined $dyx32 ) { - return "parallel vertical"; - } - elsif ( $dy10z and not $dy32z ) { # First line horizontal. - $y = $y0; - $x = $x2 + ( $y - $y2 ) * $dx32 / $dy32; - } - elsif ( not $dy10z and $dy32z ) { # Second line horizontal. - $y = $y2; - $x = $x0 + ( $y - $y0 ) * $dx10 / $dy10; - } - elsif ( $dx10z and not $dx32z ) { # First line vertical. - $x = $x0; - $y = $y2 + $dyx32 * ( $x - $x2 ); - } - elsif ( not $dx10z and $dx32z ) { # Second line vertical. - $x = $x2; - $y = $y0 + $dyx10 * ( $x - $x0 ); - } - elsif ( abs( $dyx10 - $dyx32 ) < epsilon ) { - # The slopes are suspiciously close to each other. - # Either we have parallel collinear or just parallel lines. - - # The bounding box checks have already weeded the cases - # "parallel horizontal" and "parallel vertical" away. - - my $ya = $y0 - $dyx10 * $x0; - my $yb = $y2 - $dyx32 * $x2; - - return "parallel collinear" if abs( $ya - $yb ) < epsilon; - return "parallel"; - } - else { - # None of the special cases matched. - # We have a "honest" line intersection. - - $x = ($y2 - $y0 + $dyx10*$x0 - $dyx32*$x2)/($dyx10 - $dyx32); - $y = $y0 + $dyx10 * ($x - $x0); - } - - my $h10 = $dx10 ? ($x - $x0) / $dx10 : ($dy10 ? ($y - $y0) / $dy10 : 1); - my $h32 = $dx32 ? ($x - $x2) / $dx32 : ($dy32 ? ($y - $y2) / $dy32 : 1); - - return [Slic3r::Point->new($x, $y), $h10 >= 0 && $h10 <= 1 && $h32 >= 0 && $h32 <= 1]; -} - # 2D sub bounding_box { my ($points) = @_; @@ -199,36 +61,4 @@ sub size_2D { ); } -# Used by sub collinear, which is used by test cases. -# bounding_box_intersect($d, @a, @b) -# Return true if the given bounding boxes @a and @b intersect -# in $d dimensions. Used by sub collinear. -sub bounding_box_intersect { - my ( $d, @bb ) = @_; # Number of dimensions and box coordinates. - my @aa = splice( @bb, 0, 2 * $d ); # The first box. - # (@bb is the second one.) - - # Must intersect in all dimensions. - for ( my $i_min = 0; $i_min < $d; $i_min++ ) { - my $i_max = $i_min + $d; # The index for the maximum. - return 0 if ( $aa[ $i_max ] + epsilon ) < $bb[ $i_min ]; - return 0 if ( $bb[ $i_max ] + epsilon ) < $aa[ $i_min ]; - } - - return 1; -} - -# Used by test cases. -# this assumes a CCW rotation from $p2 to $p3 around $p1 -sub angle3points { - my ($p1, $p2, $p3) = @_; - # p1 is the center - - my $angle = atan2($p2->[X] - $p1->[X], $p2->[Y] - $p1->[Y]) - - atan2($p3->[X] - $p1->[X], $p3->[Y] - $p1->[Y]); - - # we only want to return only positive angles - return $angle <= 0 ? $angle + 2*PI() : $angle; -} - 1; diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 643afe69e..d2ecefb9c 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -40,8 +40,6 @@ set(SLIC3R_SOURCES enum_bitmask.hpp ExPolygon.cpp ExPolygon.hpp - ExPolygonCollection.cpp - ExPolygonCollection.hpp Extruder.cpp Extruder.hpp ExtrusionEntity.cpp diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 25454d500..5c4b5ac17 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -240,7 +240,7 @@ TResult clipper_union( // Perform union of input polygons using the positive rule, convert to ExPolygons. //FIXME is there any benefit of not doing the boolean / using pftEvenOdd? -ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union) +inline ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union) { return PolyTreeToExPolygons(clipper_union(input, do_union ? ClipperLib::pftNonZero : ClipperLib::pftEvenOdd)); } @@ -438,7 +438,7 @@ Slic3r::Polygons offset(const Slic3r::SurfacesPtr &surfaces, const float delta, { return to_polygons(expolygons_offset(surfaces, delta, joinType, miterLimit)); } Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType, double miterLimit) //FIXME one may spare one Clipper Union call. - { return ClipperPaths_to_Slic3rExPolygons(expolygon_offset(expolygon, delta, joinType, miterLimit)); } + { return ClipperPaths_to_Slic3rExPolygons(expolygon_offset(expolygon, delta, joinType, miterLimit), /* do union */ false); } Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit) { return PolyTreeToExPolygons(expolygons_offset_pt(expolygons, delta, joinType, miterLimit)); } Slic3r::ExPolygons offset_ex(const Slic3r::Surfaces &surfaces, const float delta, ClipperLib::JoinType joinType, double miterLimit) @@ -713,6 +713,8 @@ Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r { return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::SinglePathProvider(clip.points)); } Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip) { return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::PolygonsProvider(clip)); } +Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip) + { return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::ExPolygonsProvider(clip)); } Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip) { return _clipper_pl_open(ClipperLib::ctIntersection, ClipperUtils::PolylinesProvider(subject), ClipperUtils::PolygonsProvider(clip)); } Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip) diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index d7027e0ec..484229f72 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -1,17 +1,27 @@ #ifndef slic3r_ClipperUtils_hpp_ #define slic3r_ClipperUtils_hpp_ +//#define SLIC3R_USE_CLIPPER2 + #include "libslic3r.h" -#include "clipper.hpp" #include "ExPolygon.hpp" #include "Polygon.hpp" #include "Surface.hpp" +#ifdef SLIC3R_USE_CLIPPER2 + +#include + +#else /* SLIC3R_USE_CLIPPER2 */ + +#include "clipper.hpp" // import these wherever we're included using Slic3r::ClipperLib::jtMiter; using Slic3r::ClipperLib::jtRound; using Slic3r::ClipperLib::jtSquare; +#endif /* SLIC3R_USE_CLIPPER2 */ + namespace Slic3r { static constexpr const float ClipperSafetyOffset = 10.f; @@ -298,9 +308,6 @@ namespace ClipperUtils { }; } -// Perform union of input polygons using the non-zero rule, convert to ExPolygons. -ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input, bool do_union = false); - // offset Polygons // Wherever applicable, please use the expand() / shrink() variants instead, they convey their purpose better. Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit); @@ -429,6 +436,7 @@ Slic3r::ExPolygons intersection_ex(const Slic3r::Surfaces &subject, const Slic3r Slic3r::ExPolygons intersection_ex(const Slic3r::SurfacesPtr &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No); Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygon &clip); Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::Polygons &clip); +Slic3r::Polylines intersection_pl(const Slic3r::Polyline &subject, const Slic3r::ExPolygons &clip); Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::Polygons &clip); Slic3r::Polylines intersection_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip); Slic3r::Polylines intersection_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip); diff --git a/src/libslic3r/EdgeGrid.cpp b/src/libslic3r/EdgeGrid.cpp index 1385a51d8..4985b788e 100644 --- a/src/libslic3r/EdgeGrid.cpp +++ b/src/libslic3r/EdgeGrid.cpp @@ -136,11 +136,6 @@ void EdgeGrid::Grid::create(const ExPolygons &expolygons, coord_t resolution) create_from_m_contours(resolution); } -void EdgeGrid::Grid::create(const ExPolygonCollection &expolygons, coord_t resolution) -{ - create(expolygons.expolygons, resolution); -} - // m_contours has been initialized. Now fill in the edge grid. void EdgeGrid::Grid::create_from_m_contours(coord_t resolution) { diff --git a/src/libslic3r/EdgeGrid.hpp b/src/libslic3r/EdgeGrid.hpp index 3c9929149..4be2bdd07 100644 --- a/src/libslic3r/EdgeGrid.hpp +++ b/src/libslic3r/EdgeGrid.hpp @@ -7,7 +7,6 @@ #include "Point.hpp" #include "BoundingBox.hpp" #include "ExPolygon.hpp" -#include "ExPolygonCollection.hpp" namespace Slic3r { namespace EdgeGrid { @@ -112,7 +111,6 @@ public: void create(const std::vector &polygons, coord_t resolution) { this->create(polygons, resolution, false); } void create(const ExPolygon &expoly, coord_t resolution); void create(const ExPolygons &expolygons, coord_t resolution); - void create(const ExPolygonCollection &expolygons, coord_t resolution); const std::vector& contours() const { return m_contours; } @@ -123,7 +121,6 @@ public: bool intersect(const Polygons &polygons) { for (size_t i = 0; i < polygons.size(); ++ i) if (intersect(polygons[i])) return true; return false; } bool intersect(const ExPolygon &expoly) { if (intersect(expoly.contour)) return true; for (size_t i = 0; i < expoly.holes.size(); ++ i) if (intersect(expoly.holes[i])) return true; return false; } bool intersect(const ExPolygons &expolygons) { for (size_t i = 0; i < expolygons.size(); ++ i) if (intersect(expolygons[i])) return true; return false; } - bool intersect(const ExPolygonCollection &expolygons) { return intersect(expolygons.expolygons); } // Test, whether a point is inside a contour. bool inside(const Point &pt); @@ -391,7 +388,7 @@ protected: // Referencing the source contours. // This format allows one to work with any Slic3r fixed point contour format - // (Polygon, ExPolygon, ExPolygonCollection etc). + // (Polygon, ExPolygon, ExPolygons etc). std::vector m_contours; // Referencing a contour and a line segment of m_contours. diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp index cbf6b1c1a..344450c4a 100644 --- a/src/libslic3r/ExPolygon.hpp +++ b/src/libslic3r/ExPolygon.hpp @@ -9,7 +9,7 @@ namespace Slic3r { class ExPolygon; -typedef std::vector ExPolygons; +using ExPolygons = std::vector; class ExPolygon { diff --git a/src/libslic3r/ExPolygonCollection.cpp b/src/libslic3r/ExPolygonCollection.cpp deleted file mode 100644 index a0de8f6de..000000000 --- a/src/libslic3r/ExPolygonCollection.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "ExPolygonCollection.hpp" -#include "Geometry/ConvexHull.hpp" -#include "BoundingBox.hpp" - -namespace Slic3r { - -ExPolygonCollection::ExPolygonCollection(const ExPolygon &expolygon) -{ - this->expolygons.push_back(expolygon); -} - -ExPolygonCollection::operator Points() const -{ - Points points; - Polygons pp = (Polygons)*this; - for (Polygons::const_iterator poly = pp.begin(); poly != pp.end(); ++poly) { - for (Points::const_iterator point = poly->points.begin(); point != poly->points.end(); ++point) - points.push_back(*point); - } - return points; -} - -ExPolygonCollection::operator Polygons() const -{ - Polygons polygons; - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) { - polygons.push_back(it->contour); - for (Polygons::const_iterator ith = it->holes.begin(); ith != it->holes.end(); ++ith) { - polygons.push_back(*ith); - } - } - return polygons; -} - -ExPolygonCollection::operator ExPolygons&() -{ - return this->expolygons; -} - -void -ExPolygonCollection::scale(double factor) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).scale(factor); - } -} - -void -ExPolygonCollection::translate(double x, double y) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).translate(x, y); - } -} - -void -ExPolygonCollection::rotate(double angle, const Point ¢er) -{ - for (ExPolygons::iterator it = expolygons.begin(); it != expolygons.end(); ++it) { - (*it).rotate(angle, center); - } -} - -template -bool ExPolygonCollection::contains(const T &item) const -{ - for (const ExPolygon &poly : this->expolygons) - if (poly.contains(item)) - return true; - return false; -} -template bool ExPolygonCollection::contains(const Point &item) const; -template bool ExPolygonCollection::contains(const Line &item) const; -template bool ExPolygonCollection::contains(const Polyline &item) const; - -bool -ExPolygonCollection::contains_b(const Point &point) const -{ - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) { - if (it->contains_b(point)) return true; - } - return false; -} - -void -ExPolygonCollection::simplify(double tolerance) -{ - ExPolygons expp; - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) { - it->simplify(tolerance, &expp); - } - this->expolygons = expp; -} - -Polygon -ExPolygonCollection::convex_hull() const -{ - Points pp; - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) - pp.insert(pp.end(), it->contour.points.begin(), it->contour.points.end()); - return Slic3r::Geometry::convex_hull(pp); -} - -Lines -ExPolygonCollection::lines() const -{ - Lines lines; - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) { - Lines ex_lines = it->lines(); - lines.insert(lines.end(), ex_lines.begin(), ex_lines.end()); - } - return lines; -} - -Polygons -ExPolygonCollection::contours() const -{ - Polygons contours; - contours.reserve(this->expolygons.size()); - for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it) - contours.push_back(it->contour); - return contours; -} - -void -ExPolygonCollection::append(const ExPolygons &expp) -{ - this->expolygons.insert(this->expolygons.end(), expp.begin(), expp.end()); -} - -BoundingBox get_extents(const ExPolygonCollection &expolygon) -{ - return get_extents(expolygon.expolygons); -} - -} diff --git a/src/libslic3r/ExPolygonCollection.hpp b/src/libslic3r/ExPolygonCollection.hpp deleted file mode 100644 index 35e1eef4e..000000000 --- a/src/libslic3r/ExPolygonCollection.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef slic3r_ExPolygonCollection_hpp_ -#define slic3r_ExPolygonCollection_hpp_ - -#include "libslic3r.h" -#include "ExPolygon.hpp" -#include "Line.hpp" -#include "Polyline.hpp" - -namespace Slic3r { - -class ExPolygonCollection; -typedef std::vector ExPolygonCollections; - -class ExPolygonCollection -{ -public: - ExPolygons expolygons; - - ExPolygonCollection() {} - explicit ExPolygonCollection(const ExPolygon &expolygon); - explicit ExPolygonCollection(const ExPolygons &expolygons) : expolygons(expolygons) {} - explicit operator Points() const; - explicit operator Polygons() const; - explicit operator ExPolygons&(); - void scale(double factor); - void translate(double x, double y); - void rotate(double angle, const Point ¢er); - template bool contains(const T &item) const; - bool contains_b(const Point &point) const; - void simplify(double tolerance); - Polygon convex_hull() const; - Lines lines() const; - Polygons contours() const; - void append(const ExPolygons &expolygons); -}; - -extern BoundingBox get_extents(const ExPolygonCollection &expolygon); - -} - -#endif diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index 7b2506a22..0c1165316 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -1,6 +1,6 @@ #include "ExtrusionEntity.hpp" #include "ExtrusionEntityCollection.hpp" -#include "ExPolygonCollection.hpp" +#include "ExPolygon.hpp" #include "ClipperUtils.hpp" #include "Extruder.hpp" #include "Flow.hpp" @@ -12,14 +12,14 @@ namespace Slic3r { -void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const +void ExtrusionPath::intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const { - this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection.expolygons), retval); + this->_inflate_collection(intersection_pl(Polylines{ polyline }, collection), retval); } -void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const +void ExtrusionPath::subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const { - this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection.expolygons), retval); + this->_inflate_collection(diff_pl(Polylines{ this->polyline }, collection), retval); } void ExtrusionPath::clip_end(double distance) diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 2e9e46789..52a8a563c 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -11,7 +11,8 @@ namespace Slic3r { -class ExPolygonCollection; +class ExPolygon; +using ExPolygons = std::vector; class ExtrusionEntityCollection; class Extruder; @@ -144,12 +145,12 @@ public: size_t size() const { return this->polyline.size(); } bool empty() const { return this->polyline.empty(); } bool is_closed() const { return ! this->empty() && this->polyline.points.front() == this->polyline.points.back(); } - // Produce a list of extrusion paths into retval by clipping this path by ExPolygonCollection. + // Produce a list of extrusion paths into retval by clipping this path by ExPolygons. // Currently not used. - void intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const; - // Produce a list of extrusion paths into retval by removing parts of this path by ExPolygonCollection. + void intersect_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const; + // Produce a list of extrusion paths into retval by removing parts of this path by ExPolygons. // Currently not used. - void subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const; + void subtract_expolygons(const ExPolygons &collection, ExtrusionEntityCollection* retval) const; void clip_end(double distance); void simplify(double tolerance); double length() const override; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 1a6ee4b80..aef83f21f 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3063,7 +3063,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role) if (role == erSupportMaterial) { const SupportLayer* support_layer = dynamic_cast(m_layer); //FIXME support_layer->support_islands.contains should use some search structure! - if (support_layer != NULL && support_layer->support_islands.contains(travel)) + if (support_layer != NULL && ! intersection_pl(travel, support_layer->support_islands).empty()) // skip retraction if this is a travel move inside a support material island //FIXME not retracting over a long path may cause oozing, which in turn may result in missing material // at the end of the extrusion path! diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 00fac6c38..6eae83277 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -50,13 +50,6 @@ bool contains(const std::vector &vector, const Point &point) } template bool contains(const ExPolygons &vector, const Point &point); -double rad2deg_dir(double angle) -{ - angle = (angle < PI) ? (-angle + PI/2.0) : (angle + PI/2.0); - if (angle < 0) angle += PI; - return rad2deg(angle); -} - void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval) { Polygons pp; diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 82ffbd8d1..2ca4ef884 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -291,7 +291,6 @@ bool directions_parallel(double angle1, double angle2, double max_diff = 0); bool directions_perpendicular(double angle1, double angle2, double max_diff = 0); template bool contains(const std::vector &vector, const Point &point); template T rad2deg(T angle) { return T(180.0) * angle / T(PI); } -double rad2deg_dir(double angle); template constexpr T deg2rad(const T angle) { return T(PI) * angle / T(180.0); } template T angle_to_0_2PI(T angle) { diff --git a/src/libslic3r/Geometry/ConvexHull.cpp b/src/libslic3r/Geometry/ConvexHull.cpp index 2e92535f2..9601069b5 100644 --- a/src/libslic3r/Geometry/ConvexHull.cpp +++ b/src/libslic3r/Geometry/ConvexHull.cpp @@ -104,6 +104,17 @@ Polygon convex_hull(const Polygons &polygons) return convex_hull(std::move(pp)); } +Polygon convex_hull(const ExPolygons &expolygons) +{ + Points pp; + size_t sz = 0; + for (const auto &expoly : expolygons) + sz += expoly.contour.size(); + pp.reserve(sz); + for (const auto &expoly : expolygons) + pp.insert(pp.end(), expoly.contour.points.begin(), expoly.contour.points.end()); + return convex_hull(pp); +} namespace rotcalip { diff --git a/src/libslic3r/Geometry/ConvexHull.hpp b/src/libslic3r/Geometry/ConvexHull.hpp index 03f00af6a..9ba957824 100644 --- a/src/libslic3r/Geometry/ConvexHull.hpp +++ b/src/libslic3r/Geometry/ConvexHull.hpp @@ -9,6 +9,7 @@ namespace Geometry { Pointf3s convex_hull(Pointf3s points); Polygon convex_hull(Points points); Polygon convex_hull(const Polygons &polygons); +Polygon convex_hull(const ExPolygons &expolygons); // Returns true if the intersection of the two convex polygons A and B // is not an empty set. diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 0fe4952f4..2e3affec7 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -5,10 +5,11 @@ #include "Flow.hpp" #include "SurfaceCollection.hpp" #include "ExtrusionEntityCollection.hpp" -#include "ExPolygonCollection.hpp" namespace Slic3r { +class ExPolygon; +using ExPolygons = std::vector; class Layer; using LayerPtrs = std::vector; class LayerRegion; @@ -191,7 +192,7 @@ class SupportLayer : public Layer public: // Polygons covered by the supports: base, interface and contact areas. // Used to suppress retraction if moving for a support extrusion over these support_islands. - ExPolygonCollection support_islands; + ExPolygons support_islands; // Extrusion paths for the support base and for the support interface and contacts. ExtrusionEntityCollection support_fills; diff --git a/src/libslic3r/Polyline.cpp b/src/libslic3r/Polyline.cpp index 43c5afe73..6994ef425 100644 --- a/src/libslic3r/Polyline.cpp +++ b/src/libslic3r/Polyline.cpp @@ -2,7 +2,6 @@ #include "Polyline.hpp" #include "Exception.hpp" #include "ExPolygon.hpp" -#include "ExPolygonCollection.hpp" #include "Line.hpp" #include "Polygon.hpp" #include diff --git a/src/libslic3r/SLA/SupportPointGenerator.cpp b/src/libslic3r/SLA/SupportPointGenerator.cpp index c32da0431..4c1af03eb 100644 --- a/src/libslic3r/SLA/SupportPointGenerator.cpp +++ b/src/libslic3r/SLA/SupportPointGenerator.cpp @@ -1,17 +1,14 @@ -//#include "igl/random_points_on_mesh.h" -//#include "igl/AABB.h" - #include #include "SupportPointGenerator.hpp" #include "Concurrency.hpp" +#include "Geometry/ConvexHull.hpp" #include "Model.hpp" #include "ExPolygon.hpp" #include "SVG.hpp" #include "Point.hpp" #include "ClipperUtils.hpp" #include "Tesselate.hpp" -#include "ExPolygonCollection.hpp" #include "MinAreaBoundingBox.hpp" #include "libslic3r.h" @@ -550,7 +547,7 @@ void SupportPointGenerator::uniformly_cover(const ExPolygons& islands, Structure // auto bb = get_extents(islands); if (flags & icfIsNew) { - auto chull = ExPolygonCollection{islands}.convex_hull(); + auto chull = Geometry::convex_hull(islands); auto rotbox = MinAreaBoundigBox{chull, MinAreaBoundigBox::pcConvex}; Vec2d bbdim = {unscaled(rotbox.width()), unscaled(rotbox.height())}; diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 195fc9e17..52cb177bb 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -4283,7 +4283,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( std::stable_sort(layer_cache_item.overlapping.begin(), layer_cache_item.overlapping.end(), [](auto *l1, auto *l2) { return *l1 < *l2; }); } if (! polys.empty()) - expolygons_append(support_layer.support_islands.expolygons, union_ex(polys)); + expolygons_append(support_layer.support_islands, union_ex(polys)); } // for each support_layer_id }); diff --git a/t/angles.t b/t/angles.t deleted file mode 100644 index 9dc690dea..000000000 --- a/t/angles.t +++ /dev/null @@ -1,93 +0,0 @@ -use Test::More; -use strict; -use warnings; - -plan tests => 34; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use Slic3r; -use Slic3r::Geometry qw(rad2deg_dir angle3points PI); - -#========================================================== - -{ - is line_atan([ [0, 0], [10, 0] ]), (0), 'E atan2'; - is line_atan([ [10, 0], [0, 0] ]), (PI), 'W atan2'; - is line_atan([ [0, 0], [0, 10] ]), (PI/2), 'N atan2'; - is line_atan([ [0, 10], [0, 0] ]), -(PI/2), 'S atan2'; - - is line_atan([ [10, 10], [0, 0] ]), -(PI*3/4), 'SW atan2'; - is line_atan([ [0, 0], [10, 10] ]), (PI*1/4), 'NE atan2'; - is line_atan([ [0, 10], [10, 0] ]), -(PI*1/4), 'SE atan2'; - is line_atan([ [10, 0], [0, 10] ]), (PI*3/4), 'NW atan2'; -} - -#========================================================== - -{ - is line_orientation([ [0, 0], [10, 0] ]), (0), 'E orientation'; - is line_orientation([ [0, 0], [0, 10] ]), (PI/2), 'N orientation'; - is line_orientation([ [10, 0], [0, 0] ]), (PI), 'W orientation'; - is line_orientation([ [0, 10], [0, 0] ]), (PI*3/2), 'S orientation'; - - is line_orientation([ [0, 0], [10, 10] ]), (PI*1/4), 'NE orientation'; - is line_orientation([ [10, 0], [0, 10] ]), (PI*3/4), 'NW orientation'; - is line_orientation([ [10, 10], [0, 0] ]), (PI*5/4), 'SW orientation'; - is line_orientation([ [0, 10], [10, 0] ]), (PI*7/4), 'SE orientation'; -} - -#========================================================== - -{ - is line_direction([ [0, 0], [10, 0] ]), (0), 'E direction'; - is line_direction([ [10, 0], [0, 0] ]), (0), 'W direction'; - is line_direction([ [0, 0], [0, 10] ]), (PI/2), 'N direction'; - is line_direction([ [0, 10], [0, 0] ]), (PI/2), 'S direction'; - - is line_direction([ [10, 10], [0, 0] ]), (PI*1/4), 'SW direction'; - is line_direction([ [0, 0], [10, 10] ]), (PI*1/4), 'NE direction'; - is line_direction([ [0, 10], [10, 0] ]), (PI*3/4), 'SE direction'; - is line_direction([ [10, 0], [0, 10] ]), (PI*3/4), 'NW direction'; -} - -#========================================================== - -{ - is rad2deg_dir(0), 90, 'E (degrees)'; - is rad2deg_dir(PI), 270, 'W (degrees)'; - is rad2deg_dir(PI/2), 0, 'N (degrees)'; - is rad2deg_dir(-(PI/2)), 180, 'S (degrees)'; - is rad2deg_dir(PI*1/4), 45, 'NE (degrees)'; - is rad2deg_dir(PI*3/4), 135, 'NW (degrees)'; - is rad2deg_dir(PI/6), 60, '30°'; - is rad2deg_dir(PI/6*2), 30, '60°'; -} - -#========================================================== - -{ - is angle3points([0,0], [10,0], [0,10]), PI/2, 'CW angle3points'; - is angle3points([0,0], [0,10], [10,0]), PI/2*3, 'CCW angle3points'; -} - -#========================================================== - -sub line_atan { - my ($l) = @_; - return Slic3r::Line->new(@$l)->atan2_; -} - -sub line_orientation { - my ($l) = @_; - return Slic3r::Line->new(@$l)->orientation; -} - -sub line_direction { - my ($l) = @_; - return Slic3r::Line->new(@$l)->direction; -} \ No newline at end of file diff --git a/t/avoid_crossing_perimeters.t b/t/avoid_crossing_perimeters.t deleted file mode 100644 index 86c3e91cb..000000000 --- a/t/avoid_crossing_perimeters.t +++ /dev/null @@ -1,22 +0,0 @@ -use Test::More tests => 1; -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use List::Util qw(first sum); -use Slic3r; -use Slic3r::Test; - -{ - my $config = Slic3r::Config::new_from_defaults; - $config->set('avoid_crossing_perimeters', 2); - my $print = Slic3r::Test::init_print('20mm_cube', config => $config, duplicate => 2); - ok my $gcode = Slic3r::Test::gcode($print), "no crash with avoid_crossing_perimeters and multiple objects"; -} - -__END__ diff --git a/t/bridges.t b/t/bridges.t deleted file mode 100644 index ca55862b6..000000000 --- a/t/bridges.t +++ /dev/null @@ -1,137 +0,0 @@ -use Test::More tests => 16; -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use List::Util qw(first sum); -use Slic3r; -use Slic3r::Geometry qw(scale epsilon deg2rad rad2deg); -use Slic3r::Test; - -{ - my $test = sub { - my ($bridge_size, $rotate, $expected_angle, $tolerance) = @_; - - my ($x, $y) = @$bridge_size; - my $lower = Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([-2,-2], [$x+2,-2], [$x+2,$y+2], [-2,$y+2]), - Slic3r::Polygon->new_scale([0,0], [0,$y], [$x,$y], [$x,0]), - ); - $lower->translate(scale 20, scale 20); # avoid negative coordinates for easier SVG preview - $lower->rotate(deg2rad($rotate), [$x/2,$y/2]); - my $bridge = $lower->[1]->clone; - $bridge->reverse; - $bridge = Slic3r::ExPolygon->new($bridge); - - ok check_angle([$lower], $bridge, $expected_angle, $tolerance), 'correct bridge angle for O-shaped overhang'; - }; - - $test->([20,10], 0, 90); - $test->([10,20], 0, 0); - $test->([20,10], 45, 135, 20); - $test->([20,10], 135, 45, 20); -} - -{ - my $bridge = Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([0,0], [20,0], [20,10], [0,10]), - ); - my $lower = [ - Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([-2,0], [0,0], [0,10], [-2,10]), - ), - ]; - $_->translate(scale 20, scale 20) for $bridge, @$lower; # avoid negative coordinates for easier SVG preview - - $lower->[1] = $lower->[0]->clone; - $lower->[1]->translate(scale 22, 0); - - ok check_angle($lower, $bridge, 0), 'correct bridge angle for two-sided bridge'; -} - -{ - my $bridge = Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([0,0], [20,0], [10,10], [0,10]), - ); - my $lower = [ - Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([0,0], [0,10], [10,10], [10,12], [-2,12], [-2,-2], [22,-2], [22,0]), - ), - ]; - $_->translate(scale 20, scale 20) for $bridge, @$lower; # avoid negative coordinates for easier SVG preview - - ok check_angle($lower, $bridge, 135), 'correct bridge angle for C-shaped overhang'; -} - -{ - my $bridge = Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([10,10],[20,10],[20,20], [10,20]), - ); - my $lower = [ - Slic3r::ExPolygon->new( - Slic3r::Polygon->new_scale([10,10],[10,20],[20,20],[30,30],[0,30],[0,0]), - ), - ]; - $_->translate(scale 20, scale 20) for $bridge, @$lower; # avoid negative coordinates for easier SVG preview - - ok check_angle($lower, $bridge, 45, undef, $bridge->area/2), 'correct bridge angle for square overhang with L-shaped anchors'; -} - -sub check_angle { - my ($lower, $bridge, $expected, $tolerance, $expected_coverage) = @_; - - if (ref($lower) eq 'ARRAY') { - $lower = Slic3r::ExPolygon::Collection->new(@$lower); - } - - $expected_coverage //= -1; - $expected_coverage = $bridge->area if $expected_coverage == -1; - - my $bd = Slic3r::BridgeDetector->new($bridge, $lower, scale 0.5); - - $tolerance //= rad2deg($bd->resolution) + epsilon; - $bd->detect_angle; - my $result = $bd->angle; - my $coverage = $bd->coverage; - is sum(map $_->area, @$coverage), $expected_coverage, 'correct coverage area'; - - # our epsilon is equal to the steps used by the bridge detection algorithm - ###use XXX; YYY [ rad2deg($result), $expected ]; - # returned value must be non-negative, check for that too - my $delta=rad2deg($result) - $expected; - $delta-=180 if $delta>=180 - epsilon; - return defined $result && $result>=0 && abs($delta) < $tolerance; -} - -{ - my $config = Slic3r::Config::new_from_defaults; - $config->set('top_solid_layers', 0); # to prevent bridging on sparse infill - $config->set('bridge_speed', 99); - - my $print = Slic3r::Test::init_print('bridge', config => $config); - - my %extrusions = (); # angle => length - Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { - my ($self, $cmd, $args, $info) = @_; - - if ($cmd eq 'G1' && ($args->{F} // $self->F)/60 == $config->bridge_speed) { - my $line = Slic3r::Line->new_scale( - [ $self->X, $self->Y ], - [ $info->{new_X}, $info->{new_Y} ], - ); - my $angle = $line->direction; - $extrusions{$angle} //= 0; - $extrusions{$angle} += $line->length; - } - }); - ok !!%extrusions, "bridge is generated"; - my ($main_angle) = sort { $extrusions{$b} <=> $extrusions{$a} } keys %extrusions; - is $main_angle, 0, "bridge has the expected direction"; -} - -__END__ diff --git a/t/collinear.t b/t/collinear.t deleted file mode 100644 index b28a3602c..000000000 --- a/t/collinear.t +++ /dev/null @@ -1,87 +0,0 @@ -use Test::More; -use strict; -use warnings; - -plan tests => 11; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use Slic3r; -use Slic3r::Geometry qw(collinear); - -#========================================================== - -{ - my @lines = ( - Slic3r::Line->new([0,4], [4,2]), - Slic3r::Line->new([2,3], [8,0]), - Slic3r::Line->new([6,1], [8,0]), - ); - is collinear($lines[0], $lines[1]), 1, 'collinear'; - is collinear($lines[1], $lines[2]), 1, 'collinear'; - is collinear($lines[0], $lines[2]), 1, 'collinear'; -} - -#========================================================== - -{ - # horizontal - my @lines = ( - Slic3r::Line->new([0,1], [5,1]), - Slic3r::Line->new([2,1], [8,1]), - ); - is collinear($lines[0], $lines[1]), 1, 'collinear'; -} - -#========================================================== - -{ - # vertical - my @lines = ( - Slic3r::Line->new([1,0], [1,5]), - Slic3r::Line->new([1,2], [1,8]), - ); - is collinear($lines[0], $lines[1]), 1, 'collinear'; -} - -#========================================================== - -{ - # non overlapping - my @lines = ( - Slic3r::Line->new([0,1], [5,1]), - Slic3r::Line->new([7,1], [10,1]), - ); - is collinear($lines[0], $lines[1], 1), 0, 'non overlapping'; - is collinear($lines[0], $lines[1], 0), 1, 'overlapping'; -} - -#========================================================== - -{ - # with one common point - my @lines = ( - Slic3r::Line->new([0,4], [4,2]), - Slic3r::Line->new([4,2], [8,0]), - ); - is collinear($lines[0], $lines[1], 1), 1, 'one common point'; - is collinear($lines[0], $lines[1], 0), 1, 'one common point'; -} - -#========================================================== - -{ - # not collinear - my @lines = ( - Slic3r::Line->new([290000000,690525600], [285163380,684761540]), - Slic3r::Line->new([285163380,684761540], [193267599,575244400]), - ); - is collinear($lines[0], $lines[1], 0), 0, 'not collinear'; - is collinear($lines[0], $lines[1], 1), 0, 'not collinear'; -} - -#========================================================== diff --git a/t/geometry.t b/t/geometry.t index 12a1ca743..981621ee8 100644 --- a/t/geometry.t +++ b/t/geometry.t @@ -2,7 +2,7 @@ use Test::More; use strict; use warnings; -plan tests => 26; +plan tests => 11; BEGIN { use FindBin; @@ -11,7 +11,7 @@ BEGIN { } use Slic3r; -use Slic3r::Geometry qw(PI polygon_is_convex +use Slic3r::Geometry qw(PI chained_path_from epsilon scale); { @@ -27,18 +27,6 @@ use Slic3r::Geometry qw(PI polygon_is_convex #========================================================== -my $line1 = [ [5, 15], [30, 15] ]; -my $line2 = [ [10, 20], [10, 10] ]; -is_deeply Slic3r::Geometry::line_intersection($line1, $line2, 1)->arrayref, [10, 15], 'line_intersection'; - -#========================================================== - -$line1 = [ [73.6310778185108/0.0000001, 371.74239268924/0.0000001], [73.6310778185108/0.0000001, 501.74239268924/0.0000001] ]; -$line2 = [ [75/0.0000001, 437.9853/0.0000001], [62.7484/0.0000001, 440.4223/0.0000001] ]; -isnt Slic3r::Geometry::line_intersection($line1, $line2, 1), undef, 'line_intersection'; - -#========================================================== - my $polygons = [ Slic3r::Polygon->new( # contour, ccw [45919000, 515273900], [14726100, 461246400], [14726100, 348753500], [33988700, 315389800], @@ -57,54 +45,6 @@ my $polygons = [ ), ]; -#========================================================== - -{ - my $p1 = [10, 10]; - my $p2 = [10, 20]; - my $p3 = [10, 30]; - my $p4 = [20, 20]; - my $p5 = [0, 20]; - - is Slic3r::Geometry::angle3points($p2, $p3, $p1), PI(), 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p1, $p3), PI(), 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p3, $p4), PI()/2*3, 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p4, $p3), PI()/2, 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p1, $p4), PI()/2, 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p1, $p5), PI()/2*3, 'angle3points'; -} - -{ - my $p1 = [30, 30]; - my $p2 = [20, 20]; - my $p3 = [10, 10]; - my $p4 = [30, 10]; - - is Slic3r::Geometry::angle3points($p2, $p1, $p3), PI(), 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p1, $p4), PI()/2*3, 'angle3points'; - is Slic3r::Geometry::angle3points($p2, $p1, $p1), 2*PI(), 'angle3points'; -} - -#========================================================== - -{ - my $cw_square = [ [0,0], [0,10], [10,10], [10,0] ]; - is polygon_is_convex($cw_square), 0, 'cw square is not convex'; - is polygon_is_convex([ reverse @$cw_square ]), 1, 'ccw square is convex'; - - my $convex1 = [ [0,0], [10,0], [10,10], [0,10], [0,6], [4,6], [4,4], [0,4] ]; - is polygon_is_convex($convex1), 0, 'concave polygon'; -} - -#========================================================== - -{ - my $polyline = Slic3r::Polyline->new([0, 0], [10, 0], [20, 0]); - is_deeply [ map $_->pp, @{$polyline->lines} ], [ - [ [0, 0], [10, 0] ], - [ [10, 0], [20, 0] ], - ], 'polyline_lines'; -} #========================================================== diff --git a/tests/fff_print/CMakeLists.txt b/tests/fff_print/CMakeLists.txt index 28f75bf2c..9e039c913 100644 --- a/tests/fff_print/CMakeLists.txt +++ b/tests/fff_print/CMakeLists.txt @@ -1,6 +1,8 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests.cpp + test_avoid_crossing_perimeters.cpp + test_bridges.cpp test_data.cpp test_data.hpp test_extrusion_entity.cpp diff --git a/tests/fff_print/test_avoid_crossing_perimeters.cpp b/tests/fff_print/test_avoid_crossing_perimeters.cpp new file mode 100644 index 000000000..a76ac12b5 --- /dev/null +++ b/tests/fff_print/test_avoid_crossing_perimeters.cpp @@ -0,0 +1,16 @@ +#include + +#include "test_data.hpp" + +using namespace Slic3r; + +SCENARIO("Avoid crossing perimeters", "[AvoidCrossingPerimeters]") { + WHEN("Two 20mm cubes sliced") { + std::string gcode = Slic3r::Test::slice( + { Slic3r::Test::TestMesh::cube_20x20x20, Slic3r::Test::TestMesh::cube_20x20x20 }, + { { "avoid_crossing_perimeters", true } }); + THEN("gcode not empty") { + REQUIRE(! gcode.empty()); + } + } +} diff --git a/tests/fff_print/test_bridges.cpp b/tests/fff_print/test_bridges.cpp new file mode 100644 index 000000000..91ab9b6b2 --- /dev/null +++ b/tests/fff_print/test_bridges.cpp @@ -0,0 +1,133 @@ +#include + +#include +#include + +#include "test_data.hpp" + +using namespace Slic3r; + +SCENARIO("Bridge detector", "[Bridging]") +{ + auto check_angle = [](const ExPolygons &lower, const ExPolygon &bridge, double expected, double tolerance = -1, double expected_coverage = -1) + { + if (expected_coverage < 0) + expected_coverage = bridge.area(); + + BridgeDetector bridge_detector(bridge, lower, scaled(0.5)); // extrusion width + if (tolerance < 0) + tolerance = Geometry::rad2deg(bridge_detector.resolution) + EPSILON; + + bridge_detector.detect_angle(); + double result = bridge_detector.angle; + Polygons coverage = bridge_detector.coverage(); + THEN("correct coverage area") { + REQUIRE(is_approx(area(coverage), expected_coverage)); + } + // our epsilon is equal to the steps used by the bridge detection algorithm + //##use XXX; YYY [ rad2deg($result), $expected ]; + // returned value must be non-negative, check for that too + double delta = Geometry::rad2deg(result) - expected; + if (delta >= 180. - EPSILON) + delta -= 180; + return result >= 0. && std::abs(delta) < tolerance; + }; + GIVEN("O-shaped overhang") { + auto test = [&check_angle](const Point &size, double rotate, double expected_angle, double tolerance = -1) { + ExPolygon lower{ + Polygon::new_scale({ {-2,-2}, {size.x()+2,-2}, {size.x()+2,size.y()+2}, {-2,size.y()+2} }), + Polygon::new_scale({ {0,0}, {0,size.y()}, {size.x(),size.y()}, {size.x(),0} } ) + }; + lower.rotate(Geometry::deg2rad(rotate), size / 2); + ExPolygon bridge_expoly(lower.holes.front()); + bridge_expoly.contour.reverse(); + return check_angle({ lower }, bridge_expoly, expected_angle, tolerance); + }; + WHEN("Bridge size 20x10") { + bool valid = test({20,10}, 0., 90.); + THEN("bridging angle is 90 degrees") { + REQUIRE(valid); + } + } + WHEN("Bridge size 10x20") { + bool valid = test({10,20}, 0., 0.); + THEN("bridging angle is 0 degrees") { + REQUIRE(valid); + } + } + WHEN("Bridge size 20x10, rotated by 45 degrees") { + bool valid = test({20,10}, 45., 135., 20.); + THEN("bridging angle is 135 degrees") { + REQUIRE(valid); + } + } + WHEN("Bridge size 20x10, rotated by 135 degrees") { + bool valid = test({20,10}, 135., 45., 20.); + THEN("bridging angle is 45 degrees") { + REQUIRE(valid); + } + } + } + GIVEN("two-sided bridge") { + ExPolygon bridge{ Polygon::new_scale({ {0,0}, {20,0}, {20,10}, {0,10} }) }; + ExPolygons lower { ExPolygon{ Polygon::new_scale({ {-2,0}, {0,0}, {0,10}, {-2,10} }) } }; + lower.emplace_back(lower.front()); + lower.back().translate(Point::new_scale(22, 0)); + THEN("Bridging angle 0 degrees") { + REQUIRE(check_angle(lower, bridge, 0)); + } + } + GIVEN("for C-shaped overhang") { + ExPolygon bridge{ Polygon::new_scale({ {0,0}, {20,0}, {10,10}, {0,10} }) }; + ExPolygon lower{ Polygon::new_scale({ {0,0}, {0,10}, {10,10}, {10,12}, {-2,12}, {-2,-2}, {22,-2}, {22,0} }) }; + bool valid = check_angle({ lower }, bridge, 135); + THEN("Bridging angle is 135 degrees") { + REQUIRE(valid); + } + } + GIVEN("square overhang with L-shaped anchors") { + ExPolygon bridge{ Polygon::new_scale({ {10,10}, {20,10}, {20,20}, {10,20} }) }; + ExPolygon lower{ Polygon::new_scale({ {10,10}, {10,20}, {20,20}, {30,30}, {0,30}, {0,0} }) }; + bool valid = check_angle({ lower }, bridge, 45., -1., bridge.area() / 2.); + THEN("Bridging angle is 45 degrees") { + REQUIRE(valid); + } + } +} + +SCENARIO("Bridging integration", "[Bridging]") { + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config_with({ + { "top_solid_layers", 0 }, + // to prevent bridging on sparse infill + { "bridge_speed", 99 } + }); + + std::string gcode = Slic3r::Test::slice({ Slic3r::Test::TestMesh::bridge }, config); + + GCodeReader parser; + const double bridge_speed = config.opt_float("bridge_speed") * 60.; + // angle => length + std::map extrusions; + parser.parse_buffer(gcode, [&extrusions, bridge_speed](Slic3r::GCodeReader &self, const Slic3r::GCodeReader::GCodeLine &line) + { + // if the command is a T command, set the the current tool + if (line.cmd() == "G1" && is_approx(bridge_speed, line.new_F(self))) { + // Accumulate lengths of bridging extrusions according to bridging angle. + Line l{ self.xy_scaled(), line.new_XY_scaled(self) }; + size_t angle = scaled(l.direction()); + auto it = extrusions.find(angle); + if (it == extrusions.end()) + it = extrusions.insert(std::make_pair(angle, 0.)).first; + it->second += l.length(); + } + }); + THEN("bridge is generated") { + REQUIRE(! extrusions.empty()); + } + THEN("bridge has the expected direction 0 degrees") { + // Bridging with the longest extrusion. + auto it_longest_extrusion = std::max_element(extrusions.begin(), extrusions.end(), + [](const auto &e1, const auto &e2){ return e1.second < e2.second; }); + REQUIRE(it_longest_extrusion->first == 0); + } +} diff --git a/tests/fff_print/test_fill.cpp b/tests/fff_print/test_fill.cpp index 9f30bf8be..c3af6e8fc 100644 --- a/tests/fff_print/test_fill.cpp +++ b/tests/fff_print/test_fill.cpp @@ -197,8 +197,7 @@ TEST_CASE("Fill: Pattern Path Length", "[Fill]") { SCENARIO("Infill does not exceed perimeters", "[Fill]") { auto test = [](const std::string_view pattern) { - DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config(); - config.set_deserialize_strict({ + DynamicPrintConfig config = Slic3r::DynamicPrintConfig::full_print_config_with({ { "nozzle_diameter", "0.4, 0.4, 0.4, 0.4" }, { "fill_pattern", pattern }, { "top_fill_pattern", pattern }, diff --git a/tests/libslic3r/test_clipper_utils.cpp b/tests/libslic3r/test_clipper_utils.cpp index 24d949be6..048ebba10 100644 --- a/tests/libslic3r/test_clipper_utils.cpp +++ b/tests/libslic3r/test_clipper_utils.cpp @@ -294,7 +294,7 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") { WHEN("clipping a line") { auto line = Polyline::new_scale({ { 152.742,288.086671142818 }, { 152.742,34.166466971035 } }); - Polylines intersection = intersection_pl({ line }, { circle_with_hole }); + Polylines intersection = intersection_pl(line, Polygons{ circle_with_hole }); THEN("clipped to two pieces") { REQUIRE(intersection.front().length() == Approx((Vec2d(152742000, 215178843) - Vec2d(152742000, 288086661)).norm())); REQUIRE(intersection[1].length() == Approx((Vec2d(152742000, 35166477) - Vec2d(152742000, 108087507)).norm())); diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index ab11e4989..8551aaff1 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -44,10 +44,8 @@ set(XSP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/xsp) #FIXME list the dependecies explicitely, add dependency on the typemap. set(XS_XSP_FILES ${XSP_DIR}/BoundingBox.xsp - ${XSP_DIR}/BridgeDetector.xsp ${XSP_DIR}/Config.xsp ${XSP_DIR}/ExPolygon.xsp - ${XSP_DIR}/ExPolygonCollection.xsp ${XSP_DIR}/ExtrusionEntityCollection.xsp ${XSP_DIR}/ExtrusionLoop.xsp ${XSP_DIR}/ExtrusionMultiPath.xsp diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm index 9a0181b65..5578a70ab 100644 --- a/xs/lib/Slic3r/XS.pm +++ b/xs/lib/Slic3r/XS.pm @@ -48,11 +48,6 @@ use overload '@{}' => sub { $_[0]->arrayref }, 'fallback' => 1; -package Slic3r::ExPolygon::Collection; -use overload - '@{}' => sub { $_[0]->arrayref }, - 'fallback' => 1; - package Slic3r::ExtrusionPath::Collection; use overload '@{}' => sub { $_[0]->arrayref }, @@ -179,7 +174,6 @@ sub new { package main; for my $class (qw( - Slic3r::BridgeDetector Slic3r::Config Slic3r::Config::Full Slic3r::Config::GCode @@ -188,7 +182,6 @@ for my $class (qw( Slic3r::Config::PrintRegion Slic3r::Config::Static Slic3r::ExPolygon - Slic3r::ExPolygon::Collection Slic3r::ExtrusionLoop Slic3r::ExtrusionMultiPath Slic3r::ExtrusionPath diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index e9f84b8c0..e513ec462 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -4,7 +4,6 @@ namespace Slic3r { REGISTER_CLASS(ExPolygon, "ExPolygon"); -REGISTER_CLASS(ExPolygonCollection, "ExPolygon::Collection"); REGISTER_CLASS(ExtrusionMultiPath, "ExtrusionMultiPath"); REGISTER_CLASS(ExtrusionPath, "ExtrusionPath"); REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop"); @@ -29,7 +28,6 @@ REGISTER_CLASS(ModelInstance, "Model::Instance"); REGISTER_CLASS(BoundingBox, "Geometry::BoundingBox"); REGISTER_CLASS(BoundingBoxf, "Geometry::BoundingBoxf"); REGISTER_CLASS(BoundingBoxf3, "Geometry::BoundingBoxf3"); -REGISTER_CLASS(BridgeDetector, "BridgeDetector"); REGISTER_CLASS(Point, "Point"); __REGISTER_CLASS(Vec2d, "Pointf"); __REGISTER_CLASS(Vec3d, "Pointf3"); diff --git a/xs/t/04_expolygon.t b/xs/t/04_expolygon.t index 65e274ab9..48eaed551 100644 --- a/xs/t/04_expolygon.t +++ b/xs/t/04_expolygon.t @@ -5,7 +5,7 @@ use warnings; use List::Util qw(first sum); use Slic3r::XS; -use Test::More tests => 21; +use Test::More tests => 15; use constant PI => 4 * atan2(1, 1); @@ -81,28 +81,4 @@ is $expolygon->area, 100*100-20*20, 'area'; ], 'rotate around pure-Perl Point'; } -{ - my $expolygon2 = $expolygon->clone; - $expolygon2->scale(2); - my $collection = Slic3r::ExPolygon::Collection->new($expolygon->pp, $expolygon2->pp); - is_deeply $collection->pp, [ $expolygon->pp, $expolygon2->pp ], - 'expolygon collection (pure Perl) roundtrip'; - - my $collection2 = Slic3r::ExPolygon::Collection->new($expolygon, $expolygon2); - is_deeply $collection->pp, $collection2->pp, - 'expolygon collection (XS) roundtrip'; - - $collection->clear; - is scalar(@$collection), 0, 'clear collection'; - - $collection->append($expolygon); - is scalar(@$collection), 1, 'append to collection'; - - my $exp = $collection->[0]; - $exp->scale(3); - is $collection->[0][0][0][0], $exp->[0][0][0], 'collection items are returned by reference'; - - is_deeply $collection->[0]->clone->pp, $collection->[0]->pp, 'clone collection item'; -} - __END__ diff --git a/xs/xsp/BridgeDetector.xsp b/xs/xsp/BridgeDetector.xsp deleted file mode 100644 index eb3793cf7..000000000 --- a/xs/xsp/BridgeDetector.xsp +++ /dev/null @@ -1,43 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/BridgeDetector.hpp" -%} - -%name{Slic3r::BridgeDetector} class BridgeDetector { - ~BridgeDetector(); - - bool detect_angle(); - Polygons coverage(); - %name{coverage_by_angle} Polygons coverage(double angle); - Polylines unsupported_edges(); - %name{unsupported_edges_by_angle} Polylines unsupported_edges(double angle); - double angle() - %code{% RETVAL = THIS->angle; %}; - double resolution() - %code{% RETVAL = THIS->resolution; %}; -%{ - -BridgeDetector* -BridgeDetector::new(expolygon, lower_slices, extrusion_width) - ExPolygon* expolygon; - ExPolygonCollection* lower_slices; - int extrusion_width; - CODE: - RETVAL = new BridgeDetector(*expolygon, lower_slices->expolygons, extrusion_width); - OUTPUT: - RETVAL - -BridgeDetector* -BridgeDetector::new_expolygons(expolygons, lower_slices, extrusion_width) - ExPolygonCollection* expolygons; - ExPolygonCollection* lower_slices; - int extrusion_width; - CODE: - RETVAL = new BridgeDetector(expolygons->expolygons, lower_slices->expolygons, extrusion_width); - OUTPUT: - RETVAL - -%} -}; diff --git a/xs/xsp/ExPolygonCollection.xsp b/xs/xsp/ExPolygonCollection.xsp deleted file mode 100644 index 5321afb15..000000000 --- a/xs/xsp/ExPolygonCollection.xsp +++ /dev/null @@ -1,81 +0,0 @@ -%module{Slic3r::XS}; - -%{ -#include -#include "libslic3r/ExPolygonCollection.hpp" -%} - -%name{Slic3r::ExPolygon::Collection} class ExPolygonCollection { - ~ExPolygonCollection(); - Clone clone() - %code{% RETVAL = THIS; %}; - void clear() - %code{% THIS->expolygons.clear(); %}; - void scale(double factor); - void translate(double x, double y); - void rotate(double angle, Point* center) - %code{% THIS->rotate(angle, *center); %}; - int count() - %code{% RETVAL = THIS->expolygons.size(); %}; - bool contains_point(Point* point) - %code{% RETVAL = THIS->contains(*point); %}; - bool contains_line(Line* line) - %code{% RETVAL = THIS->contains(*line); %}; - bool contains_polyline(Polyline* polyline) - %code{% RETVAL = THIS->contains(*polyline); %}; - void simplify(double tolerance); - Polygons polygons() - %code{% RETVAL = (Polygons)*THIS; %}; - Clone convex_hull(); -%{ - -ExPolygonCollection* -ExPolygonCollection::new(...) - CODE: - RETVAL = new ExPolygonCollection (); - // ST(0) is class name, others are expolygons - RETVAL->expolygons.resize(items-1); - for (unsigned int i = 1; i < items; i++) { - // Note: a COPY of the input is stored - from_SV_check(ST(i), &RETVAL->expolygons[i-1]); - } - OUTPUT: - RETVAL - -SV* -ExPolygonCollection::arrayref() - CODE: - AV* av = newAV(); - av_fill(av, THIS->expolygons.size()-1); - int i = 0; - for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { - av_store(av, i++, perl_to_SV_ref(*it)); - } - RETVAL = newRV_noinc((SV*)av); - OUTPUT: - RETVAL - -SV* -ExPolygonCollection::pp() - CODE: - AV* av = newAV(); - av_fill(av, THIS->expolygons.size()-1); - int i = 0; - for (ExPolygons::iterator it = THIS->expolygons.begin(); it != THIS->expolygons.end(); ++it) { - av_store(av, i++, to_SV_pureperl(&*it)); - } - RETVAL = newRV_noinc((SV*)av); - OUTPUT: - RETVAL - -void -ExPolygonCollection::append(...) - CODE: - for (unsigned int i = 1; i < items; i++) { - ExPolygon expolygon; - from_SV_check(ST(i), &expolygon); - THIS->expolygons.push_back(expolygon); - } - -%} -}; diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index 078e6fe72..1dbc00917 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -95,22 +95,6 @@ ExtrusionPath::append(...) THIS->polyline.points.push_back(p); } -ExtrusionEntityCollection* -ExtrusionPath::intersect_expolygons(ExPolygonCollection* collection) - CODE: - RETVAL = new ExtrusionEntityCollection (); - THIS->intersect_expolygons(*collection, RETVAL); - OUTPUT: - RETVAL - -ExtrusionEntityCollection* -ExtrusionPath::subtract_expolygons(ExPolygonCollection* collection) - CODE: - RETVAL = new ExtrusionEntityCollection (); - THIS->subtract_expolygons(*collection, RETVAL); - OUTPUT: - RETVAL - %} }; diff --git a/xs/xsp/Geometry.xsp b/xs/xsp/Geometry.xsp index 6e808fd8c..23daa4510 100644 --- a/xs/xsp/Geometry.xsp +++ b/xs/xsp/Geometry.xsp @@ -64,14 +64,6 @@ rad2deg(angle) OUTPUT: RETVAL -double -rad2deg_dir(angle) - double angle - CODE: - RETVAL = Slic3r::Geometry::rad2deg_dir(angle); - OUTPUT: - RETVAL - double deg2rad(angle) double angle diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index 4ab7fe188..da35734ff 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -3,7 +3,6 @@ %{ #include #include "libslic3r/Layer.hpp" -#include "libslic3r/ExPolygonCollection.hpp" %} %name{Slic3r::Layer::Region} class LayerRegion { @@ -59,9 +58,6 @@ Ref get_region(int idx); Ref add_region(PrintRegion* print_region); - ExPolygonCollection* slices() - %code%{ RETVAL = new ExPolygonCollection(THIS->lslices); %}; - int ptr() %code%{ RETVAL = (int)(intptr_t)THIS; %}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 131f82e79..fce0c47ad 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -88,10 +88,6 @@ ExPolygon* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -ExPolygonCollection* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - ExtrusionEntityCollection* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T @@ -163,10 +159,6 @@ GCode* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -BridgeDetector* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -Clone O_OBJECT_SLIC3R_T - Axis T_UV ExtrusionLoopRole T_UV ExtrusionRole T_UV diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index b59f4b74c..d4801fc39 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -54,9 +54,6 @@ %typemap{ExPolygon*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{ExPolygonCollection*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{Flow*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; @@ -87,9 +84,6 @@ %typemap{TriangleMesh*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; -%typemap{BridgeDetector*}; -%typemap{Ref}{simple}; -%typemap{Clone}{simple}; %typemap{SurfaceCollection*}; %typemap{Ref}{simple}; %typemap{Clone}{simple};