Script Example: Attributes and Styles¶
This example demonstrates how to plot information in the 2D view where the information is not immediately available and linked to the objects that will be used to display it.
The Aimsun Next drawing system is based on Modes (GKViewMode) and Styles (GKViewStyle) which will plot objects on a 2D view rendering them according to attributes of the object. For example a road section might be drawn in different colors depending on the traffic flow on it.
If however the task is to draw the road sections in different colors based on the public lines that use them, then the information about section usage is in the public line (GKPublicLine, inherited from GKRoute), not in the section and hence not available to be rendered in a view style. The solution is to put this information in the section using a script, then create a style to change the color based on this data.
Object Attributes¶
All Aimsun objects have attributes to hold data. The attribute (column, in Aimsun Next terms) is defined at class level (type, in Aimsun Next terms), while the data content is assigned to the attribute at instance level (object, in Aimsun Next terms). In effect, each type has a set of columns defined for it which allow an object of that type to store its data.
Aimsun Next has two methods to get and set data in any object:
GKObject::getDataValue
GKObject::setDataValue
Aimsun Next also has methods to discover the data type and the available columns:
GKModel::getType
GKModel::getColumn
GKType::GetColumn -to get columns for a particular type.
It can also create new columns using the add column method:
GKType::addColumn
Therefore, the tasks required to implement our new script are:
- Add a new column to hold the identifier of the public line.
- Fill the attribute in each section with the correct value.
The first task is completed with the following code:
type = model.getType( "GKSection" )
attr = type.addColumn( "GKSection::ptline", "PT Line", GKColumn.Int )
The first line gets the type to which we want to add the column. The second line, adds the new column. This column has:
- An internal, unique, name: GKSection::ptline.
- An external name that will be presented to the user: "PT Line".
- The type of the data we will store into, in this case an integer number: GKColumn.Int.
Multiple new columns can be created with different data types. For further details, see GKType and GKColumn classes in the HTML documentation.
The attributes are added with the following code:
ptType = model.getType( "GKPublicLine" )
for types in model.getCatalog().getUsedSubTypesFromType( ptType ):
for ptline in types.values():
for section in ptline.getRoute():
section.setDataValue(attr, QVariant(ptline.getId()))
The outer loop is for all the public lines in the model, the inner loop is for each section in the current line. Note however that the current implementation will only keep the identifier of the last line processed for sections used by more than one public line. This can be resolved in several ways depending on the remit for the script, but here, for simplicity, just the last value is used.
Modes and Styles¶
The next stage is add a new mode and a new style to change the color of the section. This can be done using the GUI or with some extra work in the script.
The code to create the mode and the style must check that it does not create modes that already exist. As the same script will be used for classifying the sections and to set the right mode and style, running it twice could create two different modes and styles. Therefore, before creating a mode, the script first checks it does not already exist.
Because the script will become quite long, in order to improve readability and to reduce errors it’s good practice to break it down in smaller functions that perform simple operations. Therefore we will write:
- a function that creates a new view style based on an attribute.
- a function that automatically creates the appropriate color ranges for the new view style, used by the above function.
- a function that creates a new view mode that uses the view style created with the above functions.
- a function that activates the new view mode.
The following function creates the new view style (if it doesn’t already exist) and initialises it. It also removes any previous ranges, as the number of routes can have changed from the last execution, and calls a function we will code later to automatically create the new ranges:
def createStyle( model, type, attr ):
style = model.getGeoModel().findStyle("GKSection::ptline style")
if style == None:
style = GKSystem.getSystem().newObject("GKViewModeStyle",model)
style.setInternalName( "GKSection::ptline style" )
style.setName( "PTLines Style" )
model.getGeoModel().addStyle( style )
if style != None:
style.setStyleType( GKViewModeStyle.eColor )
style.setVariableType( GKViewModeStyle.eDiscrete )
style.setColumn( type, attr )
style.removeAllRanges()
createRanges( model, style )
return style
The following function creates one range for each public line. Then it assigns a different color to each range and sets its name equal to the name of the public line:
def createRanges( model, style ):
ramp = GKColorRamp.getRamp( "MARK_COLORS" );
i = 0
ptType = model.getType( "GKPublicLine" )
for types in model.getCatalog().getUsedSubTypesFromType(ptType):
for ptline in types.values():
range = style.addRange( ptline.getId() )
if range != None :
range.label = ptline.getName()
range.color = ramp.getColor( i, len(types) )
i = i + 1
The following function creates the new view mode (if it doesn’t already exist) and sets it up. It calls the first function to create the style:
def createMode( model, type, attr ):
mode = model.getGeoModel().findMode( "GKSection::ptline mode" )
if mode == None :
mode = GKSystem.getSystem().newObject( "GKViewMode", model)
mode.setInternalName( "GKSection::ptline mode" )
mode.setName( "PTLines Mode" )
model.getGeoModel().addMode( mode )
if mode != None:
mode.removeAllStyles()
style = createStyle( model, type, attr )
mode.addStyle( style )
return mode
The last function to write is the one that activates the mode:
def setMode( mode ):
gui = GKGUISystem.getGUISystem().getActiveGui()
if gui != None:
activeWindow = gui.getActiveViewWindow()
if activeWindow != None:
activeWindow.setMode( mode )
To call all these functions, add the following line at the end of the script:
setMode( createMode( model, type, attr ) )