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.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.LinkType;
32 import org.opentrafficsim.core.network.LongitudinalDirectionality;
33 import org.opentrafficsim.core.network.Network;
34 import org.opentrafficsim.core.network.NetworkException;
35 import org.opentrafficsim.core.network.OTSNode;
36 import org.opentrafficsim.draw.network.LinkAnimation;
37 import org.opentrafficsim.draw.road.LaneAnimation;
38 import org.opentrafficsim.draw.road.ShoulderAnimation;
39 import org.opentrafficsim.road.network.lane.CrossSectionLink;
40 import org.opentrafficsim.road.network.lane.Lane;
41 import org.opentrafficsim.road.network.lane.NoTrafficLane;
42 import org.opentrafficsim.road.network.lane.Shoulder;
43 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
44 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
45
46 import com.vividsolutions.jts.geom.Coordinate;
47 import com.vividsolutions.jts.geom.Geometry;
48 import com.vividsolutions.jts.geom.GeometryFactory;
49 import com.vividsolutions.jts.geom.LineString;
50 import com.vividsolutions.jts.geom.Point;
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, OTSNode> 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, OTSNode> nodes = new HashMap<>();
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 OTSNode node = new OTSNode(network, nr, new OTSPoint3D(coordinate));
138 nodes.put(nr, node);
139 }
140 }
141 }
142 catch (Exception problem)
143 {
144 problem.printStackTrace();
145 }
146 finally
147 {
148 iterator.close();
149 storeNodes.dispose();
150 }
151 System.out.println("aantal knopen (353): geteld " + nodes.size());
152 return nodes;
153 }
154
155
156
157
158
159 public static boolean inspectNodeCentroid(final String number)
160 {
161 boolean isCentroid = false;
162 String[] names = removeQuotes(number).split(":");
163 String name = names[0];
164 if (name.charAt(0) == 'C')
165 {
166 isCentroid = true;
167 }
168 return isCentroid;
169 }
170
171
172
173
174
175
176
177
178
179 public static void readLinks(final Network network, final String shapeFileName, final Map<String, Link> links,
180 final Map<String, OTSNode> nodes, final OTSSimulatorInterface simulator) throws IOException
181 {
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 URL url;
200 if (new File(shapeFileName).canRead())
201 {
202 url = new File(shapeFileName).toURI().toURL();
203 }
204 else
205 {
206 url = ShapeFileReader.class.getResource(shapeFileName);
207 }
208
209 ShapefileDataStore storeLinks = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
210 SimpleFeatureSource featureSourceLinks = storeLinks.getFeatureSource();
211 SimpleFeatureCollection featureCollectionLinks = featureSourceLinks.getFeatures();
212 SimpleFeatureIterator iterator = featureCollectionLinks.features();
213
214 try
215 {
216 while (iterator.hasNext())
217 {
218 SimpleFeature feature = iterator.next();
219 GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
220 Geometry geometry = (Geometry) feature.getAttribute("the_geom");
221 Coordinate[] coords = geometry.getCoordinates();
222 LineString line = geometryFactory.createLineString(coords);
223 String nr = String.valueOf(feature.getAttribute("LINKNR"));
224 String nrBA = nr + "_BA";
225 String name = String.valueOf(feature.getAttribute("NAME"));
226
227
228 double lengthIn = Double.parseDouble(String.valueOf(feature.getAttribute("LENGTH")));
229 Length length = new Length(lengthIn, KILOMETER);
230 short direction = (short) Long.parseLong(String.valueOf(feature.getAttribute("DIRECTION")));
231 String lNodeA = String.valueOf(feature.getAttribute("ANODE"));
232 String lNodeB = String.valueOf(feature.getAttribute("BNODE"));
233
234 String linkTag = (String) feature.getAttribute("LINKTAG");
235 String wegtype = (String) feature.getAttribute("WEGTYPEAB");
236 String typeWegVak = (String) feature.getAttribute("TYPEWEGVAB");
237 String typeWeg = (String) feature.getAttribute("TYPEWEG_AB");
238 Double speedIn = Double.parseDouble(String.valueOf(feature.getAttribute("SPEEDAB")));
239 Speed speed = new Speed(speedIn, KM_PER_HOUR);
240 double capacityIn = Double.parseDouble(String.valueOf(feature.getAttribute("CAPACITYAB")));
241 Frequency capacity = new Frequency(capacityIn, PER_HOUR);
242
243
244 OTSNode nodeA = nodes.get(lNodeA);
245 OTSNode nodeB = nodes.get(lNodeB);
246
247 if (nodeA != null && nodeB != null)
248 {
249 CrossSectionLink linkAB = null;
250 CrossSectionLink linkBA = null;
251 linkAB = new CrossSectionLink(network, nr, nodeA, nodeB, LinkType.ROAD,
252 new OTSLine3D(new OTSPoint3D[] { nodeA.getPoint(), nodeB.getPoint() }), simulator,
253 LaneKeepingPolicy.KEEP_RIGHT);
254 animate(linkAB, typeWegVak, simulator);
255 linkBA = new CrossSectionLink(network, nrBA, nodeB, nodeA, LinkType.ROAD,
256 new OTSLine3D(new OTSPoint3D[] { nodeB.getPoint(), nodeA.getPoint() }), simulator,
257 LaneKeepingPolicy.KEEP_RIGHT);
258 animate(linkBA, typeWegVak, simulator);
259 if (direction == 1)
260 {
261 links.put(nr, linkAB);
262 }
263 else if (direction == 2)
264 {
265 links.put(nrBA, linkBA);
266 }
267 else if (direction == 3)
268 {
269 links.put(nr, linkAB);
270 links.put(nrBA, linkBA);
271 }
272
273 }
274 else
275 {
276 System.out.println("Node lNodeA=" + lNodeA + " or lNodeB=" + lNodeB + " not found for linknr=" + nr
277 + ", name=" + name);
278 }
279 }
280
281 }
282 catch (Exception problem)
283 {
284 problem.printStackTrace();
285 }
286 finally
287 {
288 iterator.close();
289 storeLinks.dispose();
290 }
291
292 }
293
294
295
296
297
298 public static void shapeFileInfo(final String shapeFileName) throws IOException
299 {
300 URL url;
301 if (new File(shapeFileName).canRead())
302 {
303 url = new File(shapeFileName).toURI().toURL();
304 }
305 else
306 {
307 url = ShapeFileReader.class.getResource(shapeFileName);
308 }
309 ShapefileDataStore store = (ShapefileDataStore) FileDataStoreFinder.getDataStore(url);
310
311 SimpleFeatureSource featureSource = store.getFeatureSource();
312 SimpleFeatureCollection featureCollection = featureSource.getFeatures();
313 SimpleFeatureIterator iterator = featureCollection.features();
314 try
315 {
316 while (iterator.hasNext())
317 {
318 SimpleFeature feature = iterator.next();
319 Collection<Property> areaProperties = feature.getProperties();
320 for (Property p : areaProperties)
321 {
322 System.out.println(p.getName() + " " + p.getValue().getClass() + " " + p.getValue().toString());
323 }
324 return;
325 }
326 }
327 catch (Exception problem)
328 {
329 problem.printStackTrace();
330 }
331 finally
332 {
333 iterator.close();
334 store.dispose();
335 }
336 }
337
338
339
340
341
342 public static String removeQuotes(final String name)
343 {
344 String newName = name;
345 if (newName.length() >= 2 && newName.charAt(0) == '"' && newName.charAt(newName.length() - 1) == '"')
346 {
347 newName = newName.substring(1, newName.length() - 1);
348 }
349 return newName;
350 }
351
352
353
354
355
356
357
358
359
360 private static void animate(final CrossSectionLink link, final String wegType,
361 final SimulatorInterface.TimeDoubleUnit simulator) 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 SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
424 {
425
426
427 Length m05 = new Length(0.5, METER);
428 Length m10 = new Length(1.0, METER);
429 Length m35 = new Length(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(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
442 String lr = i < 0 ? "L" : "R";
443
444 Lane laneEM = new NoTrafficLane(link, lr + "." + "EM", new Length(i * 0.75, METER), new Length(i * 0.75, METER),
445 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 = new Lane(link, "lane." + lr + "." + j, new Length(lat, METER), new Length(lat, METER), m35, m35,
452 null, speedLimit, new OvertakingConditions.LeftAndRight());
453 new LaneAnimation(lane, simulator, Color.GRAY, false);
454 lat += i * 1.75;
455 }
456
457 for (int j = 0; j < spits; j++)
458 {
459 lat += i * 1.75;
460 Lane lane = new NoTrafficLane(link, "extra." + lr + "." + j, new Length(lat, METER), new Length(lat, METER),
461 m35, m35);
462 new LaneAnimation(lane, simulator, Color.LIGHT_GRAY, false);
463 lat += i * 1.75;
464 }
465 Lane laneEO = new NoTrafficLane(link, lr + "." + "EO", new Length(lat + i * 0.25, METER),
466 new Length(lat + i * 0.25, METER), m05, m05);
467 new LaneAnimation(laneEO, simulator, Color.LIGHT_GRAY, false);
468 lat += i * 0.5;
469 Shoulder sO = new Shoulder(link, lr + "." + "sO", new Length(lat, METER), m10);
470 new ShoulderAnimation(sO, simulator, Color.GREEN);
471 }
472 }
473 catch (NamingException | RemoteException | OTSGeometryException ne)
474 {
475
476 }
477 }
478
479
480
481
482
483
484
485
486 private static void addCityStreetLanes(final int n, final boolean middenberm, final CrossSectionLink link,
487 final SimulatorInterface.TimeDoubleUnit simulator) throws NetworkException
488 {
489
490
491 Length m10 = new Length(1.0, METER);
492 Length m30 = new Length(3.0, METER);
493 Speed speedLimit = new Speed(100, KM_PER_HOUR);
494
495 try
496 {
497 if (middenberm)
498 {
499 Shoulder sM = new Shoulder(link, "sM", new Length(0.0, METER), m10);
500 new ShoulderAnimation(sM, simulator, Color.GREEN);
501 }
502 for (int i = -1; i <= 1; i += 2)
503 {
504
505 LongitudinalDirectionality dir =
506 (i < 0) ? LongitudinalDirectionality.DIR_PLUS : LongitudinalDirectionality.DIR_MINUS;
507 double lat = middenberm ? 0.5 : 0.0;
508 for (int j = 0; j < n; j++)
509 {
510 lat += i * 1.5;
511 String lr = i < 0 ? "L" : "R";
512 Lane lane = new Lane(link, "lane." + lr + "." + j, new Length(lat, METER), new Length(lat, METER), m30, m30,
513 null, speedLimit, new OvertakingConditions.LeftAndRight());
514 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
515 lat += i * 1.5;
516 }
517 }
518 }
519 catch (NamingException | RemoteException | ArrayIndexOutOfBoundsException | OTSGeometryException ne)
520 {
521 ne.printStackTrace();
522 }
523 }
524
525
526
527
528
529
530 private static void addCityStreet(final CrossSectionLink link, final SimulatorInterface.TimeDoubleUnit simulator)
531 throws NetworkException
532 {
533 Length m60 = new Length(6.0, METER);
534 Speed speedLimit = new Speed(100, KM_PER_HOUR);
535
536 try
537 {
538 Lane lane = new Lane(link, "lane", new Length(0.0, METER), new Length(0.0, METER), m60, m60, null, speedLimit,
539 new OvertakingConditions.LeftAndRight());
540 new LaneAnimation(lane, simulator, Color.DARK_GRAY, false);
541 }
542 catch (NamingException | RemoteException | OTSGeometryException ne)
543 {
544
545 }
546 }
547
548 }