Draw outline of combined rectangles in canvas - javascript

Is there a good algorithmic way to combine multiple squares (each has four x/y points) to draw an outline of the joined figured in canvas?
The figures I would want to make sure work are as follows:
two squares joined to make a rectangle
four squares joined to make a larger square
two squares that are diagonal like a rectangle with triangles at each end at 45 degrees - this is probably the most irregular/special case...
three or four squares joined to make a concave shape like a Tetris(TM) piece 'L' piece
Is there an easy way to calculate the outer points to use to draw a line path (and maybe a filled figure) from all of the squares points?
Thanks!
Update: the reason we want to do this is because we want to show squares that are of the same group that are next to each other in a 2xn array specifically (but could also be 1xn in some cases). Maybe there is an easier answer if I just iterate through the different squares and form groupings some other way?

You're looking at it from the perspective of "I've got squares".
But you need to look at it from the perspective of "I've got points" (each square is just 4 points).
What you're actually looking for is called the "Convex Hull" - and the question has already been answered on SO here:
Polygon enclosing a set of points
I actually started diagramming your solution to go about solving it - and that's when this occurred to me.
I realized when I was making my diagrams that the outline of these shapes has several interesting properties - which is when I thought "yeah right - someone has already done this - this must be around already".
So I googled "construct smallest polygon enclosing other polygons"
And found the other S.O. question.
Although you do have two seemingly dis-similar requirements:
two squares that are diagonal like a rectangle with triangles at each
end at 45 degrees - this is probably the most irregular/special
case... three or four squares joined to make a convex shape like a
Tetris(TM) piece 'L' piece
In the first example above, you say you want the "Convex Hull".
But in the second example above (the tetris pieces), you'd need the "Concave Hull".
Good luck.
Here are my diagrams:

I'm curious as to why you'd want to do that.
In any case, my intuition is that you want to find is called "concave hull", but I'm no expert.
Check out this question and see if that's what you want.
Edit: also this question on gis.stackexchange.com

Related

Position resizable circles near each other

I am working on this browser-based experiment where i am given N specific circles (let's say they have a unique picture in them) and need to position them together, leaving as little space between them as possible. It doesn't have to be arranged in a circle, but they should be "clustered" together.
The circle sizes are customizable and a user will be able to change the sizes by dragging a javascript slider, changing some circles' sizes (for example, in 10% of the slider the circle 4 will have radius of 20px, circle 2 10px, circle 5 stays the same, etc...). As you may have already guessed, i will try to "transition" the resizing-repositioning smoothly when the slider is being moved.
The approach i have tried tried so far: instead of manually trying to position them i've tried to use a physics engine-
The idea:
place some kind of gravitational pull in the center of the screen
use a physics engine to take care of the balls collision
during the "drag the time" slider event i would just set different
ball sizes and let the engine take care of the rest
For this task i have used "box2Dweb". i placed a gravitational pull to the center of the screen, however, it took a really long time until the balls were placed in the center and they floated around. Then i put a small static piece of ball in the center so they would hit it and then stop. It looked like this:
The results were a bit better, but the circles still moved for some time before they went static. Even after playing around with variables like the ball friction and different gravitational pulls, the whole thing just floated around and felt very "wobbly", while i wanted the balls move only when i drag the time slider (when they change sizes). Plus, box2d doesn't allow to change the sizes of the objects and i would have to hack my way for a workaround.
So, the box2d approach made me realize that maybe to leave a physics engine to handle this isn't the best solution for the problem. Or maybe i have to include some other force i haven't thought of. I have found this similar question to mine on StackOverflow. However, the very important difference is that it just generates some n unspecific circles "at once" and doesn't allow for additional specific ball size and position manipulation.
I am really stuck now, does anyone have any ideas how to approach this problem?
update: it's been almost a year now and i totally forgot about this thread. what i did in the end is to stick to the physics model and reset forces/stop in almost idle conditions. the result can be seen here http://stateofwealth.net/
the triangles you see are inside those circles. the remaining lines are connected via "delaunay triangulation algorithm"
I recall seeing a d3.js demo that is very similar to what you're describing. It's written by Mike Bostock himself: http://bl.ocks.org/mbostock/1747543
It uses quadtrees for fast collision detection and uses a force based graph, which are both d3.js utilities.
In the tick function, you should be able to add a .attr("r", function(d) { return d.radius; }) which will update the radius each tick for when you change the nodes data. Just for starters you can set it to return random and the circles should jitter around like crazy.
(Not a comment because it wouldn't fit)
I'm impressed that you've brought in Box2D to help with the heavy-lifting, but it's true that unfortunately it is probably not well-suited to your requirements, as Box2D is at its best when you are after simulating rigid objects and their collision dynamics.
I think if you really consider what it is that you need, it isn't quite so much a rigid body dynamics problem at all. You actually want none of the complexity of box2d as all of your geometry consists of spheres (which I assure you are vastly simpler to model than arbitrary convex polygons, which is what IMO Box2D's complexity arises from), and like you mention, Box2D's inability to smoothly change the geometric parameters isn't helping as it will bog down the browser with unnecessary geometry allocations and deallocations and fail to apply any sort of smooth animation.
What you are probably looking for is an algorithm or method to evolve the positions of a set of coordinates (each with a radius that is also potentially changing) so that they stay separated by their radii and also minimize their distance to the center position. If this has to be smooth, you can't just apply the minimal solution every time, as you may get "warping" as the optimal configuration might shift dramatically at particular points along your slider's movement. Suffice it to say there is a lot of tweaking for you to do, but not really anything scarier than what one must contend with inside of Box2D.
How important is it that your circles do not overlap? I think you should just do a simple iterative "solver" that first tries to bring the circles toward their target (center of screen?), and then tries to separate them based on radii.
I believe if you try to come up with a simplified mathematical model for the motion that you want, it will be better than trying to get Box2D to do it. Box2D is magical, but it's only good at what it's good at.
At least for me, seems like the easiest solution is to first set up the circles in a cluster. So first set the largest circle in the center, put the second circle next to the first one. For the third one you can just put it next to the first circle, and then move it along the edge until it hits the second circle.
All the other circles can follow the same method: place it next to an arbitrary circle, and move it along the edge until it is touching, but not intersecting, another circle. Note that this won't make it the most efficient clustering, but it works. After that, when you expand, say, circle 1, you'd move all the adjacent circles outward, and shift them around to re-cluster.

Efficient method to check which polygon a certain located inside

In my JavaScript application I have more than 30+ polygons. They are defined like this:
polygons:[
{name:'xx',bounds:[20,20,60,20,50,40,30,10...],minzoom:0,maxzoom:5},
{name:'yy',bounds:[.....],minzoom:6,maxzoom:8},
........
]
Now given a certain point like [10,10] with zoom 4.
Which is the fast way to check which polygon this point is located inside?
My first thought is iterator the polygons, and to check if the point is inside the polygon.
Then this question came to be a point-in-polygon question which have a lot of answers at stackoverflow.
I just wonder if there is any alternative methods?
Assuming the polygons do not overlap (or that if they do, you're only interested in the top-most polygon), you can employ the "point-in-polygon" solution that involves a canvas:
Create a canvas big enough to hold all your polygons.
Draw each polygon in a different colour, one after the other
Look up what colour the pixel is where the point is located
This will tell you the polygon that's there.
Note that you don't even need them to be human-distinguishable colours, you could literally use #000000, #000001, #000002 and so on, and use the colour's hex code as the index of the polygon.

Javascript & Canvas: Endless random animation of slightly morphing circle?

I'm completely new to canvas and animating objects with it. I did a little bit of research (e.g. I found RaphaelJS) however I couldn't find any general answer or tutorial on how to create a "morphing" circle.
The image I posted here is what I would like to do:
I'd like to create one circle that is endlessly animated via a randomizer and is slightly morphing its contours.
I know this might be not a "real" question for this forum, however I just wonder if anyone could provide a few tipps or tricks on how to do something like that.
By "how to do something like that" I'm speaking actually about the technique on how to morph a circle. Do I have to "mathematically" create a circle with dozens of anchor-points along the edge that are influenced by a randomized function?
I would really appreciate some starting help with this.
Thank you in advance.
A circle can be reasonably well approximated by 4 cubic curves (one for each quarter and the control points on the tangents - google for the correct length of the control segments or calculate them yourself - see here. You could then randomly animate the control points within a small radius to get a wobbling effect.
Do I have to "mathematically" create a circle with dozens of anchor-points along the edge that are influenced by a randomized function?
Yes, you do, although it should not be necessary to create "dozens".
You may find the .bezierCurveTo() and .quadraticCurveTo() functions useful to provide smooth interpolated curves between control points.
When you can use a raster image then for every point you can displace it along the x-axis with a sin function. You can run the same function along the y-axis but instead to simply displace the pixel you can double it. This should give you a morphing circle but it also works with other shapes.

expressing point position within a circle as a percentage of arbitrary segments

Ok, so... here's what I'm trying to do. In HTML/JS. With a math knowledge that would embarrass a twelve-year old.
With, say, 20 checkboxes on a page, the user picks.. five of them. A circle then appears on the page (I'd anticipate using one of the canvas libraries like Raphael) with their five answers arranged around it. So that's the first thing I don't know how to do; split a circle into x equal segments. Strange, foreign terms like "cos" and "sin" are looming on the horizon.
But then it gets even more fun: the user can click a point on the circle. And that point is translated into some sort of percentage value for each of the segments. So if the user checks Happy, Grumpy, Sneezy, Dopey and Bashful, and clicks the circle, I can tell them that they're 37% Happy, 42% Dopey and 21% Sneezy.
The best analogy is probably a colour-picker wheel, but I can't find any JS ones that I could repurpose. A pie chart is close - and there's a nice Raphael demo - but I've got a feeling that the fixed boundaries of a pie chart segment is going to take me down the wrong route for estimating percentage positions within the circle as a whole.
So, given my vague and poorly thought out request, and the noticeable absence of any "here's what I've tried so far" code - because I don't have the foggiest where to even start, apart from high school trigonometry books, can anyone suggest any code libraries or snippets that might get me at least pointing in the right direction?
Thanks :)
========================
Edit :
Wow, thanks for all the answers. I'll try to refine the question/s a bit:
I'm going to need to draw a circle with x number of points arranged equally around its circumference. The number of points will correlate to the number of checkboxes that the user checked.
That's the first bit I'm stuck on: I reckon that I can draw a circle, with dimensions and at a position on the page of my own choosing, (using Raphael or similar canvas library) but how can I calculate what the x/y pixel coordinates of those points should be on the circle circumference?
The second bit: the user then clicks anywhere in the circle. I guess what I'd do is calculate how far each of the circumference points are from that user click point - I'm not sure how to do that, apart from a vague suspicion it involves imaginary triangles - and then how much of a total distance each of those distances are. That last bit, at least, I can manage.
Actually, this is starting to make sense. I'm still not sure how the trig stuff works but it's amazing what typing your problem out so that strangers will understand it can do to help your own understanding...
You need to revise your question to explain more clearly what you are trying to do. In the meantime, I can give you the following information that may help you get started.
First of all, you'll need to know the locations of the five checkboxes that the user selects. In order to do this, the jQuery library offers some convenient functions such as $.position and $.offset.
Your question does not make clear exactly how the circle you want to draw is positioned in relation to the five checkboxes that the user clicks. As for actually drawing the circle, you may want to use something like the HTML5 canvas element. I've not yet used it myself, so I can't tell you much about it.
You might want to try asking another question on StackOverflow about how to draw a circle on your web page once you've computed the center and radius of the circle.
As for doing the math about the circle, you need to know that a circle can be parameterized on an x-y plane by the following equations:
x = x0 + r cos(theta)
y = y0 + r sin(theta)
where (x0,y0) is the center of the circle, r is the radius of the circle, and theta ranges over 0 to 2*Pi radians (0 to 360 degrees)
Let us know more about what you're doing and we can give you some more specific information.

how to "sort" polygons 3d?

I am still working on my "javascript 3d engine" (link inside stackoverflow).
at First, all my polygons were faces of cubes, so sorting them by average Z was working fine.
but now I've "evolved" and I want to draw my polygons (which may contain more than 4 vertices)
in the right order, namely, those who are close to the camera will be drawn last.
basically,
I know how to rotate them and "perspective"-ize them into 2D,
but don't know how to draw them in the right order.
just to clarify:
//my 3d shape = array of polygons
//polygon = array of vertices
//vertex = point with x,y,z
//rotation is around (0,0,0) and my view point is (0,0,something) I guess.
can anyone help?
p.s: some "catch phrases" I came up with, looking for the solution: z-buffering, ray casting (?!), plane equations, view vector, and so on - guess I need a simple to understand answer so that's why I asked this one. thanks.
p.s2: i don't mind too much about overlapping or intersecting polygons... so maybe the painter's algorthm indeed might be good. but: what is it exactly? how do I decide the distance of a polygon?? a polygon has many points.
The approach of sorting polygons and then drawing them bottom-to-top is called the "Painter's algorithm". Unfortunately the sorting step is in general an unsolvable problem, because it's possible for 3 polygons to overlap each other:
Thus there is not necessarily any polygon that is "on top". Alternate approaches such as using a Z buffer or BSP tree (which involves splitting polygons) don't suffer from this problem.
how do I decide the distance of a polygon?? a polygon has many points.
Painter's algorithm is the simplest to implement, but it works only in very simple cases because it assumes that there is only a single "distance" or z-value for each polygon (which you could approximate to be the average of z-values of all points in the polygon). Of course, this will produce wrong results if two polygons intersect each other.
In reality, there isn't a single distance value for a polygon -- each point on the surface of a polygon can be at a different distance from the viewer, so each point has its own "distance" or depth.
You already mentioned Z-buffering, and that is one way of doing this. I don't think you can implement this efficiently on a HTML canvas, but here's the general idea:
You need to maintain an additional canvas, the "z-buffer", where each pixel's colour represents the z-depth of the corresponding pixel on the main canvas.
To draw a polygon, you go through each point on its surface and draw only those points which are closer to the viewer than any previous objects, as indicated by the z-buffer.
I think you will have some ideas by investigating BSP tree ( binary spaces partition tree ), even if the algo will require to split some of your polygon in two.
Some example could be find here http://www.devmaster.net/articles/bsp-trees/ or by google for BSP tree. Posting some code as a reply is, in my opinion, not serious since is a complex topic.

Categories

Resources