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 011public class ImmutableGpxTrackSegment implements GpxTrackSegment { 012 013 private final List<WayPoint> wayPoints; 014 private final Bounds bounds; 015 private final double length; 016 017 /** 018 * Constructs a new {@code ImmutableGpxTrackSegment}. 019 * @param wayPoints list of waypoints 020 */ 021 public ImmutableGpxTrackSegment(Collection<WayPoint> wayPoints) { 022 this.wayPoints = Collections.unmodifiableList(new ArrayList<>(wayPoints)); 023 this.bounds = calculateBounds(); 024 this.length = calculateLength(); 025 } 026 027 private Bounds calculateBounds() { 028 Bounds result = null; 029 for (WayPoint wpt: wayPoints) { 030 if (result == null) { 031 result = new Bounds(wpt.getCoor()); 032 } else { 033 result.extend(wpt.getCoor()); 034 } 035 } 036 return result; 037 } 038 039 private double calculateLength() { 040 double result = 0.0; // in meters 041 WayPoint last = null; 042 for (WayPoint tpt : wayPoints) { 043 if (last != null) { 044 Double d = last.getCoor().greatCircleDistance(tpt.getCoor()); 045 if (!d.isNaN() && !d.isInfinite()) { 046 result += d; 047 } 048 } 049 last = tpt; 050 } 051 return result; 052 } 053 054 @Override 055 public Bounds getBounds() { 056 if (bounds == null) 057 return null; 058 else 059 return new Bounds(bounds); 060 } 061 062 @Override 063 public Collection<WayPoint> getWayPoints() { 064 return 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}