Limiting the Circle with a Rectangle

Hello everyone.

I want to constrain a circle I created in my project using a rectangle. I watched a few videos and they generally use the same method, but this method does not give the result I want.

I have prepared a visual demo for you below.

I want to constrain the angle I give using the blue circle with the red rectangle. You can see the angle as the green line. The little white circle is the value I got.

This method works correctly when the angle is 0,90,180,270 etc. However, as you can see below, it does not give the desired result for other values.

The value I want should be exactly on the green line.

Here’s my code for this demo:

using UnityEngine;
  
public class CircleLimiter : MonoBehaviour
{
    public Vector2 rectangleSize;
    public float circleRadius;
    public float angle;
  
    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(Vector3.zero, rectangleSize);
  
        Gizmos.color = Color.blue;
        Gizmos.DrawWireSphere(Vector3.zero, circleRadius);
  
        Gizmos.color = Color.green;
        Vector3 positionByAngle = new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad) * circleRadius, Mathf.Sin(angle * Mathf.Deg2Rad) * circleRadius);
        Gizmos.DrawLine(Vector3.zero, positionByAngle);
  
        Gizmos.color = Color.white;
        Gizmos.DrawWireSphere(Limit(positionByAngle, rectangleSize), 0.2f);
    }
  
    Vector2 Limit(Vector2 position, Vector2 limit)
    {
        limit /= limit;
        return new Vector2(
                        Mathf.Clamp(position.x, -limit.x, limit.x),
                        Mathf.Clamp(position.y, -limit.y, limit.y)
        );
    }
}

I would be very grateful if you could answer my question or direct me to related topics.
Thanks in advance.

I managed to solve it somehow but I would like to know if there is a better way. After dividing the area into triangles, I got the result I wanted using the right triangle formulas.

Vector3 Limiter(float ang, Vector2 limit)
{
    Vector3 result = Vector3.zero;
    float x = 0;
    float y = 0;
  
    float _ang = ang % 360;
    ang = _ang;
  
    if (_ang < 0)
        ang = 360 + _ang;
  
    float a = limit.x;
    float b = limit.y;
    float c = Mathf.Sqrt(Mathf.Pow(limit.x, 2) + Mathf.Pow(limit.y, 2));
  
    float aAngle = Mathf.Acos(a / c) * Mathf.Rad2Deg;
    float bAngle = 90 - aAngle;
  
    float zoneAngle = 0;
  
    if (ang >= 0 && ang < aAngle)
    {
        zoneAngle = ang;
        x = a;
        y = a * Mathf.Tan(zoneAngle * Mathf.Deg2Rad);
    }
    else if (ang >= aAngle && ang < aAngle + bAngle * 2)
    {
        zoneAngle = zoneAngleOverride ? zoneAngleOverrideValue : bAngle - (ang - aAngle);
        x = b * Mathf.Tan(zoneAngle * Mathf.Deg2Rad);
        y = b;
    }
    else if (ang >= aAngle + bAngle * 2 && ang < aAngle * 3 + bAngle * 2)
    {
        zoneAngle = zoneAngleOverride ? zoneAngleOverrideValue : aAngle - (ang - bAngle * 2 - aAngle);
        x = -a;
        y = a * Mathf.Tan(zoneAngle * Mathf.Deg2Rad);
    }
    else if (ang >= aAngle * 3 + bAngle * 2 && ang < aAngle * 3 + bAngle * 4)
    {
        zoneAngle = zoneAngleOverride ? zoneAngleOverrideValue : -bAngle + (ang - bAngle * 2 - aAngle * 3);
        x = b * Mathf.Tan(zoneAngle * Mathf.Deg2Rad);
        y = -b;
    }
    else
    {
        zoneAngle = ang;
        x = a;
        y = a * Mathf.Tan(zoneAngle * Mathf.Deg2Rad);
    }
  
    result = new Vector3(x, y, 0);
  
    return result;
}

Cool solution! What are you using this for ?

Here is another solution

public static Vector2 ClampPointInRect(float width, float height, Vector2 point)
{
    Vector2 vec = point;
    float pi = Mathf.PI;
    float angle = Mathf.Atan2(point.y, point.x);
    if (angle < 0)
        angle = pi * 2 + angle;
    float tan = Mathf.Tan(angle);
    float cot = 1 / Mathf.Tan(angle);
    
    if (angle < pi * .25f)
        vec = new(width,  tan * height);
    else if (angle < pi * .5f)
        vec = new(cot * width, height);
    else if (angle < pi * .75f)
        vec = new(cot * width, height);
    else if (angle < pi)
        vec = new(-width, -tan * height);
    else if (angle < pi * 1.25f)
        vec = new(-width, -tan * height);
    else if (angle < pi * 1.5f)
        vec = new(-cot * width, -height);
    else if (angle < pi * 1.75f)
        vec = new(-cot * width, -height);
    else if (angle < pi * 2.0f)
        vec = new(width, tan * height);
    
    return vec;
}