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