Browse Source

Ported nearest_point() and nearest_point_index()

Alessandro Ranellucci 11 years ago
parent
commit
b11b595c97

+ 1 - 1
lib/Slic3r/ExtrusionPath/Collection.pm

@@ -23,7 +23,7 @@ sub chained_path {
     while (@my_paths) {
     while (@my_paths) {
         # find nearest point
         # find nearest point
         my $start_index = defined $start_near
         my $start_index = defined $start_near
-            ? Slic3r::Geometry::nearest_point_index($start_near, $endpoints)
+            ? $start_near->nearest_point_index($endpoints)
             : 0;
             : 0;
 
 
         my $path_index = int($start_index/2);
         my $path_index = int($start_index/2);

+ 2 - 2
lib/Slic3r/Fill/Concentric.pm

@@ -3,7 +3,7 @@ use Moo;
 
 
 extends 'Slic3r::Fill::Base';
 extends 'Slic3r::Fill::Base';
 
 
-use Slic3r::Geometry qw(scale unscale X nearest_point_index);
+use Slic3r::Geometry qw(scale unscale X);
 use Slic3r::Geometry::Clipper qw(offset offset2 union_pt traverse_pt PFT_EVENODD);
 use Slic3r::Geometry::Clipper qw(offset offset2 union_pt traverse_pt PFT_EVENODD);
 
 
 sub fill_surface {
 sub fill_surface {
@@ -43,7 +43,7 @@ sub fill_surface {
     my @paths = ();
     my @paths = ();
     my $last_pos = [0,0];
     my $last_pos = [0,0];
     foreach my $loop (@loops) {
     foreach my $loop (@loops) {
-        push @paths, $loop->split_at_index(nearest_point_index($last_pos, $loop));
+        push @paths, $loop->split_at_index($last_pos->nearest_point_index($loop));
         $last_pos = $paths[-1][-1];
         $last_pos = $paths[-1][-1];
     }
     }
     
     

+ 1 - 1
lib/Slic3r/GCode.pm

@@ -211,7 +211,7 @@ sub extrude_loop {
     }
     }
     
     
     # split the loop at the starting point and make a path
     # split the loop at the starting point and make a path
-    my $start_at = Slic3r::Geometry::nearest_point($last_pos, \@candidates);
+    my $start_at = $last_pos->nearest_point(\@candidates);
     my $extrusion_path = $loop->split_at($start_at);
     my $extrusion_path = $loop->split_at($start_at);
     
     
     # clip the path to avoid the extruder to get exactly on the first point of the loop;
     # clip the path to avoid the extruder to get exactly on the first point of the loop;

+ 4 - 4
lib/Slic3r/GCode/MotionPlanner.pm

@@ -13,7 +13,7 @@ has '_crossing_edges' => (is => 'rw', default => sub { {} });  # edge_idx => boo
 has '_tolerance'    => (is => 'lazy');
 has '_tolerance'    => (is => 'lazy');
 
 
 use List::Util qw(first);
 use List::Util qw(first);
-use Slic3r::Geometry qw(A B scale epsilon nearest_point);
+use Slic3r::Geometry qw(A B scale epsilon);
 use Slic3r::Geometry::Clipper qw(diff_ex offset JT_MITER);
 use Slic3r::Geometry::Clipper qw(diff_ex offset JT_MITER);
 
 
 # clearance (in mm) from the perimeters
 # clearance (in mm) from the perimeters
@@ -196,13 +196,13 @@ sub find_node {
     # if we're inside a hole, move to a point on hole;
     # if we're inside a hole, move to a point on hole;
     {
     {
         my $polygon = first { $_->encloses_point($point) } (map @{$_->holes}, map @$_, @{$self->_inner});
         my $polygon = first { $_->encloses_point($point) } (map @{$_->holes}, map @$_, @{$self->_inner});
-        return nearest_point($point, $polygon) if $polygon;
+        return $point->nearest_point([ @$polygon ]) if $polygon;
     }
     }
     
     
     # if we're inside an expolygon move to a point on contour or holes
     # if we're inside an expolygon move to a point on contour or holes
     {
     {
         my $expolygon = first { $_->encloses_point_quick($point) } (map @$_, @{$self->_inner});
         my $expolygon = first { $_->encloses_point_quick($point) } (map @$_, @{$self->_inner});
-        return nearest_point($point, [ map @$_, @$expolygon ]) if $expolygon;
+        return $point->nearest_point([ map @$_, @$expolygon ]) if $expolygon;
     }
     }
     
     
     {
     {
@@ -221,7 +221,7 @@ sub find_node {
             : [ map @$_, map @$_, @{$self->_outer} ];
             : [ map @$_, map @$_, @{$self->_outer} ];
         $candidates = [ map @$_, @{$self->_outer->[$outer_polygon_idx]} ]
         $candidates = [ map @$_, @{$self->_outer->[$outer_polygon_idx]} ]
             if @$candidates == 0;
             if @$candidates == 0;
-        return nearest_point($point, $candidates);
+        return $point->nearest_point($candidates);
     }
     }
 }
 }
 
 

+ 3 - 38
lib/Slic3r/Geometry.pm

@@ -9,10 +9,10 @@ our @EXPORT_OK = qw(
     line_point_belongs_to_segment points_coincide distance_between_points 
     line_point_belongs_to_segment points_coincide distance_between_points 
     chained_path_items chained_path_points normalize tan move_points_3D
     chained_path_items chained_path_points normalize tan move_points_3D
     line_length midpoint point_in_polygon point_in_segment segment_in_segment
     line_length midpoint point_in_polygon point_in_segment segment_in_segment
-    point_is_on_left_of_segment polyline_lines polygon_lines nearest_point
+    point_is_on_left_of_segment polyline_lines polygon_lines
     point_along_segment polygon_segment_having_point polygon_has_subsegment
     point_along_segment polygon_segment_having_point polygon_has_subsegment
     polygon_has_vertex polyline_length can_connect_points deg2rad rad2deg
     polygon_has_vertex polyline_length can_connect_points deg2rad rad2deg
-    rotate_points move_points clip_segment_polygon nearest_point_index
+    rotate_points move_points clip_segment_polygon
     sum_vectors multiply_vector subtract_vectors dot perp polygon_points_visibility
     sum_vectors multiply_vector subtract_vectors dot perp polygon_points_visibility
     line_intersection bounding_box bounding_box_intersect same_point same_line
     line_intersection bounding_box bounding_box_intersect same_point same_line
     longest_segment angle3points three_points_aligned line_direction
     longest_segment angle3points three_points_aligned line_direction
@@ -239,41 +239,6 @@ sub polygon_lines {
     return polyline_lines([ @$polygon, $polygon->[0] ]);
     return polyline_lines([ @$polygon, $polygon->[0] ]);
 }
 }
 
 
-sub nearest_point {
-    my ($point, $points) = @_;
-    my $index = nearest_point_index(@_);
-    return undef if !defined $index;
-    return $points->[$index];
-}
-
-sub nearest_point_index {
-    my ($point, $points) = @_;
-    
-    my ($nearest_point_index, $distance) = ();
-    
-    my ($point_x, $point_y) = @$point;
-    my @points_pp = map $_->pp, @$points;
-    
-    for my $i (0..$#$points) {
-        my $d = ($point_x - $points_pp[$i][X])**2;
-        # If the X distance of the candidate is > than the total distance of the
-        # best previous candidate, we know we don't want it
-        next if (defined $distance && $d > $distance);
-   
-        # If the total distance of the candidate is > than the total distance of the
-        # best previous candidate, we know we don't want it
-        $d += ($point_y - $points_pp[$i][Y])**2;
-        next if (defined $distance && $d > $distance);
-
-        $nearest_point_index = $i;
-        $distance = $d;
-        
-        last if $distance < epsilon;
-    }
-
-    return $nearest_point_index;
-}
-
 # given a segment $p1-$p2, get the point at $distance from $p1 along segment
 # given a segment $p1-$p2, get the point at $distance from $p1 along segment
 sub point_along_segment {
 sub point_along_segment {
     my ($p1, $p2, $distance) = @_;
     my ($p1, $p2, $distance) = @_;
@@ -833,7 +798,7 @@ sub chained_path {
         push @result, $indices{$start_near} if $start_near;
         push @result, $indices{$start_near} if $start_near;
     }
     }
     while (@points) {
     while (@points) {
-        $start_near = nearest_point($start_near, [@points]);
+        $start_near = $start_near->nearest_point(\@points);
         @points = grep $_ ne $start_near, @points;
         @points = grep $_ ne $start_near, @points;
         push @result, $indices{$start_near};
         push @result, $indices{$start_near};
     }
     }

+ 1 - 15
lib/Slic3r/Polyline.pm

@@ -54,20 +54,6 @@ sub grow {
     )};
     )};
 }
 }
 
 
-sub nearest_point_to {
-    my $self = shift;
-    my ($point) = @_;
-    
-    $point = Slic3r::Geometry::nearest_point($point, $self);
-    return Slic3r::Point->new($point);
-}
-
-sub nearest_point_index_to {
-    my $self = shift;
-    my ($point) = @_;
-    return Slic3r::Geometry::nearest_point_index($point, $self);
-}
-
 sub clip_with_polygon {
 sub clip_with_polygon {
     my $self = shift;
     my $self = shift;
     my ($polygon) = @_;
     my ($polygon) = @_;
@@ -197,7 +183,7 @@ sub chained_path {
     while (@my_paths) {
     while (@my_paths) {
         # find nearest point
         # find nearest point
         my $start_index = defined $start_near
         my $start_index = defined $start_near
-            ? Slic3r::Geometry::nearest_point_index($start_near, $endpoints)
+            ? $start_near->nearest_point_index($endpoints)
             : 0;
             : 0;
 
 
         my $path_index = int($start_index/2);
         my $path_index = int($start_index/2);

+ 4 - 4
lib/Slic3r/Print.pm

@@ -6,8 +6,7 @@ use File::Spec;
 use List::Util qw(min max first);
 use List::Util qw(min max first);
 use Math::ConvexHull::MonotoneChain qw(convex_hull);
 use Math::ConvexHull::MonotoneChain qw(convex_hull);
 use Slic3r::ExtrusionPath ':roles';
 use Slic3r::ExtrusionPath ':roles';
-use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale move_points
-    nearest_point chained_path);
+use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale move_points chained_path);
 use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex offset
 use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex offset
     offset2 traverse_pt JT_ROUND JT_SQUARE PFT_EVENODD);
     offset2 traverse_pt JT_ROUND JT_SQUARE PFT_EVENODD);
 use Time::HiRes qw(gettimeofday tv_interval);
 use Time::HiRes qw(gettimeofday tv_interval);
@@ -552,9 +551,10 @@ EOF
             foreach my $expolygon (@unsupported_slices) {
             foreach my $expolygon (@unsupported_slices) {
                 # look for the nearest point to this island among all
                 # look for the nearest point to this island among all
                 # supported points
                 # supported points
-                my $support_point = nearest_point($expolygon->contour->[0], \@supported_points)
+                my $contour = $expolygon->contour;
+                my $support_point = $contour->first_point->nearest_point(\@supported_points)
                     or next;
                     or next;
-                my $anchor_point = nearest_point($support_point, $expolygon->contour);
+                my $anchor_point = $support_point->nearest_point([ @$contour ]);
                 printf $fh qq{    <line x1="%s" y1="%s" x2="%s" y2="%s" style="stroke-width: 2; stroke: white" />\n},
                 printf $fh qq{    <line x1="%s" y1="%s" x2="%s" y2="%s" style="stroke-width: 2; stroke: white" />\n},
                     map @$_, $support_point, $anchor_point;
                     map @$_, $support_point, $anchor_point;
             }
             }

+ 6 - 0
xs/src/MultiPoint.cpp

@@ -32,6 +32,12 @@ MultiPoint::reverse()
     std::reverse(this->points.begin(), this->points.end());
     std::reverse(this->points.begin(), this->points.end());
 }
 }
 
 
+const Point*
+MultiPoint::first_point() const
+{
+    return &(this->points.front());
+}
+
 void
 void
 MultiPoint::from_SV(SV* poly_sv)
 MultiPoint::from_SV(SV* poly_sv)
 {
 {

+ 1 - 0
xs/src/MultiPoint.hpp

@@ -19,6 +19,7 @@ class MultiPoint
     void translate(double x, double y);
     void translate(double x, double y);
     void rotate(double angle, Point* center);
     void rotate(double angle, Point* center);
     void reverse();
     void reverse();
+    const Point* first_point() const;
 };
 };
 
 
 }
 }

+ 33 - 0
xs/src/Point.cpp

@@ -1,4 +1,5 @@
 #include "Point.hpp"
 #include "Point.hpp"
+#include <math.h>
 
 
 namespace Slic3r {
 namespace Slic3r {
 
 
@@ -31,6 +32,38 @@ Point::coincides_with(const Point* point) const
     return this->x == point->x && this->y == point->y;
     return this->x == point->x && this->y == point->y;
 }
 }
 
 
+int
+Point::nearest_point_index(const Points points) const
+{
+    int idx = -1;
+    long distance = -1;
+    
+    for (Points::const_iterator it = points.begin(); it != points.end(); ++it) {
+        /* If the X distance of the candidate is > than the total distance of the
+           best previous candidate, we know we don't want it */
+        long d = pow(this->x - (*it).x, 2);
+        if (distance != -1 && d > distance) continue;
+        
+        /* If the Y distance of the candidate is > than the total distance of the
+           best previous candidate, we know we don't want it */
+        d += pow(this->y - (*it).y, 2);
+        if (distance != -1 && d > distance) continue;
+        
+        idx = it - points.begin();
+        distance = d;
+        
+        if (distance < EPSILON) break;
+    }
+    
+    return idx;
+}
+
+Point*
+Point::nearest_point(Points points) const
+{
+    return &(points.at(this->nearest_point_index(points)));
+}
+
 SV*
 SV*
 Point::to_SV_pureperl() {
 Point::to_SV_pureperl() {
     AV* av = newAV();
     AV* av = newAV();

Some files were not shown because too many files changed in this diff