How to find nearest point on line of rectangle from anywhere?












3












$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.



Sample rectangle



E.g. having point k I would like to find i. My current approach is as follows:




  1. Calculate centre of rectangle (E).


  2. Normalize point, P against centre:



    Px = kx - Ex

    Py = ky - Ey




  3. Use atan2 on P to 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



  4. 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 ;)









share|cite|improve this question











$endgroup$

















    3












    $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.



    Sample rectangle



    E.g. having point k I would like to find i. My current approach is as follows:




    1. Calculate centre of rectangle (E).


    2. Normalize point, P against centre:



      Px = kx - Ex

      Py = ky - Ey




    3. Use atan2 on P to 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



    4. 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 ;)









    share|cite|improve this question











    $endgroup$















      3












      3








      3





      $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.



      Sample rectangle



      E.g. having point k I would like to find i. My current approach is as follows:




      1. Calculate centre of rectangle (E).


      2. Normalize point, P against centre:



        Px = kx - Ex

        Py = ky - Ey




      3. Use atan2 on P to 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



      4. 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 ;)









      share|cite|improve this question











      $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.



      Sample rectangle



      E.g. having point k I would like to find i. My current approach is as follows:




      1. Calculate centre of rectangle (E).


      2. Normalize point, P against centre:



        Px = kx - Ex

        Py = ky - Ey




      3. Use atan2 on P to 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



      4. 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






      share|cite|improve this question















      share|cite|improve this question













      share|cite|improve this question




      share|cite|improve this question








      edited Apr 13 '17 at 12:20









      Community

      1




      1










      asked Apr 10 '13 at 5:26









      ZimzalabimZimzalabim

      1186




      1186






















          2 Answers
          2






          active

          oldest

          votes


















          2












          $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'.



          enter image description here



          I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)






          share|cite|improve this answer









          $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



















          1












          $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.






          share|cite|improve this answer









          $endgroup$













            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
            });


            }
            });














            draft saved

            draft discarded


















            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









            2












            $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'.



            enter image description here



            I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)






            share|cite|improve this answer









            $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
















            2












            $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'.



            enter image description here



            I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)






            share|cite|improve this answer









            $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














            2












            2








            2





            $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'.



            enter image description here



            I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)






            share|cite|improve this answer









            $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'.



            enter image description here



            I hope I haven't made a mistake here. My head is swimming with coordinates. Hopefully the idea is clear. :)







            share|cite|improve this answer












            share|cite|improve this answer



            share|cite|improve this answer










            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


















            • $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











            1












            $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.






            share|cite|improve this answer









            $endgroup$


















              1












              $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.






              share|cite|improve this answer









              $endgroup$
















                1












                1








                1





                $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.






                share|cite|improve this answer









                $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.







                share|cite|improve this answer












                share|cite|improve this answer



                share|cite|improve this answer










                answered Nov 26 '18 at 20:13









                Karl RamstedtKarl Ramstedt

                111




                111






























                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    How to send String Array data to Server using php in android

                    Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                    Is anime1.com a legal site for watching anime?