From 37f1bd324d01a425e5d396da2a363d7bdeeb36f4 Mon Sep 17 00:00:00 2001
From: Radek Oslejsek <oslejsek@fi.muni.cz>
Date: Tue, 27 Apr 2021 07:29:18 +0200
Subject: [PATCH] Added serialization

---
 .../cz/fidentis/analyst/face/HumanFace.java   | 44 ++++++++++++++++--
 .../cz/fidentis/analyst/symmetry/Plane.java   |  3 +-
 .../analyst/tests/EfficiencyTests.java        | 45 +++++++++++++++++--
 .../cz/fidentis/analyst/kdtree/KdNode.java    |  3 +-
 .../cz/fidentis/analyst/kdtree/KdTree.java    |  7 +--
 .../analyst/mesh/core/CornerTable.java        |  3 +-
 .../analyst/mesh/core/CornerTableRow.java     |  6 ++-
 .../fidentis/analyst/mesh/core/MeshFacet.java |  3 +-
 .../fidentis/analyst/mesh/core/MeshModel.java |  5 ++-
 .../fidentis/analyst/mesh/core/MeshPoint.java |  3 +-
 .../analyst/mesh/material/Material.java       | 19 +++++---
 application/src/main/resources/app.conf       |  2 +-
 12 files changed, 116 insertions(+), 27 deletions(-)

diff --git a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
index fa5bf458..17f82854 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/face/HumanFace.java
@@ -10,8 +10,12 @@ import cz.fidentis.analyst.symmetry.Plane;
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 
 /**
  * This class encapsulates data for a 3D scan of a single human face.
@@ -34,7 +38,7 @@ import java.io.InputStream;
  * 
  * @author Radek Oslejsek
  */
-public class HumanFace implements MeshListener {
+public class HumanFace implements MeshListener, Serializable {
     
     private MeshModel meshModel;
 
@@ -42,10 +46,11 @@ public class HumanFace implements MeshListener {
 
     private MeshFacet cuttingPlane;
     
-    private EventBus eventBus = new EventBus();
+    private transient EventBus eventBus = new EventBus();
     
     /**
-     * Reads a 3D human phase from file.
+     * Reads a 3D human face from the given OBJ file.
+     * Use {@link restoreFromFile} to restore the human face from a dump file.
      * 
      * @param file OBJ file
      * @throws IOException on I/O failure
@@ -55,7 +60,8 @@ public class HumanFace implements MeshListener {
     }
     
     /**
-     * Reads a 3D human phase from file.
+     * Reads a 3D human face from the given OBJ stream.
+     * Use {@link restoreFromFile} to restore the human face from a dump file.
      * 
      * @param is input stream with OBJ data
      * @throws IOException on I/O failure
@@ -136,4 +142,34 @@ public class HumanFace implements MeshListener {
     public MeshFacet getCuttingPlane() {
         return cuttingPlane;
     }
+
+    /**
+     * Creates serialized dump of the human face. Event buses are not stored.
+     * Therefore, listeners have to re-register again after recovery.
+     * 
+     * @return Dump file
+     * @throws IOException on error in creating the dump file
+     */
+    public File dumpToFile() throws IOException {
+        File tempFile = File.createTempFile(this.getClass().getSimpleName(), ".ser");
+        tempFile.deleteOnExit();
+        try (ObjectOutputStream fos = new ObjectOutputStream(new FileOutputStream(tempFile))) {
+            fos.writeObject(this);
+        }
+        return tempFile;
+    }
+    
+    /**
+     * Restores human face from a dump file.
+     * 
+     * @param dumpFile The file
+     * @return Human face
+     * @throws IOException on error in reading the dump file
+     * @throws java.lang.ClassNotFoundException on error when instantiating the human face
+     */
+    public static HumanFace restoreFromFile(File dumpFile) throws IOException, ClassNotFoundException {
+        try (ObjectInputStream fos = new ObjectInputStream(new FileInputStream(dumpFile))) {
+            return (HumanFace) fos.readObject();
+        }
+    }
 }
diff --git a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
index f27a4d69..83fa87ff 100644
--- a/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
+++ b/Comparison/src/main/java/cz/fidentis/analyst/symmetry/Plane.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.symmetry;
 
+import java.io.Serializable;
 import java.util.List;
 import javax.vecmath.Vector3d;
 
@@ -8,7 +9,7 @@ import javax.vecmath.Vector3d;
  * 
  * @author Natalia Bebjakova
  */
-public class Plane {
+public class Plane implements Serializable {
    
     private Vector3d normal;
     private double   distance;
diff --git a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
index a8f5bbda..d92797ad 100644
--- a/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
+++ b/GUI/src/main/java/cz/fidentis/analyst/tests/EfficiencyTests.java
@@ -12,6 +12,7 @@ import cz.fidentis.analyst.visitors.mesh.HausdorffDistance;
 import cz.fidentis.analyst.visitors.mesh.HausdorffDistance.Strategy;
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -25,7 +26,7 @@ public class EfficiencyTests {
     private static File girlFile = new File("src/test/resources/cz/fidentis/analyst/average_girl_17-20.obj");
     private static File boyFile = new File("src/test/resources/cz/fidentis/analyst/average_boy_17-20.obj");
     private static File faceFile2 = new File("src/test/resources/cz/fidentis/analyst/00002_01_ECA.obj");
-    private static File faceFile4 = new File("src/test/resources/cz/fidentis/analyst/00004_01_ECA.obj");
+    private static File faceFile4 = new File("/home/oslejsek/GIT/HCI/analyst2/GUI/src/test/resources/cz/fidentis/analyst/00004_01_ECA.obj");
     private static File basicFaceFile = new File("src/test/resources/cz/fidentis/analyst/basic-model-04.obj");
     
     private static HumanFace face1;
@@ -36,16 +37,27 @@ public class EfficiencyTests {
      * @param args Input arguments 
      * @throws IOException on IO error
      */
-    public static void main(String[] args) throws IOException {
-        face1 = new HumanFace(boyFile);
-        face2 = new HumanFace(faceFile4);
+    public static void main(String[] args) throws IOException, ClassNotFoundException {
+        face1 = printFaceLoad(faceFile4);
+        face2 = printFaceLoad(faceFile4);
         
         face1.getMeshModel().simplifyModel();
         face2.getMeshModel().simplifyModel();
         
+        List<HumanFace> list = new ArrayList<>();
+        for (int i = 0; i < 500; i++) {
+            System.out.print(i+". " + formatSize(Runtime.getRuntime().freeMemory()) + "/" + formatSize(Runtime.getRuntime().maxMemory()) + " ");
+            HumanFace face = printFaceLoad(faceFile4);
+            face.getMeshModel().simplifyModel();
+            list.add(face);
+        }
+        list.clear();
+        
         boolean relativeDist = false;
         boolean printDetails = false;
         
+        printFaceDump(face1);
+        
         //face1.getMeshModel().compute(new GaussianCurvature()); // initialize everything, then measure
         
         System.out.println("ICP:");
@@ -118,5 +130,30 @@ public class EfficiencyTests {
                 "\t" + plane.getNormal() + ", " + plane.getDistance()
         );
     }
+
+    private static void printFaceDump(HumanFace face) throws IOException, ClassNotFoundException {
+        long startTime = System.currentTimeMillis();
+        File file = face.dumpToFile();
+        long endTime =  System.currentTimeMillis();
+        System.out.println("Human face dumping:\t " +(endTime-startTime) + " msec");
+        
+        startTime = System.currentTimeMillis();
+        HumanFace f = HumanFace.restoreFromFile(file);
+        endTime =  System.currentTimeMillis();
+        System.out.println("Human face restore:\t " +(endTime-startTime) + " msec");
+    }
+    
+    private static HumanFace printFaceLoad(File file) throws IOException {
+        long startTime = System.currentTimeMillis();
+        HumanFace face = new HumanFace(file);
+        long endTime =  System.currentTimeMillis();
+        System.out.println("Human face loading:\t " +(endTime-startTime) + " msec");
+        return face;
+    }
     
+    public static String formatSize(long v) {
+        if (v < 1024) return v + " B";
+        int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
+        return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
+    }
 }
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
index 6bf3652f..bee586a8 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdNode.java
@@ -1,6 +1,7 @@
 package cz.fidentis.analyst.kdtree;
 
 import cz.fidentis.analyst.mesh.core.MeshFacet;
+import java.io.Serializable;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -14,7 +15,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Maria Kocurekova
  */
-public class KdNode {
+public class KdNode implements Serializable {
     
     /**
      * Current depth in the kd-tree
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
index 7feb0a6b..a2c6e7fd 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/kdtree/KdTree.java
@@ -4,6 +4,7 @@ import com.google.common.eventbus.EventBus;
 import cz.fidentis.analyst.mesh.core.MeshFacet;
 import cz.fidentis.analyst.mesh.core.MeshFacetImpl;
 import cz.fidentis.analyst.mesh.core.MeshPoint;
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -34,11 +35,11 @@ import javax.vecmath.Vector3d;
  * @author Maria Kocurekova
  * @author Radek Oslejsek
  */
-public class KdTree {
+public class KdTree implements Serializable {
     
     private KdNode root;
     
-    private EventBus eventBus = new EventBus();
+    private final transient EventBus eventBus = new EventBus();
     
     /**
      * Constructor.
@@ -140,8 +141,8 @@ public class KdTree {
     public void accept(KdTreeVisitor visitor) {
         visitor.visitKdTree(this);
     }
-
     
+
     /***********************************************************
      *  PRIVATE METHODS
      ***********************************************************/  
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
index 5157c085..57cc5615 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTable.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -13,7 +14,7 @@ import java.util.stream.Collectors;
  *
  * @author Matej Lukes
  */
-public class CornerTable {
+public class CornerTable implements Serializable {
 
     private final List<CornerTableRow> rows = new ArrayList<>();
     
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
index 761ce9e9..77826dc7 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/CornerTableRow.java
@@ -1,11 +1,13 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
+
 /**
- * single row in corner table
+ * Single row in corner table.
  *
  * @author Matej Lukes
  */
-public class CornerTableRow {
+public class CornerTableRow implements Serializable {
     
     /**
      * Index to the corner (corner table row) with a vertex on the opposite triangle
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
index 6f3a8f9f..aad67f19 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshFacet.java
@@ -2,6 +2,7 @@ package cz.fidentis.analyst.mesh.core;
 
 import java.util.List;
 import cz.fidentis.analyst.mesh.MeshVisitor;
+import java.io.Serializable;
 import javax.vecmath.Vector3d;
 
 /**
@@ -11,7 +12,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Matej Lukes
  */
-public interface MeshFacet extends Iterable<MeshTriangle> {
+public interface MeshFacet extends Iterable<MeshTriangle>, Serializable {
     
     /**
      * returns vertex of specified index
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
index de605a83..b17354e3 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshModel.java
@@ -7,6 +7,7 @@ import cz.fidentis.analyst.mesh.MeshVisitor;
 import cz.fidentis.analyst.mesh.events.FacetAddedEvent;
 import java.util.Collections;
 import cz.fidentis.analyst.mesh.events.MeshListener;
+import java.io.Serializable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -28,11 +29,11 @@ import java.util.concurrent.Executors;
  * @author Matej Lukes
  * @author Radek Oslejsek
  */
-public class MeshModel {
+public class MeshModel implements Serializable {
     
     private final List<MeshFacet> facets = new ArrayList<>();
     
-    private EventBus eventBus = new EventBus();
+    private final transient EventBus eventBus = new EventBus();
     
     /**
      * Constructor of MeshModel
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
index d79b2784..a395bdd7 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/core/MeshPoint.java
@@ -1,5 +1,6 @@
 package cz.fidentis.analyst.mesh.core;
 
+import java.io.Serializable;
 import javax.vecmath.Vector3d;
 
 /**
@@ -7,7 +8,7 @@ import javax.vecmath.Vector3d;
  *
  * @author Matej Lukes
  */
-public interface MeshPoint {
+public interface MeshPoint extends Serializable {
     
     /**
      * Helper method that calculates distance of two 3D points.
diff --git a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
index 367d4243..5a062394 100644
--- a/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
+++ b/MeshModel/src/main/java/cz/fidentis/analyst/mesh/material/Material.java
@@ -3,18 +3,25 @@ import javax.media.j3d.Texture;
 import javax.vecmath.Vector3d;
 
 /**
+ * Material.
+ * 
  * @author Matej Lukes
  */
 public class Material {
-    private String name;
-
+    
+    private final String name;
     // colour info
-    private Vector3d ambient, diffuse, specularColors;
-    private double shininess, alpha, illumination;
+    private final Vector3d ambient;
+    private final Vector3d diffuse;
+    private final Vector3d specularColors;
+    
+    private final double shininess;
+    private final double alpha;
+    private final double illumination;
 
     // texture info
-    private String textureFileName;
-    private Texture texture;
+    private final String textureFileName;
+    private final Texture texture;
 
     /**
      *
diff --git a/application/src/main/resources/app.conf b/application/src/main/resources/app.conf
index 2503371a..bcf74bd5 100644
--- a/application/src/main/resources/app.conf
+++ b/application/src/main/resources/app.conf
@@ -4,7 +4,7 @@ default_mac_userdir="${HOME}/Library/Application Support/${APPNAME}/dev"
 
 # options used by the launcher by default, can be overridden by explicit
 # command line switches
-default_options="--branding fidentisanalyst -J-Xms24m -J-Xmx1G"
+default_options="--branding fidentisanalyst -J-Xms4G -J-Xmx4G"
 # for development purposes you may wish to append: -J-Dnetbeans.logger.console=true -J-ea
 
 # default location of JDK/JRE, can be overridden by using --jdkhome <dir> switch
-- 
GitLab