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.UNITS;
15 import org.djunits.value.vdouble.scalar.Frequency;
16 import org.djunits.value.vdouble.scalar.Length;
17 import org.djunits.value.vdouble.scalar.Speed;
18 import org.geotools.data.FileDataStoreFinder;
19 import org.geotools.data.shapefile.ShapefileDataStore;
20 import org.geotools.data.simple.SimpleFeatureCollection;
21 import org.geotools.data.simple.SimpleFeatureIterator;
22 import org.geotools.data.simple.SimpleFeatureSource;
23 import org.geotools.geometry.jts.JTSFactoryFinder;
24 import org.opengis.feature.Property;
25 import org.opengis.feature.simple.SimpleFeature;
26 import org.opentrafficsim.core.geometry.OTSGeometryException;
27 import org.opentrafficsim.core.geometry.OTSLine3D;
28 import org.opentrafficsim.core.geometry.OTSPoint3D;
29 import org.opentrafficsim.core.network.Link;
30 import org.opentrafficsim.core.network.LinkType;
31 import org.opentrafficsim.core.network.LongitudinalDirectionality;
32 import org.opentrafficsim.core.network.Network;
33 import org.opentrafficsim.core.network.NetworkException;
34 import org.opentrafficsim.core.network.OTSNode;
35 import org.opentrafficsim.core.network.animation.LinkAnimation;
36 import org.opentrafficsim.road.network.animation.LaneAnimation;
37 import org.opentrafficsim.road.network.animation.ShoulderAnimation;
38 import org.opentrafficsim.road.network.lane.CrossSectionLink;
39 import org.opentrafficsim.road.network.lane.Lane;
40 import org.opentrafficsim.road.network.lane.NoTrafficLane;
41 import org.opentrafficsim.road.network.lane.Shoulder;
42 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
43 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
44
45 import com.vividsolutions.jts.geom.Coordinate;
46 import com.vividsolutions.jts.geom.Geometry;
47 import com.vividsolutions.jts.geom.GeometryFactory;
48 import com.vividsolutions.jts.geom.LineString;
49 import com.vividsolutions.jts.geom.Point;
50
51 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
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
80 public static Map<String, OTSNode> readNodes(final Network network, final String shapeFileName, final String numberType,
81 final boolean returnCentroid, final boolean allCentroids) throws IOException
82 {
83
84
85
86
87
88
89
90
91
92 URL url;
93 if (new File(shapeFileName).canRead())
94 {
95 url = new File(shapeFileName).toURI().toURL();
96 }
97 else
98 {
99 url = ShapeFileReader.class.getResource(shapeFileName);
100 }
101 ShapefileDataStore storeNodes = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
102
103 Map<String, OTSNode> nodes = new HashMap<>();
104
105 SimpleFeatureSource featureSourceNodes = storeNodes.getFeatureSource();
106 SimpleFeatureCollection featureCollectionNodes = featureSourceNodes.getFeatures();
107 SimpleFeatureIterator iterator = featureCollectionNodes.features();
108 try
109 {
110 while (iterator.hasNext())
111 {
112 SimpleFeature feature = iterator.next();
113 Coordinate coordinate = ((Point) feature.getAttribute("the_geom")).getCoordinate();
114 String nr = removeQuotes(String.valueOf(feature.getAttribute(numberType)));
115 boolean addThisNode = false;
116 if (returnCentroid)
117 {
118 if (nr.substring(0, 1).equals("C") || allCentroids)
119 {
120 addThisNode = true;
121 }
122 }
123 else
124 {
125 if (nr == null)
126 {
127 System.out.println("null found");
128 }
129 if (!nr.substring(0, 1).equals("C"))
130 {
131 addThisNode = true;
132 }
133 }
134 if (addThisNode)
135 {
136 OTSNode node = new OTSNode(network, nr, new OTSPoint3D(coordinate));
137 nodes.put(nr, node);
138 }
139 }
140 }
141 catch (Exception problem)
142 {
143 problem.printStackTrace();
144 }
145 finally
146 {
147 iterator.close();
148 storeNodes.dispose();
149 }
150 System.out.println("aantal knopen (353): geteld " + nodes.size());
151 return nodes;
152 }
153
154
155
156
157
158 public static boolean inspectNodeCentroid(final String number)
159 {
160 boolean isCentroid = false;
161 String[] names = removeQuotes(number).split(":");
162 String name = names[0];
163 if (name.charAt(0) == 'C')
164 {
165 isCentroid = true;
166 }
167 return isCentroid;
168 }
169
170
171
172
173
174
175
176
177
178 public static void readLinks(final Network network, final String shapeFileName, final Map<String, Link> links,
179 final Map<String, OTSNode> nodes, final SimulatorInterface.TimeDoubleUnit simulator) throws IOException
180 {
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 URL url;
199 if (new File(shapeFileName).canRead())
200 {
201 url = new File(shapeFileName).toURI().toURL();
202 }
203 else
204 {
205 url = ShapeFileReader.class.getResource(shapeFileName);
206 }
207
208 ShapefileDataStore storeLinks = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
209 SimpleFeatureSource featureSourceLinks = storeLinks.getFeatureSource();
210 SimpleFeatureCollection featureCollectionLinks = featureSourceLinks.getFeatures();
211 SimpleFeatureIterator iterator = featureCollectionLinks.features();
212
213 try
214 {
215 while (iterator.hasNext())
216 {
217 SimpleFeature feature = iterator.next();
218 GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
219 Geometry geometry = (Geometry) feature.getAttribute("the_geom");
220 Coordinate[] coords = geometry.getCoordinates();
221 LineString line = geometryFactory.createLineString(coords);
222 String nr = String.valueOf(feature.getAttribute("LINKNR"));
223 String nrBA = nr + "_BA";
224 String name = String.valueOf(feature.getAttribute("NAME"));
225
226
227 double lengthIn = Double.parseDouble(String.valueOf(feature.getAttribute("LENGTH")));
228 Length length = new Length(lengthIn, KILOMETER);
229 short direction = (short) Long.parseLong(String.valueOf(feature.getAttribute("DIRECTION")));
230 String lNodeA = String.valueOf(feature.getAttribute("ANODE"));
231 String lNodeB = String.valueOf(feature.getAttribute("BNODE"));
232
233 String linkTag = (String) feature.getAttribute("LINKTAG");
234 String wegtype = (String) feature.getAttribute("WEGTYPEAB");
235 String typeWegVak = (String) feature.getAttribute("TYPEWEGVAB");
236 String typeWeg = (String) feature.getAttribute("TYPEWEG_AB");
237 Double speedIn = Double.parseDouble(String.valueOf(feature.getAttribute("SPEEDAB")));
238 Speed speed = new Speed(speedIn, KM_PER_HOUR);
239 double capacityIn = Double.parseDouble(String.valueOf(feature.getAttribute("CAPACITYAB")));
240 Frequency capacity = new Frequency(capacityIn, PER_HOUR);
241
242
243 OTSNode nodeA = nodes.get(lNodeA);
244 OTSNode nodeB = nodes.get(lNodeB);
245
246 if (nodeA != null && nodeB != null)
247 {
248 CrossSectionLink linkAB = null;
249 CrossSectionLink linkBA = null;
250 linkAB = new CrossSectionLink(network, nr, nodeA, nodeB, LinkType.ROAD,
251 new OTSLine3D(new OTSPoint3D[] { nodeA.getPoint(), nodeB.getPoint() }), simulator,
252 LaneKeepingPolicy.KEEP_RIGHT);
253 animate(linkAB, typeWegVak, simulator);
254 linkBA = new CrossSectionLink(network, nrBA, nodeB, nodeA, LinkType.ROAD,
255 new OTSLine3D(new OTSPoint3D[] { nodeB.getPoint(), nodeA.getPoint() }), simulator,
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 animate(final CrossSectionLink link, final String wegType, final SimulatorInterface.TimeDoubleUnit simulator)
360 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, false);
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, new OvertakingConditions.LeftAndRight());
452 new LaneAnimation(lane, simulator, Color.GRAY, false);
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, false);
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, false);
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, new OvertakingConditions.LeftAndRight());
513 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
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 OvertakingConditions.LeftAndRight());
539 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
540 }
541 catch (NamingException | RemoteException | OTSGeometryException ne)
542 {
543
544 }
545 }
546
547 }