Skip to content
This repository has been archived by the owner on Nov 4, 2021. It is now read-only.

Portrayals

Álvaro Carrera edited this page Jun 18, 2013 · 1 revision

#summary Chapter four of the Shanks User Manual #labels Phase-Support

= 4. Graphics =

In the previous chapter we launched the first simulation, but without much expectation, since we only could see that 'something happened' through the logs of the project. SHANKS works on top of MASON to run the simulation. Thats means that we can use the graphics engine of MASON to see wath happen in real time. In this chapter we will see how to configurate or simulation's 2D and 3D graphics.

== 4.1. Enable the GUI == In previous chapters we saw that to simulate the network was necessary to define a GUI property (Graphic User Interface) as one of the parameters of the simulation, even just to set the value "NO_GUI". These lines of code can be seen in the [http://code.google.com/p/shanks-with-mason/wiki/Simulate Textbox6: HANModelSimulation.java]

Now we want graphics, so we'll have to configure the simulation accordingly. To launch a 2d grpahics simulation it iis necesary to make the simulation extends from {{{ShanskSimulation2DGUI.java}}}. Below in [http://code.google.com/p/shanks-with-mason/wiki/Portrayals#Textbox_7:_HANModelSimulation2DGUI.java Textbox 7: HANModelSimulation2DGUI.java] it can be seen how to setup the simulation properly. There are three possible lines of code that setup the graphics engine as desired. We need to choose betwen between: no graphical interface, 2D graphic interface and 3D graphic interface.

==== Textbox 7: HANModelSimulation2DGUI.java ==== {{{ package simulation; import es.upm.dit.gsi.shanks.ShanksSimulation; […]

public class HANModelSimulation2DGUI extends ShanksSimulation2DGUI {

public HANModelSimulation2DGUI(ShanksSimulation sim) { super(sim); }

public static void main (String[] args) { try { Properties scenarioProperties = new Properties(); scenarioProperties.put(Scenario.SIMULATION_GUI, Scenario.SIMULATION_2D); // scenarioProperties.put(Scenario.SIMULATION_GUI, Scenario.SIMULATION_3D); // scenarioProperties.put(Scenario.SIMULATION_GUI, Scenario.NO_GUI);

HANModelSimulation tut = new HANModelSimulation(System.currentTimeMillis(),
               HANScenario.class, "ADSL scenario", 
               HANScenario.STATUS_SUNNY, scenarioProperties);
HANModelSimulation2DGUI gui = new HANModelSimulation2DGUI(tut);
gui.start();

} catch (Exception e) { e.printStackTrace(); } } } }}}

== 4.2. Graphics 2D == To make that the MASON graphics engine paint an element of our simulation we must perform two steps: first we have to implement a portrayal class for the element and second configurate the container in which that element belongs a reference than links the element with his portrayal.

A portrayal is an implementation of the interface {{{sim.portrayal.Portrayal}}} of MASON, it tells the graphics engine where and how to paint the element. Portrayals may be located oin any package in the project, in SHANKS we decided to locate them a level below the class they represent, so that if we return to the hierarchical package tree described in section 3.1. Creating the Project to include portrayal's packages it will ends like the one shown below in Figure 6.

http://shanks-with-mason.googlecode.com/svn/wiki/images/manuals/userManual/portrayal.package.tree.jpg

You may have noticed that the simulation can be divided into components and containers. The simulation itself is a container that contains scenarios. Each scenario represents a model of our simulation. An scenario is both an element of the simulation and a container of network elements, containing each of the network elements that define the model (devices, links and failures).

In SHANKS we have chosen a notation for the classes that implement the portrayals of each element in the form...

{{{itemName[Type]Portrayal.java}}}

Where the type is optional and refers to whether 2D or 3D graphics.

=== 4.2.1. Scenario2D === To represent the scenario it should be indicated its corresponding portrayal in the simulation. The {{{ShanskSimulation2DGUI.java}}} class is responsible for searching the portrayal implementation of the scenarios that have been configured on it, so you only need to implement the portrayals of the scenarios added to it.

The scenario portrayal implementation must extend {{{Scenario2DPortrayal.java}}}, requiring to overwrite the methods {{{setupProtrayals()}}} and {{{placeElements()}}}. The first method relate elements in the scenenario with their portrayals, the second method set the location in wich will be represented each element of the scenario based on coordinates X and Y related to the GUI.

=== 4.2.2. HANModel: Scenario2D === As mentioned in the preceding paragraph we shall first activate the GUI and then configurate it in 2D mode. This can be seen in [http://code.google.com/p/shanks-with-mason/wiki/Portrayals#Textbox_7:_HANModelSimulation2DGUI.java Textbox 7: HANModelSimulation2DGUI.java]

After setting 2DGUI simulation we have to define the scenario portrayal. So we have to create the class {{{HANScenario2DPortrayal.java}}} and make it extends from {{{Scenario2DPortrayal.java}}}, implementing the necessary methods. The final result can be found in [http://code.google.com/p/shanks-with-mason/wiki/Portrayals#Textbox_8:_HANScenario2DPortrayal.java Textbox 8: HANScenario2DPortrayal.java].

Now we will explain the code implementation briefly.

  • {{{setupProtrayals()}}}: As mentioned a few paragraphs ago, this method relates the elements belonging to the stage with their portrayals. To do this we created two specific protrayals MASON grouping the devices and links. The type of grouping the devices portrayala is continuous, since the devices are painted as filled shapes color. Portrayal type grouping of network links is, for this type of paint is prepared protrayal different types of cables.
  • {{{placeElements()}}}: In this method we may define the position of each element belonging to the scenario. We use two methods described in Scenario2DPortrayal.java:
    • {{{situateDevice(device,X,Y)}}}: This method allows to define the position of the referenced devices with respect to the axis X and Y of the GUI.
    • {{{drawLink(link)}}}: This method allows to define the limits of a link connecting it between devices. The link will be drawn from the center of the representation of one device to another. Therefore the GUI do not need coordinates, MASON perform the necessary calculations to draw.

==== Textbox 8: HANScenario2DPortrayal.java ==== {{{ package es.upm.dit.gsi.shanks.tutorial.model.han.scenario.portrayal; import es.upm.dit.gsi.shanks.model.scenario.portrayal.Scenario2DPortrayal; […]

public class HANScenario2DPortrayal extends Scenario2DPortrayal {

@Override public void placeElements() { this.situateDevice((Device)this.getScenario().getNetworkElement("PC"), 5, 20); this.situateDevice((Device)this.getScenario().getNetworkElement("Router"), 30, 30); this.situateDevice((Device)this.getScenario().getNetworkElement("Modem"), 40, 30); this.situateDevice((Device)this.getScenario().getNetworkElement("WifiAccess"), 35, 25); this.situateDevice((Device)this.getScenario().getNetworkElement("iPhone"), 15, 5); this.situateDevice((Device)this.getScenario().getNetworkElement("Android"), 25, 5);

this.drawLink((Link)this.getScenario().getNetworkElement("Ethernet PC"));
this.drawLink((Link)this.getScenario().getNetworkElement("InternalBus_MRW"));

}

@Override public void setupPortrayals() { ContinuousPortrayal2D devicePortrayal = (ContinuousPortrayal2D) this.getPortrayals(). get(Scenario2DPortrayal.MAIN_DISPLAY_ID).get(ScenarioPortrayal.DEVICES_PORTRAYAL); NetworkPortrayal2D networkPortrayal = (NetworkPortrayal2D) this.getPortrayals(). get(Scenario2DPortrayal.MAIN_DISPLAY_ID).get(ScenarioPortrayal.LINKS_PORTRAYAL);

devicePortrayal.setPortrayalForClass(Computer.class, new Computer2DPortrayal());
devicePortrayal.setPortrayalForClass(EthernetRouter.class, new EthernetRouter2DPortrayal());
devicePortrayal.setPortrayalForClass(ModemADSL.class, new ModemADSL2DPortrayal());
devicePortrayal.setPortrayalForClass(WifiAccessPoint.class, new WifiAccessPoint2DPortrayal());
devicePortrayal.setPortrayalForClass(Smartphone.class, new Smartphone2DPortrayal());
            
networkPortrayal.setPortrayalForClass(EthernetCable.class, new EthernetCable2DPortrayal());
networkPortrayal.setPortrayalForClass(InternalBus.class, new InternalBus2DPortrayal());

} } }}}

=== 4.2.3. Device2D === We have seen in the two preceding paragraphs that the scenario includes definitions of the element's portrayals that it may contain. Here is how should be the portrayals of these elements, starting with the devices.

A device portrayal implementation must extend {{{Device2Dportrayal.java}}} from SHANKS which in turn extends the class {{{SimplePortrayal2D.java}}} of MASON. This class should override the {{{draw()}}} method that will be responsible for using MASON tools to paint the device.

About many tools that MASON provides and how to use them we have not go into detail in this manual. If reader wishes to investigate how to extract the maximum benefit from the platform please refer to the manual you can get from MASON on their [http://cs.gmu.edu/~eclab/projects/mason/ official website]. Chapters 9 and 11 of MASON manual deals extensively on the graphic 2D and 3D.

=== 4.2.4. HANModel: Smartphone2D === Following the development of the network simulation in this guide, we will discuss how where Smartphone's portrayals implemented for 2D GUI. As noted in the previous section is necessary for the implementation class extends {{{Device2Dportrayal.java}}} and overwrite the {{{draw()}}} method. This implementation can be seen in [http://code.google.com/p/shanks-with-mason/wiki/Portrayals#Textbox_9:_Smartphone2DPortrayal.java Textbox 9: Smartphone2DPortrayal.java].

The {{{draw()}}} method receives as parameters the object to be painted and information from MASON graphic engine itself.

In our simulation a device will be a rectangle painted in a color that will represent the state in which the device is in. The reader must understand the implementation code without too much trouble to compare the state and drawing the rectangle. In addition to drawing the device the code includes the representation of the device ID.

==== Textbox 9: Smartphone2DPortrayal.java ====

{{{ package es.upm.dit.gsi.shanks.tutorial.model.han.element.device.portrayal; importes.upm.dit.gsi.shanks.model.element.device.portrayal.Device2DPortrayal; […]

public class Smartphone2DPortrayal extends Device2DPortrayal { @Override public void draw(Object object, Graphics2D graphics, DrawInfo2D info) { Device device = (Device) object; final double width = 5; final double height = 5; String status = device.getCurrentStatus(); if (status.equals(Smartphone.STATUS_OK)) { graphics.setColor(Color.green); } else if (status.equals(Smartphone.STATUS_OFF)) { graphics.setColor(Color.black); } else if (status.equals(Smartphone.STATUS_DISCONNECTED) || status.equals(Smartphone.STATUS_DISCHARGED)) { graphics.setColor(Color.gray); } else if (status.equals(Smartphone.STATUS_OUT_OF_RANGE)) { graphics.setColor(Color.yellow); } // Draw the devices final int x = (int) (info.draw.x - width / 2.0); final int y = (int) (info.draw.y - height / 2.0); final int w = (int) (width); final int h = (int) (height); graphics.fillRect(x, y, w, h); // Draw the devices ID graphics.setColor(Color.black); graphics.drawString(device.getID(), x - 3, y); } } }}}

=== 4.2.5. Link2D === The implementation of a link's portrayal must extend {{{Link2Dportrayal.java}}} from SHANKS which in turn extends {{{SimpleEdgePortrayal2D.java}}} from MASON. This class should override the {{{draw()}}} method that will be responsible for using MASON tools to paint the device.

=== 4.2.6. HANModel: EthernetCable2D === Until now we followed the example of wireless devices including smartphone and Router-Fi. In the case of wireless link implemented by {{{WifiConnection.java}} we have chosse not give graphical representation. The connection in fact will exists but, as in reality, there will be no a tangible representation of the element. But this only a design decision , the reader can imagine ways to represent this connection, as for example it could be a signal level bar.

Instead of the wireless connection we decided to show the example of Ethernet cable representation that connects the desktop computer with the ethernet router. As noted in the previous sections it is necessary for the implementation extends {{{Link2Dportrayal.java}}} and overwrite the {{{draw()}}} method. This implementation can be seen in [http://code.google.com/p/shanks-with-mason/wiki/Portrayals#Textbox_10:_EthernetCable2DPortrayal.java Textbox 10: EthernetCable2DPortrayal.java].

In SHANKS a link representation is homologous to that of a device. A link will be a line that connect two or more devices. The color of the line will change depending on the state of the link.

This implementation is slightly more complex than before. It has overwritten the {{{draw()}}} method but it delegates work in two different methods depending on the link that will be painted is complex or simple. We have defined a single bond is one that connects two devices from one extreme to another, a complex bond is a data bus that is capable of binding multiple devices along its path.

==== Textbox 10: EthernetCable2DPortrayal.java ==== {{{ package es.upm.dit.gsi.shanks.tutorial.model.han.element.link.protrayal; import es.upm.dit.gsi.shanks.model.element.link.portrayal.Link2DPortrayal; […] public class EthernetCable2DPortrayal extends Link2DPortrayal { @Override public void draw(Object object, Graphics2D graphics, DrawInfo2D info) { Edge e = (Edge) object; Link link = (Link) e.getInfo(); if (link.getCapacity() == 2) { this.drawSimpleLink(link, object, graphics, info); } else if (link.getCapacity() > 2) { this.drawComplexLink(link, object, graphics, info); } } private void drawComplexLink(Link link, Object object, Graphics2D graphics, DrawInfo2D info) { EdgeDrawInfo2D ei = (EdgeDrawInfo2D) info; final double width = 20; final double height = 20; String status = link.getCurrentStatus(); graphics.setColor(Color.black); if (status.equals(EthernetCable.STATUS_OK)) { graphics.setColor(Color.green); } else if (status.equals(EthernetCable.STATUS_DAMAGED)) { graphics.setColor(Color.red); } else if (status.equals(EthernetCable.STATUS_CUT)) { graphics.setColor(Color.black); } final int startX = (int) ei.draw.x; final int startY = (int) ei.draw.y; final int endX = (int) ei.secondPoint.x; final int endY = (int) ei.secondPoint.y; final int midX = (int) (ei.draw.x + ei.secondPoint.x) / 2; final int midY = (int) (ei.draw.y + ei.secondPoint.y) / 2; final int w = (int) (width); final int h = (int) (height); graphics.drawLine(startX, startY, endX, endY); graphics.fillRect(midX-(int)(width/2), midY-(int)(height/2), w, h); // Draw the devices ID ID graphics.setColor(Color.black); graphics.drawString(link.getID(), midX - 5, midY); } private void drawSimpleLink(Link link, Object object, Graphics2D graphics, DrawInfo2D info) { EdgeDrawInfo2D ei = (EdgeDrawInfo2D) info; final int startX = (int) ei.draw.x; final int startY = (int) ei.draw.y; final int endX = (int) ei.secondPoint.x; final int endY = (int) ei.secondPoint.y; final int midX = (int) (ei.draw.x + ei.secondPoint.x) / 2; final int midY = (int) (ei.draw.y + ei.secondPoint.y) / 2; String status = link.getCurrentStatus(); graphics.setColor(Color.black); if (status.equals(EthernetCable.STATUS_OK)) { graphics.setColor(Color.green); } else if (status.equals(EthernetCable.STATUS_DAMAGED)) { graphics.setColor(Color.red); } else if (status.equals(EthernetCable.STATUS_CUT)) { graphics.setColor(Color.black); } graphics.drawLine(startX, startY, endX, endY); graphics.setColor(Color.blue); graphics.setFont(labelFont); int width = graphics.getFontMetrics().stringWidth(link.getID()); graphics.drawString(link.getID(), midX - width / 2, midY); } } }}}

=== 4.2.7. Failures2D === As network elements, failures are also part of the scenario that is being simulated. But unlike most network elements failures are not tangible, so it does not have a stable representation in the GUI of the simulation.

Given that in SHANKS failures are transitions in the state of a network element, the portrayals of failures just changes the color of network elements affected by them. This is a generic behavior, so that it is not necessary that the reader implement anything. The simulation itself detects a failure and then will use the instances of the necessary portrayals to change the color of affected devices.

However, if the reader wants to make a network failure representation may otherwise implement classes that extend {{{Failure2DPortrayal.java}}} and include them on the scenario portrayal in the same way we show in previous sections. In this way the failiure will be rendered as defined by the custom portrayal and not by the generic one.

== 4.3. Graphics 3D == To provide the simulation with 3D GUI is very similar to what we saw for the 2D GUI. Keep in mind that all instances that we developed in the previous section have to change their specification to 3D GUI.

First we create a simulation {{{NameSimulation3DGUI.java}}} that extend the class {{{ShanksSimulation3DGUI.java}}} from SHANKS. In addition is necesary to implement the portrayal 3D for the scenario {{{NameScenario3DPortrayal.java}}} that extends {{{Scenario3DPortrayal.java}}} from SHANKS. This class will have to overwrite the same methods that were discussed for 2D GUI with the only exception that in some of them apears a third coordinate.

For each device and link of the scenario is necessary to implement a 3D portrayal that extends {{{Device3Dportrayal.java}}} and {{{Link2Dportrayal.java}}} respectively. The difference now is that the method will have to overwrite a {{{getModel()}}}.

The reader has access to the full code that implements HAN-Module example in wich could be the 3D GUI.

== 4.4. Run the simulation with GUI == We followed all the steps to simulate the network with a two-dimensional graphical interface. Now it's time to see what SHANKS can show us. As we did in Chapter 4 to launch the simulation we have to run simulation class, in this case the class prepare in paragraph 5.1. {{{HANModelSimulation2DGUI.java}}}. After launching it we will see in our screen something that looks like what is shown in Figure 7.

http://shanks-with-mason.googlecode.com/svn/wiki/images/manuals/userManual/displays.jpg

The MASON graphics engine opens two displays with which we can manipulate the simulation. Note that when you launch the simulation with the graphic active by default it starts in pause.

The left display its called Console. It features three intuitive buttons with which we can launch, pause or stop the simulation. The other tabs in the console are additional features of MASON with which we can manipulate and view the details of the simulation.

The right window its called Main-display. This window is where MASON graphics engine draw the simulation. Controls at the top among other things allow you to zoom in or zoom out the image and record the presented simulation in a video for later viewing.

Extensive use of the graphical interface will not be discussed here so we would again refer the reader to the MASON documentation in Chapters 9 and 11.

Clone this wiki locally