For an elliptical billiard-table, how can a collision be detected and resolved between the boundary of this table and one billiard-ball?
1.) I want to see if the position, P(x,y), of the billiard-ball lies
inside
on
or outside the boundary of the ellipse. [update: part 1. is solved]
2.) If it lies on or outside the boundary, the new velocity has to be calculated (just flipping the velocity is not enough).
3.) If it lies outside, it has to be moved back to lie on the boundary first.
========
==== * ====
==== ====
= =
==== ====
==== ====
========
Given is the position P(x,y) and the velocity V(x,y) of the billiard ball, plus the position of the center of the ellipse C(x_0,y_0) and both semi-axes a,b of the ellipse.
Just use the equation of the ellipse like you used the equation for the circle:
((p.x-x0)/a)^2 + ((p.y-y0)/b)^2 = k
If k < 1 -> inside the ellipse
If k == 1 -> on the ellipse
If k > 1 -> outside the ellipse
Since you are considering an elliptical (thus convex) board, I suppose you could use something based on GJK. You would get the point of contact and a surface normal during a collision, and the minimum distance between the objects and the associated witness points if there is no collision.
Collision detection with GJK is very fast and you could implement it for other shapes very easily (you only need to recode the support function). For an ellipse, I think the support function would be something like this (try to verify that) :
h=((x^2)/(a^4)+(y^2)/(b^4))^(-1/2)
Some links :
the initial paper GJK
Some funny experiments with elliptic table. Delphi code (without error handling!).
//calculates next ball position in ellipse
//ellipse semiaxes A, B, A2 = A * A, B2 = B * B
//center CX, CY
//PX,PY - old position, VX,VY - velocity components
//V - scalar velocity V = Sqrt(VX * Vx + VY * VY)
procedure TForm1.Calc;
var
t: Double;
eqA, eqB, eqC, DD: Double;
EX, EY, DX, DY, FX, FY: Double;
begin
//new position
NPX := PX + VX;
NPY := PY + VY;
//if new position is outside
if (B2 * Sqr(NPX) + A2 * Sqr(NPY) >= A2 * B2) then begin
//find intersection point of the ray in parametric form and ellipse
eqA := B2 * VX * VX + A2 * VY * VY;
eqB := 2 * (B2 * PX * VX + A2 * PY * VY);
eqC := -A2 * B2 + B2 * PX * PX + A2 * PY * PY;
DD := eqB * eqB - 4 * eqA * eqC;
DD := Sqrt(DD);
//we need only one bigger root
t := 0.5 * (DD - eqB) / eqA;
//intersection point
EX := PX + t * VX;
EY := PY + t * VY;
//mark intersection position by little circle
Canvas.Ellipse(Round(EX - 2 + CX), Round(EY - 2 + CY),
Round(EX + 3 + CX), Round(EY + 3 + CY));
//ellipse normal direction
DX := B2 * EX;
DY := A2 * EY;
DD := 1.0 / (DY * DY + DX * DX);
//helper point, projection onto the normal
FX := DD * (NPX * DX * DX + EX * DY * DY - DY * DX * EY + DX * DY * NPY);
FY := DD * (-DX * DY * EX + DX * DX * EY + DX * NPX * DY + DY * DY * NPY);
//mirrored point
NPX := NPX + 2 * (EX - FX);
NPY := NPY + 2 * (EY - FY);
//new velocity components
DD := V / Hypot(NPX - EX, NPY - EY);
VX := (NPX - EX) * DD;
VY := (NPY - EY) * DD;
end;
//new position
PX := NPX;
PY := NPY;
//mark new position
Canvas.Ellipse(Round(PX - 1 + CX), Round(PY - 1 + CY),
Round(PX + 1 + CX), Round(PY + 1 + CY));
end;
A = 125, B = 100
Start from ellipse center (left picture) and from the right focus point (right picture), ball reaches left focus, then returns to right focus
Related
And I have no clue where to start. In case you don't know what a cornu spiral is: https://mathworld.wolfram.com/CornuSpiral.html
All that I see are intrincated maths whose terms I'm not familiar with and doesn't translate as far as I know directly to blender interface which also I don't know in depth.
I had some success setting the handle absolute positions given point position on the bezier but I have no idea how to relate them in order to achieve my goal. Can you lend me any formula to calculate the correct brezier handle positions relative to point position and also the positions of the points? I'm about a week on this and I'm still starting.
We can draw Cornu spiral using small line segments. Example in Delphi:
cx := 10;
cy := 700;
scale := 700;
step := 0.02;
Canvas.MoveTo(cx, cy);
for i := 1 to 250 do begin
t := i * step;
fresnelintegral(t, c, s);
x := cx + Round(scale * s);
y := cy - Round(scale * c);
Canvas.LineTo(x, y);
end;
here t is curve parameter (proportional to arc length), and we calculate coordinate of current point using Fresnel integrals and scaling (to make a picture of viewable size). This code generates black curve:
If we want to approximate Cornu spiral by Bezier curves, we have to get endpoints with the same equations, then get direction angles in previous point and in the current point (slope equation (2) in your link) to define intermediate control points. But we also need to calculate distances to control points - seems rather hard problem. I made quick code to demonstrate an approach.
Curvature of Cornu spiral rises along the curve. To approximate spiral better, I had to diminish steps, so Bezier segments become smaller and smaller. Small circles are Bezier endpoints, they become closer.
I tried to make coeff depending on t value, but have not found good equation. The code below generates blue curve. It is very close to black one (we can align them) in chosen t range.
Canvas.Pen.Color := clBlue;
cx := 500;
step := 0.2;
prevt := 0;
t := 0;
Canvas.MoveTo(cx, cy);
Pts[0] := Point(cx, cy);
for i := 1 to 70 do begin
t := t + step;
fresnelintegral(prevt, c, s);
prevx := cx + Round(scale * s);
prevy := cy - Round(scale * c);
prevfi := 0.5 * Pi * prevt * prevt;
fresnelintegral(t, c, s);
x := cx + Round(scale * s);
y := cy - Round(scale * c);
pts[i*3] := Point(x, y);
fi := 0.5 * Pi * t * t;
Canvas.Ellipse(x-2, y-2, x+3, y+3);
coeff := 1/3;
dist := Hypot(x - prevx, y - prevy) * coeff;
px := prevx + Round(dist * Sin(prevfi));
py := prevy - Round(dist * Cos(prevfi));
pts[i * 3 - 2] := Point(px, py);
px := x - Round(dist * Sin(fi));
py := y + Round(dist * Cos(fi));
pts[i * 3 - 1] := Point(px, py);
step := step * 0.96;
prevt := t;
end;
Canvas.PolyBezier(pts);
I know the following:
P (x,y coordinates).
A1 and A2 (angles in degrees)
R (radius of circle).
Now I need to calculate a center for the green circle, as to make it 'tangentize?' the two blue lines (it will later be minkowski'ed with other shapes to form a point of a rounded triangle).
Any help will be appreciated!
My code for the depicted example:
//KNOWNS
P=[-3.0,1.0,0.0];
A1=60; A2=-5;
R=5;
//UNKNOWN
SECRET_CALCULATION = [8.2,4.3,0];//???
//ILLUSTRATION
C0=[0,0,0,1]; C1=[0,1,1,0.3]; C2=[0,1,0,0.4]; C3=[1,0,0,0.4];//Colors
translate(P){
color(C1) rotate(A1) translate([0,-0.5,0]) square([250,1],0);
color(C1) rotate(A2) translate([0,-0.5,0]) square([250,1],0);
color(C2) translate(SECRET_CALCULATION) circle(R);
}
//EXPLANATIONS
color(C0) translate(P) {
translate(SECRET_CALCULATION){
translate([0,-0.2,0]) square([R,0.4],0);
translate([R+1,0,0]) rotate(-90) text(str("R:",R),halign="center",valign="top",0.75);
translate([0,0.2,0]) text("[x?,y?,0]",halign="center",valign="bottom",0.75);
}
rotate(((A1-A2)/2)-90) translate([0,-1,0]) text(str("P: ",P),halign="center",valign="top",0.75);
rotate(A1) text(str(" A1: ",A1,"°"),halign="left",valign="center",0.75);
rotate(A2) text(str(" A2: ",A2,"°"),halign="left",valign="center",0.75);
}
Center of circle lies at the bisector of rays A1 and A2. So we can find direction for this bisector as
B = (A1 + A2) / 2 = 27.5 here
(but don't forget about angle normalization - angle -5 might be represented as 355 and so on)
And angle between bisector and A1 or A2 is
D = (A1 - A2) / 2 = 32.5 here
We can see that points C(enter)-T(angentpoint)-P form right triangle with relation
L (P-C, DistAlongBisector) = R / Sin(D)
So we can find center coordinates as
C.X = P.X + Cos(B) * L
C.Y = P.Y + Sin(B) * L
Quick hand-check gives
L=5/Sin(32.5)=9.3
C.X = -3 + Cos(27.5)*9.3 = 5.24
C.Y = 1 + Sin(27.5)*9.3 = 5.3
Hope I'm posting this in the right section, apologys if not.
I have a expression that I use on an objects position in After Effects:
radius = 35;
startAngle = degreesToRadians(180);
T = 22;
angularSpeed = 2 * 3.1415926 / T;
xt =1082 + radius * Math.cos(angularSpeed * time + startAngle);
yt = 536 + radius * Math.sin(angularSpeed * time + startAngle);
[xt, yt]
My questions, is how do I make it go counter clockwise as oppsoed to cloackwise?
Any help appreciated,
Ian
First of all, I am not looking to for points spaced uniformly around a circle, I know that has been answered many times. Instead, I have one point on a circle, and I need to find another that is a certain distance from it.
Here is an illustration :
The distance can be either between the two points (black dotted line), or the length of the circumference between the points (blue line), whatever is simplest (accuracy is not very important).
I know the following variables:
(green point x, y)
d
r
(centre point x, y)
So how can I find one of the red points?
So, basically you want to get intersection points of two circles:
The big one (BluePoint, radius = R)
A small one (GreenPoint, radius = D)
(Please excuse my amazing drawing skills :P)
I've at first tried to solve it myself, and fruitlessly wasted several sheets of paper.
Then I started googling and found an algorithm in other question.
Here is my Java implementation
double[][] getCircleIntersection(
double x0, double y0, double r0,
double x1, double y1, double r1) {
// dist of centers
double d = sqrt(sq(x0 - x1) + sq(y0 - y1));
if (d > r0 + r1) return null; // no intersection
if (d < abs(r0 - r1)) return null; // contained inside
double a = (sq(r0) - sq(r1) + sq(d)) / (2 * d);
double h = sqrt(sq(r0) - sq(a));
// point P2
double x2 = x0 + a * (x1 - x0) / d;
double y2 = y0 + a * (y1 - y0) / d;
// solution A
double x3_A = x2 + h * (y1 - y0) / d;
double y3_A = y2 - h * (x1 - x0) / d;
// solution B
double x3_B = x2 - h * (y1 - y0) / d;
double y3_B = y2 + h * (x1 - x0) / d;
return new double[][] {
{ x3_A, y3_A },
{ x3_B, y3_B }
};
}
// helper functions
double sq(double val) {
return Math.pow(val, 2);
}
double sqrt(double val) {
return Math.sqrt(val);
}
double abs(double val) {
return Math.abs(val);
}
This is how you would use it for the question situation:
double centerX = 0;
double centerY = 0;
double radius = 5;
double pointX = 10;
double pointY = 0;
double newPointDist = 5;
double[][] points = getCircleIntersection(centerX, centerY, radius, pointX, pointY, newPointDist);
System.out.println("A = [" + points[0][0] + " , " + points[0][3] + "]");
System.out.println("B = [" + points[1][0] + " , " + points[1][4] + "]");
Project your right red point down on both axes to get X and Y.
From there, you'll get 2 distinct right angle triangles:
Solutions:
I am new to unity3d I want to make a path for animated object.
The path must be # elliptical circle # or # spring shape path #
I think there is a way to draw this path based on mathematics equation is it true?
or should I draw it using 3dmax.
Any help or related tutorial for this problem?
thanks
This is a helpful link for drawing a path w/ the mouse in game.
If you want to draw a spring programmatically you can use a Catmullrom or Bezier spline:
double bezier(double t, double p0,double p1,double p2,double p3){
double t2 = t*t;
double t3 = t2 * t;
return (0.16667 *( t3 * (-p0 + 3 * p1 + -3 * p2 + p3) + \
t2 * (3 * p0 + -6 * p1 + 3 * p2) + \
t * (-3*p0 + 3*p2) + \
1 * (p0 + 4*p1 + p2)));
}
double catmullrom(double t, double p0,double p1,double p2,double p3){
double t2 = t*t;
double t3 = t2 * t;
return (0.5 *( (2 * p1) + (-p0 + p2) * t +(2*p0 - 5*p1 + 4*p2 - p3) * t2 +(-p0 + 3*p1- 3*p2 + p3) * t3));
}
The inputs p0,p1,p2,p3 are the 4 control points for a particular segment. To see a spiral building example, the rest of this code can be found on my Github page. Look at BuildPath() in particular to see how to use those functions to build a continuous path. I dislike linking to external accounts but my usage example is a little too big for an SO answer.
If you want to draw an ellipse, the simplest way I can think is to solve the basic equation and build a ring of points:
List<Vector3> pts = new List<Vector3>();
for(float x=-2.0f; x<2.0f;x+=0.1){
y = sqrt( (1-x^2/a^2) * b^2 );//from eq. x^2/a^2 + y^2/b^2=1;
pts.Add(new Vector3(x,y,0));
}
That code assumes you have a horizontal major axis where 'a' is the radius of the horizontal major axis, 'b' is the radius of the vertical minor axis. Build the ellipse first along the X/Y axes and then apply whatever transform you wish to orient the ellipse.
Alternatively, and I don't have code for this, you can use the general parametric equations to generate a rotated ellipse already off origin.