Skip to content

The KRendering Notation Model 2

Niklas Rentz edited this page Sep 13, 2023 · 1 revision

Parts of the information below may be outdated.

Introduction

In conjunction with KGraph the KRendering notation model defines a language for describing graphical representations of structured graph-like data. The aim of this notion model is the efficient application of automatic layout on diagrams as well as easy modifiability of the representation. Examples of such modifications are the highlighting of diagram elements or the addition and reduction of details. It is not intended for describing diagram synthesis rules but for being produced by such rules.

The available elements of a diagram are determined by a network of KGraph elements (KNodes, KEdges, and KPorts). These diagram elements themselves are just structure and say nothing regarding their appearance. To fill this gap the KRendering language provides a bunch of primitive shapes that can be composed and configured in terms of diverse styles in order to obtain the desired diagram figures. The available shapes and styles are shown in the figures above.

(dead link)

Figure 1: KRendering base classes and primitive shapes.

krenderingStyles

Figure 2: KRendering styles.

The most important matter of KRendering is the abolishment of diagram figure layouters that are part of the diagram editing tool in the existing graphical editing approaches (flowLayout, toolbarLayout, gridLayout, ...). As yet they are a crucial enabler for the proper application of automatic diagram layout. As we do not want to rely on such tool support KRendering addresses this concern by providing different micro layout strategies. By their means absolute as well as relative placement rules can be formulated. They are examined while drawing the diagram and comply with size changes of the whole diagram figure by the automatic diagram layout. These features are explained by means of some examples below.

Besides simple flat diagrams like class diagrams or UML StateMachines KGraph/KRendering supports hierarchic diagrams such as Harel's Statecharts [Harel87]. By means of a KChildArea pseudo primitive the placement area of a diagram element's children can be determined.

Examples

The following examples demonstrate the usage of the KRendering structures. We present some exemplary KRendering instances by means of a simple pseudo code representation and screen shots of the desired results.

Nodes

We start with the simple case of two or more entities that are to be represented in diagram. Each diagram specification starts with a root KNode that represents the diagram canvas. The entities to be depicted are represented by further KNodes being children of the root node. For simplicity these nodes are represented by the text labels "entity1" and "entity2". On demanding KLighD to draw the so far determined diagram it's going to push the data through our automatic layout engine KIML (preceded by some minimal node size estimation) and comes with a rendering as shown on the right (the dotted lines are added to illustrate the node bounds):

KNode {
 KNode {
  Text "entity1"
 }
 KNode {
  Text "entity2"
 }
}

figure01nodes_b

Edges

Now we want to add connections to our diagam. We achieve this by just adding KEdges to our description. In the example below we added a single edge to the node "entity1" leading to node "entity2". Since, as mentioned above, the KEdge object is just structure we augment it with the rendering primitive KPolyline. Again the dotted lines are added to illustrate the node bounds.

KNode {
 KNode {
  Text "entity1"
  KEdge "/KNode.0/KNode.1" {
    KPolyline
  }
 }

 KNode {
  Text "entity2"
 }
}

figure02edges_b

Renderings, Colors and Fonts

As easy as we can introduce diagram elements we can change their appearance by adding more custom renderings. They are composed of the primitive shapes introduced above. So, for example, we can declare figures to consist of rounded rectangles or ellipses. Furthermore, we also might want to make the styles of the figures more fancy, e.g. by attaching KStyles influencing the line width, line style, colors, and/or gradients. We extend latter example as follows.

KNode {
 KNode {
  RoundedRectangle 10.0 3.0 {
   lineStyle DASHDOT
   lineWidth 3
   foregroundColor 255 0 0
   Text "red lined box" {
    font "Lucida Handwriting"
    fontSize 20
    foregroundColor 78 78 178
   }
  }
  KEdge "/KNode.0/KNode.1" {
    KPolyline
  }
 }

 KNode {
  Ellipse {
   lineStyle DASHDOTDOT
   lineWidth 3
   backgroundColor 0 255 0
   Text "green
         ellipse" {
    font Chalkduster
    foregroundColor 255 255 0
    fontSize 20
   }
  }
 }
}

figure03renderingStyles_b

Node size

Now we want to determine the size of the diagram nodes. Since these data are crucial for the automatic layout they are defined in the structural part of the diagram element – the KNode. We do this by configuring the KShapeLayout object – each KNode contains such an object.

KNode {
 KNode {
  KShapeLayout {
   width 200
   height 100
  }
  RoundedRectangle 10.0 3.0 {
   lineStyle DASHDOT
   lineWidth 3
   foregroundColor 255 0 0
   Text "red lined box" {
    font "Lucida Handwriting"
    fontSize 20
    foregroundColor 78 78 178
   }
  }
  KEdge "/KNode.0/KNode.1" {
    KPolyline
  }
 }

 KNode {
  KShapeLayout {
   width 100
   height 200
  }
  Ellipse {
   lineStyle DASHDOTDOT
   lineWidth 3
   backgroundColor 0 255 0
   Text "green
         ellipse" {
    font Chalkduster
    foregroundColor 255 255 0
    fontSize 20
   }
  }
 }
}

figure04nodeSize_b

Placements

Now if we just add another text figure to one of the diagram elements, we can't read it. That is because both figures are placed at the same position and the default placement is just direct at the position 0. So if we want to read them both, we have to add a specific placement. That can be done through adding placement data to the figures. For example we can add a specific coordinate from were the figures starts with the top position and we also specify where it ends with the bottom position. The example then can be like the next diagram (The dotted lines are added again to explain and illustrate the nodes).

KNode {
 KNode {
   Text "outer node" {
   }
  }
 }
 --> "/KNode.0/KNode.1" {
 }
 KNode {
   Text "inner node one" {
    DirectPlacementData {
     topLeft left 5 0.0 / top 5 0.0
     bottomRight right 5 0.0 / bottom 5 0.5
    }
   }
   Text "inner node two" {
    DirectPlacementData {
     topLeft left 5 0.0 / top 5 0.5
     bottomRight right 5 0.0 / bottom 5 0.0
    }
   }
  }
 }
}

tutorial6_JD

placements
direct placement

The direct placement is the default placement. It is given with two coordinates, which span the drawing area of the element. The coordinates are the top left and the bottom right coordinate of the display area. For each coordinate the origin of the coordinate system can be selected independently with left, right and top, bottom. For example, top left right, top, meaning that the upper left coordinate is defined starting from the upper-right corner of the drawing area.

For the coordinates the direct placement uses two types, absolute and relative coordinates. With absolute coordinates, the coordinates are given directly in pixels, starting from the origin of the coordinate system. With relative coordinates, the coordinates are given relative to the size of the drawing area in factors, meaning 1.0 as 1.0 multiplied with the height or width of drawing area in pixels. The given values for absolute and relative can be negative and positive floats. Positive means in the direction from the origin to the middle of the drawing area and negative in the opposite direction. Both types absolute and relative can be combined to define a coordinate. The diagrams below show a absolute, a relative and a combined placement, with the same spacing on both sides. The origins in the diagrams are the top left and the bottom right corners.

absPlc58

relPlc20

absRelPlc

other placements

There are two more placements for elements. The grid placement and the stack placement. The stack placement arranges all elements on a stack, here covers the top element of all underlying elements. The grid-placement arranges all elements on a grid by giving it the number of columns of the grid. The rows are automatically calculated by the number of elements. In the grid-placement, there is no automatic spacing between the elements.

labels

Sometimes we might want to explain some elements in the diagram. We can do this easily by adding labels to the elements. These labels are shown next to the elements which they belong.  So for example we can add labels to our edges like we have them for our nodes. This is shown in the next example. The dotted lines again are added to explain and illustrate the nodes.

KNode {
 KNode {
  Text: first node
 }
 --> "/KNode.0/KNode.1" {
  KLabel "Connection" {
  }
 }
 KNode {
  Text: second node
 }
}

tutorial7_JD

layout

By attaching KLayoutData to elements, we can specify how these elements are handled by during the layout phase. This means, we can choose a layout algorithm for a more efficient automatic placement. For an example we add multiple connected nodes to our diagram and then we just add a KLayoutData with the layout algorithm to the diagram. Through the algorithm we need no longer look after the exact placement, just about the overall structure. The example could be like one of the next four diagrams. Although we can only use one layout algorithm for an element at the time. More layout algorithms can be found in the layout section.

KNode {
 KLayoutData {
  "de.cau.cs.kieler.algorithm" =
  "de.cau.cs.kieler.kiml.ogdf.Sugiyama"
  "de.cau.cs.kieler.algorithm" =
  "de.cau.cs.kieler.kiml.ogdf.planarization"
  "de.cau.cs.kieler.algorithm" =
  "de.cau.cs.kieler.kiml.ogdf.circular"
  "de.cau.cs.kieler.algorithm" =
  "de.cau.cs.kieler.kiml.ogdf.upwardPlanarization"
 }
 KNode {
  Text: zero
 }
 --> "/KNode.0/KNode.1" {
 }
 --> "/KNode.0/KNode.2" {
 }
 --> "/KNode.0/KNode.3" {
 }
 --> "/KNode.0/KNode.4" {
 }
 --> "/KNode.0/KNode.5" {
 }
 KNode {
  Text: one
 }
}
 --> "/KNode.1/KNode.2" {
 }
 --> "/KNode.1/KNode.3" {
 }
 --> "/KNode.1/KNode.4" {
 }
 --> "/KNode.1/KNode.5" {
 }
 KNode {
  Text: two
 }
}
 --> "/KNode.2/KNode.3" {
 }
 --> "/KNode.2/KNode.4" {
 }
 --> "/KNode.2/KNode.5" {
 }
 KNode {
  Text: three
 }
}
 --> "/KNode.3/KNode.4" {
 }
 --> "/KNode.3/KNode.5" {
 }
 KNode {
  Text: four
 }
}
 --> "/KNode.4/KNode.5" {
 }
 KNode {
  Text: five
 }
}

tutorial6_JD_Sugiyama

Sugiyama's layout algorithm, based on Gansner et al. 1993 and Sander 1996.

tutorial6_JD_planarization

A planarization-based algorithm based on Gutwenger and Mutzel '04.

tutorial6_JD_circular

Circular layout after Dogrusoz, Madden and Madden 1997.

tutorial6_JD_upwardPlanarization

Upward planarization layout by Chimani, Gutwenger, Mutzel and Wong '10.

References

[Harel87]   David Harel. Statecharts: A visual formalism for complex systems. Science of Computer Programming, 8(3):231–274, June 1987. (Source: Weizmann Institute of Science. Department of Computer Science. http://www.wisdom.weizmann.ac.il/)