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()}), LaneKeepingPolicy.KEEPRIGHT);
254 animate(linkAB, typeWegVak, simulator);
255 linkBA = new CrossSectionLink(network, nrBA, nodeB, nodeA, network.getLinkType(LinkType.DEFAULTS.ROAD),
256 new OTSLine3D(new OTSPoint3D[] {nodeB.getPoint(), nodeA.getPoint()}), LaneKeepingPolicy.KEEPRIGHT);
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 animate(final CrossSectionLink link, final String wegType,
360 final SimulatorInterface.TimeDoubleUnit simulator) throws NamingException, NetworkException, RemoteException
361 {
362
363 new LinkAnimation(link, simulator, 0.1f);
364 if (wegType.startsWith("asw") || wegType.startsWith("80"))
365 {
366 int spits = 0;
367 int n = 1;
368 if (wegType.contains("2x2"))
369 {
370 n = 2;
371 }
372 if (wegType.contains("2x3"))
373 {
374 n = 3;
375 }
376 if (wegType.contains("2x4"))
377 {
378 n = 4;
379 }
380 if (wegType.contains("2x5"))
381 {
382 n = 5;
383 }
384 if (wegType.contains("+ 1") || wegType.contains("+1"))
385 {
386 spits = 1;
387 }
388 if (wegType.contains("+ 2") || wegType.contains("+2"))
389 {
390 spits = 2;
391 }
392 addNLanes(n, spits, link, simulator);
393 }
394 if (wegType.startsWith("stads"))
395 {
396 int n = 1;
397 if (wegType.contains("2x2"))
398 {
399 n = 2;
400 }
401 if (wegType.contains("2x3"))
402 {
403 n = 3;
404 }
405 boolean middenberm = wegType.contains("met middenberm");
406 addCityStreetLanes(n, middenberm, link, simulator);
407 }
408 else
409 {
410 addCityStreet(link, simulator);
411 }
412 }
413
414
415
416
417
418
419
420
421 private static void addNLanes(final int n, final int spits, final CrossSectionLink link,
422 final SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
423 {
424
425
426 Length m05 = new Length(0.5, METER);
427 Length m10 = new Length(1.0, METER);
428 Length m35 = new Length(3.5, METER);
429 Speed speedLimit = new Speed(100, KM_PER_HOUR);
430
431 try
432 {
433
434 Shoulder sM = new Shoulder(link, "sM", new Length(0.0, METER), m10);
435 new ShoulderAnimation(sM, simulator, Color.GREEN);
436 for (int i = -1; i <= 1; i += 2)
437 {
438 LongitudinalDirectionality dir =
439 (i < 0) ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS;
440
441 String lr = i < 0 ? "L" : "R";
442
443 Lane laneEM = new NoTrafficLane(link, lr + "." + "EM", new Length(i * 0.75, METER), new Length(i * 0.75, METER),
444 m05, m05);
445 new LaneAnimation(laneEM, simulator, Color.LIGHT_GRAY);
446 double lat = 1;
447 for (int j = 0; j < n; j++)
448 {
449 lat += i * 1.75;
450 Lane lane = new Lane(link, "lane." + lr + "." + j, new Length(lat, METER), new Length(lat, METER), m35, m35,
451 null, speedLimit);
452 new LaneAnimation(lane, simulator, Color.GRAY);
453 lat += i * 1.75;
454 }
455
456 for (int j = 0; j < spits; j++)
457 {
458 lat += i * 1.75;
459 Lane lane = new NoTrafficLane(link, "extra." + lr + "." + j, new Length(lat, METER), new Length(lat, METER),
460 m35, m35);
461 new LaneAnimation(lane, simulator, Color.LIGHT_GRAY);
462 lat += i * 1.75;
463 }
464 Lane laneEO = new NoTrafficLane(link, lr + "." + "EO", new Length(lat + i * 0.25, METER),
465 new Length(lat + i * 0.25, METER), m05, m05);
466 new LaneAnimation(laneEO, simulator, Color.LIGHT_GRAY);
467 lat += i * 0.5;
468 Shoulder sO = new Shoulder(link, lr + "." + "sO", new Length(lat, METER), m10);
469 new ShoulderAnimation(sO, simulator, Color.GREEN);
470 }
471 }
472 catch (NamingException | RemoteException | OTSGeometryException ne)
473 {
474
475 }
476 }
477
478
479
480
481
482
483
484
485 private static void addCityStreetLanes(final int n, final boolean middenberm, final CrossSectionLink link,
486 final SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
487 {
488
489
490 Length m10 = new Length(1.0, METER);
491 Length m30 = new Length(3.0, METER);
492 Speed speedLimit = new Speed(100, KM_PER_HOUR);
493
494 try
495 {
496 if (middenberm)
497 {
498 Shoulder sM = new Shoulder(link, "sM", new Length(0.0, METER), m10);
499 new ShoulderAnimation(sM, simulator, Color.GREEN);
500 }
501 for (int i = -1; i <= 1; i += 2)
502 {
503
504 LongitudinalDirectionality dir =
505 (i < 0) ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS;
506 double lat = middenberm ? 0.5 : 0.0;
507 for (int j = 0; j < n; j++)
508 {
509 lat += i * 1.5;
510 String lr = i < 0 ? "L" : "R";
511 Lane lane = new Lane(link, "lane." + lr + "." + j, new Length(lat, METER), new Length(lat, METER), m30, m30,
512 null, speedLimit);
513 new LaneAnimation(lane, simulator, Color.DARK_GRAY);
514 lat += i * 1.5;
515 }
516 }
517 }
518 catch (NamingException | RemoteException | ArrayIndexOutOfBoundsException | OTSGeometryException ne)
519 {
520 ne.printStackTrace();
521 }
522 }
523
524
525
526
527
528
529 private static void addCityStreet(final CrossSectionLink link, final SimulatorInterface.TimeDoubleUnit simulator)
530 throws NetworkException
531 {
532 Length m60 = new Length(6.0, METER);
533 Speed speedLimit = new Speed(100, KM_PER_HOUR);
534
535 try
536 {
537 Lane lane = new Lane(link, "lane", new Length(0.0, METER), new Length(0.0, METER), m60, m60, null, speedLimit);
538 new LaneAnimation(lane, simulator, Color.DARK_GRAY);
539 }
540 catch (NamingException | RemoteException | OTSGeometryException ne)
541 {
542
543 }
544 }
545
546 }