View Javadoc
1   package org.opentrafficsim.road.network.factory.shape;
2   
3   import java.awt.geom.Rectangle2D;
4   import java.io.File;
5   import java.io.IOException;
6   import java.net.URL;
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  
12  import javax.naming.NamingException;
13  import javax.swing.JPanel;
14  import javax.swing.SwingUtilities;
15  
16  import nl.tudelft.simulation.dsol.SimRuntimeException;
17  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
18  
19  import org.djunits.unit.TimeUnit;
20  import org.djunits.value.vdouble.scalar.Duration;
21  import org.djunits.value.vdouble.scalar.Time;
22  import org.geotools.data.FileDataStore;
23  import org.geotools.data.FileDataStoreFinder;
24  import org.geotools.data.simple.SimpleFeatureCollection;
25  import org.geotools.data.simple.SimpleFeatureSource;
26  import org.geotools.feature.FeatureIterator;
27  import org.opengis.feature.Feature;
28  import org.opengis.feature.Property;
29  import org.opentrafficsim.base.modelproperties.PropertyException;
30  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
31  import org.opentrafficsim.core.dsol.OTSModelInterface;
32  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
33  import org.opentrafficsim.core.geometry.OTSPoint3D;
34  import org.opentrafficsim.core.gtu.animation.GTUColorer;
35  import org.opentrafficsim.core.network.Network;
36  import org.opentrafficsim.core.network.NetworkException;
37  import org.opentrafficsim.core.network.OTSNetwork;
38  import org.opentrafficsim.core.network.OTSNode;
39  import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
40  import org.opentrafficsim.simulationengine.OTSSimulationException;
41  import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
42  
43  import com.vividsolutions.jts.geom.Coordinate;
44  import com.vividsolutions.jts.geom.Geometry;
45  import com.vividsolutions.jts.geom.LineString;
46  import com.vividsolutions.jts.geom.MultiLineString;
47  
48  public class TestShapeParser extends AbstractWrappableAnimation
49  {
50  
51      /**
52       * Main program.
53       * @param args String[]; the command line arguments (not used)
54       * @throws SimRuntimeException should never happen
55       */
56      public static void main(final String[] args) throws SimRuntimeException
57      {
58          SwingUtilities.invokeLater(new Runnable()
59          {
60              @Override
61              public void run()
62              {
63                  try
64                  {
65                      TestShapeParser xmlModel = new TestShapeParser();
66                      // 1 hour simulation run for testing
67                      xmlModel.buildAnimator(new Time(0.0, TimeUnit.SECOND), new Duration(0.0, TimeUnit.SECOND),
68                              new Duration(60.0, TimeUnit.MINUTE), new ArrayList<org.opentrafficsim.base.modelproperties.Property<?>>(), null, true);
69                  }
70                  catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
71                  {
72                      exception.printStackTrace();
73                  }
74              }
75          });
76      }
77  
78      /** {@inheritDoc} */
79      @Override
80      public final String shortName()
81      {
82          return "TestXMLModel";
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public final String description()
88      {
89          return "TestXMLModel";
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public final void stopTimersThreads()
95      {
96          super.stopTimersThreads();
97      }
98  
99      /** {@inheritDoc} */
100     @Override
101     protected final JPanel makeCharts(final SimpleSimulatorInterface simulator)
102     {
103         return null;
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     protected final OTSModelInterface makeModel(final GTUColorer colorer)
109     {
110         return new GisNDWImport();
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     protected final java.awt.geom.Rectangle2D.Double makeAnimationRectangle()
116     {
117         return new Rectangle2D.Double(-1000, -1000, 2000, 2000);
118     }
119 
120     /** {@inheritDoc} */
121     @Override
122     public final String toString()
123     {
124         return "TestGISParser []";
125     }
126 
127     /**
128      * Model to test the Esri Shape File Format parser.
129      * <p>
130      * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
131      * All rights reserved. BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim
132      * License</a>.
133      * <p>
134      * $LastChangedDate: 2016-08-26 16:34:41 +0200 (Fri, 26 Aug 2016) $, @version $Revision: 2150 $, by $Author: gtamminga $,
135      * initial version un 27, 2015 <br>
136      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
137      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
138      */
139     /**
140      * @author P070518
141      */
142     class GisNDWImport implements OTSModelInterface
143     {
144         /** */
145         private static final long serialVersionUID = 20141121L;
146 
147         /** The simulator. */
148         private OTSDEVSSimulatorInterface simulator;
149 
150         /** The network. */
151         private final Network network = new OTSNetwork("test network");
152 
153         /** {@inheritDoc} */
154         @Override
155         public final void constructModel(
156                 final SimulatorInterface<Time, Duration, OTSSimTimeDouble> pSimulator)
157                 throws SimRuntimeException
158         {
159 
160             this.simulator = (OTSDEVSSimulatorInterface) pSimulator;
161 
162             try
163             {
164                 // open the NWB basic shape file
165                 Map<String, AbstractNWBRoadElement> roadMapNWB = getRoadMapNWB("A58", "NWB_A58", "NWB_wegvakken");
166 
167                 // open the shape file with driving lane information
168                 Map<String, AbstractNWBRoadElement> laneMapNWB = getRoadMapNWB("A58", "rijstroken_A58", "NWB_rijstroken");
169 
170                 // open the shape file with specific lane information such as on and off ramps and weaving areas
171                 Map<String, AbstractNWBRoadElement> specialLaneMapNWB =
172                         getRoadMapNWB("A58", "mengstroken_A58", "NWB_mengstroken");
173 
174                 combineNWBMaps(roadMapNWB, laneMapNWB, specialLaneMapNWB);
175             }
176             catch (NetworkException nwe)
177             {
178                 nwe.printStackTrace();
179             }
180 
181         }
182 
183         /**
184          * Combine the data (split road elements and add lane-attributes).
185          * @param roadMapNWB
186          * @param laneMapNWB
187          * @param specialLaneMapNWB
188          */
189         private void combineNWBMaps(Map<String, AbstractNWBRoadElement> roadMapNWB,
190                 Map<String, AbstractNWBRoadElement> laneMapNWB, Map<String, AbstractNWBRoadElement> specialLaneMapNWB)
191         {
192             // TODO : Alexander, de combinemaps moet verder worden uitgewerkt!
193             // Here, a segment of the NWB wegvak is being extracted (for instance the first part of the wegvak has an on-ramp)
194             // We should thus split this NWB-wegvak in two parts, the first part with the on-ramp (additional lane) and the
195             // remainder with the original attributes
196             for (AbstractNWBRoadElement laneElement : laneMapNWB.values())
197             {
198                 NWBDrivingLane lane = (NWBDrivingLane) laneElement;
199                 NWBRoadElement road = (NWBRoadElement) roadMapNWB.get(lane.getRoadId());
200                 List<LineString> lineSegmentList = splitRoad(road, lane);
201             }
202         }
203 
204         /**
205          * Split a road if there is a lane along a PART of this road.
206          * @param road
207          * @param segment
208          * @return list of linestrings
209          */
210         private List<LineString> splitRoad(NWBRoadElement road, NWBDrivingLane segment)
211         {
212             MultiLineString lines = (MultiLineString) road.getMyGeom();
213             LineString line = (LineString) lines.getGeometryN(0);
214             List<LineString> lineSegmentList = new ArrayList<>();
215             ;
216             // The getSubstring is copied from The JCS Conflation Suite (JCS): I assume it is not supported anymore, but can
217             // still be found...
218             lineSegmentList.add(SubstringLine.getSubstring(line, segment.getBeginDistance(), segment.getEndDistance()));
219             if (segment.getBeginDistance() > 0)
220             {
221                 lineSegmentList.add(SubstringLine.getSubstring(line, 0, segment.getBeginDistance()));
222             }
223             if (segment.getEndDistance() < road.getEndDistance())
224             {
225                 lineSegmentList.add(SubstringLine.getSubstring(line, 0, segment.getBeginDistance()));
226             }
227             return lineSegmentList;
228         }
229 
230         /**
231          * Import a list of road (link) elements from a shape file
232          * @param initialDir
233          * @param fileName
234          * @param shapeIdentifier
235          * @return map of naames road elements
236          * @throws NetworkException
237          */
238         private Map<String, AbstractNWBRoadElement> getRoadMapNWB(String initialDir, String fileName, String shapeIdentifier)
239                 throws NetworkException
240         {
241             FileDataStore dataStoreLink = null;
242             try
243             {
244                 dataStoreLink = newDatastore(initialDir, fileName);
245             }
246             catch (IOException e)
247             {
248                 // TODO Auto-generated catch block
249                 e.printStackTrace();
250             }
251             // open and read shape file links
252             FeatureIterator feautureIterator = getFeatureIterator(dataStoreLink);
253             // loop through the features and first retrieve the geometry
254             Map<String, AbstractNWBRoadElement> roadMApNWB = getFeatureAttributes(feautureIterator, shapeIdentifier);
255             return roadMApNWB;
256 
257         }
258 
259         /**
260          * @param initialDir
261          * @param fileName
262          * @return shapefile datastore
263          * @throws IOException
264          */
265         private FileDataStore newDatastore(String initialDir, final String fileName) throws IOException
266         {
267             try
268             {
269                 URL url = TestShapeParser.class.getResource("/");
270                 File file = new File(url.getFile() + "../../Data/" + initialDir);
271                 String fn = file.getCanonicalPath();
272                 fn = fn.replace('\\', '/');
273                 File iniDir = new File(fn);
274                 file = new File(iniDir, fileName + ".shp");
275 
276                 FileDataStore dataStoreLink = FileDataStoreFinder.getDataStore(file);
277                 return dataStoreLink;
278 
279             }
280             catch (IOException exception)
281             {
282                 exception.printStackTrace();
283             }
284             return null;
285 
286         }
287 
288         /**
289          * @param dataStore
290          * @return iterator
291          */
292         private FeatureIterator getFeatureIterator(FileDataStore dataStore)
293         {
294             try
295             {
296                 String[] typeNameLink = dataStore.getTypeNames();
297                 SimpleFeatureSource sourceLink;
298                 sourceLink = dataStore.getFeatureSource(typeNameLink[0]);
299                 SimpleFeatureCollection featuresLink = sourceLink.getFeatures();
300                 return featuresLink.features();
301 
302             }
303             catch (IOException e)
304             {
305                 // TODO Auto-generated catch block
306                 e.printStackTrace();
307             }
308             return null;
309         }
310 
311         /**
312          * @param feautureIterator
313          * @param shapeIdentifier
314          * @return feature attributes
315          * @throws NetworkException
316          */
317         private Map<String, AbstractNWBRoadElement> getFeatureAttributes(final FeatureIterator feautureIterator,
318                 String shapeIdentifier) throws NetworkException
319         {
320             Map<String, AbstractNWBRoadElement> roadMap = new HashMap<>();
321             while (feautureIterator.hasNext())
322             {
323                 Feature feature = feautureIterator.next();
324                 // geometry is always first
325                 if (shapeIdentifier.equals("NWB_wegvakken"))
326                 {
327                     NWBRoadElement road = getPropertiesNWB(feature);
328                     roadMap.put(road.getRoadId(), road);
329                 }
330                 else if (shapeIdentifier.equals("NWB_rijstroken"))
331                 {
332                     NWBDrivingLane road = getPropertiesDrivingLanes(feature);
333                     roadMap.put(road.getRoadId(), road);
334                 }
335                 else if (shapeIdentifier.equals("NWB_mengstroken"))
336                 {
337                     NWBDrivingLane road = getPropertiesSpecialLanes(feature);
338                     roadMap.put(road.getRoadId(), road);
339                 }
340             }
341             return roadMap;
342         }
343 
344         /**
345          * @param feature
346          * @return one road element with properties
347          * @throws NetworkException
348          */
349         private NWBRoadElement getPropertiesNWB(final Feature feature) throws NetworkException
350         {
351             Geometry theGeom = (Geometry) feature.getDefaultGeometryProperty().getValue();
352             Coordinate[] coordinates = theGeom.getCoordinates();
353             Property property = feature.getProperty("WVK_ID");
354             String roadId = property.getValue().toString();
355             property = feature.getProperty("JTE_ID_BEG");
356             String junctionIdBegin = property.getValue().toString();
357             property = feature.getProperty("JTE_ID_END");
358             String junctionIdEnd = property.getValue().toString();
359             property = feature.getProperty("ADMRICHTNG");
360             String adminDirection = property.getValue().toString();
361             property = feature.getProperty("RIJRICHTNG");
362             String drivingDirection = property.getValue().toString();
363             property = feature.getProperty("BEGINKM");
364             Double beginKM = parseDouble(property);
365             property = feature.getProperty("EINDKM");
366             Double endKM = parseDouble(property);
367             property = feature.getProperty("BEGAFSTAND");
368             Double beginDistance = parseDouble(property);
369             property = feature.getProperty("ENDAFSTAND");
370             Double endDistance = parseDouble(property);
371 
372             OTSNode startNode = new OTSNode(this.network, junctionIdBegin, new OTSPoint3D(coordinates[0]));
373             OTSNode endNode = new OTSNode(this.network, junctionIdEnd, new OTSPoint3D(coordinates[coordinates.length - 1]));
374             return new NWBRoadElement(theGeom, startNode, endNode, roadId, beginDistance, endDistance, junctionIdBegin,
375                     junctionIdEnd, adminDirection, drivingDirection, beginKM, endKM);
376         }
377 
378         /**
379          * @param feature
380          * @return info on one driving lane
381          * @throws NetworkException 
382          */
383         private NWBDrivingLane getPropertiesDrivingLanes(final Feature feature) throws NetworkException
384         {
385             Geometry theGeom = (Geometry) feature.getDefaultGeometryProperty().getValue();
386             Coordinate[] coordinates = theGeom.getCoordinates();
387 
388             Property property = feature.getProperty("WVK_ID");
389             String roadId = property.getValue().toString();
390 
391             property = feature.getProperty("KANTCODE");
392             String sideCode = property.getValue().toString();
393 
394             property = feature.getProperty("BEGAFSTAND");
395             Double beginDistance = parseDouble(property);
396 
397             property = feature.getProperty("ENDAFSTAND");
398             Double endDistance = parseDouble(property);
399 
400             property = feature.getProperty("OMSCHR");
401             String laneDescription = property.getValue().toString();
402             String[] lanes = laneDescription.split("->");
403             Integer startNumberOfLanes = Integer.parseInt(lanes[0].trim());
404             Integer endNumberOfLanes = Integer.parseInt(lanes[1].trim());
405 
406             String junctionIdBegin = roadId + "_" + beginDistance;
407             String junctionIdEnd = roadId + "_" + endDistance;
408             OTSNode startNode = new OTSNode(this.network, junctionIdBegin, new OTSPoint3D(coordinates[0]));
409             OTSNode endNode = new OTSNode(this.network, junctionIdEnd, new OTSPoint3D(coordinates[coordinates.length - 1]));
410             return new NWBDrivingLane(theGeom, startNode, endNode, roadId, beginDistance, endDistance, startNumberOfLanes,
411                     endNumberOfLanes, sideCode);
412         }
413 
414         /**
415          * @param feature
416          * @return info on one special lane
417          * @throws NetworkException 
418          */
419         private NWBDrivingLane getPropertiesSpecialLanes(final Feature feature) throws NetworkException
420         {
421             Geometry theGeom = (Geometry) feature.getDefaultGeometryProperty().getValue();
422             Coordinate[] coordinates = theGeom.getCoordinates();
423 
424             Property property = feature.getProperty("WVK_ID");
425             String roadId = property.getValue().toString();
426 
427             property = feature.getProperty("KANTCODE");
428             String sideCode = property.getValue().toString();
429 
430             property = feature.getProperty("BEGAFSTAND");
431             Double beginDistance = parseDouble(property);
432 
433             property = feature.getProperty("ENDAFSTAND");
434             Double endDistance = parseDouble(property);
435 
436             property = feature.getProperty("OMSCHR");
437             String laneType = property.getValue().toString();
438 
439             property = feature.getProperty("AANT_MSK");
440             String laneDescription = property.getValue().toString();
441             String[] lanes = laneDescription.split("->");
442             Integer startNumberOfLanes = Integer.parseInt(lanes[0].trim().substring(0, 1));
443             Integer endNumberOfLanes = Integer.parseInt(lanes[1].trim().substring(0, 1));
444 
445             String junctionIdBegin = roadId + "_" + beginDistance;
446             String junctionIdEnd = roadId + "_" + endDistance;
447             OTSNode startNode = new OTSNode(this.network, junctionIdBegin, new OTSPoint3D(coordinates[0]));
448             OTSNode endNode = new OTSNode(this.network, junctionIdEnd, new OTSPoint3D(coordinates[coordinates.length - 1]));
449             return new NWBDrivingLane(theGeom, startNode, endNode, roadId, beginDistance, endDistance, startNumberOfLanes,
450                     endNumberOfLanes, sideCode);
451         }
452 
453         /**
454          * @param property
455          * @return a double
456          */
457         private Double parseDouble(Property property)
458         {
459             if (property.getValue() != null)
460             {
461                 if (property.getValue().toString() != null)
462                 {
463                     return Double.parseDouble(property.getValue().toString());
464                 }
465             }
466             return Double.NaN;
467         }
468 
469         /** {@inheritDoc} */
470         @Override
471         public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
472 
473         {
474             return this.simulator;
475         }
476 
477         /** {@inheritDoc} */
478         @Override
479         public final String toString()
480         {
481             return "TestXMLModel [simulator=" + this.simulator + "]";
482         }
483 
484     }
485 
486 }