source: josm/trunk/src/org/openstreetmap/josm/tools/RotationAngle.java@ 14159

Last change on this file since 14159 was 13623, checked in by Don-vip, 6 years ago

more use of IPrimitive instead of OsmPrimitive

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import java.util.Locale;
5
6import org.openstreetmap.josm.data.osm.IPrimitive;
7import org.openstreetmap.josm.data.osm.Node;
8import org.openstreetmap.josm.data.osm.OsmPrimitive;
9import org.openstreetmap.josm.data.osm.Way;
10
11/**
12 * Determines how an icon is to be rotated depending on the primitive to be displayed.
13 * @since 8199 (creation)
14 * @since 10599 (functional interface)
15 * @since 12756 (moved from {@code gui.util} package)
16 */
17@FunctionalInterface
18public interface RotationAngle {
19
20 /**
21 * The rotation along a way.
22 */
23 final class WayDirectionRotationAngle implements RotationAngle {
24 @Override
25 public double getRotationAngle(IPrimitive p) {
26 if (!(p instanceof Node)) {
27 return 0;
28 }
29 final Node n = (Node) p;
30 final SubclassFilteredCollection<OsmPrimitive, Way> ways = Utils.filteredCollection(n.getReferrers(), Way.class);
31 if (ways.isEmpty()) {
32 return 0;
33 }
34 final Way w = ways.iterator().next();
35 final int idx = w.getNodes().indexOf(n);
36 if (idx == 0) {
37 return -Geometry.getSegmentAngle(n.getEastNorth(), w.getNode(idx + 1).getEastNorth());
38 } else {
39 return -Geometry.getSegmentAngle(w.getNode(idx - 1).getEastNorth(), n.getEastNorth());
40 }
41 }
42
43 @Override
44 public String toString() {
45 return "way-direction";
46 }
47
48 @Override
49 public int hashCode() {
50 return 1;
51 }
52
53 @Override
54 public boolean equals(Object obj) {
55 if (this == obj) {
56 return true;
57 }
58 return obj != null && getClass() == obj.getClass();
59 }
60 }
61
62 /**
63 * A static rotation
64 */
65 final class StaticRotationAngle implements RotationAngle {
66 private final double angle;
67
68 private StaticRotationAngle(double angle) {
69 this.angle = angle;
70 }
71
72 @Override
73 public double getRotationAngle(IPrimitive p) {
74 return angle;
75 }
76
77 @Override
78 public String toString() {
79 return angle + "rad";
80 }
81
82 @Override
83 public int hashCode() {
84 final int prime = 31;
85 int result = 1;
86 long temp = Double.doubleToLongBits(angle);
87 result = prime * result + (int) (temp ^ (temp >>> 32));
88 return result;
89 }
90
91 @Override
92 public boolean equals(Object obj) {
93 if (this == obj) {
94 return true;
95 }
96 if (obj == null || getClass() != obj.getClass()) {
97 return false;
98 }
99 StaticRotationAngle other = (StaticRotationAngle) obj;
100 return Double.doubleToLongBits(angle) == Double.doubleToLongBits(other.angle);
101 }
102 }
103
104 /**
105 * A no-rotation angle that always returns 0.
106 * @since 11726
107 */
108 RotationAngle NO_ROTATION = new StaticRotationAngle(0);
109
110 /**
111 * Calculates the rotation angle depending on the primitive to be displayed.
112 * @param p primitive
113 * @return rotation angle
114 * @since 13623 (signature)
115 */
116 double getRotationAngle(IPrimitive p);
117
118 /**
119 * Always returns the fixed {@code angle}.
120 * @param angle angle
121 * @return rotation angle
122 */
123 static RotationAngle buildStaticRotation(final double angle) {
124 return new StaticRotationAngle(angle);
125 }
126
127 /**
128 * Parses the rotation angle from the specified {@code string}.
129 * @param string angle as string
130 * @return rotation angle
131 */
132 static RotationAngle buildStaticRotation(final String string) {
133 try {
134 return buildStaticRotation(parseCardinalRotation(string));
135 } catch (IllegalArgumentException e) {
136 throw new IllegalArgumentException("Invalid string: " + string, e);
137 }
138 }
139
140 /**
141 * Converts an angle diven in cardinal directions to radians.
142 * The following values are supported: {@code n}, {@code north}, {@code ne}, {@code northeast},
143 * {@code e}, {@code east}, {@code se}, {@code southeast}, {@code s}, {@code south},
144 * {@code sw}, {@code southwest}, {@code w}, {@code west}, {@code nw}, {@code northwest}.
145 * @param cardinal the angle in cardinal directions
146 * @return the angle in radians
147 */
148 static double parseCardinalRotation(final String cardinal) {
149 switch (cardinal.toLowerCase(Locale.ENGLISH)) {
150 case "n":
151 case "north":
152 return 0; // 0 degree => 0 radian
153 case "ne":
154 case "northeast":
155 return Utils.toRadians(45);
156 case "e":
157 case "east":
158 return Utils.toRadians(90);
159 case "se":
160 case "southeast":
161 return Utils.toRadians(135);
162 case "s":
163 case "south":
164 return Math.PI; // 180 degree
165 case "sw":
166 case "southwest":
167 return Utils.toRadians(225);
168 case "w":
169 case "west":
170 return Utils.toRadians(270);
171 case "nw":
172 case "northwest":
173 return Utils.toRadians(315);
174 default:
175 throw new IllegalArgumentException("Unexpected cardinal direction " + cardinal);
176 }
177 }
178
179 /**
180 * Computes the angle depending on the referencing way segment, or {@code 0} if none exists.
181 * @return rotation angle
182 */
183 static RotationAngle buildWayDirectionRotation() {
184 return new WayDirectionRotationAngle();
185 }
186}
Note: See TracBrowser for help on using the repository browser.