1 module dsurf.io.zmapsaver; 2 3 import std.stdio; 4 import std.math; 5 6 import dsurf.cartesian; 7 import dsurf.io.saver; 8 import std.conv; 9 10 /// Class provides saving cartesian surfaces to Zmap+ file 11 class ZmapSaver : CartesianSurfaceSaver 12 { 13 /// Saves a given surface in a file with a given fileName 14 override void save(CartesianSurface surface, string fileName) { 15 File file = File(fileName, "w"); 16 immutable double blank = 1e30; 17 import std.path: baseName; 18 file.writeln("! dsurf - library for surface handling"); 19 file.writeln("! for D programming language"); 20 file.writeln("! GRID FILE NAME : "); 21 file.writeln("! CREATION DATE : "); 22 file.writeln("! CREATION TIME : "); 23 file.writeln("!"); 24 file.writeln("@" ~ baseName(fileName) ~ " HEADER, GRID, 5"); 25 // according to https://github.com/OSGeo/gdal/blob/master/gdal/frmts/zmap/zmapdataset.cpp 26 // 5 is a number of values per line but both Petrel and RMS saves 5 but ignores it in actual data 27 // so do we 28 29 file.write(" " ~ (surface.nx * surface.ny).to!string ~ ", " ~ blank.to!string ~ ", " ~ "," ~ "6, 1\n"); //6 decimals and default 1 (no idea whai it means) 30 file.write(surface.ny.to!string ~ ", " ~ surface.nx.to!string ~ ", "); 31 file.write(" " ~ surface.xOrigin.to!string ~ ", "); 32 file.write((surface.xOrigin + (surface.nx - 1) * surface.dx).to!string ~ ", "); 33 file.write(surface.yOrigin.to!string ~ ", "); 34 file.write((surface.yOrigin + (surface.ny - 1) * surface.dy).to!string ~ "\n"); 35 file.writeln(" " ~ "0.00, 0.00, 0.00"); //transform apparently 36 file.writeln("@"); //start of an actual data 37 int n = 0; 38 for (int i = 0; i < surface.nx; i++) { 39 for (int j = surface.ny - 1; j >= 0; j--) { 40 if (isNaN(surface.z[i][j])) 41 file.write(blank); 42 else 43 file.write(surface.z[i][j]); 44 n++; 45 if (n > 5) { 46 n = 0; 47 file.write("\n"); 48 } 49 else { 50 file.write(" "); 51 } 52 } 53 } 54 } 55 }