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}