source: osm/applications/editors/josm/plugins/public_transport_layer/src/ptl/DistanceBetweenStops.java@ 33528

Last change on this file since 33528 was 33527, checked in by donvip, 7 years ago

update to JOSM 12663

File size: 6.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package ptl;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.text.DecimalFormat;
8import java.util.ArrayList;
9import java.util.Collections;
10import java.util.List;
11
12import javax.swing.JOptionPane;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.actions.JosmAction;
16import org.openstreetmap.josm.data.SystemOfMeasurement;
17import org.openstreetmap.josm.data.coor.LatLon;
18import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
19import org.openstreetmap.josm.data.osm.Node;
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.gui.ExtendedDialog;
24import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType;
25import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionTypeCalculator;
26import org.openstreetmap.josm.gui.util.GuiHelper;
27import org.openstreetmap.josm.gui.widgets.JosmTextArea;
28import org.openstreetmap.josm.tools.CheckParameterUtil;
29import org.openstreetmap.josm.tools.Utils;
30
31public class DistanceBetweenStops extends JosmAction {
32
33 public DistanceBetweenStops() {
34 super(tr("Distance between stops"), null, null, null, false);
35 }
36
37 static String calculateDistanceBetweenStops(final Relation route) {
38 CheckParameterUtil.ensureThat(isRouteSupported(route), "A valid public_transport:version=2 route is required");
39
40 final List<Node> stopNodes = new ArrayList<>();
41 final List<RelationMember> routeSegments = new ArrayList<>();
42 final List<Node> routeNodes = new ArrayList<>();
43 for (final RelationMember member : route.getMembers()) {
44 if (member.hasRole("stop", "stop_exit_only", "stop_entry_only") && OsmPrimitiveType.NODE.equals(member.getType())) {
45 stopNodes.add(member.getNode());
46 } else if (member.hasRole("") && OsmPrimitiveType.WAY.equals(member.getType())) {
47 routeSegments.add(member);
48 }
49 }
50
51 final WayConnectionTypeCalculator connectionTypeCalculator = new WayConnectionTypeCalculator();
52 final List<WayConnectionType> links = connectionTypeCalculator.updateLinks(routeSegments);
53 for (int i = 0; i < links.size(); i++) {
54 final WayConnectionType link = links.get(i);
55 final List<Node> nodes = routeSegments.get(i).getWay().getNodes();
56 switch (link.direction) {
57 case BACKWARD:
58 Collections.reverse(nodes);
59 // fall through
60 case FORWARD:
61 routeNodes.addAll(link.linkPrev ? nodes.subList(1, nodes.size()) : nodes);
62 break;
63 default:
64 break;
65 }
66 }
67
68 final StringBuilder sb = new StringBuilder();
69 Node lastN = null;
70 List<Node> remainingRouteNodes = routeNodes;
71 double totalLength = 0.0;
72 int lengthN = 0;
73 final boolean onlyLowerUnit = Main.pref.getBoolean("system_of_measurement.use_only_lower_unit", false);
74 Main.pref.put("system_of_measurement.use_only_lower_unit", true);
75 try {
76 for (Node n : stopNodes) {
77 final double length;
78 if (lastN != null) {
79 if (remainingRouteNodes.indexOf(lastN) > 0) {
80 remainingRouteNodes = remainingRouteNodes.subList(remainingRouteNodes.indexOf(lastN), remainingRouteNodes.size());
81 }
82 if (remainingRouteNodes.indexOf(n) > 0) {
83 final List<Node> segmentBetweenStops = remainingRouteNodes.subList(0, remainingRouteNodes.indexOf(n) + 1);
84 length = getLength(segmentBetweenStops);
85 totalLength += length;
86 lengthN++;
87 } else {
88 length = Double.NaN;
89 }
90 } else {
91 length = 0.0;
92 }
93 sb.append(SystemOfMeasurement.getSystemOfMeasurement().getDistText(length, new DecimalFormat("0"), -1));
94 sb.append("\t");
95 sb.append(n.getDisplayName(DefaultNameFormatter.getInstance()));
96 sb.append("\n");
97 lastN = n;
98 }
99 sb.insert(0, "\n");
100 sb.insert(0, route.getDisplayName(DefaultNameFormatter.getInstance()));
101 sb.insert(0, "\t");
102 sb.insert(0, SystemOfMeasurement.getSystemOfMeasurement().getDistText(totalLength / lengthN, new DecimalFormat("0"), -1));
103 } finally {
104 Main.pref.put("system_of_measurement.use_only_lower_unit", onlyLowerUnit);
105 }
106
107 return sb.toString();
108 }
109
110 private static boolean isRouteSupported(Relation route) {
111 return !route.hasIncompleteMembers()
112 && route.hasTag("type", "route")
113 && route.hasKey("route")
114 && route.hasTag("public_transport:version", "2");
115 }
116
117 private static double getLength(Iterable<Node> nodes) {
118 double length = 0;
119 Node lastN = null;
120 for (Node n : nodes) {
121 if (lastN != null) {
122 LatLon lastNcoor = lastN.getCoor();
123 LatLon coor = n.getCoor();
124 if (lastNcoor != null && coor != null) {
125 length += coor.greatCircleDistance(lastNcoor);
126 }
127 }
128 lastN = n;
129 }
130 return length;
131 }
132
133 @Override
134 public void actionPerformed(ActionEvent e) {
135 if (getLayerManager().getEditDataSet() == null) {
136 return;
137 }
138 final StringBuilder sb = new StringBuilder();
139 for (Relation relation : getLayerManager().getEditDataSet().getSelectedRelations()) {
140 if (!isRouteSupported(relation)) {
141 JOptionPane.showMessageDialog(Main.parent, "<html>" + tr("A valid public_transport:version=2 route is required")
142 + Utils.joinAsHtmlUnorderedList(Collections.singleton(relation.getDisplayName(DefaultNameFormatter.getInstance()))),
143 tr("Invalid selection"), JOptionPane.WARNING_MESSAGE);
144 continue;
145 }
146 sb.append("\n");
147 sb.append(calculateDistanceBetweenStops(relation)).append("\n");
148 }
149
150 new ExtendedDialog(Main.parent, getValue(NAME).toString(), new String[]{tr("Close")}) {
151 {
152 setButtonIcons(new String[]{"ok.png"});
153 final JosmTextArea jte = new JosmTextArea();
154 jte.setFont(GuiHelper.getMonospacedFont(jte));
155 jte.setEditable(false);
156 jte.append(sb.toString());
157 jte.setSelectionStart(0);
158 jte.setSelectionEnd(0);
159 setContent(jte);
160 }
161
162 }.showDialog();
163 }
164}
Note: See TracBrowser for help on using the repository browser.