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 }