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

In summary: I think I found the problem. It was in the 'b' calculation function. I had to change it to:public static float CalculatePointOnLine (float slope, float x, float y) { float b = y - (slope * x); b = -b; //this changed it return b; }In summary, the conversation discusses creating a line from a start and end point by creating a number of points at regular intervals. The code calculates the distance between the two points and the slope of the line, uses a loop to create points, and calculates the 'b' value in y = mx + b to determine the y-coordinate of each point. However, the code has a
  • #1
supremeruler
10
0
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] [0], 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] [0].x, touchPoints [touch.fingerId] [lastIndex].x, touchPoints [touch.fingerId] [0].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] [0].x, touchPoints [touch.fingerId] [0].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!
 
Mathematics news on Phys.org
  • #2
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.
 
  • #3
Thanks for your reply.

I changed 'j' to start at 0 and also changed #4 to this:
Code:
perfectPoint.x = touchPoints [touch.fingerId] [0].x + 												(((touchPoints [touch.fingerId] [lastIndex].x - touchPoints [touch.fingerId] [0].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.
 
  • #4
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.
 
  • #5
haruspex said:
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] [0], 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:
  • #6
supremeruler said:
You mean something like step 1 but changed to:
Code:
float touchLength = Vector2.Distance (touchPoints [touch.fingerId] [0], 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.
 
  • #7
I did what you said but didn't fix anything. :(
 
  • #8
How does your code look like now?
 
  • #9
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] [0], 
                    touchPoints [touch.fingerId] [lastIndex]) / (touchPoints [touch.fingerId].Count - 1);
				
float slope = 
  HelperFunctions.CalculateSlope (touchPoints [touch.fingerId] [0].x, 
                                  touchPoints [touch.fingerId] [lastIndex].x,
     			          touchPoints [touch.fingerId] [0].y,
                                  touchPoints [touch.fingerId] [lastIndex].y);
float b = 
  HelperFunctions.CalculatePointOnLine (slope, 
                                        touchPoints [touch.fingerId] [0].x, 
                                        touchPoints [touch.fingerId] [0].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:
  • #10
supremeruler said:
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.
 
  • #11
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.
 
  • #12
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) {
	touchPoints [touch.fingerId].Add (touch.position);
	int lastIndex = touchPoints [touch.fingerId].Count - 1;
	float slope = HelperFunctions.CalculateSlope (touchPoints [touch.fingerId] [0], touchPoints [touch.fingerId] [lastIndex]);
	float b = HelperFunctions.CalculatePointOnLine (slope, touchPoints [touch.fingerId] [0].x, touchPoints [touch.fingerId] [0].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.
 
  • #13
supremeruler said:
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.
 

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

How do I create points on a line using x, y and slope?

To create points on a line using x, y and slope, you can use the formula y = mx + b, where m represents the slope and b represents the y-intercept. Plug in your desired x values and solve for y to get your points.

What is the significance of the slope in creating points on a line?

The slope represents the rate of change between the x and y values. It tells us how much the y value changes for every unit increase in the x value. In creating points on a line, the slope helps determine the position of each point along the line.

Can I use any x and y values to create points on a line?

Yes, you can use any x and y values to create points on a line. However, the points may not fall exactly on the line if the x and y values are not consistent with the given slope.

How many points do I need to create a line using x, y and slope?

You only need two points to create a line using x, y and slope. These two points must be consistent with the given slope in order for the line to be accurate.

Is there an easier way to create points on a line using x, y and slope?

Yes, you can also use the point-slope formula, which is y - y1 = m(x - x1), where (x1, y1) is a given point on the line and m is the slope. This formula can be used to find the coordinates of any point on the line, making it a more efficient method for creating multiple points on a line.

Back
Top