skip to main content
Programmer's documentation > Using graph layout algorithms > Automatic label placement > Getting started with labeling
 
Getting started with labeling
Provides information to get started using the Label Layout framework.
*Introduction to automatic label placement
*Explains the goal and the limitations of automatic label placement.
*Getting started with Label Layout in a diagram component
*Explains how to style the label layout in a diagram component by using style sheets (CSS) to support label links of type IlvGeneralLink.
*Getting started with Label Layout in Java
*Explains how to apply the label layout by programming label layout classes in Java™.
Introduction to automatic label placement
A label placement algorithm is not a graph layout algorithm in the sense that it does not use the class IlvGraphModel and it is not a subclass of IlvGraphLayout. However, the labeling framework has many similarities to the graph layout framework.
Usually, a label is a text or decoration that should be placed close to some graphic object because the label denotes the meaning of the graphic object. The label should not be overlapped by obstacles because this would make it unreadable. If there are many potential positions for one label, the automatic label placement algorithm should find the best position for the label, so that it is close to its graphic object, not too close to unrelated objects, and not overlapped by any obstacle.
Labels occur in many application areas: diagrams, geographic maps, charts, and so on. The Labeling Layout framework can be applied to all these areas, that is, it is not restricted to placing labels in a graph. For example, if you want to label cities in a geographic map, you can use the Annealing Label Layout algorithm with appropriate point label descriptors. For simplicity, this topic shows how to place labels at links in a graph.
The label layout framework distinguishes between:
*Graphic objects called labels that must be placed
*Graphic objects called obstacles that must not move but occupy space that is not available for the labels
*Graphic objects that are ignored, that is, they are not moved nor considered as occupying space; every graphic object that is neither a label nor an obstacle is ignored
A label should not overlap any obstacle or other label. In fact, this strict condition is not feasible if there is not enough free space for the labels; in this situation the label layout algorithm tries to reduce the amount of overlaps.
In Rogue Wave  JViews, graphic objects (subclasses of IlvGraphic ) are contained in a manager ( IlvManager), and graphs are managed by graphers ( IlvGrapher, which is a subclass of IlvManager ). Because the Label Layout algorithms can be applied not only to graphs but also to any graphic objects, the algorithms work on IlvManager. Consequently, a label layout algorithm is not a subclass of IlvGraphLayout and does not use an IlvGraphModel. Rogue Wave JViews Diagrammer provides a label layout framework that is (despite many similarities) completely independent from the graph layout framework.
Rogue Wave JViews Diagrammer provides a Swing component that encapsulates a manager and the view that displays the manager. It uses a model-view architecture, that is, application objects must be provided as an SDM model, and a style sheet (CSS file) describes how the corresponding graphic objects are added to the manager and are displayed in the view.
You can use the Label Layout algorithm in the following ways:
*In a diagram component: You specify the label layout in CSS format. The diagram component loads this specification and automatically applies the label layout when necessary. The diagram component recognizes only labels of nodes and links of the types IlvGeneralNode, IlvGeneralLink, IlvSDMCompositeNode, and IlvSDMCompositeLink.
*In an application that uses Rogue Wave JViews managers: Instead of using style files, you access the API of the label layout directly. This is suitable for applications that do not need the model-view architecture. It is necessary for applications that requires the automatic placement of labels that are not part of IlvGeneralNode, IlvGeneralLink, IlvSDMCompositeNode, and IlvSDMCompositeLink.
If you have implemented your own data structures or use third-party data structures that represent labels, you can provide an adapter between your data structures and the labeling model. This complex application of the label layout package is explained in Defining your own labeling model.
Getting started with Label Layout in a diagram component
For information on how to load a style file into the diagram component and how to access the node layout, link layout, and label layout renderers, see Basic concepts.
To support labels in CSS:
1. Write a style rule specifying that links have labels.
The following CSS specification indicates that each link has one label with the text coming from the “name” property of the model links of the SDM data model:
 
link {
    class: "ilog.views.sdm.graphic.IlvGeneralLink";
    label: "@name";
}
2. Specify, for example, that each label should be placed at the left side of the corresponding link:
 
link:labelLayout {
    allowedSide: "Left";
    sideAssociation: "GLOBAL";
}
3. To enable label layout, specify the label layout renderer:
 
SMD {
    LabelLayout: "true";
}
4. Set global label layout parameters in the Label Layout section. For example, the following specification defines the minimum offsets between pairs of labels (5) and between a label and an obstacle (10):
 
LabelLayout {
    labelOffset: "5";
    obstacleOffset: "10";
}
When a style file with these CSS specifications is loaded into the diagram component, the Annealing Label layout is automatically performed. The label layout renderer always uses the Annealing Label layout, therefore it is not necessary to specify which label layout must be performed.
The complete CSS specification and a simple application that loads the specification and performs a label layout are available as a sample at: <installdir>jviews-diagrammer/codefragments/labellayout
Getting started with Label Layout in Java
To obtain a label layout, apply the Annealing Label Layout algorithm to a manager directly.
To apply the layout to a manager:
1. Create a manager object ( IlvManager) and fill it with obstacles and labels. For instance, if you want to place labels at the links of a graph, create a grapher and fill it with nodes and links (the obstacles) and additionally with the labels that should be placed at the links. In this case, the labels should be added using addObject instead of addNode because the labels should not be nodes at the same time.
Unlike with diagram component and style sheets, you are not restricted to using IlvGeneralLink, or IlvSDMCompositeLink. You can place labels at any link.
2. Create an instance of the Annealing Label Layout algorithm.
3. Declare a handle for the corresponding layout report. The layout report is an object in which the layout algorithm stores information about its behavior. For details, see The label layout report.
4. Attach the manager to the layout instance.
Here, it is assumed that the labels are subclasses of IlvLabel, IlvZoomableLabel or IlvText. If they are not, the label model can be extended as illustrated in Labels and obstacles in Java.
5. For each label, set a label descriptor.
The label descriptor describes the conditions for the placement of the label. For instance, if a label should be placed close to the source or destination node of a link, use an IlvAnnealingPolylineLabelDescriptor with the corresponding options. For details, see Label descriptors.
6. Modify the default settings for the layout parameters, if needed.
7. Call the performLayout method.
8. Read and display information from the layout report.
9. When the layout instance is no longer needed, detach the manager from the layout instance.
A complete example of these steps can be found at the location <installdir>jviews-diagrammer/codefragments/labellayout
It contains the following Java code:
 
// the JViews Graphic Framework
import ilog.views.*;
import ilog.views.graphic.*;
 
// the JViews Label Layout Framework
import ilog.views.graphlayout.labellayout.*;
 
// the JViews Annealing Label Layout
import ilog.views.graphlayout.labellayout.annealing.*;
 
// the Java AWT package
import java.awt.*;
 
// the Swing package
import javax.swing.*;
 
 
/**
 * A very simple example for the use of a Layout Algorithm.
 */
public class LayoutSample2
{
  public static final void main(String[] arg)
  {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        // Create the manager instance (subclass of IlvManager). Since we want
        // to place link labels, we use a grapher in this example.
        IlvGrapher grapher = new IlvGrapher();
 
        // Create the manager view instance
        IlvManagerView view = new IlvManagerView(grapher);
        view.setBackground(Color.white);
 
        // An Swing Frame to display
        JFrame frame = new JFrame("Label Layout Sample");
 
        // Put the manager view inside an AWT Frame and show it
        frame.getContentPane().add(view);
        frame.setSize(400, 400);
        frame.setVisible(true);
 
        // Fill the grapher with nodes and links
        IlvReliefRectangle node1 = new IlvReliefRectangle(
                                     new IlvRect(0f, 0f, 50f, 50f));
        IlvReliefRectangle node2 = new IlvReliefRectangle(
                                     new IlvRect(200f, 0f, 50f, 50f));
        IlvReliefRectangle node3 = new IlvReliefRectangle(
                                     new IlvRect(0f, 200f, 50f, 50f));
        IlvReliefRectangle node4 = new IlvReliefRectangle(
                                     new IlvRect(200f, 200f, 50f, 50f));
        grapher.addNode(node1, false);
        grapher.addNode(node2, false);
        grapher.addNode(node3, false);
        grapher.addNode(node4, false);
 
        // set some nice colors
        setNodeColors(node1, node2, node3, node4);
 
        IlvLinkImage link1 = new IlvLinkImage(node1, node2, true);
        IlvLinkImage link2 = new IlvLinkImage(node1, node3, true);
        IlvLinkImage link3 = new IlvLinkImage(node2, node4, true);
        IlvLinkImage link4 = new IlvLinkImage(node4, node3, true);
        IlvLinkImage link5 = new IlvLinkImage(node1, node4, true);
 
        grapher.addLink(link1, false);
        grapher.addLink(link2, false);
        grapher.addLink(link3, false);
        grapher.addLink(link4, false);
        grapher.addLink(link5, false);
 
        // set some nice colors
        setLinkColors(link1, link2, link3, link4, link5);
 
        // Add labels. Labels are neither "nodes" nor "links", hence add them
        // as objects. Since we perform layout later, the initial position
        // doesn’t play a role.
 
        IlvPoint p = new IlvPoint(0f,0f);
        IlvZoomableLabel label1 = new IlvZoomableLabel(p, "Label1");
        IlvZoomableLabel label2 = new IlvZoomableLabel(p, "Label2");
        IlvZoomableLabel label3 = new IlvZoomableLabel(p, "Label3");
        IlvZoomableLabel label4 = new IlvZoomableLabel(p, "Label4");
        IlvZoomableLabel label5 = new IlvZoomableLabel(p, "Start Label");
        IlvZoomableLabel label6 = new IlvZoomableLabel(p, "End Label");
 
        grapher.addObject(label1, false);
        grapher.addObject(label2, false);
        grapher.addObject(label3, false);
        grapher.addObject(label4, false);
        grapher.addObject(label5, false);
        grapher.addObject(label6, false);
 
 
        // Declare a handle for the layout instance
        IlvAnnealingLabelLayout layout = new IlvAnnealingLabelLayout();
 
        // Declare a handle for the layout report
        IlvLabelLayoutReport layoutReport = null;
 
        // Attach the manager to the layout instance
        layout.attach(grapher);
 
        // For each label, set a label descriptor that specifies: label1
           // belongs to link1, label2 belongs to link2, and so on. link5 has
        // 2 labels.
 
        layout.setLabelDescriptor(
            label1,
            new IlvAnnealingPolylineLabelDescriptor(
                label1, link1, IlvAnnealingPolylineLabelDescriptor.CENTER));
        layout.setLabelDescriptor(
            label2,
            new IlvAnnealingPolylineLabelDescriptor(
                label2, link2, IlvAnnealingPolylineLabelDescriptor.CENTER));
        layout.setLabelDescriptor(
            label3,
            new IlvAnnealingPolylineLabelDescriptor(
                label3, link3, IlvAnnealingPolylineLabelDescriptor.CENTER));
        layout.setLabelDescriptor(
            label4,
            new IlvAnnealingPolylineLabelDescriptor(
                label4, link4, IlvAnnealingPolylineLabelDescriptor.CENTER));
        layout.setLabelDescriptor(
            label5,
            new IlvAnnealingPolylineLabelDescriptor(
                label5, link5, IlvAnnealingPolylineLabelDescriptor.START));
        layout.setLabelDescriptor(
            label6,
            new IlvAnnealingPolylineLabelDescriptor(
                label6, link5, IlvAnnealingPolylineLabelDescriptor.END));
 
        // Modify the layout parameters, if needed
        layout.setLabelOffset(10);
        layout.setObstacleOffset(5);
 
        // Perform the layout and get the layout report
        layoutReport = layout.performLayout();
 
        // Print information from the layout report (optional)
        System.out.println("layout done in " +
                       layoutReport.getLayoutTime() +
                       " millisec., code = " +
                       layoutReport.getCode());
 
        // Fit the graph in the window
        view.fitTransformerToContent();
        // Redraw the grapher
        grapher.reDraw();
 
        // Detach the grapher from the layout instance
        layout.detach();
      }
    });
  }
The following figure shows the graph produced by the sample Java™ application.
Output from sample Java application

Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.