How to generate a circular nodemap in javascript? - javascript

How to generate a nodemap in the following manner?
The idea here is to fix the central node at the centre of the viewport and then create coordinates in a circular manner without overlapping and arrange each nodes to corresponding position. This is level 1.
Then we proceed to level two where each child nodes with children becomes level two. There also we generate coordinates in circular manner without overlapping and arrange those child nodes in level two.
Likewise we proceed to subsequent levels.
NOTE note that overlapping should be prevented and also minimum possible radius should be used for circular arrangement. (i.e. without any collision)
Each node has it's own dimensions (length and breadth)
This is what I've tried out
function getCircularAngles(points) {
return [...Array(points).keys()].map(
(num) => num * ((Math.PI * 2) / points)
);
}
function getCoorByAngle(
origin,
angle,
radius
) {
return {
x: origin.x + Math.sin(angle) * radius,
y: origin.y + Math.cos(angle) * radius,
};
}
function getCircularCoords(
origin,
points,
radius
) {
return getCircularAngles(points).map((angle) =>
getCoorByAngle(origin, angle, radius)
);
}
But this is not being able to generate the circular coordinates recursively.
(i.e. by traversing through the child nodes / connections) & also this is not preventing collisions.
SO I need a better way to permute nodes without colliding in a circular manner recursively
I cant use any graphing libraries because the boxes I create are custom svg... I don't think 3rd party libraries are going to support custom svg elements. Need an algorithm in vanilla js.

For the best end result you may want to look into force-directed graph drawing techniques. Basically you run a physics simulation on your graph and it just sorts itself out. Many libraries already do this, including the very popular d3.js (which supports SVG, btw).
Otherwise, you can try doing exactly as you say: start laying out nodes level by level, pre-calculating the minimum radius required to avoid overlap. The problem comes when you've got a big graph. Let's say you have two adjacent nodes that both have a lot of children. You can push one of them out really far from the center so the children of each node don't touch, but a more ideal solution would have those two nodes at opposite sides of your graph. If you're wanting that you'll either need to use a force-directed graph, or else try many permutations and settle on the best one.

You might like to experiment with the GraphViz open-source language tool to see how it decides to plot your diagram.
GraphViz uses a language to describe relationships, then calculates a graph layout by various algorithms which they actually discuss at some length. (Could it be that you could use GraphViz to accomplish this task entirely?)
GraphViz web site

Related

Group nodes which are visually together

I am implementing force-directed graph in d3js.
I want to divide my graph into two halves and colour both the halves with different colour, after the network has been rendered and forceSimulation has completed.
What I am looking for is explained in image.
I am refering here.
I don't want to update the group field into my data as described in the link because my links are changing dynamically on several events which is also changing the orientation of the network and updating group field into the data is creating the groups of same nodes whether they are near or far from each other.
Currently, I am using the window coordinates to divide this.
const screenWidth = window.screen.availWidth;
const halfScreen = screenWidth / 2;
nodes.selectAll().attr("fill", function (d) {
return d.x < halfScreen ? "blue" : "green";
});
But this is not the good idea. I would love to know any other way that is possible to do this.
So, my, interpretation of your question: you want to divide the nodes into two groups. Preferably each with half of the nodes, in which the distances between the nodes in each group is as small as possible.
The best algorithms for this that I know of are algorithms for constructing a "minimum spanning tree", for example, Kruskal's algorithm.
Adapting the algorithm to your problem, you start with (a copy of) the graph, having no edges. You then add the edges, sorted by length, smallest first. You stop doing this as soon as you have exactly two connected components. These connected components form groups in which nodes have a small mutual distance.
However, the groups probably won't have the same number of nodes, and I don't guarantee that this gives you the smallest mutual distance.
EDIT:
If there is more than 1 connected component, you could group them by starting with two empty groups and repeatedly adding a component (largest first) to the group that has the smallest number of nodes. This will probably give you more or less equal groups.

How to minimize visual width of (binary) search tree?

Introduction
I'm building an HTML5 web application that creates a visual representation of a binary search tree from a given list of numbers.
Currently, I have an algorithm which calculates the visual spacing between nodes on each row based on the maximum depth of the tree (which is a base-0 value):
offset = 50
offset *= pow(2, maxDepth - currentDepth)
From here, the position of the node is determined using this offset and the x-position of its parent.
The algorithm works well, because it's always able to accommodate for the widest-possible tree of any depth. However, this also makes the tree unnecessarily wide at times.
Examples
Tree branching to the left (too wide):
Tree branching to the left http://f.cl.ly/items/0c0t0L0L0o411h092G2w/left.png
Tree branching to both sides (left and right sides could be closer together).
Tree branching to both sides http://f.cl.ly/items/0r3X1j0w3r1D3v1V1V3b/left-right.png
Ideally, the above tree should be shaped like a pyramid, with a smaller width and with the sides straight, as depicted below:
Balanced tree (case where the algorithm works best):
Balanced tree http://f.cl.ly/items/203m2j2i3P1F2r2T3X02/balanced.png
Implementation
Properties
I'm using Backbone.js to create nodes from a Node model. Each node has the following properties:
parent (the parent node)
left (the left child node)
right (the right child node)
x (the x-position of the node in pixels)
y (the y-position of the node in pixels)
The x and y properties above are calculated based on the direction the node branches from:
if (parent.get('left') === node) {
x = parentX - offsetX;
y = parentY + offsetY;
} else if (parent.get('right') === node) {
x = parentX + offsetX;
y = parentY + offsetY;
}
At this point, the x and y properties are the exact values used to position the nodes (each is positioned absolute within a container element).
Methods
getDepth() (returns the base-0 depth of a node)
getMaxDepth() (returns the depth of the last row in the tree)
getRow(n) (returns an array of all nodes at depth-n)
Question
Therefore, my question is simple:
What is the best algorithm to minimize the aesthetic width of my binary tree?
It could help you if you looked at the answers given to a similar question; they contain links to software doing exactly the kind of tree visualization that you want.
Aesthetics is highly subjective, so this is just my opinion. I think my guidelines (not an algorithm) would be the following. I am assuming that the order of children is important (as these are binary search trees).
Only x coordinates are interesting; y coordinates should only be determined by the node's level. (I would find it rather ugly if this was violated but, as I said, tastes differ. However, the rest is based on this assumption.)
No nodes in the same level should be closer than some fixed minimum distance (say D).
If a node has two children at x1 and x2, I would prefer it to be placed at (x1+x2)/2. In some cases, it would be preferable to select some other coordinate in [x1..x2] (possibly one of its ends). I guess there could be unusual cases where a coordinate outside [x1..x2] would be preferable.
If a node has one child at x1 and its parent is at xp, I would prefer it to be placed at (x1+xp)/2 (so that it lies on the line connecting its parent to its child). In some cases, it would be preferable to deviate from this and select some other coordinate in [xp..x1] (or even outside).
Let's call width of a level the distance between the leftmost and the rightmost node. The width of the widest level should be minimal.
These guidelines impose constraints that cannot be satisfied all at the same time. Therefore, you should prioritize them, and this is again subjective. E.g., what's more important, #4 or #5? Your sketch for the 5-node tree implies that #4 is more important; if #5 was more important you'd get a house-like picture (vertical lines); if both were important, then your current result would be fine.
One way to tackle this is by assigning weights to the guidelines and define penalties if these are not followed. E.g., in guideline #3, you could and penalize with abs(x-(x1+x2)/2) if a parent is placed at x which is not halfway between its children; you could also assign a weight that tells you how important this is, in comparison with other guidelines. You should then try to minimize the total weighted penalty of the solution. In general, this would give you a constraint optimization problem and there are several ways to solve such problems.
You can use an AVL tree. These self-balance on insertion giving you a balanced tree after every insertion.
http://en.wikipedia.org/wiki/AVL_tree

Avoid collision between nodes and edges in D3 force layout

In this example: http://bl.ocks.org/mbostock/1747543:
...Mike shows us how to avoid collision among nodes so that no two nodes overlap each other.
I wonder if it is possible to avoid collision between nodes and edges so that no node 'clips' or overlaps an edge unless it is connected by that edge.
The following example using D3 force-direct shows that node L overlaps with the edge connecting I and A, and similarly, node M overlaps with the edge connecting L and D. How do we prevent such cases?
If your graph doesn't have too many nodes, you can fake it. Just insert one or more nodes for each link, and set their position along the link in the tick handler. Check out http://bl.ocks.org/couchand/7190660 for an example, but the changes to Mike Bostock's version amount to basically just:
var linkNodes = [];
graph.links.forEach(function(link) {
linkNodes.push({
source: graph.nodes[link.source],
target: graph.nodes[link.target]
});
});
and
// force.on('tick', function() {
linkNodes.forEach(function(node) {
node.x = (node.source.x + node.target.x) * 0.5;
node.y = (node.source.y + node.target.y) * 0.5;
});
This will introduce a pretty serious performance overhead if you have very many nodes and edges, but if your graph doesn't get much larger than your example it would hardly be noticed.
You may also want to fiddle with the relative force of the real nodes versus the link nodes.
Take this one step further and you get the nice curved links of http://bl.ocks.org/mbostock/4600693.

Split weakly-simple-polygon to true simple polygon or polygons

I want to divide weakly-simple polygons into simple polygons.
Background
The use case is to simplify polygons that are Simplified (Unioned) using Javascript Clipper. Javascript Clipper's as well as original Clipper's SimplifyPolygon() function removes self-intersections and combines common edges, but it cannot produce true simple polygons. The output is used in three.js, which has TriangulateShapes() which needs polygons to be simple. Three.js accepts polygon structures that have one contour and zero or multiple holes.
Input, weakly-simple polygons
Weakly-simple polygons cannot have sequential-duplicate-vertices (true duplicate points), nor holes (islands) nor self-intersections (edge crossing over other edge), but there can be non-sequential-multiple-vertices (vertices that have exactly the same coordinate but not as sequential). The input polygon can have either CW or CCW winding order, which means that CW input is outer polygon and CCW is a hole. The input is either CW or CCW polygon.
The input is an array of polygon points eg.:
// This is a true example of weakly-simple polygon:
var input = [{"X":270,"Y":520},{"X":130,"Y":490},{"X":210,"Y":250},{"X":60,"Y":170},{"X":130,"Y":490},{"X":20,"Y":410},{"X":60,"Y":300},{"X":60,"Y":20},{"X":780,"Y":40}, {"X":680,"Y":180},{"X":460,"Y":130},{"X":210,"Y":250},{"X":320,"Y":100},{"X":220,"Y":80}, {"X":210,"Y":250},{"X":520,"Y":250},{"X":680,"Y":180},{"X":770,"Y":480},{"X":540,"Y":470}, {"X":520,"Y":250},{"X":380,"Y":280},{"X":430,"Y":390},{"X":540,"Y":470},{"X":270,"Y":520},{"X":330,"Y":350},{"X":210,"Y":250}];
This is the above input polygon as an image:
And here are the points numbered, where you can easily see what points are duplicates:
As you see, the above polygon can be divided in multiple ways, eg.:
- One outer polygon with five holes
- five outer polygons of which one has one hole
Output, simple polygons as a exPolygon structure
Simple polygon is a polygon that have no self-intersections, no duplicate coordinates whether they were sequential or non-sequential, no holes. The output's simple polygon can have CW or CCW winding order. CW means outer and CCW holes.
The output can have (and in many times there will be) holes, but in certain cases the output has no holes. The output has always at least one outer polygon, but there can be also multiple outer polygons that have zero or more holes.
The output should be an array of exPolygon objects that have properties "outer" and "holes". "outer" is an array of point objects, "holes" is an array of arrays of point objects. If "holes" is populated, the holes in it have to be holes of "outer" polygon in the exPolygon object.
The example of output:
// This is an example of output, but the points are random:
[ { "outer": [{"X":54,"Y":4},{"X":2,"Y":50},{"X":30,"Y":5},{"X":10,"Y":50}],
"holes": [ [{"X":0,"Y":8},{"X":60,"Y":13},{"X":21,"Y":2},{"X":3,"Y":1}],
[{"X":21,"Y":2},{"X":50,"Y":2},{"X":6,"Y":1}] ] },
{ "outer": [{"X":54,"Y":4},{"X":2,"Y":50},{"X":30,"Y":5},{"X":10,"Y":50}],
"holes": [ [{"X":0,"Y":8},{"X":60,"Y":13},{"X":21,"Y":2},{"X":3,"Y":1}],
[{"X":21,"Y":2},{"X":50,"Y":2},{"X":6,"Y":1}] ] },
{ "outer": [{"X":54,"Y":4},{"X":2,"Y":50},{"X":30,"Y":5},{"X":10,"Y":50}],
"holes": [] }
];
Output's "outer" polygons are CW, and "holes" are CCW.
There is no limit for counts of points in polygons, count of exPolygons objects nor count of holes.
Here are other examples of weakly simple polygons:
Example of division
Here is an example of input polygon:
Here is how it could be divided:
Some other polygons can have multiple possible alternatives of ouput depending where are the pseudo-duplicate-points.
My question
How the polygons can be divided this way and the desired output structure achieved? I'm not asking full code (but if you have some spare time and want to show that it is possible). Thoughts of possible algorithms are also welcome.
I have searched hours a solution and tried to find an algorithm.
In case you want to try a solution, I have here a code which I have used to find the duplicates: http://jsbin.com/unuyev/7/edit. It shows the polygon in SVG and shows the points as red circles and an array index of each point (after pressing button "Run with JS").
Here is the same, but with 12 example polygons (change pindex in Javascript window to change the polygon):
http://jsbin.com/unuyev/4/edit
EDIT: Javascript Clipper 6 is available now and there is support for StrictlySimple. But according to the documentation "There's currently no guarantee that polygons will be strictly simple since 'simplifying' is still a work in progress". I have tested StrictlySimple and it fails in certain cases: Orientation problems and lack of rotation invariance. We hope these are fixed soon and StrictlySimple works as expected.
There may be something that I'm missing, but this looks like a classic problem of finding the articulation vertex of a graph. Essentially you're trying to find the weakest point in a graph such that when you cut the graph at that point, you end up with two separate graphs. So in your example, if you cut the polygon at that vertex, you end up with multiple polygons. You can represent your polygons quite easy as a graph, with each vertex representing a graph vertex, and the polygon edges as graph edges.
If I had to solve the problem, this is the approach that I would take. You can check out the following resources:
Articulation vertices from the Algorithm Design Manual - This is your best bet. He explains the algorithm in simple terms and also gives you C code that you can easily translate into JavaScript. If I had to start writing an algorithm, this is where I would start.
Biconnected component
Detection of Articulation Points (search for "articulation")
UPDATE
I'll try and give you a brief overview of the problem and the solution to point you in the right direction. An implementation of this algorithm using graphs will necessarily go into graph-algorithm terminologies, so if you are not familiar with graphs, you might want to read up on them.
The brute-force approach in your case would be to traverse the graph, temporarily delete each vetex and then see if the graph is connected when doing a DFS/BFS traversal on the modified graph. This is not very efficient and will run in quadratic time O(n(m + n)). But there is a linear-time algorithm that is based on classifying the edges of the resultant DFS tree that is formed from a DFS traversal.
In a DFS tree that doesn't contain any back-edges (edges connecting a "lower" node to a node "higher" in the tree [assuming "higher" nodes are those closer to the root]) leaf nodes are not articulation nodes, since deleting any one of them will still leave the graph connected. However, deleting any of the internal nodes will disconnect any nodes that follow it from the root.
Deleting the root of the tree depends on whether it has one or more children. If it has just one child, then it's more-or-less a leaf and so deleting it will have no effect. However, deleting a root node that has more than one child will disconnect the graph.
But in a general graph, you can have back-edges and so deleting any of the nodes in between will not disconnect the graph. So figuring out the articulation vertices boils down to figuring out which sections of the tree are linked to ancestor nodes by back edges (i.e., figuring out the "reachable ancestor" of a vertex).
In the page I linked to from the Algorithm Design Manual, Skiena describes three cases where a vertex can be an articulation vertex (root, bridge, and parent cut-nodes). Using the algorithm he describes, you can figure out if the vertex you are processing, meets any of those conditions. If it does, it is an articulation node.
Hopefully this helps you get started!

Spatial Data Structure for Games

I need to implement a spatial data structure to store rectangles then be able to find all rectangles that intersect a given rectangle. This will be implemented in JavaScript.
So far I am developing a Quad Tree to cut down the search space but because it is for a game, all objects that move will need to update its position in the tree. Back to square one.
Are there any data-structures or methods to help? It will need to process around 10,000 objects so brute force isn't good enough.
A hash table works fairly well as an approximate intersection test. Hash tables are used as part of a more sophisticated algorithm for detecting collisions in ODE.
Logically, this test divides the space into a regular grid. Each grid cell is labeled with a list of objects that intersect that cell. The grid is initialized by scanning all objects. I don't know javascript, so I'll use python-ish pseudocode.
for each ob in objects:
for each x in [floor(ob.x_min / grid_size) .. floor(ob.x_max / grid_size)]:
for each y in [floor(ob.y_min / grid_size) .. floor(ob.y_max / grid_size)]:
hashtable[hash(x, y)].append(ob)
To find collisions with a given object, look up near-collisions in the hash table and then apply an exact collision test to each one.
near_collisions = []
for each x in [floor(ob.x_min / grid_size) .. floor(ob.x_max / grid_size)]:
for each y in [floor(ob.y_min / grid_size) .. floor(ob.y_max / grid_size)]:
near_collisions = near_collisions ++ hashtable[hash(x, y)]
remove duplicates from near_collisions
for each ob2 in near_collisions:
if exact_collision_test(ob, ob2):
do_something
You can still use quadtree even if you have moving objects – just remove and reinsert an object every time it moves or every time it crosses region boundary.
But quadtrees aren't very good at storing rectangles and I would recommend using an R-tree instead.

Categories

Resources