83

Let's say you have two points, $(x_0, y_0)$ and $(x_1, y_1)$.

The gradient of the line between them is:

$$m = (y_1 - y_0)/(x_1 - x_0)$$

And therefore the equation of the line between them is:

$$y = m (x - x_0) + y_0$$

Now, since I want another point along this line, but a distance $d$ away from $(x_0, y_0)$, I will get an equation of a circle with radius $d$ with a center $(x_0, y_0)$ then find the point of intersection between the circle equation and the line equation.

Circle Equation w/ radius $d$:

$$(x - x_0)^2 + (y - y_0)^2 = d^2$$

Now, if I replace $y$ in the circle equation with $m(x - x_0) + y_0$ I get:

$$(x - x_0)^2 + m^2(x - x_0)^2 = d^2$$

I factor is out and simplify it and I get:

$$x = x_0 \pm d/ \sqrt{1 + m^2}$$

However, upon testing this equation out it seems that it does not work! Is there an obvious error that I have made in my theoretical side or have I just been fluffing up my calculations?

Kel196
  • 999
  • 2
    Looks about right to me. In particular, it gives the right result for reasonable values of $m = 0$, $m = 1$, $m = \infty$. Maybe there is a bug in your implementation. –  Jul 27 '12 at 15:28
  • 1
    Thanks for the quick reply Rahul, i've been trying to programme this and you are right! it was an error in my implementation. Thank you for taking the time to read my question! – Kel196 Jul 27 '12 at 15:34
  • @enzotib: It is considered impolite in this site to remove or add "thank you" comments. – Asaf Karagila Jul 27 '12 at 18:55
  • 1
    @AsafKaragila: sorry, I didn't know, in other SE sites it is considered superfluous to have such comments. I will take it into account for the future. – Vincenzo Tibullo Jul 27 '12 at 18:57
  • @Asaf: I didn't know that either. Is there a meta thread about this that I missed? –  Jul 27 '12 at 21:43
  • @Rahul: You can see that more than a handful of people expressed this opinion in various comments over meta threads. I cannot give you any recent event which is not a comment I wrote. However it feels that at least those participating the meta discussions tend to agree with that. If your Google search-fu is good you can probably find such comments on your own. – Asaf Karagila Jul 27 '12 at 21:50

8 Answers8

64

Let me explain the answer in a simple way.

Start point - $(x_0, y_0)$

End point - $(x_1, y_1)$

We need to find a point $(x_t, y_t)$ at a distance $d_t$ from start point towards end point.

Point on a line at a distance

The distance between Start and End point is given by $d = \sqrt{(x_1-x_0)^2+(y_1-y_0)^2}$

Let the ratio of distances, $t=d_t/d$

Then the point $(x_t, y_t) =(((1-t)x_0+tx_1), ((1-t)y_0+ty_1))$

When $0<t<1$, the point is on the line.

When $t<0$, the point is outside the line near to $(x_0,y_0)$.

When $t>1$, the point is outside the line near to $(x_1,y_1)$.

Bogdan
  • 103
Sen Jacob
  • 743
  • 1
    Shouldn't t = d / dt? – skibulk Apr 21 '16 at 01:54
  • 3
    @skibulk nope it's t = dt / t when I applied this to my code I followed your comment. But something was bugging out, turns out t = dt / t is correct. – Marlon Aug 09 '16 at 09:40
  • 2
    @Marlon Thank you for confirming it. – Sen Jacob Aug 09 '16 at 15:00
  • 1
    Oh yes, you're correct. For some reason it I was thinking dt was "distance total" of the segment, which is be the divisor. Bit I guess it's supposed to be "distance time". Anyway, it's correct according to the illustration. – skibulk Aug 09 '16 at 16:17
  • Multiplying x1 and y1 by t is clear but what is the logic behind multiplying x0 and y0 by (1-t) in (xt,yt)=(((1−t)x0+tx1),((1−t)y0+ty1)) ? Playing with the formula made it clear it was necessary but I wasn't able to intuit the logic behind it. – Michael Aug 12 '18 at 14:58
  • 1
    If you only want to extend the line by a percentage, you don't need to calculate the distance, where p is a decimal percentage: dt = d * p, t = (d * p) / d, thus t = p – Kyle Apr 11 '19 at 17:23
  • what if the second point is origin (i.e 0,0) ? I'm trying to use this for a pie chart centered at 0,0 and to move the slices, i get a line between start and end point of arc, from that line's center to the origin of the pie, a line is drawn and 20% of that line is what my pie should move to. – Arun Panneerselvam Oct 27 '19 at 10:17
  • @CosmoArun I presume you mean a Nightingale's Rose chart. In normal pie chart you might not need to move along a line at any angle. Consider your points in reverse order, for 20% from origin, t = 0.2 and you will get the points (0.2x1, 0.2y1) where (x1, y1) is your end point. – Sen Jacob Oct 28 '19 at 03:08
  • 1
    @SenJacob , I did it and it's working. Look at Pontios answer here (seems to me an extension of your answer). well descriptive, besides I have a largeArc Flag set for larger arcs more than 180 deg. So, svg takes care of the rest. (PS: I did it in SVG and it works great! thanks though!) Anyway, you deserve a upvote, I just upvoted your answer. – Arun Panneerselvam Oct 29 '19 at 21:19
61

Another way, using vectors:

Let $\mathbf v = (x_1,y_1)-(x_0,y_0)$. Normalize this to $\mathbf u = \frac{\mathbf v}{||\mathbf v||}$.

The point along your line at a distance $d$ from $(x_0,y_0)$ is then $(x_0,y_0)+d\mathbf u$, if you want it in the direction of $(x_1,y_1)$, or $(x_0,y_0)-d\mathbf u$, if you want it in the opposite direction. One advantage of doing the calculation this way is that you won't run into a problem with division by zero in the case that $x_0 = x_1$.

Théophile
  • 24,627
  • 1
    Thanks Theophile, absolutely ace method. I didn't even think about vectors! – Kel196 Jul 27 '12 at 16:03
  • Can you elaborate a little bit more on this solution or point me to a link so that I can understand it a little more? A program written would be awesome as well. – Dewey Sep 13 '14 at 22:08
  • 1
    @Dewey Which part are you having trouble understanding? – Théophile Sep 14 '14 at 13:07
  • How would you do Normalize this to u=v/||v||? – Dewey Sep 17 '14 at 14:16
  • 7
    @Dewey The length of a vector $\mathbf v = (v_1,v_2)$ is defined as $||\mathbf v|| = \sqrt{v_1^2 + v_2^2}$. The vector $\mathbf v \over ||\mathbf v||$, that is, $\Big(\dfrac{v_1}{\sqrt{v_1^2 + v_2^2}}, \dfrac{v_2}{\sqrt{v_1^2 + v_2^2}}\Big)$, points in the same direction as $\mathbf v$ and has unit length. For example, if $\mathbf v = (3,4)$, then $\mathbf u = ({3 \over 5}, {4 \over 5})$. – Théophile Sep 20 '14 at 23:00
  • I'm having trouble with this answer because I can't read the math notations and don't know what to Google. ("Vector notation" gives me something different). Anyway, I'm trying to solve individually for x and y given a distance. So I'd get x = x0 + du and y = y0 + du. But I can't figure out what du would be for the x component and the y component... can someone help? – jpwrunyan May 30 '19 at 00:03
  • 1
    @jpwrunyan Which notation are you having difficulty with? – Théophile May 30 '19 at 16:57
  • lol, I wish I knew how to write them. I also think I figured out the answer I was looking for, but I wish I could read the ||v|| or understand how to write it in high school math format. The v2/1 (where the 2 is over the 1) and v2/2 also throw me off. Is that referring to column/row where the x and y's are in a matrix? I can barely read matrix notation since I use it sometimes in programming. Thanks for asking by the way. I feel my question here probably needs to be asked elsewhere since it's pretty broadly "how do I read math"? – jpwrunyan May 31 '19 at 21:27
  • 3
    @jpwrunyan Ah, I see! Okay, first, $||\bf v||$ refers to the length of the vector $\bf v$, which you can calculate using Pythagoras's theorem. In other words, if ${\bf v}=(x,y)$, then its length is $\sqrt{x^2+y^2}$. Next, about $v_1^2$ and $v_2^2$: these are easier than you think! They're just a compact way of writing $(v_1)^2$ and $(v_2)^2$, so in fact they aren't related to matrix notation (although that was a good guess). So if ${\bf v}=(x,y)$, then $||{\bf v}||=\sqrt{x^2+y^2}$; this is exactly the same as my previous comment but with differently named variables. Does that make more sense? – Théophile May 31 '19 at 21:48
  • Yes! The first part about ||v|| makes sense. In v = (x, y), the x and y are x2 - x1 and y2 - y1. And now that you pointed it out, the power notation is obvious. I don't know what was wrong with me. – jpwrunyan Jun 01 '19 at 22:39
  • 1
21

You can very easily find it with trigonometry!!

Let's say Xa and Xb are the two points of your line, and D is the distance between them. And you are looking to find Xc which is D2 away from Xa (as the diagram bellow):

enter image description here

You can easily find D:

euclidean distance between Xa and Xb

The formulas that you can find Xa, Xb, Xc, D and D2 are:

enter image description here

But SINa-b and SINa-c share the same the same corner, so they are equal:

enter image description here

Since you know the distance (D2) between Xa and Xc that you are looking for, you can easily solve the following:

enter image description here

In conclusion by solving the formula for D and the last one you are done. (You need one for the Y as well, just replace in the last one, X with Y )

Hope it helps!!

Pontios
  • 319
3

The easy way in rectangular coordinate systems is to use the vector formula
P = d(B - A) + A
where
A is the starting point (x0, y0) of the line segment
B is the end point (x1, y1)
d is the distance from starting point A to the desired collinear point
P is the desired collinear point

1

I think your method is working. Here is the python code for the test and output of the test is linked below,

import numpy as np
import matplotlib.pyplot as plt

def f(x, m, c): y = m*x + c return y

def X(x0,d,m): x1 = x0 + (d/np.sqrt(1+m2)) x2 = x0 - (d/np.sqrt(1+m2)) return np.array([x1, x2])

x = np.arange(1,5,0.5) m = 1 c = 0.5 plt.plot(x, f(x, m, c), "-")

x0 = 3 d = np.array([0.25, 0.5, 0.75, 1])

X = X(x0,d,m) print(type(X)) plt.plot(X, f(X,m, c), "o") plt.show()

Output of the above code:[1] https://i.stack.imgur.com/n0XJH.png

0

I think you need to check $x_0 > x_1$ when you try to calculate $x$ (last equation in your calculation) then you determine it will be $(+)$ or $(-)$ in your equation.

  • Thank you for your contribution. This site supports basic TeX syntax, which allows formulas to be nicely typeset as $x_0>x_1$, for example. There is a short TeX tutorial. You may want to try using TeX by editing your answer (the link edit is under your post). Welcome to Math.SE! –  Jan 01 '13 at 05:47
0

There is an other way to solve this problem.

The function $\rho:\mathbb R \to \mathbb R^2$ defined by

$$\rho(t) = (1-t)(x_0,y_0) + t(x_1,y_1)$$

describes the line through the points $(x_0,y_0)$ and $(x_1,y_1)$ with $\rho(0) = (x_0, y_0)$ and $\rho(1)=(x_1,y_1)$. If you let $$D = \sqrt{(x_1-x_0)^2 + (y_1-y_0)^2},$$ then it is fairly easy to show that

$$|\rho(t) - \rho(s)| = D|t-s|$$

So, if you want to find the points a distance of $d$ from $(x_0,y_0)$, then you need to solve $$d = |\rho(t) - \rho(0)| = D|t-0|$$

You get $ t = \pm \dfrac dD$. Hence the points are

$$\rho\left( \pm \dfrac dD \right) = \left\{ \begin{array}{c} \left( 1-\dfrac dD \right)(x_0,y_0) + \dfrac dD (x_1,y_1) \\ \left( 1+\dfrac dD \right)(x_0,y_0) - \dfrac dD (x_1,y_1) \end{array} \right.$$

0

Simply put, for desired distance d, x of this point is:

$$ x_1 + d \cdot \cos(\arctan(a)) \iff a = (\frac{y_2-y_1}{x_2-x_1}) $$

THIS IS HOW:

You have given two points:

$$ P = (x_p, y_p) \\ Q = (x_q, y_q) $$

and line between them defined with the function f(x):

$$ m = \frac{y_q - y_p}{x_q - x_p} \\\ \\ f(x) = m(x - x_p) + y_p $$

or:

$$ a = \frac{y_q-y_p}{x_q-x_p} \\\ \\ b = \frac{x_{q}y_{p} - x_{p}y_{q}}{x_q-x_p} \\\ \\ f(x) = ax + b $$

You're looking for a point R between P and Q.
Note that we can "render" a triangle with the points P and R and use it to get a width of a side that we have to know. We know one side - it's desired distance, and the angle that equals $\arctan(a)$. Let's see all this stuff in the picture:

Finding point by distance from other ones

We need to calculate x' and then our point R is $(x_p+x', f(x_p+x'))$.
Example calculations for desired distance 3:

  • we have two points:

$$ P = (0, 2) \\ Q = (4, 4) $$

  • and the line between them:

$$ f(x) = \frac{1}{2}x + 2 $$

  • our distance is 3:

$$ d = 3 $$

  • we're getting an angle:

$$ \alpha = \arctan(\frac{1}{2}) = 0.4637 $$

  • now we can get a distance along X-axis:

$$ x' = d \cdot cos(\alpha) = 3 \cdot 0.8944 = 2.6832 $$

so x of our point R is:

$$ x_r = x_p + x' = 0 + 2.6832 = 2.6832 $$

and our point is at:

$$ (x_r, f(x_r)) = (2.6832, 3.3416) $$


Example implementation in JavaScript:

function findPointByDistance(p1, p2, dist) {
    const [x1,y1] = p1;
    const [x2,y2] = p2;
const m = (y2-y1)/(x2-x1);
const f = x =&gt; m*(x-x1) + y1;

const alpha = Math.atan(m);
const xVector = dist * Math.cos(alpha);
const foundX = x1 + xVector;

return 
    foundX,
    f(foundX)
].map(v =&gt; +v.toFixed(2));

}

const P = [0,2];
const Q = [4,4];
const d = 3;

findPointByDistance(P, Q, d);
// [ 2.68, 3.34 ]