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. 013 * @since 15496 014 */ 015public class GpxTrackSegment extends WithAttributes implements IGpxTrackSegment { 016 017 private final List<WayPoint> wayPoints; 018 private final Bounds bounds; 019 private final double length; 020 021 /** 022 * Constructs a new {@code GpxTrackSegment}. 023 * @param wayPoints list of waypoints 024 */ 025 public GpxTrackSegment(Collection<WayPoint> wayPoints) { 026 this.wayPoints = Collections.unmodifiableList(new ArrayList<>(wayPoints)); 027 this.bounds = calculateBounds(); 028 this.length = calculateLength(); 029 } 030 031 private Bounds calculateBounds() { 032 Bounds result = null; 033 for (WayPoint wpt: wayPoints) { 034 if (result == null) { 035 result = new Bounds(wpt.getCoor()); 036 } else { 037 result.extend(wpt.getCoor()); 038 } 039 } 040 return result; 041 } 042 043 private double calculateLength() { 044 double result = 0.0; // in meters 045 WayPoint last = null; 046 for (WayPoint tpt : wayPoints) { 047 if (last != null) { 048 Double d = last.getCoor().greatCircleDistance(tpt.getCoor()); 049 if (!d.isNaN() && !d.isInfinite()) { 050 result += d; 051 } 052 } 053 last = tpt; 054 } 055 return result; 056 } 057 058 @Override 059 public Bounds getBounds() { 060 return bounds == null ? null : new Bounds(bounds); 061 } 062 063 @Override 064 public Collection<WayPoint> getWayPoints() { 065 return Collections.unmodifiableList(wayPoints); 066 } 067 068 @Override 069 public double length() { 070 return length; 071 } 072 073 @Override 074 public int getUpdateCount() { 075 return 0; 076 } 077 078 @Override 079 public int hashCode() { 080 final int prime = 31; 081 int result = prime + super.hashCode(); 082 result = prime * result + ((wayPoints == null) ? 0 : wayPoints.hashCode()); 083 return result; 084 } 085 086 @Override 087 public boolean equals(Object obj) { 088 if (this == obj) 089 return true; 090 if (obj == null) 091 return false; 092 if (!super.equals(obj)) 093 return false; 094 if (getClass() != obj.getClass()) 095 return false; 096 GpxTrackSegment other = (GpxTrackSegment) obj; 097 if (wayPoints == null) { 098 if (other.wayPoints != null) 099 return false; 100 } else if (!wayPoints.equals(other.wayPoints)) 101 return false; 102 return true; 103 } 104}