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

Last change on this file since 34130 was 33530, checked in by donvip, 8 years ago

update to JOSM 12663

  • Property svn:eol-style set to native
File size: 9.8 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.command.ChangeCommand;
15import org.openstreetmap.josm.command.Command;
16import org.openstreetmap.josm.data.coor.EastNorth;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
20import org.openstreetmap.josm.data.osm.Relation;
21import org.openstreetmap.josm.data.osm.RelationMember;
22import org.openstreetmap.josm.data.osm.Way;
23import org.openstreetmap.josm.gui.MainApplication;
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 } else if (PublicTransportHelper.isMemberPlatform(m)) {
68 RelationMember rm = new RelationMember(
69 m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM,
70 m.getMember());
71 String platformName = PublicTransportHelper.getNameViaStoparea(rm);
72 if (platformName == null) {
73 platformName = "";
74 }
75 if (platformMembers.containsKey(platformName)) {
76 platformMembers.get(platformName).add(rm);
77 } else {
78 List<RelationMember> nList = new ArrayList<>();
79 nList.add(rm);
80 platformMembers.put(platformName, nList);
81 }
82 } else if (PublicTransportHelper.isMemberRouteway(m)) {
83 routeMembers.add(new RelationMember(m));
84 } else {
85 wtfMembers.add(new RelationMember(m));
86 }
87 }
88
89 routeMembers = RelationSorter.sortMembersByConnectivity(routeMembers);
90
91 Node lastNode = null;
92 for (int rIndex = 0; rIndex < routeMembers.size(); rIndex++) {
93 Way w = (Way) routeMembers.get(rIndex).getMember();
94 boolean dirForward = false;
95 if (lastNode == null) { // first segment
96 if (routeMembers.size() > 2) {
97 Way nextWay = (Way) routeMembers.get(rIndex + 1).getMember();
98 if (w.lastNode().equals(nextWay.lastNode()) || w.lastNode().equals(nextWay.firstNode())) {
99 dirForward = true;
100 lastNode = w.lastNode();
101 } else {
102 lastNode = w.firstNode();
103 }
104 } // else one segment - direction unknown
105 } else {
106 if (lastNode.equals(w.firstNode())) {
107 dirForward = true; lastNode = w.lastNode();
108 } 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) {
129 stopName = ""; // find of the nameless
130 }
131 if (existsPlatform || platformMembers.containsKey(stopName)) {
132 List<RelationMember> lMember = platformMembers.get(stopName);
133 if (lMember.size() == 1) {
134 recRel.addMember(lMember.get(0));
135 lMember.remove(0);
136 } else {
137 // choose closest
138 RelationMember candidat = getClosestPlatform(lMember, refNode);
139 if (candidat != null) {
140 recRel.addMember(candidat);
141 lMember.remove(candidat);
142 }
143 }
144 if (lMember.isEmpty()) {
145 platformMembers.remove(stopName);
146 }
147 }
148 }
149 }
150 }
151 }
152
153 for (RelationMember stop : stopMembers.values()) {
154 recRel.addMember(stop);
155 String stopName = PublicTransportHelper.getNameViaStoparea(stop);
156 boolean existsPlatform = platformMembers.containsKey(stopName);
157 if (!existsPlatform) {
158 stopName = ""; // find of the nameless
159 }
160 if (existsPlatform || platformMembers.containsKey(stopName)) {
161 List<RelationMember> lMember = platformMembers.get(stopName);
162 if (lMember.size() == 1) {
163 recRel.addMember(lMember.get(0));
164 lMember.remove(0);
165 } else {
166 // choose closest
167 RelationMember candidat = getClosestPlatform(lMember, stop.getNode());
168 if (candidat != null) {
169 recRel.addMember(candidat);
170 lMember.remove(candidat);
171 }
172 }
173 if (lMember.isEmpty()) {
174 platformMembers.remove(stopName);
175 }
176 }
177 }
178
179 for (List<RelationMember> lPlatforms : platformMembers.values()) {
180 for (RelationMember platform : lPlatforms) {
181 recRel.addMember(platform);
182 }
183 }
184
185 for (RelationMember route : routeMembers) {
186 recRel.addMember(route);
187 }
188 for (RelationMember wtf : wtfMembers) {
189 recRel.addMember(wtf);
190 }
191 Command command = new ChangeCommand(r, recRel);
192 MainApplication.undoRedo.add(command);
193 }
194
195 private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m
196 private RelationMember getClosestPlatform(List<RelationMember> members, Node stop) {
197 if (stop == null || members.isEmpty()) return null;
198 double maxDist = maxSqrDistBetweenStopAndPlatform;
199 RelationMember result = null;
200 for (RelationMember member : members) {
201 if (member.getType() == OsmPrimitiveType.NODE) {
202 Node node = member.getNode();
203 double sqrDist = stop.getEastNorth().distanceSq(node.getEastNorth());
204 if (sqrDist < maxDist) {
205 maxDist = sqrDist;
206 result = member;
207 }
208 } else if (member.getType() == OsmPrimitiveType.WAY) {
209 Way way = member.getWay();
210 EastNorth closest = Geometry.closestPointToSegment(
211 way.firstNode().getEastNorth(),
212 way.lastNode().getEastNorth(),
213 stop.getEastNorth()
214 );
215 double sqrDist = stop.getEastNorth().distanceSq(closest);
216 if (sqrDist < maxDist) {
217 maxDist = sqrDist;
218 result = member;
219 }
220 }
221 }
222 return result;
223 }
224
225 @Override
226 public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
227 setEnabled(isSuitableRelation(newRelation));
228 }
229
230 private boolean isSuitableRelation(Relation newRelation) {
231 return !(newRelation == null || !"route".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0);
232 }
233}
Note: See TracBrowser for help on using the repository browser.