source: osm/applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructRouteAction.java@ 36102

Last change on this file since 36102 was 36102, checked in by taylor.smock, 16 months ago

reltoolbox: Clean up a bunch of lint warnings

  • Property svn:eol-style set to native
File size: 9.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package relcontext.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.util.ArrayList;
8import java.util.LinkedHashMap;
9import java.util.List;
10import java.util.Map;
11import java.util.Objects;
12
13import javax.swing.AbstractAction;
14
15import org.openstreetmap.josm.command.ChangeCommand;
16import org.openstreetmap.josm.command.Command;
17import org.openstreetmap.josm.data.UndoRedoHandler;
18import org.openstreetmap.josm.data.coor.EastNorth;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
22import org.openstreetmap.josm.data.osm.Relation;
23import org.openstreetmap.josm.data.osm.RelationMember;
24import org.openstreetmap.josm.data.osm.Way;
25import org.openstreetmap.josm.gui.dialogs.relation.sort.RelationSorter;
26import org.openstreetmap.josm.tools.Geometry;
27import org.openstreetmap.josm.tools.ImageProvider;
28
29import relcontext.ChosenRelation;
30import relcontext.ChosenRelationListener;
31
32/**
33 * Build in order stop/platforms, stop/platforms ... route
34 * @author freeExec
35 */
36public class ReconstructRouteAction extends AbstractAction implements ChosenRelationListener {
37 private final ChosenRelation rel;
38
39 public ReconstructRouteAction(ChosenRelation rel) {
40 super(tr("Reconstruct route"));
41 putValue(SMALL_ICON, ImageProvider.get("dialogs", "filter"));
42 putValue(LONG_DESCRIPTION, "Reconstruct route relation to scheme of public_transport");
43 this.rel = rel;
44 rel.addChosenRelationListener(this);
45 setEnabled(isSuitableRelation(rel.get()));
46 }
47
48 @Override
49 public void actionPerformed(ActionEvent e) {
50 Relation r = rel.get();
51 Relation recRel = new Relation(r);
52 recRel.removeMembersFor(recRel.getMemberPrimitives());
53
54 Map<OsmPrimitive, RelationMember> stopMembers = new LinkedHashMap<>();
55 Map<String, List<RelationMember>> platformMembers = new LinkedHashMap<>();
56
57 List<RelationMember> routeMembers = new ArrayList<>();
58 List<RelationMember> wtfMembers = new ArrayList<>();
59
60 int mCount = r.getMembersCount();
61 for (int i = 0; i < mCount; i++) {
62 RelationMember m = r.getMember(i);
63 if (PublicTransportHelper.isMemberStop(m)) {
64 RelationMember rm = new RelationMember(
65 m.hasRole() ? m.getRole() : PublicTransportHelper.STOP,
66 m.getMember());
67 stopMembers.put(rm.getMember(), rm);
68 } else if (PublicTransportHelper.isMemberPlatform(m)) {
69 RelationMember rm = new RelationMember(
70 m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM,
71 m.getMember());
72 String platformName = PublicTransportHelper.getNameViaStoparea(rm);
73 if (platformName == null) {
74 platformName = "";
75 }
76 if (platformMembers.containsKey(platformName)) {
77 platformMembers.get(platformName).add(rm);
78 } else {
79 List<RelationMember> nList = new ArrayList<>();
80 nList.add(rm);
81 platformMembers.put(platformName, nList);
82 }
83 } else if (PublicTransportHelper.isMemberRouteway(m)) {
84 routeMembers.add(new RelationMember(m));
85 } else {
86 wtfMembers.add(new RelationMember(m));
87 }
88 }
89
90 routeMembers = RelationSorter.sortMembersByConnectivity(routeMembers);
91
92 Node lastNode = null;
93 for (int rIndex = 0; rIndex < routeMembers.size(); rIndex++) {
94 Way w = (Way) routeMembers.get(rIndex).getMember();
95 boolean dirForward = false;
96 if (lastNode == null) { // first segment
97 if (routeMembers.size() > 2) {
98 Way nextWay = (Way) routeMembers.get(rIndex + 1).getMember();
99 if (Objects.equals(w.lastNode(), nextWay.lastNode()) || Objects.equals(w.lastNode(), nextWay.firstNode())) {
100 dirForward = true;
101 lastNode = w.lastNode();
102 } else {
103 lastNode = w.firstNode();
104 }
105 } // else one segment - direction unknown
106 } else {
107 if (lastNode.equals(w.firstNode())) {
108 dirForward = true; lastNode = w.lastNode();
109 } else {
110 lastNode = w.firstNode();
111 }
112 }
113 final int wayNodeBeginIndex = (dirForward ? 0 : w.getNodesCount() - 1);
114 final int wayNodeEndIndex = (dirForward ? w.getNodesCount() - 1 : 0);
115 final int increment = (dirForward ? 1 : -1);
116 for (int nIndex = wayNodeBeginIndex;
117 nIndex != wayNodeEndIndex;
118 nIndex += increment) {
119 Node refNode = w.getNode(nIndex);
120 if (PublicTransportHelper.isNodeStop(refNode)) {
121 if (stopMembers.containsKey(refNode)) {
122 recRel.addMember(stopMembers.get(refNode));
123 stopMembers.remove(refNode);
124 String stopName = PublicTransportHelper.getNameViaStoparea(refNode);
125 if (stopName == null) {
126 stopName = "";
127 }
128 boolean existsPlatform = platformMembers.containsKey(stopName);
129 if (!existsPlatform) {
130 stopName = ""; // find of the nameless
131 }
132 if (existsPlatform || platformMembers.containsKey(stopName)) {
133 List<RelationMember> lMember = platformMembers.get(stopName);
134 if (lMember.size() == 1) {
135 recRel.addMember(lMember.get(0));
136 lMember.remove(0);
137 } else {
138 // choose closest
139 RelationMember candidat = getClosestPlatform(lMember, refNode);
140 if (candidat != null) {
141 recRel.addMember(candidat);
142 lMember.remove(candidat);
143 }
144 }
145 if (lMember.isEmpty()) {
146 platformMembers.remove(stopName);
147 }
148 }
149 }
150 }
151 }
152 }
153
154 for (RelationMember stop : stopMembers.values()) {
155 recRel.addMember(stop);
156 String stopName = PublicTransportHelper.getNameViaStoparea(stop);
157 boolean existsPlatform = platformMembers.containsKey(stopName);
158 if (!existsPlatform) {
159 stopName = ""; // find of the nameless
160 }
161 if (existsPlatform || platformMembers.containsKey(stopName)) {
162 List<RelationMember> lMember = platformMembers.get(stopName);
163 if (lMember.size() == 1) {
164 recRel.addMember(lMember.get(0));
165 lMember.remove(0);
166 } else {
167 // choose closest
168 RelationMember candidat = getClosestPlatform(lMember, stop.getNode());
169 if (candidat != null) {
170 recRel.addMember(candidat);
171 lMember.remove(candidat);
172 }
173 }
174 if (lMember.isEmpty()) {
175 platformMembers.remove(stopName);
176 }
177 }
178 }
179
180 for (List<RelationMember> lPlatforms : platformMembers.values()) {
181 for (RelationMember platform : lPlatforms) {
182 recRel.addMember(platform);
183 }
184 }
185
186 for (RelationMember route : routeMembers) {
187 recRel.addMember(route);
188 }
189 for (RelationMember wtf : wtfMembers) {
190 recRel.addMember(wtf);
191 }
192 Command command = new ChangeCommand(r, recRel);
193 UndoRedoHandler.getInstance().add(command);
194 }
195
196 private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m
197 private RelationMember getClosestPlatform(List<RelationMember> members, Node stop) {
198 if (stop == null || members.isEmpty()) return null;
199 double maxDist = maxSqrDistBetweenStopAndPlatform;
200 RelationMember result = null;
201 for (RelationMember member : members) {
202 if (member.getType() == OsmPrimitiveType.NODE) {
203 Node node = member.getNode();
204 double sqrDist = stop.getEastNorth().distanceSq(node.getEastNorth());
205 if (sqrDist < maxDist) {
206 maxDist = sqrDist;
207 result = member;
208 }
209 } else if (member.getType() == OsmPrimitiveType.WAY) {
210 Way way = member.getWay();
211 EastNorth closest = Geometry.closestPointToSegment(
212 way.firstNode().getEastNorth(),
213 way.lastNode().getEastNorth(),
214 stop.getEastNorth()
215 );
216 double sqrDist = stop.getEastNorth().distanceSq(closest);
217 if (sqrDist < maxDist) {
218 maxDist = sqrDist;
219 result = member;
220 }
221 }
222 }
223 return result;
224 }
225
226 @Override
227 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
228 setEnabled(isSuitableRelation(newRelation));
229 }
230
231 private boolean isSuitableRelation(Relation newRelation) {
232 return !(newRelation == null || !"route".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0);
233 }
234}
Note: See TracBrowser for help on using the repository browser.