diff --git a/.gitignore b/.gitignore
index 3913b0a3..38e146db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,9 +5,10 @@ object_script.*
 digit-exe-*.pkg
 documentation
 engauge
+Engauge Digitizer.pkg
 engauge.log
 engauge.pro.user
-engauge.pro.user.markummitchell
+engauge.pro.user.*
 engauge_*.snap
 Makefile*
 object_script.engauge
diff --git a/.lgtm.yml b/.lgtm.yml
new file mode 100644
index 00000000..83a6fc7d
--- /dev/null
+++ b/.lgtm.yml
@@ -0,0 +1,5 @@
+extraction:
+  cpp:
+    configure:
+      command:
+      - qmake engauge.pro
diff --git a/.travis.yml b/.travis.yml
index 66448a3a..24b7ff14 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,7 @@ matrix:
       env: ARCH="x86_64" BUILD_DEBUG="1"
       compiler: "clang"
      
+# xvfb setup is discussed at https://docs.travis-ci.com/user/gui-and-headless-browsers/
 before_script:
  - if [ `uname` = "Linux" ]; then
      export DISPLAY=:99.0;
@@ -23,12 +24,13 @@ before_script:
 
 before_install:
  - if [ `uname` = "Linux" ]; then
-     sudo apt-get update -qq;
-     sudo apt-get install --yes --no-install-recommends qtbase5-dev qttools5-dev qt5-default qttools5-dev-tools qt5-qmake liblog4cpp5-dev libfftw3-dev libqt5sql5-sqlite xvfb;
+     sudo -E apt-get update -qq;
+     sudo -E apt-get install --yes --no-install-recommends qtbase5-dev qttools5-dev qt5-default qttools5-dev-tools qt5-qmake liblog4cpp5-dev libfftw3-dev libqt5sql5-sqlite xvfb python3 python3-pip python3-lxml python3-numpy python3-pandas gdb;
    elif [ `uname` = "Darwin" ]; then
      brew update;
-     brew install homebrew/core/qt@5.5 fftw log4cpp;
-     export QT5BREWHOME=`brew --prefix homebrew/core/qt@5.5`;
+     brew info qt5;
+     brew install fftw log4cpp qt5;
+     export QT5BREWHOME="/usr/local/opt/qt";
    fi
 
 script:
@@ -49,8 +51,12 @@ script:
     sed -ibak2 's|-L/usr/local/Cellar|-F/usr/local/Cellar|g' Makefile;
     sed -ibak3 's|-F/usr/local/Cellar/log4cpp|-L/usr/local/Cellar/log4cpp|g' Makefile;
    fi
- - make
- - cd help && ./build.bash && cd ..;
+ - make -j4
+ - if [ `uname` = "Linux" ]; then
+    cd help && ./build.bash && cd ..;
+   else
+    cd help && ./build_qt5_12_0.bash && cd ..;   
+   fi
  - if [ `uname` = "Darwin" -a "$BUILD_DEBUG" = "1" ]; then
     cp $FFTW_HOME/lib/lib* src;
     cp $LOG4CPP_HOME/lib/lib* src;
@@ -59,6 +65,11 @@ script:
  - if [ `uname` != "Darwin" -o "$BUILD_DEBUG" = "1" ]; then
     cd src && ./build_and_run_all_gui_tests && cd ..;
    fi
+#no python tests on OSX. cd test && ./DumpGraphAndScreenCoordinates_test.py && cd ..;
+ - if [ `uname` = "Linux" ]; then
+    export ENGAUGE_EXECUTABLE=../bin/engauge;
+    cd test && ./DumpGraphAndScreenCoordinates_test.py && cd ..;
+   fi
 #no cli tests on OSX
  - if [ `uname` = "Linux" ]; then
     cd src && ./build_and_run_all_cli_tests && cd ..;
diff --git a/BUILD b/BUILD
index 6c7a93fb..640da3ac 100644
--- a/BUILD
+++ b/BUILD
@@ -78,6 +78,9 @@ These steps build and run, in Linux, the standard engauge executable for digitiz
      libopenjpeg-dev    For reading jpeg2000 image files (optional). Compiles
                         with version 2.1.7 but not with version 2.1.3
      libpng12-dev       For reading png image files (optional)
+     libssl1.0-dev      For import by dragging images from browsers. Version 1.0.2
+                        is known to work but newer version 1.1.0 gives error
+			'qt.network.ssl: Incompatible version of OpenSSL'
 
    In Debian and Ubuntu distributions, the following packages are required for
    building Engauge for your own use:
diff --git a/appveyor.yml b/appveyor.yml
index 7c4dd39e..7f38d0f5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -21,7 +21,7 @@ environment:
 install:
   - C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\vcvarsall.bat %BUILD_TYPE%
 # Qt configurations are listed at https://www.appveyor.com/docs/build-environment/#qt
-  - IF %BUILD_TYPE% == X86 (set QTDIR=C:\Qt\5.10.1\msvc2015) ELSE (set QTDIR=C:\Qt\5.10.1\msvc2015_64)
+  - IF %BUILD_TYPE% == X86 (set QTDIR=C:\Qt\5.11.3\msvc2015) ELSE (set QTDIR=C:\Qt\5.11.3\msvc2015_64)
   - set PATH=%PATH%;%QTDIR%\bin
   - cd %APPVEYOR_BUILD_FOLDER%
   - 7z x %APPVEYOR_BUILD_FOLDER%\dev\windows\appveyor\%LOG4CPP_FILE% -aoa
diff --git a/contrib/python/.gitignore b/contrib/python/.gitignore
index bee8a64b..adff01db 100644
--- a/contrib/python/.gitignore
+++ b/contrib/python/.gitignore
@@ -1 +1,4 @@
 __pycache__
+.idea
+*.csv
+*.dig
diff --git a/contrib/python/DumpGraphAndScreenCoordinates.py b/contrib/python/DumpGraphAndScreenCoordinates.py
new file mode 100755
index 00000000..2e8b1682
--- /dev/null
+++ b/contrib/python/DumpGraphAndScreenCoordinates.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+
+# Script that outputs the graph and screen coordinates of each point in a DIG file.
+# The format is:
+# 1) "xGraph yGraph xScreen yScreen" on each line
+# 2) Between each field is the export delimiter selected in the DIG file
+#
+# Requirements:
+# 1) python3 (versus python2)
+# 2) numpy
+# 3) DefaultListOrderedDict.py from the Engauge scripts directory
+# 4) ParseDig.py from the Engauge scripts directory
+
+import os
+from ParseDig import ParseDig
+import sys
+
+if len(sys.argv) != 2 or not os.path.exists (sys.argv [1]):
+    print ("Usage: python3 DumpGraphAndScreenCoordinates.py <dig file>")
+else:
+    parseDig = ParseDig (sys.argv [1])
+    curveNames = parseDig.curveNames()
+    exportDelimiter = parseDig.exportDelimiter()
+    for curveName in curveNames:
+
+        print ("# {}" . format (curveName))
+        curve = parseDig.curve (curveName)
+
+        for row in curve:
+            xGraph = row [0]
+            yGraph = row [1]
+            (xScreen, yScreen) = row [2], row [3] #parseDig.transformGraphToScreen (xGraph, yGraph)
+            print ("{}{}{}{}{}{}{}" . format (xGraph, exportDelimiter,
+                                              yGraph, exportDelimiter,
+                                              xScreen, exportDelimiter,
+                                              yScreen))
diff --git a/contrib/python/InsertDerivedColumn.py b/contrib/python/InsertDerivedColumn.py
index f75e9f08..252cea6c 100755
--- a/contrib/python/InsertDerivedColumn.py
+++ b/contrib/python/InsertDerivedColumn.py
@@ -12,6 +12,7 @@ from datetime import datetime, timedelta
 import fileinput
 import math
 import numpy as np
+import unicodedata
 
 def is_number(s):
     try:
@@ -19,9 +20,9 @@ def is_number(s):
         return True
     except ValueError:
         return False
- 
+
+def is_number_unicode(s):    
     try:
-        import unicodedata
         unicodedata.numeric(s)
         return True
     except (TypeError, ValueError):
diff --git a/contrib/python/ParseDig.py b/contrib/python/ParseDig.py
index c9f75cfa..9bf30390 100644
--- a/contrib/python/ParseDig.py
+++ b/contrib/python/ParseDig.py
@@ -1,76 +1,326 @@
+# This file converts non-xml dig files to xml if required. Directly reading non-xml
+# files (=binary) was attempted but the unpredictable length of the QPixMap in the
+# middle of the binary data, and use of string (versus bytes) by pyside2 prevented
+# that option from succeeding
 from xml.etree import ElementTree
 from DefaultListOrderedDict import DefaultListOrderedDict
 import numpy as np
+import os
+from signal import SIGSEGV
+import subprocess
+import sys
 
 class ParseDig:
-    curves = DefaultListOrderedDict () # Hash table of curve name to lists, with each list consisting of graph points
     def __init__(self, digFile):
-        with open(digFile, 'rt') as f:
-            tree = ElementTree.parse (f)
+        # Hash table of curve name to lists, with each list consisting of graph points 
+        # and screen coordinates
+        self._curves = DefaultListOrderedDict()
 
+        try:
+            with open(digFile, 'rt') as f:
+                tree = ElementTree.parse (f)
+            self.parseXml (tree)
+        except Exception as e:
+            digFileUpgraded = self.upgrade (digFile)
+            try:
+                with open(digFileUpgraded, 'rt') as f:
+                    tree = ElementTree.parse (f)
+                os.remove (digFileUpgraded)
+                self.parseXml (tree)
+            except Exception as e:
+                print ("Could not load {} even after trying an upgrade" . format (digFile))
+
+    @staticmethod
+    def callEngauge (argumentsArray, debug = False):
+        # Operating system dependent location of Engauge executable. Some typical values are:
+        #  cygwin      /usr/bin/engauge-digitizer.exe
+        #  linux       /usr/bin/engauge
+        #  osx         /Applications/Engauge\ Digitizer.app/Contents/MacOS/Engauge\ Digitizer
+        #  windows     C:/Program Files/Engauge Digitizer/engauge.exe
+        envTag = 'ENGAUGE_EXECUTABLE'
+        if envTag in os.environ and os.environ [envTag] != '':
+            engaugeExecutable = os.environ [envTag]
+        else:
+            engaugeExecutable = "/usr/bin/engauge"
+
+        if not os.path.exists (engaugeExecutable):
+
+            # Show error message            
+            noExeError = '{} {} - {}. {} {} {}.' . format (
+                'Could not execute Engauge at',
+                engaugeExecutable,
+                'Path does not exist',
+                'Try setting environment variable',
+                envTag,
+                'to the executable path')
+
+            print (noExeError)
+            sys.exit (0)
+
+        debugArgs = []
+        if (debug):
+            debugArgs = ['-debug']
+        fullArgs = [engaugeExecutable] + debugArgs + argumentsArray
+
+        # Linux has a bug where using shell requires arguments to be joined or else only first is seen. So if shell=True
+        # is added then first argument becomes ' '.join (fullArgs)
+        p = subprocess.Popen (fullArgs,
+                              stdin = subprocess.PIPE,
+                              stdout = subprocess.PIPE,
+                              stderr = subprocess.PIPE)
+        out, err = p.communicate ()
+        preturncode = p.returncode
+        if preturncode == -SIGSEGV:
+            # On Travis engauge segfaults when running engauge with -exportonly, but after high level code has completed
+            preturncode = 0
+        if preturncode:
+            # Dump log file but only, for simplicity, if it exists in the executable directory
+            engaugeLogFilename = os.path.dirname (engaugeExecutable) + os.sep + '.engauge.log'
+            if os.path.exists (engaugeLogFilename):
+                with open (engaugeLogFilename, 'r') as engaugeLogFile:
+                    for line in engaugeLogFile:
+                        print (line, end='')
+
+            # Show error message
+            noExeError = "{} {} - return={}.\nCommand line '{}'\nout='{}'\nerr='{}'\n{}" . format (
+                'Error while executing Engauge at',
+                engaugeExecutable,
+                preturncode,
+                fullArgs,
+                out.decode ('utf-8'),
+                err.decode ('utf-8'),
+                'Version 11.3 or newer is required')
+            
+            print (noExeError)
+            sys.exit (0)
+
+    def computeAffineTransformation (self, screen, graphX, graphY, graph1):
+        # Compute screen-to-graph affine transformation from screen and graph points in axes
+        screenInverse = np.linalg.inv (screen)
+        m1 = np.dot (screenInverse, graphX)
+        m2 = np.dot (screenInverse, graphY)
+        m3 = np.dot (screenInverse, graph1)
+        screenToGraph = np.array ([m1.flatten(), m2.flatten(), m3.flatten()])
+        return screenToGraph
+      
+    def curve (self, curveName):
+        return list (self._curves [curveName])
+
+    def curveNames (self):
+        return list (self._curves.keys ())
+
+    def delimiterEnumToDelimiter (self, delimiterEnum):
+        # Mapping ExportDelimiter enum
+        switcher = {
+            0: ',',
+            1: ' ',
+            2: '\t',
+            3: ';'
+            }
+        return switcher.get (delimiterEnum, ' ')
+
+    def exportDelimiter (self):
+        return self._delimiter
+
+    def getScreenAndGraph(self, node):
+        #Get screen and graph coordinates from axis data
+        #Allows for three or four axis points
+        rowsGraph = 0
+        rowsScreen = 0
+        screen = np.empty(shape=(3, 3))
+        graphX = np.empty(shape=(3, 1))
+        graphY = np.empty(shape=(3, 1))
+        graph1 = np.ones(3)
+        try:
+            for nodeAxes in node.iter():
+                if (nodeAxes.tag == 'Point'):
+                    for nodePoint in nodeAxes.iter():
+                        if (nodePoint.tag == 'PositionScreen'):
+                            x = float(nodePoint.attrib.get('X'))
+                            y = float(nodePoint.attrib.get('Y'))
+                            screen[rowsScreen][0] = x
+                            screen[rowsScreen][1] = y
+                            screen[rowsScreen][2] = 1
+                            # print ('Input positionScreenAxes', x, y)
+                            rowsScreen += 1
+                        elif (nodePoint.tag == 'PositionGraph'):
+                            x = float(nodePoint.attrib.get('X'))
+                            y = float(nodePoint.attrib.get('Y'))
+                            graphX[rowsGraph] = x
+                            graphY[rowsGraph] = y
+                            graph1[rowsGraph] = 1
+                            # print ('Input positionGraphAxes', x, y)
+                            rowsGraph += 1
+            return screen, graphX, graphY, np.ones(3), rowsGraph, rowsScreen
+        except Exception as e:
+            screenX = []
+            screenY = []
+            screenXNew = []
+            screenYNew = []
+            graphX = []
+            graphY = []
+            IsXOnly = np.array([], dtype='str')
+            for nodeAxes in node.iter():
+                if (nodeAxes.tag == 'Point'):
+                    for nodePoint in nodeAxes.iter():
+                        if (nodePoint.tag == 'Point'):
+                            IsXOnly = np.append(IsXOnly, nodePoint.attrib.get('IsXOnly'))
+                        if (nodePoint.tag == 'PositionScreen'):
+                            x = float(nodePoint.attrib.get('X'))
+                            screenX.append(x)
+                            y = float(nodePoint.attrib.get('Y')) 
+                            screenY.append(y)
+                        elif (nodePoint.tag == 'PositionGraph'):
+                            x = float(nodePoint.attrib.get('X'))
+                            graphX.append(x)
+                            y = float(nodePoint.attrib.get('Y'))
+                            graphY.append(y)
+            graphX = np.array(graphX)
+            graphX = graphX[IsXOnly == 'True']
+            graphX = np.append(graphX, graphX[0])
+            graphY = np.array(graphY)
+            graphY = graphY[IsXOnly == 'False']
+            graphY = np.append(graphY, graphY[1])
+            graphY[1] = graphY[0]
+            screenX = np.array(screenX)
+            screenY = np.array(screenY)
+            xAxesScreenX = screenX[IsXOnly == 'True']
+            xAxesScreenY = screenY[IsXOnly == 'True']
+            yAxesScreenX = screenX[IsXOnly == 'False']
+            yAxesScreenY = screenY[IsXOnly == 'False']
+            #The below section calculates the screen coords of intersections of 
+            #lines formed by the x and y axes
+            if ((yAxesScreenX[1] - yAxesScreenX[0]) != 0):
+                m1 = (yAxesScreenY[1] - yAxesScreenY[0]) / (yAxesScreenX[1] - yAxesScreenX[0])
+            else:
+                m1 = np.inf
+            m3 = (xAxesScreenY[1] - xAxesScreenY[0]) / (xAxesScreenX[1] - xAxesScreenX[0])
+            m2 = m1
+            m4 = m3
+            b1 = xAxesScreenY[0] - m1 * xAxesScreenX[0]
+            b2 = xAxesScreenY[1] - m2 * xAxesScreenX[1]
+            b3 = yAxesScreenY[0] - m3 * yAxesScreenX[0]
+            b4 = yAxesScreenY[1] - m4 * yAxesScreenX[1]
+            #Use a slightly different procedure if the y-axis
+            #has an infinite slope
+            if ((m1 == np.inf) or (m1 == -np.inf)):
+                screenXNew.append(xAxesScreenX[0])
+                screenYNew.append(m3 * screenXNew[0] + b3)
+                screenXNew.append(xAxesScreenX[1])
+                screenYNew.append(m3 * screenXNew[1] + b3)
+                screenXNew.append(xAxesScreenX[0])
+                screenYNew.append(m4 * screenXNew[2] + b4)
+            else:
+                screenXNew.append((b1 - b3) / (m3 - m1))
+                screenYNew.append(m3 * screenXNew[0] + b3)
+                screenXNew.append((b2 - b3) / (m3 - m2))
+                screenYNew.append(m3 * screenXNew[1] + b3)
+                screenXNew.append((b1 - b4) / (m4 - m1))
+                screenYNew.append(m4 * screenXNew[2] + b4)
+            return np.array([screenXNew, screenYNew, np.ones(3)]).T, graphX, graphY, np.ones(3), rowsGraph, rowsScreen  
+
+    def parseXml(self, tree):
         # (xG1 xG2 xG3) = screen * (m11 m12 m13)
         # (yG1 yG2 yG3) = screen * (m21 m22 m23)
         # (1   1   1  ) = screen * (m31 m32 m33)
-        # where 
+        # where
         # screen = (xS1 yS1 1)
         #          (xS2 yS2 1)
         #          (xS3 yS3 1)
-        rowsGraph = 0
-        rowsScreen = 0
-        screen = np.empty(shape=(3, 3)) 
-        graphX = np.empty(shape=(3, 1))
-        graphY = np.empty(shape=(3, 1))
-        graph1 = np.empty(shape=(3, 1))
-        screenToGraph = np.array([])
+        self.LogPlot = False
+        self._screenToGraph = np.array([])
+        self._delimiter = ','
         for node in tree.iter():
             # print (node.tag, '<->', node.attrib)
-            if (node.tag == 'Curve'):
-                curveName = node.attrib.get ('CurveName');
+            if (node.tag == 'Coords'):
+                self.xAxisType = node.attrib.get('ScaleXThetaString')
+                self.yAxisType = node.attrib.get('ScaleYRadiusString')
+                if ((self.xAxisType == 'Log') or (self.yAxisType == 'Log')):
+                    self.LogPlot = True
+                    #sys.exit (1)
+            elif (node.tag == 'Export'):
+                # delimiterEnum = node.attrib.get('Delimiter')
+                pass
+            elif (node.tag == 'Curve'):
+                curveName = node.attrib.get('CurveName')
                 if (curveName == 'Axes'):
-                    for nodeAxes in node.iter():
-                        if (nodeAxes.tag == 'Point'):
-                            for nodePoint in nodeAxes.iter():
-                                if (nodePoint.tag == 'PositionScreen'):
-                                    x = float (nodePoint.attrib.get ('X'))
-                                    y = float (nodePoint.attrib.get ('Y'))
-                                    screen [rowsScreen] [0] = x
-                                    screen [rowsScreen] [1] = y
-                                    screen [rowsScreen] [2] = 1
-                                    # print ('Input positionScreenAxes', x, y)
-                                    rowsScreen = rowsScreen + 1;
-                                elif (nodePoint.tag == 'PositionGraph'):
-                                    x = float (nodePoint.attrib.get ('X'))
-                                    y = float (nodePoint.attrib.get ('Y'))
-                                    graphX [rowsGraph] = x;
-                                    graphY [rowsGraph] = y;
-                                    graph1 [rowsGraph] = 1;
-                                    # print ('Input positionGraphAxes', x, y)
-                                    rowsGraph = rowsGraph + 1;
-                    screenToGraph = self.computeAffineTransformation(screen, graphX, graphY, graph1)
+                    screen, graphX, graphY, graph1, rowsGraph, rowsScreen = self.getScreenAndGraph(node)
+                    self.xScreenMax = screen[:, 0].max()
+                    self.yScreenMax = screen[:, 1].max()
+                    self.xScreenMin = screen[:, 0].min()
+                    self.yScreenMin = screen[:, 1].min()
+                    self.xMin = min(graphX)
+                    self.yMin = min(graphY)
+                    self.xMax = max(graphX)
+                    self.yMax = max(graphY)
+                    #print(self.yScreenMin)
+                    #print(self.yScreenMax)
+                    #print(self.yMin)
+                    #print(self.yMax)
+                    #print(screen)
+                    if rowsGraph < 3 or rowsScreen < 3:
+                        print ('This script requires three axes points. Quitting')
+                        sys.exit (1)
+                    self._screenToGraph = self.computeAffineTransformation(screen, graphX, graphY, graph1)
                 else:
                     for nodeGraph in node.iter():
                         if (nodeGraph.tag == 'Point'):
                             for nodePoint in nodeGraph.iter():
                                 if (nodePoint.tag == 'PositionScreen'):
-                                    x = float (nodePoint.attrib.get ('X'))
-                                    y = float (nodePoint.attrib.get ('Y'))
+                                    x = float(nodePoint.attrib.get('X'))
+                                    y = float(nodePoint.attrib.get('Y'))
                                     # print ('Input positionScreen', x, y)
-                                    vecScreen = np.array ([x, y, 1])
-                                    vecGraph = np.dot (screenToGraph, 
-                                                       vecScreen)
-                                    x = vecGraph [0]
-                                    y = vecGraph [1]
+                                    vecScreen = np.array([x, y, 1])
+                                    vecGraph = np.dot(self._screenToGraph,
+                                                      vecScreen)
+                                    xGraph = vecGraph[0]
+                                    yGraph = vecGraph[1]
+                                    if (self.xAxisType == 'Log'):
+                                        xGraph = np.exp( (xGraph - self.xMin) \
+                                                 * (np.log(self.xMax) - np.log(self.xMin)) \
+                                                 / (self.xMax - self.xMin) \
+                                                 + np.log(self.xMin) )[0]
+                                    if (self.yAxisType == 'Log'):
+                                        yGraph = np.exp( (yGraph - self.yMin) \
+                                                 * (np.log(self.yMax) - np.log(self.yMin)) \
+                                                 / (self.yMax - self.yMin) \
+                                                 + np.log(self.yMin) )[0]
                                     # print ('Computed positionGraph', x, y)
-                                    self.curves [curveName].append ([x, y]);
-    def computeAffineTransformation (self, screen, graphX, graphY, graph1):
-        # Compute screen-to-graph affine transformation from screen and graph points in axes
-        screenInverse = np.linalg.inv (screen)
-        m1 = np.dot (screenInverse, graphX)
-        m2 = np.dot (screenInverse, graphY)
-        m3 = np.dot (screenInverse, graph1)
-        screenToGraph = np.array ([m1.flatten(), m2.flatten(), m3.flatten()])
-        return screenToGraph
-    def curve (self, curveName):
-        return list (self.curves [curveName]);
-    def curveNames (self):
-        return list (self.curves.keys ());
+                                    self._curves[curveName].append([xGraph, yGraph, x, y]) 
+
+    def transformGraphToScreen (self, xGraph, yGraph):
+        graphToScreen = np.linalg.inv (self._screenToGraph)
+        vecGraph = np.array ([xGraph, yGraph, 1])
+        vecScreen = np.dot (graphToScreen,
+                            vecGraph)
+        return int (0.5 + vecScreen [0]), int (0.5 + vecScreen [1])
+
+    def upgrade (self, digFile):
+        # File naming consistent with main.cpp
+        FILE_SUFFIX = '.dig'
+        UPGRADE_TOKEN = '_upgrade'
+        count = len (FILE_SUFFIX)
+        if digFile [-count:].lower () == FILE_SUFFIX.lower ():
+            # xyz.dig turns into xyz_upgrade.dig
+            digFileWithoutSuffix = digFile [: -count]
+            digFileUpgraded = '{}{}{}' . format (digFileWithoutSuffix,
+                                                 UPGRADE_TOKEN,
+                                                 FILE_SUFFIX)
+        else:
+            # xyz turns into xyz_upgrade
+            digFileUpgraded = '{}{}' . format (digFile,
+                                               UPGRADE_TOKEN)
+
+        # Stop if this could overwrite valuable information
+        if os.path.exists (digFileUpgraded):
+            print ('Upgrade file exists and will not be overwritten. Quitting')
+            sys.exit (0)
+
+        # Create the upgrade from the old dig file. It will be removed after
+        callEngauge (["-upgrade",
+                      digFile])
+
+        return digFileUpgraded
+
+        
+
diff --git a/contrib/python/README b/contrib/python/README
index 7e87ea8a..43177b26 100644
--- a/contrib/python/README
+++ b/contrib/python/README
@@ -1,8 +1,11 @@
-CurveFitting.py             Python script that reads in a DIG file and performs polynomial curve fitting
-ExampleParseDig.py          Python script that shows how to use ParseDig.py. This script dumps the DIG file specified in
-                            the command line. This code can serve as a starting point for other scripts that can process
-                            the information into other output formats - like SQL tables and NETCDF.
-InsertDerivedColumn.py      Python script that reads in (longitude,latitude) points and output those points with a timestamp
-                            at each point that is computed assuming a constant speed through the points
-ParseDig.py                 Python class that reads Engauge Digitizer DIG files, and provides that information through a
-                            very simplie application programming interface (API)
+CurveFitting.py               Python script that reads in a DIG file and performs polynomial curve fitting
+DumpGraphAndScreenCoordinates Dumps the graph and coordinates of each point in a DIG file, to the console
+ExampleParseDig.py            Python script that shows how to use ParseDig.py. This script dumps the DIG
+                              file specified in the command line. This code can serve as a starting point
+			      for other scripts that can process the information into other output formats
+			      like SQL tables and NETCDF.
+InsertDerivedColumn.py        Python script that reads in (longitude,latitude) points and output those
+                              points with a timestamp at each point that is computed assuming a constant
+			      speed through the points
+ParseDig.py                   Python class that reads Engauge Digitizer DIG files, and provides that
+                              information through a very simplie application programming interface (API)
diff --git a/contrib/python/samples/two_bumps.dig b/contrib/python/samples/two_bumps.dig
new file mode 100644
index 00000000..94ec490b
--- /dev/null
+++ b/contrib/python/samples/two_bumps.dig
@@ -0,0 +1,344 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE engauge>
+<Document VersionNumber="11.2" AxesPointsRequired="0">
+    <Image Width="880" Height="651"><![CDATA[AAAAAYlQTkcNChoKAAAADUlIRFIAAANwAAACiwgCAAAAOKr97gAAAAlwSFlzAAALEwAACxMBAJqcGAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAACAASURBVHic7d1tjFzleT/gGQyK17vs1ilKhOqFYlw3ogIXpAiaF7sWgbBl15KFRVvcWiooTaSkFFqtFaIqbaWWxVWUoCiB/ElLK2GIo0VRqce1iELxB5MKHFEwFRiCjONV+BDysrv4LQ32/D9s2KxnzoznnOfMzHm5rk9mOPOcs7P3nPnt/ZznTLVer1cAACCp8/p9AAAA5JtACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACJI8UM7Ozo6NjY2MjIyNjc3NzUVus2vXrvPOi9jFzp07q9Vq4l0DAJAdyQPl1NTU+vXrZ2ZmNmzYsGPHjuYNnnnmmYMHD9br9YbH6/X6ww8/nHi/AABkSvJAWavVtmzZMjw8vHnz5j179jRv8Nxzz917773Nj+/evfuDH/xg4v0CAJAp1eYOYocGBwd//OMfDwwMnDhx4v3vf//bb78dvYNq4y4+/OEP79y5c/Xq1Yl3DQBAdpyf+JmnTp1avnx5pVJZvnz5iRMnOnzWvn37Vq5cedlllzX/r1qtlvhgAABIYHx8PHyQ5IFyYGDg1KlTAwMDJ0+eHBwc7PBZ991331133RX5v5p/HhETACD7kgfK1atXz8zMrF279ujRo2vWrOnwWU8++eSTTz658O9qtbphw4Z9+/a12T6V1AwAQLO0mnfJF+Vs2rRpenp6fn5+enp6YmKiw2fV37Xw7/ZpEgCA7EseKLdv375///7R0dEDBw5MTk4uPr54g8lqtbrw78V/AABQPMmnvIeHh/fu3dv8+OLa7faLuC3xBgAoBl+9CABAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBzu/3AUCvVW+cSvbE+rfvSfdIgJK6fiThE5+aS/U4IDUCJYWVODiGDCh0QqklToqB4wua9JtASb6lnhoDLT0e4RLKots5MvEBCJr0ikBJXmUtSjZbPELJEoqp7znynBaPULKkywRKciY8RyaOd4l3LVlCoYTnyMTxLvGuJUu6TKAkN+LmudTTW/sBOzk8E+KQV7GSXPdCW6uROz+8hS3FStImUJJ1eVkKs/QYYoXLLBw8EC0jOTLBrtsfuYYlaRMoya68RMlmi0clWUIu5SVHtrF4VJ0ky2z+CORK8kA5Ozv7x3/8x9/97nc/9KEP7dq1a2QkomR37dp12223nTlzZvGRN9544/bbbz9w4MDll1/+0EMPXXvttYkPgKLKb45sJllCbsS9PDEvIayTZKlhSbDkgXJqamr9+vXf/OY3H3jggR07dtx7770NGzzzzDMHDx6s1+tLH7zjjjtuuOGGPXv2PProo5/85CdfeOGFxAdA8RQpSjaINSEuWUJPdR4lc523Fg5ew5LuqDYEvs79zu/8zr//+7//1m/91quvvnrrrbe++OKLDRt86Utfuvvuu6vVs3bx8MMPb9269T3vec/bb7998cUXHzt2rM0uarXa+Ph4ssMjRwqcI9vrcJlRIX92yIQOo2QhA1YnP3shf3DOllbWSt6hPHLkyKpVqyqVyujo6OHDh5s3uPvuu5sfvP322xf+8Z3vfOe6665LvHcKQJzqcEJ84f8W+HWAPhCnNCxJVfIO5bJly955551qtXrmzJkLLrjg9OnT0TuoRuzi0KFDN9100xNPPLFu3brFB2u1WrIjIY8mvvxS+w1233llb44kU875slTK+spAKsa/tLX9BrW7H+3NkWSNV6bMUulQJg+UQ0NDb7311sDAwPHjxy+++OL5+fnoHTQFypdeemliYuLBBx8cGxtrvwtT3kXVviGnFVfpoH3rVYJ4ztmS1IernOtV8hIVUf+nvFevXj0zM7N27dqjR4+uWbOmw2e9+eab4+PjDzzwwDnTJIXUJidJSEstvBptXi7z4NApUbJz7ZeEmwGnteSBctOmTdPT03/xF38xPT09MTHR4bMmJye3bdt28803J94v+RUZj0SiNjqMlRUvIzRzlWSINldYXj/idaNZ8inv+fn5P/zDP/zud7+7fv36b3zjG0NDQ78c8d057mq1unT7hQfPO++8pXv8/ve/36a7acq7SKTJcObBoSNakumKfD29hkXR/ynv4eHhvXv3Nj++mBcjo+rSm5xTEq1ikPQTl3lwOAdRshuemot4YU1/czZfvUh3aUymTqyERma3u63VDLjpb94lUNJF0mT3nPMelmIlZWFhcs+0alV6kREo6RLT3D3TvmEpVlJkomTvmf6mBYGS9GlM9p5YSbmIkn1k+psoAiUpkyb7SKyk+NpESWmml0x/c7bz+n0AFEf1xilpMgvq376nzWve4VeoQxZJk5kS+ZpfP9LRGikKR4eSdIiSWdOmW6lVSf6Iktlk+pt36VCSAmkys9p0K1t1lCFb2nS8npqTWjKhVauSMtGhJIjV3LmgW0ku6UrmiNXfpadDSXKtGpPSSTa5sJI8kSZzp1XDWKuyHHQoSUJjMqe0KskBUTLXrP4uK4GS1MgieSFWklGiZDFEZkqKTqAkBfJHHomVZIgoWTDNq781KYvONZTE1hBBxI5cc2Elfdb+toUiSK41/Pq0LQtNh5J4loYMUbIYtCrpG1Gy8BpalfqUxaVDSQzSZIG1v2Nljw+G4nN3yVJZ+gvVpywogZJOSZNl0CpWugs6aRIlS0imLDqBko5Ik6WiVUm3tGpMipJlIFMWmkDJuUmTJaRVSfraNCYpCZmyuARKzkGaLDOtStKhMckimbKgBErakSbRqiSUxiQNZMoiEihpSZpkkVYlSWhM0opMWTgCJdGkSRpoVRKPxiTtyZTFIlASQZqkFa1Kzk1jkg7JlAUiUNKONEkzrUra0ZgkFoVRFAIljRYzgTRJG1qVNNKYJJnF8tCkzDOBkrNIA3ROq5Jf0ZgkFTJlbgmU/IpLJ0lAq7LsNCYJ52LK/BMo+SVpksTatCp7fzD0TqsoWdGYJD6ZMucESioVaZI0mP4ulzZRUpokGZkyzwRKpElSo1VZFhqTdIlMmVsCZdlJk6ROq7LIXDFJt8mU+SRQlpo0SZdYqVNMoiS9IVPmkEBZXtIkXeWmQoXSpjEJ3SBT5o1AWVLSJL2hVVkErpikL2TKXBEoy0iapJe0KnPMFZP0l0yZHwJluTR8hEuT9IxWZf5oTJIFMmVOCJTlJU3SY24qlCcak2SHTJkHAmWJ+NgmC0x/Z531N2RNQ0HKlJkkUAK9plWZXRqTZJDyywOBsiwaPqrNd9N3WpXZojFJljXUoSZl9giUpeATmmyyUicrrL8hd2TKjDm/3wdAH2hPkh0L1dicIBceUatdJ0qSF0/NCZFZpkNZfCa7yT6tyv6QJskXE98ZJlACmWClTk+5YzmQKoGy4LQnyRcrdXpBY5L80qTMKoGyyHwGk0dald2lMUnByJTZIFCWiPYkOSJTdoUbA1EAKjaTBMrCMtlN3pn+TlPkRZMak+SUie/sESiLyScuxWD6Ox0akxSeTNlvAmUpaE+SazJlEGmSQlLDGSNQFpDJbopHpkxImqTATHxniW/KAfIh8jt1fKFOS6Ik0EM6lEWjPUmxaVV2RJqkJDQpM0OgLBQfq5SBTHkO0iRlJlP2iUBZZNqTFJU7CkVr84WKUFTKOxsEyuIw2U2puKNQI1+BQ2mZ+M4AgbIgyvshSrnJlL+kMQlLyZQ9J1AWk/Yk5SFTSpOg4PtOoCwCk92UXOT0dykuqfSFirDIxHdfCZRAQZSuVakxCWSGQJl72pOwqESZUpqEZpqU/SNQ5lsxPykhQPEzpXsDQedkyl4RKAtFexIqxb6k0r2BoD3vhT4RKHPMZDe0UcBWpcYkdMLEdz8IlHmV789F6IlCZUppEhKTKbtPoCwI7UmIVIQvaXRvIIjLu6PnBMpcMtkNncv3lzRqTEIyJr57S6AESiGXmVKaBHJCoMwf7UlIJmeZUpqEQJqUPXR+vw+AeLL74Qd5sJApG95HC/+Zob/NREnokutHvJW6RIcy3zL0EQj5kelWpTQJKfLe6RWBMk9MdkNaMpoppUlInYnvnhAoc6P/H3VQLNm6o5AvVATyLOVAOTs7OzY2NjIyMjY2NjcXfR7ctWvXeecJsqG0JyFcVu4o5AsVoas0Kbsv5WA3NTW1fv36mZmZDRs27Nixo3mDZ5555uDBg/V6Pd39lo00CSnqc6bUmATyL+VAWavVtmzZMjw8vHnz5j179jRv8Nxzz917773p7rQMzHdDV/UtU0qT0BualF2W8m2Djhw5smrVqkqlMjo6evjw4eYN7r777nT3CJCKXt9RSJQECiTlDuWpU6eWL19eqVSWL19+4sSJdAcvLYu7oWd61KqUJqH3NCm7KeUO5cDAwKlTpwYGBk6ePDk4OBjrubVarcMHS85rAl21+84rJ778UsOD1Rundt95ZSrjj39pa/ODtbsfrXhrQ5eNn/2fPk9TVE13fcxVV131+OOPr1279pVXXtm6devzzz8fvddqR/ut1Wrj4+Pn3KzYtCehLyK7kqFvwFYdEb1J6JmGt2Hp331pZa2Up7w3bdo0PT09Pz8/PT09MTGR7uAAPRN5R6Ggu1S6NxBQXCkHyu3bt+/fv390dPTAgQOTk5OLj1er1cV/LPx78R+0oT0J/ZXaJZUumoSMcCVld6QcKIeHh/fu3Ts3N7d79+6hoaHFxxcnuOtnS3fvAKlLIVNKk0DR+caa7NKehIwIypTNadI0N/SXJmUXpLzKG6CQktylUmMSKA0dynzQnoQsiNGqlCYhy7wZ0yZQZpTvWoRs6ihTSpOQL2a9gwmUAPGcI1NKk0D5CJRZZDkOZFyru1RaggO5YWlOqgRKgISWZsr66fvqp+9r3EKUBMpBoMwc7UnIkYV3aESUrEiTkHmalOkRKAGCRKbJ6rLP9v5IAPpFoMwW7UnImaiWxkKadK8GyAFNypQIlABJNX32VJd9dmlvUqYESkKgzBDtSciN60ciF3RHLv0WKyHTNCnTIFACxNT2TpNBX/wNkE8CZVZoT0I+dHDfcpkSckaTMphACdCxjr8FR6YESkWgzCLtScicFhdNtrnZZMtv0wEyyI1jwwiUmeAzBjIt4Ou5LdOBXDLrHZNACdBWQJpcYPobKDyBsv8sx4HsCk6TC2RKyAFLcwIIlAAtxLxosj2ZEigwgbLPtCchi1otwQnTapmOWAlZoUmZlEAJcLaUprlb0aoEikeg7CftScicLqfJBTIlZJcmZSICJcC7epImF8iUQJEIlH2jPQnZkuoSnE648zlklCZlfAIlUHrdWYLTIct0gAIQKPtDexKyoofT3K2Y/obM0aSMSaAESiwDaXKBTAnkmkDZf9qT0B+ZSZMLZErIlv6dDfJIoOwDnxDQfz1fgtMJy3Qgu8x6tyVQAiXT1yU4nbBMB8gdgbLXLMeBfsrYNHcrpr8hEyzN6ZhACZRGTtLkApkSyBGBsqe0J6FvcpUmF8iU0H+alJ0RKIGia3XRZLbT5ALLdIBcECh7R3sS+iCHjclmlulAP2lSdkCgBIqrEGlygelvIMsEyh7RnoReK1CaXCBTQt9oUp6LQAkUUW4vmmxPpgSySaDsBe1J6J3M37c8UKtlOmIldFeBTiPdIFACBVK4ae5WtCqhz8x6n02g7DXtSeiW0qTJBTIlkB0CZdc5v0MvlCxNLpApoacszWlNoATyr6BLcDrhzudAFgiUPWW+G1JW9CU4HbJMB3qkfKeXDgmU3eWEDl1UymnuVkx/Qx+Y9X6XQAnkkzTZRKYE+kWg7B3z3ZAaabIFmRK6zqkmikDZRU7i0BUlXoLTCct0oKfMelcqFYESyBNLcDpmmQ7QSwJlj5jvhlCmuWMy/Q3d4szTRKDsFmdtSJM0mYhMCb1g1lugBHJAmgwgUwI9IFB2RcPJ2nw3JNTqoklpMg7LdCB9vobxbAIlkFUak6myTAfoHoGy67QnIQlpsgtMf0OanJGWECjT5+wMoaTJrpEpoVvKPestUAIZ46LJLpMpgdQJlN1lvhticN/yXmm1TEeshHicoN4lUKbM6RgSMs3dc1qVkLISz3oLlEAGSJN9IlMCqRAou8h8N3REmuwrmRKCOFlVKhWBMl1OwRCbJTgZ4M7nkJqyznoLlECfWIKTMZbpAIkJlN1ivhvaMc2dSaa/IQnnLoEyRc650ClpMsNkSghVyllvgRLoLWky82RKIC6BMh0Np1rz3RDNEpycsEwH4mk4j5WvSSlQAj1hCU4OWaYDdEigTJ/2JDQyzZ1bpr+hU+U+pwmUKXBuhXakyZyTKSGJks16C5RAN0mThSBTAu0JlCkz3w2/1OqiSWkynyzTgXMr8flNoAzlfAoRNCYLyjIdiKFMs94CJZA2abLQTH8DzZIHytnZ2bGxsZGRkbGxsbm5iI+KyA1efPHFa6+9dmho6Nprr33hhRcS7z2bzHeDNFkGMiW0VNbTXfJAOTU1tX79+pmZmQ0bNuzYsaPDDf7sz/7sU5/61I9+9KNPfOITd9xxR+K9Z4QTKJzFRZOlIVNCR0oz6508UNZqtS1btgwPD2/evHnPnj0dbnDo0KHbbrttxYoV27Zte+WVVxLvHcgc9y0vmVbLdMRKKKHkgfLIkSOrVq2qVCqjo6OHDx/ucIP169f/27/92/Hjxx977LGNGzcm3nsW+LpF+BVpsqy0KqFRKb+GsVqv15M9c9myZe+88061Wj1z5swFF1xw+vTpTjZ47bXXPvzhD//4xz++6KKL9u/f/9u//duL29dqtcQ/Rl9MfPmlpf+5+84r+3Uk0EfjX9ra/GDt7kd7fyT0UcP5cIGzIqXVcGLM+ClxfHw8fJDkgXJoaOitt94aGBg4fvz4xRdfPD8/38kGH/vYx2699datW7fu2rXrkUce2bdvX5td1Gq1VH7ILln6J7j2JCVlCQ7viuxKOjdSXktPjxk+K6aVtZJPea9evXpmZqZSqRw9enTNmjUdbvDMM89s27ZtcHBw69atzz33XOK9950JHZAmWcqdz6GlEsx6Jw+UmzZtmp6enp+fn56enpiY6HCDtWvX7ty58+TJk4899tgHPvCBxHsH+kyaJIplOlBOyQPl9u3b9+/fPzo6euDAgcnJycXHq9Vqmw0efvjhBx544Nd//de/8pWvfP3rXw859Owwp0PpuD0QrVmmA5VK6f7ATn4NZQ9k9hpK67spNQu66YBLKqHxbJnJU2X/r6EESuf6EWmSDulTQqkIlKH8wU1ZuGiSmCzToezKdIYUKGNzNqSMpEmSskwHfqnQa70FSuBcpEnCmP6GwhMog5jvpvgs6CYNMiUlVZqzpUAZj9Mf5WIJDumRKaHAs94CJRDFgm66wDIdKCqBMga3n6QsXDRJN1mmQ7k0nDwL2qQUKIGzSZN0n+lvKBiBMiHtSYpJmqRXZEpKpARnUYGyU05zFFyriyZLcB6kX1plSudbCq6Is94CJaAxSd9ELtOp+Bse8kagTMJ8N4UiTdJvMiXFV/STqkDZEec1CkuaJBtkSsqlcLPe5/f7AIA+ESXJmIVM2RAiF/7TvBBknA5lbM5rFIE0SVZpVVJYhT7HCpTn5kRG0UiTZJtMSSkUa9ZboIQyibw3UEWaJHPcUQjyRaA8B1+3SHG0ipLSJJnkjkIUUHHPtwIllIPGJPkkU1JkBZr1Fihj0J4kr6RJ8kymhOxz2yAoNFGSQnBHIYrjqbkiNSYX6VC24y9g8k2apFi0KimgooRLgRIKSpqkiGRKyCaBslNmVcgN9wai0GRKcq+IZ2PXUEKxiJKUgEsqIWt0KFvy9y75I01SJlqVFEQhLqMUKKEopEnKR6aEjBAoO2IOhUyLvGjSV+BQDr6kkVwq3PlZoIzmTERuaExSer6kkdzL/6y3QAl5Jk3Cu2RK6COB8tzMd5NR0iScTaYkT4p1unbbIMghURJacEch6Asdygj+nCXTpEk4F61K8ifnl1EKlJAr0iR0RqaEXhIoz8EUCVnhCxUhJncUIusKdAIXKCEPWkXJAp2MoBvcUQh6Q6Bs5CxD5mhMQhiZknzI82WUAiVkmzQJaZApoavcNqgdF1DST6IkpModhciip+Zy3ZhcpEN5Fn+tkhXSJHSHViWZlttwKVBC9kiT0E0yJaROoGzJDAh94N5A0BMyJRlSiDO8ayghM0RJ6CGXVEKKdCh/xd+m9JM0Cf2gVUnm5PMySoES+s00N/SVL9SBcAJlNPMd9IivwIEMaHXOlynpkfyf8wXKX3LWoA80JiEzfEkjGZLDWW+BEvrBNDdkkulvSEagjGC+m+4yzQ0ZplVJf+T8I0CghN7SmIQ8kCkhFoGyUnGOoDdMc0OumP6mn/J2GaVACT1hmhtyyPQ3dEigbOQCStKnMQl5JlPSI3n+XBAooZtMc0MhmP6G9gRKf2XSNaa5oUBMf9NrubqMUqCE7tCYhCKSKSGSQHkWF1CSAtPcUGimv+mi3H5SlD1Qev+TMtPcUAKmv+mR/Mx6lz1QQmo0JqFkZEpYJFD+ivlukmv1R6Q0CYVm+pv05fODQ6CEYKa5ocRMf0Ol5IHSu51QprmBSqWiVUn35OQyylIHSgiiMQks0eq6KZmSMhAof8kFlMSgMQlEaTP9LVYSQw4/TcobKL23Scj6G6AtrUpSlodZ7/P7fQCQH6Ik0JmFTNmcIBceMSdG8ZS3Q7mU9zbnJk0CMWlVklzePlwESuiA9TdAIm4qREmUNFB6J9Mp62+AYFbqECrzl1GWNFBCRzQmgZRoVVJsAqULKImiMQl0gVYlMeTqE0eghCbW3wBdY6UOhVTG2wZ509KSKAl0n5sKkcT1I1n+MNKhhHdJk0APaVVSJMkD5ezs7NjY2MjIyNjY2NxcxCdu5AZnzpz59Kc/PTQ0dPnllz/99NOJ954WfwhSqbS9YlKaBLrGSh3OIT+fQckD5dTU1Pr162dmZjZs2LBjx44ON3jooYcGBwdnZmampqY+97nPJd57Yt6lNNKYBPrKSh06leGbByUPlLVabcuWLcPDw5s3b96zZ0+HGzz22GN/+qd/unLlyltvvfW///u/E+8d0qExCWSAViV5lzxQHjlyZNWqVZVKZXR09PDhwx1u8L//+78vv/zy+9///quvvvrQoUOJ954K892l5sZAQMZoVRIhJ59KyVd5nzp1avny5ZVKZfny5SdOnOhwg/n5+YMHD77++utf+MIX7rzzzm9/+9uL29dqteZBIh9MS1cHJ8vGv7S1+cHa3Y9WKpWKqgD6Z/edV058+aXmx6s3Tu2+88reHw9ZML7k35mNLtV6vZ7smUNDQ2+99dbAwMDx48cvvvji+fn5TjZYuXLls88+u3bt2rm5uUsuuSRyNc+iWq02Pj7eZoO4Gv7I06EsI1dMAnnQqivpk6uMGj65Uv3ASitrJZ/yXr169czMTKVSOXr06Jo1azrc4NJLL3377bcrlUq9Xj///DLeBZN+kiaBnHBTIfIleaDctGnT9PT0/Pz89PT0xMREhxvccsstjz766Nzc3P33379x48bEew/nj7xycWMgIG/arNQRK8slD59TyQPl9u3b9+/fPzo6euDAgcnJycXHq9Vqmw3+6q/+6vXXX7/44oufeuqpL37xiyGHHpe3X3lpTAK5pVVJo0zePCj5pPPw8PDevXubH1+8KDNyg8HBwf/4j/9IvFOIzVJuIOfafFWj2TYyoqRfvegdWApuDAQUiOnvUsv8J1dJAyXF54pJoHDc/5zMKkug9GYrEY1JoNC0KsngZZRlCZSUhfU3QAlYqUPWlPFOkC6gLCZREiiTNit1Kj7pCumpuQw2JhfpUFII0iRQSlqVZEQpAqX3VZG5YzlQblbqlFTGupWlCJQUlsYkQKVSsVKHfivdNZQuKykIURLgbK6qLL4MX0ZZ/A6lP84KSJoEaMFVlSWSpXBZ/EBJobhiEuBc2mRKsZIuKVeg1PDPN41JgM60WqlT0arMu6x+5JXuGkpySZQEiM9VlfRMwTuU/g4rAmkSIIBWZZFl5jJKHUoyTJQESINWJd1W8A7lUt4wOSNNAqRKq7IgMvk5WOQOpXdIXomSAN2hVUmXlKhDST5IkwBdplVJ6soSKP3VlQPuMQnQK22+AVyszIGlH4vZWJdTlkBJ1mlMAvScViVpKfI1lOSDKAnQP66qJBU6lPRPqznuijQJ0FNalQQqbKBc+h7wB1YWtYmS0iRAz7mqMmcydhllYQMl2aUxCZBVbVqVYiVtCJT0lsYkQLa1alVWzIDTmkBJr7grEEB+aFUSSzEDpQsos8UcN0AOtW9VipX9l6XLKIsZKMkQc9wAeWYGnE4IlHSNxiRAUWhV0p4bm9MFbRrvoiRAPrW6BXrFXdDRoSR95rgBissMOJEKGCityOkbc9wA5WAGPCsysy7HlDdpMMcNUDJmwFmqgB1Kes0cN0BZmQFngUBJAHPcAJgBp3iB0gWUPdI+SkqTACWjVdk32biM0jWUxKcrCUCUVhdWuqqy8IrWoaS7zHEDcC5mwEtIoKRj5rgB6IwZmircsQAAFXxJREFU8LIRKOlAq8akKAlAa1qV5VGoQGlFTvrMcQMQoH2rUqxMRwbW5RQqUJIyc9wApMEMeOEJlETRmAQgbVqVBea2QZzNlygC0DW+sLGoitOhdAFlCsxxA9B9ZsDT1+/LKIsTKAlijhuA3jIDXiSmvEvPHDcAfWIGvDB0KMvNHDcA/WYGvAAEyrIyxw1AlpgBz7WCBEorcmJoHyWlSQD6RKsySF/X5biGsmR0JQHItlYXVrqqMssK0qHk3MxxA5AfZsDzRYeyBKzjBiCHrAHPkSJ0KF1A2ZLLJQHIuTaf7LqVjfp3GWURAiXRNCYBKIQ2i3Uq1utkgynvIhIlASgcM+BZJlAWiygJQKGJldkkUBaFKAlAaYiVWZP7ayityKlUpEkAysiFlRH6tC5HhzLnREkASkyrMiMEytwSJQGgUqmIlRkgUOaQKAkATcTKPsr3NZSlu4CyzY3KK9IkALiwsj+XUepQ5ocoCQAd0KrsPYEyD0RJAIhJrOwlgTLbREkACCBW9ka+r6EssjaXSz41J00CQOfaX1hZlmsruynHgbKwK3KsvAGAtNW/fU+JYmXP1+WY8s6S9r9yURIAwrSZAa+YBA8gUGaDKAkAvSJWpk6g7DdREgD6QaxMUV6voSzCBZTnvFZSmgSALivstZW9vYxSh7IfdCUBIEt0KwMJlL0lSgJAVomViSWf8p6dnR0bGxsZGRkbG5ubi0hCbTbYuXNntVpNvOtcMsENAHlwzknwXh5MXiQPlFNTU+vXr5+ZmdmwYcOOHTs636Berz/88MOJ95tLoiQA5EqbWJnjCyu7JnmgrNVqW7ZsGR4e3rx58549ezrfYPfu3R/84AcT77eSrxU5vvAGAHIr37Gyh+tykgfKI0eOrFq1qlKpjI6OHj58uPMNduzY8alPfSrxfnNDlASAQsh3rOyJ5IHy1KlTy5cvr1Qqy5cvP3HiRIcb7Nu3b+XKlZdddlni/eaAKAkAhVPMuwulJPkq74GBgVOnTg0MDJw8eXJwcLDDDe6777677rorcsBardbhg7E26KXxL21t839rdz9aydLRAgCx7L7zykqlMvHllyL/70KmXNgmI8aX/Lurkalar9eTPfOqq656/PHH165d+8orr2zduvX555/vZIOGxd0bNmzYt29fq13UarXx8fGGBzN6AaX7AQFAmbRvSWY0ojQFksislUDyKe9NmzZNT0/Pz89PT09PTEx0uEH9XQv/bpMmc8P9gACgfAr7FTuJJA+U27dv379//+jo6IEDByYnJxcfX+xBttqgOERJACg3sXJB8msoh4eH9+7d2/z44hx6qw0aNsslE9wAwLt8xY6vXoxJlAQAopQ5Viaf8u6Lfq7IMcENAJxL5ibBe3J785wFyv4QJQGAOMr2heCmvNsywQ0AJNVmEnzxwWJMgguULYiSAEAaynBtZZ6mvHt0AaUJbgAgbf28trL7l1HmKVB2nSgJAHRT+45Yfu9bacq7UqmY4AYAemQxUxZpErz0gVKUBAD6oUjXVpY4UIqSAEC/FSNW5uYayjRX5LhWEgDIkq4v2enyupySdSh1JQGArMpvt7I0gVKUBADyII+xsuiB8pxNXVESAMiefMXKfATKJBdQipIAQM51EisrHaajp+Z+lY6uH0k3COUjUMYjSgIABdI+VlYy0LAsVqAUJQGAgspyrCxEoJQjAYBy6DBWVnqbLHMeKEVJAKB8zvn9jZXeNixzcGPz6BU57W9OXnF/cgCg+NrfEb3ScFP0rt3ePG8dyk5+eDkSACiTGPPg3TmA3ATK+un7zrGFHAkAlFgn8+BdkoNAKUoCAHTunA3L1FXr9S71PoOZ3QYACNMcK5e26qrLPpvKqp0MdyiX3s+9+X8BAHAuvZkHz3CgjCRKAgDEFzkPvvvOK1MZPNO3Dard/ejiv6vLPitNAgCE6NJtKbPeoawu+2y/DwEAgHYyvCin1S3NAQAIsXSZShozwJme8gYAIPsESgAAggiUAAAEyW6gdAElAEBXLL1uspOvkjmX7AZKAAByQaAEACCIQAkAQJBM34eyVquNj4/3+ygAAIopraylQwkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAiSPFDOzs6OjY2NjIyMjY3Nzc11uMEbb7yxcePGoaGhdevWPfvss4n3DgBARiQPlFNTU+vXr5+ZmdmwYcOOHTs63OCOO+644YYbfvSjH33mM5/55Cc/mXjvAABkRPJAWavVtmzZMjw8vHnz5j179nS4wZ/8yZ/89V//9YoVK/7oj/7o9ddfT7x3AAAy4vzEzzxy5MiqVasqlcro6Ojhw4c73OD2229f+Md3vvOd6667LvHeAQDIiGq9Xk/2zGXLlr3zzjvVavXMmTMXXHDB6dOnO9/g0KFDN9100xNPPLFu3brFB2u1WrIjAQAgmfHx8fBBkncoBwYGTp06NTAwcPLkycHBwc43eOmllyYmJh588MGlabIS9fPUarVUfkgAAJql1c5Lfg3l6tWrZ2ZmKpXK0aNH16xZ0+EGb7755vj4+Fe/+tWxsbHEuwYAIDuSB8pNmzZNT0/Pz89PT09PTEx0uMHk5OS2bdtuvvnmxPsFACBTkgfK7du379+/f3R09MCBA5OTk4uPV6vVNht84xvf+Id/+Ifquyz0BgDIu+TXUA4PD+/du7f58cVVPpEbnDlzJvEeAQDIIF+9CABAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAggiUAAAEESgBAAgiUAIAEESgBAAgiEAJAEAQgRIAgCACJQAAQQRKAACCCJQAAAQRKAEACCJQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEF6HShnZ2fHxsZGRkbGxsbm5uZ6vHcAAFLX60A5NTW1fv36mZmZDRs27Nixo8d7BwAgdb0OlLVabcuWLcPDw5s3b96zZ0+P9w4AQOp6HSiPHDmyatWqSqUyOjp6+PDhHu8dAIDUVev1ei/3t2zZsnfeeadarZ45c+aCCy44ffr04v+q1Wq9PBIAAMbHx1MYpd5bg4ODJ06cqNfrx44du/DCC9tvvHv37vA9GsQgBsn1IBk5DIMYxCAGMUgbvZ7yXr169czMTKVSOXr06Jo1a3q8dwAAUtfrQLlp06bp6en5+fnp6emJiYke7x0AgNT1OlBu3759//79o6OjBw4cmJyc7PHeAQBI3fk93t/w8PDevXt7vFMAALrHVy8CABCk17cNAgCgYHQoAQAIIlACABBEoAQAIIhACQBAEIESAIAg2Q2Uu3btOu+8oMN74403Nm7cODQ0tG7dumeffTbBCK+99tpHPvKRwcHBa6655sCBAyEHs3Pnzmq1mvjpH/vYx6rv+sxnPpNskDNnznz6058eGhq6/PLLn3766WSDVM+WbJAXX3zx2muvHRoauvbaa1944YVkg/zgBz/YuHHj4ODgTTfdND8/H/fpzQU2Ozs7NjY2MjIyNjY2NzeXbJBWD8YaJEHpNg+SoHpbHXms6m0eJEH1Ng8St3qbR0hQus2DJCjd5kHilm5kPcQt11ZFFatcIweJW66R28ct1zY77bxcIweJW66Rg8Qt18hB4lZs5CBxKzZykLgVG/nbjFuxrUoiVsVGDhK3YiMHiVuxbbbvvGIjB4lbsZGDpBIPKql8I3jq9u/ff8899wQe3saNG//xH//x+PHjDz300Lp16xKMsH79+i984QvHjx//2te+duWVVyY+kjNnzmzcuDHkx7nmmmtef/31xE9f8OCDD05OTv70pz/95je/ed1114WPduuttyZ77tVXX/3www8fP37861//+jXXXJNskPHx8c9//vOzs7N///d/Pzk5Geu5kQW2ffv2e++9d25ubmpq6p577kk2SNzSjdw+bulGDhK3elsdeazqjRwkbvVGDhKretv/Fjos3chB4pZu5CBxSzeyHuKWa+Qgccs1cpC45Rq5fdxybbXTWOUaOUjcco0cJO7Jtv1r2GHFRg4St2IjB4lbsZG/zbgVGzlI3IqNHCRuxUYOErdiW20fq2IjB4lbsZGDpBIPMhoov/jFL9br9cBA+S//8i+nTp2q1+vz8/ODg4MJRnjkkUf+7//+r16vHzt2bGBgIPGRPPHEE9u3bw/5cVavXv3Tn/408dMXfPSjHz148GDgIAt+8pOf/OZv/uYPf/jDZE8fGBhY+NX8/Oc/T/zCjoyMzM7O1uv1559//oorroj13MgCu+KKK1577bV6vX7o0KGrrroq2SBxSzdy+7ilGzlI3OptdeSxqjdykLjVGzlIrOpt81vovHQjB4lbupGDxC3dyHqIW66Rg8Qt18hB4pZr5PZxy7XVTmOVa+Qgccs1cpC4J9s2r2HnFRs5SNyKjRwkbsVG/jbjVmzkIHErNnKQuBUbOUjcim21fayKjRwkbsVGDpJKPMhooFyQVgP1W9/61vXXX5/46b/4xS++8pWv3HzzzYlH+NCHPnT48OGQH+e9733vjTfeeOGFF/7+7//+D37wg2SDrFy5cteuXe973/t+93d/95VXXkl8MPV6/W/+5m/+9m//NvHTP/7xj3/ta187duzYv/7rv/7BH/xBskFGRkbm5ubq9frLL7+8YsWKBCM0/EZWrFhx4sSJer1+/PjxoaGhZIO0eTDuIPWYpRs5SNzqbR4kQfU2bJysehsGSVC9kccct3QbBklWus2BMlnpLq2HZOVajyqqBKemyMqMe6Zt3j7BybZhkGQn26WDJD7ZLh0k8cm2+TVJcLJdOkjik+3SQZJVbMNvM1nFRpZE3N9vq7qKVbGRg8St2ObtE1RswyDJKrZhkFTiQfED5SuvvHLppZe+8MILIYfxG7/xG9///veTPf3pp59e+J2F/Dhbt279r//6r/n5+bvuumvTpk3JBlm2bNnnPve5+fn5z3/+8zfccEPigzl27Nhll132s5/9LPEIr7766kUXXVSpVC666KJDhw4lG2RsbOzv/u7v5ufn//Iv/7JarSYYoeE3ct555505c6Zer58+ffq8885LNkibB+MOErd0Wx1JrOptGCRZ9TZsnKx6GwZJUL3Nx5ygdBsGSVa6DYMkK92GekhWrpFFFbdcIweJW66tjiRWuTYMkqxcGwZJVq4NgyQ72Ta/JgkqtmGQZBXbMEiyim34bSY+wTaXRIITbPMgCU6wkUcS9wS7dPvEJ9ilgyQ+wS4dJJV4UPBAefDgwUsvvfQ///M/Qwb5xS9+8dWvfvWjH/1osqd//OMf37t3bz2lfPyTn/xkZGQk2XN/7dd+7dVXX63X67Ozs8PDw4mPYdeuXdu2bUv89Hq9fv311/+///f/jh079s///M8bNmxINsirr766bt26lStXTk1Nvec970kwQsNvZHBwcOEP6GPHjl144YXJBmnzYKxBEpRuqw5lrOptbsglqN5WG8eq3oZBElRv82EkKN2GQZKVbnMqjVu6zfWQoFxbFVWsX27kIHHLtdX2scq1eZAE5drmyDsv1+ZBEpRr5JHErdjmQRJUbPMgyU62Db/NZCfYyJJI0KFsGCTBCTbySOKeYBu2T3aCbbXTWCfYhkFSiQdFDpQ//OEPL7nkklqtlniEf/qnf1q40iLkGsqGVVDJ8tPzzz9/+vTper3+1ltvve9970t2JOvWrfve975Xr9d/9rOfvfe97002SL1ev+222x5//PHET6/X68uXLz958mS9Xj958mTIxakLDhw4MDo6muCJDQV25ZVXLryjXn755auvvjrZIG0e7HyQZKXbMEiy6m0YJFn1NgySrHobBklQvc2/hQSl2zBIstJtVQ8dlm5kPcQt1zZF1Xm5Rg4St1wjt49brpGDxC3XyEHilmvkIHHLtdVrGKtiIweJW7Htf5sdVmzkbzNuxbYpic4rNnKQuBUbOUjcio3cPm7FRg4St2IjB0klHmT3tkHhJicnt23bdvPNNyceYffu3ffff/+JEyceeeSRK664Itkgi6/1wr/37duXYJA///M/f+CBB44dOzY1NXX99dcnO5Jbbrnl0UcfnZubu//++xeWlSXzP//zP1deeWXip1cqlbVr1+7cufPkyZOPPfbYBz7wgWSDXHPNNd/61rdmZ2cfeeSRW265JeR4FmzatGl6enp+fn56enpiYiJ8wMTCS7eieqPktHQj6yFuuaZSVJGDxB05cvu45Ro5SNxyjRwkbrlGDhK3XFu9hrEqNnKQuBUbOUjcio38bcat2FTOYJGDxK3YyEHiHl7k9nErNnKQuBUbOUg68SBZDu22VA6y4cZOCS6CPHTo0O/93u+tWLFi3bp1zz33XLLDWBTyaj///PPr1q0bHBy88cYb33zzzWSDHDt2bGJiYmBg4CMf+UjilT31ev3CCy98++23Ez+9Xq9/73vfu/rqqwcGBq6++uqFv4oSePLJJy+55JIVK1Z84hOf+PnPfx7ruZEFNjc3d9NNNw0PD4+Pj3fyA0YOErd0I7ePW7qRg8St3vZH3mH1Rg4St3ojB4lVva1+llilGzlI3NKNHCRu6UbWQ9xyjRyk/S+9w0Hilmvk9nHLtf1OO/lZWg0St1wjB4l7sm3148Sq2MhB4lZs5CBxKzbytxm3YiMHiVuxkYPErdjIQeJWbPvtO6zYyEHiVmzkIKnEg2q96TcEAACdK/KUNwAAPSBQAgAQRKAEACCIQAkAQBCBEgCAIAIlAABBBEoAAIIIlAAABBEoAQAIIlACABBEoAQAIIhACQBAEIESAIAgAiUAAEEESgAAgvx/O08B7CXUP3QAAAAASUVORK5CYII=]]></Image>
+    <CoordSystem>
+        <General CursorSize="3" ExtraPrecision="1"/>
+        <Coords Type="0" TypeString="Cartesian" Coords="0" ScaleXTheta="0" ScaleXThetaString="Linear" ScaleYRadius="0" ScaleYRadiusString="Linear" UnitsX="0" UnitsXString="Number" UnitsY="0" UnitsYString="Number" UnitsTheta="0" UnitsThetaString="Degrees (DDD.DDDDD)" UnitsRadius="0" UnitsRadiusString="Number" UnitsDate="3" UnitsDateString="YYYY/MM/DD" UnitsTime="2" UnitsTimeString="HH:MM:SS"/>
+        <DigitizeCurve CursorInnerRadius="5" CursorLineWidth="2" CursorSize="1" CursorStandardCross="True"/>
+        <Export PointsSelectionFunctions="0" PointsSelectionFunctionsString="InterpolateAllCurves" PointsIntervalFunctions="10" PointsIntervalUnitsFunctions="1" PointsSelectionRelations="0" PointsSelectionRelationsString="Interpolate" PointsIntervalUnitsRelations="1" PointsIntervalRelations="10" LayoutFunctions="0" LayoutFunctionsString="AllPerLine" Delimiter="0" OverrideCsvTsv="False" DelimiterString="Commas" ExtrapolateOutsideEndpoints="True" Header="1" HeaderString="Simple" XLabel="x">
+            <CurveNamesNotExported/>
+        </Export>
+        <AxesChecker Mode="1" Seconds="3" LineColor="6"/>
+        <GridDisplay Stable="True" DisableX="0" CountX="5" StartX="0" StepX="10" StopX="40" DisableY="0" CountY="4" StartY="0" StepY="0.05" StopY="0.15" Color="0" ColorString="Black"/>
+        <GridRemoval Stable="False" DefinedGridLines="False" CloseDistance="10" CoordDisableX="0" CoordDisableXString="Count" CountX="2" StartX="0.607083" StepX="5.9254" StopX="6.53249" CoordDisableY="0" CoordDisableYString="Count" CountY="22079" StartY="0.122328" StepY="0.0227811" StopY="503.083"/>
+        <PointMatch PointSize="48" ColorAccepted="4" ColorAcceptedString="Green" ColorCandidate="7" ColorCandidateString="Yellow" ColorRejected="6" ColorRejectedString="Red"/>
+        <Segments PointSeparation="25" MinLength="2" FillCorners="False" LineWidth="4" LineColor="4" LineColorString="Green"/>
+        <Curve CurveName="Axes">
+            <ColorFilter CurveName="Axes" Mode="2" ModeString="Intensity" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="180" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
+            <CurveStyle CurveName="Axes">
+                <LineStyle Width="0" Color="8" ColorString="Transparent" ConnectAs="4" ConnectAsString="ConnectSkipForAxisCurve"/>
+                <PointStyle Radius="10" LineWidth="1" Color="6" ColorString="Red" Shape="1" ShapeString="Cross"/>
+            </CurveStyle>
+            <CurvePoints>
+                <Point Identifier="Axes&#9;point&#9;1" Ordinal="1" IsAxisPoint="True" IsXOnly="False" Index="129">
+                    <PositionScreen X="52.4503" Y="614.02"/>
+                    <PositionGraph X="1" Y="0"/>
+                </Point>
+                <Point Identifier="Axes&#9;point&#9;3" Ordinal="2" IsAxisPoint="True" IsXOnly="False" Index="129">
+                    <PositionScreen X="857.336" Y="613.25"/>
+                    <PositionGraph X="36" Y="0"/>
+                </Point>
+                <Point Identifier="Axes&#9;point&#9;5" Ordinal="3" IsAxisPoint="True" IsXOnly="False" Index="129">
+                    <PositionScreen X="53.0979" Y="21.5716"/>
+                    <PositionGraph X="1" Y="0.14"/>
+                </Point>
+            </CurvePoints>
+        </Curve>
+        <CurvesGraphs>
+            <Curve CurveName="CurveLeft">
+                <ColorFilter CurveName="CurveLeft" Mode="1" ModeString="Hue" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="0" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
+                <CurveStyle CurveName="CurveLeft">
+                    <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
+                    <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="1" ShapeString="Cross"/>
+                </CurveStyle>
+                <CurvePoints>
+                    <Point Identifier="CurveLeft&#9;point&#9;6" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="59" Y="459"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;7" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="64" Y="435"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;8" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="70" Y="410"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;9" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="75" Y="386"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;10" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="82" Y="362"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;11" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="88" Y="338"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;12" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="95" Y="314"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;13" Ordinal="7" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="102" Y="290"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;14" Ordinal="8" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="111" Y="266"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;15" Ordinal="9" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="119" Y="243"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;16" Ordinal="10" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="129" Y="220"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;17" Ordinal="11" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="140" Y="197"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;18" Ordinal="12" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="151" Y="175"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;19" Ordinal="13" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="165" Y="154"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;20" Ordinal="14" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="181" Y="135"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;21" Ordinal="15" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="199" Y="117"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;22" Ordinal="16" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="219" Y="104"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;23" Ordinal="17" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="243" Y="97"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;24" Ordinal="18" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="268" Y="95"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;25" Ordinal="19" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="292" Y="99"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;26" Ordinal="20" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="315" Y="107"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;27" Ordinal="21" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="338" Y="118"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;28" Ordinal="22" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="359" Y="131"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;29" Ordinal="23" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="379" Y="145"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;30" Ordinal="24" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="400" Y="160"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;31" Ordinal="25" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="419" Y="175"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;32" Ordinal="26" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="438" Y="189"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;61" Ordinal="27" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="459" Y="207"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;62" Ordinal="28" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="478" Y="222"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;63" Ordinal="29" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="497" Y="238"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;64" Ordinal="30" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="516" Y="254"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;65" Ordinal="31" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="535" Y="270"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;66" Ordinal="32" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="555" Y="286"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;67" Ordinal="33" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="574" Y="301"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;68" Ordinal="34" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="593" Y="316"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;69" Ordinal="35" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="613" Y="331"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;70" Ordinal="36" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="633" Y="346"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;71" Ordinal="37" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="653" Y="360"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;72" Ordinal="38" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="674" Y="374"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;73" Ordinal="39" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="695" Y="387"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;74" Ordinal="40" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="716" Y="401"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;75" Ordinal="41" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="738" Y="413"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;76" Ordinal="42" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="759" Y="426"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;77" Ordinal="43" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="780" Y="437"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;78" Ordinal="44" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="801" Y="448"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;79" Ordinal="45" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="823" Y="459"/>
+                    </Point>
+                    <Point Identifier="CurveLeft&#9;point&#9;80" Ordinal="46" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="845" Y="469"/>
+                    </Point>
+                </CurvePoints>
+            </Curve>
+            <Curve CurveName="CurveRight">
+                <ColorFilter CurveName="CurveRight" Mode="1" ModeString="Hue" IntensityLow="0" IntensityHigh="50" ForegroundLow="0" ForegroundHigh="10" HueLow="0" HueHigh="360" SaturationLow="50" SaturationHigh="100" ValueLow="0" ValueHigh="50"/>
+                <CurveStyle CurveName="CurveRight">
+                    <LineStyle Width="1" Color="1" ColorString="Blue" ConnectAs="0" ConnectAsString="FunctionSmooth"/>
+                    <PointStyle Radius="10" LineWidth="1" Color="1" ColorString="Blue" Shape="5" ShapeString="X"/>
+                </CurveStyle>
+                <CurvePoints>
+                    <Point Identifier="CurveRight&#9;point&#9;81" Ordinal="0" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="59" Y="471"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;82" Ordinal="1" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="82" Y="461"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;83" Ordinal="2" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="104" Y="450"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;84" Ordinal="3" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="126" Y="439"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;85" Ordinal="4" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="149" Y="427"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;86" Ordinal="5" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="170" Y="415"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;87" Ordinal="6" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="191" Y="401"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;88" Ordinal="7" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="213" Y="389"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;89" Ordinal="8" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="234" Y="375"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;90" Ordinal="9" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="254" Y="361"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;91" Ordinal="10" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="275" Y="347"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;92" Ordinal="11" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="295" Y="332"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;93" Ordinal="12" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="315" Y="317"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;94" Ordinal="13" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="334" Y="302"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;95" Ordinal="14" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="353" Y="287"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;96" Ordinal="15" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="372" Y="271"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;97" Ordinal="16" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="391" Y="255"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;98" Ordinal="17" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="410" Y="240"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;99" Ordinal="18" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="429" Y="224"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;100" Ordinal="19" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="447" Y="209"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;101" Ordinal="20" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="459" Y="199"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;102" Ordinal="21" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="478" Y="184"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;103" Ordinal="22" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="498" Y="168"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;104" Ordinal="23" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="517" Y="153"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;105" Ordinal="24" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="538" Y="139"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;106" Ordinal="25" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="559" Y="126"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;107" Ordinal="26" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="581" Y="114"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;108" Ordinal="27" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="603" Y="103"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;109" Ordinal="28" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="627" Y="96"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;110" Ordinal="29" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="652" Y="95"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;111" Ordinal="30" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="676" Y="98"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;112" Ordinal="31" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="698" Y="108"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;113" Ordinal="32" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="717" Y="122"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;114" Ordinal="33" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="734" Y="140"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;115" Ordinal="34" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="742" Y="149"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;116" Ordinal="35" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="755" Y="170"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;117" Ordinal="36" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="768" Y="192"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;118" Ordinal="37" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="778" Y="214"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;119" Ordinal="38" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="789" Y="237"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;120" Ordinal="39" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="797" Y="261"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;121" Ordinal="40" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="805" Y="284"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;122" Ordinal="41" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="813" Y="308"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;123" Ordinal="42" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="820" Y="332"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;124" Ordinal="43" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="827" Y="356"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;125" Ordinal="44" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="833" Y="380"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;126" Ordinal="45" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="839" Y="405"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;127" Ordinal="46" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="844" Y="429"/>
+                    </Point>
+                    <Point Identifier="CurveRight&#9;point&#9;128" Ordinal="47" IsAxisPoint="False" IsXOnly="False" Index="129">
+                        <PositionScreen X="850" Y="453"/>
+                    </Point>
+                </CurvePoints>
+            </Curve>
+        </CurvesGraphs>
+    </CoordSystem>
+</Document>
diff --git a/debian/changelog b/debian/changelog
index 6d8396c3..98e654f9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+engauge-digitizer (12.1-1) UNRELEASED; urgency=medium
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 27 Mar 2020 18:14:55 +0000
+
 engauge-digitizer (10.10+ds.1-1) unstable; urgency=medium
 
   * New upstream release
diff --git a/debian/patches/020_add_qmake_hardening_flags_to_project.diff b/debian/patches/020_add_qmake_hardening_flags_to_project.diff
index f219b406..5b2cc9ee 100644
--- a/debian/patches/020_add_qmake_hardening_flags_to_project.diff
+++ b/debian/patches/020_add_qmake_hardening_flags_to_project.diff
@@ -1,9 +1,11 @@
 Description: Add hardening flags 
 Last-Update: 2015-11-15
 
---- a/engauge.pro
-+++ b/engauge.pro
-@@ -711,3 +711,8 @@
+Index: engauge-digitizer/engauge.pro
+===================================================================
+--- engauge-digitizer.orig/engauge.pro
++++ engauge-digitizer/engauge.pro
+@@ -1063,3 +1063,8 @@ TRANSLATIONS = translations/engauge_ar.t
                 translations/engauge_pt.ts \
                 translations/engauge_ru.ts \
                 translations/engauge_zh.ts
diff --git a/debian/patches/030_fix_check_for_openjpg_lib.diff b/debian/patches/030_fix_check_for_openjpg_lib.diff
index 9ec216eb..8ad56751 100644
--- a/debian/patches/030_fix_check_for_openjpg_lib.diff
+++ b/debian/patches/030_fix_check_for_openjpg_lib.diff
@@ -1,9 +1,11 @@
 Description: Fix handling of libopenjp2 in build system 
 Last-Update: 2016-07-09
 
---- a/engauge.pro
-+++ b/engauge.pro
-@@ -855,15 +855,11 @@
+Index: engauge-digitizer/engauge.pro
+===================================================================
+--- engauge-digitizer.orig/engauge.pro
++++ engauge-digitizer/engauge.pro
+@@ -923,15 +923,11 @@ jpeg2000 {
      _OPENJPEG_LIB = $$(OPENJPEG_LIB)
      isEmpty(_OPENJPEG_INCLUDE) {
        error("OPENJPEG_INCLUDE and OPENJPEG_LIB environment variables must be defined")
@@ -22,7 +24,7 @@ Last-Update: 2016-07-09
      HEADERS += src/Jpeg2000/Jpeg2000.h \
                 src/Jpeg2000/Jpeg2000Callbacks.h \
                 src/Jpeg2000/Jpeg2000Color.h \
-@@ -874,7 +870,6 @@
+@@ -942,7 +938,6 @@ jpeg2000 {
                 src/Jpeg2000/Jpeg2000Color.cpp \
                 src/Jpeg2000/Jpeg2000Convert.cpp
      QMAKE_LFLAGS += -Wl,-rpath=\'\$\$ORIGIN\'
diff --git a/debian/patches/040_fix_check_for_libpoppler.diff b/debian/patches/040_fix_check_for_libpoppler.diff
index aad22c39..28573b70 100644
--- a/debian/patches/040_fix_check_for_libpoppler.diff
+++ b/debian/patches/040_fix_check_for_libpoppler.diff
@@ -1,9 +1,11 @@
 Description: Fix handling of libpoppler in build system 
 Last-Update: 2016-07-09
 
---- a/engauge.pro
-+++ b/engauge.pro
-@@ -878,16 +878,11 @@
+Index: engauge-digitizer/engauge.pro
+===================================================================
+--- engauge-digitizer.orig/engauge.pro
++++ engauge-digitizer/engauge.pro
+@@ -946,16 +946,11 @@ jpeg2000 {
  pdf {
      message("PDF support:        yes")
      _POPPLER_INCLUDE = $$(POPPLER_INCLUDE)
diff --git a/dev/.gitignore b/dev/.gitignore
index 659c254e..7cd9eee1 100644
--- a/dev/.gitignore
+++ b/dev/.gitignore
@@ -2,3 +2,4 @@ a.out
 *.png
 .~*
 engauge.pro.user.mmitchell.linux
+ProcessFlowchart.pdf
diff --git a/dev/README_windows_prereleases.txt b/dev/README_windows_prereleases.txt
new file mode 100644
index 00000000..914506b1
--- /dev/null
+++ b/dev/README_windows_prereleases.txt
@@ -0,0 +1,13 @@
+To access Windows pre-releases, when made available by the developers, follow these steps:
+
+* Go go https://ci.appveyor.com/project/markummitchell/engauge-digitizer
+* Click on either job 'Environment: ...BUILD_TYPE=X86...' or 'Environment: ...BUILD_TYPE=x64...'
+  for a 32 or 64 bit pre-release, respectively. There should be a green bar at the beginning of
+  the job line, which means the build was successfully completed
+* Click on the Artifacts link on the right side
+* Download the file 'engauge-build.7z' or 'engauge-build-x64.7z'
+* Extract the file using a free 7z tool. For example:
+  (Linux)   p7zip -d engauge-build-x64.7z
+  (Windows) WinZip / (select engauge-build-x64.7z) / Unzip
+* Go into the new directory and run engauge.exe
+
diff --git a/dev/cygport/build_version b/dev/cygport/build_version
index 1887e507..fe53f842 100644
--- a/dev/cygport/build_version
+++ b/dev/cygport/build_version
@@ -1,10 +1,20 @@
 #!/usr/bin/bash
 
-# Setup BEFORE running this script, since we will download the zip file generated by the git tag:
-#  git tag vX.Y"
-#  git commit -m 'message'"
-#  git push"
-#  git push origin vX.Y"
+# Required packages:
+#   cygwin32-gcc (for 32 bit builds)
+#   cygwin32-w32api-runtime (for 32 bit builds)
+#   cygport
+#   gcc-g++
+#   libfftw3-devel
+#   libGL-devel
+#   libQt5Core-devel (for qmake-qt5)
+#   libQt5Help-devel
+#   qt5-devel-tools
+#   qt5-doc-tools
+#
+# Run this after a (pre)release has been made at github so zip file is available for download
+#
+# ftp stage uses password and ssh key as explained at www.cygwin.com/package-upload.html
 
 show_usage_and_quit() {
     echo "Usage: build_version <versiontag> <32|64>"
@@ -21,15 +31,17 @@ VERSION=$1
 BITS=$2
 BITSARG=--$BITS
 
-if [[ ! $VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
+# Formats are like 11 (for version 11.0) or 11.2
+if [[ ! $VERSION =~ ^[0-9]+$ ]] && [[ ! $VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then
     show_usage_and_quit
 fi
+
 if [[ ! $BITSARG =~ ^(--32|--64)$ ]]; then
     show_usage_and_quit
 fi
 
 echo "Cleaning old build directory"
-if [ $BITS == "32" ]; then
+if [ $BITS == 32 ]; then
     TARGETDIR='engauge-digitizer-'"$VERSION"'-1.i686'
 else
     TARGETDIR='engauge-digitizer-'"$VERSION"'-1.x86_64'
@@ -65,3 +77,4 @@ echo "  cd $TARGETDIR/inst/usr/bin/"
 echo "  ./engauge-digitizer.exe"
 
 echo "After uploading and testing both 32 and 64 bit releases, release according to https://cygwin.com/packaging-contributors-guide.html#acceptance"
+echo "Remember to send email as text and not text/html so it will not be rejected. In gmail, click on 3 dots at bottom then Plain Text Mode"
diff --git a/dev/cygport/engauge-digitizer.cygport.template b/dev/cygport/engauge-digitizer.cygport.template
index 710d6061..2457e0fb 100644
--- a/dev/cygport/engauge-digitizer.cygport.template
+++ b/dev/cygport/engauge-digitizer.cygport.template
@@ -10,6 +10,7 @@ CATEGORY="Math"
 LOG_DIR=/tmp
 LOG4CPP_HOME=${S}/dev/cygport/log4cpp_null
 FFTW_HOME=/usr
+# CYGQMAKE5_ARGS is forwarded by cygqmake5() in qt5-qmake.cygclass. Note FFTW_HOME is set above to where cygwin installer put fftw3
 CYGQMAKE5_ARGS="CONFIG+=cygport CONFIG+=log4cpp_null"
 SUMMARY="Convert graph images to numeric data"
 DESCRIPTION="Engauge Digitizer digitizes images of graphs into numbers"
diff --git a/dev/flatpak/build_flatpak b/dev/flatpak/build_flatpak
index 25bf6241..9424e6c4 100755
--- a/dev/flatpak/build_flatpak
+++ b/dev/flatpak/build_flatpak
@@ -1,11 +1,51 @@
 #!/bin/bash
 
-# Run this on mark-HP-Notebook in Kubuntu 16.04 (64 bit)
+# Run this on mark-HP-Notebook in Kubuntu 18.04 (64 bit)
 #
 # Assumes prerequisites are already installed:
-# 1) flatpak install flathub org.kde.Platform//5.11
-# 2) flatpak install flathub org.kde.Sdk//5.11
-# According to Nick Richards email on 7/17/18 qt version 5.10 is deprecated for 5.9 or 5.11
+# 1) Starting at https://flatpak.org/setup and picking Kubuntu (versus Ubuntu) leads
+#    to steps installing with plasma instead of gnome.
+#    Be sure to add the flathub repository
+# 2) Then installing SDK according to http://docs.flatpak.org/en/latest/first-build.html.
+#    This step will fail if the flathub repository was not added in the previous step.
+#    installed:
+#      org.freedesktop.Platform
+#      org.freedesktop.Platform.Locale
+#      org.freedesktop.Sdk
+#      org.freedesktop.Platform.GL.nvidia-389-116
+#      org.freedesktop.Sdk.Locale
+#      org.freedesktop.Platform.html5-codecs
+#      org.freedesktop.Platform.VAAPI.Intel
+# 3) sudo apt install flatpak-builder
+# 4) Install engauge-specific github repo
+#      cd $HOME
+#      git clone git@github.com:flathub/io.github.markummitchell.Engauge_Digitizer.git
+# 5) Running this script gives error about org.kde.Sdk/x86_64/5.11 not installed so
+#      flatpak install flathub org.kde.Sdk
+#    and pick the version option matching the error message
+# 6) Running this script gives error about org.kde.Platform/x86_64/5.11 not installed so
+#      flatpak install flathub org.kde.Platform
+#    and pick the version option matching the error message
+# 7) Got error:
+#      Remote listing engauge-digitizer not available; server has no summary file.
+#      Check the URL passed to remote-add was valid
+#      error: app/io.github.markummitchell.Engauge_Digitizer/x86_64/master not installed
+#    fix: flatpak remote-add --user --no-gpg-verify engauge-digitizer \
+#         file:///home/mark/io.github.markummitchell.Engauge_Digitizer/repo
+# 8) Issue 311 'Flatpak is missing default filename on Save' occurs on at least Mint/Cinnamon,
+#    with SaveAs file default file and file extension not set. Fix requires multiple steps to
+#    environment (outside of Engauge):
+#      + sudo apt install plasma-discover-flatpak-backend     (one time step)
+#      + sudo apt install xdg-desktop-portal-kde              (one time step)
+#      + find /usr -name xdg-desktop-portal                   (find xdg-desktop-portal executable)
+#      + find /usr -name xdg-desktop-portal-kde               (find xdg-desktop-portal-kde executable)
+#      + kill xdg-desktop-portal
+#      + kill xdg-desktop-portal-kde
+#      + export XDG_CURRENT_DESKTOP=KDE
+#      + /usr/.../xdg-desktop-portal-kde &
+#      + /usr/.../xdg-desktop-portal &                        (this connects later flatpak apps to KDE)
+#      + flatpak run io.github.markummitchell.Engauge_Digitizer
+
 if [[ -z $1 ]]; then
     echo "Usage: build_flathub <version>"
     exit
@@ -14,6 +54,10 @@ TARBALLDOWNLOAD="v$1.tar.gz"
 TARBALLLOCAL=/tmp/$TARBALLDOWNLOAD
 echo "Downloading $TARBALLDOWNLOAD"
 
+echo "Update the version changes in dev/gnome/engauge-digitizer.appdata.xml"
+read -n 1 -s -r -p "Press any key to continue"
+
+# If next line fails then create a prelease at github. May need to Publish. Also may need to wait for tarball to be built
 wget "https://github.com/markummitchell/engauge-digitizer/archive/$TARBALLDOWNLOAD" --output-document="$TARBALLLOCAL"
 CKSUM=`sha256sum $TARBALLLOCAL | awk '{print $1}'`
 
diff --git a/dev/gnome/engauge-digitizer.appdata.xml b/dev/gnome/engauge-digitizer.appdata.xml
index c2c540fe..133871ee 100644
--- a/dev/gnome/engauge-digitizer.appdata.xml
+++ b/dev/gnome/engauge-digitizer.appdata.xml
@@ -68,12 +68,10 @@
 		<content_attribute id="money-gambling">none</content_attribute>
 	</content_rating>
 	<releases>
-		<release date="2018-07-22" version="10.10">
+		<release date="2019-08-02" version="12.1">
 			<description>
 			  <ul>
-			    <li>Handle non-function points in functions</li>
-			    <li>Load version 4 files with unset settings</li>
-			    <li>Improved grid line setup</li>
+			    <li></li>
 			  </ul>
 			</description>
 		</release>
diff --git a/dev/privacy_policy.txt b/dev/privacy_policy.txt
new file mode 100644
index 00000000..b21d4ae0
--- /dev/null
+++ b/dev/privacy_policy.txt
@@ -0,0 +1,49 @@
+
+                    Privacy Notice
+
+This privacy notice discloses the privacy practices for Engauge Digitizer. This
+privacy notice applies solely to information collected by this application and
+the software support team. It will notify you of the following:
+   1. What personally identifiable information is collected from you by the 
+      application and the software support options
+   2. What choices are available to you regarding the use of your data
+   3. The security procedures in place to protect the misuse of your 
+      information
+   4. How you can correct any inaccuracies in the information.
+
+Information Collection, Use and Sharing
+---------------------------------------
+We are the sole owners of the information collected on this website. We only 
+have access to/collect information that you voluntarily give us via email,
+support forum, github issue tracker, or other direct contact from you. We will
+not sell or rent this information to anyone.
+
+We will use your information to respond to you, regarding the reason you
+contacted us. We may also share your document information with others as part
+of new regression tests or topics of discussion.
+
+We will not contact after the initial period of assistance has completed.
+Contact by us will be through online forums and other posts, unless responding
+to private emails initiated by you.
+
+Your Access To and Control Over Information
+-------------------------------------------
+You can do the following at any time by contacting us via email, or forum 
+or issue tracker post:
+   * See what data we have about you, if any
+   * Change/correct any data we have about you
+   * Have us delete any data we have about you
+   * Express any concern you have about our use of your data
+
+Security
+--------
+We do not purposefully collect any sensitive information about users. If we
+identify possibly sensitive information, or you notify us that sensitive
+information has been accidentally submitted, we will immediately delete that
+information and notify you of our actions. Non-sensitive information will be
+assumed to include names, nicknames, email addresses, and context for Engauge
+Digitizer sample documents. 
+
+If you feel that we are not abiding by this privacy policy, you should contact
+us immediately through any of the available methods at 
+https://github.com/markummitchell/engauge-digitizer
diff --git a/dev/snapcraft/build_snap b/dev/snapcraft/build_snap
index 7507f379..510e5210 100755
--- a/dev/snapcraft/build_snap
+++ b/dev/snapcraft/build_snap
@@ -8,6 +8,10 @@
 #  3) desktop-qt5 only snaps a minimal qt application, so other packages must be added by us
 #  4) sql plugins must be added so sqlite is available, which prevents a runtime error message about missing qsqlite
 #     that disappeared when the help feature started working
+#
+# Error like 'Authorization header missing' is fixed with 'snapcraft login'
+
+echo "Run in Kubuntu 16.04 virtual machine"
 
 echo "Removing existing snap, if any, so it will not be confused with new snap if this script is interrupted"
 sudo snap remove engauge-digitizer
@@ -18,6 +22,7 @@ rm -rf build
 rm -rf documentation
 
 mkdir -p build/desktop-file
+mkdir -p build/meta/gui
 cd build
 BUILD=`pwd`
 
@@ -29,6 +34,7 @@ sed 's/DESTDIR = bin/DESTDIR = ./g' ../../../engauge.pro >engauge.pro
 
 cp ../snapcraft.yaml .
 cp ../../engauge-digitizer.desktop desktop-file
+cp ../../../src/img/digitizer-32.png meta/gui/icon.png
 cp -r ../../../help .
 cp -r ../../../src .
 
diff --git a/dev/snapcraft/snapcraft.yaml b/dev/snapcraft/snapcraft.yaml
index 5bb53162..9f949c16 100644
--- a/dev/snapcraft/snapcraft.yaml
+++ b/dev/snapcraft/snapcraft.yaml
@@ -1,5 +1,5 @@
 name: engauge-digitizer
-version: '10.10'
+version: '12.1'
 summary: Interactively convert a bitmap graph or map into numbers.
 description: Software tool for extracting numbers from images of graphs and maps.
 grade: stable
diff --git a/doc/Engauge2SoftwareDevelopmentFile.odt b/doc/Engauge2SoftwareDevelopmentFile.odt
index ef0f390c..888b5b8d 100644
Binary files a/doc/Engauge2SoftwareDevelopmentFile.odt and b/doc/Engauge2SoftwareDevelopmentFile.odt differ
diff --git a/engauge.pro b/engauge.pro
index 7abf9727..99a7c4e2 100644
--- a/engauge.pro
+++ b/engauge.pro
@@ -34,10 +34,16 @@
 # 9) To include log4cpp_null as part of the build, add the 'log4cpp_null' config argument. This is meant only for
 #    building the snap package.
 #        qmake CONFIG+=log4cpp_null
+# 10) To add address sanitizer (sometimes trigggering race condition segfault in ubuntu), with line numbers for later gdb debugging
+#        qmake "QMAKE_CXXFLAGS+=-fsanitize=address,undefined" "QMAKE_CXXFLAGS+=-Werror=format" "QMAKE_CXXFLAGS+=-g1"
+#        "QMAKE_CXXFLAGS+=-fno-stack-protector" "LIBS=-fsanitize=address,undefined" engauge.pro
+# 11) To add thread sanitizer (sometimes trigggering race condition segfault in ubuntu), with line numbers for later gdb debugging
+#        qmake "QMAKE_CXXFLAGS+=-fsanitize=thread" "QMAKE_CXXFLAGS+=-g1" "LIBS=-fsanitize=thread" engauge.pro
 #
 # More comments are in the INSTALL file, and below
 
 QT += core gui printsupport widgets xml
+CONFIG += c++11 # For nullptr
 
 !mac {
 QT += help
@@ -80,7 +86,9 @@ HEADERS  += \
     src/Callback/CallbackCheckEditPointAxis.h \
     src/Callback/CallbackDocumentHash.h \
     src/Callback/CallbackDocumentScrub.h \
-    src/Callback/CallbackGatherXThetaValuesFunctions.h \
+    src/Callback/CallbackGatherXThetasAbstractBase.h \
+    src/Callback/CallbackGatherXThetasInCurves.h \
+    src/Callback/CallbackGatherXThetasInGridLines.h \
     src/Callback/CallbackNextOrdinal.h \
     src/Callback/CallbackPointOrdinal.h \
     src/Callback/CallbackRemovePointsInCurvesGraphs.h \
@@ -118,7 +126,7 @@ HEADERS  += \
     src/Cmd/CmdSettingsAxesChecker.h \
     src/Cmd/CmdSettingsColorFilter.h \
     src/Cmd/CmdSettingsCoords.h \
-    src/Cmd/CmdSettingsCurveAddRemove.h \
+    src/Cmd/CmdSettingsCurveList.h \
     src/Cmd/CmdSettingsCurveProperties.h \
     src/Cmd/CmdSettingsDigitizeCurve.h \
     src/Cmd/CmdSettingsExportFormat.h \
@@ -181,7 +189,9 @@ HEADERS  += \
     src/Cursor/CursorSize.h \
     src/Curve/Curve.h \
     src/Curve/CurveConnectAs.h \
+    src/include/CurveLimits.h \
     src/Curve/CurveNameList.h \
+    src/include/CurvesIncludedHash.h \
     src/Curve/CurveSettingsInt.h \
     src/Curve/CurvesGraphs.h \
     src/Curve/CurveStyle.h \
@@ -214,7 +224,7 @@ HEADERS  += \
     src/Dlg/DlgSettingsAxesChecker.h \
     src/Dlg/DlgSettingsColorFilter.h \
     src/Dlg/DlgSettingsCoords.h \
-    src/Dlg/DlgSettingsCurveAddRemove.h \
+    src/Dlg/DlgSettingsCurveList.h \
     src/Dlg/DlgSettingsCurveProperties.h \
     src/Dlg/DlgSettingsDigitizeCurve.h \
     src/Dlg/DlgSettingsExportFormat.h \
@@ -247,6 +257,7 @@ HEADERS  += \
     src/Document/DocumentModelSegments.h \
     src/Document/DocumentScrub.h \
     src/Document/DocumentSerialize.h \
+    src/util/EllipseParameters.h \
     src/include/EngaugeAssert.h \
     src/util/EnumsToQt.h \
     src/Export/ExportAlignLinear.h \
@@ -340,13 +351,14 @@ HEADERS  += \
     src/util/LinearToLog.h \
     src/Line/LineStyle.h \
     src/Load/LoadFileInfo.h \
+    src/Load/LoadImageFromUrl.h \
     src/Logger/Logger.h \
     src/Logger/LoggerUpload.h \
-    src/Matrix/Matrix.h \
     src/main/MainDirectoryPersist.h \
     src/main/MainTitleBarFormat.h \
     src/main/MainWindow.h \
     src/main/MainWindowModel.h \
+    src/Matrix/Matrix.h \
     src/util/MigrateToVersion6.h \
     src/Mime/MimePointsDetector.h \
     src/Mime/MimePointsExport.h \
@@ -377,6 +389,7 @@ HEADERS  += \
     src/Settings/SettingsForGraph.h \
     src/Spline/Spline.h \
     src/Spline/SplineCoeff.h \
+    src/Spline/SplineDrawer.h \
     src/Spline/SplinePair.h \
     src/StatusBar/StatusBar.h \
     src/StatusBar/StatusBarMode.h \
@@ -438,7 +451,9 @@ SOURCES += \
     src/Callback/CallbackCheckEditPointAxis.cpp \
     src/Callback/CallbackDocumentHash.cpp \
     src/Callback/CallbackDocumentScrub.cpp \
-    src/Callback/CallbackGatherXThetaValuesFunctions.cpp \
+    src/Callback/CallbackGatherXThetasAbstractBase.cpp \
+    src/Callback/CallbackGatherXThetasInCurves.cpp \
+    src/Callback/CallbackGatherXThetasInGridLines.cpp \
     src/Callback/CallbackNextOrdinal.cpp \
     src/Callback/CallbackPointOrdinal.cpp \
     src/Callback/CallbackRemovePointsInCurvesGraphs.cpp \
@@ -475,7 +490,7 @@ SOURCES += \
     src/Cmd/CmdSettingsAxesChecker.cpp \
     src/Cmd/CmdSettingsColorFilter.cpp \
     src/Cmd/CmdSettingsCoords.cpp \
-    src/Cmd/CmdSettingsCurveAddRemove.cpp \
+    src/Cmd/CmdSettingsCurveList.cpp \
     src/Cmd/CmdSettingsCurveProperties.cpp \
     src/Cmd/CmdSettingsDigitizeCurve.cpp \
     src/Cmd/CmdSettingsExportFormat.cpp \
@@ -514,8 +529,6 @@ SOURCES += \
     src/Coord/CoordUnitsPolarTheta.cpp \
     src/Coord/CoordUnitsTime.cpp \
     src/Correlation/Correlation.cpp \
-    src/Cursor/CursorFactory.cpp \
-    src/Cursor/CursorSize.cpp \
     src/Create/CreateActions.cpp \
     src/Create/CreateCentralWidget.cpp \
     src/Create/CreateCommandStackShadow.cpp \
@@ -533,6 +546,8 @@ SOURCES += \
     src/Create/CreateToolBars.cpp \
     src/Create/CreateTutorial.cpp \
     src/Create/CreateZoomMaps.cpp \
+    src/Cursor/CursorFactory.cpp \
+    src/Cursor/CursorSize.cpp \
     src/Curve/Curve.cpp \
     src/Curve/CurveConnectAs.cpp \
     src/Curve/CurveNameList.cpp \
@@ -568,7 +583,7 @@ SOURCES += \
     src/Dlg/DlgSettingsAxesChecker.cpp \
     src/Dlg/DlgSettingsColorFilter.cpp \
     src/Dlg/DlgSettingsCoords.cpp \
-    src/Dlg/DlgSettingsCurveAddRemove.cpp \
+    src/Dlg/DlgSettingsCurveList.cpp \
     src/Dlg/DlgSettingsCurveProperties.cpp \
     src/Dlg/DlgSettingsDigitizeCurve.cpp \
     src/Dlg/DlgSettingsExportFormat.cpp \
@@ -599,6 +614,7 @@ SOURCES += \
     src/Document/DocumentModelSegments.cpp \
     src/Document/DocumentScrub.cpp \
     src/Document/DocumentSerialize.cpp \
+    src/util/EllipseParameters.cpp \
     src/util/EnumsToQt.cpp \
     src/Export/ExportAlignLinear.cpp \
     src/Export/ExportAlignLog.cpp \
@@ -681,13 +697,14 @@ SOURCES += \
     src/util/LinearToLog.cpp \
     src/Line/LineStyle.cpp \
     src/Load/LoadFileInfo.cpp \
+    src/Load/LoadImageFromUrl.cpp \
     src/Logger/Logger.cpp \
     src/Logger/LoggerUpload.cpp \
-    src/Matrix/Matrix.cpp \
     src/main/main.cpp \
     src/main/MainDirectoryPersist.cpp \
     src/main/MainWindow.cpp \
     src/main/MainWindowModel.cpp \
+    src/Matrix/Matrix.cpp \
     src/util/MigrateToVersion6.cpp \
     src/Mime/MimePointsDetector.cpp \
     src/Mime/MimePointsExport.cpp \
@@ -715,8 +732,10 @@ SOURCES += \
     src/Settings/SettingsForGraph.cpp \
     src/Spline/Spline.cpp \
     src/Spline/SplineCoeff.cpp \
+    src/Spline/SplineDrawer.cpp \
     src/Spline/SplinePair.cpp \
     src/StatusBar/StatusBar.cpp \
+    src/StatusBar/StatusBarMode.cpp \
     src/Transformation/Transformation.cpp \
     src/Transformation/TransformationStateAbstractBase.cpp \
     src/Transformation/TransformationStateContext.cpp \
@@ -784,12 +803,11 @@ macx-* {
 }
 
 linux-* {
+  QMAKE_CXXFLAGS += -Wunused-parameter
   QT += network
   DEFINES += "NETWORKING"
-  HEADERS += src/Load/LoadImageFromUrl.h \
-             src/Network/NetworkClient.h
-  SOURCES += src/Load/LoadImageFromUrl.cpp \
-             src/Network/NetworkClient.cpp
+  HEADERS += src/Network/NetworkClient.h
+  SOURCES += src/Network/NetworkClient.cpp
   INCLUDEPATH += $$(FFTW_HOME)/include
   LIBS += -L/$$(FFTW_HOME)/lib
   !log4cpp_null {
@@ -990,23 +1008,36 @@ log4cpp_null {
     message("log4cpp_null build: no")
 }
 
+contains(DEFINES, NETWORKING) {
+    message("networking build:   yes")
+} else {
+    message("networking build:   no")
+}
+
 # People interested in translating a language can contact the developers for help. 
 # 
 # Translation file names are 'engauge_XX_YY' or 'engauge_XX' where:
 #   XX = two letter language codes in column '639-1' at https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
 #   YY = two letter country codes in column 'ISO 3166-2' at https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
 # where XX and YY are:
+#
+#    ************************************************************
+#    THIS LIST MUST BE UPDATED BELOW AND IN translations/step_*
+#    AND IN dev/windows/engauge*.wxs
+#    ************************************************************
 #   ar = Arabic     Egypt=_eg
 #   cs = Czech      Czech Republic=_cs
 #   de = German     Germany=_de
 #   en = English    USA=us
 #   es = Spanish    Spain=_es
+#   fa = Farsi      Iraq=_ir
 #   fr = French     France=_fr
 #   hi = Hindi      India=_in
 #   it = Italian    Italy=_it
 #   ja = Japanese   Japan=_jp
 #   kk = Kazakh     Kazakhstan=_kz
 #   ko = Korean     SouthKorea=_kr
+#   nb = Norwegian  
 #   pt = Portuguese Brazil=_br
 #   ru = Russian    Federation=_ru
 #   zh = Chinese    China=_cn
@@ -1021,12 +1052,14 @@ TRANSLATIONS = translations/engauge_ar.ts \
                translations/engauge_de.ts \
                translations/engauge_en.ts \
                translations/engauge_es.ts \
+               translations/engauge_fa_IR.ts \               
                translations/engauge_fr.ts \               
                translations/engauge_hi.ts \               
                translations/engauge_it.ts \               
                translations/engauge_ja.ts \               
                translations/engauge_kk.ts \
                translations/engauge_ko.ts \
+               translations/engauge_nb.ts \               
                translations/engauge_pt.ts \
                translations/engauge_ru.ts \
                translations/engauge_zh.ts
diff --git a/help/.gitignore b/help/.gitignore
index e0c3053b..f7473dc4 100644
--- a/help/.gitignore
+++ b/help/.gitignore
@@ -1 +1,2 @@
-engauge.qch
\ No newline at end of file
+engauge.qch
+engauge.qhc
\ No newline at end of file
diff --git a/help/build_qt5_12_0.bash b/help/build_qt5_12_0.bash
new file mode 100755
index 00000000..9827b7e0
--- /dev/null
+++ b/help/build_qt5_12_0.bash
@@ -0,0 +1,64 @@
+# This bash script creates .qch and .qhc output files. Optional argument is target directory.
+# Since bash has different locations depending on the operating system, no #! line is included.
+#
+# Usage: .../build_qt5_12_0.bash [destdir]
+# where:
+#   [destdir]   Optional destination directory relative to the directory containing this script.
+#               Default is ../bin/documentation
+#
+# This version is for qt 5.12.0 or newer, for which qcollectiongenerator is deprecated in favor of
+# qhelpgenerator. Earlier versions of qcollectiongenerator fail since qch file is NOT generated
+VER=`qmake -query QT_VERSION`
+MAJOR=$(echo $VER | cut -f1 -d. )
+MINOR=$(echo $VER | cut -f2 -d. )
+SUBMINOR=$(echo $VER | cut -f3 -d. )
+MAJORMIN=5
+MINORMIN=12
+SUBMINORMIN=0
+SUCCESS=1
+if (( MAJOR < MAJORMIN )); then
+    SUCCESS=0
+elif (( MAJOR == MAJORMIN )); then
+    if (( MINOR < MINORMIN )); then
+	SUCCESS=0
+    elif (( MINOR == MINORMIN )); then
+	if (( SUBMINOR < SUBMINORMIN )); then
+	    SUCCESS=0
+	fi
+    fi
+fi    
+if (( SUCCESS == 0 )); then
+    echo "Qt version must be $MAJORMIN.$MINORMIN.$SUBMINORMIN or newer. Use another build script"
+    exit
+fi    
+# Run this script in the 'help' subdirectory to prevent confusion about $1 argument being relative
+# script directory or current working directory. Flathub build script likes the 'cd' command in
+# this script rather than outside
+SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+WORKPATH=`pwd`
+WORKDIR=`basename $WORKPATH`
+if [[ $WORKDIR != "help" ]]; then
+    # Changing to script directory
+    cd $SCRIPTDIR
+fi
+
+if [ $# -eq 0 ]; then
+    DESTDIR=../bin/documentation
+else
+    DESTDIR=$1
+fi
+
+# Specifying ../bin/documentation directory here creates files in this directory
+# AND ../bin/documentation (with different sizes) so we build into the local directory.
+# Outputs:
+#   engauge.qch 3MB binary file
+#   engauge.qhc 32K SQLite file
+qhelpgenerator engauge.qhp
+
+# Move to target directory which is relative to the help subdirectory. OSX does not use qhc file
+mkdir -p $DESTDIR
+mv engauge.qch $DESTDIR
+if [ -f engauge.qhc ]; then
+    mv engauge.qhc $DESTDIR
+fi
+
diff --git a/src/Background/BackgroundImage.cpp b/src/Background/BackgroundImage.cpp
index 568a500a..f46bd46a 100644
--- a/src/Background/BackgroundImage.cpp
+++ b/src/Background/BackgroundImage.cpp
@@ -8,20 +8,21 @@
 
 QString backgroundImageToString (BackgroundImage backgroundImage)
 {
+  QString rtn;
+
   switch (backgroundImage) {
     case BACKGROUND_IMAGE_NONE:
-      return "None";
+      rtn = "None";
       break;
 
     case BACKGROUND_IMAGE_ORIGINAL:
-      return "Original";
+      rtn = "Original";
       break;
 
     case BACKGROUND_IMAGE_FILTERED:
-      return "Filtered";
+      rtn = "Filtered";
       break;
-
-    default:
-      return "Unknown";
   }
+
+  return rtn;
 }
diff --git a/src/Background/BackgroundStateAbstractBase.cpp b/src/Background/BackgroundStateAbstractBase.cpp
index e5142ddf..9b204007 100644
--- a/src/Background/BackgroundStateAbstractBase.cpp
+++ b/src/Background/BackgroundStateAbstractBase.cpp
@@ -16,7 +16,7 @@ BackgroundStateAbstractBase::BackgroundStateAbstractBase(BackgroundStateContext
                                                          GraphicsScene &scene) :
   m_context (context),
   m_scene (scene),
-  m_imageItem (0)
+  m_imageItem (nullptr)
 {
   // Create an image but do not show it until the appropriate state is reached
   QPixmap dummy;
diff --git a/src/Background/BackgroundStateAbstractBase.h b/src/Background/BackgroundStateAbstractBase.h
index b429fa74..c43339d1 100644
--- a/src/Background/BackgroundStateAbstractBase.h
+++ b/src/Background/BackgroundStateAbstractBase.h
@@ -33,7 +33,7 @@ class BackgroundStateAbstractBase
   /// Single constructor
   BackgroundStateAbstractBase(BackgroundStateContext &context,
                               GraphicsScene &scene);
-  ~BackgroundStateAbstractBase();
+  virtual ~BackgroundStateAbstractBase();
 
   /// Method that is called at the exact moment a state is entered. Typically called just after end for the previous state.
   virtual void begin() = 0;
diff --git a/src/Background/BackgroundStateContext.cpp b/src/Background/BackgroundStateContext.cpp
index 2b983b26..cad62b53 100644
--- a/src/Background/BackgroundStateContext.cpp
+++ b/src/Background/BackgroundStateContext.cpp
@@ -35,6 +35,11 @@ BackgroundStateContext::BackgroundStateContext(MainWindow &mainWindow) :
   completeRequestedStateTransitionIfExists();
 }
 
+BackgroundStateContext::~BackgroundStateContext()
+{
+  qDeleteAll (m_states);
+}
+
 void BackgroundStateContext::close()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "BackgroundStateContext::close";
@@ -102,7 +107,8 @@ void BackgroundStateContext::setBackgroundImage (BackgroundImage backgroundImage
   LOG4CPP_INFO_S ((*mainCat)) << "BackgroundStateContext::setBackgroundImage"
                               << " background=" << backgroundImageToString (backgroundImage).toLatin1().data();
 
-  BackgroundState backgroundState;
+  BackgroundState backgroundState= BACKGROUND_STATE_NONE;
+  
   switch (backgroundImage) {
     case BACKGROUND_IMAGE_FILTERED:
       backgroundState = BACKGROUND_STATE_CURVE;
@@ -115,10 +121,6 @@ void BackgroundStateContext::setBackgroundImage (BackgroundImage backgroundImage
      case BACKGROUND_IMAGE_ORIGINAL:
       backgroundState = BACKGROUND_STATE_ORIGINAL;
       break;
-
-    default:
-      LOG4CPP_ERROR_S ((*mainCat)) << "BackgroundStateContext::selectBackgroundImage";
-      exit (-1);
   }
 
   // It is safe to transition to the new state immediately since no BackgroundState classes are on the stack
diff --git a/src/Background/BackgroundStateContext.h b/src/Background/BackgroundStateContext.h
index c2e179b1..f2fe1643 100644
--- a/src/Background/BackgroundStateContext.h
+++ b/src/Background/BackgroundStateContext.h
@@ -35,6 +35,9 @@ class BackgroundStateContext
   /// Single constructor
   BackgroundStateContext(MainWindow &mainWindow);
 
+  /// Destructor deallocates memory
+  ~BackgroundStateContext();
+  
   /// Open Document is being closed so remove the background
   void close();
 
diff --git a/src/Callback/CallbackAxisPointsAbstract.cpp b/src/Callback/CallbackAxisPointsAbstract.cpp
index c48fd674..ab1ebb18 100644
--- a/src/Callback/CallbackAxisPointsAbstract.cpp
+++ b/src/Callback/CallbackAxisPointsAbstract.cpp
@@ -12,6 +12,10 @@
 #include "QtToString.h"
 #include "Transformation.h"
 
+// Epsilon test values
+const double ONE_PIXEL = 1.0; // Screen coordinates
+const double ZERO_EPSILON = 0.0; // Graph coordinates
+
 CallbackAxisPointsAbstract::CallbackAxisPointsAbstract(const DocumentModelCoords &modelCoords,
                                                        DocumentAxesPointsRequired documentAxesPointsRequired) :
   m_modelCoords (modelCoords),
@@ -34,13 +38,14 @@ CallbackAxisPointsAbstract::CallbackAxisPointsAbstract(const DocumentModelCoords
 {
 }
 
-bool CallbackAxisPointsAbstract::anyPointsRepeatPair (const CoordPairVector &vector) const
+bool CallbackAxisPointsAbstract::anyPointsRepeatPair (const CoordPairVector &vector,
+                                                      double epsilon) const
 {
   for (int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
     for (int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
 
-      if ((vector.at(pointLeft).x() == vector.at(pointRight).x()) &&
-          (vector.at(pointLeft).y() == vector.at(pointRight).y())) {
+      if (qAbs (vector.at(pointLeft).x() - vector.at(pointRight).x()) <= epsilon &&
+          qAbs (vector.at(pointLeft).y() - vector.at(pointRight).y()) <= epsilon) {
 
         // Points pointLeft and pointRight repeat each other, which means matrix cannot be inverted
         return true;
@@ -52,12 +57,13 @@ bool CallbackAxisPointsAbstract::anyPointsRepeatPair (const CoordPairVector &vec
   return false;
 }
 
-bool CallbackAxisPointsAbstract::anyPointsRepeatSingle (const CoordSingleVector &vector) const
+bool CallbackAxisPointsAbstract::anyPointsRepeatSingle (const CoordSingleVector &vector,
+                                                        double epsilon) const
 {
   for (int pointLeft = 0; pointLeft < vector.count(); pointLeft++) {
     for (int pointRight = pointLeft + 1; pointRight < vector.count(); pointRight++) {
 
-      if (vector.at(pointLeft) == vector.at(pointRight)) {
+      if (qAbs (vector.at(pointLeft) - vector.at(pointRight)) <= epsilon) {
 
         // Points pointLeft and pointRight repeat each other, which means matrix cannot be inverted
         return true;
@@ -120,7 +126,8 @@ CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire2AxisPoints (con
     }
 
     // Error checking
-    if (anyPointsRepeatPair (m_screenInputs)) {
+    if (anyPointsRepeatPair (m_screenInputs,
+                             ONE_PIXEL)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an existing axis point");
@@ -165,7 +172,7 @@ CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (con
     // Error checking
     if ((m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2 ||
          m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) &&
-        anyPointsRepeatPair (m_screenInputs)) {
+        anyPointsRepeatPair (m_screenInputs, ONE_PIXEL)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an existing axis point");
@@ -173,19 +180,23 @@ CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire3AxisPoints (con
 
     } else if ((m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2 ||
                 m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) &&
-               anyPointsRepeatPair (m_graphOutputs)) {
+               anyPointsRepeatPair (m_graphOutputs, ZERO_EPSILON)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("New axis point cannot have the same graph coordinates as an existing axis point");
       rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
 
-    } else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform)) {
+    } else if ((numberPoints == 3) && threePointsAreCollinear (m_screenInputsTransform,
+                                                               COORD_IS_LINEAR,
+                                                               COORD_IS_LINEAR)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("No more than two axis points can lie along the same line on the screen");
       rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
 
-    } else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform)) {
+    } else if ((numberPoints == 3) && threePointsAreCollinear (m_graphOutputsTransform,
+                                                               logXGraph (),
+                                                               logYGraph ())) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("No more than two axis points can lie along the same line in graph coordinates");
@@ -260,27 +271,35 @@ CallbackSearchReturn CallbackAxisPointsAbstract::callbackRequire4AxisPoints (boo
     }
 
     // Error checking
-    if (anyPointsRepeatPair (m_screenInputsX) ||
-        anyPointsRepeatPair (m_screenInputsY)) {
+    if (anyPointsRepeatPair (m_screenInputsX,
+                             ONE_PIXEL) ||
+        anyPointsRepeatPair (m_screenInputsY,
+                             ONE_PIXEL)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("New axis point cannot be at the same screen position as an existing axis point");
       rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
 
-    } else if (anyPointsRepeatSingle (m_graphOutputsX) ||
-               anyPointsRepeatSingle (m_graphOutputsY)) {
+    } else if (anyPointsRepeatSingle (m_graphOutputsX,
+                                      ZERO_EPSILON) ||
+               anyPointsRepeatSingle (m_graphOutputsY,
+                                      ZERO_EPSILON)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("New axis point cannot have the same graph coordinates as an existing axis point");
       rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
 
-    } else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform)) {
+    } else if ((numberPoints == 4) && threePointsAreCollinear (m_screenInputsTransform,
+                                                               COORD_IS_LINEAR,
+                                                               COORD_IS_LINEAR)) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("No more than two axis points can lie along the same line on the screen");
       rtn = CALLBACK_SEARCH_RETURN_INTERRUPT;
 
-    } else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform)) {
+    } else if ((numberPoints == 4) && threePointsAreCollinear (m_graphOutputsTransform,
+                                                               logXGraph (),
+                                                               logYGraph ())) {
 
       m_isError = true;
       m_errorMessage = QObject::tr ("No more than two axis points can lie along the same line in graph coordinates");
@@ -456,6 +475,16 @@ void CallbackAxisPointsAbstract::loadTransforms4 ()
                                         1.0      , 1.0                , 1.0                );
 }
 
+CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logXGraph () const
+{
+  return m_modelCoords.coordScaleXTheta() == COORD_SCALE_LOG ? COORD_IS_LOG : COORD_IS_LINEAR;
+}
+
+CallbackAxisPointsAbstract::LinearOrLog CallbackAxisPointsAbstract::logYGraph () const
+{
+  return m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG ? COORD_IS_LOG : COORD_IS_LINEAR;
+}
+
 QTransform CallbackAxisPointsAbstract::matrixGraph () const
 {
   return m_graphOutputsTransform;
@@ -469,15 +498,31 @@ QTransform CallbackAxisPointsAbstract::matrixScreen () const
 unsigned int CallbackAxisPointsAbstract::numberAxisPoints () const
 {
   if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_2) {
-    return m_screenInputs.count();
+    return unsigned (m_screenInputs.count());
   } else if (m_documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3) {
-    return m_screenInputs.count();
+    return unsigned (m_screenInputs.count());
   } else {
-    return m_screenInputsX.count() + m_screenInputsY.count();
+    return unsigned (m_screenInputsX.count() + m_screenInputsY.count());
   }
 }
 
-bool CallbackAxisPointsAbstract::threePointsAreCollinear (const QTransform &transform)
+bool CallbackAxisPointsAbstract::threePointsAreCollinear (const QTransform &transformIn,
+                                                          LinearOrLog logX,
+                                                          LinearOrLog logY) const
 {
-  return (transform.determinant() == 0);
+  double m11 = (logX == COORD_IS_LOG) ? qLn (transformIn.m11()) : transformIn.m11();
+  double m12 = (logX == COORD_IS_LOG) ? qLn (transformIn.m12()) : transformIn.m12();
+  double m13 = (logX == COORD_IS_LOG) ? qLn (transformIn.m13()) : transformIn.m13();
+  double m21 = (logY == COORD_IS_LOG) ? qLn (transformIn.m21()) : transformIn.m21();
+  double m22 = (logY == COORD_IS_LOG) ? qLn (transformIn.m22()) : transformIn.m22();
+  double m23 = (logY == COORD_IS_LOG) ? qLn (transformIn.m23()) : transformIn.m23();
+  double m31 = transformIn.m31();
+  double m32 = transformIn.m32();
+  double m33 = transformIn.m33();
+
+  QTransform transform (m11, m12, m13,
+                        m21, m22, m23,
+                        m31, m32, m33);
+
+  return !transform.isInvertible ();
 }
diff --git a/src/Callback/CallbackAxisPointsAbstract.h b/src/Callback/CallbackAxisPointsAbstract.h
index 5d524837..933e5cc8 100644
--- a/src/Callback/CallbackAxisPointsAbstract.h
+++ b/src/Callback/CallbackAxisPointsAbstract.h
@@ -84,8 +84,18 @@ protected:
 
 private:
 
-  bool anyPointsRepeatPair (const CoordPairVector &vector) const;
-  bool anyPointsRepeatSingle (const CoordSingleVector &vector) const;
+  enum LinearOrLog {
+    COORD_IS_LINEAR,
+    COORD_IS_LOG
+  };
+
+  /// Check for repeating points. Epsilon test is used to prevent floating point comparison compiler warning for -Wall
+  bool anyPointsRepeatPair (const CoordPairVector &vector,
+                            double epsilon) const;
+  
+  /// Check for repeating points. Epsilon test is used to prevent floating point comparison compiler warning for -Wall
+  bool anyPointsRepeatSingle (const CoordSingleVector &vector,
+                              double epsilon) const;
   CallbackSearchReturn callbackRequire2AxisPoints (const QPointF &posScreen,
                                                    const QPointF &posGraph);
   CallbackSearchReturn callbackRequire3AxisPoints (const QPointF &posScreen,
@@ -98,7 +108,11 @@ private:
   void loadTransforms2();
   void loadTransforms3();
   void loadTransforms4();
-  bool threePointsAreCollinear (const QTransform &transform);
+  LinearOrLog logXGraph () const;
+  LinearOrLog logYGraph () const;
+  bool threePointsAreCollinear (const QTransform &transform,
+                                LinearOrLog logX,
+                                LinearOrLog logY) const;
 
   // Coordinates information that will be applied to the coordinates before they are used to compute the transformation
   DocumentModelCoords m_modelCoords;
diff --git a/src/Callback/CallbackBoundingRects.cpp b/src/Callback/CallbackBoundingRects.cpp
index 7224b0de..1ea50d55 100644
--- a/src/Callback/CallbackBoundingRects.cpp
+++ b/src/Callback/CallbackBoundingRects.cpp
@@ -12,77 +12,128 @@
 #include "QtToString.h"
 #include "Transformation.h"
 
-CallbackBoundingRects::CallbackBoundingRects(const Transformation &transformation) :
-  m_isEmpty (true),
+CallbackBoundingRects::CallbackBoundingRects(DocumentAxesPointsRequired documentAxesPointsRequired,
+                                             const Transformation &transformation) :
+  m_documentAxesPointsRequired (documentAxesPointsRequired),
+  m_isEmptyGraphX (true),
+  m_isEmptyGraphY (true),
+  m_isEmptyScreenX (true),
+  m_isEmptyScreenY (true),
   m_transformation (transformation)
 {
 }
 
-QRectF CallbackBoundingRects::boundingRectGraph (bool &isEmpty) const
+QPointF CallbackBoundingRects::boundingRectGraphMax (bool &isEmpty) const
 {
-  isEmpty = m_isEmpty;
+  // Need both X and Y before results are useful
+  isEmpty = m_isEmptyGraphX || m_isEmptyGraphY;
 
-  return m_boundingRectGraph;
+  return m_boundingRectGraphMax;
+}
+
+QPointF CallbackBoundingRects::boundingRectGraphMin (bool &isEmpty) const
+{
+  // Need both X and Y before results are useful
+  isEmpty = m_isEmptyGraphX || m_isEmptyGraphY;
+
+  return m_boundingRectGraphMin;
 }
 
 QRectF CallbackBoundingRects::boundingRectScreen (bool &isEmpty) const
 {
-  isEmpty = m_isEmpty;
+  // Need both X and Y before results are useful
+  isEmpty = m_isEmptyScreenX || m_isEmptyScreenY;
 
-  return m_boundingRectScreen;
+  return QRectF (m_boundingRectScreenMin,
+                 m_boundingRectScreenMax).normalized();
 }
 
 CallbackSearchReturn CallbackBoundingRects::callback (const QString &curveName,
                                                       const Point &point)
 {
   QPointF posGraph;
+  bool haveGraphX = true,  haveGraphY = true;
   if (curveName == AXIS_CURVE_NAME) {
     posGraph = point.posGraph(); // Axis point has graph coordinates
+
+    haveGraphX = (m_documentAxesPointsRequired != DOCUMENT_AXES_POINTS_REQUIRED_4) || point.isXOnly();
+    haveGraphY = (m_documentAxesPointsRequired != DOCUMENT_AXES_POINTS_REQUIRED_4) || !point.isXOnly();
+
   } else {
     m_transformation.transformScreenToRawGraph (point.posScreen(),
                                                 posGraph); // Curve point has undefined graph coordinates, but they can be calculated
   }
-  mergeCoordinates (posGraph,
-                    m_boundingRectGraph);
-  mergeCoordinates (point.posScreen(),
-                    m_boundingRectScreen);
 
-  m_isEmpty = false; // Set this after the calls to mergeCoordinates which uses it
+  if (haveGraphX) {
+    mergeCoordinateX (posGraph,
+                      m_boundingRectGraphMin,
+                      m_boundingRectGraphMax,
+                      m_isEmptyGraphX);
+  }
+  if (haveGraphY) {
+    mergeCoordinateY (posGraph,
+                      m_boundingRectGraphMin,
+                      m_boundingRectGraphMax,
+                      m_isEmptyGraphY);
+  }
+  mergeCoordinateX (point.posScreen(),
+                    m_boundingRectScreenMin,
+                    m_boundingRectScreenMax,
+                    m_isEmptyScreenX);
+  mergeCoordinateY (point.posScreen(),
+                    m_boundingRectScreenMin,
+                    m_boundingRectScreenMax,
+                    m_isEmptyScreenY);
 
   return CALLBACK_SEARCH_RETURN_CONTINUE;
 }
 
-void CallbackBoundingRects::mergeCoordinates (const QPointF &pos,
-                                              QRectF &boundingRect)
+void CallbackBoundingRects::mergeCoordinateX (const QPointF &pos,
+                                              QPointF &boundingRectMin,
+                                              QPointF &boundingRectMax,
+                                              bool &isEmpty)
 {
-  bool newGraphLeft   = m_isEmpty;
-  bool newGraphTop    = m_isEmpty;
-  bool newGraphRight  = m_isEmpty;
-  bool newGraphBottom = m_isEmpty;
+  bool newGraphMin = isEmpty;
+  bool newGraphMax = isEmpty;
 
-  if (!newGraphLeft) {
-    newGraphLeft   = (pos.x() < boundingRect.left());
+  if (!newGraphMin) {
+    newGraphMin = (pos.x() < boundingRectMin.x());
   }
-  if (!newGraphTop) {
-    newGraphTop    = (pos.y() < boundingRect.top());
+  if (!newGraphMax) {
+    newGraphMax = (boundingRectMax.x() < pos.x());
   }
-  if (!newGraphRight) {
-    newGraphRight  = (boundingRect.right() < pos.x());
+
+  if (newGraphMin) {
+    boundingRectMin.setX (pos.x());
   }
-  if (!newGraphBottom) {
-    newGraphBottom = (boundingRect.bottom() < pos.y());
+  if (newGraphMax) {
+    boundingRectMax.setX (pos.x());
   }
 
-  if (newGraphLeft) {
-    boundingRect.setLeft (pos.x());
+  isEmpty = false;
+}
+
+void CallbackBoundingRects::mergeCoordinateY (const QPointF &pos,
+                                              QPointF &boundingRectMin,
+                                              QPointF &boundingRectMax,
+                                              bool &isEmpty)
+{
+  bool newGraphMin = isEmpty;
+  bool newGraphMax = isEmpty;
+
+  if (!newGraphMin) {
+    newGraphMin = (pos.y() < boundingRectMin.y());
   }
-  if (newGraphTop) {
-    boundingRect.setTop (pos.y());
+  if (!newGraphMax) {
+    newGraphMax = (boundingRectMax.y() < pos.y());
   }
-  if (newGraphRight) {
-    boundingRect.setRight (pos.x());
+
+  if (newGraphMin) {
+    boundingRectMin.setY (pos.y());
   }
-  if (newGraphBottom) {
-    boundingRect.setBottom (pos.y());
+  if (newGraphMax) {
+    boundingRectMax.setY (pos.y());
   }
+
+  isEmpty = false;
 }
diff --git a/src/Callback/CallbackBoundingRects.h b/src/Callback/CallbackBoundingRects.h
index 4516ae8f..cfd1f905 100644
--- a/src/Callback/CallbackBoundingRects.h
+++ b/src/Callback/CallbackBoundingRects.h
@@ -8,6 +8,7 @@
 #define CALLBACK_BOUNDING_RECTS_H
 
 #include "CallbackSearchReturn.h"
+#include "DocumentAxesPointsRequired.h"
 #include <QPointF>
 #include <QRectF>
 #include <QString>
@@ -20,10 +21,18 @@ class CallbackBoundingRects
 {
 public:
   /// Single constructor
-  CallbackBoundingRects(const Transformation &transformation);
+  CallbackBoundingRects(DocumentAxesPointsRequired documentAxesPointsRequired,
+                        const Transformation &transformation);
 
-  /// Graph coordinate bounding rectangle
-  QRectF boundingRectGraph (bool &isEmpty) const;
+  /// Graph coordinate bounding rectangle's (xmin,ymin) corner. QRectF is not returned since it rounds
+  /// off the smaller coordinates to zero when large dynamic ranges appear, and those zeros
+  /// break the log scale algorithm
+  QPointF boundingRectGraphMin (bool &isEmpty) const;
+
+  /// Graph coordinate bounding rectangle's (xmax,ymax) corner. QRectF is not returned since it rounds
+  /// off the smaller coordinates to zero when large dynamic ranges appear, and those zeros
+  /// break the log scale algorithm
+  QPointF boundingRectGraphMax (bool &isEmpty) const;
 
   /// Screen coordinate bounding rectangle
   QRectF boundingRectScreen (bool &isEmpty) const;
@@ -35,13 +44,25 @@ public:
 private:
   CallbackBoundingRects();
 
-  void mergeCoordinates (const QPointF &pos,
-                         QRectF &boundingRect);
+  void mergeCoordinateX (const QPointF &pos,
+                         QPointF &boundingRectMin,
+                         QPointF &boundingRectMax,
+                         bool &isEmpty);
+  void mergeCoordinateY (const QPointF &pos,
+                         QPointF &boundingRectMin,
+                         QPointF &boundingRectMax,
+                         bool &isEmpty);
 
-  bool m_isEmpty;
+  DocumentAxesPointsRequired m_documentAxesPointsRequired;
+  bool m_isEmptyGraphX; // Have x graph bounds been initialized
+  bool m_isEmptyGraphY; // Have y graph bounds been initialized
+  bool m_isEmptyScreenX; // Have x screen bounds been initialized
+  bool m_isEmptyScreenY; // Have y screen bounds been initialized
   const Transformation m_transformation;
-  QRectF m_boundingRectGraph;
-  QRectF m_boundingRectScreen;
+  QPointF m_boundingRectGraphMin; // Not a QRectF for reasons explained by boundingRectGraphMin
+  QPointF m_boundingRectGraphMax; // Not a QRectF for reasons explained by boundingRectGraphMax
+  QPointF m_boundingRectScreenMin; // Consistent with m_boundingRectGraphMin
+  QPointF m_boundingRectScreenMax; // Consistent with m_boundingRectGraphMax
 };
 
 #endif // CALLBACK_BOUNDING_RECTS_H
diff --git a/src/Callback/CallbackDocumentHash.cpp b/src/Callback/CallbackDocumentHash.cpp
index 56b621f3..c107c17e 100644
--- a/src/Callback/CallbackDocumentHash.cpp
+++ b/src/Callback/CallbackDocumentHash.cpp
@@ -18,6 +18,10 @@ CallbackDocumentHash::CallbackDocumentHash(DocumentAxesPointsRequired documentAx
 {
 }
 
+CallbackDocumentHash::~CallbackDocumentHash()
+{
+}
+
 CallbackSearchReturn CallbackDocumentHash::callback (const QString &curveName,
                                                      const Point &point)
 {
@@ -61,9 +65,6 @@ CallbackSearchReturn CallbackDocumentHash::callback (const QString &curveName,
 
       }
       break;
-
-    default:
-      ENGAUGE_ASSERT (false);
     }
   }
 
diff --git a/src/Callback/CallbackDocumentHash.h b/src/Callback/CallbackDocumentHash.h
index 7077db27..0943d76c 100644
--- a/src/Callback/CallbackDocumentHash.h
+++ b/src/Callback/CallbackDocumentHash.h
@@ -4,8 +4,8 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#ifndef CALLBACK_BOUNDING_RECTS_H
-#define CALLBACK_BOUNDING_RECTS_H
+#ifndef CALLBACK_BOUNDING_HASH_H
+#define CALLBACK_BOUNDING_HASH_H
 
 #include "CallbackSearchReturn.h"
 #include "DocumentAxesPointsRequired.h"
@@ -21,6 +21,7 @@ class CallbackDocumentHash
 public:
   /// Single constructor
   CallbackDocumentHash(DocumentAxesPointsRequired documentAxesPointsRequired);
+  virtual ~CallbackDocumentHash ();
 
   /// Callback method.
   CallbackSearchReturn callback (const QString &curveName,
@@ -36,4 +37,4 @@ private:
   QCryptographicHash m_documentHash;
 };
 
-#endif // CALLBACK_BOUNDING_RECTS_H
+#endif // CALLBACK_BOUNDING_HASH_H
diff --git a/src/Callback/CallbackGatherXThetaValuesFunctions.cpp b/src/Callback/CallbackGatherXThetaValuesFunctions.cpp
deleted file mode 100644
index 952346a4..00000000
--- a/src/Callback/CallbackGatherXThetaValuesFunctions.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************************************
- * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
- * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
- * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
- ******************************************************************************************************/
-
-#include "CallbackGatherXThetaValuesFunctions.h"
-#include "DocumentModelExportFormat.h"
-#include "ExportAlignLinear.h"
-#include "ExportAlignLog.h"
-#include "ExportLayoutFunctions.h"
-#include "ExportPointsSelectionFunctions.h"
-#include "Logger.h"
-#include "Point.h"
-
-CallbackGatherXThetaValuesFunctions::CallbackGatherXThetaValuesFunctions(const DocumentModelExportFormat &modelExport,
-                                                                         const QStringList &curvesIncluded,
-                                                                         const Transformation &transformation) :
-  m_transformation (transformation)
-{
-  bool firstCurveForGatherXTheta = (modelExport.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
-
-  // Included just the first curve, or all curves depending on DocumentModelExportFormat
-  QStringList::const_iterator itr;
-  for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
-
-    QString curveIncluded = *itr;
-    m_curveNamesIncluded [curveIncluded] = true;
-
-    if (firstCurveForGatherXTheta) {
-
-      // We only want points belonging to the first included curve so exit this loop
-      break;
-
-    }
-  }
-}
-
-CallbackSearchReturn CallbackGatherXThetaValuesFunctions::callback (const QString &curveName,
-                                                                    const Point &point)
-{
-  LOG4CPP_DEBUG_S ((*mainCat)) << "CallbackGatherXThetaValuesFunctions::callback"
-                               << " curveName=" << curveName.toLatin1().data()
-                               << " point=" << point.identifier().toLatin1().data();
-
-  if (m_curveNamesIncluded.contains (curveName)) {
-
-    QPointF posGraph;
-    m_transformation.transformScreenToRawGraph (point.posScreen(),
-                                                posGraph);
-
-    m_xThetaValues [posGraph.x ()] = true;
-  }
-
-  return CALLBACK_SEARCH_RETURN_CONTINUE;
-}
-
-ValuesVectorXOrY CallbackGatherXThetaValuesFunctions::xThetaValuesRaw () const
-{
-  LOG4CPP_INFO_S ((*mainCat)) << "CallbackGatherXThetaValuesFunctions::xThetaValuesRaw";
-
-  return m_xThetaValues;
-}
diff --git a/src/Callback/CallbackGatherXThetaValuesFunctions.h b/src/Callback/CallbackGatherXThetaValuesFunctions.h
deleted file mode 100644
index 729d930f..00000000
--- a/src/Callback/CallbackGatherXThetaValuesFunctions.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/******************************************************************************************************
- * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
- * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
- * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
- ******************************************************************************************************/
-
-#ifndef CALLBACK_GATHER_X_THETA_VALUES_FUNCTIONS_H
-#define CALLBACK_GATHER_X_THETA_VALUES_FUNCTIONS_H
-
-#include "CallbackSearchReturn.h"
-#include "ExportValuesXOrY.h"
-#include <QHash>
-#include <QMap>
-#include "Transformation.h"
-#include "ValuesVectorXOrY.h"
-
-class DocumentModelExportFormat;
-class Point;
-
-// Save values into container that preserves order by key (QMap). These are common to all included curves
-// QMap is for fast random access
-typedef QMap<double, bool> ValuesVectorXOrY;
-
-typedef QHash<QString, bool> CurveNamesIncluded;
-
-/// Callback for collecting X/Theta independent variables, for functions, in preparation for exporting.
-class CallbackGatherXThetaValuesFunctions
-{
-public:
-  /// Single constructor.
-  CallbackGatherXThetaValuesFunctions(const DocumentModelExportFormat &modelExport,
-                                      const QStringList &curveNamesIncluded,
-                                      const Transformation &transformation);
-
-  /// Callback method.
-  CallbackSearchReturn callback (const QString &curveName,
-                                 const Point &point);
-
-  /// Resulting x/theta values for all included functions
-  ValuesVectorXOrY xThetaValuesRaw () const;
-
-private:
-  CallbackGatherXThetaValuesFunctions();
-
-  const Transformation m_transformation;
-  CurveNamesIncluded m_curveNamesIncluded;
-  ValuesVectorXOrY m_xThetaValues;
-};
-
-#endif // CALLBACK_GATHER_X_THETA_VALUES_FUNCTIONS_H
diff --git a/src/Callback/CallbackGatherXThetasAbstractBase.cpp b/src/Callback/CallbackGatherXThetasAbstractBase.cpp
new file mode 100644
index 00000000..613d9cc7
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasAbstractBase.cpp
@@ -0,0 +1,107 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#include "CallbackGatherXThetasAbstractBase.h"
+#include "DocumentModelExportFormat.h"
+#include "EngaugeAssert.h"
+#include "ExportAlignLinear.h"
+#include "ExportAlignLog.h"
+#include "ExportLayoutFunctions.h"
+#include "ExportPointsSelectionFunctions.h"
+#include "Logger.h"
+#include "Point.h"
+
+CallbackGatherXThetasAbstractBase::CallbackGatherXThetasAbstractBase(bool firstCurveOnly,
+                                                                     bool extrapolateOutsideEndpoints,
+                                                                     const QStringList &curvesIncluded,
+                                                                     const Transformation &transformation) :
+  m_extrapolateOutsideEndpoints (extrapolateOutsideEndpoints),
+  m_curvesIncluded (curvesIncluded),
+  m_transformation (transformation)
+{
+  // Include just the first curve, or all curves depending on DocumentModelExportFormat
+  QStringList::const_iterator itr;
+  for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
+
+    QString curveIncluded = *itr;
+    m_curvesIncludedHash [curveIncluded] = true;
+
+    if (firstCurveOnly) {
+
+      // We only want points belonging to the first included curve so exit this loop
+      break;
+
+    }
+  }
+}
+
+CallbackGatherXThetasAbstractBase::~CallbackGatherXThetasAbstractBase()
+{
+}
+
+void CallbackGatherXThetasAbstractBase::addGraphX (double xGraph)
+{
+  m_xThetaValues [xGraph] = true;
+}
+
+CurveLimits CallbackGatherXThetasAbstractBase::curveLimitsMax () const
+{
+  return m_curveLimitsMax;
+}
+
+CurveLimits CallbackGatherXThetasAbstractBase::curveLimitsMin () const
+{
+  return m_curveLimitsMin;
+}
+
+QStringList CallbackGatherXThetasAbstractBase::curvesIncluded () const
+{
+  return m_curvesIncluded;
+}
+
+CurvesIncludedHash CallbackGatherXThetasAbstractBase::curvesIncludedHash () const
+{
+  return m_curvesIncludedHash;
+}
+
+const Transformation &CallbackGatherXThetasAbstractBase::transformation () const
+{
+  return m_transformation;
+}
+
+void CallbackGatherXThetasAbstractBase::updateMinMax (const QString &curveName,
+                                                      const Point &point)
+{
+  // Skip unless the endpoints are to be collected. We update the min/max values
+  // even if the curve is not curvesIncludedHash since endpoints are sometimes
+  // required for curves other than the first when collecting just xTheta values from
+  // the first curve
+  if (!m_extrapolateOutsideEndpoints) {
+
+    QPointF posGraph;
+    transformation ().transformScreenToRawGraph (point.posScreen(),
+                                                 posGraph);
+
+    if (!m_curveLimitsMin.contains (curveName) ||
+        posGraph.x() < m_curveLimitsMin [curveName]) {
+
+      m_curveLimitsMin [curveName] = posGraph.x ();
+    }
+
+    if (!m_curveLimitsMax.contains (curveName) ||
+        posGraph.x() > m_curveLimitsMax [curveName]) {
+
+      m_curveLimitsMax [curveName] = posGraph.x ();
+    }
+  }
+}
+
+ValuesVectorXOrY CallbackGatherXThetasAbstractBase::xThetaValuesRaw () const
+{
+  LOG4CPP_INFO_S ((*mainCat)) << "CallbackGatherXThetasAbstractBase::xThetaValuesRaw";
+
+  return m_xThetaValues;
+}
diff --git a/src/Callback/CallbackGatherXThetasAbstractBase.h b/src/Callback/CallbackGatherXThetasAbstractBase.h
new file mode 100644
index 00000000..d26d498c
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasAbstractBase.h
@@ -0,0 +1,75 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#ifndef CALLBACK_GATHER_X_THETAS_ABSTRACT_BASE_H
+#define CALLBACK_GATHER_X_THETAS_ABSTRACT_BASE_H
+
+#include "CallbackSearchReturn.h"
+#include "CurveLimits.h"
+#include "CurvesIncludedHash.h"
+#include "ExportValuesXOrY.h"
+#include "Transformation.h"
+#include "ValuesVectorXOrY.h"
+
+class Point;
+
+/// Base callback for collecting X/Theta independent variables, for functions, in preparation for exporting
+class CallbackGatherXThetasAbstractBase
+{
+public:
+  /// Single constructor.
+  CallbackGatherXThetasAbstractBase(bool firstCurveOnly,
+                                    bool extrapolateOutsideEndpoints,
+                                    const QStringList &curvesIncluded,
+                                    const Transformation &transformation);
+  virtual ~CallbackGatherXThetasAbstractBase ();
+
+  /// Callback method.
+  virtual CallbackSearchReturn callback (const QString &curveName,
+                                         const Point &point) = 0;
+
+  /// Endpoint maxima for each curve, if extrapolation has been disabled
+  CurveLimits curveLimitsMax () const;
+
+  /// Endpoint minima for each curve, if extrapolation has been disabled
+  CurveLimits curveLimitsMin () const;
+
+  /// Resulting x/theta values for all included functions
+  ValuesVectorXOrY xThetaValuesRaw () const;
+
+protected:
+
+  /// Save one graph x value
+  void addGraphX (double xGraph);
+  
+  /// Get method for included names
+  QStringList curvesIncluded () const;
+  
+  /// Get method for included names as hash
+  CurvesIncludedHash curvesIncludedHash () const;
+
+  /// Get method for transformation
+  const Transformation &transformation() const;
+
+  /// Update the tracked min and max values for each curve
+  void updateMinMax (const QString &curveName,
+                     const Point &point);
+
+private:
+  CallbackGatherXThetasAbstractBase();
+
+  bool m_extrapolateOutsideEndpoints;
+  QStringList m_curvesIncluded;
+  const Transformation m_transformation;
+  CurvesIncludedHash m_curvesIncludedHash;
+  ValuesVectorXOrY m_xThetaValues;
+
+  // Curve limits that may or may not be merged into m_xThetaValues
+  CurveLimits m_curveLimitsMin;
+  CurveLimits m_curveLimitsMax;
+};
+
+#endif // CALLBACK_GATHER_X_THETAS_ABSTRACT_BASE_H
diff --git a/src/Callback/CallbackGatherXThetasInCurves.cpp b/src/Callback/CallbackGatherXThetasInCurves.cpp
new file mode 100644
index 00000000..b71fff58
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasInCurves.cpp
@@ -0,0 +1,44 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#include "CallbackGatherXThetasInCurves.h"
+#include "DocumentModelExportFormat.h"
+#include "EngaugeAssert.h"
+#include "ExportPointsSelectionFunctions.h"
+#include "Logger.h"
+#include "Point.h"
+
+CallbackGatherXThetasInCurves::CallbackGatherXThetasInCurves(const DocumentModelExportFormat &modelExport,
+                                                             const QStringList &curvesIncluded,
+                                                             const Transformation &transformation) :
+  CallbackGatherXThetasAbstractBase ((modelExport.pointsSelectionFunctions() ==
+                                      EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE),
+                                     modelExport.extrapolateOutsideEndpoints (),
+                                     curvesIncluded,
+                                     transformation)
+{
+}
+
+CallbackSearchReturn CallbackGatherXThetasInCurves::callback (const QString &curveName,
+                                                              const Point &point)
+{
+  LOG4CPP_DEBUG_S ((*mainCat)) << "CallbackGatherXThetasInCurves::callback"
+                               << " curveName=" << curveName.toLatin1().data()
+                               << " point=" << point.identifier().toLatin1().data();
+
+  updateMinMax (curveName,
+                point);
+
+  if (curvesIncludedHash ().contains (curveName)) {
+
+    QPointF posGraph;
+    transformation ().transformScreenToRawGraph (point.posScreen(),
+                                                 posGraph);
+    addGraphX (posGraph.x ());
+  }
+
+  return CALLBACK_SEARCH_RETURN_CONTINUE;
+}
diff --git a/src/Callback/CallbackGatherXThetasInCurves.h b/src/Callback/CallbackGatherXThetasInCurves.h
new file mode 100644
index 00000000..69bddbdb
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasInCurves.h
@@ -0,0 +1,42 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#ifndef CALLBACK_GATHER_X_THETAS_IN_CURVES_H
+#define CALLBACK_GATHER_X_THETAS_IN_CURVES_H
+
+#include "CallbackGatherXThetasAbstractBase.h"
+#include "CallbackSearchReturn.h"
+#include "ExportValuesXOrY.h"
+#include "Transformation.h"
+#include "ValuesVectorXOrY.h"
+
+class DocumentModelExportFormat;
+class Point;
+
+/// Callback for collecting X/Theta independent variables, for functions, in preparation for exporting,
+/// based on curve points.
+///
+/// Although most of the time the X values are extracted from the X values of the document curves, they are sometimes
+/// extracted from the X coordinates of the grid lines (depending on ExportPointsSelectionFunctions), or even
+/// both the document curves and grid lines
+class CallbackGatherXThetasInCurves : public CallbackGatherXThetasAbstractBase
+{
+public:
+  /// Single constructor.
+  CallbackGatherXThetasInCurves(const DocumentModelExportFormat &modelExport,
+                                const QStringList &curvesIncluded,
+                                   const Transformation &transformation);
+
+  /// Callback method.
+  virtual CallbackSearchReturn callback (const QString &curveName,
+                                         const Point &point);
+  
+private:
+  CallbackGatherXThetasInCurves();
+
+};
+
+#endif // CALLBACK_GATHER_X_THETAS_IN_CURVES_H
diff --git a/src/Callback/CallbackGatherXThetasInGridLines.cpp b/src/Callback/CallbackGatherXThetasInGridLines.cpp
new file mode 100644
index 00000000..1118749f
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasInGridLines.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#include "CallbackGatherXThetasInGridLines.h"
+#include "Document.h"
+#include "EngaugeAssert.h"
+#include "ExportAlignLinear.h"
+#include "ExportAlignLog.h"
+#include "ExportLayoutFunctions.h"
+#include "ExportPointsSelectionFunctions.h"
+#include "GridLineLimiter.h"
+#include "Logger.h"
+#include "MainWindowModel.h"
+#include "Point.h"
+#include <qmath.h>
+
+const bool NOT_FIRST_CURVE_ONLY = false;
+
+CallbackGatherXThetasInGridLines::CallbackGatherXThetasInGridLines(const MainWindowModel &modelMainWindow,
+                                                                   const DocumentModelExportFormat &modelExport,
+                                                                   const QStringList &curvesIncluded,
+                                                                   const Transformation &transformation,
+                                                                   const Document &document) :
+  CallbackGatherXThetasAbstractBase (NOT_FIRST_CURVE_ONLY,
+                                     modelExport.extrapolateOutsideEndpoints (),
+                                     curvesIncluded,
+                                     transformation)
+{
+  addGridLines (modelMainWindow,
+                transformation,
+                document);
+}
+
+void CallbackGatherXThetasInGridLines::addGridLines (const MainWindowModel &modelMainWindow,
+                                                     const Transformation &transformation,
+                                                     const Document &document)
+{
+  DocumentModelGridDisplay gridLines = document.modelGridDisplay();
+
+  // Prevent overflow
+  GridLineLimiter gridLineLimiter;
+  double startX = document.modelGridDisplay().startX();
+  double stepX = document.modelGridDisplay().stepX();
+  double stopX = document.modelGridDisplay().stopX();
+  gridLineLimiter.limitForXTheta (document,
+                                  transformation,
+                                  document.modelCoords(),
+                                  modelMainWindow,
+                                  document.modelGridDisplay(),
+                                  startX,
+                                  stepX,
+                                  stopX);
+  if (document.modelCoords().coordScaleXTheta() == COORD_SCALE_LINEAR) {
+    // Linear
+    int countX = qFloor (0.5 + 1 + (stopX - startX) / stepX);
+    for (int i = 0; i < countX; i++) {
+      double x = startX + i * stepX;
+      addGraphX (x);
+    }
+  } else {
+    // Log
+    int countX = qFloor (1.0 + (qLn (stopX) - qLn (startX)) / qLn (stepX));
+    for (int i = 0; i < countX; i++) {
+      double x = startX * qPow (stepX, i);
+      addGraphX (x);
+    }
+  }
+}
+
+CallbackSearchReturn CallbackGatherXThetasInGridLines::callback (const QString &curveName,
+                                                                 const Point &point)
+{
+  LOG4CPP_DEBUG_S ((*mainCat)) << "CallbackGatherXThetasInGridLines::callback"
+                               << " curveName=" << curveName.toLatin1().data()
+                               << " point=" << point.identifier().toLatin1().data();
+
+  updateMinMax (curveName,
+                point);
+
+  return CALLBACK_SEARCH_RETURN_CONTINUE;
+}
diff --git a/src/Callback/CallbackGatherXThetasInGridLines.h b/src/Callback/CallbackGatherXThetasInGridLines.h
new file mode 100644
index 00000000..ab8ac5ee
--- /dev/null
+++ b/src/Callback/CallbackGatherXThetasInGridLines.h
@@ -0,0 +1,50 @@
+/******************************************************************************************************
+ * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#ifndef CALLBACK_GATHER_X_THETAS_IN_GRID_LINES_H
+#define CALLBACK_GATHER_X_THETAS_IN_GRID_LINES_H
+
+#include "CallbackGatherXThetasAbstractBase.h"
+#include "CallbackSearchReturn.h"
+#include "ExportValuesXOrY.h"
+#include "Transformation.h"
+#include <QHash>
+#include <QString>
+#include "ValuesVectorXOrY.h"
+
+class Document;
+class MainWindowModel;
+class Point;
+
+/// Callback for collecting X/Theta independent variables, for functions, in preparation for exporting,
+/// based on grid lines.
+///
+/// Although most of the time the X values are extracted from the X values of the document curves, they are sometimes
+/// extracted from the X coordinates of the grid lines (depending on ExportPointsSelectionFunctions), or even
+/// both the document curves and grid lines
+class CallbackGatherXThetasInGridLines : public CallbackGatherXThetasAbstractBase
+{
+public:
+  /// Single constructor.
+  CallbackGatherXThetasInGridLines(const MainWindowModel &modelMainWindow,
+                                   const DocumentModelExportFormat &modelExport,
+                                   const QStringList &curvesIncluded,
+                                   const Transformation &transformation,
+                                   const Document &document);
+
+  /// Callback method.
+  virtual CallbackSearchReturn callback (const QString &curveName,
+                                         const Point &point);
+  
+private:
+  CallbackGatherXThetasInGridLines();
+
+  void addGridLines (const MainWindowModel &modelMainWindow,
+                     const Transformation &transformation,
+                     const Document &document);
+};
+
+#endif // CALLBACK_GATHER_X_THETAS_IN_GRID_LINES_H
diff --git a/src/Callback/CallbackNextOrdinal.cpp b/src/Callback/CallbackNextOrdinal.cpp
index 9992352d..ffd0bd2f 100644
--- a/src/Callback/CallbackNextOrdinal.cpp
+++ b/src/Callback/CallbackNextOrdinal.cpp
@@ -7,6 +7,7 @@
 #include "CallbackNextOrdinal.h"
 #include "Logger.h"
 #include "Point.h"
+#include <qmath.h>
 
 CallbackNextOrdinal::CallbackNextOrdinal(const QString &curveName) :
   m_curveName (curveName),
@@ -28,7 +29,7 @@ CallbackSearchReturn CallbackNextOrdinal::callback (const QString &curveName,
 
 double CallbackNextOrdinal::nextOrdinal () const
 {
-  int nextOrdinal = m_maxOrdinalUsed + 1;
+  int nextOrdinal = qFloor (m_maxOrdinalUsed) + 1;
 
   LOG4CPP_INFO_S ((*mainCat)) << "CallbackNextOrdinal::nextOrdinal"
                               << " ordinal=" << nextOrdinal;
diff --git a/src/Callback/CallbackPointOrdinal.cpp b/src/Callback/CallbackPointOrdinal.cpp
index 528439f2..485cf911 100644
--- a/src/Callback/CallbackPointOrdinal.cpp
+++ b/src/Callback/CallbackPointOrdinal.cpp
@@ -41,13 +41,14 @@ CallbackSearchReturn CallbackPointOrdinal::callback (const Point &pointStart,
                        &projectedDistanceOutsideLine,
                        &distanceToLine);
 
-  // Compare to best so far
+  // Compare the best so far
+  bool distancesAreEqual = (qAbs (distanceToLine - m_minimumDistanceToLine) <= 0); // Epsilon test prevents compiler warning
   if (!m_haveMinimumDistanceToLine ||
       (distanceToLine < m_minimumDistanceToLine) ||
-      (distanceToLine == m_minimumDistanceToLine && projectedDistanceOutsideLine < m_minimumProjectedDistanceOutsideLine)) {
+      (distancesAreEqual && projectedDistanceOutsideLine < m_minimumProjectedDistanceOutsideLine)) {
 
-    // Compute ordinal
-    if (projectedDistanceOutsideLine == 0) {
+    // Compute ordinal using epsilon test to prevent compiler warning
+    if (qAbs (projectedDistanceOutsideLine) <= 0) {
 
       // Put new point inside the line segment
       m_ordinal = (pointStart.ordinal() + pointStop.ordinal()) / 2.0;
diff --git a/src/Callback/CallbackScaleBar.cpp b/src/Callback/CallbackScaleBar.cpp
index ed6a467e..4addcd9a 100644
--- a/src/Callback/CallbackScaleBar.cpp
+++ b/src/Callback/CallbackScaleBar.cpp
@@ -33,8 +33,8 @@ CallbackSearchReturn CallbackScaleBar::callback (const QString &curveName,
 
   if (curveName == AXIS_CURVE_NAME) {
 
-    bool isNonzeroX = (point.posGraph ().x () != 0);
-    bool isNonzeroY = (point.posGraph ().y () != 0);
+    bool isNonzeroX = (qAbs (point.posGraph ().x ()) > 0);
+    bool isNonzeroY = (qAbs (point.posGraph ().y ()) > 0);
     
     if (isNonzeroX || isNonzeroY) {
 
diff --git a/src/Callback/CallbackUpdateTransform.cpp b/src/Callback/CallbackUpdateTransform.cpp
index 72cf953a..7bc3ca51 100644
--- a/src/Callback/CallbackUpdateTransform.cpp
+++ b/src/Callback/CallbackUpdateTransform.cpp
@@ -26,9 +26,6 @@ bool CallbackUpdateTransform::transformIsDefined () const
 
   case DOCUMENT_AXES_POINTS_REQUIRED_4:
     return !isError () && (numberAxisPoints () == 4);
-
-  default:
-    ENGAUGE_ASSERT (false);
   }
 
   return !isError () && (numberAxisPoints () == 4);
diff --git a/src/Checker/Checker.cpp b/src/Checker/Checker.cpp
index e8c2b811..492f07e5 100644
--- a/src/Checker/Checker.cpp
+++ b/src/Checker/Checker.cpp
@@ -36,6 +36,11 @@ Checker::Checker(QGraphicsScene &scene) :
 {
 }
 
+Checker::~Checker()
+{
+  m_gridLines.clear ();
+}
+
 void Checker::adjustPolarAngleRanges (const DocumentModelCoords &modelCoords,
                                       const Transformation &transformation,
                                       const QList<Point> &points,
diff --git a/src/Checker/Checker.h b/src/Checker/Checker.h
index 03f4f698..084765cf 100644
--- a/src/Checker/Checker.h
+++ b/src/Checker/Checker.h
@@ -35,7 +35,8 @@ class Checker
 public:
   /// Single constructor for DlgSettingsAxesChecker, which does not have an explicit transformation. The identity transformation is assumed
   Checker(QGraphicsScene &scene);
-
+  virtual ~Checker ();
+  
   /// Create the polygon from current information, including pixel coordinates, just prior to display. This is for DlgSettingsAxesChecker.
   /// The identity matrix is used for the transformations between screen and graph coordinates. The point radius is used to exclude
   /// the lines from  the axes points for clarity
diff --git a/src/Checker/CheckerMode.cpp b/src/Checker/CheckerMode.cpp
index fedfe0c2..af6a5c1f 100644
--- a/src/Checker/CheckerMode.cpp
+++ b/src/Checker/CheckerMode.cpp
@@ -9,17 +9,21 @@
 
 QString checkerModeToString (CheckerMode checkerMode)
 {
+  QString rtn;
+
   switch (checkerMode) {
     case CHECKER_MODE_NEVER:
-      return QObject::tr ("Never");
+      rtn = QObject::tr ("Never");
+      break;
 
     case CHECKER_MODE_N_SECONDS:
-      return QObject::tr ("NSeconds");
+      rtn = QObject::tr ("NSeconds");
+      break;
 
     case CHECKER_MODE_FOREVER:
-      return QObject::tr ("Forever");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Forever");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Checklist/ChecklistGuide.cpp b/src/Checklist/ChecklistGuide.cpp
index 8e0a312e..e1fde20f 100644
--- a/src/Checklist/ChecklistGuide.cpp
+++ b/src/Checklist/ChecklistGuide.cpp
@@ -13,7 +13,7 @@
 
 ChecklistGuide::ChecklistGuide (QWidget *parent) :
   QDockWidget (parent),
-  m_browser (0)
+  m_browser (nullptr)
 {
   setVisible (false);
   setAllowedAreas (Qt::AllDockWidgetAreas);
diff --git a/src/Checklist/ChecklistGuidePage.cpp b/src/Checklist/ChecklistGuidePage.cpp
index 405bd476..cf11a983 100644
--- a/src/Checklist/ChecklistGuidePage.cpp
+++ b/src/Checklist/ChecklistGuidePage.cpp
@@ -15,8 +15,8 @@
 
 ChecklistGuidePage::ChecklistGuidePage(const QString &title) :
   m_row (0),
-  m_checklineLineEditContainer (0),
-  m_checklineLineEditLayout (0)
+  m_checklineLineEditContainer (nullptr),
+  m_checklineLineEditLayout (nullptr)
 {
   setTitle (title);
 
@@ -59,7 +59,7 @@ void ChecklistGuidePage::addLineEdit (ChecklistLineEdit *edit,
 
   bool isFirst = false;
 
-  if (m_checklineLineEditContainer == 0) {
+  if (m_checklineLineEditContainer == nullptr) {
 
     isFirst = true;
 
diff --git a/src/Checklist/ChecklistGuidePageCurves.cpp b/src/Checklist/ChecklistGuidePageCurves.cpp
index a9e49c7a..66039a39 100644
--- a/src/Checklist/ChecklistGuidePageCurves.cpp
+++ b/src/Checklist/ChecklistGuidePageCurves.cpp
@@ -25,7 +25,7 @@ ChecklistGuidePageCurves::ChecklistGuidePageCurves(const QString &title) :
   addHtml (QString ("<p>%1</p>")
            .arg (tr ("What are the names of the curves that are to be digitized? At least one entry is required.")));
 
-  m_edit = new ChecklistLineEdit* [NUM_CURVE_NAMES()];
+  m_edit = new ChecklistLineEdit* [unsigned (NUM_CURVE_NAMES())];
 
   for (int i = 0; i < NUM_CURVE_NAMES(); i++) {
     m_edit [i] = new ChecklistLineEdit;
diff --git a/src/Checklist/ChecklistGuideWizard.cpp b/src/Checklist/ChecklistGuideWizard.cpp
index aeaf023d..664996b1 100644
--- a/src/Checklist/ChecklistGuideWizard.cpp
+++ b/src/Checklist/ChecklistGuideWizard.cpp
@@ -46,7 +46,7 @@ ChecklistGuideWizard::ChecklistGuideWizard (MainWindow &mainWindow,
 
 QStringList ChecklistGuideWizard::curveNames(CoordSystemIndex coordSystemIndex) const
 {
-  return m_pageCurves [coordSystemIndex]->curveNames();
+  return m_pageCurves [signed (coordSystemIndex)]->curveNames();
 }
 
 QString ChecklistGuideWizard::pageCurvesTitle (CoordSystemIndex coordSystemIndex,
@@ -77,7 +77,7 @@ void ChecklistGuideWizard::populateCurvesGraphs (CoordSystemIndex coordSystemInd
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideWizard::populateCurvesGraphs";
 
-  QStringList curveNames = m_pageCurves [coordSystemIndex]->curveNames();
+  QStringList curveNames = m_pageCurves [signed (coordSystemIndex)]->curveNames();
   QStringList::const_iterator itr;
   for (itr = curveNames.begin(); itr != curveNames.end(); itr++) {
 
@@ -94,8 +94,8 @@ QString ChecklistGuideWizard::templateHtml (CoordSystemIndex coordSystemIndex) c
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ChecklistGuideWizard::templateHtml";
 
-  QStringList curveNames = m_pageCurves [coordSystemIndex]->curveNames();
-  bool withLines = m_pageCurves [coordSystemIndex]->withLines();
+  QStringList curveNames = m_pageCurves [signed (coordSystemIndex)]->curveNames();
+  bool withLines = m_pageCurves [signed (coordSystemIndex)]->withLines();
 
   QString html;
   QTextStream str (&html);
diff --git a/src/Cmd/CmdFactory.cpp b/src/Cmd/CmdFactory.cpp
index 36681ef5..5a783566 100644
--- a/src/Cmd/CmdFactory.cpp
+++ b/src/Cmd/CmdFactory.cpp
@@ -20,7 +20,7 @@
 #include "CmdSettingsAxesChecker.h"
 #include "CmdSettingsColorFilter.h"
 #include "CmdSettingsCoords.h"
-#include "CmdSettingsCurveAddRemove.h"
+#include "CmdSettingsCurveList.h"
 #include "CmdSettingsCurveProperties.h"
 #include "CmdSettingsDigitizeCurve.h"
 #include "CmdSettingsExportFormat.h"
@@ -43,7 +43,7 @@ CmdAbstract *CmdFactory::createCmd (MainWindow &mainWindow,
                                     Document &document,
                                     QXmlStreamReader &reader)
 {
-  CmdAbstract *cmd = 0;
+  CmdAbstract *cmd = nullptr;
 
   QXmlStreamAttributes attributes = reader.attributes();
   if (!attributes.hasAttribute(DOCUMENT_SERIALIZE_CMD_TYPE) ||
@@ -128,11 +128,11 @@ CmdAbstract *CmdFactory::createCmd (MainWindow &mainWindow,
                                  document,
                                  cmdDescription,
                                  reader);
-  } else if (cmdType == DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_ADD_REMOVE) {
-    cmd = new CmdSettingsCurveAddRemove (mainWindow,
-                                         document,
-                                         cmdDescription,
-                                         reader);
+  } else if (cmdType == DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_LIST) {
+    cmd = new CmdSettingsCurveList (mainWindow,
+                                    document,
+                                    cmdDescription,
+                                    reader);
   } else if (cmdType == DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_PROPERTIES) {
     cmd = new CmdSettingsCurveProperties (mainWindow,
                                           document,
diff --git a/src/Cmd/CmdPointChangeBase.cpp b/src/Cmd/CmdPointChangeBase.cpp
index 7d5e3ac9..d6556103 100644
--- a/src/Cmd/CmdPointChangeBase.cpp
+++ b/src/Cmd/CmdPointChangeBase.cpp
@@ -17,8 +17,8 @@ CmdPointChangeBase::CmdPointChangeBase(MainWindow &mainWindow,
   CmdAbstract (mainWindow,
                document,
                cmdDescription),
-  m_curveAxes (0),
-  m_curvesGraphs (0)
+  m_curveAxes (nullptr),
+  m_curvesGraphs (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CmdPointChangeBase::CmdPointChangeBase";
 }
@@ -31,8 +31,8 @@ void CmdPointChangeBase::restoreDocumentState (Document &document) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CmdPointChangeBase::restoreDocumentState";
 
-  ENGAUGE_ASSERT (m_curveAxes != 0);
-  ENGAUGE_ASSERT (m_curvesGraphs != 0);
+  ENGAUGE_CHECK_PTR (m_curveAxes);
+  ENGAUGE_CHECK_PTR (m_curvesGraphs);
 
   document.setCurveAxes (*m_curveAxes);
   document.setCurvesGraphs (*m_curvesGraphs);
diff --git a/src/Cmd/CmdSettingsCurveAddRemove.cpp b/src/Cmd/CmdSettingsCurveList.cpp
similarity index 70%
rename from src/Cmd/CmdSettingsCurveAddRemove.cpp
rename to src/Cmd/CmdSettingsCurveList.cpp
index c40c266e..fc46de65 100644
--- a/src/Cmd/CmdSettingsCurveAddRemove.cpp
+++ b/src/Cmd/CmdSettingsCurveList.cpp
@@ -4,7 +4,7 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#include "CmdSettingsCurveAddRemove.h"
+#include "CmdSettingsCurveList.h"
 #include "CurveNameList.h"
 #include "Document.h"
 #include "DocumentSerialize.h"
@@ -13,16 +13,16 @@
 #include <QXmlStreamReader>
 #include "Xml.h"
 
-const QString CMD_DESCRIPTION ("Curve add/remove");
+const QString CMD_DESCRIPTION ("Curve list");
 
-CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove(MainWindow &mainWindow,
-                                                     Document &document,
-                                                     const CurveNameList &modelCurves) :
+CmdSettingsCurveList::CmdSettingsCurveList(MainWindow &mainWindow,
+                                           Document &document,
+                                           const CurveNameList &modelCurves) :
   CmdAbstract(mainWindow,
               document,
               CMD_DESCRIPTION)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove";
+  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveList::CmdSettingsCurveList";
 
   m_curvesGraphsBefore = document.curvesGraphs ();
 
@@ -36,7 +36,8 @@ CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove(MainWindow &mainWindow,
     if (!curveNameOriginal.isEmpty ()) {
 
       // There was an original Curve
-      const Curve *curveOriginal = ((const Document&) document).curveForCurveName (curveNameOriginal);
+      const Document &documentConst = const_cast<Document&> (document);
+      const Curve *curveOriginal = documentConst.curveForCurveName (curveNameOriginal);
       Curve curveCurrent (*curveOriginal);
       curveCurrent.setCurveName (curveNameCurrent);
 
@@ -55,15 +56,15 @@ CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove(MainWindow &mainWindow,
   }
 }
 
-CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove (MainWindow &mainWindow,
-                                                      Document &document,
-                                                      const QString &cmdDescription,
-                                                      QXmlStreamReader &reader) :
+CmdSettingsCurveList::CmdSettingsCurveList (MainWindow &mainWindow,
+                                            Document &document,
+                                            const QString &cmdDescription,
+                                            QXmlStreamReader &reader) :
   CmdAbstract (mainWindow,
                document,
                cmdDescription)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove";
+  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveList::CmdSettingsCurveList";
 
   bool success = true;
 
@@ -102,34 +103,34 @@ CmdSettingsCurveAddRemove::CmdSettingsCurveAddRemove (MainWindow &mainWindow,
   }
 }
 
-CmdSettingsCurveAddRemove::~CmdSettingsCurveAddRemove ()
+CmdSettingsCurveList::~CmdSettingsCurveList ()
 {
 }
 
-void CmdSettingsCurveAddRemove::cmdRedo ()
+void CmdSettingsCurveList::cmdRedo ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveAddRemove::cmdRedo";
+  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveList::cmdRedo";
 
   saveOrCheckPreCommandDocumentStateHash (document ());
-  mainWindow().updateSettingsCurveAddRemove(m_curvesGraphsAfter);
+  mainWindow().updateSettingsCurveList(m_curvesGraphsAfter);
   mainWindow().updateAfterCommand();
   saveOrCheckPostCommandDocumentStateHash (document ());
 }
 
-void CmdSettingsCurveAddRemove::cmdUndo ()
+void CmdSettingsCurveList::cmdUndo ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveAddRemove::cmdUndo";
+  LOG4CPP_INFO_S ((*mainCat)) << "CmdSettingsCurveList::cmdUndo";
 
   saveOrCheckPostCommandDocumentStateHash (document ());
-  mainWindow().updateSettingsCurveAddRemove(m_curvesGraphsBefore);
+  mainWindow().updateSettingsCurveList(m_curvesGraphsBefore);
   mainWindow().updateAfterCommand();
   saveOrCheckPreCommandDocumentStateHash (document ());
 }
 
-void CmdSettingsCurveAddRemove::saveXml (QXmlStreamWriter &writer) const
+void CmdSettingsCurveList::saveXml (QXmlStreamWriter &writer) const
 {
   writer.writeStartElement(DOCUMENT_SERIALIZE_CMD);
-  writer.writeAttribute(DOCUMENT_SERIALIZE_CMD_TYPE, DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_ADD_REMOVE);
+  writer.writeAttribute(DOCUMENT_SERIALIZE_CMD_TYPE, DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_LIST);
   writer.writeAttribute(DOCUMENT_SERIALIZE_CMD_DESCRIPTION, QUndoCommand::text ());
   m_curvesGraphsBefore.saveXml(writer);
   m_curvesGraphsAfter.saveXml(writer);
diff --git a/src/Cmd/CmdSettingsCurveAddRemove.h b/src/Cmd/CmdSettingsCurveList.h
similarity index 58%
rename from src/Cmd/CmdSettingsCurveAddRemove.h
rename to src/Cmd/CmdSettingsCurveList.h
index 8b9c2758..62b4bbfe 100644
--- a/src/Cmd/CmdSettingsCurveAddRemove.h
+++ b/src/Cmd/CmdSettingsCurveList.h
@@ -4,8 +4,8 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#ifndef CMD_SETTINGS_CURVE_ADD_REMOVE_H
-#define CMD_SETTINGS_CURVE_ADD_REMOVE_H
+#ifndef CMD_SETTINGS_CURVE_LIST_H
+#define CMD_SETTINGS_CURVE_LIST_H
 
 #include "CmdAbstract.h"
 #include "CurvesGraphs.h"
@@ -13,32 +13,32 @@
 class CurveNameList;
 class QXmlStreamReader;
 
-/// Command for DlgSettingsCurveAddRemove
-class CmdSettingsCurveAddRemove : public CmdAbstract
+/// Command for DlgSettingsCurveList
+class CmdSettingsCurveList : public CmdAbstract
 {
 public:
   /// Constructor for normal creation
-  CmdSettingsCurveAddRemove(MainWindow &mainWindow,
-                            Document &document,
-                            const CurveNameList &modelCurves);
+  CmdSettingsCurveList(MainWindow &mainWindow,
+                       Document &document,
+                       const CurveNameList &modelCurves);
 
   /// Constructor for parsing error report file xml
-  CmdSettingsCurveAddRemove(MainWindow &mainWindow,
-                            Document &document,
-                            const QString &cmdDescription,
-                            QXmlStreamReader &reader);
+  CmdSettingsCurveList(MainWindow &mainWindow,
+                       Document &document,
+                       const QString &cmdDescription,
+                       QXmlStreamReader &reader);
   
-  virtual ~CmdSettingsCurveAddRemove();
+  virtual ~CmdSettingsCurveList();
 
   virtual void cmdRedo ();
   virtual void cmdUndo ();
   virtual void saveXml (QXmlStreamWriter &writer) const;
 
 private:
-  CmdSettingsCurveAddRemove();
+  CmdSettingsCurveList();
 
   CurvesGraphs m_curvesGraphsBefore;
   CurvesGraphs m_curvesGraphsAfter;
 };
 
-#endif // CMD_SETTINGS_CURVE_ADD_REMOVE_H
+#endif // CMD_SETTINGS_CURVE_LIST_H
diff --git a/src/Cmd/CmdStackShadow.cpp b/src/Cmd/CmdStackShadow.cpp
index c823098f..d085a116 100644
--- a/src/Cmd/CmdStackShadow.cpp
+++ b/src/Cmd/CmdStackShadow.cpp
@@ -19,7 +19,7 @@
 #include "Xml.h"
 
 CmdStackShadow::CmdStackShadow() :
-  m_mainWindow (0)
+  m_mainWindow (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CmdStackShadow::CmdStackShadow";
 }
@@ -73,18 +73,18 @@ void CmdStackShadow::slotRedo ()
     // Remove this command from the shadow command stack
     m_cmdList.pop_front();
 
-    if (m_mainWindow != 0) {
+    if (m_mainWindow != nullptr) {
 
       CmdRedoForTest *cmdRedoForTest = dynamic_cast<CmdRedoForTest*> (cmd);
       CmdUndoForTest *cmdUndoForTest = dynamic_cast<CmdUndoForTest*> (cmd);
 
-      if (cmdRedoForTest != 0) {
+      if (cmdRedoForTest != nullptr) {
 
         // Redo command is a special case. Redo of this command is equivalent to redo of the last command on the command stack
         // (which will never be CmdRedoForTest or CmdUndoForTest since they are never passed onto that command stack)
         emit (signalRedo ());
 
-      } else if (cmdUndoForTest != 0) {
+      } else if (cmdUndoForTest != nullptr) {
 
         // Undo command is a special case. Redo of this command is equivalent to undo of the last command on the command stack
         // (which will never be CmdRedoForTest or CmdUndoForTest since they are never passed onto that command stack)
diff --git a/src/Color/ColorFilter.cpp b/src/Color/ColorFilter.cpp
index cadb4fee..de79198c 100644
--- a/src/Color/ColorFilter.cpp
+++ b/src/Color/ColorFilter.cpp
@@ -22,6 +22,11 @@ ColorFilter::ColorFilter()
   createStrategies ();
 }
 
+ColorFilter::~ColorFilter()
+{
+  qDeleteAll (m_strategies);
+}
+
 bool ColorFilter::colorCompare (QRgb rgb1,
                                 QRgb rgb2) const
 {
diff --git a/src/Color/ColorFilter.h b/src/Color/ColorFilter.h
index ba604932..ff664bdf 100644
--- a/src/Color/ColorFilter.h
+++ b/src/Color/ColorFilter.h
@@ -23,6 +23,9 @@ public:
   /// Single constructor.
   ColorFilter();
 
+  /// Destructor deallocates memory
+  ~ColorFilter();
+
   /// See if the two color values are close enough to be considered to be the same.
   bool colorCompare (QRgb rgb1,
                      QRgb rgb2) const;
diff --git a/src/Color/ColorFilterHistogram.cpp b/src/Color/ColorFilterHistogram.cpp
index 964afb82..b8b782b6 100644
--- a/src/Color/ColorFilterHistogram.cpp
+++ b/src/Color/ColorFilterHistogram.cpp
@@ -8,6 +8,7 @@
 #include "ColorFilterHistogram.h"
 #include "EngaugeAssert.h"
 #include <QImage>
+#include <qmath.h>
 
 ColorFilterHistogram::ColorFilterHistogram()
 {
@@ -30,7 +31,7 @@ int ColorFilterHistogram::binFromPixel (const ColorFilter &filter,
 
   if (s >= 0) {
 
-    bin = FIRST_NON_EMPTY_BIN_AT_START () + s * (LAST_NON_EMPTY_BIN_AT_END () - FIRST_NON_EMPTY_BIN_AT_START ());
+    bin = qFloor (FIRST_NON_EMPTY_BIN_AT_START () + s * (LAST_NON_EMPTY_BIN_AT_END () - FIRST_NON_EMPTY_BIN_AT_START ()));
 
   }
 
@@ -68,7 +69,7 @@ void ColorFilterHistogram::generate (const ColorFilter &filter,
         ++(histogramBins [bin]);
 
         if (histogramBins [bin] > maxBinCount) {
-          maxBinCount = histogramBins [bin];
+          maxBinCount = qFloor (histogramBins [bin]);
         }
       }
     }
@@ -80,7 +81,7 @@ int ColorFilterHistogram::valueFromBin (const ColorFilter &filter,
                                         int bin)
 {
   // Just do everything in binFromPixel backwards
-  double s = (double) (bin - FIRST_NON_EMPTY_BIN_AT_START ()) / (double) (LAST_NON_EMPTY_BIN_AT_END () - FIRST_NON_EMPTY_BIN_AT_START ());
+  double s = double (bin - FIRST_NON_EMPTY_BIN_AT_START ()) / double (LAST_NON_EMPTY_BIN_AT_END () - FIRST_NON_EMPTY_BIN_AT_START ());
   s = qMin (qMax (s, 0.0), 1.0);
 
   return filter.zeroToOneToValue (colorFilterMode,
diff --git a/src/Color/ColorFilterSettings.cpp b/src/Color/ColorFilterSettings.cpp
index a8bd556a..ffe3c6cc 100644
--- a/src/Color/ColorFilterSettings.cpp
+++ b/src/Color/ColorFilterSettings.cpp
@@ -104,6 +104,11 @@ ColorFilterSettings &ColorFilterSettings::operator=(const ColorFilterSettings &o
   return *this;
 }
 
+ColorFilterSettings::~ColorFilterSettings ()
+{
+  qDeleteAll (m_strategies);
+}
+
 ColorFilterMode ColorFilterSettings::colorFilterMode() const
 {
   return m_colorFilterMode;
@@ -111,6 +116,8 @@ ColorFilterMode ColorFilterSettings::colorFilterMode() const
 
 void ColorFilterSettings::createStrategies ()
 {
+  qDeleteAll (m_strategies); // Prevent memory leak from one constructor calling another
+  
   m_strategies [COLOR_FILTER_MODE_FOREGROUND] = new ColorFilterSettingsStrategyForeground ();
   m_strategies [COLOR_FILTER_MODE_HUE       ] = new ColorFilterSettingsStrategyHue        ();
   m_strategies [COLOR_FILTER_MODE_INTENSITY ] = new ColorFilterSettingsStrategyIntensity  ();
@@ -186,14 +193,14 @@ void ColorFilterSettings::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_LOW) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_HIGH)) {
 
-    setColorFilterMode ((ColorFilterMode) attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE).toInt());
+    setColorFilterMode (static_cast<ColorFilterMode> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE).toInt()));
     setIntensityLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_LOW).toInt());
-    setIntensityHigh ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_HIGH).toInt());
+    setIntensityHigh (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_HIGH).toInt()));
     setForegroundLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_LOW).toInt());
     setForegroundHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_HIGH).toInt());
     setHueLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_LOW).toInt());
     setHueHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_HIGH).toInt());
-    setSaturationLow ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_LOW).toInt());
+    setSaturationLow (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_LOW).toInt()));
     setSaturationHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_HIGH).toInt());
     setValueLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_LOW).toInt());
     setValueHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_HIGH).toInt());
diff --git a/src/Color/ColorFilterSettings.h b/src/Color/ColorFilterSettings.h
index 2582bd9a..efd9cf65 100644
--- a/src/Color/ColorFilterSettings.h
+++ b/src/Color/ColorFilterSettings.h
@@ -44,6 +44,9 @@ public:
   /// Assignment operator.
   ColorFilterSettings &operator= (const ColorFilterSettings &other);
 
+  /// Destructor deallocates memory
+  ~ColorFilterSettings ();
+  
   /// Get method for filter mode.
   ColorFilterMode colorFilterMode() const;
 
diff --git a/src/Color/ColorFilterSettingsStrategyForeground.cpp b/src/Color/ColorFilterSettingsStrategyForeground.cpp
index a6e69fd2..8dd90f16 100644
--- a/src/Color/ColorFilterSettingsStrategyForeground.cpp
+++ b/src/Color/ColorFilterSettingsStrategyForeground.cpp
@@ -7,6 +7,7 @@
 #include "ColorConstants.h"
 #include "ColorFilterSettings.h"
 #include "ColorFilterSettingsStrategyForeground.h"
+#include <qmath.h>
 #include <QTextStream>
 
 ColorFilterSettingsStrategyForeground::ColorFilterSettingsStrategyForeground ()
@@ -19,14 +20,14 @@ ColorFilterSettingsStrategyForeground::~ColorFilterSettingsStrategyForeground ()
 
 double ColorFilterSettingsStrategyForeground::high (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.foregroundHigh () - FOREGROUND_MIN) /
-    (double) (FOREGROUND_MAX - FOREGROUND_MIN); 
+  return double (colorFilterSettings.foregroundHigh () - FOREGROUND_MIN) /
+    double (FOREGROUND_MAX - FOREGROUND_MIN);
 }
 
 double ColorFilterSettingsStrategyForeground::low (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.foregroundLow () - FOREGROUND_MIN) /
-    (double) (FOREGROUND_MAX - FOREGROUND_MIN);
+  return double (colorFilterSettings.foregroundLow () - FOREGROUND_MIN) /
+    double (FOREGROUND_MAX - FOREGROUND_MIN);
 }
 
 void ColorFilterSettingsStrategyForeground::printStream (const ColorFilterSettings &colorFilterSettings,
@@ -40,11 +41,11 @@ void ColorFilterSettingsStrategyForeground::printStream (const ColorFilterSettin
 void ColorFilterSettingsStrategyForeground::setHigh (ColorFilterSettings &colorFilterSettings,
                                                      double s0To1)
 {
-  colorFilterSettings.setForegroundHigh (FOREGROUND_MIN + s0To1 * (FOREGROUND_MAX - FOREGROUND_MIN));  
+  colorFilterSettings.setForegroundHigh (qFloor (FOREGROUND_MIN + s0To1 * (FOREGROUND_MAX - FOREGROUND_MIN)));
 }
 
 void ColorFilterSettingsStrategyForeground::setLow (ColorFilterSettings &colorFilterSettings,
                                                     double s0To1)
 {
-  colorFilterSettings.setForegroundLow (FOREGROUND_MIN + s0To1 * (FOREGROUND_MAX - FOREGROUND_MIN));
+  colorFilterSettings.setForegroundLow (qFloor (FOREGROUND_MIN + s0To1 * (FOREGROUND_MAX - FOREGROUND_MIN)));
 }
diff --git a/src/Color/ColorFilterSettingsStrategyHue.cpp b/src/Color/ColorFilterSettingsStrategyHue.cpp
index dcdaf42c..2c4815ff 100644
--- a/src/Color/ColorFilterSettingsStrategyHue.cpp
+++ b/src/Color/ColorFilterSettingsStrategyHue.cpp
@@ -7,6 +7,7 @@
 #include "ColorConstants.h"
 #include "ColorFilterSettings.h"
 #include "ColorFilterSettingsStrategyHue.h"
+#include <qmath.h>
 #include <QTextStream>
 
 ColorFilterSettingsStrategyHue::ColorFilterSettingsStrategyHue ()
@@ -19,14 +20,14 @@ ColorFilterSettingsStrategyHue::~ColorFilterSettingsStrategyHue ()
 
 double ColorFilterSettingsStrategyHue::high (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.hueHigh () - HUE_MIN) /
-    (double) (HUE_MAX - HUE_MIN); 
+  return double (colorFilterSettings.hueHigh () - HUE_MIN) /
+    double (HUE_MAX - HUE_MIN);
 }
 
 double ColorFilterSettingsStrategyHue::low (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.hueLow () - HUE_MIN) /
-    (double) (HUE_MAX - HUE_MIN);
+  return double (colorFilterSettings.hueLow () - HUE_MIN) /
+    double (HUE_MAX - HUE_MIN);
 }
 
 void ColorFilterSettingsStrategyHue::printStream (const ColorFilterSettings &colorFilterSettings,
@@ -40,11 +41,11 @@ void ColorFilterSettingsStrategyHue::printStream (const ColorFilterSettings &col
 void ColorFilterSettingsStrategyHue::setHigh (ColorFilterSettings &colorFilterSettings,
                                               double s0To1)
 {
-  colorFilterSettings.setHueHigh (HUE_MIN + s0To1 * (HUE_MAX - HUE_MIN));  
+  colorFilterSettings.setHueHigh (qFloor (HUE_MIN + s0To1 * (HUE_MAX - HUE_MIN)));
 }
 
 void ColorFilterSettingsStrategyHue::setLow (ColorFilterSettings &colorFilterSettings,
                                              double s0To1)
 {
-  colorFilterSettings.setHueLow (HUE_MIN + s0To1 * (HUE_MAX - HUE_MIN));
+  colorFilterSettings.setHueLow (qFloor (HUE_MIN + s0To1 * (HUE_MAX - HUE_MIN)));
 }
diff --git a/src/Color/ColorFilterSettingsStrategyIntensity.cpp b/src/Color/ColorFilterSettingsStrategyIntensity.cpp
index 63b416a5..99885191 100644
--- a/src/Color/ColorFilterSettingsStrategyIntensity.cpp
+++ b/src/Color/ColorFilterSettingsStrategyIntensity.cpp
@@ -7,6 +7,7 @@
 #include "ColorConstants.h"
 #include "ColorFilterSettings.h"
 #include "ColorFilterSettingsStrategyIntensity.h"
+#include <qmath.h>
 #include <QTextStream>
 
 ColorFilterSettingsStrategyIntensity::ColorFilterSettingsStrategyIntensity ()
@@ -19,14 +20,14 @@ ColorFilterSettingsStrategyIntensity::~ColorFilterSettingsStrategyIntensity ()
 
 double ColorFilterSettingsStrategyIntensity::high (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.intensityHigh () - INTENSITY_MIN) /
-    (double) (INTENSITY_MAX - INTENSITY_MIN); 
+  return double (colorFilterSettings.intensityHigh () - INTENSITY_MIN) /
+    double (INTENSITY_MAX - INTENSITY_MIN);
 }
 
 double ColorFilterSettingsStrategyIntensity::low (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.intensityLow () - INTENSITY_MIN) /
-    (double) (INTENSITY_MAX - INTENSITY_MIN);
+  return double (colorFilterSettings.intensityLow () - INTENSITY_MIN) /
+    double (INTENSITY_MAX - INTENSITY_MIN);
 }
 
 void ColorFilterSettingsStrategyIntensity::printStream (const ColorFilterSettings &colorFilterSettings,
@@ -40,11 +41,11 @@ void ColorFilterSettingsStrategyIntensity::printStream (const ColorFilterSetting
 void ColorFilterSettingsStrategyIntensity::setHigh (ColorFilterSettings &colorFilterSettings,
                                                     double s0To1)
 {
-  colorFilterSettings.setIntensityHigh (INTENSITY_MIN + s0To1 * (INTENSITY_MAX - INTENSITY_MIN));  
+  colorFilterSettings.setIntensityHigh (qFloor (INTENSITY_MIN + s0To1 * (INTENSITY_MAX - INTENSITY_MIN)));
 }
 
 void ColorFilterSettingsStrategyIntensity::setLow (ColorFilterSettings &colorFilterSettings,
                                                    double s0To1)
 {
-  colorFilterSettings.setIntensityLow (INTENSITY_MIN + s0To1 * (INTENSITY_MAX - INTENSITY_MIN));
+  colorFilterSettings.setIntensityLow (qFloor (INTENSITY_MIN + s0To1 * (INTENSITY_MAX - INTENSITY_MIN)));
 }
diff --git a/src/Color/ColorFilterSettingsStrategySaturation.cpp b/src/Color/ColorFilterSettingsStrategySaturation.cpp
index 293298ef..7d56b8ee 100644
--- a/src/Color/ColorFilterSettingsStrategySaturation.cpp
+++ b/src/Color/ColorFilterSettingsStrategySaturation.cpp
@@ -7,6 +7,7 @@
 #include "ColorConstants.h"
 #include "ColorFilterSettings.h"
 #include "ColorFilterSettingsStrategySaturation.h"
+#include <qmath.h>
 #include <QTextStream>
 
 ColorFilterSettingsStrategySaturation::ColorFilterSettingsStrategySaturation ()
@@ -19,14 +20,14 @@ ColorFilterSettingsStrategySaturation::~ColorFilterSettingsStrategySaturation ()
 
 double ColorFilterSettingsStrategySaturation::high (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.saturationHigh () - SATURATION_MIN) /
-    (double) (SATURATION_MAX - SATURATION_MIN); 
+  return double (colorFilterSettings.saturationHigh () - SATURATION_MIN) /
+    double (SATURATION_MAX - SATURATION_MIN);
 }
 
 double ColorFilterSettingsStrategySaturation::low (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.saturationLow () - SATURATION_MIN) /
-    (double) (SATURATION_MAX - SATURATION_MIN);
+  return double (colorFilterSettings.saturationLow () - SATURATION_MIN) /
+    double (SATURATION_MAX - SATURATION_MIN);
 }
 
 void ColorFilterSettingsStrategySaturation::printStream (const ColorFilterSettings &colorFilterSettings,
@@ -40,11 +41,11 @@ void ColorFilterSettingsStrategySaturation::printStream (const ColorFilterSettin
 void ColorFilterSettingsStrategySaturation::setHigh (ColorFilterSettings &colorFilterSettings,
                                                      double s0To1)
 {
-  colorFilterSettings.setSaturationHigh (SATURATION_MIN + s0To1 * (SATURATION_MAX - SATURATION_MIN));  
+  colorFilterSettings.setSaturationHigh (qFloor (SATURATION_MIN + s0To1 * (SATURATION_MAX - SATURATION_MIN)));
 }
 
 void ColorFilterSettingsStrategySaturation::setLow (ColorFilterSettings &colorFilterSettings,
                                                     double s0To1)
 {
-  colorFilterSettings.setSaturationLow (SATURATION_MIN + s0To1 * (SATURATION_MAX - SATURATION_MIN));
+  colorFilterSettings.setSaturationLow (qFloor (SATURATION_MIN + s0To1 * (SATURATION_MAX - SATURATION_MIN)));
 }
diff --git a/src/Color/ColorFilterSettingsStrategyValue.cpp b/src/Color/ColorFilterSettingsStrategyValue.cpp
index 9c831506..496ac10b 100644
--- a/src/Color/ColorFilterSettingsStrategyValue.cpp
+++ b/src/Color/ColorFilterSettingsStrategyValue.cpp
@@ -7,6 +7,7 @@
 #include "ColorConstants.h"
 #include "ColorFilterSettings.h"
 #include "ColorFilterSettingsStrategyValue.h"
+#include <qmath.h>
 #include <QTextStream>
 
 ColorFilterSettingsStrategyValue::ColorFilterSettingsStrategyValue ()
@@ -19,14 +20,14 @@ ColorFilterSettingsStrategyValue::~ColorFilterSettingsStrategyValue ()
 
 double ColorFilterSettingsStrategyValue::high (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.valueHigh () - VALUE_MIN) /
-    (double) (VALUE_MAX - VALUE_MIN); 
+  return double (colorFilterSettings.valueHigh () - VALUE_MIN) /
+    double (VALUE_MAX - VALUE_MIN);
 }
 
 double ColorFilterSettingsStrategyValue::low (const ColorFilterSettings &colorFilterSettings) const
 {
-  return (double) (colorFilterSettings.valueLow () - VALUE_MIN) /
-    (double) (VALUE_MAX - VALUE_MIN);
+  return double (colorFilterSettings.valueLow () - VALUE_MIN) /
+    double (VALUE_MAX - VALUE_MIN);
 }
 
 void ColorFilterSettingsStrategyValue::printStream (const ColorFilterSettings &colorFilterSettings,
@@ -40,11 +41,11 @@ void ColorFilterSettingsStrategyValue::printStream (const ColorFilterSettings &c
 void ColorFilterSettingsStrategyValue::setHigh (ColorFilterSettings &colorFilterSettings,
                                                 double s0To1)
 {
-  colorFilterSettings.setValueHigh (VALUE_MIN + s0To1 * (VALUE_MAX - VALUE_MIN));  
+  colorFilterSettings.setValueHigh (qFloor (VALUE_MIN + s0To1 * (VALUE_MAX - VALUE_MIN)));
 }
 
 void ColorFilterSettingsStrategyValue::setLow (ColorFilterSettings &colorFilterSettings,
                                                double s0To1)
 {
-  colorFilterSettings.setValueLow (VALUE_MIN + s0To1 * (VALUE_MAX - VALUE_MIN));
+  colorFilterSettings.setValueLow (qFloor (VALUE_MIN + s0To1 * (VALUE_MAX - VALUE_MIN)));
 }
diff --git a/src/Color/ColorFilterStrategyForeground.cpp b/src/Color/ColorFilterStrategyForeground.cpp
index 79af6bb0..8305cea2 100644
--- a/src/Color/ColorFilterStrategyForeground.cpp
+++ b/src/Color/ColorFilterStrategyForeground.cpp
@@ -20,13 +20,13 @@ ColorFilterStrategyForeground::~ColorFilterStrategyForeground ()
 double ColorFilterStrategyForeground::pixelToZeroToOne (const QColor &pixel,
                                                         QRgb rgbBackground) const
 {
-  double distance = qSqrt (pow ((double) pixel.red()   - qRed   (rgbBackground), 2) +
-                           pow ((double) pixel.green() - qGreen (rgbBackground), 2) +
-                           pow ((double) pixel.blue()  - qBlue  (rgbBackground), 2));
+  double distance = qSqrt (pow (double (pixel.red())   - qRed   (rgbBackground), 2) +
+                           pow (double (pixel.green()) - qGreen (rgbBackground), 2) +
+                           pow (double (pixel.blue())  - qBlue  (rgbBackground), 2));
   return distance / qSqrt (255.0 * 255.0 + 255.0 * 255.0 + 255.0 * 255.0);
 }
 
 int ColorFilterStrategyForeground::zeroToOneToValue (double s) const
 {
-  return FOREGROUND_MIN + s * (FOREGROUND_MAX - FOREGROUND_MIN);
+  return qFloor (FOREGROUND_MIN + s * (FOREGROUND_MAX - FOREGROUND_MIN));
 }
diff --git a/src/Color/ColorFilterStrategyHue.cpp b/src/Color/ColorFilterStrategyHue.cpp
index 68020ed3..e1c403a6 100644
--- a/src/Color/ColorFilterStrategyHue.cpp
+++ b/src/Color/ColorFilterStrategyHue.cpp
@@ -30,5 +30,5 @@ double ColorFilterStrategyHue::pixelToZeroToOne (const QColor &pixel,
 
 int ColorFilterStrategyHue::zeroToOneToValue (double s) const
 {
-  return HUE_MIN + s * (HUE_MAX - HUE_MIN);
+  return qFloor (HUE_MIN + s * (HUE_MAX - HUE_MIN));
 }
diff --git a/src/Color/ColorFilterStrategyIntensity.cpp b/src/Color/ColorFilterStrategyIntensity.cpp
index 44ff0584..9b25e8a5 100644
--- a/src/Color/ColorFilterStrategyIntensity.cpp
+++ b/src/Color/ColorFilterStrategyIntensity.cpp
@@ -20,13 +20,13 @@ ColorFilterStrategyIntensity::~ColorFilterStrategyIntensity ()
 double ColorFilterStrategyIntensity::pixelToZeroToOne (const QColor &pixel,
                                                        QRgb /* rgbBackground */) const
 {
-  double distance = qSqrt (pow ((double) pixel.red(), 2) +
-                           pow ((double) pixel.green(), 2) +
-                           pow ((double) pixel.blue(), 2));
+  double distance = qSqrt (pow (double (pixel.red())  , 2) +
+                           pow (double (pixel.green()), 2) +
+                           pow (double (pixel.blue()) , 2));
   return distance / qSqrt (255.0 * 255.0 + 255.0 * 255.0 + 255.0 * 255.0);
 }
 
 int ColorFilterStrategyIntensity::zeroToOneToValue (double s) const
 {
-  return INTENSITY_MIN + s * (INTENSITY_MAX - INTENSITY_MIN);
+  return qFloor (INTENSITY_MIN + s * (INTENSITY_MAX - INTENSITY_MIN));
 }
diff --git a/src/Color/ColorFilterStrategySaturation.cpp b/src/Color/ColorFilterStrategySaturation.cpp
index 7408b100..1f212295 100644
--- a/src/Color/ColorFilterStrategySaturation.cpp
+++ b/src/Color/ColorFilterStrategySaturation.cpp
@@ -25,5 +25,5 @@ double ColorFilterStrategySaturation::pixelToZeroToOne (const QColor &pixel,
 
 int ColorFilterStrategySaturation::zeroToOneToValue (double s) const
 {
-  return SATURATION_MIN + s * (SATURATION_MAX - SATURATION_MIN);
+  return qFloor (SATURATION_MIN + s * (SATURATION_MAX - SATURATION_MIN));
 }
diff --git a/src/Color/ColorFilterStrategyValue.cpp b/src/Color/ColorFilterStrategyValue.cpp
index a5e3ab66..1c512582 100644
--- a/src/Color/ColorFilterStrategyValue.cpp
+++ b/src/Color/ColorFilterStrategyValue.cpp
@@ -25,5 +25,5 @@ double ColorFilterStrategyValue::pixelToZeroToOne (const QColor &pixel,
 
 int ColorFilterStrategyValue::zeroToOneToValue (double s) const
 {
-  return VALUE_MIN + s * (VALUE_MAX - VALUE_MIN);
+  return qFloor (VALUE_MIN + s * (VALUE_MAX - VALUE_MIN));
 }
diff --git a/src/Coord/CoordScale.cpp b/src/Coord/CoordScale.cpp
index d4d22ced..7abf992f 100644
--- a/src/Coord/CoordScale.cpp
+++ b/src/Coord/CoordScale.cpp
@@ -8,14 +8,17 @@
 
 QString coordScaleToString (CoordScale coordScale)
 {
+  QString rtn;
+
   switch (coordScale) {
     case COORD_SCALE_LINEAR:
-      return "Linear";
+      rtn ="Linear";
+      break;
 
     case COORD_SCALE_LOG:
-      return "Log";
-
-    default:
-      return "Unknown";
+      rtn = "Log";
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Coord/CoordsType.cpp b/src/Coord/CoordsType.cpp
index 4f4404cc..e163a91c 100644
--- a/src/Coord/CoordsType.cpp
+++ b/src/Coord/CoordsType.cpp
@@ -8,14 +8,17 @@
 
 QString coordsTypeToString (CoordsType coordsType)
 {
+  QString rtn;
+
   switch (coordsType) {
     case COORDS_TYPE_CARTESIAN:
-      return "Cartesian";
+      rtn = "Cartesian";
+      break;
 
      case COORDS_TYPE_POLAR:
-      return "Polar";
-
-    default:
-      return "Unknown";
+      rtn = "Polar";
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/CoordSystem/CoordSystem.cpp b/src/CoordSystem/CoordSystem.cpp
index 382ebbcb..3a1b5788 100644
--- a/src/CoordSystem/CoordSystem.cpp
+++ b/src/CoordSystem/CoordSystem.cpp
@@ -25,6 +25,7 @@
 #include <QDebug>
 #include <QFile>
 #include <QImage>
+#include <qmath.h>
 #include <QtToString.h>
 #include <QXmlStreamReader>
 #include <QXmlStreamWriter>
@@ -59,6 +60,11 @@ CoordSystem::CoordSystem () :
   }
 }
 
+CoordSystem::~CoordSystem()
+{
+  delete m_curveAxes;
+}
+
 void CoordSystem::addGraphCurveAtEnd (const QString &curveName)
 {
   m_curvesGraphs.addGraphCurveAtEnd  (Curve (curveName,
@@ -321,8 +327,8 @@ void CoordSystem::initializeUnsetGridRemovalFromGridDisplay (double version)
       m_modelGridRemoval.setStepY (m_modelGridDisplay.stepY ());
       m_modelGridRemoval.setStopX (m_modelGridDisplay.stopX ());
       m_modelGridRemoval.setStopY (m_modelGridDisplay.stopY ());
-      m_modelGridRemoval.setCountX (m_modelGridDisplay.countX ());
-      m_modelGridRemoval.setCountY (m_modelGridDisplay.countY ());
+      m_modelGridRemoval.setCountX (signed (m_modelGridDisplay.countX ()));
+      m_modelGridRemoval.setCountY (signed (m_modelGridDisplay.countY ()));
     }
   }
 }
@@ -391,30 +397,30 @@ void CoordSystem::loadPreVersion6 (QDataStream &str,
   str >> st; // CurveCmbText selection
   str >> st; // MeasureCmbText selection
   str >> int32;
-  m_modelCoords.setCoordsType((CoordsType) int32);
+  m_modelCoords.setCoordsType(static_cast<CoordsType> (int32));
   if (version >= 3) {
-    str >> (double &) radius;
+    str >> static_cast<double &> (radius);
   }
   m_modelCoords.setOriginRadius(radius);
   str >> int32;
   m_modelCoords.setCoordUnitsRadius(COORD_UNITS_NON_POLAR_THETA_NUMBER);
-  m_modelCoords.setCoordUnitsTheta((CoordUnitsPolarTheta) int32);
+  m_modelCoords.setCoordUnitsTheta(static_cast<CoordUnitsPolarTheta> (int32));
   str >> int32;
-  m_modelCoords.setCoordScaleXTheta((CoordScale) int32);
+  m_modelCoords.setCoordScaleXTheta(static_cast<CoordScale> (int32));
   str >> int32;
-  m_modelCoords.setCoordScaleYRadius((CoordScale) int32);
+  m_modelCoords.setCoordScaleYRadius(static_cast<CoordScale> (int32));
 
   str >> int32;
-  m_modelExport.setDelimiter((ExportDelimiter) int32);
+  m_modelExport.setDelimiter(static_cast<ExportDelimiter> (int32));
   str >> int32;
-  m_modelExport.setLayoutFunctions((ExportLayoutFunctions) int32);
+  m_modelExport.setLayoutFunctions(static_cast<ExportLayoutFunctions> (int32));
   str >> int32;
-  m_modelExport.setPointsSelectionFunctions((ExportPointsSelectionFunctions) int32);
+  m_modelExport.setPointsSelectionFunctions(static_cast<ExportPointsSelectionFunctions> (int32));
   m_modelExport.setPointsSelectionRelations(EXPORT_POINTS_SELECTION_RELATIONS_RAW); // Best for maps
-  m_modelExport.setPointsIntervalUnitsFunctions((ExportPointsIntervalUnits) int32);
-  m_modelExport.setPointsIntervalUnitsRelations((ExportPointsIntervalUnits) int32);
+  m_modelExport.setPointsIntervalUnitsFunctions(static_cast<ExportPointsIntervalUnits> (int32));
+  m_modelExport.setPointsIntervalUnitsRelations(static_cast<ExportPointsIntervalUnits> (int32));
   str >> int32;
-  m_modelExport.setHeader((ExportHeader) int32);
+  m_modelExport.setHeader(static_cast<ExportHeader> (int32));
   if (version >= 5.1) {
     str >> st; // X label
     if (m_modelCoords.coordsType() == COORDS_TYPE_CARTESIAN) {
@@ -437,9 +443,9 @@ void CoordSystem::loadPreVersion6 (QDataStream &str,
   str >> int32;
   m_modelGridRemoval.setCountY(int32);
   str >> int32;
-  m_modelGridRemoval.setGridCoordDisableX((GridCoordDisable) int32);
+  m_modelGridRemoval.setGridCoordDisableX(static_cast<GridCoordDisable> (int32));
   str >> int32;
-  m_modelGridRemoval.setGridCoordDisableY((GridCoordDisable) int32);
+  m_modelGridRemoval.setGridCoordDisableY(static_cast<GridCoordDisable> (int32));
   str >> dbl;
   m_modelGridRemoval.setStartX(dbl);
   str >> dbl;
@@ -468,13 +474,13 @@ void CoordSystem::loadPreVersion6 (QDataStream &str,
   str >> int32;
   m_modelGridDisplay.setStable(int32);
   str >> int32;
-  m_modelGridDisplay.setCountX(int32);
+  m_modelGridDisplay.setCountX(unsigned (int32));
   str >> int32;
-  m_modelGridDisplay.setCountY(int32);
+  m_modelGridDisplay.setCountY(unsigned (int32));
   str >> int32;
-  m_modelGridDisplay.setDisableX((GridCoordDisable) int32);
+  m_modelGridDisplay.setDisableX(static_cast<GridCoordDisable> (int32));
   str >> int32;
-  m_modelGridDisplay.setDisableY((GridCoordDisable) int32);
+  m_modelGridDisplay.setDisableY(static_cast<GridCoordDisable> (int32));
   str >> dbl;
   m_modelGridDisplay.setStartX (dbl);
   str >> dbl;
@@ -497,20 +503,20 @@ void CoordSystem::loadPreVersion6 (QDataStream &str,
   str >> int32;
   m_modelSegments.setLineWidth(int32);
   str >> int32;
-  m_modelSegments.setLineColor((ColorPalette) int32);
+  m_modelSegments.setLineColor(static_cast<ColorPalette> (int32));
 
   str >> int32; // Point separation
   str >> int32;
   m_modelPointMatch.setMaxPointSize(int32);
   str >> int32;
-  m_modelPointMatch.setPaletteColorAccepted((ColorPalette) int32);
+  m_modelPointMatch.setPaletteColorAccepted(static_cast<ColorPalette> (int32));
   str >> int32;
-  m_modelPointMatch.setPaletteColorRejected((ColorPalette) int32);
+  m_modelPointMatch.setPaletteColorRejected(static_cast<ColorPalette> (int32));
   if (version < 4) {
     m_modelPointMatch.setPaletteColorCandidate(COLOR_PALETTE_BLUE);
   } else {
     str >> int32;
-    m_modelPointMatch.setPaletteColorCandidate((ColorPalette) int32);
+    m_modelPointMatch.setPaletteColorCandidate(static_cast<ColorPalette> (int32));
   }
 
   str >> int32; // Discretize method
@@ -531,12 +537,14 @@ void CoordSystem::loadPreVersion6 (QDataStream &str,
   if (curveScaleIn->numPoints() == 2) {
     // Nondefault case is map with scale bar
     documentAxesPointsRequired = DOCUMENT_AXES_POINTS_REQUIRED_2;
+    delete m_curveAxes;
     m_curveAxes = curveScaleIn;
     m_curveAxes->setCurveName (AXIS_CURVE_NAME); // Override existing "Scale" name
     delete curveAxesIn;
   } else {
     // Default case is graph with axes
     documentAxesPointsRequired = DOCUMENT_AXES_POINTS_REQUIRED_3;
+    delete m_curveAxes;    
     m_curveAxes = curveAxesIn;
     delete curveScaleIn;
   }
@@ -579,6 +587,7 @@ void CoordSystem::loadVersion6 (QXmlStreamReader &reader,
       } else if (tag == DOCUMENT_SERIALIZE_COORDS) {
         m_modelCoords.loadXml (reader);
       } else if (tag == DOCUMENT_SERIALIZE_CURVE) {
+        delete m_curveAxes;        
         m_curveAxes = new Curve (reader);
       } else if (tag == DOCUMENT_SERIALIZE_CURVES_GRAPHS) {
         m_curvesGraphs.loadXml (reader);
@@ -636,6 +645,7 @@ void CoordSystem::loadVersions7AndUp (QXmlStreamReader &reader)
       } else if (tag == DOCUMENT_SERIALIZE_COORDS) {
         m_modelCoords.loadXml (reader);
       } else if (tag == DOCUMENT_SERIALIZE_CURVE) {
+        delete m_curveAxes;                
         m_curveAxes = new Curve (reader);
       } else if (tag == DOCUMENT_SERIALIZE_CURVES_GRAPHS) {
         m_curvesGraphs.loadXml (reader);
@@ -733,7 +743,7 @@ void CoordSystem::movePoint (const QString &pointIdentifier,
   QString curveName = Point::curveNameFromPointIdentifier (pointIdentifier);
 
   Curve *curve = curveForCurveName (curveName);
-  ENGAUGE_ASSERT (curve != 0);
+  ENGAUGE_CHECK_PTR (curve);
   curve->movePoint (pointIdentifier,
                     deltaScreen);
 }
@@ -751,7 +761,7 @@ int CoordSystem::nextOrdinalForCurve (const QString &curveName) const
     m_curvesGraphs.iterateThroughCurvesPoints (ftorWithCallback);
   }
 
-  return ftor.nextOrdinal ();
+  return qFloor (ftor.nextOrdinal ());
 }
 
 QPointF CoordSystem::positionGraph (const QString &pointIdentifier) const
@@ -849,7 +859,7 @@ void CoordSystem::removePointsInCurvesGraphs (CurvesGraphs &curvesGraphs)
 void CoordSystem::resetSelectedCurveNameIfNecessary ()
 {
   if (m_selectedCurveName.isEmpty () ||
-      curveForCurveName (m_selectedCurveName) == 0) {
+      curveForCurveName (m_selectedCurveName) == nullptr) {
 
     // Selected curve name is empty, or the curve has been removed so we pick another. The first is arbitrarily picked
     m_selectedCurveName = m_curvesGraphs.curvesGraphsNames().first();
diff --git a/src/CoordSystem/CoordSystem.h b/src/CoordSystem/CoordSystem.h
index 2592a84a..8c010751 100644
--- a/src/CoordSystem/CoordSystem.h
+++ b/src/CoordSystem/CoordSystem.h
@@ -44,6 +44,7 @@ class CoordSystem : public CoordSystemInterface
 public:
   /// Single constructor
   CoordSystem ();
+  ~CoordSystem ();
 
   /// Constructor for opened Graphs, and error report files. The specified file is opened and read
   CoordSystem (const QString &fileName);
diff --git a/src/CoordSystem/CoordSystemContext.cpp b/src/CoordSystem/CoordSystemContext.cpp
index bfbf066b..5d3ca271 100644
--- a/src/CoordSystem/CoordSystemContext.cpp
+++ b/src/CoordSystem/CoordSystemContext.cpp
@@ -20,13 +20,7 @@ CoordSystemContext::~CoordSystemContext()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::~CoordSystemContext";
 
-  for (int i = 0; i < m_coordSystems.count(); i++) {
-    CoordSystem *coordSystem = m_coordSystems.at (i);
-    delete coordSystem;
-  }
-
-  m_coordSystems.clear ();
-  m_coordSystemIndex = 0;
+  qDeleteAll (m_coordSystems);
 }
 
 void CoordSystemContext::addCoordSystems(unsigned int numberCoordSystemToAdd)
@@ -44,7 +38,7 @@ void CoordSystemContext::addGraphCurveAtEnd (const QString &curveName)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addGraphCurveAtEnd";
 
-  m_coordSystems [m_coordSystemIndex]->addGraphCurveAtEnd(curveName);
+  m_coordSystems [signed (m_coordSystemIndex)]->addGraphCurveAtEnd(curveName);
 }
 
 void CoordSystemContext::addPointAxisWithGeneratedIdentifier (const QPointF &posScreen,
@@ -55,11 +49,11 @@ void CoordSystemContext::addPointAxisWithGeneratedIdentifier (const QPointF &pos
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addPointAxisWithGeneratedIdentifier";
 
-  m_coordSystems [m_coordSystemIndex]->addPointAxisWithGeneratedIdentifier(posScreen,
-                                                                           posGraph,
-                                                                           identifier,
-                                                                           ordinal,
-                                                                           isXOnly);
+  m_coordSystems [signed (m_coordSystemIndex)]->addPointAxisWithGeneratedIdentifier(posScreen,
+                                                                                    posGraph,
+                                                                                    identifier,
+                                                                                    ordinal,
+                                                                                    isXOnly);
 }
 
 void CoordSystemContext::addPointAxisWithSpecifiedIdentifier (const QPointF &posScreen,
@@ -70,11 +64,11 @@ void CoordSystemContext::addPointAxisWithSpecifiedIdentifier (const QPointF &pos
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addPointAxisWithSpecifiedIdentifier";
 
-  m_coordSystems [m_coordSystemIndex]->addPointAxisWithSpecifiedIdentifier(posScreen,
-                                                                           posGraph,
-                                                                           identifier,
-                                                                           ordinal,
-                                                                           isXOnly);
+  m_coordSystems [signed (m_coordSystemIndex)]->addPointAxisWithSpecifiedIdentifier(posScreen,
+                                                                                    posGraph,
+                                                                                    identifier,
+                                                                                    ordinal,
+                                                                                    isXOnly);
 }
 
 void CoordSystemContext::addPointGraphWithGeneratedIdentifier (const QString &curveName,
@@ -84,10 +78,10 @@ void CoordSystemContext::addPointGraphWithGeneratedIdentifier (const QString &cu
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addPointGraphWithGeneratedIdentifier";
 
-  m_coordSystems [m_coordSystemIndex]->addPointGraphWithGeneratedIdentifier(curveName,
-                                                                            posScreen,
-                                                                            generatedIdentifier,
-                                                                            ordinal);
+  m_coordSystems [signed (m_coordSystemIndex)]->addPointGraphWithGeneratedIdentifier(curveName,
+                                                                                     posScreen,
+                                                                                     generatedIdentifier,
+                                                                                     ordinal);
 }
 
 void CoordSystemContext::addPointGraphWithSpecifiedIdentifier (const QString &curveName,
@@ -97,17 +91,17 @@ void CoordSystemContext::addPointGraphWithSpecifiedIdentifier (const QString &cu
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addPointGraphWithSpecifiedIdentifier";
 
-  m_coordSystems [m_coordSystemIndex]->addPointGraphWithSpecifiedIdentifier(curveName,
-                                                                            posScreen,
-                                                                            identifier,
-                                                                            ordinal);
+  m_coordSystems [signed (m_coordSystemIndex)]->addPointGraphWithSpecifiedIdentifier(curveName,
+                                                                                     posScreen,
+                                                                                     identifier,
+                                                                                     ordinal);
 }
 
 void CoordSystemContext::addPointsInCurvesGraphs (CurvesGraphs &curvesGraphs)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addPointsInCurvesGraphs";
 
-  m_coordSystems [m_coordSystemIndex]->addPointsInCurvesGraphs(curvesGraphs);
+  m_coordSystems [signed (m_coordSystemIndex)]->addPointsInCurvesGraphs(curvesGraphs);
 }
 
 void CoordSystemContext::checkAddPointAxis (const QPointF &posScreen,
@@ -119,12 +113,12 @@ void CoordSystemContext::checkAddPointAxis (const QPointF &posScreen,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::checkAddPointAxis";
 
-  m_coordSystems [m_coordSystemIndex]->checkAddPointAxis(posScreen,
-                                                         posGraph,
-                                                         isError,
-                                                         errorMessage,
-                                                         isXOnly,
-                                                         documentAxesPointsRequired);
+  m_coordSystems [signed (m_coordSystemIndex)]->checkAddPointAxis(posScreen,
+                                                                  posGraph,
+                                                                  isError,
+                                                                  errorMessage,
+                                                                  isXOnly,
+                                                                  documentAxesPointsRequired);
 }
 
 void CoordSystemContext::checkEditPointAxis (const QString &pointIdentifier,
@@ -136,24 +130,24 @@ void CoordSystemContext::checkEditPointAxis (const QString &pointIdentifier,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::checkEditPointAxis";
 
-  m_coordSystems [m_coordSystemIndex]->checkEditPointAxis(pointIdentifier,
-                                                          posScreen,
-                                                          posGraph,
-                                                          isError,
-                                                          errorMessage,
-                                                          documentAxesPointsRequired);
+  m_coordSystems [signed (m_coordSystemIndex)]->checkEditPointAxis(pointIdentifier,
+                                                                   posScreen,
+                                                                   posGraph,
+                                                                   isError,
+                                                                   errorMessage,
+                                                                   documentAxesPointsRequired);
 }
 
 const CoordSystem &CoordSystemContext::coordSystem () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::coordSystem";
 
-  return *(m_coordSystems [m_coordSystemIndex]);
+  return *(m_coordSystems [signed (m_coordSystemIndex)]);
 }
 
 unsigned int CoordSystemContext::coordSystemCount() const
 {
-  return m_coordSystems.count();
+  return unsigned (m_coordSystems.count());
 }
 
 CoordSystemIndex CoordSystemContext::coordSystemIndex () const
@@ -165,42 +159,42 @@ const Curve &CoordSystemContext::curveAxes () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curveAxes";
 
-  return m_coordSystems [m_coordSystemIndex]->curveAxes();
+  return m_coordSystems [signed (m_coordSystemIndex)]->curveAxes();
 }
 
 Curve *CoordSystemContext::curveForCurveName (const QString &curveName)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curveForCurveName";
 
-  return m_coordSystems [m_coordSystemIndex]->curveForCurveName(curveName);
+  return m_coordSystems [signed (m_coordSystemIndex)]->curveForCurveName(curveName);
 }
 
 const Curve *CoordSystemContext::curveForCurveName (const QString &curveName) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curveForCurveName";
 
-  return m_coordSystems [m_coordSystemIndex]->curveForCurveName(curveName);
+  return m_coordSystems [signed (m_coordSystemIndex)]->curveForCurveName(curveName);
 }
 
 const CurvesGraphs &CoordSystemContext::curvesGraphs () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curvesGraphs";
 
-  return m_coordSystems [m_coordSystemIndex]->curvesGraphs();
+  return m_coordSystems [signed (m_coordSystemIndex)]->curvesGraphs();
 }
 
 QStringList CoordSystemContext::curvesGraphsNames () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curvesGraphsNames";
 
-  return m_coordSystems [m_coordSystemIndex]->curvesGraphsNames();
+  return m_coordSystems [signed (m_coordSystemIndex)]->curvesGraphsNames();
 }
 
 int CoordSystemContext::curvesGraphsNumPoints (const QString &curveName) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::curvesGraphsNumPoints";
 
-  return m_coordSystems [m_coordSystemIndex]->curvesGraphsNumPoints(curveName);
+  return m_coordSystems [signed (m_coordSystemIndex)]->curvesGraphsNumPoints(curveName);
 }
 
 void CoordSystemContext::editPointAxis (const QPointF &posGraph,
@@ -208,8 +202,8 @@ void CoordSystemContext::editPointAxis (const QPointF &posGraph,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::editPointAxis";
 
-  m_coordSystems [m_coordSystemIndex]->editPointAxis(posGraph,
-                                                     identifier);
+  m_coordSystems [signed (m_coordSystemIndex)]->editPointAxis(posGraph,
+                                                              identifier);
 }
 
 void CoordSystemContext::editPointGraph (bool isX,
@@ -221,33 +215,33 @@ void CoordSystemContext::editPointGraph (bool isX,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::editPointGraph";
 
-  m_coordSystems [m_coordSystemIndex]->editPointGraph (isX,
-                                                       isY,
-                                                       x,
-                                                       y,
-                                                       identifiers,
-                                                       transformation);
+  m_coordSystems [signed (m_coordSystemIndex)]->editPointGraph (isX,
+                                                                isY,
+                                                                x,
+                                                                y,
+                                                                identifiers,
+                                                                transformation);
 }
 
 bool CoordSystemContext::isXOnly (const QString &pointIdentifier) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::isXOnly";
 
-  return m_coordSystems [m_coordSystemIndex]->isXOnly (pointIdentifier);
+  return m_coordSystems [signed (m_coordSystemIndex)]->isXOnly (pointIdentifier);
 }
 
 void CoordSystemContext::iterateThroughCurvePointsAxes (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::iterateThroughCurvePointsAxes";
 
-  m_coordSystems [m_coordSystemIndex]->iterateThroughCurvePointsAxes(ftorWithCallback);
+  m_coordSystems [signed (m_coordSystemIndex)]->iterateThroughCurvePointsAxes(ftorWithCallback);
 }
 
 void CoordSystemContext::iterateThroughCurvePointsAxes (const Functor2wRet<const QString  &, const Point &, CallbackSearchReturn> &ftorWithCallback) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::iterateThroughCurvePointsAxes";
 
-  m_coordSystems [m_coordSystemIndex]->iterateThroughCurvePointsAxes(ftorWithCallback);
+  m_coordSystems [signed (m_coordSystemIndex)]->iterateThroughCurvePointsAxes(ftorWithCallback);
 }
 
 void CoordSystemContext::iterateThroughCurveSegments (const QString &curveName,
@@ -255,29 +249,29 @@ void CoordSystemContext::iterateThroughCurveSegments (const QString &curveName,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::iterateThroughCurveSegments";
 
-  m_coordSystems [m_coordSystemIndex]->iterateThroughCurveSegments(curveName,
-                                                                   ftorWithCallback);
+  m_coordSystems [signed (m_coordSystemIndex)]->iterateThroughCurveSegments(curveName,
+                                                                            ftorWithCallback);
 }
 
 void CoordSystemContext::iterateThroughCurvesPointsGraphs (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::iterateThroughCurvesPointsGraphs";
 
-  m_coordSystems [m_coordSystemIndex]->iterateThroughCurvesPointsGraphs(ftorWithCallback);
+  m_coordSystems [signed (m_coordSystemIndex)]->iterateThroughCurvesPointsGraphs(ftorWithCallback);
 }
 
 void CoordSystemContext::iterateThroughCurvesPointsGraphs (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::iterateThroughCurvesPointsGraphs";
 
-  m_coordSystems [m_coordSystemIndex]->iterateThroughCurvesPointsGraphs(ftorWithCallback);
+  m_coordSystems [signed (m_coordSystemIndex)]->iterateThroughCurvesPointsGraphs(ftorWithCallback);
 }
 
 bool CoordSystemContext::loadCurvesFile (const QString &curvesFile)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::loadCurvesFile";
 
-  return m_coordSystems [m_coordSystemIndex]->loadCurvesFile (curvesFile);
+  return m_coordSystems [signed (m_coordSystemIndex)]->loadCurvesFile (curvesFile);
 }
 
 void CoordSystemContext::loadPreVersion6 (QDataStream &str,
@@ -286,9 +280,9 @@ void CoordSystemContext::loadPreVersion6 (QDataStream &str,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::loadPreVersion6";
 
-  m_coordSystems [m_coordSystemIndex]->loadPreVersion6 (str,
-                                                        version,
-                                                        documentAxesPointsRequired);
+  m_coordSystems [signed (m_coordSystemIndex)]->loadPreVersion6 (str,
+                                                                 version,
+                                                                 documentAxesPointsRequired);
 }
 
 void CoordSystemContext::loadVersion6 (QXmlStreamReader &reader,
@@ -296,8 +290,8 @@ void CoordSystemContext::loadVersion6 (QXmlStreamReader &reader,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::loadVersion6";
 
-  m_coordSystems [m_coordSystemIndex]->loadVersion6 (reader,
-                                                     documentAxesPointsRequired);
+  m_coordSystems [signed (m_coordSystemIndex)]->loadVersion6 (reader,
+                                                              documentAxesPointsRequired);
 }
 
 void CoordSystemContext::loadVersions7AndUp (QXmlStreamReader &reader)
@@ -312,77 +306,77 @@ DocumentModelAxesChecker CoordSystemContext::modelAxesChecker() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelAxesChecker";
 
-  return m_coordSystems [m_coordSystemIndex]->modelAxesChecker();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelAxesChecker();
 }
 
 DocumentModelColorFilter CoordSystemContext::modelColorFilter() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelColorFilter";
 
-  return m_coordSystems [m_coordSystemIndex]->modelColorFilter();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelColorFilter();
 }
 
 DocumentModelCoords CoordSystemContext::modelCoords () const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelCoords";
 
-  return m_coordSystems [m_coordSystemIndex]->modelCoords();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelCoords();
 }
 
 CurveStyles CoordSystemContext::modelCurveStyles() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelCurveStyles";
 
-  return m_coordSystems [m_coordSystemIndex]->modelCurveStyles();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelCurveStyles();
 }
 
 DocumentModelDigitizeCurve CoordSystemContext::modelDigitizeCurve() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelDigitizeCurve";
 
-  return m_coordSystems [m_coordSystemIndex]->modelDigitizeCurve();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelDigitizeCurve();
 }
 
 DocumentModelExportFormat CoordSystemContext::modelExport() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelExport";
 
-  return m_coordSystems [m_coordSystemIndex]->modelExport();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelExport();
 }
 
 DocumentModelGeneral CoordSystemContext::modelGeneral() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelGeneral";
 
-  return m_coordSystems [m_coordSystemIndex]->modelGeneral();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelGeneral();
 }
 
 DocumentModelGridDisplay CoordSystemContext::modelGridDisplay() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelGridDisplay";
 
-  return m_coordSystems [m_coordSystemIndex]->modelGridDisplay();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelGridDisplay();
 }
 
 DocumentModelGridRemoval CoordSystemContext::modelGridRemoval() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelGridRemoval";
 
-  return m_coordSystems [m_coordSystemIndex]->modelGridRemoval();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelGridRemoval();
 }
 
 DocumentModelPointMatch CoordSystemContext::modelPointMatch() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelPointMatch";
 
-  return m_coordSystems [m_coordSystemIndex]->modelPointMatch();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelPointMatch();
 }
 
 DocumentModelSegments CoordSystemContext::modelSegments() const
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "CoordSystemContext::modelSegments";
 
-  return m_coordSystems [m_coordSystemIndex]->modelSegments();
+  return m_coordSystems [signed (m_coordSystemIndex)]->modelSegments();
 }
 
 void CoordSystemContext::movePoint (const QString &pointIdentifier,
@@ -390,36 +384,36 @@ void CoordSystemContext::movePoint (const QString &pointIdentifier,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::movePoint";
 
-  return m_coordSystems [m_coordSystemIndex]->movePoint(pointIdentifier,
-                                                        deltaScreen);
+  return m_coordSystems [signed (m_coordSystemIndex)]->movePoint(pointIdentifier,
+                                                                 deltaScreen);
 }
 
 int CoordSystemContext::nextOrdinalForCurve (const QString &curveName) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::nextOrdinalForCurve";
 
-  return m_coordSystems [m_coordSystemIndex]->nextOrdinalForCurve(curveName);
+  return m_coordSystems [signed (m_coordSystemIndex)]->nextOrdinalForCurve(curveName);
 }
 
 QPointF CoordSystemContext::positionGraph (const QString &pointIdentifier) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::positionGraph";
 
-  return m_coordSystems [m_coordSystemIndex]->positionGraph(pointIdentifier);
+  return m_coordSystems [signed (m_coordSystemIndex)]->positionGraph(pointIdentifier);
 }
 
 QPointF CoordSystemContext::positionScreen (const QString &pointIdentifier) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::addGraphCurveAtEnd";
 
-  return m_coordSystems [m_coordSystemIndex]->positionScreen(pointIdentifier);
+  return m_coordSystems [signed (m_coordSystemIndex)]->positionScreen(pointIdentifier);
 }
 
 void CoordSystemContext::print () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::print";
 
-  return m_coordSystems [m_coordSystemIndex]->print();
+  return m_coordSystems [signed (m_coordSystemIndex)]->print();
 }
 
 void CoordSystemContext::printStream (QString indentation,
@@ -427,36 +421,36 @@ void CoordSystemContext::printStream (QString indentation,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::printStream";
 
-  m_coordSystems [m_coordSystemIndex]->printStream(indentation,
-                                                   str);
+  m_coordSystems [signed (m_coordSystemIndex)]->printStream(indentation,
+                                                            str);
 }
 
 QString CoordSystemContext::reasonForUnsuccessfulRead () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::reasonForUnsuccessfulRead";
 
-  return m_coordSystems [m_coordSystemIndex]->reasonForUnsuccessfulRead();
+  return m_coordSystems [signed (m_coordSystemIndex)]->reasonForUnsuccessfulRead();
 }
 
 void CoordSystemContext::removePointAxis (const QString &identifier)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::removePointAxis";
 
-  m_coordSystems [m_coordSystemIndex]->removePointAxis(identifier);
+  m_coordSystems [signed (m_coordSystemIndex)]->removePointAxis(identifier);
 }
 
 void CoordSystemContext::removePointGraph (const QString &identifier)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::removePointGraph";
 
-  m_coordSystems [m_coordSystemIndex]->removePointGraph(identifier);
+  m_coordSystems [signed (m_coordSystemIndex)]->removePointGraph(identifier);
 }
 
 void CoordSystemContext::removePointsInCurvesGraphs (CurvesGraphs &curvesGraphs)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::removePointsInCurvesGraphs";
 
-  m_coordSystems [m_coordSystemIndex]->removePointsInCurvesGraphs(curvesGraphs);
+  m_coordSystems [signed (m_coordSystemIndex)]->removePointsInCurvesGraphs(curvesGraphs);
 }
 
 void CoordSystemContext::saveXml (QXmlStreamWriter &writer) const
@@ -470,7 +464,7 @@ void CoordSystemContext::saveXml (QXmlStreamWriter &writer) const
 
 QString CoordSystemContext::selectedCurveName () const
 {
-  return m_coordSystems [m_coordSystemIndex]->selectedCurveName();
+  return m_coordSystems [signed (m_coordSystemIndex)]->selectedCurveName();
 }
 
 void CoordSystemContext::setCoordSystemIndex(CoordSystemIndex coordSystemIndex)
@@ -478,7 +472,7 @@ void CoordSystemContext::setCoordSystemIndex(CoordSystemIndex coordSystemIndex)
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setCoordSystemIndex"
                               << " index=" << coordSystemIndex;
 
-  ENGAUGE_ASSERT(coordSystemIndex < (unsigned int) m_coordSystems.count());
+  ENGAUGE_ASSERT(coordSystemIndex < unsigned (m_coordSystems.count()));
 
   m_coordSystemIndex = coordSystemIndex;
 }
@@ -487,108 +481,108 @@ void CoordSystemContext::setCurveAxes (const Curve &curveAxes)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setCurveAxes";
 
-  m_coordSystems [m_coordSystemIndex]->setCurveAxes(curveAxes);
+  m_coordSystems [signed (m_coordSystemIndex)]->setCurveAxes(curveAxes);
 }
 
 void CoordSystemContext::setCurvesGraphs (const CurvesGraphs &curvesGraphs)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setCurvesGraphs";
 
-  m_coordSystems [m_coordSystemIndex]->setCurvesGraphs(curvesGraphs);
+  m_coordSystems [signed (m_coordSystemIndex)]->setCurvesGraphs(curvesGraphs);
 }
 
 void CoordSystemContext::setModelAxesChecker(const DocumentModelAxesChecker &modelAxesChecker)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelAxesChecker";
 
-  m_coordSystems [m_coordSystemIndex]->setModelAxesChecker(modelAxesChecker);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelAxesChecker(modelAxesChecker);
 }
 
 void CoordSystemContext::setModelColorFilter(const DocumentModelColorFilter &modelColorFilter)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelColorFilter";
 
-  m_coordSystems [m_coordSystemIndex]->setModelColorFilter(modelColorFilter);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelColorFilter(modelColorFilter);
 }
 
 void CoordSystemContext::setModelCoords (const DocumentModelCoords &modelCoords)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelCoords";
 
-  m_coordSystems [m_coordSystemIndex]->setModelCoords(modelCoords);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelCoords(modelCoords);
 }
 
 void CoordSystemContext::setModelCurveStyles(const CurveStyles &modelCurveStyles)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelCurveStyles";
 
-  m_coordSystems [m_coordSystemIndex]->setModelCurveStyles(modelCurveStyles);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelCurveStyles(modelCurveStyles);
 }
 
 void CoordSystemContext::setModelDigitizeCurve (const DocumentModelDigitizeCurve &modelDigitizeCurve)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelDigitizeCurve";
 
-  m_coordSystems [m_coordSystemIndex]->setModelDigitizeCurve(modelDigitizeCurve);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelDigitizeCurve(modelDigitizeCurve);
 }
 
 void CoordSystemContext::setModelExport(const DocumentModelExportFormat &modelExport)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelExport";
 
-  m_coordSystems [m_coordSystemIndex]->setModelExport (modelExport);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelExport (modelExport);
 }
 
 void CoordSystemContext::setModelGeneral (const DocumentModelGeneral &modelGeneral)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelGeneral";
 
-  m_coordSystems [m_coordSystemIndex]->setModelGeneral(modelGeneral);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelGeneral(modelGeneral);
 }
 
 void CoordSystemContext::setModelGridDisplay(const DocumentModelGridDisplay &modelGridDisplay)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelGridDisplay";
 
-  m_coordSystems [m_coordSystemIndex]->setModelGridDisplay(modelGridDisplay);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelGridDisplay(modelGridDisplay);
 }
 
 void CoordSystemContext::setModelGridRemoval(const DocumentModelGridRemoval &modelGridRemoval)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelGridRemoval";
 
-  m_coordSystems [m_coordSystemIndex]->setModelGridRemoval(modelGridRemoval);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelGridRemoval(modelGridRemoval);
 }
 
 void CoordSystemContext::setModelPointMatch(const DocumentModelPointMatch &modelPointMatch)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelPointMatch";
 
-  m_coordSystems [m_coordSystemIndex]->setModelPointMatch(modelPointMatch);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelPointMatch(modelPointMatch);
 }
 
 void CoordSystemContext::setModelSegments(const DocumentModelSegments &modelSegments)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::setModelSegments";
 
-  m_coordSystems [m_coordSystemIndex]->setModelSegments(modelSegments);
+  m_coordSystems [signed (m_coordSystemIndex)]->setModelSegments(modelSegments);
 }
 
 void CoordSystemContext::setSelectedCurveName(const QString &selectedCurveName)
 {
-  m_coordSystems [m_coordSystemIndex]->setSelectedCurveName(selectedCurveName);
+  m_coordSystems [signed (m_coordSystemIndex)]->setSelectedCurveName(selectedCurveName);
 }
 
 bool CoordSystemContext::successfulRead () const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::successfulRead";
 
-  return m_coordSystems [m_coordSystemIndex]->successfulRead();
+  return m_coordSystems [signed (m_coordSystemIndex)]->successfulRead();
 }
 
 void CoordSystemContext::updatePointOrdinals (const Transformation &transformation)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CoordSystemContext::updatePointOrdinals";
 
-  m_coordSystems [m_coordSystemIndex]->updatePointOrdinals(transformation);
+  m_coordSystems [signed (m_coordSystemIndex)]->updatePointOrdinals(transformation);
 }
diff --git a/src/Correlation/Correlation.cpp b/src/Correlation/Correlation.cpp
index bcae07c4..e4cc5912 100644
--- a/src/Correlation/Correlation.cpp
+++ b/src/Correlation/Correlation.cpp
@@ -13,12 +13,12 @@
 
 Correlation::Correlation(int N) :
   m_N (N),
-  m_signalA ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1))),
-  m_signalB ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1))),
-  m_outShifted ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1))),
-  m_outA ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1))),
-  m_outB ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1))),
-  m_out ((fftw_complex *) fftw_malloc(sizeof(fftw_complex) * (2 * N - 1)))
+  m_signalA (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1)))),
+  m_signalB (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1)))),
+  m_outShifted (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1)))),
+  m_outA (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1)))),
+  m_outB (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1)))),
+  m_out (static_cast<fftw_complex *> (fftw_malloc(sizeof(fftw_complex) * unsigned (2 * N - 1))))
 {
   m_planA = fftw_plan_dft_1d(2 * N - 1, m_signalA, m_outA, FFTW_FORWARD, FFTW_ESTIMATE);
   m_planB = fftw_plan_dft_1d(2 * N - 1, m_signalB, m_outB, FFTW_FORWARD, FFTW_ESTIMATE);
diff --git a/src/Create/CreateActions.cpp b/src/Create/CreateActions.cpp
index 3f7ee938..4c7ee2d7 100644
--- a/src/Create/CreateActions.cpp
+++ b/src/Create/CreateActions.cpp
@@ -71,19 +71,25 @@ void CreateActions::createDigitize (MainWindow &mw)
   mw.m_actionDigitizeAxis->setWhatsThis (tr ("Digitize Axis Point\n\n"
                                              "Digitizes an axis point for a graph by placing a new point at the cursor "
                                              "after a mouse click. The coordinates of the axis point are then "
-                                             "entered. In a graph, three axis points are required to define "
-                                             "the graph coordinates."));
+                                             "entered. After Import and Import (Advanced), three axis points with "
+                                             "(X1,Y1) (X2,Y2) (X3,Y3) coordinates can be digitized to define the graph coordinates. "
+                                             "Optionally, after Import (Advanced) four axis points with "
+                                             "(X1) (X2) (Y3) (Y4) coordinates can be digitized to define the graph coordinates.\n\n"
+                                             "This tool is disabled when a complete set of axis points has been defined, or "
+                                             "after Import (Advanced) if Scale Bar is selected."));
   connect (mw.m_actionDigitizeAxis, SIGNAL (triggered ()), &mw, SLOT (slotDigitizeAxis ()));
 
   mw.m_actionDigitizeScale = new QAction (iconScale, tr ("Scale Bar Tool"), &mw);
   mw.m_actionDigitizeScale->setShortcut (QKeySequence (tr ("Shift+F8")));
   mw.m_actionDigitizeScale->setCheckable (true);
-  mw.m_actionDigitizeScale->setStatusTip (tr ("Digitize scale bar for a map."));
+  mw.m_actionDigitizeScale->setStatusTip (tr ("Digitize scale bar for a map. Requires Import (Advanced)."));
   mw.m_actionDigitizeScale->setWhatsThis (tr ("Digitize Scale Bar\n\n"
                                               "Digitize a scale bar for a map by clicking and dragging. The length of the "
                                               "scale bar is then entered. In a map, the two endpoints of the scale "
                                               "bar define the distances in graph coordinates.\n\n"
-                                              "Maps must be imported using Import (Advanced)."));
+                                              "This tool is enabled by selecting Scale Bar in Import (Advanced).\n\n"
+                                              "This tool is disabled when a scale bar has been defined, or "
+                                              "if axis points were selected during import."));
   connect (mw.m_actionDigitizeScale, SIGNAL (triggered ()), &mw, SLOT (slotDigitizeScale ()));
 
   mw.m_actionDigitizeCurve = new QAction (iconCurve, tr ("Curve Point Tool"), &mw);
@@ -331,11 +337,11 @@ void CreateActions::createSettings (MainWindow &mw)
                                                "Coordinate settings determine how the graph coordinates are mapped to the pixels in the image"));
   connect (mw.m_actionSettingsCoords, SIGNAL (triggered ()), &mw, SLOT (slotSettingsCoords ()));
 
-  mw.m_actionSettingsCurveAddRemove = new QAction (tr ("Curve List..."), &mw);
-  mw.m_actionSettingsCurveAddRemove->setStatusTip (tr ("Edit Curve List settings."));
-  mw.m_actionSettingsCurveAddRemove->setWhatsThis (tr ("Curve List\n\n"
-                                                       "Curve list settings add, rename and/or remove curves in the current document"));
-  connect (mw.m_actionSettingsCurveAddRemove, SIGNAL (triggered ()), &mw, SLOT (slotSettingsCurveAddRemove ()));
+  mw.m_actionSettingsCurveList = new QAction (tr ("Curve List..."), &mw);
+  mw.m_actionSettingsCurveList->setStatusTip (tr ("Edit Curve List settings."));
+  mw.m_actionSettingsCurveList->setWhatsThis (tr ("Curve List\n\n"
+                                                  "Curve list settings add, rename and/or remove curves in the current document"));
+  connect (mw.m_actionSettingsCurveList, SIGNAL (triggered ()), &mw, SLOT (slotSettingsCurveList ()));
 
   mw.m_actionSettingsCurveProperties = new QAction (tr ("Curve Properties..."), &mw);
   mw.m_actionSettingsCurveProperties->setStatusTip (tr ("Edit Curve Properties settings."));
diff --git a/src/Create/CreateHelpWindow.cpp b/src/Create/CreateHelpWindow.cpp
index 8a3d71a1..f501955e 100644
--- a/src/Create/CreateHelpWindow.cpp
+++ b/src/Create/CreateHelpWindow.cpp
@@ -14,7 +14,11 @@ CreateHelpWindow::CreateHelpWindow()
 {
 }
 
-void CreateHelpWindow::create (MainWindow &mw)
+void CreateHelpWindow::create (MainWindow &
+#if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)                               
+                               mw
+#endif                               
+                               )
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CreateHelpWindow::create";
 
diff --git a/src/Create/CreateLoadImage.cpp b/src/Create/CreateLoadImage.cpp
index e4bd02ad..ab03f24a 100644
--- a/src/Create/CreateLoadImage.cpp
+++ b/src/Create/CreateLoadImage.cpp
@@ -17,8 +17,6 @@ void CreateLoadImage::create(MainWindow &mw)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CreateLoadImage::create";
   
-#ifdef NETWORKING
   mw.m_loadImageFromUrl = new LoadImageFromUrl (mw);
-#endif
 }
 
diff --git a/src/Create/CreateMenus.cpp b/src/Create/CreateMenus.cpp
index 879a8043..01457162 100644
--- a/src/Create/CreateMenus.cpp
+++ b/src/Create/CreateMenus.cpp
@@ -25,7 +25,7 @@ void CreateMenus::create(MainWindow &mw)
   mw.m_menuFile->addAction (mw.m_actionOpen);
 #if !defined(OSX_DEBUG) && !defined(OSX_RELEASE)
   mw.m_menuFileOpenRecent = new QMenu (tr ("Open &Recent"));
-  for (unsigned int i = 0; i < MAX_RECENT_FILE_LIST_SIZE; i++) {
+  for (int i = 0; i < signed (MAX_RECENT_FILE_LIST_SIZE); i++) {
     mw.m_menuFileOpenRecent->addAction (mw.m_actionRecentFiles.at (i));
   }
   mw.m_menuFile->addMenu (mw.m_menuFileOpenRecent);
@@ -123,7 +123,7 @@ void CreateMenus::create(MainWindow &mw)
 
   mw.m_menuSettings = mw.menuBar()->addMenu(tr ("Settings"));
   mw.m_menuSettings->addAction (mw.m_actionSettingsCoords);
-  mw.m_menuSettings->addAction (mw.m_actionSettingsCurveAddRemove);
+  mw.m_menuSettings->addAction (mw.m_actionSettingsCurveList);
   mw.m_menuSettings->addAction (mw.m_actionSettingsCurveProperties);
   mw.m_menuSettings->addAction (mw.m_actionSettingsDigitizeCurve);
   mw.m_menuSettings->addAction (mw.m_actionSettingsExport);
diff --git a/src/Create/CreateNetwork.cpp b/src/Create/CreateNetwork.cpp
index 2105ed27..18e43be1 100644
--- a/src/Create/CreateNetwork.cpp
+++ b/src/Create/CreateNetwork.cpp
@@ -15,7 +15,11 @@ CreateNetwork::CreateNetwork()
 {
 }
 
-void CreateNetwork::create(MainWindow &mw)
+void CreateNetwork::create(MainWindow &
+#ifdef NETWORKING
+                           mw
+#endif                           
+                           )
 {
   LOG4CPP_INFO_S ((*mainCat)) << "CreateNetwork::create";
   
diff --git a/src/Create/CreateSettingsDialogs.cpp b/src/Create/CreateSettingsDialogs.cpp
index da631a92..6ffe591b 100644
--- a/src/Create/CreateSettingsDialogs.cpp
+++ b/src/Create/CreateSettingsDialogs.cpp
@@ -8,7 +8,7 @@
 #include "DlgSettingsAxesChecker.h"
 #include "DlgSettingsColorFilter.h"
 #include "DlgSettingsCoords.h"
-#include "DlgSettingsCurveAddRemove.h"
+#include "DlgSettingsCurveList.h"
 #include "DlgSettingsCurveProperties.h"
 #include "DlgSettingsDigitizeCurve.h"
 #include "DlgSettingsExportFormat.h"
@@ -30,7 +30,7 @@ void CreateSettingsDialogs::create (MainWindow & mw)
   LOG4CPP_INFO_S ((*mainCat)) << "CreateSettingsDialogs::create";
 
   mw.m_dlgSettingsCoords = new DlgSettingsCoords (mw);
-  mw.m_dlgSettingsCurveAddRemove = new DlgSettingsCurveAddRemove (mw);
+  mw.m_dlgSettingsCurveList = new DlgSettingsCurveList (mw);
   mw.m_dlgSettingsCurveProperties = new DlgSettingsCurveProperties (mw);
   mw.m_dlgSettingsDigitizeCurve = new DlgSettingsDigitizeCurve (mw);
   mw.m_dlgSettingsExportFormat = new DlgSettingsExportFormat (mw);
@@ -44,7 +44,7 @@ void CreateSettingsDialogs::create (MainWindow & mw)
   mw.m_dlgSettingsMainWindow = new DlgSettingsMainWindow (mw);
 
   mw.m_dlgSettingsCoords->setVisible (false);
-  mw.m_dlgSettingsCurveAddRemove->setVisible (false);
+  mw.m_dlgSettingsCurveList->setVisible (false);
   mw.m_dlgSettingsCurveProperties->setVisible (false);
   mw.m_dlgSettingsDigitizeCurve->setVisible (false);
   mw.m_dlgSettingsExportFormat->setVisible (false);
diff --git a/src/Create/CreateToolBars.cpp b/src/Create/CreateToolBars.cpp
index b67e4ce3..469db599 100644
--- a/src/Create/CreateToolBars.cpp
+++ b/src/Create/CreateToolBars.cpp
@@ -8,7 +8,7 @@
 #include "DlgSettingsAxesChecker.h"
 #include "DlgSettingsColorFilter.h"
 #include "DlgSettingsCoords.h"
-#include "DlgSettingsCurveAddRemove.h"
+#include "DlgSettingsCurveList.h"
 #include "DlgSettingsCurveProperties.h"
 #include "DlgSettingsDigitizeCurve.h"
 #include "DlgSettingsExportFormat.h"
diff --git a/src/Curve/Curve.cpp b/src/Curve/Curve.cpp
index c81017e7..6ea60f47 100644
--- a/src/Curve/Curve.cpp
+++ b/src/Curve/Curve.cpp
@@ -15,6 +15,7 @@
 #include "PointComparator.h"
 #include <QDataStream>
 #include <QDebug>
+#include <qmath.h>
 #include <QMultiMap>
 #include <QTextStream>
 #include <QXmlStreamReader>
@@ -130,7 +131,7 @@ Curve &Curve::operator=(const Curve &curve)
   return *this;
 }
 
-void Curve::addPoint (Point point)
+void Curve::addPoint (const Point &point)
 {
   m_points.push_back (point);
 }
@@ -249,7 +250,7 @@ void Curve::exportToClipboard (const QHash<QString, bool> &selectedHash,
       curveStyleDefault.setPointStyle(PointStyle::defaultGraphCurve (curvesGraphs.numCurves ()));
 
       // Check if this curve already exists from a previously exported point
-      if (curvesGraphs.curveForCurveName (m_curveName) == 0) {
+      if (curvesGraphs.curveForCurveName (m_curveName) == nullptr) {
         Curve curve(m_curveName,
                     ColorFilterSettings::defaultFilter (),
                     curveStyleDefault);
@@ -289,7 +290,6 @@ bool Curve::isXOnly(const QString &pointIdentifier) const
     const Point &point = *itr;
     if (pointIdentifier == point.identifier ()) {
       return point.isXOnly();
-      break;
     }
   }
 
@@ -318,12 +318,12 @@ void Curve::iterateThroughCurveSegments (const Functor2wRet<const Point&, const
   // Loop through Points. They are assumed to be already sorted by their ordinals, but we do NOT
   // check the ordinal ordering since this could be called before, or while, the ordinal sorting is done
   QList<Point>::const_iterator itr;
-  const Point *pointBefore = 0;
+  const Point *pointBefore = nullptr;
   for (itr = m_points.begin(); itr != m_points.end(); itr++) {
 
     const Point &point = *itr;
 
-    if (pointBefore != 0) {
+    if (pointBefore != nullptr) {
 
       CallbackSearchReturn rtn = ftorWithCallback (*pointBefore,
                                                    point);
@@ -445,7 +445,7 @@ Point *Curve::pointForPointIdentifier (const QString pointIdentifier)
   }
 
   ENGAUGE_ASSERT (false);
-  return 0;
+  return nullptr;
 }
 
 const Points Curve::points () const
@@ -655,7 +655,7 @@ void Curve::updatePointOrdinalsFunctions (const Transformation &transformation)
     ENGAUGE_ASSERT (pointIdentifierToOrdinal.contains (point.identifier()));
 
     // Point is to be included since it is in the map list.
-    int ordinalNew = pointIdentifierToOrdinal [point.identifier()];
+    int ordinalNew = qFloor (pointIdentifierToOrdinal [point.identifier()]);
     point.setOrdinal (ordinalNew);
   }
 }
diff --git a/src/Curve/Curve.h b/src/Curve/Curve.h
index 977b41cc..fb77b71a 100644
--- a/src/Curve/Curve.h
+++ b/src/Curve/Curve.h
@@ -51,7 +51,7 @@ public:
   Curve &operator=(const Curve &curve);
 
   /// Add Point to this Curve.
-  void addPoint (Point point);
+  void addPoint (const Point &point);
 
   /// Return the color filter.
   ColorFilterSettings colorFilterSettings () const;
diff --git a/src/Curve/CurveConnectAs.cpp b/src/Curve/CurveConnectAs.cpp
index 10ac808e..f3de8b33 100644
--- a/src/Curve/CurveConnectAs.cpp
+++ b/src/Curve/CurveConnectAs.cpp
@@ -9,24 +9,30 @@
 
 QString curveConnectAsToString (CurveConnectAs curveConnectAs)
 {
+  QString rtn;
+
   switch (curveConnectAs) {
 
     case CONNECT_AS_FUNCTION_SMOOTH:
-      return QObject::tr ("FunctionSmooth");
+      rtn = QObject::tr ("FunctionSmooth");
+      break;
 
     case CONNECT_AS_FUNCTION_STRAIGHT:
-      return QObject::tr ("FunctionStraight");
+      rtn = QObject::tr ("FunctionStraight");
+      break;
 
     case CONNECT_AS_RELATION_SMOOTH:
-      return QObject::tr ("RelationSmooth");
+      rtn = QObject::tr ("RelationSmooth");
+      break;
 
     case CONNECT_AS_RELATION_STRAIGHT:
-      return QObject::tr ("RelationStraight");
+      rtn = QObject::tr ("RelationStraight");
+      break;
 
     case CONNECT_SKIP_FOR_AXIS_CURVE:
-      return QObject::tr ("ConnectSkipForAxisCurve");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("ConnectSkipForAxisCurve");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Curve/CurveNameList.cpp b/src/Curve/CurveNameList.cpp
index e4e7f32a..0661d5e8 100644
--- a/src/Curve/CurveNameList.cpp
+++ b/src/Curve/CurveNameList.cpp
@@ -179,7 +179,7 @@ unsigned int CurveNameList::numPointsForSelectedCurves (const QList<unsigned int
 {
   int numPoints = 0;
   for (int i = 0; i < rowsSelected.count(); i++) {
-    int row = rowsSelected [i];
+    int row = signed (rowsSelected [i]);
 
     QModelIndex idx = index (row, CURVE_NAME_LIST_COLUMN_CURRENT);
     QString currentCurve = data (idx).toString ();
@@ -193,7 +193,7 @@ unsigned int CurveNameList::numPointsForSelectedCurves (const QList<unsigned int
     }
   }
 
-  return numPoints;
+  return unsigned (numPoints);
 }
 
 bool CurveNameList::removeRows (int row,
diff --git a/src/Curve/CurveNameList.h b/src/Curve/CurveNameList.h
index 4e027de5..55404b44 100644
--- a/src/Curve/CurveNameList.h
+++ b/src/Curve/CurveNameList.h
@@ -22,7 +22,7 @@ enum CurveNameListColumns {
   NUMBER_CURVE_NAME_LIST_COLUMNS
 };
 
-/// Model for DlgSettingsCurveAddRemove and CmdSettingsCurveAddRemove. This is displayed as a QListView, with visible first column
+/// Model for DlgSettingsCurveList and CmdSettingsCurveList. This is displayed as a QListView, with visible first column
 /// showing current curve name. Second column is hidden with curve name at the start of editing, or empty if none.
 class CurveNameList : public QStandardItemModel
 {
diff --git a/src/Curve/CurveStyles.cpp b/src/Curve/CurveStyles.cpp
index 8e1a64be..44ea4e5f 100644
--- a/src/Curve/CurveStyles.cpp
+++ b/src/Curve/CurveStyles.cpp
@@ -102,7 +102,7 @@ const LineStyle CurveStyles::lineStyle (const QString &curveName) const
 int CurveStyles::lineWidth (const QString &curveName) const
 {
   ENGAUGE_ASSERT (m_curveStyles.contains (curveName));
-  return m_curveStyles [curveName].lineStyle().width();
+  return signed (m_curveStyles [curveName].lineStyle().width());
 }
 
 void CurveStyles::loadXml (QXmlStreamReader &reader)
diff --git a/src/Curve/CurvesGraphs.cpp b/src/Curve/CurvesGraphs.cpp
index 53995af1..03641d6d 100644
--- a/src/Curve/CurvesGraphs.cpp
+++ b/src/Curve/CurvesGraphs.cpp
@@ -21,7 +21,7 @@ CurvesGraphs::CurvesGraphs()
 {
 }
 
-void CurvesGraphs::addGraphCurveAtEnd (Curve curve)
+void CurvesGraphs::addGraphCurveAtEnd (const Curve &curve)
 {
   m_curvesGraphs.push_back (curve);
 }
@@ -46,7 +46,7 @@ Curve *CurvesGraphs::curveForCurveName (const QString &curveName)
     }
   }
 
-  return 0;
+  return nullptr;
 }
 
 const Curve *CurvesGraphs::curveForCurveName (const QString &curveName) const
@@ -61,7 +61,7 @@ const Curve *CurvesGraphs::curveForCurveName (const QString &curveName) const
     }
   }
 
-  return 0;
+  return nullptr;
 }
 
 QStringList CurvesGraphs::curvesGraphsNames () const
diff --git a/src/Curve/CurvesGraphs.h b/src/Curve/CurvesGraphs.h
index 786e4fb6..dbd2cf54 100644
--- a/src/Curve/CurvesGraphs.h
+++ b/src/Curve/CurvesGraphs.h
@@ -27,7 +27,7 @@ public:
   CurvesGraphs();
 
   /// Append new graph Curve to end of Curve list.
-  void addGraphCurveAtEnd (Curve curve);
+  void addGraphCurveAtEnd (const Curve &curve);
 
   /// Append new Point to the specified Curve.
   void addPoint (const Point &point);
diff --git a/src/DigitizeState/DigitizeStateAxis.cpp b/src/DigitizeState/DigitizeStateAxis.cpp
index 3bbc1dff..ac7fefdd 100644
--- a/src/DigitizeState/DigitizeStateAxis.cpp
+++ b/src/DigitizeState/DigitizeStateAxis.cpp
@@ -56,7 +56,7 @@ void DigitizeStateAxis::createTemporaryPoint (CmdMediator *cmdMediator,
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateAxis::createTemporaryPoint";
 
-  GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
+  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
 
   // Temporary point that user can see while DlgEditPointAxis is active
   const Curve &curveAxes = cmdMediator->curveAxes();
@@ -131,7 +131,7 @@ void DigitizeStateAxis::handleMouseRelease (CmdMediator *cmdMediator,
 
   if (context().mainWindow().transformIsDefined()) {
 
-    QMessageBox::warning (0,
+    QMessageBox::warning (nullptr,
                           QObject::tr ("Engauge Digitizer"),
                           QObject::tr ("Three axis points have been defined, and no more are needed or allowed."));
 
@@ -172,7 +172,7 @@ void DigitizeStateAxis::handleMouseRelease (CmdMediator *cmdMediator,
 
       if (isError) {
 
-        QMessageBox::warning (0,
+        QMessageBox::warning (nullptr,
                               QObject::tr ("Engauge Digitizer"),
                               errorMessage);
 
diff --git a/src/DigitizeState/DigitizeStateColorPicker.cpp b/src/DigitizeState/DigitizeStateColorPicker.cpp
index 063404ae..e93a47ba 100644
--- a/src/DigitizeState/DigitizeStateColorPicker.cpp
+++ b/src/DigitizeState/DigitizeStateColorPicker.cpp
@@ -18,6 +18,7 @@
 #include <QGraphicsPixmapItem>
 #include <QGraphicsScene>
 #include <QImage>
+#include <qmath.h>
 #include <QMessageBox>
 
 DigitizeStateColorPicker::DigitizeStateColorPicker (DigitizeStateContext &context) :
@@ -100,7 +101,7 @@ bool DigitizeStateColorPicker::computeFilterFromPixel (CmdMediator *cmdMediator,
     }
 
     // Generate histogram
-    double *histogramBins = new double [ColorFilterHistogram::HISTOGRAM_BINS ()];
+    double *histogramBins = new double [unsigned (ColorFilterHistogram::HISTOGRAM_BINS ())];
 
     ColorFilterHistogram filterHistogram;
     int maxBinCount;
@@ -147,7 +148,7 @@ bool DigitizeStateColorPicker::computeFilterFromPixel (CmdMediator *cmdMediator,
 
   } else {
 
-    QMessageBox::warning (0,
+    QMessageBox::warning (nullptr,
                           QObject::tr ("Color Picker"),
                           QObject::tr ("Sorry, but the color picker point must be near a non-background pixel. Please try again."));
 
@@ -292,9 +293,12 @@ void DigitizeStateColorPicker::handleMouseRelease (CmdMediator *cmdMediator,
 
 void DigitizeStateColorPicker::saveLowerValueUpperValue (DocumentModelColorFilter &modelColorFilterAfter,
                                                          const QString &curveName,
-                                                         double lowerValue,
-                                                         double upperValue)
+                                                         double lowerValueIn,
+                                                         double upperValueIn)
 {
+  int lowerValue = qFloor (lowerValueIn);
+  int upperValue = qFloor (upperValueIn);
+
   switch (modelColorFilterAfter.colorFilterMode (curveName)) {
     case COLOR_FILTER_MODE_FOREGROUND:
       modelColorFilterAfter.setForegroundLow(curveName,
diff --git a/src/DigitizeState/DigitizeStateContext.cpp b/src/DigitizeState/DigitizeStateContext.cpp
index 77550f95..718118ef 100644
--- a/src/DigitizeState/DigitizeStateContext.cpp
+++ b/src/DigitizeState/DigitizeStateContext.cpp
@@ -53,6 +53,7 @@ DigitizeStateContext::DigitizeStateContext(MainWindow &mainWindow,
 
 DigitizeStateContext::~DigitizeStateContext()
 {
+  qDeleteAll (m_states);
 }
 
 QString DigitizeStateContext::activeCurve () const
diff --git a/src/DigitizeState/DigitizeStatePointMatch.cpp b/src/DigitizeState/DigitizeStatePointMatch.cpp
index b1928a5d..d2052595 100644
--- a/src/DigitizeState/DigitizeStatePointMatch.cpp
+++ b/src/DigitizeState/DigitizeStatePointMatch.cpp
@@ -35,8 +35,8 @@ const double Z_VALUE = 200.0;
 
 DigitizeStatePointMatch::DigitizeStatePointMatch (DigitizeStateContext &context) :
   DigitizeStateAbstractBase (context),
-  m_outline (0),
-  m_candidatePoint (0)
+  m_outline (nullptr),
+  m_candidatePoint (nullptr)
 {
 }
 
@@ -98,7 +98,7 @@ void DigitizeStatePointMatch::createTemporaryPoint (CmdMediator *cmdMediator,
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::createTemporaryPoint";
 
-  GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
+  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
 
   const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
 
@@ -137,7 +137,7 @@ void DigitizeStatePointMatch::end ()
   // Remove outline before leaving state
   ENGAUGE_CHECK_PTR (m_outline);
   context().mainWindow().scene().removeItem (m_outline);
-  m_outline = 0;
+  m_outline = nullptr;
 }
 
 QList<PointMatchPixel> DigitizeStatePointMatch::extractSamplePointPixels (const QImage &img,
@@ -151,15 +151,15 @@ QList<PointMatchPixel> DigitizeStatePointMatch::extractSamplePointPixels (const
   // were happening (example, 3x3 point would appear to be found in several places inside 8x32 rectangle)
   QList<PointMatchPixel> samplePointPixels;
 
-  int radiusMax = modelPointMatch.maxPointSize() / 2;
+  int radiusMax = qFloor (modelPointMatch.maxPointSize() / 2);
 
   ColorFilter colorFilter;
   for (int xOffset = -radiusMax; xOffset <= radiusMax; xOffset++) {
     for (int yOffset = -radiusMax; yOffset <= radiusMax; yOffset++) {
 
-      int x = posScreen.x() + xOffset;
-      int y = posScreen.y() + yOffset;
-      int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
+      int x = qFloor (posScreen.x() + xOffset);
+      int y = qFloor (posScreen.y() + yOffset);
+      int radius = qFloor (qSqrt (xOffset * xOffset + yOffset * yOffset));
 
       if (radius <= radiusMax) {
 
@@ -230,8 +230,8 @@ void DigitizeStatePointMatch::handleMouseMove (CmdMediator *cmdMediator,
   const QImage &img = context().mainWindow().imageFiltered();
   int radiusLimit = cmdMediator->document().modelGeneral().cursorSize();
   bool pixelShouldBeOn = pixelIsOnInImage (img,
-                                           posScreen.x(),
-                                           posScreen.y(),
+                                           qFloor (posScreen.x()),
+                                           qFloor (posScreen.y()),
                                            radiusLimit);
 
   QColor penColorIs = m_outline->pen().color();
@@ -303,7 +303,7 @@ bool DigitizeStatePointMatch::pixelIsOnInImage (const QImage &img,
   for (int xOffset = -radiusLimit; xOffset <= radiusLimit; xOffset++) {
     for (int yOffset = -radiusLimit; yOffset <= radiusLimit; yOffset++) {
 
-      int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
+      int radius = qFloor (qSqrt (xOffset * xOffset + yOffset * yOffset));
 
       if (radius <= radiusLimit) {
 
@@ -346,7 +346,7 @@ void DigitizeStatePointMatch::popCandidatePoint (CmdMediator *cmdMediator)
   } else {
 
     // No more points. Inform user
-    QMessageBox::information (0,
+    QMessageBox::information (nullptr,
                               QObject::tr ("Point Match"),
                               QObject::tr ("There are no more matching points"));
 
diff --git a/src/DigitizeState/DigitizeStateScale.cpp b/src/DigitizeState/DigitizeStateScale.cpp
index 65ddc31b..89749b8c 100644
--- a/src/DigitizeState/DigitizeStateScale.cpp
+++ b/src/DigitizeState/DigitizeStateScale.cpp
@@ -26,9 +26,9 @@
 
 DigitizeStateScale::DigitizeStateScale (DigitizeStateContext &context) :
   DigitizeStateAbstractBase (context),
-  m_temporaryPoint0 (0),
-  m_temporaryPoint1 (0),
-  m_line (0)
+  m_temporaryPoint0 (nullptr),
+  m_temporaryPoint1 (nullptr),
+  m_line (nullptr)
 {
 }
 
@@ -102,7 +102,7 @@ void DigitizeStateScale::handleKeyPress (CmdMediator * /* cmdMediator */,
 void DigitizeStateScale::handleMouseMove (CmdMediator * /* cmdMediator */,
                                           QPointF posScreen)
 {
-  if (m_temporaryPoint1 != 0) {
+  if (m_temporaryPoint1 != nullptr) {
 
     LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateScale::handleMouseMove"
                                  << " oldPos=" << QPointFToString (m_temporaryPoint1->pos ()).toLatin1().data()
@@ -119,7 +119,7 @@ void DigitizeStateScale::handleMousePress (CmdMediator *cmdMediator,
 { 
   LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateScale::handleMousePress";
 
-  GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
+  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
 
   // Create the scale bar to give the user immediate feedback that something was created
   const Curve &curveAxes = cmdMediator->curveAxes();
@@ -169,7 +169,7 @@ void DigitizeStateScale::handleMouseRelease (CmdMediator *cmdMediator,
 
   if (context().mainWindow().transformIsDefined()) {
 
-    QMessageBox::warning (0,
+    QMessageBox::warning (nullptr,
                           QObject::tr ("Engauge Digitizer"),
                           QObject::tr ("The scale bar has been defined, and another is not needed or allowed."));
 
@@ -219,9 +219,9 @@ void DigitizeStateScale::removeTemporaryPointsAndLine ()
   context().mainWindow().scene().removePoint (m_pointIdentifier1); // Deallocates GraphicsPoint automaticall
   context().mainWindow().scene().removeItem (m_line);
   delete m_line;
-  m_temporaryPoint0 = 0;
-  m_temporaryPoint1 = 0;
-  m_line = 0;
+  m_temporaryPoint0 = nullptr;
+  m_temporaryPoint1 = nullptr;
+  m_line = nullptr;
 }
 
 QString DigitizeStateScale::state() const
diff --git a/src/DigitizeState/DigitizeStateSegment.cpp b/src/DigitizeState/DigitizeStateSegment.cpp
index 35cf6f85..7c611f95 100644
--- a/src/DigitizeState/DigitizeStateSegment.cpp
+++ b/src/DigitizeState/DigitizeStateSegment.cpp
@@ -8,6 +8,7 @@
 #include "DigitizeStateContext.h"
 #include "DigitizeStateSegment.h"
 #include "EngaugeAssert.h"
+#include "GraphicsScene.h"
 #include "Logger.h"
 #include "MainWindow.h"
 #include "OrdinalGenerator.h"
@@ -66,7 +67,7 @@ void DigitizeStateSegment::end ()
   LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSegment::end";
 
   GraphicsScene &scene = context().mainWindow().scene();
-  SegmentFactory segmentFactory ((QGraphicsScene &) scene,
+  SegmentFactory segmentFactory (dynamic_cast<QGraphicsScene &> (scene),
                                  context().isGnuplot());
 
   segmentFactory.clearSegments(m_segments);
@@ -93,7 +94,7 @@ void DigitizeStateSegment::handleCurveChange(CmdMediator *cmdMediator)
   QImage img = context().mainWindow().imageFiltered();
 
   GraphicsScene &scene = context().mainWindow().scene();
-  SegmentFactory segmentFactory ((QGraphicsScene &) scene,
+  SegmentFactory segmentFactory (dynamic_cast<QGraphicsScene &> (scene),
                                  context().isGnuplot());
 
   segmentFactory.clearSegments (m_segments);
@@ -158,7 +159,7 @@ Segment *DigitizeStateSegment::segmentFromSegmentStart (const QPointF &posSegmen
 
   LOG4CPP_ERROR_S ((*mainCat)) << "DigitizeStateSegment::segmentFromSegmentStart";
   ENGAUGE_ASSERT (false);
-  return 0;
+  return nullptr;
 }
 
 void DigitizeStateSegment::slotMouseClickOnSegment(QPointF posSegmentStart)
@@ -173,7 +174,7 @@ void DigitizeStateSegment::slotMouseClickOnSegment(QPointF posSegmentStart)
 
   // Generate point coordinates. Nothing is created in the GraphicsScene at this point
   GraphicsScene &scene = context().mainWindow().scene();
-  SegmentFactory segmentFactory ((QGraphicsScene &) scene,
+  SegmentFactory segmentFactory (dynamic_cast<QGraphicsScene &> (scene),
                                  context().isGnuplot());
 
   QList<QPoint> points = segmentFactory.fillPoints (m_cmdMediator->document().modelSegments(),
diff --git a/src/DigitizeState/DigitizeStateSelect.cpp b/src/DigitizeState/DigitizeStateSelect.cpp
index 127a4eb1..3e51d660 100644
--- a/src/DigitizeState/DigitizeStateSelect.cpp
+++ b/src/DigitizeState/DigitizeStateSelect.cpp
@@ -144,7 +144,7 @@ void DigitizeStateSelect::handleContextMenuEventAxis2 (CmdMediator *cmdMediator)
     bool isError;
     QString errorMessage;
 
-    bool isXNonzero = (posGraphBefore.x() != 0); // Identify which coordinate is to be edited
+    bool isXNonzero = (qAbs (posGraphBefore.x()) > 0); // Identify which coordinate is to be edited
     QPointF posGraphAfter (isXNonzero ? scaleLength : 0,
                            isXNonzero ? 0 : scaleLength);
     context().mainWindow().cmdMediator()->document().checkEditPointAxis(pointIdentifier,
@@ -155,7 +155,7 @@ void DigitizeStateSelect::handleContextMenuEventAxis2 (CmdMediator *cmdMediator)
 
     if (isError) {
 
-      QMessageBox::warning (0,
+      QMessageBox::warning (nullptr,
                             engaugeWindowTitle(),
                             errorMessage);
 
@@ -216,7 +216,7 @@ void DigitizeStateSelect::handleContextMenuEventAxis34 (CmdMediator *cmdMediator
 
     if (isError) {
 
-      QMessageBox::warning (0,
+      QMessageBox::warning (nullptr,
                             engaugeWindowTitle(),
                             errorMessage);
 
@@ -241,56 +241,62 @@ void DigitizeStateSelect::handleContextMenuEventGraph (CmdMediator *cmdMediator,
   LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateSelect::handleContextMenuEventGraph "
                               << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
 
-  double *x = 0, *y = 0;
+  // Editing graph coordinates before the axes are defined is not useful because:
+  // 1) That functionality is for fine tuning point placement based on defined axes
+  // 2) The transformation from screen to graph coordinates below will crash
+  if (context().mainWindow().transformation().transformIsDefined()) {
 
-  if (pointIdentifiers.count() == 1) {
+    double *x = nullptr, *y = nullptr;
 
-    // There is exactly one point so pass its coordinates to the dialog
-    x = new double;
-    y = new double;
+    if (pointIdentifiers.count() == 1) {
 
-    QPointF posScreenBefore = cmdMediator->document().positionScreen (pointIdentifiers.first());
-    QPointF posGraphBefore;
-    context().mainWindow().transformation().transformScreenToRawGraph (posScreenBefore,
-                                                                       posGraphBefore);
+      // There is exactly one point so pass its coordinates to the dialog
+      x = new double;
+      y = new double;
 
-    // Ask user for coordinates
-    *x = posGraphBefore.x();
-    *y = posGraphBefore.y();
-  }
+      QPointF posScreenBefore = cmdMediator->document().positionScreen (pointIdentifiers.first());
+      QPointF posGraphBefore;
+      context().mainWindow().transformation().transformScreenToRawGraph (posScreenBefore,
+                                                                         posGraphBefore);
 
-  DlgEditPointGraph *dlg = new DlgEditPointGraph (context().mainWindow(),
-                                                  cmdMediator->document().modelCoords(),
-                                                  cmdMediator->document().modelGeneral(),
-                                                  context().mainWindow().modelMainWindow(),
-                                                  context().mainWindow().transformation(),
-                                                  x,
-                                                  y);
-  delete x;
-  delete y;
+      // Ask user for coordinates
+      *x = posGraphBefore.x();
+      *y = posGraphBefore.y();
+    }
 
-  x = 0;
-  y = 0;
+    DlgEditPointGraph *dlg = new DlgEditPointGraph (context().mainWindow(),
+                                                    cmdMediator->document().modelCoords(),
+                                                    cmdMediator->document().modelGeneral(),
+                                                    context().mainWindow().modelMainWindow(),
+                                                    context().mainWindow().transformation(),
+                                                    x,
+                                                    y);
+    delete x;
+    delete y;
 
-  int rtn = dlg->exec ();
+    x = nullptr;
+    y = nullptr;
 
-  bool isXGiven, isYGiven;
-  double xGiven, yGiven;
-  dlg->posGraph (isXGiven, xGiven, isYGiven, yGiven); // One or both coordinates are returned
-  delete dlg;
+    int rtn = dlg->exec ();
 
-  if (rtn == QDialog::Accepted) {
+    bool isXGiven, isYGiven;
+    double xGiven, yGiven;
+    dlg->posGraph (isXGiven, xGiven, isYGiven, yGiven); // One or both coordinates are returned
+    delete dlg;
 
-    // Create a command to edit the point
-    CmdEditPointGraph *cmd = new CmdEditPointGraph (context().mainWindow(),
-                                                    cmdMediator->document(),
-                                                    pointIdentifiers,
-                                                    isXGiven,
-                                                    isYGiven,
-                                                    xGiven,
-                                                    yGiven);
-    context().appendNewCmd(cmdMediator,
-                           cmd);
+    if (rtn == QDialog::Accepted) {
+
+      // Create a command to edit the point
+      CmdEditPointGraph *cmd = new CmdEditPointGraph (context().mainWindow(),
+                                                      cmdMediator->document(),
+                                                      pointIdentifiers,
+                                                      isXGiven,
+                                                      isYGiven,
+                                                      xGiven,
+                                                      yGiven);
+      context().appendNewCmd(cmdMediator,
+                             cmd);
+    }
   }
 }
 
@@ -349,8 +355,8 @@ void DigitizeStateSelect::handleMouseRelease (CmdMediator *cmdMediator,
   bool positionHasChanged = (positionHasChangedIdentifers.count () > 0);
 
   if (positionHasChanged && (
-        deltaScreen.x () != 0 ||
-        deltaScreen.y () != 0)) {
+        qAbs (deltaScreen.x ()) > 0 ||
+        qAbs (deltaScreen.y ()) > 0)) {
 
     QString moveText = moveTextFromDeltaScreen (deltaScreen);
 
diff --git a/src/Dlg/DlgEditPointAxis.cpp b/src/Dlg/DlgEditPointAxis.cpp
index 14d41da4..90830bdc 100644
--- a/src/Dlg/DlgEditPointAxis.cpp
+++ b/src/Dlg/DlgEditPointAxis.cpp
@@ -23,6 +23,7 @@
 #include <QGroupBox>
 #include <QHBoxLayout>
 #include <QLabel>
+#include <QLineEdit>
 #include <QRect>
 #include "QtToString.h"
 #include <QVBoxLayout>
@@ -64,7 +65,8 @@ DlgEditPointAxis::DlgEditPointAxis (MainWindow &mainWindow,
   setWindowTitle (tr ("Edit Axis Point"));
 
   createCoords (layout);
-  createHint (layout);
+  createHints (layout,
+               documentAxesPointsRequired);
   createOkCancel (layout);
 
   initializeGraphCoordinates (xInitialValue,
@@ -132,7 +134,7 @@ void DlgEditPointAxis::createCoords (QVBoxLayout *layoutOuter)
   m_editGraphX->setValidator (m_validatorGraphX);
   // setStatusTip does not work for modal dialogs
   m_editGraphX->setWhatsThis (tr ("Enter the first graph coordinate of the axis point.\n\n"
-                                  "For cartesian plots this is X. For polar plots this is the radius R.\n\n"
+                                  "For cartesian plots this is X. For polar plots this is the angle Theta.\n\n"
                                   "The expected format of the coordinate value is determined by the locale setting. If "
                                   "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
   layout->addWidget(m_editGraphX, 0);
@@ -147,7 +149,7 @@ void DlgEditPointAxis::createCoords (QVBoxLayout *layoutOuter)
   m_editGraphY->setValidator (m_validatorGraphY);
   // setStatusTip does not work for modal dialogs
   m_editGraphY->setWhatsThis (tr ("Enter the second graph coordinate of the axis point.\n\n"
-                                  "For cartesian plots this is Y. For polar plots this is the angle Theta.\n\n"
+                                  "For cartesian plots this is Y. For polar plots this is the radius R.\n\n"
                                   "The expected format of the coordinate value is determined by the locale setting. If "
                                   "typed values are not recognized as expected, check the locale setting in Settings / Main Window..."));
   layout->addWidget(m_editGraphY, 0);
@@ -157,23 +159,47 @@ void DlgEditPointAxis::createCoords (QVBoxLayout *layoutOuter)
   layout->addWidget(labelGraphParRight, 0);
 }
 
-void DlgEditPointAxis::createHint (QVBoxLayout *layoutOuter)
+void DlgEditPointAxis::createHints (QVBoxLayout *layoutOuter,
+                                    DocumentAxesPointsRequired documentAxesPointsRequired)
 {
-  // Insert a hint explaining why decimal points may not be accepted. Very confusing for user to figure out the problem at first, and
-  // then figure out which setting should change to fix it. The hint is centered so it is slightly less intrusive
+  // Insert:
+  // 1) a hint to advertise that axes with only one coordinate can be handled
+  // 2) a hint explaining why decimal points may not be accepted. Very confusing for user to figure out the problem at first, and
+  //    then figure out which setting should change to fix it. The hint is centered so it is slightly less intrusive
+
+  const int MIN_EDIT_WIDTH = 180;
 
   QWidget *widget = new QWidget;
   layoutOuter->addWidget (widget, 0, Qt::AlignCenter);
 
-  QHBoxLayout *layout = new QHBoxLayout;
+  QGridLayout *layout = new QGridLayout;
   widget->setLayout (layout);
-
+  int row = 0;
+
+  // Hint 1
+  QLabel *labelNumberCoordinates = new QLabel (tr ("Number of coordinates per axis point:"));
+  layout->addWidget (labelNumberCoordinates, row, 0, 1, 1);
+  QLineEdit *editNumberCoordinates = new QLineEdit;
+  editNumberCoordinates->setWhatsThis (tr ("Three axis points with two coordinates each are normally used. "
+                                           "If each axis point has only one known coordinate, then start over "
+                                           "with File / Import (Advanced) / 4 Axis Points."));
+  editNumberCoordinates->setReadOnly (true);
+  editNumberCoordinates->setText (documentAxesPointsRequired == DOCUMENT_AXES_POINTS_REQUIRED_3 ?
+                                    "2" :
+                                    "1");
+  editNumberCoordinates->setMinimumWidth (MIN_EDIT_WIDTH);
+  layout->addWidget (editNumberCoordinates, row++, 1, 1, 1);
+
+  // Hint 2
+  QLabel *labelLocale = new QLabel (tr ("Number format:"));
+  layout->addWidget (labelLocale, row, 0, 1, 1);
+  QLineEdit *editLocale = new QLineEdit;
+  editLocale->setWhatsThis (tr ("Locale which determines the allowed number formats. This is set by Settings / Main Window."));
+  editLocale->setReadOnly (true);
   QString locale = QLocaleToString (m_modelMainWindow.locale ());
-  QString hint = QString ("%1: %2")
-                 .arg (tr ("Number format"))
-                 .arg (locale);
-  QLabel *label = new QLabel (hint);
-  layout->addWidget (label);
+  editLocale->setText (locale);
+  editLocale->setMinimumWidth (MIN_EDIT_WIDTH);
+  layout->addWidget (editLocale, row++, 1, 1, 1);
 }
 
 void DlgEditPointAxis::createOkCancel (QVBoxLayout *layoutOuter)
@@ -202,8 +228,8 @@ void DlgEditPointAxis::initializeGraphCoordinates (const double *xInitialValue,
   LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointAxis::initializeGraphCoordinates";
 
   QString xTheta, yRadius;
-  if ((xInitialValue != 0) &&
-      (yInitialValue != 0)) {
+  if ((xInitialValue != nullptr) &&
+      (yInitialValue != nullptr)) {
 
     FormatCoordsUnits format;
     format.unformattedToFormatted (*xInitialValue,
diff --git a/src/Dlg/DlgEditPointAxis.h b/src/Dlg/DlgEditPointAxis.h
index a6d41ffe..5a5f670c 100644
--- a/src/Dlg/DlgEditPointAxis.h
+++ b/src/Dlg/DlgEditPointAxis.h
@@ -8,15 +8,15 @@
 #define DLG_EDIT_POINT_AXIS_H
 
 #include "DocumentAxesPointsRequired.h"
+#include "DocumentModelCoords.h"
+#include "DocumentModelGeneral.h"
+#include "MainWindowModel.h"
 #include <QDialog>
 #include <QLineEdit>
 #include <QPushButton>
 
 class DlgValidatorAbstract;
-class DocumentModelCoords;
-class DocumentModelGeneral;
 class MainWindow;
-class MainWindowModel;
 class QVBoxLayout;
 class Transformation;
 
@@ -47,7 +47,8 @@ private slots:
 
 private:
   void createCoords (QVBoxLayout *layoutOuter);
-  void createHint (QVBoxLayout *layoutOuter);
+  void createHints (QVBoxLayout *layoutOuter,
+                    DocumentAxesPointsRequired documentAxesPointsRequired);
   void createOkCancel (QVBoxLayout *layoutOuter);
   void initializeGraphCoordinates (const double *xInitialValue,
                                    const double *yInitialValue,
@@ -69,9 +70,9 @@ private:
 
   DocumentAxesPointsRequired m_documentAxesPointsRequired;
 
-  const DocumentModelCoords &m_modelCoords;
-  const DocumentModelGeneral &m_modelGeneral;
-  const MainWindowModel &m_modelMainWindow;
+  const DocumentModelCoords m_modelCoords;
+  const DocumentModelGeneral m_modelGeneral;
+  const MainWindowModel m_modelMainWindow;
 };
 
 #endif // DLG_EDIT_POINT_AXIS_H
diff --git a/src/Dlg/DlgEditPointGraph.cpp b/src/Dlg/DlgEditPointGraph.cpp
index d2152b7a..8fe3dcaa 100644
--- a/src/Dlg/DlgEditPointGraph.cpp
+++ b/src/Dlg/DlgEditPointGraph.cpp
@@ -183,8 +183,8 @@ void DlgEditPointGraph::initializeGraphCoordinates (const double *xInitialValue,
   LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraph::initializeGraphCoordinates";
 
   QString xTheta, yRadius;
-  if ((xInitialValue != 0) &&
-      (yInitialValue != 0)) {
+  if ((xInitialValue != nullptr) &&
+      (yInitialValue != nullptr)) {
 
     FormatCoordsUnits format;
     format.unformattedToFormatted (*xInitialValue,
diff --git a/src/Dlg/DlgEditPointGraph.h b/src/Dlg/DlgEditPointGraph.h
index 359af040..c6c2a81a 100644
--- a/src/Dlg/DlgEditPointGraph.h
+++ b/src/Dlg/DlgEditPointGraph.h
@@ -7,16 +7,16 @@
 #ifndef DLG_EDIT_POINT_GRAPH_H
 #define DLG_EDIT_POINT_GRAPH_H
 
+#include "DocumentModelCoords.h"
+#include "DocumentModelGeneral.h"
+#include "MainWindowModel.h"
 #include <QDialog>
 #include <QPointF>
 #include <QString>
 
 class DlgEditPointGraphLineEdit;
 class DlgValidatorAbstract;
-class DocumentModelCoords;
-class DocumentModelGeneral;
 class MainWindow;
-class MainWindowModel;
 class QPushButton;
 class QVBoxLayout;
 class Transformation;
@@ -69,9 +69,9 @@ private:
   // Enable Ok button once text has changed. For simplicity, this is true even when original text is restored
   bool m_changed;
 
-  const DocumentModelCoords &m_modelCoords;
-  const DocumentModelGeneral &m_modelGeneral;
-  const MainWindowModel &m_modelMainWindow;
+  const DocumentModelCoords m_modelCoords;
+  const DocumentModelGeneral m_modelGeneral;
+  const MainWindowModel m_modelMainWindow;
 };
 
 #endif // DLG_EDIT_POINT_GRAPH_H
diff --git a/src/Dlg/DlgEditScale.cpp b/src/Dlg/DlgEditScale.cpp
index 29a10942..f1b2a153 100644
--- a/src/Dlg/DlgEditScale.cpp
+++ b/src/Dlg/DlgEditScale.cpp
@@ -126,7 +126,7 @@ void DlgEditScale::createScaleLength (QVBoxLayout *layoutOuter)
 
 void DlgEditScale::initializeScaleLength (const double *scaleLength)
 {
-  if (scaleLength != 0) {
+  if (scaleLength != nullptr) {
     m_editScaleLength->setText (QString::number (*scaleLength));
   }
 }
diff --git a/src/Dlg/DlgFilterThread.cpp b/src/Dlg/DlgFilterThread.cpp
index 6ad0779b..84f09c51 100644
--- a/src/Dlg/DlgFilterThread.cpp
+++ b/src/Dlg/DlgFilterThread.cpp
@@ -13,14 +13,14 @@ DlgFilterThread::DlgFilterThread(const QPixmap &pixmapOriginal,
   m_pixmapOriginal (pixmapOriginal),
   m_rgbBackground (rgbBackground),
   m_dlgSettingsColorFilter (dlgSettingsColorFilter),
-  m_dlgFilterWorker (0)
+  m_dlgFilterWorker (nullptr)
 {
 }
 
 void DlgFilterThread::run ()
 {
   // Create worker only once
-  if (m_dlgFilterWorker == 0) {
+  if (m_dlgFilterWorker == nullptr) {
 
     m_dlgFilterWorker = new DlgFilterWorker (m_pixmapOriginal,
                                              m_rgbBackground);
diff --git a/src/Dlg/DlgImportAdvanced.cpp b/src/Dlg/DlgImportAdvanced.cpp
index b4f8fb15..8208457f 100644
--- a/src/Dlg/DlgImportAdvanced.cpp
+++ b/src/Dlg/DlgImportAdvanced.cpp
@@ -121,7 +121,7 @@ void DlgImportAdvanced::load(CmdMediator & /* cmdMediator */)
 
 unsigned int DlgImportAdvanced::numberCoordSystem () const
 {
-  return m_spinCoordSystemCount->value ();
+  return unsigned (m_spinCoordSystemCount->value ());
 }
 
 void DlgImportAdvanced::setSmallDialogs(bool /* smallDialogs */)
diff --git a/src/Dlg/DlgImportCroppingNonPdf.cpp b/src/Dlg/DlgImportCroppingNonPdf.cpp
index d2d913ad..232dab7b 100644
--- a/src/Dlg/DlgImportCroppingNonPdf.cpp
+++ b/src/Dlg/DlgImportCroppingNonPdf.cpp
@@ -27,7 +27,8 @@ int DlgImportCroppingNonPdf::MINIMUM_PREVIEW_HEIGHT = 200;
 
 DlgImportCroppingNonPdf::DlgImportCroppingNonPdf(const QString &fileName) :
   m_fileName (fileName),
-  m_pixmap (0)
+  m_pixmap (nullptr),
+  m_nonPdfCropping (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::DlgImportCroppingNonPdf";
 
@@ -54,6 +55,8 @@ DlgImportCroppingNonPdf::DlgImportCroppingNonPdf(const QString &fileName) :
 DlgImportCroppingNonPdf::~DlgImportCroppingNonPdf()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::~DlgImportCroppingNonPdf";
+
+  delete m_nonPdfCropping;
 }
 
 void DlgImportCroppingNonPdf::createNonPdfCropping ()
@@ -131,7 +134,7 @@ QImage DlgImportCroppingNonPdf::image () const
 {
   // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
   // portion is to be returned
-  ENGAUGE_ASSERT (m_nonPdfCropping != 0);
+  ENGAUGE_CHECK_PTR (m_nonPdfCropping);
   QRectF rectFramePixels = m_nonPdfCropping->frameRect ();
 
   return m_image.copy (rectFramePixels.toRect ());
@@ -158,7 +161,7 @@ QImage DlgImportCroppingNonPdf::loadImage () const
 void DlgImportCroppingNonPdf::saveGeometryToSettings()
 {
   // Store the settings for use by showEvent
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
   settings.setValue (SETTINGS_IMPORT_CROPPING_POS, saveGeometry ());
   settings.endGroup();
@@ -166,13 +169,14 @@ void DlgImportCroppingNonPdf::saveGeometryToSettings()
 
 void DlgImportCroppingNonPdf::showEvent (QShowEvent * /* event */)
 {
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
   if (settings.contains (SETTINGS_IMPORT_CROPPING_POS)) {
 
     // Restore the settings that were stored by the last call to saveGeometryToSettings
     restoreGeometry (settings.value (SETTINGS_IMPORT_CROPPING_POS).toByteArray ());
   }
+  settings.endGroup ();
 }
 
 void DlgImportCroppingNonPdf::slotCancel ()
@@ -203,7 +207,7 @@ void DlgImportCroppingNonPdf::updatePreview ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingNonPdf::updatePreview";
 
-  if (m_pixmap != 0) {
+  if (m_pixmap != nullptr) {
     m_scenePreview->removeItem (m_pixmap);
   }
 
diff --git a/src/Dlg/DlgImportCroppingPdf.cpp b/src/Dlg/DlgImportCroppingPdf.cpp
index 0c478105..8b042b18 100644
--- a/src/Dlg/DlgImportCroppingPdf.cpp
+++ b/src/Dlg/DlgImportCroppingPdf.cpp
@@ -13,6 +13,7 @@
 #include <QApplication>
 #include <QGraphicsPixmapItem>
 #include <QGraphicsScene>
+#include <QGridLayout>
 #include <QImage>
 #include <QLabel>
 #include <QLayout>
@@ -36,7 +37,7 @@ DlgImportCroppingPdf::DlgImportCroppingPdf(const Poppler::Document &document,
                                            int resolution) :
   m_document (document),
   m_resolution (resolution),
-  m_pixmap (0)
+  m_pixmap (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::DlgImportCroppingPdf";
 
@@ -167,7 +168,7 @@ QImage DlgImportCroppingPdf::image () const
 {
   // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
   // portion is to be returned
-  ENGAUGE_ASSERT (m_pdfCropping != 0);
+  ENGAUGE_ASSERT (m_pdfCropping != nullptr);
   QRectF rectFramePixels = m_pdfCropping->frameRect ();
 
   return m_image.copy (rectFramePixels.toRect ());
@@ -189,7 +190,7 @@ QImage DlgImportCroppingPdf::loadImage (int page1Based) const
 
   int page0Based = page1Based - 1;
   Page *page = m_document.page (page0Based);
-  if (page != 0) {
+  if (page != nullptr) {
 
     image = page->renderToImage (m_resolution,
                                  m_resolution,
@@ -207,7 +208,7 @@ QImage DlgImportCroppingPdf::loadImage (int page1Based) const
 void DlgImportCroppingPdf::saveGeometryToSettings()
 {
   // Store the settings for use by showEvent
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
   settings.setValue (SETTINGS_IMPORT_CROPPING_POS, saveGeometry ());
   settings.endGroup();
@@ -215,13 +216,14 @@ void DlgImportCroppingPdf::saveGeometryToSettings()
 
 void DlgImportCroppingPdf::showEvent (QShowEvent * /* event */)
 {
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
   if (settings.contains (SETTINGS_IMPORT_CROPPING_POS)) {
 
     // Restore the settings that were stored by the last call to saveGeometryToSettings
     restoreGeometry (settings.value (SETTINGS_IMPORT_CROPPING_POS).toByteArray ());
   }
+  settings.endGroup ();
 }
 
 void DlgImportCroppingPdf::slotCancel ()
@@ -271,7 +273,7 @@ void DlgImportCroppingPdf::updatePreview ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::updatePreview";
 
-  if (m_pixmap != 0) {
+  if (m_pixmap != nullptr) {
     m_scenePreview->removeItem (m_pixmap);
   }
 
diff --git a/src/Dlg/DlgSettingsAbstractBase.cpp b/src/Dlg/DlgSettingsAbstractBase.cpp
index 4047eedf..58a1fa56 100644
--- a/src/Dlg/DlgSettingsAbstractBase.cpp
+++ b/src/Dlg/DlgSettingsAbstractBase.cpp
@@ -16,6 +16,7 @@
 #include <QSettings>
 #include <QSpacerItem>
 #include <QVBoxLayout>
+#include "Settings.h"
 
 int DlgSettingsAbstractBase::MINIMUM_DIALOG_WIDTH = 380; // May be overridden by subclass
 int DlgSettingsAbstractBase::MINIMUM_PREVIEW_HEIGHT = 100;
@@ -25,7 +26,7 @@ DlgSettingsAbstractBase::DlgSettingsAbstractBase(const QString &title,
                                                  MainWindow &mainWindow) :
   QDialog (&mainWindow),
   m_mainWindow (mainWindow),
-  m_cmdMediator (0),
+  m_cmdMediator (nullptr),
   m_dialogName (dialogName),
   m_disableOkAtStartup (true)
 {
@@ -158,7 +159,7 @@ void DlgSettingsAbstractBase::populateColorComboWithTransparent (QComboBox &comb
 void DlgSettingsAbstractBase::saveGeometryToSettings()
 {
   // Store the settings for use by showEvent
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.setValue (m_dialogName, saveGeometry ());
 }
 
@@ -172,13 +173,18 @@ void DlgSettingsAbstractBase::setDisableOkAtStartup(bool disableOkAtStartup)
   m_disableOkAtStartup = disableOkAtStartup;
 }
 
+void DlgSettingsAbstractBase::hideEvent (QHideEvent * /* event */)
+{
+  saveGeometryToSettings();
+}
+
 void DlgSettingsAbstractBase::showEvent (QShowEvent * /* event */)
 {
   if (m_disableOkAtStartup) {
     m_btnOk->setEnabled (false);
   }
 
-  QSettings settings;
+  QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   if (settings.contains (m_dialogName)) {
 
     // Restore the settings that were stored by the last call to saveGeometryToSettings
@@ -190,7 +196,6 @@ void DlgSettingsAbstractBase::slotCancel ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAbstractBase::slotCancel";
 
-  saveGeometryToSettings();
   hide();
 }
 
@@ -198,8 +203,6 @@ void DlgSettingsAbstractBase::slotOk ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAbstractBase::slotOk";
 
-  saveGeometryToSettings();
-
   // Forward to leaf class
   handleOk ();
 }
diff --git a/src/Dlg/DlgSettingsAbstractBase.h b/src/Dlg/DlgSettingsAbstractBase.h
index 488acb78..de47b21d 100644
--- a/src/Dlg/DlgSettingsAbstractBase.h
+++ b/src/Dlg/DlgSettingsAbstractBase.h
@@ -99,6 +99,9 @@ private:
 
   void saveGeometryToSettings ();
   
+  /// Do shutdown when dialog disappears
+  virtual void hideEvent (QHideEvent *event);
+
   /// Do preparation before dialog is displayed.
   virtual void showEvent (QShowEvent *event);
 
diff --git a/src/Dlg/DlgSettingsAxesChecker.cpp b/src/Dlg/DlgSettingsAxesChecker.cpp
index 7670aaa6..90c04618 100644
--- a/src/Dlg/DlgSettingsAxesChecker.cpp
+++ b/src/Dlg/DlgSettingsAxesChecker.cpp
@@ -39,10 +39,10 @@ DlgSettingsAxesChecker::DlgSettingsAxesChecker(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Axes Checker"),
                            "DlgSettingsAxesChecker",
                            mainWindow),
-  m_checker (0),
-  m_modelAxesCheckerBefore (0),
-  m_modelAxesCheckerAfter (0),
-  m_modelCoords (0)
+  m_checker (nullptr),
+  m_modelAxesCheckerBefore (nullptr),
+  m_modelAxesCheckerAfter (nullptr),
+  m_modelCoords (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::DlgSettingsAxesChecker";
 
@@ -53,6 +53,8 @@ DlgSettingsAxesChecker::DlgSettingsAxesChecker(MainWindow &mainWindow) :
 DlgSettingsAxesChecker::~DlgSettingsAxesChecker()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::~DlgSettingsAxesChecker";
+
+  delete m_checker;
 }
 
 void DlgSettingsAxesChecker::createControls (QGridLayout *layout,
@@ -261,7 +263,7 @@ void DlgSettingsAxesChecker::slotLineColor(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotLineColor";
 
-  m_modelAxesCheckerAfter->setLineColor ((ColorPalette) m_cmbLineColor->currentData().toInt());
+  m_modelAxesCheckerAfter->setLineColor (static_cast<ColorPalette> (m_cmbLineColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
@@ -292,7 +294,7 @@ void DlgSettingsAxesChecker::updatePreview()
 
   QPolygonF polygon (points);
 
-  ENGAUGE_ASSERT (m_checker != 0);
+  ENGAUGE_CHECK_PTR (m_checker);
   m_checker->prepareForDisplay (polygon,
                                 ZERO_RADIUS_SINCE_NO_POINTS,
                                 *m_modelAxesCheckerAfter,
diff --git a/src/Dlg/DlgSettingsColorFilter.cpp b/src/Dlg/DlgSettingsColorFilter.cpp
index d55cf135..310ee0b4 100644
--- a/src/Dlg/DlgSettingsColorFilter.cpp
+++ b/src/Dlg/DlgSettingsColorFilter.cpp
@@ -37,11 +37,11 @@ DlgSettingsColorFilter::DlgSettingsColorFilter(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Color Filter"),
                            "DlgSettingsColorFilter",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_filterThread (0),
-  m_modelColorFilterBefore (0),
-  m_modelColorFilterAfter (0)
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_filterThread (nullptr),
+  m_modelColorFilterBefore (nullptr),
+  m_modelColorFilterAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::DlgSettingsColorFilter";
 
@@ -53,6 +53,8 @@ DlgSettingsColorFilter::DlgSettingsColorFilter(MainWindow &mainWindow) :
 DlgSettingsColorFilter::~DlgSettingsColorFilter()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::~DlgSettingsColorFilter";
+
+  delete m_filterThread;
 }
 
 void DlgSettingsColorFilter::createControls (QGridLayout *layout, int &row)
@@ -201,7 +203,7 @@ QRgb DlgSettingsColorFilter::createThread ()
   QRgb rgbBackground = filter.marginColor(&image);
 
   // Only create thread once
-  if (m_filterThread == 0) {
+  if (m_filterThread == nullptr) {
 
     m_filterThread = new DlgFilterThread (cmdMediator().document().pixmap(),
                                           rgbBackground,
@@ -265,7 +267,7 @@ void DlgSettingsColorFilter::loadForCurveName()
   QString curveName = m_cmbCurveName->currentText();
 
   // Skip if everything is not set up yet
-  if (!curveName.isEmpty () && m_modelColorFilterAfter != 0) {
+  if (!curveName.isEmpty () && m_modelColorFilterAfter != nullptr) {
 
     // Populate controls
     ColorFilterMode colorFilterMode = m_modelColorFilterAfter->colorFilterMode(curveName);
@@ -304,14 +306,14 @@ void DlgSettingsColorFilter::slotCurveName(const QString & /* curveName */)
 void DlgSettingsColorFilter::slotDividerHigh (double xCenter)
 {
   m_modelColorFilterAfter->setHigh (m_cmbCurveName->currentText(),
-                                    xCenter / (double) PROFILE_SCENE_WIDTH ());
+                                    xCenter / double (PROFILE_SCENE_WIDTH ()));
   updatePreview();
 }
 
 void DlgSettingsColorFilter::slotDividerLow (double xCenter)
 {
   m_modelColorFilterAfter->setLow (m_cmbCurveName->currentText(),
-                                   xCenter / (double) PROFILE_SCENE_WIDTH ());
+                                   xCenter / double (PROFILE_SCENE_WIDTH ()));
   updatePreview();
 }
 
@@ -407,7 +409,7 @@ void DlgSettingsColorFilter::updateHistogram()
   // Start with original image
   QImage image = cmdMediator().document().pixmap().toImage();
 
-  double *histogramBins = new double [ColorFilterHistogram::HISTOGRAM_BINS ()];
+  double *histogramBins = new double [unsigned (ColorFilterHistogram::HISTOGRAM_BINS ())];
 
   ColorFilter filter;
   ColorFilterHistogram filterHistogram;
@@ -421,7 +423,7 @@ void DlgSettingsColorFilter::updateHistogram()
   // Draw histogram, normalizing so highest peak exactly fills the vertical range. Log scale is used
   // so smaller peaks do not disappear
   double logMaxBinCount = qLn (maxBinCount);
-  if (logMaxBinCount != 0) { // Will not have divide by zero from logMaxBinCount below
+  if (qAbs (logMaxBinCount) > 0) { // Will not have divide by zero from logMaxBinCount below
     for (int bin = 1; bin < ColorFilterHistogram::HISTOGRAM_BINS (); bin++) {
 
       double x0 = PROFILE_SCENE_WIDTH () * (bin - 1.0) / (ColorFilterHistogram::HISTOGRAM_BINS () - 1.0);
@@ -447,13 +449,13 @@ void DlgSettingsColorFilter::updateHistogram()
                                         *m_viewProfile,
                                         PROFILE_SCENE_WIDTH (),
                                         PROFILE_SCENE_HEIGHT (),
-                                        PROFILE_SCENE_HEIGHT () * 2.0 / 3.0,
+                                        qFloor (PROFILE_SCENE_HEIGHT () * 2.0 / 3.0),
                                         true);
   m_dividerHigh = new ViewProfileDivider(*m_sceneProfile,
                                          *m_viewProfile,
                                          PROFILE_SCENE_HEIGHT (),
                                          PROFILE_SCENE_WIDTH (),
-                                         PROFILE_SCENE_HEIGHT () / 3.0,
+                                         qFloor (PROFILE_SCENE_HEIGHT () / 3.0),
                                          false);
 
   // Connect the dividers to each other since the shaded areas depend on both divides when low divider is
@@ -501,7 +503,7 @@ void DlgSettingsColorFilter::updateHistogram()
 
   }
 
-  free (histogramBins);
+  delete[] histogramBins;
 }
 
 void DlgSettingsColorFilter::updatePreview ()
diff --git a/src/Dlg/DlgSettingsCoords.cpp b/src/Dlg/DlgSettingsCoords.cpp
index c5931668..2ff64510 100644
--- a/src/Dlg/DlgSettingsCoords.cpp
+++ b/src/Dlg/DlgSettingsCoords.cpp
@@ -26,6 +26,7 @@
 #include <QGraphicsScene>
 #include <QLabel>
 #include <QLineEdit>
+#include <qmath.h>
 #include <QPalette>
 #include <QRadioButton>
 #include <QStackedWidget>
@@ -75,15 +76,15 @@ DlgSettingsCoords::DlgSettingsCoords(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Coordinates"),
                            "DlgSettingsCoords",
                            mainWindow),
-  m_btnCartesian (0),
-  m_btnPolar (0),
-  m_validatorOriginRadius (0),
-  m_cmbDate (0),
-  m_cmbTime (0),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelCoordsBefore (0),
-  m_modelCoordsAfter (0)
+  m_btnCartesian (nullptr),
+  m_btnPolar (nullptr),
+  m_validatorOriginRadius (nullptr),
+  m_cmbDate (nullptr),
+  m_cmbTime (nullptr),
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelCoordsBefore (nullptr),
+  m_modelCoordsAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::DlgSettingsCoords";
 
@@ -103,7 +104,7 @@ void DlgSettingsCoords::annotateAngles (const QFont &defaultFont) {
   for (int direction = 0; direction < 4; direction++) {
 
     QString angle;
-    CoordUnitsPolarTheta thetaUnits = (CoordUnitsPolarTheta) m_cmbXThetaUnits->currentData().toInt();
+    CoordUnitsPolarTheta thetaUnits = static_cast<CoordUnitsPolarTheta> (m_cmbXThetaUnits->currentData().toInt());
 
     switch (thetaUnits) {
       case COORD_UNITS_POLAR_THETA_DEGREES:
@@ -185,10 +186,13 @@ void DlgSettingsCoords::annotateRadiusAtOrigin(const QFont &defaultFont) {
                       YCENTER);
 }
 
-QRectF DlgSettingsCoords::boundingRectGraph (CmdMediator &cmdMediator,
-                                             bool &isEmpty) const
+void DlgSettingsCoords::boundingRectGraph (CmdMediator &cmdMediator,
+                                           bool &isEmpty,
+                                           QPointF &boundingRectGraphMin,
+                                           QPointF &boundingRectGraphMax) const
 {
-  CallbackBoundingRects ftor (mainWindow().transformation());
+  CallbackBoundingRects ftor (cmdMediator.document().documentAxesPointsRequired(),
+                              mainWindow().transformation());
 
   Functor2wRet<const QString &, const Point&, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
                                                                                                     &CallbackBoundingRects::callback);
@@ -203,7 +207,8 @@ QRectF DlgSettingsCoords::boundingRectGraph (CmdMediator &cmdMediator,
     cmdMediator.iterateThroughCurvesPointsGraphs (ftorWithCallback);
   }
 
-  return ftor.boundingRectGraph(isEmpty);
+  boundingRectGraphMin = ftor.boundingRectGraphMin (isEmpty);
+  boundingRectGraphMax = ftor.boundingRectGraphMax (isEmpty);
 }
 
 void DlgSettingsCoords::createDateTime (QGridLayout *layout,
@@ -557,10 +562,13 @@ void DlgSettingsCoords::load (CmdMediator &cmdMediator)
 
   // Remove if coordinates are log so later constraints can be applied
   bool isEmpty;
-  QRectF rectGraph = boundingRectGraph (cmdMediator,
-                                        isEmpty);
-  bool xThetaGoesNegative = !isEmpty && (rectGraph.x() <= 0);
-  bool yRGoesNegative = !isEmpty && (rectGraph.y() <= 0);
+  QPointF boundingRectGraphMin, boundingRectGraphMax;
+  boundingRectGraph (cmdMediator,
+                     isEmpty,
+                     boundingRectGraphMin,
+                     boundingRectGraphMax);
+  bool xThetaGoesNegative = !isEmpty && (boundingRectGraphMin.x() <= 0);
+  bool yRGoesNegative = !isEmpty && (boundingRectGraphMin.y() <= 0);
   m_xThetaLinear->setEnabled (!xThetaGoesNegative);
   m_xThetaLog->setEnabled (!xThetaGoesNegative);
   m_yRadiusLinear->setEnabled (!yRGoesNegative);
@@ -710,10 +718,10 @@ void DlgSettingsCoords::loadComboBoxUnitsPolar (QComboBox &cmb,
 
 void DlgSettingsCoords::resetSceneRectangle ()
 {
-  QRect rect (CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
-              CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0,
-              CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP,
-              CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP);
+  QRect rect (qFloor (CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0),
+              qFloor (CARTESIAN_COORD_MIN - CARTESIAN_COORD_STEP / 2.0),
+              qFloor (CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP),
+              qFloor (CARTESIAN_COORD_MAX - CARTESIAN_COORD_MIN + CARTESIAN_COORD_STEP));
 
   QGraphicsRectItem *itemPerimeter = new QGraphicsRectItem(rect);
   itemPerimeter->setVisible(false);
@@ -746,7 +754,7 @@ void DlgSettingsCoords::slotDate(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotDate";
 
-  CoordUnitsDate coordUnits = (CoordUnitsDate) m_cmbDate->currentData ().toInt();
+  CoordUnitsDate coordUnits = static_cast<CoordUnitsDate> (m_cmbDate->currentData ().toInt());
   m_modelCoordsAfter->setCoordUnitsDate(coordUnits);
   updateControls();
   updatePreview();
@@ -767,7 +775,7 @@ void DlgSettingsCoords::slotTime(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotTime";
 
-  CoordUnitsTime coordUnits = (CoordUnitsTime) m_cmbTime->currentData ().toInt();
+  CoordUnitsTime coordUnits = static_cast<CoordUnitsTime> (m_cmbTime->currentData ().toInt());
   m_modelCoordsAfter->setCoordUnitsTime(coordUnits);
   updateControls();
   updatePreview();
@@ -778,10 +786,10 @@ void DlgSettingsCoords::slotUnitsXTheta(const QString &)
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsXTheta";
 
   if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
-    CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
+    CoordUnitsNonPolarTheta coordUnits = static_cast<CoordUnitsNonPolarTheta> (m_cmbXThetaUnits->currentData ().toInt ());
     m_modelCoordsAfter->setCoordUnitsX(coordUnits);
   } else {
-    CoordUnitsPolarTheta coordUnits = (CoordUnitsPolarTheta) m_cmbXThetaUnits->currentData ().toInt ();
+    CoordUnitsPolarTheta coordUnits = static_cast<CoordUnitsPolarTheta> (m_cmbXThetaUnits->currentData ().toInt ());
     m_modelCoordsAfter->setCoordUnitsTheta(coordUnits);
   }
   updateControls ();
@@ -792,7 +800,7 @@ void DlgSettingsCoords::slotUnitsYRadius(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCoords::slotUnitsYRadius";
 
-  CoordUnitsNonPolarTheta coordUnits = (CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt ();
+  CoordUnitsNonPolarTheta coordUnits = static_cast<CoordUnitsNonPolarTheta> (m_cmbYRadiusUnits->currentData ().toInt ());
   if (m_modelCoordsAfter->coordsType() == COORDS_TYPE_CARTESIAN) {
     m_modelCoordsAfter->setCoordUnitsY(coordUnits);
   } else {
@@ -920,10 +928,10 @@ void DlgSettingsCoords::updateControls ()
 
   bool enableDateTime;
   if (m_btnCartesian->isChecked()) {
-    enableDateTime = (((CoordUnitsNonPolarTheta) m_cmbXThetaUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME) ||
-                      ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
+    enableDateTime = ((static_cast<CoordUnitsNonPolarTheta> (m_cmbXThetaUnits->currentData ().toInt()) == COORD_UNITS_NON_POLAR_THETA_DATE_TIME) ||
+                      (static_cast<CoordUnitsNonPolarTheta> (m_cmbYRadiusUnits->currentData ().toInt()) == COORD_UNITS_NON_POLAR_THETA_DATE_TIME));
   } else {
-    enableDateTime = ((CoordUnitsNonPolarTheta) m_cmbYRadiusUnits->currentData ().toInt() == COORD_UNITS_NON_POLAR_THETA_DATE_TIME);
+    enableDateTime = (static_cast<CoordUnitsNonPolarTheta> (m_cmbYRadiusUnits->currentData ().toInt()) == COORD_UNITS_NON_POLAR_THETA_DATE_TIME);
   }
   m_cmbDate->setEnabled (enableDateTime);
   m_cmbTime->setEnabled (enableDateTime);
diff --git a/src/Dlg/DlgSettingsCoords.h b/src/Dlg/DlgSettingsCoords.h
index 58cadfe5..3a7a42b9 100644
--- a/src/Dlg/DlgSettingsCoords.h
+++ b/src/Dlg/DlgSettingsCoords.h
@@ -57,8 +57,10 @@ private:
 
   void annotateAngles(const QFont &defaultFont);
   void annotateRadiusAtOrigin(const QFont &defaultFont);
-  QRectF boundingRectGraph (CmdMediator &cmdMediator,
-                            bool &isEmpty) const;
+  void boundingRectGraph (CmdMediator &cmdMediator,
+                          bool &isEmpty,
+                          QPointF &boundingRectGraphMin,
+                          QPointF &boundingRectGraphMax) const;
   void createDateTime(QGridLayout *layout,
                       int &row);
   void createGroupCoordsType(QGridLayout *layout,
diff --git a/src/Dlg/DlgSettingsCurveAddRemove.cpp b/src/Dlg/DlgSettingsCurveList.cpp
similarity index 78%
rename from src/Dlg/DlgSettingsCurveAddRemove.cpp
rename to src/Dlg/DlgSettingsCurveList.cpp
index 3a31d9c3..36403940 100644
--- a/src/Dlg/DlgSettingsCurveAddRemove.cpp
+++ b/src/Dlg/DlgSettingsCurveList.cpp
@@ -5,9 +5,9 @@
  ******************************************************************************************************/
 
 #include "CmdMediator.h"
-#include "CmdSettingsCurveAddRemove.h"
+#include "CmdSettingsCurveList.h"
 #include "CurveNameList.h"
-#include "DlgSettingsCurveAddRemove.h"
+#include "DlgSettingsCurveList.h"
 #include "EngaugeAssert.h"
 #include "Logger.h"
 #include "MainWindow.h"
@@ -28,28 +28,28 @@
 
 const int MINIMUM_HEIGHT = 500;
 
-DlgSettingsCurveAddRemove::DlgSettingsCurveAddRemove(MainWindow &mainWindow) :
+DlgSettingsCurveList::DlgSettingsCurveList(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Curve List"),
-                           "DlgSettingsCurveAddRemove",
+                           "DlgSettingsCurveList",
                            mainWindow),
-  m_curveNameList (0)
+  m_curveNameList (nullptr)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::DlgSettingsCurveAddRemove";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::DlgSettingsCurveList";
 
   QWidget *subPanel = createSubPanel ();
   finishPanel (subPanel);
 }
 
-DlgSettingsCurveAddRemove::~DlgSettingsCurveAddRemove()
+DlgSettingsCurveList::~DlgSettingsCurveList()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::~DlgSettingsCurveAddRemove";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::~DlgSettingsCurveList";
 }
 
-void DlgSettingsCurveAddRemove::appendCurveName (const QString &curveNameNew,
-                                                 const QString &curveNameOriginal,
-                                                 int numPoints)
+void DlgSettingsCurveList::appendCurveName (const QString &curveNameNew,
+                                            const QString &curveNameOriginal,
+                                            int numPoints)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::appendCurveName"
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::appendCurveName"
                               << " curve=" << curveNameNew.toLatin1().data();
 
   ENGAUGE_CHECK_PTR (m_curveNameList);
@@ -61,10 +61,10 @@ void DlgSettingsCurveAddRemove::appendCurveName (const QString &curveNameNew,
                    numPoints);
 }
 
-void DlgSettingsCurveAddRemove::createButtons (QGridLayout *layout,
-                                               int &row)
+void DlgSettingsCurveList::createButtons (QGridLayout *layout,
+                                          int &row)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::createButtons";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::createButtons";
 
   m_btnAdd = new QPushButton (tr ("Add..."));
   m_btnAdd->setWhatsThis (tr ("Adds a new curve to the curve list. The curve name can be edited in the curve name list.\n\n"
@@ -81,10 +81,10 @@ void DlgSettingsCurveAddRemove::createButtons (QGridLayout *layout,
   layout->addWidget (m_btnRemove, row++, 2, 1, 1, Qt::AlignRight);
 }
 
-void DlgSettingsCurveAddRemove::createListCurves (QGridLayout *layout,
-                                                  int &row)
+void DlgSettingsCurveList::createListCurves (QGridLayout *layout,
+                                             int &row)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::createListCurves";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::createListCurves";
 
   QLabel *label = new QLabel (QString ("%1:").arg (tr ("Curve Names")));
   layout->addWidget (label, row++, 1);
@@ -114,9 +114,9 @@ void DlgSettingsCurveAddRemove::createListCurves (QGridLayout *layout,
   m_listCurves->setModel (m_curveNameList);
 }
 
-void DlgSettingsCurveAddRemove::createOptionalSaveDefault (QHBoxLayout *layout)
+void DlgSettingsCurveList::createOptionalSaveDefault (QHBoxLayout *layout)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::createOptionalSaveDefault";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::createOptionalSaveDefault";
 
   m_btnSaveDefault = new QPushButton (tr ("Save As Default"));
   m_btnSaveDefault->setWhatsThis (tr ("Save the curve names for use as defaults for future graph curves."));
@@ -132,9 +132,9 @@ void DlgSettingsCurveAddRemove::createOptionalSaveDefault (QHBoxLayout *layout)
   layout->addItem (spacer);
 }
 
-QWidget *DlgSettingsCurveAddRemove::createSubPanel ()
+QWidget *DlgSettingsCurveList::createSubPanel ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::createSubPanel";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::createSubPanel";
 
   const int EMPTY_COLUMN_WIDTH = 30;
 
@@ -156,7 +156,7 @@ QWidget *DlgSettingsCurveAddRemove::createSubPanel ()
   return subPanel;
 }
 
-bool DlgSettingsCurveAddRemove::endsWithNumber (const QString &str) const
+bool DlgSettingsCurveList::endsWithNumber (const QString &str) const
 {
   bool success = false;
 
@@ -168,33 +168,33 @@ bool DlgSettingsCurveAddRemove::endsWithNumber (const QString &str) const
   return success;
 }
 
-void DlgSettingsCurveAddRemove::handleOk ()
+void DlgSettingsCurveList::handleOk ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::handleOk";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::handleOk";
 
-  CmdSettingsCurveAddRemove *cmd = new CmdSettingsCurveAddRemove (mainWindow (),
-                                                                  cmdMediator ().document(),
-                                                                  *m_curveNameList);
+  CmdSettingsCurveList *cmd = new CmdSettingsCurveList (mainWindow (),
+                                                        cmdMediator ().document(),
+                                                        *m_curveNameList);
   cmdMediator ().push (cmd);
 
   hide ();
 }
 
-void DlgSettingsCurveAddRemove::insertCurveName (int row,
-                                                 const QString &curveNameNew,
-                                                 const QString &curveNameOriginal,
-                                                 int numPoints)
+void DlgSettingsCurveList::insertCurveName (int row,
+                                            const QString &curveNameNew,
+                                            const QString &curveNameOriginal,
+                                            int numPoints)
 {
   // Track all entries
   m_curveNameList->insertRow (row,
                               curveNameNew,
                               curveNameOriginal,
-                              numPoints);
+                              unsigned (numPoints));
 }
 
-void DlgSettingsCurveAddRemove::load (CmdMediator &cmdMediator)
+void DlgSettingsCurveList::load (CmdMediator &cmdMediator)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::load";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::load";
 
   setCmdMediator (cmdMediator);
 
@@ -213,10 +213,11 @@ void DlgSettingsCurveAddRemove::load (CmdMediator &cmdMediator)
 
   selectCurveName (curveNames.first());
 
+  updateControls (); // Make especially sure Remove is disabled if there is just one curve, or none are selected
   enableOk (false); // Disable Ok button since there not yet any changes
 }
 
-int DlgSettingsCurveAddRemove::newRowFromSelection () const
+int DlgSettingsCurveList::newRowFromSelection () const
 {
   int numSelectedItems = m_listCurves->selectionModel ()->selectedIndexes ().count ();
   int numItems = m_listCurves->model ()->rowCount ();
@@ -239,7 +240,7 @@ int DlgSettingsCurveAddRemove::newRowFromSelection () const
   return newRow;
 }
 
-QString DlgSettingsCurveAddRemove::nextCurveName () const
+QString DlgSettingsCurveList::nextCurveName () const
 {
   const QString DASH_ONE ("-1"); // Nice value to start a new range at a lower level than the current level
 
@@ -330,7 +331,7 @@ QString DlgSettingsCurveAddRemove::nextCurveName () const
   return curveNameNext;
 }
 
-int DlgSettingsCurveAddRemove::numberAtEnd (const QString &str) const
+int DlgSettingsCurveList::numberAtEnd (const QString &str) const
 {
   ENGAUGE_ASSERT (endsWithNumber (str));
 
@@ -349,7 +350,7 @@ int DlgSettingsCurveAddRemove::numberAtEnd (const QString &str) const
   return sign * str.mid (ch).toInt ();
 }
 
-unsigned int DlgSettingsCurveAddRemove::numPointsForSelectedCurves () const
+unsigned int DlgSettingsCurveList::numPointsForSelectedCurves () const
 {
   QList<unsigned int > rowsSelected;
 
@@ -357,20 +358,20 @@ unsigned int DlgSettingsCurveAddRemove::numPointsForSelectedCurves () const
   for (int i = 0; i < m_listCurves->selectionModel()->selectedIndexes ().count (); i++) {
 
     int row = m_listCurves->selectionModel()->selectedIndexes ().at (i).row ();
-    rowsSelected << row;
+    rowsSelected << unsigned (row);
   }
 
   return m_curveNameList->numPointsForSelectedCurves (rowsSelected);
 }
 
-void DlgSettingsCurveAddRemove::printStream(QTextStream &str) const
+void DlgSettingsCurveList::printStream(QTextStream &str) const
 {
   str << m_curveNameList->currentCurvesAsString();
 }
 
-void DlgSettingsCurveAddRemove::removeSelectedCurves ()
+void DlgSettingsCurveList::removeSelectedCurves ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::removeSelectedCurves";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::removeSelectedCurves";
 
   ENGAUGE_ASSERT (m_listCurves->selectionModel ()->selectedIndexes ().count () > 0); // Also guarantees number of indexes > 0
 
@@ -409,9 +410,9 @@ void DlgSettingsCurveAddRemove::removeSelectedCurves ()
   selectCurveName(firstCurveAfter);
 }
 
-void DlgSettingsCurveAddRemove::selectCurveName (const QString &curveWanted)
+void DlgSettingsCurveList::selectCurveName (const QString &curveWanted)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::selectCurveName"
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::selectCurveName"
                               << " curve=" << curveWanted.toLatin1().data();
 
   for (int row = 0; row < m_listCurves->model()->rowCount(); row++) {
@@ -429,16 +430,16 @@ void DlgSettingsCurveAddRemove::selectCurveName (const QString &curveWanted)
   }
 }
 
-void DlgSettingsCurveAddRemove::setSmallDialogs(bool smallDialogs)
+void DlgSettingsCurveList::setSmallDialogs(bool smallDialogs)
 {
   if (!smallDialogs) {
     setMinimumHeight (MINIMUM_HEIGHT);
   }
 }
 
-void DlgSettingsCurveAddRemove::slotDataChanged (const QModelIndex &topLeft,
-                                                 const QModelIndex &bottomRight,
-                                                 const QVector<int> &roles)
+void DlgSettingsCurveList::slotDataChanged (const QModelIndex &topLeft,
+                                            const QModelIndex &bottomRight,
+                                            const QVector<int> &roles)
 {
   // LOG4CPP_INFO_S is below
 
@@ -447,7 +448,7 @@ void DlgSettingsCurveAddRemove::slotDataChanged (const QModelIndex &topLeft,
   QTextStream str (&curveEntries);
   printStream (str);
 
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotDataChanged"
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::slotDataChanged"
                               << " topLeft=(" << topLeft.row () << "," << topLeft.column () << ")"
                               << " bottomRight=(" << bottomRight.row () << "," << bottomRight.column () << ")"
                               << " roles=" << rolesAsString (roles).toLatin1 ().data ()
@@ -457,11 +458,11 @@ void DlgSettingsCurveAddRemove::slotDataChanged (const QModelIndex &topLeft,
   updateControls ();
 }
 
-void DlgSettingsCurveAddRemove::slotRowsAboutToBeRemoved (const QModelIndex &parent,
-                                                          int rowFirst,
-                                                          int rowLast)
+void DlgSettingsCurveList::slotRowsAboutToBeRemoved (const QModelIndex &parent,
+                                                     int rowFirst,
+                                                     int rowLast)
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotRowsAboutToBeRemoved"
+  LOG4CPP_DEBUG_S ((*mainCat)) << "DlgSettingsCurveList::slotRowsAboutToBeRemoved"
                                << " parentValid=" << (parent.isValid() ? "yes" : "no")
                                << " rowFirst=" << rowFirst
                                << " rowLast=" << rowLast;
@@ -469,9 +470,9 @@ void DlgSettingsCurveAddRemove::slotRowsAboutToBeRemoved (const QModelIndex &par
   updateControls ();
 }
 
-void DlgSettingsCurveAddRemove::slotNew ()
+void DlgSettingsCurveList::slotNew ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotNew";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::slotNew";
 
   const QString NO_ORIGINAL_CURVE_NAME;
   const int NO_POINTS = 0;
@@ -490,12 +491,12 @@ void DlgSettingsCurveAddRemove::slotNew ()
   updateControls();
 }
 
-void DlgSettingsCurveAddRemove::slotRemove ()
+void DlgSettingsCurveList::slotRemove ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotRemove";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::slotRemove";
 
   // Count the number of curve points to be deleted
-  int numPoints = numPointsForSelectedCurves ();
+  int numPoints = signed (numPointsForSelectedCurves ());
 
   int rtn = QMessageBox::Ok;
   if (numPoints > 0) {
@@ -513,7 +514,7 @@ void DlgSettingsCurveAddRemove::slotRemove ()
             .arg (tr ("points. Continue?"));
     }
 
-    rtn = QMessageBox::warning (0,
+    rtn = QMessageBox::warning (nullptr,
                                 tr ("Curves With Points"),
                                 msg,
                                 QMessageBox::Ok,
@@ -527,9 +528,9 @@ void DlgSettingsCurveAddRemove::slotRemove ()
   updateControls();
 }
 
-void DlgSettingsCurveAddRemove::slotResetDefault()
+void DlgSettingsCurveList::slotResetDefault()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotResetDefault";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::slotResetDefault";
 
   const QString REMOVE_ALL_SETTINGS_IN_GROUP; // Empty string
 
@@ -550,9 +551,9 @@ void DlgSettingsCurveAddRemove::slotResetDefault()
   }
 }
 
-void DlgSettingsCurveAddRemove::slotSaveDefault()
+void DlgSettingsCurveList::slotSaveDefault()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::slotSaveDefault";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::slotSaveDefault";
 
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
 
@@ -574,9 +575,9 @@ void DlgSettingsCurveAddRemove::slotSaveDefault()
   }
 }
 
-void DlgSettingsCurveAddRemove::updateControls ()
+void DlgSettingsCurveList::updateControls ()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveAddRemove::updateControls";
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveList::updateControls";
 
   enableOk (true);
 
diff --git a/src/Dlg/DlgSettingsCurveAddRemove.h b/src/Dlg/DlgSettingsCurveList.h
similarity index 90%
rename from src/Dlg/DlgSettingsCurveAddRemove.h
rename to src/Dlg/DlgSettingsCurveList.h
index 7505c1f6..e0947389 100644
--- a/src/Dlg/DlgSettingsCurveAddRemove.h
+++ b/src/Dlg/DlgSettingsCurveList.h
@@ -4,8 +4,8 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#ifndef DLG_SETTINGS_CURVE_ADD_REMOVE_H
-#define DLG_SETTINGS_CURVE_ADD_REMOVE_H
+#ifndef DLG_SETTINGS_CURVE_LIST_H
+#define DLG_SETTINGS_CURVE_LIST_H
 
 #include "DlgSettingsAbstractBase.h"
 #include <QItemSelection>
@@ -21,14 +21,14 @@ class QTableView;
 class QTextStream;
 
 /// Dialog for editing curve names settings.
-class DlgSettingsCurveAddRemove : public DlgSettingsAbstractBase
+class DlgSettingsCurveList : public DlgSettingsAbstractBase
 {
   Q_OBJECT;
 
 public:
   /// Single constructor.
-  DlgSettingsCurveAddRemove(MainWindow &mainWindow);
-  virtual ~DlgSettingsCurveAddRemove();
+  DlgSettingsCurveList(MainWindow &mainWindow);
+  virtual ~DlgSettingsCurveList();
 
   virtual void createOptionalSaveDefault (QHBoxLayout *layout);
   virtual QWidget *createSubPanel ();
@@ -85,4 +85,4 @@ private:
 
 };
 
-#endif // DLG_SETTINGS_CURVE_ADD_REMOVE_H
+#endif // DLG_SETTINGS_CURVE_LIST_H
diff --git a/src/Dlg/DlgSettingsCurveProperties.cpp b/src/Dlg/DlgSettingsCurveProperties.cpp
index da1ad726..d8c9d32e 100644
--- a/src/Dlg/DlgSettingsCurveProperties.cpp
+++ b/src/Dlg/DlgSettingsCurveProperties.cpp
@@ -26,6 +26,7 @@
 #include <QLabel>
 #include <QLineEdit>
 #include <QListWidget>
+#include <qmath.h>
 #include <QPen>
 #include <QPushButton>
 #include <QSettings>
@@ -62,10 +63,10 @@ DlgSettingsCurveProperties::DlgSettingsCurveProperties(MainWindow &mainWindow) :
                            "DlgSettingsCurveProperties",
                            mainWindow),
   m_modelMainWindow (mainWindow.modelMainWindow()),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelCurveStylesBefore (0),
-  m_modelCurveStylesAfter (0)
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelCurveStylesBefore (nullptr),
+  m_modelCurveStylesAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsCurveProperties::DlgSettingsCurveProperties";
 
@@ -142,7 +143,8 @@ void DlgSettingsCurveProperties::createLine (QGridLayout *layout,
                                    "endpoints.\n\n"
                                    "Lines are drawn between successively ordered points.\n\n"
                                    "Straight curves are drawn with straight lines between successive points. Smooth curves are drawn "
-                                   "with smooth lines between successive points.\n\n"
+                                   "with smooth lines between successive points, using natural cubic splines of (x,y) pairs versus "
+                                   "scalar ordinal (t) values.\n\n"
                                     "This applies only to graph curves. No lines are ever drawn between axis points."));
   connect (m_cmbLineType, SIGNAL (activated (const QString &)), this, SLOT (slotLineType (const QString &))); // activated() ignores code changes
   layoutGroup->addWidget (m_cmbLineType, 2, 1);
@@ -170,10 +172,14 @@ void DlgSettingsCurveProperties::createPoint (QGridLayout *layout,
                             POINT_SHAPE_CROSS);
   m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_DIAMOND),
                             POINT_SHAPE_DIAMOND);
+  m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_HOURGLASS),
+                            POINT_SHAPE_HOURGLASS);  
   m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_SQUARE),
                             POINT_SHAPE_SQUARE);
   m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_TRIANGLE),
                             POINT_SHAPE_TRIANGLE);
+  m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_TRIANGLE2),
+                            POINT_SHAPE_TRIANGLE2);
   m_cmbPointShape->addItem (pointShapeToString (POINT_SHAPE_X),
                             POINT_SHAPE_X);
   connect (m_cmbPointShape, SIGNAL (activated (const QString &)), this, SLOT (slotPointShape (const QString &))); // activated() ignores code changes
@@ -329,7 +335,7 @@ void DlgSettingsCurveProperties::drawLine (bool isRelation,
 void DlgSettingsCurveProperties::drawPoints (const PointStyle &pointStyle)
 {
   const QString NULL_IDENTIFIER;
-  GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
+  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
 
   GraphicsPointFactory pointFactory;
 
@@ -446,10 +452,10 @@ void DlgSettingsCurveProperties::loadForCurveName (const QString &curveName)
 void DlgSettingsCurveProperties::resetSceneRectangle ()
 {
 
-  QRect rect (0.0,
-              0.0,
-              PREVIEW_WIDTH,
-              PREVIEW_HEIGHT);
+  QRect rect (0,
+              0,
+              qFloor (PREVIEW_WIDTH),
+              qFloor (PREVIEW_HEIGHT));
 
   QGraphicsRectItem *itemPerimeter = new QGraphicsRectItem(rect);
   itemPerimeter->setVisible(false);
@@ -477,7 +483,7 @@ void DlgSettingsCurveProperties::slotCurveName(const QString &curveName)
   // Dirty flag is not set when simply changing to new curve
 
   // Do nothing if combobox is getting cleared, or load has not been called yet
-  if (!curveName.isEmpty () && (m_modelCurveStylesAfter != 0)) {
+  if (!curveName.isEmpty () && (m_modelCurveStylesAfter != nullptr)) {
 
     loadForCurveName (curveName);
   }
@@ -490,7 +496,7 @@ void DlgSettingsCurveProperties::slotLineColor(const QString &lineColor)
   m_isDirty = true;
 
   m_modelCurveStylesAfter->setLineColor(m_cmbCurveName->currentText(),
-                                        (ColorPalette) m_cmbLineColor->currentData().toInt());
+                                        static_cast<ColorPalette> (m_cmbLineColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
@@ -514,7 +520,7 @@ void DlgSettingsCurveProperties::slotLineType(const QString &lineType)
   m_isDirty = true;
 
   m_modelCurveStylesAfter->setLineConnectAs(m_cmbCurveName->currentText(),
-                                            (CurveConnectAs) m_cmbLineType->currentData().toInt ());
+                                            static_cast<CurveConnectAs> (m_cmbLineType->currentData().toInt ()));
   updateControls();
   updatePreview();
 }
@@ -526,7 +532,7 @@ void DlgSettingsCurveProperties::slotPointColor(const QString &pointColor)
   m_isDirty = true;
 
   m_modelCurveStylesAfter->setPointColor(m_cmbCurveName->currentText(),
-                                         (ColorPalette) m_cmbPointColor->currentData().toInt ());
+                                         static_cast<ColorPalette> (m_cmbPointColor->currentData().toInt ()));
   updateControls();
   updatePreview();
 }
@@ -562,7 +568,7 @@ void DlgSettingsCurveProperties::slotPointShape(const QString &)
   m_isDirty = true;
 
   m_modelCurveStylesAfter->setPointShape(m_cmbCurveName->currentText(),
-                                         (PointShape) m_cmbPointShape->currentData().toInt ());
+                                         static_cast<PointShape> (m_cmbPointShape->currentData().toInt ()));
   updateControls();
   updatePreview();
 }
diff --git a/src/Dlg/DlgSettingsDigitizeCurve.cpp b/src/Dlg/DlgSettingsDigitizeCurve.cpp
index 75cbf47a..486a3d9d 100644
--- a/src/Dlg/DlgSettingsDigitizeCurve.cpp
+++ b/src/Dlg/DlgSettingsDigitizeCurve.cpp
@@ -41,10 +41,10 @@ DlgSettingsDigitizeCurve::DlgSettingsDigitizeCurve(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Digitize Curve"),
                            "DlgSettingsDigitizeCurve",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelDigitizeCurveBefore (0),
-  m_modelDigitizeCurveAfter (0)
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelDigitizeCurveBefore (nullptr),
+  m_modelDigitizeCurveAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::DlgSettingsDigitizeCurve";
 
@@ -249,7 +249,7 @@ void DlgSettingsDigitizeCurve::slotCursorSize (const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorSize";
 
-  m_modelDigitizeCurveAfter->setCursorSize ((CursorSize) m_cmbSize->currentData().toInt());
+  m_modelDigitizeCurveAfter->setCursorSize (static_cast<CursorSize> (m_cmbSize->currentData().toInt()));
   updateControls();
   updatePreview();
 }
diff --git a/src/Dlg/DlgSettingsExportFormat.cpp b/src/Dlg/DlgSettingsExportFormat.cpp
index 4321ad47..7c6b76c6 100644
--- a/src/Dlg/DlgSettingsExportFormat.cpp
+++ b/src/Dlg/DlgSettingsExportFormat.cpp
@@ -48,15 +48,17 @@ const int TAB_WIDGET_INDEX_RELATIONS = 1;
 
 const QString EMPTY_PREVIEW;
 
-const int MINIMUM_DIALOG_WIDTH_EXPORT_FORMAT = 650;
+const int MINIMUM_DIALOG_WIDTH_EXPORT_FORMAT = 600;
 const int MINIMUM_HEIGHT = 780;
 
 DlgSettingsExportFormat::DlgSettingsExportFormat(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Export Format"),
                            "DlgSettingsExportFormat",
                            mainWindow),
-  m_modelExportBefore (0),
-  m_modelExportAfter (0),
+  m_validatorFunctionsPointsEvenlySpacing (nullptr),
+  m_validatorRelationsPointsEvenlySpacing (nullptr),
+  m_modelExportBefore (nullptr),
+  m_modelExportAfter (nullptr),
   m_haveFunction (false),
   m_haveRelation (false)
 {
@@ -70,6 +72,9 @@ DlgSettingsExportFormat::DlgSettingsExportFormat(MainWindow &mainWindow) :
 DlgSettingsExportFormat::~DlgSettingsExportFormat()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::~DlgSettingsExportFormat";
+
+  delete m_validatorFunctionsPointsEvenlySpacing;
+  delete m_validatorRelationsPointsEvenlySpacing;  
 }
 
 void DlgSettingsExportFormat::createCurveSelection (QGridLayout *layout, int &row)
@@ -196,8 +201,15 @@ void DlgSettingsExportFormat::createFunctionsPointsSelection (QHBoxLayout *layou
   m_btnFunctionsPointsAllCurves = new QRadioButton (tr ("Interpolate Ys at Xs from all curves"));
   m_btnFunctionsPointsAllCurves->setWhatsThis (tr ("Exported file will have values at every unique X "
                                                    "value from every curve. Y values will be linearly interpolated if necessary"));
-  layoutPointsSelections->addWidget (m_btnFunctionsPointsAllCurves, row++, 0, 1, 4);
+  layoutPointsSelections->addWidget (m_btnFunctionsPointsAllCurves, row, 0, 1, 2);
   connect (m_btnFunctionsPointsAllCurves, SIGNAL (released()), this, SLOT (slotFunctionsPointsAllCurves()));
+  
+  // Put extrapolation control up near interpolation controls and away from raw control which never uses extrapolation
+  m_chkExtrapolateOutsideEndpoints = new QCheckBox (tr ("Extrapolate outside endpoints"));
+  m_chkExtrapolateOutsideEndpoints->setWhatsThis (tr ("Enable or disable extrapolation outside of endpoints of each curve. If disabled, "
+                                                      "only points between the endpoints of each curve are exported"));
+  layoutPointsSelections->addWidget (m_chkExtrapolateOutsideEndpoints, row++, 3, 1, 1, Qt::AlignRight);
+  connect (m_chkExtrapolateOutsideEndpoints, SIGNAL (stateChanged (int)), this, SLOT (slotFunctionsExtrapolateOutsideEndpoints(int)));
 
   m_btnFunctionsPointsFirstCurve = new QRadioButton (tr ("Interpolate Ys at Xs from first curve"));
   m_btnFunctionsPointsFirstCurve->setWhatsThis (tr ("Exported file will have values at every unique X "
@@ -205,7 +217,7 @@ void DlgSettingsExportFormat::createFunctionsPointsSelection (QHBoxLayout *layou
   layoutPointsSelections->addWidget (m_btnFunctionsPointsFirstCurve, row++, 0, 1, 4);
   connect (m_btnFunctionsPointsFirstCurve, SIGNAL (released()), this, SLOT (slotFunctionsPointsFirstCurve()));
 
-  m_btnFunctionsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values."));
+  m_btnFunctionsPointsEvenlySpaced = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values that are automatically selected"));
   m_btnFunctionsPointsEvenlySpaced->setWhatsThis (tr ("Exported file will have values at evenly spaced X values, separated by the interval selected below."));
   layoutPointsSelections->addWidget (m_btnFunctionsPointsEvenlySpaced, row++, 0, 1, 4);
   connect (m_btnFunctionsPointsEvenlySpaced, SIGNAL (released()), this, SLOT (slotFunctionsPointsEvenlySpaced()));
@@ -233,13 +245,18 @@ void DlgSettingsExportFormat::createFunctionsPointsSelection (QHBoxLayout *layou
                                                             "consistent across the graph, even if the X scale is logarithmic.\n\n"
                                                             "Graph units are preferred when the spacing is to depend on the X scale."));
   m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_GRAPH),
-                                                                                     QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
+                                                  QVariant (EXPORT_POINTS_INTERVAL_UNITS_GRAPH));
   m_cmbFunctionsPointsEvenlySpacingUnits->addItem(exportPointsIntervalUnitsToString (EXPORT_POINTS_INTERVAL_UNITS_SCREEN),
-                                                                                     QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
+                                                  QVariant (EXPORT_POINTS_INTERVAL_UNITS_SCREEN));
   connect (m_cmbFunctionsPointsEvenlySpacingUnits, SIGNAL (activated (const QString &)),
            this, SLOT (slotFunctionsPointsEvenlySpacedIntervalUnits (const QString &))); // activated() ignores code changes
   layoutPointsSelections->addWidget (m_cmbFunctionsPointsEvenlySpacingUnits, row++, 3, 1, 1, Qt::AlignLeft);
 
+  m_btnFunctionsPointsGridLines = new QRadioButton (tr ("Interpolate Ys at evenly spaced X values on grid lines"));
+  m_btnFunctionsPointsGridLines->setWhatsThis (tr ("Exported file will have values at evenly spaced X values at the vertical grid lines."));
+  layoutPointsSelections->addWidget (m_btnFunctionsPointsGridLines, row++, 0, 1, 4);
+  connect (m_btnFunctionsPointsGridLines, SIGNAL (released()), this, SLOT (slotFunctionsPointsGridLines()));
+
   m_btnFunctionsPointsRaw = new QRadioButton (tr ("Raw Xs and Ys"));
   m_btnFunctionsPointsRaw->setWhatsThis (tr ("Exported file will have only original X and Y values"));
   layoutPointsSelections->addWidget (m_btnFunctionsPointsRaw, row++, 0, 1, 4);
@@ -288,6 +305,11 @@ void DlgSettingsExportFormat::createOptionalSaveDefault (QHBoxLayout *layout)
   m_btnSaveDefault->setWhatsThis (tr ("Save the settings for use as future defaults."));
   connect (m_btnSaveDefault, SIGNAL (released ()), this, SLOT (slotSaveDefault ()));
   layout->addWidget (m_btnSaveDefault, 0, Qt::AlignLeft);
+
+  m_btnLoadDefault = new QPushButton (tr ("Load Default"));
+  m_btnLoadDefault->setWhatsThis (tr ("Load the default settings."));
+  connect (m_btnLoadDefault, SIGNAL (released ()), this, SLOT (slotLoadDefault ()));
+  layout->addWidget (m_btnLoadDefault, 0, Qt::AlignLeft);
 }
 
 void DlgSettingsExportFormat::createPreview(QGridLayout *layout, int &row)
@@ -408,7 +430,7 @@ QWidget *DlgSettingsExportFormat::createSubPanel ()
 }
 
 void DlgSettingsExportFormat::createTabWidget (QGridLayout *layout,
-                                         int &row)
+                                               int &row)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createTabWidget";
 
@@ -440,26 +462,17 @@ void DlgSettingsExportFormat::createTabWidget (QGridLayout *layout,
 }
 
 void DlgSettingsExportFormat::createXLabel (QGridLayout *layoutHeader,
-                                      int colLabel)
+                                            int colLabel)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::createXLabel";
 
   int row = 1; // Skip first row
 
-  QLabel *title;
-  if (true) {
-    title = new QLabel (QString ("%1:").arg (tr ("X Label")));
-  } else {
-    title = new QLabel (QString ("%1:").arg (tr ("Theta Label")));
-  }
+  QLabel *title = new QLabel (QString ("%1:").arg (tr ("X Label")));
   layoutHeader->addWidget (title, row++, colLabel, 1, 1);
 
   m_editXLabel = new QLineEdit;
-  if (true) {
-    m_editXLabel->setWhatsThis (tr ("Label in the header for x values"));
-  } else {
-    m_editXLabel->setWhatsThis (tr ("Label in the header for theta values"));
-  }
+  m_editXLabel->setWhatsThis (tr ("Label in the header for x values"));
   layoutHeader->addWidget (m_editXLabel, row++, colLabel, 1, 1);
   connect (m_editXLabel, SIGNAL (textChanged (const QString &)), this, SLOT (slotXLabel(const QString &)));
 }
@@ -539,7 +552,8 @@ void DlgSettingsExportFormat::initializeIntervalConstraints ()
   const int MAX_POINTS_ACROSS_RANGE = 5000;
 
   // Get min and max of graph and screen coordinates
-  CallbackBoundingRects ftor (mainWindow().transformation());
+  CallbackBoundingRects ftor (cmdMediator().document().documentAxesPointsRequired(),
+                              mainWindow().transformation());
 
   Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
                                                                                                      &CallbackBoundingRects::callback);
@@ -547,12 +561,12 @@ void DlgSettingsExportFormat::initializeIntervalConstraints ()
 
   // If there are no points, then interval will be zero. That special case must be handled downstream to prevent infinite loops
   bool isEmpty;
-  double maxSizeGraph = qMax (ftor.boundingRectGraph(isEmpty).width(),
-                              ftor.boundingRectGraph(isEmpty).height());
-  double maxSizeScreen = qMax (ftor.boundingRectScreen(isEmpty).width(),
-                               ftor.boundingRectScreen(isEmpty).height());
-  m_minIntervalGraph = maxSizeGraph / MAX_POINTS_ACROSS_RANGE;
-  m_minIntervalScreen = maxSizeScreen / MAX_POINTS_ACROSS_RANGE;
+  QPointF boundingRectGraphMin = ftor.boundingRectGraphMin (isEmpty);
+  QPointF boundingRectGraphMax = ftor.boundingRectGraphMax (isEmpty);
+  double maxSizeGraph = boundingRectGraphMax.x() - boundingRectGraphMin.x();
+  double maxSizeScreen = ftor.boundingRectScreen(isEmpty).width();
+  m_minIntervalGraph = maxSizeGraph / MAX_POINTS_ACROSS_RANGE; // Should be unaffected by y range
+  m_minIntervalScreen = maxSizeScreen / MAX_POINTS_ACROSS_RANGE; // Should be unaffected by y range
 }
 
 void DlgSettingsExportFormat::load (CmdMediator &cmdMediator)
@@ -592,6 +606,7 @@ void DlgSettingsExportFormat::load (CmdMediator &cmdMediator)
   m_btnFunctionsPointsAllCurves->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
   m_btnFunctionsPointsFirstCurve->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
   m_btnFunctionsPointsEvenlySpaced->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
+  m_btnFunctionsPointsGridLines->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES);
   m_btnFunctionsPointsRaw->setChecked (pointsSelectionFunctions == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
 
   ExportLayoutFunctions layoutFunctions = m_modelExportAfter->layoutFunctions ();
@@ -608,6 +623,8 @@ void DlgSettingsExportFormat::load (CmdMediator &cmdMediator)
   m_btnDelimitersTabs->setChecked (delimiter == EXPORT_DELIMITER_TAB);
   m_btnDelimitersSemicolons->setChecked (delimiter == EXPORT_DELIMITER_SEMICOLON);
 
+  m_chkExtrapolateOutsideEndpoints->setChecked (m_modelExportAfter->extrapolateOutsideEndpoints ());
+
   m_chkOverrideCsvTsv->setChecked (m_modelExportAfter->overrideCsvTsv());
 
   ExportHeader header = m_modelExportAfter->header ();
@@ -713,6 +730,15 @@ void DlgSettingsExportFormat::slotExclude ()
   updatePreview();
 }
 
+void DlgSettingsExportFormat::slotFunctionsExtrapolateOutsideEndpoints(int)
+{
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsExtrapolateOutsideEndpoints";
+
+  m_modelExportAfter->setExtrapolateOutsideEndpoints (m_chkExtrapolateOutsideEndpoints->isChecked());  
+  updateControls();
+  updatePreview();
+}
+
 void DlgSettingsExportFormat::slotFunctionsLayoutAllCurves()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsLayoutAllCurves";
@@ -755,7 +781,7 @@ void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedInterval(const QStr
 
   // Prevent infinite loop on empty and "-" values which get treated as zero interval
   if (goodIntervalFunctions()) {
-   m_modelExportAfter->setPointsIntervalFunctions(m_editFunctionsPointsEvenlySpacing->text().toDouble());
+    m_modelExportAfter->setPointsIntervalFunctions(m_editFunctionsPointsEvenlySpacing->text().toDouble());
     updateControls();
     updatePreview();
   } else {
@@ -768,7 +794,7 @@ void DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits(const
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsEvenlySpacedIntervalUnits";
 
   int index = m_cmbFunctionsPointsEvenlySpacingUnits->currentIndex();
-  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbFunctionsPointsEvenlySpacingUnits->itemData (index).toInt();
+  ExportPointsIntervalUnits units = static_cast<ExportPointsIntervalUnits> (m_cmbFunctionsPointsEvenlySpacingUnits->itemData (index).toInt());
 
   m_modelExportAfter->setPointsIntervalUnitsFunctions(units);
   updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
@@ -785,6 +811,15 @@ void DlgSettingsExportFormat::slotFunctionsPointsFirstCurve()
   updatePreview();
 }
 
+void DlgSettingsExportFormat::slotFunctionsPointsGridLines()
+{
+    LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsGridLines";
+
+    m_modelExportAfter->setPointsSelectionFunctions(EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES);
+    updateControls();
+    updatePreview();
+}
+
 void DlgSettingsExportFormat::slotFunctionsPointsRaw()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotFunctionsPointsRaw";
@@ -874,6 +909,57 @@ void DlgSettingsExportFormat::slotListIncluded()
   // Do not call updatePreview since this method changes nothing
 }
 
+void DlgSettingsExportFormat::slotLoadDefault()
+{
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotLoadDefault";
+
+  // Get defaults from constructor
+  DocumentModelExportFormat modelExportDefaults;
+
+  // Apply defaults to controls. That will trigger updates to m_modelExportAfter
+
+  m_btnHeaderGnuplot->setChecked (modelExportDefaults.header() == EXPORT_HEADER_GNUPLOT);
+  m_btnHeaderNone->setChecked (modelExportDefaults.header() == EXPORT_HEADER_NONE);
+  m_btnHeaderSimple->setChecked (modelExportDefaults.header() == EXPORT_HEADER_SIMPLE);
+
+  m_editXLabel->setText (modelExportDefaults.xLabel());
+
+  m_btnDelimitersCommas->setChecked (modelExportDefaults.delimiter() == EXPORT_DELIMITER_COMMA);
+  m_btnDelimitersSemicolons->setChecked (modelExportDefaults.delimiter() == EXPORT_DELIMITER_SEMICOLON);
+  m_btnDelimitersSpaces->setChecked (modelExportDefaults.delimiter() == EXPORT_DELIMITER_SPACE);
+  m_btnDelimitersTabs->setChecked (modelExportDefaults.delimiter() == EXPORT_DELIMITER_TAB);
+
+  m_chkOverrideCsvTsv->setChecked (modelExportDefaults.overrideCsvTsv());
+
+  m_btnCurvesLayoutAllCurves->setChecked (modelExportDefaults.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE);
+  m_btnCurvesLayoutOneCurve->setChecked (modelExportDefaults.layoutFunctions() == EXPORT_LAYOUT_ONE_PER_LINE);
+
+  m_editFunctionsPointsEvenlySpacing->setText (QString::number (modelExportDefaults.pointsIntervalFunctions ()));
+  m_editRelationsPointsEvenlySpacing->setText (QString::number (modelExportDefaults.pointsIntervalRelations ()));
+
+  m_btnFunctionsPointsAllCurves->setChecked (modelExportDefaults.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES);
+  m_btnFunctionsPointsFirstCurve->setChecked (modelExportDefaults.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE);
+  m_btnFunctionsPointsEvenlySpaced->setChecked (modelExportDefaults.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC);
+  m_btnFunctionsPointsGridLines->setChecked (modelExportDefaults.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES);
+  m_btnFunctionsPointsRaw->setChecked (modelExportDefaults.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW);
+
+  m_btnRelationsPointsEvenlySpaced->setChecked (modelExportDefaults.pointsSelectionRelations() == EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE);
+  m_btnRelationsPointsRaw->setChecked (modelExportDefaults.pointsSelectionRelations() == EXPORT_POINTS_SELECTION_RELATIONS_RAW);
+
+  m_chkExtrapolateOutsideEndpoints->setChecked (modelExportDefaults.extrapolateOutsideEndpoints());
+
+  int indexFunctions = m_cmbFunctionsPointsEvenlySpacingUnits->findData (QVariant (modelExportDefaults.pointsIntervalUnitsFunctions ()));
+  int indexRelations = m_cmbRelationsPointsEvenlySpacingUnits->findData (QVariant (modelExportDefaults.pointsIntervalUnitsRelations ()));
+  m_cmbFunctionsPointsEvenlySpacingUnits->setCurrentIndex (indexFunctions);
+  m_cmbRelationsPointsEvenlySpacingUnits->setCurrentIndex (indexRelations);
+
+  // Apply defaults to 'after' settings
+  *m_modelExportAfter = modelExportDefaults;
+
+  updateControls();
+  updatePreview();
+}
+
 void DlgSettingsExportFormat::slotOverrideCsvTsv(int)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotOverrideCsvTsv";
@@ -906,7 +992,7 @@ void DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits(const
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsExportFormat::slotRelationsPointsEvenlySpacedIntervalUnits";
 
   int index = m_cmbRelationsPointsEvenlySpacingUnits->currentIndex();
-  ExportPointsIntervalUnits units = (ExportPointsIntervalUnits) m_cmbRelationsPointsEvenlySpacingUnits->itemData (index).toInt();
+  ExportPointsIntervalUnits units = static_cast<ExportPointsIntervalUnits> (m_cmbRelationsPointsEvenlySpacingUnits->itemData (index).toInt());
 
   m_modelExportAfter->setPointsIntervalUnitsRelations(units);
   updateIntervalConstraints(); // Call this before updateControls so constraint checking is updated for ok button
@@ -930,8 +1016,14 @@ void DlgSettingsExportFormat::slotSaveDefault()
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_EXPORT);
 
+  // Sync these settings with DocumentModelExportFormat::DocumentModelExportFormat()
+  // and DlgSettingsExportFormat::slotLoadDefault()
   settings.setValue (SETTINGS_EXPORT_DELIMITER,
                      QVariant (m_modelExportAfter->delimiter()));
+  settings.setValue (SETTINGS_EXPORT_DELIMITER_OVERRIDE_CSV_TSV,
+                     QVariant (m_modelExportAfter->overrideCsvTsv()));
+  settings.setValue (SETTINGS_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS,
+                     QVariant (m_modelExportAfter->extrapolateOutsideEndpoints()));
   settings.setValue (SETTINGS_EXPORT_HEADER,
                      QVariant (m_modelExportAfter->header()));
   settings.setValue (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
@@ -976,6 +1068,9 @@ void DlgSettingsExportFormat::updateControls ()
                      goodIntervalRelations();
   enableOk (isGoodState);
 
+  // Function extrapolation never applies when using raw points
+  m_chkExtrapolateOutsideEndpoints->setEnabled (!m_btnFunctionsPointsRaw->isChecked ());
+
   int selectedForInclude = m_listExcluded->selectedItems().count();
   int selectedForExclude = m_listIncluded->selectedItems().count();
   int inInclude = m_listIncluded->count();
@@ -1041,6 +1136,12 @@ void DlgSettingsExportFormat::updateIntervalConstraints ()
                            m_minIntervalGraph :
                            m_minIntervalScreen);
 
+  if (cmdMediator().document().modelCoords().coordScaleYRadius() == COORD_SCALE_LOG) {
+    // Override scale factor with log scale so Export classes are assured that multiplying by the scale factor will
+    // cause an increase
+    functionsMin = qMax (1.00000001, functionsMin);
+  }
+
   if (m_tabWidget->currentIndex() == TAB_WIDGET_INDEX_FUNCTIONS) {
 
     if (m_modelExportAfter->pointsIntervalFunctions() < functionsMin) {
diff --git a/src/Dlg/DlgSettingsExportFormat.h b/src/Dlg/DlgSettingsExportFormat.h
index 23941839..ca06bf39 100644
--- a/src/Dlg/DlgSettingsExportFormat.h
+++ b/src/Dlg/DlgSettingsExportFormat.h
@@ -45,6 +45,7 @@ private slots:
   void slotDelimitersSpaces();
   void slotDelimitersTabs();
   void slotExclude();
+  void slotFunctionsExtrapolateOutsideEndpoints(int);
   void slotFunctionsLayoutAllCurves();
   void slotFunctionsLayoutOneCurve();
   void slotFunctionsPointsAllCurves();
@@ -52,6 +53,7 @@ private slots:
   void slotFunctionsPointsEvenlySpacedInterval(const QString  &);
   void slotFunctionsPointsEvenlySpacedIntervalUnits(const QString &);
   void slotFunctionsPointsFirstCurve();
+  void slotFunctionsPointsGridLines();
   void slotFunctionsPointsRaw();
   void slotHeaderGnuplot();
   void slotHeaderNone();
@@ -59,6 +61,7 @@ private slots:
   void slotInclude();
   void slotListExcluded();
   void slotListIncluded();
+  void slotLoadDefault();
   void slotOverrideCsvTsv(int);
   void slotRelationsPointsEvenlySpaced();
   void slotRelationsPointsEvenlySpacedInterval(const QString &);
@@ -108,8 +111,10 @@ private:
   QLineEdit *m_editFunctionsPointsEvenlySpacing;
   QDoubleValidator *m_validatorFunctionsPointsEvenlySpacing;
   QComboBox *m_cmbFunctionsPointsEvenlySpacingUnits;
+  QRadioButton *m_btnFunctionsPointsGridLines;
   QRadioButton *m_btnFunctionsPointsRaw;
-
+  QCheckBox *m_chkExtrapolateOutsideEndpoints;
+  
   QRadioButton *m_btnCurvesLayoutAllCurves;
   QRadioButton *m_btnCurvesLayoutOneCurve;
 
@@ -134,6 +139,7 @@ private:
   QTextEdit *m_editPreview;
 
   QPushButton *m_btnSaveDefault;
+  QPushButton *m_btnLoadDefault;
 
   DocumentModelExportFormat *m_modelExportBefore;
   DocumentModelExportFormat *m_modelExportAfter;
diff --git a/src/Dlg/DlgSettingsGeneral.cpp b/src/Dlg/DlgSettingsGeneral.cpp
index be275347..038862dc 100644
--- a/src/Dlg/DlgSettingsGeneral.cpp
+++ b/src/Dlg/DlgSettingsGeneral.cpp
@@ -25,8 +25,8 @@ DlgSettingsGeneral::DlgSettingsGeneral(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("General"),
                            "DlgSettingsGeneral",
                            mainWindow),
-  m_modelGeneralBefore (0),
-  m_modelGeneralAfter (0)
+  m_modelGeneralBefore (nullptr),
+  m_modelGeneralAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGeneral::DlgSettingsGeneral";
 
diff --git a/src/Dlg/DlgSettingsGridDisplay.cpp b/src/Dlg/DlgSettingsGridDisplay.cpp
index 488d7dd7..4b909adf 100644
--- a/src/Dlg/DlgSettingsGridDisplay.cpp
+++ b/src/Dlg/DlgSettingsGridDisplay.cpp
@@ -31,10 +31,18 @@ DlgSettingsGridDisplay::DlgSettingsGridDisplay(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Grid Display"),
                            "DlgSettingsGridDisplay",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelGridDisplayBefore (0),
-  m_modelGridDisplayAfter (0)
+  m_validatorCountX (nullptr),
+  m_validatorStartX (nullptr),
+  m_validatorStepX (nullptr),
+  m_validatorStopX (nullptr),
+  m_validatorCountY (nullptr),
+  m_validatorStartY (nullptr),
+  m_validatorStepY (nullptr),
+  m_validatorStopY (nullptr),  
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelGridDisplayBefore (nullptr),
+  m_modelGridDisplayAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::DlgSettingsGridDisplay";
 
@@ -45,6 +53,15 @@ DlgSettingsGridDisplay::DlgSettingsGridDisplay(MainWindow &mainWindow) :
 DlgSettingsGridDisplay::~DlgSettingsGridDisplay()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::~DlgSettingsGridDisplay";
+
+  delete m_validatorCountX;
+  delete m_validatorStartX;
+  delete m_validatorStepX;
+  delete m_validatorStopX;
+  delete m_validatorCountY;
+  delete m_validatorStartY;
+  delete m_validatorStepY;
+  delete m_validatorStopY;
 }
 
 void DlgSettingsGridDisplay::createDisplayCommon (QGridLayout *layout, int &row)
@@ -136,7 +153,7 @@ void DlgSettingsGridDisplay::createDisplayGridLinesX (QGridLayout *layout, int &
 
   m_editStepX = new QLineEdit;
   m_editStepX->setWhatsThis (tr ("Difference in value between two successive X grid lines.\n\n"
-                                 "The step value must be greater than zero"));
+                                 "The step value must be greater than zero (linear) or one (log)"));
   m_validatorStepX = new QDoubleValidator;
   m_editStepX->setValidator (m_validatorStepX);
   connect (m_editStepX, SIGNAL (textEdited (const QString &)), this, SLOT  (slotStepX (const QString &)));
@@ -212,7 +229,7 @@ void DlgSettingsGridDisplay::createDisplayGridLinesY (QGridLayout *layout, int &
 
   m_editStepY = new QLineEdit;
   m_editStepY->setWhatsThis (tr ("Difference in value between two successive Y grid lines.\n\n"
-                                 "The step value must be greater than zero"));
+                                 "The step value must be greater than zero (linear) or one (log)"));
   m_validatorStepY = new QDoubleValidator;
   m_editStepY->setValidator (m_validatorStepY);
   connect (m_editStepY, SIGNAL (textEdited (const QString &)), this, SLOT  (slotStepY (const QString &)));
@@ -357,7 +374,7 @@ void DlgSettingsGridDisplay::slotColor (QString const &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::slotColor";
 
-  m_modelGridDisplayAfter->setPaletteColor((ColorPalette) m_cmbColor->currentData().toInt());
+  m_modelGridDisplayAfter->setPaletteColor(static_cast<ColorPalette> (m_cmbColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
@@ -366,7 +383,7 @@ void DlgSettingsGridDisplay::slotCountX(const QString &count)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::slotCountX";
 
-  m_modelGridDisplayAfter->setCountX(count.toInt());
+  m_modelGridDisplayAfter->setCountX(unsigned (count.toInt()));
   updateDisplayedVariableX ();
   updateControls ();
   updatePreview();
@@ -376,7 +393,7 @@ void DlgSettingsGridDisplay::slotCountY(const QString &count)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::slotCountY";
 
-  m_modelGridDisplayAfter->setCountY(count.toInt());
+  m_modelGridDisplayAfter->setCountY(unsigned (count.toInt()));
   updateDisplayedVariableY ();
   updateControls ();
   updatePreview();
@@ -386,7 +403,7 @@ void DlgSettingsGridDisplay::slotDisableX(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::slotDisableX";
 
-  GridCoordDisable gridCoordDisable = (GridCoordDisable) m_cmbDisableX->currentData().toInt();
+  GridCoordDisable gridCoordDisable = static_cast<GridCoordDisable> (m_cmbDisableX->currentData().toInt());
   m_modelGridDisplayAfter->setDisableX(gridCoordDisable);
   updateDisplayedVariableX ();
   updateControls();
@@ -397,7 +414,7 @@ void DlgSettingsGridDisplay::slotDisableY(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridDisplay::slotDisableY";
 
-  GridCoordDisable gridCoordDisable = (GridCoordDisable) m_cmbDisableY->currentData().toInt();
+  GridCoordDisable gridCoordDisable = static_cast<GridCoordDisable> (m_cmbDisableY->currentData().toInt());
   m_modelGridDisplayAfter->setDisableY(gridCoordDisable);
   updateDisplayedVariableY ();
   updateControls();
@@ -502,7 +519,7 @@ bool DlgSettingsGridDisplay::textItemsAreValid () const
     double stepX = textCountX.toDouble ();
     double stepY = textCountY.toDouble ();
 
-    if (stepX != 0 && stepY != 0) {
+    if (qAbs (stepX) > 0 && qAbs (stepY) > 0) {
 
       ok = true;
     }
@@ -553,13 +570,13 @@ bool DlgSettingsGridDisplay::textItemsDoNotBreakLineCountLimit ()
 
 void DlgSettingsGridDisplay::updateControls ()
 {
-  GridCoordDisable disableX = (GridCoordDisable) m_cmbDisableX->currentData().toInt();
+  GridCoordDisable disableX = static_cast<GridCoordDisable> (m_cmbDisableX->currentData().toInt());
   m_editCountX->setEnabled (disableX != GRID_COORD_DISABLE_COUNT);
   m_editStartX->setEnabled (disableX != GRID_COORD_DISABLE_START);
   m_editStepX->setEnabled (disableX != GRID_COORD_DISABLE_STEP);
   m_editStopX->setEnabled (disableX != GRID_COORD_DISABLE_STOP);
 
-  GridCoordDisable disableY = (GridCoordDisable) m_cmbDisableY->currentData().toInt();
+  GridCoordDisable disableY = static_cast<GridCoordDisable> (m_cmbDisableY->currentData().toInt());
   m_editCountY->setEnabled (disableY != GRID_COORD_DISABLE_COUNT);
   m_editStartY->setEnabled (disableY != GRID_COORD_DISABLE_START);
   m_editStepY->setEnabled (disableY != GRID_COORD_DISABLE_STEP);
@@ -592,25 +609,21 @@ void DlgSettingsGridDisplay::updateDisplayedVariableX ()
       m_editStartX->setText (QString::number (initializer.computeStart (linearAxis,
                                                                         m_modelGridDisplayAfter->stopX (),
                                                                         m_modelGridDisplayAfter->stepX (),
-                                                                        m_modelGridDisplayAfter->countX ())));
+                                                                        signed (m_modelGridDisplayAfter->countX ()))));
       break;
 
     case GRID_COORD_DISABLE_STEP:
       m_editStepX->setText (QString::number (initializer.computeStep (linearAxis,
                                                                       m_modelGridDisplayAfter->startX (),
                                                                       m_modelGridDisplayAfter->stopX (),
-                                                                      m_modelGridDisplayAfter->countX ())));
+                                                                      signed (m_modelGridDisplayAfter->countX ()))));
       break;
 
     case GRID_COORD_DISABLE_STOP:
       m_editStopX->setText (QString::number (initializer.computeStop (linearAxis,
                                                                       m_modelGridDisplayAfter->startX (),
                                                                       m_modelGridDisplayAfter->stepX (),
-                                                                      m_modelGridDisplayAfter->countX ())));
-      break;
-
-    default:
-      LOG4CPP_ERROR_S ((*mainCat)) << "DlgSettingsGridDisplay::updateDisplayedVariableX";
+                                                                      signed (m_modelGridDisplayAfter->countX ()))));
       break;
   }
 }
@@ -633,25 +646,21 @@ void DlgSettingsGridDisplay::updateDisplayedVariableY ()
       m_editStartY->setText (QString::number (initializer.computeStart (linearAxis,
                                                                         m_modelGridDisplayAfter->stopY (),
                                                                         m_modelGridDisplayAfter->stepY (),
-                                                                        m_modelGridDisplayAfter->countY ())));
+                                                                        signed (m_modelGridDisplayAfter->countY ()))));
       break;
 
     case GRID_COORD_DISABLE_STEP:
       m_editStepY->setText (QString::number (initializer.computeStep (linearAxis,
                                                                       m_modelGridDisplayAfter->startY (),
                                                                       m_modelGridDisplayAfter->stopY (),
-                                                                      m_modelGridDisplayAfter->countY ())));
+                                                                      signed (m_modelGridDisplayAfter->countY ()))));
       break;
 
     case GRID_COORD_DISABLE_STOP:
       m_editStopY->setText (QString::number (initializer.computeStop (linearAxis,
                                                                       m_modelGridDisplayAfter->startY (),
                                                                       m_modelGridDisplayAfter->stepY (),
-                                                                      m_modelGridDisplayAfter->countY ())));
-      break;
-
-    default:
-      LOG4CPP_ERROR_S ((*mainCat)) << "DlgSettingsGridDisplay::updateDisplayedVariableY";
+                                                                      signed (m_modelGridDisplayAfter->countY ()))));
       break;
   }
 }
diff --git a/src/Dlg/DlgSettingsGridRemoval.cpp b/src/Dlg/DlgSettingsGridRemoval.cpp
index 3a465d97..fb89d9c3 100644
--- a/src/Dlg/DlgSettingsGridRemoval.cpp
+++ b/src/Dlg/DlgSettingsGridRemoval.cpp
@@ -36,10 +36,19 @@ DlgSettingsGridRemoval::DlgSettingsGridRemoval(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Grid Removal"),
                            "DlgSettingsGridRemoval",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelGridRemovalBefore (0),
-  m_modelGridRemovalAfter (0)
+  m_validatorCloseDistance (nullptr),
+  m_validatorCountX (nullptr),
+  m_validatorStartX (nullptr),
+  m_validatorStepX (nullptr),
+  m_validatorStopX (nullptr),      
+  m_validatorCountY (nullptr),
+  m_validatorStartY (nullptr),
+  m_validatorStepY (nullptr),
+  m_validatorStopY (nullptr),  
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelGridRemovalBefore (nullptr),
+  m_modelGridRemovalAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridRemoval::DlgSettingsGridRemoval";
 
@@ -50,6 +59,16 @@ DlgSettingsGridRemoval::DlgSettingsGridRemoval(MainWindow &mainWindow) :
 DlgSettingsGridRemoval::~DlgSettingsGridRemoval()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridRemoval::~DlgSettingsGridRemoval";
+
+  delete m_validatorCloseDistance;
+  delete m_validatorCountX;
+  delete m_validatorStartX;
+  delete m_validatorStepX;
+  delete m_validatorStopX;      
+  delete m_validatorCountY;
+  delete m_validatorStartY;
+  delete m_validatorStepY;
+  delete m_validatorStopY;
 }
 
 void DlgSettingsGridRemoval::createOptionalSaveDefault (QHBoxLayout * /* layout */)
@@ -161,7 +180,7 @@ void DlgSettingsGridRemoval::createRemoveGridLinesX (QGridLayout *layout, int &r
 
   m_editStepX = new QLineEdit;
   m_editStepX->setWhatsThis (tr ("Difference in value between two successive X grid lines.\n\n"
-                                 "The step value must be greater than zero"));
+                                 "The step value must be greater than zero (linear) or one (log)"));
   m_validatorStepX = new QDoubleValidator;
   m_editStepX->setValidator (m_validatorStepX);
   connect (m_editStepX, SIGNAL (textChanged (const QString &)), this, SLOT  (slotStepX (const QString &)));
@@ -239,7 +258,7 @@ void DlgSettingsGridRemoval::createRemoveGridLinesY (QGridLayout *layout, int &r
 
   m_editStepY = new QLineEdit;
   m_editStepY->setWhatsThis (tr ("Difference in value between two successive Y grid lines.\n\n"
-                                 "The step value must be greater than zero"));
+                                 "The step value must be greater than zero (linear) or one (log)"));
   m_validatorStepY = new QDoubleValidator;
   m_editStepY->setValidator (m_validatorStepY);
   connect (m_editStepY, SIGNAL (textChanged (const QString &)), this, SLOT  (slotStepY (const QString &)));
@@ -378,7 +397,7 @@ void DlgSettingsGridRemoval::slotDisableX(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridRemoval::slotDisableX";
 
-  GridCoordDisable gridCoordDisable = (GridCoordDisable) m_cmbDisableX->currentData().toInt();
+  GridCoordDisable gridCoordDisable = static_cast<GridCoordDisable> (m_cmbDisableX->currentData().toInt());
   m_modelGridRemovalAfter->setGridCoordDisableX(gridCoordDisable);
   updateDisplayedVariableX ();
   updateControls();
@@ -389,7 +408,7 @@ void DlgSettingsGridRemoval::slotDisableY(const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsGridRemoval::slotDisableY";
 
-  GridCoordDisable gridCoordDisable = (GridCoordDisable) m_cmbDisableY->currentData().toInt();
+  GridCoordDisable gridCoordDisable = static_cast<GridCoordDisable> (m_cmbDisableY->currentData().toInt());
   m_modelGridRemovalAfter->setGridCoordDisableY(gridCoordDisable);
   updateDisplayedVariableY ();
   updateControls();
@@ -471,7 +490,7 @@ void DlgSettingsGridRemoval::updateControls ()
 
   m_cmbDisableX->setEnabled (m_chkRemoveGridLines->isChecked ());
 
-  GridCoordDisable disableX = (GridCoordDisable) m_cmbDisableX->currentData().toInt();
+  GridCoordDisable disableX = static_cast<GridCoordDisable> (m_cmbDisableX->currentData().toInt());
   m_editCountX->setEnabled (m_chkRemoveGridLines->isChecked () && (disableX != GRID_COORD_DISABLE_COUNT));
   m_editStartX->setEnabled (m_chkRemoveGridLines->isChecked () && (disableX != GRID_COORD_DISABLE_START));
   m_editStepX->setEnabled (m_chkRemoveGridLines->isChecked () && (disableX != GRID_COORD_DISABLE_STEP));
@@ -479,7 +498,7 @@ void DlgSettingsGridRemoval::updateControls ()
 
   m_cmbDisableY->setEnabled (m_chkRemoveGridLines->isChecked ());
 
-  GridCoordDisable disableY = (GridCoordDisable) m_cmbDisableY->currentData().toInt();
+  GridCoordDisable disableY = static_cast<GridCoordDisable> (m_cmbDisableY->currentData().toInt());
   m_editCountY->setEnabled (m_chkRemoveGridLines->isChecked () && (disableY != GRID_COORD_DISABLE_COUNT));
   m_editStartY->setEnabled (m_chkRemoveGridLines->isChecked () && (disableY != GRID_COORD_DISABLE_START));
   m_editStepY->setEnabled (m_chkRemoveGridLines->isChecked () && (disableY != GRID_COORD_DISABLE_STEP));
@@ -542,10 +561,6 @@ void DlgSettingsGridRemoval::updateDisplayedVariableX ()
                                                                       m_modelGridRemovalAfter->stepX (),
                                                                       m_modelGridRemovalAfter->countX ())));
       break;
-
-    default:
-      LOG4CPP_ERROR_S ((*mainCat)) << "DlgSettingsGridRemoval::updateDisplayedVariableX";
-      break;
   }
 }
 
@@ -583,10 +598,6 @@ void DlgSettingsGridRemoval::updateDisplayedVariableY ()
                                                                       m_modelGridRemovalAfter->stepY (),
                                                                       m_modelGridRemovalAfter->countY ())));
       break;
-
-    default:
-      LOG4CPP_ERROR_S ((*mainCat)) << "DlgSettingsGridRemoval::updateDisplayedVariableY";
-      break;
   }
 }
 
diff --git a/src/Dlg/DlgSettingsMainWindow.cpp b/src/Dlg/DlgSettingsMainWindow.cpp
index d8f345c0..f66dafd8 100644
--- a/src/Dlg/DlgSettingsMainWindow.cpp
+++ b/src/Dlg/DlgSettingsMainWindow.cpp
@@ -11,8 +11,10 @@
 #include "Logger.h"
 #include "MainWindow.h"
 #include "MainWindowModel.h"
+#include <QApplication>
 #include <QCheckBox>
 #include <QComboBox>
+#include <QDir>
 #include <QDoubleSpinBox>
 #include <QGraphicsScene>
 #include <QGridLayout>
@@ -22,6 +24,7 @@
 #include <QPushButton>
 #include <QSpinBox>
 #include "QtToString.h"
+#include "TranslatorContainer.h"
 #include "ZoomControl.h"
 #include "ZoomFactorInitial.h"
 #include "ZoomLabels.h"
@@ -40,8 +43,8 @@ DlgSettingsMainWindow::DlgSettingsMainWindow(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Main Window"),
                            "DlgSettingsMainWindow",
                            mainWindow),
-  m_modelMainWindowBefore (0),
-  m_modelMainWindowAfter (0)
+  m_modelMainWindowBefore (nullptr),
+  m_modelMainWindowAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::DlgSettingsMainWindow";
 
@@ -66,17 +69,17 @@ void DlgSettingsMainWindow::createControls (QGridLayout *layout,
   layout->addWidget (labelZoomFactor, row, 1);
 
   m_cmbZoomFactor = new QComboBox;
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_16_TO_1  , QVariant (ZOOM_INITIAL_16_TO_1));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_8_TO_1   , QVariant (ZOOM_INITIAL_8_TO_1));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_4_TO_1   , QVariant (ZOOM_INITIAL_4_TO_1));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_2_TO_1   , QVariant (ZOOM_INITIAL_2_TO_1));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_1_TO_1   , QVariant (ZOOM_INITIAL_1_TO_1));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_1_TO_2   , QVariant (ZOOM_INITIAL_1_TO_2));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_1_TO_4   , QVariant (ZOOM_INITIAL_1_TO_4));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_1_TO_8   , QVariant (ZOOM_INITIAL_1_TO_8));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_1_TO_16  , QVariant (ZOOM_INITIAL_1_TO_16));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_FILL     , QVariant (ZOOM_INITIAL_FILL));
-  m_cmbZoomFactor->addItem (LABEL_ZOOM_PREVIOUS , QVariant (ZOOM_INITIAL_PREVIOUS));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_16_TO_1  , QVariant (ZOOM_INITIAL_16_TO_1));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_8_TO_1   , QVariant (ZOOM_INITIAL_8_TO_1));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_4_TO_1   , QVariant (ZOOM_INITIAL_4_TO_1));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_2_TO_1   , QVariant (ZOOM_INITIAL_2_TO_1));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_1_TO_1   , QVariant (ZOOM_INITIAL_1_TO_1));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_1_TO_2   , QVariant (ZOOM_INITIAL_1_TO_2));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_1_TO_4   , QVariant (ZOOM_INITIAL_1_TO_4));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_1_TO_8   , QVariant (ZOOM_INITIAL_1_TO_8));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_1_TO_16  , QVariant (ZOOM_INITIAL_1_TO_16));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_FILL     , QVariant (ZOOM_INITIAL_FILL));
+  m_cmbZoomFactor->addItem (*LABEL_ZOOM_PREVIOUS , QVariant (ZOOM_INITIAL_PREVIOUS));
   m_cmbZoomFactor->setWhatsThis(tr ("Initial Zoom\n\n"
                                     "Select the initial zoom factor when a new document is loaded. Either the previous "
                                     "zoom can be kept, or the specified zoom can be applied."));
@@ -96,7 +99,7 @@ void DlgSettingsMainWindow::createControls (QGridLayout *layout,
   connect (m_cmbZoomControl, SIGNAL (currentTextChanged (const QString)), this, SLOT (slotZoomControl(const QString)));
   layout->addWidget (m_cmbZoomControl, row++, 2);
 
-  QLabel *labelLocale = new QLabel (QString ("%1:").arg (tr ("Locale")));
+  QLabel *labelLocale = new QLabel (QString ("%1:").arg (tr ("Locale (requires restart)")));
   layout->addWidget (labelLocale, row, 1);
 
   // Initialization of combobox is liberated from Qt Calendar example
@@ -107,15 +110,15 @@ void DlgSettingsMainWindow::createControls (QGridLayout *layout,
                                 "The locale determines how numbers are formatted. Specifically, either commas or "
                                 "periods will be used as group delimiters in each number entered "
                                 "by the user, displayed in the user interface, or exported to a file."));
-  for (int indexLang = QLocale::C; indexLang <= QLocale::LastLanguage; indexLang++) {
-    QLocale::Language lang = static_cast<QLocale::Language> (indexLang);
-    QList<QLocale::Country> countries = QLocale::countriesForLanguage(lang);
-    for (int indexCountry = 0; indexCountry < countries.count(); indexCountry++) {
-      QLocale::Country country = countries.at(indexCountry);
-      QLocale locale (lang, country);
-      QString label = QLocaleToString (locale);
-      m_cmbLocale->addItem (label, locale);
-    }
+  QStringList qmFilenames;
+  qmFilenames << gatherQmFilenames ();
+  for (int i = 0; i < qmFilenames.size(); i++) {
+    QString localeSelector = qmFilenames [i]; // "engauge_de.qm"
+    localeSelector.truncate (localeSelector.lastIndexOf ('.')); // "engauge_de"
+    localeSelector.remove (0, localeSelector.indexOf ('_') + 1); // "de"
+    QLocale locale (localeSelector);
+    QString label = QLocaleToString (locale);
+    m_cmbLocale->addItem (label, locale);
   }
   m_cmbLocale->model()->sort(COLUMN0); // Sort the new entries
   connect (m_cmbLocale, SIGNAL (currentIndexChanged (int)), this, SLOT (slotLocale (int)));
@@ -225,6 +228,17 @@ void DlgSettingsMainWindow::createControls (QGridLayout *layout,
   connect (m_chkDragDropExport, SIGNAL (toggled (bool)), this, SLOT (slotDragDropExport (bool)));
   layout->addWidget (m_chkDragDropExport, row++, 2);
 
+  QLabel *labelImageReplaceRenamesDocument = new QLabel (QString ("%1:").arg (tr ("Image replace renames document")));
+  layout->addWidget (labelImageReplaceRenamesDocument, row, 1);
+
+  m_chkImageReplaceRenamesDocument = new QCheckBox;
+  m_chkImageReplaceRenamesDocument->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
+  m_chkImageReplaceRenamesDocument->setWhatsThis (tr ("Image Replace Renames Document\n\n"
+                                                      "When an image is imported to replace the current image, the document "
+                                                      "will be renamed if this is true, otherwise the name will stay the same."));
+  connect (m_chkImageReplaceRenamesDocument, SIGNAL (toggled (bool)), this, SLOT (slotImageReplaceRenamesDocument (bool)));
+  layout->addWidget (m_chkImageReplaceRenamesDocument, row++, 2);
+
   QLabel *labelSignificantDigits = new QLabel (QString ("%1:").arg (tr ("Significant digits")));
   layout->addWidget (labelSignificantDigits, row, 1);
 
@@ -264,6 +278,16 @@ QWidget *DlgSettingsMainWindow::createSubPanel ()
   return subPanel;
 }
 
+QStringList DlgSettingsMainWindow::gatherQmFilenames () const
+{
+  // Get available locales. The static QLocale::matchingLocales gives the few available translations
+  // but also the many unavailable translations. We use a list of translation files to see what is available
+  QDir translationPath (TranslatorContainer::qmDirectory ());
+  QStringList filenames = translationPath.entryList (QStringList ("engauge_*.qm"));
+
+  return filenames;
+}
+
 void DlgSettingsMainWindow::handleOk ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::handleOk";
@@ -272,6 +296,7 @@ void DlgSettingsMainWindow::handleOk ()
 
   hide ();
 }
+
 void DlgSettingsMainWindow::load (CmdMediator & /* cmdMediator */)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::load";
@@ -301,6 +326,11 @@ void DlgSettingsMainWindow::loadMainWindowModel (CmdMediator &cmdMediator,
   m_cmbZoomControl->setCurrentIndex (index);
   QString locLabel = QLocaleToString (m_modelMainWindowAfter->locale());
   index = m_cmbLocale->findText (locLabel);
+  if (index < 0) {
+    // Somehow an invalid locale is selected. Fix it by setting to default
+    locLabel = QLocaleToString (QLocale::system().name());
+    index = m_cmbLocale->findText (locLabel);
+  }
   m_cmbLocale->setCurrentIndex(index);
   index = m_cmbImportCropping->findData (m_modelMainWindowAfter->importCropping());
   m_cmbImportCropping->setCurrentIndex (index);
@@ -314,6 +344,7 @@ void DlgSettingsMainWindow::loadMainWindowModel (CmdMediator &cmdMediator,
   m_chkSmallDialogs->setChecked (m_modelMainWindowAfter->smallDialogs());
   m_chkDragDropExport->setChecked (m_modelMainWindowAfter->dragDropExport());
   m_spinSignificantDigits->setValue (m_modelMainWindowAfter->significantDigits ());
+  m_chkImageReplaceRenamesDocument->setChecked (m_modelMainWindowAfter->imageReplaceRenamesDocument());
 
   updateControls ();
   enableOk (false); // Disable Ok button since there not yet any changes
@@ -339,11 +370,19 @@ void DlgSettingsMainWindow::slotHighlightOpacity(double)
   updateControls();
 }
 
+void DlgSettingsMainWindow::slotImageReplaceRenamesDocument (bool)
+{
+  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotImageReplaceRenamesDocument";
+
+  m_modelMainWindowAfter->setImageReplaceRenamesDocument (m_chkImageReplaceRenamesDocument->isChecked());
+  updateControls ();
+}
+
 void DlgSettingsMainWindow::slotImportCropping (int index)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotImportCropping";
 
-  m_modelMainWindowAfter->setImportCropping ((ImportCropping) m_cmbImportCropping->itemData (index).toInt ());
+  m_modelMainWindowAfter->setImportCropping (static_cast<ImportCropping> (m_cmbImportCropping->itemData (index).toInt ()));
   updateControls();
 }
 
@@ -351,7 +390,9 @@ void DlgSettingsMainWindow::slotLocale (int index)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotLocale";
 
-  m_modelMainWindowAfter->setLocale (m_cmbLocale->itemData (index).toLocale());
+  QLocale locale = m_cmbLocale->itemData (index).toLocale();
+
+  m_modelMainWindowAfter->setLocale (locale);
   updateControls();
 }
 
@@ -411,7 +452,7 @@ void DlgSettingsMainWindow::slotZoomControl(const QString)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWindow::slotZoomControl";
 
-  m_modelMainWindowAfter->setZoomControl ((ZoomControl) m_cmbZoomControl->currentData().toInt());
+  m_modelMainWindowAfter->setZoomControl (static_cast<ZoomControl> (m_cmbZoomControl->currentData().toInt()));
   updateControls();
 }
 
@@ -419,7 +460,7 @@ void DlgSettingsMainWindow::slotZoomFactor(const QString)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsMainWIndow::slotZoomFactor";
 
-  m_modelMainWindowAfter->setZoomFactorInitial((ZoomFactorInitial) m_cmbZoomFactor->currentData().toInt());
+  m_modelMainWindowAfter->setZoomFactorInitial(static_cast<ZoomFactorInitial> (m_cmbZoomFactor->currentData().toInt()));
   updateControls();
 }
 
diff --git a/src/Dlg/DlgSettingsMainWindow.h b/src/Dlg/DlgSettingsMainWindow.h
index a09a440d..1af0b66f 100644
--- a/src/Dlg/DlgSettingsMainWindow.h
+++ b/src/Dlg/DlgSettingsMainWindow.h
@@ -9,6 +9,8 @@
 
 #include "DlgSettingsAbstractBase.h"
 #include <QLocale>
+#include <QString>
+#include <QStringList>
 
 class QCheckBox;
 class QComboBox;
@@ -40,6 +42,7 @@ public:
 private slots:
   void slotDragDropExport (bool);
   void slotHighlightOpacity (double);
+  void slotImageReplaceRenamesDocument (bool);
   void slotImportCropping (int index);
   void slotLocale (int index);
   void slotMaximumGridLines (int limit);
@@ -58,6 +61,7 @@ private:
 
   void createControls (QGridLayout *layout,
                        int &row);
+  QStringList gatherQmFilenames () const;
   void updateControls();
 
   QComboBox *m_cmbZoomFactor;
@@ -72,6 +76,7 @@ private:
   QCheckBox *m_chkSmallDialogs;
   QCheckBox *m_chkDragDropExport;
   QSpinBox *m_spinSignificantDigits;
+  QCheckBox *m_chkImageReplaceRenamesDocument;
 
   MainWindowModel *m_modelMainWindowBefore;
   MainWindowModel *m_modelMainWindowAfter;
diff --git a/src/Dlg/DlgSettingsPointMatch.cpp b/src/Dlg/DlgSettingsPointMatch.cpp
index 185ca5d9..a720217a 100644
--- a/src/Dlg/DlgSettingsPointMatch.cpp
+++ b/src/Dlg/DlgSettingsPointMatch.cpp
@@ -30,11 +30,11 @@ DlgSettingsPointMatch::DlgSettingsPointMatch(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Point Match"),
                            "DlgSettingsPointMatch",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_circle (0),
-  m_modelPointMatchBefore (0),
-  m_modelPointMatchAfter (0)
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_circle (nullptr),
+  m_modelPointMatchBefore (nullptr),
+  m_modelPointMatchAfter (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::DlgSettingsPointMatch";
 
@@ -223,7 +223,7 @@ void DlgSettingsPointMatch::load (CmdMediator &cmdMediator)
   ENGAUGE_ASSERT (POINT_SIZE_MAX > m_modelPointMatchAfter->maxPointSize());
 
   // Populate controls
-  m_spinPointSize->setValue(m_modelPointMatchAfter->maxPointSize());
+  m_spinPointSize->setValue(qFloor (m_modelPointMatchAfter->maxPointSize()));
 
   int indexAccepted = m_cmbAcceptedPointColor->findData(QVariant(m_modelPointMatchAfter->paletteColorAccepted()));
   ENGAUGE_ASSERT (indexAccepted >= 0);
@@ -271,7 +271,7 @@ void DlgSettingsPointMatch::slotAcceptedPointColor (const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotAcceptedPointColor";
 
-  m_modelPointMatchAfter->setPaletteColorAccepted((ColorPalette) m_cmbAcceptedPointColor->currentData().toInt());
+  m_modelPointMatchAfter->setPaletteColorAccepted(static_cast<ColorPalette> (m_cmbAcceptedPointColor->currentData().toInt()));
 
   updateControls();
   updatePreview();
@@ -281,7 +281,7 @@ void DlgSettingsPointMatch::slotCandidatePointColor (const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotCandidatePointColor";
 
-  m_modelPointMatchAfter->setPaletteColorCandidate((ColorPalette) m_cmbCandidatePointColor->currentData().toInt());
+  m_modelPointMatchAfter->setPaletteColorCandidate(static_cast<ColorPalette> (m_cmbCandidatePointColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
@@ -308,7 +308,7 @@ void DlgSettingsPointMatch::slotRejectedPointColor (const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotRejectedPointColor";
 
-  m_modelPointMatchAfter->setPaletteColorRejected((ColorPalette) m_cmbRejectedPointColor->currentData().toInt());
+  m_modelPointMatchAfter->setPaletteColorRejected(static_cast<ColorPalette> (m_cmbRejectedPointColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
diff --git a/src/Dlg/DlgSettingsSegments.cpp b/src/Dlg/DlgSettingsSegments.cpp
index e68ddea9..5f6a23ca 100644
--- a/src/Dlg/DlgSettingsSegments.cpp
+++ b/src/Dlg/DlgSettingsSegments.cpp
@@ -40,10 +40,10 @@ DlgSettingsSegments::DlgSettingsSegments(MainWindow &mainWindow) :
   DlgSettingsAbstractBase (tr ("Segment Fill"),
                            "DlgSettingsSegments",
                            mainWindow),
-  m_scenePreview (0),
-  m_viewPreview (0),
-  m_modelSegmentsBefore (0),
-  m_modelSegmentsAfter (0),
+  m_scenePreview (nullptr),
+  m_viewPreview (nullptr),
+  m_modelSegmentsBefore (nullptr),
+  m_modelSegmentsAfter (nullptr),
   m_loading (false)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::DlgSettingsSegments";
@@ -170,15 +170,15 @@ QImage DlgSettingsSegments::createPreviewImage () const
   int margin = IMAGE_WIDTH / 15;
   int yCenter = IMAGE_HEIGHT / 2;
   int yHeight = IMAGE_HEIGHT / 4;
-  int x, y, xLast, yLast;
+  int x, y, xLast = 0, yLast = 0;
   bool isFirst;
 
   // Draw sinusoid
   isFirst = true;
   int xStart = margin, xEnd = IMAGE_WIDTH / 2 - margin;
   for (x = xStart; x < xEnd; x++) {
-    double s = (double) (x - xStart) / (double) (xEnd - xStart);
-    int y = yCenter - yHeight * qSin (TWOPI * s);
+    double s = double (x - xStart) / double (xEnd - xStart);
+    int y = qFloor (yCenter - yHeight * qSin (TWOPI * s));
 
     if (!isFirst) {
       painter.drawLine (xLast, yLast, x, y);
@@ -190,15 +190,16 @@ QImage DlgSettingsSegments::createPreviewImage () const
 
   // Draw triangular waveform that looks like sinusoid straightened up into line segments
   isFirst = true;
-  xStart = IMAGE_WIDTH / 2 + margin, xEnd = IMAGE_WIDTH - margin;
+  xStart = IMAGE_WIDTH / 2 + margin;
+  xEnd = IMAGE_WIDTH - margin;
   for (x = xStart; x < xEnd; x++) {
-    double s = (double) (x - xStart) / (double) (xEnd - xStart);
+    double s = double (x - xStart) / double (xEnd - xStart);
     if (s <= 0.25) {
-      y = yCenter - yHeight * (4.0 * s);
+      y = qFloor (yCenter - yHeight * (4.0 * s));
     } else if (s < 0.75) {
-      y = yCenter - yHeight * (1.0 - 4.0 * (s - 0.25));
+      y = qFloor (yCenter - yHeight * (1.0 - 4.0 * (s - 0.25)));
     } else {
-      y = yCenter + yHeight * (1.0 - 4 * (s - 0.75));
+      y = qFloor (yCenter + yHeight * (1.0 - 4 * (s - 0.75)));
     }
 
     if (!isFirst) {
@@ -271,10 +272,10 @@ void DlgSettingsSegments::load (CmdMediator &cmdMediator)
   ENGAUGE_ASSERT (POINT_SEPARATION_MAX >= m_modelSegmentsAfter->pointSeparation());
 
   // Populate controls
-  m_spinPointSeparation->setValue (m_modelSegmentsAfter->pointSeparation());
-  m_spinMinLength->setValue (m_modelSegmentsAfter->minLength());
+  m_spinPointSeparation->setValue (qFloor (m_modelSegmentsAfter->pointSeparation()));
+  m_spinMinLength->setValue (qFloor (m_modelSegmentsAfter->minLength()));
   m_chkFillCorners->setChecked (m_modelSegmentsAfter->fillCorners ());
-  m_spinLineWidth->setValue (m_modelSegmentsAfter->lineWidth());
+  m_spinLineWidth->setValue (qFloor (m_modelSegmentsAfter->lineWidth()));
 
   int indexLineColor = m_cmbLineColor->findData(QVariant (m_modelSegmentsAfter->lineColor()));
   ENGAUGE_ASSERT (indexLineColor >= 0);
@@ -308,7 +309,7 @@ void DlgSettingsSegments::slotLineColor (const QString &)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsSegments::slotLineColor";
 
-  m_modelSegmentsAfter->setLineColor((ColorPalette) m_cmbLineColor->currentData().toInt());
+  m_modelSegmentsAfter->setLineColor(static_cast<ColorPalette> (m_cmbLineColor->currentData().toInt()));
   updateControls();
   updatePreview();
 }
@@ -353,7 +354,8 @@ void DlgSettingsSegments::updatePreview()
   const QString ARBITRARY_IDENTIFIER ("");
   const QColor COLOR (Qt::blue);
   const int RADIUS = 5;
-  GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
+  GeometryWindow *NULL_GEOMETRY_WINDOW = nullptr;
+  const bool NO_DIALOG = false; // If true then dueling modal dialogs will trigger infinite loops in QSpinBox up/down
 
   if (!m_loading) {
 
@@ -366,7 +368,8 @@ void DlgSettingsSegments::updatePreview()
     // Create new segments
     segmentFactory.makeSegments (createPreviewImage(),
                                  *m_modelSegmentsAfter,
-                                 m_segments);
+                                 m_segments,
+                                 NO_DIALOG);
 
     // Make the segment visible
     QList<Segment*>::iterator itrS;
@@ -378,11 +381,12 @@ void DlgSettingsSegments::updatePreview()
     // Create some points
     PointStyle pointStyle (POINT_SHAPE_CROSS,
                            RADIUS,
-                           BRUSH_WIDTH,
+                           qFloor (BRUSH_WIDTH),
                            COLOR_PALETTE_BLUE);
     QPolygonF polygon = pointStyle.polygon();
     QList<QPoint> points = segmentFactory.fillPoints (*m_modelSegmentsAfter,
                                                       m_segments);
+
     QList<QPoint>::iterator itrP;
     for (itrP = points.begin(); itrP != points.end(); itrP++) {
       QPoint pos = *itrP;
diff --git a/src/Document/Document.cpp b/src/Document/Document.cpp
index 6c06d56d..c900ac55 100644
--- a/src/Document/Document.cpp
+++ b/src/Document/Document.cpp
@@ -47,6 +47,8 @@ const int VERSION_7 = 7;
 const int VERSION_8 = 8;
 const int VERSION_9 = 9;
 const int VERSION_10 = 10;
+const int VERSION_11 = 11;
+const int VERSION_12 = 12;
 
 Document::Document (const QImage &image) :
   m_name ("untitled"),
@@ -72,11 +74,11 @@ Document::Document (const QString &fileName) :
   m_successfulRead = true;
 
   // Grab first few bytes to determine the version number
-  QFile *file = new QFile (fileName);
-  if (file->open(QIODevice::ReadOnly)) {
+  QFile fileVersion (fileName);
+  if (fileVersion.open(QIODevice::ReadOnly)) {
 
-    QByteArray bytesStart = file->read (FOUR_BYTES);
-    file->close ();
+    QByteArray bytesStart = fileVersion.read (FOUR_BYTES);
+    fileVersion.close ();
 
     if (bytesIndicatePreVersion6 (bytesStart)) {
 
@@ -109,6 +111,8 @@ Document::Document (const QString &fileName) :
           case VERSION_8:
           case VERSION_9:
           case VERSION_10:
+          case VERSION_11:
+          case VERSION_12:
             loadVersions7AndUp (file);
             break;
 
@@ -125,7 +129,7 @@ Document::Document (const QString &fileName) :
         // Close and deactivate
         file->close ();
         delete file;
-        file = 0;
+        file = nullptr;
 
       } else {
 
@@ -134,7 +138,7 @@ Document::Document (const QString &fileName) :
       }
     }
   } else {
-    file->close ();
+    fileVersion.close ();
     m_successfulRead = false;
     m_reasonForUnsuccessfulRead = QString ("%1 '%2' %3")
                                   .arg (QObject::tr ("File"))
@@ -411,7 +415,8 @@ void Document::initializeGridDisplay (const Transformation &transformation)
   ENGAUGE_ASSERT (!m_coordSystemContext.modelGridDisplay().stable());
 
   // Get graph coordinate bounds
-  CallbackBoundingRects ftor (transformation);
+  CallbackBoundingRects ftor (m_documentAxesPointsRequired,
+                              transformation);
 
   Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
                                                                                                      &CallbackBoundingRects::callback);
@@ -420,12 +425,14 @@ void Document::initializeGridDisplay (const Transformation &transformation)
 
   // Initialize. Note that if there are no graph points then these next steps have no effect
   bool isEmpty;
-  QRectF boundingRectGraph =  ftor.boundingRectGraph(isEmpty);
+  QPointF boundingRectGraphMin = ftor.boundingRectGraphMin (isEmpty);
+  QPointF boundingRectGraphMax = ftor.boundingRectGraphMax (isEmpty);
   if (!isEmpty) {
 
     GridInitializer gridInitializer;
 
-    DocumentModelGridDisplay modelGridDisplay = gridInitializer.initializeWithWidePolarCoverage (boundingRectGraph,
+    DocumentModelGridDisplay modelGridDisplay = gridInitializer.initializeWithWidePolarCoverage (boundingRectGraphMin,
+                                                                                                 boundingRectGraphMax,
                                                                                                  modelCoords(),
                                                                                                  transformation,
                                                                                                  m_pixmap.size ());
@@ -633,7 +640,7 @@ void Document::loadVersions7AndUp (QFile *file)
 
       QXmlStreamAttributes attributes = reader.attributes();
       if (attributes.hasAttribute (DOCUMENT_SERIALIZE_AXES_POINTS_REQUIRED)) {
-        m_documentAxesPointsRequired = (DocumentAxesPointsRequired) attributes.value (DOCUMENT_SERIALIZE_AXES_POINTS_REQUIRED).toInt();
+        m_documentAxesPointsRequired = static_cast<DocumentAxesPointsRequired> (attributes.value (DOCUMENT_SERIALIZE_AXES_POINTS_REQUIRED).toInt());
       } else {
         m_documentAxesPointsRequired = DOCUMENT_AXES_POINTS_REQUIRED_3;
       }
@@ -1081,7 +1088,7 @@ int Document::versionFromFile (QFile *file) const
       if (attributes.contains (DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER)) {
 
         QDomElement elem = node.toElement();
-        version = (int) elem.attribute (DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER).toDouble();
+        version = qFloor (elem.attribute (DOCUMENT_SERIALIZE_APPLICATION_VERSION_NUMBER).toDouble());
       }
     }
   }
diff --git a/src/Document/DocumentModelAxesChecker.cpp b/src/Document/DocumentModelAxesChecker.cpp
index 27b9413d..e7f73afa 100644
--- a/src/Document/DocumentModelAxesChecker.cpp
+++ b/src/Document/DocumentModelAxesChecker.cpp
@@ -77,9 +77,9 @@ void DocumentModelAxesChecker::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_AXES_CHECKER_SECONDS) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_AXES_CHECKER_LINE_COLOR)) {
 
-    setCheckerMode ((CheckerMode) attributes.value(DOCUMENT_SERIALIZE_AXES_CHECKER_MODE).toInt());
+    setCheckerMode (static_cast<CheckerMode> (attributes.value(DOCUMENT_SERIALIZE_AXES_CHECKER_MODE).toInt()));
     setCheckerSeconds (attributes.value(DOCUMENT_SERIALIZE_AXES_CHECKER_SECONDS).toInt());
-    setLineColor ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_AXES_CHECKER_LINE_COLOR).toInt());
+    setLineColor (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_AXES_CHECKER_LINE_COLOR).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
diff --git a/src/Document/DocumentModelCoords.cpp b/src/Document/DocumentModelCoords.cpp
index 7c3cc9ef..a970734d 100644
--- a/src/Document/DocumentModelCoords.cpp
+++ b/src/Document/DocumentModelCoords.cpp
@@ -146,16 +146,16 @@ void DocumentModelCoords::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_COORDS_UNITS_DATE) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_COORDS_UNITS_TIME)) {
 
-    setCoordsType ((CoordsType) attributes.value(DOCUMENT_SERIALIZE_COORDS_TYPE).toInt());
+    setCoordsType (static_cast<CoordsType> (attributes.value(DOCUMENT_SERIALIZE_COORDS_TYPE).toInt()));
     setOriginRadius (attributes.value(DOCUMENT_SERIALIZE_COORDS_ORIGIN_RADIUS).toDouble());
-    setCoordScaleXTheta ((CoordScale) attributes.value(DOCUMENT_SERIALIZE_COORDS_SCALE_X_THETA).toInt());
-    setCoordScaleYRadius ((CoordScale) attributes.value(DOCUMENT_SERIALIZE_COORDS_SCALE_Y_RADIUS).toInt());
-    setCoordUnitsX ((CoordUnitsNonPolarTheta) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_X).toInt());
-    setCoordUnitsY ((CoordUnitsNonPolarTheta) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_Y).toInt());
-    setCoordUnitsTheta ((CoordUnitsPolarTheta) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_THETA).toInt());
-    setCoordUnitsRadius ((CoordUnitsNonPolarTheta) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_RADIUS).toInt());
-    setCoordUnitsDate ((CoordUnitsDate) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_DATE).toInt());
-    setCoordUnitsTime ((CoordUnitsTime) attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_TIME).toInt());
+    setCoordScaleXTheta (static_cast<CoordScale> (attributes.value(DOCUMENT_SERIALIZE_COORDS_SCALE_X_THETA).toInt()));
+    setCoordScaleYRadius (static_cast<CoordScale> (attributes.value(DOCUMENT_SERIALIZE_COORDS_SCALE_Y_RADIUS).toInt()));
+    setCoordUnitsX (static_cast<CoordUnitsNonPolarTheta> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_X).toInt()));
+    setCoordUnitsY (static_cast<CoordUnitsNonPolarTheta> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_Y).toInt()));
+    setCoordUnitsTheta (static_cast<CoordUnitsPolarTheta> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_THETA).toInt()));
+    setCoordUnitsRadius (static_cast<CoordUnitsNonPolarTheta> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_RADIUS).toInt()));
+    setCoordUnitsDate (static_cast<CoordUnitsDate> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_DATE).toInt()));
+    setCoordUnitsTime (static_cast<CoordUnitsTime> (attributes.value(DOCUMENT_SERIALIZE_COORDS_UNITS_TIME).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
diff --git a/src/Document/DocumentModelDigitizeCurve.cpp b/src/Document/DocumentModelDigitizeCurve.cpp
index 5a19a7f8..aa8b6717 100644
--- a/src/Document/DocumentModelDigitizeCurve.cpp
+++ b/src/Document/DocumentModelDigitizeCurve.cpp
@@ -90,7 +90,7 @@ void DocumentModelDigitizeCurve::loadXml(QXmlStreamReader &reader)
 
     setCursorInnerRadius (attributes.value(DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_INNER_RADIUS).toInt());
     setCursorLineWidth (attributes.value(DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_LINE_WIDTH).toInt());
-    setCursorSize ((CursorSize) attributes.value(DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_SIZE).toInt());
+    setCursorSize (static_cast<CursorSize> (attributes.value(DOCUMENT_SERIALIZE_DIGITIZE_CURVE_CURSOR_SIZE).toInt()));
     setCursorStandardCross (standardCrossValue == DOCUMENT_SERIALIZE_BOOL_TRUE);
 
     // Read until end of this subtree
diff --git a/src/Document/DocumentModelExportFormat.cpp b/src/Document/DocumentModelExportFormat.cpp
index 26083c89..f70ecf2d 100644
--- a/src/Document/DocumentModelExportFormat.cpp
+++ b/src/Document/DocumentModelExportFormat.cpp
@@ -22,34 +22,39 @@ const QString DEFAULT_X_LABEL ("x");
 const ExportPointsIntervalUnits DEFAULT_POINTS_INTERVAL_UNITS_FUNCTIONS = EXPORT_POINTS_INTERVAL_UNITS_SCREEN; // Consistent with DEFAULT_POINTS_INTERVAL_FUNCTIONS
 const ExportPointsIntervalUnits DEFAULT_POINTS_INTERVAL_UNITS_RELATIONS = EXPORT_POINTS_INTERVAL_UNITS_SCREEN; // Consistent with DEFAULT_POINTS_INTERVAL_RELATIONS
 const bool DEFAULT_EXPORT_DELIMITER_OVERRIDE = false; // Target beginner users who expect simplest behavior. Issue #169
+const bool DEFAULT_EXTRAPOLATE = true; // Traditional behavior before version 11
 
 DocumentModelExportFormat::DocumentModelExportFormat()
 {
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_EXPORT);
 
+  // Sync these settings with DlgSettingsExportFormat::slotLoadDefault()
+  // and DlgSettingsExportFormat::slotSaveDefault()
   m_curveNamesNotExported = settings.value (SETTINGS_EXPORT_CURVE_NAMES_NOT_EXPORTED,
                                             QVariant (DEFAULT_CURVE_NAMES_NOT_EXPORTED)).toStringList();
-  m_delimiter = (ExportDelimiter) settings.value (SETTINGS_EXPORT_DELIMITER,
-                                                  QVariant (EXPORT_DELIMITER_COMMA)).toInt();
+  m_delimiter = static_cast<ExportDelimiter> (settings.value (SETTINGS_EXPORT_DELIMITER,
+                                                              QVariant (EXPORT_DELIMITER_COMMA)).toInt());  
+  m_extrapolateOutsideEndpoints = settings.value (SETTINGS_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS,
+                                                  QVariant (DEFAULT_EXTRAPOLATE)).toBool();
   m_overrideCsvTsv = settings.value (SETTINGS_EXPORT_DELIMITER_OVERRIDE_CSV_TSV,
                                      QVariant (DEFAULT_EXPORT_DELIMITER_OVERRIDE)).toBool();
-  m_header = (ExportHeader) settings.value (SETTINGS_EXPORT_HEADER,
-                                            QVariant (EXPORT_HEADER_SIMPLE)).toInt();
-  m_layoutFunctions = (ExportLayoutFunctions) settings.value (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
-                                                              QVariant (EXPORT_LAYOUT_ALL_PER_LINE)).toInt();
+  m_header = static_cast<ExportHeader> (settings.value (SETTINGS_EXPORT_HEADER,
+                                                        QVariant (EXPORT_HEADER_SIMPLE)).toInt());
+  m_layoutFunctions = static_cast<ExportLayoutFunctions> (settings.value (SETTINGS_EXPORT_LAYOUT_FUNCTIONS,
+                                                                          QVariant (EXPORT_LAYOUT_ALL_PER_LINE)).toInt());
   m_pointsIntervalFunctions = settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS,
                                               QVariant (DEFAULT_POINTS_INTERVAL_FUNCTIONS)).toDouble();
   m_pointsIntervalRelations = settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_RELATIONS,
                                               QVariant (DEFAULT_POINTS_INTERVAL_RELATIONS)).toDouble();
-  m_pointsIntervalUnitsFunctions = (ExportPointsIntervalUnits) settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS,
-                                                                               QVariant (DEFAULT_POINTS_INTERVAL_UNITS_FUNCTIONS)).toInt();
-  m_pointsIntervalUnitsRelations = (ExportPointsIntervalUnits) settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS,
-                                                                               QVariant (DEFAULT_POINTS_INTERVAL_UNITS_RELATIONS)).toInt();
-  m_pointsSelectionFunctions = (ExportPointsSelectionFunctions) settings.value (SETTINGS_EXPORT_POINTS_SELECTION_FUNCTIONS,
-                                                                                QVariant (EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES)).toInt();
-  m_pointsSelectionRelations = (ExportPointsSelectionRelations) settings.value (SETTINGS_EXPORT_POINTS_SELECTION_RELATIONS,
-                                                                                QVariant (EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE)).toInt();
+  m_pointsIntervalUnitsFunctions = static_cast<ExportPointsIntervalUnits> (settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS,
+                                                                                           QVariant (DEFAULT_POINTS_INTERVAL_UNITS_FUNCTIONS)).toInt());
+  m_pointsIntervalUnitsRelations = static_cast<ExportPointsIntervalUnits> (settings.value (SETTINGS_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS,
+                                                                                           QVariant (DEFAULT_POINTS_INTERVAL_UNITS_RELATIONS)).toInt());
+  m_pointsSelectionFunctions = static_cast<ExportPointsSelectionFunctions> (settings.value (SETTINGS_EXPORT_POINTS_SELECTION_FUNCTIONS,
+                                                                                            QVariant (EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES)).toInt());
+  m_pointsSelectionRelations = static_cast<ExportPointsSelectionRelations> (settings.value (SETTINGS_EXPORT_POINTS_SELECTION_RELATIONS,
+                                                                                            QVariant (EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE)).toInt());
   m_xLabel = settings.value (SETTINGS_EXPORT_X_LABEL,
                              QVariant (DEFAULT_X_LABEL)).toString();
 }
@@ -64,6 +69,7 @@ DocumentModelExportFormat::DocumentModelExportFormat (const Document &document)
   m_pointsIntervalUnitsRelations (document.modelExport().pointsIntervalUnitsRelations()),
   m_layoutFunctions (document.modelExport().layoutFunctions()),
   m_delimiter (document.modelExport().delimiter()),
+  m_extrapolateOutsideEndpoints (document.modelExport().extrapolateOutsideEndpoints()),
   m_overrideCsvTsv (document.modelExport().overrideCsvTsv()),
   m_header (document.modelExport().header()),
   m_xLabel (document.modelExport().xLabel())
@@ -80,6 +86,7 @@ DocumentModelExportFormat::DocumentModelExportFormat(const DocumentModelExportFo
   m_pointsIntervalUnitsRelations (other.pointsIntervalUnitsRelations()),
   m_layoutFunctions (other.layoutFunctions()),
   m_delimiter (other.delimiter()),
+  m_extrapolateOutsideEndpoints (other.extrapolateOutsideEndpoints()),
   m_overrideCsvTsv (other.overrideCsvTsv()),
   m_header (other.header()),
   m_xLabel (other.xLabel ())
@@ -97,6 +104,7 @@ DocumentModelExportFormat &DocumentModelExportFormat::operator=(const DocumentMo
   m_pointsIntervalUnitsRelations = other.pointsIntervalUnitsRelations();
   m_layoutFunctions = other.layoutFunctions();
   m_delimiter = other.delimiter();
+  m_extrapolateOutsideEndpoints = other.extrapolateOutsideEndpoints();
   m_overrideCsvTsv = other.overrideCsvTsv();
   m_header = other.header();
   m_xLabel = other.xLabel();
@@ -114,6 +122,11 @@ ExportDelimiter DocumentModelExportFormat::delimiter() const
   return m_delimiter;
 }
 
+bool DocumentModelExportFormat::extrapolateOutsideEndpoints() const
+{
+  return m_extrapolateOutsideEndpoints;
+}
+
 ExportHeader DocumentModelExportFormat::header() const
 {
   return m_header;
@@ -132,6 +145,7 @@ void DocumentModelExportFormat::loadXml(QXmlStreamReader &reader)
 
   QXmlStreamAttributes attributes = reader.attributes();
 
+  // DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS is specific to versions 11 and newer
   if (attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_POINTS_SELECTION_FUNCTIONS) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_FUNCTIONS) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS) &&
@@ -143,14 +157,14 @@ void DocumentModelExportFormat::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_HEADER) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_X_LABEL)) {
 
-    setPointsSelectionFunctions ((ExportPointsSelectionFunctions) attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_SELECTION_FUNCTIONS).toInt());
+    setPointsSelectionFunctions (static_cast<ExportPointsSelectionFunctions> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_SELECTION_FUNCTIONS).toInt()));
     setPointsIntervalFunctions (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_FUNCTIONS).toDouble());
-    setPointsIntervalUnitsFunctions ((ExportPointsIntervalUnits) attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS).toInt());
-    setPointsSelectionRelations ((ExportPointsSelectionRelations) attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_SELECTION_RELATIONS).toInt());
+    setPointsIntervalUnitsFunctions (static_cast<ExportPointsIntervalUnits> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_UNITS_FUNCTIONS).toInt()));
+    setPointsSelectionRelations (static_cast<ExportPointsSelectionRelations> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_SELECTION_RELATIONS).toInt()));
     setPointsIntervalRelations (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_RELATIONS).toDouble());
-    setPointsIntervalUnitsRelations ((ExportPointsIntervalUnits) attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS).toInt());
-    setLayoutFunctions ((ExportLayoutFunctions) attributes.value(DOCUMENT_SERIALIZE_EXPORT_LAYOUT_FUNCTIONS).toInt());
-    setDelimiter ((ExportDelimiter) attributes.value (DOCUMENT_SERIALIZE_EXPORT_DELIMITER).toInt());
+    setPointsIntervalUnitsRelations (static_cast<ExportPointsIntervalUnits> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_POINTS_INTERVAL_UNITS_RELATIONS).toInt()));
+    setLayoutFunctions (static_cast<ExportLayoutFunctions> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_LAYOUT_FUNCTIONS).toInt()));
+    setDelimiter (static_cast<ExportDelimiter> (attributes.value (DOCUMENT_SERIALIZE_EXPORT_DELIMITER).toInt()));
     if (attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_DELIMITER_OVERRIDE_CSV_TSV)) {
 
       // Boolean value
@@ -158,7 +172,15 @@ void DocumentModelExportFormat::loadXml(QXmlStreamReader &reader)
 
       setOverrideCsvTsv(stringOverrideCsvTsv == DOCUMENT_SERIALIZE_BOOL_TRUE);
     }
-    setHeader ((ExportHeader) attributes.value(DOCUMENT_SERIALIZE_EXPORT_HEADER).toInt());
+    if (attributes.hasAttribute(DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS)) {
+
+      // Boolean value
+      QString stringExtrapolate = attributes.value (DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS).toString();
+      
+      setExtrapolateOutsideEndpoints (stringExtrapolate == DOCUMENT_SERIALIZE_BOOL_TRUE);
+    }
+
+    setHeader (static_cast<ExportHeader> (attributes.value(DOCUMENT_SERIALIZE_EXPORT_HEADER).toInt()));
     setXLabel (attributes.value(DOCUMENT_SERIALIZE_EXPORT_X_LABEL).toString());
 
     // Read element containing excluded curve names
@@ -240,7 +262,7 @@ ExportPointsSelectionRelations DocumentModelExportFormat::pointsSelectionRelatio
 }
 
 void DocumentModelExportFormat::printStream(QString indentation,
-                                      QTextStream &str) const
+                                            QTextStream &str) const
 {
   str << indentation << "DocumentModelExportFormat\n";
 
@@ -266,6 +288,7 @@ void DocumentModelExportFormat::printStream(QString indentation,
       << exportPointsIntervalUnitsToString (m_pointsIntervalUnitsRelations) << "\n";
   str << indentation << "exportLayoutFunctions=" << exportLayoutFunctionsToString (m_layoutFunctions) << "\n";
   str << indentation << "exportDelimiter=" << exportDelimiterToString (m_delimiter) << "\n";
+  str << indentation << "exportExtrapolateOutsideEndpoints=" << (m_extrapolateOutsideEndpoints ? "yes" : "no") << "\n";
   str << indentation << "overrideCsvTsv=" << (m_overrideCsvTsv ? "true" : "false") << "\n";
   str << indentation << "exportHeader=" << exportHeaderToString (m_header) << "\n";
   str << indentation << "xLabel=" << m_xLabel << "\n";
@@ -288,9 +311,12 @@ void DocumentModelExportFormat::saveXml(QXmlStreamWriter &writer) const
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_LAYOUT_FUNCTIONS_STRING, exportLayoutFunctionsToString (m_layoutFunctions));
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_DELIMITER, QString::number (m_delimiter));
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_DELIMITER_OVERRIDE_CSV_TSV, m_overrideCsvTsv ?
-                          DOCUMENT_SERIALIZE_BOOL_TRUE :
-                          DOCUMENT_SERIALIZE_BOOL_FALSE);
+                        DOCUMENT_SERIALIZE_BOOL_TRUE :
+                        DOCUMENT_SERIALIZE_BOOL_FALSE);
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_DELIMITER_STRING, exportDelimiterToString (m_delimiter));
+  writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS, m_extrapolateOutsideEndpoints ?
+                        DOCUMENT_SERIALIZE_BOOL_TRUE :
+                        DOCUMENT_SERIALIZE_BOOL_FALSE);
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_HEADER, QString::number (m_header));
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_HEADER_STRING, exportHeaderToString (m_header));
   writer.writeAttribute(DOCUMENT_SERIALIZE_EXPORT_X_LABEL, m_xLabel);
@@ -319,6 +345,11 @@ void DocumentModelExportFormat::setDelimiter(ExportDelimiter delimiter)
   m_delimiter = delimiter;
 }
 
+void DocumentModelExportFormat::setExtrapolateOutsideEndpoints(bool extrapolateOutsideEndpoints)
+{
+  m_extrapolateOutsideEndpoints = extrapolateOutsideEndpoints;
+}
+
 void DocumentModelExportFormat::setHeader(ExportHeader header)
 {
   m_header = header;
diff --git a/src/Document/DocumentModelExportFormat.h b/src/Document/DocumentModelExportFormat.h
index c55528b8..970819ab 100644
--- a/src/Document/DocumentModelExportFormat.h
+++ b/src/Document/DocumentModelExportFormat.h
@@ -41,6 +41,9 @@ public:
   /// Get method for delimiter.
   ExportDelimiter delimiter() const;
 
+  /// Get methods for extrapolation.
+  bool extrapolateOutsideEndpoints() const;
+  
   /// Get method for header.
   ExportHeader header() const;
 
@@ -82,6 +85,9 @@ public:
   /// Set method for delimiter.
   void setDelimiter(ExportDelimiter exportDelimiter);
 
+  /// Set methods for extrapolation.
+  void setExtrapolateOutsideEndpoints (bool extrapolateOutsideEndpoints);
+  
   /// Set method for header.
   void setHeader(ExportHeader exportHeader);
 
@@ -128,6 +134,7 @@ private:
   ExportPointsIntervalUnits m_pointsIntervalUnitsRelations;
   ExportLayoutFunctions m_layoutFunctions;
   ExportDelimiter m_delimiter;
+  bool m_extrapolateOutsideEndpoints;
   bool m_overrideCsvTsv;
   ExportHeader m_header;
   QString m_xLabel;
diff --git a/src/Document/DocumentModelGridDisplay.cpp b/src/Document/DocumentModelGridDisplay.cpp
index 479fcfc9..7e472f60 100644
--- a/src/Document/DocumentModelGridDisplay.cpp
+++ b/src/Document/DocumentModelGridDisplay.cpp
@@ -128,17 +128,17 @@ void DocumentModelGridDisplay::loadXml(QXmlStreamReader &reader)
     QString stableValue = attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_STABLE).toString();
 
     setStable (stableValue == DOCUMENT_SERIALIZE_BOOL_TRUE);
-    setDisableX ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_DISABLE_X).toInt());
-    setCountX (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COUNT_X).toInt());
+    setDisableX (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_DISABLE_X).toInt()));
+    setCountX (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COUNT_X).toUInt());
     setStartX (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_START_X).toDouble());
     setStepX (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_STEP_X).toDouble());
     setStopX (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_STOP_X).toDouble());
-    setDisableY ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_DISABLE_Y).toInt());
-    setCountY (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COUNT_Y).toInt());
+    setDisableY (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_DISABLE_Y).toUInt()));
+    setCountY (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COUNT_Y).toUInt());
     setStartY (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_START_Y).toDouble());
     setStepY (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_STEP_Y).toDouble());
     setStopY (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_STOP_Y).toDouble());
-    setPaletteColor ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COLOR).toInt());
+    setPaletteColor (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_GRID_DISPLAY_COLOR).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
diff --git a/src/Document/DocumentModelGridRemoval.cpp b/src/Document/DocumentModelGridRemoval.cpp
index 84a7acc7..dde86678 100644
--- a/src/Document/DocumentModelGridRemoval.cpp
+++ b/src/Document/DocumentModelGridRemoval.cpp
@@ -165,12 +165,12 @@ void DocumentModelGridRemoval::loadXml(QXmlStreamReader &reader)
     setStable (stableValue == DOCUMENT_SERIALIZE_BOOL_TRUE);
     setRemoveDefinedGridLines (definedValue == DOCUMENT_SERIALIZE_BOOL_TRUE);
     setCloseDistance (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_CLOSE_DISTANCE).toDouble());
-    setGridCoordDisableX ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COORD_DISABLE_X).toInt());
+    setGridCoordDisableX (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COORD_DISABLE_X).toInt()));
     setCountX (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COUNT_X).toInt());
     setStartX (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_START_X).toDouble());
     setStepX (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_STEP_X).toDouble());
     setStopX (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_STOP_X).toDouble());
-    setGridCoordDisableY ((GridCoordDisable) attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COORD_DISABLE_Y).toInt());
+    setGridCoordDisableY (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COORD_DISABLE_Y).toInt()));
     setCountY (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_COUNT_Y).toInt());
     setStartY (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_START_Y).toDouble());
     setStepY (attributes.value(DOCUMENT_SERIALIZE_GRID_REMOVAL_STEP_Y).toDouble());
diff --git a/src/Document/DocumentModelPointMatch.cpp b/src/Document/DocumentModelPointMatch.cpp
index 021af676..92757674 100644
--- a/src/Document/DocumentModelPointMatch.cpp
+++ b/src/Document/DocumentModelPointMatch.cpp
@@ -68,9 +68,9 @@ void DocumentModelPointMatch::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_REJECTED)) {
 
     setMaxPointSize (attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_POINT_SIZE).toDouble());
-    setPaletteColorAccepted ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_ACCEPTED).toInt());
-    setPaletteColorCandidate ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_CANDIDATE).toInt());
-    setPaletteColorRejected ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_REJECTED).toInt());
+    setPaletteColorAccepted (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_ACCEPTED).toInt()));
+    setPaletteColorCandidate (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_CANDIDATE).toInt()));
+    setPaletteColorRejected (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_POINT_MATCH_COLOR_REJECTED).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
diff --git a/src/Document/DocumentSerialize.cpp b/src/Document/DocumentSerialize.cpp
index 12e392e8..67ddda3d 100644
--- a/src/Document/DocumentSerialize.cpp
+++ b/src/Document/DocumentSerialize.cpp
@@ -33,7 +33,7 @@ const QString DOCUMENT_SERIALIZE_CMD_SELECT_COORD_SYSTEM ("CmdSelectCoordSystem"
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_AXES_CHECKER ("CmdSettingsAxesChecker");
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_COLOR_FILTER ("CmdSettingsColorFilter");
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_COORDS ("CmdSettingsCoords");
-const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_ADD_REMOVE ("CmdSettingsCurveAddRemove");
+const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_LIST ("CmdSettingsCurveAddRemove"); // AddRemove versus List for old dig files
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_PROPERTIES ("CmdSettingsCurveProperties");
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_DIGITIZE_CURVE ("CmdSettingsDigitizeCurve");
 const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_EXPORT ("CmdSettingsExport");
@@ -115,6 +115,7 @@ const QString DOCUMENT_SERIALIZE_EXPORT_CURVE_NAMES_NOT_EXPORTED ("CurveNamesNot
 const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER ("Delimiter");
 const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER_OVERRIDE_CSV_TSV ("OverrideCsvTsv");
 const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER_STRING ("DelimiterString");
+const QString DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS ("ExtrapolateOutsideEndpoints");
 const QString DOCUMENT_SERIALIZE_EXPORT_HEADER ("Header");
 const QString DOCUMENT_SERIALIZE_EXPORT_HEADER_STRING ("HeaderString");
 const QString DOCUMENT_SERIALIZE_EXPORT_LAYOUT_FUNCTIONS ("LayoutFunctions");
diff --git a/src/Document/DocumentSerialize.h b/src/Document/DocumentSerialize.h
index a54fc35b..1d88f430 100644
--- a/src/Document/DocumentSerialize.h
+++ b/src/Document/DocumentSerialize.h
@@ -37,7 +37,7 @@ extern const QString DOCUMENT_SERIALIZE_CMD_SELECT_COORD_SYSTEM;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_AXES_CHECKER;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_COLOR_FILTER;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_COORDS;
-extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_ADD_REMOVE;
+extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_LIST;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_CURVE_PROPERTIES;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_DIGITIZE_CURVE;
 extern const QString DOCUMENT_SERIALIZE_CMD_SETTINGS_EXPORT;
@@ -118,6 +118,7 @@ extern const QString DOCUMENT_SERIALIZE_EXPORT_CURVE_NAMES_NOT_EXPORTED;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER_OVERRIDE_CSV_TSV;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_DELIMITER_STRING;
+extern const QString DOCUMENT_SERIALIZE_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_HEADER;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_HEADER_STRING;
 extern const QString DOCUMENT_SERIALIZE_EXPORT_LAYOUT_FUNCTIONS;
diff --git a/src/Doxyfile b/src/Doxyfile
index e3cb5b0c..065d7463 100644
--- a/src/Doxyfile
+++ b/src/Doxyfile
@@ -398,7 +398,7 @@ LOOKUP_CACHE_SIZE      = 0
 # normally produced when WARNINGS is set to YES.
 # The default value is: NO.
 
-EXTRACT_ALL            = NO
+EXTRACT_ALL            = YES
 
 # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
 # be included in the documentation.
@@ -743,7 +743,7 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  =
+INPUT                  = .
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -898,7 +898,7 @@ SOURCE_BROWSER         = YES
 # classes and enums directly into the documentation.
 # The default value is: NO.
 
-INLINE_SOURCES         = NO
+INLINE_SOURCES         = YES
 
 # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
 # special comment blocks from generated source code fragments. Normal C, C++ and
@@ -1137,7 +1137,7 @@ HTML_DYNAMIC_SECTIONS  = NO
 # Minimum value: 0, maximum value: 9999, default value: 100.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_INDEX_NUM_ENTRIES = 100
+HTML_INDEX_NUM_ENTRIES = 1000
 
 # If the GENERATE_DOCSET tag is set to YES, additional index files will be
 # generated that can be used as input for Apple's Xcode 3 integrated development
@@ -1583,7 +1583,7 @@ COMPACT_LATEX          = NO
 # The default value is: a4.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-PAPER_TYPE             = a4
+PAPER_TYPE             = letter
 
 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
 # that should be included in the LaTeX output. To get the times font for
@@ -1895,7 +1895,7 @@ ENABLE_PREPROCESSING   = YES
 # The default value is: NO.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
 # the macro expansion is limited to the macros specified with the PREDEFINED and
@@ -1917,7 +1917,7 @@ SEARCH_INCLUDES        = YES
 # preprocessor.
 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
-INCLUDE_PATH           =
+INCLUDE_PATH           = .
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2049,7 +2049,7 @@ HIDE_UNDOC_RELATIONS   = YES
 # set to NO
 # The default value is: NO.
 
-HAVE_DOT               = NO
+HAVE_DOT               = YES
 
 # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
 # to run in parallel. When set to 0 doxygen will base this on the number of
@@ -2215,7 +2215,7 @@ DOT_IMAGE_FORMAT       = png
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-INTERACTIVE_SVG        = NO
+INTERACTIVE_SVG        = YES
 
 # The DOT_PATH tag can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
diff --git a/src/Export/ExportAlignLinear.cpp b/src/Export/ExportAlignLinear.cpp
index 1b02a814..0c743191 100644
--- a/src/Export/ExportAlignLinear.cpp
+++ b/src/Export/ExportAlignLinear.cpp
@@ -22,7 +22,7 @@ ExportAlignLinear::ExportAlignLinear(double xMin,
   // are D=0 for 0.1 to 0.99..., D=1 for 1 to 9.99..., D=2 for 10 to 99.999...
   double absMin = qAbs (xMin);
   double absMax = qAbs (xMax);
-  int D = (int) (log10 (qMax (absMin, absMax)) + EPSILON);
+  int D = qFloor (log10 (qMax (absMin, absMax)) + EPSILON);
 
   // Number of significant digits S will start at 1 and then get increased until
   //    rounded(xMin) + 10^R <= xMax
@@ -40,9 +40,8 @@ ExportAlignLinear::ExportAlignLinear(double xMin,
       roundedMin -= nominalStep;
     }
 
-    if (roundedMin + nominalStep <= xMax) {
-
-      // Success. We have found a reasonable range that just fits xMin and xMax
+    // Need at least one step between roundedMin and xMax, otherwise ranges
+    if (roundedMin + 2 * nominalStep <= xMax) {
       break;
     }
 
@@ -66,7 +65,7 @@ double ExportAlignLinear::roundToDigit (double value,
                                         int digit) const
 {
   double scale = qPow (10.0, digit);
-  int valueRoundedWithWrongScale = (int) (value / scale + EPSILON);
+  int valueRoundedWithWrongScale = qFloor (value / scale + EPSILON);
   double valueRounded = valueRoundedWithWrongScale * scale;
 
   return valueRounded;
diff --git a/src/Export/ExportDelimiter.cpp b/src/Export/ExportDelimiter.cpp
index 8156f691..44c673d2 100644
--- a/src/Export/ExportDelimiter.cpp
+++ b/src/Export/ExportDelimiter.cpp
@@ -9,45 +9,55 @@
 
 QString exportDelimiterToString (ExportDelimiter exportDelimiter)
 {
+  QString rtn;
+
   switch (exportDelimiter) {
     case EXPORT_DELIMITER_COMMA:
-      return QObject::tr ("Commas");
+      rtn = QObject::tr ("Commas");
+      break;
 
     case EXPORT_DELIMITER_SEMICOLON:
-      return QObject::tr ("Semicolons");
+      rtn = QObject::tr ("Semicolons");
+      break;
 
     case EXPORT_DELIMITER_SPACE:
-      return QObject::tr ("Spaces");
+      rtn = QObject::tr ("Spaces");
+      break;
 
     case EXPORT_DELIMITER_TAB:
-      return QObject::tr ("Tabs");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Tabs");
+      break;
   }
+
+  return rtn;
 }
 
 QString exportDelimiterToText (ExportDelimiter exportDelimiter,
                                bool isGnuplotDelimiter)
 {
+  QString rtn;
+
   switch (exportDelimiter) {
     case EXPORT_DELIMITER_COMMA:
       if (isGnuplotDelimiter) {
-        return ", "; // Gnuplot needs a space
+        rtn = ", "; // Gnuplot needs a space
       } else {
-        return ",";
+        rtn = ",";
       }
+      break;
 
     case EXPORT_DELIMITER_SEMICOLON:
-      return ";";
+      rtn = ";";
+      break;
 
     case EXPORT_DELIMITER_SPACE:
-      return " ";
+      rtn = " ";
+      break;
 
     case EXPORT_DELIMITER_TAB:
-      return "\t";
-
-    default:
-      return "?";
+      rtn = "\t";
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportFileAbstractBase.cpp b/src/Export/ExportFileAbstractBase.cpp
index 21fb3b64..c3fd2799 100644
--- a/src/Export/ExportFileAbstractBase.cpp
+++ b/src/Export/ExportFileAbstractBase.cpp
@@ -22,6 +22,10 @@ ExportFileAbstractBase::ExportFileAbstractBase()
 {
 }
 
+ExportFileAbstractBase::~ExportFileAbstractBase()
+{
+}
+
 QStringList ExportFileAbstractBase::curvesToInclude (const DocumentModelExportFormat &modelExportOverride,
                                                      const Document &document,
                                                      const QStringList &curvesGraphsNames,
diff --git a/src/Export/ExportFileAbstractBase.h b/src/Export/ExportFileAbstractBase.h
index e017f84d..a050e349 100644
--- a/src/Export/ExportFileAbstractBase.h
+++ b/src/Export/ExportFileAbstractBase.h
@@ -8,8 +8,8 @@
 #define EXPORT_FILE_ABSTRACT_BASE_H
 
 #include "CurveConnectAs.h"
-#include "ExportFileAbstractBase.h"
 #include "ExportHeader.h"
+#include <QPointF>
 #include <QStringList>
 #include <QVector>
 #include <vector>
@@ -27,7 +27,8 @@ class ExportFileAbstractBase
 public:
   /// Single constructor.
   ExportFileAbstractBase();
-
+  virtual ~ExportFileAbstractBase ();
+  
 protected:
 
   /// Identify curves to include in export. The specified DocumentModelExportFormat overrides same data in Document for previewing window
diff --git a/src/Export/ExportFileFunctions.cpp b/src/Export/ExportFileFunctions.cpp
index 98ed9e13..97f334ac 100644
--- a/src/Export/ExportFileFunctions.cpp
+++ b/src/Export/ExportFileFunctions.cpp
@@ -4,7 +4,8 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#include "CallbackGatherXThetaValuesFunctions.h"
+#include "CallbackGatherXThetasInCurves.h"
+#include "CallbackGatherXThetasInGridLines.h"
 #include "CurveConnectAs.h"
 #include "Document.h"
 #include "DocumentModelGeneral.h"
@@ -14,6 +15,7 @@
 #include "ExportOrdinalsSmooth.h"
 #include "ExportXThetaValuesMergedFunctions.h"
 #include "FormatCoordsUnits.h"
+#include "GridLineLimiter.h"
 #include "LinearToLog.h"
 #include "Logger.h"
 #include <qmath.h>
@@ -39,6 +41,8 @@ void ExportFileFunctions::exportAllPerLineXThetaValuesMerged (const DocumentMode
                                                               const Transformation &transformation,
                                                               bool isLogXTheta,
                                                               bool isLogYRadius,
+                                                              const CurveLimits curveLimitsMin,
+                                                              const CurveLimits curveLimitsMax,
                                                               QTextStream &str,
                                                               unsigned int &numWritesSoFar) const
 {
@@ -58,6 +62,8 @@ void ExportFileFunctions::exportAllPerLineXThetaValuesMerged (const DocumentMode
                      isLogXTheta,
                      isLogYRadius,
                      xThetaValues,
+                     curveLimitsMin,
+                     curveLimitsMax,
                      yRadiusValues);
 
   outputXThetaYRadiusValues (modelExportOverride,
@@ -83,6 +89,8 @@ void ExportFileFunctions::exportOnePerLineXThetaValuesMerged (const DocumentMode
                                                               const Transformation &transformation,
                                                               bool isLogXTheta,
                                                               bool isLogYRadius,
+                                                              const CurveLimits curveLimitsMin,
+                                                              const CurveLimits curveLimitsMax,
                                                               QTextStream &str,
                                                               unsigned int &numWritesSoFar) const
 {
@@ -94,27 +102,29 @@ void ExportFileFunctions::exportOnePerLineXThetaValuesMerged (const DocumentMode
     // This curve
     const int CURVE_COUNT = 1;
     QString curveIncluded = *itr;
-    QStringList curvesIncluded (curveIncluded);
+    QStringList curvesIncludedIter (curveIncluded);
 
     int xThetaCount = xThetaValues.count();
     QVector<QVector<QString*> > yRadiusValues (CURVE_COUNT, QVector<QString*> (xThetaCount));
-    initializeYRadiusValues (curvesIncluded,
+    initializeYRadiusValues (curvesIncludedIter,
                              xThetaValues,
                              yRadiusValues);
     loadYRadiusValues (modelExportOverride,
                        document,
                        modelMainWindow,
-                       curvesIncluded,
+                       curvesIncludedIter,
                        transformation,
                        isLogXTheta,
                        isLogYRadius,
                        xThetaValues,
+                       curveLimitsMin,
+                       curveLimitsMax,
                        yRadiusValues);
     outputXThetaYRadiusValues (modelExportOverride,
                                document.modelCoords(),
                                document.modelGeneral(),
                                modelMainWindow,
-                               curvesIncluded,
+                               curvesIncludedIter,
                                xThetaValues,
                                transformation,
                                yRadiusValues,
@@ -149,17 +159,37 @@ void ExportFileFunctions::exportToFile (const DocumentModelExportFormat &modelEx
   const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
                                                    modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
 
-  // Get x/theta values to be used
-  CallbackGatherXThetaValuesFunctions ftor (modelExportOverride,
-                                            curvesIncluded,
-                                            transformation);
-  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
-                                                                                                     &CallbackGatherXThetaValuesFunctions::callback);
-  document.iterateThroughCurvesPointsGraphs(ftorWithCallback);
+  // Get x/theta values to be used. Also get the endpoint limits, if any
+  CurveLimits curveLimitsMin, curveLimitsMax;
+  ValuesVectorXOrY valuesVector;
+  if (modelExportOverride.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES) {
+    CallbackGatherXThetasInGridLines ftor (modelMainWindow,
+                                           modelExportOverride,
+                                           curvesIncluded,
+                                           transformation,
+                                           document);
+    Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
+                                                                                                       &CallbackGatherXThetasInGridLines::callback);
+    document.iterateThroughCurvesPointsGraphs(ftorWithCallback);
+    valuesVector = ftor.xThetaValuesRaw();
+    curveLimitsMin = ftor.curveLimitsMin();
+    curveLimitsMax = ftor.curveLimitsMax();
+  } else {
+    CallbackGatherXThetasInCurves ftor (modelExportOverride,
+                                        curvesIncluded,
+                                        transformation);
+    Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
+                                                                                                       &CallbackGatherXThetasInCurves::callback);
+    document.iterateThroughCurvesPointsGraphs(ftorWithCallback);
+    valuesVector = ftor.xThetaValuesRaw();
+    curveLimitsMin = ftor.curveLimitsMin();
+    curveLimitsMax = ftor.curveLimitsMax();
+  }
 
   ExportXThetaValuesMergedFunctions exportXTheta (modelExportOverride,
-                                                  ftor.xThetaValuesRaw(),
+                                                  valuesVector,
                                                   transformation);
+
   ExportValuesXOrY xThetaValuesMerged = exportXTheta.xThetaValues ();
 
   // Skip if every curve was a relation
@@ -176,6 +206,8 @@ void ExportFileFunctions::exportToFile (const DocumentModelExportFormat &modelEx
                                           transformation,
                                           isLogXTheta,
                                           isLogYRadius,
+                                          curveLimitsMin,
+                                          curveLimitsMax,
                                           str,
                                           numWritesSoFar);
     } else {
@@ -188,6 +220,8 @@ void ExportFileFunctions::exportToFile (const DocumentModelExportFormat &modelEx
                                           transformation,
                                           isLogXTheta,
                                           isLogYRadius,
+                                          curveLimitsMin,
+                                          curveLimitsMax,
                                           str,
                                           numWritesSoFar);
     }
@@ -219,7 +253,7 @@ double ExportFileFunctions::linearlyInterpolate (const Points &points,
   // If point is within the range of the function points then interpolation will be used, otherwise
   // extrapolation will be used
   double yRadius = 0;
-  QPointF posGraphBefore, posScreenBefore; // Not set until ip=1
+  QPointF posGraphBefore; // Not set until ip=1
   bool foundIt = false;
   for (int ip = 0; !foundIt && (ip < points.count()); ip++) {
 
@@ -292,6 +326,8 @@ void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &mo
                                              bool isLogXTheta,
                                              bool isLogYRadius,
                                              const ExportValuesXOrY &xThetaValues,
+                                             const CurveLimits &curveLimitsMin,
+                                             const CurveLimits &curveLimitsMax,
                                              QVector<QVector<QString*> > &yRadiusValues) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValues";
@@ -314,6 +350,9 @@ void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &mo
                                     points,
                                     xThetaValues,
                                     transformation,
+                                    curveName,
+                                    curveLimitsMin,
+                                    curveLimitsMax,
                                     yRadiusValues [col]);
     } else {
 
@@ -328,6 +367,9 @@ void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &mo
                                                      transformation,
                                                      isLogXTheta,
                                                      isLogYRadius,
+                                                     curveName,
+                                                     curveLimitsMin,
+                                                     curveLimitsMax,
                                                      yRadiusValues [col]);
 
       } else {
@@ -338,6 +380,9 @@ void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &mo
                                                        points,
                                                        xThetaValues,
                                                        transformation,
+                                                       curveName,
+                                                       curveLimitsMin,
+                                                       curveLimitsMax,
                                                        yRadiusValues [col]);
       }
     }
@@ -352,6 +397,9 @@ void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const Doc
                                                                        const Transformation &transformation,
                                                                        bool isLogXTheta,
                                                                        bool isLogYRadius,
+                                                                       const QString &curveName,
+                                                                       const CurveLimits &curveLimitsMin,
+                                                                       const CurveLimits &curveLimitsMax,
                                                                        QVector<QString*> &yRadiusValues) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth";
@@ -394,22 +442,31 @@ void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const Doc
         double x1 = xy.at (1).x ();
         double y0 = xy.at (0).y ();
         double y1 = xy.at (1).y ();
-        if (x0 == x1) {
+        double numerator = (xTheta - x0);
+        double denominator = (x1 - x0);
+        if (qAbs (denominator) < qAbs (numerator) / 1.0e6) {
           // Cannot do linear interpolation using two points at the same x value
           yRadius = xy.at (0).y ();
         } else {
-          double s = (xTheta - x0) / (x1 - x0);
+          double s = numerator / denominator;
           yRadius = (1.0 - s) * y0 + s * y1;
         }
       }
-      format.unformattedToFormatted (xTheta,
-                                     yRadius,
-                                     modelCoords,
-                                     modelGeneral,
-                                     modelMainWindow,
-                                     dummyXThetaOut,
-                                     *(yRadiusValues [row]),
-                                     transformation);
+      if (xThetaIsNotOutOfBounds (xTheta,
+                                  curveName,
+                                  curveLimitsMin,
+                                  curveLimitsMax)) {
+        format.unformattedToFormatted (xTheta,
+                                       yRadius,
+                                       modelCoords,
+                                       modelGeneral,
+                                       modelMainWindow,
+                                       dummyXThetaOut,
+                                       *(yRadiusValues [row]),
+                                       transformation);
+      } else {
+        *(yRadiusValues [row]) = "";
+      }
     }
 
   } else {
@@ -440,15 +497,21 @@ void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const Doc
                                                   isLogYRadius);
 
         // Save y/radius value for this row into yRadiusValues, after appropriate formatting
-        QString dummyXThetaOut;
-        format.unformattedToFormatted (xTheta,
-                                       yRadius,
-                                       modelCoords,
-                                       modelGeneral,
-                                       modelMainWindow,
-                                       dummyXThetaOut,
-                                       *(yRadiusValues [row]),
-                                       transformation);
+        if (xThetaIsNotOutOfBounds (xTheta,
+                                    curveName,
+                                    curveLimitsMin,
+                                    curveLimitsMax)) {
+          format.unformattedToFormatted (xTheta,
+                                         yRadius,
+                                         modelCoords,
+                                         modelGeneral,
+                                         modelMainWindow,
+                                         dummyXThetaOut,
+                                         *(yRadiusValues [row]),
+                                         transformation);
+        } else {
+          *(yRadiusValues [row]) = "";
+        }
       }
     }
   }
@@ -460,6 +523,9 @@ void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const D
                                                                          const Points &points,
                                                                          const ExportValuesXOrY &xThetaValues,
                                                                          const Transformation &transformation,
+                                                                         const QString &curveName,
+                                                                         const CurveLimits &curveLimitsMin,
+                                                                         const CurveLimits &curveLimitsMax,
                                                                          QVector<QString*> &yRadiusValues) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight";
@@ -467,24 +533,34 @@ void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const D
   FormatCoordsUnits format;
 
   // Get value at desired points
+  QString dummyXThetaOut;
   for (int row = 0; row < xThetaValues.count(); row++) {
 
-    double xThetaValue = xThetaValues.at (row);
+    double xTheta = xThetaValues.at (row);
 
-    double yRadius = linearlyInterpolate (points,
-                                          xThetaValue,
-                                          transformation);
+    // Interpolation on curve with no points will trigger an assert so check the point count
+    *(yRadiusValues [row]) = "";
+    if (points.count () > 0) {
 
-    // Save y/radius value for this row into yRadiusValues, after appropriate formatting
-    QString dummyXThetaOut;
-    format.unformattedToFormatted (xThetaValue,
-                                   yRadius,
-                                   modelCoords,
-                                   modelGeneral,
-                                   modelMainWindow,
-                                   dummyXThetaOut,
-                                   *(yRadiusValues [row]),
-                                   transformation);
+      double yRadius = linearlyInterpolate (points,
+                                            xTheta,
+                                            transformation);
+
+      // Save y/radius value for this row into yRadiusValues, after appropriate formatting
+      if (xThetaIsNotOutOfBounds (xTheta,
+                                  curveName,
+                                  curveLimitsMin,
+                                  curveLimitsMax)) {
+        format.unformattedToFormatted (xTheta,
+                                       yRadius,
+                                       modelCoords,
+                                       modelGeneral,
+                                       modelMainWindow,
+                                       dummyXThetaOut,
+                                       *(yRadiusValues [row]),
+                                       transformation);
+      }
+    }
   }
 }
 
@@ -494,6 +570,9 @@ void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoord
                                                         const Points &points,
                                                         const ExportValuesXOrY &xThetaValues,
                                                         const Transformation &transformation,
+                                                        const QString &curveName,
+                                                        const CurveLimits &curveLimitsMin,
+                                                        const CurveLimits &curveLimitsMax,
                                                         QVector<QString*> &yRadiusValues) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveRaw";
@@ -516,9 +595,9 @@ void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoord
     int rowClosest = 0;
     for (int row = 0; row < xThetaValues.count(); row++) {
 
-      double xThetaValue = xThetaValues.at (row);
+      double xTheta = xThetaValues.at (row);
 
-      double separation = qAbs (posGraph.x() - xThetaValue);
+      double separation = qAbs (posGraph.x() - xTheta);
 
       if ((row == 0) ||
           (separation < closestSeparation)) {
@@ -530,15 +609,22 @@ void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoord
     }
 
     // Save y/radius value for this row into yRadiusValues, after appropriate formatting
-    QString dummyXThetaOut;
-    format.unformattedToFormatted (posGraph.x(),
-                                   posGraph.y(),
-                                   modelCoords,
-                                   modelGeneral,
-                                   modelMainWindow,
-                                   dummyXThetaOut,
-                                   *(yRadiusValues [rowClosest]),
-                                   transformation);
+    if (xThetaIsNotOutOfBounds (posGraph.x(),
+                                curveName,
+                                curveLimitsMin,
+                                curveLimitsMax)) {
+      QString dummyXThetaOut;
+      format.unformattedToFormatted (posGraph.x(),
+                                     posGraph.y(),
+                                     modelCoords,
+                                     modelGeneral,
+                                     modelMainWindow,
+                                     dummyXThetaOut,
+                                     *(yRadiusValues [rowClosest]),
+                                     transformation);
+    } else {
+      *(yRadiusValues [rowClosest]) = "";
+    }
   }
 }
 
@@ -629,3 +715,21 @@ bool ExportFileFunctions::rowHasAtLeastOneYRadiusEntry (const QVector<QVector<QS
 
   return hasEntry;
 }
+
+bool ExportFileFunctions::xThetaIsNotOutOfBounds (double xTheta,
+                                                  const QString &curveName,
+                                                  const CurveLimits &curveLimitsMin,
+                                                  const CurveLimits &curveLimitsMax) const
+{
+  bool ok = true;
+
+  if (curveLimitsMin.contains (curveName)) {
+    ok = ok && (curveLimitsMin [curveName] <= xTheta);
+  }
+
+  if (curveLimitsMax.contains (curveName)) {
+    ok = ok && (xTheta <= curveLimitsMax [curveName]);
+  }
+
+  return ok;
+}
diff --git a/src/Export/ExportFileFunctions.h b/src/Export/ExportFileFunctions.h
index ab01cf4e..581a8cfb 100644
--- a/src/Export/ExportFileFunctions.h
+++ b/src/Export/ExportFileFunctions.h
@@ -7,10 +7,13 @@
 #ifndef EXPORT_FILE_FUNCTIONS_H
 #define EXPORT_FILE_FUNCTIONS_H
 
+#include "CurveLimits.h"
 #include "ExportFileAbstractBase.h"
 #include "ExportValuesXOrY.h"
+#include "Points.h"
 #include <QStringList>
 #include <QVector>
+#include "ValuesVectorXOrY.h"
 
 class Document;
 class DocumentModelCoords;
@@ -50,6 +53,8 @@ private:
                                            const Transformation &transformation,
                                            bool isLogXTheta,
                                            bool isLogYRadius,
+                                           const CurveLimits curveLimitsMin,
+                                           const CurveLimits curveLimitsMax,
                                            QTextStream &str,
                                            unsigned int &numWritesSoFar) const;
   void exportOnePerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
@@ -61,6 +66,8 @@ private:
                                            const Transformation &transformation,
                                            bool isLogXTheta,
                                            bool isLogYRadius,
+                                           const CurveLimits curveLimitsMin,
+                                           const CurveLimits curveLimitsMax,
                                            QTextStream &str,
                                            unsigned int &numWritesSoFar) const;
 
@@ -74,7 +81,7 @@ private:
   double linearlyInterpolate (const Points &points,
                               double xThetaValue,
                               const Transformation &transformation) const;
-  void loadYRadiusValues (const DocumentModelExportFormat &modelExport,
+  void loadYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
                           const Document &document,
                           const MainWindowModel &modelMainWindow,
                           const QStringList &curvesIncluded,
@@ -82,6 +89,8 @@ private:
                           bool isLogXTheta,
                           bool isLogYRadius,
                           const ExportValuesXOrY &xThetaValues,
+                          const CurveLimits &curveLimitsMin,
+                          const CurveLimits &curveLimitsMax,
                           QVector<QVector<QString*> > &yRadiusValues) const;
   void loadYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
                                                     const DocumentModelGeneral &modelGeneral,
@@ -91,6 +100,9 @@ private:
                                                     const Transformation &transformation,
                                                     bool isLogXTheta,
                                                     bool isLogYRadius,
+                                                    const QString &curveName,
+                                                    const CurveLimits &curveLimitsMin,
+                                                    const CurveLimits &curveLimitsMax,
                                                     QVector<QString*> &yRadiusValues) const;
   void loadYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
                                                       const DocumentModelGeneral &modelGeneral,
@@ -98,6 +110,9 @@ private:
                                                       const Points &points,
                                                       const ExportValuesXOrY &xThetaValues,
                                                       const Transformation &transformation,
+                                                      const QString &curveName,
+                                                      const CurveLimits &curveLimitsMin,
+                                                      const CurveLimits &curveLimitsMax,
                                                       QVector<QString*> &yRadiusValues) const;
   void loadYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
                                      const DocumentModelGeneral &modelGeneral,
@@ -105,6 +120,9 @@ private:
                                      const Points &points,
                                      const ExportValuesXOrY &xThetaValues,
                                      const Transformation &transformation,
+                                     const QString &curveName,
+                                     const CurveLimits &curveLimitsMin,
+                                     const CurveLimits &curveLimitsMax,
                                      QVector<QString*> &yRadiusValues) const;
 
   /// Output 2D y/radius array along with x/theta vector in first column
@@ -123,6 +141,12 @@ private:
   // since the union of all x/theta values is applied to each curve
   bool rowHasAtLeastOneYRadiusEntry (const QVector<QVector<QString*> > &yRadiusValues,
                                      int row) const;
+
+  // If there are bounds for the curve, make sure xTheta is within those bounds
+  bool xThetaIsNotOutOfBounds (double xTheta,
+                               const QString &curveName,
+                               const CurveLimits &curveLimitsMin,
+                               const CurveLimits &curveLimitsMax) const;
 };
 
 #endif // EXPORT_FILE_FUNCTIONS_H
diff --git a/src/Export/ExportFileRelations.h b/src/Export/ExportFileRelations.h
index aae3245f..e57034db 100644
--- a/src/Export/ExportFileRelations.h
+++ b/src/Export/ExportFileRelations.h
@@ -10,6 +10,7 @@
 #include "ExportFileAbstractBase.h"
 #include "ExportPointsIntervalUnits.h"
 #include "ExportValuesOrdinal.h"
+#include "Points.h"
 #include <QStringList>
 #include <QVector>
 
diff --git a/src/Export/ExportHeader.cpp b/src/Export/ExportHeader.cpp
index 21fbe4c2..1768d5a7 100644
--- a/src/Export/ExportHeader.cpp
+++ b/src/Export/ExportHeader.cpp
@@ -9,17 +9,21 @@
 
 QString exportHeaderToString (ExportHeader exportHeader)
 {
+  QString rtn;
+
   switch (exportHeader) {
     case EXPORT_HEADER_GNUPLOT:
-      return QObject::tr ("Gnuplot");
+      rtn = QObject::tr ("Gnuplot");
+      break;
 
     case EXPORT_HEADER_NONE:
-      return QObject::tr ("None");
+      rtn = QObject::tr ("None");
+      break;
 
     case EXPORT_HEADER_SIMPLE:
-      return QObject::tr ("Simple");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Simple");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportImageForRegression.cpp b/src/Export/ExportImageForRegression.cpp
index c0e0078e..1593895d 100644
--- a/src/Export/ExportImageForRegression.cpp
+++ b/src/Export/ExportImageForRegression.cpp
@@ -22,7 +22,7 @@ void ExportImageForRegression::fileExport (const QString &filename) const
 {
   QFile file (filename);
   if (!file.open (QIODevice::WriteOnly)) {
-    QMessageBox::critical (0,
+    QMessageBox::critical (nullptr,
                            QObject::tr ("Export Image"),
                            QObject::tr ("Cannot export file"));
   } else {
diff --git a/src/Export/ExportLayoutFunctions.cpp b/src/Export/ExportLayoutFunctions.cpp
index a1717e74..dcd9eec7 100644
--- a/src/Export/ExportLayoutFunctions.cpp
+++ b/src/Export/ExportLayoutFunctions.cpp
@@ -9,14 +9,17 @@
 
 QString exportLayoutFunctionsToString (ExportLayoutFunctions exportLayoutFunctions)
 {
+  QString rtn;
+
   switch (exportLayoutFunctions) {
     case EXPORT_LAYOUT_ALL_PER_LINE:
-      return QObject::tr ("AllPerLine");
+      rtn = QObject::tr ("AllPerLine");
+      break;
 
     case EXPORT_LAYOUT_ONE_PER_LINE:
-      return QObject::tr ("OnePerLine");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("OnePerLine");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportOrdinalsSmooth.cpp b/src/Export/ExportOrdinalsSmooth.cpp
index 9934956d..2319188b 100644
--- a/src/Export/ExportOrdinalsSmooth.cpp
+++ b/src/Export/ExportOrdinalsSmooth.cpp
@@ -94,9 +94,9 @@ ExportValuesOrdinal ExportOrdinalsSmooth::ordinalsAtIntervalsGraph (const vector
     int iTLastInterval = 0;
     for (int iT = 0; iT < NUM_SMALLER_INTERVALS; iT++) {
 
-      double t = tMin + ((tMax - tMin) * iT) / (NUM_SMALLER_INTERVALS - 1.0);
+      double tIter = tMin + ((tMax - tMin) * iT) / (NUM_SMALLER_INTERVALS - 1.0);
 
-      SplinePair pairNew = spline.interpolateCoeff(t);
+      SplinePair pairNew = spline.interpolateCoeff(tIter);
 
       QPointF posNew = QPointF (pairNew.x(),
                                 pairNew.y());
@@ -113,9 +113,9 @@ ExportValuesOrdinal ExportOrdinalsSmooth::ordinalsAtIntervalsGraph (const vector
         if (iT == 0) {
           sInterp = 0.0;
         } else {
-          sInterp = (double) pointsInterval / (double) integratedSeparation;
+          sInterp = double (pointsInterval) / double (integratedSeparation);
         }
-        double tInterp = (1.0 - sInterp) * tLast + sInterp * t;
+        double tInterp = (1.0 - sInterp) * tLast + sInterp * tIter;
 
         integratedSeparation -= pointsInterval; // Part of delta that was not used gets applied to next interval
 
@@ -124,7 +124,7 @@ ExportValuesOrdinal ExportOrdinalsSmooth::ordinalsAtIntervalsGraph (const vector
         iTLastInterval = iT;
       }
 
-      tLast = t;
+      tLast = tIter;
       posLast = posNew;
     }
 
diff --git a/src/Export/ExportPointsIntervalUnits.cpp b/src/Export/ExportPointsIntervalUnits.cpp
index 85d786d5..faec3b27 100644
--- a/src/Export/ExportPointsIntervalUnits.cpp
+++ b/src/Export/ExportPointsIntervalUnits.cpp
@@ -9,14 +9,17 @@
 
 QString exportPointsIntervalUnitsToString (ExportPointsIntervalUnits exportPointsIntervalUnits)
 {
+  QString rtn;
+
   switch (exportPointsIntervalUnits) {
   case EXPORT_POINTS_INTERVAL_UNITS_GRAPH:
-    return QObject::tr ("Graph Units");
+    rtn = QObject::tr ("Graph Units");
+    break;
 
   case EXPORT_POINTS_INTERVAL_UNITS_SCREEN:
-    return QObject::tr ("Pixels");
-
-  default:
-    return QObject::tr ("Unknown");
+    rtn = QObject::tr ("Pixels");
+    break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportPointsSelectionFunctions.cpp b/src/Export/ExportPointsSelectionFunctions.cpp
index 0d844720..bd7be46f 100644
--- a/src/Export/ExportPointsSelectionFunctions.cpp
+++ b/src/Export/ExportPointsSelectionFunctions.cpp
@@ -9,20 +9,29 @@
 
 QString exportPointsSelectionFunctionsToString (ExportPointsSelectionFunctions exportPointsSelectionFunctions)
 {
+  QString rtn;
+
   switch (exportPointsSelectionFunctions) {
     case EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES:
-      return QObject::tr ("InterpolateAllCurves");
+      rtn = QObject::tr ("InterpolateAllCurves");
+      break;
 
     case EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE:
-      return QObject::tr ("InterpolateFirstCurve");
+      rtn = QObject::tr ("InterpolateFirstCurve");
+      break;
 
     case EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC:
-      return QObject::tr ("InterpolatePeriodic");
+      rtn = QObject::tr ("InterpolatePeriodic");
+      break;
 
     case EXPORT_POINTS_SELECTION_FUNCTIONS_RAW:
-      return QObject::tr ("Raw");
+      rtn = QObject::tr ("Raw");
+      break;
 
     default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Unknown");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportPointsSelectionFunctions.h b/src/Export/ExportPointsSelectionFunctions.h
index 8c85057c..873ecc6d 100644
--- a/src/Export/ExportPointsSelectionFunctions.h
+++ b/src/Export/ExportPointsSelectionFunctions.h
@@ -13,7 +13,8 @@ enum ExportPointsSelectionFunctions {
   EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_ALL_CURVES,
   EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_FIRST_CURVE,
   EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC,
-  EXPORT_POINTS_SELECTION_FUNCTIONS_RAW
+  EXPORT_POINTS_SELECTION_FUNCTIONS_RAW,
+  EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES
 };
 
 extern QString exportPointsSelectionFunctionsToString (ExportPointsSelectionFunctions exportPointsSelectionFunctions);
diff --git a/src/Export/ExportPointsSelectionRelations.cpp b/src/Export/ExportPointsSelectionRelations.cpp
index b9c53f59..1bf9e1c4 100644
--- a/src/Export/ExportPointsSelectionRelations.cpp
+++ b/src/Export/ExportPointsSelectionRelations.cpp
@@ -9,14 +9,17 @@
 
 extern QString exportPointsSelectionRelationsToString (ExportPointsSelectionRelations exportPointsSelectionRelations)
 {
+  QString rtn;
+
   switch (exportPointsSelectionRelations) {
     case EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE:
-      return QObject::tr ("Interpolate");
+      rtn = QObject::tr ("Interpolate");
+      break;
 
     case EXPORT_POINTS_SELECTION_RELATIONS_RAW:
-      return QObject::tr ("Raw");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Raw");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Export/ExportXThetaValuesMergedFunctions.cpp b/src/Export/ExportXThetaValuesMergedFunctions.cpp
index 76f73c14..12532723 100644
--- a/src/Export/ExportXThetaValuesMergedFunctions.cpp
+++ b/src/Export/ExportXThetaValuesMergedFunctions.cpp
@@ -121,7 +121,9 @@ ExportValuesXOrY ExportXThetaValuesMergedFunctions::periodicLinearScreen (double
 {
   LOG4CPP_INFO_S ((*mainCat)) << "ExportXThetaValuesMergedFunctions::periodicLinearScreen";
 
-  const double ARBITRARY_Y = 0.0;
+  // This must be greater than zero. Otherwise, logarithmic y axis will trigger errors in the
+  // transform, which cascades into NaN values for the x coordinates below
+  const double ARBITRARY_Y = 1.0;
 
   // Screen coordinates of endpoints
   QPointF posScreenFirst, posScreenLast;
@@ -132,15 +134,13 @@ ExportValuesXOrY ExportXThetaValuesMergedFunctions::periodicLinearScreen (double
                                                       ARBITRARY_Y),
                                              posScreenLast);
   double deltaScreenX = posScreenLast.x() - posScreenFirst.x();
-  double deltaScreenY = posScreenLast.y() - posScreenFirst.y();
-  double deltaScreen = qSqrt (deltaScreenX * deltaScreenX + deltaScreenY * deltaScreenY);
 
   // Need calculations to find the scaling to be applied to successive points
   double s = 1.0;
   double interval = m_modelExport.pointsIntervalFunctions();
   if ((interval > 0) &&
-      (interval < deltaScreen)) {
-    s = interval / deltaScreen;
+      (interval < deltaScreenX)) {
+    s = interval / deltaScreenX;
   }
 
   // Example: xThetaMin=0.1 and xThetaMax=100 (points are 0.1, 1, 10, 100) with s=1/3 so scale should be 10
@@ -191,17 +191,21 @@ ExportValuesXOrY ExportXThetaValuesMergedFunctions::periodicLogGraph (double xTh
   // Convert the gathered values into a periodic sequence
   ValuesVectorXOrY values;
   double xTheta = xThetaFirstSimplestNumber;
-  while (xTheta > xThetaMin) {
-    xTheta /= m_modelExport.pointsIntervalFunctions(); // Go backwards until reaching or passing minimum
+  if (m_modelExport.pointsIntervalFunctions() > 1) { // Safe to iterate
+    while (xTheta > xThetaMin) {
+      xTheta /= m_modelExport.pointsIntervalFunctions(); // Go backwards until reaching or passing minimum
+    }
   }
   if (xTheta < xThetaMin) {
     values [xThetaMin] = true; // We passed minimum so insert point right at xThetaMin
   }
 
-  xTheta *= m_modelExport.pointsIntervalFunctions();
-  while (xTheta <= xThetaMax) {
-    values [xTheta] = true;
-    xTheta *= m_modelExport.pointsIntervalFunctions(); // Insert point at a simple number
+  if (m_modelExport.pointsIntervalFunctions() > 1) { // Safe to iterate
+    xTheta *= m_modelExport.pointsIntervalFunctions();
+    while (xTheta <= xThetaMax) {
+      values [xTheta] = true;
+      xTheta *= m_modelExport.pointsIntervalFunctions(); // Insert point at a simple number
+    }
   }
 
   if (xTheta > xThetaMax) {
@@ -263,7 +267,7 @@ ExportValuesXOrY ExportXThetaValuesMergedFunctions::xThetaValues () const
   if (m_modelExport.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_PERIODIC) {
 
     // Special case that occurs when there are no points
-    if (m_modelExport.pointsIntervalFunctions() == 0) {
+    if (qAbs (m_modelExport.pointsIntervalFunctions()) <= 0) {
 
       ExportValuesXOrY empty;
       return empty;
diff --git a/src/FileCmd/FileCmdFactory.cpp b/src/FileCmd/FileCmdFactory.cpp
index b7e5064b..90968432 100644
--- a/src/FileCmd/FileCmdFactory.cpp
+++ b/src/FileCmd/FileCmdFactory.cpp
@@ -24,7 +24,7 @@ FileCmdFactory::~FileCmdFactory()
 
 FileCmdAbstract *FileCmdFactory::createFileCmd (QXmlStreamReader &reader) const
 {
-  FileCmdAbstract *cmd = 0;
+  FileCmdAbstract *cmd = nullptr;
 
   QXmlStreamAttributes attributes = reader.attributes();
   if (!attributes.hasAttribute (FILE_CMD_SERIALIZE_CMD_TYPE)) {
diff --git a/src/FileCmd/FileCmdScript.cpp b/src/FileCmd/FileCmdScript.cpp
index 8fe373c3..772db359 100644
--- a/src/FileCmd/FileCmdScript.cpp
+++ b/src/FileCmd/FileCmdScript.cpp
@@ -21,35 +21,40 @@ FileCmdScript::FileCmdScript(const QString &fileCmdScriptFile)
   LOG4CPP_INFO_S ((*mainCat)) << "FileCmdScript::FileCmdScript"
                               << " curDir=" << QDir::currentPath().toLatin1().data();
 
-  // Read commands into stack. The file is known to exist since it was checked in parseCmdLine
-  QFile file (fileCmdScriptFile);
+  // A non-existent script file is allowed in which case nothing gets done, as a way
+  // of tracking MainWindow being in a regression test that has no command script
+  if (!fileCmdScriptFile.isEmpty ()) {
 
-  QXmlStreamReader reader (&file);
-  if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+    // Read commands into stack. The file is known to exist since it was checked in parseCmdLine
+    QFile file (fileCmdScriptFile);
 
-    QString msg = QString ("%1 %2 %3 %4")
-      .arg (QObject::tr ("Cannot read script file"))
-      .arg (fileCmdScriptFile)
-      .arg (QObject::tr ("from directory"))
-      .arg (QDir::currentPath());
-    QMessageBox::critical (0,
-                           "Script File",
-                           msg);
-    exit (-1);
-  }
+    QXmlStreamReader reader (&file);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+
+      QString msg = QString ("%1 %2 %3 %4")
+          .arg (QObject::tr ("Cannot read script file"))
+          .arg (fileCmdScriptFile)
+          .arg (QObject::tr ("from directory"))
+          .arg (QDir::currentPath());
+      QMessageBox::critical (nullptr,
+                             "Script File",
+                             msg);
+      exit (-1);
+    }
 
-  // Load commands
-  FileCmdFactory factory;
-  while (!reader.atEnd() && !reader.hasError()) {
+    // Load commands
+    FileCmdFactory factory;
+    while (!reader.atEnd() && !reader.hasError()) {
 
-    if ((loadNextFromReader (reader) == QXmlStreamReader::StartElement) &&
-        (reader.name() == FILE_CMD_SERIALIZE_CMD)) {
+      if ((loadNextFromReader (reader) == QXmlStreamReader::StartElement) &&
+          (reader.name() == FILE_CMD_SERIALIZE_CMD)) {
 
-      // Extract and append new command to command stack
-      m_fileCmdStack.push_back (factory.createFileCmd (reader));
+        // Extract and append new command to command stack
+        m_fileCmdStack.push_back (factory.createFileCmd (reader));
+      }
     }
+    file.close();
   }
-  file.close();
 }
 
 FileCmdScript::~FileCmdScript()
diff --git a/src/Fitting/FittingCurve.cpp b/src/Fitting/FittingCurve.cpp
index adafe364..c8456cba 100644
--- a/src/Fitting/FittingCurve.cpp
+++ b/src/Fitting/FittingCurve.cpp
@@ -32,7 +32,7 @@ FittingCurve::FittingCurve (const FittingCurveCoefficients &fittingCoef,
     for (int i = 0; i < NUM_POINTS; i++) {
 
       // Compute (x,y) point in graph coordinates
-      double s = (double) i / (double) (NUM_POINTS - 1);
+      double s = double (i) / double (NUM_POINTS - 1);
       double x = xMin + s * (xMax - xMin);
       double y = yFromCoefficientsAndX (fittingCoef,
                                         x);
diff --git a/src/Fitting/FittingStatistics.cpp b/src/Fitting/FittingStatistics.cpp
index 5ce2f562..e3d8ec58 100644
--- a/src/Fitting/FittingStatistics.cpp
+++ b/src/Fitting/FittingStatistics.cpp
@@ -122,7 +122,7 @@ void FittingStatistics::calculateCurveFitAndStatistics (unsigned int order,
   // To prevent having an underdetermined system with an infinite number of solutions (which will result
   // in divide by zero when computing an inverse) we reduce the order here if necessary.
   // In other words, we limit the order to -1 for no points, 0 for one point, 1 for two points, and so on
-  int orderReduced = qMin ((int) order,
+  int orderReduced = qMin (qFloor (order),
                            pointsConvenient.size() - 1);
 
   calculateCurveFit (orderReduced,
@@ -217,7 +217,7 @@ double FittingStatistics::yFromXAndCoefficients (const FittingCurveCoefficients
     if (order < coefficients.size ()) {
       coef = coefficients [order];
     }
-    sum += coef * qPow (x, (double) order);
+    sum += coef * qPow (x, double (order));
   }
 
   return sum;
diff --git a/src/Fitting/FittingWindow.cpp b/src/Fitting/FittingWindow.cpp
index 1cfda65a..211a390f 100644
--- a/src/Fitting/FittingWindow.cpp
+++ b/src/Fitting/FittingWindow.cpp
@@ -63,13 +63,13 @@ void FittingWindow::calculateCurveFitAndStatistics ()
   FittingStatistics fittingStatistics;
 
   double mse = 0, rms = 0, rSquared = 0;
-  fittingStatistics.calculateCurveFitAndStatistics (maxOrder (),
+  fittingStatistics.calculateCurveFitAndStatistics (unsigned (maxOrder ()),
                                                     m_pointsConvenient,
                                                     m_coefficients,
                                                     mse,
                                                     rms,
                                                     rSquared,
-                                                    m_significantDigits);
+                                                    qFloor (m_significantDigits));
 
   m_lblMeanSquareError->setText (QString::number (mse));
   m_lblRootMeanSquare->setText (QString::number (rms));
diff --git a/src/Format/FormatCoordsUnitsStrategyAbstractBase.cpp b/src/Format/FormatCoordsUnitsStrategyAbstractBase.cpp
index 64ce04b0..55ff9cb4 100644
--- a/src/Format/FormatCoordsUnitsStrategyAbstractBase.cpp
+++ b/src/Format/FormatCoordsUnitsStrategyAbstractBase.cpp
@@ -20,7 +20,7 @@ int FormatCoordsUnitsStrategyAbstractBase::precisionDigitsForRawNumber (double v
                                                                         const DocumentModelGeneral &modelGeneral,
                                                                         const Transformation &transformation) const
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyAbstractBase::precisionDigitsForRawNumber";
+  //LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyAbstractBase::precisionDigitsForRawNumber";
 
   const double PIXEL_SHIFT = 1;
   const int DEFAULT_PRECISION = 5; // Precision used before transformation is available. Equal or greater than x/y pixel counts
diff --git a/src/Format/FormatCoordsUnitsStrategyNonPolarTheta.cpp b/src/Format/FormatCoordsUnitsStrategyNonPolarTheta.cpp
index c4e9a19e..75748117 100644
--- a/src/Format/FormatCoordsUnitsStrategyNonPolarTheta.cpp
+++ b/src/Format/FormatCoordsUnitsStrategyNonPolarTheta.cpp
@@ -23,7 +23,7 @@ double FormatCoordsUnitsStrategyNonPolarTheta::formattedToUnformatted (const QSt
                                                                        CoordUnitsDate coordUnitsDate,
                                                                        CoordUnitsTime coordUnitsTime) const
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyNonPolarTheta::formattedToUnformatted";
+  //LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyNonPolarTheta::formattedToUnformatted";
 
   double value;
 
@@ -70,7 +70,7 @@ QString FormatCoordsUnitsStrategyNonPolarTheta::unformattedToFormatted (double v
                                                                         const Transformation &transformation,
                                                                         double valueUnformattedOther) const
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyNonPolarTheta::unformattedToFormatted";
+  //LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyNonPolarTheta::unformattedToFormatted";
 
   const char FORMAT ('g');
 
diff --git a/src/Format/FormatCoordsUnitsStrategyPolarTheta.cpp b/src/Format/FormatCoordsUnitsStrategyPolarTheta.cpp
index 9ed7266f..214e2c5d 100644
--- a/src/Format/FormatCoordsUnitsStrategyPolarTheta.cpp
+++ b/src/Format/FormatCoordsUnitsStrategyPolarTheta.cpp
@@ -19,7 +19,7 @@ double FormatCoordsUnitsStrategyPolarTheta::formattedToUnformatted (const QStrin
                                                                     const QLocale &locale,
                                                                     CoordUnitsPolarTheta coordUnits) const
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyPolarTheta::formattedToUnformatted";
+  //LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyPolarTheta::formattedToUnformatted";
 
   double value;
 
@@ -57,7 +57,7 @@ QString FormatCoordsUnitsStrategyPolarTheta::unformattedToFormatted (double valu
                                                                      const Transformation &transformation,
                                                                      double valueUnformattedOther) const
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyPolarTheta::unformattedToFormatted";
+  //LOG4CPP_DEBUG_S ((*mainCat)) << "FormatCoordsUnitsStrategyPolarTheta::unformattedToFormatted";
 
   const char FORMAT ('g');
   const bool IS_X_THETA = true;
diff --git a/src/Format/FormatDateTime.cpp b/src/Format/FormatDateTime.cpp
index ec4192f0..9f73c2b2 100644
--- a/src/Format/FormatDateTime.cpp
+++ b/src/Format/FormatDateTime.cpp
@@ -8,6 +8,7 @@
 #include "FormatDateTime.h"
 #include "Logger.h"
 #include <QDateTime>
+#include <qmath.h>
 #include <QTimeZone>
 
 // Need a reference time zone so exported outputs do not exhibit unpredictable local/UTC hours differences
@@ -136,7 +137,9 @@ QString FormatDateTime::formatOutput (CoordUnitsDate coordUnitsDate,
   QString format = m_formatsDateFormat [coordUnitsDate] + " " + m_formatsTimeFormat [coordUnitsTime];
   format = format.trimmed();
 
-  QDateTime dt = QDateTime::fromTime_t (value);
+  // Range of unsigned versus signed is not a problem here. A signed value maxes out at 2.4 billion
+  // which is year 2038
+  QDateTime dt = QDateTime::fromTime_t (unsigned (qFloor (value)));
 
   return dt.toTimeSpec(REFERENCE_TIME_ZONE).toString (format);
 }
diff --git a/src/Format/FormatDegreesMinutesSecondsBase.cpp b/src/Format/FormatDegreesMinutesSecondsBase.cpp
index 28516572..70684505 100644
--- a/src/Format/FormatDegreesMinutesSecondsBase.cpp
+++ b/src/Format/FormatDegreesMinutesSecondsBase.cpp
@@ -29,15 +29,15 @@ FormatDegreesMinutesSecondsBase::~FormatDegreesMinutesSecondsBase()
 
 QString FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSeconds (double value) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSeconds"
-                              << " value=" << value;
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSeconds"
+  //                            << " value=" << value;
 
   // Only smallest resolution value is floating point
   bool negative = (value < 0);
   value = qAbs (value);
   int degrees = qFloor (value);
   value -= degrees;
-  int minutes = value * DEGREES_TO_MINUTES;
+  int minutes = qFloor (value * DEGREES_TO_MINUTES);
   value -= minutes * MINUTES_TO_DEGREES;
   double seconds = value * DEGREES_TO_SECONDS;
   degrees *= (negative ? -1.0 : 1.0);
@@ -54,16 +54,16 @@ QString FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSeconds (doub
 QString FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSecondsNsew (double value,
                                                                                 bool isNsHemisphere) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSecondsNsew"
-                              << " value=" << value
-                              << " isNsHemisphere=" << (isNsHemisphere ? "true" : "false");
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSecondsNsew"
+  //                            << " value=" << value
+  //                            << " isNsHemisphere=" << (isNsHemisphere ? "true" : "false");
 
   // Only smallest resolution value is floating point
   bool negative = (value < 0);
   value = qAbs (value);
   int degrees = qFloor (value);
   value -= degrees;
-  int minutes = value * DEGREES_TO_MINUTES;
+  int minutes = qFloor (value * DEGREES_TO_MINUTES);
   value -= minutes * MINUTES_TO_DEGREES;
   double seconds = value * DEGREES_TO_SECONDS;
 
@@ -87,8 +87,8 @@ QString FormatDegreesMinutesSecondsBase::formatOutputDegreesMinutesSecondsNsew (
 QValidator::State FormatDegreesMinutesSecondsBase::parseInput (const QString &stringUntrimmed,
                                                                double &value) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::parseInput"
-                              << " string=" << stringUntrimmed.toLatin1().data();
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsBase::parseInput"
+  //                            << " string=" << stringUntrimmed.toLatin1().data();
 
   const QString string = stringUntrimmed.trimmed ();
 
diff --git a/src/Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp b/src/Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp
index 12b91fa4..c4968088 100644
--- a/src/Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp
+++ b/src/Format/FormatDegreesMinutesSecondsNonPolarTheta.cpp
@@ -20,7 +20,7 @@ QString FormatDegreesMinutesSecondsNonPolarTheta::formatOutput (CoordUnitsNonPol
                                                                 double value,
                                                                 bool isNsHemisphere) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsNonPolarTheta::formatOutput";
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsNonPolarTheta::formatOutput";
 
   // See if similar method with hemisphere argument should have been called
   ENGAUGE_ASSERT (coordUnits != COORD_UNITS_NON_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW);
diff --git a/src/Format/FormatDegreesMinutesSecondsPolarTheta.cpp b/src/Format/FormatDegreesMinutesSecondsPolarTheta.cpp
index cc50d64b..51df0bfe 100644
--- a/src/Format/FormatDegreesMinutesSecondsPolarTheta.cpp
+++ b/src/Format/FormatDegreesMinutesSecondsPolarTheta.cpp
@@ -22,7 +22,7 @@ QString FormatDegreesMinutesSecondsPolarTheta::formatOutput (CoordUnitsPolarThet
                                                              double value,
                                                              bool isNsHemisphere) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutput";
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutput";
 
   // See if similar method with hemisphere argument should have been called
   ENGAUGE_ASSERT (coordUnits != COORD_UNITS_POLAR_THETA_DEGREES_MINUTES_SECONDS_NSEW);
@@ -53,7 +53,7 @@ QString FormatDegreesMinutesSecondsPolarTheta::formatOutput (CoordUnitsPolarThet
 
 QString FormatDegreesMinutesSecondsPolarTheta::formatOutputDegrees (double value) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutputDegrees";
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutputDegrees";
 
   // Since version 6 there has been no number-only option (=without degrees symbol) for theta in CoordUnitsPolarTheta.
   // The degrees symbol causes more problems than it is worth for COORD_UNITS_POLAR_THETA_DEGREES, so we output only
@@ -64,7 +64,7 @@ QString FormatDegreesMinutesSecondsPolarTheta::formatOutputDegrees (double value
 
 QString FormatDegreesMinutesSecondsPolarTheta::formatOutputDegreesMinutes (double value) const
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutputDegreesMinutes";
+  //LOG4CPP_INFO_S ((*mainCat)) << "FormatDegreesMinutesSecondsPolarTheta::formatOutputDegreesMinutes";
 
   // Only smallest resolution value is floating point
   bool negative = (value < 0);
diff --git a/src/Geometry/GeometryModel.cpp b/src/Geometry/GeometryModel.cpp
index fa2703aa..4286f991 100644
--- a/src/Geometry/GeometryModel.cpp
+++ b/src/Geometry/GeometryModel.cpp
@@ -22,6 +22,9 @@ GeometryModel::~GeometryModel()
 
 QVariant GeometryModel::data(const QModelIndex &index, int role) const
 {
+  const int HEADER_OFFSET = 1;
+  const int NUM_LEGEND_ROWS_UNSPANNED = 2; // Match with GeometryWindow::NUM_LEGEND_ROWS_UNSPANNED
+
 //  LOG4CPP_DEBUG_S ((*mainCat)) << "GeometryModel::data"
 //                               << " rowHighlighted=" << m_rowToBeHighlighted
 //                               << " index=(row=" << index.row() << ",col=" << index.column() << ",role=" << role << ")="
@@ -32,10 +35,21 @@ QVariant GeometryModel::data(const QModelIndex &index, int role) const
       !m_pointIdentifier.isEmpty () &&
       (index.row () == m_rowToBeHighlighted)) {
 
-    // This row is to be highlighted
+    // This row is to be highlighted with gray
     return QVariant (QColor (230, 230, 230));
   }
 
+  bool ambiguousSegment = ((role == Qt::BackgroundRole) &&
+                           (m_ambiguousRows.contains (index.row () - HEADER_OFFSET)));
+  bool ambiguousFootnote = ((role == Qt::BackgroundRole) &&
+                            (m_ambiguousRows.size () > 0) &&
+                            (index.row () >= rowCount () - NUM_LEGEND_ROWS_UNSPANNED));
+  if (ambiguousSegment || ambiguousFootnote) {
+
+    // This row is to be highlighted with light red. Note that gray color preempts this behavior
+    return QVariant (QColor (255, 0, 0, 50));
+  }
+
   // Standard behavior
   return QStandardItemModel::data (index, role);
 }
@@ -100,3 +114,14 @@ void GeometryModel::setCurrentPointIdentifier (const QString &pointIdentifier)
                     indexBottomRight,
                     roles);
 }
+
+void GeometryModel::setPotentialExportAmbiguity (const QVector<bool> &isPotentialExportAmbiguity)
+{
+  // Save row numbers with ambiguities
+  m_ambiguousRows.clear ();
+  for (int i = 0; i < isPotentialExportAmbiguity.size (); i++) {
+    if (isPotentialExportAmbiguity.at (i)) {
+      m_ambiguousRows [i] = true;
+    }
+  }
+}
diff --git a/src/Geometry/GeometryModel.h b/src/Geometry/GeometryModel.h
index a491c3fd..9a754c0d 100644
--- a/src/Geometry/GeometryModel.h
+++ b/src/Geometry/GeometryModel.h
@@ -7,7 +7,9 @@
 #ifndef GEOMETRY_MODEL_H
 #define GEOMETRY_MODEL_H
 
+#include <QHash>
 #include <QString>
+#include <QVector>
 #include "WindowModelBase.h"
 
 /// Model that adds row highlighting according to the currently select point identifier
@@ -24,12 +26,18 @@ public:
   /// Set the point identifier to be highlighted. Value is empty for no highlighting
   void setCurrentPointIdentifier (const QString  &pointIdentifier);
 
+  /// Remember which rows could have ambiguities during export - these will be highlighted
+  void setPotentialExportAmbiguity (const QVector<bool> &isPotentialExportAmbiguity);
+
 private:
 
   int rowToBeHighlighted () const;
 
   int m_rowToBeHighlighted;
   QString m_pointIdentifier; // Point to be higlighted. Empty if none
+
+  // Row numbers with ambiguities
+  QHash<int, bool> m_ambiguousRows;
 };
 
 #endif // GEOMETRY_MODEL_H
diff --git a/src/Geometry/GeometryStrategyAbstractBase.cpp b/src/Geometry/GeometryStrategyAbstractBase.cpp
index a90051e2..377ce677 100644
--- a/src/Geometry/GeometryStrategyAbstractBase.cpp
+++ b/src/Geometry/GeometryStrategyAbstractBase.cpp
@@ -74,7 +74,7 @@ void GeometryStrategyAbstractBase::insertSubintervalsAndLoadDistances (int subin
     vector<double> t;
     vector<SplinePair> xy;
     for (int i = 0; i < positionsGraph.size (); i++) {
-      t.push_back ((double) i);
+      t.push_back (double (i));
       xy.push_back (SplinePair (positionsGraph [i].x(),
                                 positionsGraph [i].y()));
     }
@@ -91,7 +91,7 @@ void GeometryStrategyAbstractBase::insertSubintervalsAndLoadDistances (int subin
       for (int subinterval = 0; subinterval < subintervalsPerInterval; subinterval++) {
 
         // Go from i-1 (exclusive) to i (inclusive)
-        double t = (double) (i - 1.0) + (double) (subinterval + 1) / (double) (subintervalsPerInterval);
+        double t = double (i - 1.0) + double (subinterval + 1) / double (subintervalsPerInterval);
 
         SplinePair splinePair = spline.interpolateCoeff (t);
 
@@ -133,6 +133,16 @@ void GeometryStrategyAbstractBase::insertSubintervalsAndLoadDistances (int subin
   }
 }
 
+void GeometryStrategyAbstractBase::loadPotentialExportVector (QVector<QString> &x,
+                                                              QVector<QString> & /* y */,
+                                                              const Transformation & /* transformation */,
+                                                              QVector<bool> &isPotentialExportAmbiguity) const
+{
+  for (int i = 0; i < x.size(); i++) {
+    isPotentialExportAmbiguity.append (false);
+  }
+}
+
 void GeometryStrategyAbstractBase::loadXY (const QVector<QPointF> &positionsGraph,
                                            const DocumentModelCoords &modelCoords,
                                            const DocumentModelGeneral &modelGeneral,
diff --git a/src/Geometry/GeometryStrategyAbstractBase.h b/src/Geometry/GeometryStrategyAbstractBase.h
index 4eea2a78..b267a9a4 100644
--- a/src/Geometry/GeometryStrategyAbstractBase.h
+++ b/src/Geometry/GeometryStrategyAbstractBase.h
@@ -9,6 +9,7 @@
 
 #include "Points.h"
 #include <QPolygonF>
+#include <QString>
 #include <QVector>
 
 class DocumentModelCoords;
@@ -37,6 +38,7 @@ public:
                                   QString &polyArea,
                                   QVector<QString> &x,
                                   QVector<QString> &y,
+                                  QVector<bool> &isPotentialExportAmbiguity,
                                   QVector<QString> &distanceGraphForward,
                                   QVector<QString> &distancePercentForward,
                                   QVector<QString> &distanceGraphBackward,
@@ -63,6 +65,12 @@ protected:
                                            QVector<QString> &distanceGraphBackward,
                                            QVector<QString> &distancePercentBackward) const;
 
+  /// Load isPotentialExportAmbiguity vector. Default in base class is to load false values since there are no ambiguities
+  virtual void loadPotentialExportVector (QVector<QString> &x,
+                                          QVector<QString> &y,
+                                          const Transformation &transformation,
+                                          QVector<bool> &isPotentialExportAmbiguity) const;
+
   /// Load x and y coordinate vectors
   void loadXY (const QVector<QPointF> &positionsGraph,
                const DocumentModelCoords &modelCoords,
diff --git a/src/Geometry/GeometryStrategyContext.cpp b/src/Geometry/GeometryStrategyContext.cpp
index 96536663..af0cdd15 100644
--- a/src/Geometry/GeometryStrategyContext.cpp
+++ b/src/Geometry/GeometryStrategyContext.cpp
@@ -5,6 +5,8 @@
  ******************************************************************************************************/
 
 #include "CurveConnectAs.h"
+#include "DocumentModelCoords.h"
+#include "DocumentModelGeneral.h"
 #include "GeometryStrategyContext.h"
 #include "GeometryStrategyFunctionSmooth.h"
 #include "GeometryStrategyFunctionStraight.h"
@@ -22,6 +24,7 @@ GeometryStrategyContext::GeometryStrategyContext()
 
 GeometryStrategyContext::~GeometryStrategyContext()
 {
+  qDeleteAll (m_strategies);
 }
 
 void GeometryStrategyContext::calculateGeometry (const Points &points,
@@ -34,6 +37,7 @@ void GeometryStrategyContext::calculateGeometry (const Points &points,
                                                  QString &polyArea,
                                                  QVector<QString> &x,
                                                  QVector<QString> &y,
+                                                 QVector<bool> &isPotentialExportAmbiguity,
                                                  QVector<QString> &distanceGraphForward,
                                                  QVector<QString> &distancePercentForward,
                                                  QVector<QString> &distanceGraphBackward,
@@ -50,6 +54,7 @@ void GeometryStrategyContext::calculateGeometry (const Points &points,
                                                  polyArea,
                                                  x,
                                                  y,
+                                                 isPotentialExportAmbiguity,
                                                  distanceGraphForward,
                                                  distancePercentForward,
                                                  distanceGraphBackward,
diff --git a/src/Geometry/GeometryStrategyContext.h b/src/Geometry/GeometryStrategyContext.h
index b4a8cda5..2ce225ae 100644
--- a/src/Geometry/GeometryStrategyContext.h
+++ b/src/Geometry/GeometryStrategyContext.h
@@ -36,6 +36,7 @@ public:
                           QString &polyArea,
                           QVector<QString> &x,
                           QVector<QString> &y,
+                          QVector<bool> &isPotentialExportAmbiguity,
                           QVector<QString> &distanceGraphForward,
                           QVector<QString> &distancePercentForward,
                           QVector<QString> &distanceGraphBackward,
diff --git a/src/Geometry/GeometryStrategyFunctionSmooth.cpp b/src/Geometry/GeometryStrategyFunctionSmooth.cpp
index fd693a33..3bd9ee3a 100644
--- a/src/Geometry/GeometryStrategyFunctionSmooth.cpp
+++ b/src/Geometry/GeometryStrategyFunctionSmooth.cpp
@@ -5,8 +5,13 @@
  ******************************************************************************************************/
 
 #include "GeometryStrategyFunctionSmooth.h"
+#include "Spline.h"
+#include "SplineDrawer.h"
+#include "SplinePair.h"
 #include "Transformation.h"
 
+using namespace std;
+
 GeometryStrategyFunctionSmooth::GeometryStrategyFunctionSmooth()
 {
 }
@@ -24,6 +29,7 @@ void GeometryStrategyFunctionSmooth::calculateGeometry (const Points &points,
                                                         QString &polyArea,
                                                         QVector<QString> &x,
                                                         QVector<QString> &y,
+                                                        QVector<bool> &isPotentialExportAmbiguity,
                                                         QVector<QString> &distanceGraphForward,
                                                         QVector<QString> &distancePercentForward,
                                                         QVector<QString> &distanceGraphBackward,
@@ -53,7 +59,53 @@ void GeometryStrategyFunctionSmooth::calculateGeometry (const Points &points,
           x,
           y);
 
+  loadSmoothAmbiguityVector (x,
+                             y,
+                             transformation,
+                             isPotentialExportAmbiguity);
+
   // Set header values
   funcArea = QString::number (fArea);
   polyArea = "";
 }
+
+void GeometryStrategyFunctionSmooth::loadSmoothAmbiguityVector (QVector<QString> &x,
+                                                                QVector<QString> &y,
+                                                                const Transformation &transformation,
+                                                                QVector<bool> &isPotentialExportAmbiguity) const
+{
+  // There are N-1 segments for N points
+  int numSegments = x.size () - 1;
+
+  // Graph/screen transformation must be defined for SplineDrawer, and
+  // at least one point must be defined for Spline. Even better, one segment
+  // must be defined for Spline
+  if (transformation.transformIsDefined() &&
+      numSegments > 0) {
+
+    // Create spline
+    vector<double> t (unsigned (x.size ()));
+    vector<SplinePair> xy (unsigned (x.size ()));
+    for (unsigned int i = 0; i < unsigned (x.size ()); i++) {
+      t [i] = i;
+      xy [i] = SplinePair (x.at (signed (i)).toDouble (),
+                           y.at (signed (i)).toDouble ());
+    }
+    Spline s (t,
+              xy);
+
+    SplineDrawer sd (transformation);
+
+    for (int segment = 0; segment < numSegments; segment++) {
+      bool isMultiValued = sd.segmentIsMultiValued (s,
+                                                    x.size (),
+                                                    segment);
+      isPotentialExportAmbiguity.push_back (isMultiValued);
+    }
+  } else {
+
+    for (int segment = 0; segment < numSegments; segment++) {
+      isPotentialExportAmbiguity.push_back (false);
+    }
+  }
+}
diff --git a/src/Geometry/GeometryStrategyFunctionSmooth.h b/src/Geometry/GeometryStrategyFunctionSmooth.h
index 7bb3b9ac..fd4a8e1d 100644
--- a/src/Geometry/GeometryStrategyFunctionSmooth.h
+++ b/src/Geometry/GeometryStrategyFunctionSmooth.h
@@ -30,11 +30,18 @@ public:
                                   QString &polyArea,
                                   QVector<QString> &x,
                                   QVector<QString> &y,
+                                  QVector<bool> &isPotentialExportAmbiguity,
                                   QVector<QString> &distanceGraphForward,
                                   QVector<QString> &distancePercentForward,
                                   QVector<QString> &distanceGraphBackward,
                                   QVector<QString> &distancePercentBackward) const;
 
+  /// Generate a vector that identifies points belonging to segments that overlap, for
+  /// smoothly connected functions
+  virtual void loadSmoothAmbiguityVector (QVector<QString> &x,
+                                          QVector<QString> &y,
+                                          const Transformation &transformation,
+                                          QVector<bool> &isPotentialExportAmbiguity) const;
 };
 
 #endif // GEOMETRY_STRATEGY_FUNCTION_SMOOTH_H
diff --git a/src/Geometry/GeometryStrategyFunctionStraight.cpp b/src/Geometry/GeometryStrategyFunctionStraight.cpp
index 36cbc45f..faaf796e 100644
--- a/src/Geometry/GeometryStrategyFunctionStraight.cpp
+++ b/src/Geometry/GeometryStrategyFunctionStraight.cpp
@@ -24,6 +24,7 @@ void GeometryStrategyFunctionStraight::calculateGeometry (const Points &points,
                                                           QString &polyArea,
                                                           QVector<QString> &x,
                                                           QVector<QString> &y,
+                                                          QVector<bool> &isPotentialExportAmbiguity,
                                                           QVector<QString> &distanceGraphForward,
                                                           QVector<QString> &distancePercentForward,
                                                           QVector<QString> &distanceGraphBackward,
@@ -53,6 +54,11 @@ void GeometryStrategyFunctionStraight::calculateGeometry (const Points &points,
           x,
           y);
 
+  loadPotentialExportVector (x,
+                             y,
+                             transformation,
+                             isPotentialExportAmbiguity);
+
   // Set header values
   funcArea = QString::number (fArea);
   polyArea = "";
diff --git a/src/Geometry/GeometryStrategyFunctionStraight.h b/src/Geometry/GeometryStrategyFunctionStraight.h
index 61c2fa19..d324975d 100644
--- a/src/Geometry/GeometryStrategyFunctionStraight.h
+++ b/src/Geometry/GeometryStrategyFunctionStraight.h
@@ -30,6 +30,7 @@ public:
                                   QString &polyArea,
                                   QVector<QString> &x,
                                   QVector<QString> &y,
+                                  QVector<bool> &isPotentialExportAmbiguity,
                                   QVector<QString> &distanceGraphForward,
                                   QVector<QString> &distancePercentForward,
                                   QVector<QString> &distanceGraphBackward,
diff --git a/src/Geometry/GeometryStrategyRelationSmooth.cpp b/src/Geometry/GeometryStrategyRelationSmooth.cpp
index b3d27c8a..8833425e 100644
--- a/src/Geometry/GeometryStrategyRelationSmooth.cpp
+++ b/src/Geometry/GeometryStrategyRelationSmooth.cpp
@@ -24,6 +24,7 @@ void GeometryStrategyRelationSmooth::calculateGeometry (const Points &points,
                                                         QString &polyArea,
                                                         QVector<QString> &x,
                                                         QVector<QString> &y,
+                                                        QVector<bool> &isPotentialExportAmbiguity,
                                                         QVector<QString> &distanceGraphForward,
                                                         QVector<QString> &distancePercentForward,
                                                         QVector<QString> &distanceGraphBackward,
@@ -53,6 +54,11 @@ void GeometryStrategyRelationSmooth::calculateGeometry (const Points &points,
           x,
           y);
 
+  loadPotentialExportVector (x,
+                             y,
+                             transformation,
+                             isPotentialExportAmbiguity);
+
   // Set header values
   funcArea = "";
   polyArea = QString::number (pArea);
diff --git a/src/Geometry/GeometryStrategyRelationSmooth.h b/src/Geometry/GeometryStrategyRelationSmooth.h
index eac7bf02..1a527bc6 100644
--- a/src/Geometry/GeometryStrategyRelationSmooth.h
+++ b/src/Geometry/GeometryStrategyRelationSmooth.h
@@ -30,6 +30,7 @@ public:
                                   QString &polyArea,
                                   QVector<QString> &x,
                                   QVector<QString> &y,
+                                  QVector<bool> &isPotentialExportAmbiguity,
                                   QVector<QString> &distanceGraphForward,
                                   QVector<QString> &distancePercentForward,
                                   QVector<QString> &distanceGraphBackward,
diff --git a/src/Geometry/GeometryStrategyRelationStraight.cpp b/src/Geometry/GeometryStrategyRelationStraight.cpp
index 3822b9a4..a8796e84 100644
--- a/src/Geometry/GeometryStrategyRelationStraight.cpp
+++ b/src/Geometry/GeometryStrategyRelationStraight.cpp
@@ -24,6 +24,7 @@ void GeometryStrategyRelationStraight::calculateGeometry (const Points &points,
                                                           QString &polyArea,
                                                           QVector<QString> &x,
                                                           QVector<QString> &y,
+                                                          QVector<bool> &isPotentialExportAmbiguity,
                                                           QVector<QString> &distanceGraphForward,
                                                           QVector<QString> &distancePercentForward,
                                                           QVector<QString> &distanceGraphBackward,
@@ -53,6 +54,11 @@ void GeometryStrategyRelationStraight::calculateGeometry (const Points &points,
           x,
           y);
 
+  loadPotentialExportVector (x,
+                             y,
+                             transformation,
+                             isPotentialExportAmbiguity);
+
   // Set header values
   funcArea = "";
   polyArea = QString::number (pArea);
diff --git a/src/Geometry/GeometryStrategyRelationStraight.h b/src/Geometry/GeometryStrategyRelationStraight.h
index 6a703250..de27eaaa 100644
--- a/src/Geometry/GeometryStrategyRelationStraight.h
+++ b/src/Geometry/GeometryStrategyRelationStraight.h
@@ -30,6 +30,7 @@ public:
                                   QString &polyArea,
                                   QVector<QString> &x,
                                   QVector<QString> &y,
+                                  QVector<bool> &isPotentialExportAmbiguity,
                                   QVector<QString> &distanceGraphForward,
                                   QVector<QString> &distancePercentForward,
                                   QVector<QString> &distanceGraphBackward,
diff --git a/src/Geometry/GeometryWindow.cpp b/src/Geometry/GeometryWindow.cpp
index a0206155..deabb07c 100644
--- a/src/Geometry/GeometryWindow.cpp
+++ b/src/Geometry/GeometryWindow.cpp
@@ -4,7 +4,6 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
-#include "CallbackGatherXThetaValuesFunctions.h"
 #include "CmdMediator.h"
 #include "Curve.h"
 #include "CurveConnectAs.h"
@@ -48,6 +47,7 @@ GeometryWindow::GeometryWindow (MainWindow *mainWindow) :
 
 GeometryWindow::~GeometryWindow()
 {
+  delete m_model;
 }
 
 void GeometryWindow::clear ()
@@ -196,6 +196,8 @@ void GeometryWindow::update (const CmdMediator &cmdMediator,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GeometryWindow::update";
 
+  const int NUM_LEGEND_ROWS_UNSPANNED = 2; // Match with GeometryModel::NUM_LEGEND_ROWS_UNSPANNED
+
   // Save inputs
   m_modelExport = cmdMediator.document().modelExport();
   m_model->setDelimiter (m_modelExport.delimiter());
@@ -210,6 +212,7 @@ void GeometryWindow::update (const CmdMediator &cmdMediator,
 
   QString funcArea, polyArea;
   QVector<QString> x, y, distanceGraphForward, distancePercentForward, distanceGraphBackward, distancePercentBackward;
+  QVector<bool> isPotentialExportAmbiguity;
 
   CurveStyle curveStyle = cmdMediator.document().modelCurveStyles().curveStyle (curveSelected);
   m_geometryStrategyContext.calculateGeometry (points,
@@ -222,13 +225,20 @@ void GeometryWindow::update (const CmdMediator &cmdMediator,
                                                polyArea,
                                                x,
                                                y,
+                                               isPotentialExportAmbiguity,
                                                distanceGraphForward,
                                                distancePercentForward,
                                                distanceGraphBackward,
                                                distancePercentBackward);
 
+  // Was there a potential export ambiguity
+  bool wasAmbiguity = isPotentialExportAmbiguity.contains (true);
+
+  // Unmerge any merged cells from the previous update
+  m_view->clearSpans();
+
   // Output to table
-  resizeTable (NUM_HEADER_ROWS + points.count());
+  resizeTable (NUM_HEADER_ROWS + points.count() + (wasAmbiguity ? NUM_LEGEND_ROWS_UNSPANNED : 0));
 
   m_model->setItem (HEADER_ROW_NAME, COLUMN_HEADER_VALUE, new QStandardItem (curveSelected));
   m_model->setItem (HEADER_ROW_FUNC_AREA, COLUMN_HEADER_VALUE, new QStandardItem (funcArea));
@@ -236,9 +246,10 @@ void GeometryWindow::update (const CmdMediator &cmdMediator,
 
   if (transformation.transformIsDefined()) {
 
+    m_model->setPotentialExportAmbiguity (isPotentialExportAmbiguity);
+
     int row = NUM_HEADER_ROWS;
-    int index = 0;
-    for (; index < points.count(); row++, index++) {
+    for (int index = 0; index < points.count(); row++, index++) {
 
       const Point &point = points.at (index);
 
@@ -255,6 +266,15 @@ void GeometryWindow::update (const CmdMediator &cmdMediator,
       m_model->setItem (row, COLUMN_BODY_DISTANCE_PERCENT_BACKWARD, new QStandardItem (distancePercentBackward [index]));
       m_model->setItem (row, COLUMN_BODY_POINT_IDENTIFIERS, new QStandardItem (point.identifier()));
     }
+
+    if (wasAmbiguity) {
+      // Merge row into one big cell so text fits. Requires unmerge at start of next update
+      m_view->setSpan (row, 0, NUM_LEGEND_ROWS_UNSPANNED, NUM_BODY_COLUMNS);
+      m_model->setItem (row, COLUMN_BODY_X,
+                        new QStandardItem (tr ("Highlighted segments may have unexpected values when exported due to overlaps. "
+                                               "Adjust points or change Settings / Curve Properties / Connect As.")));
+      row++;
+    }
   }
 
   // Unselect everything
diff --git a/src/Ghosts/Ghosts.cpp b/src/Ghosts/Ghosts.cpp
index 95c33cc9..fd8cfe1f 100644
--- a/src/Ghosts/Ghosts.cpp
+++ b/src/Ghosts/Ghosts.cpp
@@ -33,7 +33,7 @@ void Ghosts::captureGraphicsItems (QGraphicsScene &scene)
     QGraphicsItem *item = *itr;
 
     QGraphicsEllipseItem *itemEllipse = dynamic_cast<QGraphicsEllipseItem*> (item);
-    if (itemEllipse != 0) {
+    if (itemEllipse != nullptr) {
 
       GhostEllipse ghost (itemEllipse->boundingRect(),
                           itemEllipse->pen(),
@@ -43,7 +43,7 @@ void Ghosts::captureGraphicsItems (QGraphicsScene &scene)
     } else {
 
       QGraphicsPathItem *itemPath = dynamic_cast<QGraphicsPathItem*> (item);
-      if (itemPath != 0) {
+      if (itemPath != nullptr) {
 
         GhostPath ghost (itemPath->path (),
                          itemPath->pen(),
@@ -53,7 +53,7 @@ void Ghosts::captureGraphicsItems (QGraphicsScene &scene)
       } else {
 
         QGraphicsPolygonItem *itemPolygon = dynamic_cast<QGraphicsPolygonItem*> (item);
-        if (itemPolygon != 0) {
+        if (itemPolygon != nullptr) {
 
           // Polygon is centered at origin so we have to add offset
           QPolygonF polygon = itemPolygon->polygon();
diff --git a/src/Graphics/GraphicsItemsExtractor.cpp b/src/Graphics/GraphicsItemsExtractor.cpp
index a3975b13..2b89f2c0 100644
--- a/src/Graphics/GraphicsItemsExtractor.cpp
+++ b/src/Graphics/GraphicsItemsExtractor.cpp
@@ -29,7 +29,7 @@ bool GraphicsItemsExtractor::allSelectedItemsAreEitherAxisOrGraph (const QList<Q
   for (itr = items.begin(); itr != items.end(); itr++) {
 
     QGraphicsItem *item = *itr;
-    GraphicsItemType type = (GraphicsItemType) item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ();
+    GraphicsItemType type = static_cast<GraphicsItemType> (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ());
 
     if (type == GRAPHICS_ITEM_TYPE_POINT) {
 
diff --git a/src/Graphics/GraphicsLinesForCurve.cpp b/src/Graphics/GraphicsLinesForCurve.cpp
index 653fefdb..9d9cc30f 100644
--- a/src/Graphics/GraphicsLinesForCurve.cpp
+++ b/src/Graphics/GraphicsLinesForCurve.cpp
@@ -18,10 +18,12 @@
 #include "PointStyle.h"
 #include <QGraphicsItem>
 #include <QMap>
+#include <QPainterPath>
 #include <QPen>
 #include <QTextStream>
 #include "QtToString.h"
 #include "Spline.h"
+#include "SplineDrawer.h"
 #include "Transformation.h"
 #include "ZValues.h"
 
@@ -64,7 +66,10 @@ void GraphicsLinesForCurve::addPoint (const QString &pointIdentifier,
   m_graphicsPoints [ordinal] = &graphicsPoint;
 }
 
-QPainterPath GraphicsLinesForCurve::drawLinesSmooth ()
+QPainterPath GraphicsLinesForCurve::drawLinesSmooth (const LineStyle &lineStyle,
+                                                     SplineDrawer &splineDrawer,
+                                                     QPainterPath &pathMultiValued,
+                                                     LineStyle &lineMultiValued)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::drawLinesSmooth"
                               << " curve=" << m_curveName.toLatin1().data();
@@ -91,38 +96,69 @@ QPainterPath GraphicsLinesForCurve::drawLinesSmooth ()
     // Spline through points
     Spline spline (t, xy);
 
-    // Drawing from point i-1 to this point i uses the control points from point i-1
-    int segmentEndingAtPointI = 0;
+    splineDrawer.bindToSpline (lineStyle,
+                               m_graphicsPoints.count(),
+                               spline);
 
-    // Create QPainterPath through the points
-    bool isFirst = true;
-    for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
+    // Create QPainterPath through the points. Loop has one segment per stop point,
+    // with first point handled outside first
+    int segment; // Only incremented after a draw, corresponding to finishing a segment
+    OrdinalToGraphicsPoint::const_iterator itr = m_graphicsPoints.begin();
 
-      const GraphicsPoint *point = itr.value();
+    const GraphicsPoint *point = itr.value();
+    path.moveTo (point->pos ());
+    pathMultiValued.moveTo (point->pos ());
+    ++itr;
 
-      if (isFirst) {
-        isFirst = false;
-        path.moveTo (point->pos());
-      } else {
+    for (segment = 0;
+         itr != m_graphicsPoints.end();
+         segment++, itr++) {
 
-        QPointF p1 (spline.p1 (segmentEndingAtPointI).x(),
-                    spline.p1 (segmentEndingAtPointI).y());
-        QPointF p2 (spline.p2 (segmentEndingAtPointI).x(),
-                    spline.p2 (segmentEndingAtPointI).y());
+      const GraphicsPoint *point = itr.value();
 
-        path.cubicTo (p1,
-                      p2,
-                      point->pos ());
+      SplineDrawerOperation operation = splineDrawer.segmentOperation (segment);
+
+      QPointF p1 (spline.p1 (unsigned (segment)).x(),
+                  spline.p1 (unsigned (segment)).y());
+      QPointF p2 (spline.p2 (unsigned (segment)).x(),
+                  spline.p2 (unsigned (segment)).y());
+
+      switch (operation) {
+      case SPLINE_DRAWER_ENUM_VISIBLE_DRAW:
+        {
+          // Show this segment
+          path.cubicTo (p1,
+                        p2,
+                        point->pos ());
+        }
+        break;
+
+      case SPLINE_DRAWER_ENUM_INVISIBLE_MOVE:
+
+        // Hide this segment as a regular curve, and show it as the error curve
+        path.moveTo (point->pos ());
+
+        // Show curveMultiValued instead in what would have been the original curve's path
+        OrdinalToGraphicsPoint::const_iterator itrBefore = itr - 1;
+        const GraphicsPoint *pointBefore = itrBefore.value();
+        pathMultiValued.moveTo (pointBefore->pos ());
+        pathMultiValued.cubicTo (p1,
+                                 p2,
+                                 point->pos ());
+        lineMultiValued = lineStyle; // Remember to not use the same line style
+        break;
 
-        ++segmentEndingAtPointI;
       }
+
+      // Always move to next point for curveMultiValued
+      pathMultiValued.moveTo (point->pos ());
     }
   }
 
   return path;
 }
 
-QPainterPath GraphicsLinesForCurve::drawLinesStraight ()
+QPainterPath GraphicsLinesForCurve::drawLinesStraight (QPainterPath  & /* pathMultiValued */)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::drawLinesStraight"
                               << " curve=" << m_curveName.toLatin1().data();
@@ -167,7 +203,10 @@ double GraphicsLinesForCurve::identifierToOrdinal (const QString &identifier) co
   return 0;
 }
 
-void GraphicsLinesForCurve::lineMembershipPurge (const LineStyle &lineStyle)
+void GraphicsLinesForCurve::lineMembershipPurge (const LineStyle &lineStyle,
+                                                 SplineDrawer &splineDrawer,
+                                                 QPainterPath &pathMultiValued,
+                                                 LineStyle &lineMultiValued)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::lineMembershipPurge"
                               << " curve=" << m_curveName.toLatin1().data();
@@ -204,7 +243,10 @@ void GraphicsLinesForCurve::lineMembershipPurge (const LineStyle &lineStyle)
 
   setPen (pen);
 
-  updateGraphicsLinesToMatchGraphicsPoints (lineStyle);
+  updateGraphicsLinesToMatchGraphicsPoints (lineStyle,
+                                            splineDrawer,
+                                            pathMultiValued,
+                                            lineMultiValued);
 }
 
 void GraphicsLinesForCurve::lineMembershipReset ()
@@ -244,7 +286,7 @@ bool GraphicsLinesForCurve::needOrdinalRenumbering () const
 void GraphicsLinesForCurve::printStream (QString indentation,
                                          QTextStream &str) const
 {
-  DataKey type = (DataKey) data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt();
+  DataKey type = static_cast<DataKey> (data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt());
 
   str << indentation << "GraphicsLinesForCurve=" << m_curveName
       << " dataIdentifier=" << data (DATA_KEY_IDENTIFIER).toString().toLatin1().data()
@@ -282,6 +324,8 @@ void GraphicsLinesForCurve::removeTemporaryPointIfExists()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::removeTemporaryPointIfExists";
 
+  // Compiler warning about this loop only iterating once is not an issue since there
+  // is never more than one temporary point
   OrdinalToGraphicsPoint::iterator itr;
   for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
 
@@ -328,7 +372,7 @@ void GraphicsLinesForCurve::updateAfterCommand (GraphicsScene &scene,
                                << " curve=" << m_curveName.toLatin1().data()
                                << " pointCount=" << m_graphicsPoints.count();
 
-  GraphicsPoint *graphicsPoint = 0;
+  GraphicsPoint *graphicsPoint = nullptr;
   if (m_graphicsPoints.contains (point.ordinal())) {
 
     graphicsPoint = m_graphicsPoints [point.ordinal()];
@@ -382,7 +426,10 @@ void GraphicsLinesForCurve::updateHighlightOpacity (double highlightOpacity)
   }
 }
 
-void GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle)
+void GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle,
+                                                                      SplineDrawer &splineDrawer,
+                                                                      QPainterPath &pathMultiValued,
+                                                                      LineStyle &lineMultiValued)
 {
   // LOG4CPP_INFO_S is below
 
@@ -406,9 +453,12 @@ void GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints (const Line
         lineStyle.curveConnectAs() == CONNECT_AS_RELATION_STRAIGHT ||
         m_graphicsPoints.count () < 3) {
 
-      path = drawLinesStraight ();
+      path = drawLinesStraight (pathMultiValued);
     } else {
-      path = drawLinesSmooth ();
+      path = drawLinesSmooth (lineStyle,
+                              splineDrawer,
+                              pathMultiValued,
+                              lineMultiValued);
     }
 
    setPath (path);
@@ -420,7 +470,7 @@ void GraphicsLinesForCurve::updatePointOrdinalsAfterDrag (const LineStyle &lineS
 {
   CurveConnectAs curveConnectAs = lineStyle.curveConnectAs();
 
-  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints"
+  LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurve::updatePointOrdinalsAfterDrag"
                                << " curve=" << m_curveName.toLatin1().data()
                                << " curveConnectAs=" << curveConnectAsToString(curveConnectAs).toLatin1().data();
 
diff --git a/src/Graphics/GraphicsLinesForCurve.h b/src/Graphics/GraphicsLinesForCurve.h
index 13a73172..4163ead7 100644
--- a/src/Graphics/GraphicsLinesForCurve.h
+++ b/src/Graphics/GraphicsLinesForCurve.h
@@ -17,7 +17,9 @@ class GraphicsPoint;
 class GraphicsScene;
 class LineStyle;
 class PointStyle;
+class QPainterPath;
 class QTestStream;
+class SplineDrawer;
 class Transformation;
 
 /// This class stores the GraphicsLine objects for one Curve. The container is a QMap since that container
@@ -41,7 +43,10 @@ public:
   double identifierToOrdinal (const QString &identifier) const;
 
   /// Mark the end of addPoint calls. Remove stale lines, insert missing lines, and draw the graphics lines
-  void lineMembershipPurge (const LineStyle &lineStyle);
+  void lineMembershipPurge (const LineStyle &lineStyle,
+                            SplineDrawer &splineDrawer,
+                            QPainterPath &pathMultiValued,
+                            LineStyle &lineMultiValued);
 
   /// Mark points as unwanted. Afterwards, lineMembershipPurge gets called
   void lineMembershipReset ();
@@ -67,7 +72,10 @@ public:
   void updateCurveStyle (const CurveStyle &curveStyle);
 
   /// Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly
-  void updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle);
+  void updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle,
+                                                 SplineDrawer &splineDrawer,
+                                                 QPainterPath &pathMultiValued,
+                                                 LineStyle &lineMultiValued);
 
   /// Update the highlight opacity value. This may or may not affect the current display immediately depending on the state
   void updateHighlightOpacity (double highlightOpacity);
@@ -78,8 +86,11 @@ public:
 
 private:
 
-  QPainterPath drawLinesSmooth ();
-  QPainterPath drawLinesStraight ();
+  QPainterPath drawLinesSmooth (const LineStyle &lineStyle,
+                                SplineDrawer &splineDrawer,
+                                QPainterPath &pathMultiValued,
+                                LineStyle &lineMultiValued);
+  QPainterPath drawLinesStraight (QPainterPath &pathMultiValued);
   bool needOrdinalRenumbering () const; // True if m_graphicsPoints ordinal keys need renumbering
   void renumberOrdinals(); // Renumbers m_graphicsPoints ordinal keys
 
diff --git a/src/Graphics/GraphicsLinesForCurves.cpp b/src/Graphics/GraphicsLinesForCurves.cpp
index 4eb92692..386b18c7 100644
--- a/src/Graphics/GraphicsLinesForCurves.cpp
+++ b/src/Graphics/GraphicsLinesForCurves.cpp
@@ -14,9 +14,11 @@
 #include "GraphicsPointAbstractBase.h"
 #include "GraphicsScene.h"
 #include <iostream>
+#include "LineStyle.h"
 #include "Logger.h"
 #include "Point.h"
 #include <QGraphicsItem>
+#include <QPainterPath>
 #include <QTextStream>
 #include "QtToString.h"
 #include "Transformation.h"
@@ -80,7 +82,10 @@ void GraphicsLinesForCurves::addRemoveCurves (GraphicsScene &scene,
   }
 }
 
-void GraphicsLinesForCurves::lineMembershipPurge(const CurveStyles &curveStyles)
+void GraphicsLinesForCurves::lineMembershipPurge(const CurveStyles &curveStyles,
+                                                 SplineDrawer &splineDrawer,
+                                                 QPainterPath &pathMultiValued,
+                                                 LineStyle &lineMultiValued)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurves::lineMembershipPurge";
 
@@ -90,7 +95,10 @@ void GraphicsLinesForCurves::lineMembershipPurge(const CurveStyles &curveStyles)
     const QString curveName = itr.key ();
     GraphicsLinesForCurve *graphicsLines = itr.value();
 
-    graphicsLines->lineMembershipPurge (curveStyles.lineStyle (curveName));
+    graphicsLines->lineMembershipPurge (curveStyles.lineStyle (curveName),
+                                        splineDrawer,
+                                        pathMultiValued,
+                                        lineMultiValued);
   }
 }
 
@@ -199,7 +207,10 @@ void GraphicsLinesForCurves::updateCurveStyles (const CurveStyles &modelCurveSty
   }
 }
 
-void GraphicsLinesForCurves::updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles &curveStyles)
+void GraphicsLinesForCurves::updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles &curveStyles,
+                                                                       SplineDrawer &splineDrawer,
+                                                                       QPainterPath &pathMultiValued,
+                                                                       LineStyle &lineMultiValued)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurves::updateGraphicsLinesToMatchGraphicsPoints";
 
@@ -211,7 +222,10 @@ void GraphicsLinesForCurves::updateGraphicsLinesToMatchGraphicsPoints (const Cur
     // This is where we add lines for non-axes curves
     if (curveName != AXIS_CURVE_NAME) {
 
-      m_graphicsLinesForCurve [curveName]->updateGraphicsLinesToMatchGraphicsPoints(curveStyles.lineStyle (curveName));
+      m_graphicsLinesForCurve [curveName]->updateGraphicsLinesToMatchGraphicsPoints(curveStyles.lineStyle (curveName),
+                                                                                    splineDrawer,
+                                                                                    pathMultiValued,
+                                                                                    lineMultiValued);
     }
   }
 }
diff --git a/src/Graphics/GraphicsLinesForCurves.h b/src/Graphics/GraphicsLinesForCurves.h
index f34cff41..d90beff9 100644
--- a/src/Graphics/GraphicsLinesForCurves.h
+++ b/src/Graphics/GraphicsLinesForCurves.h
@@ -14,10 +14,13 @@ class GeometryWindow;
 class GraphicsLinesForCurve;
 class GraphicsPoint;
 class GraphicsScene;
+class LineStyle;
 class Point;
 class QGraphicsItem;
+class QPainterPath;
 class QPointF;
 class QTextStream;
+class SplineDrawer;
 class Transformation;
 
 typedef QHash<QString, GraphicsLinesForCurve*> GraphicsLinesContainer;
@@ -41,7 +44,10 @@ public:
                         const QStringList &curveNames);
 
   /// Mark the end of addPoint calls. Remove stale lines, insert missing lines, and draw the graphics lines
-  void lineMembershipPurge (const CurveStyles &curveStyles);
+  void lineMembershipPurge (const CurveStyles &curveStyles,
+                            SplineDrawer &splineDrawer,
+                            QPainterPath &pathMultiValued,
+                            LineStyle &lineMultiValued);
 
   /// Mark points as unwanted. Afterwards, lineMembershipPurge gets called
   void lineMembershipReset ();
@@ -74,7 +80,10 @@ public:
   void updateCurveStyles (const CurveStyles &modelCurveStyles);
 
   /// Calls to moveLinesWithDraggedPoint have finished so update the lines correspondingly
-  void updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles &curveStyles);
+  void updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles &curveStyles,
+                                                 SplineDrawer &splineDrawer,
+                                                 QPainterPath &pathMultiValued,
+                                                 LineStyle &lineMultiValued);
 
   /// Update the highlight opacity value. This may or may not affect the current display immediately depending on the state
   void updateHighlightOpacity (double highlightOpacity);
diff --git a/src/Graphics/GraphicsPoint.cpp b/src/Graphics/GraphicsPoint.cpp
index 5fe67b15..a67a260b 100644
--- a/src/Graphics/GraphicsPoint.cpp
+++ b/src/Graphics/GraphicsPoint.cpp
@@ -37,10 +37,10 @@ GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
                              GeometryWindow *geometryWindow) :
   GraphicsPointAbstractBase (),
   m_scene (scene),
-  m_graphicsItemEllipse (0),
-  m_shadowZeroWidthEllipse (0),
-  m_graphicsItemPolygon (0),
-  m_shadowZeroWidthPolygon (0),
+  m_graphicsItemEllipse (nullptr),
+  m_shadowZeroWidthEllipse (nullptr),
+  m_graphicsItemPolygon (nullptr),
+  m_shadowZeroWidthPolygon (nullptr),
   m_identifier (identifier),
   m_posScreen (posScreen),
   m_color (color),
@@ -64,10 +64,10 @@ GraphicsPoint::GraphicsPoint(QGraphicsScene &scene,
                              GeometryWindow *geometryWindow) :
   GraphicsPointAbstractBase (),
   m_scene (scene),
-  m_graphicsItemEllipse (0),
-  m_shadowZeroWidthEllipse (0),
-  m_graphicsItemPolygon (0),
-  m_shadowZeroWidthPolygon (0),
+  m_graphicsItemEllipse (nullptr),
+  m_shadowZeroWidthEllipse (nullptr),
+  m_graphicsItemPolygon (nullptr),
+  m_shadowZeroWidthPolygon (nullptr),
   m_identifier (identifier),
   m_posScreen (posScreen),
   m_color (color),
@@ -86,15 +86,15 @@ GraphicsPoint::~GraphicsPoint()
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::~GraphicsPoint";
 
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
 
     QGraphicsScene *scene = m_graphicsItemPolygon->scene();
 
     // Since m_shadowZeroWidthPolygon is a child of m_graphicsItemPolygon, removing the parent removes both
     scene->removeItem (m_graphicsItemPolygon);
     delete m_graphicsItemPolygon;
-    m_graphicsItemPolygon = 0;
-    m_shadowZeroWidthPolygon = 0;
+    m_graphicsItemPolygon = nullptr;
+    m_shadowZeroWidthPolygon = nullptr;
 
 
   } else {
@@ -104,15 +104,15 @@ GraphicsPoint::~GraphicsPoint()
     // Since m_shadowZeroWidthEllipse is a child of m_graphicsItemEllipse, removing the parent removes both
     scene->removeItem (m_graphicsItemEllipse);
     delete m_graphicsItemEllipse;
-    m_graphicsItemEllipse = 0;
-    m_shadowZeroWidthEllipse = 0;
+    m_graphicsItemEllipse = nullptr;
+    m_shadowZeroWidthEllipse = nullptr;
 
   }
 }
 
 QRectF GraphicsPoint::boundingRect () const
 {
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     return m_graphicsItemPolygon->boundingRect ();
   } else {
     return m_graphicsItemEllipse->boundingRect ();
@@ -123,7 +123,7 @@ void GraphicsPoint::createPointEllipse (unsigned int radius)
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::createPointEllipse";
 
-  const int radiusSigned = radius; // Radius must be signed before multiplying by -1 below, for Visual Studio
+  const int radiusSigned = signed (radius); // Radius must be signed before multiplying by -1 below, for Visual Studio
   m_graphicsItemEllipse = new GraphicsPointEllipse (*this,
                                                     QRect (- radiusSigned,
                                                            - radiusSigned,
@@ -142,7 +142,7 @@ void GraphicsPoint::createPointEllipse (unsigned int radius)
                                    QGraphicsItem::ItemIsMovable |
                                    QGraphicsItem::ItemSendsGeometryChanges);
   m_graphicsItemEllipse->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
-  if (m_geometryWindow != 0) {
+  if (m_geometryWindow != nullptr) {
     QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
     QObject::connect (m_graphicsItemEllipse, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
   }
@@ -181,7 +181,7 @@ void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
                                    QGraphicsItem::ItemIsMovable |
                                    QGraphicsItem::ItemSendsGeometryChanges);
   m_graphicsItemPolygon->setData (DATA_KEY_GRAPHICS_ITEM_TYPE, GRAPHICS_ITEM_TYPE_POINT);
-  if (m_geometryWindow != 0) {
+  if (m_geometryWindow != nullptr) {
     QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverEnter (QString)), m_geometryWindow, SLOT (slotPointHoverEnter (QString)));
     QObject::connect (m_graphicsItemPolygon, SIGNAL (signalPointHoverLeave (QString)), m_geometryWindow, SLOT (slotPointHoverLeave (QString)));
   }
@@ -200,7 +200,7 @@ void GraphicsPoint::createPointPolygon (const QPolygonF &polygon)
 
 QVariant GraphicsPoint::data (int key) const
 {
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     return m_graphicsItemPolygon->data (key);
   } else {
     return m_graphicsItemEllipse->data (key);
@@ -214,7 +214,7 @@ double GraphicsPoint::highlightOpacity () const
 
 QPointF GraphicsPoint::pos () const
 {
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     return m_graphicsItemPolygon->pos ();
   } else {
     return m_graphicsItemEllipse->pos ();
@@ -232,7 +232,7 @@ void GraphicsPoint::printStream (QString indentation,
   QString identifier;
   QString pointType;
   QPointF pos;
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     identifier = m_graphicsItemPolygon->data (DATA_KEY_IDENTIFIER).toString ();
     pointType = "polygon";
     pos = m_graphicsItemPolygon->pos();
@@ -242,7 +242,7 @@ void GraphicsPoint::printStream (QString indentation,
     pos = m_graphicsItemEllipse->pos();
   }
 
-  DataKey type = (DataKey) data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt();
+  DataKey type = static_cast<DataKey> (data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt());
 
   str << indentation << identifier
       << " ordinalKey=" << ordinalKey
@@ -259,10 +259,10 @@ void GraphicsPoint::reset ()
 void GraphicsPoint::setData (int key, const QVariant &data)
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsPoint::setData"
-                               << " key=" << dataKeyToString ((DataKey) key).toLatin1().data()
+                               << " key=" << dataKeyToString (static_cast<DataKey> (key)).toLatin1().data()
                                << " data=" << data.toString().toLatin1().data();
 
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     m_graphicsItemPolygon->setData (key, data);
   } else {
     m_graphicsItemEllipse->setData (key, data);
@@ -280,7 +280,7 @@ void GraphicsPoint::setHighlightOpacity (double highlightOpacity)
 
 void GraphicsPoint::setPassive ()
 {
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsFocusable, false);
     m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsMovable, false);
     m_graphicsItemPolygon->setFlag (QGraphicsItem::ItemIsSelectable, false);
@@ -295,15 +295,15 @@ void GraphicsPoint::setPointStyle(const PointStyle &pointStyle)
 {
   // Setting pen and radius of parent graphics items below also affects the child shadows
   // (m_shadowItemPolygon and m_shadowItemEllipse)
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     if (pointStyle.shape() == POINT_SHAPE_CIRCLE) {
 
       // Transition from non-circle to circle. Deleting parent also deletes child shadow
       delete m_graphicsItemPolygon;
-      m_graphicsItemPolygon = 0;
-      m_shadowZeroWidthPolygon = 0;
+      m_graphicsItemPolygon = nullptr;
+      m_shadowZeroWidthPolygon = nullptr;
 
-      createPointEllipse (pointStyle.radius());
+      createPointEllipse (unsigned (pointStyle.radius()));
 
     } else {
 
@@ -321,8 +321,8 @@ void GraphicsPoint::setPointStyle(const PointStyle &pointStyle)
 
       // Transition from circle to non-circlee. Deleting parent also deletes child shadow
       delete m_graphicsItemEllipse;
-      m_graphicsItemEllipse = 0;
-      m_shadowZeroWidthEllipse = 0;
+      m_graphicsItemEllipse = nullptr;
+      m_shadowZeroWidthEllipse = nullptr;
 
       createPointPolygon (pointStyle.polygon());
 
@@ -341,7 +341,7 @@ void GraphicsPoint::setPointStyle(const PointStyle &pointStyle)
 
 void GraphicsPoint::setPos (const QPointF pos)
 {
-  if (m_graphicsItemEllipse == 0) {
+  if (m_graphicsItemEllipse == nullptr) {
     m_graphicsItemPolygon->setPos (pos);
   } else {
     m_graphicsItemEllipse->setPos (pos);
diff --git a/src/Graphics/GraphicsPointEllipse.cpp b/src/Graphics/GraphicsPointEllipse.cpp
index 75fa6898..5824153b 100644
--- a/src/Graphics/GraphicsPointEllipse.cpp
+++ b/src/Graphics/GraphicsPointEllipse.cpp
@@ -16,7 +16,7 @@ GraphicsPointEllipse::GraphicsPointEllipse(GraphicsPoint &graphicsPoint,
                                            const QRect &rect) :
   QGraphicsEllipseItem (rect),
   m_graphicsPoint (graphicsPoint),
-  m_shadow (0)
+  m_shadow (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPointEllipse::GraphicsPointEllipse";
 }
@@ -62,7 +62,7 @@ void GraphicsPointEllipse::setOpacityForSubtree (double opacity)
   // Set this item
   setOpacity (opacity);
 
-  if (m_shadow != 0) {
+  if (m_shadow != nullptr) {
 
     // Set the child item. Opacity < MAX_OPACITY is too dark so child is set to totally transparent
     m_shadow->setOpacity (opacity < MAX_OPACITY ? 0.0 : opacity);
diff --git a/src/Graphics/GraphicsPointFactory.cpp b/src/Graphics/GraphicsPointFactory.cpp
index e8983e3d..a2994e8b 100644
--- a/src/Graphics/GraphicsPointFactory.cpp
+++ b/src/Graphics/GraphicsPointFactory.cpp
@@ -26,7 +26,7 @@ GraphicsPoint *GraphicsPointFactory::createPoint (QGraphicsScene &scene,
                                                   const PointStyle &pointStyle,
                                                   GeometryWindow *geometryWindow)
 {
-  GraphicsPoint *item = 0;
+  GraphicsPoint *item = nullptr;
 
   switch (pointStyle.shape ())
   {
@@ -36,7 +36,7 @@ GraphicsPoint *GraphicsPointFactory::createPoint (QGraphicsScene &scene,
                                   identifier,
                                   posScreen,
                                   ColorPaletteToQColor (pointStyle.paletteColor ()),
-                                  pointStyle.radius (),
+                                  unsigned (pointStyle.radius ()),
                                   pointStyle.lineWidth(),
                                   geometryWindow);
       }
diff --git a/src/Graphics/GraphicsPointPolygon.cpp b/src/Graphics/GraphicsPointPolygon.cpp
index bd32b3d3..c5f684a3 100644
--- a/src/Graphics/GraphicsPointPolygon.cpp
+++ b/src/Graphics/GraphicsPointPolygon.cpp
@@ -15,7 +15,7 @@ GraphicsPointPolygon::GraphicsPointPolygon(GraphicsPoint &graphicsPoint,
                                            const QPolygonF &polygon) :
   QGraphicsPolygonItem (polygon),
   m_graphicsPoint (graphicsPoint),
-  m_shadow (0)
+  m_shadow (nullptr)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsPointPolygon::GraphicsPointPolygon";
 }
@@ -61,7 +61,7 @@ void GraphicsPointPolygon::setOpacityForSubtree (double opacity)
   // Set this item
   setOpacity (opacity);
 
-  if (m_shadow != 0) {
+  if (m_shadow != nullptr) {
 
     // Set the child item. Opacity < MAX_OPACITY is too dark so child is set to totally transparent
     m_shadow->setOpacity (opacity < MAX_OPACITY ? 0.0 : opacity);
diff --git a/src/Graphics/GraphicsScene.cpp b/src/Graphics/GraphicsScene.cpp
index c2bf4d43..5cd8bc00 100644
--- a/src/Graphics/GraphicsScene.cpp
+++ b/src/Graphics/GraphicsScene.cpp
@@ -23,10 +23,16 @@
 #include <QApplication>
 #include <QGraphicsItem>
 #include "QtToString.h"
+#include "SplineDrawer.h"
 #include "Transformation.h"
 
 GraphicsScene::GraphicsScene(MainWindow *mainWindow) :
-  QGraphicsScene(mainWindow)
+  QGraphicsScene(mainWindow),
+  m_pathItemMultiValued (nullptr)
+{
+}
+
+GraphicsScene::~GraphicsScene()
 {
 }
 
@@ -87,7 +93,7 @@ GraphicsPoint *GraphicsScene::createPoint (const QString &identifier,
 
 QString GraphicsScene::dumpCursors () const
 {
-  QString cursorOverride = (QApplication::overrideCursor () != 0) ?
+  QString cursorOverride = (QApplication::overrideCursor () != nullptr) ?
                              QtCursorToString (QApplication::overrideCursor ()->shape ()) :
                              "<null>";
   QString cursorImage = QtCursorToString (image()->cursor().shape ());
@@ -128,11 +134,11 @@ const QGraphicsPixmapItem *GraphicsScene::image () const
     QGraphicsItem* item = *itr;
     if (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt () == GRAPHICS_ITEM_TYPE_IMAGE) {
 
-      return (QGraphicsPixmapItem *) item;
+      return dynamic_cast<QGraphicsPixmapItem *> (item);
     }
   }
 
-  return 0;
+  return nullptr;
 }
 
 QStringList GraphicsScene::positionHasChangedPointIdentifiers () const
@@ -269,7 +275,8 @@ void GraphicsScene::showCurves (bool show,
 
 void GraphicsScene::updateAfterCommand (CmdMediator &cmdMediator,
                                         double highlightOpacity,
-                                        GeometryWindow *geometryWindow)
+                                        GeometryWindow *geometryWindow,
+                                        const Transformation &transformation)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updateAfterCommand";
 
@@ -279,7 +286,8 @@ void GraphicsScene::updateAfterCommand (CmdMediator &cmdMediator,
 
   // Update the points
   updatePointMembership (cmdMediator,
-                         geometryWindow);
+                         geometryWindow,
+                         transformation);
 }
 
 void GraphicsScene::updateCurves (CmdMediator &cmdMediator)
@@ -314,12 +322,39 @@ void GraphicsScene::updateGraphicsLinesToMatchGraphicsPoints (const CurveStyles
                                                            transformation);
 
     // Recompute the lines one time for efficiency
-    m_graphicsLinesForCurves.updateGraphicsLinesToMatchGraphicsPoints (curveStyles);
+    SplineDrawer splineDrawer (transformation);
+    QPainterPath pathMultiValued;
+    LineStyle lineMultiValued;
+    m_graphicsLinesForCurves.updateGraphicsLinesToMatchGraphicsPoints (curveStyles,
+                                                                       splineDrawer,
+                                                                       pathMultiValued,
+                                                                       lineMultiValued);
+
+    updatePathItemMultiValued (pathMultiValued,
+                               lineMultiValued);
   }
 }
 
+void GraphicsScene::updatePathItemMultiValued (const QPainterPath &pathMultiValued,
+                                               const LineStyle &lineMultiValued)
+{
+  // It looks much better to use a consistent line width
+  int lineWidth = signed (lineMultiValued.width());
+
+  // Draw m_curveMultiValued. If empty then nothing will appear
+  delete m_pathItemMultiValued;
+  m_pathItemMultiValued = this->addPath (pathMultiValued);
+  m_pathItemMultiValued->setPen (QPen (QBrush (QColor (Qt::red)),
+                                       lineWidth,
+                                       Qt::DotLine));
+  m_pathItemMultiValued->setAcceptHoverEvents (true);
+  m_pathItemMultiValued->setToolTip (tr ("Function currently has multiple Y values for one X value. Please adjust nearby points, "
+                                         "or change the curve type in Curve Properties"));
+}
+
 void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator,
-                                           GeometryWindow *geometryWindow)
+                                           GeometryWindow *geometryWindow,
+                                           const Transformation &transformation)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GraphicsScene::updatePointMembership";
 
@@ -342,5 +377,13 @@ void GraphicsScene::updatePointMembership (CmdMediator &cmdMediator,
 
   // Next pass:
   // 1) Remove points that were just removed from the Document
-  m_graphicsLinesForCurves.lineMembershipPurge (cmdMediator.document().modelCurveStyles());
+  SplineDrawer splineDrawer (transformation);
+  QPainterPath pathMultiValued;
+  LineStyle lineMultiValued;
+  m_graphicsLinesForCurves.lineMembershipPurge (cmdMediator.document().modelCurveStyles(),
+                                                splineDrawer,
+                                                pathMultiValued,
+                                                lineMultiValued);
+  updatePathItemMultiValued (pathMultiValued,
+                             lineMultiValued);
 }
diff --git a/src/Graphics/GraphicsScene.h b/src/Graphics/GraphicsScene.h
index 699ac841..e3b7b5c5 100644
--- a/src/Graphics/GraphicsScene.h
+++ b/src/Graphics/GraphicsScene.h
@@ -10,6 +10,7 @@
 #include "CmdMediator.h"
 #include "GraphicsLinesForCurves.h"
 #include <QGraphicsScene>
+#include <QObject>
 #include <QStringList>
 
 class CmdMediator;
@@ -18,8 +19,10 @@ class CurvesGraphs;
 class CurveStyles;
 class GeometryWindow;
 class GraphicsPoint;
+class LineStyle;
 class MainWindow;
 class PointStyle;
+class QGraphicsPathItem;
 class QTextStream;
 class ScaleBar;
 class Transformation;
@@ -32,10 +35,16 @@ class Transformation;
 /// the points and lines are accessible for updates (like when dragging points around and we need to update the attached lines).
 class GraphicsScene : public QGraphicsScene
 {
+  // We use Q_OBJECT so translations work
+  Q_OBJECT;
+  
 public:
   /// Single constructor.
   GraphicsScene(MainWindow *mainWindow);
 
+  /// Virtual destructor needed since using Q_OBJECT
+  virtual ~GraphicsScene();
+
   /// Add one temporary point to m_graphicsLinesForCurves. Non-temporary points are handled by the updateLineMembership functions
   void addTemporaryPoint (const QString &identifier,
                           GraphicsPoint *point);
@@ -88,7 +97,8 @@ public:
   /// updating would be done on out of date information (since that would be brought up to date by the NEXT command)
   void updateAfterCommand (CmdMediator &cmdMediator,
                            double highlightOpacity,
-                           GeometryWindow *geometryWindow);
+                           GeometryWindow *geometryWindow,
+                           const Transformation &transformation);
 
   /// Update curve styles after settings changed.
   void updateCurveStyles(const CurveStyles &modelCurveStyles);
@@ -108,12 +118,23 @@ private:
   /// Remove expired curves and add new curves
   void updateCurves (CmdMediator &cmdMediator);
 
+  /// Update path item showing where multi-valued issues are occuring. Nothing appears if there are no problems
+  void updatePathItemMultiValued (const QPainterPath &pathMultiValued,
+                                  const LineStyle &lineMultiValued);
+
   /// Update Points using a multi-pass algorithm.
   void updatePointMembership (CmdMediator &cmdMediator,
-                              GeometryWindow *geometryWindow);
+                              GeometryWindow *geometryWindow,
+                              const Transformation &transformation);
 
   /// Curve name to GraphicsLinesForCurve
   GraphicsLinesForCurves m_graphicsLinesForCurves;
+
+  /// Special path item that in happy times is never seen. It appears in place of bad line segments on the
+  /// other curves. Bad=segment is multi-valued for a function since functions should always be single-valued.
+  /// This special curve lives here rather than in m_graphicsLinesForCurves so it is decoupled from
+  /// that member (especially since that gets serialized)
+  QGraphicsPathItem *m_pathItemMultiValued;
 };
 
 #endif // GRAPHICS_SCENE_H
diff --git a/src/Graphics/GraphicsView.cpp b/src/Graphics/GraphicsView.cpp
index 8ca46442..fecef32d 100644
--- a/src/Graphics/GraphicsView.cpp
+++ b/src/Graphics/GraphicsView.cpp
@@ -121,59 +121,73 @@ void GraphicsView::dragMoveEvent (QDragMoveEvent *event)
 
 void GraphicsView::dropEvent (QDropEvent *event)
 {
-  const QString MIME_FORMAT_TEXT_PLAIN ("text/plain");
+  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::dropEvent";
 
   // Urls from text/uri-list
   QList<QUrl> urlList = event->mimeData ()->urls ();
-  QString urls;
-  QTextStream str (&urls);
-  QList<QUrl>::const_iterator itr;
-  for (itr = urlList.begin (); itr != urlList.end (); itr++) {
-    QUrl url = *itr;
-    str << " url=" << url.toString () << " ";
-  }
 
+  const QString MIME_FORMAT_TEXT_PLAIN ("text/plain");
   QString textPlain (event->mimeData()->data (MIME_FORMAT_TEXT_PLAIN));
 
-  LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::dropEvent"
-                              << " formats=(" << event->mimeData()->formats().join (", ").toLatin1().data() << ")"
-                              << " hasUrls=" << (event->mimeData()->hasUrls() ? "yes" : "no")
-                              << " urlCount=" << urlList.count()
-                              << " urls=(" << urls.toLatin1().data() << ")"
-                              << " text=" << textPlain.toLatin1().data()
-                              << " hasImage=" << (event->mimeData()->hasImage() ? "yes" : "no");
-
-  LoadFileInfo loadFileInfo;
-  if (loadFileInfo.loadsAsDigFile (textPlain)) {
-
-    LOG4CPP_INFO_S ((*mainCat)) << "QGraphicsView::dropEvent dig file";
-    QUrl url (textPlain);
-    emit signalDraggedDigFile (url.toLocalFile());
-    event->acceptProposedAction();
-
-  } else if (event->mimeData ()->hasImage ()) {
+  QUrl urlFirst;
+  if (event->mimeData ()->hasUrls () &&
+      urlList.count () > 0) {
+    urlFirst = urlList.at (0);
+  }
 
-    // This branch never seems to get executed, but will be kept in case it ever applies (since hasUrls branch is messier and less reliable)
-    QImage image = qvariant_cast<QImage> (event->mimeData ()->imageData ());
-    LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::dropEvent image";
-    emit signalDraggedImage (image);
+  QImage image;
+  if (event->mimeData()->hasImage()) {
+    image = qvariant_cast<QImage> (event->mimeData ()->imageData ());
+  }
 
-  } else if (event->mimeData ()->hasUrls () &&
-             urlList.count () > 0) {
+  if (handleDropEvent (textPlain,
+                       event->mimeData ()->hasUrls (),
+                       urlFirst,
+                       event->mimeData ()->hasImage (),
+                       image)) {
 
-    // Sometimes images can be dragged in, but sometimes the url points to an html page that
-    // contains just the image, in which case importing will fail
-    QUrl url = urlList.at(0);
-    LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::dropEvent url=" << url.toString ().toLatin1 ().data ();
-    emit signalDraggedImageUrl (url);
     event->acceptProposedAction();
 
   } else {
 
     LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::dropEvent dropped";
     QGraphicsView::dropEvent (event);
+  }
+}
 
+bool GraphicsView::handleDropEvent (const QString &possibleDigFileName,
+                                    bool hasUrl,
+                                    const QUrl &urlFirst,
+                                    bool hasImage,
+                                    const QImage &image)
+{
+  bool willAccept = false;
+
+  LoadFileInfo loadFileInfo;
+  if (loadFileInfo.loadsAsDigFile (possibleDigFileName)) {
+
+    // Branch that applies when a dig file name has been dropped
+    LOG4CPP_INFO_S ((*mainCat)) << "QGraphicsView::handleDropEvent dig file";
+    QUrl url (possibleDigFileName);
+    emit signalDraggedDigFile (url.toLocalFile());
+    willAccept = true;
+
+  } else if (hasImage) {
+
+    // Branch that applies when an image selected within another application (e.g. LibreOffice Draw) has been dropped
+    LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::handleDropEvent image";
+    emit signalDraggedImage (image);
+    willAccept = true;
+
+  } else if (hasUrl) {
+
+    // Branch that applies when a local file name or internet url has been dropped
+    LOG4CPP_INFO_S ((*mainCat)) << "GraphicsView::handleDropEvent url=" << urlFirst.toString ().toLatin1 ().data ();
+    emit signalDraggedImageUrl (urlFirst);
+    willAccept = true;
   }
+
+  return willAccept;
 }
 
 bool GraphicsView::inBounds (const QPointF &posScreen)
@@ -191,7 +205,7 @@ void GraphicsView::keyPressEvent (QKeyEvent *event)
   LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsView::keyPressEvent";
 
   // Intercept up/down/left/right if any items are selected
-  Qt::Key key = (Qt::Key) event->key();
+  Qt::Key key = static_cast<Qt::Key> (event->key());
 
   bool atLeastOneSelectedItem = (scene ()->selectedItems ().count () > 0);
 
@@ -260,7 +274,7 @@ void GraphicsView::mouseReleaseEvent (QMouseEvent *event)
   // Send a signal, unless this is a right click. We still send if out of bounds since
   // a click-and-drag often ends out of bounds (and user is unlikely to expect different
   // behavior when endpoint is outside, versus inside, the image boundary)
-  int bitFlag = (event->buttons () & Qt::RightButton);
+  int bitFlag = (unsigned (event->buttons ()) & Qt::RightButton);
   bool isRightClick = (bitFlag != 0);
 
   if (!isRightClick) {
@@ -282,7 +296,7 @@ QStringList GraphicsView::pointIdentifiersFromSelection (const QList<QGraphicsIt
   for (itr = items.begin(); itr != items.end(); itr++) {
 
     QGraphicsItem *item = *itr;
-    GraphicsItemType type = (GraphicsItemType) item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ();
+    GraphicsItemType type = static_cast<GraphicsItemType> (item->data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt ());
     ENGAUGE_ASSERT (type == GRAPHICS_ITEM_TYPE_POINT);
 
     QString pointIdentifier = item->data (DATA_KEY_IDENTIFIER).toString ();
@@ -292,6 +306,25 @@ QStringList GraphicsView::pointIdentifiersFromSelection (const QList<QGraphicsIt
   return pointIdentifiers;
 }
 
+void GraphicsView::slotDropRegression (QString urlText)
+{
+  // Regression test with local file or internet url specified
+  QString emptyDigFileName;
+  bool hasUrl = true;
+  QUrl url (urlText); // Works as is for internet url
+  if (!urlText.contains ("http")) {
+    url = QUrl::fromLocalFile (urlText);
+  }
+  bool hasImage = false;
+  QImage emptyImage;
+
+  handleDropEvent (emptyDigFileName,
+                   hasUrl,
+                   url,
+                   hasImage,
+                   emptyImage);
+}
+
 void GraphicsView::wheelEvent(QWheelEvent *event)
 {
   const int ANGLE_THRESHOLD = 15; // From QWheelEvent documentation
diff --git a/src/Graphics/GraphicsView.h b/src/Graphics/GraphicsView.h
index 3e56a80d..5d907b2b 100644
--- a/src/Graphics/GraphicsView.h
+++ b/src/Graphics/GraphicsView.h
@@ -88,9 +88,18 @@ signals:
   /// Send wheel event to MainWindow for zooming out
   void signalViewZoomOut();
 
+public slots:
+  /// Receive drag and drop regression test url
+  void slotDropRegression (QString);
+
 private:
   GraphicsView();
 
+  bool handleDropEvent (const QString &possibleDigFileName,
+                        bool hasUrls,
+                        const QUrl &urlFirst,
+                        bool hasImage,
+                        const QImage &image);
   QStringList pointIdentifiersFromSelection (const QList<QGraphicsItem*> &items) const;
   bool inBounds (const QPointF &posScreen);
 
diff --git a/src/Grid/GridClassifier.cpp b/src/Grid/GridClassifier.cpp
index 007b9a4d..5cd139b4 100644
--- a/src/Grid/GridClassifier.cpp
+++ b/src/Grid/GridClassifier.cpp
@@ -15,17 +15,18 @@
 #include <QDebug>
 #include <QFile>
 #include <QImage>
+#include <qmath.h>
 #include "QtToString.h"
 #include "Transformation.h"
 
 int GridClassifier::NUM_PIXELS_PER_HISTOGRAM_BINS = 1;
 double GridClassifier::PEAK_HALF_WIDTH = 4;
-int GridClassifier::MIN_STEP_PIXELS = 4 * GridClassifier::PEAK_HALF_WIDTH; // Step includes down ramp, flat part, up ramp
+int GridClassifier::MIN_STEP_PIXELS = qFloor (4 * GridClassifier::PEAK_HALF_WIDTH); // Step includes down ramp, flat part, up ramp
 const QString GNUPLOT_DELIMITER ("\t");
 
 // We set up the picket fence with binStart arbitrarily set close to zero. Peak is
 // not exactly at zero since we want to include the left side of the first peak.
-int GridClassifier::BIN_START_UNSHIFTED = GridClassifier::PEAK_HALF_WIDTH;
+int GridClassifier::BIN_START_UNSHIFTED = qFloor (GridClassifier::PEAK_HALF_WIDTH);
 
 using namespace std;
 
@@ -41,7 +42,7 @@ int GridClassifier::binFromCoordinate (double coord,
   ENGAUGE_ASSERT (coordMin <= coord);
   ENGAUGE_ASSERT (coord <= coordMax);
 
-  int bin = 0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin);
+  int bin = qFloor (0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin));
 
   return bin;
 }
@@ -66,8 +67,8 @@ void GridClassifier::classify (bool isGnuplot,
   double xMin, xMax, yMin, yMax;
   double binStartX, binStepX, binStartY, binStepY;
 
-  m_binsX = new double [m_numHistogramBins];
-  m_binsY = new double [m_numHistogramBins];
+  m_binsX = new double [unsigned (m_numHistogramBins)];
+  m_binsY = new double [unsigned (m_numHistogramBins)];
 
   computeGraphCoordinateLimits (image,
                                 transformation,
@@ -161,7 +162,7 @@ double GridClassifier::coordinateFromBin (int bin,
   ENGAUGE_ASSERT (1 < m_numHistogramBins);
   ENGAUGE_ASSERT (coordMin < coordMax);
 
-  return coordMin + (coordMax - coordMin) * (double) bin / ((double) m_numHistogramBins - 1.0);
+  return coordMin + (coordMax - coordMin) * double (bin) / (double (m_numHistogramBins) - 1.0);
 }
 
 void GridClassifier::copyVectorToVector (const double from [],
@@ -198,13 +199,13 @@ void GridClassifier::dumpGnuplotCoordinate (const QString &coordinateLabel,
   int binCountMax = 0;
   for (bin = 0; bin < m_numHistogramBins; bin++) {
     if (bins [bin] > binCountMax) {
-      binCountMax = qMax ((double) binCountMax,
-                          bins [bin]);
+      binCountMax = qMax (signed (binCountMax),
+                          signed (bins [bin]));
     }
   }
 
   // Get picket fence
-  double *picketFence = new double [m_numHistogramBins];
+  double *picketFence = new double [unsigned (m_numHistogramBins)];
   loadPicketFence (picketFence,
                    binStart,
                    binStep,
@@ -268,10 +269,10 @@ void GridClassifier::dumpGnuplotCorrelations (const QString &coordinateLabel,
   }
 
   // Prevent divide by zero error
-  if (signalAMax == 0) {
+  if (qAbs (signalAMax) <= 0) {
     signalAMax = 1.0;
   }
-  if (signalBMax == 0) {
+  if (qAbs (signalBMax) <= 0) {
     signalBMax = 1.0;
   }
   
@@ -310,12 +311,12 @@ void GridClassifier::loadPicketFence (double picketFence [],
   ENGAUGE_ASSERT (binStart >= PEAK_HALF_WIDTH);
   ENGAUGE_ASSERT (binStep != 0);
   if (!isCount) {
-    count = 1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep;
+    count = qFloor (1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep);
   }
 
   // Bins that we need to worry about
-  int binStartMinusHalfWidth = binStart - PEAK_HALF_WIDTH;
-  int binStopPlusHalfWidth = (binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH;
+  int binStartMinusHalfWidth = qFloor (binStart - PEAK_HALF_WIDTH);
+  int binStopPlusHalfWidth = qFloor ((binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH);
 
   // To normalize, we compute the area under the picket fence. Constraint is
   // areaUnnormalized + NUM_HISTOGRAM_BINS * normalizationOffset = 0
@@ -332,7 +333,7 @@ void GridClassifier::loadPicketFence (double picketFence [],
         (bin <= binStopPlusHalfWidth)) {
 
       // Closest peak
-      int ordinalClosestPeak = (int) ((bin - binStart + binStep / 2) / binStep);
+      int ordinalClosestPeak = qFloor ((bin - binStart + binStep / 2) / binStep);
       int binClosestPeak = binStart + ordinalClosestPeak * binStep;
 
       // Distance from closest peak is used to define an isosceles triangle
@@ -341,7 +342,7 @@ void GridClassifier::loadPicketFence (double picketFence [],
       if (distanceToClosestPeak < PEAK_HALF_WIDTH) {
 
         // Map 0 to PEAK_HALF_WIDTH to 1 to 0
-        picketFence [bin] = 1.0 - (double) distanceToClosestPeak / PEAK_HALF_WIDTH + normalizationOffset;
+        picketFence [bin] = 1.0 - double (distanceToClosestPeak) / PEAK_HALF_WIDTH + normalizationOffset;
 
       }
     }
@@ -414,15 +415,15 @@ void GridClassifier::searchCountSpace (double bins [],
 
   // Loop though the space of possible counts
   Correlation correlation (m_numHistogramBins);
-  double *picketFence = new double [m_numHistogramBins];
-  double corr, corrMax;
+  double *picketFence = new double [unsigned (m_numHistogramBins)];
+  double corr, corrMax = 0;
   bool isFirst = true;
-  int countStop = 1 + (m_numHistogramBins - binStart) / binStep;
+  int countStop = qFloor (1 + (m_numHistogramBins - binStart) / binStep);
   for (int count = 2; count <= countStop; count++) {
 
     loadPicketFence (picketFence,
-                     binStart,
-                     binStep,
+                     qFloor (binStart),
+                     qFloor (binStep),
                      count,
                      true);
 
@@ -454,14 +455,14 @@ void GridClassifier::searchStartStepSpace (bool isGnuplot,
   LOG4CPP_INFO_S ((*mainCat)) << "GridClassifier::searchStartStepSpace";
 
   // Correlations are tracked for logging
-  double *signalA = new double [m_numHistogramBins];
-  double *signalB = new double [m_numHistogramBins];
-  double *correlations = new double [m_numHistogramBins];
-  double *correlationsMax = new double [m_numHistogramBins];
+  double *signalA = new double [unsigned (m_numHistogramBins)];
+  double *signalB = new double [unsigned (m_numHistogramBins)];
+  double *correlations = new double [unsigned (m_numHistogramBins)];
+  double *correlationsMax = new double [unsigned (m_numHistogramBins)];
 
   // Loop though the space of possible gridlines using the independent variables (start,step).
   Correlation correlation (m_numHistogramBins);
-  double *picketFence = new double [m_numHistogramBins];
+  double *picketFence = new double [unsigned (m_numHistogramBins)];
   int binStart;
   double corr = 0, corrMax = 0;
   bool isFirst = true;
@@ -478,7 +479,7 @@ void GridClassifier::searchStartStepSpace (bool isGnuplot,
     loadPicketFence (picketFence,
                      BIN_START_UNSHIFTED,
                      binStep,
-                     PEAK_HALF_WIDTH,
+                     qFloor (PEAK_HALF_WIDTH),
                      false);
 
     correlation.correlateWithShift (m_numHistogramBins,
@@ -519,13 +520,13 @@ void GridClassifier::searchStartStepSpace (bool isGnuplot,
   }
 
   // Convert from bins back to graph coordinates
-  start = coordinateFromBin (binStartMax,
+  start = coordinateFromBin (qFloor (binStartMax),
                              valueMin,
                              valueMax);
   if (binStartMax + binStepMax < m_numHistogramBins) {
 
     // Normal case where a reasonable step value is being calculated
-    double next = coordinateFromBin (binStartMax + binStepMax,
+    double next = coordinateFromBin (qFloor (binStartMax + binStepMax),
                                      valueMin,
                                      valueMax);
     step = next - start;
diff --git a/src/Grid/GridCoordDisable.cpp b/src/Grid/GridCoordDisable.cpp
index 3a04bafe..d5124c10 100644
--- a/src/Grid/GridCoordDisable.cpp
+++ b/src/Grid/GridCoordDisable.cpp
@@ -9,20 +9,25 @@
 
 QString gridCoordDisableToString (GridCoordDisable gridCoordDisable)
 {
+  QString rtn;
+
   switch (gridCoordDisable) {
     case GRID_COORD_DISABLE_COUNT:
-      return QObject::tr ("Count");
+      rtn = QObject::tr ("Count");
+      break;
 
     case GRID_COORD_DISABLE_START:
-      return QObject::tr ("Start");
+      rtn = QObject::tr ("Start");
+      break;
 
     case GRID_COORD_DISABLE_STEP:
-      return QObject::tr ("Step");
+      rtn = QObject::tr ("Step");
+      break;
 
     case GRID_COORD_DISABLE_STOP:
-      return QObject::tr ("Stop");
-
-    default:
-      return QObject::tr ("Unknown");
+      rtn = QObject::tr ("Stop");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Grid/GridHealerAbstractBase.cpp b/src/Grid/GridHealerAbstractBase.cpp
index fdf9998e..ca471ec2 100644
--- a/src/Grid/GridHealerAbstractBase.cpp
+++ b/src/Grid/GridHealerAbstractBase.cpp
@@ -112,7 +112,7 @@ const MutualPairHalves &GridHealerAbstractBase::mutualPairHalvesBelow () const
 int GridHealerAbstractBase::pixelCountInRegionThreshold (const DocumentModelGridRemoval &modelGridRemoval)
 {
   // For now we will use the close distance as the minimum pixel count
-  return modelGridRemoval.closeDistance();
+  return qFloor (modelGridRemoval.closeDistance());
 }
 
 bool GridHealerAbstractBase::pointsAreGood (const QImage &image,
@@ -135,6 +135,6 @@ void GridHealerAbstractBase::saveGapSeparation (double gapSeparation)
 {
   // Right triangle with one edge crossing the gap (separation value) and hypotenuse giving
   // maximum point separation (closest distance) gives the maximum horizontal separation
-  m_maxPointSeparation = qSqrt (qPow (modelGridRemoval().closeDistance(), 2) -
-                                qPow (gapSeparation, 2));
+  m_maxPointSeparation = qFloor (qSqrt (qPow (modelGridRemoval().closeDistance(), 2) -
+                                        qPow (gapSeparation, 2)));
 }
diff --git a/src/Grid/GridHealerHorizontal.cpp b/src/Grid/GridHealerHorizontal.cpp
index d96fb9d7..d000a2eb 100644
--- a/src/Grid/GridHealerHorizontal.cpp
+++ b/src/Grid/GridHealerHorizontal.cpp
@@ -84,7 +84,7 @@ void GridHealerHorizontal::doHealingAcrossGaps (QImage &image)
             doHealingOnBelowRange (image,
                                    xBelowStart,
                                    xBelowEnd,
-                                   maxPointSeparation());
+                                   qFloor (maxPointSeparation()));
 
             // Go back to outer loop, which will skip to xBelowEnd
             break;
diff --git a/src/Grid/GridHealerVertical.cpp b/src/Grid/GridHealerVertical.cpp
index f131458b..9e99eabd 100644
--- a/src/Grid/GridHealerVertical.cpp
+++ b/src/Grid/GridHealerVertical.cpp
@@ -84,7 +84,7 @@ void GridHealerVertical::doHealingAcrossGaps (QImage &image)
             doHealingOnBelowRange (image,
                                    yBelowStart,
                                    yBelowEnd,
-                                   maxPointSeparation());
+                                   qFloor (maxPointSeparation()));
 
             // Go back to outer loop, which will skip to xBelowEnd
             break;
diff --git a/src/Grid/GridInitializer.cpp b/src/Grid/GridInitializer.cpp
index 8d21f755..1b471555 100644
--- a/src/Grid/GridInitializer.cpp
+++ b/src/Grid/GridInitializer.cpp
@@ -46,11 +46,11 @@ void GridInitializer::axisScale (double xMin,
   // Round off average to first significant digit of range
   xAverage = (xMin + xMax) / 2.0;
   xRange = xMax - xMin;
-  if (xRange == 0) {
+  if (qAbs (xRange) <= 0) {
     xRange = fabs (xAverage / 10.0); // for null range use arbitrary range
   }
   nDigitRange = valuePower (xRange);
-  xDelta = pow ((double) 10.0, (double) nDigitRange);
+  xDelta = pow (10.0, double (nDigitRange));
   xAverageRoundedUp = xDelta * floor ((xAverage + xDelta / 2.0) / xDelta);
 
   if (xRange > range_epsilon) {
@@ -72,14 +72,14 @@ void GridInitializer::axisScale (double xMin,
     xStop += xDelta;
   }
 
-  xCount = 1 + (int) floor ((xStop - xStart) / xDelta + 0.5);
+  xCount = 1 + qFloor ((xStop - xStart) / xDelta + 0.5);
 
   if (!linearAxis) {
 
     // Convert from log scale back to linear scale. We make sure to keep numbers like 10^-8 unmolested
-    xStart = pow((double) 10.0, xStart);
-    xStop = pow((double) 10.0, xStop);
-    xDelta = pow((double) 10.0, xDelta);
+    xStart = pow(10.0, xStart);
+    xStop = pow(10.0, xStop);
+    xDelta = pow(10.0, xDelta);
 
   } else {
 
@@ -100,16 +100,16 @@ int GridInitializer::computeCount (bool linearAxis,
   int count;
 
   if (linearAxis) {
-    if (step == 0) {
+    if (qAbs (step) <= 0) {
       count = 1;
     } else {
-      count = (int) (1.0 + (stop - start) / step);
+      count = qFloor (1.0 + (stop - start) / step);
     }
   } else {
     if ((start <= 0) || (step <= 0.0)) {
       count = 1;
     } else {
-      count = (int) (1.0 + log10 (stop / start) / log10 (step));
+      count = qFloor (1.0 + log10 (stop / start) / log10 (step));
     }
   }
 
@@ -126,7 +126,7 @@ double GridInitializer::computeStart (bool linearAxis,
   if (linearAxis) {
     start = stop - step * (count - 1);
   } else {
-    start = stop / pow (step, (double) (count - 1));
+    start = stop / pow (step, double (count - 1));
   }
 
   return start;
@@ -150,7 +150,7 @@ double GridInitializer::computeStep (bool linearAxis,
       step = 1.0;
     } else {
       if (count > 1) {
-        step = pow (stop / start, (double) 1.0 / (count - 1));
+        step = pow (stop / start, 1.0 / double (count - 1));
       } else {
         step = stop / start;
       }
@@ -170,13 +170,14 @@ double GridInitializer::computeStop (bool linearAxis,
   if (linearAxis) {
     stop = start + step * (count - 1);
   } else {
-    stop = start * pow (step, (double) (count - 1));
+    stop = start * pow (step, double (count - 1));
   }
 
   return stop;
 }
 
-DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QRectF &boundingRectGraph,
+DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QPointF &boundingRectGraphMin,
+                                                                        const QPointF &boundingRectGraphMax,
                                                                         const DocumentModelCoords &modelCoords) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GridInitializer::initializeWithNarrowCoverage";
@@ -187,8 +188,8 @@ DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QR
   double start, stop, step;
 
   // X/theta coordinate
-  axisScale (boundingRectGraph.x(),
-             boundingRectGraph.x() + boundingRectGraph.width(),
+  axisScale (boundingRectGraphMin.x(),
+             boundingRectGraphMax.x(),
              (modelCoords.coordScaleXTheta() == COORD_SCALE_LINEAR),
              start,
              stop,
@@ -196,14 +197,14 @@ DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QR
              count);
 
   modelGridDisplay.setDisableX (GRID_COORD_DISABLE_COUNT);
-  modelGridDisplay.setCountX (count);
+  modelGridDisplay.setCountX (unsigned (count));
   modelGridDisplay.setStartX (start);
   modelGridDisplay.setStepX (step);
   modelGridDisplay.setStopX (stop);
 
   // Y/radius coordinate
-  axisScale (boundingRectGraph.y(),
-             boundingRectGraph.y() + boundingRectGraph.height(),
+  axisScale (boundingRectGraphMin.y(),
+             boundingRectGraphMax.y(),
              (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR),
              start,
              stop,
@@ -211,7 +212,7 @@ DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QR
              count);
 
   modelGridDisplay.setDisableY (GRID_COORD_DISABLE_COUNT);
-  modelGridDisplay.setCountY (count);
+  modelGridDisplay.setCountY (unsigned (count));
   modelGridDisplay.setStartY (start);
   modelGridDisplay.setStepY (step);
   modelGridDisplay.setStopY (stop);
@@ -221,14 +222,16 @@ DocumentModelGridDisplay GridInitializer::initializeWithNarrowCoverage (const QR
   return modelGridDisplay;
 }
 
-DocumentModelGridDisplay GridInitializer::initializeWithWidePolarCoverage (const QRectF &boundingRectGraph,
+DocumentModelGridDisplay GridInitializer::initializeWithWidePolarCoverage (const QPointF &boundingRectGraphMin,
+                                                                           const QPointF &boundingRectGraphMax,
                                                                            const DocumentModelCoords &modelCoords,
                                                                            const Transformation &transformation,
                                                                            const QSize &imageSize) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "GridInitializer::initializeWithWidePolarCoverage";
 
-  DocumentModelGridDisplay modelGridDisplay = initializeWithNarrowCoverage (boundingRectGraph,
+  DocumentModelGridDisplay modelGridDisplay = initializeWithNarrowCoverage (boundingRectGraphMin,
+                                                                            boundingRectGraphMax,
                                                                             modelCoords);
 
   if (modelCoords.coordsType() == COORDS_TYPE_POLAR) {
@@ -254,11 +257,11 @@ void GridInitializer::overridePolarCoordinateSettings (const DocumentModelCoords
   double startX = 0.0;
   double stopX = 360.0;
   double stepX = 30.0;
-  int countX = (int) (0.5 + (stopX - startX) / stepX);
+  int countX = qFloor (0.5 + (stopX - startX) / stepX);
   modelGridDisplay.setStartX (startX);
   modelGridDisplay.setStepX (stepX);
   modelGridDisplay.setStopX (stopX);
-  modelGridDisplay.setCountX (countX);
+  modelGridDisplay.setCountX (unsigned (countX));
 
   // We extend the range to cover the four corners of the image, since otherwise
   // areas around at least some graph corners are not covered by the grid lines
@@ -284,21 +287,21 @@ void GridInitializer::overridePolarCoordinateSettings (const DocumentModelCoords
                         stepY :
                         qLn (stepY));
   int countY = 1;
-  if (denominator != 0) {
+  if (qAbs (denominator) > 0) {
     countY = (modelCoords.coordScaleYRadius() == COORD_SCALE_LINEAR ?
-              (int) (0.5 + (stopY - startY) / denominator) :
-              (int) (0.5 + (qLn (stopY) - qLn (startY)) / denominator));
+              qFloor (0.5 + (stopY - startY) / denominator) :
+              qFloor (0.5 + (qLn (stopY) - qLn (startY)) / denominator));
   }
 
   modelGridDisplay.setStartY (startY);
   modelGridDisplay.setStopY (stopY);
-  modelGridDisplay.setCountY (countY);
+  modelGridDisplay.setCountY (unsigned (countY));
 }
 
 double GridInitializer::roundOffToPower(double arg,
                                         int power) const
 {
-  double powerOf10 = pow ((double) 10, power);
+  double powerOf10 = pow (10.0, power);
   return powerOf10 * floor (arg / powerOf10 + 0.5);
 }
 
@@ -310,6 +313,6 @@ int GridInitializer::valuePower(double value) const
   if (avalue < pow(10.0, minPower)) {
     return minPower;
   } else {
-    return (int) floor (log10 (avalue));
+    return qFloor (log10 (avalue));
   }
 }
diff --git a/src/Grid/GridInitializer.h b/src/Grid/GridInitializer.h
index d5c24c23..e70a1fbf 100644
--- a/src/Grid/GridInitializer.h
+++ b/src/Grid/GridInitializer.h
@@ -40,15 +40,21 @@ class GridInitializer
                       double step,
                       int count) const;
 
-  /// Initialize given the boundaries of the graph coordinates. The output is useful for the Checker class
-  DocumentModelGridDisplay initializeWithNarrowCoverage (const QRectF &boundingRectGraph,
+  /// Initialize given the boundaries of the graph coordinates. The output is useful for the Checker class.
+  /// The bounding rectangle is handled as two QPointFs rather one QRectF since QRectF rounds off the
+  /// lower coordinate to zero when there is a large dynamic range (1e-3 to 1e+9) and zeros break log calculations
+  DocumentModelGridDisplay initializeWithNarrowCoverage (const QPointF &boundingRectGraphMin,
+                                                         const QPointF &boundingRectGraphMax,
                                                          const DocumentModelCoords &modelCoords) const;
 
   /// Initialize given the boundaries of the graph coordinates, and then extra processing for polar coordinates:
   /// -# radial range expanded to cover the center (to remove hole at center) to the image corners
   ///    (to guarantee coverage at corners of graph)
   /// -# angular range is expanded to cover the entire circle (so coverage is total for all directions)
-  DocumentModelGridDisplay initializeWithWidePolarCoverage (const QRectF &boundingRectGraph,
+  /// The bounding rectangle is handled as two QPointFs rather one QRectF since QRectF rounds off the
+  /// lower coordinate to zero when there is a large dynamic range (1e-3 to 1e+9) and zeros break log calculations
+  DocumentModelGridDisplay initializeWithWidePolarCoverage (const QPointF &boundingRectGraphMin,
+                                                            const QPointF &boundingRectGraphMax,
                                                             const DocumentModelCoords &modelCoords,
                                                             const Transformation &transformation,
                                                             const QSize &imageSize) const;
diff --git a/src/Grid/GridLine.cpp b/src/Grid/GridLine.cpp
index b24154c0..78d36391 100644
--- a/src/Grid/GridLine.cpp
+++ b/src/Grid/GridLine.cpp
@@ -15,6 +15,11 @@ GridLine::GridLine ()
 {
 }
 
+GridLine::GridLine (const GridLine & /* other */)
+{
+  ENGAUGE_ASSERT (false);
+}
+
 GridLine::~GridLine ()
 {
   // Crash here means QGraphicsScene::clear was called, which is entirely unnecessary
@@ -27,11 +32,6 @@ GridLine::~GridLine ()
   m_segments.clear ();
 }
 
-GridLine::GridLine (const GridLine & /* other */)
-{
-  ENGAUGE_ASSERT (false);
-}
-
 GridLine &GridLine::operator= (GridLine & /* other */)
 {
   ENGAUGE_ASSERT (false);
@@ -48,14 +48,14 @@ void GridLine::setPen (const QPen &pen)
 {
   for (int i = 0; i < m_segments.count(); i++) {
     QGraphicsItem *item = m_segments [i];
-    if (item != 0) {
+    if (item != nullptr) {
 
       // Downcast since QGraphicsItem does not have a pen
       QGraphicsLineItem *itemLine = dynamic_cast<QGraphicsLineItem*> (item);
       QGraphicsEllipseItem *itemArc = dynamic_cast<QGraphicsEllipseItem*> (item);
-      if (itemLine != 0) {
+      if (itemLine != nullptr) {
         itemLine->setPen (pen);
-      } else if (itemArc != 0) {
+      } else if (itemArc != nullptr) {
         itemArc->setPen (pen);
       }
     }
diff --git a/src/Grid/GridLineFactory.cpp b/src/Grid/GridLineFactory.cpp
index 77a954f0..2d3b6d2a 100644
--- a/src/Grid/GridLineFactory.cpp
+++ b/src/Grid/GridLineFactory.cpp
@@ -101,7 +101,7 @@ GridLine *GridLineFactory::createGridLine (double xFrom,
   // Loop through steps. Final step i=NUM_STEPS does final processing if a segment is active
   for (int i = 0; i <= NUM_STEPS; i++) {
 
-    double s = (double) i / (double) NUM_STEPS;
+    double s = double (i) / double (NUM_STEPS);
 
     // Interpolate coordinates assuming normal linear scaling
     double xGraph = (1.0 - s) * xFrom + s * xTo;
@@ -264,8 +264,9 @@ void GridLineFactory::createTransformAlign (const Transformation &transformation
                                                                                 posXRadiusY0AlignedScreen,
                                                                                 posX0YRadiusAlignedScreen);
 
+  // Use \n rather than endl to prevent compiler warning "nonnull argument t compared to null"
   LOG4CPP_INFO_S ((*mainCat)) << "GridLineFactory::createTransformAlign"
-                              << " transformation=" << QTransformToString (transformation.transformMatrix()).toLatin1().data() << endl
+                              << " transformation=" << QTransformToString (transformation.transformMatrix()).toLatin1().data() << "\n"
                               << " radiusLinearCartesian=" << radiusLinearCartesian
                               << " posXRadiusY0Screen=" << QPointFToString (posXRadiusY0Screen).toLatin1().data()
                               << " posX0YRadiusScreen=" << QPointFToString (posX0YRadiusScreen).toLatin1().data()
@@ -330,8 +331,8 @@ QGraphicsItem *GridLineFactory::ellipseItem (const Transformation &transformatio
                        2 * ellipseXAxis,
                        2 * ellipseYAxis);
   GraphicsArcItem *item = new GraphicsArcItem (boundingRect);
-  item->setStartAngle (angleStart * RADIANS_TO_TICS);
-  item->setSpanAngle (angleSpan * RADIANS_TO_TICS);
+  item->setStartAngle (qFloor (angleStart * RADIANS_TO_TICS));
+  item->setSpanAngle (qFloor (angleSpan * RADIANS_TO_TICS));
 
   item->setTransform (transformAlign.transposed ().inverted ());
 
diff --git a/src/Grid/GridLineLimiter.cpp b/src/Grid/GridLineLimiter.cpp
index 76c4166e..6a9a57a9 100644
--- a/src/Grid/GridLineLimiter.cpp
+++ b/src/Grid/GridLineLimiter.cpp
@@ -20,11 +20,14 @@ GridLineLimiter::GridLineLimiter ()
 {
 }
 
-QRectF GridLineLimiter::documentBounds (const Document &document,
-                                        const Transformation &transformation) const
+void GridLineLimiter::documentBounds (const Document &document,
+                                      const Transformation &transformation,
+                                      QPointF &boundingRectMin,
+                                      QPointF &boundingRectMax) const
 {
   // Get graph coordinate bounds
-  CallbackBoundingRects ftor (transformation);
+  CallbackBoundingRects ftor (document.documentAxesPointsRequired(),
+                              transformation);
 
   Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
                                                                                                      &CallbackBoundingRects::callback);
@@ -32,9 +35,8 @@ QRectF GridLineLimiter::documentBounds (const Document &document,
   document.iterateThroughCurvesPointsGraphs (ftorWithCallback);
 
   bool isEmpty;
-  QRectF boundingRectGraph = ftor.boundingRectGraph(isEmpty);
-
-  return boundingRectGraph;
+  boundingRectMin = ftor.boundingRectGraphMin (isEmpty);
+  boundingRectMax = ftor.boundingRectGraphMax (isEmpty);
 }
 
 void GridLineLimiter::limitForXTheta (const Document &document,
@@ -49,7 +51,7 @@ void GridLineLimiter::limitForXTheta (const Document &document,
   startX = modelGrid.startX();
   stopX = modelGrid.stopX();
   stepX = modelGrid.stepX();
-  int countX = modelGrid.countX();
+  int countX = signed (modelGrid.countX());
 
   bool needReduction = (countX > modelMainWindow.maximumGridLines());
 
@@ -61,7 +63,7 @@ void GridLineLimiter::limitForXTheta (const Document &document,
         stepX = 0;
         needReduction = true;
       } else {
-        countX = 1.0 + (stopX - startX) / stepX;
+        countX = qFloor (1.0 + (stopX - startX) / stepX);
         needReduction = (countX > modelMainWindow.maximumGridLines());
       }
     }
@@ -76,11 +78,14 @@ void GridLineLimiter::limitForXTheta (const Document &document,
     if (startX <= 0) {
 
       // Start value is invalid so override both start and step
-      QRectF boundingRectGraph = documentBounds (document,
-                                                 transformation);
+      QPointF boundingRectGraphMin, boundingRectGraphMax;
+      documentBounds (document,
+                      transformation,
+                      boundingRectGraphMin,
+                      boundingRectGraphMax);
 
       // Override lower bound
-      startX = boundingRectGraph.left ();
+      startX = boundingRectGraphMin.x ();
     }
 
     if (!needReduction) {
@@ -88,7 +93,7 @@ void GridLineLimiter::limitForXTheta (const Document &document,
         stepX = 1;
         needReduction = true;        
       } else {
-        countX = 1.0 + (qLn (stopX) - qLn (startX)) / qLn (stepX);
+        countX = qFloor (1.0 + (qLn (stopX) - qLn (startX)) / qLn (stepX));
         needReduction = (countX > modelMainWindow.maximumGridLines());
       }
     }
@@ -111,7 +116,7 @@ void GridLineLimiter::limitForYRadius (const Document &document,
   startY = modelGrid.startY();
   stopY = modelGrid.stopY();
   stepY = modelGrid.stepY();
-  int countY = modelGrid.countY();
+  int countY = signed (modelGrid.countY());
 
   bool needReduction = (countY > modelMainWindow.maximumGridLines());
 
@@ -123,7 +128,7 @@ void GridLineLimiter::limitForYRadius (const Document &document,
         stepY = 0;
         needReduction = true;        
       } else {
-        countY = 1.0 + (stopY - startY) / stepY;
+        countY = qFloor (1.0 + (stopY - startY) / stepY);
         needReduction = (countY > modelMainWindow.maximumGridLines());
       }
     }
@@ -138,11 +143,14 @@ void GridLineLimiter::limitForYRadius (const Document &document,
     if (startY <= 0) {
 
       // Start value is invalid so override both start and step
-      QRectF boundingRectGraph = documentBounds (document,
-                                                 transformation);
+      QPointF boundingRectGraphMin, boundingRectGraphMax;
+      documentBounds (document,
+                      transformation,
+                      boundingRectGraphMin,
+                      boundingRectGraphMax);
 
       // Override lower bound
-      startY = boundingRectGraph.top ();
+      startY = boundingRectGraphMin.y ();
     }
 
     if (!needReduction) {
@@ -150,7 +158,7 @@ void GridLineLimiter::limitForYRadius (const Document &document,
         stepY = 1;
         needReduction = true;        
       } else {
-        countY = 1.0 + (qLn (stopY) - qLn (startY)) / qLn (stepY);
+        countY = qFloor (1.0 + (qLn (stopY) - qLn (startY)) / qLn (stepY));
         needReduction = (countY > modelMainWindow.maximumGridLines());
       }
     }
diff --git a/src/Grid/GridLineLimiter.h b/src/Grid/GridLineLimiter.h
index 7745ccea..ffa29c86 100644
--- a/src/Grid/GridLineLimiter.h
+++ b/src/Grid/GridLineLimiter.h
@@ -7,7 +7,7 @@
 #ifndef GRID_LINE_LIMITER_H
 #define GRID_LINE_LIMITER_H
 
-#include <QRectF>
+#include <QPointF>
 
 class Document;
 class DocumentModelCoords;
@@ -48,8 +48,10 @@ public:
 
 private:
 
-  QRectF documentBounds (const Document &document,
-                         const Transformation &transformation) const;
+  void documentBounds (const Document &document,
+                       const Transformation &transformation,
+                       QPointF &boundingRectMin,
+                       QPointF &boundingRectMax) const;
 
 };
 
diff --git a/src/Grid/GridLines.cpp b/src/Grid/GridLines.cpp
index 6bc72f81..f1b8673d 100644
--- a/src/Grid/GridLines.cpp
+++ b/src/Grid/GridLines.cpp
@@ -11,6 +11,11 @@ GridLines::GridLines()
 {
 }
 
+GridLines::~GridLines()
+{
+  qDeleteAll (m_gridLinesContainer);
+}
+
 void GridLines::add (GridLine *gridLine)
 {
   m_gridLinesContainer.push_back (gridLine);
diff --git a/src/Grid/GridLines.h b/src/Grid/GridLines.h
index 089c1037..f0b117eb 100644
--- a/src/Grid/GridLines.h
+++ b/src/Grid/GridLines.h
@@ -21,6 +21,9 @@ class GridLines
   /// Single constructor
   GridLines();
 
+  /// Destructor deallocates memory
+  ~GridLines();
+  
   /// Add specified grid line. Ownership of all allocated QGraphicsItems is passed to new GridLine
   void add (GridLine *gridLine);
 
diff --git a/src/Grid/GridRemoval.cpp b/src/Grid/GridRemoval.cpp
index 504530e1..a9fe8fbd 100644
--- a/src/Grid/GridRemoval.cpp
+++ b/src/Grid/GridRemoval.cpp
@@ -163,13 +163,13 @@ void GridRemoval::removeLine (const QPointF &posMin,
                                                          modelGridRemoval);
       gridHealers.push_back (gridHealer);
 
-      int xMin = qMin (pos1.x(), pos2.x());
-      int xMax = qMax (pos1.x(), pos2.x());
-      int yAtXMin = (pos1.x() < pos2.x() ? pos1.y() : pos2.y());
-      int yAtXMax = (pos1.x() < pos2.x() ? pos2.y() : pos1.y());
+      int xMin = qMin (qFloor (pos1.x()), qFloor (pos2.x()));
+      int xMax = qMax (qFloor (pos1.x()), qFloor (pos2.x()));
+      int yAtXMin = (pos1.x() < pos2.x() ? qFloor (pos1.y()) : qFloor (pos2.y()));
+      int yAtXMax = (pos1.x() < pos2.x() ? qFloor (pos2.y()) : qFloor (pos1.y()));
       for (int x = xMin; x <= xMax; x++) {
-        double s = (double) (x - xMin) / (double) (xMax - xMin);
-        int yLine = (int) (0.5 + (1.0 - s) * yAtXMin + s * yAtXMax);
+        double s = double (x - xMin) / double (xMax - xMin);
+        int yLine = qFloor (0.5 + (1.0 - s) * yAtXMin + s * yAtXMax);
         for (int yOffset = -HALF_WIDTH; yOffset <= HALF_WIDTH; yOffset++) {
           int y = yLine + yOffset;
           image.setPixel (x, y, QColor(Qt::white).rgb());
@@ -184,13 +184,13 @@ void GridRemoval::removeLine (const QPointF &posMin,
                                                                    modelGridRemoval);
       gridHealers.push_back (gridHealer);
 
-      int yMin = qMin (pos1.y(), pos2.y());
-      int yMax = qMax (pos1.y(), pos2.y());
-      int xAtYMin = (pos1.y() < pos2.y() ? pos1.x() : pos2.x());
-      int xAtYMax = (pos1.y() < pos2.y() ? pos2.x() : pos1.x());
+      int yMin = qMin (qFloor (pos1.y()), qFloor (pos2.y()));
+      int yMax = qMax (qFloor (pos1.y()), qFloor (pos2.y()));
+      int xAtYMin = (pos1.y() < pos2.y() ? qFloor (pos1.x()) : qFloor (pos2.x()));
+      int xAtYMax = (pos1.y() < pos2.y() ? qFloor (pos2.x()) : qFloor (pos1.x()));
       for (int y = yMin; y <= yMax; y++) {
-        double s = (double) (y - yMin) / (double) (yMax - yMin);
-        int xLine = (int) (0.5  + (1.0 - s) * xAtYMin + s * xAtYMax);
+        double s = double (y - yMin) / double (yMax - yMin);
+        int xLine = qFloor (0.5  + (1.0 - s) * xAtYMin + s * xAtYMax);
         for (int xOffset = -HALF_WIDTH; xOffset <= HALF_WIDTH; xOffset++) {
           int x = xLine + xOffset;
           image.setPixel (x, y, QColor(Qt::white).rgb());
diff --git a/src/Grid/GridTriangleFill.cpp b/src/Grid/GridTriangleFill.cpp
index 6aac9c22..bc61c143 100644
--- a/src/Grid/GridTriangleFill.cpp
+++ b/src/Grid/GridTriangleFill.cpp
@@ -9,6 +9,7 @@
 #include "GridTriangleFill.h"
 #include <QImage>
 #include <QList>
+#include <qmath.h>
 #include <QPoint>
 
 // Non-member comparison function
@@ -81,8 +82,8 @@ void GridTriangleFill::fill (GridLog &gridLog,
 
       // General case is handled by splitting the triangle into one flat top piece and
       // one flat bottom piece. Fourth point is at same y value as middle point p1
-      double s = (double) (p1.y() - p0.y())/ (double) (p2.y() - p0.y());
-      QPoint p3 ((int) (p0.x() + s * (p2.x() - p0.x())),
+      double s = double (p1.y() - p0.y()) / double (p2.y() - p0.y());
+      QPoint p3 (qFloor (p0.x() + s * (p2.x() - p0.x())),
                  p1.y());
       flatBottom (gridLog, image, p0, p1, p3);
       flatTop (gridLog, image, p1, p3, p2);
@@ -99,7 +100,7 @@ void GridTriangleFill::flatBottom (GridLog &gridLog,
   // Either neither or both denominators are zero, since p1.y()=p2.y()
   double denom0 = p1.y() - p0.y();
   double denom1 = p2.y() - p0.y();
-  if (denom0 == 0 || denom1 == 0) {
+  if (qAbs (denom0) <= 0 || qAbs (denom1) <= 0) {
     drawLine (gridLog,
               image,
               p0.x(),
@@ -123,8 +124,8 @@ void GridTriangleFill::flatBottom (GridLog &gridLog,
     for (int scanLineY = p0.y(); scanLineY <= p1.y(); scanLineY++) {
       drawLine (gridLog,
                 image,
-                (int) x0,
-                (int) x1,
+                qFloor (x0),
+                qFloor (x1),
                 scanLineY);
       x0 += slopeInverse0;
       x1 += slopeInverse1;
@@ -141,7 +142,7 @@ void GridTriangleFill::flatTop (GridLog &gridLog,
   // Either neither or both denominators are zero, since p0.y()=p1.y()
   double denom0 = p2.y() - p0.y();
   double denom1 = p2.y() - p1.y();
-  if (denom0 == 0 || denom1 == 0) {
+  if (qAbs (denom0) <= 0 || qAbs (denom1) <= 0) {
     drawLine (gridLog,
               image,
               p0.x(),
@@ -165,8 +166,8 @@ void GridTriangleFill::flatTop (GridLog &gridLog,
     for (int scanLineY = p2.y(); scanLineY >= p0.y(); scanLineY--) {
       drawLine (gridLog,
                 image,
-                (int) x0,
-                (int) x1,
+                qFloor (x0),
+                qFloor (x1),
                 scanLineY);
       x0 -= slopeInverse0;
       x1 -= slopeInverse1;
diff --git a/src/Import/ImportCroppingUtilPdf.cpp b/src/Import/ImportCroppingUtilPdf.cpp
index fd623a01..78ef42cc 100644
--- a/src/Import/ImportCroppingUtilPdf.cpp
+++ b/src/Import/ImportCroppingUtilPdf.cpp
@@ -19,7 +19,7 @@ bool ImportCroppingUtilPdf::applyImportCropping (bool isErrorReportRegressionTes
                                                  ImportCropping importCropping,
                                                  Document *&document) const
 {
-  document = 0;
+  document = nullptr;
 
   bool cropping = false;
 
@@ -32,7 +32,7 @@ bool ImportCroppingUtilPdf::applyImportCropping (bool isErrorReportRegressionTes
       QApplication::setOverrideCursor (Qt::BusyCursor); // Since load could take a while
       document = Document::load (fileName);
       QApplication::restoreOverrideCursor();
-      if (document != 0) {
+      if (document != nullptr) {
         if (!document->isLocked ()) {
 
           cropping = (importCropping == IMPORT_CROPPING_ALWAYS ||
diff --git a/src/Jpeg2000/Jpeg2000.cpp b/src/Jpeg2000/Jpeg2000.cpp
index 82996295..22a51e0f 100644
--- a/src/Jpeg2000/Jpeg2000.cpp
+++ b/src/Jpeg2000/Jpeg2000.cpp
@@ -76,7 +76,7 @@ int Jpeg2000::getFileFormat(const char *filename) const
                                TIF_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT,
                                J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT, J2K_CFMT};
   const char * ext = strrchr(filename, '.');
-  if (ext == NULL) {
+  if (ext == nullptr) {
     return -1;
   }
   ext++;
@@ -121,7 +121,7 @@ int Jpeg2000::inputFormat(const char *filename) const
   reader = fopen(filename,
                  "rb");
 
-  if (reader == NULL) {
+  if (reader == nullptr) {
     return -2;
   }
 
diff --git a/src/Jpeg2000/Jpeg2000Color.cpp b/src/Jpeg2000/Jpeg2000Color.cpp
index 7bc7a1d7..cf1be47d 100644
--- a/src/Jpeg2000/Jpeg2000Color.cpp
+++ b/src/Jpeg2000/Jpeg2000Color.cpp
@@ -35,11 +35,12 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <assert.h>
+#include <math.h>
+#include <qmath.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <math.h>
-#include <assert.h>
 
 #include "Jpeg2000Color.h"
 
@@ -68,13 +69,13 @@ void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
   int r, g, b;
 
   cb -= offset; cr -= offset;
-  r = y + (int)(1.402 * (float)cr);
+  r = y + qFloor (1.402 * double (cr));
   if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
 
-  g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
+  g = y - qFloor (0.344 * double (cb) + 0.714 * double (cr));
   if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
 
-  b = y + (int)(1.772 * (float)cb);
+  b = y + qFloor (1.772 * double (cb));
   if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
 }
 
@@ -84,19 +85,20 @@ void sycc444_to_rgb(opj_image_t *img)
   const int *y, *cb, *cr;
   int maxw, maxh, max, i, offset, upb;
 
-  i = (int)img->comps[0].prec;
+  i = qFloor (img->comps[0].prec);
   offset = 1<<(i - 1); upb = (1<<i)-1;
 
-  maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+  maxw = qFloor (img->comps[0].w);
+  maxh = qFloor (img->comps[0].h);
   max = maxw * maxh;
 
   y = img->comps[0].data;
   cb = img->comps[1].data;
   cr = img->comps[2].data;
 
-  d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
-  d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
-  d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+  d0 = r = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d1 = g = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d2 = b = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
 
   for(i = 0; i < max; ++i)
   {
@@ -117,19 +119,20 @@ void sycc422_to_rgb(opj_image_t *img)
   int maxw, maxh, max, offset, upb;
   int i, j;
 
-  i = (int)img->comps[0].prec;
+  i = qFloor (img->comps[0].prec);
   offset = 1<<(i - 1); upb = (1<<i)-1;
 
-  maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+  maxw = qFloor (img->comps[0].w);
+  maxh = qFloor (img->comps[0].h);
   max = maxw * maxh;
 
   y = img->comps[0].data;
   cb = img->comps[1].data;
   cr = img->comps[2].data;
 
-  d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
-  d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
-  d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+  d0 = r = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d1 = g = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d2 = b = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
 
   for(i=0; i < maxh; ++i)
   {
@@ -152,8 +155,10 @@ void sycc422_to_rgb(opj_image_t *img)
   img->comps[1].w = maxw; img->comps[1].h = maxh;
   img->comps[2].w = maxw; img->comps[2].h = maxh;
 #else
-  img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
-  img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
+  img->comps[1].w = static_cast<OPJ_UINT32> (maxw);
+  img->comps[1].h = static_cast<OPJ_UINT32> (maxh);
+  img->comps[2].w = static_cast<OPJ_UINT32> (maxw);
+  img->comps[2].h = static_cast<OPJ_UINT32> (maxh);
 #endif
   img->comps[1].dx = img->comps[0].dx;
   img->comps[2].dx = img->comps[0].dx;
@@ -169,19 +174,20 @@ void sycc420_to_rgb(opj_image_t *img)
   int maxw, maxh, max, offset, upb;
   int i, j;
 
-  i = (int)img->comps[0].prec;
+  i = qFloor (img->comps[0].prec);
   offset = 1<<(i - 1); upb = (1<<i)-1;
 
-  maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
+  maxw = qFloor (img->comps[0].w);
+  maxh = qFloor (img->comps[0].h);
   max = maxw * maxh;
 
   y = img->comps[0].data;
   cb = img->comps[1].data;
   cr = img->comps[2].data;
 
-  d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
-  d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
-  d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
+  d0 = r = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d1 = g = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
+  d2 = b = static_cast<int*> (malloc(sizeof(int) * static_cast<size_t> (max)));
 
   for(i=0; i < maxh; i += 2)
   {
@@ -216,8 +222,10 @@ void sycc420_to_rgb(opj_image_t *img)
   img->comps[1].w = maxw; img->comps[1].h = maxh;
   img->comps[2].w = maxw; img->comps[2].h = maxh;
 #else
-  img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
-  img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
+  img->comps[1].w = static_cast<OPJ_UINT32> (maxw);
+  img->comps[1].h = static_cast<OPJ_UINT32> (maxh);
+  img->comps[2].w = static_cast<OPJ_UINT32> (maxw);
+  img->comps[2].h = static_cast<OPJ_UINT32> (maxh);
 #endif
   img->comps[1].dx = img->comps[0].dx;
   img->comps[2].dx = img->comps[0].dx;
@@ -304,16 +312,16 @@ void color_apply_icc_profile(opj_image_t *image)
   in_prof = 
   cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
 
-  if(in_prof == NULL) return;
+  if(in_prof == nullptr) return;
 
   in_space = cmsGetPCS(in_prof);
   out_space = cmsGetColorSpace(in_prof);
   intent = cmsGetHeaderRenderingIntent(in_prof);
 
 	
-  max_w = (int)image->comps[0].w;
-  max_h = (int)image->comps[0].h;
-  prec = (int)image->comps[0].prec;
+  max_w = qFloor (image->comps[0].w);
+  max_h = qFloor (image->comps[0].h);
+  prec = qFloor (image->comps[0].prec);
   oldspace = image->color_space;
 
   if(out_space == cmsSigRgbData) /* enumCS 16 */
@@ -364,7 +372,7 @@ void color_apply_icc_profile(opj_image_t *image)
   cmsCloseProfile(out_prof);
 #endif
 
-  if(transform == NULL)
+  if(transform == nullptr)
   {
     image->color_space = oldspace;
 #ifdef OPJ_HAVE_LIBLCMS1
@@ -403,9 +411,9 @@ void color_apply_icc_profile(opj_image_t *image)
 
       for(i = 0; i < max; ++i)
       {
-	*r++ = (int)*out++;
-	*g++ = (int)*out++;
-	*b++ = (int)*out++;
+	*r++ = qFloor (*out++);
+	*g++ = qFloor (*out++);
+        *b++ = qFloor (*out++);
       }
       free(inbuf); free(outbuf);
     }
@@ -436,9 +444,9 @@ void color_apply_icc_profile(opj_image_t *image)
 
       for(i = 0; i < max; ++i)
       {
-	*r++ = (int)*out++;
-	*g++ = (int)*out++;
-	*b++ = (int)*out++;
+	*r++ = qFloor (*out++);
+	*g++ = qFloor (*out++);
+	*b++ = qFloor (*out++);
       }
       free(inbuf); free(outbuf);
     }
@@ -479,7 +487,9 @@ void color_apply_icc_profile(opj_image_t *image)
 
     for(i = 0; i < max; ++i)
     {
-      *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
+      *r++ = qFloor (*out++);
+      *g++ = qFloor (*out++);
+      *b++ = qFloor (*out++);
     }
     free(inbuf); free(outbuf);
 
diff --git a/src/Jpeg2000/Jpeg2000Convert.cpp b/src/Jpeg2000/Jpeg2000Convert.cpp
index b73dc82f..8467085b 100644
--- a/src/Jpeg2000/Jpeg2000Convert.cpp
+++ b/src/Jpeg2000/Jpeg2000Convert.cpp
@@ -44,12 +44,13 @@
 #include <QBuffer>
 #include <QDataStream>
 #include <QDebug>
+#include <qmath.h>
 #include <string.h>
 
 int imagetopnm(opj_image_t * image,
                QBuffer &buffer)
 {
-  int *red, *green, *blue, *alpha = NULL;
+  int *red, *green, *blue, *alpha = nullptr;
   int wr, hr, max;
   int i;
   unsigned int compno, ncomp;
@@ -59,7 +60,7 @@ int imagetopnm(opj_image_t * image,
   char bufferLocal[1024];
   QDataStream str (&buffer);
 
-  if((prec = (int)image->comps[0].prec) > 16)
+  if((prec = qFloor (image->comps[0].prec)) > 16)
   {
     fprintf(stderr,"%s:%d:imagetopnm\n\tprecision %d is larger than 16"
             "\n\t: refused.\n",__FILE__,__LINE__,prec);
@@ -80,7 +81,8 @@ int imagetopnm(opj_image_t * image,
   {
     two = (prec > 8);
     triple = (ncomp > 2);
-    wr = (int)image->comps[0].w; hr = (int)image->comps[0].h;
+    wr = qFloor (image->comps[0].w);
+    hr = qFloor (image->comps[0].h);
     max = (1<<prec) - 1; has_alpha = (ncomp == 4 || ncomp == 2);
 
     red = image->comps[0].data;
@@ -90,7 +92,7 @@ int imagetopnm(opj_image_t * image,
       green = image->comps[1].data;
       blue = image->comps[2].data;
     }
-    else green = blue = NULL;
+    else green = blue = nullptr;
 
     if(has_alpha)
     {
@@ -141,8 +143,8 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c%c",
-                (unsigned char)(v>>8),
-                (unsigned char)v);
+                static_cast<unsigned char> (v>>8),
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           2);
 
@@ -153,8 +155,8 @@ int imagetopnm(opj_image_t * image,
 
           sprintf(bufferLocal,
                   "%c%c",
-                  (unsigned char)(v>>8),
-                  (unsigned char)v);
+                  static_cast<unsigned char> (v>>8),
+                  static_cast<unsigned char> (v));
           str.writeRawData  (bufferLocal,
                              2);
 
@@ -163,8 +165,8 @@ int imagetopnm(opj_image_t * image,
 
           sprintf(bufferLocal,
                   "%c%c",
-                  (unsigned char)(v>>8),
-                  (unsigned char)v);
+                  static_cast<unsigned char> (v>>8),
+                  static_cast<unsigned char> (v));
           str.writeRawData (bufferLocal,
                             2);
 
@@ -177,8 +179,8 @@ int imagetopnm(opj_image_t * image,
 
           sprintf(bufferLocal,
                   "%c%c",
-                  (unsigned char)(v>>8),
-                  (unsigned char)v);
+                  static_cast<unsigned char> (v>>8),
+                  static_cast<unsigned char> (v));
           str.writeRawData (bufferLocal,
                             2);
         }
@@ -192,7 +194,7 @@ int imagetopnm(opj_image_t * image,
 
       sprintf(bufferLocal,
               "%c",
-              (unsigned char)v);
+              static_cast<unsigned char> (v));
       str.writeRawData (bufferLocal,
                         1);
       if(triple)
@@ -202,7 +204,7 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c",
-                (unsigned char)v);
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           1);
 	v = *blue++;
@@ -210,7 +212,7 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c",
-                (unsigned char)v);
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           1);
       }
@@ -221,7 +223,7 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c",
-                (unsigned char)v);
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           1);
       }
@@ -239,9 +241,9 @@ int imagetopnm(opj_image_t * image,
 
   for (compno = 0; compno < ncomp; compno++)
   {
-    wr = (int)image->comps[compno].w;
-    hr = (int)image->comps[compno].h;
-    prec = (int)image->comps[compno].prec;
+    wr = qFloor (image->comps[compno].w);
+    hr = qFloor (image->comps[compno].h);
+    prec = qFloor (image->comps[compno].prec);
     max = (1<<prec) - 1;
 
     sprintf(bufferLocal,
@@ -266,7 +268,8 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c%c",
-                (unsigned char)(v>>8), (unsigned char)v);
+                static_cast<unsigned char> (v>>8),
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           2);
 
@@ -277,7 +280,8 @@ int imagetopnm(opj_image_t * image,
 
           sprintf(bufferLocal,
                   "%c%c",
-                  (unsigned char)(v>>8), (unsigned char)v);
+                  static_cast<unsigned char> (v>>8),
+                  static_cast<unsigned char> (v));
           str.writeRawData (bufferLocal,
                             2);
         }
@@ -292,7 +296,7 @@ int imagetopnm(opj_image_t * image,
 
         sprintf(bufferLocal,
                 "%c",
-                (unsigned char)v);
+                static_cast<unsigned char> (v));
         str.writeRawData (bufferLocal,
                           1);
       }
diff --git a/src/Line/LineStyle.cpp b/src/Line/LineStyle.cpp
index 2f2bec46..726fa7a5 100644
--- a/src/Line/LineStyle.cpp
+++ b/src/Line/LineStyle.cpp
@@ -28,11 +28,11 @@ LineStyle::LineStyle ()
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_CURVE_AXES);
   m_width = settings.value (SETTINGS_CURVE_LINE_WIDTH,
-                            DEFAULT_LINE_WIDTH_AXES).toInt();
-  m_paletteColor = (ColorPalette) settings.value (SETTINGS_CURVE_LINE_COLOR,
-                                                  DEFAULT_LINE_COLOR_AXES).toInt();
-  m_curveConnectAs = (CurveConnectAs) settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
-                                                      DEFAULT_LINE_CONNECT_AS_AXES).toInt();
+                            DEFAULT_LINE_WIDTH_AXES).toUInt();
+  m_paletteColor = static_cast<ColorPalette> (settings.value (SETTINGS_CURVE_LINE_COLOR,
+                                                              DEFAULT_LINE_COLOR_AXES).toInt());
+  m_curveConnectAs = static_cast<CurveConnectAs> (settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
+                                                                  DEFAULT_LINE_CONNECT_AS_AXES).toInt());
 }
 
 LineStyle::LineStyle (unsigned int width,
@@ -71,12 +71,12 @@ LineStyle LineStyle::defaultAxesCurve ()
   settings.beginGroup (SETTINGS_GROUP_CURVE_AXES);
   int width = settings.value (SETTINGS_CURVE_LINE_WIDTH,
                               DEFAULT_LINE_WIDTH_AXES).toInt();
-  ColorPalette color = (ColorPalette) settings.value (SETTINGS_CURVE_LINE_COLOR,
-                                                      DEFAULT_LINE_COLOR_AXES).toInt();
-  CurveConnectAs connectAs = (CurveConnectAs) settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
-                                                              DEFAULT_LINE_CONNECT_AS_AXES).toInt();
+  ColorPalette color = static_cast<ColorPalette> (settings.value (SETTINGS_CURVE_LINE_COLOR,
+                                                                  DEFAULT_LINE_COLOR_AXES).toInt());
+  CurveConnectAs connectAs = static_cast<CurveConnectAs> (settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
+                                                                          DEFAULT_LINE_CONNECT_AS_AXES).toInt());
 
-  return LineStyle (width,
+  return LineStyle (unsigned (width),
                     color,
                     connectAs);
 }
@@ -91,12 +91,12 @@ LineStyle LineStyle::defaultGraphCurve (int index)
   settings.beginGroup (groupName);
   int width = settings.value (SETTINGS_CURVE_LINE_WIDTH,
                               DEFAULT_LINE_WIDTH_GRAPH).toInt();
-  ColorPalette color = (ColorPalette) settings.value (SETTINGS_CURVE_LINE_COLOR,
-                                                      DEFAULT_LINE_COLOR_GRAPH).toInt();
-  CurveConnectAs connectAs = (CurveConnectAs) settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
-                                                              DEFAULT_LINE_CONNECT_AS_GRAPH).toInt();
+  ColorPalette color = static_cast<ColorPalette> (settings.value (SETTINGS_CURVE_LINE_COLOR,
+                                                                  DEFAULT_LINE_COLOR_GRAPH).toInt());
+  CurveConnectAs connectAs = static_cast<CurveConnectAs> (settings.value (SETTINGS_CURVE_LINE_CONNECT_AS,
+                                                                          DEFAULT_LINE_CONNECT_AS_GRAPH).toInt());
 
-  return LineStyle (width,
+  return LineStyle (unsigned (width),
                     color,
                     connectAs);
 }
@@ -112,8 +112,8 @@ void LineStyle::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_LINE_STYLE_CONNECT_AS)) {
 
     setWidth (attributes.value(DOCUMENT_SERIALIZE_LINE_STYLE_WIDTH).toInt());
-    setPaletteColor ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_LINE_STYLE_COLOR).toInt());
-    setCurveConnectAs ((CurveConnectAs) attributes.value(DOCUMENT_SERIALIZE_LINE_STYLE_CONNECT_AS).toInt());
+    setPaletteColor (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_LINE_STYLE_COLOR).toInt()));
+    setCurveConnectAs (static_cast<CurveConnectAs> (attributes.value(DOCUMENT_SERIALIZE_LINE_STYLE_CONNECT_AS).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
@@ -167,7 +167,7 @@ void LineStyle::setPaletteColor (ColorPalette paletteColor)
 
 void LineStyle::setWidth (int width)
 {
-  m_width = width;
+  m_width = unsigned (width);
 }
 
 unsigned int LineStyle::width () const
diff --git a/src/Load/LoadFileInfo.cpp b/src/Load/LoadFileInfo.cpp
index c27198b9..e0e4938c 100644
--- a/src/Load/LoadFileInfo.cpp
+++ b/src/Load/LoadFileInfo.cpp
@@ -21,14 +21,21 @@ bool LoadFileInfo::loadsAsDigFile (const QString &urlString) const
 {
   LOG4CPP_INFO_S ((*mainCat)) << "LoadFileInfo::loadsAsDigFile";
 
-  QString fileName = urlString;
+  bool success = false;
 
-  QUrl url (urlString);
-  if (url.isLocalFile ()) {
-    fileName = url.toLocalFile();
-  }
+  if (urlString.length() > 0) {
+
+    QString fileName = urlString;
+
+    QUrl url (urlString);
+    if (url.isLocalFile ()) {
+      fileName = url.toLocalFile();
+    }
 
-  Document document (fileName);
+    Document document (fileName);
+
+    success = document.successfulRead();
+  }
 
-  return document.successfulRead();
+  return success;
 }
diff --git a/src/Load/LoadImageFromUrl.cpp b/src/Load/LoadImageFromUrl.cpp
index 684629bd..9a053956 100644
--- a/src/Load/LoadImageFromUrl.cpp
+++ b/src/Load/LoadImageFromUrl.cpp
@@ -9,15 +9,20 @@
 #include "MainWindow.h"
 #include <QFileInfo>
 #include <QMessageBox>
+#include <QTextStream>
+#ifdef NETWORKING
 #include <QtNetwork/QNetworkReply>
+#endif
 #include <QUrl>
 #include "Version.h"
 
 LoadImageFromUrl::LoadImageFromUrl (MainWindow &mainWindow) :
   m_mainWindow (mainWindow),
+#ifdef NETWORKING
   m_http (this),
-  m_reply (0),
-  m_buffer (0)
+  m_reply (nullptr),
+#endif
+  m_buffer (nullptr)
 {
   connect (this, SIGNAL (signalImportImage (QString, QImage)), &m_mainWindow, SLOT (slotFileImportImage (QString, QImage)));
 }
@@ -29,11 +34,13 @@ LoadImageFromUrl::~LoadImageFromUrl ()
 
 void LoadImageFromUrl::deallocate ()
 {
+#ifdef NETWORKING
   delete m_reply;
   delete m_buffer;
   
-  m_reply = 0;
-  m_buffer = 0;
+  m_reply = nullptr;
+  m_buffer = nullptr;
+#endif
 }
 
 void LoadImageFromUrl::slotFinished ()
@@ -98,6 +105,8 @@ void LoadImageFromUrl::startLoadImage (const QUrl &url)
 
   } else {
 
+    // Drop on the floor if networking is not enabled
+#ifdef NETWORKING
     // Asynchronous read from url
     deallocate ();
     m_buffer = new QByteArray;
@@ -106,10 +115,13 @@ void LoadImageFromUrl::startLoadImage (const QUrl &url)
 
     connect (m_reply, SIGNAL (readyRead()), this, SLOT (slotReadData()));
     connect (m_reply, SIGNAL (finished ()), this, SLOT (slotFinished ()));
+#endif
   }
 }
 
 void LoadImageFromUrl::slotReadData ()
 {
+#ifdef NETWORKING
   *m_buffer += m_reply->readAll ();
+#endif
 }
diff --git a/src/Load/LoadImageFromUrl.h b/src/Load/LoadImageFromUrl.h
index 535ef3aa..a7bedc51 100644
--- a/src/Load/LoadImageFromUrl.h
+++ b/src/Load/LoadImageFromUrl.h
@@ -8,7 +8,9 @@
 #define LOAD_IMAGE_FROM_URL_H
 
 #include <QImage>
+#ifdef NETWORKING
 #include <QtNetwork/QNetworkAccessManager>
+#endif
 #include <QObject>
 #include <QString>
 #include <QUrl>
@@ -44,8 +46,10 @@ private:
 
   MainWindow &m_mainWindow;
   QUrl m_url;
+#ifdef NETWORKING
   QNetworkAccessManager m_http;
   QNetworkReply *m_reply;
+#endif
   QByteArray *m_buffer;
 };
 
diff --git a/src/Logger/Logger.cpp b/src/Logger/Logger.cpp
index aac915f4..0199f6ba 100644
--- a/src/Logger/Logger.cpp
+++ b/src/Logger/Logger.cpp
@@ -22,7 +22,7 @@ void initializeLogging (const QString &name,
                         const QString &filename,
                         bool isDebug)
 {
-  LayoutAppender *appender = 0;
+  LayoutAppender *appender = nullptr;
 
   const size_t MAX_FILE_SIZE_BYTES = 6 * 1024 * 1024; // Size that should satisfy most email servers
   const unsigned int MAX_BACKUP_INDEX = 2;
@@ -36,7 +36,9 @@ void initializeLogging (const QString &name,
                                                                      APPEND_TO_PREVIOUS_FILE));
                                            
   PatternLayout *layout = new PatternLayout ();
-  layout->setConversionPattern ("%d{%H:%M:%S.%l} %-5p %c - %m%n");
+  // With date:    %d{%H:%M:%S.%l} %-5p %c - %m%n
+  // Without date:                 %-5p %c - %m%n
+  layout->setConversionPattern ("%-5p %c - %m%n");
   appender->setLayout (layout);
 
   mainCat = &Category::getRoot ();
diff --git a/src/Logger/LoggerUpload.cpp b/src/Logger/LoggerUpload.cpp
index c08f7e1b..37899294 100644
--- a/src/Logger/LoggerUpload.cpp
+++ b/src/Logger/LoggerUpload.cpp
@@ -8,7 +8,7 @@
 #include "LoggerUpload.h"
 #include "MainWindow.h"
 
-MainWindow *LoggerUpload::m_mainWindow = (MainWindow*) 0;
+MainWindow *LoggerUpload::m_mainWindow = static_cast<MainWindow*> (nullptr);
 
 LoggerUpload::LoggerUpload()
 {
@@ -44,7 +44,7 @@ void LoggerUpload::loggerOutput(const char *comment,
                                 int line,
                                 const char *context)
 {
-  if (m_mainWindow != 0) {
+  if (m_mainWindow != nullptr) {
     m_mainWindow->saveErrorReportFileAndExit(comment,
                                              file,
                                              line,
diff --git a/src/Matrix/Matrix.cpp b/src/Matrix/Matrix.cpp
index 52192a78..aeb6eb11 100644
--- a/src/Matrix/Matrix.cpp
+++ b/src/Matrix/Matrix.cpp
@@ -247,7 +247,7 @@ Matrix Matrix::inverseGaussianElimination (int significantDigits,
 
     // In pathological situations we have (rowFrom, colFirstWithNonzero) = 0 in which case the solution cannot be obtained
     // so we exit
-    if (working.get (rowFrom, colFirstWithNonZero) == 0) {
+    if (qAbs (working.get (rowFrom, colFirstWithNonZero)) <= 0) {
       matrixConsistent = MATRIX_INCONSISTENT;
       return inv;
     }
@@ -261,7 +261,7 @@ Matrix Matrix::inverseGaussianElimination (int significantDigits,
     // Apply the 'from' row to all the 'to' rows
     for (rowTo = rowFrom + 1; rowTo < rows (); rowTo++) {
 
-      if (working.get (rowTo, colFirstWithNonZero) != 0) {
+      if (qAbs (working.get (rowTo, colFirstWithNonZero)) > 0) {
 
         // We need to merge rowFrom and rowTo into rowTo
         double denominator = working.get (rowFrom, colFirstWithNonZero);
@@ -276,16 +276,16 @@ Matrix Matrix::inverseGaussianElimination (int significantDigits,
     int colFirstWithNonZero = rowFrom; // This is true since we should have 1s all down the diagonal at this point
 
     // Normalize the 'from' row with diagonal term set to 1. The first term should be like 0.9999 or 1.0001 but we want exactly one
-    MatrixConsistent matrixConsistent;
-    working.normalizeRow (rowFrom, colFirstWithNonZero, significantDigits, matrixConsistent);
-    if (matrixConsistent == MATRIX_INCONSISTENT) {
+    MatrixConsistent matrixConsistentIter;
+    working.normalizeRow (rowFrom, colFirstWithNonZero, significantDigits, matrixConsistentIter);
+    if (matrixConsistentIter == MATRIX_INCONSISTENT) {
       return inv;
     }
 
     // Apply the 'from' row to all the 'to' rows
     for (rowTo = rowFrom - 1; rowTo >= 0; rowTo--) {
 
-      if (working.get (rowTo, colFirstWithNonZero) != 0) {
+      if (qAbs (working.get (rowTo, colFirstWithNonZero)) > 0) {
 
         // We need to merge rowFro and rowTo into rowTo
         double denominator = working.get (rowFrom, colFirstWithNonZero);
@@ -315,7 +315,7 @@ unsigned int Matrix::leadingZeros (int row) const
 {
   unsigned int sum = 0;
   for (int col = 0; col < cols (); col++) {
-    if (get (row, col) != 0) {
+    if (qAbs (get (row, col)) > 0) {
       ++sum;
     }
   }
diff --git a/src/NonPdf/NonPdfCropping.cpp b/src/NonPdf/NonPdfCropping.cpp
index 56561677..26ce8e5e 100644
--- a/src/NonPdf/NonPdfCropping.cpp
+++ b/src/NonPdf/NonPdfCropping.cpp
@@ -9,6 +9,7 @@
 #include "NonPdfFrameHandle.h"
 #include <QGraphicsRectItem>
 #include <QGraphicsScene>
+#include <qmath.h>
 #include <QRect>
 #include "QtToString.h"
 #include "ViewPreview.h"
@@ -18,23 +19,35 @@ const int Z_HANDLE = 100; // Over box and background image
 
 NonPdfCropping::NonPdfCropping (QGraphicsScene &scene,
                                 ViewPreview &view) :
-  m_view (view)
+  m_view (view),
+  m_handleTL (nullptr),
+  m_handleTR (nullptr),
+  m_handleBR (nullptr),
+  m_handleBL (nullptr)
 {
   createWidgets (scene);
 }
 
+NonPdfCropping::~NonPdfCropping ()
+{
+  delete m_handleTL;
+  delete m_handleTR;
+  delete m_handleBR;
+  delete m_handleBL;
+}
+
 void NonPdfCropping::createWidgets(QGraphicsScene &scene)
 {
   const double MARGIN_PERCENT = 5.0;
   const int ZERO_WIDTH_IS_ALWAYS_VISIBLE = 0;
 
-  int marginHor = scene.width()  * MARGIN_PERCENT / 100.0;
-  int marginVer = scene.height() * MARGIN_PERCENT / 100.0;
+  int marginHor = qFloor (scene.width()  * MARGIN_PERCENT / 100.0);
+  int marginVer = qFloor (scene.height() * MARGIN_PERCENT / 100.0);
 
-  QRect box (scene.sceneRect().left() + marginHor,
-             scene.sceneRect().top()  + marginVer,
-             scene.sceneRect().width() - 2 * marginHor,
-             scene.sceneRect().height() - 2 * marginVer);
+  QRect box (qFloor (scene.sceneRect().left() + marginHor),
+             qFloor (scene.sceneRect().top()  + marginVer),
+             qFloor (scene.sceneRect().width() - 2 * marginHor),
+             qFloor (scene.sceneRect().height() - 2 * marginVer));
 
   m_handleTL = new NonPdfFrameHandle (scene, m_view, box.topLeft()    , NON_PDF_CROPPING_LEFT   | NON_PDF_CROPPING_TOP    , *this, Z_HANDLE);
   m_handleTR = new NonPdfFrameHandle (scene, m_view, box.topRight()   , NON_PDF_CROPPING_RIGHT  | NON_PDF_CROPPING_TOP    , *this, Z_HANDLE);
@@ -164,6 +177,6 @@ void NonPdfCropping::updateBox ()
 
 QSize NonPdfCropping::windowSize () const
 {
-  return QSize (m_view.scene()->width(),
-                m_view.scene()->height());
+  return QSize (qFloor (m_view.scene()->width()),
+                qFloor (m_view.scene()->height()));
 }
diff --git a/src/NonPdf/NonPdfCropping.h b/src/NonPdf/NonPdfCropping.h
index 1ca1e078..053ae235 100644
--- a/src/NonPdf/NonPdfCropping.h
+++ b/src/NonPdf/NonPdfCropping.h
@@ -25,6 +25,7 @@ public:
   /// Single constructor
   NonPdfCropping(QGraphicsScene &scene,
                  ViewPreview &view);
+  ~NonPdfCropping();
 
   /// Frame rectangle selected by user
   QRectF frameRect () const;
diff --git a/src/NonPdf/NonPdfFrameHandle.cpp b/src/NonPdf/NonPdfFrameHandle.cpp
index ef9bbb0f..fccbb30c 100644
--- a/src/NonPdf/NonPdfFrameHandle.cpp
+++ b/src/NonPdf/NonPdfFrameHandle.cpp
@@ -9,6 +9,7 @@
 #include <QBrush>
 #include <QGraphicsScene>
 #include <QGraphicsView>
+#include <qmath.h>
 #include <QStyleOptionGraphicsItem>
 
 const double HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE = 30;
@@ -92,8 +93,8 @@ QVariant NonPdfFrameHandle::itemChange (GraphicsItemChange change,
 
     // This sequence is from http://www.qtcentre.org/threads/47248-How-to-efficiently-get-position-of-a-QGraphicsItem-in-view-coordinates
     QRectF newRectItem (newPos,
-                        QSize (boundingRect().size().width(),
-                               boundingRect().size().height()));
+                        QSize (qFloor (boundingRect().size().width()),
+                               qFloor (boundingRect().size().height())));
     QPolygonF newRectScene = mapToScene (newRectItem);
     QPolygon newRectView = m_view.mapFromScene (newRectScene.boundingRect());
 
diff --git a/src/Pdf/Pdf.cpp b/src/Pdf/Pdf.cpp
index 71d2f997..8a8f228a 100644
--- a/src/Pdf/Pdf.cpp
+++ b/src/Pdf/Pdf.cpp
@@ -28,7 +28,7 @@ PdfReturn Pdf::load (const QString &fileName,
                      ImportCropping importCropping,
                      bool isErrorReportRegressionTest) const
 {
-  Document *document = 0;
+  Document *document = nullptr;
 
   ImportCroppingUtilPdf importCroppingUtil;
   bool cropping = importCroppingUtil.applyImportCropping (isErrorReportRegressionTest,
@@ -54,7 +54,7 @@ PdfReturn Pdf::load (const QString &fileName,
   QApplication::restoreOverrideCursor();
 
   delete document;
-  document = 0;
+  document = nullptr;
 
   return rtn;
 }
@@ -96,11 +96,11 @@ PdfReturn Pdf::loadWithoutCropping (const QString &fileName,
     // Try to read the file
     Document *document = Document::load (fileName);
 
-    if (document != 0) {
+    if (document != nullptr) {
       if (!document->isLocked ()) {
 
         Page *page = document->page (FIRST_PAGE_1_BASED - 1);
-        if (page != 0) {
+        if (page != nullptr) {
 
           image = page->renderToImage (resolution,
                                        resolution,
diff --git a/src/Pdf/PdfCropping.cpp b/src/Pdf/PdfCropping.cpp
index 764b3d06..e3f9e20b 100644
--- a/src/Pdf/PdfCropping.cpp
+++ b/src/Pdf/PdfCropping.cpp
@@ -9,6 +9,7 @@
 #include "PdfFrameHandle.h"
 #include <QGraphicsRectItem>
 #include <QGraphicsScene>
+#include <qmath.h>
 #include <QRect>
 #include "QtToString.h"
 #include "ViewPreview.h"
@@ -28,13 +29,13 @@ void PdfCropping::createWidgets(QGraphicsScene &scene)
   const double MARGIN_PERCENT = 5.0;
   const int ZERO_WIDTH_IS_ALWAYS_VISIBLE = 0;
 
-  int marginHor = scene.width()  * MARGIN_PERCENT / 100.0;
-  int marginVer = scene.height() * MARGIN_PERCENT / 100.0;
+  int marginHor = qFloor (scene.width()  * MARGIN_PERCENT / 100.0);
+  int marginVer = qFloor (scene.height() * MARGIN_PERCENT / 100.0);
 
-  QRect box (scene.sceneRect().left() + marginHor,
-             scene.sceneRect().top()  + marginVer,
-             scene.sceneRect().width() - 2 * marginHor,
-             scene.sceneRect().height() - 2 * marginVer);
+  QRect box (qFloor (scene.sceneRect().left() + marginHor),
+             qFloor (scene.sceneRect().top()  + marginVer),
+             qFloor (scene.sceneRect().width() - 2 * marginHor),
+             qFloor (scene.sceneRect().height() - 2 * marginVer));
 
   m_handleTL     = new PdfFrameHandle (scene, m_view, box.topLeft()    , PDF_CROPPING_LEFT   | PDF_CROPPING_TOP    , *this, Z_HANDLE);
   m_handleTR     = new PdfFrameHandle (scene, m_view, box.topRight()   , PDF_CROPPING_RIGHT  | PDF_CROPPING_TOP    , *this, Z_HANDLE);
@@ -164,6 +165,6 @@ void PdfCropping::updateBox ()
 
 QSize PdfCropping::windowSize () const
 {
-  return QSize (m_view.scene()->width(),
-                m_view.scene()->height());
+  return QSize (qFloor (m_view.scene()->width()),
+                qFloor (m_view.scene()->height()));
 }
diff --git a/src/Pdf/PdfFrameHandle.cpp b/src/Pdf/PdfFrameHandle.cpp
index 486cb042..666fb28a 100644
--- a/src/Pdf/PdfFrameHandle.cpp
+++ b/src/Pdf/PdfFrameHandle.cpp
@@ -9,6 +9,7 @@
 #include <QBrush>
 #include <QGraphicsScene>
 #include <QGraphicsView>
+#include <qmath.h>
 #include <QStyleOptionGraphicsItem>
 
 const double HANDLE_SIZE_AS_FRACTION_OF_WINDOW_SIZE = 30;
@@ -57,14 +58,14 @@ PdfFrameHandle::PdfFrameHandle (QGraphicsScene &scene,
 
   // Adjust positions of handles that are not at the top left so handles are laid out symmetrically
   QPointF pointPos = pointReference;
-  if ((orientationFlags && PdfCropping::PDF_CROPPING_LEFT) != 0) {
+  if ((orientationFlags & PdfCropping::PDF_CROPPING_LEFT) != 0) {
     pointPos.setX (pointPos.x() - handleSize.width() / 2.0);
-  } else if ((orientationFlags && PdfCropping::PDF_CROPPING_RIGHT) != 0) {
+  } else if ((orientationFlags & PdfCropping::PDF_CROPPING_RIGHT) != 0) {
     pointPos.setX (pointPos.x() + handleSize.width() / 2.0);
   }
-  if ((orientationFlags && PdfCropping::PDF_CROPPING_TOP) != 0) {
+  if ((orientationFlags & PdfCropping::PDF_CROPPING_TOP) != 0) {
     pointPos.setY (pointPos.y() - handleSize.height() / 2.0);
-  } else if ((orientationFlags && PdfCropping::PDF_CROPPING_BOTTOM) != 0) {
+  } else if ((orientationFlags & PdfCropping::PDF_CROPPING_BOTTOM) != 0) {
     pointPos.setY (pointPos.y() + handleSize.height() / 2.0);
   }
 
@@ -92,8 +93,8 @@ QVariant PdfFrameHandle::itemChange (GraphicsItemChange change,
 
     // This sequence is from http://www.qtcentre.org/threads/47248-How-to-efficiently-get-position-of-a-QGraphicsItem-in-view-coordinates
     QRectF newRectItem (newPos,
-                        QSize (boundingRect().size().width(),
-                               boundingRect().size().height()));
+                        QSize (qFloor (boundingRect().size().width()),
+                               qFloor (boundingRect().size().height())));
     QPolygonF newRectScene = mapToScene (newRectItem);
     QPolygon newRectView = m_view.mapFromScene (newRectScene.boundingRect());
 
diff --git a/src/Point/Point.cpp b/src/Point/Point.cpp
index 6884a7f5..ed2b3cf3 100644
--- a/src/Point/Point.cpp
+++ b/src/Point/Point.cpp
@@ -316,7 +316,7 @@ void Point::loadXml(QXmlStreamReader &reader)
     }
 
     m_identifier = fixUnderscores (attributes.value(DOCUMENT_SERIALIZE_POINT_IDENTIFIER).toString());
-    m_identifierIndex = attributes.value(DOCUMENT_SERIALIZE_POINT_IDENTIFIER_INDEX).toInt();
+    m_identifierIndex = attributes.value(DOCUMENT_SERIALIZE_POINT_IDENTIFIER_INDEX).toUInt();
     m_isAxisPoint = (isAxisPoint == DOCUMENT_SERIALIZE_BOOL_TRUE);
     m_hasPosGraph = false;
     m_posGraph.setX (MISSING_POSGRAPH_VALUE);
diff --git a/src/Point/PointMatchAlgorithm.cpp b/src/Point/PointMatchAlgorithm.cpp
index 3033a59f..94a27ef2 100644
--- a/src/Point/PointMatchAlgorithm.cpp
+++ b/src/Point/PointMatchAlgorithm.cpp
@@ -37,10 +37,10 @@ void PointMatchAlgorithm::allocateMemory(double** array,
 {
   LOG4CPP_INFO_S ((*mainCat)) << "PointMatchAlgorithm::allocateMemory";
 
-  *array = new double [width * height];
+  *array = new double [unsigned (width * height)];
   ENGAUGE_CHECK_PTR(*array);
 
-  *arrayPrime = new fftw_complex [width * height];
+  *arrayPrime = new fftw_complex [unsigned (width * height)];
   ENGAUGE_CHECK_PTR(*arrayPrime);
 }
 
@@ -146,7 +146,7 @@ void PointMatchAlgorithm::computeConvolution(fftw_complex* imagePrime,
 
   // The convolution pattern is shifted by (sampleXExtent, sampleYExtent). So the downstream code
   // does not have to repeatedly compensate for that shift, we unshift it here
-  double *temp = new double [width * height];
+  double *temp = new double [unsigned (width * height)];
   ENGAUGE_CHECK_PTR(temp);
 
   for (int i = 0; i < width; i++) {
@@ -332,7 +332,7 @@ void PointMatchAlgorithm::loadImage(const QImage &imageProcessed,
                                  width,
                                  height,
                                  pointsExisting,
-                                 modelPointMatch.maxPointSize());
+                                 qFloor (modelPointMatch.maxPointSize()));
 
   // Forward transform the image
   fftw_plan pImage = fftw_plan_dft_r2c_2d(width,
@@ -480,10 +480,10 @@ void PointMatchAlgorithm::populateSampleArray(const QList<PointMatchPixel> &samp
   bool first = true;
   unsigned int i;
   int xMin = width, yMin = height, xMax = 0, yMax = 0;
-  for (i = 0; i < (unsigned int) samplePointPixels.size(); i++) {
+  for (i = 0; i < static_cast<unsigned int> (samplePointPixels.size()); i++) {
 
-    int x = (samplePointPixels.at(i)).xOffset();
-    int y = (samplePointPixels.at(i)).yOffset();
+    int x = samplePointPixels.at(signed (i)).xOffset();
+    int y = samplePointPixels.at(signed (i)).yOffset();
     if (first || (x < xMin))
       xMin = x;
     if (first || (x > xMax))
@@ -516,15 +516,15 @@ void PointMatchAlgorithm::populateSampleArray(const QList<PointMatchPixel> &samp
   // affect the center of mass computed only from on pixels
   double xSumOn = 0, ySumOn = 0, countOn = 0;
 
-  for (i = 0; i < (unsigned int) samplePointPixels.size(); i++) {
+  for (i = 0; i < static_cast<unsigned int> (samplePointPixels.size()); i++) {
 
     // Place, quite arbitrarily, the sample image up against the top left corner
-    x = (samplePointPixels.at(i)).xOffset() - xMin;
-    y = (samplePointPixels.at(i)).yOffset() - yMin;
+    x = (samplePointPixels.at(signed (i))).xOffset() - xMin;
+    y = (samplePointPixels.at(signed (i))).yOffset() - yMin;
     ENGAUGE_ASSERT((0 < x) && (x < width));
     ENGAUGE_ASSERT((0 < y) && (y < height));
 
-    bool pixelIsOn = samplePointPixels.at(i).pixelIsOn();
+    bool pixelIsOn = samplePointPixels.at(signed (i)).pixelIsOn();
 
     (*sample) [FOLD2DINDEX(x, y, height)] = (pixelIsOn ? PIXEL_ON : PIXEL_OFF);
 
@@ -537,8 +537,8 @@ void PointMatchAlgorithm::populateSampleArray(const QList<PointMatchPixel> &samp
 
   // Compute location of center of mass, which will represent the center of the point
   countOn = qMax (1.0, countOn);
-  *sampleXCenter = (int) (0.5 + xSumOn / countOn);
-  *sampleYCenter = (int) (0.5 + ySumOn / countOn);
+  *sampleXCenter = qFloor (0.5 + xSumOn / countOn);
+  *sampleYCenter = qFloor (0.5 + ySumOn / countOn);
 
   // Dimensions of portion of array actually used by sample (rest is empty)
   *sampleXExtent = xMax - xMin + 1;
@@ -571,8 +571,8 @@ void PointMatchAlgorithm::removePixelsNearExistingPoints(double* image,
 
   for (int i = 0; i < pointsExisting.size(); i++) {
 
-    int xPoint = pointsExisting.at(i).posScreen().x();
-    int yPoint = pointsExisting.at(i).posScreen().y();
+    int xPoint = qFloor (pointsExisting.at(signed (i)).posScreen().x());
+    int yPoint = qFloor (pointsExisting.at(signed (i)).posScreen().y());
 
     // Loop through rows of pixels
     int yMin = yPoint - pointSeparation;
@@ -588,7 +588,7 @@ void PointMatchAlgorithm::removePixelsNearExistingPoints(double* image,
       int radical = pointSeparation * pointSeparation - (y - yPoint) * (y - yPoint);
       if (0 < radical) {
 
-        int xMin = (int) (xPoint - qSqrt((double) radical));
+        int xMin = qFloor (xPoint - qSqrt(double (radical)));
         if (xMin < 0)
           xMin = 0;
         int xMax = xPoint + (xPoint - xMin);
diff --git a/src/Point/PointShape.cpp b/src/Point/PointShape.cpp
index 710e614e..3cb6ba0c 100644
--- a/src/Point/PointShape.cpp
+++ b/src/Point/PointShape.cpp
@@ -9,26 +9,41 @@
 
 QString pointShapeToString (PointShape pointShape)
 {
+  QString rtn;
+
   switch (pointShape) {
     case POINT_SHAPE_CIRCLE:
-      return QObject::tr ("Circle");
+      rtn = QObject::tr ("Circle");
+      break;
 
     case POINT_SHAPE_CROSS:
-      return QObject::tr ("Cross");
+      rtn = QObject::tr ("Cross");
+      break;
 
     case POINT_SHAPE_DIAMOND:
-      return QObject::tr ("Diamond");
+      rtn = QObject::tr ("Diamond");
+      break;
+
+    case POINT_SHAPE_HOURGLASS:
+      rtn = QObject::tr ("Hourglass");
+      break;      
 
     case POINT_SHAPE_SQUARE:
-      return QObject::tr ("Square");
+      rtn = QObject::tr ("Square");
+      break;
 
     case POINT_SHAPE_TRIANGLE:
-      return QObject::tr ("Triangle");
+      rtn = QObject::tr ("Triangle");
+      break;
 
-    case POINT_SHAPE_X:
-      return QObject::tr ("X");
+    case POINT_SHAPE_TRIANGLE2:
+      rtn = QObject::tr ("Triangle2");
+      break;      
 
-    default:
-      return QObject::tr ("Unknown");
+    case POINT_SHAPE_X:
+      rtn = QObject::tr ("X");
+      break;
   }
+
+  return rtn;
 }
diff --git a/src/Point/PointShape.h b/src/Point/PointShape.h
index ac6080c8..e60f4eec 100644
--- a/src/Point/PointShape.h
+++ b/src/Point/PointShape.h
@@ -15,7 +15,9 @@ enum PointShape {
   POINT_SHAPE_DIAMOND,
   POINT_SHAPE_SQUARE,
   POINT_SHAPE_TRIANGLE,
-  POINT_SHAPE_X
+  POINT_SHAPE_X,
+  POINT_SHAPE_HOURGLASS,
+  POINT_SHAPE_TRIANGLE2
 };
 
 extern QString pointShapeToString (PointShape pointShape);
diff --git a/src/Point/PointStyle.cpp b/src/Point/PointStyle.cpp
index a79fa841..ec96f613 100644
--- a/src/Point/PointStyle.cpp
+++ b/src/Point/PointStyle.cpp
@@ -26,7 +26,12 @@ const PointShape DEFAULT_POINT_SHAPE_AXIS = POINT_SHAPE_CROSS;
 const double PI = 3.1415926535;
 const double TWO_PI = 2.0 * PI;
 
-PointStyle::PointStyle ()
+PointStyle::PointStyle () :
+  // Defaults that prevent address sanitizer warnings. Overwritten immediately
+  m_shape (DEFAULT_POINT_SHAPE_AXIS),
+  m_radius (DEFAULT_POINT_RADIUS),
+  m_lineWidth (DEFAULT_POINT_LINE_WIDTH),
+  m_paletteColor (DEFAULT_POINT_COLOR_GRAPH)
 {
 }
 
@@ -64,14 +69,14 @@ PointStyle PointStyle::defaultAxesCurve ()
   // Get settings if available, otherwise use defaults
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (SETTINGS_GROUP_CURVE_AXES);
-  PointShape shape = (PointShape) settings.value (SETTINGS_CURVE_POINT_SHAPE,
-                                                  DEFAULT_POINT_SHAPE_AXIS).toInt();
-  int radius = settings.value (SETTINGS_CURVE_POINT_RADIUS,
-                               DEFAULT_POINT_RADIUS).toInt();
+  PointShape shape = static_cast<PointShape> (settings.value (SETTINGS_CURVE_POINT_SHAPE,
+                                                              DEFAULT_POINT_SHAPE_AXIS).toInt());
+  unsigned int radius = settings.value (SETTINGS_CURVE_POINT_RADIUS,
+                                        DEFAULT_POINT_RADIUS).toUInt();
   int pointLineWidth = settings.value (SETTINGS_CURVE_POINT_LINE_WIDTH,
                                        DEFAULT_POINT_LINE_WIDTH).toInt();
-  ColorPalette pointColor = (ColorPalette) settings.value (SETTINGS_CURVE_POINT_COLOR,
-                                                           DEFAULT_POINT_COLOR_AXES).toInt();
+  ColorPalette pointColor = static_cast<ColorPalette> (settings.value (SETTINGS_CURVE_POINT_COLOR,
+                                                                       DEFAULT_POINT_COLOR_AXES).toInt());
   settings.endGroup ();
 
   return PointStyle (shape,
@@ -97,12 +102,12 @@ PointStyle PointStyle::defaultGraphCurve (int index)
   // Get settings if available, otherwise use defaults
   QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
   settings.beginGroup (groupName);
-  int radius = settings.value (SETTINGS_CURVE_POINT_RADIUS,
-                               DEFAULT_POINT_RADIUS).toInt();
+  unsigned int radius = settings.value (SETTINGS_CURVE_POINT_RADIUS,
+                                        DEFAULT_POINT_RADIUS).toUInt();
   int pointLineWidth = settings.value (SETTINGS_CURVE_POINT_LINE_WIDTH,
                                        DEFAULT_POINT_LINE_WIDTH).toInt();
-  ColorPalette pointColor = (ColorPalette) settings.value (SETTINGS_CURVE_POINT_COLOR,
-                                                           DEFAULT_POINT_COLOR_GRAPH).toInt();
+  ColorPalette pointColor = static_cast<ColorPalette> (settings.value (SETTINGS_CURVE_POINT_COLOR,
+                                                                       DEFAULT_POINT_COLOR_GRAPH).toInt());
   settings.endGroup ();
 
   return PointStyle (shape,
@@ -132,10 +137,10 @@ void PointStyle::loadXml(QXmlStreamReader &reader)
       attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_STYLE_COLOR) &&
       attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_STYLE_SHAPE)) {
 
-    setRadius (attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_RADIUS).toInt());
+    setRadius (attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_RADIUS).toUInt());
     setLineWidth (attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_LINE_WIDTH).toInt());
-    setPaletteColor ((ColorPalette) attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_COLOR).toInt());
-    setShape ((PointShape) attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_SHAPE).toInt());
+    setPaletteColor (static_cast<ColorPalette> (attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_COLOR).toInt()));
+    setShape (static_cast<PointShape> (attributes.value(DOCUMENT_SERIALIZE_POINT_STYLE_SHAPE).toInt()));
 
     // Read until end of this subtree
     while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
@@ -161,9 +166,9 @@ QPolygonF PointStyle::polygon () const
 
     case POINT_SHAPE_CIRCLE:
       {
-        int xyWidth = m_radius;
+        int xyWidth = signed (m_radius);
         for (int i = 0; i <= NUM_XY; i++) {
-          double angle = TWO_PI * (double) i / (double) NUM_XY;
+          double angle = TWO_PI * double (i) / double (NUM_XY);
           double x = xyWidth * cos (angle);
           double y = xyWidth * sin (angle);
           points.append (QPointF (x, y));
@@ -173,7 +178,7 @@ QPolygonF PointStyle::polygon () const
 
     case POINT_SHAPE_CROSS:
       {
-        int xyWidth = m_radius;
+        int xyWidth = signed (m_radius);
 
         points.append (QPointF (-1 * xyWidth, 0));
         points.append (QPointF (xyWidth, 0));
@@ -186,7 +191,7 @@ QPolygonF PointStyle::polygon () const
 
     case POINT_SHAPE_DIAMOND:
       {
-        int xyWidth = m_radius;
+        int xyWidth = signed (m_radius);
 
         points.append (QPointF (0, -1 * xyWidth));
         points.append (QPointF (-1 * xyWidth, 0));
@@ -195,9 +200,20 @@ QPolygonF PointStyle::polygon () const
       }
       break;
 
+    case POINT_SHAPE_HOURGLASS:
+      {
+        int xyWidth = signed (m_radius);
+
+        points.append (QPointF (-1 * xyWidth, -1 * xyWidth));
+        points.append (QPointF (xyWidth, -1 * xyWidth));
+        points.append (QPointF (-1 * xyWidth, xyWidth));
+        points.append (QPointF (xyWidth, xyWidth));        
+      }
+      break;      
+
     case POINT_SHAPE_SQUARE:
       {
-        int xyWidth = m_radius;
+        int xyWidth = signed (m_radius);
 
         points.append (QPointF (-1 * xyWidth, -1 * xyWidth));
         points.append (QPointF (-1 * xyWidth, xyWidth));
@@ -208,7 +224,7 @@ QPolygonF PointStyle::polygon () const
 
     case POINT_SHAPE_TRIANGLE:
       {
-        int xyWidth = m_radius;
+        int xyWidth = signed (m_radius);
 
         points.append (QPointF (-1 * xyWidth, -1 * xyWidth));
         points.append (QPointF (0, xyWidth));
@@ -216,9 +232,19 @@ QPolygonF PointStyle::polygon () const
       }
       break;
 
+    case POINT_SHAPE_TRIANGLE2:
+      {
+        int xyWidth = signed (m_radius);
+
+        points.append (QPointF (-1 * xyWidth, xyWidth));
+        points.append (QPointF (0, -1 * xyWidth));
+        points.append (QPointF (xyWidth, xyWidth));
+      }
+      break;      
+
     case POINT_SHAPE_X:
       {
-        int xyWidth = m_radius * qSqrt (0.5);
+        int xyWidth = qFloor (m_radius * qSqrt (0.5));
 
         points.append (QPointF (-1 * xyWidth, -1 * xyWidth));
         points.append (QPointF (xyWidth, xyWidth));
@@ -228,9 +254,6 @@ QPolygonF PointStyle::polygon () const
         points.append (QPointF (0, 0));
       }
       break;
-
-    default:
-      ENGAUGE_ASSERT (false);
   }
 
   QPolygonF polygon (points);
@@ -250,7 +273,7 @@ void PointStyle::printStream(QString indentation,
   str << indentation << "color=" << colorPaletteToString (m_paletteColor) << "\n";
 }
 
-int PointStyle::radius () const
+unsigned int PointStyle::radius () const
 {
   return m_radius;
 }
@@ -279,7 +302,7 @@ void PointStyle::setPaletteColor (ColorPalette paletteColor)
   m_paletteColor = paletteColor;
 }
 
-void PointStyle::setRadius (int radius)
+void PointStyle::setRadius (unsigned int radius)
 {
   m_radius = radius;
 }
diff --git a/src/Point/PointStyle.h b/src/Point/PointStyle.h
index 480f8a1d..bd87645d 100644
--- a/src/Point/PointStyle.h
+++ b/src/Point/PointStyle.h
@@ -61,7 +61,7 @@ public:
                     QTextStream &str) const;
 
   /// Radius of point. For a circle this is all that is needed to draw a circle. For a polygon, the radius determines the size of the polygon
-  int radius () const;
+  unsigned int radius () const;
 
   /// Serialize to stream
   void saveXml(QXmlStreamWriter &writer) const;
@@ -73,7 +73,7 @@ public:
   void setPaletteColor (ColorPalette paletteColor);
 
   /// Set method for point radius.
-  void setRadius (int radius);
+  void setRadius (unsigned int radius);
 
   /// Set method for point shape.
   void setShape (PointShape shape);
diff --git a/src/Segment/Segment.cpp b/src/Segment/Segment.cpp
index 35617b09..ce64ed5b 100644
--- a/src/Segment/Segment.cpp
+++ b/src/Segment/Segment.cpp
@@ -27,15 +27,10 @@ Segment::Segment(QGraphicsScene &scene,
   m_length (0),
   m_isGnuplot (isGnuplot)
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "Segment::Segment"
-                              << " address=0x" << hex << (quintptr) this;
 }
 
 Segment::~Segment()
 {
-  LOG4CPP_INFO_S ((*mainCat)) << "Segment::~Segment"
-                              << " address=0x" << hex << (quintptr) this;
-
   QList<SegmentLine*>::iterator itr;
   for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
 
@@ -54,7 +49,7 @@ void Segment::appendColumn(int x,
   int yNew = y;
 
   LOG4CPP_DEBUG_S ((*mainCat)) << "Segment::appendColumn"
-                               << " segment=0x" << std::hex << (quintptr) this << std::dec
+                               << " segment=0x" << std::hex << static_cast<void*> (this) << std::dec
                                << " adding ("
                                << xOld << "," << yOld << ") to ("
                                << xNew << "," << yNew << ")";
@@ -85,10 +80,10 @@ void Segment::createAcceptablePoint(bool *pFirst,
                                     double x,
                                     double y)
 {
-  int iOld = (int) (*xPrev + 0.5);
-  int jOld = (int) (*yPrev + 0.5);
-  int i = (int) (x + 0.5);
-  int j = (int) (y + 0.5);
+  int iOld = qFloor (*xPrev + 0.5);
+  int jOld = qFloor (*yPrev + 0.5);
+  int i = qFloor (x + 0.5);
+  int j = qFloor (y + 0.5);
 
   if (*pFirst || (iOld != i) || (jOld != j)) {
     *xPrev = x;
@@ -135,10 +130,10 @@ void Segment::dumpToGnuplot (QTextStream &strDump,
       SegmentLine *line = *itr;
       ENGAUGE_CHECK_PTR (line);
 
-      int x1 = line->line().x1();
-      int y1 = line->line().y1();
-      int x2 = line->line().x2();
-      int y2 = line->line().y2();
+      int x1 = qFloor (line->line().x1());
+      int y1 = qFloor (line->line().y1());
+      int x2 = qFloor (line->line().x2());
+      int y2 = qFloor (line->line().y2());
 
       rows = qMax (rows, y1 + 1);
       rows = qMax (rows, y2 + 1);
@@ -148,10 +143,10 @@ void Segment::dumpToGnuplot (QTextStream &strDump,
 
     // Horizontal and vertical width is computed so merged line mostly fills the plot window,
     // and (xInt,yInt) is at the center
-    int halfWidthX = 1.5 * qMax (qAbs (lineOld->line().dx()),
-                                 qAbs (lineNew->line().dx()));
-    int halfWidthY = 1.5 * qMax (qAbs (lineOld->line().dy()),
-                                 qAbs (lineNew->line().dy()));
+    int halfWidthX = qFloor (1.5 * qMax (qAbs (lineOld->line().dx()),
+                                         qAbs (lineNew->line().dx())));
+    int halfWidthY = qFloor (1.5 * qMax (qAbs (lineOld->line().dy()),
+                                         qAbs (lineNew->line().dy())));
 
     // Zoom in so changes are easier to see
     strDump << "set xrange [" << (xInt - halfWidthX - 1) << ":" << (xInt + halfWidthX + 1) << "]\n";
@@ -182,10 +177,10 @@ void Segment::dumpToGnuplot (QTextStream &strDump,
     for (int index = 0; index < m_lines.count(); index++) {
 
       SegmentLine *line = m_lines.at (index);
-      int x1 = line->line().x1();
-      int y1 = line->line().y1();
-      int x2 = line->line().x2();
-      int y2 = line->line().y2();
+      int x1 = qFloor (line->line().x1());
+      int y1 = qFloor (line->line().y1());
+      int x2 = qFloor (line->line().x2());
+      int y2 = qFloor (line->line().y2());
 
       if (index % 2 == 0) {
         strEven << x1 << " " << y1 << "\n";
@@ -241,11 +236,11 @@ QList<QPoint> Segment::fillPointsFillingCorners(const DocumentModelSegments &mod
       SegmentLine *line = *itr;
 
       ENGAUGE_CHECK_PTR(line);
-      xNext = (double) line->line().x2();
-      yNext = (double) line->line().y2();
+      xNext = double (line->line().x2());
+      yNext = double (line->line().y2());
 
-      double xStart = (double) line->line().x1();
-      double yStart = (double) line->line().y1();
+      double xStart = double (line->line().x1());
+      double yStart = double (line->line().y1());
       if (isCorner (yPrev, yStart, yNext)) {
 
         // Insert a corner point
@@ -344,8 +339,8 @@ QList<QPoint> Segment::fillPointsWithoutFillingCorners(const DocumentModelSegmen
       SegmentLine *line = *itr;
 
       ENGAUGE_CHECK_PTR(line);
-      xNext = (double) line->line().x2();
-      yNext = (double) line->line().y2();
+      xNext = double (line->line().x2());
+      yNext = double (line->line().y2());
 
       // Distance formula
       double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
@@ -410,7 +405,12 @@ bool Segment::pointsAreCloseToLine(double xLeft,
 {
   QList<QPoint>::iterator itr;
   for (itr = removedPoints.begin(); itr != removedPoints.end(); ++itr) {
-    if (!pointIsCloseToLine(xLeft, yLeft, (double) (*itr).x(), (double) (*itr).y(), xRight, yRight)) {
+    if (!pointIsCloseToLine(xLeft,
+                            yLeft,
+                            double ((*itr).x()),
+                            double ((*itr).y()),
+                            xRight,
+                            yRight)) {
       return false;
     }
   }
@@ -422,8 +422,8 @@ void Segment::removeUnneededLines (int *foldedLines)
 {
   LOG4CPP_INFO_S ((*mainCat)) << "Segment::removeUnneededLines";
 
-  QFile *fileDump = 0;
-  QTextStream *strDump = 0;
+  QFile *fileDump = nullptr;
+  QTextStream *strDump = nullptr;
   if (m_isGnuplot) {
 
     QString filename ("segment.gnuplot");
@@ -440,7 +440,7 @@ void Segment::removeUnneededLines (int *foldedLines)
   // into optimizing away all but one point at the origin and another point at the far right.
   // From this we see that we cannot simply throw away points that were optimized away since they
   // are needed later to see if we have diverged from the curve
-  SegmentLine *linePrevious = 0; // Previous line which corresponds to itrPrevious
+  SegmentLine *linePrevious = nullptr; // Previous line which corresponds to itrPrevious
   QList<SegmentLine*>::iterator itr, itrPrevious;
   QList<QPoint> removedPoints;
   for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
@@ -448,7 +448,7 @@ void Segment::removeUnneededLines (int *foldedLines)
     SegmentLine *line = *itr;
     ENGAUGE_CHECK_PTR(line);
 
-    if (linePrevious != 0) {
+    if (linePrevious != nullptr) {
 
       double xLeft = linePrevious->line().x1();
       double yLeft = linePrevious->line().y1();
@@ -469,8 +469,8 @@ void Segment::removeUnneededLines (int *foldedLines)
 
             // Dump
             dumpToGnuplot (*strDump,
-                           xInt,
-                           yInt,
+                           qFloor (xInt),
+                           qFloor (yInt),
                            linePrevious,
                            line);
           }
@@ -479,7 +479,7 @@ void Segment::removeUnneededLines (int *foldedLines)
           ++(*foldedLines);
 
           LOG4CPP_DEBUG_S ((*mainCat)) << "Segment::removeUnneededLines"
-                                       << " segment=0x" << std::hex << (quintptr) this << std::dec
+                                       << " segment=0x" << std::hex << static_cast<void*> (this) << std::dec
                                        << " removing ("
                                        << linePrevious->line().x1() << "," << linePrevious->line().y1() << ") to ("
                                        << linePrevious->line().x2() << "," << linePrevious->line().y2() << ") "
@@ -489,7 +489,8 @@ void Segment::removeUnneededLines (int *foldedLines)
                                        << xLeft << "," << yLeft << ") to ("
                                        << xRight << "," << yRight << ")";
 
-          removedPoints.append(QPoint((int) xInt, (int) yInt));
+          removedPoints.append(QPoint(qFloor (xInt),
+                                      qFloor (yInt)));
           m_lines.erase (itrPrevious);
           delete linePrevious;
 
@@ -513,7 +514,7 @@ void Segment::removeUnneededLines (int *foldedLines)
     }
   }
 
-  if (strDump != 0) {
+  if (strDump != nullptr) {
 
     // Final gnuplot processing
     *strDump << "set terminal x11 persist\n";
diff --git a/src/Segment/SegmentFactory.cpp b/src/Segment/SegmentFactory.cpp
index 29f8ca46..deedc521 100644
--- a/src/Segment/SegmentFactory.cpp
+++ b/src/Segment/SegmentFactory.cpp
@@ -10,9 +10,11 @@
 #include "Logger.h"
 #include <QApplication>
 #include <QGraphicsScene>
+#include <qmath.h>
 #include <QProgressDialog>
 #include "Segment.h"
 #include "SegmentFactory.h"
+#include <vector>
 
 using namespace std;
 
@@ -54,13 +56,13 @@ Segment *SegmentFactory::adjacentSegment(SegmentVector &lastSegment,
     if ((0 <= y) && (y < height)) {
 
       ENGAUGE_ASSERT (y < height);
-      if (lastSegment [y]) {
-        return lastSegment [y];
+      if (lastSegment [unsigned (y)]) {
+        return lastSegment [unsigned (y)];
       }
     }
   }
 
-  return 0;
+  return nullptr;
 }
 
 int SegmentFactory::adjacentSegments(SegmentVector &lastSegment,
@@ -75,11 +77,11 @@ int SegmentFactory::adjacentSegments(SegmentVector &lastSegment,
     if ((0 <= y) && (y < height)) {
 
       ENGAUGE_ASSERT (y < height);
-      if (!inSegment && lastSegment [y]) {
+      if (!inSegment && lastSegment [unsigned (y)]) {
 
        inSegment = true;
         ++adjacentSegments;
-      } else if (inSegment && !lastSegment [y]) {
+      } else if (inSegment && !lastSegment [unsigned (y)]) {
         inSegment = false;
       }
     }
@@ -141,7 +143,7 @@ void SegmentFactory::finishRun(bool *lastBool,
 
     // This is the start of a new segment
     seg = new Segment(m_scene,
-                      (int) (0.5 + (yStart + yStop) / 2.0),
+                      qFloor (0.5 + (yStart + yStop) / 2.0),
                       m_isGnuplot);
     ENGAUGE_CHECK_PTR (seg);
 
@@ -152,13 +154,13 @@ void SegmentFactory::finishRun(bool *lastBool,
 
     ++(*madeLines);
     ENGAUGE_CHECK_PTR(seg);
-    seg->appendColumn(x, (int) (0.5 + (yStart + yStop) / 2.0), modelSegments);
+    seg->appendColumn(x, qFloor (0.5 + (yStart + yStop) / 2.0), modelSegments);
   }
 
   for (int y = yStart; y <= yStop; y++) {
 
     ENGAUGE_ASSERT (y < height);
-    currSegment [y] = seg;
+    currSegment [unsigned (y)] = seg;
   }
 }
 
@@ -180,7 +182,7 @@ void SegmentFactory::loadSegment (SegmentVector &columnSegment,
                                   int height)
 {
   for (int y = 0; y < height; y++) {
-    columnSegment [y] = 0;
+    columnSegment [unsigned (y)] = nullptr;
   }
 }
 
@@ -211,7 +213,7 @@ void SegmentFactory::makeSegments (const QImage &imageFiltered,
   int width = imageFiltered.width();
   int height = imageFiltered.height();
 
-  QProgressDialog* dlg = 0;
+  QProgressDialog* dlg = nullptr;
   if (useDlg)
   {
 
@@ -220,14 +222,14 @@ void SegmentFactory::makeSegments (const QImage &imageFiltered,
     dlg->show();
   }
 
-  bool* lastBool = new bool [height];
+  bool* lastBool = new bool [unsigned (height)];
   ENGAUGE_CHECK_PTR(lastBool);
-  bool* currBool = new bool [height];
+  bool* currBool = new bool [unsigned (height)];
   ENGAUGE_CHECK_PTR(currBool);
-  bool* nextBool = new bool [height];
+  bool* nextBool = new bool [unsigned (height)];
   ENGAUGE_CHECK_PTR(nextBool);
-  SegmentVector lastSegment (height);
-  SegmentVector currSegment (height);
+  SegmentVector lastSegment (static_cast<unsigned long> (height));
+  SegmentVector currSegment (static_cast<unsigned long> (height));
 
   ColorFilter filter;
   loadBool(filter, lastBool, imageFiltered, -1);
@@ -372,20 +374,20 @@ void SegmentFactory::removeUnneededLines(SegmentVector &lastSegment,
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentFactory::removeUnneededLines";
 
-  Segment *segLast = 0;
+  Segment *segLast = nullptr;
   for (int yLast = 0; yLast < height; yLast++) {
 
     ENGAUGE_ASSERT (yLast < height);
-    if (lastSegment [yLast] && (lastSegment [yLast] != segLast)) {
+    if (lastSegment [unsigned (yLast)] && (lastSegment [unsigned (yLast)] != segLast)) {
 
-      segLast = lastSegment [yLast];
+      segLast = lastSegment [unsigned (yLast)];
 
       // If the segment is found in the current column then it is still in work so postpone processing
       bool found = false;
       for (int yCur = 0; yCur < height; yCur++) {
 
         ENGAUGE_ASSERT (yCur < height);
-        if (segLast == currSegment [yCur]) {
+        if (segLast == currSegment [unsigned (yCur)]) {
           found = true;
           break;
         }
@@ -401,7 +403,7 @@ void SegmentFactory::removeUnneededLines(SegmentVector &lastSegment,
           // covers more than one pixel
           *shortLines += segLast->lineCount();
           delete segLast;
-          lastSegment [yLast] = 0;
+          lastSegment [unsigned (yLast)] = nullptr;
 
         } else {
 
@@ -431,7 +433,7 @@ void SegmentFactory::scrollSegment(SegmentVector &left,
                                    int height)
 {
   for (int y = 0; y < height; y++) {
-    left [y] = right [y];
+    left [static_cast<unsigned long> (y)] = right [static_cast<unsigned long> (y)];
   }
 }
 
diff --git a/src/Segment/SegmentLine.cpp b/src/Segment/SegmentLine.cpp
index 4b0d3326..db221c9e 100644
--- a/src/Segment/SegmentLine.cpp
+++ b/src/Segment/SegmentLine.cpp
@@ -21,7 +21,7 @@ SegmentLine::SegmentLine(QGraphicsScene  &scene,
   m_segment (segment)
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentLine::SegmentLine"
-                               << " address=0x" << std::hex << (quintptr) this;
+                               << " address=0x" << std::hex << static_cast<void *> (this);
 
   setData (DATA_KEY_GRAPHICS_ITEM_TYPE, QVariant (GRAPHICS_ITEM_TYPE_SEGMENT));
 
@@ -40,7 +40,7 @@ SegmentLine::SegmentLine(QGraphicsScene  &scene,
 SegmentLine::~SegmentLine ()
 {
   LOG4CPP_DEBUG_S ((*mainCat)) << "SegmentLine::~SegmentLine"
-                               << " address=0x" << std::hex << (quintptr) this;
+                               << " address=0x" << std::hex << static_cast<void *> (this);
 }
 
 void SegmentLine::hoverEnterEvent(QGraphicsSceneHoverEvent * /* event */)
diff --git a/src/Settings/Settings.cpp b/src/Settings/Settings.cpp
index ebfbb31b..bd53b467 100644
--- a/src/Settings/Settings.cpp
+++ b/src/Settings/Settings.cpp
@@ -28,8 +28,11 @@ const QString SETTINGS_GROUP_MAIN_WINDOW ("MainWindow"); // Capitalize both M an
 const QString SETTINGS_HELP_POS ("helpPos");
 const QString SETTINGS_HELP_SIZE ("helpSize");
 const QString SETTINGS_HIGHLIGHT_OPACITY ("highlightOpacity");
+const QString SETTINGS_IMAGE_REPLACE_RENAMES_DOCUMENT ("imageReplaceRenamesDocument");
 const QString SETTINGS_LOCALE_COUNTRY ("country");
 const QString SETTINGS_LOCALE_LANGUAGE ("language");
+const QString SETTINGS_MAIN_DIRECTORY_EXPORT_SAVE ("exportSave");
+const QString SETTINGS_MAIN_DIRECTORY_IMPORT_LOAD ("importLoad");
 const QString SETTINGS_MAIN_TITLE_BAR_FORMAT ("titleBarFormat");
 const QString SETTINGS_MAXIMUM_GRID_LINES ("maximumGridLines");
 const QString SETTINGS_POS ("pos");
@@ -70,10 +73,12 @@ const QString SETTINGS_GROUP_IMPORT ("Import");
 const QString SETTINGS_IMPORT_CROPPING ("Cropping");
 const QString SETTINGS_IMPORT_PDF_RESOLUTION ("PdfResolution");
 
-// Export group
+// Export group. Any new entries here should probably be added to DlgSettingsExportFormat::slotSaveDefault()
+// and DocumentModelExportFormat::DocumentModelExportFormat()
 const QString SETTINGS_EXPORT_CURVE_NAMES_NOT_EXPORTED ("curveNamesNotExported");
 const QString SETTINGS_EXPORT_DELIMITER ("delimiter");
 const QString SETTINGS_EXPORT_DELIMITER_OVERRIDE_CSV_TSV ("overrideCsvTsv");
+const QString SETTINGS_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS ("extrapolateOutsideEndpoints");
 const QString SETTINGS_EXPORT_HEADER ("header");
 const QString SETTINGS_EXPORT_LAYOUT_FUNCTIONS ("layoutFunctions");
 const QString SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS ("pointsIntervalFunctions");
diff --git a/src/Settings/Settings.h b/src/Settings/Settings.h
index 707eadee..22cedaee 100644
--- a/src/Settings/Settings.h
+++ b/src/Settings/Settings.h
@@ -29,6 +29,7 @@ extern const QString SETTINGS_ENGAUGE;
 extern const QString SETTINGS_EXPORT_CURVE_NAMES_NOT_EXPORTED;
 extern const QString SETTINGS_EXPORT_DELIMITER;
 extern const QString SETTINGS_EXPORT_DELIMITER_OVERRIDE_CSV_TSV;
+extern const QString SETTINGS_EXPORT_EXTRAPOLATE_OUTSIDE_ENDPOINTS;
 extern const QString SETTINGS_EXPORT_HEADER;
 extern const QString SETTINGS_EXPORT_LAYOUT_FUNCTIONS;
 extern const QString SETTINGS_EXPORT_POINTS_INTERVAL_FUNCTIONS;
@@ -56,11 +57,14 @@ extern const QString SETTINGS_GROUP_MAIN_WINDOW;
 extern const QString SETTINGS_HELP_POS;
 extern const QString SETTINGS_HELP_SIZE;
 extern const QString SETTINGS_HIGHLIGHT_OPACITY;
+extern const QString SETTINGS_IMAGE_REPLACE_RENAMES_DOCUMENT;
 extern const QString SETTINGS_IMPORT_CROPPING;
 extern const QString SETTINGS_IMPORT_CROPPING_POS;
 extern const QString SETTINGS_IMPORT_PDF_RESOLUTION;
 extern const QString SETTINGS_LOCALE_COUNTRY;
 extern const QString SETTINGS_LOCALE_LANGUAGE;
+extern const QString SETTINGS_MAIN_DIRECTORY_EXPORT_SAVE;
+extern const QString SETTINGS_MAIN_DIRECTORY_IMPORT_LOAD;
 extern const QString SETTINGS_MAIN_TITLE_BAR_FORMAT;
 extern const QString SETTINGS_MAXIMUM_GRID_LINES;
 extern const QString SETTINGS_POS;
diff --git a/src/Spline/Spline.cpp b/src/Spline/Spline.cpp
old mode 100755
new mode 100644
index 31785995..8a75e61d
--- a/src/Spline/Spline.cpp
+++ b/src/Spline/Spline.cpp
@@ -4,17 +4,23 @@
 
 #include "EngaugeAssert.h"
 #include <iostream>
+#include "Logger.h"
+#include <qmath.h>
 #include "Spline.h"
 
 using namespace std;
 
 Spline::Spline(const std::vector<double> &t,
-               const std::vector<SplinePair> &xy)
+               const std::vector<SplinePair> &xy,
+               SplineTCheck splineTCheck)
 {
   ENGAUGE_ASSERT (t.size() == xy.size());
   ENGAUGE_ASSERT (xy.size() > 0); // Need at least one point for this class to not fail with a crash
 
-  checkTIncrements (t);
+  if (splineTCheck == SPLINE_ENABLE_T_CHECK) {
+    // In normal production this check should be performed
+    checkTIncrements (t);
+  }
   computeCoefficientsForIntervals (t, xy);
   computeControlPointsForIntervals ();
 }
@@ -40,8 +46,9 @@ void Spline::computeCoefficientsForIntervals (const std::vector<double> &t,
   if (xy.size() > 1) {
 
     // There are enough points to compute the coefficients
-    int i, j;
-    int n = (int) xy.size() - 1;
+    unsigned int i;
+    int jneg; // Can go negative
+    unsigned int n = unsigned (qFloor (xy.size()) - 1);
 
     m_t = t;
     m_xy = xy;
@@ -66,7 +73,8 @@ void Spline::computeCoefficientsForIntervals (const std::vector<double> &t,
     z[n] = SplinePair (0.0);
     c[n] = SplinePair (0.0);
 
-    for (j = n - 1; j >= 0; j--) {
+    for (jneg = signed (n - 1); jneg >= 0; jneg--) {
+      unsigned int j = unsigned (jneg);
       c[j] = z[j] - u[j] * c[j+1];
       b[j] = (xy[j+1] - xy[j]) / (h[j]) - (h[j] * (c[j+1] + SplinePair (2.0) * c[j])) / SplinePair (3.0);
       d[j] = (c[j+1] - c[j]) / (SplinePair (3.0) * h[j]);
@@ -92,25 +100,73 @@ void Spline::computeCoefficientsForIntervals (const std::vector<double> &t,
 
 void Spline::computeControlPointsForIntervals ()
 {
-  int n = (int) m_xy.size() - 1;
+  int i, n = qFloor (m_xy.size()) - 1; // Must be signed to handle zero length array
 
-  for (int i = 0; i < n; i++) {
-    const SplineCoeff &element = m_elements[i];
+  for (i = 0; i < n; i++) {
+    unsigned int iU = unsigned (i);
+    const SplineCoeff &element = m_elements[iU];
 
     // Derivative at P0 from (1-s)^3*P0+(1-s)^2*s*P1+(1-s)*s^2*P2+s^3*P3 with s=0 evaluates to 3(P1-P0). That
     // derivative must match the derivative of y=a+b*(t-ti)+c*(t-ti)^2+d*(t-ti)^3 with t=ti which evaluates to b.
     // So 3(P1-P0)=b
-    SplinePair p1 = m_xy [i] + element.b() /
+    SplinePair p1 = m_xy [iU] + element.b() /
                     SplinePair (3.0);
 
     // Derivative at P2 from (1-s)^3*P0+(1-s)^2*s*P1+(1-s)*s^2*P2+s^3*P3 with s=1 evaluates to 3(P3-P2). That
     // derivative must match the derivative of y=a+b*(t-ti)+c*(t-ti)^2+d*(t-ti)^3 with t=ti+1 which evaluates to b+2*c+3*d
-    SplinePair p2 = m_xy [i + 1] - (element.b() + SplinePair (2.0) * element.c() + SplinePair (3.0) * element.d()) /
+    SplinePair p2 = m_xy [iU + 1] - (element.b() + SplinePair (2.0) * element.c() + SplinePair (3.0) * element.d()) /
                     SplinePair (3.0);
 
     m_p1.push_back (p1);
     m_p2.push_back (p2);
   }
+
+  // Debug logging
+  for (i = 0; i < qFloor (m_xy.size ()) - 1; i++) {
+    unsigned int iU = unsigned (i);
+    LOG4CPP_DEBUG_S ((*mainCat)) << "Spline::computeControlPointsForIntervals" << " i=" << i
+             << " xy=" << m_xy [iU]
+             << " elementt=" << m_elements[iU].t()
+             << " elementa=" << m_elements[iU].a()
+             << " elementb=" << m_elements[iU].b()
+             << " elementc=" << m_elements[iU].c()
+             << " elementd=" << m_elements[iU].d()
+             << " p1=" << m_p1[iU]
+             << " p2=" << m_p2[iU];
+  }
+
+  if (m_xy.size() > 1) {
+    unsigned int iU = unsigned (m_xy.size() - 1);
+    LOG4CPP_DEBUG_S ((*mainCat)) << "Spline::computeControlPointsForIntervals" << " i=" << iU
+                  << " xy=" << m_xy [iU];
+  }
+}
+
+void Spline::computeUntranslatedCoefficients (double aTranslated,
+                                              double bTranslated,
+                                              double cTranslated,
+                                              double dTranslated,
+                                              double tI,
+                                              double &aUntranslated,
+                                              double &bUntranslated,
+                                              double &cUntranslated,
+                                              double &dUntranslated) const
+{
+  // Expanding the equation using t translated as (t-ti) we get the equation using untranslated (t) as follows
+  //   xy=d*t^3+
+  //      (c-3*d*ti)*t^2+
+  //      (b-2*c*ti+3*d*ti^2)*t+
+  //      (a-b*ti+c*ti^2-d*ti^3)
+  // which matches up with
+  //   xy=d*t^3+
+  //      c*t^2+
+  //      b*t+
+  //      a
+  // Both equations are given in the header file documentation for this method
+  aUntranslated = aTranslated - bTranslated * tI + cTranslated * tI * tI - dTranslated * tI * tI * tI;
+  bUntranslated = bTranslated - 2.0 * cTranslated * tI + 3.0 * dTranslated * tI * tI;
+  cUntranslated = cTranslated - 3.0 * dTranslated * tI;
+  dUntranslated = dTranslated;
 }
 
 SplinePair Spline::findSplinePairForFunctionX (double x,
@@ -121,7 +177,18 @@ SplinePair Spline::findSplinePairForFunctionX (double x,
   double tLow = m_t[0];
   double tHigh = m_t[m_xy.size() - 1];
 
-  // This method implicitly assumes that the x values are monotonically increasing
+  // This method implicitly assumes that the x values are monotonically increasing - except for the
+  // "export raw points" exception right here
+
+  // Subtle stuff here - we first look for exact matches in m_elements. If a match is found, we exit
+  // immediately. This strategy works for "export raw points" option with functions having overlaps,
+  // in which case users expect interpolation to be used (issue #303)
+  for (unsigned int i = 0; i < m_xy.size(); i++) {
+    const SplinePair &sp = m_xy.at (i);
+    if (sp.x() == x) {
+      return sp;
+    }
+  }
 
   // Extrapolation that is performed if x is out of bounds. As a starting point, we assume that the t
   // values and x values behave the same, which is linearly. This assumption works best when user
@@ -180,7 +247,7 @@ SplinePair Spline::interpolateControlPoints (double t) const
 {
   ENGAUGE_ASSERT (m_xy.size() != 0);
 
-  for (int i = 0; i < (signed) m_xy.size() - 1; i++) {
+  for (unsigned int i = 0; i < unsigned (m_xy.size() - 1); i++) {
 
     if (m_t[i] <= t && t <= m_t[i+1]) {
 
@@ -201,14 +268,14 @@ SplinePair Spline::interpolateControlPoints (double t) const
 
 SplinePair Spline::p1 (unsigned int i) const
 {
-  ENGAUGE_ASSERT (i < (unsigned int) m_p1.size ());
+  ENGAUGE_ASSERT (i < m_p1.size ());
 
   return m_p1 [i];
 }
 
 SplinePair Spline::p2 (unsigned int i) const
 {
-  ENGAUGE_ASSERT (i < (unsigned int) m_p2.size ());
+  ENGAUGE_ASSERT (i < m_p2.size ());
 
   return m_p2 [i];
 }
diff --git a/src/Spline/Spline.h b/src/Spline/Spline.h
index 03e6c5a1..963e7fc3 100644
--- a/src/Spline/Spline.h
+++ b/src/Spline/Spline.h
@@ -4,10 +4,18 @@
  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
  ******************************************************************************************************/
 
+#ifndef SPLINE_H
+#define SPLINE_H
+
 #include "SplineCoeff.h"
 #include "SplinePair.h"
 #include <vector>
 
+enum SplineTCheck {
+  SPLINE_ENABLE_T_CHECK,
+  SPLINE_DISABLE_T_CHECK
+};
+
 /// Cubic interpolation given independent and dependent value vectors. X is handled as a dependent variable
 /// based on the unitless independent parameter t so curves are not restricted to x(i)!=x(i+1).
 ///
@@ -20,15 +28,33 @@
 ///    external code that relies on control points to perform its own interpolation 
 class Spline 
 {
+  /// For unit testing
+  friend class TestSpline;
+
  public:
   /// Initialize spline with independent (t) and dependent (x and y) value vectors. Besides initializing
   /// the a,b,c,d coefficients for each interval, this constructor initializes bezier points (P1 and P2)
   /// for each interval, where P0 and P3 are the start and end points for each interval.
   Spline(const std::vector<double> &t,
-         const std::vector<SplinePair> &xy);
+         const std::vector<SplinePair> &xy,
+         SplineTCheck splineTCheck = SPLINE_ENABLE_T_CHECK);
 
   virtual ~Spline();
 
+  /// From coefficients in
+  ///   xy=d*(t-ti)^3+c*(t-ti)^2+b*(t-ti)+a
+  /// we compute and return the coefficients in
+  ///   xy=d* t    ^3+c* t    ^2+b* t    +a
+  void computeUntranslatedCoefficients (double aTranslated,
+                                        double bTranslated,
+                                        double cTranslated,
+                                        double dTranslated,
+                                        double tI,
+                                        double &aUntranslated,
+                                        double &bUntranslated,
+                                        double &cUntranslated,
+                                        double &dUntranslated) const;
+
   /// Use bisection algorithm to iteratively find the SplinePair interpolated to best match the specified x value.
   /// This assumes the curve is a function since otherwise there is the potential for multiple solutions
   SplinePair findSplinePairForFunctionX (double x,
@@ -73,3 +99,5 @@ private:
   std::vector<SplinePair> m_p1;
   std::vector<SplinePair> m_p2;
 };
+
+#endif // SPLINE_H
diff --git a/src/Spline/SplineDrawer.cpp b/src/Spline/SplineDrawer.cpp
new file mode 100644
index 00000000..b2540fc9
--- /dev/null
+++ b/src/Spline/SplineDrawer.cpp
@@ -0,0 +1,117 @@
+/******************************************************************************************************
+ * (C) 2018 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#include "EngaugeAssert.h"
+#include "LineStyle.h"
+#include <qmath.h>
+#include "Spline.h"
+#include "SplineDrawer.h"
+
+SplineDrawer::SplineDrawer(const Transformation &transformation) :
+  m_transformation (transformation)
+{
+}
+
+void SplineDrawer::bindToSpline (const LineStyle &lineStyle,
+                                 int numSegments,
+                                 const Spline &spline)
+{
+  m_segmentOperations.resize (numSegments);
+
+  // Loop through segments to get move/draw choice. We do not need to worry about
+  // applying a move (versus a draw) for the first segment since that first point
+  // is handled by external code
+  for (int segment = 0; segment < numSegments; segment++) {
+
+    bool itsAKeeper = true;
+    if (m_transformation.transformIsDefined()) {
+
+      // We have the graph<->screen transformation so let's use it. Could there be an ambiguity issue?
+      if ((lineStyle.curveConnectAs() == CONNECT_AS_FUNCTION_SMOOTH) &&
+          segmentIsMultiValued (spline,
+                                numSegments,
+                                segment)) {
+        itsAKeeper = false;
+      }
+
+      // Invisible or visible?
+      m_segmentOperations [segment] = (itsAKeeper ?
+                                       SPLINE_DRAWER_ENUM_VISIBLE_DRAW :
+                                       SPLINE_DRAWER_ENUM_INVISIBLE_MOVE);
+    }
+  }
+}
+
+bool SplineDrawer::segmentIsMultiValued (const Spline &spline,
+                                         int numSegments,
+                                         int segment) const
+{
+  ENGAUGE_ASSERT (m_transformation.transformIsDefined());
+
+  if (segment < numSegments - 1) {
+
+    // Not at very end
+    double tI = double (segment);
+    double tIp1 = double (segment + 1);
+
+    // Compute number of pixels between endpoints
+    SplinePair posScreenStart  = spline.interpolateCoeff (tI);
+    SplinePair posScreenEnd = spline.interpolateCoeff (tIp1);
+
+    int deltaX = qFloor (posScreenEnd.x() - posScreenStart.x());
+    int deltaY = qFloor (posScreenEnd.y() - posScreenStart.y());
+    double pixelDistance = qSqrt (deltaX * deltaX + deltaY * deltaY);
+    double numSteps = pixelDistance;
+
+    // Search through a sufficiently large number of points to verify single-valuedness
+    double tIDelta = 1.0 / numSteps;
+    for (int itI = 1; itI < numSteps - 1; itI++) {
+
+      double tIm1 = segment + (itI - 1) * tIDelta;
+      double tI   = segment + (itI    ) * tIDelta;
+      double tIp1 = segment + (itI + 1) * tIDelta;
+
+      SplinePair spBefore = spline.interpolateCoeff (tIm1);
+      SplinePair spCurrent = spline.interpolateCoeff (tI);
+      SplinePair spAfter = spline.interpolateCoeff (tIp1);
+
+      QPointF posScreenBefore (spBefore.x(), spBefore.y());
+      QPointF posScreenCurrent (spCurrent.x(), spCurrent.y());
+      QPointF posScreenAfter (spAfter.x(), spAfter.y());
+
+      QPointF posGraphBefore, posGraphCurrent, posGraphAfter;
+      m_transformation.transformScreenToRawGraph (posScreenBefore,
+                                                  posGraphBefore);
+      m_transformation.transformScreenToRawGraph (posScreenCurrent,
+                                                  posGraphCurrent);
+      m_transformation.transformScreenToRawGraph (posScreenAfter,
+                                                  posGraphAfter);
+
+      // In between the start and end points we look for deltaXBefore>0 and deltaXAfter<0,
+      // or deltaXBefore<0 and deltaXAfter>0, either of those two cases indicates multi-valued
+      double deltaXBefore = posGraphCurrent.x() - posGraphBefore.x();
+      double deltaXAfter = posGraphAfter.x() - posGraphCurrent.x();
+
+      if ((deltaXBefore > 0 && deltaXAfter < 0) ||
+          (deltaXBefore < 0 && deltaXAfter > 0)) {
+
+        // Multi-valued
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+SplineDrawerOperation SplineDrawer::segmentOperation (int segment) const
+{
+  if (segment < m_segmentOperations.count()) {
+    return m_segmentOperations.at (segment);
+  } else {
+    return SPLINE_DRAWER_ENUM_INVISIBLE_MOVE;
+  }
+}
diff --git a/src/Spline/SplineDrawer.h b/src/Spline/SplineDrawer.h
new file mode 100644
index 00000000..a93a6f00
--- /dev/null
+++ b/src/Spline/SplineDrawer.h
@@ -0,0 +1,65 @@
+/******************************************************************************************************
+ * (C) 2018 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#ifndef SPLINE_DRAWER_H
+#define SPLINE_DRAWER_H
+
+#include "SplinePair.h"
+#include "Transformation.h"
+#include <QVector>
+
+class LineStyle;
+class Spline;
+
+enum SplineDrawerOperation {
+  SPLINE_DRAWER_ENUM_INVISIBLE_MOVE, // Move to final point in segment
+  SPLINE_DRAWER_ENUM_VISIBLE_DRAW // Draw to final point in segment
+};
+
+typedef QVector<SplineDrawerOperation> SegmentOperations;
+
+/// This class takes the output from Spline and uses that to draw the curve in the graphics window, as
+/// a sequence of moves and draws. The moves and draws by themselves would be trivial (move,draw,draw,draw...)
+/// but this actually draws, when needed, differently styled curve segments to indicate each curve segment
+/// should be CONNECT_AS_FUNCTION_SMOOTH but actually is not single-valued (=not a function)
+///
+/// This class is aware of the Transformation, unlike the Spline class which is decoupled from that for simplicity.
+/// Specifically, this class converts the screen coordinates to graph coordinates to check for single-valuedness.
+///
+/// The algorithm used here has to work in cartesian, polar, linear and/or log coordinates. This requirement,
+/// along with the goal of keeping the Spline class simple, pretty much requires using the Transformation
+/// and working in graph coordinates.
+class SplineDrawer
+{
+  // For unit testing
+  friend class TestSplineDrawer;
+  
+ public:
+  /// Single constructor
+  SplineDrawer(const Transformation &transformation);
+
+  /// Analyze each segment in the Spline
+  void bindToSpline (const LineStyle &lineStyle,
+                     int numSegments,
+                     const Spline &spline);
+
+  /// Return true if specified segment is multi-valued, else false
+  bool segmentIsMultiValued (const Spline &spline,
+                             int numSegments,
+                             int segment) const;
+
+  /// Indicate if, and how, segment is to be drawn
+  SplineDrawerOperation segmentOperation (int segment) const;
+
+private:
+  SplineDrawer();
+
+  const Transformation m_transformation;
+
+  SegmentOperations m_segmentOperations;
+};
+
+#endif // SPLINE_DRAWER_H
diff --git a/src/Spline/SplinePair.cpp b/src/Spline/SplinePair.cpp
index 55ca923e..3752dfe0 100644
--- a/src/Spline/SplinePair.cpp
+++ b/src/Spline/SplinePair.cpp
@@ -6,6 +6,8 @@
 
 #include "SplinePair.h"
 
+using namespace std;
+
 SplinePair::SplinePair () :
   m_x (0.0),
   m_y (0.0)
@@ -25,7 +27,15 @@ SplinePair::SplinePair(double x,
 {
 }
 
-SplinePair::SplinePair(const SplinePair&other) :
+SplinePair &SplinePair::operator=(const SplinePair &other)
+{
+  m_x = other.x();
+  m_y = other.y();
+
+  return *this;
+}
+
+SplinePair::SplinePair(const SplinePair &other) :
   m_x (other.x()),
   m_y (other.y())
 {
@@ -63,6 +73,13 @@ SplinePair SplinePair::operator/(const SplinePair &other) const
   return result;
 }
 
+ostream &operator<< (ostream &str, const SplinePair &pair)
+{
+  str << "(" << pair.x() << "," << pair.y() << ")";
+
+  return str;
+}
+
 double SplinePair::x() const
 {
   return m_x;
diff --git a/src/Spline/SplinePair.h b/src/Spline/SplinePair.h
index 1026b4cd..77a97ae7 100644
--- a/src/Spline/SplinePair.h
+++ b/src/Spline/SplinePair.h
@@ -7,6 +7,8 @@
 #ifndef SPLINE_PAIR_H
 #define SPLINE_PAIR_H
 
+#include <ostream>
+
 /// Single X/Y pair for cubic spline interpolation initialization and calculations
 class SplinePair
 {
@@ -21,8 +23,11 @@ class SplinePair
   SplinePair(double x,
              double y);
 
-  /// Assigment constructor
-  SplinePair(const SplinePair&other);
+  /// Assignment constructor
+  SplinePair &operator=(const SplinePair &other);
+
+  /// Copy constructor
+  SplinePair(const SplinePair &other);
 
   /// Addition operator
   SplinePair operator+(const SplinePair &other) const;
@@ -48,4 +53,7 @@ class SplinePair
   double m_y;
 };
 
+/// Insertion operator for qDebug and Logger
+std::ostream &operator<< (std::ostream &str, const SplinePair &pair);
+
 #endif // SPLINE_PAIR_H
diff --git a/src/StatusBar/StatusBar.cpp b/src/StatusBar/StatusBar.cpp
index a327c2ee..6a1de549 100644
--- a/src/StatusBar/StatusBar.cpp
+++ b/src/StatusBar/StatusBar.cpp
@@ -14,6 +14,7 @@
 #include <QTimer>
 #include <QWhatsThis>
 #include "StatusBar.h"
+#include "StatusBarMode.h"
 #include "ZoomFactor.h"
 #include "ZoomLabels.h"
 
@@ -27,8 +28,9 @@ const int MAX_HEIGHT_EDIT_COORDS = 24;
 StatusBar::StatusBar(QStatusBar &statusBar) :
   m_statusBar (statusBar),
   m_statusBarMode (STATUS_BAR_MODE_ALWAYS),
-  m_timer (0)
+  m_timer (nullptr)
 {
+  createZoomLabels ();
   createZoom ();
   createZoomMaps ();
   createGroupUnits ();
@@ -75,9 +77,9 @@ void StatusBar::createGroupUnits ()
 
   m_groupUnits = new QFrame;
   m_groupUnits->setFrameStyle (QFrame::Box);
-  QPalette *palette = new QPalette;
-  palette->setColor (QPalette::Foreground, Qt::gray);
-  m_groupUnits->setPalette (*palette);
+  QPalette palette;
+  palette.setColor (QPalette::Foreground, Qt::gray);
+  m_groupUnits->setPalette (palette);
 
   QHBoxLayout *groupLayout = new QHBoxLayout;
   m_groupUnits->setLayout (groupLayout);
@@ -94,33 +96,33 @@ void StatusBar::createZoom ()
   m_cmbZoom = new QComboBox ();
   m_cmbZoom->setEnabled (false); // Disabled until file is opened
   m_cmbZoom->setMinimumWidth (MIN_WIDTH_ZOOM);
-  m_cmbZoom->addItem (LABEL_ZOOM_16_TO_1);
-  m_cmbZoom->addItem (LABEL_ZOOM_16_TO_1_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1);
-  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1);
-  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1);
-  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8_FARTHER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_16_CLOSER);
-  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_16);
-  m_cmbZoom->addItem (LABEL_ZOOM_FILL);
-  m_cmbZoom->setCurrentText (LABEL_ZOOM_1_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_16_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_16_TO_1_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_8_TO_1_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_8_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_8_TO_1_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_4_TO_1_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_4_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_4_TO_1_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_2_TO_1_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_2_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_2_TO_1_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_1_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_1);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_1_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_2_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_2);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_2_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_4_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_4);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_4_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_8_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_8);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_8_FARTHER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_16_CLOSER);
+  m_cmbZoom->addItem (*LABEL_ZOOM_1_TO_16);
+  m_cmbZoom->addItem (*LABEL_ZOOM_FILL);
+  m_cmbZoom->setCurrentText (*LABEL_ZOOM_1_TO_1);
   m_cmbZoom->setMaximumWidth (80);
   m_cmbZoom->setToolTip (tr ("Select zoom."));
   m_cmbZoom->setWhatsThis (tr("Select Zoom\n\n"
@@ -131,61 +133,92 @@ void StatusBar::createZoom ()
   m_statusBar.addPermanentWidget (m_cmbZoom);
 }
 
+void StatusBar::createZoomLabels ()
+{
+  LABEL_ZOOM_16_TO_1= new QString (tr ("16:1"));
+  LABEL_ZOOM_16_TO_1_FARTHER= new QString (tr ("16:1 farther"));
+  LABEL_ZOOM_8_TO_1_CLOSER= new QString (tr ("8:1 closer"));
+  LABEL_ZOOM_8_TO_1= new QString (tr ("8:1"));
+  LABEL_ZOOM_8_TO_1_FARTHER= new QString (tr ("8:1 farther"));
+  LABEL_ZOOM_4_TO_1_CLOSER= new QString (tr ("4:1 closer"));
+  LABEL_ZOOM_4_TO_1= new QString (tr ("4:1"));
+  LABEL_ZOOM_4_TO_1_FARTHER= new QString (tr ("4:1 farther"));
+  LABEL_ZOOM_2_TO_1_CLOSER= new QString (tr ("2:1 closer"));
+  LABEL_ZOOM_2_TO_1= new QString (tr ("2:1"));
+  LABEL_ZOOM_2_TO_1_FARTHER= new QString (tr ("2:1 farther"));
+  LABEL_ZOOM_1_TO_1_CLOSER= new QString (tr ("1:1 closer"));
+  LABEL_ZOOM_1_TO_1= new QString (tr ("1:1"));
+  LABEL_ZOOM_1_TO_1_FARTHER= new QString (tr ("1:1 farther"));
+  LABEL_ZOOM_1_TO_2_CLOSER= new QString (tr ("1:2 closer"));
+  LABEL_ZOOM_1_TO_2= new QString (tr ("1:2"));
+  LABEL_ZOOM_1_TO_2_FARTHER= new QString (tr ("1:2 farther"));
+  LABEL_ZOOM_1_TO_4_CLOSER= new QString (tr ("1:4 closer"));
+  LABEL_ZOOM_1_TO_4= new QString (tr ("1:4"));
+  LABEL_ZOOM_1_TO_4_FARTHER= new QString (tr ("1:4 farther"));
+  LABEL_ZOOM_1_TO_8_CLOSER= new QString (tr ("1:8 closer"));
+  LABEL_ZOOM_1_TO_8= new QString (tr ("1:8"));
+  LABEL_ZOOM_1_TO_8_FARTHER= new QString (tr ("1:8 farther"));
+  LABEL_ZOOM_1_TO_16_CLOSER= new QString (tr ("1:16 closer"));
+  LABEL_ZOOM_1_TO_16= new QString (tr ("1:16"));
+  LABEL_ZOOM_FILL= new QString (tr ("Fill"));
+  LABEL_ZOOM_PREVIOUS= new QString (tr ("Previous"));
+}
+
 void StatusBar::createZoomMaps ()
 {
-  m_zoomMapToLabel [ZOOM_16_TO_1] = LABEL_ZOOM_16_TO_1;
-  m_zoomMapToLabel [ZOOM_16_TO_1_FARTHER] = LABEL_ZOOM_16_TO_1_FARTHER;
-  m_zoomMapToLabel [ZOOM_8_TO_1_CLOSER] = LABEL_ZOOM_8_TO_1_CLOSER;
-  m_zoomMapToLabel [ZOOM_8_TO_1] = LABEL_ZOOM_8_TO_1;
-  m_zoomMapToLabel [ZOOM_8_TO_1_FARTHER] = LABEL_ZOOM_8_TO_1_FARTHER;
-  m_zoomMapToLabel [ZOOM_4_TO_1_CLOSER] = LABEL_ZOOM_4_TO_1_CLOSER;
-  m_zoomMapToLabel [ZOOM_4_TO_1] = LABEL_ZOOM_4_TO_1;
-  m_zoomMapToLabel [ZOOM_4_TO_1_FARTHER] = LABEL_ZOOM_4_TO_1_FARTHER;
-  m_zoomMapToLabel [ZOOM_2_TO_1_CLOSER] = LABEL_ZOOM_2_TO_1_CLOSER;
-  m_zoomMapToLabel [ZOOM_2_TO_1] = LABEL_ZOOM_2_TO_1;
-  m_zoomMapToLabel [ZOOM_2_TO_1_FARTHER] = LABEL_ZOOM_2_TO_1_FARTHER;
-  m_zoomMapToLabel [ZOOM_1_TO_1_CLOSER] = LABEL_ZOOM_1_TO_1_CLOSER;
-  m_zoomMapToLabel [ZOOM_1_TO_1] = LABEL_ZOOM_1_TO_1;
-  m_zoomMapToLabel [ZOOM_1_TO_1_FARTHER] = LABEL_ZOOM_1_TO_1_FARTHER;
-  m_zoomMapToLabel [ZOOM_1_TO_2_CLOSER] = LABEL_ZOOM_1_TO_2_CLOSER;
-  m_zoomMapToLabel [ZOOM_1_TO_2] = LABEL_ZOOM_1_TO_2;
-  m_zoomMapToLabel [ZOOM_1_TO_2_FARTHER] = LABEL_ZOOM_1_TO_2_FARTHER;
-  m_zoomMapToLabel [ZOOM_1_TO_4_CLOSER] = LABEL_ZOOM_1_TO_4_CLOSER;
-  m_zoomMapToLabel [ZOOM_1_TO_4] = LABEL_ZOOM_1_TO_4;
-  m_zoomMapToLabel [ZOOM_1_TO_4_FARTHER] = LABEL_ZOOM_1_TO_4_FARTHER;
-  m_zoomMapToLabel [ZOOM_1_TO_8_CLOSER] = LABEL_ZOOM_1_TO_8_CLOSER;
-  m_zoomMapToLabel [ZOOM_1_TO_8] = LABEL_ZOOM_1_TO_8;
-  m_zoomMapToLabel [ZOOM_1_TO_8_FARTHER] = LABEL_ZOOM_1_TO_8_FARTHER;
-  m_zoomMapToLabel [ZOOM_1_TO_16_CLOSER] = LABEL_ZOOM_1_TO_16_CLOSER;
-  m_zoomMapToLabel [ZOOM_1_TO_16] = LABEL_ZOOM_1_TO_16;
-  m_zoomMapToLabel [ZOOM_FILL] = LABEL_ZOOM_FILL;
-
-  m_zoomMapFromLabel [LABEL_ZOOM_16_TO_1] = ZOOM_16_TO_1;
-  m_zoomMapFromLabel [LABEL_ZOOM_16_TO_1_FARTHER] = ZOOM_16_TO_1_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1_CLOSER] = ZOOM_8_TO_1_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1] = ZOOM_8_TO_1;
-  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1_FARTHER] = ZOOM_8_TO_1_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1_CLOSER] = ZOOM_4_TO_1_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1] = ZOOM_4_TO_1;
-  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1_FARTHER] = ZOOM_4_TO_1_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1_CLOSER] = ZOOM_2_TO_1_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1] = ZOOM_2_TO_1;
-  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1_FARTHER] = ZOOM_2_TO_1_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1_CLOSER] = ZOOM_1_TO_1_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1] = ZOOM_1_TO_1;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1_FARTHER] = ZOOM_1_TO_1_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2_CLOSER] = ZOOM_1_TO_2_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2] = ZOOM_1_TO_2;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2_FARTHER] = ZOOM_1_TO_2_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4_CLOSER] = ZOOM_1_TO_4_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4] = ZOOM_1_TO_4;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4_FARTHER] = ZOOM_1_TO_4_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8_CLOSER] = ZOOM_1_TO_8_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8] = ZOOM_1_TO_8;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8_FARTHER] = ZOOM_1_TO_8_FARTHER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_16_CLOSER] = ZOOM_1_TO_16_CLOSER;
-  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_16] = ZOOM_1_TO_16;
-  m_zoomMapFromLabel [LABEL_ZOOM_FILL] = ZOOM_FILL;
+  m_zoomMapToLabel [ZOOM_16_TO_1] = *LABEL_ZOOM_16_TO_1;
+  m_zoomMapToLabel [ZOOM_16_TO_1_FARTHER] = *LABEL_ZOOM_16_TO_1_FARTHER;
+  m_zoomMapToLabel [ZOOM_8_TO_1_CLOSER] = *LABEL_ZOOM_8_TO_1_CLOSER;
+  m_zoomMapToLabel [ZOOM_8_TO_1] = *LABEL_ZOOM_8_TO_1;
+  m_zoomMapToLabel [ZOOM_8_TO_1_FARTHER] = *LABEL_ZOOM_8_TO_1_FARTHER;
+  m_zoomMapToLabel [ZOOM_4_TO_1_CLOSER] = *LABEL_ZOOM_4_TO_1_CLOSER;
+  m_zoomMapToLabel [ZOOM_4_TO_1] = *LABEL_ZOOM_4_TO_1;
+  m_zoomMapToLabel [ZOOM_4_TO_1_FARTHER] = *LABEL_ZOOM_4_TO_1_FARTHER;
+  m_zoomMapToLabel [ZOOM_2_TO_1_CLOSER] = *LABEL_ZOOM_2_TO_1_CLOSER;
+  m_zoomMapToLabel [ZOOM_2_TO_1] = *LABEL_ZOOM_2_TO_1;
+  m_zoomMapToLabel [ZOOM_2_TO_1_FARTHER] = *LABEL_ZOOM_2_TO_1_FARTHER;
+  m_zoomMapToLabel [ZOOM_1_TO_1_CLOSER] = *LABEL_ZOOM_1_TO_1_CLOSER;
+  m_zoomMapToLabel [ZOOM_1_TO_1] = *LABEL_ZOOM_1_TO_1;
+  m_zoomMapToLabel [ZOOM_1_TO_1_FARTHER] = *LABEL_ZOOM_1_TO_1_FARTHER;
+  m_zoomMapToLabel [ZOOM_1_TO_2_CLOSER] = *LABEL_ZOOM_1_TO_2_CLOSER;
+  m_zoomMapToLabel [ZOOM_1_TO_2] = *LABEL_ZOOM_1_TO_2;
+  m_zoomMapToLabel [ZOOM_1_TO_2_FARTHER] = *LABEL_ZOOM_1_TO_2_FARTHER;
+  m_zoomMapToLabel [ZOOM_1_TO_4_CLOSER] = *LABEL_ZOOM_1_TO_4_CLOSER;
+  m_zoomMapToLabel [ZOOM_1_TO_4] = *LABEL_ZOOM_1_TO_4;
+  m_zoomMapToLabel [ZOOM_1_TO_4_FARTHER] = *LABEL_ZOOM_1_TO_4_FARTHER;
+  m_zoomMapToLabel [ZOOM_1_TO_8_CLOSER] = *LABEL_ZOOM_1_TO_8_CLOSER;
+  m_zoomMapToLabel [ZOOM_1_TO_8] = *LABEL_ZOOM_1_TO_8;
+  m_zoomMapToLabel [ZOOM_1_TO_8_FARTHER] = *LABEL_ZOOM_1_TO_8_FARTHER;
+  m_zoomMapToLabel [ZOOM_1_TO_16_CLOSER] = *LABEL_ZOOM_1_TO_16_CLOSER;
+  m_zoomMapToLabel [ZOOM_1_TO_16] = *LABEL_ZOOM_1_TO_16;
+  m_zoomMapToLabel [ZOOM_FILL] = *LABEL_ZOOM_FILL;
+
+  m_zoomMapFromLabel [*LABEL_ZOOM_16_TO_1] = ZOOM_16_TO_1;
+  m_zoomMapFromLabel [*LABEL_ZOOM_16_TO_1_FARTHER] = ZOOM_16_TO_1_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_8_TO_1_CLOSER] = ZOOM_8_TO_1_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_8_TO_1] = ZOOM_8_TO_1;
+  m_zoomMapFromLabel [*LABEL_ZOOM_8_TO_1_FARTHER] = ZOOM_8_TO_1_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_4_TO_1_CLOSER] = ZOOM_4_TO_1_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_4_TO_1] = ZOOM_4_TO_1;
+  m_zoomMapFromLabel [*LABEL_ZOOM_4_TO_1_FARTHER] = ZOOM_4_TO_1_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_2_TO_1_CLOSER] = ZOOM_2_TO_1_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_2_TO_1] = ZOOM_2_TO_1;
+  m_zoomMapFromLabel [*LABEL_ZOOM_2_TO_1_FARTHER] = ZOOM_2_TO_1_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_1_CLOSER] = ZOOM_1_TO_1_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_1] = ZOOM_1_TO_1;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_1_FARTHER] = ZOOM_1_TO_1_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_2_CLOSER] = ZOOM_1_TO_2_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_2] = ZOOM_1_TO_2;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_2_FARTHER] = ZOOM_1_TO_2_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_4_CLOSER] = ZOOM_1_TO_4_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_4] = ZOOM_1_TO_4;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_4_FARTHER] = ZOOM_1_TO_4_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_8_CLOSER] = ZOOM_1_TO_8_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_8] = ZOOM_1_TO_8;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_8_FARTHER] = ZOOM_1_TO_8_FARTHER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_16_CLOSER] = ZOOM_1_TO_16_CLOSER;
+  m_zoomMapFromLabel [*LABEL_ZOOM_1_TO_16] = ZOOM_1_TO_16;
+  m_zoomMapFromLabel [*LABEL_ZOOM_FILL] = ZOOM_FILL;
 }
 
 QString StatusBar::labelCoordsGraph () const
@@ -234,7 +267,9 @@ void StatusBar::setStatusBarMode(StatusBarMode statusBarMode)
 
 void StatusBar::showTemporaryMessage(const QString &message)
 {
-  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::showTemporaryMessage message=" << message.toLatin1 ().data ();
+  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::showTemporaryMessage"
+                               << " mode=" << statusBarModeToString (m_statusBarMode).toLatin1 ().data ()
+                               << " message=" << message.toLatin1 ().data ();
 
   if (m_statusBarMode != STATUS_BAR_MODE_NEVER) {
     if (m_statusBarMode == STATUS_BAR_MODE_TEMPORARY) {
@@ -279,7 +314,7 @@ void StatusBar::slotTimeout()
   LOG4CPP_INFO_S ((*mainCat)) << "StatusBar::slotTimeout";
 
   delete m_timer;
-  m_timer = 0;
+  m_timer = nullptr;
 
   m_statusBar.show();
 }
@@ -289,7 +324,7 @@ void StatusBar::slotZoom(int zoom)
   LOG4CPP_INFO_S ((*mainCat)) << "StatusBar::slotZoom zoom=" << zoom;
 
   // Show string for the numeric zoom value
-  ZoomFactor zoomFactor = (ZoomFactor) zoom;
+  ZoomFactor zoomFactor = static_cast<ZoomFactor> (zoom);
   ENGAUGE_ASSERT (m_zoomMapToLabel.contains (zoomFactor));
   m_cmbZoom->setCurrentText (m_zoomMapToLabel [zoomFactor]);
 }
diff --git a/src/StatusBar/StatusBar.h b/src/StatusBar/StatusBar.h
index 0b67190f..2e165376 100644
--- a/src/StatusBar/StatusBar.h
+++ b/src/StatusBar/StatusBar.h
@@ -74,6 +74,7 @@ private:
 
   void createGroupUnits ();
   void createZoom ();
+  void createZoomLabels ();
   void createZoomMaps ();
   QString labelCoordsGraph () const; // Return string initialized after QTranslator has become available
   QString labelCoordsScreen () const; // Return string initialized after QTranslator has become available
diff --git a/src/StatusBar/StatusBarMode.cpp b/src/StatusBar/StatusBarMode.cpp
new file mode 100644
index 00000000..a8bbc381
--- /dev/null
+++ b/src/StatusBar/StatusBarMode.cpp
@@ -0,0 +1,28 @@
+/******************************************************************************************************
+ * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released      *
+ * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
+ * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission.     *
+ ******************************************************************************************************/
+
+#include "StatusBarMode.h"
+
+QString statusBarModeToString (StatusBarMode statusBarMode)
+{
+  QString rtn;
+
+  switch (statusBarMode) {
+    case STATUS_BAR_MODE_ALWAYS:
+      rtn = "Always";
+      break;
+
+    case STATUS_BAR_MODE_NEVER:
+      rtn = "Never";
+      break;
+
+    case STATUS_BAR_MODE_TEMPORARY:
+      rtn = "Temporary";
+      break;      
+  }
+
+  return rtn;
+}
diff --git a/src/StatusBar/StatusBarMode.h b/src/StatusBar/StatusBarMode.h
index 57b0da3f..5289f1a8 100644
--- a/src/StatusBar/StatusBarMode.h
+++ b/src/StatusBar/StatusBarMode.h
@@ -7,10 +7,14 @@
 #ifndef STATUS_BAR_MODE_H
 #define STATUS_BAR_MODE_H
 
+#include <QString>
+
 enum StatusBarMode {
   STATUS_BAR_MODE_ALWAYS,
   STATUS_BAR_MODE_NEVER,
   STATUS_BAR_MODE_TEMPORARY
 };
 
+extern QString statusBarModeToString (StatusBarMode statusBarMode);
+
 #endif // STATUS_BAR_MODE_H
diff --git a/src/Test/TestCorrelation.cpp b/src/Test/TestCorrelation.cpp
index e2532d13..7febaed5 100644
--- a/src/Test/TestCorrelation.cpp
+++ b/src/Test/TestCorrelation.cpp
@@ -19,6 +19,7 @@ void TestCorrelation::cleanupTestCase ()
 
 void TestCorrelation::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -37,6 +38,7 @@ void TestCorrelation::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,                
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestExport.cpp b/src/Test/TestExport.cpp
index 1212e150..7dda4c10 100644
--- a/src/Test/TestExport.cpp
+++ b/src/Test/TestExport.cpp
@@ -21,13 +21,14 @@ QTEST_MAIN (TestExport)
 
 using namespace std;
 
+const bool NO_DROP_REGRESSION = false;
 const bool NOT_USING_GNUPLOT = false;
 const bool EXPORT_ONLY= true;
 const QString NO_ERROR_REPORT_LOG_FILE;
 const QString NO_REGRESSION_OPEN_FILE;
 const bool NO_GNUPLOT_LOG_FILES = false;
 const bool NO_REGRESSION_IMPORT = false;
-const bool NO_RESET = false;
+const bool IS_RESET = true; // Eliminate issues due to unexpected config file settings
 const bool NO_EXPORT_ONLY = false;
 const bool NO_EXTRACT_IMAGE_ONLY = false;
 const QString NO_EXTRACT_IMAGE_EXTENSION;
@@ -64,7 +65,8 @@ bool TestExport::checkCommasInFunctionsForDelimiter (ExportDelimiter delimiter,
     bool isLogYRadius = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG);
     unsigned int numWritesSoFar = 0;
 
-    ExportFileFunctions exportFile;    
+    ExportFileFunctions exportFile;
+    CurveLimits curveLimitsMin, curveLimitsMax; // Empty containers mean no limits are in effect
     exportFile.exportAllPerLineXThetaValuesMerged (m_modelExportOverride,
                                                    *m_document,
                                                    m_modelMainWindow,
@@ -74,6 +76,8 @@ bool TestExport::checkCommasInFunctionsForDelimiter (ExportDelimiter delimiter,
                                                    m_transformation,
                                                    isLogXTheta,
                                                    isLogYRadius,
+                                                   curveLimitsMin,
+                                                   curveLimitsMax,
                                                    str,
                                                    numWritesSoFar);
   }
@@ -213,15 +217,21 @@ void TestExport::initTestCase ()
 
   m_mainWindow = new MainWindow (NO_ERROR_REPORT_LOG_FILE,
                                  NO_REGRESSION_OPEN_FILE,
+                                 NO_DROP_REGRESSION,
                                  NO_REGRESSION_IMPORT,                
                                  NO_GNUPLOT_LOG_FILES,
-                                 NO_RESET,
+                                 IS_RESET,
                                  NO_EXPORT_ONLY,
                                  NO_EXTRACT_IMAGE_ONLY,
                                  NO_EXTRACT_IMAGE_EXTENSION,                                 
                                  NO_LOAD_STARTUP_FILES,
                                  NO_COMMAND_LINE);
 
+  // Values loaded in the constructor of this class are overwritten so the settings reset just
+  // performed by MainWindow will give us predictable settings (which ultimately affect the test results)
+  DocumentModelExportFormat exportDefault;
+  m_modelExportOverride = exportDefault;
+
   m_mainWindow->show ();
 }
 
@@ -608,7 +618,8 @@ void TestExport::testLogExtrapolationFunctionsAll ()
     bool isLogYRadius = (m_modelCoords.coordScaleYRadius() == COORD_SCALE_LOG);
     unsigned int numWritesSoFar = 0;
     
-    ExportFileFunctions exportFile;    
+    ExportFileFunctions exportFile;
+    CurveLimits curveLimitsMin, curveLimitsMax; // Empty containers mean no limits are in effect    
     exportFile.exportAllPerLineXThetaValuesMerged (m_modelExportOverride,
                                                    *m_document,
                                                    m_modelMainWindow,
@@ -618,6 +629,8 @@ void TestExport::testLogExtrapolationFunctionsAll ()
                                                    m_transformation,
                                                    isLogXTheta,
                                                    isLogYRadius,
+                                                   curveLimitsMin,
+                                                   curveLimitsMax,
                                                    str,
                                                    numWritesSoFar);
   }
diff --git a/src/Test/TestExport.h b/src/Test/TestExport.h
index 0777610e..d3b60ec7 100644
--- a/src/Test/TestExport.h
+++ b/src/Test/TestExport.h
@@ -57,7 +57,7 @@ private:
   MainWindow *m_mainWindow;
   Document *m_document;
   DocumentModelCoords m_modelCoords;
-  DocumentModelExportFormat m_modelExportOverride;
+  DocumentModelExportFormat m_modelExportOverride; // Values from constructor, loaded before settings reset, are overwritten
   DocumentModelGeneral m_modelGeneral;
   MainWindowModel m_modelMainWindow;
   Transformation m_transformation;
diff --git a/src/Test/TestFitting.cpp b/src/Test/TestFitting.cpp
index 8950dd82..8bb10f97 100644
--- a/src/Test/TestFitting.cpp
+++ b/src/Test/TestFitting.cpp
@@ -152,6 +152,7 @@ bool TestFitting::generalNonFunctionTest () const
 
 void TestFitting::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -170,6 +171,7 @@ void TestFitting::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestFormats.cpp b/src/Test/TestFormats.cpp
index 4ef0da70..2bc0d18a 100644
--- a/src/Test/TestFormats.cpp
+++ b/src/Test/TestFormats.cpp
@@ -18,6 +18,7 @@ void TestFormats::cleanupTestCase ()
 
 void TestFormats::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -36,6 +37,7 @@ void TestFormats::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,                
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestGraphCoords.cpp b/src/Test/TestGraphCoords.cpp
index 9d614ccd..99b16c99 100644
--- a/src/Test/TestGraphCoords.cpp
+++ b/src/Test/TestGraphCoords.cpp
@@ -1,3 +1,4 @@
+#include "CallbackAxisPointsAbstract.h"
 #include "CallbackUpdateTransform.h"
 #include "Logger.h"
 #include "MainWindow.h"
@@ -6,6 +7,8 @@
 
 QTEST_MAIN (TestGraphCoords)
 
+const double EPSILON = 0.0;
+
 TestGraphCoords::TestGraphCoords(QObject *parent) :
   QObject(parent)
 {
@@ -19,6 +22,7 @@ void TestGraphCoords::cleanupTestCase ()
 
 void TestGraphCoords::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -37,6 +41,7 @@ void TestGraphCoords::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,                
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
@@ -56,7 +61,8 @@ void TestGraphCoords::testAnyColumnsRepeatNo ()
   vector.push_back (QPointF (300, 100));
   vector.push_back (QPointF (200, 200));
 
-  QVERIFY (!m_callback->anyPointsRepeatPair (vector));
+  QVERIFY (!m_callback->anyPointsRepeatPair (vector,
+                                             EPSILON));
 }
 
 void TestGraphCoords::testAnyColumnsRepeatYes ()
@@ -68,7 +74,8 @@ void TestGraphCoords::testAnyColumnsRepeatYes ()
   vector.push_back (QPointF (100, 100));
   vector.push_back (QPointF (200, 200));
 
-  QVERIFY (m_callback->anyPointsRepeatPair (vector));
+  QVERIFY (m_callback->anyPointsRepeatPair (vector,
+                                            EPSILON));
 }
 
 void TestGraphCoords::testThreeCollinearPointsNo ()
@@ -78,7 +85,9 @@ void TestGraphCoords::testThreeCollinearPointsNo ()
                 100, 150, 200,
                 1  , 1  , 1  );
 
-  QVERIFY (!m_callback->threePointsAreCollinear (m));
+  QVERIFY (!m_callback->threePointsAreCollinear (m,
+                                                 CallbackAxisPointsAbstract::LinearOrLog::COORD_IS_LINEAR,
+                                                 CallbackAxisPointsAbstract::LinearOrLog::COORD_IS_LINEAR));
 }
 
 void TestGraphCoords::testThreeCollinearPointsYes ()
@@ -88,5 +97,7 @@ void TestGraphCoords::testThreeCollinearPointsYes ()
                 100, 150, 200,
                 1  , 1  , 1  );
 
-  QVERIFY (m_callback->threePointsAreCollinear (m));
+  QVERIFY (m_callback->threePointsAreCollinear (m,
+                                                CallbackAxisPointsAbstract::LinearOrLog::COORD_IS_LINEAR,
+                                                CallbackAxisPointsAbstract::LinearOrLog::COORD_IS_LINEAR));
 }
diff --git a/src/Test/TestGridLineLimiter.cpp b/src/Test/TestGridLineLimiter.cpp
index 7b4f2f51..1d4d9bd5 100644
--- a/src/Test/TestGridLineLimiter.cpp
+++ b/src/Test/TestGridLineLimiter.cpp
@@ -24,6 +24,7 @@ void TestGridLineLimiter::cleanupTestCase ()
 
 void TestGridLineLimiter::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -42,6 +43,7 @@ void TestGridLineLimiter::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,                
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestMatrix.cpp b/src/Test/TestMatrix.cpp
index 1597e05e..cf152d72 100644
--- a/src/Test/TestMatrix.cpp
+++ b/src/Test/TestMatrix.cpp
@@ -19,6 +19,7 @@ void TestMatrix::cleanupTestCase ()
 
 void TestMatrix::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -37,6 +38,7 @@ void TestMatrix::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,                
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestProjectedPoint.cpp b/src/Test/TestProjectedPoint.cpp
index aa283eb3..91b4f280 100644
--- a/src/Test/TestProjectedPoint.cpp
+++ b/src/Test/TestProjectedPoint.cpp
@@ -26,6 +26,7 @@ void TestProjectedPoint::cleanupTestCase ()
 
 void TestProjectedPoint::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -44,6 +45,7 @@ void TestProjectedPoint::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
@@ -69,8 +71,8 @@ void TestProjectedPoint::testProjectedPoints ()
   int angleStep = 13;
 
   // Critical angle in degrees
-  int angleCriticalRight = (int) (0.5 + qAcos (radiusCircle / radiusProjection) * RADIANS_TO_DEGREES);
-  int angleCriticalUp = (int) (0.5 + qAsin (radiusCircle / radiusProjection) * RADIANS_TO_DEGREES);
+  int angleCriticalRight = qFloor (0.5 + qAcos (radiusCircle / radiusProjection) * RADIANS_TO_DEGREES);
+  int angleCriticalUp = qFloor (0.5 + qAsin (radiusCircle / radiusProjection) * RADIANS_TO_DEGREES);
 
   for (int angle = 0; angle <= 360; angle += angleStep) {
 
diff --git a/src/Test/TestSegmentFill.cpp b/src/Test/TestSegmentFill.cpp
index 4fb8d3a4..b8cfeeb1 100644
--- a/src/Test/TestSegmentFill.cpp
+++ b/src/Test/TestSegmentFill.cpp
@@ -30,6 +30,7 @@ void TestSegmentFill::cleanupTestCase ()
 
 void TestSegmentFill::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -48,6 +49,7 @@ void TestSegmentFill::initTestCase ()
 
   MainWindow m (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestSpline.cpp b/src/Test/TestSpline.cpp
index 68fa6db6..6d0d4a2d 100644
--- a/src/Test/TestSpline.cpp
+++ b/src/Test/TestSpline.cpp
@@ -1,15 +1,26 @@
+#include <iostream>
 #include "Logger.h"
 #include "MainWindow.h"
+#include <map>
 #include <qmath.h>
 #include <QtTest/QtTest>
 #include "Spline.h"
 #include "SplinePair.h"
+#include <sstream>
 #include "Test/TestSpline.h"
 
 QTEST_MAIN (TestSpline)
 
 using namespace std;
 
+const QString WEBPAGE ("https://tools.timodenk.com/cubic-spline-interpolation");
+
+// Flags to enable extra information for investigating splines
+//#define SHOWCOEFFICIENTS 1
+//#define GNUPLOT 1
+
+const int NUM_ITERATIONS = 24;
+
 TestSpline::TestSpline(QObject *parent) :
   QObject(parent)
 {
@@ -20,8 +31,162 @@ void TestSpline::cleanupTestCase ()
 
 }
 
+bool TestSpline::coefCheckX (const vector<double> &t,
+#ifdef SHOWCOEFFICIENTS
+                             const vector<SplinePair> &xy,
+#else
+                             const vector<SplinePair> & /* xy */,
+#endif
+                             const Spline &s) const
+{
+  unsigned int i;
+  double aUntranslated = 0, bUntranslated = 0, cUntranslated = 0, dUntranslated = 0;
+
+  // X coordinate fit
+#ifdef SHOWCOEFFICIENTS
+  cout << endl
+       << "(t,x) inputs to be copied to " << WEBPAGE.toLatin1().data()
+       << endl;
+  for (i = 0; i < t.size(); i++) {
+    cout << t[i] << "   " << xy[i].x() << endl;
+  }
+  cout << endl
+       << "x=d*(t-ti)^3+c*(t-ti)^2+b*(t-ti)+a natural cubic spline results to be used in this code"
+       << endl;
+  for (i = 0; i < t.size() - 1; i++) {
+    coefShow ("x =",
+              "(t-ti)",
+              t[i],
+              t[i+1],
+              s.m_elements[i].a().x(),
+              s.m_elements[i].b().x(),
+              s.m_elements[i].c().x(),
+              s.m_elements[i].d().x());
+  }
+  cout << endl
+       << "x=d*t^3+c*t^2+b*t+a outputs to be compared to results from " << WEBPAGE.toLatin1().data()
+       << endl;
+#endif
+  for (i = 0; i < t.size() - 1; i++) {
+    s.computeUntranslatedCoefficients (s.m_elements[i].a().x(),
+                                       s.m_elements[i].b().x(),
+                                       s.m_elements[i].c().x(),
+                                       s.m_elements[i].d().x(),
+                                       t[i],
+                                       aUntranslated,
+                                       bUntranslated,
+                                       cUntranslated,
+                                       dUntranslated);
+#ifdef SHOWCOEFFICIENTS
+    coefShow ("x =",
+              "t",
+              t[i],
+              t[i+1],
+              aUntranslated,
+              bUntranslated,
+              cUntranslated,
+              dUntranslated);
+#endif
+  }
+
+  // Spot check the (arbitrarily chosen) final row with results from the WEBPAGE
+  bool success = true;
+  success &= (qAbs (aUntranslated - -8.3608) < 8.3608 / 10000.0);
+  success &= (qAbs (bUntranslated - 4.2505) < 4.2505 / 10000.0);
+  success &= (qAbs (cUntranslated - -0.63092) < 0.63092 / 10000.0);
+  success &= (qAbs (dUntranslated - 0.035051) < 0.035051 / 10000.0);
+
+  return success;
+}
+
+bool TestSpline::coefCheckY (const vector<double> &t,
+#ifdef SHOWCOEFFICIENTS
+                             const vector<SplinePair> &xy,
+#else
+                             const vector<SplinePair> & /* xy */,
+#endif
+                             const Spline &s) const
+{
+  unsigned int i;
+  double aUntranslated = 0, bUntranslated = 0, cUntranslated = 0, dUntranslated = 0;
+
+  // Y coordinate fit
+#ifdef SHOWCOEFFICIENTS
+  cout << endl
+       << "(t,y) inputs to be copied to " << WEBPAGE.toLatin1().data()
+       << endl;
+  for (i = 0; i < xy.size(); i++) {
+    cout << t[i] << "   " << xy[i].y() << endl;
+  }
+  cout << endl
+       << "y=d*(t-ti)^3+c*(t-ti)^2+b*(t-ti)+a natural cubic spline results to be used in this code"
+       << endl;
+  for (i = 0; i < xy.size() - 1; i++) {
+    coefShow ("y =",
+              "(t-ti)",
+              t[i],
+              t[i+1],
+              s.m_elements[i].a().y(),
+              s.m_elements[i].b().y(),
+              s.m_elements[i].c().y(),
+              s.m_elements[i].d().y());
+  }
+  cout << endl
+       << "y=d*t^3+c*t^2+b*t+a outputs to be compared to results from " << WEBPAGE.toLatin1().data()
+       << endl;
+#endif
+  for (i = 0; i < t.size() - 1; i++) {
+    s.computeUntranslatedCoefficients (s.m_elements[i].a().y(),
+                                       s.m_elements[i].b().y(),
+                                       s.m_elements[i].c().y(),
+                                       s.m_elements[i].d().y(),
+                                       t[i],
+                                       aUntranslated,
+                                       bUntranslated,
+                                       cUntranslated,
+                                       dUntranslated);
+#ifdef SHOWCOEFFICIENTS
+    coefShow ("y =",
+              "t",
+              t[i],
+              t[i+1],
+              aUntranslated,
+              bUntranslated,
+              cUntranslated,
+              dUntranslated);
+#endif
+  }
+
+  // Spot check the (arbitrarily chosen) final row with results from the WEBPAGE
+  bool success = true;
+  success &= (qAbs (aUntranslated - -7.0) < 7.0 / 10000.0);
+  success &= (qAbs (bUntranslated - 3.5667) < 3.5667 / 10000.0);
+  success &= (qAbs (cUntranslated - -0.6) < 0.6 / 10000.0);
+  success &= (qAbs (dUntranslated - 0.033333) < 0.033333 / 10000.0);
+
+  return success;
+}
+
+void TestSpline::coefShow (const QString &leftHandSide,
+                           const QString &independentVariable,
+                           double tLow,
+                           double tHigh,
+                           double a,
+                           double b,
+                           double c,
+                           double d) const
+{
+  cout << leftHandSide.toLatin1().data() << scientific
+       << d << "*" << independentVariable.toLatin1().data() << "^3 + "
+       << c << "*" << independentVariable.toLatin1().data() << "^2 + "
+       << b << "*" << independentVariable.toLatin1().data() << " + "
+       << a << " (" << tLow << "<t<" << tHigh << ")" << endl;
+
+}
+
 void TestSpline::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -40,6 +205,7 @@ void TestSpline::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
@@ -51,6 +217,143 @@ void TestSpline::initTestCase ()
   w.show ();
 }
 
+void TestSpline::testCoefficientsFromOrdinals ()
+{
+  bool success = true;
+  vector<double> t;
+  vector<SplinePair> xy;
+
+  // Input data for testSharpTransition
+  xy.push_back (SplinePair (0.1, 1.0));
+  xy.push_back (SplinePair (0.5, 1.0));
+  xy.push_back (SplinePair (0.8, 1.0));
+  xy.push_back (SplinePair (1.0, 0.5));
+  xy.push_back (SplinePair (1.01, 0));
+  xy.push_back (SplinePair (1.5, 0.0));
+  xy.push_back (SplinePair (2.0, 0.0));
+
+  int counter = 0;
+  vector<SplinePair>::const_iterator itr;
+  for (itr = xy.begin(); itr != xy.end(); itr++) {
+    t.push_back (counter++);
+  }
+
+  // Generate the spline
+  Spline s (t, xy);
+
+  success &= coefCheckX (t,
+                         xy,
+                         s);
+  success &= coefCheckY (t,
+                         xy,
+                         s);
+
+  QVERIFY(success);
+}
+
+void TestSpline::testSharpTransition ()
+{
+  const int NUM_T = 60;
+  const double SPLINE_EPSILON = 0.01;
+
+  map<double, bool> xMerged; // Preserve order
+
+  bool success = true;
+
+  vector<double> t;
+  vector<SplinePair> xyBefore;
+
+  // Values with a sharp transition that can trigger overlap (=not a function)
+  xyBefore.push_back (SplinePair (0.1, 1.0));
+  xyBefore.push_back (SplinePair (0.5, 1.0));
+  xyBefore.push_back (SplinePair (0.8, 1.0));
+  xyBefore.push_back (SplinePair (1.0, 0.5));
+  xyBefore.push_back (SplinePair (1.01, 0));
+  xyBefore.push_back (SplinePair (1.5, 0.0));
+  xyBefore.push_back (SplinePair (2.0, 0.0));
+
+  // Copy x values into t vector and initial version of xMerged vector
+  vector<SplinePair>::const_iterator itrB;
+  for (itrB = xyBefore.begin(); itrB != xyBefore.end(); itrB++) {
+    const SplinePair &pair = *itrB;
+    t.push_back (pair.x());
+    xMerged [pair.x ()] = true;
+  }
+
+  // Merge many more plotting points into xMerged
+  double tStart = t[0];
+  double tStop = t[t.size() - 1];
+  for (int i = 0; i <= NUM_T; i++) {
+    double t = tStart + (double) i * (tStop - tStart) / (double) NUM_T;
+
+    if (xMerged.find (t) == xMerged.end ()) {
+      xMerged [t] = true;
+    }
+  }
+
+  // Generate the spline
+  Spline s (t, xyBefore, SPLINE_DISABLE_T_CHECK);
+
+  // Plot the points after generating the spline
+  vector<SplinePair> xyAfter;
+  map<double, bool>::const_iterator itrX;
+  for (itrX = xMerged.begin(); itrX != xMerged.end(); itrX++) {
+    double x = itrX->first;
+    SplinePair pair = s.interpolateCoeff (x);
+    xyAfter.push_back (pair);
+  }
+
+#ifdef GNUPLOT
+  cout << "set datafile missing \"?\"" << endl;
+  cout << "plot \"gnuplot.in\" using 1:2 with linespoints, \"gnuplot.in\" using 1:3 with lines" << endl;
+#endif
+
+  // Output the merged before/after curves
+  map<double, bool>::const_iterator itrM;
+  for (itrM = xMerged.begin(); itrM != xMerged.end(); itrM++) {
+    double x = itrM->first;
+
+    string yB = "?", yA = "?";
+
+    vector<SplinePair>::iterator itrB;
+    for (itrB = xyBefore.begin(); itrB != xyBefore.end(); itrB++) {
+      if (itrB->x() == x) {
+        ostringstream osB;
+        osB << itrB->y();
+        yB = osB.str();
+        break;
+      }
+    }
+
+    vector<SplinePair>::iterator itrA;
+    for (itrA = xyAfter.begin(); itrA != xyAfter.end(); itrA++) {
+      if (itrA->x() == x) {
+        ostringstream osA;
+        osA << itrA->y();
+        yA = osA.str();
+        break;
+      }
+    }
+
+    if (itrB != xyBefore.end() &&
+        itrA != xyAfter.end()) {
+
+      // This x value has y values from both before and after that we can compare for success
+      double yBefore = itrB->y();
+      double yAfter = itrA->y();
+      if (qAbs (yBefore - yAfter) > SPLINE_EPSILON) {
+        success = false;
+      }
+    }
+
+#ifdef GNUPLOT
+    cout << x << ", " << yB << ", " << yA << endl;
+#endif
+  }
+
+  QVERIFY (success);
+}
+
 void TestSpline::testSplinesAsControlPoints ()
 {
   const int T_START = 1, T_STOP = 7;
@@ -62,7 +365,7 @@ void TestSpline::testSplinesAsControlPoints ()
   vector<double> t;
   vector<SplinePair> xy;
   
-  // Independent variable must be evenly spaced
+  // Independent variable are evenly spaced
   t.push_back (T_START);
   t.push_back (2);
   t.push_back (3);
diff --git a/src/Test/TestSpline.h b/src/Test/TestSpline.h
index 400d7056..bd1640e7 100644
--- a/src/Test/TestSpline.h
+++ b/src/Test/TestSpline.h
@@ -2,6 +2,11 @@
 #define TEST_SPLINE_H
 
 #include <QObject>
+#include <QString>
+#include "SplinePair.h"
+#include <vector>
+
+class Spline;
 
 /// Unit test of spline library
 class TestSpline : public QObject
@@ -17,7 +22,25 @@ private slots:
   void cleanupTestCase ();
   void initTestCase ();
 
+  void testCoefficientsFromOrdinals (); /// Compare with third party calculations on a web page
+  void testSharpTransition (); /// Uses x values in t array to get single-valued function across sharp transition
   void testSplinesAsControlPoints ();
+
+private:
+  bool coefCheckX (const std::vector<double> &t,
+                   const std::vector<SplinePair> &xy,
+                   const Spline &s) const;
+  bool coefCheckY (const std::vector<double> &t,
+                   const std::vector<SplinePair> &xy,
+                   const Spline &s) const;
+  void coefShow (const QString &leftHandSide,
+                 const QString &independentVariable,
+                 double tLow,
+                 double tHigh,
+                 double a,
+                 double b,
+                 double c,
+                 double d) const;
 };
 
 #endif // TEST_SPLINE_H
diff --git a/src/Test/TestSplineDrawer.cpp b/src/Test/TestSplineDrawer.cpp
new file mode 100644
index 00000000..dbb2f16e
--- /dev/null
+++ b/src/Test/TestSplineDrawer.cpp
@@ -0,0 +1,156 @@
+#include "DocumentModelCoords.h"
+#include "DocumentModelGeneral.h"
+#include "Logger.h"
+#include "MainWindow.h"
+#include "MainWindowModel.h"
+#include <map>
+#include <qmath.h>
+#include <QtTest/QtTest>
+#include "Spline.h"
+#include "SplineDrawer.h"
+#include "SplinePair.h"
+#include <sstream>
+#include "Test/TestSplineDrawer.h"
+#include "Transformation.h"
+
+QTEST_MAIN (TestSplineDrawer)
+
+using namespace std;
+
+TestSplineDrawer::TestSplineDrawer(QObject *parent) :
+  QObject(parent)
+{
+}
+
+void TestSplineDrawer::cleanupTestCase ()
+{
+
+}
+
+void TestSplineDrawer::initTestCase ()
+{
+  const bool NO_DROP_REGRESSION = false;
+  const QString NO_ERROR_REPORT_LOG_FILE;
+  const QString NO_REGRESSION_OPEN_FILE;
+  const bool NO_GNUPLOT_LOG_FILES = false;
+  const bool NO_REGRESSION_IMPORT = false;
+  const bool NO_RESET = false;
+  const bool NO_EXPORT_ONLY = false;
+  const bool NO_EXPORT_IMAGE_ONLY = false;
+  const QString NO_EXPORT_IMAGE_EXTENSION;
+  const bool DEBUG_FLAG = false;
+  const QStringList NO_LOAD_STARTUP_FILES;
+  const QStringList NO_COMMAND_LINE;  
+
+  initializeLogging ("engauge_test",
+                     "engauge_test.log",
+                     DEBUG_FLAG);
+
+  MainWindow w (NO_ERROR_REPORT_LOG_FILE,
+                NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
+                NO_REGRESSION_IMPORT,
+                NO_GNUPLOT_LOG_FILES,
+                NO_RESET,
+                NO_EXPORT_ONLY,
+                NO_EXPORT_IMAGE_ONLY,
+                NO_EXPORT_IMAGE_EXTENSION,                
+                NO_LOAD_STARTUP_FILES,
+                NO_COMMAND_LINE);
+  w.show ();
+}
+
+bool TestSplineDrawer::testMultiValuedGeneric (const vector<SplinePair> &xy,
+                                               const vector<bool> &isMultiValued) const
+{
+  bool success = true;
+  vector<double> t;
+
+  // Models
+  DocumentModelCoords modelCoords;
+  DocumentModelGeneral modelGeneral;
+  MainWindowModel modelMainWindow;
+
+  modelCoords.setCoordScaleXTheta (COORD_SCALE_LOG);
+  modelCoords.setCoordScaleYRadius (COORD_SCALE_LINEAR);
+
+  // Transformation
+  Transformation trans;
+  trans.setModelCoords (modelCoords,
+                        modelGeneral,
+                        modelMainWindow);
+  QTransform matrixScreen (198.5  , 627.562, 55.625 ,
+                           562.562, 562.562, 155.562,
+                           1      , 1      , 1      );
+  QTransform matrixGraph (0.001, 1.0, 0.0001,
+                          0    , 0  , 30    ,
+                          1    , 1  , 1     );
+  trans.updateTransformFromMatrices (matrixScreen,
+                                     matrixGraph);
+
+  int counter = 0;
+  vector<SplinePair>::const_iterator itr;
+  for (itr = xy.begin(); itr != xy.end(); itr++) {
+    t.push_back (counter++);
+  }
+
+  // Generate the spline
+  Spline s (t, xy);
+
+  SplineDrawer sd (trans);
+  for (unsigned int segment = 0; segment < isMultiValued.size(); segment++) {
+    if (isMultiValued [segment] != sd.segmentIsMultiValued (s,
+                                                            xy.size(),
+                                                            segment)) {
+      success = false;
+    }
+  }
+
+  return success;
+}
+
+void TestSplineDrawer::testMultiValuedLeadingOverlap ()
+{
+  vector<SplinePair> xy;
+  vector<bool> isMultiValued;
+
+  xy.push_back (SplinePair (198.388, 426.423)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (198.531, 399.463)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (384.589, 263.384)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (409.525, 250.684)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (441.360, 535.685)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (484.557, 358.601)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (495.663, 454.633)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (527.411, 182.426)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (633.561, 155.353)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (756.603, 358.646)); // Last point has no corresponding segment
+
+  bool success = testMultiValuedGeneric (xy,
+                                         isMultiValued);
+
+  QVERIFY (success);
+}
+
+void TestSplineDrawer::testMultiValuedTrailingOverlap ()
+{
+  vector<SplinePair> xy;
+  vector<bool> isMultiValued;
+
+  // Same data as testMultiValuedLeadingOverlap but horizontally flipped about x=(198+756)/2
+  double maxPlusMin = 756.603 + 198.388;
+  xy.push_back (SplinePair (maxPlusMin - 756.603, 358.646)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 633.561, 155.353)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 527.411, 182.426)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 495.663, 454.633)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 484.557, 358.601)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 441.360, 535.685)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (maxPlusMin - 409.525, 250.684)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (maxPlusMin - 384.589, 263.384)); isMultiValued.push_back (false);
+  xy.push_back (SplinePair (maxPlusMin - 198.531, 399.463)); isMultiValued.push_back (true);
+  xy.push_back (SplinePair (maxPlusMin - 198.388, 426.423)); // Last point has no corresponding segment
+
+  bool success = testMultiValuedGeneric (xy,
+                                         isMultiValued);
+
+  QVERIFY (success);
+}
diff --git a/src/Test/TestSplineDrawer.h b/src/Test/TestSplineDrawer.h
new file mode 100644
index 00000000..ae9c9a52
--- /dev/null
+++ b/src/Test/TestSplineDrawer.h
@@ -0,0 +1,34 @@
+#ifndef TEST_SPLINE_DRAWER_H
+#define TEST_SPLINE_DRAWER_H
+
+#include <QObject>
+#include <QString>
+#include "SplinePair.h"
+#include <vector>
+
+class Spline;
+
+/// Unit test of spline drawer, which classifies single- versus multi-valued data
+class TestSplineDrawer : public QObject
+{
+  Q_OBJECT
+public:
+  /// Single constructor.
+  explicit TestSplineDrawer(QObject *parent = 0);
+
+signals:
+
+private slots:
+  void cleanupTestCase ();
+  void initTestCase ();
+
+  void testMultiValuedLeadingOverlap (); /// Overlap in first segment, and once in middle
+  void testMultiValuedTrailingOverlap (); /// Overlap in final segment, and once in middle
+
+private:
+
+  bool testMultiValuedGeneric (const std::vector<SplinePair> &xy,
+                               const std::vector<bool> &isMultiValued) const;
+};
+
+#endif // TEST_SPLINE_DRAWER_H
diff --git a/src/Test/TestTransformation.cpp b/src/Test/TestTransformation.cpp
index 2b116235..4050dab3 100644
--- a/src/Test/TestTransformation.cpp
+++ b/src/Test/TestTransformation.cpp
@@ -33,6 +33,7 @@ double TestTransformation::differenceMagnitude (const QPointF &vector1,
 }
 void TestTransformation::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -51,6 +52,7 @@ void TestTransformation::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestValidators.cpp b/src/Test/TestValidators.cpp
index 08ef47cc..0989132b 100644
--- a/src/Test/TestValidators.cpp
+++ b/src/Test/TestValidators.cpp
@@ -20,6 +20,7 @@ void TestValidators::cleanupTestCase ()
 
 void TestValidators::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -38,6 +39,7 @@ void TestValidators::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Test/TestZoomTransition.cpp b/src/Test/TestZoomTransition.cpp
index 3e4cdd54..11b3a1ef 100644
--- a/src/Test/TestZoomTransition.cpp
+++ b/src/Test/TestZoomTransition.cpp
@@ -25,6 +25,7 @@ void TestZoomTransition::cleanupTestCase ()
 
 void TestZoomTransition::initTestCase ()
 {
+  const bool NO_DROP_REGRESSION = false;
   const QString NO_ERROR_REPORT_LOG_FILE;
   const QString NO_REGRESSION_OPEN_FILE;
   const bool NO_GNUPLOT_LOG_FILES = false;
@@ -43,6 +44,7 @@ void TestZoomTransition::initTestCase ()
 
   MainWindow w (NO_ERROR_REPORT_LOG_FILE,
                 NO_REGRESSION_OPEN_FILE,
+                NO_DROP_REGRESSION,
                 NO_REGRESSION_IMPORT,
                 NO_GNUPLOT_LOG_FILES,
                 NO_RESET,
diff --git a/src/Transformation/Transformation.h b/src/Transformation/Transformation.h
index 86a52bc0..ac2881f9 100644
--- a/src/Transformation/Transformation.h
+++ b/src/Transformation/Transformation.h
@@ -32,6 +32,7 @@ class Transformation
 {
   // For unit testing
   friend class TestExport;
+  friend class TestSplineDrawer;
   friend class TestTransformation;
 
 public:
diff --git a/src/Transformation/TransformationStateContext.cpp b/src/Transformation/TransformationStateContext.cpp
index fb81ff81..25d43dfd 100644
--- a/src/Transformation/TransformationStateContext.cpp
+++ b/src/Transformation/TransformationStateContext.cpp
@@ -27,6 +27,7 @@ TransformationStateContext::TransformationStateContext(QGraphicsScene &scene,
 
 TransformationStateContext::~TransformationStateContext()
 {
+  qDeleteAll (m_states);
 }
 
 bool TransformationStateContext::isGnuplot() const
diff --git a/src/Translator/TranslatorContainer.cpp b/src/Translator/TranslatorContainer.cpp
index 0a900e44..7e3c44bb 100644
--- a/src/Translator/TranslatorContainer.cpp
+++ b/src/Translator/TranslatorContainer.cpp
@@ -14,10 +14,10 @@ TranslatorContainer::TranslatorContainer(QApplication & /* app */)
   settings.beginGroup(SETTINGS_GROUP_MAIN_WINDOW);
 
   // Get the locale settings outside of the settings retrieval methods in MainWindow
-  QLocale::Language language = (QLocale::Language) settings.value (SETTINGS_LOCALE_LANGUAGE,
-                                                                   QVariant (localeDefault.language())).toInt();
-  QLocale::Country country = (QLocale::Country) settings.value (SETTINGS_LOCALE_COUNTRY,
-                                                                QVariant (localeDefault.country())).toInt();
+  QLocale::Language language = static_cast<QLocale::Language> (settings.value (SETTINGS_LOCALE_LANGUAGE,
+                                                                               QVariant (localeDefault.language())).toInt());
+  QLocale::Country country = static_cast<QLocale::Country> (settings.value (SETTINGS_LOCALE_COUNTRY,
+                                                                            QVariant (localeDefault.country())).toInt());
   QLocale locale (language,
                   country);
   
@@ -30,10 +30,12 @@ TranslatorContainer::TranslatorContainer(QApplication & /* app */)
   if ((localeDefault.name().toLower() != "en_us") ||
       (localeDefault.name().toLower() != locale.name().toLower())) {
 
+    QString localeName = locale.name().toLower();
+
     // Basic translators, like buttons in QWizard
     m_translatorGeneric = new QTranslator;
-    m_translatorGeneric->load ("qt_" + locale.name().toLower(),
-                               QLibraryInfo::location (QLibraryInfo::TranslationsPath));
+    m_translatorGeneric->load ("qt_" + localeName,
+                                QLibraryInfo::location (QLibraryInfo::TranslationsPath));
     QApplication::installTranslator (m_translatorGeneric);
 
     // Engauge-specific translators. As documented in engauge.pro, the country-specific engauge_XX_YY locale is loaded
@@ -43,15 +45,28 @@ TranslatorContainer::TranslatorContainer(QApplication & /* app */)
     // QCoreApplication::applicationDirPath points to ../Engauge Digitizer.app/Contents/MacOS (which we want)
     QString delimiters ("._");
     m_translatorEngauge = new QTranslator;
+    // Handle usual translations like es_es
+    bool rtn = m_translatorEngauge->load ("engauge_" + localeName,
+                                           qmDirectory(),
+                                           delimiters);
+    if (!rtn) {
+      // Handle country-specific translations like fa_IR. Transifex capitalizes the last two characters
+      QString localeNameUpper = QString ("%1%2")
+          .arg (localeName.left (localeName.length() - 2))
+          .arg (localeName.right (2).toUpper ());
+      m_translatorEngauge->load ("engauge_" + localeNameUpper,
+                                 qmDirectory(),
+                                 delimiters);
+    }
+    QApplication::installTranslator (m_translatorEngauge);
+  }
+}
+
+QString TranslatorContainer::qmDirectory()
+{
 #if defined(OSX_DEBUG) || defined(OSX_RELEASE)
-    m_translatorEngauge->load ("engauge_" + locale.name().toLower(),
-                               QCoreApplication::applicationDirPath () + "/../Resources/translations",
-                               delimiters);
+    return QCoreApplication::applicationDirPath () + "/../Resources/translations";
 #else
-    m_translatorEngauge->load ("engauge_" + locale.name().toLower(),
-                               QCoreApplication::applicationDirPath () + "/translations",
-                               delimiters);
+    return QCoreApplication::applicationDirPath () + "/translations";
 #endif
-    QApplication::installTranslator (m_translatorEngauge);
-  }
 }
diff --git a/src/Translator/TranslatorContainer.h b/src/Translator/TranslatorContainer.h
index 2c79c2eb..5d6b4de2 100644
--- a/src/Translator/TranslatorContainer.h
+++ b/src/Translator/TranslatorContainer.h
@@ -1,6 +1,8 @@
 #ifndef TRANSLATOR_CONTAINER_H
 #define TRANSLATOR_CONTAINER_H
 
+#include <QString>
+
 class QApplication;
 class QTranslator;
 
@@ -11,6 +13,9 @@ class TranslatorContainer
   /// Single constructor. Argument is needed so object is not optimized away in main() in Windows
   TranslatorContainer(QApplication &app);
 
+  /// Platform dependent directory containing qm translation files
+  static QString qmDirectory ();
+
  private:
   TranslatorContainer();
 
diff --git a/src/Tutorial/TutorialButton.cpp b/src/Tutorial/TutorialButton.cpp
index 0dd12c67..de5e04d9 100644
--- a/src/Tutorial/TutorialButton.cpp
+++ b/src/Tutorial/TutorialButton.cpp
@@ -9,6 +9,7 @@
 #include <QGraphicsRectItem>
 #include <QGraphicsScene>
 #include <QGraphicsTextItem>
+#include <qmath.h>
 #include "TutorialButton.h"
 #include "TutorialButtonRect.h"
 #include "TutorialButtonText.h"
@@ -18,7 +19,9 @@ const int VERTICAL_PADDING = 5;
 const double Z_IN_FRONT = 1;
 
 TutorialButton::TutorialButton (const QString &text,
-                                QGraphicsScene &scene)
+                                QGraphicsScene &scene) :
+  m_rect (nullptr),
+  m_text (nullptr)
 {
   createRect (scene);
   createText (text);
@@ -26,8 +29,13 @@ TutorialButton::TutorialButton (const QString &text,
 
 TutorialButton::~TutorialButton ()
 {
-  QGraphicsScene *scene = m_rect->scene();
-  scene->removeItem (m_rect); // This also removes m_text from the scene
+  if (m_rect != nullptr) {
+    QGraphicsScene *scene = m_rect->scene();
+    scene->removeItem (m_rect); // This also removes m_text from the scene
+
+    delete m_rect;
+  }
+  delete m_text;
 }
 
 void TutorialButton::createRect (QGraphicsScene &scene)
@@ -54,8 +62,8 @@ void TutorialButton::createText (const QString &text)
 QSize TutorialButton::size () const
 {
   // The size of the rectangle is not updated until later so we use the size of the text
-  return QSize (m_text->boundingRect().size().width() + 2 * HORIZONTAL_PADDING,
-                m_text->boundingRect().size().height() + 2 * VERTICAL_PADDING);
+  return QSize (qFloor (m_text->boundingRect().size().width() + 2 * HORIZONTAL_PADDING),
+                qFloor (m_text->boundingRect().size().height() + 2 * VERTICAL_PADDING));
 }
 
 void TutorialButton::handleTriggered()
diff --git a/src/Tutorial/TutorialDlg.cpp b/src/Tutorial/TutorialDlg.cpp
index 558b493b..897ea58e 100644
--- a/src/Tutorial/TutorialDlg.cpp
+++ b/src/Tutorial/TutorialDlg.cpp
@@ -14,23 +14,33 @@
 #include "TutorialDlg.h"
 #include "TutorialStateContext.h"
 
-const int SCENE_WIDTH = 550;
-const int SCENE_HEIGHT = 450;
+const int SCENE_WIDTH = 580;
+const int SCENE_HEIGHT = 480;
 
 TutorialDlg::TutorialDlg (MainWindow *mainWindow) :
-    QDialog (mainWindow)
+  QDialog (mainWindow),
+  m_context (nullptr),
+  m_scene (nullptr),
+  m_view (nullptr)
 {
   setWindowTitle ("Engauge Digitizer Tutorial");
 
   // Dialog size is determined by scene size
   QVBoxLayout *layout = new QVBoxLayout;
-  layout->setSizeConstraint (QLayout::SetFixedSize);
+  layout->setSizeConstraint (QLayout::SetMinimumSize);
   setLayout (layout);
 
   createSceneAndView();
   createContext();
 }
 
+TutorialDlg::~TutorialDlg ()
+{
+  delete m_view;
+  delete m_scene;
+  delete m_context;
+}
+
 QSize TutorialDlg::backgroundSize () const
 {
   return QSize (SCENE_WIDTH,
diff --git a/src/Tutorial/TutorialDlg.h b/src/Tutorial/TutorialDlg.h
index 524b3f8b..3ede2c17 100644
--- a/src/Tutorial/TutorialDlg.h
+++ b/src/Tutorial/TutorialDlg.h
@@ -21,6 +21,7 @@ class TutorialDlg : public QDialog
  public:
   /// Single constructor
   TutorialDlg (MainWindow *mainWindow);
+  ~TutorialDlg ();
 
   /// Make geometry available for layout
   QSize backgroundSize () const;
diff --git a/src/Tutorial/TutorialStateAxisPoints.cpp b/src/Tutorial/TutorialStateAxisPoints.cpp
index b1b5917e..9099cc31 100644
--- a/src/Tutorial/TutorialStateAxisPoints.cpp
+++ b/src/Tutorial/TutorialStateAxisPoints.cpp
@@ -15,7 +15,14 @@
 #include "TutorialStateContext.h"
 
 TutorialStateAxisPoints::TutorialStateAxisPoints (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_previous (nullptr),
+  m_next (nullptr)
 {
 }
 
@@ -23,6 +30,8 @@ void TutorialStateAxisPoints::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateAxisPoints::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Axis Points"));
   m_background = createPixmapItem (":/engauge/img/panel_axis_points.png",
                                    QPoint (0, 30));
@@ -61,28 +70,8 @@ void TutorialStateAxisPoints::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateAxisPoints::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_next;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_next = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateAxisPoints::slotNext ()
diff --git a/src/Tutorial/TutorialStateChecklistWizardAbstract.cpp b/src/Tutorial/TutorialStateChecklistWizardAbstract.cpp
index b35a21bd..425ecf2d 100644
--- a/src/Tutorial/TutorialStateChecklistWizardAbstract.cpp
+++ b/src/Tutorial/TutorialStateChecklistWizardAbstract.cpp
@@ -15,7 +15,14 @@
 #include "TutorialStateContext.h"
 
 TutorialStateChecklistWizardAbstract::TutorialStateChecklistWizardAbstract (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_text3 (nullptr),
+  m_previous (nullptr)
 {
 }
 
@@ -23,6 +30,8 @@ void TutorialStateChecklistWizardAbstract::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateChecklistWizardAbstract::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Checklist Wizard and Checklist Guide"));
   m_background = createPixmapItem (":/engauge/img/panel_checklist.png",
                                    QPoint (0, 30));
@@ -57,29 +66,8 @@ void TutorialStateChecklistWizardAbstract::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateChecklistWizardAbstract::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  context().tutorialDlg().scene().removeItem (m_text3);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_text3;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_text3 = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 TutorialButton *TutorialStateChecklistWizardAbstract::previous()
diff --git a/src/Tutorial/TutorialStateChecklistWizardLines.cpp b/src/Tutorial/TutorialStateChecklistWizardLines.cpp
index a99353a6..2514742b 100644
--- a/src/Tutorial/TutorialStateChecklistWizardLines.cpp
+++ b/src/Tutorial/TutorialStateChecklistWizardLines.cpp
@@ -12,6 +12,7 @@
 TutorialStateChecklistWizardLines::TutorialStateChecklistWizardLines (TutorialStateContext &context) : 
   TutorialStateChecklistWizardAbstract (context)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateChecklistWizardLines::TutorialStateChecklistWizardLines";
 }
 
 void TutorialStateChecklistWizardLines::begin ()
diff --git a/src/Tutorial/TutorialStateChecklistWizardPoints.cpp b/src/Tutorial/TutorialStateChecklistWizardPoints.cpp
index 658c08f9..8ac3ad95 100644
--- a/src/Tutorial/TutorialStateChecklistWizardPoints.cpp
+++ b/src/Tutorial/TutorialStateChecklistWizardPoints.cpp
@@ -12,6 +12,7 @@
 TutorialStateChecklistWizardPoints::TutorialStateChecklistWizardPoints (TutorialStateContext &context) : 
   TutorialStateChecklistWizardAbstract (context)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateChecklistWizardPoints::TutorialStateChecklistWizardPoints";
 }
 
 void TutorialStateChecklistWizardPoints::begin ()
diff --git a/src/Tutorial/TutorialStateColorFilter.cpp b/src/Tutorial/TutorialStateColorFilter.cpp
index d6cb988c..0d449f33 100644
--- a/src/Tutorial/TutorialStateColorFilter.cpp
+++ b/src/Tutorial/TutorialStateColorFilter.cpp
@@ -15,14 +15,25 @@
 #include "TutorialStateContext.h"
 
 TutorialStateColorFilter::TutorialStateColorFilter (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_text3 (nullptr),
+  m_text4 (nullptr),
+  m_back (nullptr)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateColorFilter::TutorialStateColorFilter";
 }
 
 void TutorialStateColorFilter::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateColorFilter::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Color Filter"));
   m_background = createPixmapItem (":/engauge/img/panel_color_filter.png",
                                    QPoint (0, 30));
@@ -62,32 +73,8 @@ void TutorialStateColorFilter::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateColorFilter::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  context().tutorialDlg().scene().removeItem (m_text3);
-  context().tutorialDlg().scene().removeItem (m_text4);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_text3;
-  delete m_text4;
-  delete m_back;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_text3 = 0;
-  m_text4 = 0;
-  m_back = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateColorFilter::slotBack ()
diff --git a/src/Tutorial/TutorialStateContext.cpp b/src/Tutorial/TutorialStateContext.cpp
index 81b9140b..48f91a98 100644
--- a/src/Tutorial/TutorialStateContext.cpp
+++ b/src/Tutorial/TutorialStateContext.cpp
@@ -29,6 +29,11 @@ TutorialStateContext::TutorialStateContext (TutorialDlg &tutorialDlg) :
   createTimer ();
 }
 
+TutorialStateContext::~TutorialStateContext ()
+{
+  qDeleteAll (m_states);
+}
+
 void TutorialStateContext::createStates ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateContext::createStates";
diff --git a/src/Tutorial/TutorialStateContext.h b/src/Tutorial/TutorialStateContext.h
index 0faa5793..94d9d27d 100644
--- a/src/Tutorial/TutorialStateContext.h
+++ b/src/Tutorial/TutorialStateContext.h
@@ -25,6 +25,9 @@ class TutorialStateContext : public QObject
   /// Single constructor
   TutorialStateContext(TutorialDlg &tutorialDlg);
 
+  /// Destructor deallocates memory
+  ~TutorialStateContext();
+
   /// Request a transition to the specified state from the current state. A timer is used. This assumes TutorialStateContext
   /// is NOT on the stack - probably since an external event (mouse click, ...) resulted in a callback to the current state
   void requestDelayedStateTransition (TutorialState tutorialState);
diff --git a/src/Tutorial/TutorialStateCurveSelection.cpp b/src/Tutorial/TutorialStateCurveSelection.cpp
index a43b7a69..b95b6924 100644
--- a/src/Tutorial/TutorialStateCurveSelection.cpp
+++ b/src/Tutorial/TutorialStateCurveSelection.cpp
@@ -9,20 +9,33 @@
 #include <QGraphicsPixmapItem>
 #include <QGraphicsScene>
 #include <QGraphicsView>
+#include <qmath.h>
 #include "TutorialButton.h"
 #include "TutorialDlg.h"
 #include "TutorialStateCurveSelection.h"
 #include "TutorialStateContext.h"
 
 TutorialStateCurveSelection::TutorialStateCurveSelection (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_text3 (nullptr),
+  m_previous (nullptr),
+  m_colorFilter (nullptr),  
+  m_next (nullptr)  
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveSelection::TutorialStateCurveSelection";
 }
 
 void TutorialStateCurveSelection::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveSelection::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle ("Curve Selection");
   m_background = createPixmapItem (":/engauge/img/panel_curve_selection.png",
                                    QPoint (0, 30));
@@ -60,8 +73,8 @@ void TutorialStateCurveSelection::begin ()
 
   m_colorFilter = new TutorialButton (tr ("Color Filter Settings"),
                                       context().tutorialDlg().scene());
-  m_colorFilter->setGeometry (QPoint (backgroundSize.width () / 2.0 - m_colorFilter->size ().width () / 2,
-                                      backgroundSize.height () - buttonMargin () - m_colorFilter->size ().height ()));
+  m_colorFilter->setGeometry (QPoint (qFloor (backgroundSize.width () / 2.0 - m_colorFilter->size ().width () / 2),
+                                      qFloor (backgroundSize.height () - buttonMargin () - m_colorFilter->size ().height ())));
   connect (m_colorFilter, SIGNAL (signalTriggered ()), this, SLOT (slotColorFilter ()));
 
   m_next = new TutorialButton (tr ("Next"),
@@ -75,33 +88,8 @@ void TutorialStateCurveSelection::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveSelection::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  context().tutorialDlg().scene().removeItem (m_text3);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_text3;
-  delete m_next;
-  delete m_colorFilter;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_text3 = 0;
-  m_next = 0;
-  m_colorFilter = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateCurveSelection::slotColorFilter ()
diff --git a/src/Tutorial/TutorialStateCurveType.cpp b/src/Tutorial/TutorialStateCurveType.cpp
index 260e94b8..e3467119 100644
--- a/src/Tutorial/TutorialStateCurveType.cpp
+++ b/src/Tutorial/TutorialStateCurveType.cpp
@@ -9,20 +9,32 @@
 #include <QGraphicsPixmapItem>
 #include <QGraphicsScene>
 #include <QGraphicsView>
+#include <qmath.h>
 #include "TutorialButton.h"
 #include "TutorialDlg.h"
 #include "TutorialStateContext.h"
 #include "TutorialStateCurveType.h"
 
 TutorialStateCurveType::TutorialStateCurveType (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_previous (nullptr),
+  m_nextLines (nullptr),
+  m_nextPoints (nullptr)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveType::TutorialStateCurveType";
 }
 
 void TutorialStateCurveType::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveType::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Curve Type"));
   m_background = createPixmapItem (":/engauge/img/panel_lines_points.png",
                                    QPoint (0, 0));
@@ -49,15 +61,15 @@ void TutorialStateCurveType::begin ()
   connect (m_previous, SIGNAL (signalTriggered ()), this, SLOT (slotPrevious ()));
 
   m_nextLines = new TutorialButton (tr ("Next (Lines)"),
-                                     context().tutorialDlg().scene());
-  m_nextLines->setGeometry (QPoint (backgroundSize.width () - buttonMargin () - m_nextLines->size ().width (),
-                                     backgroundSize.height () / 3.0 - m_nextLines->size ().height () / 2.0));
+                                    context().tutorialDlg().scene());
+  m_nextLines->setGeometry (QPoint (qFloor (backgroundSize.width () - buttonMargin () - m_nextLines->size ().width ()),
+                                    qFloor (backgroundSize.height () / 3.0 - m_nextLines->size ().height () / 2.0)));
   connect (m_nextLines, SIGNAL (signalTriggered ()), this, SLOT (slotNextCurves ()));
 
   m_nextPoints = new TutorialButton (tr ("Next (Points)"),
-                                    context().tutorialDlg().scene());
-  m_nextPoints->setGeometry (QPoint (backgroundSize.width () - buttonMargin () - m_nextPoints->size ().width (),
-                                    backgroundSize.height () * 2.0 / 3.0 - m_nextPoints->size ().height () / 2.0));
+                                     context().tutorialDlg().scene());
+  m_nextPoints->setGeometry (QPoint (qFloor (backgroundSize.width () - buttonMargin () - m_nextPoints->size ().width ()),
+                                     qFloor (backgroundSize.height () * 2.0 / 3.0 - m_nextPoints->size ().height () / 2.0)));
   connect (m_nextPoints, SIGNAL (signalTriggered ()), this, SLOT (slotNextLines ()));
 }
 
@@ -65,30 +77,8 @@ void TutorialStateCurveType::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateCurveType::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_nextLines;
-  delete m_nextPoints;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_nextLines = 0;
-  m_nextPoints = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateCurveType::slotNextCurves ()
diff --git a/src/Tutorial/TutorialStateIntroduction.cpp b/src/Tutorial/TutorialStateIntroduction.cpp
index 748dcba9..1c999b2f 100644
--- a/src/Tutorial/TutorialStateIntroduction.cpp
+++ b/src/Tutorial/TutorialStateIntroduction.cpp
@@ -15,14 +15,23 @@
 #include "TutorialStateIntroduction.h"
 
 TutorialStateIntroduction::TutorialStateIntroduction (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_next (nullptr)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateIntroduction::TutorialStateIntroduction";
 }
 
 void TutorialStateIntroduction::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateIntroduction::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Introduction"));
   m_background = createPixmapItem (":/engauge/img/SpreadsheetsForDoc.png",
                                    QPoint (0, 0));
@@ -49,26 +58,8 @@ void TutorialStateIntroduction::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateIntroduction::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_next;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_next = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateIntroduction::slotNext ()
diff --git a/src/Tutorial/TutorialStateIntroduction.h b/src/Tutorial/TutorialStateIntroduction.h
index 7288fbe8..4784d877 100644
--- a/src/Tutorial/TutorialStateIntroduction.h
+++ b/src/Tutorial/TutorialStateIntroduction.h
@@ -22,7 +22,7 @@ class TutorialStateIntroduction : public TutorialStateAbstractBase
  public:
   /// Single constructor
   TutorialStateIntroduction (TutorialStateContext &context);
-
+  
   virtual void begin ();
   virtual void end ();
 
diff --git a/src/Tutorial/TutorialStatePointMatch.cpp b/src/Tutorial/TutorialStatePointMatch.cpp
index 904b9d53..5d9ba77f 100644
--- a/src/Tutorial/TutorialStatePointMatch.cpp
+++ b/src/Tutorial/TutorialStatePointMatch.cpp
@@ -15,14 +15,25 @@
 #include "TutorialStatePointMatch.h"
 
 TutorialStatePointMatch::TutorialStatePointMatch (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_text3 (nullptr),
+  m_previous (nullptr),
+  m_next (nullptr)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStatePointMatch::TutorialStatePointMatch";
 }
 
 void TutorialStatePointMatch::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStatePointMatch::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Point Match"));
   m_background = createPixmapItem (":/engauge/img/panel_point_match.png",
                                    QPoint (0, 30));
@@ -64,31 +75,8 @@ void TutorialStatePointMatch::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStatePointMatch::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  context().tutorialDlg().scene().removeItem (m_text3);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_text3;
-  delete m_next;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_text3 = 0;
-  m_next = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStatePointMatch::slotNext ()
diff --git a/src/Tutorial/TutorialStateSegmentFill.cpp b/src/Tutorial/TutorialStateSegmentFill.cpp
index 948e1bda..42292aaa 100644
--- a/src/Tutorial/TutorialStateSegmentFill.cpp
+++ b/src/Tutorial/TutorialStateSegmentFill.cpp
@@ -15,14 +15,24 @@
 #include "TutorialStateSegmentFill.h"
 
 TutorialStateSegmentFill::TutorialStateSegmentFill (TutorialStateContext &context) : 
-  TutorialStateAbstractBase (context)
+  TutorialStateAbstractBase (context),
+  m_title (nullptr),
+  m_background (nullptr),
+  m_text0 (nullptr),
+  m_text1 (nullptr),
+  m_text2 (nullptr),
+  m_previous (nullptr),
+  m_next (nullptr)
 {
+  LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateSegmentFill::TutorialStateSegmentFill";
 }
 
 void TutorialStateSegmentFill::begin ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateSegmentFill::begin ()";
 
+  context().tutorialDlg().scene().clear ();
+
   m_title = createTitle (tr ("Segment Fill"));
   m_background = createPixmapItem (":/engauge/img/panel_segment_fill.png",
                                    QPoint (0, 30));
@@ -59,28 +69,8 @@ void TutorialStateSegmentFill::end ()
 {
   LOG4CPP_INFO_S ((*mainCat)) << "TutorialStateSegmentFill::end ()";
 
-  context().tutorialDlg().scene().removeItem (m_title);
-  context().tutorialDlg().scene().removeItem (m_background);
-  context().tutorialDlg().scene().removeItem (m_text0);
-  context().tutorialDlg().scene().removeItem (m_text1);
-  context().tutorialDlg().scene().removeItem (m_text2);
-  // TutorialButtons removes themselves from the scene
-
-  delete m_title;
-  delete m_background;
-  delete m_text0;
-  delete m_text1;
-  delete m_text2;
-  delete m_next;
-  delete m_previous;
-
-  m_title = 0;
-  m_background = 0;
-  m_text0 = 0;
-  m_text1 = 0;
-  m_text2 = 0;
-  m_next = 0;
-  m_previous = 0;
+  // It is not safe to remove and deallocate items here since an active TutorialButton
+  // may be on the stack. So we clear the scene as the first step in the next begin()
 }
 
 void TutorialStateSegmentFill::slotNext ()
diff --git a/src/View/ViewPreview.cpp b/src/View/ViewPreview.cpp
index 06b69d10..9c1c897f 100644
--- a/src/View/ViewPreview.cpp
+++ b/src/View/ViewPreview.cpp
@@ -47,7 +47,7 @@ void ViewPreview::resizeEvent(QResizeEvent *event)
     for (int i = 0; i < scene()->items().count (); i++) {
       const QGraphicsItem *item = scene()->items().at (i);
       const QGraphicsPixmapItem *itemPixmap = dynamic_cast<const QGraphicsPixmapItem*> (item);
-      if (itemPixmap != 0) {
+      if (itemPixmap != nullptr) {
         foundImage = true;
         fitInView (itemPixmap->boundingRect());
       }
diff --git a/src/View/ViewProfileDivider.cpp b/src/View/ViewProfileDivider.cpp
index 95272be0..104a7a01 100644
--- a/src/View/ViewProfileDivider.cpp
+++ b/src/View/ViewProfileDivider.cpp
@@ -39,8 +39,8 @@ ViewProfileDivider::ViewProfileDivider (QGraphicsScene &scene,
                      PADDLE_HEIGHT),
   m_view (view),
   m_yCenter (yCenter),
-  m_divider (0),
-  m_shadedArea (0),
+  m_divider (nullptr),
+  m_shadedArea (nullptr),
   m_sceneWidth (sceneWidth),
   m_sceneHeight (sceneHeight),
   m_isLowerBoundary (isLowerBoundary)
@@ -92,7 +92,7 @@ QVariant ViewProfileDivider::itemChange (GraphicsItemChange change, const QVaria
     QPointF newPos = QPointF (value.toPointF().x(), 0.0) + m_startDragPos;
     double newX = newPos.x();
     newX = qMax (newX, 0.0);
-    newX = qMin (newX, (double) m_sceneWidth);
+    newX = qMin (newX, double (m_sceneWidth));
     newPos.setX (newX);
     newPos -= m_startDragPos; // Change from absolute coordinates back to relative coordinates
 
diff --git a/src/View/ViewSegmentFilter.cpp b/src/View/ViewSegmentFilter.cpp
index 1681f367..5778a971 100644
--- a/src/View/ViewSegmentFilter.cpp
+++ b/src/View/ViewSegmentFilter.cpp
@@ -9,6 +9,7 @@
 #include "ColorFilterSettings.h"
 #include "EngaugeAssert.h"
 #include "Logger.h"
+#include <qmath.h>
 #include <QPainter>
 #include <QPixmap>
 #include "ViewSegmentFilter.h"
@@ -37,17 +38,17 @@ QColor ViewSegmentFilter::colorFromSetting (ColorFilterMode coloFilterMode,
   {
     case COLOR_FILTER_MODE_FOREGROUND:
       {
-        double s = (double) (foreground - FOREGROUND_MIN) / (double) (FOREGROUND_MAX - FOREGROUND_MIN);
+        double s = double (foreground - FOREGROUND_MIN) / double (FOREGROUND_MAX - FOREGROUND_MIN);
         if (qGray (m_rgbBackground.rgb ()) < 127) {
           // Go from blackish to white
-          r = s * 255;
-          g = s * 255;
-          b = s * 255;
+          r = qFloor (s * 255);
+          g = qFloor (s * 255);
+          b = qFloor (s * 255);
         } else {
           // Go from whitish to black
-          r = (1.0 - s) * 255;
-          g = (1.0 - s) * 255;
-          b = (1.0 - s) * 255;
+          r = qFloor ((1.0 - s) * 255);
+          g = qFloor ((1.0 - s) * 255);
+          b = qFloor ((1.0 - s) * 255);
         }
       }
       break;
@@ -56,24 +57,24 @@ QColor ViewSegmentFilter::colorFromSetting (ColorFilterMode coloFilterMode,
       {
         // red-green and green-blue like ViewProfileScale::paintHue
 
-        int HUE_THRESHOLD_LOW = 0.666 * HUE_MIN + 0.333 * HUE_MAX;
-        int HUE_THRESHOLD_HIGH = 0.333 * HUE_MIN + 0.666 * HUE_MAX;
+        int HUE_THRESHOLD_LOW = qFloor (0.666 * HUE_MIN + 0.333 * HUE_MAX);
+        int HUE_THRESHOLD_HIGH = qFloor (0.333 * HUE_MIN + 0.666 * HUE_MAX);
 
         if (hue < HUE_THRESHOLD_LOW) {
           // 0-0.333 is red-green
-          double s = (double) (hue - HUE_MIN) / (double) (HUE_THRESHOLD_LOW - HUE_MIN);
-          r = (1.0 - s) * 255;
-          g = s * 255;
+          double s = double (hue - HUE_MIN) / double (HUE_THRESHOLD_LOW - HUE_MIN);
+          r = qFloor ((1.0 - s) * 255);
+          g = qFloor (s * 255);
         } else if (hue < HUE_THRESHOLD_HIGH) {
           // 0.333-0.666 is green-blue
-          double s = (double) (hue - HUE_THRESHOLD_LOW) / (double) (HUE_THRESHOLD_HIGH - HUE_THRESHOLD_LOW);
-          g = (1.0 - s) * 255;
-          b = s * 255;
+          double s = double (hue - HUE_THRESHOLD_LOW) / double (HUE_THRESHOLD_HIGH - HUE_THRESHOLD_LOW);
+          g = qFloor ((1.0 - s) * 255);
+          b = qFloor (s * 255);
         } else {
           // 0.666-1 is blue-red
-          double s = (double) (hue - HUE_THRESHOLD_HIGH) / (double) (HUE_MAX - HUE_THRESHOLD_HIGH);
-          b = (1.0 - s) * 255;
-          r = s * 255;
+          double s = double (hue - HUE_THRESHOLD_HIGH) / double (HUE_MAX - HUE_THRESHOLD_HIGH);
+          b = qFloor ((1.0 - s) * 255);
+          r = qFloor (s * 255);
         }
       }
       break;
@@ -82,10 +83,10 @@ QColor ViewSegmentFilter::colorFromSetting (ColorFilterMode coloFilterMode,
       {
         // black-white like ViewProfileScale::paintIntensity
 
-        double s = (double) (intensity - INTENSITY_MIN) / (double) (INTENSITY_MAX - INTENSITY_MIN);
-        r = s * 255;
-        g = s * 255;
-        b = s * 255;
+        double s = double (intensity - INTENSITY_MIN) / double (INTENSITY_MAX - INTENSITY_MIN);
+        r = qFloor (s * 255);
+        g = qFloor (s * 255);
+        b = qFloor (s * 255);
       }
       break;
 
@@ -93,10 +94,10 @@ QColor ViewSegmentFilter::colorFromSetting (ColorFilterMode coloFilterMode,
       {
         // white-red like ViewProfileScale::paintSaturation
 
-        double s = (double) (saturation - SATURATION_MIN) / (double) (SATURATION_MAX - SATURATION_MIN);
-        r = 255;
-        g = (1.0 - s) * 255;
-        b = (1.0 - s) * 255;
+        double s = double (saturation - SATURATION_MIN) / double (SATURATION_MAX - SATURATION_MIN);
+        r = qFloor (255);
+        g = qFloor ((1.0 - s) * 255);
+        b = qFloor ((1.0 - s) * 255);
       }
       break;
 
@@ -104,10 +105,10 @@ QColor ViewSegmentFilter::colorFromSetting (ColorFilterMode coloFilterMode,
       {
         // black-red like ViewProfileScale::paintValue
 
-        double s = (double) (value - VALUE_MIN) / (double) (VALUE_MAX - VALUE_MIN);
-        r = s * 255;
-        g = 0;
-        b = 0;
+        double s = double (value - VALUE_MIN) / double (VALUE_MAX - VALUE_MIN);
+        r = qFloor (s * 255);
+        g = qFloor (0);
+        b = qFloor (0);
       }
       break;
 
diff --git a/src/Window/WindowAbstractBase.cpp b/src/Window/WindowAbstractBase.cpp
index 07f945eb..a8cf184a 100644
--- a/src/Window/WindowAbstractBase.cpp
+++ b/src/Window/WindowAbstractBase.cpp
@@ -24,7 +24,7 @@ void WindowAbstractBase::getTableStatus (bool &tableIsActive,
   tableIsActive = false;
   tableIsCopyable = false;
 
-  if (view() != 0) {
+  if (view() != nullptr) {
 
     QItemSelectionModel *selectionModel = view()->selectionModel ();
     QModelIndexList selection = selectionModel->selectedIndexes ();
diff --git a/src/Window/WindowModelBase.cpp b/src/Window/WindowModelBase.cpp
index 9d54fe3d..0809c04f 100644
--- a/src/Window/WindowModelBase.cpp
+++ b/src/Window/WindowModelBase.cpp
@@ -14,7 +14,7 @@
 #include "WindowTable.h"
 
 WindowModelBase::WindowModelBase () :
-  m_view (0)
+  m_view (nullptr)
 {
 }
 
@@ -34,7 +34,7 @@ int WindowModelBase::fold2dIndexes (int row,
 QMimeData *WindowModelBase::mimeData(const QModelIndexList &indexes) const
 {
   if (indexes.isEmpty ()) {
-    return Q_NULLPTR;
+    return nullptr;
   }
 
   QMimeData *data = new QMimeData ();
diff --git a/src/Zoom/ZoomLabels.cpp b/src/Zoom/ZoomLabels.cpp
index 65dd082f..a5135f33 100644
--- a/src/Zoom/ZoomLabels.cpp
+++ b/src/Zoom/ZoomLabels.cpp
@@ -7,30 +7,30 @@
 #include <QObject>
 #include "ZoomLabels.h"
 
-const QString LABEL_ZOOM_16_TO_1 ("16:1");
-const QString LABEL_ZOOM_16_TO_1_FARTHER (QObject::tr ("16:1 farther"));
-const QString LABEL_ZOOM_8_TO_1_CLOSER (QObject::tr ("8:1 closer"));
-const QString LABEL_ZOOM_8_TO_1 ("8:1");
-const QString LABEL_ZOOM_8_TO_1_FARTHER (QObject::tr ("8:1 farther"));
-const QString LABEL_ZOOM_4_TO_1_CLOSER (QObject::tr ("4:1 closer"));
-const QString LABEL_ZOOM_4_TO_1 ("4:1");
-const QString LABEL_ZOOM_4_TO_1_FARTHER (QObject::tr ("4:1 farther"));
-const QString LABEL_ZOOM_2_TO_1_CLOSER (QObject::tr ("2:1 closer"));
-const QString LABEL_ZOOM_2_TO_1 ("2:1");
-const QString LABEL_ZOOM_2_TO_1_FARTHER (QObject::tr ("2:1 farther"));
-const QString LABEL_ZOOM_1_TO_1_CLOSER (QObject::tr ("1:1 closer"));
-const QString LABEL_ZOOM_1_TO_1 ("1:1");
-const QString LABEL_ZOOM_1_TO_1_FARTHER (QObject::tr ("1:1 farther"));
-const QString LABEL_ZOOM_1_TO_2_CLOSER (QObject::tr ("1:2 closer"));
-const QString LABEL_ZOOM_1_TO_2 ("1:2");
-const QString LABEL_ZOOM_1_TO_2_FARTHER (QObject::tr ("1:2 farther"));
-const QString LABEL_ZOOM_1_TO_4_CLOSER (QObject::tr ("1:4 closer"));
-const QString LABEL_ZOOM_1_TO_4 ("1:4");
-const QString LABEL_ZOOM_1_TO_4_FARTHER (QObject::tr ("1:4 farther"));
-const QString LABEL_ZOOM_1_TO_8_CLOSER (QObject::tr ("1:8 closer"));
-const QString LABEL_ZOOM_1_TO_8 ("1:8");
-const QString LABEL_ZOOM_1_TO_8_FARTHER (QObject::tr ("1:8 farther"));
-const QString LABEL_ZOOM_1_TO_16_CLOSER (QObject::tr ("1:16 closer"));
-const QString LABEL_ZOOM_1_TO_16 ("1:16");
-const QString LABEL_ZOOM_FILL (QObject::tr ("Fill"));
-const QString LABEL_ZOOM_PREVIOUS (QObject::tr ("Previous"));
+const QString* LABEL_ZOOM_16_TO_1;
+const QString* LABEL_ZOOM_16_TO_1_FARTHER;
+const QString* LABEL_ZOOM_8_TO_1_CLOSER;
+const QString* LABEL_ZOOM_8_TO_1;
+const QString* LABEL_ZOOM_8_TO_1_FARTHER;
+const QString* LABEL_ZOOM_4_TO_1_CLOSER;
+const QString* LABEL_ZOOM_4_TO_1;
+const QString* LABEL_ZOOM_4_TO_1_FARTHER;
+const QString* LABEL_ZOOM_2_TO_1_CLOSER;
+const QString* LABEL_ZOOM_2_TO_1;
+const QString* LABEL_ZOOM_2_TO_1_FARTHER;
+const QString* LABEL_ZOOM_1_TO_1_CLOSER;
+const QString* LABEL_ZOOM_1_TO_1;
+const QString* LABEL_ZOOM_1_TO_1_FARTHER;
+const QString* LABEL_ZOOM_1_TO_2_CLOSER;
+const QString* LABEL_ZOOM_1_TO_2;
+const QString* LABEL_ZOOM_1_TO_2_FARTHER;
+const QString* LABEL_ZOOM_1_TO_4_CLOSER;
+const QString* LABEL_ZOOM_1_TO_4;
+const QString* LABEL_ZOOM_1_TO_4_FARTHER;
+const QString* LABEL_ZOOM_1_TO_8_CLOSER;
+const QString* LABEL_ZOOM_1_TO_8;
+const QString* LABEL_ZOOM_1_TO_8_FARTHER;
+const QString* LABEL_ZOOM_1_TO_16_CLOSER;
+const QString* LABEL_ZOOM_1_TO_16;
+const QString* LABEL_ZOOM_FILL;
+const QString* LABEL_ZOOM_PREVIOUS;
diff --git a/src/Zoom/ZoomLabels.h b/src/Zoom/ZoomLabels.h
index 9c2b1e0a..6defe700 100644
--- a/src/Zoom/ZoomLabels.h
+++ b/src/Zoom/ZoomLabels.h
@@ -9,32 +9,32 @@
 
 #include <QString>
 
-extern const QString LABEL_ZOOM_16_TO_1;
-extern const QString LABEL_ZOOM_16_TO_1_FARTHER;
-extern const QString LABEL_ZOOM_8_TO_1_CLOSER;
-extern const QString LABEL_ZOOM_8_TO_1;
-extern const QString LABEL_ZOOM_8_TO_1_FARTHER;
-extern const QString LABEL_ZOOM_4_TO_1_CLOSER;
-extern const QString LABEL_ZOOM_4_TO_1;
-extern const QString LABEL_ZOOM_4_TO_1_FARTHER;
-extern const QString LABEL_ZOOM_2_TO_1_CLOSER;
-extern const QString LABEL_ZOOM_2_TO_1;
-extern const QString LABEL_ZOOM_2_TO_1_FARTHER;
-extern const QString LABEL_ZOOM_1_TO_1_CLOSER;
-extern const QString LABEL_ZOOM_1_TO_1;
-extern const QString LABEL_ZOOM_1_TO_1_FARTHER;
-extern const QString LABEL_ZOOM_1_TO_2_CLOSER;
-extern const QString LABEL_ZOOM_1_TO_2;
-extern const QString LABEL_ZOOM_1_TO_2_FARTHER;
-extern const QString LABEL_ZOOM_1_TO_4_CLOSER;
-extern const QString LABEL_ZOOM_1_TO_4;
-extern const QString LABEL_ZOOM_1_TO_4_FARTHER;
-extern const QString LABEL_ZOOM_1_TO_8_CLOSER;
-extern const QString LABEL_ZOOM_1_TO_8;
-extern const QString LABEL_ZOOM_1_TO_8_FARTHER;
-extern const QString LABEL_ZOOM_1_TO_16_CLOSER;
-extern const QString LABEL_ZOOM_1_TO_16;
-extern const QString LABEL_ZOOM_FILL;
-extern const QString LABEL_ZOOM_PREVIOUS;
+extern const QString* LABEL_ZOOM_16_TO_1;
+extern const QString* LABEL_ZOOM_16_TO_1_FARTHER;
+extern const QString* LABEL_ZOOM_8_TO_1_CLOSER;
+extern const QString* LABEL_ZOOM_8_TO_1;
+extern const QString* LABEL_ZOOM_8_TO_1_FARTHER;
+extern const QString* LABEL_ZOOM_4_TO_1_CLOSER;
+extern const QString* LABEL_ZOOM_4_TO_1;
+extern const QString* LABEL_ZOOM_4_TO_1_FARTHER;
+extern const QString* LABEL_ZOOM_2_TO_1_CLOSER;
+extern const QString* LABEL_ZOOM_2_TO_1;
+extern const QString* LABEL_ZOOM_2_TO_1_FARTHER;
+extern const QString* LABEL_ZOOM_1_TO_1_CLOSER;
+extern const QString* LABEL_ZOOM_1_TO_1;
+extern const QString* LABEL_ZOOM_1_TO_1_FARTHER;
+extern const QString* LABEL_ZOOM_1_TO_2_CLOSER;
+extern const QString* LABEL_ZOOM_1_TO_2;
+extern const QString* LABEL_ZOOM_1_TO_2_FARTHER;
+extern const QString* LABEL_ZOOM_1_TO_4_CLOSER;
+extern const QString* LABEL_ZOOM_1_TO_4;
+extern const QString* LABEL_ZOOM_1_TO_4_FARTHER;
+extern const QString* LABEL_ZOOM_1_TO_8_CLOSER;
+extern const QString* LABEL_ZOOM_1_TO_8;
+extern const QString* LABEL_ZOOM_1_TO_8_FARTHER;
+extern const QString* LABEL_ZOOM_1_TO_16_CLOSER;
+extern const QString* LABEL_ZOOM_1_TO_16;
+extern const QString* LABEL_ZOOM_FILL;
+extern const QString* LABEL_ZOOM_PREVIOUS;
 
 #endif // ZOOM_LABELS_H
diff --git a/src/Zoom/ZoomTransition.cpp b/src/Zoom/ZoomTransition.cpp
index 02edc688..f41679e1 100644
--- a/src/Zoom/ZoomTransition.cpp
+++ b/src/Zoom/ZoomTransition.cpp
@@ -68,7 +68,7 @@ ZoomFactor ZoomTransition::zoomIn (ZoomFactor currentZoomFactor,
     double scale = qMin(xScale, yScale); // Fit so large extent just fits
 
     for (int zoom = ZOOM_1_TO_16_CLOSER; zoom >= 0; zoom--) {
-      ZoomFactor zoomFactor = (ZoomFactor) zoom;
+      ZoomFactor zoomFactor = static_cast<ZoomFactor> (zoom);
       if (scale < m_zoomMapToFactor [zoomFactor]) {
         zoomFactorOld = zoomFactor;
         break;
@@ -78,7 +78,7 @@ ZoomFactor ZoomTransition::zoomIn (ZoomFactor currentZoomFactor,
 
   ZoomFactor zoomFactorNew = ZOOM_16_TO_1;
   if (zoomFactorOld > ZOOM_16_TO_1) {
-    zoomFactorNew = (ZoomFactor) (zoomFactorOld - 1);
+    zoomFactorNew = static_cast<ZoomFactor> (zoomFactorOld - 1);
   }
 
   return zoomFactorNew;
@@ -103,7 +103,7 @@ ZoomFactor ZoomTransition::zoomOut (ZoomFactor currentZoomFactor,
     double scale = qMax(xScale, yScale); // Fit so larger extent just fits
 
     for (int zoom = 0; zoom <= ZOOM_1_TO_16_CLOSER; zoom++) {
-      ZoomFactor zoomFactor = (ZoomFactor) zoom;
+      ZoomFactor zoomFactor = static_cast<ZoomFactor> (zoom);
       if (scale > m_zoomMapToFactor [zoomFactor]) {
         zoomFactorOld = zoomFactor;
         break;
@@ -113,7 +113,7 @@ ZoomFactor ZoomTransition::zoomOut (ZoomFactor currentZoomFactor,
 
   ZoomFactor zoomFactorNew = ZOOM_1_TO_16;
   if (zoomFactorOld < ZOOM_1_TO_16) {
-    zoomFactorNew = (ZoomFactor) (zoomFactorOld + 1);
+    zoomFactorNew = static_cast<ZoomFactor> (zoomFactorOld + 1);
   }
 
   return zoomFactorNew;
diff --git a/src/build_and_run_all_cli_tests b/src/build_and_run_all_cli_tests
index a467f3d3..59e9eba5 100755
--- a/src/build_and_run_all_cli_tests
+++ b/src/build_and_run_all_cli_tests
@@ -21,6 +21,7 @@ testsAvailable=( \
     TestProjectedPoint \
     TestSegmentFill \
     TestSpline \
+    TestSplineDrawer \
     TestTransformation \
     TestValidators \
     TestZoomTransition)
@@ -90,12 +91,13 @@ else
     do
 	sed "s/TEST/$t/g" engauge_test_template.pro >engauge_test.pro
 	qmake $CONFIGARGS engauge_test.pro
-	make all 2>>$LOGFILE >/dev/null || {
+	make -j4 all 2>>$LOGFILE >/dev/null || {
 	    echo "FAIL   : Compilation error is described in build_and_run_all_cli_tests.log"
 	    echo "         Testing will be stopped"
 	    exit 1
         }
-	../bin/$t
+	# sed is used to add color to PASS and FAIL. 'Using QtTest' lines are dropped
+	../bin/$t | sed "s/PASS   :/$(tput setaf 2)PASS$(tput sgr0)   :/" | sed "s/FAIL   :/$(tput setaf 1)FAIL$(tput sgr0)   :/" | grep -v 'Using QtTest'
 	if [ $selectedCount -ne 1 ]
 	then
             rm engauge_test.pro
diff --git a/src/build_and_run_all_gui_tests b/src/build_and_run_all_gui_tests
index a962db46..c2b2ce53 100755
--- a/src/build_and_run_all_gui_tests
+++ b/src/build_and_run_all_gui_tests
@@ -7,15 +7,17 @@
 # where: jpeg2000 = run jpeg2000 test(s). Requires CONFIG+=jpeg2000 in qmake build
 #        pdf      = run pdf test(s). Requires CONFIG+=pdf in qmake build
 
+DEBUG=0
+
 FILTERJPEG2000="skip"
 FILTERPDF="skip"
 while test $# -gt 0
 do
     case "$1" in
 	jpeg2000) FILTERJPEG2000=""
-	    ;;
+	    ;; 
         pdf) FILTERPDF=""
-            ;;
+	    ;;
     esac
     shift
 done
@@ -34,8 +36,12 @@ do
 
 	# Run regression test. Standard error is redirected to standard out so we can strip out unimportant
 	# 'QXcbXSettings::QXcbXSettings(QXcbScreen*) Failed to get selection owner for XSETTINGS_S atom' errors
-	commandLine=`cat $script`
-	../bin/engauge $commandLine 2>&1 | grep -v 'Failed to get selection owner'
+	commandLineArgs=`cat $script`
+	if [ $DEBUG == 1 ]; then
+	    echo " "
+	    echo "engauge $commandLineArgs"
+	fi
+	../bin/engauge $commandLineArgs 2>&1 | grep -v 'Failed to get selection owner'
 
 	# Compare actual and desired output files. There is one pair for each coordinate system
 	scriptfile=`basename $script`
@@ -50,8 +56,7 @@ do
 	for EXPECTED in $EXPECTED_FILES
 	do
 	    actual=${EXPECTED/expected/actual}
-	    if [[ COUNT -gt 1 ]]; 
-	    then
+	    if [[ COUNT -gt 1 ]]; then
 		COUNTERSTRING="[$COUNTER/$COUNT]";
 	    else
 		COUNTERSTRING="";