Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Get 2D points normalized distance between an axis-aligned inner & outer rect? [SOLVED]

Discussion in 'Scripting' started by keenanwoodall, Mar 10, 2020.

  1. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    Is there a clean way to get a points normalized distance between the closest edges of an inner and outer rect?

    Here's an example image of what I'm talking about:
    upload_2020-3-10_17-25-13.png
    The red dots are example points and the grey lines are the shortest paths between the two rects that the points lie on. The numbers are the points' normalized distance along said line.

    I'm pretty sure I can solve this by projecting the point onto the closest side of the inner and outer rect and getting the distance between the points, but that seems like a very heavy-handed solution.

    [SOLVED]
     
    Last edited: Mar 11, 2020
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    For axis-aligned rectangles, calculating distance to a side can be done just by subtracting coordinates on the appropriate axis.

    For example, if the inner rectangle stretches from x = 50 to x = 100, then the distance of point P to the closer vertical edge is

    if (P.x < 50) return 50 - P.x;
    if (P.x > 100) return P.x - 100;
    else P is inside the inner box OR the closest side is definitely not one of the vertical ones
     
  3. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    I don't think this would handle a point being closest to a corner from the outside of a rect would it?
     
    Antistone likes this.
  4. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    I ended up figuring out a good solution using sdfs.

    Using this SDF function
    Code (CSharp):
    1. // Equation used from https://www.ronja-tutorials.com/2018/11/10/2d-sdf-basics.html
    2. private float GetDistanceToRect(Rect rect, Vector2 point)
    3. {
    4.     Vector2 halfSize = rect.size / 2f;
    5.     point -= rect.center;
    6.     Vector2 cwed = new Vector2(Mathf.Abs(point.x), Mathf.Abs(point.y)) - halfSize;
    7.     float outsideDistance = new Vector2(Mathf.Max(cwed.x, 0f), Mathf.Max(cwed.y, 0f)).magnitude;
    8.     float insideDistance = Mathf.Min(0f, Mathf.Max(cwed.x, cwed.y));
    9.     return outsideDistance + insideDistance;
    10. }
    I could get the points distance to the inner and outer rect. Dividing the distance to the inner rect by the difference in distance to both rects you can get the normalized distance between the two rects.
    Code (CSharp):
    1. float innerDist = GetDistanceToRect(innerRect, screenPosition);
    2. float outerDist = GetDistanceToRect(outerRect, screenPosition);
    3. float t = Mathf.Clamp01(innerDist / (innerDist - outerDist));
    t = 0 when the point is on the inner rect and t = 1 when it's on the outer rect
     
  5. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Fair point. Now that you call my attention to it, your original diagram doesn't match your description of the problem; for the diagonal line in the top-right of your diagram, you are not going to the closest point on the outer rectangle (for that, you should always go horizontally or vertically). Looks like you are instead projecting a ray from the closest point on the inner rectangle through the red dot.
     
  6. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    Ah yea you're right, apologies