I've been pulling my hair out over this one...
I am trying to find a newPoint that is always situated nVectorLength to the left of a sourcePoint.
Note: x,y,z values are never static.
I have two points:
sourcePoint(x,y,z)
endPoint(x,y,z) where the source-point is moving to.
- Can be used to find out where the source-point is facing to (aka up-direction)
- Unsure if this point is needed when you have x,y,z values of sourcePoint.
The example below with VectorLength = 22 explains this better:
NOTE: red point is drawn to the right, this should be to the left ofc. My mistake.
I tried rotating the blue point 90 degrees first, but my code is wrong:
function rotatePoint(point, center, angle)
angle = (angle) * (math.pi/180)
local rotatedX = math.cos(angle) * (point.x - center.x) - math.sin(angle) * (point.y - center.y) + center.x
local rotatedY = math.sin(angle) * (point.x - center.x) + math.cos(angle) * (point.y - center.y) + center.y
local rotatedZ = math.sin(angle) * (point.x - center.x) + math.cos(angle) * (point.y - center.y) + center.z
local newPoint = {x = rotatedX, y = rotatedY, z = rotatedZ}
return newPoint
end
I havent come to the part where I set it to nVectorLength, but I'm hoping someone can give me a working example of how to do the rotation + length part.
I'll assume a 2D space: Your source (green), end (blue), and new (red) points lie in the xy-plane. There is a unit vector (0, 0, 1) perpendicular to the plane pointing out at you. Positive rotations from the x-axis follow the right hand rule: counterclockwise.
If that's the case, then this is an easy problem.
calculate the unit vector from the source to the end point. I'll assume you know how to do that.
Rotate the unit vector 90 degrees in the clockwise direction.
Multiply the rotated unit vector by the length and add to the source point coordinates to get the new point coordinates.
All this holds true in a 3D space as well. You'll just need to transform from the 3D plane that you wish into the 2D plane, do the calculation, and transform back.
Related
I am trying to make a function that if a point is outside a certain circle, the point move to the point where the line passing by the center of the circle and the point collide. the code:
def inside_circle(self, pos):
if ((pos[0]-self.pos[0])**2 + (pos[1]-self.pos[1])**2) <= teleport_range**2:
return "inside"#pos
else:
pente = (pos[1]-self.pos[1])/(pos[0]-self.pos[0])
origine = pos[1]-pente*pos[0]
A = pente**2 + 1
B = 2 * -self.pos[0] + (origine+self.pos[1])*pente*2
C = self.pos[0]**2 + (origine+self.pos[1])**2 - teleport_range**2
if pos[0] > self.pos[0]:
X = (-B + math.sqrt(B**2 - 4*A*C))/(2*A)
Y = pente * X + origine
return "outside bot"#(X,Y)
elif pos[0] < self.pos[0]:
X = (-B - math.sqrt(B**2 - 4*A*C))/(2*A)
Y = pente * X + origine
return "outside top"#(X,Y)
self.pos is the center of the circle, pos is where the point I wanna check is, both are tuple
pente is the tilt of the line (its in french sorry)
origine is the Y origin of the line (french also)
teleport_range is the radius, being a constant 300
the actual return I want are commented for testing purposes
When I run it, if it is inside the circle, everythings fine but if it is outside, an error show up because it is trying to square root a negative
X = (-B + math.sqrt(B**2 - 4*A*C))/(2*A)
ValueError: math domain error
the square root in the quadratic equation is only negative when there is no collide point between the line and the circle, however, the line pass by the center of the circle and a point, so there should be two collide point.
I know there can be only one collide point when the line is a constant but I will fix that when I understand why (B**2 - 4*A*C) is negative when it shouldnt
I am not good in math, if someone could help me please, also dont hesitate to tell me if the code could be simplified without loosing clarity
thanks :)
Here is an easier, shorter, clearer way to get your desired point on the circle.
theta = math.atan2(pos[0] - self.pos[0], pos[1] - self.pos[1])
X = self.pos[0] + teleport_range * math.cos(theta)
Y = self.pos[1] + teleport_range * math.sin(theta)
This code first finds the angle of inclination of the ray from the circle's center to the point. It then uses that angle to find a point on the circle with the same angle.
Note that this code even works for points inside the circle: it finds the point on the circle with the same angle from the center. If the point is the circle's center, the desired point is ambiguous but the code returns one particular point.
I need to move a point by vectors of fixed norm around a central circle.
So to do this, I need to calculate the circle tangent vector to apply to my point.
Here is a descriptive graph :
So I know p1 coordinates, circle radius and center, and the vector norm d. I need to find p2 (= finding the vector v orientation).
I put on the graph some ideas I got to find it : p1' is p1 projected on the circle. And t is the tangent vector to C in p1'.
That should be easy, but I'm too weak in maths to figure how to implement this. So I would like an idea of the implementation this (language agnostic is okay, javascript is cool).
Extra cool if you can also get me how to implement clockwise and counter clockwise movement with this.
Edit : Obtained this
let vx = cx - p1x,
vy = cy - p1y,
norm = Math.sqrt((vx * vx) + (vy * vy)),
p2x = p1x - (vy * d / norm),
p2y = p1y + (vx * d / norm);
But there is still a quirk : using this on time, the point is slowly getting away from the center of the circle, performing a spiral.
Obtain vector Center of circle - point P1. Let's call this vector
v1.
Tangent vector 't' is perpendicular to v1. If v1=(vx, vy) then
t=(-vy,vx) . Just swap values and a sign (I wrote -vy, it could also be -vx, but not both -vy,-vx).
Setting one direction or the order is just using t2= -t1= (vy, -vx), or (-vy, vx)
For movements you must use normalized (||v|| = 1) vectors.
How calc angle of sectors by two points, radius, center of circle.
I try this: (p1,p2 - points in circle, center - center of circle)
startAngle = (int)(180 / Mathf.PI * Mathf.Atan2(p1.y - center.y, p1.x - center.x));
endAngle = (int)(180 / Mathf.PI * Mathf.Atan2(p2.y - center.y, p2.x - center.x));
What you have looks good to me, assuming you want to measure the angles in degrees anticlockwise about the x axis.
Here it is in Latex, with the subscript zero quantities being the centre of the circle.
You can find angle between vectors to the first point and to the second point using cross product and scalar product. This approach gives signed (directed) angle.
dy1 = p1.y - center.y;
dx1 = p1.x - center.x;
dy2 = p2.y - center.y;
dx2 = p2.x - center.x;
SectorAngle = Mathf.Atan2(dx1*dy2-dx2*dy1, dx1*dx2+dy1*dy2)
EDIT: THIS IS NOT A DUPLICATE, please read the description of the problem
Just to be clear, these line segments does not have an end point. They start at a point and goes to infinity based on a direction vector. I've found solutions for finite line segments, but they do not apply in this particular case (I think).
So, the title is basically my entire question - I've got
point p1
point p2
direction vector n1 (a normalized vector)
direction vector n2 (a normalized vector)
The first line segment starts at p1 and points towards n1
The second line segment starts at p2 and points towards n2
I need two answers:
If they intersects and
What is the point of intersection
I've found these two answers, but I'm so bad at math that I could not adapt them to fit my problem, but it could help you guys, I hope.
How do you detect where two line segments intersect?
and
Given two points and two vectors, find point of intersection
Thanks a lot!
Edit: (BTW, I'm working at 2D Space, so you don't have to worry about the z axis, thanks)
So, I've used the info provided by this post:
Determining if two rays intersect
And the info provided by a friend to solve this problem.
The first post stated that, given two points (p1 and p2) and two direction vectors (n1 and n2), the following formula applies:
bool DoesRaysIntersects(Point p1, Point p2, Point n1, Point n2)
{
float u = (p1.y * n2.x + n2.y * p2.x - p2.y * n2.x - n2.y * p1.x) / (n1.x * n2.y - n1.y * n2.x);
float v = (p1.x + n1.x * u - p2.x) / n.x;
return u > 0 && v > 0;
}
if both u and v are greater than 0, it's because the two rays collide.
If they collide, we can use the equation of the line to provide the point of collision. I don't know if this is the best way to achieve it, but it worked for me:
First, we need the slope of each of the lines. With their slopes, we can calculate the y-intercept of each line. And with this two datas, we can calculate the point of collision:
Point GetPointOfIntersection(Point p1, Point p2, Point n1, Point n2)
{
Point p1End = p1 + n1; // another point in line p1->n1
Point p2End = p2 + n2; // another point in line p2->n2
float m1 = (p1End.y - p1.y) / (p1End.x - p1.x); // slope of line p1->n1
float m2 = (p2End.y - p2.y) / (p2End.x - p2.x); // slope of line p2->n2
float b1 = p1.y - m1 * p1.x; // y-intercept of line p1->n1
float b2 = p2.y - m2 * p2.x; // y-intercept of line p2->n2
float px = (b2 - b1) / (m1 - m2); // collision x
float py = m1 * px + b1; // collision y
return new Point(px, py); // return statement
}
Thanks everyone!
I was in need of a little math help that I can't seem to find the answer to, any links to documentation would be greatly appreciated.
Heres my situation, I have no idea where I am in this maze, but I need to move around and find my way back to the start. I was thinking of implementing a waypoint list of places i've been offset from my start at 0,0. This is a 2D cartesian plane.
I've been given 2 properties, my translation speed from 0-1 and my rotation speed from -1 to 1. -1 is very left and +1 is very right. These are speed and not angles so thats where my problem lies. If I'm given 0 as a translation speed and 0.2 I will continually turn to my right at a slow speed.
How do I figure out the offsets given these 2 variables? I can store it every time I take a 'step'.
I just need to figure out the offsets in x and y terms given the translations and rotation speeds. And the rotation to get to those points.
Any help is appreciated.
Your question is unclear on a couple of points, so I have to make some assumptions:
During each time interval, translation speed and rotational velocity are constant.
You know the values of these variables in every time interval (and you know rotational velocity in usable units, like radians per second, not just "very left").
You know initial heading.
You can maintain enough precision that roundoff error is not a problem.
Given that, there is an exact solution. First the easy part:
delta_angle = omega * delta_t
Where omega is the angular velocity. The distance traveled (maybe along a curve) is
dist = speed * delta_t
and the radius of the curve is
radius = dist / delta_angle
(This gets huge when angular velocity is near zero-- we'll deal with that in a moment.) If angle (at the beginning of the interval) is zero, defined as pointing in the +x direction, then the translation in the interval is easy, and we'll call it deta_x_0 and delta_y_0:
delta_x_0 = radius * sin(delta_angle)
delta_y_0 = radius * (1 - cos(delta_angle))
Since we want to be able to deal with very small delta_angle and very large radius, we'll expand sin and cos, and use this only when angular velocity is close to zero:
dx0 = r * sin(da) = (dist/da) * [ da - da^3/3! + da^5/5! - ...]
= dist * [ 1 - da^2/3! + da^4/5! - ...]
dy0 = r * (1-cos(da)) = (dist/da) * [ da^2/2! - da^4/4! + da^6/6! - ...]
= dist * [ da/2! - da^3/4! + da^5/6! - ...]
But angle generally isn't equal to zero, so we have to rotate these displacements:
dx = cos(angle) * dx0 - sin(angle) * dy0
dy = sin(angle) * dx0 - cos(angle) * dy0
You could do it in two stages. First work out the change of direction to get a new direction vector and then secondly work out the new position using this new direction. Something like
angle = angle + omega * delta_t;
const double d_x = cos( angle );
const double d_y = sin( angle );
x = x + d_x * delta_t * v;
y = y + d_y * delta_t * v;
where you store your current angle out at each step. ( d_x, d_y ) is the current direction vector and omega is the rotation speed that you have. delta_t is obviously your timestep and v is your speed.
This may be too naive to split it up into two distinct stages. I'm not sure I haven't really thought it through too much and haven't tested it but if it works let me know!