用循环切割的方式处理矩形地图中的障碍物占用问题

需求:已知固定长方形地图,其中有很多矩形房间,要在矩形房间外摆放矩形障碍物,这时候需要先求出障碍物可摆放区域。

 

 处理思路如上图所示,循环遍历房间。每一次做一回图三的切割方式,最终得到切割的结果,就是未占用的区域。

核心代码如下:


    /// <summary>
    /// 判断两个矩形是否相交
    /// </summary>   
    public bool IsIntersectionRectangles(Cutting _a, Cutting _b)
    {
        return Mathf.Max(_a.startPos.x, _b.startPos.x) < Mathf.Min(_a.startPos.x + _a.areaVe2.x, _b.startPos.x + _b.areaVe2.x)
            && Mathf.Min(_a.startPos.y, _b.startPos.y) > Mathf.Max(_a.startPos.y - _a.areaVe2.y, _b.startPos.y - _b.areaVe2.y);
    }


    /// <summary>
    /// 对比整个网格,求出最大面积的空快
    /// </summary>
    public Vector2 GetCreatMax(List<CreatItem> _list)
    {
        //需要求出所有的空闲四方格
        //遍历循环找到所有的占用区域,然后进行无限切割
        var _cL = new List<Cutting>();
        _cL.Add(new Cutting()
        {
            startPos = Vector2.zero,
            areaVe2 = maxArea,
        });
        var _num = 1;
        foreach (var idx in _list)
        {
            var _b = new Cutting()
            {
                startPos = idx.startPos,
                areaVe2 = idx.areaVe2,
            };
            //var _start = idx.startPos;
            //var _end = idx.startPos + idx.areaVe2;
            var _count = _cL.Count - 1;

            var _str = "";
            foreach (var _jj in _cL)
            {
                //var _oo = GameObject.CreatePrimitive(PrimitiveType.Cube);
                //_oo.transform.SetParent(GameObject.Find("地图 ("+_num+ ")").transform);
                //_oo.transform.localScale = new Vector3(_jj.areaVe2.x, 0, _jj.areaVe2.y);
                //var _ve = _jj.startPos + new Vector2(_jj.areaVe2.x, -_jj.areaVe2.y) * 0.5f;
                //_oo.transform.localPosition = new Vector3(_ve.x, 0, _ve.y);
                _str += _jj.startPos + " " + _jj.areaVe2 + "\n";
            }
            _num++;
            Debug.Log(_num + "~~~~~~" + _cL.Count + "\n" + _str);

            for (var _i = _count; _i >= 0; _i--)
            {
                var _a = _cL[_i];
                if (IsIntersectionRectangles(_a, _b))
                {
                    Debug.Log("相交" + _a.startPos + ":" + _a.areaVe2 + ":" + _b.startPos + ":" + _b.areaVe2);
                    var _aV2 = new Vector2(_a.startPos.x + _a.areaVe2.x, _a.startPos.y - _a.areaVe2.y);
                    var _bV2 = new Vector2(_b.startPos.x + _b.areaVe2.x, _b.startPos.y - _b.areaVe2.y);
                    _cL.Remove(_a);
                    //包含/重叠:干掉
                    if (_a.startPos.x >= _b.startPos.x && (_aV2.x <= _bV2.x)
                        &&
                        _a.startPos.y <= _b.startPos.y && (_aV2.y >= _bV2.y)
                        )
                    {
                        Debug.Log("包含/重叠");
                    }
                    else
                    {
                        //依次取上、右、下、左(顺时针)切割,当小于0的时候丢弃
                        var _c1 = new Cutting();
                        var _c2 = new Cutting();
                        var _c3 = new Cutting();
                        var _c4 = new Cutting();

                        if (_a.startPos.y > _b.startPos.y)
                        {
                            Debug.Log("up " + _a.startPos.y + ":" + _b.startPos.y);
                            _c1.startPos = _a.startPos;
                            _c1.areaVe2 = new Vector2(_a.areaVe2.x, _a.startPos.y - _b.startPos.y);
                            _cL.Add(_c1);
                        }

                        if (_aV2.x > _bV2.x)
                        {
                            Debug.Log("right:" + _aV2.x + ":" + _bV2.x);
                            _c2.startPos = new Vector2(_bV2.x, Mathf.Min(_a.startPos.y, _b.startPos.y));
                            _c2.areaVe2 = new Vector2(_aV2.x - _bV2.x, _c2.startPos.y - _aV2.y);
                            _cL.Add(_c2);
                        }

                        if (_bV2.y > _aV2.y)
                        {
                            Debug.Log("down:" + _bV2.y + ":" + _aV2.y);
                            _c3.startPos = new Vector2(_a.startPos.x, _bV2.y);
                            _c3.areaVe2 = new Vector2(Mathf.Min(_bV2.x, _aV2.x) - _c3.startPos.x, _bV2.y - _aV2.y);
                            _cL.Add(_c3);
                        }

                        if (_a.startPos.x < _b.startPos.x)
                        {
                            Debug.Log("left:" + _a.startPos.x + ":" + _b.startPos.x);
                            _c4.startPos = new Vector2(_a.startPos.x, Mathf.Min(_a.startPos.y, _b.startPos.y));
                            _c4.areaVe2 = new Vector2(_b.startPos.x - _a.startPos.x, Mathf.Min(_a.startPos.y, _b.startPos.y) - Mathf.Max(_aV2.y, _bV2.y));
                            _cL.Add(_c4);
                        }

                    }
                }
            }

            做一次吞并:将包含的小数据给合并掉
            //_count = _cL.Count - 1;


        }


        return Vector2.zero;
    }


    /// <summary>
    /// 切割格子
    /// </summary>
    public class Cutting
    {
        public Vector2 startPos;//地图中的摆放位置
        public Vector2 areaVe2;//大小
    }

    public class CreatItem
    {
        public string id;//id
        public bool isRoom;//类似:房间,障碍物
        public Vector2 areaVe2;//大小
        public float ran;//随机权重
        public int max;//最大个数

        public Vector2 startPos;//地图中的摆放位置
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值