Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Currently I was trying to solve a problem with the condition below:
1. giving an elliptic curve y^2 = x^3 + ax + b
2. the user will input a, b and two points that exactly on the curve.
To put it simply, what I really need to do is make a secant line of the graph with the two points P and Q and try to check that if there is any point of intersection existing. If it exists, get the x and y of this point. I'm so struggled to solve this problem. Could someone give me some hints?
I'd homogenize this to x^3 + axz^2 + bz^3 - y^2z = 0 and points P = [Px : Py : Pz] and Q = [Qx : Qy : Qz]. Then any point R = λP + μQ with (λ, μ) ≠ (0, 0) lies on the line spanned by P and Q. If you wanted to avoid homogenizations, you'd require λ+μ=1 but that usually leads to divisions I'd rather avoid until the very end.
Plug the resulting coordinates of R into the homogenized equation of the elliptic curve, and you obtain a homogeneous cubic equation in λ and μ, i.e. something like
αλ³ + βλ²μ + γλμ² + δμ³ = 0
with the α, β, γ and δ depending on your a, b, P, Q. For μ=0 you get a coordinate vector which is a multiple of P, and as homogeneous coordinates identify multiples, you get point P itself, which lies on the curve. So μ=0 must satisfy the equation, hence you know α=0 even before you compute it. Likewise λ=0 represents Q so δ=0 if that point lies on the curve. You are left with
(βλ + γμ)λμ = 0
The trailing two factors encode the two known intersections I just mentioned. The parenthesis is the third intersection, the one you need. Now simply pick λ=γ and μ=−β to obtain a simple expression for the third point of intersection.
If you want to dehomogenize at the end, simply divide the first two coordinates of the resulting homogeneous coordinate vector by the third.
If I didn't mess up my sympy computation, you have
β = 3*Px^2*Qx + 2*Px*Pz*Qz*a - Py^2*Qz - 2*Py*Pz*Qy + Pz^2*Qx*a + 3*Pz^2*Qz*b
γ = 3*Px*Qx^2 + 2*Pz*Qx*Qz*a - Pz*Qy^2 - 2*Py*Qy*Qz + Px*Qz^2*a + 3*Pz*Qz^2*b
Which is expectedly very symmetric in P and Q. So essentially you just need a single function, and then you get β=f(P,Q) and γ=f(Q,P).
In C++ and with the whole homogenization / dehomogenization in place:
inline double f(double Px, double Py, double Qx, double Qy, double a, double b) {
return 3*Px*Px*Qx + 2*Px*a - Py*Py - 2*Py*Qy + Qx*a + 3*b;
}
std::pair<double, double> third_intersection(double Px, double Py, double Qx, double Qy, double a, double b) {
double beta = f(Px, Py, Qx, Qy, a, b);
double gamma = f(Qx, Qy, Px, Py, a, b);
double denominator = gamma - beta; // Might be zero if line PQ is an asymptote!
double x = (gamma*Px - beta*Qx) / denominator;
double y = (gamma*Py - beta*Qy) / denominator;
return std::make_pair(x, y);
}
Related
I am currently looking to implement an algorithm that will be able to compute the arc midpoint. From here on out, I will be referring to the diagram below. What is known are the start and end nodes (A and B respectively), the center (point C) and point P which is the intersection point of the line AB and CM (I am able to find this point without knowing point M because line AB is perpendicular to line CM and thus, the slope is -1/m). I also know the arc angle and the radius of the arc. I am looking to find point M.
I have been looking at different sources. Some suggest converting coordinates to polar, computing the mid point from the polar coordinates then reverting back to Cartesian. This involves sin and cos (and arctan) which I am a little reluctant to do since trig functions take computing time.
I have been looking to directly computing point M by treating the arc as a circle and having Line CP as a line that intersects the circle at Point M. I would then get two values and the value closest to point P would be the correct intersection point. However, this method, the algebra becomes long and complex. Then I would need to create special cases for when P = C and for when the line AB is horizontal and vertical. This method is ok but I am wondering if there are any better methods out there that can compute this point that are simpler?
Also, as a side note, I will be creating this algorithm in C++.
A circumference in polar form is expressed by
x = Cx + R cos(alpha)
y = Cy + R sin(alpha)
Where alpha is the angle from center C to point x,y. The goal now is how to get alpha without trigonometry.
The arc-midpoint M, the point S in the middle of the segment AB, and your already-calculated point P, all of them have the same alpha, they are on the same line from C.
Let's get vector vx,vy as C to S. Also calculate its length:
vx = Sx - Cx = (Ax + Bx)/2 - Cx
vy = Sy - Cy = (Ay + By)/2 - Cy
leV = sqrt(vx * vx + vy * vy)
I prefer S to P because we can avoid some issues like infinite CP slope or sign to apply to slope (towards M or its inverse).
By defintions of sin and cos we know that:
sin(alpha) = vy / leV
cos(alpha) = vx / leV
and finally we get
Mx = Cx + R * vx / leV
My = Cy + R * vy / leV
Note: To calculate Ryou need another sqrt function, which is not quick, but it's faster than sin or cos.
For better accuracy use the average of Ra= dist(AC) and Rb= dist(BC)
I would then get two values
This is algebraically unavoidable.
and the value closest to point P would be the correct intersection point.
Only if the arc covers less than 180°.
Then I would need to create special cases for when P = C
This is indeed the most tricky case. If A, B, C lie on a line, you don't know which arc is the arc, and won't be able to answer the question. Unless you have some additional information to start with, e.g. know that the arc goes from A to B in a counter-clockwise direction. In this case, you know the orientation of the triangle ABM and can use that to decide which solition to pick, instead of using the distance.
and for when the line AB is horizontal and vertical
Express a line as ax + by + c = 0 and you can treat all slopes the same. THese are homogeneous coordinates of the line, you can compute them e.g. using the cross product (a, b, c) = (Ax, Ay, 1) × (Bx, By, 1). But more detailed questions on how best to compute these lines or intersect it with the circle should probably go to the Math Stack Exchange.
if there are any better methods out there that can compute this point that are simpler?
Projective geometry and homogeneous coordinates can avoid a lot of nasty corner cases, like circles of infinite radius (also known as lines) or the intersection of parallel lines. But the problem of deciding between two solutions remains, so it probably doesn't make things as simple as you'd like them to be.
I am making a little game and I am now working on a "radar". Now to do this I need to find two points based off how much a point has rotated around a center point.
A is going to rotate around C.
As A rotates around C, B & D will move along with A and stay in the same "positions" based off of where A is.
So for example, if A rotates around C 90 degrees B & D would then move and be in this position
But I am not very good at trig, so I don't really know the math I would need in order to find B & D based off how much A has rotated around C.
How do i find B & D based off of how much A has rotated around C?
I would image the final math would look somewhat similar to this:
float * returnB(float * APoint, float * CPoint)
{
float B_Out[2];
//calculate where B is based off A & C
B_Out[0] = B_X;
B_Out[1] = B_Y;
return B_Out;
}
float B[2];
B[0] = returnB(A,C)[0];
B[1] = returnB(A,C)[1];
float * returnD(float * APoint, float * CPoint)
{
float D_Out[2];
//calculate where D is based off A & C
D_Out[0] = D_X;
D_Out[1] = D_Y;
return D_Out;
}
float D[2];
D[0] = returnD(A,C)[0];
D[1] = returnD(A,C)[1];
You can rotate a point (x, y) around the origin by performing a simple matrix multiplication, which gives the following equations for the transformed point (x0, y0):
x0 = x * cos(theta) - y * sin(theta);
y0 = x * sin(theta) + y * cos(theta);
So you know A's relative 2d position respect to C. Lets say it is (ax, ay).
If you cross product(0,0,1) with (ax, ay, 0) you will find relative position of D that will be something like (dx, dy, 0)
d = (dx, dy) is relative position of D.
b is also -d
https://en.wikipedia.org/wiki/Cross_product
Locked. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
I have two functions. I am giving here the basic structure only, as they have quite a few parameters each to adjust their exact shape.
For example, y = sin(.1*pi*x)^2 and y = e^-(x-5)^2.
The question is how much area of the sine is captured by the e function:
I tried to be clever and recursively find the points of intersection, but that turned out to be a lot more work than was necessary.
As n.m. pointed out, you want the integral from a to b of min(f, g). Since you're integrating by approximation, you're already stepping through the interval, meaning you can check at each step which function is greater and compute the area of the current trapezoid.
Simple implementation in C:
#define SLICES 10000
/*
* Computes the integral of min(f, g) on [a, b].
*
* Intended use is for when f and g are both non-negative, real-valued
* functions of one variable.
*
* That is, f: R -> R and g: R -> R.
*
* Assumes b ≥ a.
*
* #param a left boundary of interval to integrate over
* #param b right boundary of interval to integrate over
* #param f function accepting one double argument which returns a double
* #param g function accepting one double argument which returns a double
* #return integral of min(f, g) on [a, b]
*/
double minIntegrate (double a, double b, double (*f)(double), double (*g)(double)) {
double area = 0.0;
// the height of each trapezoid
double deltaX = (b - a) / SLICES;
/*
* We are integrating by partitioning the interval into SLICES pieces, then
* adding the areas of the trapezoids formed to our running total.
* To save a computation, we can cache the last side encountered.
* That is, let lastSide be the minimum of f(x) and g(x), where x was the
* previous "fence post" (side of the trapezoid) encountered.
* Initialize lastSide with the minimum of f and g at the left boundary.
*/
double lastSide = min(f(a), g(a));
// The loop starts at 1 since we already have the last (trapezoid) side
// for the 0th fencepost.
for (int i = 1; i <= SLICES; i++) {
double fencePost = a + (i * deltaX);
double currentSide = min(f(fencePost), g(fencePost));
area += trapezoid(lastSide, currentSide, deltaX);
lastSide = currentSide;
}
return area;
}
/*
* Computes the area of a trapezoid with bases `a` and `b` and height `height`.
*/
double trapezoid (double a, double b, double height) {
return h * (a + b) / 2.0;
}
If you're looking for something really, really simple, why don't you do Monte Carlo Integration?
Use the fact that the functions are easy to calculate to sample a large number of points. For each point, check whether it's below 0, 1, or 2 of the curves.
You might have some fiddling to find the boundaries for the sampling, but this method will work for a variety of curves.
https://en.wikipedia.org/wiki/Monte_Carlo_integration
I'm guessing your exponential is actually of the form e^-(x-5)^2 so that the exponential decays to zero at plus/minus infinity.
Given that, your integral would be most quickly and accurately calculated by something called Gaussian quadrature. There are a few types of common integrals which have very simple solutions using different polynomials (Hermite, Legendre, etc.). Yours specifically looks like it could be solved using Gauss-Hermite quadrature.
Hope this helps.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
I am working with set of points, and my goal is to add 4 vectors together and calculate the resultant between start and end point,
Since I already prepared the code to do the above part which seems to be working fine but am not to sure about it.
Anyway the real reason I am posting this question is to do with the resultant direction and angle.
I find it hard to either understand the concept of finding resultant angle and direction as well as PROGRAMMING wise.
Consider this scenario....Image
1st add vectors "Head 2 Tail"
From what I have learned about vector addition is to subtract x2 - x1, y2 -y1 this will dive me the misplacement difference and do the same calculation for all the points from A-E
To get the resultant I square root all the points x to power of 2 and add all the y position to power of 2.
This ideology seem to work fine.....
But the QUESTION here is how do i get the angle and direction of that resultant....?
the code I use to calculate resultant:
double Pta;
double Ptb;
Point vect;
float R1, R2;
float resultant;
for(vector<Point>::iterator iter_a = Left_Arm_xy.begin()+1; iter_a != Left_Arm_xy.end(); ++iter_a)
{
if(center.y <= 240)
{
vect.x = iter_a->x - (iter_a -1)->x;
vect.y = iter_a->y - (iter_a -1)->y;
vect_add.push_back(Point(vect.x,vect.y));
for(vector<Point>::iterator iter_v = vect_add.begin(); iter_v - vect_add.begin() + 4 < vect_add.size(); iter_v+=4)
{
R1 = iter_v->x + (iter_v +1)->x + (iter_v +2)->x + (iter_v +3)->x;
R2 = iter_v->y + (iter_v +1)->y + (iter_v +2)->y + (iter_v +3)->y;
resultant = sqrt(pow(R1,2) + pow(R2,2));
}
}
Consider this..............
Ok lets consider Points A[2,4], B[4,8], C[10,12], To add this vectors i add vectors/points I subtract point B x4 - A x2 and point B y8 - A y4 and point C x10 - B x4 and point C y12 - B y8 this will give me the the displacements between points....Now to get the Resultant i add all the Points X's and Y's x's 2+4+10 = 16 y's 4+8+12 = 24, Next i would square root 16 ^2 + 24^2 = 28.84. So based on these calculations where resultant is a number not and x and y value how can i get the direction and angle....?
It is a simple summation of vectors.
(x, y) = (x1, y1) + (x2, y2) + ... = (x1+x2+..., y1+y2+...)
When you have the final vector, it's angle is found by using
tan(angle) = y/x
The angle between two vectors is generally defined as:
Angle = arccos( DotProduct(v1, v2) / ( Length(v1) * Length(v2) ) );
The direction is simply subtraction of the two vectors:
Direction = v2 - v1;
Usually, you have to normalize this to get a unit vector:
Len = SquareRoot( direction.x * direction.x + direction.y * direction.y );
Direction.x /= Len;
Direction.y /= Len;
Thus, you'll have a unit direction vector and the angle of the vector.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Does anyone know a very simple physics engine, or just a set of basic functions that could complete these tasks: Simple point, line, and rectangle collision detection? I looked at Box2D but it is way too advanced for what I am making. I just need some simple code. Thanks in advance!
Here's my shot at point/line collision detection. The important thing is to avoid trig functions, divisions, and other expensive operations so as not to slow things down too much.
As GMan's comment notes, you need to bear in mind that the point will be moving. So you'll have the current position of the point (let's call it A) and the possible new position of the point (B). You need to find out if, when the point moves from A to B, it would collide with a line.
Let's call the start and end points of the line C and D. A collision will occur only if the lines AB and CD intersect.
Let's describe the line AB using the standard equation Ux + Vy + W = 0. After some algebra, the equation comes out as:
(ay - by) x + (bx - ax) y + ax by - bx ay = 0
We can describe the line CD in terms of a parameter t and constants X Y U V:
x = X + Ut
y = Y + Vt
It's helpful if we set t=0 at point C, and t=1 at point D. By considering t=0 we can work out X and Y. And by considering t=1 we can work out U and V. This gives
x = cx + (dx - cx) t
y = cy + (dy - cy) t
To find the intersection point of the two lines, substitute these into the equation we found for AB, which gives
(ay - by) (cx + (dx - cx) t) + (bx - ax) (cy + (dy - cy) t) + ax by - bx ay = 0
This reduces to
t = (ax by - bx ay + bx cy - cx by + cx ay - ax cy) / q
where q = (ay - by)(cx - dx) - (ax - bx)(cy - dy)
If q is zero, the lines are parallel and do not meet.
If 0 < t < 1 then the line extrapolated from AB intersects CD.
But we still don't know that this intersection is actually between the points A and B. So we need to repeat all the previous steps, swapping AB and CD, and writing the line AB in terms of a parameter s. This gives:
s = (cx dy - dx cy + dx ay - ax dy + ax cy - cx ay) / q
If 0 < s < 1 then the line extrapolated from CD intersects AB.
That's it. So in your code you start by calculating q. If q is zero then the lines are parallel. Otherwise, go on to calculate t and s. If 0 < t < 1 and 0 < s < 1 then a collision is about to happen. To find the location of the collision, substitute t or s back into the original equations for CD.
For extra speed you can remove the divisions by q - it's possible to just check whether the top half of each fraction is in the correct range, and then each check should only need 10 multiplication operations.
Is there a reason you couldn't use basic geometry for this?
Two points collide when their coordinates are the same.
A point intersects with a line when its position is a solution to the equation for the line.
A point intersects a rectangle when the point is bounded by the rectangle.
More complex composite cases can be constructed by composing these cases. Were you specifically looking for a library for some reason?