1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.data.osm;
|
---|
3 |
|
---|
4 | import java.awt.geom.Line2D;
|
---|
5 | import java.util.Objects;
|
---|
6 |
|
---|
7 | /**
|
---|
8 | * A segment consisting of 2 consecutive nodes out of a way.
|
---|
9 | */
|
---|
10 | public final class WaySegment implements Comparable<WaySegment> {
|
---|
11 |
|
---|
12 | /**
|
---|
13 | * The way.
|
---|
14 | */
|
---|
15 | public final Way way;
|
---|
16 |
|
---|
17 | /**
|
---|
18 | * The index of one of the 2 nodes in the way. The other node has the
|
---|
19 | * index <code>lowerIndex + 1</code>.
|
---|
20 | */
|
---|
21 | public final int lowerIndex;
|
---|
22 |
|
---|
23 | /**
|
---|
24 | * Constructs a new {@code WaySegment}.
|
---|
25 | * @param w The way
|
---|
26 | * @param i The node lower index
|
---|
27 | * @throws IllegalArgumentException in case of invalid index
|
---|
28 | */
|
---|
29 | public WaySegment(Way w, int i) {
|
---|
30 | way = w;
|
---|
31 | lowerIndex = i;
|
---|
32 | if (i < 0 || i >= w.getNodesCount() - 1) {
|
---|
33 | throw new IllegalArgumentException(toString());
|
---|
34 | }
|
---|
35 | }
|
---|
36 |
|
---|
37 | /**
|
---|
38 | * Returns the first node of the way segment.
|
---|
39 | * @return the first node
|
---|
40 | */
|
---|
41 | public Node getFirstNode() {
|
---|
42 | return way.getNode(lowerIndex);
|
---|
43 | }
|
---|
44 |
|
---|
45 | /**
|
---|
46 | * Returns the second (last) node of the way segment.
|
---|
47 | * @return the second node
|
---|
48 | */
|
---|
49 | public Node getSecondNode() {
|
---|
50 | return way.getNode(lowerIndex + 1);
|
---|
51 | }
|
---|
52 |
|
---|
53 | /**
|
---|
54 | * Determines and returns the way segment for the given way and node pair.
|
---|
55 | * @param way way
|
---|
56 | * @param first first node
|
---|
57 | * @param second second node
|
---|
58 | * @return way segment
|
---|
59 | * @throws IllegalArgumentException if the node pair is not part of way
|
---|
60 | */
|
---|
61 | public static WaySegment forNodePair(Way way, Node first, Node second) {
|
---|
62 | int endIndex = way.getNodesCount() - 1;
|
---|
63 | while (endIndex > 0) {
|
---|
64 | final int indexOfFirst = way.getNodes().subList(0, endIndex).lastIndexOf(first);
|
---|
65 | if (second.equals(way.getNode(indexOfFirst + 1))) {
|
---|
66 | return new WaySegment(way, indexOfFirst);
|
---|
67 | }
|
---|
68 | endIndex--;
|
---|
69 | }
|
---|
70 | throw new IllegalArgumentException("Node pair is not part of way!");
|
---|
71 | }
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * Returns this way segment as complete way.
|
---|
75 | * @return the way segment as {@code Way}
|
---|
76 | */
|
---|
77 | public Way toWay() {
|
---|
78 | Way w = new Way();
|
---|
79 | w.addNode(getFirstNode());
|
---|
80 | w.addNode(getSecondNode());
|
---|
81 | return w;
|
---|
82 | }
|
---|
83 |
|
---|
84 | @Override
|
---|
85 | public boolean equals(Object o) {
|
---|
86 | if (this == o) return true;
|
---|
87 | if (o == null || getClass() != o.getClass()) return false;
|
---|
88 | WaySegment that = (WaySegment) o;
|
---|
89 | return lowerIndex == that.lowerIndex &&
|
---|
90 | Objects.equals(way, that.way);
|
---|
91 | }
|
---|
92 |
|
---|
93 | @Override
|
---|
94 | public int hashCode() {
|
---|
95 | return Objects.hash(way, lowerIndex);
|
---|
96 | }
|
---|
97 |
|
---|
98 | @Override
|
---|
99 | public int compareTo(WaySegment o) {
|
---|
100 | return o == null ? -1 : (equals(o) ? 0 : toWay().compareTo(o.toWay()));
|
---|
101 | }
|
---|
102 |
|
---|
103 | /**
|
---|
104 | * Checks whether this segment crosses other segment
|
---|
105 | *
|
---|
106 | * @param s2 The other segment
|
---|
107 | * @return true if both segments crosses
|
---|
108 | */
|
---|
109 | public boolean intersects(WaySegment s2) {
|
---|
110 | if (getFirstNode().equals(s2.getFirstNode()) || getSecondNode().equals(s2.getSecondNode()) ||
|
---|
111 | getFirstNode().equals(s2.getSecondNode()) || getSecondNode().equals(s2.getFirstNode()))
|
---|
112 | return false;
|
---|
113 |
|
---|
114 | return Line2D.linesIntersect(
|
---|
115 | getFirstNode().getEastNorth().east(), getFirstNode().getEastNorth().north(),
|
---|
116 | getSecondNode().getEastNorth().east(), getSecondNode().getEastNorth().north(),
|
---|
117 | s2.getFirstNode().getEastNorth().east(), s2.getFirstNode().getEastNorth().north(),
|
---|
118 | s2.getSecondNode().getEastNorth().east(), s2.getSecondNode().getEastNorth().north());
|
---|
119 | }
|
---|
120 |
|
---|
121 | /**
|
---|
122 | * Checks whether this segment and another way segment share the same points
|
---|
123 | * @param s2 The other segment
|
---|
124 | * @return true if other way segment is the same or reverse
|
---|
125 | */
|
---|
126 | public boolean isSimilar(WaySegment s2) {
|
---|
127 | return (getFirstNode().equals(s2.getFirstNode()) && getSecondNode().equals(s2.getSecondNode()))
|
---|
128 | || (getFirstNode().equals(s2.getSecondNode()) && getSecondNode().equals(s2.getFirstNode()));
|
---|
129 | }
|
---|
130 |
|
---|
131 | @Override
|
---|
132 | public String toString() {
|
---|
133 | return "WaySegment [way=" + way.getUniqueId() + ", lowerIndex=" + lowerIndex + ']';
|
---|
134 | }
|
---|
135 | }
|
---|