/*
* Copyright (C) 2008 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: 10-Dec-2008
*/
package uk.me.parabola.mkgmap.osmstyle;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.mkgmap.general.LineAdder;
import uk.me.parabola.mkgmap.general.MapLine;
import uk.me.parabola.mkgmap.scan.SyntaxException;
import uk.me.parabola.mkgmap.scan.TokenScanner;
/**
* Reads the overlay file.
* There are not many line types available in the version of the .img
* format that we are using, but you can simulate more by clever use
* of TYP files and overlaying lines on top of each other.
*
* The format of the file is just a series of lines that start with
* the fake type and followed by a list of types that will actually
* be created.
*
* Eg.
* 0x123: 0x12, 0x14, 0x15
*
* If a rule results in the type 0x123 (which wouldn't normally show up)
* it is replaced by three lines with the type 0x12, 0x14, 0x15.
*
* @author Steve Ratcliffe
* @see <a href="TODO: find url">Example of the technique</a>
*
*/
public class OverlayReader {
private final Map<Integer, List<Integer>> overlays = new HashMap<Integer, List<Integer>>();
private final Reader reader;
private final String filename;
public OverlayReader(Reader r, String filename) {
reader = r;
this.filename = filename;
}
public void readOverlays() {
TokenScanner ts = new TokenScanner(filename, reader);
while (!ts.isEndOfFile()) {
String line = ts.readLine();
// Remove comments before parsing
int commentstart = line.indexOf("#");
if (commentstart != -1)
line = line.substring(0, commentstart);
String[] fields = line.split(":", 2);
if (fields.length == 2) {
try {
overlays.put(Integer.decode(fields[0]), readReplacements(ts, fields[1]));
} catch (NumberFormatException e) {
throw new SyntaxException(ts, "Expecting a number");
}
}
}
}
/**
* Read the line of replacements.
*/
private List<Integer> readReplacements(TokenScanner ts, String line) {
List<Integer> l = new ArrayList<Integer>();
String[] nums = line.split("[ ,]");
for (String n : nums) {
if (n == null || n.length() == 0)
continue;
try {
l.add(Integer.decode(n));
} catch (NumberFormatException e) {
throw new SyntaxException(ts, "List of numbers expected");
}
}
return l;
}
public void addLine(MapLine line, LineAdder adder) {
int origType = line.getType();
List<Integer> integerList = overlays.get(origType);
if (integerList != null) {
MapLine newline = line.copy();
newline.setType(integerList.get(0));
List<Coord> points = line.getPoints();
newline.setPoints(points);
adder.add(newline);
// Force all following types to be added as lines rather than roads.
for (ListIterator<Integer> t=integerList.listIterator(1); t.hasNext(); ) {
newline = new MapLine(line);
newline.setType(t.next());
newline.setPoints(new ArrayList<Coord>(points));
adder.add(newline);
}
} else {
adder.add(line);
}
}
public Map<Integer, List<Integer>> getOverlays() {
return overlays;
}
}