001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.gpx; 003 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.Collections; 007import java.util.List; 008 009import org.openstreetmap.josm.data.Bounds; 010 011/** 012 * A gpx track segment consisting of multiple waypoints, that cannot be changed. 013 */ 014public class ImmutableGpxTrackSegment implements GpxTrackSegment { 015 016 private final List<WayPoint> wayPoints; 017 private final Bounds bounds; 018 private final double length; 019 020 /** 021 * Constructs a new {@code ImmutableGpxTrackSegment}. 022 * @param wayPoints list of waypoints 023 */ 024 public ImmutableGpxTrackSegment(Collection<WayPoint> wayPoints) { 025 this.wayPoints = Collections.unmodifiableList(new ArrayList<>(wayPoints)); 026 this.bounds = calculateBounds(); 027 this.length = calculateLength(); 028 } 029 030 private Bounds calculateBounds() { 031 Bounds result = null; 032 for (WayPoint wpt: wayPoints) { 033 if (result == null) { 034 result = new Bounds(wpt.getCoor()); 035 } else { 036 result.extend(wpt.getCoor()); 037 } 038 } 039 return result; 040 } 041 042 private double calculateLength() { 043 double result = 0.0; // in meters 044 WayPoint last = null; 045 for (WayPoint tpt : wayPoints) { 046 if (last != null) { 047 Double d = last.getCoor().greatCircleDistance(tpt.getCoor()); 048 if (!d.isNaN() && !d.isInfinite()) { 049 result += d; 050 } 051 } 052 last = tpt; 053 } 054 return result; 055 } 056 057 @Override 058 public Bounds getBounds() { 059 return bounds == null ? null : new Bounds(bounds); 060 } 061 062 @Override 063 public Collection<WayPoint> getWayPoints() { 064 return Collections.unmodifiableList(wayPoints); 065 } 066 067 @Override 068 public double length() { 069 return length; 070 } 071 072 @Override 073 public int getUpdateCount() { 074 return 0; 075 } 076 077 @Override 078 public int hashCode() { 079 return 31 + ((wayPoints == null) ? 0 : wayPoints.hashCode()); 080 } 081 082 @Override 083 public boolean equals(Object obj) { 084 if (this == obj) 085 return true; 086 if (obj == null) 087 return false; 088 if (getClass() != obj.getClass()) 089 return false; 090 ImmutableGpxTrackSegment other = (ImmutableGpxTrackSegment) obj; 091 if (wayPoints == null) { 092 if (other.wayPoints != null) 093 return false; 094 } else if (!wayPoints.equals(other.wayPoints)) 095 return false; 096 return true; 097 } 098}