1
2
3
4 package org.opentrafficsim.road.network.factory.vissim;
5
6 import java.io.File;
7 import java.util.ArrayList;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11
12 import javax.xml.bind.JAXBContext;
13 import javax.xml.bind.JAXBException;
14 import javax.xml.bind.Marshaller;
15 import javax.xml.bind.PropertyException;
16
17 import org.djunits.unit.DirectionUnit;
18 import org.djunits.unit.LengthUnit;
19 import org.djunits.unit.SpeedUnit;
20 import org.djunits.value.vdouble.scalar.Length;
21 import org.djunits.value.vdouble.scalar.Speed;
22 import org.opentrafficsim.core.geometry.OTSPoint3D;
23 import org.opentrafficsim.core.gtu.GTUType;
24 import org.opentrafficsim.core.network.NetworkException;
25 import org.opentrafficsim.road.network.factory.vissim.xsd.DEFINITIONS;
26 import org.opentrafficsim.road.network.factory.vissim.xsd.GLOBAL;
27 import org.opentrafficsim.road.network.factory.vissim.xsd.GTU;
28 import org.opentrafficsim.road.network.factory.vissim.xsd.LINK;
29 import org.opentrafficsim.road.network.factory.vissim.xsd.LINK.BEZIER;
30 import org.opentrafficsim.road.network.factory.vissim.xsd.NETWORK;
31 import org.opentrafficsim.road.network.factory.vissim.xsd.NODE;
32 import org.opentrafficsim.road.network.factory.vissim.xsd.ObjectFactory;
33 import org.opentrafficsim.road.network.factory.vissim.xsd.ROADLAYOUT;
34 import org.opentrafficsim.road.network.factory.vissim.xsd.ROADTYPE;
35 import org.opentrafficsim.road.network.lane.Lane;
36 import org.opentrafficsim.road.network.lane.object.LaneBasedObject;
37 import org.opentrafficsim.road.network.lane.object.sensor.SingleSensor;
38
39
40
41
42 public class XMLNetworkWriter
43 {
44
45 static void writeToXML(File file, Map<String, LinkTag> linkTags, Map<String, NodeTag> nodeTags, String sinkKillClassName,
46 String sensorClassName, String trafficLightName) throws NetworkException
47 {
48 try
49 {
50
51 DEFINITIONS definitions = generateDefinitions();
52
53 generateGtusAndRoadtypes(definitions);
54
55 List<NODE> nodes = new ArrayList<>();
56 generateNodes(nodes, nodeTags);
57
58 List<LINK> links = new ArrayList<>();
59 List<ROADLAYOUT> roadLayouts = new ArrayList<>();
60 generateLinks(links, roadLayouts, linkTags, sinkKillClassName, sensorClassName, trafficLightName);
61 definitions.getContent().addAll(roadLayouts);
62
63 marshall(file, definitions, nodes, links);
64
65 }
66 catch (JAXBException e)
67 {
68 e.printStackTrace();
69 }
70 }
71
72 private static DEFINITIONS generateDefinitions()
73 {
74 DEFINITIONS definitions = new DEFINITIONS();
75 generateGTUTypes(definitions);
76 GLOBAL global = new GLOBAL();
77 definitions.getContent().add(global);
78 return definitions;
79 }
80
81 private static void generateGTUTypes(DEFINITIONS definitions)
82 {
83 List<GTUTYPE> gtuTypes = new ArrayList<>();
84 GTUTYPE gtuType = new GTUTYPE();
85 gtuType.setNAME("CAR");
86 gtuTypes.add(gtuType);
87 definitions.getContent().addAll(gtuTypes);
88 }
89
90 private static void generateGtusAndRoadtypes(DEFINITIONS definitions)
91 {
92
93 List<GTU> gtus = new ArrayList<>();
94 GTU gtu = new GTU();
95 gtu.setNAME("CAR");
96 gtu.setGTUTYPE("CAR");
97 gtu.setMAXSPEED("CONST(" + new Speed(140, SpeedUnit.KM_PER_HOUR).getInUnit(SpeedUnit.KM_PER_HOUR) + ") km/h");
98 gtu.setLENGTH("CONST(" + new Length(4.5, LengthUnit.METER).getInUnit(LengthUnit.METER) + ") m");
99 gtu.setWIDTH("CONST(" + new Length(2.0, LengthUnit.METER).getInUnit(LengthUnit.METER) + ") m");
100 gtus.add(gtu);
101 definitions.getContent().addAll(gtus);
102
103
104 List<ROADTYPE> roadTypes = new ArrayList<>();
105 ROADTYPE roadType = new ROADTYPE();
106 roadType.setDEFAULTLANEKEEPING("KEEPLANE");
107 roadType.setDEFAULTOVERTAKING("NONE");
108 roadType.setDEFAULTLANEWIDTH("3.5m");
109 roadType.setNAME("RINGROAD");
110 ROADTYPE.SPEEDLIMIT speedLimit = new ROADTYPE.SPEEDLIMIT();
111 speedLimit.setGTUTYPE(gtu.getGTUTYPE());
112 speedLimit.setLEGALSPEEDLIMIT(new Speed(140, SpeedUnit.KM_PER_HOUR).getInUnit(SpeedUnit.KM_PER_HOUR) + " km/h");
113 roadType.getSPEEDLIMIT().add(speedLimit);
114 roadTypes.add(roadType);
115 definitions.getContent().addAll(roadTypes);
116
117 }
118
119 private static void marshall(File file, DEFINITIONS definitions, List<NODE> nodes, List<LINK> links)
120 throws JAXBException, PropertyException
121 {
122 JAXBContext jaxbContext = JAXBContext.newInstance("org.opentrafficsim.road.network.factory.vissim.xsd");
123 Marshaller marshaller = jaxbContext.createMarshaller();
124 ObjectFactory outputFactory = new ObjectFactory();
125 NETWORK networkElement = outputFactory.createNETWORK();
126 networkElement.getDEFINITIONSOrIncludeOrNODE().add(definitions);
127 networkElement.getDEFINITIONSOrIncludeOrNODE().addAll(nodes);
128 networkElement.getDEFINITIONSOrIncludeOrNODE().addAll(links);
129 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
130 marshaller.marshal(networkElement, System.out);
131 marshaller.marshal(networkElement, file);
132 }
133
134 private static void generateLinks(List<LINK> links, List<ROADLAYOUT> roadLayouts, Map<String, LinkTag> linkTags,
135 String sinkKillClassName, String sensorClassName, String trafficLightName) throws NetworkException
136 {
137
138 Iterator<LinkTag> iter = linkTags.values().iterator();
139 while (iter.hasNext())
140 {
141 LinkTag inputLink = iter.next();
142 LINK link = new LINK();
143
144 link.setNAME(inputLink.name);
145 String layoutName = "rl" + link.getNAME();
146 link.setROADLAYOUTAttribute(layoutName);
147
148 if (inputLink.arcTag != null)
149 {
150 LINK.ARC arc = new LINK.ARC();
151 arc.setANGLE(inputLink.arcTag.angle.getInUnit(DirectionUnit.EAST_DEGREE) + " deg");
152 arc.setRADIUS("" + inputLink.arcTag.radius.getInUnit(LengthUnit.METER));
153 arc.setDIRECTION("" + inputLink.arcTag.direction);
154 link.setARC(arc);
155 }
156
157 if (inputLink.bezierTag != null)
158 {
159 LINK.BEZIER bezier = new BEZIER();
160 link.setBEZIER(bezier);
161 }
162
163 ROADLAYOUT rla = new ROADLAYOUT();
164 rla.setROADTYPE("RINGROAD");
165 rla.setNAME(layoutName);
166
167 Iterator<Lane> lanes = inputLink.lanes.values().iterator();
168 while (lanes.hasNext())
169 {
170 ROADLAYOUT.LANE lane = new ROADLAYOUT.LANE();
171 Lane inputLane = lanes.next();
172 lane.setNAME(inputLane.getId());
173 lane.setWIDTH(inputLane.getBeginWidth().getInUnit(LengthUnit.METER) + "m");
174 lane.setOFFSET(inputLane.getDesignLineOffsetAtBegin().getInUnit(LengthUnit.METER) + "m");
175 if (inputLane.getDesignLineOffsetAtBegin().ne(inputLane.getDesignLineOffsetAtEnd()))
176 {
177 double differenceOffset = inputLane.getDesignLineOffsetAtEnd().minus(inputLane.getDesignLineOffsetAtBegin())
178 .getInUnit(LengthUnit.METER);
179 link.setOFFSETEND("" + differenceOffset + "m");
180 }
181 if (inputLink.connector)
182 {
183 lane.setCOLOR("BLACK");
184 }
185 else
186 {
187 lane.setCOLOR("GRAY");
188 }
189 lane.setDIRECTION("FORWARD");
190 ROADLAYOUT.LANE.SPEEDLIMIT speedLimit = new ROADLAYOUT.LANE.SPEEDLIMIT();
191 speedLimit.setLEGALSPEEDLIMIT(
192 inputLane.getSpeedLimit(GTUType.VEHICLE).getInUnit(SpeedUnit.KM_PER_HOUR) + " km/h");
193 speedLimit.setGTUTYPE("CAR");
194 lane.getSPEEDLIMIT().add(speedLimit);
195 rla.getLANEOrNOTRAFFICLANEOrSHOULDER().add(lane);
196 for (SingleSensor inputSensor : inputLane.getSensors())
197 {
198 LINK.SENSOR sensor = new LINK.SENSOR();
199 sensor.setNAME(inputSensor.getId());
200 sensor.setLANE(lane.getNAME());
201 sensor.setPOSITION(
202 Double.toString(inputSensor.getLongitudinalPosition().getInUnit(LengthUnit.METER)) + " m");
203 sensor.setTRIGGER(" " + inputSensor.getPositionType());
204 if (sensor.getNAME().startsWith("SINK@"))
205 {
206 sensor.setCLASS(sinkKillClassName);
207 }
208 else
209 {
210 sensor.setCLASS(sensorClassName);
211 }
212 link.getLANEOVERRIDEOrGENERATOROrLISTGENERATOR().add(sensor);
213 }
214
215 for (LaneBasedObject inputSimpleTrafficLight : inputLane.getLaneBasedObjects())
216 {
217 LINK.TRAFFICLIGHT simpleTrafficLight = new LINK.TRAFFICLIGHT();
218 simpleTrafficLight.setNAME(inputSimpleTrafficLight.getId());
219 simpleTrafficLight.setLANE(lane.getNAME());
220 simpleTrafficLight.setPOSITION(
221 Double.toString(inputSimpleTrafficLight.getLongitudinalPosition().getInUnit(LengthUnit.METER))
222 + " m");
223 simpleTrafficLight.setCLASS(trafficLightName);
224 link.getLANEOVERRIDEOrGENERATOROrLISTGENERATOR().add(simpleTrafficLight);
225 }
226 ROADLAYOUT.STRIPE stripe = new ROADLAYOUT.STRIPE();
227 stripe.setTYPE("DASHED");
228 stripe.setOFFSET(inputLane.getDesignLineOffsetAtBegin().minus(inputLane.getBeginWidth().divideBy(2.0))
229 .getInUnit(LengthUnit.METER) + "m");
230 rla.getLANEOrNOTRAFFICLANEOrSHOULDER().add(stripe);
231
232 }
233
234 roadLayouts.add(rla);
235
236 if (inputLink.straightTag != null)
237 {
238 LINK.STRAIGHT straight = new LINK.STRAIGHT();
239 if (inputLink.straightTag.length != null)
240 {
241 straight.setLENGTH(inputLink.straightTag.length.getInUnit(LengthUnit.METER) + " m");
242 }
243 link.setSTRAIGHT(straight);
244 }
245
246 if (inputLink.polyLineTag != null)
247 {
248 LINK.POLYLINE polyLine = new LINK.POLYLINE();
249 String coordString = null;
250 int length = inputLink.polyLineTag.vertices.length;
251 for (int i = 0; i < length; i++)
252 {
253 OTSPoint3D coord = inputLink.polyLineTag.vertices[i];
254 coordString = "(" + coord.x + "," + coord.y + "," + coord.z + ")";
255 polyLine.getINTERMEDIATEPOINTS().add(coordString);
256 }
257 link.setPOLYLINE(polyLine);
258 }
259
260 link.setNODESTART(inputLink.nodeStartTag.name);
261 link.setNODEEND(inputLink.nodeEndTag.name);
262 links.add(link);
263 }
264 }
265
266 private static void generateNodes(List<NODE> nodes, Map<String, NodeTag> nodeTags)
267 {
268 Iterator<NodeTag> iterNode = nodeTags.values().iterator();
269 while (iterNode.hasNext())
270 {
271 NodeTag inputNode = iterNode.next();
272 NODE node = new NODE();
273 node.setNAME(inputNode.name);
274 node.setCOORDINATE(inputNode.coordinate.toString());
275 node.setANGLE(inputNode.angle.getInUnit(DirectionUnit.EAST_DEGREE) + " deg");
276 nodes.add(node);
277 }
278 }
279
280 }