Line Segment Search - Rectangle Intersection Point

Simply put, I have:

  • The rectangle of the viewport, where (0,0) is the lower left corner, (1,1) is the upper right corner, and (0,5,0,5) is the center of the screen.
  • A point (a, b) that is outside the rectangle.

This is in the coordinates of the viewport, therefore + X is right, + Y is on the screen.

And I need a function that takes these parameters and returns a point on the edge of the rectangle, where the line (between the center of the rectangle (0,5,0,5) and the point (a, b)) intersects it.

I know how to do this on paper with given coordinates, but I just can't figure it out when it comes to code. In addition, I understand that such issues have been addressed in different threads, but I cannot find a simple input for the output function anywhere.

I do this in the Unity3D engine, so it is desirable in Javascript, but any language or pseudo-code will be a big help, since I can probably pass it.

EDIT To clarify, I'm looking for something like:

function IntersectFromViewportCenter(x : float, y : float) {
    ...
    return Point(x1, y1);
}

Where (x, y) is the point outside the circle and (x1, y1) is the intersection point.

thank

+3
source share
4 answers

Move the entire system to the center at (0,0). Calc the intersection of the ray from the origin to the (shifted) point (x ', y') with the field (-1, -1) - (1,1). Scale and slide back. I did not consider the trivial case with a dot inside the box (is this necessary?)

x = x - 0.5
y = y - 0.5
if Abs(x) >= Abs(y) then  //vertical box edge
  y1 = y/x  //care with case both y and x = 0
  x1 = Sign(x) //+-1
else   // horizontal edge
  x1 = x/y
  y1 = Sign(y)

x1 = 0.5*x1 + 0.5
y1 = 0.5*y1 + 0.5
+2
source

MBo . Unity. , UnityScript - , , . ( , Unity Unity3D.)

script :

using UnityEngine;

public static class UnityEngineExtensions {

public static Vector2 Abs(this Vector2 vector) {
    for (int i = 0; i < 2; ++i) vector[i] = Mathf.Abs(vector[i]);
    return vector;
}   

public static Vector2 DividedBy(this Vector2 vector, Vector2 divisor) {
    for (int i = 0; i < 2; ++i) vector[i] /= divisor[i];
    return vector;
}

public static Vector2 Max(this Rect rect) {
    return new Vector2(rect.xMax, rect.yMax);
}

public static Vector2 IntersectionWithRayFromCenter(this Rect rect, Vector2 pointOnRay) {
    Vector2 pointOnRay_local = pointOnRay - rect.center;
    Vector2 edgeToRayRatios = (rect.Max() - rect.center).DividedBy(pointOnRay_local.Abs());
    return (edgeToRayRatios.x < edgeToRayRatios.y) ?
        new Vector2(pointOnRay_local.x > 0 ? rect.xMax : rect.xMin, 
            pointOnRay_local.y * edgeToRayRatios.x + rect.center.y) :
        new Vector2(pointOnRay_local.x * edgeToRayRatios.y + rect.center.x, 
            pointOnRay_local.y > 0 ? rect.yMax : rect.yMin);
}

}

script .

#pragma warning disable 0649
using System;
using UnityEngine;

public class VisualizeRectIntersectionWithRayFromCenter : MonoBehaviour {

[SerializeField] Rect rect;
[SerializeField] Vector2 point;

[Serializable] class Colors {
    public Color rect, point, intersection;
} [SerializeField] Colors colors;

void OnDrawGizmos() {
    Gizmos.color = colors.rect;
    Vector2[] corners = {new Vector2(rect.xMin, rect.yMin), new Vector2(rect.xMin, rect.yMax),
        rect.Max(), new Vector2(rect.xMax, rect.yMin)};
    int i = 0;
    while (i < 3) Gizmos.DrawLine(corners[i], corners[++i]);
    Gizmos.DrawLine(corners[3], corners[0]);

    Gizmos.color = colors.point;
    Gizmos.DrawLine(rect.center, point);

    Gizmos.color = colors.intersection;
    Gizmos.DrawLine(rect.center, rect.IntersectionWithRayFromCenter(pointOnRay: point));
}

}
+1
bool LineRectIntersection(Vector2 lineStartPoint, Vector2 lineEndPoint, Rect rectangle, ref double resultX, ref double resultY)
{
    Vector2 minXLinePoint = (lineStartPoint.x <= lineEndPoint.x) ? (lineStartPoint) : (lineEndPoint);
    Vector2 maxXLinePoint = (lineStartPoint.x <= lineEndPoint.x) ? (lineEndPoint) : (lineStartPoint);
    Vector2 minYLinePoint = (lineStartPoint.y <= lineEndPoint.y) ? (lineStartPoint) : (lineEndPoint);
    Vector2 maxYLinePoint = (lineStartPoint.y <= lineEndPoint.y) ? (lineEndPoint) : (lineStartPoint);

    double rectMaxX = rectangle.xMax;
    double rectMinX = rectangle.xMin;
    double rectMaxY = rectangle.yMax;
    double rectMinY = rectangle.yMin;

    if (minXLinePoint.x <= rectMaxX && rectMaxX <= maxXLinePoint.x)
    {
        double m = (maxXLinePoint.y - minXLinePoint.y) / (maxXLinePoint.x - minXLinePoint.x);

        double intersectionY = ((rectMaxX - ((double)minXLinePoint.x)) * m) + ((double)minXLinePoint.y);

        if(minYLinePoint.y <= intersectionY && intersectionY <= maxYLinePoint.y)
        {
            resultX = rectMaxX;
            resultY = intersectionY;

            return true;
        }
    }

    if (minXLinePoint.x <= rectMinX && rectMinX <= maxXLinePoint.x)
    {
        double m = (maxXLinePoint.y - minXLinePoint.y) / (maxXLinePoint.x - minXLinePoint.x);

        double intersectionY = ((rectMinX - ((double)minXLinePoint.x)) * m) + ((double)minXLinePoint.y);

        if (minYLinePoint.y <= intersectionY && intersectionY <= maxYLinePoint.y)
        {
            resultX = rectMinX;
            resultY = intersectionY;

            return true;
        }
    }

    if (minYLinePoint.y <= rectMaxY && rectMaxY <= maxYLinePoint.y)
    {
        double rm = (maxYLinePoint.x - minYLinePoint.x) / (maxYLinePoint.y - minYLinePoint.y);

        double intersectionX = ((rectMaxY - ((double)minYLinePoint.y)) * rm) + ((double)minYLinePoint.x);

        if (minXLinePoint.x <= intersectionX && intersectionX <= maxXLinePoint.x)
        {
            resultX = intersectionX;
            resultY = rectMaxY;

            return true;
        }
    }

    if (minYLinePoint.y <= rectMinY && rectMinY <= maxYLinePoint.y)
    {
        double rm = (maxYLinePoint.x - minYLinePoint.x) / (maxYLinePoint.y - minYLinePoint.y);

        double intersectionX = ((rectMinY - ((double)minYLinePoint.y)) * rm) + ((double)minYLinePoint.x);

        if (minXLinePoint.x <= intersectionX && intersectionX <= maxXLinePoint.x)
        {
            resultX = intersectionX;
            resultY = rectMinY;

            return true;
        }
    }

    return false;
}
+1
source

@chakmeshma, your solution is almost correct, but you should also check if the intersection point is inside the rectangle to avoid borderline cases:

private static bool LineRectIntersection(Vector2 lineStartPoint, Vector2 lineEndPoint, Rect rectangle, ref Vector2 result)
    {
        Vector2 minXLinePoint = lineStartPoint.x <= lineEndPoint.x ? lineStartPoint : lineEndPoint;
        Vector2 maxXLinePoint = lineStartPoint.x <= lineEndPoint.x ? lineEndPoint : lineStartPoint;
        Vector2 minYLinePoint = lineStartPoint.y <= lineEndPoint.y ? lineStartPoint : lineEndPoint;
        Vector2 maxYLinePoint = lineStartPoint.y <= lineEndPoint.y ? lineEndPoint : lineStartPoint;

        double rectMaxX = rectangle.xMax;
        double rectMinX = rectangle.xMin;
        double rectMaxY = rectangle.yMax;
        double rectMinY = rectangle.yMin;

        if (minXLinePoint.x <= rectMaxX && rectMaxX <= maxXLinePoint.x)
        {
            double m = (maxXLinePoint.y - minXLinePoint.y) / (maxXLinePoint.x - minXLinePoint.x);

            double intersectionY = ((rectMaxX - minXLinePoint.x) * m) + minXLinePoint.y;

            if (minYLinePoint.y <= intersectionY && intersectionY <= maxYLinePoint.y
                && rectMinY <= intersectionY && intersectionY <= rectMaxY)
            {
                result = new Vector2((float)rectMaxX, (float)intersectionY);

                return true;
            }
        }

        if (minXLinePoint.x <= rectMinX && rectMinX <= maxXLinePoint.x)
        {
            double m = (maxXLinePoint.y - minXLinePoint.y) / (maxXLinePoint.x - minXLinePoint.x);

            double intersectionY = ((rectMinX - minXLinePoint.x) * m) + minXLinePoint.y;

            if (minYLinePoint.y <= intersectionY && intersectionY <= maxYLinePoint.y
                && rectMinY <= intersectionY && intersectionY <= rectMaxY)
            {
                result = new Vector2((float)rectMinX, (float)intersectionY);

                return true;
            }
        }

        if (minYLinePoint.y <= rectMaxY && rectMaxY <= maxYLinePoint.y)
        {
            double rm = (maxYLinePoint.x - minYLinePoint.x) / (maxYLinePoint.y - minYLinePoint.y);

            double intersectionX = ((rectMaxY - minYLinePoint.y) * rm) + minYLinePoint.x;

            if (minXLinePoint.x <= intersectionX && intersectionX <= maxXLinePoint.x
                && rectMinX <= intersectionX && intersectionX <= rectMaxX)
            {
                result = new Vector2((float)intersectionX, (float)rectMaxY);

                return true;
            }
        }

        if (minYLinePoint.y <= rectMinY && rectMinY <= maxYLinePoint.y)
        {
            double rm = (maxYLinePoint.x - minYLinePoint.x) / (maxYLinePoint.y - minYLinePoint.y);

            double intersectionX = ((rectMinY - minYLinePoint.y) * rm) + minYLinePoint.x;

            if (minXLinePoint.x <= intersectionX && intersectionX <= maxXLinePoint.x
                && rectMinX <= intersectionX && intersectionX <= rectMaxX)
            {
                result = new Vector2((float)intersectionX, (float)rectMinY);

                return true;
            }
        }

        return false;
    }
}
0
source

All Articles