comparison flys-backend/src/main/java/de/intevation/flys/importer/parsers/W80CSVParser.java @ 5808:c69ce591e3ea

Initial version of W80CSVParser (stripped W80Parser).
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Wed, 24 Apr 2013 12:03:54 +0200
parents
children
comparison
equal deleted inserted replaced
5807:b9ae676a9afe 5808:c69ce591e3ea
1 package de.intevation.flys.importer.parsers;
2
3 import de.intevation.artifacts.common.utils.FileTools;
4
5 import de.intevation.flys.importer.XY;
6
7 import de.intevation.flys.importer.parsers.tim.Coordinate;
8
9 import de.intevation.flys.utils.DateGuesser;
10 import de.intevation.flys.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/csv format.
28 */
29 public class W80CSVParser extends LineParser implements CrossSectionParser
30 {
31 /** Private logger. */
32 private static Logger logger = Logger.getLogger(W80CSVParser.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 W80CSVParser() {
88 data = new TreeMap<Double, List<XY>>(EpsilonComparator.CMP);
89 }
90
91
92 /**
93 * Get the description of the cross section parsed -
94 * directory name of current file.
95 */
96 @Override
97 public String getDescription() {
98 return getInputFile().getParentFile().getName();
99 }
100
101
102 /** Get the year of this cross sections measurement. */
103 @Override
104 public Integer getYear() {
105 if (anchorDate == null) {
106 return null;
107 }
108 Calendar dateCalendar = Calendar.getInstance();
109 dateCalendar.setTime(anchorDate);
110 return dateCalendar.get(Calendar.YEAR);
111 }
112
113
114 /**
115 * Return the data parsed.
116 * @return map of stations (km) to list of points.
117 */
118 @Override
119 public Map<Double, List<XY>> getData() {
120 return data;
121 }
122
123
124 /** Recursively descend root, ask the callback for every file
125 * found and parse it if callback acks. When done, notify callback. */
126 public void parseW80CSVs(File root, final Callback callback) {
127
128 FileTools.walkTree(root, new FileTools.FileVisitor() {
129 @Override
130 public boolean visit(File file) {
131 if (file.isFile() && file.canRead()
132 && file.getName().toLowerCase().endsWith(".csv")
133 && (callback == null || callback.accept(file))) {
134 reset();
135 try {
136 parse(file);
137 logger.info("parsing done");
138 if (callback != null) {
139 callback.parsed(W80CSVParser.this);
140 }
141 }
142 catch (IOException ioe) {
143 logger.error("IOException while parsing file");
144 return false;
145 }
146 }
147 return true;
148 }
149 });
150 }
151
152
153 /** Called before consuming first line of file. */
154 public void reset() {
155 data.clear();
156 currentLine = new ArrayList<XY>();
157 anchor = null;
158 anchorDate = null;
159 lastPointGK = new double[] {0d,0d};
160 }
161
162
163 /**
164 * Get the Index of the last cross-section lines point.
165 * @return last points index, -1 if not available.
166 */
167 private int getLastPointIdx() {
168 if (currentLine == null || currentLine.isEmpty()) {
169 return -1;
170 }
171 XY lastPoint = this.currentLine.get(currentLine.size()-1);
172 return lastPoint.getIndex();
173 }
174
175
176 private double getLastPointX() {
177 if (currentLine == null || currentLine.isEmpty()) {
178 return 0d;
179 }
180 XY lastPoint = this.currentLine.get(currentLine.size()-1);
181 return lastPoint.getX();
182 }
183
184
185 /**
186 * Add a Point (YZ,Index) to the current cross section line.
187 * @param y The y coordinate of new point.
188 * @param z The z coordinate of new point.
189 * @param idx Ignored, the parameter of new point.
190 * @return true if point could been added, false otherwise (e.g. not
191 * parsable y or z values.
192 */
193 private boolean addPoint(double gkr, double gkh, double height, String idx) {
194 // Calculate distance between this and lst point (add distances).
195 double d = distanceToLastPoint(gkr, gkh);
196 double totalX = getLastPointX() + d;
197
198 // We ignore idx, and increment instead.
199 int index;
200 int lastPointIdx = getLastPointIdx();
201 if (lastPointIdx <= 0) {
202 index = 1;
203 } else {
204 index = lastPointIdx + 1;
205 }
206
207 this.lastPointGK[0] = gkr;
208 this.lastPointGK[1] = gkh;
209 currentLine.add(new XY(totalX, height/1000d, index));
210 return true;
211 }
212
213 // As per documentation:
214 // BW;WPA;ST;UF;PN;LS;BL-LS;Y;X;Z;DL;LZK;SY;SX;SZ;BML;HS;BL-HS;H;DH;HZK;SH;WVA;BMH;BMP;DST;DB;LDS;LKZ;
215
216
217 /**
218 * Called for each line. Try to extract info from a w80 line.
219 * @param lineNum Number of line (starting with 1).
220 */
221 @Override
222 protected void handleLine(int lineNum, String line) {
223 // First two lines are 'comment'-like.
224 if (lineNum == 1 || lineNum == 2) {
225 return;
226 }
227 // The 'shore' field shows which side of the river the shore is measured.
228 // Therefore, the points have to be added in the correct order (also
229 // because later distances are calculated which cannot be
230 // negative.
231 String[] fields = line.split(";");
232 String station = fields[2];
233 String shore = fields[3];
234 // TODO: There is 'station' and a 'shore'-code behind.
235 // 1 = left, 2 = right. none = middle
236 String pointIndex = line.substring(16,21);
237 // For GK, first seven digits are of interest.
238 String gkRight = fields[7];
239 String gkHigh = fields[8];
240 String date = fields[10];
241 String height = fields[18];
242 String dateH = line.substring(54,60);
243 String dateDec = line.substring(64,70);
244
245 double stationKm = Double.parseDouble(station) / 1000d;
246 double gkRightKm = Double.parseDouble(gkRight.replace(",","."));//.substring(0,7));
247 double gkHighKm = Double.parseDouble(gkHigh.replace(",","."));//.substring(0,7));
248 double heightM = Double.parseDouble(height.replace(",","."));
249
250 // New (or first) line.
251 if (anchor == null || !anchor.sameStation(stationKm)) {
252 anchor = new Anchor(gkRightKm, gkHighKm, heightM, stationKm);
253 lastPointGK[0] = gkRightKm;
254 lastPointGK[1] = gkHighKm;
255 currentLine = new ArrayList<XY>();
256 data.put(stationKm, currentLine);
257 currentLine.add(new XY(0d, heightM, 0));
258 try {
259 anchorDate = DateGuesser.guessDate(date);
260 }
261 catch (IllegalArgumentException iae) {
262 logger.warn("W80CSV: Invalid date '" + date + "'.");
263 }
264 }
265 else {
266 addPoint(gkRightKm, gkHighKm, heightM, pointIndex);
267 }
268 }
269
270
271 /** Called when file is fully consumed. */
272 @Override
273 protected void finish() {
274 logger.info("Parsed " + data.size() + " lines");
275 }
276
277
278 /** Parses files given as arguments. */
279 public static void main(String [] args) {
280
281 W80CSVParser parser = new W80CSVParser();
282
283 logger.warn("Start parsing files.");
284 for (String arg: args) {
285 logger.warn("Parsing a file.");
286 parser.parseW80CSVs(new File(arg), null);
287 }
288 logger.error("Finished parsing files.");
289 }
290 }
291 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org