001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.awt.geom.Line2D;
005
006/**
007 * A segment consisting of 2 consecutive nodes out of a way.
008 */
009public final class WaySegment implements Comparable<WaySegment> {
010
011    /**
012     * The way.
013     */
014    public Way way;
015
016    /**
017     * The index of one of the 2 nodes in the way.  The other node has the
018     * index <code>lowerIndex + 1</code>.
019     */
020    public int lowerIndex;
021
022    /**
023     * Constructs a new {@code WaySegment}.
024     * @param w The way
025     * @param i The node lower index
026     */
027    public WaySegment(Way w, int i) {
028        way = w;
029        lowerIndex = i;
030    }
031
032    /**
033     * Returns the first node of the way segment.
034     * @return the first node
035     */
036    public Node getFirstNode() {
037        return way.getNode(lowerIndex);
038    }
039
040    /**
041     * Returns the second (last) node of the way segment.
042     * @return the second node
043     */
044    public Node getSecondNode(){
045        return way.getNode(lowerIndex + 1);
046    }
047
048    /**
049     * Returns this way segment as complete way.
050     * @return the way segment as {@code Way}
051     */
052    public Way toWay() {
053        Way w = new Way();
054        w.addNode(getFirstNode());
055        w.addNode(getSecondNode());
056        return w;
057    }
058
059    @Override
060    public boolean equals(Object o) {
061        return o instanceof WaySegment
062            && ((WaySegment) o).way == way
063            && ((WaySegment) o).lowerIndex == lowerIndex;
064    }
065
066    @Override
067    public int hashCode() {
068        return way.hashCode() ^ lowerIndex;
069    }
070
071    @Override
072    public int compareTo(WaySegment o) {
073        return equals(o) ? 0 : toWay().compareTo(o.toWay());
074    }
075
076    /**
077     * Checks whether this segment crosses other segment
078     *
079     * @param s2 The other segment
080     * @return true if both segments crosses
081     */
082    public boolean intersects(WaySegment s2) {
083        if (getFirstNode().equals(s2.getFirstNode()) || getSecondNode().equals(s2.getSecondNode()) ||
084                getFirstNode().equals(s2.getSecondNode()) || getSecondNode().equals(s2.getFirstNode()))
085            return false;
086
087        return Line2D.linesIntersect(
088                getFirstNode().getEastNorth().east(), getFirstNode().getEastNorth().north(),
089                getSecondNode().getEastNorth().east(), getSecondNode().getEastNorth().north(),
090                s2.getFirstNode().getEastNorth().east(), s2.getFirstNode().getEastNorth().north(),
091                s2.getSecondNode().getEastNorth().east(), s2.getSecondNode().getEastNorth().north());
092    }
093
094    @Override
095    public String toString() {
096        return "WaySegment [way=" + way.getUniqueId() + ", lowerIndex=" + lowerIndex + "]";
097    }
098}