comparison backend/src/main/java/org/dive4elements/river/importer/parsers/W80Parser.java @ 5838:5aa05a7a34b7

Rename modules to more fitting names.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 15:23:37 +0200
parents flys-backend/src/main/java/org/dive4elements/river/importer/parsers/W80Parser.java@18619c1e7c2a
children 4dd33b86dc61
comparison
equal deleted inserted replaced
5837:d9901a08d0a6 5838:5aa05a7a34b7
1 package org.dive4elements.river.importer.parsers;
2
3 import org.dive4elements.artifacts.common.utils.FileTools;
4
5 import org.dive4elements.river.importer.XY;
6
7 import org.dive4elements.river.importer.parsers.tim.Coordinate;
8
9 import org.dive4elements.river.utils.DateGuesser;
10 import org.dive4elements.river.utils.EpsilonComparator;
11
12 import java.io.File;
13 import java.io.IOException;
14
15 import java.util.ArrayList;
16 import java.util.Calendar;
17 import java.util.Date;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.TreeMap;
21
22 import org.apache.log4j.Logger;
23
24
25 /**
26 * To create cross-sections, generate: Map<double,list<xy>> from files
27 * in w80 format.
28 */
29 public class W80Parser extends LineParser implements CrossSectionParser
30 {
31 /** Private logger. */
32 private static Logger logger = Logger.getLogger(W80Parser.class);
33
34
35 /** The current line to which add points. */
36 private List<XY> currentLine;
37
38
39 /** Data collected so far, last element will be currentLine. */
40 protected Map<Double, List<XY>> data;
41
42
43 /** Anchor to project to. */
44 private static class Anchor extends Coordinate {
45
46 private static final double EPSILON = 1e-5;
47
48 private double station;
49
50 public Anchor(double x, double y, double z, double station) {
51 super(x, y, z);
52 this.station = station;
53 }
54
55 public boolean sameStation(double station) {
56 return Math.abs(this.station - station) < EPSILON;
57 }
58 }
59
60
61 /** Reference point for simple projection. */
62 private Anchor anchor;
63
64
65 /**
66 * Reference point for distance calculations, introduced to
67 * deal with bends in the lines.
68 * Array has two entrys: first is GK-Right, second GK-High.
69 */
70 private double[] lastPointGK;
71
72
73 /** Measurement date of anchor as listed in w80 file. */
74 private Date anchorDate;
75
76
77 private double distanceToLastPoint(double gkr, double gkh) {
78 double dx = gkr - lastPointGK[0];
79 double dy = gkh - lastPointGK[1];
80 double d = dx*dx + dy*dy;
81
82 return Math.sqrt(d);
83 }
84
85
86 /** Trivial constructor. */
87 public W80Parser() {
88 data = new TreeMap<Double, List<XY>>(EpsilonComparator.CMP);
89 }
90
91
92 /** Get the description of the cross section parsed. */
93 @Override
94 public String getDescription() {
95 return FileTools.removeExtension(getFileName());
96 }
97
98
99 /** Get the year of this cross sections measurement. */
100 @Override
101 public Integer getYear() {
102 if (anchorDate == null) {
103 return null;
104 }
105 Calendar dateCalendar = Calendar.getInstance();
106 dateCalendar.setTime(anchorDate);
107 return dateCalendar.get(Calendar.YEAR);
108 }
109
110
111 /**
112 * Return the data parsed.
113 * @return map of stations (km) to list of points.
114 */
115 @Override
116 public Map<Double, List<XY>> getData() {
117 return data;
118 }
119
120
121 public void parseW80s(File root, final Callback callback) {
122
123 FileTools.walkTree(root, new FileTools.FileVisitor() {
124 @Override
125 public boolean visit(File file) {
126 if (file.isFile() && file.canRead()
127 && file.getName().toLowerCase().endsWith(".w80")
128 && (callback == null || callback.accept(file))) {
129 reset();
130 try {
131 parse(file);
132 logger.info("parsing done");
133 if (callback != null) {
134 callback.parsed(W80Parser.this);
135 }
136 }
137 catch (IOException ioe) {
138 logger.error("IOException while parsing file");
139 return false;
140 }
141 }
142 return true;
143 }
144 });
145 }
146
147
148 /** Called before consuming first line of file. */
149 public void reset() {
150 data.clear();
151 currentLine = new ArrayList<XY>();
152 anchor = null;
153 anchorDate = null;
154 lastPointGK = new double[] {0d,0d};
155 }
156
157
158 /**
159 * Get the Index of the last cross-section lines point.
160 * @return last points index, -1 if not available.
161 */
162 private int getLastPointIdx() {
163 if (currentLine == null || currentLine.isEmpty()) {
164 return -1;
165 }
166 XY lastPoint = this.currentLine.get(currentLine.size()-1);
167 return lastPoint.getIndex();
168 }
169
170
171 private double getLastPointX() {
172 if (currentLine == null || currentLine.isEmpty()) {
173 return 0d;
174 }
175 XY lastPoint = this.currentLine.get(currentLine.size()-1);
176 return lastPoint.getX();
177 }
178
179
180 /**
181 * Add a Point (YZ,Index) to the current cross section line.
182 * @param y The y coordinate of new point.
183 * @param z The z coordinate of new point.
184 * @param idx Ignored, the parameter of new point.
185 * @return true if point could been added, false otherwise (e.g. not
186 * parsable y or z values.
187 */
188 private boolean addPoint(double gkr, double gkh, double height, String idx) {
189 // Calculate distance between this and lst point (add distances).
190 double d = distanceToLastPoint(gkr, gkh);
191 double totalX = getLastPointX() + d;
192
193 // We ignore idx, and increment instead.
194 int index;
195 int lastPointIdx = getLastPointIdx();
196 if (lastPointIdx <= 0) {
197 index = 1;
198 } else {
199 index = lastPointIdx + 1;
200 }
201
202 this.lastPointGK[0] = gkr;
203 this.lastPointGK[1] = gkh;
204 currentLine.add(new XY(totalX, height/1000d, index));
205 return true;
206 }
207
208
209 /**
210 * Called for each line. Try to extract info from a w80 line.
211 */
212 @Override
213 protected void handleLine(int lineNum, String line) {
214 // The 'shore' field shows which side of the river the shore is measured.
215 // Therefore, the points have to be added in the correct order (also
216 // because later distances are calculated which cannot be
217 // negative.
218 String pointId = line.substring(0,20);
219 String station = line.substring(9,15);
220 String shore = line.substring(15,16);
221 // TODO: There is 'station' and a 'shore'-code behind.
222 // 1 = left, 2 = right. none = middle
223 String pointIndex = line.substring(16,21);
224 // For GK, first seven digits are of interest.
225 String gkRight = line.substring(20,30);
226 String gkHigh = line.substring(30,40);
227 String date = line.substring(40,46);
228 /* Fields not (yet?) of interest for FLYS
229 String locType = line.substring(46,47);
230 */
231 String height = line.substring(47,54);
232 String dateH = line.substring(54,60);
233 /* Fields not (yet?) of interest for FLYS
234 String typeH = line.substring(60,61);
235 String kindH = line.substring(61,64);
236 */
237 String dateDec = line.substring(64,70);
238 /* Fields not (yet?) of interest for FLYS
239 String note = line.substring(70,78);
240 String actual = line.substring(78);
241 */
242
243 double stationKm = Double.parseDouble(station) / 1000d;
244 double gkRightKm = Double.parseDouble(gkRight.substring(0,7));
245 double gkHighKm = Double.parseDouble(gkHigh.substring(0,7));
246 double heightM = Double.parseDouble(height);
247
248 // New (or first) line.
249 if (anchor == null || !anchor.sameStation(stationKm)) {
250 anchor = new Anchor(gkRightKm, gkHighKm, heightM, stationKm);
251 lastPointGK[0] = gkRightKm;
252 lastPointGK[1] = gkHighKm;
253 currentLine = new ArrayList<XY>();
254 data.put(stationKm, currentLine);
255 currentLine.add(new XY(0d, heightM, 0));
256 try {
257 anchorDate = DateGuesser.guessDate(date);
258 }
259 catch (IllegalArgumentException iae) {
260 logger.warn("W80: Invalid date '" + date + "'.");
261 }
262 }
263 else {
264 addPoint(gkRightKm, gkHighKm, heightM, pointIndex);
265 }
266 }
267
268
269 /** Called when file is fully consumed. */
270 @Override
271 protected void finish() {
272 logger.info("Parsed " + data.size() + " lines");
273 }
274
275
276 /** Parses files given as arguments. */
277 public static void main(String [] args) {
278
279 W80Parser parser = new W80Parser();
280
281 logger.warn("Start parsing files.");
282 for (String arg: args) {
283 logger.warn("Parsing a file.");
284 parser.parseW80s(new File(arg), null);
285 }
286 logger.error("Finished parsing files.");
287 }
288 }
289 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org