FTreeIO.hpp 8.38 KB
Newer Older
1
// See LICENCE file at project root
2 3 4 5 6 7
#ifndef FTREEIO_HPP
#define FTREEIO_HPP

#include <iostream>
#include <fstream>

COULAUD Olivier's avatar
COULAUD Olivier committed
8 9 10 11
#include "Utils/FPoint.hpp"
#include "Containers/FBufferReader.hpp"
#include "Containers/FBufferWriter.hpp"
#include "Utils/FPoint.hpp"
12 13


14 15 16 17 18 19 20 21 22 23 24
/** This class proposes static methods to save and load
  * a tree.
  * It used binary format (so FReal must be the same!)
  *
  * The format is :
  * [nb leaves]
  * [nb particles in leaf][particles.....] ...
  * [nb cells at level]
  * [morton index][cell] ....
  * ...
  */
25
template <class FReal>
26
class FTreeIO{
27 28 29 30 31 32 33

    enum TargetSourceDiff{
        TsmUndef,
        TsmUsed,
        TsmUnused
    };

34 35
public:
    /** To save in memory */
36
    template <class OctreeClass, class CellClass, class LeafClass, class ContainerClass >
37 38
    static bool Save(const char filename[], OctreeClass& tree){
        std::ofstream file(filename, std::ofstream::binary | std::ofstream::out );
39
        FBufferWriter buffer;
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

        if(!file.good()){
            return false;
        }

        const size_t sizeof_freal = sizeof(FReal);
        file.write((const char*)&sizeof_freal, sizeof(size_t));

        const int height = tree.getHeight();
        file.write((const char*)&height, sizeof(int));

        const int subHeight = tree.getSubHeight();
        file.write((const char*)&subHeight, sizeof(int));

        const FReal width = tree.getBoxWidth();
        file.write((const char*)&width, sizeof(FReal));

57
        file.write((const char*)&tree.getBoxCenter(), sizeof(FPoint<FReal>));
58 59 60 61 62 63 64 65 66 67 68

        {
            typename OctreeClass::Iterator octreeIterator(&tree);

            int nbLeaf = 0;
            const std::ofstream::pos_type posNbLeaf = file.tellp();
            file.write((const char*)&nbLeaf,sizeof(int));

            octreeIterator.gotoBottomLeft();
            const bool useTargetSource = (octreeIterator.getCurrentListSrc() != octreeIterator.getCurrentListTargets());
            if( useTargetSource ){
69 70 71
                TargetSourceDiff tsm = TsmUsed;
                file.write((const char*)&tsm,sizeof(tsm));

72
                do{
73 74
                    const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex();
                    file.write((const char*)&mindex,sizeof(mindex));
75 76

                    buffer.reset();
77 78
                    octreeIterator.getCurrentListSrc()->save(buffer);
                    octreeIterator.getCurrentListTargets()->save(buffer);
79

80 81
                    const FSize sizeOfLeaf = buffer.getSize();
                    file.write((const char*) &sizeOfLeaf, sizeof(FSize));
82
                    file.write(buffer.data(), buffer.getSize());
83 84 85 86 87

                    ++nbLeaf;
                } while(octreeIterator.moveRight());
            }
            else{
88 89
                TargetSourceDiff tsm = TsmUnused;
                file.write((const char*)&tsm,sizeof(tsm));
90
                do{
91 92
                    const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex();
                    file.write((const char*)&mindex,sizeof(mindex));
93 94

                    buffer.reset();
95
                    octreeIterator.getCurrentListSrc()->save(buffer);
96

97 98
                    const FSize sizeOfLeaf = buffer.getSize();
                    file.write((const char*) &sizeOfLeaf, sizeof(FSize));
99 100
                    file.write(buffer.data(), buffer.getSize());

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
                    ++nbLeaf;
                } while(octreeIterator.moveRight());
            }

            const std::ofstream::pos_type currentPos = file.tellp();
            file.seekp(posNbLeaf);
            file.write((const char*)&nbLeaf,sizeof(int));
            file.seekp(currentPos);
        }

        // Start from leal level - 1
        typename OctreeClass::Iterator octreeIterator(&tree);
        octreeIterator.gotoBottomLeft();

        typename OctreeClass::Iterator avoidGotoLeftIterator(octreeIterator);

        // for each levels
        for(int idxLevel = tree.getHeight() - 1 ; idxLevel > 1 ; --idxLevel ){
            int nbCells = 0;
            const std::ofstream::pos_type posNbCells = file.tellp();
            file.write((const char*)&nbCells,sizeof(int));

            do{
                const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex();
125 126 127 128
                file.write((const char*)&mindex,sizeof(MortonIndex));

                buffer.reset();
                octreeIterator.getCurrentCell()->save(buffer);
129 130
                const FSize sizeOfCell = buffer.getSize();
                file.write((const char*) &sizeOfCell, sizeof(FSize));
131 132
                file.write(buffer.data(), buffer.getSize());

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
                ++nbCells;
            } while(octreeIterator.moveRight());

            const std::ofstream::pos_type currentPos = file.tellp();
            file.seekp(posNbCells);
            file.write((const char*)&nbCells,sizeof(int));
            file.seekp(currentPos);

            avoidGotoLeftIterator.moveUp();
            octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft();
        }


        file.flush();
        file.close();

        return true;
    }


    /** To load from memory */
154
    template <class OctreeClass, class CellClass, class LeafClass, class ContainerClass  >
155 156
    static bool Load(const char filename[], OctreeClass& tree){
        std::ifstream file(filename, std::ifstream::binary | std::ifstream::in );
157
        FBufferReader buffer;
158 159 160 161 162 163 164 165

        if(!file.good()){
            return false;
        }

        size_t sizeof_freal = 0;
        file.read((char*)&sizeof_freal, sizeof(size_t));
        if( sizeof_freal != sizeof(FReal)){
166 167
            std::cerr << "[Loader] Error Freal do not coincide with file type:\n";
            std::cerr << "[Loader] In file : " << sizeof_freal << " Real : " << sizeof(FReal) << "\n";
168 169 170 171 172 173 174 175 176
            return false;
        }

        int treeHeight = 0;
        file.read((char*)&treeHeight, sizeof(int));
        int treeSubHeight = 0;
        file.read((char*)&treeSubHeight, sizeof(int));
        FReal boxWidth = 0;
        file.read((char*)&boxWidth, sizeof(FReal));
177 178
        FPoint<FReal> center;
        file.read((char*)&center, sizeof(FPoint<FReal>));
179 180 181 182 183 184 185 186

        tree.~OctreeClass();
        new (&tree) OctreeClass(treeHeight,treeSubHeight,boxWidth,center);

        {
            int nbLeaf = 0;
            file.read((char*)&nbLeaf, sizeof(int));

187 188
            TargetSourceDiff tsm = TsmUndef;
            file.read((char*)&tsm,sizeof(tsm));
189 190

            for(int idxLeaf = 0 ; idxLeaf < nbLeaf ; ++idxLeaf){
191 192
                MortonIndex mindex = 0;
                file.read((char*)&mindex, sizeof(mindex));
193

194 195
                FSize sizeOfLeaf = 0;
                file.read((char*)&sizeOfLeaf, sizeof(FSize));
196

COULAUD Olivier's avatar
COULAUD Olivier committed
197
                buffer.seek(0);
198 199 200
                buffer.reserve(sizeOfLeaf);
                file.read((char*)buffer.data(), sizeOfLeaf);

201 202 203 204 205
                LeafClass*const leaf = tree.createLeaf(mindex);
                leaf->getSrc()->restore(buffer);

                if( tsm == TsmUsed ){
                    leaf->getTargets()->restore(buffer);
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
                }
            }
        }

        // Start from leal level - 1
        typename OctreeClass::Iterator octreeIterator(&tree);
        octreeIterator.gotoBottomLeft();

        typename OctreeClass::Iterator avoidGotoLeftIterator(octreeIterator);

        // for each levels
        for(int idxLevel = tree.getHeight() - 1 ; idxLevel > 1 ; --idxLevel ){
            int nbCells = 0;
            file.read((char*)&nbCells, sizeof(int));

            do{
                MortonIndex mindex;
                file.read((char*)&mindex, sizeof(MortonIndex));
                if(mindex != octreeIterator.getCurrentGlobalIndex()){
225
                    std::cerr << "[Loader] Error indexes are different\n";
226 227 228
                    return false;
                }

229 230
                FSize sizeOfCell = 0;
                file.read((char*)&sizeOfCell, sizeof(FSize));
231

COULAUD Olivier's avatar
COULAUD Olivier committed
232
                buffer.seek(0);
233 234 235 236 237
                buffer.reserve(sizeOfCell);
                file.read((char*)buffer.data(), sizeOfCell);

                octreeIterator.getCurrentCell()->restore(buffer);

238 239 240 241
                --nbCells;
            } while(octreeIterator.moveRight());

            if(nbCells != 0){
242
                std::cerr << "[Loader] Wrong number of cells at level " << idxLevel << "\n";
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
                return false;
            }

            avoidGotoLeftIterator.moveUp();
            octreeIterator = avoidGotoLeftIterator;
        }

        file.close();

        return true;
    }

};


#endif // FTREEIO_HPP