AnyLogic
Expand
Font size

Create road network by code

If needed, you can create a road network programmatically.

Programmatically created road networks can't be modified by code during runtime.

In this article we look at the code example of the following model:

Demo model: Create Road Network by Code Open the model page in AnyLogic Cloud. There you can run the model or download it (by clicking Model source files).

We create a road network that consists of three roads forming a T-intersection, a bus stop, parking lot and stop line.

To create a road network programmatically, we type the following Java code in the On startup action of the Main agent (Agent actions properties section):

The sample code

Expand to see full Java code
// create West Road
westRoad = new Road(); 
westRoad.setOwner(this);
westRoad.setForwardLanesCount(2);
westRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape = new MarkupSegmentLine(50, 100, 0, 450, 100, 0);
westRoad.addSegment(roadShape);

// create East Road
eastRoad = new Road();
eastRoad.setOwner(this);
eastRoad.setForwardLanesCount(2);
eastRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape1 = new MarkupSegmentLine(500, 100, 0, 1000, 100, 0);
eastRoad.addSegment(roadShape1);

// create South Road
southRoad = new Road(); 
southRoad.setOwner(this);
southRoad.setForwardLanesCount(2);
southRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape3 = new MarkupSegmentLine(475, 130, 0, 475, 400, 0);
southRoad.addSegment(roadShape3);

// create an intersection
Intersection intersection = new Intersection();
intersection.setOwner(this);

// adding roads to intersection
intersection.addRoad(westRoad, PathEndType.END);
intersection.addRoad(eastRoad, PathEndType.BEGIN);
intersection.addRoad(southRoad, PathEndType.BEGIN);

// adding connections to intersection for each road
intersection.addConnection(westRoad, 0, eastRoad, 0);
intersection.addConnection(westRoad, 1, westRoad, 0);
intersection.addConnection(westRoad, 1, westRoad, 1);
intersection.addConnection(westRoad, 1, eastRoad, 1);
intersection.addConnection(westRoad, 0, southRoad, 0);

intersection.addConnection(eastRoad, 1, westRoad, 1);
intersection.addConnection(eastRoad, 0, westRoad, 0);
intersection.addConnection(eastRoad, 1, eastRoad, 0);
intersection.addConnection(eastRoad, 1, eastRoad, 1);
intersection.addConnection(eastRoad, 1, southRoad, 0);
intersection.addConnection(eastRoad, 1, southRoad, 1);

//create a stop line
StopLine stopLine = new StopLine();
stopLine.setOwner(this);
stopLine.setRoad(eastRoad);
stopLine.setOnForwardSide(false);
stopLine.setOffset(100);
stopLine.setLaneIndexFrom(0);
stopLine.setLaneIndexTo(1);
stopLine.addSpeedLimitSign(10, SpeedUnits.KPH);

// create a bus stop
busStop = new BusStop();
busStop.setOwner(this);
busStop.setOnForwardSide(true);
busStop.setRoad(eastRoad);
busStop.setOffset(200);
busStop.setLength(40, METER);

// create a parking lot
parkingLot = new ParkingLot();
parkingLot.setOwner(this);
parkingLot.setRoad(westRoad); 
parkingLot.setOnForwardSide(true);
parkingLot.setOffset(200);
parkingLot.setParkingType(PARKING_LOT_PARALLEL);
parkingLot.setParkingSpaceLength(6, METER);
parkingLot.setParkingSpaceWidth(2.5, METER);
parkingLot.setNSpaces(5);

//create a road network
roadNetwork = new RoadNetwork(this, "roadNetwork", SHAPE_DRAW_2D3D);
roadNetwork.setDrivingDirection(ROAD_RIGHT_HAND);
// ...setup other network properties here, before initialization
roadNetwork.addAll(westRoad, eastRoad, southRoad, parkingLot, busStop, intersection, stopLine);

// create a level with the network and initialize the level
Level level = new Level(this, "myLevel", SHAPE_DRAW_2D3D, 0);
level.add(roadNetwork);
level.initialize(); // cannot be changed after initialization!

//adding all road network elements to presentation
presentation.insert(0, stopLine);
presentation.insert(0, parkingLot);
presentation.insert(0, busStop);
presentation.insert(0, intersection);
level.getRoadNetworks().get(0).getRoads().forEach( r -> presentation.insert(0, r));

Code explanation

Creating roads

We start with creating three roads. Each road is created in a similar manner, so we will describe how the first one, West Road, is created.

First, we use the Road class constructor. Then we set the road to belong to Main agent (accessible here as this) - we need to do this step for each space markup shape, so you will meet this line of code for every shape we create.

Next, we set the number of forward lanes and the number of backward lanes. In our example the road will have four lanes in total.

Each road consists of segments. Our road will consist of only one segment, roadShape. It is created via the MarkupSegmentLine constructor. This constructor accepts six arguments: X, Y, Z coordinates of the start point of the segment followed by X, Y, Z coordinates of its end point. Finally, we add this segment to the West road we are creating here: westRoad.addSegment(roadShape);

// create West Road
westRoad = new Road(); 
westRoad.setOwner(this);
westRoad.setForwardLanesCount(2);
westRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape = new MarkupSegmentLine(50, 100, 0, 450, 100, 0);
westRoad.addSegment(roadShape);

If you look how two other roads are created, you will see almost the same code lines (only the coordinates passed to the MarkupSegmentLine constructor differ). All roads are drawn in the same plane, they have zero Z-coordinates. The west road is parallel to X-axis and goes from point (50, 100) to point (450, 100). The east road goes in the same direction from (500, 100) to (1000, 100). So these two roads form one line except for the gap from 450 to 500 that we intentionally leave "blank" to add intersection shape here later.

// create East Road
eastRoad = new Road();
eastRoad.setOwner(this);
eastRoad.setForwardLanesCount(2);
eastRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape1 = new MarkupSegmentLine(500, 100, 0, 1000, 100, 0);
eastRoad.addSegment(roadShape1);

// create South Road
southRoad = new Road(); 
southRoad.setOwner(this);
southRoad.setForwardLanesCount(2);
southRoad.setBackwardLanesCount(2);
MarkupSegmentLine roadShape3 = new MarkupSegmentLine(475, 130, 0, 475, 400, 0);
southRoad.addSegment(roadShape3);

Creating an intersection

The intersection is created in the similar way.

// create an intersection
Intersection intersection = new Intersection();
intersection.setOwner(this);

When you add roads to the intersection, you specify whether the start point or the end point of the road should be connected. In our case when we have created westRoad earlier, we have "drawn" it from left to right, so its end point is located at the place where we want to create the intersection, and therefore we connect the road's end point. As for the eastRoad and southRoad, their start points are located at the intersection, and so their start points are connected.

// adding roads to intersection
intersection.addRoad(westRoad, PathEndType.END);
intersection.addRoad(eastRoad, PathEndType.BEGIN);
intersection.addRoad(southRoad, PathEndType.BEGIN);

The next code snippet is probably less intuitive. Here we set up lane connections inside the intersection. You can see several calls of the intersection's addConnection() function. It connects the specified lane of one road to the specified lane of another (or the same) road. The function accepts four arguments: the road that cars take to get to the intersection, the index of this road's lane you want to connect, the road that cars take to leave the intersection, and the index of its lane.

// adding connections to intersection for each road
intersection.addConnection(westRoad, 0, eastRoad, 0);
intersection.addConnection(westRoad, 1, westRoad, 0);
intersection.addConnection(westRoad, 1, westRoad, 1);
intersection.addConnection(westRoad, 1, eastRoad, 1);
intersection.addConnection(westRoad, 0, southRoad, 0);

intersection.addConnection(eastRoad, 1, westRoad, 1);
intersection.addConnection(eastRoad, 0, westRoad, 0);
intersection.addConnection(eastRoad, 1, eastRoad, 0);
intersection.addConnection(eastRoad, 1, eastRoad, 1);
intersection.addConnection(eastRoad, 1, southRoad, 0);
intersection.addConnection(eastRoad, 1, southRoad, 1);

Let us examine a pair of code lines to understand how the connected lanes are defined. The first line of code here connects the lane of westRoad with index 0 to the lane of eastRoad with index 0.

intersection.addConnection(westRoad, 0, eastRoad, 0);
Note that enumeration in Java starts with 0, so the first lane has index 0, the second lane has index 1, etc.

In the figure below, the indexes of the connected lanes are highlighted in blue, and you can also see the dotted line on the intersection displaying the lane connection.

This function establishes a new route for cars through the intersection. So for the first specified road we consider only those lanes that cars use to get to the intersection (they are numbered as in the figure below). And for the subsequent road passed to the function, we consider only those lanes that are used by cars to leave the intersection.

The next line of code connects two lanes of the same road. In this case the second forward lane is connected to the first backward lane of this road. You can see the resulting connection shown in the figure below:

intersection.addConnection(westRoad, 1, westRoad, 0);
Note that in our example we consider right-hand traffic (we set it up in the last code snippet). For the left-hand traffic, the lanes order will differ.

Creating a stop line

Our example demonstrates how to create different types of road network elements programmatically. You may study these code snippets if you need to add such elements in your road network on model startup.

Next, we will show how to create a stop line. Here we specify the road where the stop line should be added (eastRoad). The stop line is located at a distance of 100 pixels from the beginning of the road. We place it on both road's backward lanes (the lanes with indexes from 0 to 1 are affected). This stop line will be used to restrict the speed by 10 kilometers per hour.

//create a stop line
StopLine stopLine = new StopLine();
stopLine.setOwner(this);
stopLine.setRoad(eastRoad);
stopLine.setOnForwardSide(false);
stopLine.setOffset(100);
stopLine.setLaneIndexFrom(0);
stopLine.setLaneIndexTo(1);
stopLine.addSpeedLimitSign(10, SpeedUnits.KPH);

Creating a parking lot

Next, we create a parking lot. We specify that this parking lot will be located at westRoad.

Next, we set its location there: it will be located at a distance of 200 pixels from the beginning of the road.

Then we set the type of the parking, it can be either parallel or perpendicular. We use the PARKING_LOT_PARALLEL constant to make it parallel.

Using the setParkingSpaceLength() function we set the length of the parking lot to 6 meters (the second argument accepts one of AnyLogic length unit constants). The next line defines the lot's width in the similar manner.

// create a parking lot
parkingLot = new ParkingLot();
parkingLot.setOwner(this);
parkingLot.setRoad(westRoad); 
parkingLot.setOnForwardSide(true);
parkingLot.setOffset(200);
parkingLot.setParkingType(PARKING_LOT_PARALLEL);
parkingLot.setParkingSpaceLength(6, METER);
parkingLot.setParkingSpaceWidth(2.5, METER);
parkingLot.setNSpaces(5);

Creating a road network

We now have all the elements that are needed to create our road network. In the RoadNetwork constructor, we set the network's owner (again, Main is accessed using this keyword), pass the network name, and set the road network to be visible both at 2D and 3D animation. Now we can set the important road network properties. We will only specify that we have right-hand traffic in our model, but you can also configure the network's visual appearance here, if required. Finally, we add to the road network all the space markup elements that compose it.

//create a road network
roadNetwork = new RoadNetwork(this, "roadNetwork", SHAPE_DRAW_2D3D);
roadNetwork.setDrivingDirection(ROAD_RIGHT_HAND);
// ...setup other network properties here, before initialization
roadNetwork.addAll(westRoad, eastRoad, southRoad, parkingLot, busStop, intersection, stopLine);

Creating a level

On the last step we create a level, add our road network there, and initialize the level via its initialize() function. Please note that initialization is the ultimate step, and you cannot modify the road network after it.

// create a level with the network and initialize the level
Level level = new Level(this, "myLevel", SHAPE_DRAW_2D3D, 0);
level.add(roadNetwork);
level.initialize(); // cannot be changed after initialization!

Adding road network elements to the presentation

Finally all space markup shapes should be added to presentation. Here we call the insert() method for each shape. You can simply pass 0 as the first argument value. The last Java line here shows how you can add several elements of the same type by one line of code. Here we add all three roads at once. If you want to use the same approach for other elements, substitute getRoads() function with the one you need (e.g. getParkingLots()), and use some other unused name for the local variable instead of r used here.

//adding all road network elements to presentation
presentation.insert(0, stopLine);
presentation.insert(0, parkingLot);
presentation.insert(0, busStop);
presentation.insert(0, intersection);
level.getRoadNetworks().get(0).getRoads().forEach(r -> presentation.insert(0, r));
How can we improve this article?