Document flowchart in Raphael - javascript

I know how to draw a simple rectangle in Raphael and I understand the sense of all its parameters. For example, these parameters give a nice rectangle with width equal to 201 and height equal to 179
M0,0 L0,179 L210,179 L210,0 L0,0Z
But I do not want a simple rectangle, I want a document flowchart which should look like this
I know from here, that in Raphael I can draw curved lines, for example with these parameters:
M150,150 A100,70 0 0,0 250,220
But unfortunatelly, the book does not explain the sense of these parameters. I know what M means, but I do not know what A means and all the following coordinates.
So, how can I fix my initial rectangle coordinates to get a document flowchart?

Your missing piece here is the SVG Path Spec.
Your initial rectangle:
M0,0 L0,179 L210,179 L210,0 L0,0Z
...is read as "go to 0,0, then draw a line to 0,179, then draw a line to 210,179, then draw a line to 210,0, then draw a line to 0,0 and return to the start." (The last part, the Z, is a little superfluous, since we've already closed the path.)
You want to replace the second line – from 0,179 to 210,179 – with an arc. I'm not a designer but I'd spitball that maybe a Quadratic Bezier Curve would do the trick:
M0,0 L0,179 Q53,159 105,179 T210,179 L210,0 L0,0Z
That means, starting at the Q, "draw a quadratic Bezier curve from the start point [0,179] to 105,179 using 53,159 as the control point. Then draw another from 105,179 to 210,179 using a reflection of the last control point." I haven't tested this path, so you may need to tweak the control point to get the curve you want. (Increasing the y distance between the control point and 179 will make a more dramatic curve; decreasing it will make a more gentle curve.)
The Raphael documentation explains more about using paths in Raphael.

Related

Warp an SVG in JavaScript into an arc

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.

Cubic Bezier Curve between two points on a sphere in three.js

I'm letting the user click on two points on a sphere and I would then like to draw a line between the two points along the surface of the sphere (basically on the great circle). I've been able to get the coordinates of the two selected points and draw a QuadraticBezierCurve3 between the points, but I need to be using CubicBezierCurve3. The problem is is that I have no clue how to find the two control points.
Part of the issue is everything I find is for circular arcs and only deals with [x,y] coordinates (whereas I'm working with [x,y,z]). I found this other question which I used to get a somewhat-working solution using QuadraticBezierCurve3. I've found numerous other pages with math/code like this, this, and this, but I really just don't know what to apply. Something else I came across mentioned the tangents (to the selected points), their intersection, and their midpoints. But again, I'm unsure of how to do that in 3D space (since the tangent can go in more than one direction, i.e. a plane).
An example of my code: http://jsfiddle.net/GhB82/
To draw the line, I'm using:
function drawLine(point) {
var middle = [(pointA['x'] + pointB['x']) / 2, (pointA['y'] + pointB['y']) / 2, (pointA['z'] + pointB['z']) / 2];
var curve = new THREE.QuadraticBezierCurve3(new THREE.Vector3(pointA['x'], pointA['y'], pointA['z']), new THREE.Vector3(middle[0], middle[1], middle[2]), new THREE.Vector3(pointB['x'], pointB['y'], pointB['z']));
var path = new THREE.CurvePath();
path.add(curve);
var curveMaterial = new THREE.LineBasicMaterial({
color: 0xFF0000
});
curvedLine = new THREE.Line(path.createPointsGeometry(20), curveMaterial);
scene.add(curvedLine);
}
Where pointA and pointB are arrays containing the [x,y,z] coordinates of the selected points on the sphere. I need to change the QuadraticBezierCurve3 to CubicBezierCurve3, but again, I'm really at a loss on finding those control points.
I have a description on how to fit cubic curves to circular arcs over at http://pomax.github.io/bezierinfo/#circles_cubic, the 3D case is essentially the same in that you need to find out the (great) circular cross-section your two points form on the sphere, and then build the cubic Bezier section along that circle.
Downside: Unless your arc is less than or equal to roughly a quarter circle, one curve is not going to be enough, you'll need two or more. You can't actually model true circular curves with Bezier curves, so using cubic instead of quadratic just means you can approximate a longer arc segment before it starts to look horribly off.
So on a completely different solution note: if you have an arc command available, much better to use that than to roll your own (and if three.js doesn't support them, definitely worth filing a feature request for, I'd think)

Interconnected curved lines

Given a series of JSON co-ordinates typically in the format:
{from: {x:0, y:0}, to: {x:0, y:10}, ...}
I would like to draw a series of straight dotted paths which are connected with simple, fixed radius rounded corners. I have been looking at Slope Intercept Form to calculate the points along the straight line but I am a little perplexed as to the approach for calcualting the points along the (Bezier?) curves.
e.g. I want to draw curves between p1 and p2 and p3 and p4. Despite what the poor mockup might imply I am happy for the corners to be a fixed radius e.g. 10px
I would like to abstract out the drawing logic and therefore am seeking a generalised approach to returning a JavaScript point array which I can then render in a number of ways (hence I am avoiding using any inbuilt functions provided by SVG, Canvas etc).
What you want is a cubic bezier curve.
http://www.blackpawn.com/texts/splines/
Look at the first applet on this page. If A is p1, D is p2, the direction A-B is line 1's angle and the direction C-D is line 2's angle you can see how this gives you the properties you need - it starts at angle 1 and ends at angle 2 and is flush with the points.
So, to get your points C and D, one way to do this would be to take the line segment 1, copy it, place it starting at p1 - and say where the new line ends is B, and similar with line segment 2 and p2 for D. (And you could do things like have a factor that multiplies into the copied line segments' distance to make the curves stick out more or less... etc)
Then just do the math :)
http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
And once you have your equation for the curve, step through it with a delta t of the desired precision (e.g. every 0.1 of t, every 0.01...) and spit out every pair of points on the curve as a line segment.

How to convert SVG 'c' curve to a list of cubic bezier curve?

I have a path as follow:
d="m 0,0 38.913,455.481 c 7.122,83.37 6.816,164.779 13.005,236.077 18.924,218.078 232.099,308.663 268.399,493.918 16.874,86.119 -37.253,229.874 -42.144,323.022 -7.527,143.381 69.579,142.669 104.526,244.648"
I don't quite understand how it is represented.
I guess it is converted as a list of multiple simple cubic bezier curves, but how? What should i take as control points, start point, end point each time?
And what coordinates here exactly are relatives? And relative to what?
I am totally new to SVG graphics and (it seems to me that) w3 references doesn't give enough details on those points.
If it can help my goal here, is to represent this curve with javascript in a canvas point by point.
You seem to have cubic bezier curves, not quadratic ones. The specification text explains what the control points are and what they are relative to (the end point of the previous move/line/curve generally)

JavaScript Separating Axis Theorem

I'm trying to wrap my head around using the Separating Axis Theorem in JavaScript to detect two squares colliding (one rotated, one not). As hard as I try, I can't figure out what this would look like in JavaScript, nor can I find any JavaScript examples. Please help, an explanation with plain numbers or JavaScript code would be most useful.
Update: After researching lots of geometry and math theories I've decided to roll out a simplified SAT implementation in a GitHub repo. You can find a working copy of SAT in JavaScript here: https://github.com/ashblue/canvas-sat
Transforming polygons
First you have to transform all points of your convex polygons (squares in this case) so they are all in the same space, by applying a rotation of angle.
For future support of scaling, translation, etc. I recommend doing this through matrix transforms. You'll have to code your own Matrix class or find some library that has this functionality already (I'm sure there are plenty of options).
Then you'll use code in the vain of:
var transform = new Matrix();
transform.appendRotation(alpha);
points = transform.transformPoints(points);
Where points is an array of Point objects or so.
Collision algorithm overview
So that's all before you get to any collision stuff. Regarding the collision algorithm, it's standard practice to try and separate 2 convex polygons (squares in your case) using the following steps:
For each polygon edge (edges of both polygon 0 and polygon 1):
Classify both polgyons as "in front", "spanning" or "behind" the edge.
If both polygons are on different sides (1 "in front" and 1 "behind"), there is no collision, and you can stop the algorithm (early exit).
If you get here, no edge was able to separate the polgyons: The polygons intersect/collide.
Note that conceptually, the "separating axis" is the axis perpendicular to the edge we're classifying the polygons with.
Classifying polygons with regards to an edge
In order to do this, we'll classify a polygon's points/vertices with regards to the edge. If all points are on one side, the polygon's on that side. Otherwise, the polygon's spanning the edge (partially on one side, partially on the other side).
To classify points, we first need to get the edge's normal:
// this code assumes p0 and p1 are instances of some Vector3D class
var p0 = edge[0]; // first point of edge
var p1 = edge[1]; // second point of edge
var v = p1.subtract(p0);
var normal = new Vector3D(0, 0, 1).crossProduct(v);
normal.normalize();
The above code uses the cross-product of the edge direction and the z-vector to get the normal. Ofcourse, you should pre-calculate this for each edge instead.
Note: The normal represents the separating axis from the SAT.
Next, we can classify an arbitrary point by first making it relative to the edge (subtracting an edge point), and using the dot-product with the normal:
// point is the point to classify as "in front" or "behind" the edge
var point = point.subtract(p0);
var distance = point.dotProduct(normal);
var inFront = distance >= 0;
Now, inFront is true if the point is in front or on the edge, and false otherwise.
Note that, when you loop over a polygon's points to classify the polygon, you can also exit early if you have at least 1 point in front and 1 behind, since then it's already determined that the polygon is spanning the edge (and not in front or behind).
So as you can see, you still have quite a bit of coding to do. Find some js library with Matrix and Vector3D classes or so and use that to implement the above. Represent your collision shapes (polygons) as sequences of Point and Edge instances.
Hopefully, this will get you started.

Categories