I have a "complex" problem where I have a bunch of tooltips (orange) on top of elements (black) that can be randomly placed on screen. The tooltips are a big square with a triangle in the middle of one of it's 4 sides pointing though the element direction. By default, the triangle will be in the middle of the element, but can be moved as long as it stay close to it, so we can't easily understand it refer to this element and not another one.
The problem is, the tooltip must NOT overlap each other, and can't be out of screen.
Image of my tooltip problem
I thought about first placing every tooltips to their default position (triangle pointing down), and then check if they are out of screen or overlap another one, and if so, try another position. But using this technique (which is probably the simplest one), I do not guarantee the best placement since once a tooltip has been placed, I will not replace him if another one can't fit anywhere otherwise it become too complex.
Does someone have any tips/idea how to deal with this type of problem?
Thanks!!
This looks like an instance of the map labelling problem. Wikipedia has an article about it.
You could place all the tooltips using some sort of physical simulation of repulsive electrical charges, similar to what is done in some algorithms for drawing graphs. You could model each tooltip as an object attached with a soft spring to its black box, while simulating a strong repulsive force between all the tooltips and between a tooltip and the edge of the image. You calculate all the forces and move the tooltips iteratively, until all positions converge. You could play with making the force scale as inverse square, inverse cube, etc to find nice results.
This might be a bit of work to implement, but should probably give decent results for simple cases. It is probably impossible to guarantee that a good solution always exists, since if you add too many tooltips, your image will be full.
Related
I'm aware my question is maybe somewhat lazy. But I hope someone could maybe give me head start with my idea, or can provide me with an existing code example that points me in the right direction.
I want to create an organic shape/blob that more or less fills up existing space, but wraps around typographical elements. Whenever these elements move around, the shape should adjust itself accordingly. I was looking at Paper.js where examples like http://paperjs.org/examples/candy-crash/ and http://paperjs.org/examples/voronoi/ make it seem like this should be possible.
You can use the path.subtract() boolean operation, along with the path.smooth() function to smooth your shape with the type of smoothing of your choice.
Here is a demo sketch. You can also try to smooth the rectangles ; and maybe randomly add points on your curves or randomly displace all segment handles.
I am placing icons with a fixed diameter/radius on a line using d3.scaleTime. This works well except for the case in which dates are close to one another, leading to an unwanted overlap.
In that specific case, I would want the icons to "relax" and not touch.
My code rather complex, including animations etc. — so I drew the problem here:
These are my attempts:
I looked at d3-force for collision prevention, but I was not quite sure how to merge such an approach with an existing time scale. Could this be helpful? http://jsbin.com/gist/fee5ce57c3fc3e94c3332577d1415df4 However, it may occur that the icons then do not align on a horizontal straight line anymore, which is a disadvantage, because I do not want them to spread vertically.
I also thought about calculating overlaps and then manually adjusting the data so that the overlap does not occur. That, however seems a bit more complex because I would have to somehow recursively find the best position for every icon.
Could interpolation help me? I thought there must be something like "snap to grid", but then two icons could snap to the same position, couldn't they?
Which d3 concept makes most sense to solve this problem?
My app needs to show several buttons, without overlap, and preferably without scrolling or zooming. They must be big enough to poke with a finger and read the text. Button width depends on its text length, and the height is constant. The screen size is known.
Each button represents a food about which I know some nutritional information. I'll calculate a protein:carb ratio and a fat content, both ranging from 0% to 100%.
I want to put the buttons close to a position that reflects their nutritional content: e.g. protein-rich at the top, carby at the bottom, fatty on the right and lean on the left. So cake would be bottom right and meats would be somewhere on the top edge.
Often, there'll be overlap and I'll have to nudge them away from each other.
The puzzle is to invent an algorithm for that nudging. The desiderata in order of priority are:
1) Readable and pokeable size, no overlap.
2) No scrolling or zooming required, although it'll happen when there are so many buttons that they could never fit on the screen even if we didn't care where they were.
3) Buttons should be close to where the user would look based on knowing the nutritional content of the food.
Incidentally, I'm using JS on a smartphone, not prolog or the like.
(There are some seeming dupes, but no solutions. One is about diagonal stalks, another just advocates throwing it at a game engine, but most are devoid of answers.)
Ther MArVL group at Monash University does work on constraint-based layout work. Some of their software might be applicable to your problem.
The number of nodes in my d3 graph is too large. So I built a zoom mechanism in that graph. Now the problem is, I just cannot display text for each nodes since they will overlap each other. However when I zoom in to the nodes, the space is enough to display texts.
So how do I show texts when the space is enough to show all of them without overlapping?
I have had this same problem in the past. Unfortunately optimal label placement is not an easy problem. To mitigate overlap effects one option is to use a restricted force layout for label placement. You can also try using callouts to allow the labels to move farther away from the nodes.
In the past I have implemented a sort of greedy collision detection based algorithm that goes something like:
sort the labels in decreasing priority
for each label in the list // so most important first
if the label does not overlap any placed labels
place the label and add it to my collision data structure (e.g. quad tree)
else
hide the label
Obviously this will have some non-optimal cases and it can be slow if you have a lot of animations going on. But when you have the option to zoom in to see more label and if your absolute number of labels is not too high then it works quite well. There are also a number of obvious ways to speed it up like restricting testing to only labels within the view (but then you need to update on pan).
You may find some helpful suggestions here including an implementation of collision detection.
I'm working on a game where you have an 8x12 grid where each cell is the same size and all the cells are directly next to one another.
You drag around various Tetris-like shapes and place them on the grid in valid locations, a valid location being one where all the cells that the shape will occupy are not occupied by some other shape.
My problem is that I'm not sure how to search the grid space for valid locations. I've been searching for an algorithm that will solve this sort of problem, but I have come up empty handed thus far. It seems like it should be pretty straightforward to detect valid locations, but I have not been able to come to a successful solution.
Any processes, algorithm suggestions, or ideas for how to go about solving this would be extremely helpful. Thanks!
EDIT:
Here is the expected functionality: When the shape is in a valid location, it can be dragged between valid locations freely and follows the mouse pointer. However, when you try to drag the shape into an invalid area (ie movement in the direction specified would place one or more blocks of the shape in invalid locations), it stays in the last valid location.
At this point, when the mouse is in an invalid area, I want to do some "predictive" movement so that if the player moves the mouse cursor near a valid position, the shape then "snaps" into place, say if the valid position is two grid spaces away.
Thanks for your suggestion so far; I hadn't thought of that method!
As described, the algorithm would be quite simple. Arbitrarily choose a starting block on your shape, and try to match it to each open cell of the grid. If "drawing" the shape with the block aligned with the current cell doesn't cause a collision, you've found a valid position.