From 11204ea7b72a48418e86d920a5c817d7d90e9f8d Mon Sep 17 00:00:00 2001
From: Michael Innerberger <michael.innerberger@asc.tuwien.ac.at>
Date: Tue, 8 Aug 2023 16:16:54 -0400
Subject: [PATCH] Use MooAFEM plotting in triangulation plots

---
 examples/storingLevelOrientedData.m           |   2 +-
 .../@LevelData/plotLevelTriangulation.m       |  83 -------------
 lib/storage/@LevelData/plotTriangulation.m    |  34 +++---
 .../@LevelData/plotTriangulationToFile.m      | 112 ++++--------------
 4 files changed, 44 insertions(+), 187 deletions(-)
 delete mode 100644 lib/storage/@LevelData/plotLevelTriangulation.m

diff --git a/examples/storingLevelOrientedData.m b/examples/storingLevelOrientedData.m
index 5aa2c31..7488882 100644
--- a/examples/storingLevelOrientedData.m
+++ b/examples/storingLevelOrientedData.m
@@ -123,7 +123,7 @@ function leveldata = storingLevelOrientedData(doPlots, doStore)
         figure();
         leveldata.plotTriangulation();
     
-        % export refinement video (generates video of about 110 MB)
+        % export refinement video (generates video of about 2MB)
         leveldata.plotTriangulationToFile();
     end
 end
diff --git a/lib/storage/@LevelData/plotLevelTriangulation.m b/lib/storage/@LevelData/plotLevelTriangulation.m
deleted file mode 100644
index deae87b..0000000
--- a/lib/storage/@LevelData/plotLevelTriangulation.m
+++ /dev/null
@@ -1,83 +0,0 @@
-function plotLevelTriangulation(obj, ax, jLevel)
-%%PLOTLEVELTRIANGULATION auxiliary private function for creation of plots
-%of triangulations, it extracts the triangulation data in various possible
-%formats (compatible with octAFEM and MooAFEM)
-%   PLOTLEVELTRIANGULATION(obj, ax, jLevel)
-
-% Copyright 2023 Philipp Bringmann
-%
-% This program is free software: you can redistribute it and/or modify
-% it under the terms of the GNU General Public License as published by
-% the Free Software Foundation, either version 3 of the License, or
-% (at your option) any later version.
-%
-% This program is distributed in the hope that it will be useful,
-% but WITHOUT ANY WARRANTY; without even the implied warranty of
-% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-% GNU General Public License for more details.
-%
-% You should have received a copy of the GNU General Public License
-% along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%
-
-
-    % This functions plots a single level only
-    assert(numel(jLevel) == 1);
-
-    % Determine names of variables containing mesh information
-    arrayDataFound = false;
-    transposeArrays = false;
-    if isfield(obj.level(jLevel), 'c4n')
-        % Arrays in octAFEM style
-        coordinatesName = 'c4n';
-        elementsName = 'n4e';
-        arrayDataFound = true;
-    elseif isfield(obj.level(jLevel), 'coordinates')
-        % Arrays in MooAFEM style
-        coordinatesName = 'coordinates';
-        elementsName = 'elements';
-        arrayDataFound = true;
-        transposeArrays = true;
-    end
-
-    % Extract mesh information
-    if arrayDataFound
-        % Extract data present as coordinates / elements arrays
-        c4n = obj.level(jLevel).(coordinatesName);
-        n4e = obj.level(jLevel).(elementsName);
-        if transposeArrays
-            c4n = permute(c4n, [2 1]);
-            n4e = permute(n4e, [2 1]);
-        end
-        % Reorganise mesh information
-        c4e = permute(reshape(c4n(n4e,:), length(n4e), 3, 2), ...
-                      [3 2 1]);
-    else
-        % Extract data present as mesh object
-        for k = 1:length(obj.label)
-            data = obj.level(jLevel).(obj.label(k));
-            if isa(data, 'MeshData')
-                % octAFEM MeshData object
-                c4e = data.c4e;
-                break
-            elseif isa(data, 'Mesh')
-                % MooAFEM Mesh object
-                c4n = permute(obj.level(jLevel).(coordinatesName), [2 1]);
-                n4e = permute(obj.level(jLevel).(elementsName), [2 1]);
-                % Reorganise mesh information
-                c4e = permute(reshape(c4n(n4e,:), length(n4e), 3, 2), ...
-                              [3 2 1]);
-            end
-        end
-    end
-
-    % Plot mesh
-    edgecolor = [0 0.4470 0.7410];
-    patch(ax, permute(c4e(1,:,:), [2 3 1]), permute(c4e(2,:,:), [2 3 1]), ...
-          'white', 'EdgeColor', edgecolor);
-
-    % Format plot
-    title(ax, {'Mesh plot'; [num2str(size(c4e, 3)), ' triangles']});
-    axis(ax, 'equal');
-    axis(ax, 'tight');
-end
\ No newline at end of file
diff --git a/lib/storage/@LevelData/plotTriangulation.m b/lib/storage/@LevelData/plotTriangulation.m
index 9870913..caae924 100644
--- a/lib/storage/@LevelData/plotTriangulation.m
+++ b/lib/storage/@LevelData/plotTriangulation.m
@@ -1,11 +1,11 @@
-function ax = plotTriangulation(obj, jLevel)
+function ax = plotTriangulation(obj, jLevel, opt)
 %%PLOTTRIANGULATION creates (a series of) plots for triangulations (must be
 %stored as pair c4n (double: nNodes x 2) and n4e (int: nElem x 3) or as
 %pair coordinates (double: 2 x nNodes) and elements (int: 3 x nElem)
 %   ax = PLOTTRIANGULATION(obj) plots all levels
-%   ax = PLOTTRIANGULATION(obj, ':')
-%   ax = PLOTTRIANGULATION(obj, jLevel)
-%   ax = PLOTTRIANGULATION(obj, 'end')
+%   ax = PLOTTRIANGULATION(obj, jLevel) plots levels specified in jLevel
+%   ax = PLOTTRIANGULATION(obj, jLevel, opt) additionally specifies options:
+%      - timePerLevel (default 1s)
 
 % Copyright 2023 Philipp Bringmann
 %
@@ -23,26 +23,26 @@ function ax = plotTriangulation(obj, jLevel)
 % along with this program.  If not, see <http://www.gnu.org/licenses/>.
 %
 
+    arguments
+        obj
+        jLevel (1,:) {mustBeIndexVector} = ':'
+        opt.timePerLevel {mustBeNumeric} = 1
+    end
 
-    % Proceed input
-    if nargin < 2
-        jLevel = 1:obj.nLevel;
-    elseif strcmp(jLevel, ':')
+    if strcmp(jLevel, ':')
         jLevel = 1:obj.nLevel;
-    elseif strcmp(jLevel, 'end')
-        jLevel = obj.nLevel;
     end
 
-    % Compute time per frame to obtain an overall duration of 20 seconds
-    DURATION = 20;
-    timePerLevel = DURATION / length(jLevel);
-
     % Create axes object
     ax = gca;
 
     % Plot every frame
-    for k = 1:length(jLevel)
-        obj.plotLevelTriangulation(ax, jLevel(k));
-        pause(timePerLevel);
+    % TODO: store whole mesh such that also boundary can be plotted?
+    for k = jLevel
+        coordinates = obj.level(k).coordinates;
+        elements = obj.level(k).elements;
+        mesh = Mesh(coordinates, elements, {});
+        plot(mesh, 'FaceAlpha', 0.0);
+        pause(opt.timePerLevel);
     end
 end
\ No newline at end of file
diff --git a/lib/storage/@LevelData/plotTriangulationToFile.m b/lib/storage/@LevelData/plotTriangulationToFile.m
index a5b9827..65db0d8 100644
--- a/lib/storage/@LevelData/plotTriangulationToFile.m
+++ b/lib/storage/@LevelData/plotTriangulationToFile.m
@@ -1,11 +1,11 @@
-function plotTriangulationToFile(obj, jLevel)
+function plotTriangulationToFile(obj, jLevel, opt)
 %%PLOTTRIANGULATIONTOFILE creates (a series of) plots for triangulations
 %and stores it to a file, filename is generated automatically from
 %information in LevelData object
 %   ax = PLOTTRIANGULATIONTOFILE(obj) plots all levels
-%   ax = PLOTTRIANGULATIONTOFILE(obj, ':')
-%   ax = PLOTTRIANGULATIONTOFILE(obj, jLevel)
-%   ax = PLOTTRIANGULATIONTOFILE(obj, 'end')
+%   ax = PLOTTRIANGULATIONTOFILE(obj, jLevel) plots levels specified in jLevel
+%   ax = PLOTTRIANGULATIONTOFILE(obj, jLevel, opt) additionally specifies options:
+%      - timePerLevel (default 1s)
 %
 %   See also LevelData/plotTriangulation
 
@@ -25,115 +25,55 @@ function plotTriangulationToFile(obj, jLevel)
 % along with this program.  If not, see <http://www.gnu.org/licenses/>.
 %
 
+    arguments
+        obj
+        jLevel (1,:) {mustBeIndexVector} = ':'
+        opt.timePerLevel {mustBeNumeric} = 1
+    end
 
-    % Proceed input
-    if nargin < 2
-        jLevel = 1:obj.nLevel;
-    elseif strcmp(jLevel, ':')
+    if strcmp(jLevel, ':')
         jLevel = 1:obj.nLevel;
-    elseif strcmp(jLevel, 'end')
-        jLevel = obj.nLevel;
     end
 
-    % Create problem- and method-specific folder
     ensureFolderExists(obj.foldername);
-
-    % Create new figure
     h = createStandardFigure();
 
     if length(jLevel) == 1
         % Create single image
-        h = createStandardisedFigure();
-        obj.plotLevelTriangulation(gca(), jLevel);
-        % Export plot
-        print(h, '-dpng', '-r600', [obj.foldername, '/', obj.filename, '.png']);
+        coordinates = obj.level(jLevel).coordinates;
+        elements = obj.level(jLevel).elements;
+        mesh = Mesh(coordinates, elements, {});
+        plot(mesh);
+        print(h, '-dpng', '-r600', obj.foldername + '/' + obj.filename + '.png');
     else
-        % Set duration of video in seconds
-        DURATION = 20;
         % Create video as series of images
-        if isOctave()
-            createTriangulationGIF(obj, h, jLevel, DURATION);
-        else
-            createTriangulationAVI(obj, h, jLevel, DURATION);
-        end
+        createTriangulationAVI(obj, h, jLevel, opt.timePerLevel);
     end
 
-    % Close figure
     close(h);
 end
 
 
-function createTriangulationAVI(obj, h, jLevel, duration)
-%%CREATETRIANGULATIONAVI creates a video of the mesh refinement in AVI format
-
-    % Set video quality parameter
-    FPS = 30;
+function createTriangulationAVI(obj, h, jLevel, secondsPerFrame)
+    % video quality parameter
+    FPS = 1 / secondsPerFrame;
 
     % Create video writer
-    videowriter = VideoWriter([obj.foldername, '/', obj.filename, '.avi']);
+    videowriter = VideoWriter(obj.foldername + '/' + obj.filename + '.avi');
     set(videowriter, 'FrameRate', FPS);
     open(videowriter);
 
-    % Compute time per frame to obtain a fixed overall duration
-    framesPerLevel = fix(FPS * duration / length(jLevel));
     ax = gca();
     set(ax, 'NextPlot', 'replaceChildren');
 
     % Plot every frame
-    for k = 1:length(jLevel)
-        obj.plotLevelTriangulation(ax, jLevel(k));
-        for l = 1:framesPerLevel
-            writeVideo(videowriter, getframe(h));
-        end
+    for k = jLevel
+        coordinates = obj.level(k).coordinates;
+        elements = obj.level(k).elements;
+        mesh = Mesh(coordinates, elements, {});
+        plot(mesh, 'FaceAlpha', 0.0);
+        writeVideo(videowriter, getframe(h));
     end
 
-    % Close video writer
     close(videowriter);
 end
-
-
-function createTriangulationGIF(obj, h, jLevel, duration)
-%%CREATETRIANGULATIONGIF creates a video of the mesh refinement in GIF format
-
-    error('not working yet')
-
-    ax = gca();
-
-    % Determine time for delay in GIF
-    delayTime = duration / length(jLevel);
-
-    % Define path
-    filepath = [obj.foldername, '/', obj.filename, '.gif'];
-
-    % Assign plot to a frame
-    frame = getframe(h);
-
-    % Convert frame to RGB image (3 dimensional)
-    im = frame2im(frame);
-
-    % Transform RGB samples to 1 dimension with a color map "cm".
-    [imind, cm] = rgb2ind(im);
-
-    % Compute time per frame to obtain a fixed overall duration
-    imwrite(imind, cm, filepath, 'gif', ...
-            'DelayTime', delayTime, 'Compression' , 'lzw');
-
-    % Plot every frame
-    for k = 1:length(jLevel)
-        obj.plotLevelTriangulation(ax, jLevel(k));
-            % Assign plot to a frame
-    frame = getframe(h);
-
-    % Convert frame to RGB image (3 dimensional)
-    im = frame2im(frame);
-
-    % Transform RGB samples to 1 dimension with a color map "cm".
-    [imind, cm] = rgb2ind(im);
-
-        % Create GIF file
-        % Add each new plot to GIF
-        imwrite(imind, cm, filepath, 'gif', ...
-                'WriteMode', 'append', 'DelayTime', delayTime, ...
-                'Compression', 'lzw');
-    end
-end
-- 
GitLab