From 39896ea770b4a61243dcae07fdcbcf8a60cdecda Mon Sep 17 00:00:00 2001
From: Lewin Probst <info@emirror.de>
Date: Tue, 9 Jun 2020 18:02:40 +0200
Subject: [PATCH] Added option to plot topographical lines from etopo file.

The etopo file must be downloaded separately and linked as parameter
etopo in the files section in artoa.ini file.
---
 VERSION                                       |  2 +-
 artoa.ini.example                             |  1 +
 lib/+artoa/+controller/+file/loadEtopoFile.m  | 25 +++++++++++
 .../buttonToggleTopographicalTable.m          | 18 ++++++++
 .../checkboxTopographicalLines.m              | 12 ++++++
 .../+trajectoryOutput/clearTrajectoryPlot.m   |  6 +++
 .../+track/+trajectoryOutput/open.m           | 19 ++++++++-
 .../+track/+trajectoryOutput/plot.m           |  7 ++++
 .../plotTopographicalLines.m                  | 39 +++++++++++++++++
 .../tableTopographicalLinesEdit.m             | 39 +++++++++++++++++
 lib/+artoa/+gui/+track/trajectoryOutput.m     | 42 +++++++++++++++++++
 .../+versioning/+migrations/versions/v4226.m  | 14 +++++++
 12 files changed, 222 insertions(+), 2 deletions(-)
 create mode 100644 lib/+artoa/+controller/+file/loadEtopoFile.m
 create mode 100644 lib/+artoa/+controller/+track/+trajectoryOutput/buttonToggleTopographicalTable.m
 create mode 100644 lib/+artoa/+controller/+track/+trajectoryOutput/checkboxTopographicalLines.m
 create mode 100644 lib/+artoa/+controller/+track/+trajectoryOutput/plotTopographicalLines.m
 create mode 100644 lib/+artoa/+controller/+track/+trajectoryOutput/tableTopographicalLinesEdit.m
 create mode 100644 lib/+artoa/+versioning/+migrations/versions/v4226.m

diff --git a/VERSION b/VERSION
index bcad854..0e4c1b3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-225
\ No newline at end of file
+226
\ No newline at end of file
diff --git a/artoa.ini.example b/artoa.ini.example
index 5b69e51..4071072 100644
--- a/artoa.ini.example
+++ b/artoa.ini.example
@@ -4,6 +4,7 @@
 -soundsourcefile    /your/filepath/here/input/HAFOS.soso
 -floatfile          ..\HAFOS.flo  % not used in artoa4 yet
 -bathyfile            % not used in artoa4 yet
+-etopo              /your/filepath/here/data/etopo1_bed_c.flt
 
 [directory]
 -interim        /your/filepath/here/
diff --git a/lib/+artoa/+controller/+file/loadEtopoFile.m b/lib/+artoa/+controller/+file/loadEtopoFile.m
new file mode 100644
index 0000000..7d0e148
--- /dev/null
+++ b/lib/+artoa/+controller/+file/loadEtopoFile.m
@@ -0,0 +1,25 @@
+function [] = loadEtopoFile(pLatLimit, pLonLimit)
+%LOADETOPOFILE Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaDataInput artoaConfig;
+
+if nargin ~= 2
+    pLatLimit = [-90, 0];
+    pLonLimit = [-180, 180];
+end
+
+if artoa.data.hasMember(artoaConfig, 'files', 'etopo') ...
+        & isfile(artoaConfig.files.etopo)
+    artoaDataInput.etopo = struct();
+    [artoaDataInput.etopo.Z, artoaDataInput.etopo.refvec] = etopo( ...
+        artoaConfig.files.etopo, ...
+        1, ...
+        pLatLimit, ...
+        pLonLimit ...
+        );
+else
+    warning('ETOPO file has not been found! Please download the file at http://cromwell.marine.unc.edu/data/long_bay/etopo/etopo1_bed_c.flt and set etopo parameter in the files section in your artoa.ini');
+end
+
+end
\ No newline at end of file
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/buttonToggleTopographicalTable.m b/lib/+artoa/+controller/+track/+trajectoryOutput/buttonToggleTopographicalTable.m
new file mode 100644
index 0000000..770e21f
--- /dev/null
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/buttonToggleTopographicalTable.m
@@ -0,0 +1,18 @@
+function [] = buttonToggleTopographicalTable(~, ~)
+%BUTTONDELETEALLTRAJECTORIES Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaGui;
+
+%% Show/hide topographical table
+
+if strcmp(artoaGui.trajectoryOutput.frameTopographicalLinesList.Visible, 'off')
+    artoaGui.trajectoryOutput.frameTopographicalLinesList.Visible = 'on';
+    artoaGui.trajectoryOutput.frameTrackList.Visible = 'off';
+else
+    artoaGui.trajectoryOutput.frameTopographicalLinesList.Visible = 'off';
+    artoaGui.trajectoryOutput.frameTrackList.Visible = 'on';
+end
+
+end
+
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/checkboxTopographicalLines.m b/lib/+artoa/+controller/+track/+trajectoryOutput/checkboxTopographicalLines.m
new file mode 100644
index 0000000..fadeef6
--- /dev/null
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/checkboxTopographicalLines.m
@@ -0,0 +1,12 @@
+function [] = checkboxTopographicalLines(~, event)
+%CHECKBOXUPDATETRACKPARAMETERWINDOW Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaWorkspace;
+
+artoaWorkspace.trajectoryOutput.showTopographicalLines = logical(event.Source.Value);
+
+artoa.controller.track.trajectoryOutput.plot();
+
+end
+
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m b/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m
index 5da7a36..b7ec57c 100644
--- a/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/clearTrajectoryPlot.m
@@ -25,6 +25,11 @@ if artoa.data.hasMember(artoaGui, 'trajectoryOutput', 'textScatterFloatSatData')
     delete(artoaGui.trajectoryOutput.textScatterFloatSatData);
 end
 
+%% Topographical lines
+if artoa.data.hasMember(artoaGui, 'trajectoryOutput', 'contourTopographicalLines')
+    deleteHandles(artoaGui.trajectoryOutput.contourTopographicalLines);
+end
+
 %% Trajectories
 if artoa.data.hasMember(artoaGui, {'trajectoryOutput', 'trajectoryHandles'})
     trajectories = artoaGui.trajectoryOutput.trajectoryHandles;
@@ -48,6 +53,7 @@ for i = 1:length(trajectories)
     end
 end
 
+
     function deleteHandles(pInput)
         if iscell(pInput)
             cellfun(@deleteHandles, pInput);
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/open.m b/lib/+artoa/+controller/+track/+trajectoryOutput/open.m
index 8352b73..1d258bf 100644
--- a/lib/+artoa/+controller/+track/+trajectoryOutput/open.m
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/open.m
@@ -2,7 +2,7 @@ function [] = open(~, ~)
 %OPEN Initializes the trajectory output gui.
 %   
 
-global artoaGui artoaWorkspace;
+global artoaGui artoaWorkspace artoaConfig;
 
 %% Check if the gui is already opened
 
@@ -20,9 +20,12 @@ callbacks.buttonDeleteSingle = @artoa.controller.track.trajectoryOutput.buttonDe
 callbacks.buttonDeleteAll = @artoa.controller.track.trajectoryOutput.buttonDeleteAllTrajectories;
 callbacks.checkboxTrueDistance = @artoa.controller.track.trajectoryOutput.checkboxTrueDistance;
 callbacks.checkboxTrackVisible = '';
+callbacks.checkboxShowTopographicalLines = @artoa.controller.track.trajectoryOutput.checkboxTopographicalLines;
 callbacks.buttonTrackInfos = '';
 callbacks.buttonVelocities = '';
+callbacks.buttonToggleTopographicalTable = @artoa.controller.track.trajectoryOutput.buttonToggleTopographicalTable;
 callbacks.tableGeneratedTracksSelect = @artoa.controller.track.trajectoryOutput.tableGeneratedTracksSelect;
+callbacks.tableTopographicalLinesEdit = @artoa.controller.track.trajectoryOutput.tableTopographicalLinesEdit;
 callbacks.checkboxUpdateTrackParameterWindow = @artoa.controller.track.trajectoryOutput.checkboxUpdateTrackParameterWindow;
 callbacks.checkboxShowPositionDates = @artoa.controller.track.trajectoryOutput.checkboxShowPositionDates;
 callbacks.checkboxSynchronizeZoomToaWindow = @artoa.controller.track.trajectoryOutput.checkboxSyncZoomToaWindow;
@@ -37,9 +40,11 @@ if ~isfield(artoaWorkspace, 'trajectoryOutput')
     artoaWorkspace.trajectoryOutput = struct();
     artoaWorkspace.trajectoryOutput.updateTrackParameterWindow = false;
     artoaWorkspace.trajectoryOutput.showPositionDates = true;
+    artoaWorkspace.trajectoryOutput.topographicalLines = artoaConfig.defaults.topographicalLines;
     artoaWorkspace.trajectoryOutput.enableMercatorProjection = false;
     artoaWorkspace.trajectoryOutput.syncZoomToaWindow = true;
     artoaWorkspace.trajectoryOutput.enableTrueDistance = false;
+    artoaWorkspace.trajectoryOutput.showTopographicalLines = false;
 end
 
 %% Add listener to sync zoom of TOA window
@@ -93,6 +98,18 @@ if artoa.data.hasMember(artoaWorkspace, {'trajectoryOutput', 'syncZoomToaWindow'
 else
     artoaGui.trajectoryOutput.checkboxSynchronizeZoomToaWindow.Value = false;
 end
+if artoa.data.hasMember(artoaWorkspace, {'trajectoryOutput', 'showTopographicalLines'})
+    artoaGui.trajectoryOutput.checkboxShowTopographicalLines.Value = ...
+        artoaWorkspace.trajectoryOutput.showTopographicalLines;
+else
+    artoaGui.trajectoryOutput.checkboxShowTopographicalLines.Value = false;
+end
+if artoa.data.hasMember(artoaWorkspace, {'trajectoryOutput', 'topographicalLines'})
+    artoaGui.trajectoryOutput.tableTopographicalLines.Data = ...
+        artoaWorkspace.trajectoryOutput.topographicalLines;
+else
+    artoaGui.trajectoryOutput.checkboxShowTopographicalLines.Value = false;
+end
 
 %% Plot everything available
 artoa.controller.track.trajectoryOutput.plot(artoaWorkspace.trajectoryOutput.enableMercatorProjection);
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m b/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m
index 54b6f0e..147202c 100644
--- a/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/plot.m
@@ -138,5 +138,12 @@ for i = 1:length(trajectories)
     end
 end
 
+
+%% Plot topographic lines
+if artoa.data.hasMember(artoaWorkspace, 'trajectoryOutput', 'showTopographicalLines') ...
+        & artoaWorkspace.trajectoryOutput.showTopographicalLines
+    artoaGui.trajectoryOutput.contourTopographicalLines = artoa.controller.track.trajectoryOutput.plotTopographicalLines(artoaGui.trajectoryOutput.axesTrajectoryOutput);
+end
+
 end
 
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/plotTopographicalLines.m b/lib/+artoa/+controller/+track/+trajectoryOutput/plotTopographicalLines.m
new file mode 100644
index 0000000..d8ad114
--- /dev/null
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/plotTopographicalLines.m
@@ -0,0 +1,39 @@
+function [topographicalLineHandles] = plotTopographicalLines(pAxesHandle)
+%PLOTSOUNDSOURCELINES Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaWorkspace artoaDataInput;
+
+%% Load etopo
+
+artoa.controller.file.loadEtopoFile( ...
+    pAxesHandle.YLim, ...
+    pAxesHandle.XLim ...
+    );
+
+
+%% Plot topographical lines
+
+% make handle the current axes
+axes(pAxesHandle);
+
+hold(pAxesHandle, 'on');
+topographicalLineHandles = cell(length(artoaWorkspace.trajectoryOutput.topographicalLines), 1);
+
+for o = 1:length(artoaWorkspace.trajectoryOutput.topographicalLines)
+    if isnan(artoaWorkspace.trajectoryOutput.topographicalLines{o})
+        continue;
+    end
+    [~, topographicalLineHandles{o}] = contourm( ...
+        artoaDataInput.etopo.Z, ...
+        artoaDataInput.etopo.refvec, ...
+        [artoaWorkspace.trajectoryOutput.topographicalLines{o}, artoaWorkspace.trajectoryOutput.topographicalLines{o}], ...
+        'ShowText', 'on', ...
+        'LabelSpacing', 400 ...
+        );
+end
+
+hold(pAxesHandle, 'off');
+
+end
+
diff --git a/lib/+artoa/+controller/+track/+trajectoryOutput/tableTopographicalLinesEdit.m b/lib/+artoa/+controller/+track/+trajectoryOutput/tableTopographicalLinesEdit.m
new file mode 100644
index 0000000..4a69734
--- /dev/null
+++ b/lib/+artoa/+controller/+track/+trajectoryOutput/tableTopographicalLinesEdit.m
@@ -0,0 +1,39 @@
+function [] = tableTopographicalLinesEdit(~, ~)
+%UPDATETABLEGENERATEDTRACKS Summary of this function goes here
+%   Detailed explanation goes here
+
+global artoaGui artoaWorkspace;
+
+%% Save to workspace
+artoaWorkspace.trajectoryOutput.topographicalLines = artoaGui.trajectoryOutput.tableTopographicalLines.Data;
+
+%% Plot if required
+if ~artoaWorkspace.trajectoryOutput.showTopographicalLines
+    return;
+end
+
+if artoa.data.hasMember(artoaGui, 'trajectoryOutput', 'contourTopographicalLines')
+    deleteHandles(artoaGui.trajectoryOutput.contourTopographicalLines);
+end
+
+artoaGui.trajectoryOutput.contourTopographicalLines = ...
+    artoa.controller.track.trajectoryOutput.plotTopographicalLines( ...
+        artoaGui.trajectoryOutput.axesTrajectoryOutput ...
+        );
+
+%% Helper function
+
+    function deleteHandles(pInput)
+        if iscell(pInput)
+            cellfun(@deleteHandles, pInput);
+        end
+        if isstruct(pInput)
+            structfun(@deleteHandles, pInput);
+        end
+        if ishandle(pInput)
+            delete(pInput);
+        end
+    end
+    
+end
+
diff --git a/lib/+artoa/+gui/+track/trajectoryOutput.m b/lib/+artoa/+gui/+track/trajectoryOutput.m
index 47be370..eabf818 100644
--- a/lib/+artoa/+gui/+track/trajectoryOutput.m
+++ b/lib/+artoa/+gui/+track/trajectoryOutput.m
@@ -15,8 +15,11 @@ availableCallbacks = { ...
     'checkboxTrueDistance'...
     'checkboxTrackVisible', ...
     'tableGeneratedTracksSelect', ...
+    'tableTopographicalLinesEdit', ...
     'checkboxShowPositionDates', ...
     'checkboxSynchronizeZoomToaWindow', ...
+    'checkboxShowTopographicalLines', ...
+    'buttonToggleTopographicalTable', ...
     'checkboxUpdateTrackParameterWindow' ...
 };
 
@@ -254,6 +257,15 @@ artoaGui.trajectoryOutput.checkboxUpdateTrackParameterWindow = uicontrol( ...
     'CallBack', pCallbacks.checkboxUpdateTrackParameterWindow ...
 );
 
+artoaGui.trajectoryOutput.buttonToggleTopographicalTable = uicontrol( ...
+    'Parent', artoaGui.trajectoryOutput.frameGenericOptions, ...
+    'String', 'Toggle Topo Editor', ...
+    'Style', 'PushButton', ...
+    'FontSize', 8, ...
+    'Units', 'normalized', ...
+    'Position', [.1 .1 .8 .3], ...
+    'CallBack', pCallbacks.buttonToggleTopographicalTable ...
+);
 
 %% Display options
 
@@ -305,6 +317,36 @@ artoaGui.trajectoryOutput.checkboxSynchronizeZoomToaWindow = uicontrol( ...
     'CallBack', pCallbacks.checkboxSynchronizeZoomToaWindow ...
 );
 
+artoaGui.trajectoryOutput.checkboxShowTopographicalLines = uicontrol( ...
+    'Parent', artoaGui.trajectoryOutput.frameDisplayOptions, ...
+    'String', 'Topographical Lines', ...
+    'Style', 'CheckBox', ...
+    'FontSize', 8, ...
+    'Units', 'normalized', ...
+    'Position', [.1 .4 .8 .175], ...
+    'CallBack', pCallbacks.checkboxShowTopographicalLines ...
+);
+
+%% Topographical line table
+artoaGui.trajectoryOutput.frameTopographicalLinesList = uipanel( ...
+    'Title', 'Topographical lines', ...
+    'Units', 'normalized', ...
+    'BackgroundColor', 'white', ...
+    'Position', [rightSidebarLeft, .675, rightSidebarWidth, .3], ...
+    'Visible', 'off' ...
+);
+
+artoaGui.trajectoryOutput.tableTopographicalLines = uitable( ...
+    artoaGui.trajectoryOutput.frameTopographicalLinesList, ...
+    'Units', 'normalized', ...
+    'Position', [.05, .05, .9, .9], ...
+    'Data', cell(3, 1), ...
+    'ColumnName', {'Depth'}, ...
+    'ColumnEditable', true, ...
+    'ColumnWidth', {160}, ...
+    'CellEditCallback', pCallbacks.tableTopographicalLinesEdit ...
+);    
+
 %% Set current axes to trajectory output
 artoaGui.figures.trajectoryOutput.CurrentAxes = artoaGui.trajectoryOutput.axesTrajectoryOutput;
 
diff --git a/lib/+artoa/+versioning/+migrations/versions/v4226.m b/lib/+artoa/+versioning/+migrations/versions/v4226.m
new file mode 100644
index 0000000..c01f3c2
--- /dev/null
+++ b/lib/+artoa/+versioning/+migrations/versions/v4226.m
@@ -0,0 +1,14 @@
+%% Add topographical switch if required
+
+if ~artoa.data.hasMember(artoaWorkspace, 'trajectoryOutput', 'showTopographicalLines')
+    artoaWorkspace.trajectoryOutput.showTopographicalLines = false;
+end
+
+%% Add defaults for topographical lines if required
+if ~artoa.data.hasMember(artoaConfig, 'defaults', 'topographicalLines')
+    artoaConfig.defaults.topographicalLines = { ...
+        -1000; ...
+        -2000; ...
+        -3000 ...
+        };
+end
\ No newline at end of file
-- 
GitLab