Get a 3rd point along a line - c#

I have a line, start Vector2(4,5) end Vector2(10,10) for example.
I then calculate a point on this line with a specific location on the line (assume 0.4F for now):
float x = start.x + location * (end.x - start.x);
float y = start.y + location * (end.y - start.y);
return new Vector2 (x,y);
Now i have the location, and i want to place this point at an offset from the line.
So if the line is at a 45Angle, i want to be able to place a point at X offset +90 or -90 degrees from the existing line. Keeping the new location parallel on the existing line though.
Does anyone have any idea about how to do this?
I work in Unity3D if that enables you do do some more Vector2 stuff or not.
Many thanks in advance,
Smiley

You can get a perpendicular vector to the vector joining start and end using the following x and y components
float x2 = -(end.y - start.y);
float y2 = (end.x - start.x);
and create a 2D vector from those. That give you the direction vector which you can scale accordingly and add to points on your line to generate other points in this perpendicular direction.

Related

Arc lines between 2 objects on a sphere Unity3D

I need a little help with maths for drawing lines between 2 points on a sphere. I have a 3d globe and some markers on it. I need to draw curved line from point 1 to point 2. I managed to draw lines from point to point with LineRenderer, but they are drawn with the wrong angle and I can't figure out, how to implement lines that go at the right angle. The code by far:
public static void DrawLine(Transform From, Transform To){
float count = 12f;
LineRenderer linerenderer;
GameObject line = new GameObject("Line");
linerenderer = line.AddComponent<LineRenderer>();
var points = new List<Vector3>();
Vector3 center = new Vector3(
(From.transform.position.x + To.transform.position.x) / 2f,
(From.transform.position.y + To.transform.position.y) ,
(From.transform.position.z + To.transform.position.z) / 2f
);
for (float ratio = 0; ratio <= 1; ratio += 1 / count)
{
var tangent1 = Vector3.Lerp(From.position, center, ratio);
var tangent2 = Vector3.Lerp(center, To.position, ratio);
var curve = Vector3.Lerp(tangent1, tangent2, ratio);
points.Add(curve);
}
linerenderer.positionCount = points.Count;
linerenderer.SetPositions(points.ToArray());
}
So what I have now is creepy lines rising above along y axis:
What should I take into account to let lines go along the sphere?
I suggest you to find the normal vector of your two points with a cross product (if your sphere is centered at the origin) and then normalize it to use it as a rotation axis for a rotation using quaternions. To make the interpolations, you can simply rotate the first point around this vector with an angle of k * a where k is a parameter from 0 to 1 and a is the angle between your first two vectors which you can find with the acos() of the dot product of your two normalized points
EDIT : I thought about a much easier solution (again, if the sphere is centered) : you can do a lerp between your two vectors and then normalize the result and multiply it by the radius of the sphere. However, the spacings between the resulting points wont be constant, especially if they are far from each other.
EDIT 2 : you can fix the problem of the second solution by using a function instead of a linear parameter for the lerp : f(t) = sin(t*a)/sin((PI+a*(1-2*t))/2)/dist(point1, point2) where a is the angle between the two points.

Get points x distance inside a polygon

I can't figure out a way to do this. I have a list of vector2 points and I need all the points which are inside that polygon with a x distance.
So I have a List of Green points and looking for a List of Red points that have a x distance from respective green points.
I am thinking of getting 2 imaginary points, 1 unity towards the previous and next point.
Then moving towards the center of that 2 points by x distance. But then if the inter angle is not 90 then it will move outside of the polygon.
Vector2 me = point; // point
Vector2 next = n_point; // on left
Vector2 previous = p_point; // on right
//Debug.DrawLine(me, (me - next), Color.green);
// 2 points ep1 & ep2
Vector2 center = Vector2.Lerp(ep1,ep2, 0.5f);
Vector2 finalpoint = Vector2.Lerp(me,center,0.1f); //move towards center
I think I am overthinking this. Is there a super-easy way to do this?
Assuming that all the edges are either horizontal or vertical I would simply consider each possible case separately.
Get the direction vectors.
Vector2 from = me - previous;
Vector2 to = next - me;
I also assume that there is always a turn. I.e., if from is horizontal, then to is vertical and vice versa. Either x or y is 0.0f and the other coordinate is not zero.
I also assume that the x-axis points to the right and the y-axis upwards.
Assuming points are listed clock-wise.
float x, y;
if (from.x > 0.0f) { // from points to the right
y = me.y - distance;
if (to.y > 0.0f) x = me.x + distance else x = me.x - distance;
} else if (from.x < 0.0f) { // from points to the left
y = me.y + distance;
if (to.y > 0.0f) x = me.x + distance else x = me.x - distance;
} else if (from.y > 0.0f) { // from points upwards
x = me.x + distance;
if (to.x > 0.0f) y = me.y - distance else y = me.y + distance;
} else { // from.y < 0.0f, points downwards
x = me.x - distance;
if (to.x > 0.0f) y = me.y - distance else y = me.y + distance;
}
Vector2 me_inner = new Vector2(x, y);
I hope I got all the signs right.
There are two methods that spring to mind
Option1:
For each line define a normal, i.e. a perpendicular line pointing outward
Define a normal for each vertex as the average of the normals of the lines the vertex is part of.
Move the vertex X units along the normal.
This is fairly easy to implement, but may have problems with self-intersection for some kinds of geometry.
Option2:
For each line define a normal, i.e. a perpendicular line pointing outward
Move each line-segment X Units along the normal.
for each sequential pair of line segments determine if:
the two line segments intersect, if so, use the intersection point as the vertex. i.e. add the intersection point into your point-list.
If they do not intersect, insert a new line segment between the start and end point of the lines. i.e. Insert both start and end vertex to your point-list.
This should handle self-intersection better, but there might still be problem-cases. And it a bit more cumbersome to implement. It somewhat depend on how exact you need the new line positioned, and well it should handle different kinds of geometry.

Find slope in degrees between two vector3

Hi,
I found a large number of references but without being able to adapt them to my needs.
As per attached figures I have my character in a given position. Below the character's feet is a new plane (). With the mouse wheel I move the character up along the Y axis and the plane moves with it. Then I drag the character to any position and I join the three vector3s with Gizmos lines. Now I need to know the slope in degrees between the starting point (the red point) and the new position of the character. I tried to use Vector3.Angle or Atan2 and many examples found around but all return different values when you rotate the character despite the slope is always the same. For example charAngle = Vector3.Angle (initialCharPos - character.transform.position, Vector3.left) returns the correct value only in that certain direction and I can get the 4 points left, right, forward, back. But for directions other than these? I was wondering if for each of the 360 points it is necessary to make checks based on the direction or if there is a faster way to get this value.
You can use Vector3.Angle, you just need to take it between the down direction & the direction from the new feet position to the start feet position, and subtract the result from 90:
Vector3 newFeetPosition;
Vector3 startFeetPosition;
// direction of "down", could be different in a zero g situation for instance
Vector3 downDirection = Vector3.down:
float slopeDegrees = 90f - Vector3.Angle(newFeetPosition - startFeetPosition, downDirection);
If you need the rise/run for other reasons, you can get them in the process of calculating the angle yourself using vector math:
Vector3 newFeetPosition;
Vector3 startFeetPosition;
// direction of "up", could be different in a zero g situation for instance
Vector3 upDirection = Vector3.up:
Vector3 feetDiff = newFeetPosition - startFeetPosition:
float riseMagnitude = Vector3.Dot(feetDiff, upDirection);
Vector3 riseVector = riseMagnitude * upDirection;
float runMagnitude = (feetDiff - riseVector).magnitude;
float slopeDegrees = Mathf.Rad2Deg * Mathf.Atan2(riseMagnitude, runMagnitude);

Calculate a specific curve with specific rotation, c#

I am trying to code for a game I am working on a specific curve with a specific rotation. I am not a great mathematician... At all... Tried searching for solutions for a few hours, but I'm affraid I do not find any solution.
So, a small picture to illustrate first:
This is an eighth of a circle, radius of 9, beggining is (0,0)
The end is now at about 6.364, -2.636. But I need this same curve, with a 45° direction at the end, but ending at aexactly 6.0,-3.0.
Could any of you show me how to do this? I need to be able to calculate precisly any point on this curve & its exact length. I would suppose using some kind of eliptical math could be a solution? I admit my math class are reaaaly far now and have now good clue for now...
Thank for any possible help
I think I found a quadratic curve which sastisfies your requirement:
f(x) = -1/12 x^2 + 9
Copy the following into https://www.desmos.com/calculator to see it:
-\frac{1}{12}x^2+9
f'(x) would be -1/6x, so when x=6, the derivative would be -1, which corresponds to a -45° inclination. There are probably infinite curves that satisfy your requirement but if my calculus isn't too rusty this is one of them.
I tried to fit an ellipse with foci starting at y=6 here and starting at y=9 here to your points but the slope doesn't look like 45°.
Also starting at any height k, here doesn't seem to work.
I don't think you've fully understood the question I asked in the comments about the "inclination" angle. So I will give a general case solution, where you have an explicit tangent vector for the end of the curve. (You can calculate this using the inclination angle; if we clarify what you mean by it then I will be happy to edit with a formula to calculate the tangent vector if necessary)
Let's draw a diagram of how the setup can look:
(Not 100% accurate)
A and B are your fixed points. T is the unit tangent vector. r and C are the radius and center of the arc we need to calculate.
The angle θ is given by the angle between BA and T minus π/2 radians (90 degrees). We can calculate it using the dot product:
The (signed) distance from the center of AB to C is given by:
Note that this is negative for the case on the right, and positive for the left. The radius is given by:
(You can simplify by substituting and using a cosine addition rule, but I prefer to keep things in terms of variables in the diagram). To obtain the point C, we need the perpendicular vector to AB (call it n):
Now that we have the radius and center of the circular arc, we still need to determine which direction we are moving in, i.e. whether we are moving clockwise or anti-clockwise when going from A to B. This is a simple test, using the cross-product:
If this is negative, then T is as in the diagram, and we need to move clockwise, and vice versa. The length of the arc l, and the angular displacement γ when we move by a distance x along the arc:
Nearly there! Just one more step - we need to work out how to rotate the point A by angle γ around point C, to get the point we want (call it D):
(Adapted from this Wikipedia page)
Now for some code, in case the above was confusing (it probably was!):
public Vector2 getPointOnArc(Vector2 A, Vector2 B, Vector2 T, double x)
{
// calculate preliminaries
Vector2 BA = B - A;
double d = BA.Length();
double theta = Math.Acos(Vector2.DotProduct(BA, T) / d) - Math.PI * 0.5;
// calculate radius
double r = d / (2.0 * Math.Cos(theta));
// calculate center
Vector2 n = new Vector2(BA.y, -BA.x);
Vector2 C = 0.5 * (A + B + n * Math.Tan(theta));
// calculate displacement angle from point A
double l = (Math.PI - 2.0 * theta) * r;
double gamma = (2.0 * Math.PI * x) / l;
// sign change as discussed
double cross = T.x * BA.y - T.y * BA.x;
if (cross < 0.0) gamma = -gamma;
// finally return the point we want
Vector2 disp = A - C;
double c_g = Math.Cos(gamma), s_g = Math.Sin(gamma);
return new Vector2(disp.X * c_g + disp.Y * s_g + C.X,
disp.Y * c_g - disp.X * s_g + C.Y);
}

Unity destination Vector based on rotation and the amount to move

I'm having an issue where I can't figure out the algorithm to find out the destination point based on objects rotation and the amount to move. I have to move to the direction of my rotation a certain amount, but I don't know how to calculate the destination point I end up being at. Example:
Object location = (0, 0)
Object rotation = 45
Amount to move = 4
with these variables the destination point would be (2.5, 2.5)
Example 2:
Object location = (0, 0)
Object rotation = 0
Amount to move = 4
and with these it would be (0, 4)
The problem is, I don't know how to calculate the destination point when I know those variables. I need an algorithm that will calculate the destination point, can somebody help with this? :)
Regards, Tuukka.
If this is a strictly algorithmic question where you want to calculate the destination point (i.e. no game object to move around, but abstract data), you can do this:
Consider the two-dimensional plane in cartesian coordinates, (i.e. the standard x/y system). Let O be an object at point (0,0). From your "destination point" (2.5, 2.5) I can assume that you want the following thing:
So 45° is the angle and 4 (amount to move) is the length of the line segment you want to move along. Starting from (0,0), this end point can be calculated using sine and cosine by using the formula for the polar representation of a point:
But actually, that image is wrong, which we'll see in the following computation. If the movement is along the line with a slope angle of 45°, you'd land a little bit elsewhere.
Anyways, for this example, alpha would be 45° which is pi/4 in radians (you get this by dividing by 180 and multiplying with pi), and the radius r would be 4 (the amount we want to move), so we'd have calculated the destination point as:
If the point is located anywhere in the room (not at (0,0) but at (x_0, y_0)), then you can still add it as an offset:
So in code you'd write:
public static Vector2 ComputeDestination(Vector2 origin, float amountToMove, float angle)
{
//convert degrees to radians
var rad = angle * Mathf.Deg2Rad;
//calculate end point
var end_point = origin + amountToMove * new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
return end_point;
}
float homMuchToMove = 4f;
float angle = 45f;
float pointX = Mathf.Cos (ConvertToRadians (angle)) * homMuchToMove;
float pointY = Mathf.Sin (ConvertToRadians (angle)) * homMuchToMove;
public float ConvertToRadians(float angle)
{
return (Mathf.PI / 180f) * angle;
}
For these values you will get both points at 2.828427f

Categories

Resources