AnsweredAssumed Answered

Coordinates of Nodes in a Diagram Layout are Sometimes not correct if labes are attached to the Connections

Question asked by k0k0pelli on Jan 9, 2014
Latest reply on Jan 16, 2014 by frederikheremans1
We are using the Activiti Engine library 5.13 for executing workflows. We use the DiagramLayout for retrieving the coordinates of the currently running activities with the following code:


public List<DiagramNode> getActivityCoordinates(String wfId) {
  RuntimeService runtimeService = processEngine.getRuntimeService();
  RepositoryService repositoryService = processEngine.getRepositoryService();
  ExecutionEntity pi = (ExecutionEntty) processEngine.
                                         getRuntimeService().createProcessInstanceQuery().
                                         processInstanceId(wfId).singleResult();
  ArrayList<DiagramNode> list = new ArrayList<DiagramNode>();
 
   if (pi != null) {
       DiagramLayout processDiagramLayout = repositoryService.
              getProcessDiagramLayout(pi.getProcessDefinitionId());
       List<String> activeActivityIds = runtimeService.getActiveActivityIds(pi.getId());
       for (String activeActivityId : activeActivityIds) {
             list.add(processDiagramLayout.getNode(activeActivityId));
         }
    }
    return list;
}


The coordinates are then used for highlighting the corresponding activity nodes in the diagram image by overlaying it with a colored frame. This works so far quite well.

However, we observed that if labels are attached to the connections in a diagram, under some circumstances the coordinates of the current activities returned by the Activiti Engine are not correct. We could localize that the problem occurs because of negative x and y coordinates in the corresponding label layout information. The coordinates may be negative because they seem to be relative to the middle pair of waypoints of the corresponding line. The factory org.activiti.engine.impl.bpmn.diagram.ProcessDiagramLayoutFactory, which is responsible for composing the DiagramLayout elements, contains the following method that computes the size of the diagram:


protected DiagramNode getDiagramBoundsFromBpmnDi(Document bpmnModel) {
    Double minX = null;
    Double minY = null;
    Double maxX = null;
    Double maxY = null;
 
    // Node positions and dimensions
    NodeList setOfBounds = bpmnModel.getElementsByTagNameNS(BpmnParser.BPMN_DC_NS, "Bounds");
    for (int i = 0; i < setOfBounds.getLength(); i++) {
      Element element = (Element) setOfBounds.item(i);
      Double x = Double.valueOf(element.getAttribute("x"));
      Double y = Double.valueOf(element.getAttribute("y"));
      Double width = Double.valueOf(element.getAttribute("width"));
      Double height = Double.valueOf(element.getAttribute("height"));
 
      if (x == 0.0 && y == 0.0 && width == 0.0 && height == 0.0) {
        // Ignore empty labels like the ones produced by Yaoqiang:
        // <bpmndi:BPMNLabel><dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel>
      } else {
        if (minX == null || x < minX) {
          minX = x;
        }
        if (minY == null || y < minY) {
          minY = y;
        }
        if (maxX == null || maxX < (x + width)) {
          maxX = (x + width);
        }
        if (maxY == null || maxY < (y + height)) {
          maxY = (y + height);
        }
      }
    }

}


The code excerpt above taken from the procedure determines the bounds of the diagram by iterating over all nodes and maximizing the dimension. Unfortunately, the computation of the bounds incorporates all kind of nodes, including normal shapes which have absolute coordinates, but also label nodes which have relative coordinates. The label coordinates may also be negative. When computing the size of entire diagram layout, this leads to a phantom area in the canvas, i.e., the resulting size of the diagram is calculated too big, which leads somehow to a wrong scaling of the node coordinates and finally results in a wrong position when drawing an overlaying frame showing the current activities.

In the attachment, there is an example model and the corresponding diagram image which results in the wrong coordinates when computing them by the method getActivityCoordinates above. Activiti Designer 5.12 was used to create the diagram. Without connection labels, the position of the current activities is correctly computed.

I tested the same diagram using the Actitiviti Explorer.  It correctly rendered the diagram and the highlighted activities. This is due to the fact that Activiti Explorer does not overlay a highlighting frame but instead generates the diagram from scratch using org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator.generateDiagram(bpmnModel, im-ageType, highLightedActivities, highLightedFlows). This method allows the user of the method to specify the nodes that will be highlighted when drawing the diagram. But it does not seem to render the labels. So it’s no option for us.

For me it looks like a bug. I think the correct way to fix the problem is to calculate the absolute coordinates for the label nodes (by determining the coordinates of the middle waypoint pair). A quick and dirty fix would be to exclude label nodes from the computation or simply to ignore negative coordinates when computing the size of the diagram.

Could somebody confirm the problem or explain what's wrong? Thanks in advance.

Outcomes