Package net.sourceforge.gpstools

Source Code of net.sourceforge.gpstools.Ovl2gpx$GPXWriter

package net.sourceforge.gpstools;

/* gpsdings
* Copyright (C) 2006 Moritz Ringler
* $Id: Ovl2gpx.java 441 2010-12-13 20:04:20Z ringler $
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  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.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.gpstools.ovl.AbstractOVLSymbol;
import net.sourceforge.gpstools.ovl.Coordinate;
import net.sourceforge.gpstools.ovl.OVL;
import net.sourceforge.gpstools.ovl.OVLSymbol;
import net.sourceforge.gpstools.ovl.OVLTrackSegment;
import net.sourceforge.gpstools.ovl.OVLVisitor;
import net.sourceforge.gpstools.ovl.OVLWaypoint;
import de.mospace.xml.SaxXMLWriter;
import org.xml.sax.SAXException;

public class Ovl2gpx {
    private final static Pattern SYMBOL = Pattern
            .compile("(?i)\\s*\\[Symbol (\\d+)]");
    private final static int SYMBOL_INDEX = 1;

    private final static Pattern COORDS = Pattern.compile("(x|y)koord(\\d*)");
    private final static Pattern COORDS_VALUE = Pattern
            .compile("[+-]?\\d*((\\d\\.?)|(\\.\\d))\\d*");

    private final static Pattern KEYVALUE = Pattern
            .compile("(.*?)\\s*=\\s*(.*)");
    private final static int KEYVALUE_KEY = 1;
    private final static int KEYVALUE_VALUE = 2;

    private int linesRead = 0;
    private String unparsed;
    private OVL parseresult = new OVL();
    private boolean eof = false;

    public void transform(InputStream in, OutputStream out) throws IOException,
            OVLVisitor.OVLVisitorException, ParseException {
        BufferedReader read = new BufferedReader(new InputStreamReader(in));

        /* read */
        linesRead = 0;
        OVLSymbol sym = readOVLSymbol(read);
        while (!eof) {
            if (sym != null) {
                // add symbol to parse tree
                sym.apply(parseresult);
            }
            // read next symbol
            sym = readOVLSymbol(read);
        }

        /* write */
        GPXWriter gxw = new GPXWriter(out);
        gxw.write(parseresult);
        gxw = null;
    }

    /**
     * Parses a coordinate in decimal degrees.
     *
     * @return the double value of the coordinate or Double.NaN if value does
     *         not have the required format or is out of range
     **/
    private static double toCoords(String value, char axis) {
        double d = Double.NaN;
        double maxdeg = (axis == 'x') ? 180 : 90;
        String val = value.trim();
        if (COORDS_VALUE.matcher(val).matches()) {
            try {
                d = Double.parseDouble(value);
            } catch (NumberFormatException cannothappen) {
                throw new RuntimeException(cannothappen);
            }
            if (Math.abs(d) > maxdeg) {
                d = Double.NaN;
            }
        }
        return d;
    }

    private OVLSymbol readOVLSymbol(BufferedReader read) throws IOException,
            ParseException {
        // find a new symbol;
        Matcher mSymbol = SYMBOL.matcher("");
        int symbol = -1;
        int symbolStart = -1;
        while (symbol == -1) {
            if (unparsed == null) {
                unparsed = read.readLine();
                linesRead++;
                if (unparsed == null) {
                    eof = true;
                    return null;
                }
            }
            mSymbol.reset(unparsed);
            if (mSymbol.matches()) {
                symbolStart = linesRead;
                try {
                    symbol = Integer.parseInt(mSymbol.group(SYMBOL_INDEX));
                } catch (NumberFormatException cannothappen) {
                    throw new RuntimeException(cannothappen);
                }
            }
            unparsed = null;
        }
        // we're at the start of a new symbol

        Map<String, Object> kv = new TreeMap<String, Object>();
        Matcher mKeyval = KEYVALUE.matcher("");
        Matcher mCoords = COORDS.matcher("");
        unparsed = read.readLine();
        eof = (unparsed == null);
        linesRead++;

        for (String key, value; !eof;) {
            mKeyval.reset(unparsed);
            if (!mKeyval.matches()) {
                break;
            }
            key = mKeyval.group(KEYVALUE_KEY).toLowerCase().trim();
            value = mKeyval.group(KEYVALUE_VALUE).toLowerCase().trim();
            if (mCoords.reset(key).matches()) {
                double d = toCoords(value, key.charAt(0));
                if (d == Double.NaN) {
                    throw new ParseException("Illegal coordinate value "
                            + value + " at line " + linesRead, linesRead);
                }
                kv.put(key, Double.valueOf(d));
            } else {
                kv.put(key, value);
            }
            unparsed = read.readLine();
            eof = (unparsed == null);
            linesRead++;
        }

        // we're at the end of a symbol;
        return AbstractOVLSymbol.getInstance(symbol, symbolStart, kv);
    }

    private static class GPXWriter implements OVLVisitor {
        private final SaxXMLWriter xw;
        private final NumberFormat cf;

        public GPXWriter(OutputStream out) throws OVLVisitorException {
            try {
                xw = new SaxXMLWriter(out, "UTF-8",
                        "http://www.topografix.com/GPX/1/1");
                final DecimalFormat dcf = new DecimalFormat("00.000000");
                final DecimalFormatSymbols sym = dcf.getDecimalFormatSymbols();
                sym.setDecimalSeparator('.');
                dcf.setDecimalFormatSymbols(sym);
                cf = dcf;
            } catch (UnsupportedEncodingException wonthappen) {
                throw new Error(wonthappen);
            } catch (SAXException ex) {
                throw new OVLVisitorException(ex);
            }
        }

        @Override
        public void visitWaypoint(OVLWaypoint wpt) throws OVLVisitorException {
            try {
                // <wpt>
                xw.attribute("lat", cf.format(wpt.coord.latitude()));
                xw.attribute("lon", cf.format(wpt.coord.longitude()));
                xw.startElement("wpt");
                // <name>
                xw.startElement("name");
                xw.text("Symbol " + wpt.id());
                xw.endElement("name");
                // <desc>
                xw.startElement("desc");
                xw.text("Symbol " + wpt.id());
                xw.endElement("desc");
                // </wpt>
                xw.endElement("wpt");
            } catch (SAXException ex) {
                throw new OVLVisitorException(ex);
            }
        }

        @Override
        public void visitTrackSegment(OVLTrackSegment trkseg)
                throws OVLVisitorException {
            try {
                // <trkseg>
                xw.startElement("trkseg");
                for (Coordinate pt : trkseg.getCoords()) {
                    // <trkpt />
                    xw.attribute("lat", cf.format(pt.latitude()));
                    xw.attribute("lon", cf.format(pt.longitude()));
                    xw.emptyElement("trkpt");
                }
                xw.endElement("trkseg");
            } catch (SAXException ex) {
                throw new OVLVisitorException(ex);
            }
        }

        public void write(OVL ovl) throws OVLVisitorException {
            try {
                // <gpx>
                final String XSI = "http://www.w3.org/2001/XMLSchema-instance";
                xw.declarePrefix("xsi", XSI);
                xw.attribute("creator", "net.sourceforge.gpstools.Ovl2gpx");
                xw.attribute("version", "1.1");
                xw.attribute(
                        "schemaLocation",
                        "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd",
                        XSI);
                xw.startElement("gpx");
                // <metadata>
                xw.startElement("metadata");
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                df.setTimeZone(TimeZone.getTimeZone("UTC"));
                // <time>
                xw.startElement("time");
                xw.text(df.format(new Date()));
                xw.endElement("time");
                // <bounds>
                Rectangle2D.Double bounds = ovl.getBounds();
                xw.attribute("minlat", String.valueOf(bounds.y));
                xw.attribute("maxlat", String.valueOf(bounds.y + bounds.height));
                xw.attribute("minlon", String.valueOf(bounds.x));
                xw.attribute("maxlon", String.valueOf(bounds.x + bounds.width));
                xw.emptyElement("bounds");
                // </metadata>
                xw.endElement("metadata");
                for (OVLWaypoint wpt : ovl.getWaypoints()) {
                    // <wpt>
                    wpt.apply(this);
                }
                for (String name : ovl.getTrackNames()) {
                    // <trk>
                    xw.startElement("trk");
                    xw.startElement("name");
                    xw.text("Track " + name);
                    xw.endElement("name");
                    for (OVLTrackSegment trkseg : ovl.getTrack(name)) {
                        trkseg.apply(this);
                    }
                    xw.endElement("trk");
                }
                // </gpx>
                xw.endElement("gpx");
                xw.close();
            } catch (SAXException ex) {
                throw new OVLVisitorException(ex);
            }
        }
    }

}
TOP

Related Classes of net.sourceforge.gpstools.Ovl2gpx$GPXWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.