1 package org.opentrafficsim.importexport.osm;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7
8
9
10
11
12
13
14
15
16
17 public class Network
18 {
19
20 private HashMap<Long, Node> nodes;
21
22
23 private HashMap<Long, Way> ways;
24
25
26 private HashMap<Long, Relation> relations;
27
28
29 private String name;
30
31
32 private List<Link> links;
33
34
35
36
37
38 public Network(final String name)
39 {
40 this.setName(name);
41 this.nodes = new HashMap<Long, Node>();
42 this.ways = new HashMap<Long, Way>();
43 this.relations = new HashMap<Long, Relation>();
44 this.links = new ArrayList<Link>();
45 }
46
47
48
49
50
51 public Network(final Network net)
52 {
53 this.setName(net.getName());
54 this.nodes = new HashMap<Long, Node>(net.getNodes());
55 this.ways = new HashMap<Long, Way>(net.getWays());
56 this.relations = new HashMap<Long, Relation>(net.getRelations());
57 this.links = new ArrayList<Link>(net.getLinks());
58 }
59
60
61
62
63
64
65
66 public final List<Long> getNodesFromWay(final Long wayid) throws IOException
67 {
68 if (this.ways.get(wayid) == null)
69 {
70 throw new IOException("Way with the ID: " + wayid + "was not found");
71 }
72 else
73 {
74 return this.ways.get(wayid).getNodes();
75 }
76 }
77
78
79
80
81
82
83
84 public final Node getNode(final long nodeid) throws IOException
85 {
86 if (this.nodes.get(nodeid) == null)
87 {
88 throw new IOException("Node with the ID: " + nodeid + "was not found");
89 }
90 else
91 {
92 return this.nodes.get(nodeid);
93 }
94 }
95
96
97
98
99 public final HashMap<Long, Node> getNodes()
100 {
101 return this.nodes;
102 }
103
104
105
106
107
108
109
110 public final Relation getRelation(final long relid) throws IOException
111 {
112 if (this.relations.get(relid) == null)
113 {
114 throw new IOException("Relation with the ID: " + relid + "was not found");
115 }
116 else
117 {
118 return this.relations.get(relid);
119 }
120 }
121
122
123
124
125 public final HashMap<Long, Relation> getRelations()
126 {
127 return this.relations;
128 }
129
130
131
132
133
134
135
136 public final Way getWay(final long wayid) throws IOException
137 {
138 if (this.ways.get(wayid) == null)
139 {
140 throw new IOException("Way with the ID: " + wayid + "was not found");
141 }
142 else
143 {
144 return this.ways.get(wayid);
145 }
146 }
147
148
149
150
151 public final String getName()
152 {
153 return this.name;
154 }
155
156
157
158
159
160 public final void setName(final String name)
161 {
162 this.name = name;
163 }
164
165
166
167
168
169
170 public final void setNodes(final HashMap<Long, Node> newnodes)
171 {
172 this.nodes = newnodes;
173 }
174
175
176
177
178
179 public final void addNode(final Node node)
180 {
181 this.nodes.put(node.getID(), node);
182 }
183
184
185
186
187
188 public final void delNode(final Node node)
189 {
190 this.nodes.remove(node.getID());
191 }
192
193
194
195
196
197 public final void delNode(final Long nodeid)
198 {
199 this.nodes.remove(nodeid);
200 }
201
202
203
204
205
206 public final void addWay(final Way way)
207 {
208 this.ways.put(way.getID(), way);
209 }
210
211
212
213
214
215 public final void addRelation(final Relation rel)
216 {
217 this.relations.put(rel.getID(), rel);
218 }
219
220
221
222
223 public final HashMap<Long, Way> getWays()
224 {
225 return this.ways;
226 }
227
228
229
230
231 public final List<Link> getLinks()
232 {
233 return this.links;
234 }
235
236
237
238
239
240 public final void makeLinks() throws IOException
241 {
242 List<Link> links2 = new ArrayList<Link>();
243 double length;
244 Node n1;
245 Node n2;
246 double x1;
247 double x2;
248 double y1;
249 double y2;
250 for (Long wayid : this.ways.keySet())
251 {
252 List<Long> waynodes = this.getWay(wayid).getNodes();
253 for (int i = 0; i < (waynodes.size() - 1); i++)
254 {
255 n1 = this.getNode(waynodes.get(i).longValue());
256 n2 = this.getNode(waynodes.get(i + 1).longValue());
257
258 if (n1 == n2)
259 {
260 continue;
261 }
262 x1 = n1.getLatitude();
263 x2 = n2.getLatitude();
264 y1 = n1.getLongitude();
265 y2 = n2.getLongitude();
266 length = distanceLongLat(x1, y1, x2, y2);
267 Link e = new Link(n1, n2, this.getWay(wayid).getTags(), length);
268 links2.add(e);
269 }
270 }
271 this.links = links2;
272 }
273
274
275
276
277
278
279
280
281 private static double distanceLongLat(final double xx1, final double yy1, final double xx2, final double yy2)
282 {
283
284 double y1 = yy1;
285 double y2 = yy2;
286 if (y1 < 0)
287 {
288 y1 = 360 + yy1;
289 }
290 if (y2 < 0)
291 {
292 y2 = 360 + yy2;
293 }
294 double x1 = 90 - xx1;
295 double x2 = 90 - xx2;
296 x1 = x1 * (2 * Math.PI / 360);
297 x2 = x2 * (2 * Math.PI / 360);
298 y1 = y1 * (2 * Math.PI / 360);
299 y2 = y2 * (2 * Math.PI / 360);
300 double distance;
301 distance =
302 Math.acos(Math.sin(x1) * Math.sin(x2) * Math.cos(y1 - y2) + Math.cos(x1) * Math.cos(x2)) * 6371 * 1000;
303 return distance;
304 }
305
306
307
308
309 public final void removeRedundancy()
310 {
311 boolean again = false;
312 do
313 {
314 again = this.redundancyCheck();
315 }
316 while (again);
317 }
318
319
320
321
322
323
324 private boolean redundancyCheck()
325 {
326 List<Link> checkedLinks = new ArrayList<Link>();
327 List<Link> removedLinks = new ArrayList<Link>();
328 boolean redundancy = false;
329 for (Link l1 : this.links)
330 {
331 if (removedLinks.contains(l1))
332 {
333 continue;
334 }
335 String name1 = "1";
336 for (Tag t1 : l1.getTags())
337 {
338 if (t1.getKey().equals("name"))
339 {
340 name1 = t1.getValue();
341 }
342 }
343 for (Link l2 : this.links)
344 {
345 if (removedLinks.contains(l2))
346 {
347 continue;
348 }
349 String name2 = "2";
350 for (Tag t2 : l2.getTags())
351 {
352 if (t2.getKey().equals("name"))
353 {
354 name2 = t2.getValue();
355 }
356 }
357 if (l1.getEnd().equals(l2.getStart()) && name1.equalsIgnoreCase(name2)
358 && l1.getEnd().getTags().isEmpty() && l1.getTags().containsAll(l2.getTags())
359 && l1.getLanes() == l2.getLanes() && l1.getForwardLanes() == l2.getForwardLanes()
360 && l1.getStart() != l2.getEnd())
361 {
362 if (removedLinks.contains(l1))
363 {
364 for (int i = 0; i < this.links.size(); i++)
365 {
366 Link l = this.links.get(i);
367 if (l == l1)
368 {
369 System.out.println("found link " + l + " at position " + i);
370 }
371 }
372 throw new Error("about to add " + l1 + " to removeLinks which already contains that link");
373 }
374 redundancy = true;
375 Link lnew =
376 new Link(l1.getStart(), l2.getEnd(), l1.getTags(), l1.getLength() + l2.getLength(),
377 l1.getLanes(), l1.getForwardLanes());
378 if (!l1.getSplineList().isEmpty())
379 {
380 for (Node n1 : l1.getSplineList())
381 {
382 lnew.addSpline(n1);
383 }
384 }
385 if (!l2.getSplineList().isEmpty())
386 {
387 for (Node n2 : l2.getSplineList())
388 {
389 lnew.addSpline(n2);
390 }
391 }
392
393
394 checkedLinks.add(lnew);
395 removedLinks.add(l1);
396 removedLinks.add(l2);
397 break;
398 }
399 }
400 }
401
402
403
404
405
406
407 this.links.removeAll(removedLinks);
408 this.links.addAll(checkedLinks);
409
410 return redundancy;
411 }
412
413
414
415
416
417
418 public final Link findFollowingLink(final Link l)
419 {
420 if (!this.links.contains(l))
421 {
422 throw new Error("This link does not exist in this network: " + l);
423 }
424 for (Link l2: this.links)
425 {
426 if (l.getEnd().equals(l2.getStart()))
427 {
428 return l2;
429 }
430 }
431 return null;
432 }
433
434
435
436
437
438
439 public final Link findPrecedingLink(final Link l)
440 {
441 if (!this.links.contains(l))
442 {
443 throw new Error("This link does not exist in this network: " + l);
444 }
445 for (Link l2: this.links)
446 {
447 if (l.getStart().equals(l2.getEnd()))
448 {
449 return l2;
450 }
451 }
452 return null;
453 }
454
455
456
457
458
459
460 public final boolean hasPrecedingLink(final Link l)
461 {
462 if (!this.links.contains(l))
463 {
464 throw new Error("This link does not exist in this network: " + l);
465 }
466 for (Link l2: this.links)
467 {
468 if (l.getStart().equals(l2.getEnd()))
469 {
470 return true;
471 }
472 }
473 return false;
474 }
475
476
477
478
479
480
481 public final boolean hasFollowingLink(final Link l)
482 {
483 if (!this.links.contains(l))
484 {
485 throw new Error("This link does not exist in this network: " + l);
486 }
487 for (Link l2: this.links)
488 {
489 if (l.getEnd().equals(l2.getStart()))
490 {
491 return true;
492 }
493 }
494 return false;
495 }
496 }