001 //License: GPLv2 or later
002 //Copyright 2007 by Raphael Mack and others
003
004 package org.openstreetmap.josm.data.gpx;
005
006 import java.awt.Color;
007 import java.util.ArrayList;
008 import java.util.Date;
009 import java.util.List;
010
011 import org.openstreetmap.josm.Main;
012 import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
013 import org.openstreetmap.josm.data.coor.EastNorth;
014 import org.openstreetmap.josm.data.coor.LatLon;
015 import org.openstreetmap.josm.data.projection.Projections;
016 import org.openstreetmap.josm.tools.PrimaryDateParser;
017 import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider;
018
019 public class WayPoint extends WithAttributes implements Comparable<WayPoint>, TemplateEngineDataProvider {
020
021 private static ThreadLocal<PrimaryDateParser> dateParser = new ThreadLocal<PrimaryDateParser>() {
022 @Override protected PrimaryDateParser initialValue() {
023 return new PrimaryDateParser();
024 }
025 };
026
027 public double time;
028 public Color customColoring;
029 public boolean drawLine;
030 public int dir;
031
032 public WayPoint(WayPoint p) {
033 attr.putAll(p.attr);
034 lat = p.lat;
035 lon = p.lon;
036 east = p.east;
037 north = p.north;
038 time = p.time;
039 customColoring = p.customColoring;
040 drawLine = p.drawLine;
041 dir = p.dir;
042 }
043
044 public WayPoint(LatLon ll) {
045 lat = ll.lat();
046 lon = ll.lon();
047 }
048
049 /*
050 * We "inline" lat/lon, rather than usinga LatLon internally => reduces memory overhead. Relevant
051 * because a lot of GPX waypoints are created when GPS tracks are downloaded from the OSM server.
052 */
053 private double lat = 0;
054 private double lon = 0;
055
056 /*
057 * internal cache of projected coordinates
058 */
059 private double east = Double.NaN;
060 private double north = Double.NaN;
061
062 /**
063 * Invalidate the internal cache of east/north coordinates.
064 */
065 public void invalidateEastNorthCache() {
066 this.east = Double.NaN;
067 this.north = Double.NaN;
068 }
069
070 public final LatLon getCoor() {
071 return new LatLon(lat,lon);
072 }
073
074 /**
075 * <p>Replies the projected east/north coordinates.</p>
076 *
077 * <p>Uses the {@link Main#getProjection() global projection} to project the lan/lon-coordinates.
078 * Internally caches the projected coordinates.</p>
079 *
080 * <p><strong>Caveat:</strong> doesn't listen to projection changes. Clients must
081 * {@link #reproject() trigger a reprojection} or {@link #invalidateEastNorthCache() invalidate the internal cache}.</p>
082 *
083 * @return the east north coordinates or {@code null}
084 * @see #invalidateEastNorthCache()
085 *
086 */
087 public final EastNorth getEastNorth() {
088 if (Double.isNaN(east) || Double.isNaN(north)) {
089 // projected coordinates haven't been calculated yet,
090 // so fill the cache of the projected waypoint coordinates
091 EastNorth en = Projections.project(new LatLon(lat, lon));
092 this.east = en.east();
093 this.north = en.north();
094 }
095 return new EastNorth(east, north);
096 }
097
098 @Override
099 public String toString() {
100 return "WayPoint (" + (attr.containsKey("name") ? attr.get("name") + ", " :"") + getCoor().toString() + ", " + attr + ")";
101 }
102
103 /**
104 * Convert the time stamp of the waypoint into seconds from the epoch
105 */
106 public void setTime() {
107 if(attr.containsKey("time")) {
108 try {
109 time = dateParser.get().parse(attr.get("time").toString()).getTime() / 1000.; /* ms => seconds */
110 } catch(Exception e) {
111 time = 0;
112 }
113 }
114 }
115
116 public int compareTo(WayPoint w) {
117 return Double.compare(time, w.time);
118 }
119
120 public Date getTime() {
121 return new Date((long) (time * 1000));
122 }
123
124 @Override
125 public Object getTemplateValue(String name, boolean special) {
126 if (!special)
127 return attr.get(name);
128 else
129 return null;
130 }
131
132 @Override
133 public boolean evaluateCondition(Match condition) {
134 throw new UnsupportedOperationException();
135 }
136
137 @Override
138 public List<String> getTemplateKeys() {
139 return new ArrayList<String>(attr.keySet());
140 }
141 }