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