Package net.sourceforge.gpstools

Source Code of net.sourceforge.gpstools.GoogleMapMaker$GMapCommandLine

package net.sourceforge.gpstools;

/* gpsdings
* Copyright (C) 2006 Moritz Ringler
* $Id: GoogleMapMaker.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.PrintStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import net.sourceforge.gpstools.gpx.Trkpt;
import net.sourceforge.gpstools.gpx.Wpt;
import net.sourceforge.gpstools.utils.GpsFormat;
import net.sourceforge.gpstools.utils.GpsMath;
import net.sourceforge.gpstools.utils.TemplateEvent;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.MissingOptionException;
import org.apache.commons.cli.Options;

public class GoogleMapMaker extends AbstractMapMaker {
    private boolean encodePolylines = false;

    public GoogleMapMaker() {
        super();
    }

    /** @deprecated use {@link #setGMapApiKey} instead */
    @Deprecated
    public void setApiKey(String gMapApiKey) {
        setGMapApiKey(gMapApiKey);
    }

    public void setEncodePolylines(boolean b) {
        encodePolylines = b;
    }

    @Override
    protected void printHTML(OutputStream out) throws IOException {
        message("Writing HTML");
        processTemplate(
                "/net/sourceforge/gpstools/res/GoogleMap.html.template", out);
    }

    @Override
    protected void printJS(OutputStream out) throws IOException {
        message("Writing Google Maps Javascript");
        Rectangle2D bounds = getBounds();
        if (bounds == null) {
            message("no trkpts or wpts");
            return;
        }
        processTemplate("/net/sourceforge/gpstools/res/GoogleMap.js.template",
                out);
    }

    private void wptsToGMarkers(Appendable mapjs) throws IOException {
        GpsFormat format = GpsFormat.getInstance();
        for (Wpt wpt : getGpx().getWpt()) {
            String desc = wpt.getDesc();
            desc = (desc == null) ? "" : desc.trim();
            String name = wpt.getName();
            name = (name == null) ? "Wpt" : name.trim();
            int linkstart = desc.indexOf("http://");
            if (linkstart >= 0) {
                String link = desc.substring(linkstart);
                link = link.replaceFirst("\\s.*", "");
                mapjs.append("map.addOverlay(createUrlMarker(new GLatLng(");
                mapjs.append(format.asLatLon(wpt.getLat(), wpt.getLon()));
                mapjs.append("), {clickable: true, title: \"");
                mapjs.append(name).append("\"}, \"").append(link)
                        .append("\"));");
            } else {
                mapjs.append("map.addOverlay(createMarker(new GLatLng(");
                mapjs.append(format.asLatLon(wpt.getLat(), wpt.getLon()));
                mapjs.append("), {clickable: false, title: \"");
                mapjs.append(name).append("\"}));\n");
            }
        }
    }

    @Override
    protected CharSequence draw(Trkpt[] pts, String color, String name) {
        StringBuilder builder = new StringBuilder();
        try {
            if (encodePolylines) {
                trksegToEncodedGPolyline(pts, color, builder);
            } else {
                trksegToUnencodedGPolyline(pts, color, builder);
            }
        } catch (IOException ex) {
            throw new Error(ex);
            // won't happen. StringBuilder throws no IOExceptions
        }
        return builder;
    }

    private static void trksegToUnencodedGPolyline(Trkpt[] pts, String color,
            Appendable mapjs) throws IOException {
        GpsFormat format = GpsFormat.getInstance();
        mapjs.append("points = [];\n");
        for (Trkpt pt : pts) {
            mapjs.append("points.push(new GLatLng(");
            mapjs.append(format.asLatLon(pt.getLat(), pt.getLon()));
            mapjs.append("));\n");
        }
        mapjs.append("map.addOverlay(new GPolyline(points, \"");
        mapjs.append(color).append("\", 2));\n");
    }

    private static void trksegToEncodedGPolyline(Trkpt[] pts, String color,
            Appendable mapjs) throws IOException {
        GpsFormat format = GpsFormat.getInstance();
        final int len = pts.length;
        int[] ilevels = new int[len];
        mapjs.append("//new segment\n");

        /*
         * we encode at most 100 points simultaneously to avoid big rounding
         * errors and overlong strings
         */
        for (int start = 0, stop = 100; stop != len; start = stop - 1) {
            mapjs.append("map.addOverlay(GPolyline.fromEncoded({\n");
            mapjs.append("  color: \"").append(color).append("\",\n");
            mapjs.append("  weight: 2,\n");
            mapjs.append("  opacity: 0.5,\n");

            /* encode first point */
            mapjs.append("  points: \"");
            Trkpt previous;
            Trkpt current = pts[start];
            format.asGPolylineCoordinate(current.getLat(), null, mapjs);
            format.asGPolylineCoordinate(current.getLon(), null, mapjs);

            stop = start + 100;
            if (len <= stop) {
                stop = len;
            }

            /* encode other points */
            for (int i = start + 1; i < stop; i++) {
                previous = current;
                current = pts[i];
                format.asGPolylineCoordinate(current.getLat(),
                        previous.getLat(), mapjs);
                format.asGPolylineCoordinate(current.getLon(),
                        previous.getLon(), mapjs);
            }

            mapjs.append("\",\n");

            /* calculate and encode levels */
            mapjs.append("  levels: \"");
            calculateLevels(pts, start, stop, ilevels);

            for (int i = start; i < stop; i++) {
                format.gEncodeUnsignedInt(ilevels[i], mapjs);
            }

            mapjs.append("\",\n");
            mapjs.append("  zoomFactor: 2,\n");
            mapjs.append("  numLevels: 18\n");
            mapjs.append("}));\n");

            start = stop - 1;
        }
    }

    /*
     * Java port of Javascript code written by Mark McClure in September 2006.
     * http
     * ://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/encodePolyline.js
     */
    private static int NUM_LEVELS = 18;
    private static int SMALL0 = 500;
    private static int UNSET = -1;

    private static int[] calculateLevels(Trkpt[] points, int start, int stop,
            int[] levels) {
        int i, j;
        Arrays.fill(levels, start, stop, UNSET);

        // Set the endpoints to show at all zoom levels
        levels[start] = NUM_LEVELS - 1;
        levels[stop - 1] = NUM_LEVELS - 1;

        // Starting at the largest possible level, we step down through
        // the levels labelling points which need to appear at
        // lower resolutions.
        for (int level = NUM_LEVELS - 1; level >= 0; level--) {
            // Set "small" for the current level.
            // More generally, we might use
            // small = small0*Math.pow(2.0, -18*(NUM_LEVELS-level)/NUM_LEVELS);
            double small = SMALL0 * Math.pow(2.0, level - 18);

            // Figure out which points need to occur at this level,
            // the main criteria being that we've stepped a certain
            // distance (called "small") from the previous set point.
            i = j = 1;
            while (i < stop - 1) {
                double dist = GpsMath.kmDistance(points[i].getLat(),
                        points[i].getLon(), points[j].getLat(),
                        points[j].getLon());
                if (dist >= small && levels[i] == UNSET) {
                    levels[i] = level;
                    j = i;
                }
                if (levels[i] != UNSET) {
                    j = i;
                }
                i++;
            }
        }
        // Set any unset points to level 0.
        for (i = start; i < stop; i++) {
            if (levels[i] == UNSET) {
                levels[i] = 0;
            }
        }
        return levels;
    }

    private void zoomMap(Appendable mapjs) throws IOException {
        Rectangle2D.Double bd = getBounds();
        float padding = getPadding();
        GpsFormat format = GpsFormat.getInstance();
        mapjs.append("map.setZoom(\n");
        mapjs.append("    map.getBoundsZoomLevel(\n");
        mapjs.append("        new GLatLngBounds(\n");
        mapjs.append("            new GLatLng(");
        mapjs.append(
                format.asLatLon(bd.x - bd.width * padding, bd.y - bd.height
                        * padding)).append("),\n");
        mapjs.append("            new GLatLng(");
        mapjs.append(format.asLatLon(bd.x + bd.width * (1.0f + padding), bd.y
                + bd.height * (1.0f + padding)));
        mapjs.append(")\n");
        mapjs.append("        )\n");
        mapjs.append("    )\n");
        mapjs.append(");\n");
    }

    private void centerMap(Appendable mapjs) throws IOException {
        Rectangle2D.Double bd = getBounds();
        mapjs.append("map.setCenter(new GLatLng(");
        mapjs.append(GpsFormat.getInstance().asLatLon(bd.x + 0.5 * bd.width,
                bd.y + 0.5 * bd.height));
        mapjs.append("), 13);\n");
    }

    private void loadPhotos(Appendable html) throws IOException {
        if (getPhotoJavaScript() != null) {
            html.append("addPhotoMarkers(myMap, '");
            html.append(getPhotoURLPrefix());
            html.append("', 200);");
        }
    }

    @Override
    protected void includePhotoJS(Appendable html) throws IOException {
        if (photojs != null) {
            includeGPSDingsJS(html);
        }
        super.includePhotoJS(html);
    }

    @Override
    public void handleTemplateEvent(TemplateEvent e) throws IOException {
        Appendable app = e.getDest();
        String var = e.getVariable();
        if ("cssURL".equals(var)) {
            app.append(url.get(Output.CSS));
        } else if ("jsURL".equals(var)) {
            app.append(getURL(Output.MapJS));
        } else if ("includeGPSDingsJS".equals(var)) {
            includeGPSDingsJS(app);
        } else if ("includePhotoJS".equals(var)) {
            includePhotoJS(app);
        } else if ("loadPhotos".equals(var)) {
            loadPhotos(app);
        } else if ("title".equals(var)) {
            app.append(getHTMLTitle());
        } else if ("gMapsApiKey".equals(var)) {
            app.append(getGMapApiKey());
        } else if ("boundsCenter".equals(var)) {
            centerMap(app);
        } else if ("trk".equals(var)) {
            if (getIncludeTrks()) {
                drawTracks(app);
            }
        } else if ("wpt".equals(var)) {
            if (getIncludeWpts()) {
                wptsToGMarkers(app);
            }
        } else if ("boundsZoom".equals(var)) {
            zoomMap(app);
        } else {
            message("Skipping unknown variable " + var);
        }
    }

    public static void main(String[] argv) {
        (new GMapCommandLine(argv)).execute();
    }

    private static class GMapCommandLine extends MapCommandLine<GoogleMapMaker> {
        public final static String OPT_ENCODE = "encode-polylines";

        public GMapCommandLine(String[] argv) {
            super(new GoogleMapMaker(), argv);
        }

        @Override
        public void printHelp(PrintStream out) {
            try {
                super.printHelp(out);
                cat("googlemap.txt");
            } catch (Exception ex) {
                throw new Error(ex);
            }
        }

        @Override
        protected Options createOptions() {
            Options options = super.createOptions();
            options.addOption(makeOption(OPT_TITLE, String.class, 1, "title"));
            options.addOption(makeOption(OPT_ENCODE, Boolean.class, 0, null));
            return options;
        }

        @Override
        protected CommandLine processOptions(Options options)
                throws org.apache.commons.cli.ParseException, IOException,
                java.text.ParseException {
            CommandLine cl = super.processOptions(options);
            char c;

            /* apiKey option */
            opt = OPT_API_KEY;
            c = opt.charAt(0);
            if (cl.hasOption(c)) {
                app.setApiKey(cl.getOptionValue(c));
            }

            /* output options */
            opt = OPT_HTML;
            c = opt.charAt(0);
            if (cl.hasOption(c)) {
                if (!cl.hasOption(OPT_API_KEY.charAt(0))) {
                    throw new MissingOptionException(
                            "HTML output requires that a google maps api key "
                                    + "is specified with the -"
                                    + OPT_API_KEY.charAt(0) + ",--"
                                    + OPT_API_KEY + " option.");
                }
                app.enableOutput(Output.HTML, cl.getOptionValue(c));
            }

            if (cl.hasOption('c') || cl.hasOption('C')) {
                System.err
                        .println("WARNING: The css and CSS options no longer have any effect");
            }

            /* encode option */
            opt = OPT_ENCODE;
            c = opt.charAt(0);
            app.setEncodePolylines(cl.hasOption(c));

            return cl;
        }
    }
}
TOP

Related Classes of net.sourceforge.gpstools.GoogleMapMaker$GMapCommandLine

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.