Comments (8)
this is now available in v0.11.4, let me know how that works!
from d3-dag.
If I understand correctly, it actually should be pretty easy to do, and part of a change I've been meaning to make for quite a while.
Currently, the order of the nodes in the "grid" layout is just defined by a topological sort, that breaks ties randomly:
Lines 158 to 159 in 37cc714
However, there are many ways we could augment the topological sort. The most straightforward might be to use something like the rank operator for simplex layering. Essentially this allows you to specify a rank for any node in the graph, and the layout implicitly adds invisible edges from lower ranks to higher ranks.
If I understood you correctly, then you could assign each CTE with its rank in the initial query, and that should produce the layout you want. Am I understanding you correctly?
On a side note, grid returns pretty generic control points for the edges. If you want the edges to render like your figma I suggest you use the grid tweak found in my observable notebook, repeat here for preservation sake:
gridTweak = (layout) => (dag) => {
// Tweak allows a basis interpolation to curve the lines
// We essentially take the three point lines and make them five, with two points on either side of the bend
const { width, height } = layout(dag);
for (const { points } of dag.ilinks()) {
const [first, middle, last] = points;
if (last !== undefined) {
points.splice(
0,
3,
first,
{
x: middle.x + Math.sign(first.x - middle.x) * nodeRadius,
y: middle.y
},
middle,
{ x: middle.x, y: middle.y + nodeRadius },
last
);
}
}
return { width, height };
}
from d3-dag.
Yes, that's exactly what I'm hoping for β a way to pass in some kind of rank to enforce an ordering.
from d3-dag.
@hamilton I started throwing together an implementation and ran into a stumbling block that hopefully you can help clear up.
In the simplex layering, nodes can be assigned the same height, so leaving some nodes unconstrained (i.e. without a rank) is a natural way to structure it.
However for the grid layout, we're ultimately selecting between any valid topological sorting of the nodes. The current implementation just chooses one arbitrarily based on a depth first search. You're proposing one with rank constraints. You could also imagine one that attempted to minimize the length of all edges drawn (e.g. compactness).
For now, lets only focus on your case, assigning rank constraints that must be fulfilled. There are two possible ways to implement this.
- My initial idea, the easiest and most performant to implement would be to use the same visiting algorithm as specified, but take nodes with the lowest rank first. In order to guarantee that this preserves rank constraints, any unranked node must implicitly have rank -Infinity, e.g. we'll always pick unranked nodes before ranked nodes
- Treat rank constraints as faux edges. Like the way it's currently done, any ordering which is topologically sound, and conforms to the rank constraints will be arbitrarily chosen based on node ordering. There are two downsides to this approach.
- the only implementation I can think of has n^2 performance for adjacent (in sorted order ranks), e.g. if n nodes have rank 1, and k nodes have rank 2, and no nodes have a rank between 1 and 2, then the algorithm will add n * k complexity to the standard order.
- Because we're implicitly adding edges, we run the risk of creating cycles. The first method will essentially ignore those constraints, but this will have to throw an error.
Based on what you want to do, is there an obvious preference? In general 2 seems more robust overall, but I'm curious of 1 does the trick.
from d3-dag.
I see ~ thank you for taking the time to look into this! For my use-case, there will never be a situation where I'm not ranking the nodes (and there will never be ties), so the first option would suffice if I'm understanding correctly. This is because these subqueries & expressions within a big SQL query always have a line + column number where they appear, which should work for the ranking.
from d3-dag.
Awesome, thank you @erikbrinkman! I will give this a try.
from d3-dag.
Did a quick timeboxed prototype last night with the new rank operator. This is a fantastic feature and will solve my use case. I appreciate the thoughtfulness you put into development ~ thanks for implementing!
from d3-dag.
That looks great! I always love seeing things come together! Glad this could be useful
from d3-dag.
Related Issues (20)
- Basic TypeScript type check error HOT 6
- Tips for writing my own layering HOT 2
- General question about node ordering HOT 2
- Specific key order appears to cause decrossOpt to hang HOT 4
- TS: Errors with typescript version 4.9.4 HOT 3
- example code not runable HOT 4
- How to plot a horizonal sugiyama graph HOT 1
- Guidance on Implementing Radial Drawing with d3-dag's Sugiyama Algorithm HOT 3
- Implement Brandes/KΓΆpf Coordinate Assignment
- Expand d3-dag to handle multiple paths from parent->child HOT 4
- Dynamic nodeSize? HOT 1
- TS, export SugiNode<NodeDatum = unknown, LinkDatum = unknown> ? HOT 3
- TS Sugestion(?) HOT 4
- Possible linking bug in docs HOT 3
- elkjs, external layout algorithms? HOT 1
- Support for TypeScript <4.5
- How to extend DagNode in vanilla js? HOT 6
- Error: size of dag to decrossOpt is too large and will likely crash instead of complete, enable "large" grahps to run anyway HOT 9
- Layout direction HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from d3-dag.