Consider the given image of the soccer field
As you can see in the image the various ball movements, some of them are curved(i.e. in case of (1), (2), (3) in the image)) and some may not(i.e a line(4)),
so I need to find the intersection points of ball path with goalline and sideline. Sometimes the input may not be a curve(i.e a line) like in case of (4) given image
I have written a program, I have no clue what is wrong - is this right way to solve this kind of program.
if yes then, how to convert bezier curve into an equation for better solving
considering the given as
beizer curve eqaution -> a(x*x) + b*x + c
and line segment equation -> y = y1 + m(x-x1)
//maxCurvedPoint is the topmost of the curve
var getIntersectionPoint = function (room, ballFromPosition, ballToPosition, maxCurvePoint)
{
var linepoints = [[m1,n1], [m2, n2], [m3, n3], [m4, n4]];
//converting three points(ballFromPosition, maxCurvePoint, ballToPosition) into the quadratic equation (Bezier curve) --(1)
//getting the equation of the line segment using the linepoints --(2)
//equating (1) and (2) and getting a quadratic equation and solving and finding intersection points
return intersectionPoint;
}
// solves //(-b(+-)sqrt(b*b - 4ac)/2ac)
function solve(a, b, c)
{
//check curve intersects line or not
if((Math.pow(b, 2) - (4 * a * c)) >= 0)
{
result1 = (-1 * b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
result2 = (-1 * b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
return [result1, result2];
}
return [];
}
Can anyone help me with this? Also is the most curve point can be called vertex of the curve?
I find it easier to work with vector equations since the algebra will be rotation-invariant (hence you don't have to re-write the code to deal with e.g. a "horizontal" parabola).
1. Curve representation + Intersection test
Consider a quadratic Bezier curve with endpoints A, C, control point B and parameter t:
And an infinite line with source O, direction D and parameter s:
Equating P and R give a pair of quadratic simultaneous equations, which can be re-arranged to eliminate s and find the parabolic parameter t:
Solve this quadratic equation for t, and only accept real roots in the range [0, 1]. This ensures that any intersection point is always on the segment itself.
2. Dealing with line segments
You can also restrict the intersection point to a line segment, by computing s from t using the equations above, and limiting its value - which equals the distance along the line from O if D is normalized.
3. Computing the control point B
Note that a general value of the control point B will not give a symmetrical parabola. To compute B for a general symmetric curve:
Defining the variables:
M: midpoint of AB
n: clockwise normal to the direction AC
q: signed bulge distance - absolute value is the distance from M to the midpoint of the curve
k: signed distance from M to B
A surprisingly simple result.
4. Sample C# (-style) code
public static Vector2[] computeIntersection
(
Vector2 A, Vector2 C, double q, // parabola segment
Vector2 O, Vector2 P // line segment
)
{
// quadratic solve
double[] solve(double a, double b, double c)
{
double d = b * b - 4.0 * a * c;
if (d < 0.0) // imaginary roots - no intersection at all
return null;
if (d > 0.0) // two distinct real roots
{
double sd = Math.Sqrt(d);
return new double[2] { (-b + sd) / (2.0 * a),
(-b - sd) / (2.0 * a) };
}
else // only one (line segment is tangent to curve)
{
return new double[1] { -b / (2.0 * a) };
}
}
// cross product (in-case undefined)
double cross(Vector2 i, Vector2 j)
{
return i.x * j.y - i.y * j.x;
}
// validity check for t and s
bool valid(double v)
{
return (v >= 0.0) && (v <= 1.0);
}
// compute control point B
Vector2 E = C - A;
Vector2 M = 0.5 * (A + C);
Vector2 N = (new Vector2(E.y, -E.x)).normalize();
Vector2 B = M + (2.0 * q) * N;
// solving for t
Vector2 D = P - O;
bool useX = Math.Abs(D.X) > Math.Abs(D.Y);
double[] T = solve(cross(A + C - 2.0 * B, D),
cross(B - A, D) * 2.0,
cross(A - O, D));
if (T == null) return null;
Vector2[] I = new Vector2[2];
int c = 0;
for (int i = 0; i < T.Length; i++)
{
// check if t is within curve range
double t = T[i];
if (!valid(t)) continue;
// solve for s and check if is within line range
double u = (1 - t) * (1 - t);
double v = 2 * t * (1 - t);
double w = t * t;
double s = useX ? ((u * A.X + v * B.X + w * C.X - O.X) / D.X)
: ((u * A.Y + v * B.Y + w * C.Y - O.Y) / D.Y);
if (!valid(s)) continue;
// compute the corresponding intersection point
I[c++] = O + s * D;
}
// only return valid solutions
if (c == 0) return null;
Array.Resize(ref I, c);
return I;
}
If you translate and rotate all the endpoints in such a way that the line segment becomes (0, 0)-(d, 0), the problem simplifies.
Let the control points be (Xk, Yk), k= 0, 1, 2. The intersections with the axis X are obtained by solving for t the quadratic equation
Y0 (1-t)² + 2 Y1 t(1-t) + Y2 t² = 0.
The corresponding abscissas are given by
X0 (1-t)² + 2 X1 t(1-t) + X2 t² = 0.
You can check if these belong to the interval [0, d]. Then apply the reverse rotation and translation.
Addendum: intersection of two quadratic Beziers
The vector equation of one of the curves can be written
P = P0 (1 - t)² + 2 P1 t (1 - t) + P2 t²
= P0 + 2 (P1 - P0) t + (P0 - 2 P1 + P2) t².
If you apply the affine change of coordinates such that the reference frame becomes (P0, P1 - P0, P0 - 2 P1 + P2), the equation simplifies to
X = 2t
Y = t²
which is the implicit equation
X² = 4Y.
Now by applying the same transform to the control points of the second curve and plugging the parametric equations in the above, you get a quartic equation in t (square of a quadratic polynomial on one side, quadratic polynomial on the other).
There are closed-form formulas for the roots of a quartic equation, and there can be four of them. After selecting the real roots in [0, 1], you evaluate the t parameter of the first curve and also check membership in [0, 1].
Don't forget to restore the original coordinates.
Related
I am working on a browser game which includes cubic interpolation in many dimensions. I need to take a set of values and a set of coordinates and output the estimated value that point in nD space would have. I have found some great tutorials for 1d cubic interpolation, and some examples of nD cubic interpolation in c++ (Both here). The problem is that this c++ code uses many pointers and bit shifters, both of which I don't think JS has.
1D cubic interpolation is long, but it looks like this for whoever is interested:
f(a, b, c, d, x) = b + 0.5 * x*(c - a + x*(2*a - 5*b + 4*c - d + x*(3*(b - c) + d - a))), Where a-d are known values, and x is a value between 0 and 1 that determines the points relative placement between b and c
Js:
function interpolate(p, x){
return p[1] + 0.5 * x*(p[2] - p[0] + x*(2*p[0] - 5*p[1] + 4*p[2] - p[3] + x*(3*(p[1] - p[2]) + p[3] - p[0])));
}
2d interpolation can be achieved simply like this:
g(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4, x, y) =
f(f(a1, b1, c1, d1, y), f(a2, b2, c2, d2, y), f(a3, b3, c3, d3, y), f(a4, b4, c4, d4, y), x)
Js:
function interpolate2d(arr, x, y){
let a = [
interpolate(arr[0], y),
interpolate(arr[1], y),
interpolate(arr[2], y),
interpolate(arr[3], y),
];
return interpolate(a, x);
}
3d is the same way:
function interpolate3d(arr, x, y, z){
let a = [
interpolate2d(arr[0], y, z),
interpolate2d(arr[1], y, z),
interpolate2d(arr[2], y, z),
interpolate2d(arr[3], y, z)
];
return interpolate(a, x);
}
I'm new to Js, (just came from c++ and java) and don't know many of the extra features. I haven't found anything online, except for Array.reduce() (don't know how that would work with nested arrays) and the recursive c++ code from the link above:
double nCubicInterpolate (int n, double* p, double coordinates[]) {
assert(n > 0);
if (n == 1) {
return cubicInterpolate(p, *coordinates);
}
else {
double arr[4];
int skip = 1 << (n - 1) * 2;
arr[0] = nCubicInterpolate(n - 1, p, coordinates + 1);
arr[1] = nCubicInterpolate(n - 1, p + skip, coordinates + 1);
arr[2] = nCubicInterpolate(n - 1, p + 2*skip, coordinates + 1);
arr[3] = nCubicInterpolate(n - 1, p + 3*skip, coordinates + 1);
return cubicInterpolate(arr, *coordinates);
}
}
What would the Js function to replicate this be?
The translation to JavaScript can be:
function nCubicInterpolate(p, coordinates) {
if (coordinates.length == 1) {
return cubicInterpolate(p, coordinates[0]);
} else {
let fewerCoordinates = coordinates.slice(1);
let arr = p.map(hyperplane => nCubicInterpolate(hyperplane, fewerCoordinates));
return cubicInterpolate(arr, coordinates[0]);
}
}
Note that the parameter n is not needed in JavaScript, as the length of the coordinates array argument corresponds to it. Also the nesting level of p should be that same n. JavaScript has no compile-time type checking, so that liberty comes to our advantage here: no pointers; p is an array, but it can be an array of numbers, or an array of array of numbers, or ...etc.
To be complete, the cubicInterpolate function is as you specified in the question:
function cubicInterpolate(p, x) {
return p[1] + 0.5 * x*(p[2] - p[0] + x*(2*p[0] - 5*p[1] + 4*p[2] - p[3] + x*(3*(p[1] - p[2]) + p[3] - p[0])));
}
I have two lines defined by two points each(P1, P2, P3, P4).
I'd like to find the 2 points(X0, Y0) that are distanced r units from both lines.
I found a way but I think it's too long to solve(too difficult for me) and maybe there's one shorter(https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line).
my way:
Without solving it it's impossible tp create the function
I'd like to have the solution not the sistem.
Example(I'd like to find the yellow points knowing r):
Thanks.
(Sorry for my terrible english)
Variant A:
represent your lines in general form
a * x + b * y + c = 0
d * x + e * y + f = 0
with normalized coefficients (divide equation by Sqrt(a^2+b^2))
For this form point lies at distance r if
|a * x + b * y + c| = r
|d * x + e * y + f| = r
Open absolute value brackets with all possible +/- sign combinations and get 4 linear systems for 4 possible points
Variant B:
1) Find unit direction vectors of both lines da and db
2) Find intersection point C of two lines
3) Calculate angle between lines as
Fi = atan2(da.cross.db, da.dot.db)
4) Find unit bisector vector
b = (da + db).Normalized
5) Find perpendicular bisector
pb = (-b.y, b.x)
6) Get needed points as
C + b * r / Sin(Fi/2)
C - b * r / Sin(Fi/2)
C + pb * r / Cos(Fi/2)
C - pb * r / Cos(Fi/2)
I am drawing on shape on canvas(using HTML5) and need to determine(in javascript, jquery) if drawn Line Points (x,y cordinates) connect or intersect each other and form some shape(like triangle, square etc.). The purpose of this is to fill these shapes with colors, just like painting tools.
Have read few articles like http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/ but did not clearly understand if this can be used as solution for this problem.
Please suggest and algorithm to determine, if line points are connected to each other and form shapes.
Thanks,
Here are some links which has some required guidance for what I was looking out. Sharing the details here can be helpful for others looking for similar info.
https://gist.github.com/lengstrom/8499382
extract from jsfiddle
http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
// if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
var denominator, a, b, numerator1, numerator2, result = {
x: null,
y: null,
onLine1: false,
onLine2: false
};
denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
if (denominator == 0) {
return result;
}
a = line1StartY - line2StartY;
b = line1StartX - line2StartX;
numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
a = numerator1 / denominator;
b = numerator2 / denominator;
// if we cast these lines infinitely in both directions, they intersect here:
result.x = line1StartX + (a * (line1EndX - line1StartX));
result.y = line1StartY + (a * (line1EndY - line1StartY));
/*
// it is worth noting that this should be the same as:
x = line2StartX + (b * (line2EndX - line2StartX));
y = line2StartX + (b * (line2EndY - line2StartY));
*/
// if line1 is a segment and line2 is infinite, they intersect if:
if (a > 0 && a < 1) {
result.onLine1 = true;
}
// if line2 is a segment and line1 is infinite, they intersect if:
if (b > 0 && b < 1) {
result.onLine2 = true;
}
// if line1 and line2 are segments, they intersect if both of the above are true
return result;
};
Test if two lines intersect - JavaScript function
Given a point on a line and that line's slope how would one determine if the line, extending in each direction infinitely, intersects with a line segment (x1,y1), (x2,y2) and, if so, the point at which the intersection occurs?
I found this, but I'm unsure if it's helpful here.
If someone wants to help me understand "rays", that's alright with me.
http://www.realtimerendering.com/intersections.html
I'm sorry that I'm an idiot.
Arbitrary point on the first line has parametric equation
dx = Cos(slope)
dy = Sin(Slope)
x = x0 + t * dx (1)
y = y0 + t * dy
Line containing the second segment
dxx = x2 - x1
dyy = y2 - y1
x = x1 + u * dxx (2)
y = y1 + u * dyy
Intersection exists if linear system
x0 + t * dx = x1 + u * dxx (3)
y0 + t * dy = y1 + u * dyy
has solution for unknowns t and u
and u lies in range [0..1]
Intersection point could be calculated with substitution of u found in the equation pair (2)
Please don't ask me to explain how exactly this is working, I've just extrapolated/rewritten it from some ancient code I've had laying around. (Actionscript 1)
some functions to build the objects for this example:
function point(x, y){
return {x, y}
}
function line(x0, y0, x1, y1){
return {
start: point(x0, y0),
end: point(x1, y1)
}
}
function ray(x, y, vx, vy){
return {
start: point(x, y),
vector: point(vx, vy)
}
}
function ray2(x, y, angle){
var rad = angle * Math.PI / 180;
return ray(x, y, Math.cos(rad), Math.sin(rad));
}
the intersection-code:
//returns the difference vector between two points (pointB - pointA)
function delta(a, b){ return point( b.x - a.x, b.y - a.y ) }
//kind of a 2D-version of the cross-product
function cp(a, b){ return a.y * b.x - a.x * b.y }
function intersection(a, b){
var d21 = a.vector || delta(a.start, a.end),
d43 = b.vector || delta(b.start, b.end),
d13 = delta(b.start, a.start),
d = cp(d43, d21);
//rays are paralell, no intersection possible
if(!d) return null;
//if(!d) return { a, b, position: null, hitsA: false, hitsB: false };
var u = cp(d13, d21) / d,
v = cp(d13, d43) / d;
return {
a, b,
//position of the intersection
position: point(
a.start.x + d21.x * v,
a.start.y + d21.y * v
),
//is position on lineA?
hitsA: v >= 0 && v <= 1,
//is position on lineB?
hitsB: u >= 0 && u <= 1,
timeTillIntersection: v,
};
}
and an example:
var a = line(0, 0, 50, 50);
var b = line(0, 50, 50, 0); //lines are crossing
console.log(intersection(a, b));
var c = line(100, 50, 150, 0); //lines are not crossing
console.log(intersection(a, c));
var d = line(100, -1000, 100, 1000); //intersection is only on d, not on a
console.log(intersection(a, d));
var e = ray(100, 50, -1, -1); //paralell to a
console.log(intersection(a, e));
returns information about the intersection point, and wether it is on the passed lines/rays. Doesn't care wether you pass lines or rays.
about timeTillIntersection: if the first argument/ray represents a ball/bullet/whatever with current position and motion-vector, and the second argument represents a wall or so, then v, aka timeTillIntersection determines how much time it takes till this ball intersects/hits the wall (at the current conditions) in the same unit as used for the velocity of the ball. So you basically get some information for free.
What you search is the dot product. A line can be represented as a vector.
When you have 2 lines they will intersect at some point. Except in the case when they are parallel.
Parallel vectors a,b (both normalized) have a dot product of 1 (dot(a,b) = 1).
If you have the starting and end point of line i, then you can also construct the vector i easily.
I want to draw a line that signifies the altitude of a triangle. I know all 3 points of the circle (a, b, c). I want to draw the altitude through a.
I have the following functions to work out the perpendicular gradient of bc
gradient = function(a, b) {
return b.y - a.y / b.x - a.x;
};
perpendicularGradient = function (a, b) {
return -1 / gradient(a, b);
};
I can now get the equation of the line using y = mx + c for line of a with a perpendicular slope of bc and I can work out the y intercept.
function perpendicularLine(vertex, a, b) {
// b = y - m * x
var slope = perpendicularGradient(a, b),
yIntercept = (- slope * vertex.x) + vertex.y;
//how do I find the coordinates of the point on bc to draw a line from vertex
}
I don't know what to do next, i.e. how do I find the coordinates of the point on bc to join the line from a.
From googling about, I know I could use vectors but I have not covered that yet on my maths course and I would prefer to use the equation of a line.
Right, after you have your yIntercept and the slope of the perpendicular line, you need to construct a system of 2 linear equations with 2 unknowns (x0, y0) from the 2 line equations (bc line and line passing through a). The solution to this system is your intersection point along the bc line.
Let a point p along bc, given by the vector equation p = b + t bc, where t is a parameter. You express orthogonality of the altitude and the base by
ap.bc = 0, or (ab + t bc) bc = 0.
This gives
t = -ab.bc/bc²
which allows you to compute p.