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

Last change on this file since 32395 was 32395, checked in by donvip, 10 years ago

checkstyle, update to JOSM 10279

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