1 | |
---|
2 | from anuga.coordinate_transforms.geo_reference import Geo_reference |
---|
3 | from anuga.geospatial_data.geospatial_data import Geospatial_data |
---|
4 | |
---|
5 | def _read_hecras_cross_sections(lines): |
---|
6 | """Return block of surface lines for each cross section |
---|
7 | Starts with SURFACE LINE, |
---|
8 | Ends with END CROSS-SECTION |
---|
9 | """ |
---|
10 | |
---|
11 | points = [] |
---|
12 | |
---|
13 | reading_surface = False |
---|
14 | for i, line in enumerate(lines): |
---|
15 | if len(line.strip()) == 0: #Ignore blanks |
---|
16 | continue |
---|
17 | |
---|
18 | if lines[i].strip().startswith('SURFACE LINE'): |
---|
19 | reading_surface = True |
---|
20 | continue |
---|
21 | |
---|
22 | if lines[i].strip().startswith('END') and reading_surface: |
---|
23 | yield points |
---|
24 | reading_surface = False |
---|
25 | points = [] |
---|
26 | |
---|
27 | if reading_surface: |
---|
28 | fields = line.strip().split(',') |
---|
29 | easting = float(fields[0]) |
---|
30 | northing = float(fields[1]) |
---|
31 | elevation = float(fields[2]) |
---|
32 | points.append([easting, northing, elevation]) |
---|
33 | |
---|
34 | |
---|
35 | |
---|
36 | def sdf2pts(name_in, |
---|
37 | name_out=None, |
---|
38 | verbose=False): |
---|
39 | """Read HEC-RAS Elevation datal from the following ASCII format (.sdf) |
---|
40 | |
---|
41 | basename_in Sterm of input filename. |
---|
42 | basename_out Sterm of output filename. |
---|
43 | verbose True if this function is to be verbose. |
---|
44 | |
---|
45 | Example: |
---|
46 | |
---|
47 | # RAS export file created on Mon 15Aug2005 11:42 |
---|
48 | # by HEC-RAS Version 3.1.1 |
---|
49 | |
---|
50 | BEGIN HEADER: |
---|
51 | UNITS: METRIC |
---|
52 | DTM TYPE: TIN |
---|
53 | DTM: v:\1\cit\perth_topo\river_tin |
---|
54 | STREAM LAYER: c:\local\hecras\21_02_03\up_canning_cent3d.shp |
---|
55 | CROSS-SECTION LAYER: c:\local\hecras\21_02_03\up_can_xs3d.shp |
---|
56 | MAP PROJECTION: UTM |
---|
57 | PROJECTION ZONE: 50 |
---|
58 | DATUM: AGD66 |
---|
59 | VERTICAL DATUM: |
---|
60 | NUMBER OF REACHES: 19 |
---|
61 | NUMBER OF CROSS-SECTIONS: 14206 |
---|
62 | END HEADER: |
---|
63 | |
---|
64 | Only the SURFACE LINE data of the following form will be utilised |
---|
65 | CROSS-SECTION: |
---|
66 | STREAM ID:Southern-Wungong |
---|
67 | REACH ID:Southern-Wungong |
---|
68 | STATION:19040.* |
---|
69 | CUT LINE: |
---|
70 | 405548.671603161 , 6438142.7594925 |
---|
71 | 405734.536092045 , 6438326.10404912 |
---|
72 | 405745.130459356 , 6438331.48627354 |
---|
73 | 405813.89633823 , 6438368.6272789 |
---|
74 | SURFACE LINE: |
---|
75 | 405548.67, 6438142.76, 35.37 |
---|
76 | 405552.24, 6438146.28, 35.41 |
---|
77 | 405554.78, 6438148.78, 35.44 |
---|
78 | 405555.80, 6438149.79, 35.44 |
---|
79 | 405559.37, 6438153.31, 35.45 |
---|
80 | 405560.88, 6438154.81, 35.44 |
---|
81 | 405562.93, 6438156.83, 35.42 |
---|
82 | 405566.50, 6438160.35, 35.38 |
---|
83 | 405566.99, 6438160.83, 35.37 |
---|
84 | ... |
---|
85 | END CROSS-SECTION |
---|
86 | |
---|
87 | Convert to NetCDF pts format which is |
---|
88 | |
---|
89 | points: (Nx2) float array |
---|
90 | elevation: N float array |
---|
91 | """ |
---|
92 | |
---|
93 | import os |
---|
94 | from anuga.file.netcdf import NetCDFFile |
---|
95 | |
---|
96 | if name_in[-4:] != '.sdf': |
---|
97 | raise IOError('Input file %s should be of type .sdf.' % name_in) |
---|
98 | |
---|
99 | if name_out is None: |
---|
100 | name_out = name_in[:-4] + '.pts' |
---|
101 | elif name_out[-4:] != '.pts': |
---|
102 | raise IOError('Input file %s should be of type .pts.' % name_out) |
---|
103 | |
---|
104 | # Get ASCII file |
---|
105 | infile = open(name_in, 'r') |
---|
106 | |
---|
107 | if verbose: log.critical('Reading DEM from %s' % (root + '.sdf')) |
---|
108 | |
---|
109 | lines = infile.readlines() |
---|
110 | infile.close() |
---|
111 | |
---|
112 | if verbose: log.critical('Converting to pts format') |
---|
113 | |
---|
114 | # Scan through the header, picking up stuff we need. |
---|
115 | i = 0 |
---|
116 | while lines[i].strip() == '' or lines[i].strip().startswith('#'): |
---|
117 | i += 1 |
---|
118 | |
---|
119 | assert lines[i].strip().upper() == 'BEGIN HEADER:' |
---|
120 | i += 1 |
---|
121 | |
---|
122 | assert lines[i].strip().upper().startswith('UNITS:') |
---|
123 | units = lines[i].strip().split()[1] |
---|
124 | i += 1 |
---|
125 | |
---|
126 | assert lines[i].strip().upper().startswith('DTM TYPE:') |
---|
127 | i += 1 |
---|
128 | |
---|
129 | assert lines[i].strip().upper().startswith('DTM:') |
---|
130 | i += 1 |
---|
131 | |
---|
132 | assert lines[i].strip().upper().startswith('STREAM') |
---|
133 | i += 1 |
---|
134 | |
---|
135 | assert lines[i].strip().upper().startswith('CROSS') |
---|
136 | i += 1 |
---|
137 | |
---|
138 | assert lines[i].strip().upper().startswith('MAP PROJECTION:') |
---|
139 | projection = lines[i].strip().split(':')[1] |
---|
140 | i += 1 |
---|
141 | |
---|
142 | assert lines[i].strip().upper().startswith('PROJECTION ZONE:') |
---|
143 | zone = int(lines[i].strip().split(':')[1]) |
---|
144 | i += 1 |
---|
145 | |
---|
146 | assert lines[i].strip().upper().startswith('DATUM:') |
---|
147 | datum = lines[i].strip().split(':')[1] |
---|
148 | i += 1 |
---|
149 | |
---|
150 | assert lines[i].strip().upper().startswith('VERTICAL DATUM:') |
---|
151 | i += 1 |
---|
152 | |
---|
153 | assert lines[i].strip().upper().startswith('NUMBER OF REACHES:') |
---|
154 | i += 1 |
---|
155 | |
---|
156 | assert lines[i].strip().upper().startswith('NUMBER OF CROSS-SECTIONS:') |
---|
157 | number_of_cross_sections = int(lines[i].strip().split(':')[1]) |
---|
158 | i += 1 |
---|
159 | |
---|
160 | # Now read all points |
---|
161 | points = [] |
---|
162 | elevation = [] |
---|
163 | for j, entries in enumerate(_read_hecras_cross_sections(lines[i:])): |
---|
164 | for k, entry in enumerate(entries): |
---|
165 | points.append(entry[:2]) |
---|
166 | elevation.append(entry[2]) |
---|
167 | |
---|
168 | msg = 'Actual #number_of_cross_sections == %d, Reported as %d'\ |
---|
169 | %(j+1, number_of_cross_sections) |
---|
170 | assert j+1 == number_of_cross_sections, msg |
---|
171 | |
---|
172 | # Get output file, write PTS data |
---|
173 | if name_out == None: |
---|
174 | ptsname = name_in[:-4] + '.pts' |
---|
175 | else: |
---|
176 | ptsname = name_out |
---|
177 | |
---|
178 | geo_ref = Geo_reference(zone, 0, 0, datum, projection, units) |
---|
179 | geo = Geospatial_data(points, {"elevation":elevation}, |
---|
180 | verbose=verbose, geo_reference=geo_ref) |
---|
181 | geo.export_points_file(ptsname) |
---|