# Read flows.json , and position the nodes in most efficient/readable way!

**URL:** https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158
**Category:** General
**Created:** [3 May 2023 21:49 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158 "2023-05-03T21:49:32Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [3 May 2023 21:49 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/1 "2023-05-03T21:49:33Z")

</div>

Hello everyone!  
First i want to thanks @BartButenaers for bringing me in javascript development several years ago 🤗

Working on a javascript project that will generate a flows.json file from a config file.... Don't ask me why 😁  
Managed to append subflows files, create nodes, connect them, put them in one flow, all of that based on one file.  
Now i can load up the flow, but all of the elements are with x,y coordinates of 100 🤣  
But they are connected as i want (defined the nodes, and connections in the original config file).

Now the part where i ran out of ideas is... How can i position nodes in the most efficient (readable way).  
Essentially the desired input itself is a flow.json file, searched npm packages but could not find anything useful 😕

The only idea i had in mind is to filter out the flows.json to have a variable that will essentially look something like this:

> {  
> injectnodeId:{ changenodeId : { debugnodeId}}  
> }

And from here create a function that will assign x,y for each of the node.  
But again this will break if we would have multiple flows...

Any ideas, and advices are welcome!

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [4 May 2023 11:14 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/2 "2023-05-04T11:14:43Z")

</div>

> [@lizzardguki](#):
>
> How can i position nodes in the most efficient (readable way)

Well, that is a whole entire area of Math in its own right. It is an incredibly complex task. Have fun doing the research on the math principles of graph theory. 😁

> [@lizzardguki](#):
>
> And from here create a function that will asign x,y for each of the node.

Honestly, the application of the x/y values is trivial. It is the working out of what they need to be for each node that is complex. As you will be aware, Node-RED itself does not really do that, it just has a stab at the x/y of the next node.

You could potentially simplify the calculations by setting max x bounds, making an assumption about the size of each node and calculating a suitable x/y grid of coordinates and then apply those to your flow. But that has some serious limitations and assumptions. That the nodes are a particular size, that you don't mind the wires crossing back to x=0 when you reach max x, that all of your nodes were added in a logical sequence. And, of course, that still doesn't deal with multiple flow fragments.

---

<div class="post-metadata">

### Author: ![drmibell](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/drmibell/32/8424_2.png) [@drmibell](https://discourse.nodered.org/u/drmibell)
#### Post date: [4 May 2023 18:55 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/3 "2023-05-04T18:55:01Z")

</div>

> [@TotallyInformation](#):
>
> Have fun doing the research on the math principles of graph theory. 😁

Fortunately, you may not have to understand much graph theory to get started. The flows.json file tells you which nodes are connected to one another, and that information is enough to start up an algorithm like this:

> **[Force-directed graph drawing](https://en.wikipedia.org/wiki/Force-directed_graph_drawing)**
>
> Force-directed graph drawing algorithms are a class of algorithms for drawing graphs in an aesthetically-pleasing way. Their purpose is to position the nodes of a graph in two-dimensional or three-dimensional space so that all the edges are of more or less equal length and there are as few crossing edges as possible, by assigning forces among the set of edges and the set of nodes, based on their relative positions, and then using these forces either to simulate the motion of the edges and nodes o...

There are JavaScript libraries (for [example](https://js.cytoscape.org)) that implement variations on this method, and will return a set of node positions that you can push back into the flow file.

All this is easier said than done, and I've never done it, but I think this should involve more programming than calculation.

---

<div class="post-metadata">

### Author: ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)
#### Post date: [4 May 2023 19:52 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/4 "2023-05-04T19:52:24Z")

</div>

Hi @lizzardguki,

That is quite a long time ago. I assume you have become meanwhile a true Javascript magician 😉

You might also have a look at this old pull-request:

> <https://github.com/node-red/node-red/pull/2267>
>
> \- \[X\] New experimental feature (non-breaking change which adds functionality)
> 
> …
> \## Proposed changes
> 
> This is an \*\*experimental\*\* PR to add an auto-layout algorithm to the editor.
> 
> This is \*\*not\*\* in the plan for 1.0, but wanted to get this shared now so others can play if they want.
> 
> - it doesn't work very well for anything but a subset of typical flows.
> - it only works on flows with a single input
> - it doesn't work on flows with loops of any sort
> - it uses a fixes offset between nodes and doesn't take into account their actual height/width
> - It works reasonably well for flows that have limited branches and tries to keep the 'main' branch of the flow horizontal
> - the code is not at all optimised, nor documented, and is probably crazy inefficient
> 
> To try it out (once you've pulled down the \`auto-layout-2\` branch:
> 
> 1. select \*one\* node in the flow to layout (see restrictions above)
> 2. trigger the \`core:layout-flow\` action
> 3. ...
> 4. 
> 
> To trigger the action you can either:
> - Use Cmd/Ctrl-Shift-P to open the Action palette - search for and trigger \`core:layout-flow\`.
> - In the JS Console, run \`RED.actions.invoke("core:layout-flow")\`
> - Open the Keyboard shortcuts dialog and assign a shortcut to it to save typing

It was an experiment to auto layout the nodes in a flow. As you can see it has never been merged (very unfortunately...), but you might have a look at the code how they did it...

Good luck with yet another crazy project,  
Bart

---

<div class="post-metadata">

### Author: ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)
#### Post date: [5 May 2023 23:43 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/5 "2023-05-05T23:43:49Z")

</div>

I've always wanted to implement a D3 "auto-layout" feature for node-red, so I'm glad you reminded me!

As @drmibell suggested, the simplest way to implement this is using a force-directed graph... essentially, each node tries to get away from the others, but is tethered to those nodes that are linked. Obviously, this would not use the x.y coords to position the nodes, but it would make sense to use them for "relative" positioning between linked nodes.

That being said, there are endless ways to implement the layout -- for instance, some people want the flow to be left-\>right, while other want top-\>bottom. Either way, the goal would be to minimize the length of each link (arrow) which effectively ends up presenting a "readable" version of the flow.

If only I was retired and could spend my days working on cool stuff like this...  
\_\_  
Steve

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [6 May 2023 11:00 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/6 "2023-05-06T11:00:55Z")

</div>

> [@shrickus](#):
>
> simplest way to implement this is using a force-directed graph

I don't believe that would work well for Node-RED since all nodes have the entry at the left and exits at the right. Force-directed graphs don't use that assumption I don't believe.

> [@shrickus](#):
>
> If only I was retired and could spend my days working on cool stuff like this...

Something I say to myself a lot too! 😁

---

<div class="post-metadata">

### Author: ![drmibell](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/drmibell/32/8424_2.png) [@drmibell](https://discourse.nodered.org/u/drmibell)
#### Post date: [6 May 2023 16:36 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/7 "2023-05-06T16:36:15Z")

</div>

> [@TotallyInformation](#):
>
> nodes have the entry at the left and exits at the right. Force-directed graphs don't use that assumption I don't believe.

True, but not as much of an issue as you might think. The flow.json file specifies just one set of (x,y) coordinates for each node, presumably the position of the center of the node. The editor handles adjustments related to the size of the label, number of outputs, routing of wires, etc. (Actually, changes can cause nodes to overlap, requiring manual adjustment .) A placement algorithm (force-directed or other) only needs to place the center of the node as if all connections were made at that point, and the editor should handle the rest, just as when a flow is loaded from a file.

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [9 May 2023 16:21 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/8 "2023-05-09T16:21:39Z")

</div>

Yes, the nodes x and y are actually the center of the node. I think some placement algorithms should just have the rules for "sizing the node" based on number of outputs or based on the node name length.

Will leave progress here!

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [10 May 2023 15:14 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/9 "2023-05-10T15:14:07Z")

</div>

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/5/3536429032fb04f3789b76794b12df62310ff822.png)

**I hope this counts as progress...**

**What i did...**  
Filtered out the flows.json file to get nodes with x & y properties on Flow 1 only (_subflows will be created by a user, so no need to format them_).

Sorted the filtered node by number of output wires going out of the node (_with most outputs first_).  
Defined node sizes, function to increase height and width based on number of outputs or node.name length ( _i know that some of the nodes will display URL such as httpin node, mqtt nodes, influxdb node etc..._)

Then used [dagre](https://github.com/dagrejs/dagre/wiki) to lay out the nodes as a directed graph (_left to right, because less wires, more power 😃_ )

Also , i set edges (wires) (based on the connections), defined the margins 20x20 (_so no node is cropped by the top or left border_)

Created the layout, mapped back the dagre-s node x & y output back to nodes in flow.json, and magically it works!

Tested with only this flow, because as i mentioned, i am converting a config file to flows file to help with scaling of fleet of RPI running node-red 🙂

> Thanks for pointing me to force-directed graphs!

EDIT :  
Here is another image of its layout capabilities (just testing)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/1/e1d829268cbc9140d3d987575ff6f60cc044f4ce.png)

---

<div class="post-metadata">

### Author: ![HaroldPetersInskipp](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/haroldpetersinskipp/32/42319_2.png) [@HaroldPetersInskipp](https://discourse.nodered.org/u/HaroldPetersInskipp)
#### Post date: [11 May 2023 17:20 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/10 "2023-05-11T17:20:38Z")

</div>

Could this also be adapted into a feature that allows you to set a flow tab to "auto-layout" on an individual basis in the Node-RED editor? Often I'm very pick about how my nodes are positioned, but when prototyping a quick project it might be nice to have. It could also encourage more readable flows and screenshots of Node-RED posted online, if integrated into the "export nodes" dialog to have an option to select auto-layout before copy/pasting a quick flow online.

---

<div class="post-metadata">

### Author: ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)
#### Post date: [11 May 2023 17:39 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/11 "2023-05-11T17:39:59Z")

</div>

Rather than bloating Node-RED itself. How about having an extended plugin module instead? Then it could also potentially be expanded for different layout types if needed. A side-panel to control the layout could also be developed over time that could adjust things like grid sizing.

---

<div class="post-metadata">

### Author: ![lizzardguki](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/lizzardguki/32/103637_2.png) [@lizzardguki](https://discourse.nodered.org/u/lizzardguki)
#### Post date: [15 May 2023 14:46 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/12 "2023-05-15T14:46:09Z")

</div>

Will need more work to integrate this in a node-red, but unfortunately needed this for another project, and can't work on this...  
But for anyone interested here is the file: [https://pastebin.com/TJRFD3mg](https://pastebin.com/TJRFD3mg)

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [14 July 2023 14:46 UTC](https://discourse.nodered.org/t/read-flows-json-and-position-the-nodes-in-most-efficient-readable-way/78158/13 "2023-07-14T14:46:54Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
