【Unity小工具】计算四边形区域的中心点、判断点是否在区域内、区域内随机生成多个点

目标:

  • 计算四边形区域的中心点
  • 判断点是否在区域内
  • 区域内随机生成多个点

时间:

  • 2023年10月20日 晚上09:52

产出:

1、计算四边形区域的中心点

    /// <summary>
    /// 获取不规则多边形几何中心点
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    public Vector2 GetCenterPoint(List<Vector2> mPoints)
    {
        float cx = (GetMinX(mPoints) + GetMaxX(mPoints)) / 2;
        float cy = (GetMinY(mPoints) + GetMaxY(mPoints)) / 2;
        return new Vector2(cx, cy);
    }

    /// <summary>
    /// 获取最小X值
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    private float GetMinX(List<Vector2> mPoints)
    {
        float minX = 0;
        if (mPoints.Count > 0)
        {
            minX = mPoints[0].x;
            foreach (Vector2 point in mPoints)
            {
                if (point.x < minX)
                    minX = point.x;
            }
        }

        return minX;
    }

    /// <summary>
    /// 获取最大X值
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    private float GetMaxX(List<Vector2> mPoints)
    {
        float maxX = 0;
        if (mPoints.Count > 0)
        {
            maxX = mPoints[0].x;
            foreach (Vector2 point in mPoints)
            {
                if (point.x > maxX)
                    maxX = point.x;
            }
        }

        return maxX;
    }

    /// <summary>
    /// 获取最小Y值
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    private float GetMinY(List<Vector2> mPoints)
    {
        float minY = 0;
        if (mPoints.Count > 0)
        {
            minY = mPoints[0].y;
            foreach (Vector2 point in mPoints)
            {
                if (point.y < minY)
                    minY = point.y;
            }
        }

        return minY;
    }

    /// <summary>
    /// 获取最大Y值
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    private float GetMaxY(List<Vector2> mPoints)
    {
        float maxY = 0;
        if (mPoints.Count > 0)
        {
            maxY = mPoints[0].y;
            foreach (Vector2 point in mPoints)
            {
                if (point.y > maxY)
                    maxY = point.y;
            }
        }

        return maxY;
    }
    
 	/// <summary>
    /// 获取不规则多边形重心
    /// </summary>
    /// <param name="mPoints"></param>
    /// <returns></returns>
    public Vector2 GetCenterOfGravityPoint(List<Vector2> mPoints)
    {
        float area = 0.0f; //多边形面积
        float gx = 0.0f, gy = 0.0f; // 重心的x、y
        for (int i = 1; i <= mPoints.Count; i++)
        {
            float iX = mPoints[i % mPoints.Count].x;
            float iY = mPoints[i % mPoints.Count].y;
            float nextX = mPoints[i - 1].x;
            float nextY = mPoints[i - 1].y;
            float temp = (iX * nextY - iY * nextX) / 2.0f;
            area += temp;
            gx += temp * (iX + nextX) / 3.0f;
            gy += temp * (iY + nextY) / 3.0f;
        }
        gx = gx / area;
        gy = gy / area;
        Vector2 v2 = new Vector2(gx, gy);
        return v2;
    }

2、判断点是否在区域内

    /// <summary>
    /// 判断点是否在区域内
    /// </summary>
    /// <param name="polyPoints"></param>
    /// <param name="p"></param>
    /// <returns></returns>
    public bool ContainsPoint(List<Vector2> polyPoints, Vector2 p)
    {
        var j = polyPoints.Count - 1;
        var inside = false;
        for (int i = 0; i < polyPoints.Count; j = i++)
        {
            var pi = polyPoints[i];
            var pj = polyPoints[j];
            if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
                (p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
                inside = !inside;
        }
        return inside;
    }

3、区域内随机生成多个点

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

public class ModelControlManager : MonoBehaviour
{

    public Transform trans;
    public List<Transform> lisTrans = new List<Transform>();

    public List<Vector2> listV2 = new List<Vector2>();

    public bool isRandom = false;
    public bool isRandomPoint = false;
    private float minX, maxX, minY, maxY;
    public List<Vector2> listRandomPoints = new List<Vector2>();
    public Transform trans1;
    public Transform trans2;
    
    void Start()
    {
        foreach (var item in lisTrans)
        {
            Vector2 v2 = new Vector2(item.position.x, item.position.z);
            if(!listV2.Contains(v2))
                listV2.Add(v2);
        }

        minX = Mathf.Min(listV2[0].x, listV2[1].x, listV2[2].x, listV2[3].x);
        maxX = Mathf.Max(listV2[0].x, listV2[1].x, listV2[2].x, listV2[3].x);
        
        minY = Mathf.Min(listV2[0].y, listV2[1].y, listV2[2].y, listV2[3].y);
        maxY = Mathf.Max(listV2[0].y, listV2[1].y, listV2[2].y, listV2[3].y);
    }

    private void Update()
    {
        if (isRandom)
        {
            isRandom = false;
            isRandomPoint = true;
            listRandomPoints.Clear();
        }
        if (isRandomPoint)
        {
            float x = Random.Range(minX, maxX);
            float y = Random.Range(minY, maxY);
            Vector2 v2 = new Vector2(x, y);
            bool isArea = ContainsPoint(listV2, v2);
            if (isArea)
            {
                if (!listRandomPoints.Contains(v2))
                    listRandomPoints.Add(v2);
                if (listRandomPoints.Count>=2)
                {
                    isRandomPoint = false;
                    trans1.position = new Vector3(listRandomPoints[0].x,trans1.position.y,listRandomPoints[0].y);
                    trans2.position = new Vector3(listRandomPoints[1].x,trans2.position.y,listRandomPoints[1].y);
                }
            }
        }
    }

    public bool ContainsPoint(List<Vector2> polyPoints, Vector2 p)
    {
        var j = polyPoints.Count - 1;
        var inside = false;
        for (int i = 0; i < polyPoints.Count; j = i++)
        {
            var pi = polyPoints[i];
            var pj = polyPoints[j];
            if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
                (p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
                inside = !inside;
        }
        return inside;
    }
    
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趙銭孫李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值