package net.sourceforge.gpstools;
/* gpsdings
* Copyright (C) 2006 Moritz Ringler
* $Id: OpenLayersMap.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.net.URL;
import net.sourceforge.gpstools.gpx.Trkpt;
import net.sourceforge.gpstools.gpx.Wpt;
import net.sourceforge.gpstools.utils.GpsFormat;
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 OpenLayersMap extends AbstractMapMaker {
public static enum BaseLayer {
GSat, GMap, GHyb, GTerrain, YMap, YSat, YHybrid, MSVEMap, MSVESat, MSVEHyb, OSMMapnik, OSMOsmarender, OSMCyclemap,
}
private BaseLayer[] baselayers = new BaseLayer[] { BaseLayer.OSMMapnik };
public OpenLayersMap() {
super();
}
public void setBaseLayers(BaseLayer[] bL) {
if (bL == null || bL.length == 0) {
throw new IllegalArgumentException(
"You must specify at least one base layer.");
}
baselayers = bL;
}
@Override
protected void printHTML(OutputStream out) throws IOException {
message("Writing HTML");
processTemplate(
"/net/sourceforge/gpstools/res/OpenLayers.html.template", out);
}
@Override
protected void printJS(OutputStream out) throws IOException {
message("Writing OpenStreetMap Javascript");
Rectangle2D.Double bounds = getBounds();
if (bounds == null) {
message("no trkpts or wpts");
return;
}
processTemplate("/net/sourceforge/gpstools/res/OpenLayers.js.template",
out);
}
private void drawWaypoints(Appendable mapjs) throws IOException {
GpsFormat format = GpsFormat.getInstance();
Wpt[] points = getGpx().getWpt();
if (points != null) {
for (Wpt wpt : points) {
String desc = wpt.getDesc();
String name = wpt.getName();
name = (name == null) ? "Wpt" : name.trim();
mapjs.append("gpxmap.addWpt({lon:");
mapjs.append(format.asLatLon(wpt.getLon()));
mapjs.append(",lat:").append(format.asLatLon(wpt.getLat()));
mapjs.append(",desc:'<div class=\"wpt-name\">")
.append(name.replace('\'', ' ')).append("</div>");
if (desc != null && desc.length() != 0
&& !desc.trim().equals(name)) {
mapjs.append("<div class=\"wpt-desc\">").append(
desc.replace('\'', ' ').trim());
}
mapjs.append("</div>'});\n");
}
}
}
private void setBounds(Appendable mapjs) throws IOException {
Rectangle2D.Double bd = getBounds();
float padding = getPadding();
GpsFormat format = GpsFormat.getInstance();
mapjs.append("W:").append(format.asLatLon(bd.y - bd.height * padding));
mapjs.append(",S:").append(format.asLatLon(bd.x - bd.width * padding));
mapjs.append(",E:").append(
format.asLatLon(bd.y + bd.height * (1.0f + padding)));
mapjs.append(",N:").append(
format.asLatLon(bd.x + bd.width * (1.0f + padding)));
}
private void loadPhotos(Appendable html) throws IOException {
if (getPhotoJavaScript() != null) {
html.append("addPhotoMarkers(gpxmap, '");
html.append(getPhotoURLPrefix());
html.append("', 200, null, 'openlayers');");
}
}
private void loadKML(Appendable js) throws IOException {
String kmlurl = url.get(Output.KML);
if (kmlurl != null) {
for (String kurl : kmlurl.split("\\s+", -1)) {
String title = kurl.replaceAll(".*/", "").replaceAll(".kml$",
"");
if (Character.isLowerCase(title.charAt(0))) {
title = Character.toUpperCase(title.charAt(0))
+ title.substring(1);
}
js.append("gpxmap.addKML('");
js.append(title.replace('\'', ' ')).append("', '");
js.append(kurl.replace('\'', ' ')).append("');");
}
}
}
@Override
protected CharSequence draw(Trkpt[] pts, String color, String name) {
return trksegToLine(pts, color, name);
}
private static CharSequence trksegToLine(Trkpt[] pts, String color,
String name) {
CharSequence result = "//less than two trkpts";
if (pts.length > 1) {
GpsFormat format = GpsFormat.getInstance();
StringBuilder sb = new StringBuilder("points = [\n");
for (Trkpt pt : pts) {
sb.append("{lon:");
sb.append(format.asLatLon(pt.getLon())).append(",lat:");
sb.append(format.asLatLon(pt.getLat())).append("},\n");
}
sb.deleteCharAt(sb.length() - 2);
sb.append("];\n");
sb.append("gpxmap.addTrkSeg({trkpt: points, color: '");
sb.append(color).append("'}");
if (name != null) {
sb.append(", '").append(name).append("'");
}
sb.append(");\n").append("delete points;\n");
result = sb;
}
return result;
}
@Override
public void handleTemplateEvent(TemplateEvent e) throws IOException {
Appendable app = e.getDest();
String var = e.getVariable();
if ("kml".equals(var)) {
loadKML(app);
} 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 ("wpt".equals(var)) {
if (getIncludeWpts()) {
drawWaypoints(app);
}
} else if ("trk".equals(var)) {
if (getIncludeTrks()) {
drawTracks(app);
}
} else if ("bounds".equals(var)) {
setBounds(app);
} else if ("baseLayers".equals(var)) {
StringBuilder sb = new StringBuilder();
for (BaseLayer layer : baselayers) {
sb.append(layer.name().toLowerCase());
sb.append(":true,");
}
sb.deleteCharAt(sb.length() - 1);
app.append(sb);
} else if ("baseLayerScript".equals(var)) {
loadBaseLayerAPIs(app);
} else {
message("Skipping unknown variable " + var);
}
}
private void loadBaseLayerAPIs(Appendable app) throws IOException {
boolean g = true;
boolean y = true;
boolean osm = true;
boolean ve = true;
for (BaseLayer layer : baselayers) {
final String name = layer.name();
if (name.startsWith("G")) {
if (g) {
g = false;
app.append("<script src='http://maps.google.com/maps?file=api&v=2&key=");
app.append(getGMapApiKey()).append("'></script>\n");
}
} else if (name.startsWith("OSM")) {
if (osm) {
osm = false;
app.append("<script src=\"http://gpstools.sourceforge.net/js/OpenStreetMap-0.6.js\" type=\"text/javascript\"></script>\n");
}
} else if (name.startsWith("MSVE")) {
if (ve) {
ve = false;
app.append("<script src='http://dev.virtualearth.net/mapcontrol/v3/mapcontrol.js'></script>\n");
}
} else if (name.startsWith("Y")) {
if (y) {
y = false;
app.append("<script src=\"http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=euzuro-openlayers\"></script>\n");
}
}
}
}
public static void main(String[] argv) {
(new OpenLayersCommandLine(argv)).execute();
}
private static class OpenLayersCommandLine extends
MapCommandLine<OpenLayersMap> {
public final static String OPT_KML_URL = "kml-URLs";
public final static String OPT_BASE_LAYERS = "base-layers";
public OpenLayersCommandLine(String[] argv) {
super(new OpenLayersMap(), argv);
}
@Override
public void printHelp(PrintStream out) {
try {
super.printHelp(out);
cat("openlayers.txt");
} catch (Exception ex) {
throw new Error(ex);
}
}
@Override
protected Options createOptions() {
Options options = super.createOptions();
options.addOption(makeOption(OPT_KML_URL, URL.class, 1, null));
options.addOption(makeOption(OPT_BASE_LAYERS, String.class, 1,
"base layer(s)"));
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;
opt = OPT_BASE_LAYERS;
c = opt.charAt(0);
if (cl.hasOption(c)) {
String[] baseLayers = cl.getOptionValue(c).split("\\s+", -1);
final int nL = baseLayers.length;
BaseLayer[] bL = new BaseLayer[nL];
for (int i = 0; i < nL; i++) {
try {
bL[i] = BaseLayer.valueOf(baseLayers[i]);
} catch (IllegalArgumentException ex) {
throw new IllegalArgumentException(
"\nOnly the following base layers are currently implemented:\n"
+ java.util.Arrays.asList(BaseLayer
.values()), ex);
}
if (baseLayers[i].charAt(0) == 'G'
&& !cl.hasOption(OPT_API_KEY.charAt(0))) {
throw new MissingOptionException(
"You must specify a google maps api key when you use a google maps base layer.");
}
}
app.setBaseLayers(bL);
}
opt = OPT_KML_URL;
c = opt.charAt(0);
if (cl.hasOption(c)) {
app.setURL(Output.KML, cl.getOptionValue(c));
}
return cl;
}
}
}