1 module dsurf.io.zmaploader;
2 
3 import std.conv;
4 import std.stdio; 
5 import std.file;
6 import std..string;
7 import std.conv;
8 import std.math;
9 
10 import dsurf.cartesian;
11 import dsurf.io.loader;
12 
13 /**
14 Class that provides loading of IRAP Classic ASCII (aka ROXAR text) files
15 */
16 class ZmapLoader : CartesianSurfaceLoader {
17 
18     /// Loads an Zmap+ surface from a file in a given path
19     override CartesianSurface load(string fileName)
20     {
21         if (!exists(fileName))
22             throw new Exception("File " ~ fileName ~ " doesn't exist");
23         File file = File(fileName, "r");
24         auto surface = new CartesianSurface;
25         bool readingHeader = true;
26         int i = -1;
27         int j = -1;
28         double xOrigin = double.nan, yOrigin = double.nan;
29         double xMax = double.nan, yMax = double.nan;
30         double dx = double.nan, dy = double.nan;
31         int nx = -1, ny = -1;
32         double blank = double.nan;
33         while(!file.eof()) {
34             string line = file.readln().chomp().replace("\"", "");
35             if (readingHeader) {
36             if (line.startsWith("!"))
37                 continue;
38                 string [] words = line.replace(",", "").split();
39                 if (isNaN(blank)) {
40                     if (line.startsWith("@"))
41                         continue;
42                     blank = words[1].to!double;
43                 }
44                 else if (nx < 0) {
45                     nx = words[1].to!int;
46                     ny = words[0].to!int;
47                     xOrigin = words[2].to!double;
48                     yOrigin = words[4].to!double;
49                     xMax = words[3].to!double;
50                     yMax = words[5].to!double;
51                 }
52                 else if (isNaN(dx)) {
53                     dx = words[0].to!double;
54                     dy = words[1].to!double;
55                     if (dx == 0 || dy == 0) {
56                         dx = (xMax - xOrigin) / (nx - 1);
57                         dy = (yMax - yOrigin) / (ny - 1);
58                     }
59                 }
60                 else if (line.startsWith("@")) {
61                     surface.setHeader(nx, ny, xOrigin, yOrigin, dx, dy);
62                     readingHeader = false;
63                     i = 0;
64                     j = ny - 1;
65                 }
66             }
67             else {
68                 if (i < 0 || j < 0)
69                     throw new Exception("Invalid index");  //TODO add some information
70                 auto words = line.split();
71                 if (words.empty)
72                     continue;
73                 if (words[0].startsWith("+"))  //RMS specific
74                     continue;
75                 foreach (word; words) {
76                     double value = 0;
77                     try
78                         value = to!double(word);
79                     catch (ConvException e)
80                         value = double.nan;
81                     if (value == blank)
82                         surface.z[i][j] = double.nan;
83                     else
84                         surface.z[i][j] = value;
85                     
86                     j--;
87                     if (j < 0) {
88                         i++;
89                         j = surface.ny() - 1;
90                     }
91                 }
92             }
93         }
94         if (surface.nx == 0 || 
95             surface.ny == 0 || 
96             surface.dx == 0 || 
97             surface.dy == 0)
98             throw new Exception("Invalid header");
99         return surface;
100     }
101 }