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