From 53907a9cfee63abf99940bbffe5f1785d151e843 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Tue, 18 Oct 2016 16:44:05 +0200
Subject: [PATCH] Fix of a crash when setting a viewport over an empty platter.
 Exported bounding box 'empty' method to perl.

---
 lib/Slic3r/GUI/3DScene.pm        | 21 ++++++++++++---------
 xs/src/libslic3r/BoundingBox.hpp |  4 ++--
 xs/src/libslic3r/libslic3r.h     |  1 +
 xs/xsp/BoundingBox.xsp           |  3 +++
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm
index d72679b3e..2a39bc875 100644
--- a/lib/Slic3r/GUI/3DScene.pm
+++ b/lib/Slic3r/GUI/3DScene.pm
@@ -354,15 +354,18 @@ sub select_view {
             $dirvec = VIEW_REAR;
         }
     }
-    $self->_sphi($dirvec->[0]);
-    $self->_stheta($dirvec->[1]);
-    # Avoid gimball lock.
-    $self->_stheta(150) if $self->_stheta > 150;
-    $self->_stheta(0) if $self->_stheta < 0;
-    # View everything.
-    $self->zoom_to_volumes;
-    $self->on_viewport_changed->() if $self->on_viewport_changed;
-    $self->Refresh;
+    my $bb = $self->volumes_bounding_box;
+    if (! $bb->empty) {
+        $self->_sphi($dirvec->[0]);
+        $self->_stheta($dirvec->[1]);
+        # Avoid gimball lock.
+        $self->_stheta(150) if $self->_stheta > 150;
+        $self->_stheta(0) if $self->_stheta < 0;
+        # View everything.
+        $self->zoom_to_bounding_box($bb);
+        $self->on_viewport_changed->() if $self->on_viewport_changed;
+        $self->Refresh;
+    }
 }
 
 sub zoom_to_bounding_box {
diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp
index 7746515cb..21c2e384e 100644
--- a/xs/src/libslic3r/BoundingBox.hpp
+++ b/xs/src/libslic3r/BoundingBox.hpp
@@ -102,13 +102,13 @@ inline bool operator!=(const BoundingBoxBase<VT> &bb1, const BoundingBoxBase<VT>
 template<typename VT>
 inline bool empty(const BoundingBoxBase<VT> &bb)
 {
-    return bb.min.x > bb.max.x || bb.min.y > bb.max.y;
+    return ! bb.defined || bb.min.x > bb.max.x || bb.min.y > bb.max.y;
 }
 
 template<typename VT>
 inline bool empty(const BoundingBox3Base<VT> &bb)
 {
-    return bb.min.x > bb.max.x || bb.min.y > bb.max.y || bb.min.z > bb.max.z;
+    return ! bb.defined || bb.min.x > bb.max.x || bb.min.y > bb.max.y || bb.min.z > bb.max.z;
 }
 
 } // namespace Slic3r
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index e92124536..fb37afcd0 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -17,6 +17,7 @@
 // Scaling factor for a conversion from coord_t to coordf_t: 10e-6
 // This scaling generates a following fixed point representation with for a 32bit integer:
 // 0..4294mm with 1nm resolution
+// int32_t fits an interval of (-2147.48mm, +2147.48mm)
 #define SCALING_FACTOR 0.000001
 // RESOLUTION, SCALED_RESOLUTION: Used as an error threshold for a Douglas-Peucker polyline simplification algorithm.
 #define RESOLUTION 0.0125
diff --git a/xs/xsp/BoundingBox.xsp b/xs/xsp/BoundingBox.xsp
index efb5dea3b..fd07713f2 100644
--- a/xs/xsp/BoundingBox.xsp
+++ b/xs/xsp/BoundingBox.xsp
@@ -21,6 +21,7 @@
     Clone<Polygon> polygon();
     Clone<Point> size();
     Clone<Point> center();
+    bool empty() %code{% RETVAL = empty(*THIS); %};
     double radius();
     Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
     Clone<Point> max_point() %code{% RETVAL = THIS->max; %};
@@ -56,6 +57,7 @@ new_from_points(CLASS, points)
     Clone<Pointf> size();
     Clone<Pointf> center();
     double radius();
+    bool empty() %code{% RETVAL = empty(*THIS); %};
     Clone<Pointf> min_point() %code{% RETVAL = THIS->min; %};
     Clone<Pointf> max_point() %code{% RETVAL = THIS->max; %};
     double x_min() %code{% RETVAL = THIS->min.x; %};
@@ -94,6 +96,7 @@ new_from_points(CLASS, points)
     Clone<Pointf3> size();
     Clone<Pointf3> center();
     double radius();
+    bool empty() %code{% RETVAL = empty(*THIS); %};
     Clone<Pointf3> min_point() %code{% RETVAL = THIS->min; %};
     Clone<Pointf3> max_point() %code{% RETVAL = THIS->max; %};
     double x_min() %code{% RETVAL = THIS->min.x; %};