How to find nearest point on line of rectangle from anywhere?
$begingroup$
Having a rectangle where upper left corner, width and height is given. How can I find nearest line on that rectangle from any point?
To visualize. Having the rectangle (OK, here a square, but anyhow) ABCD. Green dots represents points and red lines intersections I want to find.

E.g. having point k I would like to find i. My current approach is as follows:
- Calculate centre of rectangle (E).
Normalize point,
Pagainst centre:
Px = kx - Ex
Py = ky - Ey
Use atan2 on
Pto find which plane it belongs to.
By plane I mean: I divide the rectangle in eight planes as with a quadrant - but divide those four in half as well. Atan2 is a
special arctan variant that gives value {0, Π} for points below
x-axis and {0, -Π} above x-axis.
{-PI/2, -PI} y {-0, -PI/2}
A +------------|-------------.+ B
| . | . |
| . 3 | 2 . |
| . | . |
| . | . |
| 4 . | . 1 |
| .| . |
-------------E--------------- x
| . | . |
| 5 . | . |
| . | . 8 |
| . | . | {PI/2, PI} | {0, PI/2}
| . | . |
| . 6 | 7 . |
| . | .|
D +------------|----i---------+ C
|
|
|
k
Then I do a check by:
IF atan2 > PI / 4 * 3 THEN
Plane 5: use A.x for x, and points y-value.
ELSE IF atan2 > PI / 4 * 2 THEN
Plane 6: use D.y for y, and points x-value.
...
By sample from picture that would give
atan2 < PI / 4 * 3
atan2 < PI / 4 * 2
atan2 > PI / 4 <-- OK at plane 7.
I would believe there is a more direct approach for this. Any help would be
greatly appreciated. My mathematics is very rusty, but working on it.
EDIT:
OK. Looking at my nice ASCII I realized I can combine planes:
- 1 + 8 Use x from C by check on absolute value of atan2 (0 to PI/4)
- 2 + 3 Use y from A
- 4 + 5 Use x from A by check on absolute value of atan2 (PI/4*3 to PI)
- 6 + 7 Use y from C
Eliminating quite a few steps. I have to look closer at Billy's nice
answer as well.
However I thought there might be a more direct approach. As in:
f(x, y, ABCD) .... => point ;)
geometry
$endgroup$
add a comment |
$begingroup$
Having a rectangle where upper left corner, width and height is given. How can I find nearest line on that rectangle from any point?
To visualize. Having the rectangle (OK, here a square, but anyhow) ABCD. Green dots represents points and red lines intersections I want to find.

E.g. having point k I would like to find i. My current approach is as follows:
- Calculate centre of rectangle (E).
Normalize point,
Pagainst centre:
Px = kx - Ex
Py = ky - Ey
Use atan2 on
Pto find which plane it belongs to.
By plane I mean: I divide the rectangle in eight planes as with a quadrant - but divide those four in half as well. Atan2 is a
special arctan variant that gives value {0, Π} for points below
x-axis and {0, -Π} above x-axis.
{-PI/2, -PI} y {-0, -PI/2}
A +------------|-------------.+ B
| . | . |
| . 3 | 2 . |
| . | . |
| . | . |
| 4 . | . 1 |
| .| . |
-------------E--------------- x
| . | . |
| 5 . | . |
| . | . 8 |
| . | . | {PI/2, PI} | {0, PI/2}
| . | . |
| . 6 | 7 . |
| . | .|
D +------------|----i---------+ C
|
|
|
k
Then I do a check by:
IF atan2 > PI / 4 * 3 THEN
Plane 5: use A.x for x, and points y-value.
ELSE IF atan2 > PI / 4 * 2 THEN
Plane 6: use D.y for y, and points x-value.
...
By sample from picture that would give
atan2 < PI / 4 * 3
atan2 < PI / 4 * 2
atan2 > PI / 4 <-- OK at plane 7.
I would believe there is a more direct approach for this. Any help would be
greatly appreciated. My mathematics is very rusty, but working on it.
EDIT:
OK. Looking at my nice ASCII I realized I can combine planes:
- 1 + 8 Use x from C by check on absolute value of atan2 (0 to PI/4)
- 2 + 3 Use y from A
- 4 + 5 Use x from A by check on absolute value of atan2 (PI/4*3 to PI)
- 6 + 7 Use y from C
Eliminating quite a few steps. I have to look closer at Billy's nice
answer as well.
However I thought there might be a more direct approach. As in:
f(x, y, ABCD) .... => point ;)
geometry
$endgroup$
add a comment |
$begingroup$
Having a rectangle where upper left corner, width and height is given. How can I find nearest line on that rectangle from any point?
To visualize. Having the rectangle (OK, here a square, but anyhow) ABCD. Green dots represents points and red lines intersections I want to find.

E.g. having point k I would like to find i. My current approach is as follows:
- Calculate centre of rectangle (E).
Normalize point,
Pagainst centre:
Px = kx - Ex
Py = ky - Ey
Use atan2 on
Pto find which plane it belongs to.
By plane I mean: I divide the rectangle in eight planes as with a quadrant - but divide those four in half as well. Atan2 is a
special arctan variant that gives value {0, Π} for points below
x-axis and {0, -Π} above x-axis.
{-PI/2, -PI} y {-0, -PI/2}
A +------------|-------------.+ B
| . | . |
| . 3 | 2 . |
| . | . |
| . | . |
| 4 . | . 1 |
| .| . |
-------------E--------------- x
| . | . |
| 5 . | . |
| . | . 8 |
| . | . | {PI/2, PI} | {0, PI/2}
| . | . |
| . 6 | 7 . |
| . | .|
D +------------|----i---------+ C
|
|
|
k
Then I do a check by:
IF atan2 > PI / 4 * 3 THEN
Plane 5: use A.x for x, and points y-value.
ELSE IF atan2 > PI / 4 * 2 THEN
Plane 6: use D.y for y, and points x-value.
...
By sample from picture that would give
atan2 < PI / 4 * 3
atan2 < PI / 4 * 2
atan2 > PI / 4 <-- OK at plane 7.
I would believe there is a more direct approach for this. Any help would be
greatly appreciated. My mathematics is very rusty, but working on it.
EDIT:
OK. Looking at my nice ASCII I realized I can combine planes:
- 1 + 8 Use x from C by check on absolute value of atan2 (0 to PI/4)
- 2 + 3 Use y from A
- 4 + 5 Use x from A by check on absolute value of atan2 (PI/4*3 to PI)
- 6 + 7 Use y from C
Eliminating quite a few steps. I have to look closer at Billy's nice
answer as well.
However I thought there might be a more direct approach. As in:
f(x, y, ABCD) .... => point ;)
geometry
$endgroup$
Having a rectangle where upper left corner, width and height is given. How can I find nearest line on that rectangle from any point?
To visualize. Having the rectangle (OK, here a square, but anyhow) ABCD. Green dots represents points and red lines intersections I want to find.

E.g. having point k I would like to find i. My current approach is as follows:
- Calculate centre of rectangle (E).
Normalize point,
Pagainst centre:
Px = kx - Ex
Py = ky - Ey
Use atan2 on
Pto find which plane it belongs to.
By plane I mean: I divide the rectangle in eight planes as with a quadrant - but divide those four in half as well. Atan2 is a
special arctan variant that gives value {0, Π} for points below
x-axis and {0, -Π} above x-axis.
{-PI/2, -PI} y {-0, -PI/2}
A +------------|-------------.+ B
| . | . |
| . 3 | 2 . |
| . | . |
| . | . |
| 4 . | . 1 |
| .| . |
-------------E--------------- x
| . | . |
| 5 . | . |
| . | . 8 |
| . | . | {PI/2, PI} | {0, PI/2}
| . | . |
| . 6 | 7 . |
| . | .|
D +------------|----i---------+ C
|
|
|
k
Then I do a check by:
IF atan2 > PI / 4 * 3 THEN
Plane 5: use A.x for x, and points y-value.
ELSE IF atan2 > PI / 4 * 2 THEN
Plane 6: use D.y for y, and points x-value.
...
By sample from picture that would give
atan2 < PI / 4 * 3
atan2 < PI / 4 * 2
atan2 > PI / 4 <-- OK at plane 7.
I would believe there is a more direct approach for this. Any help would be
greatly appreciated. My mathematics is very rusty, but working on it.
EDIT:
OK. Looking at my nice ASCII I realized I can combine planes:
- 1 + 8 Use x from C by check on absolute value of atan2 (0 to PI/4)
- 2 + 3 Use y from A
- 4 + 5 Use x from A by check on absolute value of atan2 (PI/4*3 to PI)
- 6 + 7 Use y from C
Eliminating quite a few steps. I have to look closer at Billy's nice
answer as well.
However I thought there might be a more direct approach. As in:
f(x, y, ABCD) .... => point ;)
geometry
geometry
edited Apr 13 '17 at 12:20
Community♦
1
1
asked Apr 10 '13 at 5:26
ZimzalabimZimzalabim
1186
1186
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
$begingroup$
That sounds more or less sensible, but there are some difficult cases you've forgotten to check for. It also doesn't quite work when the rectangle isn't a square. I think the best solution is actually a little simpler.
For simplicity, let me give this rectangle some coordinates: call the bottom left point (0, 0), the bottom right point (a, 0), the top left point (0, b) and the top right point (a, b).
The embarrassingly garish image below shows that there are actually 8 regions you need to look at. The good news is: if k is outside the square, you can just read off the nearest point and calculate its distance directly. (For example, if k is in the light blue area above the square, with coordinates (x, y), the nearest point on the rectangle is (x, b). If it's in the yellow area to the left, with coordinates (x, y), the nearest point is (0, y). If it's in the pink area to the lower right, the nearest point is (a, 0).)
If k is inside the square, it's a little more annoying. But the basic recipe is the same. If k has coordinates (x, y), you need to work out which is smallest out of these four numbers: x, a-x, y, b-y. If x is the smallest, the nearest point is (0, y). If a-x is the smallest, the nearest point is (a, y). And so on.
There are also ambiguous points, like (a/2, b/2), which have more than one 'nearest point'.

I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)
$endgroup$
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
add a comment |
$begingroup$
Having recently coded a simple physics engine for a course, I did this as a part of rectangle-circle collision. Being put into practice means that my method is verified to work, since bugs would otherwise occur.
For clarity, let's call P the point you wish to find the closest point to on the rectangle.
When P is outside of the rectangle the closest point on the rectangle is P clamped to the bounds of the rectangle.
If P is inside the rectangle you need to work out which side is the closest, then use that side's coordinate as the value on the corresponding axis for the closest point.
For example, if your point is the closest to the negative Y bound (Bottom) then the closest point is (P.x, Bottom), where P.x is the X coordinate of the point P and Bottom is the Y coordinate of the negative Y bound. And if P is the closest to the negative X bound (Left) then it's (Left, P.y), e.t.c..
There are ambiguous points in the exact middle between two sides, which have more than one closest point.
In pseudocode:
bool insideX = center.x-bounds.x < P.x && P.x < center.x+bounds.x;
bool insideY = center.y-bounds.y < P.y && P.y < center.y+bounds.y;
bool pointInsideRectangle = insideX && insideY;
if (!pointInsideRectangle){ //Outside
closestPoint.x = Max(center.x-bounds.x, Min(P.x, center.x + bounds.x));
closestPoint.y = Max(center.y-bounds.y, Min(P.y, center.y + bounds.y));
}
else { //Inside
Vector2D distanceToPositiveBounds = center+bounds - P;
Vector2D distanceToNegativeBounds = -(center-bounds - P);
float smallestX = Min(distanceToPositiveBounds.x, distanceToNegativeBounds.x);
float smallestY = Min(distanceToPositiveBounds.y, distanceToNegativeBounds.y);
float smallestDistance = Min(smallestX, smallestY);
if (smallestDistance == distanceToPositiveBounds.x)
closestPoint = (center.x+bounds.x, P.y);
else if (smallestDistance == distanceToNegativeBounds.x)
closestPoint = (center.x-bounds.x, P.y);
else if (smallestDistance == distanceToPositiveBounds.y)
closestPoint = (P.x, center.y+bounds.y);
else
closestPoint = (P.x, center.y-bounds.y);
}
Where Max returns the largest of two values and Min returns the smallest.
The code assumes that rectangle data is stored as center and bounds; for example center.y+bounds.y is the Y coordinate of the higher bound (Top) of the rectangle.
Actual code used can be found here.
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["$", "$"], ["\\(","\\)"]]);
});
});
}, "mathjax-editing");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "69"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmath.stackexchange.com%2fquestions%2f356792%2fhow-to-find-nearest-point-on-line-of-rectangle-from-anywhere%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
That sounds more or less sensible, but there are some difficult cases you've forgotten to check for. It also doesn't quite work when the rectangle isn't a square. I think the best solution is actually a little simpler.
For simplicity, let me give this rectangle some coordinates: call the bottom left point (0, 0), the bottom right point (a, 0), the top left point (0, b) and the top right point (a, b).
The embarrassingly garish image below shows that there are actually 8 regions you need to look at. The good news is: if k is outside the square, you can just read off the nearest point and calculate its distance directly. (For example, if k is in the light blue area above the square, with coordinates (x, y), the nearest point on the rectangle is (x, b). If it's in the yellow area to the left, with coordinates (x, y), the nearest point is (0, y). If it's in the pink area to the lower right, the nearest point is (a, 0).)
If k is inside the square, it's a little more annoying. But the basic recipe is the same. If k has coordinates (x, y), you need to work out which is smallest out of these four numbers: x, a-x, y, b-y. If x is the smallest, the nearest point is (0, y). If a-x is the smallest, the nearest point is (a, y). And so on.
There are also ambiguous points, like (a/2, b/2), which have more than one 'nearest point'.

I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)
$endgroup$
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
add a comment |
$begingroup$
That sounds more or less sensible, but there are some difficult cases you've forgotten to check for. It also doesn't quite work when the rectangle isn't a square. I think the best solution is actually a little simpler.
For simplicity, let me give this rectangle some coordinates: call the bottom left point (0, 0), the bottom right point (a, 0), the top left point (0, b) and the top right point (a, b).
The embarrassingly garish image below shows that there are actually 8 regions you need to look at. The good news is: if k is outside the square, you can just read off the nearest point and calculate its distance directly. (For example, if k is in the light blue area above the square, with coordinates (x, y), the nearest point on the rectangle is (x, b). If it's in the yellow area to the left, with coordinates (x, y), the nearest point is (0, y). If it's in the pink area to the lower right, the nearest point is (a, 0).)
If k is inside the square, it's a little more annoying. But the basic recipe is the same. If k has coordinates (x, y), you need to work out which is smallest out of these four numbers: x, a-x, y, b-y. If x is the smallest, the nearest point is (0, y). If a-x is the smallest, the nearest point is (a, y). And so on.
There are also ambiguous points, like (a/2, b/2), which have more than one 'nearest point'.

I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)
$endgroup$
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
add a comment |
$begingroup$
That sounds more or less sensible, but there are some difficult cases you've forgotten to check for. It also doesn't quite work when the rectangle isn't a square. I think the best solution is actually a little simpler.
For simplicity, let me give this rectangle some coordinates: call the bottom left point (0, 0), the bottom right point (a, 0), the top left point (0, b) and the top right point (a, b).
The embarrassingly garish image below shows that there are actually 8 regions you need to look at. The good news is: if k is outside the square, you can just read off the nearest point and calculate its distance directly. (For example, if k is in the light blue area above the square, with coordinates (x, y), the nearest point on the rectangle is (x, b). If it's in the yellow area to the left, with coordinates (x, y), the nearest point is (0, y). If it's in the pink area to the lower right, the nearest point is (a, 0).)
If k is inside the square, it's a little more annoying. But the basic recipe is the same. If k has coordinates (x, y), you need to work out which is smallest out of these four numbers: x, a-x, y, b-y. If x is the smallest, the nearest point is (0, y). If a-x is the smallest, the nearest point is (a, y). And so on.
There are also ambiguous points, like (a/2, b/2), which have more than one 'nearest point'.

I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)
$endgroup$
That sounds more or less sensible, but there are some difficult cases you've forgotten to check for. It also doesn't quite work when the rectangle isn't a square. I think the best solution is actually a little simpler.
For simplicity, let me give this rectangle some coordinates: call the bottom left point (0, 0), the bottom right point (a, 0), the top left point (0, b) and the top right point (a, b).
The embarrassingly garish image below shows that there are actually 8 regions you need to look at. The good news is: if k is outside the square, you can just read off the nearest point and calculate its distance directly. (For example, if k is in the light blue area above the square, with coordinates (x, y), the nearest point on the rectangle is (x, b). If it's in the yellow area to the left, with coordinates (x, y), the nearest point is (0, y). If it's in the pink area to the lower right, the nearest point is (a, 0).)
If k is inside the square, it's a little more annoying. But the basic recipe is the same. If k has coordinates (x, y), you need to work out which is smallest out of these four numbers: x, a-x, y, b-y. If x is the smallest, the nearest point is (0, y). If a-x is the smallest, the nearest point is (a, y). And so on.
There are also ambiguous points, like (a/2, b/2), which have more than one 'nearest point'.

I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)
answered Apr 10 '13 at 5:53
BillyBilly
3,552818
3,552818
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
add a comment |
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
$begingroup$
Thanks. I'll look at this and do some testing. Need to try it out :)
$endgroup$
– Zimzalabim
Apr 10 '13 at 6:05
add a comment |
$begingroup$
Having recently coded a simple physics engine for a course, I did this as a part of rectangle-circle collision. Being put into practice means that my method is verified to work, since bugs would otherwise occur.
For clarity, let's call P the point you wish to find the closest point to on the rectangle.
When P is outside of the rectangle the closest point on the rectangle is P clamped to the bounds of the rectangle.
If P is inside the rectangle you need to work out which side is the closest, then use that side's coordinate as the value on the corresponding axis for the closest point.
For example, if your point is the closest to the negative Y bound (Bottom) then the closest point is (P.x, Bottom), where P.x is the X coordinate of the point P and Bottom is the Y coordinate of the negative Y bound. And if P is the closest to the negative X bound (Left) then it's (Left, P.y), e.t.c..
There are ambiguous points in the exact middle between two sides, which have more than one closest point.
In pseudocode:
bool insideX = center.x-bounds.x < P.x && P.x < center.x+bounds.x;
bool insideY = center.y-bounds.y < P.y && P.y < center.y+bounds.y;
bool pointInsideRectangle = insideX && insideY;
if (!pointInsideRectangle){ //Outside
closestPoint.x = Max(center.x-bounds.x, Min(P.x, center.x + bounds.x));
closestPoint.y = Max(center.y-bounds.y, Min(P.y, center.y + bounds.y));
}
else { //Inside
Vector2D distanceToPositiveBounds = center+bounds - P;
Vector2D distanceToNegativeBounds = -(center-bounds - P);
float smallestX = Min(distanceToPositiveBounds.x, distanceToNegativeBounds.x);
float smallestY = Min(distanceToPositiveBounds.y, distanceToNegativeBounds.y);
float smallestDistance = Min(smallestX, smallestY);
if (smallestDistance == distanceToPositiveBounds.x)
closestPoint = (center.x+bounds.x, P.y);
else if (smallestDistance == distanceToNegativeBounds.x)
closestPoint = (center.x-bounds.x, P.y);
else if (smallestDistance == distanceToPositiveBounds.y)
closestPoint = (P.x, center.y+bounds.y);
else
closestPoint = (P.x, center.y-bounds.y);
}
Where Max returns the largest of two values and Min returns the smallest.
The code assumes that rectangle data is stored as center and bounds; for example center.y+bounds.y is the Y coordinate of the higher bound (Top) of the rectangle.
Actual code used can be found here.
$endgroup$
add a comment |
$begingroup$
Having recently coded a simple physics engine for a course, I did this as a part of rectangle-circle collision. Being put into practice means that my method is verified to work, since bugs would otherwise occur.
For clarity, let's call P the point you wish to find the closest point to on the rectangle.
When P is outside of the rectangle the closest point on the rectangle is P clamped to the bounds of the rectangle.
If P is inside the rectangle you need to work out which side is the closest, then use that side's coordinate as the value on the corresponding axis for the closest point.
For example, if your point is the closest to the negative Y bound (Bottom) then the closest point is (P.x, Bottom), where P.x is the X coordinate of the point P and Bottom is the Y coordinate of the negative Y bound. And if P is the closest to the negative X bound (Left) then it's (Left, P.y), e.t.c..
There are ambiguous points in the exact middle between two sides, which have more than one closest point.
In pseudocode:
bool insideX = center.x-bounds.x < P.x && P.x < center.x+bounds.x;
bool insideY = center.y-bounds.y < P.y && P.y < center.y+bounds.y;
bool pointInsideRectangle = insideX && insideY;
if (!pointInsideRectangle){ //Outside
closestPoint.x = Max(center.x-bounds.x, Min(P.x, center.x + bounds.x));
closestPoint.y = Max(center.y-bounds.y, Min(P.y, center.y + bounds.y));
}
else { //Inside
Vector2D distanceToPositiveBounds = center+bounds - P;
Vector2D distanceToNegativeBounds = -(center-bounds - P);
float smallestX = Min(distanceToPositiveBounds.x, distanceToNegativeBounds.x);
float smallestY = Min(distanceToPositiveBounds.y, distanceToNegativeBounds.y);
float smallestDistance = Min(smallestX, smallestY);
if (smallestDistance == distanceToPositiveBounds.x)
closestPoint = (center.x+bounds.x, P.y);
else if (smallestDistance == distanceToNegativeBounds.x)
closestPoint = (center.x-bounds.x, P.y);
else if (smallestDistance == distanceToPositiveBounds.y)
closestPoint = (P.x, center.y+bounds.y);
else
closestPoint = (P.x, center.y-bounds.y);
}
Where Max returns the largest of two values and Min returns the smallest.
The code assumes that rectangle data is stored as center and bounds; for example center.y+bounds.y is the Y coordinate of the higher bound (Top) of the rectangle.
Actual code used can be found here.
$endgroup$
add a comment |
$begingroup$
Having recently coded a simple physics engine for a course, I did this as a part of rectangle-circle collision. Being put into practice means that my method is verified to work, since bugs would otherwise occur.
For clarity, let's call P the point you wish to find the closest point to on the rectangle.
When P is outside of the rectangle the closest point on the rectangle is P clamped to the bounds of the rectangle.
If P is inside the rectangle you need to work out which side is the closest, then use that side's coordinate as the value on the corresponding axis for the closest point.
For example, if your point is the closest to the negative Y bound (Bottom) then the closest point is (P.x, Bottom), where P.x is the X coordinate of the point P and Bottom is the Y coordinate of the negative Y bound. And if P is the closest to the negative X bound (Left) then it's (Left, P.y), e.t.c..
There are ambiguous points in the exact middle between two sides, which have more than one closest point.
In pseudocode:
bool insideX = center.x-bounds.x < P.x && P.x < center.x+bounds.x;
bool insideY = center.y-bounds.y < P.y && P.y < center.y+bounds.y;
bool pointInsideRectangle = insideX && insideY;
if (!pointInsideRectangle){ //Outside
closestPoint.x = Max(center.x-bounds.x, Min(P.x, center.x + bounds.x));
closestPoint.y = Max(center.y-bounds.y, Min(P.y, center.y + bounds.y));
}
else { //Inside
Vector2D distanceToPositiveBounds = center+bounds - P;
Vector2D distanceToNegativeBounds = -(center-bounds - P);
float smallestX = Min(distanceToPositiveBounds.x, distanceToNegativeBounds.x);
float smallestY = Min(distanceToPositiveBounds.y, distanceToNegativeBounds.y);
float smallestDistance = Min(smallestX, smallestY);
if (smallestDistance == distanceToPositiveBounds.x)
closestPoint = (center.x+bounds.x, P.y);
else if (smallestDistance == distanceToNegativeBounds.x)
closestPoint = (center.x-bounds.x, P.y);
else if (smallestDistance == distanceToPositiveBounds.y)
closestPoint = (P.x, center.y+bounds.y);
else
closestPoint = (P.x, center.y-bounds.y);
}
Where Max returns the largest of two values and Min returns the smallest.
The code assumes that rectangle data is stored as center and bounds; for example center.y+bounds.y is the Y coordinate of the higher bound (Top) of the rectangle.
Actual code used can be found here.
$endgroup$
Having recently coded a simple physics engine for a course, I did this as a part of rectangle-circle collision. Being put into practice means that my method is verified to work, since bugs would otherwise occur.
For clarity, let's call P the point you wish to find the closest point to on the rectangle.
When P is outside of the rectangle the closest point on the rectangle is P clamped to the bounds of the rectangle.
If P is inside the rectangle you need to work out which side is the closest, then use that side's coordinate as the value on the corresponding axis for the closest point.
For example, if your point is the closest to the negative Y bound (Bottom) then the closest point is (P.x, Bottom), where P.x is the X coordinate of the point P and Bottom is the Y coordinate of the negative Y bound. And if P is the closest to the negative X bound (Left) then it's (Left, P.y), e.t.c..
There are ambiguous points in the exact middle between two sides, which have more than one closest point.
In pseudocode:
bool insideX = center.x-bounds.x < P.x && P.x < center.x+bounds.x;
bool insideY = center.y-bounds.y < P.y && P.y < center.y+bounds.y;
bool pointInsideRectangle = insideX && insideY;
if (!pointInsideRectangle){ //Outside
closestPoint.x = Max(center.x-bounds.x, Min(P.x, center.x + bounds.x));
closestPoint.y = Max(center.y-bounds.y, Min(P.y, center.y + bounds.y));
}
else { //Inside
Vector2D distanceToPositiveBounds = center+bounds - P;
Vector2D distanceToNegativeBounds = -(center-bounds - P);
float smallestX = Min(distanceToPositiveBounds.x, distanceToNegativeBounds.x);
float smallestY = Min(distanceToPositiveBounds.y, distanceToNegativeBounds.y);
float smallestDistance = Min(smallestX, smallestY);
if (smallestDistance == distanceToPositiveBounds.x)
closestPoint = (center.x+bounds.x, P.y);
else if (smallestDistance == distanceToNegativeBounds.x)
closestPoint = (center.x-bounds.x, P.y);
else if (smallestDistance == distanceToPositiveBounds.y)
closestPoint = (P.x, center.y+bounds.y);
else
closestPoint = (P.x, center.y-bounds.y);
}
Where Max returns the largest of two values and Min returns the smallest.
The code assumes that rectangle data is stored as center and bounds; for example center.y+bounds.y is the Y coordinate of the higher bound (Top) of the rectangle.
Actual code used can be found here.
answered Nov 26 '18 at 20:13
Karl RamstedtKarl Ramstedt
111
111
add a comment |
add a comment |
Thanks for contributing an answer to Mathematics Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fmath.stackexchange.com%2fquestions%2f356792%2fhow-to-find-nearest-point-on-line-of-rectangle-from-anywhere%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown