Math Error in Bezier curve - math

I'm trying to get plots to generate a cubic Bezier Curve, and I've managed to be able to generate linear and quad easily, but I keep getting an error with my cubic formula,
Linear formula:x = (1-t)*(p0x + (t * p1x))
quad formula:x = (1-t)^2 * p0x + 2*(1-t) * t * p1x + t^2 * p2x
cubic formula:x = (1–t)^3 * p0x + 3*(1–t)^2 * t * p1x + 3*(1–t)*t^2 * p2x + t^3 * p3x
Though the quad and cubic formula are very similar, the cubic errors "')' expected near '–'". How can this be fixed?
I'm programming this in Lua.

The subtraction signs in your cubic formula aren't plain -:
>>> s = """
... linear formula: `x = (1-t)*(p0x + (t * p1x))`
... quad formula: `x = (1-t)^2 * p0x + 2*(1-t) * t * p1x + t^2 * p2x`
... cubic formula: `x = (1–t)^3 * p0x + 3*(1–t)^2 * t * p1x + 3*(1–t)*t^2 * p2x + t^3 * p3x`
...
... """
>>> for line in s.splitlines():
... print repr(line)
...
''
'linear formula: `x = (1-t)*(p0x + (t * p1x))`'
'quad formula: `x = (1-t)^2 * p0x + 2*(1-t) * t * p1x + t^2 * p2x`'
'cubic formula: `x = (1\xe2\x80\x93t)^3 * p0x + 3*(1\xe2\x80\x93t)^2 * t * p1x + 3*(1\xe2\x80\x93t)*t^2 * p2x + t^3 * p3x`'
''
They're actually U+2013 –, which is EN DASH. Fix those and it should be fine.

Related

Coding likelihood and log-likelihood function in r to perform optimization

I am working on a paper that requires me to find the MLE of Gumbel’s type I
bivariate exponential distribution. I have proved the likelihood and log-likelihood functions likelihood and log-likelihood but I am struggling to implement it in r to perform optimization with Optim function. My code generates NA values.
Below are my codes.
# likelihood function of x
likelihood.x = function(params, data) {
lambda1 = params[1]
lambda2 = params[2]
theta = params[3]
A = (1 - theta) * (lambda1 * lambda2)
B = theta * (lambda1 ^ 2) * lambda2 * data$X1
C = theta * lambda1 * (lambda2 ^ 2) * data$X2
D = (theta ^ 2) * (lambda1 ^ 2) * (lambda2 ^ 2) * data$X1 * data$X2
E = (lambda1 * data$X1) + (lambda2 * data$X2) + (theta * lambda1 * lambda2 * data$X1 * data$X2)
f = sum(log(A + B + C + D)) - sum(E)
return(exp(f))
}
# Log-likelihood function of x
log.likelihood.x = function(params, data){
lambda1 = params[1]
lambda2 = params[2]
theta = params[3]
A = (1 - theta) * (lambda1 * lambda2)
B = theta * (lambda1 ^ 2) * lambda2 * data$X1
C = theta * lambda1 * (lambda2 ^ 2) * data$X2
D = (theta ^ 2) * (lambda1 ^ 2) * (lambda2 ^ 2) * data$X1 * data$X2
E = (lambda1 * data$X1) + (lambda2 * data$X2) + (theta * lambda1 * lambda2 * data$X1 * data$X2)
f = sum(log(A + B + C + D)) - sum(E)
return(-f)
}
Here's the function for generating the data
# Simulating data
rGBVE = function(n, lambda1, lambda2, theta) {
x1 = rexp(n, lambda1)
lambda12 = lambda1 * lambda2
pprod = lambda12 * theta
C = exp(lambda1 * x1)
A = (lambda12 - pprod + pprod * lambda1 * x1) / C
B = (pprod * lambda2 + pprod ^ 2 * x1) / C
D = lambda2 + pprod * x1
wExp = A / D
wGamma = B / D ^ 2
data.frame(x1, x2 = rgamma(n, (runif(n) > wExp / (wExp + wGamma)) + 1, D))
}
data = rGBVE(n=100, lambda1 = 1.2, lambda2 = 1.4, theta = 0.5)
colnames(data) = c("X1", "X2")
My goal is to find MLE for lambda1, lambda2 and theta using Optim() in r.
Kindly assist me to implement my likelihood and log-likelihood function in r.
Thank you.
Your concern appears to be about the warning message
In log(A+B+C+D): NaNs produced
Such warnings are usually harmless — it just means that the optimization algorithm tried a set of parameters somewhere along the way that violated the condition A+B+C+D ≥ 0. Since these are reasonably complex expressions it would take a little bit of effort to figure out how one might constrain the parameters (or reparameterize the function, e.g. fitting some of the parameters on the log scale) to avoid the warning, but taking a guess that keeping the parameters non-negative will help, we can try using the L-BFGS-B algorithm (which is the only algorithm available in optim() that allows multidimensional bounded optimization).
r1 <- optim(par = c(1,2,1),
fn = log.likelihood.x,
dat = data)
r2 <- optim(par = c(1,2,1),
fn = log.likelihood.x,
lower = rep(0,3),
method = "L-BFGS-B",
dat = data)
The second does not generate warnings, and the results are close (if not identical):
all.equal(r1$par, r2$par)
## "Mean relative difference: 0.0001451953"
You might want to use bbmle, which has some additional features for likelihood modeling:
library(bbmle)
fwrap <- function(x) log.likelihood.x(x, dat = data)
parnames(fwrap) <- c("lambda1", "lambda2", "theta")
m1 <- mle2(fwrap, start = c(lambda1 = 1, lambda2 = 2, theta = 1), vecpar = TRUE,
method = "L-BFGS-B", lower = c(0, 0, -0.5))
pp <- profile(m1)
plot(pp)
confint(pp)
confint(m1, method = "quad")

Given a position and rotation, how can I find a point that extends X distance from it?

I have a point in 3D space, and that point has an orientation. I want to get the end point of a line X distance from the origin point, following in orientation. How would I do this?
The answer doesn't have to be specific to any library, but I am using Three.JS.
In regards to Three.JS, depending on what you're starting with, or your comfort, there are several solutions.
Object3D
It provides you with extra utility methods that lets Three.js figure out the math for you:
// Create an Object3D
const element = new THREE.Object3D();
// Set position and orientation
element.position.copy(startPosition);
element.rotation.copy(eulerRotations);
// Move "forward" by the desired distance
element.translateZ(distance);
// Now we have our final position!
console.log(element.position);
I think the key to your question is the Object3D.translateZ() method, you can read more about it in the docs.
Vector3
Internally, what Object3D just did was Vector3 math. If you're only dealing with points and orientations, it might make more sense to use Vector3 directly:
const finalPosition = new Vector3(0, 0, 1)
.applyQuaternion(quaternionRotations)
.multiplyScalar(distance)
.add(startPosition);
Math
If you only want the math, this is what Three.JS is doing under the hood:
let x = 0;
let y = 0;
let z = 1;
const ix = quaternionW * x + quaternionY * z - quaternionZ * y;
const iy = quaternionW * y + quaternionZ * x - quaternionX * z;
const iz = quaternionW * z + quaternionX * y - quaternionY * x;
const iw = - quaternionX * x - quaternionY * y - quaternionZ * z;
x = ix * quaternionW + iw * - quaternionX + iy * - quaternionZ - iz * - quaternionY;
y = iy * quaternionW + iw * - quaternionY + iz * - quaternionX - ix * - quaternionZ;
z = iz * quaternionW + iw * - quaternionZ + ix * - quaternionY - iy * - quaternionX;
x = x * distance + originalPositionX;
y = y * distance + originalPositionY;
z = z * distance + originalPositionZ;
Which can be simplified to this:
function ray(position, distance, direction) {
const dy2 = 2 * direction.y;
const dx2 = 2 * direction.x;
const x = position.x + distance * (dy2 * direction.w + dx2 * direction.z);
const y = position.y + distance * (dy2 * direction.z - dx2 * direction.w);
const z =
position.z +
distance *
(-1 * Math.pow(direction.y, 2) +
Math.pow(direction.z, 2) +
Math.pow(direction.w, 2) -
Math.pow(direction.x, 2));
return {x, y, z};
}

How does B(t) of a bezier curve move when P1/P2 move along tangent?

When P1 changes from (0,4) to (0,2), Q1(t=0.5) and Q2(t=0.6) move 0.75 and 0.576 respectively. How can I calculate for any B(t) the distance it moves when P1 or P2 move along (Start--P1) or (P2--End) respectively?
Just write Bezier curve expression:
B(t) = P0 * (1-t)^3 + P1 * 3 * t * (1-t)^2 + P2 * 3 * t^2 * (1-t) + P3 * t^3
Let's P1' is new position of P1 control point. Only the second term will be changed, so
DeltaB(t) = B'(t) - B(t) = (P1' - P1) * 3 * t * (1-t)^2
if P1' lies on P0-P1, then
P1' = P0 + (P1 - P0) * u
DeltaB(t) = (P0 + (P1 - P0) * u - P1) * 3 * t * (1-t)^2 =
(P0 - P1) * (1 - u) * 3 * t * (1-t)^2
For your example data
u = 0.5
(P0 - P1) * (1 - u) = (0, -2) // (x,y) components of vector
DeltaB(0.5) = (0, -2 * 3 * 0.5 * 0.25) = (0, -0.75)
DeltaB(0.6) = (0, -2 * 3 * 0.6 * 0.4 * 0.4) = (0, -0.576)

Relative position of a point within a quadrilateral

I am trying to find the easiest way to determine a relative position of a point within a quadrilateral. The known are (see figure) the positions of points 1, 2, 3, 4 and 5 in the xy-coordinate system: x1, y1, x2, y2, x3, y3, x4, y4, x5, y5.
Also known are the positions of points 1, 2, 3, and 4 in the ξ-η coordinate systems (see figure).
From this data, I want to determine what are the ξ and η for point 5.
Results
Thank you to all who anwsered! I find the solution by #dbc and #agentp similar. Also I find this solution better than the perspective transformation solution by #MBo, since I do not have to compute the inverse of a matrix (Ax=B --> x=inv(A)*B).
I get the following result for:
u = 0.5 * (ξ + 1)
v = 0.5 * (η + 1)
In my case all points are within the rectangle, therefore u>0 and v>0.
What you have here is a 2d bilinear blended surface. For simplicity, let's change its coordinates to range from zero to one:
u = 0.5 * (ξ + 1)
v = 0.5 * (η + 1)
In that case, the surface evaluator can be expressed as
F(u, v) = P1 + u * (P2 - P1) + v * ((P4 + u * (P3 - P4)) - (P1 + u * (P2 - P1)))
I.e., for a given u, construct a line passing through the following two points:
Pv0 = P1 + u * (P2 - P1);
Pv1 = P4 + u * (P3 - P4);
then interpolate between then for given v
F(u, v) = Pv0 + v * (Pv1 - Pv0)
What you seek are values (u,v) such that F(u, v) = P5. This will occur for given u when the line from Pv0 to Pv1 passes through P5, which will occur when P5 - Pv0 is parallel to Pv1 - Pv0 -- i.e. when their 2d cross is zero:
cross2d(P5 - Pv0, Pv1 - Pv0) = 0
⇒
cross2d(P5 - (P1 + u * (P2 - P1)),
P4 + u * (P3 - P4) - (P1 + u * (P2 - P1))) = 0
Now, the 2d cross of two 2d vectors A ⨯ B is given by Ax*By - Ay*Bx, so that equation becomes
(x5 - (x1 + u * (x2 - x1))) * (y4 + u * (y3 - y4) - (y1 + u * (y2 - y1))) - (y5 - (y1 + u * (y2 - y1))) * (x4 + u * (x3 - x4) - (x1 + u * (x2 - x1))) = 0
Expanding this expression out and collecting collecting together terms in u, we get
u^2 * (x1*y3 - x1*y4 - x2*y3 + x2*y4 + (-x3)*y1 + x3*y2 + x4*y1 - x4*y2)
+ u * (-x1*y3 + 2*x1*y4 - x1*y5 - x2*y4 + x2*y5 + x3*y1 - x3*y5 - 2*x4*y1 + x4*y2 + x4*y5 + x5*y1 - x5*y2 + x5*y3 - x5*y4)
+ (-x1*y4 + x1*y5 + x4*y1 - x4*y5 - x5*y1 + x5*y4)
= 0
This is now a quadratic equation over u, and can be solved as such. Note that in cases where the top and bottom edges of your quadrilateral are parallel then the quadratic devolves into a linear equation; your quadratic equation solver must needs handle this.
double a = (x1 * y3 - x1 * y4 - x2 * y3 + x2 * y4 + (-x3) * y1 + x3 * y2 + x4 * y1 - x4 * y2);
double b = (-x1 * y3 + 2 * x1 * y4 - x1 * y5 - x2 * y4 + x2 * y5 + x3 * y1 - x3 * y5 - 2 * x4 * y1 + x4 * y2 + x4 * y5 + x5 * y1 - x5 * y2 + x5 * y3 - x5 * y4);
double c = (-x1 * y4 + x1 * y5 + x4 * y1 - x4 * y5 - x5 * y1 + x5 * y4);
double[] solutions = Quadratic.Solve(a, b, c);
There may be more than one solution. There might also be no solutions for a degenerate quadrilateral.
Having solved for value(s) of u, finding the equivalent v is straightforward. Given points
Pv0 = P1 + u * (P2 - P1);
Pv1 = P4 + u * (P3 - P4);
you seek v such that
v * (Pv1 - Pv0) = P5 - Pv0;
Pick the coordinate index 0 or 1 such that |(Pv1 - Pv0)[index]| is maximized. (If both coordinates are almost zero, then give up -- there's no solution for this specific u. Then set
v = (P5 - Pv0)[index] / (Pv1 - Pv0)[index];
Finally, if you have more that one solution, prefer a solution inside the [u, v] boundaries of the blend. Then finally set
ξ = 2 * u - 1;
η = 2 * v - 1;
This looks like a standard finite element parameterization
(The question doesn't specify a particular mapping, but I imagine someone might be interested in this specific case)
{x, y} == (
(1 - eta) (1 - ci) {p1x, p1y} +
(1 - eta) (1 + ci) {p2x, p2y} +
(1 + eta) (1 + ci) {p3x, p3y} +
(1 + eta) (1 - ci) {p4x, p4y} )/4
This can be solved in closed form for {eta,ci}, but the expression is pretty unwieldy to post.
In practice, compute these constants:
ax = p1x + p2x + p3x + p4x
bx = p1x - p2x - p3x + p4x
cx = p1x + p2x - p3x - p4x
dx = p1x - p2x + p3x - p4x
ay = p1y + p2y + p3y + p4y
by = p1y - p2y - p3y + p4y
cy = p1y + p2y - p3y - p4y;
dy = p1y - p2y + p3y - p4y;
Solve this quadratic for eta :
(ax by - bx ay) - 4 (by x - bx y) +
eta (dx ay - cx by + bx cy - ax dy + 4 (x dy - dx y)) +
eta^2 (cx dy - dx cy) == 0
then get ci as:
ci = ((-ax + eta cx + 4 x)/(-bx + eta dx))
If the polygon is not too distorted just one of the solutions will satisfy -1<eta<1 and -1<ci<1
Referring to the self-answer of #blaz (please vote up the answers of #blaze, #dbc and #agentp)
For everybody who is not willing to copy the formulas by hand, here is the formula as C# code:
double v_sqrt = Math.Sqrt(
4 * (
(x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) * (x4 * (-1 * y + y1) + x1 * (y - y4) + x * (-1 * y1 + y4)) +
Math.Pow(
(x3 * y - x4 * y - x3 * y1 + 2 * x4 * y1 - x4 * y2 + x1 * (y + y3 - 2 * y4) + x2 * (-1 * y + y4) + x * (-1 * y1 + y2 - y3 + y4))
, 2)
);
double u_sqrt = Math.Sqrt(
4 * ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4))
* (
x4 * (-1 * y + y1) + x1 * (y - y4) + x * (-1 * y1 + y4)
) +
Math.Pow(
(x3 * y - x4 * y - x3 * y1 + 2 * x4 * y1 - x4 * y2 + x1 * (y + y3 - 2 * y4) + x2 * (-1 * y + y4) + x * (-1 * y1 + y2 - y3 + y4))
, 2)
);
double k = 1 / (2 * ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)));
double l = 1 / (2 * ((x1 - x4) * (y2 - y3) - (x2 - x3) * (y1 - y4)));
///////////////////////////////////////////////////////////////////////////////////////////////
double v1 = l *
(x2 * y - x3 * y + x4 * y + x * y1 - 2 * x2 * y1 + x3 * y1 - x * y2 - x4 * y2 + x * y3 - x1 * (y - 2 * y2 + y3) - x * y4 + x2 * y4 +
v_sqrt);
///////////////////////////////////////////////////////////////////////////////////////////////
double u1 = -1 * k *
(-x2 * y + x3 * y - x * y1 - x3 * y1 + 2 * x4 * y1 + x * y2 - x4 * y2 - x * y3 + x1 * (y + y3 - 2 * y4) + x * y4 + x2 * y4 +
u_sqrt);
double v2 = -1 * l *
(x1 * y + x3 * y - x4 * y - x * y1 - 2 * x3 * y1 + x * y2 - -2 * x1 * y2 + x4 * y2 - x * y3 + x1 * y3 + x * y4 - x2 * (y - 2 * y1 + y4) +
v_sqrt);
/////////////////////////////////////////////////////////////////////////////////////////////////
double u2 = k *
(x2 * y - x3 * y + x4 * y + x * y1 + x3 * y1 - 2 * x4 * y1 - x * y2 + x4 * y2 + x * y3 - x1 * (y + y3 - 2 * y4) - x * y4 - x2 * y4 +
u_sqrt);
In most cases it is u1 and v1 so there should not be the need for computing the other ones.
I used it to calibrate the coordinates of a Pegasus Air-Pen device (ultrasonic stylus) on a sheet of paper. It does work best if your coordinates for point 1 to 5 are also >= 0.
Sry for posting this as an answer but it is too long for a comment and I think it is a valuable help for this post as it would be for me.
You need to calculate a matrix of perspective transformation, that maps 4 points of source quadrilateral to 4 points of destination quadrilateral (example) (more mathemathics), then apply this transformation to coordinates of 5th point (multiply matrix by coordinate vector)

Drawing a Rotated Rectangle

I realize this might be more of a math problem.
To draw the lines for my rectangles I need to solve for their corners.
I have a rectangle center at (x,y) With a defined Width and Height.
To find the blue points on a non rotated rectangle on top (angle = 0)
It is
UL = (x-Width/2),(y+height/2)
UR = (x+Width/2),(y+height/2)
LR = (x+Width/2),(y-height/2)
LL = (x-Width/2),(y-height/2)
How do I find the points if the angle isn't 0?
Thanks in advance.
Update: although I have (0,0) in my picture as the center point most likely the center point won't be at that location.
First transform the centre point to 0,0
X' = X-x
Y' = Y-y
Then rotate for an angle of A
X'' = (X-x) * cos A - (Y-y) * sin A
Y'' = (Y-y) * cos A + (X-x) * sin A
Again transform back the centre point to x,y
X''' = (X-x) * cos A - (Y-y) * sin A + x
Y''' = (Y-y) * cos A + (X-x) * sin A + y
Hence compute for all 4 points of (X,Y) with following transformation
X''' = (X-x) * cos A - (Y-y) * sin A + x
Y''' = (Y-y) * cos A + (X-x) * sin A + y
where x, y are the centre points of rectangle and X,Y are the corner points
You have n't defined correctly even the corner points when Angle is 0 as I have given in the comments.
After substituting you will get
UL = x + ( Width / 2 ) * cos A - ( Height / 2 ) * sin A , y + ( Height / 2 ) * cos A + ( Width / 2 ) * sin A
UR = x - ( Width / 2 ) * cos A - ( Height / 2 ) * sin A , y + ( Height / 2 ) * cos A - ( Width / 2 ) * sin A
BL = x + ( Width / 2 ) * cos A + ( Height / 2 ) * sin A , y - ( Height / 2 ) * cos A + ( Width / 2 ) * sin A
BR = x - ( Width / 2 ) * cos A + ( Height / 2 ) * sin A , y - ( Height / 2 ) * cos A - ( Width / 2 ) * sin A
I think this suits your solution.
If 'theta' is the anti-clockwise angle of rotation, then the rotation matrix is:
| cos(theta) -sin(theta) |
| sin(theta) cos(theta) |
i.e.
x' = x.cos(theta) - y.sin(theta)
y' = x.sin(theta) + y.cos(theta)
If the rotation point isn't at the origin, subtract the center of rotation from your original coordinates, perform the rotation as shown above, and then add the center of rotation back in again.
There's examples of other transformations at http://en.wikipedia.org/wiki/Transformation_matrix
Rotation matrix
(this is becoming a FAQ)
See 2D Rotation.
q = initial angle, f = angle of rotation.
x = r cos q
y = r sin q
x' = r cos ( q + f ) = r cos q cos f - r sin q sin f
y' = r sin ( q + w ) = r sin q cos f + r cos q sin f
hence:
x' = x cos f - y sin f
y' = y cos f + x sin f
One of the easiest ways to do this is to take the location of the point before rotation and then apply a coordinate transform. Since it's centred on (0,0), this is simply a case of using:
x' = x cos(theta) - y sin(theta)
y' = y cos(theta) + x sin(theta)
use this....I got succeded...
ctx.moveTo(defaults.x1, defaults.y1);
// Rotation formula
var x2 = (defaults.x1) + defaults.lineWidth * Math.cos(defaults.rotation * (Math.PI / 180));
var y2 = (defaults.y1) + defaults.lineWidth * Math.sin(defaults.rotation * (Math.PI / 180));
ctx.lineTo(x2, y2);
x2 = (x2) + defaults.lineHeight * Math.cos((defaults.rotation + 90) * (Math.PI / 180));
y2 = (y2) + defaults.lineHeight * Math.sin((defaults.rotation + 90) * (Math.PI / 180));
ctx.lineTo(x2, y2);
x2 = (x2) + defaults.lineWidth * Math.cos((defaults.rotation + 180) * (Math.PI / 180));
y2 = (y2) + defaults.lineWidth * Math.sin((defaults.rotation + 180) * (Math.PI / 180));
ctx.lineTo(x2, y2);
x2 = (x2) + defaults.lineHeight * Math.cos((defaults.rotation + 270) * (Math.PI / 180));
y2 = (y2) + defaults.lineHeight * Math.sin((defaults.rotation + 270) * (Math.PI / 180));

Resources