diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm
index e4bf3958e..04451986c 100644
--- a/lib/Slic3r/Extruder.pm
+++ b/lib/Slic3r/Extruder.pm
@@ -73,7 +73,7 @@ sub extrude {
     
     # retract if distance from previous position is greater or equal to the one
     # specified by the user *and* to the maximum distance between infill lines
-    my $distance_from_last_pos = Slic3r::Geometry::distance_between_points($self->last_pos, $path->points->[0]->p) * $Slic3r::resolution;
+    my $distance_from_last_pos = Slic3r::Geometry::distance_between_points($self->last_pos, $path->points->[0]) * $Slic3r::resolution;
     if ($distance_from_last_pos >= $Slic3r::retract_before_travel
         && ($Slic3r::fill_density == 0 || $distance_from_last_pos >= $Slic3r::flow_width / $Slic3r::fill_density * sqrt(2))) {
         $gcode .= $self->retract;
@@ -135,7 +135,7 @@ sub G1 {
         $gcode .= sprintf " X%.${dec}f Y%.${dec}f", 
             ($point->x * $Slic3r::resolution) + $self->shift_x, 
             ($point->y * $Slic3r::resolution) + $self->shift_y; #**
-        $self->last_pos($point->p);
+        $self->last_pos($point);
     }
     if (defined $z && $z != $self->z) {
         $self->z($z);
diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm
index 2503c77d8..38b17a7fe 100644
--- a/lib/Slic3r/ExtrusionLoop.pm
+++ b/lib/Slic3r/ExtrusionLoop.pm
@@ -9,7 +9,7 @@ sub split_at {
     my $self = shift;
     my ($point) = @_;
     
-    $point = Slic3r::Point->cast($point);
+    $point = Slic3r::Point->new($point);
     
     # find index of point
     my $i = -1;
diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm
index 6bacc1119..3358cf887 100644
--- a/lib/Slic3r/ExtrusionPath.pm
+++ b/lib/Slic3r/ExtrusionPath.pm
@@ -18,17 +18,15 @@ sub clip_end {
             next;
         }
         
-        my $new_point = Slic3r::Geometry::point_along_segment($last_point->p, $self->points->[-1]->p, $distance);
-        push @{$self->points}, Slic3r::Point->cast($new_point);
+        my $new_point = Slic3r::Geometry::point_along_segment($last_point, $self->points->[-1], $distance);
+        push @{$self->points}, Slic3r::Point->new($new_point);
         $distance = 0;
     }
 }
 
 sub endpoints {
     my $self = shift;
-    my ($as_arrayref) = @_;
-    my @points = ($self->points->[0], $self->points->[-1]);
-    return $as_arrayref ? map($_->p, @points) : @points;
+    return ($self->points->[0], $self->points->[-1]);
 }
 
 sub reverse {
diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm
index 0179d991f..1601bcdbc 100644
--- a/lib/Slic3r/ExtrusionPath/Collection.pm
+++ b/lib/Slic3r/ExtrusionPath/Collection.pm
@@ -18,22 +18,18 @@ sub add {
 
 sub endpoints {
     my $self = shift;
-    my ($as_arrayref) = @_;
-    return map $_->endpoints($as_arrayref), @{$self->paths};
+    return map $_->endpoints, @{$self->paths};
 }
 
 sub shortest_path {
     my $self = shift;
     my ($start_near) = @_;
     
-    # get point as arrayref
-    $start_near = $start_near->p if $start_near && ref $start_near ne 'ARRAY';
-    
     my @paths = ();
     my $start_at;
     CYCLE: while (@{$self->paths}) {
         # find nearest point
-        $start_at = Slic3r::Point->cast(Slic3r::Geometry::nearest_point($start_near, [ $self->endpoints(1) ]));
+        $start_at = Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, [ $self->endpoints ]));
         
         # loop through paths to find the one that starts or ends at the point found
         PATH: for (my $i = 0; $i <= $#{$self->paths}; $i++) {
@@ -45,7 +41,7 @@ sub shortest_path {
             } else {
                 next PATH;
             }
-            $start_near = $paths[-1]->points->[-1]->p;
+            $start_near = $paths[-1]->points->[-1];
             next CYCLE;
         }
     }
diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm
index b2eb15952..9c975ca31 100644
--- a/lib/Slic3r/Layer.pm
+++ b/lib/Slic3r/Layer.pm
@@ -87,7 +87,7 @@ sub add_surface {
     my (@vertices) = @_;
     
     # convert arrayref points to Point objects
-    @vertices = map Slic3r::Point->cast($_), @vertices;
+    @vertices = map Slic3r::Point->new($_), @vertices;
     
     my $surface = Slic3r::Surface->new(
         contour => Slic3r::Polyline::Closed->new(points => \@vertices),
diff --git a/lib/Slic3r/Line.pm b/lib/Slic3r/Line.pm
index cbfccb4c6..b4ab97b6b 100644
--- a/lib/Slic3r/Line.pm
+++ b/lib/Slic3r/Line.pm
@@ -13,7 +13,7 @@ sub cast {
     my ($line, %args) = @_;
     if (ref $line eq 'ARRAY') {
         @$line == 2 or die "Line needs two points!";
-        return $class->new(points => [ map Slic3r::Point->cast($_), @$line ], %args);
+        return $class->new(points => [ map Slic3r::Point->new($_), @$line ], %args);
     } else {
         return $line;
     }
@@ -39,7 +39,7 @@ sub coordinates {
 
 sub p {
     my $self = shift;
-    return [ $self->a->p, $self->b->p ];
+    return [ $self->a, $self->b ];
 }
 
 sub coincides_with {
diff --git a/lib/Slic3r/Point.pm b/lib/Slic3r/Point.pm
index cf3075f9d..a79093b07 100644
--- a/lib/Slic3r/Point.pm
+++ b/lib/Slic3r/Point.pm
@@ -1,51 +1,46 @@
 package Slic3r::Point;
-use Moo;
+use strict;
+use warnings;
 
-has 'x' => (
-    is          => 'ro',
-    required    => 1,
-    #coerce      => sub { sprintf '%.0f', $_[0] },
-);
-
-has 'y' => (
-    is          => 'ro',
-    required    => 1,
-    #coerce      => sub { sprintf '%.0f', $_[0] },
-);
-
-sub cast {
+sub new {
     my $class = shift;
-    my ($point) = @_;
-    return ref $point eq 'ARRAY' 
-        ? Slic3r::Point->new(x => $point->[0], y => $point->[1])  # ==
-        : $point;
+    my $self;
+    if (@_ == 2) {
+        $self = [@_];
+    } elsif (ref $_[0] eq 'ARRAY') {
+        $self = [@{$_[0]}];
+    } elsif ($_[0]->isa(__PACKAGE__)) {
+        return $_[0];
+    } else {
+        die "Invalid arguments for ${class}->new";
+    }
+    bless $self, $class;
+    return $self;
 }
 
 sub id {
     my $self = shift;
-    return $self->x . "," . $self->y; #;;
+    return join ',', @$self;
 }
 
 sub coordinates {
     my $self = shift;
-    return ($self->x, $self->y); #))
-}
-
-sub p {
-    my $self = shift;
-    return [ $self->coordinates ];
+    return @$self;
 }
 
 sub coincides_with {
     my $self = shift;
     my ($point) = @_;
-    return Slic3r::Geometry::points_coincide($self->p, $point->p);
+    return Slic3r::Geometry::points_coincide($self, $point);
 }
 
 sub distance_to {
     my $self = shift;
     my ($point) = @_;
-    return Slic3r::Geometry::distance_between_points($self->p, $point->p);
+    return Slic3r::Geometry::distance_between_points($self, $point);
 }
 
+sub x { $_[0]->[0] }
+sub y { $_[0]->[1] }
+
 1;
diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm
index 51846e8db..40e7e032c 100644
--- a/lib/Slic3r/Polyline.pm
+++ b/lib/Slic3r/Polyline.pm
@@ -24,7 +24,7 @@ sub cast {
     my $class = shift;
     my ($points) = @_;
     
-    $points = [ map { ref $_ eq 'ARRAY' ? Slic3r::Point->cast($_) : $_ } @$points ];
+    $points = [ map { ref $_ eq 'ARRAY' ? Slic3r::Point->new($_) : $_ } @$points ];
     return $class->new(points => $points);
 }
 
@@ -43,7 +43,7 @@ sub lines {
 
 sub p {
     my $self = shift;
-    return [ map $_->p, @{$self->points} ];
+    return [ @{$self->points} ];
 }
 
 sub merge_continuous_lines {
@@ -54,7 +54,7 @@ sub merge_continuous_lines {
     } else {
         polyline_remove_parallel_continuous_edges($points);
     }
-    @{$self->points} = map Slic3r::Point->cast($_), @$points;
+    @{$self->points} = map Slic3r::Point->new($_), @$points;
 }
 
 sub remove_acute_vertices {
@@ -65,7 +65,7 @@ sub remove_acute_vertices {
     } else {
         polyline_remove_acute_vertices($points);
     }
-    @{$self->points} = map Slic3r::Point->cast($_), @$points;
+    @{$self->points} = map Slic3r::Point->new($_), @$points;
 }
 
 sub cleanup {
@@ -74,7 +74,7 @@ sub cleanup {
     
     my $points = $self->p;
     push @$points, $points->[0] if $self->isa('Slic3r::Polyline::Closed');
-    my @clean_points = map Slic3r::Point->cast($_), 
+    my @clean_points = map Slic3r::Point->new($_), 
         Slic3r::Geometry::Douglas_Peucker($self->p, $tolerance);
     pop @clean_points if $self->isa('Slic3r::Polyline::Closed');
     @{$self->points} = @clean_points;
@@ -104,11 +104,8 @@ sub nearest_point_to {
     my $self = shift;
     my ($point) = @_;
     
-    # get point as arrayref
-    $point = ref $point eq 'ARRAY' ? $point : $point->p;
-    
     $point = Slic3r::Geometry::nearest_point($point, $self->p);
-    return Slic3r::Point->cast($point);
+    return Slic3r::Point->new($point);
 }
 
 sub has_segment {
diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm
index 2cf9fd9c6..ddc797667 100644
--- a/lib/Slic3r/Print.pm
+++ b/lib/Slic3r/Print.pm
@@ -146,7 +146,7 @@ sub detect_surfaces_type {
                 # okay, this is an Ugly Hack(tm) to avoid floating point math problems
                 # with diagonal bridges. will find a nicer solution, promised.
                 my $offset = offset([$_->contour->p], 100, 100, JT_MITER, 2);
-                @{$_->contour->points} = map Slic3r::Point->cast($_), @{ $offset->[0] };
+                @{$_->contour->points} = map Slic3r::Point->new($_), @{ $offset->[0] };
             }
             
             #Slic3r::SVG::output(undef, "layer_" . $layer->id . "_diff.svg",
diff --git a/lib/Slic3r/STL.pm b/lib/Slic3r/STL.pm
index 52aec8afe..f06362733 100644
--- a/lib/Slic3r/STL.pm
+++ b/lib/Slic3r/STL.pm
@@ -258,6 +258,9 @@ sub _read_ascii {
             }
         }
     }
+    if ($facet) {
+        die "STL file seems invalid\n";
+    }
 }
 
 sub _read_binary {