Code Monkey home page Code Monkey logo

klayjs's Introduction

Deprecated: Use elkjs

elkjs is now available and klayjs is deprecated. In other words, open bugs will be migrated to elkjs and hopefully fixed there. This repository will persist, however, no fixes or new builds are to be expected. Some words on ELK: The ELK project is the successor of the KIELER project, which formed the basis of klayjs. KIELER didn't die however, we only extracted the parts of the code related to automatic layout and put it into an official Eclipse project.

KLayJS

KLayJS is a layer-based layout algorithm that is particularly suited for node-link diagrams with an inherent direction and ports (explicit attachment points on a node's border). It is based on the ideas originally introduced by Sugiyama et al.

The algorithm is developed in Java and compiled to JavaScript using GWT. For further information see the KIELER Wiki pages.

In case you want to use the layout in conjunction with D3.js you can take a look at our KLayJS-D3 extension.

Example Layout of a Ptolemy Diagram

Installation

Either download the klay.js file or install it using npm or bower.

npm install klayjs
bower install klayjs

Usage

The library can be used in the browser, in a WebWorker, and with server-side node.js.

Input graph

We use the JSON KGraph format to specify a graph with its properties. A minimal example looks like this:

var graph = {
  "id": "root",
  "properties": {
      "direction": "RIGHT", "spacing": 40
  },
  "children": [{"id": "n1", "width": 40, "height": 40}, 
               {"id": "n2", "width": 40, "height": 40}],
  "edges": [{"id": "e1", "source": "n1", "target": "n2"}]
};

Browser

Within the browser KLayJS is registered globally with the $klay variable and can be used as follows. Note the difference between local layout options specified for specific elements in the graph and global layout options that are applied to every graph element.

<script type="text/javascript" src="klayjs.js"></script>
<script>
$klay.layout({
  graph: graph,
  options: { spacing: 20 },
  success: function(layouted) { console.log(layouted); },
  error: function(error) { console.log(error); }
});
</script>

Web Worker

Depending on the graph size the layout process can take some time possibly freezing your browser (though it should be fast in most cases). Modern browsers support web workers, some kind of threads for the browser. The following code snippet demonstrates how to start and communicate with a web worker performing layout.

var worker = new Worker('klayjs.js');
// send layout request
worker.postMessage({
  graph: [graph],
  options: [options]
});
// 
worker.addEventListener('message', function (e) {
  var graph = e.data;
  // [ applyLayout(graph) ]
}, false);

node.js

For rapid prototyping or headless diagram generation no browser is required and you might want to use node.js.

npm install klayjs
var klay = require('klayjs');
klay.layout({
  graph: [graph],
  options: [options],
  success: function(g) { console.log(g); }
});

Layout Options

A broad variety of layout options is supported. The available options and their effects are discussed here

Differences

  • Other than for the original java version of the layouter, the layoutHierarchy option is by default true.
  • If you intend to use the fixed layouter (de.cau.cs.kieler.fixed) at some point, you have to set layoutHierarchy to false.

Examples

Some examples using the KLayJS-D3 extension are available at:

See the examples folder of the klayjs-d3 project.

klayjs's People

Contributors

uruuru avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

klayjs's Issues

Time Savings with Interactive Mode

I'm using klay to render large graphs (~400 nodes) and this is taking around 7 seconds. I was wondering if there is any mechanism to take into account previous positions when adding another node as to not incur the entire cost of the layout algorithm. In example if I had a graph of 400 nodes graphed and want to add another node to the graph.

I saw the interactive mode example and this seems promising, but just wanted to see if this is possible before I get started.

fixed layout option not working

If we run layout on json data like below (assume edges have bendpoints as well)
{
id: 'root',
properties: { algorithm: 'de.cau.cs.kieler.fixed' },
children: [
{ id: '1', x: 100, y : 25},{id: '2', x: 200, y: 45},{id: '3', x: 200, y: 20}
],
edges: [
{source: '1', target: '2'}, {source: '1', target: '3'},{source: '3', target: '2'}
]
}

'algorithm' property is not considered and x, y positions for nodes get re-calculated.

Is this property supported for JavaScript version?

To elaborate more, what I am trying is to use klayjs to layout a workflow, and allow user to drag nodes to different position on the browser. At this point I wanted to avoid node position calculation, but want edge bend point calculation only.

is there any other way to achieve this?

Allow node and edge id's as integers.

Otherwise throws an error "Invalid format for 'id'. Must be a string,(...)". I guess integers are fine right.

Almost forgot to say, this repo was just what i was looking for, a minimal but highly effective elegant implementation, thanks.

Different direction within the graph

Thanks for developing this library, its potential is huge!

I've been playing around with the options, and I'm wondering if it's possible to use multiple directions within the same layout?

I.e. in the following example:
screen shot 2016-12-21 at 19 56 02

The root level direction (between Chippy.. and Namespace) would ideally be downwards, then the direction within them should be rightwards, this way it'd be evenly spaced out down/rightwards.

The same goes for the edges, i.e. is it possible to have the edge from 'dqw' to 'Method 1' route to the left, so it doesn't have to go all the way around?

Lastly, I was wondering if it's possible to have 'Deb' show up on the same row as 'Method 1' and 'dqw'?

Thanks! My options are:

  var defaultOptions = {
    edgeRouting: 'POLYLINE',
    direction: 'RIGHT',
    crossMin: 'INTERACTIVE',
    nodeLayering: 'INTERACTIVE',
    nodePlace: 'NETWORK_SIMPLEX',
    fixedAlignment: 'BALANCED',
    cycleBreaking: 'INTERACTIVE',
    thoroughness: 2500,
    spacing: 25,
    borderSpacing: 35,
    algorithm: 'de.cau.cs.kieler.klay.layered',
    feedBackEdges: false,
    layoutHierarchy: true
  };

Edges labels placement is wrong in edges between Parent Node and children nodes

The problem occurs when I have a KGraph that has edges between parent and Children Nodes as seen below (the edges labels are the blue ones):

image

The initial graph is:

{
  "id": "root",
  "children": [
    {
      "id": "bar-chart",
      "labels": [
        {
          "text": "bar-chart",
          "width": 63,
          "height": 10
        }
      ],
      "width": 130,
      "height": 70,
      "ports": [
        {
          "id": "dataColumns_bar-chart_input",
          "properties": {
            "portSide": "WEST"
          },
          "labels": [
            {
              "text": "dataColumns",
              "width": 55,
              "height": 10
            }
          ],
          "height": 10
        },
        {
          "id": "xLabels_bar-chart_input",
          "properties": {
            "portSide": "WEST"
          },
          "labels": [
            {
              "text": "xLabels",
              "width": 35,
              "height": 10
            }
          ],
          "height": 10
        }
      ],
      "properties": {
        "portConstraints": "FIXED_SIDE",
        "portLabelPlacement": "OUTSIDE",
        "nodeLabelPlacement": "V_TOP",
        "portAlignment": "CENTER",
        "portSpacing": 3,
        "borderSpacing": 40,
        "labelSpacing": 6
      },
      "children": [
        {
          "id": "chart1",
          "labels": [
            {
              "text": "base-chart",
              "width": 70,
              "height": 10
            }
          ],
          "width": 130,
          "height": 85,
          "ports": [
            {
              "id": "dataColumns_chart1_input",
              "properties": {
                "portSide": "WEST"
              },
              "labels": [
                {
                  "text": "dataColumns",
                  "width": 55,
                  "height": 10
                }
              ],
              "height": 10
            },
            {
              "id": "xLabels_chart1_input",
              "properties": {
                "portSide": "WEST"
              },
              "labels": [
                {
                  "text": "xLabels",
                  "width": 35,
                  "height": 10
                }
              ],
              "height": 10
            },
            {
              "id": "type_chart1_input",
              "properties": {
                "portSide": "WEST"
              },
              "labels": [
                {
                  "text": "type",
                  "width": 20,
                  "height": 10
                }
              ],
              "height": 10
            }
          ],
          "properties": {
            "portConstraints": "FIXED_SIDE",
            "portLabelPlacement": "INSIDE",
            "nodeLabelPlacement": "V_TOP",
            "portAlignment": "CENTER",
            "portSpacing": 3,
            "borderSpacing": 12,
            "labelSpacing": 6
          }
        }
      ]
    }
  ],
  "edges": [
    {
      "id": "con1",
      "labels": [
        {
          "text": "con1",
          "width": 20,
          "height": 10
        }
      ],
      "source": "bar-chart",
      "sourcePort": "dataColumns_bar-chart_input",
      "target": "chart1",
      "targetPort": "dataColumns_chart1_input"
    },
    {
      "id": "con2",
      "labels": [
        {
          "text": "con2",
          "width": 20,
          "height": 10
        }
      ],
      "source": "bar-chart",
      "sourcePort": "xLabels_bar-chart_input",
      "target": "chart1",
      "targetPort": "xLabels_chart1_input"
    }
  ]
}

And the initial options:

var layouter = klay.d3kgraph()
    .size([this.dataflowViewWidth, this.dataflowViewHeight])
    .transformGroup(root)
    .options({
      layoutHierarchy: true,
      intCoordinates: true,
      direction: 'RIGHT',
      edgeRouting: 'ORTHOGONAL',
      nodeLayering: 'NETWORK_SIMPLEX',
      nodePlace: 'BRANDES_KOEPF',
      crossMin: 'LAYER_SWEEP',
      algorithm: 'de.cau.cs.kieler.klay.layered'
    });

When i change the option portLabelPlacement in parent node to 'INSIDE' I got this other issue: edges labels are correctly located, but the source points of edges are wrong

image

When there are no those edges everything is correctly located:
image

Location of the Java source code

For those who wonder where to find the Java source.

On the Git repository server is the KIELER project. It contains the pragmatics subproject, where you can find the klayjs source branch. Cloning the whole repository transfers currently circa 210 MiB.

For instance KlayLayered.java โ€” a main class that contains the KLay Layered layout algorithm โ€” is at the location

plugins/de.cau.cs.kieler.klay.layered/src/de/cau/cs/kieler/klay/layered/KlayLayered.java

Effectively:

$ git clone http://git.rtsys.informatik.uni-kiel.de/scm/kieler/pragmatics.git
$ cd pragmatics/
$ git checkout origin/klayjs

'Short hierarchical edges' not imported if layoutHierarchy false

Setting layoutHierarchy to false results in short hierarchical edges not being imported by the JsonGraphImporter#643. Theoretically such edges would be supported in this mode (external port dummies would be introduced). The workaround is to set layoutHierarchy to true.

Incorrect end points with cross hierarchical edges and node padding

Hi,
I need a sub graph to have padding to ensure there will be space above it to put some other controls.
But when I set the padding to a non-zero value, the edges going into and out of that sub graph ignore it, causing a misalignment.

To see this, look at the hierarchy2 demo and add a top padding to the sub graph. You'll see that the edge placement is wrong.
Is this a bug or is there some setting I'm missing?

Thanks

collapse parent

Is there a property to collapse parent/group nodes? Or is that generally done manually to the graph, before handing to layout?

Force edge to leave and re-enter parent source node when targeting descendant node

Hello,

I am trying to find a way to prompt klay to layout an edge that originates in a parent node and targets a descendant node, such that the edge exits and re-enters the parent node.

My use case is as follows. In the Statecharts formalism, there are two varieties of transitions: internal and external. This distinction is relevant when a transition originates from a parent state and targets a substate. The difference between these two transition types, semantically, is that when a transition is taken, an external transition causes the source state to be exited and re-entered, while the internal transition does not cause the source state to be exited.

I have found that the KlayJS default layout works very well for internal transitions:

I have tried to force klay to exit the parent node by creating an invisible "pseudonode" with width and height 0, however this results in a graphical artifact, as a bend point is created which overlaps with the edge originating from the pseudonode. You can see the results below:

Input KGraph JSON:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a_a2",
            "source": "a",
            "target": "$generated-1",
            "labels": [
                {
                    "text": "t1",
                    "width": 3.109375,
                    "height": 4.5
                }
            ],
            "$type": "hyperlink"
        },
        {
            "id": "a2_b",
            "source": "a2",
            "target": "b",
            "labels": [
                {
                    "text": "t2",
                    "width": 3.109375,
                    "height": 4.5
                }
            ]
        },
        {
            "id": "b_c",
            "source": "b",
            "target": "c",
            "labels": [
                {
                    "text": "t3",
                    "width": 3.109375,
                    "height": 4.5
                }
            ]
        },
        {
            "id": "$generated-1_a2",
            "source": "$generated-1",
            "target": "a2"
        }
    ],
    "width": 11.4375,
    "height": 9.5,
    "$type": "scxml",
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 6.765625,
            "height": 9.5,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 9.5,
                    "x": 0,
                    "y": 0
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 9.5,
                    "x": 0,
                    "y": 0
                }
            ],
            "x": 0,
            "y": 0
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 9.5,
            "x": 0,
            "y": 0
        },
        {
            "id": "c",
            "labels": [
                {
                    "text": "c"
                }
            ],
            "edges": [],
            "width": 6.765625,
            "height": 9.5,
            "x": 0,
            "y": 0
        },
        {
            "id": "$generated-1",
            "$type": "pseudonode",
            "width": 0,
            "height": 0,
            "edges": [],
            "x": 0,
            "y": 0
        }
    ]
}

Kgraph after layout:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a_a2",
            "source": "a",
            "target": "$generated-1",
            "labels": [
                {
                    "text": "t1",
                    "width": 3,
                    "height": 4,
                    "x": 23,
                    "y": 56
                }
            ],
            "$type": "hyperlink",
            "sourcePoint": {
                "x": 87,
                "y": 46
            },
            "targetPoint": {
                "x": 10,
                "y": 36
            },
            "bendPoints": [
                {
                    "x": 96,
                    "y": 46
                },
                {
                    "x": 96,
                    "y": 63
                },
                {
                    "x": 16,
                    "y": 63
                },
                {
                    "x": 16,
                    "y": 36
                }
            ],
            "junctionPoints": []
        },
        {
            "id": "a2_b",
            "source": "a2",
            "target": "b",
            "labels": [
                {
                    "text": "t2",
                    "width": 3,
                    "height": 4,
                    "x": 64,
                    "y": 18
                }
            ],
            "sourcePoint": {
                "x": 37,
                "y": 26
            },
            "targetPoint": {
                "x": 77,
                "y": 26
            },
            "junctionPoints": []
        },
        {
            "id": "b_c",
            "source": "b",
            "target": "c",
            "labels": [
                {
                    "text": "t3",
                    "width": 3,
                    "height": 4,
                    "x": 133,
                    "y": 28
                }
            ],
            "sourcePoint": {
                "x": 123,
                "y": 36
            },
            "targetPoint": {
                "x": 146,
                "y": 36
            },
            "junctionPoints": []
        },
        {
            "id": "$generated-1_a2",
            "source": "$generated-1",
            "target": "a2",
            "sourcePoint": {
                "x": 10,
                "y": 36
            },
            "targetPoint": {
                "x": 68,
                "y": 36
            },
            "junctionPoints": []
        }
    ],
    "width": 163,
    "height": 74,
    "$type": "scxml",
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 47,
            "height": 46,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8,
                    "height": 9,
                    "x": 10,
                    "y": 10
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8,
                    "height": 9,
                    "x": 28,
                    "y": 21
                }
            ],
            "x": 39,
            "y": 10,
            "$H": 25
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 9,
            "x": 116,
            "y": 31
        },
        {
            "id": "c",
            "labels": [
                {
                    "text": "c"
                }
            ],
            "edges": [],
            "width": 6,
            "height": 9,
            "x": 146,
            "y": 31
        },
        {
            "id": "$generated-1",
            "$type": "pseudonode",
            "width": 0,
            "height": 0,
            "edges": [],
            "x": 10,
            "y": 36
        }
    ],
    "$H": 1
}

I was wondering if there is a better way to use the klay API to support this use case? Thank you for your guidance on this.

Help with debugging; exception after adding a node

Hello, I am getting an exception in klayjs.js and am unable to debug due to the cryptic code. I am building a graph visualization dynamically and the exception (below) occurs when I add a node to an existing graph.
I'd like to be able to see values of variables/params being passed, but unable to do so due to the cryptic/compressed JavaScript code.

I am using klay.js version 0.4.1 build 201604131004

The error reported by klayjs:

Error: {"type":"com.google.gwt.core.client.JavaScriptException","text":"(TypeError) : Cannot read property 'f' of null","stacktrace":"Unknown.x9(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.A9(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown._Q(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.aR(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.aR(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.YQ(http://localhost:63342/las/web_apps/js/klayjs/klay.js)\nUnknown.AQ(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.IP(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.layout(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.d3klay.kgraph(http://localhost:63342/web_apps/js/klayjs-d3/klayjs-d3.js)"}
    function x9 (a, b)
    {
        var c, d, e, f, g, h, i, j, k, l, m;
        switch (a.g.e)
        {
            case 1:
                d = Wv (rJ (a, (Rib (), uib)), 12);
                c = Wv (rJ (d, vib), 44);
                !c ? (c = new jJ) : Ckb (Ixb (Xv (rJ (d, Iib)))) && (c = lJ (c));
                j = Wv (rJ (a, qib), 7);
                k = MI (Bv (tv (qz, 1), Fzb, 10, 0, [j.f.i, j.i, j.a]));
                if (b <= k.a)
                {
                    return k.b
                }
                TI (c, k, c.a, c.a.a);
          *      l = Wv (rJ (a, rib), 7); // var 'l' is being returned as null
                m = MI (Bv (tv (qz, 1), Fzb, 10, 0, [l.f.i, l.i, l.a]));
                if (m.a <= b)
                {
                    return m.b
                }
                TI (c, m, c.c.b, c.c);
...

Btw, is there un-compressed code Klayjs.js code available?
Thanks!

How to compile from original source?

Very interesting project, it does not seem to be very open source however. Is it on purpose?

If not on purpose and if this project is supposed to be open source then where is the original source exactly? Do you have any makefiles/toolchain files to build KlayJS from the original Java source?

Edge label placement fails where source and target are the same node and graph contains more than one node

Please consider the following two cases.

Graph contains one node

screen shot 2016-04-13 at 3 17 13 pm

The edge label is positioned above the last path segment, which appears correct.

Graph contains two nodes

screen shot 2016-04-13 at 3 16 44 pm

The edge label is not positioned above the last path segment. It appears not toeflect the nav-open node's updated coordinate space.

Here is the associated JSON, JSON+layout information, and resulting SVG:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "nav-open_nav-open",
            "source": "nav-open",
            "target": "nav-open",
            "labels": [
                {
                    "text": "menu",
                    "width": 10,
                    "height": 5
                }
            ]
        }
    ],
    "width": 12.171875,
    "height": 10,
    "children": [
        {
            "id": "nav-closed",
            "labels": [
                {
                    "text": "nav-closed"
                }
            ],
            "edges": [],
            "width": 24.765625,
            "height": 10
        },
        {
            "id": "nav-open",
            "labels": [
                {
                    "text": "nav-open"
                }
            ],
            "edges": [],
            "width": 21.953125,
            "height": 10
        }
    ]
}
{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "nav-open_nav-open",
            "source": "nav-open",
            "target": "nav-open",
            "labels": [
                {
                    "text": "menu",
                    "width": 10,
                    "height": 5
                }
            ]
        }
    ],
    "width": 12.171875,
    "height": 10,
    "children": [
        {
            "id": "nav-closed",
            "labels": [
                {
                    "text": "nav-closed"
                }
            ],
            "edges": [],
            "width": 24.765625,
            "height": 10,
            "x": 0,
            "y": 0
        },
        {
            "id": "nav-open",
            "labels": [
                {
                    "text": "nav-open"
                }
            ],
            "edges": [],
            "width": 21.953125,
            "height": 10,
            "x": 0,
            "y": 0
        }
    ]
}
<?xml version="1.0"?>
<svg class="schviz2 ng-isolate-scope" display-model="displayModel" viewBox="0 0 90.76562428474426 77.99999976158142">
  <desc>Created with Snap</desc>
  <defs/>
  <g>
    <g class="node compound">
      <rect/>
      <g id="nav-closed" transform="matrix(1,0,0,1,40,12)" class="node leaf highlighted">
        <rect x="0" y="0" width="24.765625" height="10"/>
        <text x="2.5" y="2.5" style="dominant-baseline: text-before-edge;">nav-closed</text>
      </g>
      <g id="nav-open" transform="matrix(1,0,0,1,41.4062,42)" class="node leaf">
        <rect x="0" y="0" width="21.953125" height="10"/>
        <text x="2.5" y="2.5" style="dominant-baseline: text-before-edge;">nav-open</text>
      </g>
      <path d="M63.35937452316284 47 L78.76562428474426 47 L78.76562428474426 65.99999976158142 L12 65.99999976158142 L12 47  L41.40624952316284 47" class="link"/>
      <text x="12" y="12" dominant-baseline="text-before-edge">menu</text>
    </g>
  </g>
  <defs>
    <marker id="end" viewBox="0 -5 10 10" refX="10" refY="0" markerWidth="3" markerHeight="5" orient="auto">
      <path d="M0,-5L10,0L0,5"/>
    </marker>
  </defs>
</svg>

Thank you for looking into this.

Proper script (multi-)registration

To support browser, node, and web worker, the script has to be registered in different ways. Currently, this is done in one of the java classes.

A better idea might be to use browserify. The default configuration would thus be a node module and browserify would be a part of the grunt task. A question is how the web worker fits into the picture though.

doesn't work as npm module (with browserify)

hi,

I'm using browserify, and I just tried this:

var klay = require('klayjs');
console.log(klay);
console.log(klay.layout);

node js output:

{ layout: [Function] }
[Function]

however, in the browser I get:

Object {}
undefined

any idea why that might be?

intCoordinates results in misaligned edges originating from and targeting the same port

Please consider the following example:

Options:

{
  "algorithm": "de.cau.cs.kieler.klay.layered",
  "spacing": 10,
  "borderSpacing" : 10,
  "labelSpacing" : 0,
  "layoutHierarchy": true,
  "intCoordinates": true,
  "edgeRouting": "ORTHOGONAL"
}

KLay JSON:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a:0",
            "source": "a",
            "target": "a2",
            "labels": [],
            "sourcePort": "a_enter0",
            "targetPort": "a2_enter0",
        },
        {
            "id": "a1:0",
            "source": "a1",
            "target": "b",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 5
                }
            ]
        },
        {
            "id": "$generated_a_initial_0:0",
            "source": "$generated_a_initial_0",
            "target": "a1",
            "labels": []
        },
        {
            "id": "$generated_root_initial_0:0",
            "source": "$generated_root_initial_0",
            "target": "a",
            "labels": []
        },
        {
            "id": "a_exit0_a_enter0",
            "source": "a",
            "target": "a",
            "sourcePort": "a_exit0",
            "targetPort": "a_enter0",
            "labels": [
                {
                    "text": "t",
                    "width": 1.109375,
                    "height": 5
                }
            ],
        }
    ],
    "width": 11.4375,
    "height": 10,
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 6.765625,
            "height": 10,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "x": 0,
                    "y": 0
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "ports": [
                        {
                            "id": "a2_enter0"
                        },
                        {
                            "id": "a2_exit0"
                        }
                    ],
                    "x": 0,
                    "y": 0
                },
                {
                    "id": "$generated_a_initial_0",
                    "labels": [],
                    "edges": [],
                    "width": 4,
                    "height": 4,
                    "x": 0,
                    "y": 0
                }
            ],
            "ports": [
                {
                    "id": "a_enter0"
                },
                {
                    "id": "a_exit0"
                }
            ],
            "x": 0,
            "y": 0
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 10,
            "x": 0,
            "y": 0
        },
        {
            "id": "$generated_root_initial_0",
            "labels": [],
            "edges": [],
            "width": 4,
            "height": 4,
            "x": 0,
            "y": 0
        }
    ]
}

This yields the following layout:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "a:0",
            "source": "a",
            "target": "a2",
            "labels": [],
            "sourcePort": "a_enter0",
            "targetPort": "a2_enter0",
            "sourcePoint": {
                "x": 0,
                "y": 38
            },
            "targetPoint": {
                "x": 24,
                "y": 38
            },
            "junctionPoints": []
        },
        {
            "id": "a1:0",
            "source": "a1",
            "target": "b",
            "labels": [
                {
                    "text": "t",
                    "width": 1,
                    "height": 5,
                    "x": 59,
                    "y": 14
                }
            ],
            "sourcePoint": {
                "x": 32,
                "y": 20
            },
            "targetPoint": {
                "x": 70,
                "y": 20
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_a_initial_0:0",
            "source": "$generated_a_initial_0",
            "target": "a1",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 20
            },
            "targetPoint": {
                "x": 24,
                "y": 20
            },
            "junctionPoints": []
        },
        {
            "id": "$generated_root_initial_0:0",
            "source": "$generated_root_initial_0",
            "target": "a",
            "labels": [],
            "sourcePoint": {
                "x": 14,
                "y": 45
            },
            "targetPoint": {
                "x": 27,
                "y": 45
            },
            "junctionPoints": []
        },
        {
            "id": "a_exit0_a_enter0",
            "source": "a",
            "target": "a",
            "sourcePort": "a_exit0",
            "targetPort": "a_enter0",
            "labels": [
                {
                    "text": "t",
                    "width": 1,
                    "height": 5,
                    "x": 10,
                    "y": 10
                }
            ],
            "sourcePoint": {
                "x": 70,
                "y": 26
            },
            "targetPoint": {
                "x": 27,
                "y": 55
            },
            "bendPoints": [
                {
                    "x": 80,
                    "y": 26
                },
                {
                    "x": 80,
                    "y": 10
                },
                {
                    "x": 20,
                    "y": 10
                },
                {
                    "x": 20,
                    "y": 55
                }
            ],
            "junctionPoints": []
        }
    ],
    "width": 115,
    "height": 82,
    "children": [
        {
            "id": "a",
            "labels": [
                {
                    "text": "a"
                }
            ],
            "edges": [],
            "width": 42,
            "height": 55,
            "children": [
                {
                    "id": "a1",
                    "labels": [
                        {
                            "text": "a1"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "x": 24,
                    "y": 15
                },
                {
                    "id": "a2",
                    "labels": [
                        {
                            "text": "a2"
                        }
                    ],
                    "edges": [],
                    "width": 8.765625,
                    "height": 10,
                    "ports": [
                        {
                            "id": "a2_enter0",
                            "x": 0,
                            "y": 3,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        },
                        {
                            "id": "a2_exit0",
                            "x": 0,
                            "y": 6,
                            "width": 0,
                            "height": 0,
                            "properties": {
                                "de.cau.cs.kieler.portSide": "WEST"
                            }
                        }
                    ],
                    "x": 24,
                    "y": 35
                },
                {
                    "id": "$generated_a_initial_0",
                    "labels": [],
                    "edges": [],
                    "width": 4,
                    "height": 4,
                    "x": 10,
                    "y": 18
                }
            ],
            "ports": [
                {
                    "id": "a_enter0",
                    "x": 0,
                    "y": 38,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "WEST"
                    }
                },
                {
                    "id": "a_exit0",
                    "x": 42,
                    "y": 10,
                    "width": 0,
                    "height": 0,
                    "properties": {
                        "de.cau.cs.kieler.portSide": "EAST"
                    }
                }
            ],
            "x": 27,
            "y": 16,
        },
        {
            "id": "b",
            "labels": [
                {
                    "text": "b"
                }
            ],
            "edges": [],
            "width": 7,
            "height": 10,
            "x": 98,
            "y": 32
        },
        {
            "id": "$generated_root_initial_0",
            "labels": [],
            "edges": [],
            "width": 4,
            "height": 4,
            "x": 10,
            "y": 43
        }
    ],
}

Which when visualized as SVG yields:

screen shot 2017-05-25 at 10 29 21 pm

You can see that the y attributes of the edge targeting port a_enter0 and the edge originating from port a_enter0 are misaligned.

Specifically, in screen coordinates, the y coordinate of target point of edge a:0 is 54 (16 + 38, which is coordinates of node a, plus target point of edge a:0). The y coordinate of target point of edge a_exit0_a_enter0 is 55. Therefore there is an off-by-one error on the coordinates of the port.

I was only able to reproduce this behavior when the layout yielded edges which were crossing, so I think that this might be related.

Please let me know what you think. Thank you.

child edge positioning

In klayjs-svg, child edges are rendered as children of the translated group. This means that the edges are layered behind other groups.

child edge

{ children:
  [ { id: 'Parent1'
    , children:
      [ { id: 'Child1' }
      ]
    , edges:
      [ {source: 'Child1', target: 'Child2'}
      ]
    }
  , { id: 'Parent2'
    , children:
      [ { id: 'Child2' }
      ]
    }
  ]
, edges:
  [ {source: 'Parent1', target: 'Parent2'}
  ]
}

If I don't define the edges as child edges in the input graph, their positioning is still offset, so I'd have to walk the graph to find the edge's source node's parent's offset. This seems like a bug: edges defined on the root node should be positioned relative to the root.

root edge

{ children:
  [ { id: 'Parent1'
    , children:
      [ { id: 'Child1' }
      ]
    }
  , { id: 'Parent2'
    , children:
      [ { id: 'Child2' }
      ]
    }
  ]
, edges:
  [ {source: 'Parent1', target: 'Parent2'}
  , {source: 'Child1', target: 'Child2'}
  ]
}

Tips for improving efficiency

I'm making a patching environment for real-time graphics for mobile, and I want the graph to have the autolayout so that it's always clean and consistent. This means that every time you add a new node or edges, it should apply the layout algorithm. However, when the graph gets beyond a certain size the layouting gets slower and slower until doing it every change is unrealistic.

Are there ways of only laying out certain parts? Just the parts that have changed instead of calculating the layout of the whole graph even if most of it doesn't change.

Which of the layout options is the most efficient?

How big a graph would you expect to have calculation time of less than half a second?

Thanks!

Global layout option not applied

I feel specifying node label placement as a global option is not applied to the individual nodes. Check why.

'de.cau.cs.kieler.nodeLabelPlacement': 'OUTSIDE V_TOP H_CENTER',

Max graph width and node 'wrap'

Is there a way to specify a maximum graph width, beyond which the nodes are wrapped so that they stay inside the bounds? Kind of like word wrap in text editors.

Interpreting edge label position

Hi,

Please consider the following Klay JSON:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "off_on",
            "source": "off",
            "target": "on",
            "labels": [
                {
                    "text": "touch",
                    "width": 10.140625,
                    "height": 5
                }
            ]
        },
        {
            "id": "on_off",
            "source": "on",
            "target": "off",
            "labels": [
                {
                    "text": "touch",
                    "width": 10.140625,
                    "height": 5
                }
            ]
        }
    ],
    "width": 10,
    "height": 10,
    "children": [
        {
            "id": "off",
            "labels": [
                {
                    "text": "off"
                }
            ],
            "edges": [],
            "width": 10,
            "height": 10
        },
        {
            "id": "on",
            "labels": [
                {
                    "text": "on"
                }
            ],
            "edges": [],
            "width": 10,
            "height": 10
        }
    ]
}

When layout is applied, this yields the following kgraph:

{
    "id": "root",
    "labels": [
        {
            "text": "root"
        }
    ],
    "edges": [
        {
            "id": "off_on",
            "source": "off",
            "target": "on",
            "labels": [
                {
                    "text": "touch",
                    "width": 10.140625,
                    "height": 5,
                    "x": 37.99999952316284,
                    "y": 0
                }
            ],
            "sourcePoint": {
                "x": 88.14062404632568,
                "y": 24
            },
            "targetPoint": {
                "x": 22,
                "y": 24
            },
            "junctionPoints": []
        },
        {
            "id": "on_off",
            "source": "on",
            "target": "off",
            "labels": [
                {
                    "text": "touch",
                    "width": 10.140625,
                    "height": 5,
                    "x": 37.99999952316284,
                    "y": 16
                }
            ],
            "sourcePoint": {
                "x": 22,
                "y": 27.333333333333332
            },
            "targetPoint": {
                "x": 88.14062404632568,
                "y": 27.333333333333336
            },
            "bendPoints": [
                {
                    "x": 35.99999976158142,
                    "y": 27.333333333333332
                },
                {
                    "x": 35.99999976158142,
                    "y": 40
                },
                {
                    "x": 74.14062428474426,
                    "y": 40
                },
                {
                    "x": 74.14062428474426,
                    "y": 27.333333333333336
                }
            ],
            "junctionPoints": []
        }
    ],
    "width": 110.14062404632568,
    "height": 53,
    "children": [
        {
            "id": "off",
            "labels": [
                {
                    "text": "off"
                }
            ],
            "edges": [],
            "width": 10,
            "height": 10,
            "x": 88.14062404632568,
            "y": 20.666666666666668,
            "$H": 26
        },
        {
            "id": "on",
            "labels": [
                {
                    "text": "on"
                }
            ],
            "edges": [],
            "width": 10,
            "height": 10,
            "x": 12,
            "y": 20.666666666666664,
            "$H": 27
        }
    ],
    "$H": 1
}

I was wondering if you could guide me as to how to interpret the x and y values of the edge labels.

When both edge labels are interpreted as being in the coordinate space (sharing the offset of) node "on", then this renders beautifully:

screen shot 2016-04-12 at 12 12 14 am

However it is unclear to me how to characterize the general relationship between these edge coordinates and node "on". For example, edge "on_off" has a relationship with "on" such that "on" is the source of "on_off". But this is not true of edge "off_on" - in this case node "on" is the target.

I would appreciate any guidance you can offer on how to interpret these coordinates. Thank you.

Jaged/spiky edges with edgeRouting = SPLINES

When using the SPLINES edgeRouting option in a big graph with ports, some of the edges take spiky detours, and get a seemingly unnecessary number of bendPoints. This makes the edges appear jagged with spikes in the opposite direction:

screenshot 2015-11-13 at 6 50 38 am

If I remove the first two cubic instructions (i.e. the first 6 bendPoints) for these particular examples, the lines appear more smooth.

I've been using the plainjslinker nightly, and I follow the instructions from here to render the lines. Are these still up to date with the latest version?

bendPoints must be set for interactive layout

Setting crossMin: "INTERACTIVE" seems to require every edge to have a bendPoints element. There's no reason for this. Not setting it is just as fine as an empty array.

Error:

type: 'de.cau.cs.kieler.klay.gwt.client.layout.UnsupportedJsonGraphException',
text: 'Invalid format of an edge's \'bendPoints\' property.',

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.