I googled it but didn't find a good answer. Specifically, I want to learn:
to slice an image into curved pieces
to create individual objects from those pieces (i assume that i need
this to reassemble)
thanks.
There are several pieces to this puzzle. :)
The first piece is SVG and its Canvas. That's what you'll need to draw, because otherwise you can't make a curved piece out of a picture. Only rectangles are possible with standard HTML/CSS.
The second piece is an algorithm for generating jigsaw pieces from the picture. Google should help you with that if you can't figure one out by yourself (though it doesn't seem very complicated).
The rest should be straightforward.
Added: A quick Google search gave just such a jigsaw engine in the first result. Check out the source of that.
I'll assume the image you want to saw to pieces is a raster image with a resolution that you will use for the puzzle pieces, call that /picture/. Also, I assume you have the edges along which you wish to saw in a second raster image with the same dimensions, call that /raster/. Then your problem amounts to determining all connected areas in the raster. Each pixel of the raster gets annotated with the id of the jigsaw piece it belongs to, initially 'none', -1 or whatever. Then your algorithm scans across all pixels in the raster, skipping pixels that already belong to a piece. For each unassigned piece it executes a flood fill, "coloring" the pixels with the pieces id (e.g. number). In a second scan, after allocating an image for each piece, you add the corresponding pixels of the image to the piece. As part of your first pass you can maintain for each piece id the bounding box. That allows you to allocate the the images for the pieces to their proper dimensions.
You need a suitable convention to deal with border pixels: e.g. border pixels to the right belong to the piece if they have the same x-position, but are above they also belong to the piece.
Related
How can I draw a Bezier Line between two non-static DOM elements, like this:
The two lines should be drawn between the
<div class="brick small">Line starts here</div>
and the
<div class="brick small">Line ends here</div>
of this CodePen: https://codepen.io/anon/pen/XeamWe
Note that the boxes can be dragged. If one of the elements changes its position, the line should be updated accordingly.
If I'm not wrong I can't use a canvas, right? What can I use instead?
Let me point you toward the answer I beleve you're looking for, it's a dom element type called 'SVG' which is supported by most if not all web browsers of today (so you won't need to plug in anything external), in which you can draw lines, shapes, apply graphical filters much like in Photoshop and many other useful things, but the one to be pointed out here is the so called 'path', a shape that can consist of both straight lines with sharp corners, or curved lines (bezier) or both combined.
The easiest way to create such paths is to first draw them in for example Illustrator, save the shape in the SVG format, open that file in a text editor and pretty much just copy the generated markup code and paste it into your html, as it is supported there. This will result in the drawn shape to be displayed on your site. But in your case, you won't come around the a little bit complex structuring of the paths, because you wish to have control of it using javascript, so I would suggest first making a few simple paths in this way by exporting from Illustrator, study these in code, then manipulate their bezier values in javascript until you get the hang of how they work, once you've done that you will be able to create the accurate bezier shape you have in mind and (knowing the positions of the elements you want to connect) position them so that they connect your boxes.
Paths can even be decorated with markers, like an arrowhead in the end or beginning of the path, you can even design your own markers as you like them to look and much more if you would dig deeper into it.
Good luck! :)
I am looking to achieve something like this. A HTML view has a finite number of images (shown as red boxes in the image below). Are there any browser/jQuery APIs available today (cross-browser) which will let me calculate the dimensions of the remaining space (shown in green boxes) quickly? In the example shown below, it is easy to calculate the green area dimensions using simple geometry given the dimensions of the red boxes. But I am talking about very complex scenarios and complicated combination of images.
Appreciate any help. Thanks.
If you every images have absolute property, you can calculate dimension through top and left properties like $('#elementID').offset().top and $('#elementID').offset().left
From my experience working with DOM element dimensions, you cannot rely on them for exact values, and certainly can't really on them for the same values cross-browser. You can get OK results, but if you have complex scenarios then you will probably come undone at some point.
One way I have achieved similar things in the past is by drawing images to HTML5 Canvas. Using canvas you can have very fine-grained control. I have even iterated canvases pixel-by-pixel to get pixel perfect measurements of items on the canvas.
Check out this tutorial for a brief overview of drawing an image.
UPDATE
There is no easy way to do it. Using this method is low-level and will require you to use mathematics, and possibly byte-level image data from the canvas. However, if your problem is as complex as you suggest then you will have to get stuck in. When I did something similar I was also looking for an easy way to achieve what I wanted in the browser, then spent a month getting to grips with the canvas API, learning about byte-level colour data etc, but in then end I got what I needed, and ended up with something quite unique as it was difficult to achieve in a browser.
To get started, first I would say look at implementing a layered canvas by absolutely positioning multiple canvases on top of each other, then drawing a single image on each one. You already know the sizes of the images, and you can decide the coordinates of where to draw the image, so that's a start. In fact that may be all you need, you can track each image as you draw them by storing coords and dimensions, and you should be able to build up an accurate picture in numbers of where all your images are in 2D space.
Using those numbers you should then be able to calculate any empty spaces on there. However, that is a beyond me and probably a question for Mathematics Stack Exchange (which is actually down at the moment :D).
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.
I'm creating a planning tool for a game. Imagine two 2D static gun emplacements with different ranges and damage per second. I want to draw these ranges with different colours according to damage, in a scale similar to this http://www.celtrio.com/support/documentation/coverazone/2.1.0/ui.viewmode.heatmapcolorscale.html
I got that part working with CSS border radiuses. My problem is that if ranges overlap, the overlapping area doesn't show the combined damage.
I found heatmap.js http://www.patrick-wied.at/static/heatmapjs/ but it doesn't allow you to set a different radius for each point. I also can't find a way to turn off the gradient... the damage of these guns at its maximum range is the same at its minimum range. I realise that's sort of the point of a heatmap normally haha but I'm not too sure what I should be googling.
I had a think about a PHP solution which would create a greyscale image using varying levels of opacity to represent different damage. I'd then loop through all the pixels and recolour them according to the scale. But that would be far too slow. It needs to update in as close to realtime as possible as the user drags the guns around the screen.
There's probably a very simple way to do this, a CSS filter maybe, but I can't find anything. Any ideas? Thanks!
CSS is the wrong tool for this job -- you really ought to be doing stuff like this using SVG or Canvas. It'll be a lot easier to achieve complex graphical effects using a proper graphics system than trying to hack it with shapes created in CSS.
For example, in SVG, you would simply need to use the fill feature to fill each area with whatever colour you wanted. See an example SVG image here. It's an SVG Venn diagram where the overlap areas are completely different colours to the parent circles. Canvas has similar functionality.
You might also want to consider using a Javascript library such as RaphaelJS or PaperJS to help you with this. (using Canvas would imply that you're using some Javascript anyway, and it will make SVG easier to work with too).
However if you must do it using CSS, if you want elements to show through so the colours are merged when they overlay each other, then you'll want to use some sort of opacity effect.
Either opacity:0.5 or an rgba colour for the background.
That's as good as you'll get with CSS; you won't be able to get arbitrary colours in the overlap portions; just a combination of colours from the layered opacity effects.
If you look at the code of heatmap.js, you'll see that it works like this:
Paint circles onto a canvas, using a radial gradient from transparent to some percent opaque (depending on the strength of the point).
Color-map that grayscale image (converting each gray value to one of an array of 256 colors).
Your problem could be solved in the same way, but painting a circle of constant opacity and variable radius in step 1.
I have a canvas with image drawn to it.
When the user clicks on the image, I need to find the color region that the user clicked on. A region is defined as a set of 4-way connected pixels with the same color as the pixel that was clicked on.
I need the region in a form that I could use to set a clipping path on the canvas, so that I could fill the area with, say, a gradient, etc.
Are there efficient algorithms for finding a boundary? Something more optimal than flood fill algorithms (I do not need to fill, I just need to find a path around my region).
I believe the Moore Neighborhood tracing algorithm will do what you want. By definition, the Moore Neighborhood looks at 8-connectedness, but you should be able to easily adjust it to 4-connectedness. Your resulting regions will most likely be better if you test for 8-connectedness, but your application may have specific requirements.
Wikipedia has a good outline of the algorithm here. I've worked with this in the past and had great success--it's very fast.