From 69882db50f5f3af3cb3bdf10940ceb00b30ca41a Mon Sep 17 00:00:00 2001
From: remicres <remi.cresson@teledetection.fr>
Date: Tue, 23 Aug 2016 15:23:30 +0000
Subject: [PATCH] ADD: Generic methods in segmenters for graphs serialization

---
 include/lsrmBaatzSegmenter.h   |   2 +
 include/lsrmBaatzSegmenter.txx |  36 +++++++++
 include/lsrmSegmenter.h        | 140 ++++++++++++++++++++++++++++++++-
 3 files changed, 177 insertions(+), 1 deletion(-)

diff --git a/include/lsrmBaatzSegmenter.h b/include/lsrmBaatzSegmenter.h
index 0495d09..52b221e 100644
--- a/include/lsrmBaatzSegmenter.h
+++ b/include/lsrmBaatzSegmenter.h
@@ -93,6 +93,8 @@ namespace lsrm
 		void Update();
 		float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
 		void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
+        void WriteSpecificAttributes(NodePointerType node, FILE * nodeStream);
+        void ReadSpecificAttributes(NodePointerType node, FILE * nodeStream);
 		void InitFromImage();
 		long long unsigned int GetNodeMemory(NodePointerType &node);
 	};
diff --git a/include/lsrmBaatzSegmenter.txx b/include/lsrmBaatzSegmenter.txx
index 5f30c26..aada2bc 100644
--- a/include/lsrmBaatzSegmenter.txx
+++ b/include/lsrmBaatzSegmenter.txx
@@ -104,6 +104,42 @@ namespace lsrm
 	}
 
 	template<class TImage>
+	void
+	BaatzSegmenter<TImage>::WriteSpecificAttributes(NodePointerType node, FILE * nodeStream)
+	{
+	  std::size_t bands = node->m_Means.size();
+	  fwrite(&(bands), sizeof(bands), 1, nodeStream);
+
+	  for(unsigned int b = 0; b < node->m_Means.size(); b++)
+	    {
+	    fwrite(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream);
+	    fwrite(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream);
+	    fwrite(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream);
+	    fwrite(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream);
+	    }
+	}
+
+    template<class TImage>
+    void
+    BaatzSegmenter<TImage>::ReadSpecificAttributes(NodePointerType node, FILE * nodeStream)
+    {
+      std::size_t bands;
+      fread(&(bands), sizeof(bands), 1, nodeStream);
+      node->m_Means.assign(bands, 0);
+      node->m_SquareMeans.assign(bands, 0);
+      node->m_SpectralSum.assign(bands, 0);
+      node->m_Std.assign(bands, 0);
+
+      for(unsigned int b = 0; b < bands; b++)
+        {
+        fread(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream);
+        fread(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream);
+        fread(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream);
+        fread(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream);
+        }
+    }
+
+    template<class TImage>
 	void
 	BaatzSegmenter<TImage>::Update()
 	{
diff --git a/include/lsrmSegmenter.h b/include/lsrmSegmenter.h
index c73c9ed..c7782dc 100644
--- a/include/lsrmSegmenter.h
+++ b/include/lsrmSegmenter.h
@@ -54,7 +54,7 @@ namespace lsrm
 
 		/*
 		 * Given 2 smart adjacent node pointers (boost::shared_ptr), this
-		 * method merges th node n2 into the node n1 by updating the customized
+		 * method merges the node n2 into the node n1 by updating the customized
 		 * attributes of the node n1.
 		 *
 		 * @params
@@ -64,6 +64,144 @@ namespace lsrm
 		 */
 		virtual void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2) = 0;
 
+        /*
+         * Given 1 smart node pointer (boost::shared_ptr), this
+         * method writes the node specific attributes into the node stream.
+         *
+         * @params
+         * NodePointerType n : Smart pointer of node
+         *
+         */
+        virtual void WriteSpecificAttributes(NodePointerType node, FILE * nodeStream) = 0;
+
+        /*
+         * Given 1 smart node pointer (boost::shared_ptr), this
+         * method read the node specific attributes from the node stream.
+         *
+         * @params
+         * NodePointerType n : Smart pointer of node
+         * FILE * nodeStream : Node stream
+         *
+         */
+        virtual void ReadSpecificAttributes(NodePointerType node, FILE * nodeStream) = 0;
+
+        /*
+         * Given 1 smart node pointer (boost::shared_ptr), this
+         * method writes the node into a stream.
+         *
+         * @params
+         * NodePointerType n : Smart pointer of node
+         * FILE * nodeStream : Node stream
+         *
+         */
+        void WriteNode(NodePointerType node, FILE * nodeStream)
+        {
+          fwrite(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream);
+          fwrite(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream);
+          fwrite(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream);
+          fwrite(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream);
+          fwrite(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream);
+          fwrite(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream);
+          fwrite(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream);
+
+          this->WriteSpecificAttributes(node, nodeStream);
+
+          std::size_t contourSize = node->m_Contour.size();
+          fwrite(&(contourSize), sizeof(contourSize), 1, nodeStream);
+          short moves[contourSize];
+          for(unsigned int b = 0; b < contourSize; b++)
+            {
+            moves[b] = node->m_Contour[b];
+            }
+          fwrite(moves, sizeof(short), contourSize, nodeStream);
+        }
+
+        /*
+         * This method reads a graph from a stream.
+         *
+         * @params
+         * FILE * nodeStream : Node stream
+         *
+         */
+        void ReadGraph(FILE * nodeStream, FILE * edgeStream)
+        {
+
+          std::unordered_map<long unsigned int, NodePointerType> nodeMap;
+
+          // Read the size of the graph
+          {
+          std::size_t graphSize;
+          fread(&graphSize, sizeof(graphSize), 1, nodeStream);
+          this->m_Graph.m_Nodes.reserve(graphSize);
+
+          // Creation of the nodes
+          for(std::size_t i = 0; i < graphSize; i++)
+            {
+            NodePointerType node(new NodeType());
+
+            node->m_Valid = true;
+            node->m_Expired = false;
+            node->m_IsMerged = true; // force to compute costs for the first iteration
+
+            fread(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream);
+            fread(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream);
+            fread(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream);
+            fread(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream);
+            fread(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream);
+            fread(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream);
+            fread(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream);
+
+            this->ReadSpecificAttributes(node, nodeStream);
+
+            {
+              std::size_t contourSize;
+              fread(&(contourSize), sizeof(contourSize), 1, nodeStream);
+              short moves[contourSize];
+              fread(&moves, sizeof(short), contourSize, nodeStream);
+              for(unsigned int b = 0; b < contourSize; b++)
+                {
+                node->m_Contour.push_back(moves[b]);
+                }
+            }
+            nodeMap[node->m_Id] = node;
+            this->m_Graph.m_Nodes.push_back(node);
+            }
+          }
+
+          for(auto& node: this->m_Graph.m_Nodes)
+            {
+            long unsigned int nodeId;
+            fread(&(nodeId), sizeof(nodeId), 1, edgeStream);
+            assert(nodeId == node->m_Id);
+
+            std::size_t edgeSize;
+            fread(&(edgeSize), sizeof(edgeSize), 1, edgeStream);
+            node->m_Edges.reserve(edgeSize);
+            for(unsigned int b = 0; b < edgeSize; b++)
+              {
+              long unsigned int targetId;
+              unsigned int boundary;
+              fread(&(targetId), sizeof(targetId), 1, edgeStream);
+              fread(&(boundary), sizeof(boundary), 1, edgeStream);
+              node->m_Edges.push_back(EdgeType(nodeMap[targetId], 0, boundary));
+              }
+            }
+
+        }
+
+        /*
+         * This method writes the edge into a stream.
+         *
+         * @params
+         * EdgePointerType edg : Smart pointer of edge
+         *
+         */
+        void WriteEdge(typename NodeType::CRPTNeighborType edg, FILE * edgeStream)
+        {
+          fwrite(&(edg.GetRegion()->m_Id), sizeof(edg.GetRegion()->m_Id), 1, edgeStream);
+          fwrite(&(edg.m_Boundary), sizeof(edg.m_Boundary), 1, edgeStream);
+        }
+
 		/*
 		 * Given the input image, this method initializes the
 		 * internal and specific attributes of the graph.
-- 
GitLab