# PLEASE check my math. Creating points on a line using x, y and slope.

I know it's long but I really need help. I'm terrible at math. Anyway, given only a start and end point, I'm trying to draw a line by creating a number of points at regular intervals between those start and end points.
This is what I have so far (it's from C# code so I hope it's not too hard to understand).

1. Find this distance between the start and end points.
Code:
float touchLength = Vector2.Distance (touchPoints [touch.fingerId] , touchPoints [touch.fingerId] [lastIndex]);
2. Calculate the slope of the line using the start and end points.
Code:
float slope = HelperFunctions.CalculateSlope (touchPoints [touch.fingerId] .x, touchPoints [touch.fingerId] [lastIndex].x, touchPoints [touch.fingerId] .y, touchPoints [touch.fingerId] [lastIndex].y);
This is the slope calculation function:
Code:
public static float CalculateSlope (float y1, float y2, float x1, float x2)
{
float slope = (y2 - y1) / (x2 - x1);

return slope;
}
3. Loop through how many points SHOULD be on the line (this is dictated by the user).

4. Within the loop, create a point on the line and give it an x value based on the length of the line so that all points created will be equi-distant.
Code:
perfectPoint.x = j * (touchLength / touchPoints [touch.fingerId].Count);
(j represents the point number, so it will loop from 1 to however many points need to be created.)

5. Calculate the 'b' in 'y = mx + b' so we can figure what the corresponding y co-ordinate of perfectPoint.x.
Code:
float b = HelperFunctions.CalculatePointOnLine (slope, touchPoints [touch.fingerId] .x, touchPoints [touch.fingerId] .y);
This is the 'b' calculation function:
Code:
public static float CalculatePointOnLine (float slope, float x, float y)
{
float b = y - (slope * x);
return b;
}
6. That's it! However, it always ends up messed up. The line doesn't start at my start point or even end there. It's way off. the slope seems OK but I can't be sure of that.

Thanks!

mfb
Mentor
Your "perfectPoint.x" starts at 0, not at the first finger. You'll have to add that finger position, then it should work. Also start at j=0 or end at count-1, otherwise your line is not symmetric at the end points.

The code has another design issue: If both fingers get the same x-position, CalculateSlope divides by 0 and the code crashes.
And it is way to complicated. You found the nice way to find the x-positions of the coordinates (with the fix as above). You can simply do the same for y. This will also solve the "divide by 0" issue.

I changed 'j' to start at 0 and also changed #4 to this:
Code:
perfectPoint.x = touchPoints [touch.fingerId] .x + 												(((touchPoints [touch.fingerId] [lastIndex].x - touchPoints [touch.fingerId] .x) / touchPoints [touch.fingerId].Count) * j);
This gives me the correct length, but for some reason, it's always offset a little bit to the right. I don't understand why because when j = 0, the x coordinate value should be the same as the point the user started touching the screen.

I also try changing the y coordinate calculation to be the same as x's (but replacing every .x with .y) and it did not work. The y coordinate is always offset upwards by a fairly considerable amount.

EDIT: Oh yes, also this only works for one finger. In the slope calculation function, the x2 is the x coordinate that the user lifts his finger off the screen and the y2 is the corresponding y coordinate. x1 and y1 are the coordinates the user first touched the screen at.

haruspex
Homework Helper
Gold Member
What exactly is Count? You need to divide the length by the number of intervals. If Count includes the endpoints than that's Count-1.

What exactly is Count? You need to divide the length by the number of intervals. If Count includes the endpoints than that's Count-1.
The basic idea is, the user draws a line on the screen. Now, when the user draws a line, it won't be perfect. It will also contain a certain number of points. (The number of points is determined by how fast the user moves his finger.) Then I create a perfect line from the point the user started touching the screen to the point he lifted his finger off the screen composed of however many points the original line contains.

Count is the number of points that were counted when when the user drew the line.

I hope that makes sense. I'm not the best at explaining things. :/
And yes, Count includes ALL points (start, end, etc).

EDIT: Also I don't really know what dividing the length by the number of intervals you accomplish.
You mean something like step 1 but changed to:
Code:
float touchLength = Vector2.Distance (touchPoints [touch.fingerId] , touchPoints [touch.fingerId] [lastIndex]) / touchPoints[touch.fingerId].Count - 1;
?
Because the way I figure, is that the length could be long but the x values could only increase very slightly while the y value increases greatly. That will give it a long length but x values will only increase a little bit.

Last edited:
haruspex
Homework Helper
Gold Member
You mean something like step 1 but changed to:
Code:
float touchLength = Vector2.Distance (touchPoints [touch.fingerId] , touchPoints [touch.fingerId] [lastIndex]) / touchPoints[touch.fingerId].Count - 1;
?
Yes, except you need parntheses:
/( touchPoints[touch.fingerId].Count - 1);
If you have three datapoints in a straight line, (x1, y1), (x2, y2), (x3, y3), then y2-y1 = (y3-y1)/2, not (y3-y1)/3. Three points, two intervals. Three power poles, two wires.

I did what you said but didn't fix anything. :(

mfb
Mentor
How does your code look like now?

This is the main part of the code:
Mod note: Redid the indentation in your code to make it easier to read, and so that it wouldn't scroll off the right edge as much.
Code:
int lastIndex = touchPoints [touch.fingerId].Count - 1;
float touchLength =
Vector2.Distance (touchPoints [touch.fingerId] ,
touchPoints [touch.fingerId] [lastIndex]) / (touchPoints [touch.fingerId].Count - 1);

float slope =
HelperFunctions.CalculateSlope (touchPoints [touch.fingerId] .x,
touchPoints [touch.fingerId] [lastIndex].x,
touchPoints [touch.fingerId] .y,
touchPoints [touch.fingerId] [lastIndex].y);
float b =
HelperFunctions.CalculatePointOnLine (slope,
touchPoints [touch.fingerId] .x,
touchPoints [touch.fingerId] .y);

for (int j = 0; j < touchPoints[touch.fingerId].Count - 1; j++) {
Vector2 perfectPoint = new Vector2 (touchPoints [touch.fingerId] [j].x,
(slope * touchPoints [touch.fingerId] [j].x) + b);
}
Those are the 2 helper functions I use:

Code:
public static float CalculateSlope (float y1, float y2, float x1, float x2)
{
float slope = (y2 - y1) / (x2 - x1);

return slope;
}

public static float CalculatePointOnLine (float slope, float x, float y)
{
float b = y - (slope * x);
return b;
}
I also decided to assume the x coordinate the user puts in is correct so I have only have to check for the y. It seems the y is always wrong and the slope sometimes is.

Last edited by a moderator:
haruspex
Homework Helper
Gold Member
Code:
for (int j = 0; j < touchPoints[touch.fingerId].Count - 1; j++) {
Vector2 perfectPoint = new Vector2 (touchPoints [touch.fingerId] [j].x,
(slope * touchPoints [touch.fingerId] [j].x) + b);
}
I can't make sense of that loop.
I thought the inputs were the first and last points, and a count, and you were trying to fill in the intermediate points. The loop above seems to be reading intermediate points and writing to a local vector that then becomes lost memory.

mfb
Mentor
Now you made it even more complicated instead of easier :(. You can calculate both coordinates with a single line of code each, no helper functions necessary.

I just noted another error in post #1: You want your x-position to vary within a range given by the difference in x-position, not the total (2D) distance between initial and final point.

Concerning the loop, I share haruspex' confusion.

I changed the plan a bit. The plan is to re-create each point of the user's touch path on the SAME x coordinate then adjust the y-coordinate based on the corresponding x-coordinate to create a straight line between the start and end point.

This is what I have I changed a lot:
(Thanks for the help so far guys, btw.)
Code:
if (touch.phase == TouchPhase.Ended) {
int lastIndex = touchPoints [touch.fingerId].Count - 1;
float slope = HelperFunctions.CalculateSlope (touchPoints [touch.fingerId] , touchPoints [touch.fingerId] [lastIndex]);
float b = HelperFunctions.CalculatePointOnLine (slope, touchPoints [touch.fingerId] .x, touchPoints [touch.fingerId] .y);

for (int j = 1; j < lastIndex - 1; j++) {
Vector2 perfectPoint = new Vector2 (touchPoints [touch.fingerId] [j].x, (slope * touchPoints [touch.fingerId] [j].x) + b);
}
}
I changed the loop to start at 1 and end at count - 1 because 0 is the start point and count - 1 is the end point, and those 2 points will always be correct.

haruspex
Homework Helper
Gold Member
Code:
	for (int j = 1; j < lastIndex - 1; j++) {
Vector2 perfectPoint = new Vector2 (touchPoints [touch.fingerId] [j].x, (slope * touchPoints [touch.fingerId] [j].x) + b);
}
}
The loop still makes no sense.
In the loop you are creating new vector objects, storing values in them, storing the address in a local variable, then immediately losing that address.
According to your 'new plan', you want update the y values in existing vector objects. There should be no calls to new in the loop.