//License: GPLv2 or later. Copyright 2007 by Raphael Mack and others package org.openstreetmap.josm.data.gpx; import java.io.File; import java.util.Collection; import java.util.LinkedList; import java.util.Map; import org.openstreetmap.josm.data.Bounds; /** * Objects of this class represent a gpx file with tracks, waypoints and routes. * It uses GPX v1.1, see {@link <a href="http://www.topografix.com/GPX/1/1/">the spec</a>} * for details. * * @author Raphael Mack <ramack@raphael-mack.de> */ public class GpxData extends WithAttributes { public static final String META_PREFIX = "meta."; public static final String META_AUTHOR_NAME = META_PREFIX + "author.name"; public static final String META_AUTHOR_EMAIL = META_PREFIX + "author.email"; public static final String META_AUTHOR_LINK = META_PREFIX + "author.link"; public static final String META_COPYRIGHT_AUTHOR = META_PREFIX + "copyright.author"; public static final String META_COPYRIGHT_LICENSE = META_PREFIX + "copyright.license"; public static final String META_COPYRIGHT_YEAR = META_PREFIX + "copyright.year"; public static final String META_DESC = META_PREFIX + "desc"; public static final String META_KEYWORDS = META_PREFIX + "keywords"; public static final String META_LINKS = META_PREFIX + "links"; public static final String META_NAME = META_PREFIX + "name"; public static final String META_TIME = META_PREFIX + "time"; public File storageFile; public boolean fromServer; public final Collection<GpxTrack> tracks = new LinkedList<GpxTrack>(); public final Collection<GpxRoute> routes = new LinkedList<GpxRoute>(); public final Collection<WayPoint> waypoints = new LinkedList<WayPoint>(); @SuppressWarnings("unchecked") public void mergeFrom(GpxData other) { if (storageFile == null && other.storageFile != null) { storageFile = other.storageFile; } fromServer = fromServer && other.fromServer; for (Map.Entry<String, Object> ent : other.attr.entrySet()) { // TODO: Detect conflicts. String k = ent.getKey(); if (k.equals(META_LINKS) && attr.containsKey(META_LINKS)) { ((Collection<GpxLink>) attr.get(META_LINKS)).addAll( (Collection<GpxLink>) ent.getValue()); } else { attr.put(k, ent.getValue()); } } tracks.addAll(other.tracks); routes.addAll(other.routes); waypoints.addAll(other.waypoints); } public boolean hasTrackPoints() { for (GpxTrack trk : tracks) { for (GpxTrackSegment trkseg : trk.getSegments()) { if (!trkseg.getWayPoints().isEmpty()) return true; } } return false; } public boolean hasRoutePoints() { for (GpxRoute rte : routes) { if (!rte.routePoints.isEmpty()) return true; } return false; } public boolean isEmpty() { return !hasRoutePoints() && !hasTrackPoints() && waypoints.isEmpty(); } // FIXME might perhaps use visitor pattern? public Bounds recalculateBounds() { Bounds bounds = null; for (WayPoint wpt : waypoints) { if (bounds == null) { bounds = new Bounds(wpt.getCoor()); } else { bounds.extend(wpt.getCoor()); } } for (GpxRoute rte : routes) { for (WayPoint wpt : rte.routePoints) { if (bounds == null) { bounds = new Bounds(wpt.getCoor()); } else { bounds.extend(wpt.getCoor()); } } } for (GpxTrack trk : tracks) { Bounds trkBounds = trk.getBounds(); if (trkBounds != null) { if (bounds == null) { bounds = new Bounds(trkBounds); } else { bounds.extend(trkBounds); } } } return bounds; } /** * calculates the sum of the lengths of all track segments */ public double length(){ double result = 0.0; // in meters for (GpxTrack trk : tracks) { result += trk.length(); } return result; } }