Subversion Repositories mkgmap

Rev

Rev 2573 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * 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;
        }
       

}