Javascript spline/arc interpolation for dummies - javascript

I'm hitting a wall in some work I'm doing; I've searched on here for many, many threads regarding numerical interpolation and have found them either to contain too much math for me to interpret them, or that their coding solutions have been too specific to be generalized to the task I'm working on.
I have sets of coordinates (currently float x, y distances around an 0,0 origin point) which I am, via Javascript, transposing to latitude, longitude coordinates. (The transposition is easy, so don't worry about that — I'm just telling you that to make the application more clear.)
For the rest, refer to the below graphic:
The dots are the coordinates. (They are generated algorithmically.) The blue line shows a simple, linear interpolation between the points. What I want is something more like the red line. It's not quite an ellipse — you can see that around the first coordinates, it forms arcs that are almost like a perfect circle.
Note that some of the points are negative in various places. Note that the lines between them must be draw sequentially — an algorithm that generates the points out of sequence will make things much harder for this application.
What I'd like is to have a Javascript function that would let me do the following: specify two sequential points from this series (x1,y1; x2,y2), specify a number of interpolated steps in between (say, 5 to 10), and then output an array of coordinates that would, when linked linearly (that is, when a straight line is drawn between them), look something like the red line above (with the degree of curviness obviously constrained by the number of steps).
Of all of the many spline functions out there, which of these satisfies these requirements? The mathematical precision of the spline function is less important to me than the simplicity of adapting it to this purpose, and to its aesthetic output. I would be fine with manually setting the eccentricity/circle-ness of each individual set of coordinates, too (so the first ones really should be very circle-like, but the latter should not be).
Put another way, I am looking for a simple function for getting the interior coordinates of an arc between any two sets of coordinates. EDIT to clarify that I'm fine with there being a third variable that sets the inclination of the arc (positive or negative) and its eccentricity or whatever. The function doesn't necessarily have to know where it is on the diagram above, as I will know that. I'm just looking for something that can help me interpolate the arc points.
I think I understand the parameters of the problem; what I'm bad at is geometry and turning mathematical answers into usable Javascript. (Because I don't really understand the math.)
I have already looked at Midpoint circle algorithm and found it difficult to adapt to this purpose (because of the need for sequentiality and non-integer coordinates); I've also looked at a variety of spline interpolation methods and found them way too complicated for my dummy-self to make sense of.
Any pointers, help, and code would be appreciated!

Related

Is it possible to convert svg path with stroke to svg path without any styles and properties? [duplicate]

This question already has answers here:
svg: generate 'outline path'
(2 answers)
Closed 5 years ago.
I want to convert a stroked path to a filled object. (Programmatically, in JavaScript.)
The line is just a simple curved line, a sequence of coordinates. I can render this line as a path, and give it a stroke of a certain thickness... but I'm trying to get a filled shape rather than a stroked line, so that I can do further modifications on it, such as warping it, so the resulting 'stroke' might vary in thickness or have custom bits cut out of it (neither of these things are possible with a real SVG stroke, as far as I can tell).
So I'm trying to manually 'thicken' a line into a solid shape. I can't find any function that does this – I've looked through the docs of D3.js and Raphaël, but no luck. Does anyone know of a library/function that would do this?
Or, even better: if someone could explain to me the geometry theory about how I would do this task manually, by taking the list of line coordinates I have and working out a new path that effectively 'strokes' it, that would be amazing. To put it another way, what does the browser do when you tell it to stroke a path – how does it work out what shape the stroke should be?
There has been a similar question recently:
svg: generate 'outline path'
All in all, this is a non-trivial task. As mentioned in my answer to the linked question, PostScript has a command for generating paths that produce basically the same output as a stroke, called strokepath. If you look at what Ghostscript spits out when you run the code I posted at the linked question, it's pretty ugly. And even Inkscape doesn't really do a good job. I just tried Path => Outline stroke in Inkscape (I think that's what the English captions should say), and what came out didn't really look the same as the stroked path.
The "simplest" case would be if you only have non-self-intersecting polylines, polygons or paths that don't contain curves because in general, you can't draw exact "parallel" Bézier curves to the right and the left of a non-trivial Bézier curve that would delimit the stroked area - it's mathematically non-existent. So you would have to approximate it one way or the other. For straight line segments, the exact solution can be found comparatively easily.
The classic way of rendering vector paths with curves/arcs in them is to approximate everything with a polyline that is sufficiently smooth. De Casteljau's Algorithm is typically used for turning Bézier curves into line segments. (That's also basically what comes out when you use the strokepath command in Ghostscript.) You can then find delimiting parallel line segments, but have to join them correctly, using the appropriate linejoin and miterlimit rules. Of course, don't forget the linecaps.
I thought that self-intersecting paths might be tricky because you might get hollow areas inside the path, i.e. the "crossing area" of a black path might become white. This might not be an issue for open paths when using nonzero winding rule, but I'd be cautious about this. For closed paths, you probably need the two "delimiting" paths to run in opposite orientation. But I'm not sure right now whether this really covers all the potential pitfalls.
Sorry if I cause a lot of confusion with this and maybe am not of much help.
This page has a fairly good tutorial on bezier curves in general with a nice section on offset curves.
http://pomax.github.io/bezierinfo/
A less precise but possibly faster method can be found here.
http://seant23.wordpress.com/2010/11/12/offset-bezier-curves/
There is no mathematical answer, because the curve parallel to a bezier curve is not generally a bezier curve. Most methods have degenerate cases, especially when dealing with a series of curves.
Think of a simple curve as one with no trouble spots. No cusps, no loops, no inflections, and ideally a strictly increasing curvature. Chop up all the starting curves into these simple curves. Find all the offset curves of these simple curves. Put all the offset curves back together dealing with gaps and intersections. Quadratic curves are much more tractable if you have the option to work with them.
I think most browsers do something similar to processingjs, as they have degenerate cases even with quadratic curves. For example, look at the curve 200,300 719,301 500,300 with a thickness of 100 or more.
The standard method is the Tiller-Hanson algorithm (Offsets of Two-Dimensional Profiles, 1984, which irritatingly is not on line for free) which creates a good approximation. The idea is that because the control points of each Bezier curve lie on lines tangent to the start and end of the curve, a parallel curve will have the same property. So we offset the start and the end of the curve, then find new control points using these intersections. However, that gives very bad results for sharp curves, so the first step is to bisect the original curve, which is very easy to do to Bezier curves, until it turns through a sufficiently small angle.
Other refinements are needed to deal with (i) intersections between the parallels, on the inside of each vertex; (ii) inserting an arc of a circle to fill the gap on the outside of each vertex; and (iii) adding end-caps - square, butt or circular.
Tiller-Hanson is difficult to implement, but there's a good open-source implementation in the FreeType library, in ftstroke.c (http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/base/ftstroke.c).
I'm sorry to say that it can be quite difficult to integrate this code, but I have used it successfully, and it works well.

Plotting vector to a line

I'm working on a simulation in which I have an aircraft and I need to be able to fly to a starting point of a line. When arriving at that point, it needs to be aligned with the angle of the line. The starting point can be either point on the line. It is similar to simulating an aircraft landing on a runway but I do not need to factor in altitude.
example
I have the following information:
aircraft vector
latitude/longitude
heading
speed
destination line (two points)
point 1 latitude/longitude
point 2 latitude/longitude
Aircraft position is updated every 0.5 second and is limited to 3 degrees per second turn rate.
I am currently using Jean Brouwers python interpretation of geodesy tools (https://github.com/mrJean1/PyGeodesy) for a lot of my trigonometric and vector-based methods.
I'm looking for a way to plot my aircraft to the destination line with the proper heading.
Any help with the rationale or math would be greatly appreciated. It's been a long time since I have done any complex trig.
Thanks
It looks like a problem in a field of Optimal control, if you really want to deal with plane speed and position, not just to build a smooth graph connecting two or three dots.
This is a theory for finding control functions that can bring mathematical systems from one state to another.
Your goal is to represent everything as a system of variables: state variables x(t) (position in rectangular or polar coordinates, direction, speed) and control variables u(t) (throttle position, steering position). Then you describe dependencies between them as a system of differential equations x'(t) = f(x(t), u(t)).
And for that mathematical system, applying constraints s on your control variables and providing sets of target values of state variables, you synthesize a control functions for control variables. Synthesizing relies heavily on Pontryagin's maximum principle.
Check out simple examples of applying the theory, if you can.
Of course, it is a general approach which is used in real aviation and spaceships... Maybe you don't really need this and something simpler's gonna fit :)

How to detect collision in not easily polygon divided body

Say we are coding something in Javascript and we have a body, say an apple, and want to detect collision of a rock being thrown at it: it's easy because we can simply consider the apple as a circle.
But how about we have, for example, a "very complex" fractal? Then there is no polygon similar to it and we also cannot break it into smaller polygons without a herculean amount of effort. Is there any way to detect perfect collision in this case, as opposed to making something that "kind" of works, like considering the fractal a polygon (not perfect because there will be collision detected even in blank spaces)?
You can use a physics editor
https://www.codeandweb.com/physicseditor
It'll work with most game engines. You'll have to figure how to make it work in JS.
Here's an tutorial from the site using typescript - related to JS
http://www.gamefromscratch.com/post/2014/11/27/Adventures-in-Phaser-with-TypeScript-Physics-using-P2-Physics-Engine.aspx
If you have coordinates of the polygons, you can make an intersection of subject and clip polygons using Javascript Clipper
The question doesn't provide too much information of the collision objects, but usually anything can be represented as polygon(s) to certain precision.
EDIT:
It should be fast enough for real time rendering (depending of complexity of polygons). If the polygons are complex (many self intersections and/or many points), there are many methods to speedup the intersection detection:
reduce the point count using ClipperLib.JS.Lighten(). It removes the points that have no effect to the outline (eg. duplicate points and points on edge)
get first bounding rectangles of polygons using ClipperLib.JS.BoundsOfPath() or ClipperLib.JS.BoundsOfPaths(). If bounding rectangles are not in collision, there is no need to make intersection operation. This function is very fast, because it just gets min/max of x and y.
If the polygons are static (ie their geometry/pointdata doesn't change during animation), you can lighten and get bounds of paths and add polygons to Clipper before animation starts. Then during each frame, you have to do only minimal effort to get the actual intersections.
EDIT2:
If you are worried about the framerate, you could consider using an experimental floating point (double) Clipper, which is 4.15x faster than IntPoint version and when big integers are needed in IntPoint version, the float version is 8.37x faster than IntPoint version. The final speed is actually a bit higher because IntPoint Clipper needs that coordinates are first scaled up (to integers) and then scaled down (to floats) and this scaling time is not taken into account in the above measurements. However float version is not fully tested and should be used with care in production environments.
The code of experimental float version: http://jsclipper.sourceforge.net/6.1.3.4b_fpoint/clipper_unminified_6.1.3.4b_fpoint.js
Demo: http://jsclipper.sourceforge.net/6.1.3.4b_fpoint/main_demo3.html
Playground: http://jsbin.com/sisefo/1/edit?html,javascript,output
EDIT3:
If you don't have polygon point coordinates of your objects and the objects are bitmaps (eg. png/canvas), you have to first trace the bitmaps eg. using Marching Squares algorithm. One implementation is at
https://github.com/sakri/MarchingSquaresJS.
There you get an array of outline points, but because the array consists of huge amount of unneeded points (eg. straight lines can easily be represented as start and end point), you can reduce the point count using eg. ClipperLib.JS.Lighten() or http://mourner.github.io/simplify-js/.
After these steps you have very light polygonal representations of your bitmap objects, which are fast to run through intersection algorithm.
You can create bitmaps that indicate the area occupied by your objects in pixels. If there is intersection between the bitmaps, then there is a collision.

How would I implement the shoelace theorem to find the areas of multiple convex polygons created from intersecting lines?

I am creating a piece of javascript code where it's necessary to identify every polygon created from a number of randomly generated intersecting lines. The following screenshot will give a better explanation of what I'm talking about:
Now, I need to calculate the area of each polygon and return the largest area. The approach I'm taking is to identify every intersection (denoted with red dots) and treat them as a vertex of whichever polygon(s) they belong to. If I can somehow identify which polygon(s) each vertex/intersection belongs to, then arrange the vertices of each polygon in a clockwise direction then it would be simple to apply the shoelace theorem to find the area of each polygon.
However, I'm afraid that I'm completely lost and have tried various (failed) methods to achieve this. What is the best way to compile a list of clockwise-arranged vertices for each polygon? I'm working on acquiring which segments are associated with every given intersection, and I think this is a step in the right direction but I don't know where to go from there. Does this require some vector work?
I can think of one possibility. Here I've labeled each of the vertices.
(source: i.imm.io)
I'm assuming that if you know the lines involved and their intersections, you can find all the line segments that intersect at a particular point. So lets start with a particular point, say K, and a directed segment, IK. Now we have four directed segments that lead from the end of that, KI, KJ, KL, and KM. We are interested only in the two that are closest to, but not on, the line KI. Let's focus on KM, although you can do the same thing with KJ.
(Note that if there are more than two lines intersecting at the point, we can still find the two that are closest to the line, generally one forming a positive angle with the initial segment, the other a negative one.)
We notice that IKM is a positive angle, and then examine the segments containing M, choosing the one with the smallest positive angle with KM, in this case MF, do this again at F (although there are only two choices here) to get FG, and then GH, and then HI, which completes one polygon, the hexagon IKMFGH.
Going back to our original segment of IK, we look at our other smallest angle, IKJ, and do a similar process to find the triangle IKJ. We have now found all the polygons containing IK.
Then of course you do this again, each other segment. You will need to remove duplicates, or be smarter about not continuing to analyze a path when you can see it will be a duplicate. (Each angle will be in at most one polygon, so if you see an angle already recorded, you can skip it.)
This would not work if your polygons weren't convex, but if they are made from lines cut through a rectangle, I'm pretty sure they will always be convex.
I haven't actually tried to code this, but I'm pretty sure it will work.
Two methods I can think of that are probably not the most efficient but should help out:
You can figure out the set of points that make up the polygon containing an arbitrary point by drawing an imaginary line from the arbitrary point to each other point, the ones that draw a line not intersecting any lines in your image are the vertices that make the convex polygon you care about. The problem with this method is I can't think of any particularly good method to reliably get all of the polygons (since you only care about the largest perhaps random/periodic sampling will suffice?)
For each possible polygon check to see if there is any line segment that lies within that polygon (a line segment that bisects 2 edges of the polygon) and if there is remove that polygon from your set. At the end you should only be left with the ones you care about. This method is very slow though.
If my explanations were unclear I can update with a couple pictures to help explain.
Hope this helps!

I'd like to know how WebKitCSSMatrix actually works

Apple's official documentation says:
WebKitCSSMatrix objects represent a 4x4 homogeneous matrix for 3D transforms or a vector for 2D transforms. You can use these objects to manipulate matrices in JavaScript. For example, you can multiply, translate, and scale matrices.
I'm a glorified designer, not an engineer, so I'm assuming that's the reason why I can't make any sense of that description. Please, can somebody point me in the right direction to understand how this matrix and/or vectors work?
Whew, this is the most difficult question I've attempted to answer. The short answer is that, as web designers, we don't have the vocabulary to express 3d transformations. In order to explain it to you in a comprehensible way I'd have to use math concepts which I don't understand myself.
If you'd like to investigate further you can take a look at:
http://www.eleqtriq.com/2010/05/css-3d-matrix-transformations/
But, I can explain it visually.
http://duopixel.com/stack/webkitmatrix/ (you'll have to view this under Safari 5 w/Snow Leopard, or an iPad, or course).
What you're seeing is just an interface to the 16 values webkitCSSMatrix, the sliders that seem to do nothing are related to the z axis, which I suspect would be visible if we had more objects in the 3d canvas.
Edit: after studying the link I placed before, I noticed the original author has done the same example before, doh! http://www.eleqtriq.com/wp-content/static/demos/2010/css3d/matrix3dexplorer.html
Even though it's for ActionScript, check out Understanding the Transformation Matrix in Flash 8. It's got pretty pictures, too :)
Before getting into how transformation matrices (matrices is plural of matrix) work, it is important to understand what a matrix is. A matrix is a rectangular array (or table) of numbers consisting of any number of rows and columns. A matrix consisting of m rows and n columns is known as an m x n matrix. This represents the matrix's dimensions. You'll commonly seen matrices with numbers in rows and columns surrounded by two large bracket symbols.
...
Affine transformations are transformations that preserve collinearity and relative distancing in a transformed coordinate space. This means points on a line will remain in a line after an affine transformation is applied to the coordinate space in which that line exists. It also means parallel lines remain parallel and that relative spacing or distancing, though it may scale, will always maintain at a consistent ratio. Affine transformations allow for repositioning, scaling, skewing and rotation. Things they cannot do include tapering or distorting with perspective. If you're ever worked with transforming symbols in Flash, you probably recognize these qualities.
(source: senocular.com)

Categories