1 package org.opentrafficsim.demo.geometry.shape;
2
3 import java.awt.Color;
4 import java.io.File;
5 import java.io.IOException;
6 import java.net.URL;
7 import java.rmi.RemoteException;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.Map;
11
12 import javax.naming.NamingException;
13
14 import org.djunits.unit.FrequencyUnit;
15 import org.djunits.unit.SpeedUnit;
16 import org.djunits.unit.UNITS;
17 import org.djunits.value.vdouble.scalar.DoubleScalar;
18 import org.djunits.value.vdouble.scalar.Length;
19 import org.djunits.value.vdouble.scalar.Speed;
20 import org.geotools.data.FileDataStoreFinder;
21 import org.geotools.data.shapefile.ShapefileDataStore;
22 import org.geotools.data.simple.SimpleFeatureCollection;
23 import org.geotools.data.simple.SimpleFeatureIterator;
24 import org.geotools.data.simple.SimpleFeatureSource;
25 import org.geotools.geometry.jts.JTSFactoryFinder;
26 import org.opengis.feature.Property;
27 import org.opengis.feature.simple.SimpleFeature;
28 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
29 import org.opentrafficsim.core.geometry.OTSGeometryException;
30 import org.opentrafficsim.core.geometry.OTSLine3D;
31 import org.opentrafficsim.core.geometry.OTSPoint3D;
32 import org.opentrafficsim.core.network.Link;
33 import org.opentrafficsim.core.network.LinkType;
34 import org.opentrafficsim.core.network.LongitudinalDirectionality;
35 import org.opentrafficsim.core.network.NetworkException;
36 import org.opentrafficsim.core.network.OTSNode;
37 import org.opentrafficsim.core.network.animation.LinkAnimation;
38 import org.opentrafficsim.road.network.animation.LaneAnimation;
39 import org.opentrafficsim.road.network.animation.ShoulderAnimation;
40 import org.opentrafficsim.road.network.lane.CrossSectionLink;
41 import org.opentrafficsim.road.network.lane.Lane;
42 import org.opentrafficsim.road.network.lane.NoTrafficLane;
43 import org.opentrafficsim.road.network.lane.Shoulder;
44 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
45 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
46
47 import com.vividsolutions.jts.geom.Coordinate;
48 import com.vividsolutions.jts.geom.Geometry;
49 import com.vividsolutions.jts.geom.GeometryFactory;
50 import com.vividsolutions.jts.geom.LineString;
51 import com.vividsolutions.jts.geom.Point;
52
53
54
55
56
57
58
59
60
61
62
63 public final class ShapeFileReader implements UNITS
64 {
65
66 private ShapeFileReader()
67 {
68
69 }
70
71
72
73
74
75
76
77
78
79 public static Map<String, OTSNode> readNodes(final String shapeFileName, final String numberType,
80 final boolean returnCentroid, final boolean allCentroids) throws IOException
81 {
82
83
84
85
86
87
88
89
90
91 URL url;
92 if (new File(shapeFileName).canRead())
93 {
94 url = new File(shapeFileName).toURI().toURL();
95 }
96 else
97 {
98 url = ShapeFileReader.class.getResource(shapeFileName);
99 }
100 ShapefileDataStore storeNodes = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
101
102 Map<String, OTSNode> nodes = new HashMap<>();
103
104 SimpleFeatureSource featureSourceNodes = storeNodes.getFeatureSource();
105 SimpleFeatureCollection featureCollectionNodes = featureSourceNodes.getFeatures();
106 SimpleFeatureIterator iterator = featureCollectionNodes.features();
107 try
108 {
109 while (iterator.hasNext())
110 {
111 SimpleFeature feature = iterator.next();
112 Coordinate coordinate = ((Point) feature.getAttribute("the_geom")).getCoordinate();
113 String nr = removeQuotes(String.valueOf(feature.getAttribute(numberType)));
114 boolean addThisNode = false;
115 if (returnCentroid)
116 {
117 if (nr.substring(0, 1).equals("C") || allCentroids)
118 {
119 addThisNode = true;
120 }
121 }
122 else
123 {
124 if (nr == null)
125 {
126 System.out.println("null found");
127 }
128 if (!nr.substring(0, 1).equals("C"))
129 {
130 addThisNode = true;
131 }
132 }
133 if (addThisNode)
134 {
135 OTSNode node = new OTSNode(nr, new OTSPoint3D(coordinate));
136 nodes.put(nr, node);
137 }
138 }
139 }
140 catch (Exception problem)
141 {
142 problem.printStackTrace();
143 }
144 finally
145 {
146 iterator.close();
147 storeNodes.dispose();
148 }
149 System.out.println("aantal knopen (353): geteld " + nodes.size());
150 return nodes;
151 }
152
153
154
155
156
157 public static boolean inspectNodeCentroid(final String number)
158 {
159 boolean isCentroid = false;
160 String[] names = removeQuotes(number).split(":");
161 String name = names[0];
162 if (name.charAt(0) == 'C')
163 {
164 isCentroid = true;
165 }
166 return isCentroid;
167 }
168
169
170
171
172
173
174
175
176 public static void readLinks(final String shapeFileName, final Map<String, Link> links,
177 final Map<String, OTSNode> nodes, final OTSSimulatorInterface simulator) throws IOException
178 {
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 URL url;
197 if (new File(shapeFileName).canRead())
198 {
199 url = new File(shapeFileName).toURI().toURL();
200 }
201 else
202 {
203 url = ShapeFileReader.class.getResource(shapeFileName);
204 }
205
206 ShapefileDataStore storeLinks = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
207 SimpleFeatureSource featureSourceLinks = storeLinks.getFeatureSource();
208 SimpleFeatureCollection featureCollectionLinks = featureSourceLinks.getFeatures();
209 SimpleFeatureIterator iterator = featureCollectionLinks.features();
210
211 try
212 {
213 while (iterator.hasNext())
214 {
215 SimpleFeature feature = iterator.next();
216 GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
217 Geometry geometry = (Geometry) feature.getAttribute("the_geom");
218 Coordinate[] coords = geometry.getCoordinates();
219 LineString line = geometryFactory.createLineString(coords);
220 String nr = String.valueOf(feature.getAttribute("LINKNR"));
221 String nrBA = nr + "_BA";
222 String name = String.valueOf(feature.getAttribute("NAME"));
223
224
225 double lengthIn = Double.parseDouble(String.valueOf(feature.getAttribute("LENGTH")));
226 Length.Rel length = new Length.Rel(lengthIn, KILOMETER);
227 short direction = (short) Long.parseLong(String.valueOf(feature.getAttribute("DIRECTION")));
228 String lNodeA = String.valueOf(feature.getAttribute("ANODE"));
229 String lNodeB = String.valueOf(feature.getAttribute("BNODE"));
230
231 String linkTag = (String) feature.getAttribute("LINKTAG");
232 String wegtype = (String) feature.getAttribute("WEGTYPEAB");
233 String typeWegVak = (String) feature.getAttribute("TYPEWEGVAB");
234 String typeWeg = (String) feature.getAttribute("TYPEWEG_AB");
235 Double speedIn = Double.parseDouble(String.valueOf(feature.getAttribute("SPEEDAB")));
236 DoubleScalar<SpeedUnit> speed = new Speed(speedIn, KM_PER_HOUR);
237 double capacityIn = Double.parseDouble(String.valueOf(feature.getAttribute("CAPACITYAB")));
238 DoubleScalar<FrequencyUnit> capacity = new DoubleScalar.Abs<FrequencyUnit>(capacityIn, PER_HOUR);
239
240
241 OTSNode nodeA = nodes.get(lNodeA);
242 OTSNode nodeB = nodes.get(lNodeB);
243
244 if (nodeA != null && nodeB != null)
245 {
246 CrossSectionLink linkAB = null;
247 CrossSectionLink linkBA = null;
248 linkAB =
249 new CrossSectionLink(nr, nodeA, nodeB, LinkType.ALL, new OTSLine3D(new OTSPoint3D[]{
250 nodeA.getPoint(), nodeB.getPoint()}), LongitudinalDirectionality.DIR_BOTH,
251 LaneKeepingPolicy.KEEP_RIGHT);
252 animate(linkAB, typeWegVak, simulator);
253 linkBA =
254 new CrossSectionLink(nrBA, nodeB, nodeA, LinkType.ALL, new OTSLine3D(new OTSPoint3D[]{
255 nodeB.getPoint(), nodeA.getPoint()}), LongitudinalDirectionality.DIR_BOTH,
256 LaneKeepingPolicy.KEEP_RIGHT);
257 animate(linkBA, typeWegVak, simulator);
258 if (direction == 1)
259 {
260 links.put(nr, linkAB);
261 }
262 else if (direction == 2)
263 {
264 links.put(nrBA, linkBA);
265 }
266 else if (direction == 3)
267 {
268 links.put(nr, linkAB);
269 links.put(nrBA, linkBA);
270 }
271
272 }
273 else
274 {
275 System.out.println("Node lNodeA=" + lNodeA + " or lNodeB=" + lNodeB + " not found for linknr=" + nr
276 + ", name=" + name);
277 }
278 }
279
280 }
281 catch (Exception problem)
282 {
283 problem.printStackTrace();
284 }
285 finally
286 {
287 iterator.close();
288 storeLinks.dispose();
289 }
290
291 }
292
293
294
295
296
297 public static void shapeFileInfo(final String shapeFileName) throws IOException
298 {
299 URL url;
300 if (new File(shapeFileName).canRead())
301 {
302 url = new File(shapeFileName).toURI().toURL();
303 }
304 else
305 {
306 url = ShapeFileReader.class.getResource(shapeFileName);
307 }
308 ShapefileDataStore store = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
309
310 SimpleFeatureSource featureSource = store.getFeatureSource();
311 SimpleFeatureCollection featureCollection = featureSource.getFeatures();
312 SimpleFeatureIterator iterator = featureCollection.features();
313 try
314 {
315 while (iterator.hasNext())
316 {
317 SimpleFeature feature = iterator.next();
318 Collection<Property> areaProperties = feature.getProperties();
319 for (Property p : areaProperties)
320 {
321 System.out.println(p.getName() + " " + p.getValue().getClass() + " " + p.getValue().toString());
322 }
323 return;
324 }
325 }
326 catch (Exception problem)
327 {
328 problem.printStackTrace();
329 }
330 finally
331 {
332 iterator.close();
333 store.dispose();
334 }
335 }
336
337
338
339
340
341 public static String removeQuotes(final String name)
342 {
343 String newName = name;
344 if (newName.length() >= 2 && newName.charAt(0) == '"' && newName.charAt(newName.length() - 1) == '"')
345 {
346 newName = newName.substring(1, newName.length() - 1);
347 }
348 return newName;
349 }
350
351
352
353
354
355
356
357
358
359 private static void
360 animate(final CrossSectionLink link, final String wegType, final OTSSimulatorInterface simulator)
361 throws NamingException, NetworkException, RemoteException
362 {
363
364 new LinkAnimation(link, simulator, 0.1f);
365 if (wegType.startsWith("asw") || wegType.startsWith("80"))
366 {
367 int spits = 0;
368 int n = 1;
369 if (wegType.contains("2x2"))
370 {
371 n = 2;
372 }
373 if (wegType.contains("2x3"))
374 {
375 n = 3;
376 }
377 if (wegType.contains("2x4"))
378 {
379 n = 4;
380 }
381 if (wegType.contains("2x5"))
382 {
383 n = 5;
384 }
385 if (wegType.contains("+ 1") || wegType.contains("+1"))
386 {
387 spits = 1;
388 }
389 if (wegType.contains("+ 2") || wegType.contains("+2"))
390 {
391 spits = 2;
392 }
393 addNLanes(n, spits, link, simulator);
394 }
395 if (wegType.startsWith("stads"))
396 {
397 int n = 1;
398 if (wegType.contains("2x2"))
399 {
400 n = 2;
401 }
402 if (wegType.contains("2x3"))
403 {
404 n = 3;
405 }
406 boolean middenberm = wegType.contains("met middenberm");
407 addCityStreetLanes(n, middenberm, link, simulator);
408 }
409 else
410 {
411 addCityStreet(link, simulator);
412 }
413 }
414
415
416
417
418
419
420
421
422 private static void addNLanes(final int n, final int spits, final CrossSectionLink link,
423 final OTSSimulatorInterface simulator) throws NetworkException
424 {
425
426
427 Length.Rel m05 = new Length.Rel(0.5, METER);
428 Length.Rel m10 = new Length.Rel(1.0, METER);
429 Length.Rel m35 = new Length.Rel(3.5, METER);
430 Speed speedLimit = new Speed(100, KM_PER_HOUR);
431
432 try
433 {
434
435 Shoulder sM = new Shoulder(link, "sM", new Length.Rel(0.0, METER), m10);
436 new ShoulderAnimation(sM, simulator, Color.GREEN);
437 for (int i = -1; i <= 1; i += 2)
438 {
439 LongitudinalDirectionality dir =
440 (i < 0) ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS;
441 String lr = i < 0 ? "L" : "R";
442
443 Lane laneEM =
444 new NoTrafficLane(link, lr + "." + "EM", new Length.Rel(i * 0.75, METER), new Length.Rel(i * 0.75,
445 METER), m05, m05);
446 new LaneAnimation(laneEM, simulator, Color.LIGHT_GRAY, false);
447 double lat = 1;
448 for (int j = 0; j < n; j++)
449 {
450 lat += i * 1.75;
451 Lane lane =
452 new Lane(link, "lane." + lr + "." + j, new Length.Rel(lat, METER), new Length.Rel(lat, METER),
453 m35, m35, null, dir, speedLimit, new OvertakingConditions.LeftAndRight());
454 new LaneAnimation(lane, simulator, Color.GRAY, false);
455 lat += i * 1.75;
456 }
457
458 for (int j = 0; j < spits; j++)
459 {
460 lat += i * 1.75;
461 Lane lane =
462 new NoTrafficLane(link, "extra." + lr + "." + j, new Length.Rel(lat, METER), new Length.Rel(
463 lat, METER), m35, m35);
464 new LaneAnimation(lane, simulator, Color.LIGHT_GRAY, false);
465 lat += i * 1.75;
466 }
467 Lane laneEO =
468 new NoTrafficLane(link, lr + "." + "EO", new Length.Rel(lat + i * 0.25, METER), new Length.Rel(lat
469 + i * 0.25, METER), m05, m05);
470 new LaneAnimation(laneEO, simulator, Color.LIGHT_GRAY, false);
471 lat += i * 0.5;
472 Shoulder sO = new Shoulder(link, lr + "." + "sO", new Length.Rel(lat, METER), m10);
473 new ShoulderAnimation(sO, simulator, Color.GREEN);
474 }
475 }
476 catch (NamingException | RemoteException | OTSGeometryException ne)
477 {
478
479 }
480 }
481
482
483
484
485
486
487
488
489 private static void addCityStreetLanes(final int n, final boolean middenberm, final CrossSectionLink link,
490 final OTSSimulatorInterface simulator) throws NetworkException
491 {
492
493
494 Length.Rel m10 = new Length.Rel(1.0, METER);
495 Length.Rel m30 = new Length.Rel(3.0, METER);
496 Speed speedLimit = new Speed(100, KM_PER_HOUR);
497
498 try
499 {
500 if (middenberm)
501 {
502 Shoulder sM = new Shoulder(link, "sM", new Length.Rel(0.0, METER), m10);
503 new ShoulderAnimation(sM, simulator, Color.GREEN);
504 }
505 for (int i = -1; i <= 1; i += 2)
506 {
507 LongitudinalDirectionality dir =
508 (i < 0) ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS;
509 double lat = middenberm ? 0.5 : 0.0;
510 for (int j = 0; j < n; j++)
511 {
512 lat += i * 1.5;
513 String lr = i < 0 ? "L" : "R";
514 Lane lane =
515 new Lane(link, "lane." + lr + "." + j, new Length.Rel(lat, METER), new Length.Rel(lat, METER),
516 m30, m30, null, dir, speedLimit, new OvertakingConditions.LeftAndRight());
517 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
518 lat += i * 1.5;
519 }
520 }
521 }
522 catch (NamingException | RemoteException | ArrayIndexOutOfBoundsException | OTSGeometryException ne)
523 {
524 ne.printStackTrace();
525 }
526 }
527
528
529
530
531
532
533 private static void addCityStreet(final CrossSectionLink link, final OTSSimulatorInterface simulator)
534 throws NetworkException
535 {
536 Length.Rel m60 = new Length.Rel(6.0, METER);
537 Speed speedLimit = new Speed(100, KM_PER_HOUR);
538
539 try
540 {
541 Lane lane =
542 new Lane(link, "lane", new Length.Rel(0.0, METER), new Length.Rel(0.0, METER), m60, m60, null,
543 LongitudinalDirectionality.DIR_PLUS, speedLimit, new OvertakingConditions.LeftAndRight());
544 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
545 }
546 catch (NamingException | RemoteException | OTSGeometryException ne)
547 {
548
549 }
550 }
551
552 }