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