Let's set this up in Python. I'm assuming that all the points are pygame.math.Vector2
objects, so that we can add them and take dot products and so on. I'm also assuming that we're using Python 3, so that division returns a float
. If you're using Python 2, then you'll need:
from __future__ import division
I'm going to use capital letters for vectors and lower case for scalars:
Let's set this up in Python. I'm assuming that all the points are pygame.math.Vector2
objects, so that we can add them and take dot products and so on. I'm going to use capital letters for vectors and lower case for scalars:
Let's set this up in Python. I'm assuming that all the points are pygame.math.Vector2
objects, so that we can add them and take dot products and so on. I'm also assuming that we're using Python 3, so that division returns a float
. If you're using Python 2, then you'll need:
from __future__ import division
I'm going to use capital letters for vectors and lower case for scalars:
Circle with centre q with line segment p1-p2 crossing it
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p_1·p_1 + q·q − 2p_1·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients$$ a = v·v, b = 2(v·(p_1 − q)), c = p_1·p_1 + q·q − 2p_1·q − r^2 $$
$$\begin{array}{rl} a &= v·v \\ b &= 2(v·(p_1 − q)) \\ c &= p_1·p_1 + q·q − 2p_1·q − r^2\end{array}$$
and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p_1·p_1 + q·q − 2p_1·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients$$ a = v·v, b = 2(v·(p_1 − q)), c = p_1·p_1 + q·q − 2p_1·q − r^2 $$ and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Circle with centre q with line segment p1-p2 crossing it
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p_1·p_1 + q·q − 2p_1·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients
$$\begin{array}{rl} a &= v·v \\ b &= 2(v·(p_1 − q)) \\ c &= p_1·p_1 + q·q − 2p_1·q − r^2\end{array}$$
and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p·p + q·q − 2p·q − r^2) = 0 $$$$ t^2(v·v)+2t(v·(p_1 − q)) + (p_1·p_1 + q·q − 2p_1·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients $$ a = v·v, b = 2(v·(p_1 − q)), c = p·p + q·q − 2p·q − r^2 $$$$ a = v·v, b = 2(v·(p_1 − q)), c = p_1·p_1 + q·q − 2p_1·q − r^2 $$ and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Now, the closest point on the extended line to the centre of the circle is \$ p_1 + tv \$ where $$ t = { (p_1 - q)·v \over \lvert v \rvert^2 } = { b \over 2a }. $$$$ t = { (q - p_1)·v \over \lvert v \rvert^2 } = { -b \over 2a }. $$ See Wikipedia for an explanation. But we want to ensure that the point is on the line segment, so we must clamp \$ t \$ to lie between 0 and 1.
t = max(0, min(1, - b / (2 * a)))
return True, P1 + t * V
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p·p + q·q − 2p·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients $$ a = v·v, b = 2(v·(p_1 − q)), c = p·p + q·q − 2p·q − r^2 $$ and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Now, the closest point on the extended line to the centre of the circle is \$ p_1 + tv \$ where $$ t = { (p_1 - q)·v \over \lvert v \rvert^2 } = { b \over 2a }. $$ See Wikipedia for an explanation. But we want to ensure that the point is on the line segment, so we must clamp \$ t \$ to lie between 0 and 1.
t = max(0, min(1, b / (2 * a)))
return True, P1 + t * V
Now, a point \$ x \$ is on the circle if its distance from the centre of the circle is equal to the circle's radius, that is, if $$ \lvert x - q \rvert = r. $$ So the line intersects the circle when $$ \lvert p_1 + tv - q \rvert = r. $$ Squaring both sides gives $$ \lvert p_1 + tv - q \rvert^2 = r^2, $$ and now we can use a property of the dot product (namely \$ \lvert A \rvert^2 = A·A \$ for any vector \$ A \$) to get $$ (p_1 + tv - q)·(p_1 + tv - q) = r^2. $$ Expanding the dot product and collecting powers of \$ t \$ gives $$ t^2(v·v)+2t(v·(p_1 − q)) + (p_1·p_1 + q·q − 2p_1·q − r^2) = 0 $$ which is a quadratic equation in \$ t \$ with coefficients $$ a = v·v, b = 2(v·(p_1 − q)), c = p_1·p_1 + q·q − 2p_1·q − r^2 $$ and solutions $$ t = { −b ± \sqrt{b^2 − 4ac} \over 2a }. $$ Let's compute the coefficients in Python:
Now, the closest point on the extended line to the centre of the circle is \$ p_1 + tv \$ where $$ t = { (q - p_1)·v \over \lvert v \rvert^2 } = { -b \over 2a }. $$ See Wikipedia for an explanation. But we want to ensure that the point is on the line segment, so we must clamp \$ t \$ to lie between 0 and 1.
t = max(0, min(1, - b / (2 * a)))
return True, P1 + t * V
- 50.1k
- 3
- 130
- 210