亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

C# Raycasting / 從方向查找最近的矩形

C# Raycasting / 從方向查找最近的矩形

C#
動漫人物 2022-11-13 17:31:53
所以,我試圖找到一種方法來找到我的點將擊中的第一個矩形(從矩形列表中,所有 2D),沿著特定方向(在 C# 中),但是我似乎無法正確描述術語(如果有這樣的東西,我發現最接近的東西是光線投射)。我的目標是從一個特定的“點”開始(在這種情況下,從下面的示例中可以看到星號-*),然后從那里選擇一個特定的方向(左、右、下、上)(無角度)。所以假設我們選擇 Down,那么它會命中的第一個矩形是“I'M A RECT 2”,因此應該返回這個。我已經知道矩形的所有位置和大小,所以我得到了這些信息。我該怎么做呢?     *       [I'M A RECT 1][I'M A RECT 2]                 [I'M A RECT 3][I'M A RECT 4]
查看完整描述

1 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

您可以檢查矩形是否可以與源自該點的射線相交,然后計算與 的距離point:


var point = new PointF(1.2f, 2.5f);

var rectangles = new RectangleF[]

{

    new RectangleF(1, 1, 1, 1),

    new RectangleF(3, 1, 1, 1),

    new RectangleF(5, 2, 1, 1),

};


var hit = rectangles

    .Select(x =>

    {

        if (IsBetween(point.X, x.Left, x.Left + x.Width))

            return new { Rectangle = x, Distance = GetClosestDistance(point.Y, x.Top - x.Height, x.Top) as float? };

        else if (IsBetween(point.X, x.Top - x.Height, x.Top))

            return new { Rectangle = x, Distance = GetClosestDistance(point.Y, x.Left, x.Left + x.Width) as float? };

        else return new { Rectangle = x, Distance = default(float?) };

    })

    .Where(x => x.Distance != null)

    .OrderBy(x => x.Distance)

    .FirstOrDefault()?.Rectangle;


bool IsBetween(float value, float lBound, float uBound) => lBound <= value && value <= uBound;

float GetClosestDistance(float value, float p0, float p1) => Math.Min(Math.Abs(p0 - value), Math.Abs(p1 - value));

編輯:


var hit = RayTest(point, rectangles, RayDirections.Right | RayDirections.Down) // or, try just `Down`

    .Where(x => x.Success)

    .OrderBy(x => x.Distance)

    .FirstOrDefault()?.Target;


[Flags]

public enum RayDirections { None = 0, Left = 1 << 0, Up = 1 << 1, Right = 1 << 2, Down = 1 << 3, All = (1 << 4) - 1 }

public class RayHit<T>

{

    public T Target { get; }

    public float? Distance { get; }

    public bool Success => Distance.HasValue;


    public RayHit(T target, float? distance)

    {

        this.Target = target;

        this.Distance = distance;

    }

}


public IEnumerable<RayHit<RectangleF>> RayTest(PointF point, IEnumerable<RectangleF> rectangles, RayDirections directions = RayDirections.All)

{

    if (directions == RayDirections.None)

        return Enumerable.Empty<RayHit<RectangleF>>();


    var ray = new

    {

        Horizontal = new

        {

            LBound = directions.HasFlag(RayDirections.Left) ? float.MinValue : point.X,

            UBound = directions.HasFlag(RayDirections.Right) ? float.MaxValue : point.X,

        },

        Vertical = new

        {

            LBound = directions.HasFlag(RayDirections.Down) ? float.MinValue : point.Y,

            UBound = directions.HasFlag(RayDirections.Up) ? float.MaxValue : point.Y,

        },

    };


    return rectangles

        .Select(x =>

        {

            float left = x.Left, right = x.Left + x.Width;

            float top = x.Top, bottom = x.Top - x.Height;


            if (IsBetween(point.X, left, right) && (IsBetween(top, ray.Vertical.LBound, ray.Vertical.UBound) || IsBetween(bottom, ray.Vertical.LBound, ray.Vertical.UBound)))

                return new RayHit<RectangleF>(x, GetClosestDistance(point.Y, bottom, top) as float?);

            else if (IsBetween(point.X, bottom, top) && (IsBetween(left, ray.Horizontal.LBound, ray.Horizontal.UBound) || IsBetween(right, ray.Horizontal.LBound, ray.Horizontal.UBound)))

                return new RayHit<RectangleF>(x, GetClosestDistance(point.Y, left, right) as float?);

            else return new RayHit<RectangleF>(x, default);

        });


    bool IsBetween(float value, float lBound, float uBound) => lBound <= value && value <= uBound;

    float GetClosestDistance(float value, float p0, float p1) => Math.Min(Math.Abs(p0 - value), Math.Abs(p1 - value));

}

注意:在這兩個版本中,當點在矩形內時都會出現錯誤。計算的距離將是到最近邊緣的距離,而不是 0 或負值。


查看完整回答
反對 回復 2022-11-13
  • 1 回答
  • 0 關注
  • 102 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號