I'm working on a project in paper.js where I need to create new paths based on the intersection, difference and union of two others. I did some digging and found the mathematical function that interpolates a cubic bezier spline, but I was wondering if there were any javascript libraries that did svg-like vector arithmetic. If anything, I'll copy inkscape's and convert it to javascript, but you never know.
Anyway, the mathematical function for interpolating cubic beziers is as follows:
Pointx = (Ax * percent^3) + (Bx * 3 * (percent^2 * (1-percent))) + (Cx * 3 * (percent * (1-percent)^2)) + (Dx * (1-percent)^3)
Pointy = (Ay * percent^3) + (By * 3 * (percent^2 * (1-percent))) + (Cy * 3 * (percent * (1-percent)^2)) + (Dy * (1-percent)^3)
Where A, B, C and D are the points for the curve. A is the start, D is the end, and B and C are the "control points" that manipulate the curvature between A and D. The percent is how far along the curve to calculate on a scale from 0 to 1.
So it would be pretty trivial coming up with an interpolation function that returns a point for a provided bezier and a percentage along the bezier. Finding the inverse - a percentage(s) for a given point (or x value or y value) would be difficult. Or even more difficult, where two beziers intersect (I'm not very good at math). I'm hoping that's what inkscape's functions provide.
Are there any javascript libraries that can do this kind of vector interpolation quickly? If not, I'll post the algorithm I come up with here.
Thank you!
What you are looking for is something called Boolean Operations on Polygons
Paper.js seems to now use fairly nice BoolOps and they deal directly with bezier curves. This should be the first choice if you ask me. Here's a nice example.
In another scenario, you could polygonize the shapes using De-Casteljau algorithm and feed them into Javascript Clipper. If you use high sampling the visual result is identical to true curves, but you lose the curvy nature of the paths.
While I wouldn't go so far as to say this is a duplicate question I believe you will find great insight from the answers to this question as it is quite similar.
I did find one other resource that is not mentioned amongst the answers to that question here:
http://13thparallel.com/archive/bezier-curves/
Other than that the best resource that was mentioned in that question is here:
http://blog.mackerron.com/2011/01/01/javascript-cubic-splines/
Both these resources detail specific functions that will do what you are looking for. While they are not quite "libraries" the code will be easily ported to your project for your purposes.
Related
I am currently working moving different cars around a race track. I am using the formula listed in
Canvas move object in circle
arccos (1- ( d ⁄ r ) 2 ⁄ 2 )
to vary the speed of the cars around the ends of the track and it works very well. What I don't understand is how the formula is derived. I have been working on trying to derive it from the second derivative of the arcsin or arccos but I can't get out the formula (so am guessing I'm walking the wrong path). Anyways, I am never comfortable using code I don't understand, so I would appreciate it if someone could shed some light on it for me.
As detailed in the linked question, the movement of an object along a circle can be parametrized with a single angle theta which in loose terms describes how many "revolutions" the object has already made. Now, the question is for which angle theta the object is at Euclidean distance d from the initial (current) position A:
In other words, if you fix the time step delta of your simulation, the problem can be restated as to how one should adjust (increment) the angle so that the object displaces within the time interval delta to distance d.
From the law of cosines, one gets:
d^2 = r^2 + r^2 - 2*r*r*cos(theta) = 2*r^2*(1 - cos(theta))
Thus:
cos(theta) = 1 - 1/2*(d/r)^2
theta = arccos(1 - 1/2*(d/r)^2)
Whatever it is I'm doing, I don't know what it's called, but I need help because I know it can be done with math. This is for a simulation I'm building, and the role it plays is very difficult to explain, but it has something to do with defining the properties of an object.
Here is my JavaScript: https://jsfiddle.net/vdocnmzu/
DM.prototype.get = function(coords){
var dist;
val = 0;
for(var j,i = 0; i < this.distortions.length; i += 1){
dist = 0;
for(j = 0; j < coords.length; j += 1){
dist += Math.pow( coords[j] - this.distortions[i].coords[j], 2);
}
dist = Math.pow(dist,.5);
if( dist <= this.distortions[i].range){
val += Math.cos( (dist/this.distortions[i].range) * Math.PI/2 ) * this.distortions[i].amp;//;
}
}
return val;
}
What's happening is this: I have this 3D cube, where I can pick x & y, and get Z(the grayscale pixel color). In this sample code, I'm picking a grid of points across the entire x,y plane of the cube. The "bubbles" you see (you may need to refresh a few times) are multiple points being picked and creating that image.
What I'm trying to do is not have bubbles, but rather, organic flows between bubbles.
Right now, the z value comes from these "distortion points" that each of these 3DCubes have. It can have any amount of these points.
These "distortion points" don't have to be points. They can be sets of points, or lines, or any type of base geometry to define the skeleton of some type of distance function.
I think that distance function is what I'm struggling with, because I only know how to do it with points. I feel like lines would still be too rigid. What's the math associated with doing this with curves? Distance to a curve? Are there more approaches to this? If there's not a good single 1 to pick, it's okay to have a collection as well.
Your question is very complicated to understand. The overall feeling is that your expectations are too high. Some advanced math 101 might help (feel free to google buzzwords):
Defining a curve is an very hard problem that challenged the brightest mathematicians of the history. From the naive approach of the greeks, through the calculus of Newton and Leibniz, passing by Euler and Gauss, to the mathematical analysis of Weisstreiss, the word curve changed meaning several times. The accepted definition nowadays says that curves are continous functions in two variables, where continous is a very special word that has an exact meaning coined in the 19th century (naively is a function without jumps from one value to another). Togheter with the notion of continuity, came the notions of connected, compact, differentiable (and so on) curves, which defined new conditions for special curves. The subject developed to what is now known as topology and mathematical analysis.
Mathematicians usually uses definitions to reproduce a class of ideas that can be brought and thought togheter. To their surprise, the definition of continuity did include really weird functions to be curves: space-filling-curves, fractals!!! They called them monsters at the time.
After this introduction, lets go back to your question. You need a geometrical object to calculate distances from a point. Lets avoid weird curves and go from continous to differentiable. Now it's better. A (conected compact) differentiable function can be expanded in Taylor series, for example, which means that all functions of this class can be written as an infinite sum of polynomial functions. In two dimensions, you need to calculate matrices involved in this expansion (Calculus in many variables is a pre-requisite). Another step further is truncating this expansion in some degree, lets say 3. Then the general curve in this case is: ax + by + cx^2 + dy^2 + ex^3 + fy^3 + gx^2y + hxy^2 + ixy + j = 0 (ab...j are free parameters). Oh! This is reasonable, you might think. Well, actually there is a name for this kind of curve: algebraic curve of deggre 3. This is an active research theme of algebraic geometry, which is a very hard field even among mathematicians. Generally speaking, there are milestone theorems about the general behavior of those curves, which involves singularities and intersection points that are allowed in the general case.
In essence, what you are looking for does not exist, and is a very hard subject. Your algorithm works with points (really cool pictures by the way) and you should baby step it into a straight line. This step already requires you to think about how to calculate distance between a point and a straight line. This is another subject that was developed in general in the 19th century, togheter with mathematical analysis: metric spaces. The straightfoward answer to this question is defining the distance between a point and a line to be the smallest distance from the point to all line points. In this case, it can be shown that the distance is the modulus of the vector that connects the point to the line in a 90 degrees angle. But this is just one definition among infinte possible ones. To be considered a distance (like the one I just described and the euclidean distance) there is a set of axioms that needs to be verified. You can have hyperbolic metrics, discrete metrics, metrics that count words, letters, LotsOfFamousPeople metric spaces... the possibilities are infinite.
So, baby steps. Do it with straight lines and euclidean minimum distance metric. Play around with other metrics you find on google. Understand the axioms and make your own!!! Going to second degree polynomials is already a big challenge, as you have to understand everything that those curves can make (they can really do weird unexpect stuff) and define a distance to it (metric space).
Well thats it! Good luck with your project. Looks really cool!
I'm new to Javascript and I'm trying to use inverse tangent to find the angle in degrees between a line and the x axis on an elevated y. I don't see any command for it so I really need some help.
Use Math.atan() function and then Math.toDegrees() multiply it by 180/Math.PI to convert radians to degrees
Found the answer it here
Later edit:
Here is an example of angle calculation between a line defined by 2 points (A and B) and the X axis.
The elevation of the second line (parallel with the X axis) is irrelevant since the angle stays the same.
/*
* Calculates the angle between AB and the X axis
* A and B are points (ax,ay) and (bx,by)
*/
function getAngleDeg(ax,ay,bx,by) {
var angleRad = Math.atan((ay-by)/(ax-bx));
var angleDeg = angleRad * 180 / Math.PI;
return(angleDeg);
}
console.log(getAngleDeg(0,1,0,0));
I found this short and simple:
const calculateAngle = (width, height) => Math.atan(width/height)/(Math.PI / 180) // Angle in degrees
Try using Math.atan (outputs angle in radians) and some trigonometry.
Questions like these are best answered by the reference. I see a bunch of trigonometric functions there, including:
acos()
asin()
atan()
atan2()
cos()
degrees()
radians()
sin()
tan()
Note: As of Dec 5, 2018, the repository has been archived and processingjs.org redirects there.
With the development of p5js and the API advances in Processing itself, as well as Processing.js itself having been in maintenance mode for quite a few years now, this project has been archived as of December 2018.
Processing.js would like to thank everyone who contributed over the years: it's been an amazing project! The code will still be available in read-only mode, no releases will be pulled from any of the places it was distributed through, but the last version is, and will forever be, v1.6.6.
Thank you for your support, and happy coding (with newer solutions)!
Ok, this is one for math people, I guess. I have some basic knowledge of ease functions but need some helping hand with this.
I have an element that is translated with CSS transition (translateX) using ‘easeOutSine’ function.
It covers distance A in 1500 ms.
I need to find out how much time it needs to cover a distance B (somewhere in between)
The function for ‘easeOutSine’ is:
function easeOutSine(t, b, c, d) {
return c * Math.sin(t/d * (Math.PI/2)) + b;
}
Obviously A and B are known values for me. But I need to know where to put them in the arguments or how to handle this at all. Thanks very much in advance!
EDIT:
Example: Let’s say the element moves 1000px in those 1500ms. How much time has exactly passed when it is at 360px? It is simple to find out when it moves linear but I can’t get ahead of this with the easeOutSine function. (When it reaches this position I’d like to attach a class to another element)
Assumptions
What I'm hearing is that if you were to trace the line y = c * sin(t/d*pi/2) + b on a piece of paper from t=0 to t=1500, the distance traveled by your pencil would be A. Your goal is to find the t such that the distance is B.
Solution
Long story short, you're gonna be looking at the arc length formula. Specifically, you're going to need to solve B = integral from 0 to t of sqrt(1+(pi*c/(2d))^2 * cos(pi*t/(2*d))^2)dt, where B, c, and d are constants and the variable you're looking for is B.
It's not really obvious to me how the information you have about A can help you solve this, so I would recommend a binary search for t where your initial range is from [0, 1500] and you 'evaluate' the function (that integral) via some technique for approximating integrals. The function y = integral from 0 to t of sqrt(1+(pi*c/(2d))^2 * cos(pi*t/(2*d))^2)dt is monotonic over t, so that would get you the correct answer.
Sorry about how mathy that got; what you're looking to do isn't really possible to calculate explicitly. You might want to check out some tutorial on how to binary search an answer to a math problem if you're not familiar with that method. Good luck!
I am creating a Multiplayer game using socket io in javascript. The game works perfectly at the moment aside from the client interpolation. Right now, when I get a packet from the server, I simply set the clients position to the position sent by the server. Here is what I have tried to do:
getServerInfo(packet) {
var otherPlayer = players[packet.id]; // GET PLAYER
otherPlayer.setTarget(packet.x, packet.y); // SET TARGET TO MOVE TO
...
}
So I set the players Target position. And then in the Players Update method I simply did this:
var update = function(delta) {
if (x != target.x || y != target.y){
var direction = Math.atan2((target.y - y), (target.x - x));
x += (delta* speed) * Math.cos(direction);
y += (delta* speed) * Math.sin(direction);
var dist = Math.sqrt((x - target.x) * (x - target.x) + (y - target.y)
* (y - target.y));
if (dist < treshhold){
x = target.x;
y = target.y;
}
}
}
This basically moves the player in the direction of the target at a fixed speed. The issue is that the player arrives at the target either before or after the next information arrives from the server.
Edit: I have just read Gabriel Bambettas Article on this subject, and he mentions this:
Say you receive position data at t = 1000. You already had received data at t = 900, so you know where the player was at t = 900 and t = 1000. So, from t = 1000 and t = 1100, you show what the other player did from t = 900 to t = 1000. This way you’re always showing the user actual movement data, except you’re showing it 100 ms “late”.
This again assumed that it is exactly 100ms late. If your ping varies a lot, this will not work.
Would you be able to provide some pseudo code so I can get an Idea of how to do this?
I have found this question online here. But none of the answers provide an example of how to do it, only suggestions.
I'm completely fresh to multiplayer game client/server architecture and algorithms, however in reading this question the first thing that came to mind was implementing second-order (or higher) Kalman filters on the relevant variables for each player.
Specifically, the Kalman prediction steps which are much better than simple dead-reckoning. Also the fact that Kalman prediction and update steps work somewhat as weighted or optimal interpolators. And futhermore, the dynamics of players could be encoded directly rather than playing around with abstracted parameterizations used in other methods.
Meanwhile, a quick search led me to this:
An improvement of dead reckoning algorithm using kalman filter for minimizing network traffic of 3d on-line games
The abstract:
Online 3D games require efficient and fast user interaction support
over network, and the networking support is usually implemented using
network game engine. The network game engine should minimize the
network delay and mitigate the network traffic congestion. To minimize
the network traffic between game users, a client-based prediction
(dead reckoning algorithm) is used. Each game entity uses the
algorithm to estimates its own movement (also other entities'
movement), and when the estimation error is over threshold, the entity
sends the UPDATE (including position, velocity, etc) packet to other
entities. As the estimation accuracy is increased, each entity can
minimize the transmission of the UPDATE packet. To improve the
prediction accuracy of dead reckoning algorithm, we propose the Kalman
filter based dead reckoning approach. To show real demonstration, we
use a popular network game (BZFlag), and improve the game optimized
dead reckoning algorithm using Kalman filter. We improve the
prediction accuracy and reduce the network traffic by 12 percents.
Might seem wordy and like a whole new problem to learn what it's all about... and discrete state-space for that matter.
Briefly, I'd say a Kalman filter is a filter that takes into account uncertainty, which is what you've got here. It normally works on measurement uncertainty at a known sample rate, but it could be re-tooled to work with uncertainty in measurement period/phase.
The idea being that in lieu of a proper measurement, you'd simply update with the kalman predictions. The tactic is similar to target tracking applications.
I was recommended them on stackexchange myself - took about a week to figure out how they were relevant but I've since implemented them successfully in vision processing work.
(...it's making me want to experiment with your problem now !)
As I wanted more direct control over the filter, I copied someone else's roll-your-own implementation of a Kalman filter in matlab into openCV (in C++):
void Marker::kalmanPredict(){
//Prediction for state vector
Xx = A * Xx;
Xy = A * Xy;
//and covariance
Px = A * Px * A.t() + Q;
Py = A * Py * A.t() + Q;
}
void Marker::kalmanUpdate(Point2d& measuredPosition){
//Kalman gain K:
Mat tempINVx = Mat(2, 2, CV_64F);
Mat tempINVy = Mat(2, 2, CV_64F);
tempINVx = C*Px*C.t() + R;
tempINVy = C*Py*C.t() + R;
Kx = Px*C.t() * tempINVx.inv(DECOMP_CHOLESKY);
Ky = Py*C.t() * tempINVy.inv(DECOMP_CHOLESKY);
//Estimate of velocity
//units are pixels.s^-1
Point2d measuredVelocity = Point2d(measuredPosition.x - Xx.at<double>(0), measuredPosition.y - Xy.at<double>(0));
Mat zx = (Mat_<double>(2,1) << measuredPosition.x, measuredVelocity.x);
Mat zy = (Mat_<double>(2,1) << measuredPosition.y, measuredVelocity.y);
//kalman correction based on position measurement and velocity estimate:
Xx = Xx + Kx*(zx - C*Xx);
Xy = Xy + Ky*(zy - C*Xy);
//and covariance again
Px = Px - Kx*C*Px;
Py = Py - Ky*C*Py;
}
I don't expect you to be able to use this directly though, but if anyone comes across it and understand what 'A', 'P', 'Q' and 'C' are in state-space (hint hint, state-space understanding is a pre-req here) they'll likely see how connect the dots.
(both matlab and openCV have their own Kalman filter implementations included by the way...)
This question is being left open with a request for more detail, so I’ll try to fill in the gaps of Patrick Klug’s answer. He suggested, reasonably, that you transmit both the current position and the current velocity at each time point.
Since two position and two velocity measurements give a system of four equations, it enables us to solve for a system of four unknowns, namely a cubic spline (which has four coefficients, a, b, c and d). In order for this spline to be smooth, the first and second derivatives (velocity and acceleration) should be equal at the endpoints. There are two standard, equivalent ways of calculating this: Hermite splines (https://en.wikipedia.org/wiki/Cubic_Hermite_spline) and Bézier splines (http://mathfaculty.fullerton.edu/mathews/n2003/BezierCurveMod.html). For a two-dimensional problem such as this, I suggested separating variables and finding splines for both x and y based on the tangent data in the updates, which is called a clamped piecewise cubic Hermite spline. This has several advantages over the splines in the link above, such as cardinal splines, which do not take advantage of that information. The locations and velocities at the control points will match, you can interpolate up to the last update rather than the one before, and you can apply this method just as easily to polar coordinates if the game world is inherently polar like Space wars. (Another approach sometimes used for periodic data is to perform a FFT and do trigonometric interpolation in the frequency domain, but that doesn’t sound applicable here.)
What originally appeared here was a derivation of the Hermite spline using linear algebra in a somewhat unusual way that (unless I made a mistake entering it) would have worked. However, the comments convinced me it would be more helpful to give the standard names for what I was talking about. If you are interested in the mathematical details of how and why this works, this is a better explanation: https://math.stackexchange.com/questions/62360/natural-cubic-splines-vs-piecewise-hermite-splines
A better algorithm than the one I gave is to represent the sample points and first derivatives as a tridiagonal matrix that, multiplied by a column vector of coefficients, produces the boundary conditions, and solve for the coefficients. An alternative is to add control points to a Bézier curve where the tangent lines at the sampled points intersect and on the tangent lines at the endpoints. Both methods produce the same, unique, smooth cubic spline.
One situation you might be able to avoid if you were choosing the points rather than receiving updates is if you get a bad sample of points. You can’t, for example, intersect parallel tangent lines, or tell what happened if it’s back in the same place with a nonzero first derivative. You’d never choose those points for a piecewise spline, but you might get them if an object made a swerve between updates.
If my computer weren’t broken right now, here is where I would put fancy graphics like the ones I posted to TeX.SX. Unfortunately, I have to bow out of those for now.
Is this better than straight linear interpolation? Definitely: linear interpolation will get you straight- line paths, quadratic splines won't be smooth, and higher-order polynomials will likely be overfitted. Cubic splines are the standard way to solve that problem.
Are they better for extrapolation, where you try to predict where a game object will go? Possibly not: this way, you’re assuming that a player who’s accelerating will keep accelerating, rather than that they will immediately stop accelerating, and that could put you much further off. However, the time between updates should be short, so you shouldn’t get too far off.
Finally, you might make things a lot easier on yourself by programming in a bit more conservation of momentum. If there’s a limit to how quickly objects can turn, accelerate or decelerate, their paths will not be able to diverge as much from where you predict based on their last positions and velocities.
Depending on your game you might want to prefer smooth player movement over super-precise location. If so, then I'd suggest to aim for 'eventual consistency'. I think your idea of keeping 'real' and 'simulated' data-points is a good one. Just make sure that from time to time you force the simulated to converge with the real, otherwise the gap will get too big.
Regarding your concern about different movement speed I'd suggest you include the current velocity and direction of the player in addition to the current position in your packet. This will enable you to more smoothly predict where the player would be based on your own framerate/update timing.
Essentially you would calculate the current simulated velocity and direction taking into account the last simulated location and velocity as well as last known location and velocity (put more emphasis on the second) and then simulate new position based on that.
If the gap between simulated and known gets too big, just put more emphasis on the known location and the otherPlayer will catch up quicker.