Warp an SVG in JavaScript into an arc - javascript

I saw a d3 helper function which can create an svg arc: making an arc in d3.js
Is there a way to bend an existing svg into an arc in d3.js? If not, how can it be done in JavaScript? The initial image could be a square with negative space inside that makes a silhouette of something like a cat.
I included a drawing of what I want. I eventually want to make more and create a ring, and then concentric rings of smaller transformations.

I think conformal mapping is the way to go. As an example, I have started with the original square source and the circularly arranged (and appropriately warped) squares using conformal mapping. See the Circular Image and the Corresponding Square Image. Note, however, that I first converted the SVG source into a png image, and then applied conformal mapping transformation to each pixel in the png image. If anyone has a method of mapping entirely in the SVG domain [where the source uses only straight lines and bezier curves], pl. let us know!
I am not able to provide the code -- it is too complex and uses proprietary libraries). Here is a way to do it.
In order to compute the conformal mapping, I used a complex algebra library. JEP is one example. For each pixel in the OUTPUT image, you set Z = (x, y) where (x, y) are the coordinates of the pixel and Z is a complex variable with real part x and imaginary part y. Then you compute NEWZ = f(Z) where f is any function you want. for circle, I used an expression such as "(ln(Z*1)/pi)*6-9" where the log (ln) provides circularity, the 6 implies 6 bent squares in a circle and the -9 is a scaling factor to center and place the image. From the (X, Y) values of the NEWZ, you look up the old image to find the pixel to place in the new image. When the (X, Y) values are outside the size of the old image, I just use tiling of the old image to determine the pixel. When X and Y are fractional (non-integer) you average the neighbors in a weighted way.

Related

Voxelizing in three.js — particle materials from Textures

I have an image that I am mapping to a PlaneGeometry using the TextureLoader#load() — it renders nicely as long as my camera is not looking "along" the plane, in which case it (of course) is of zero-width, and disappears from view.
I'm trying to figure out how to give the image some depth, so my current ideas are:
Generate a ParticleSystem where the particle at (x, y) shares its color with the (greyscale) pixel in the image at (x, y) — effectively, making each pixel a camera-facing billboard
"Cube-ifying" each pixel in the image so it takes up some space in the z direction. So a pixel at (x, y) becomes a cube at (x, y, z) with some size in all three dimensions.
Both allow me to look 'along' the edge of the image and see something, whereas the plane is invisible.
My first question is, is this possible, and second, what is the name for this voxelization technique? Is it natively supported in three.js?
Very happy to provide more info or some basic code if that's at all helpful.
It is definite possible.
The idea with the cubes should be doable in every decent 3d-engine.
Its just a matter of cloning / instancing cubes, and than position and color them accordingly.
Not sure if there is a name for this technique.
Also not sure about particle-systems in threejs, but i suppose that would be a option too.
My real answer is this: Use Heightmaps
They kind of do exactly what you want. A heightmap is a greyscale texture, and for each verticle of the geometry it is mapped on, it will offset the y-component of the verticles positions according to the grayscale (white = no offset, black = full offset)
http://danni-three.blogspot.de/2013/09/threejs-heightmaps.html

Find where a bisectrix interesects a specific area of an Image

First of all I am using javascript and KineticJS.
I have a picture of an xray(so you can picture what kind of colors its using) and the picture is a profile picture of the scull like these. I have some lines that are formed after users clicks at some specific points, which some of them intersect. In a pair of them I need to know when the bisectrix of the angle formed by the two intersecting lines, intersect with a specific part of the scull that is when the bone starts (which is greyer i think) My question is there a good way of checking this? I mean Suppoze i take each point on my bisectrix line and check the color of the pixels? How can I be sure since xrays might differ(film brightness etc). Could you give me a suggestion or lead me to somewhere?
Your question is a bit confusing.
If 2 lines intersect then 4 angles are created and therefore 4 bisecting lines are created.
Anyway here's how to get started...
Once you determine which points are interesting, you can use context.getImageData to fetch the rgba values of the pixels at those points.
Then convert each rgba pixel color to hsl format. Hsl format separates the Hue, Saturation & Lightness of a color.
Bones & teeth appear lighter so you can compare lightness values to discover bone/teeth.
[ Addition: Calculating points along the bisecting line ]
If you know the intersection point of 2 lines [x,y] and you know the angle you're interested in (radianAngle), then you can compute a point at distance (d) along the line that bisects that angle like this:
var lineX = x + d * Math.cos(radianAngle);
var lineY = y + d * Math.sin(radianAngle);
Then you can use the data from getImageData to fetch the rgba color at point [lineX,lineY]. Then convert to the hsl format and use the Light value to determine if [lineX,lineY] is over the lighter bone.

How to curl paths into spiral on hover using Raphael JS

I have a set of Raphael paths that I want to animate when a separate path is hovered over.
The client sent an SVG illustration that I had converted into Raphael code. This is just a small section of the larger image.
What I'm trying to do is as follows:
starting canvas
Start with a set of path objects in a line. When you hover over the red path they animate in a spiral until they form
ending canvas
I've done some research, and I think that I'm going to have to animate each circle along a hidden path that depicts the arcs they have to move to get to the final spiral shape (Animate along a path), but I'm not sure if this is the most efficient way to create this animation.
On top of that, I'm not really sure how to calculate the angle and size of the hidden paths the circles would be following. What is going to be the best way to create this animation?
Thanks!
I think moving each circle along a hidden path is easiest way.
I would suggest to create a new SVG file in InkScape vector editor, draw circles in start and end positions and then connect them with arcs. Save the file. Then open the file in any text editor and copy all data to your JS code (copy path's "d" parameter and coordinates of circles).
It's been more than one year since it's asked but maybe it might help other people.
Using simple algebra thought in high school you can define two functions: linear and spiral.
function linear(i){
x = i*15;
y = x;
return {cx:x+offset,cy:y+offset};
}
function spiral(i){
r = 50 - i*5;
x = r*Math.cos(i);
y = r*Math.sin(i);
return {cx:x+offset,cy:y+offset};
}
This is just a 5 min fiddling, so it might seem cheap. Of course, you can define better algorithms using transform functions.
jsfiddle here

How to Draw line in 3D rectangle based on x,y and z?

I would like draw 3D points represented in image to 3D rectangle. Any idea how could I represent these in x,y and z axis
Here projection type is orthographic.
Thanks
Okay. Let's look at a simple example of what you are trying to accomplish it, and why this is such a complicated problem.
First, lets look a some projection functions. You need a way to mathematically describe how to transform a 3D (or higher dimensional) point into a 2D space (your monitor), or a projection.
The simpiest to understand is a very simple dimetric projection. Something like:
x' = x + z/2;
y' = y + z/4;
What does this mean? Well, x' is you x coordinate 2D projection: for every unit you move backwards in space, the projection will move that point half that many units to the right. And y' represents that same projection for your y coordinate: for every unit you move backwards in space, the projection will move that point a quarter unit up.
So a point at [0,0,0] will get projected to a 2d point of [0,0]. A point at [0,0,4] will get projected to a 2d point of [2,1].
Implemented in JavaScript, it would look something like this:
// Dimetric projection functions
var dimetricTx = function(x,y,z) { return x + z/2; };
var dimetricTy = function(x,y,z) { return y + z/4; };
Once you have these projection functions -- or ways to translate from 3D space into 2D space -- you can use them to start draw your image. A simple example of that using js canvas. First, some context stuff:
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
Now, lets make a little helper to draw a 3D point:
var drawPoint = (function(ctx,tx,ty, size) {
return function(p) {
size = size || 3;
// Draw "point"
ctx.save();
ctx.fillStyle="#f00";
ctx.translate(tx.apply(undefined, p), ty.apply(undefined,p));
ctx.beginPath();
ctx.arc(0,0,size,0,Math.PI*2);
ctx.fill();
ctx.restore();
};
})(ctx,dimetricTx,dimetricTy);
This is pretty simple function, we are injecting the canvas context as ctx, as well as our tx and ty functions, which in this case our the dimetric functions we saw earlier.
And now a polygon drawer:
var drawPoly = (function(ctx,tx,ty) {
return function() {
var args = Array.prototype.slice.call(arguments, 0);
// Begin the path
ctx.beginPath();
// Move to the first point
var p = args.pop();
if(p) {
ctx.moveTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
// Draw to the next point
while((p = args.pop()) !== undefined) {
ctx.lineTo(tx.apply(undefined, p), ty.apply(undefined, p));
}
ctx.closePath();
ctx.stroke();
};
})(ctx, dimetricTx, dimetricTy);
With those two functions, you could effectively draw the kind of graph you are looking for. For example:
// The array of points
var points = [
// [x,y,z]
[20,30,40],
[100,70,110],
[30,30,75]
];
(function(width, height, depth, points) {
var c = document.getElementById("cnvs");
var ctx = c.getContext("2d");
// Set some context
ctx.save();
ctx.scale(1,-1);
ctx.translate(0,-c.height);
ctx.save();
// Move our graph
ctx.translate(100,20);
// Draw the "container"
ctx.strokeStyle="#999";
drawPoly([0,0,depth],[0,height,depth],[width,height,depth],[width,0,depth]);
drawPoly([0,0,0],[0,0,depth],[0,height,depth],[0,height,0]);
drawPoly([width,0,0],[width,0,depth],[width,height,depth],[width,height,0]);
drawPoly([0,0,0],[0,height,0],[width,height,0],[width,0,0]);
ctx.stroke();
// Draw the points
for(var i=0;i<points.length;i++) {
drawPoint(points[i]);
}
})(150,100,150,points);
However, you should now be able to start to see some of the complexity of your actual question emerge. Namely, you asked about rotation, in this example we are using an extremely simple projection (our dimetric projection) which doesn't take much other than an oversimplified relationship between depth and its influences on x,y position. As the projections become more complex, you need to know more about your relationship/orientation in 3D space in order to create a reasonable 2D projection.
A working example of the above code can be found here. The example also includes isometric projection functions that can be swapped out for the dimetric ones to see how that changes the way the graph looks. It also does some different visualization stuff that I didn't include here, like drawing "shadows" to help "visualize" the actual orientation -- the limitations of 3D to 2D projections.
It's complicated, and even a superficial discussion is kind of beyond the scope of this stackoverflow. I recommend you read more into the mathematics behind 3D, there are plenty of resources, both online and in print form. Once you have a more solid understanding of the basics of how the math works then return here if you have a specific implementation question about it.
What you want to do is impossible to do using the method you've stated - this is because a box - when rotated in 3 dimensions won't look anything like that diagram of yours. It will also vary based on the type of projection you need. You can, however get started using three.js which is a 3D drawing library for Javascript.
Hope this helps.
How to Draw 3D Rectangle?
posted in: Parallelogram | updated on: 14 Sep, 2012
To sketch 3 - Dimensional Rectangle means we are dealing with the figures which are different from 2 – D figures, which would need 3 axes to represent them. So, how to draw 3D rectangle?
To start with, first make two lines, one vertical and another horizontal in the middle of the paper such that they represent a “t” letter of English. This is what we need to draw for temporary use and will be removed later after the construction of the 3 – D rectangle is complete. Next we draw a Square whose measure of each side is 1 inch. Square must be perfect in Geometry so that 90 degree angles that are formed at respective corners are exact in measure. Now starting from upper right corner of the square we draw a line segment that will be stretched to a measure of 2 inches in the direction at an angle of 45 degrees. Similarly, we repeat the procedure by drawing another Line Segment from the upper left corner of the square and stretching it to 2 inches length in the direction at an angle of 45 degrees. These 2 line segments are considered to be the diagonals with respect to the horizontal line that we drew temporarily in starting. Also these lines will be parallel to each other. Next we draw a line that joins the end Point of these two diagonals.
Next starting from the very right of the 2 inch diagonal end point, draw a line of measure 1 inch that is supposed to be perpendicular to the temporary horizontal line. Next we need to join the lower left corner of the square with end point of the last 1’’ line we drew in 4th step and finally we get our 3 - D rectangular. Now we can erase our initial “t”. This 3- D rectangle resembles a Cuboid.

Pixel Perfect Collision Detection in HTML5 Canvas

I want to check a collision between two Sprites in HTML5 canvas. So for the sake of the discussion, let's assume that both sprites are IMG objects and a collision means that the alpha channel is not 0. Now both of these sprites can have a rotation around the object's center but no other transformation in case this makes this any easier.
Now the obvious solution I came up with would be this:
calculate the transformation matrix for both
figure out a rough estimation of the area where the code should test (like offset of both + calculated extra space for the rotation)
for all the pixels in the intersecting rectangle, transform the coordinate and test the image at the calculated position (rounded to nearest neighbor) for the alpha channel. Then abort on first hit.
The problem I see with that is that a) there are no matrix classes in JavaScript which means I have to do that in JavaScript which could be quite slow, I have to test for collisions every frame which makes this pretty expensive. Furthermore I have to replicate something I already have to do on drawing (or what canvas does for me, setting up the matrices).
I wonder if I'm missing anything here and if there is an easier solution for collision detection.
I'm not a javascript coder but I'd imagine the same optimisation tricks work just as well for Javascript as they do for C++.
Just rotate the corners of the sprite instead of every pixel. Effectively you would be doing something like software texture mapping. You could work out the x,y position of a given pixel using various gradient information. Look up software texture mapping for more info.
If you quadtree decomposed the sprite into "hit" and "non-hit" areas then you could effectively check to see if a given quad tree decomposition is all "non-hit", "all hit" or "possible hit" (ie contains hits and non-hit pixels. The first 2 are trivial to pass through. In the last case you then go down to the next decomposition level and repeat the test. This way you only check the pixels you need too and for large areas of "non-hit" and "hit" you don't have to do such a complex set of checks.
Anyway thats just a couple of thoughts.
I have to replicate something I already have to do on drawing
Well, you could make a new rendering context, plot one rotated white-background mask to it, set the compositing operation to lighter and plot the other rotated mask on top at the given offset.
Now if there's a non-white pixel left, there's a hit. You'd still have to getImageData and sift through the pixels to find that out. You might be able to reduce that workload a bit by scaling the resultant image downwards (relying on anti-aliasing to keep some pixels non-white), but I'm thinking it's probably still going to be quite slow.
I have to test for collisions every frame which makes this pretty expensive.
Yeah, I think realistically you're going to be using precalculated collision tables. If you've got space for it, you could store one hit/no hit bit for every combination of sprite a, sprite b, relative rotation, relative-x-normalised-to-rotation and relative-y-normalised-to-rotation. Depending on how many sprites you have and how many steps of rotation or movement, this could get rather large.
A compromise would be to store the pre-rotated masks of each sprite in a JavaScript array (of Number, giving you 32 bits/pixels of easily &&-able data, or as a character in a Sring, giving you 16 bits) and && each line of intersecting sprite masks together.
Or, give up on pixels and start looking at eg. paths.
Same problem, an alternative solution. First I use getImageData data to find a polygon that surrounds the sprite. Careful here because the implementation works with images with transparent background that have a single solid object. Like a ship. The next step is Ramer Douglas Peucker Algorithm to reduce the number of vertices in the polygon. I finally get a polygon of very few vertices easy and cheap to rotate and check collisions with the other polygons for each sprite.
http://jsfiddle.net/rnrlabs/9dxSg/
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = document.getElementById("img");
context.drawImage(img, 0,0);
var dat = context.getImageData(0,0,img.width, img.height);
// see jsfiddle
var startPixel = findStartPixel(dat, 0);
var path = followPath(startPixel, dat, 0);
// 4 is RDP epsilon
map1 = properRDP(path.map, 4, path.startpixel.x, path.startpixel.y);
// draw
context.beginPath();
context.moveTo(path.startpixel.x, path.startpixel.x);
for(var i = 0; i < map.length; i++) {
var p = map[i];
context.lineTo(p.x, p.y);
}
context.strokeStyle = 'red';
context.closePath();
context.stroke();

Categories