Positioning items inside container - javascript

I have a mathematical problem that I am trying to solve and want to realize in javascript.
I have a "space" meaning: a rectangular format. This shall work as a kind of container.
Then I have smaller forms: other rectangular ones and circles.
I need to find out a solution how to calculate how many of these forms fit into the container.
So I kind of need the ideal way, how to stack these items in there.
If it is too many, leaving out some. And if it is too few, stacking them from bottom up.
I am trying to realize this in Javascript but not getting far.
From my vision it should be kind of like this:
var items = [circle1,2],[rect1,2,4],[rect2,5,6]]; // array with the forms to put inside container, stating a radius for circle and width/height for rectangles
var container = [10, 4]; // given the size of the container in width and height.
function stackItIn (container, items){
// now this is where I am totally lost
}
The premium part would be even showing it graphically at the end.
Any help would be appreciated!
Thank you!

You can try a treemap. Sort the tiles and pick the first and create a node in a tree. Split the tree on both axis and pick the next tile and find the best fit of the nodes.

Related

How do I prevent nodes from overlapping

How do I prevent nodes in a graph from stacking on each other? I want there to be a minimum distance between nodes and if someone was to drag a node over another the graph throws an error to the user. I saw this solution and tried it but it doesnt work Prevent node overlap in JGraphX
I'll appreciate any ideas.
For rearranging your diagram automatically with some distance between them you can try to use something like this:
let layout = new mxHierarchicalLayout(this.graph, mxConstants.DIRECTION_WEST);
layout.intraCellSpacing = 50; //horizontal
layout.interRankCellSpacing = 200; //vertical
layout.execute(this.parent);
The mxHierarchicalLayout method will automatically rearrange your current nodes. The other two settings will give spacing between them ( horizontally and vertically )
Also, run this before rendering the screen or if you want to change after the display has already rendered, just this.graph.refresh() if needed

Setting variable width on d3 tree nodes

I'm using d3 to create an Org Chart, which has some nodes with longer names.
I've managed to modify the width of longer nodes, but have trouble properly placing their children and the lines (paths) to their children.
I tried calculating myself with determineChildXValue(), but that didn't work properly.
Is there a way to initialize the tree with variable widths so it will take care of the calculations of translations for child nodes?
Currently, I'm initializing it with hard-coded node sizes:
var tree = d3.layout.tree().nodeSize([70, 40]);
I've replicated the behavior in this example - expand Departments, then DEPARTMENT STORES to see the overlap.
Thanks in advance!
I consulted a colleague who was able to build a proper fix:
Define the source and target properties (before the projection is set) for the diagonal (paths)
Track the tierDisplacementX and cumulativeDisplacementX
Use these when translating the positions of the child nodes and their paths
See this fiddle to see the working code.

Vis.js not showing graph when many nodes are added

I am making a web app to show relationships between items using Vis.js, everything works perfectly fine until I get to the point where I need to display ~260 nodes with ~1200 edges between them.
Once I get to that amount of nodes, the graph just shows a blank space and a blue line, nothing else. As soon as I try to zoom it, the line disappears and it's all white.
When I look at the position of the nodes I can see that many of them are in negative or very big x, y positions (generally -300 for x and around 478759527705558300000 for y).
I have tried, to no avail, to disable physics. The graph is in hierarchichal mode, with levels manually set in the code, but the levels are correct.
Network options (the improvedLayout option was just a possibility I found on the internet; it works just the same if I remove it):
var options = {
layout: {
improvedLayout: false,
hierarchical: {
direction: direction,
sortMethod: "directed"
}
}
}
Screenshot:
I have hierarchical layout graph which consists of around 615 nodes and 614 edges (excluding 40 odd cluster nodes, some of them cluster of clusters). I landed into same problem with visjs.
One quick thing which helped me to get over this problem was to explicitly call network.stabilize() method with an argument specifying number of iterations. Default iterations are 1000. I passed 10000 and graph stabilized it self nicely. It took a few more seconds, i was fine with that. But stabilization times shoots up as number nodes increased to ~1000. So i started looking into visjs code for solution.
While looking in visjs code, i found that inside function setupHierarchicalLayout() there is a call to _condenseHierarchy().
This method tries to minimize white spaces between nodes and edges (yet to understand the code fully). _condenseHierarchy() modifies coordinates of a node. See Y coordinate before and after call to _condenseHierarchy() below:
(this.body.nodes["node-11"]).y
1530
(this.body.nodes["node-11"]).y
64920
When a node gets a distant position it takes lots of iterations (in stabilize) to bring it closer together with other nodes in graph. I disabled _condenseHierarchy() and got the graph displayed nicely.
I'm sure disabling _condenseHierarchy() would bring in some other issues as i proceed further. I am going to spend some more time to understand and experiment with _condenseHierarchy().
To solve this problem, you can adjust hierarchical layout parameters, such as nodeSpacing, levelSeparation and treeSpacing. Here is an example hierarchicalLayoutWithoutPhysics

d3 venn diagram labels layering

Im using this great article to produce a venn diagram with D3.
http://www.benfrederickson.com/venn-diagrams-with-d3.js/
It looks great but on occasion I get bubbles overlapping the the labels become hidden. Is there a way to make sure the text element is always on top? (see the picture below.. label A needs to be on top of circle B.
I found this good article but im struggling in how to implement this in the venn.
How can I bring a circle to the front with d3?
You should grab the latest code from master: this commit should fix the issue you had there https://github.com/benfred/venn.js/commit/4cb3bbef65b5b3c3ce02aee7d913e8814e898baf
Instead of having the 'A' label be overtop of the 'B' circle - it willnow move the label so that its in the certain of the 'A' region that isn't overlapped with 'B'. Some details are in this issue here: https://github.com/benfred/venn.js/issues/18
You might find it easier to work in actual layers. You can use g elements to create them. For example:
var lowerLayer = svg.append('g');
var upperLayer = svg.append('g');
Now anything you append to upperLayer will appear above anything you append to lowerLayer because the two g elements have been added to the DOM and are in a specific order.
Also check out this answer I wrote up for a similar question.

Randomly display dots

I am trying to design a little game using JS, and what I want it to do is make a random number say... 1-100 and then randomly scatter the dots (I used periods with the font size at 200) on the screen. By random, I just mean that I don't want them to be arranged in rows and columns. What I have so far achieves all but scattering the dots, so how do I do that?
var i=0;
var inhtml="."
var num=10
function exe(){
i=Math.floor(Math.random()*100)
//alert(i)
while (i<=100){
document.getElementById("dot").innerHTML = inhtml + "."
inhtml = document.getElementById("dot").innerHTML
if (inhtml.length>num){
inhtml=document.getElementById("dot").innerHTML+"<br />"
num=num+20
}
i++;
}
}
Instead of using a single element containing several periods at a large size, I'd recommend using separate elements for each dot. Then, (besides not having to use 200px periods), you can use CSS to position each element however you want. I have an example here.
Edit: I don't know what the exact problem with getting the dots to not overlap you're having is, but you basically need to do this:
First you pick a position. Then, you check that position against all the other positions (which you'd probably want to do using Manhattan distance). If the point is valid, you use that point and add it to the array of taken positions. Otherwise, go back to the first step.
You may want to check your syntax errors before progressing; I do not know whether you copied all of your code, but you are missing semicolons at the end of your lines. Syntactical issues aside, one possible way to achieve what you describe would be to assign the x- and y-coordinate of each point to a random number. Examination of the code reveals that only the initial value of i is assigned to the value of random(). Incrementing i will make the coordinates of future points dependent on the initial value of i, which is something you may want to take into account. But nowhere in your code do I see you changing the position of the each element based on the values you generate.
I strongly suggest that you use the HTML5 Canvas instead of attempting to move HTML elements; the latter would be cumbersome and lead to messy and inefficient code. If you still want to stick to the method you are trying to use now, check to make sure that the CSS display property is set to block for these elements. You are using the getElementById() method, which is not very useful in this circumstance, since IDs are unique in HTML files. I would suggest using getElementsByTagName() and using those returned elements with a specific class attribute instead.
You might want to look at the HTML 5 Canvas. It allows you draw arcs (aka circles) In any postion, size, and fill color.
Look here for details, here for a tutorial, and here for a demo.
To not be bound by the browser's text layout constraints, you pretty much have to absolutely position your dots:
<div style="position: absolute; top: {random number}; left: {random number}">.</div>

Categories

Resources