需求:已知固定长方形地图,其中有很多矩形房间,要在矩形房间外摆放矩形障碍物,这时候需要先求出障碍物可摆放区域。
处理思路如上图所示,循环遍历房间。每一次做一回图三的切割方式,最终得到切割的结果,就是未占用的区域。
核心代码如下:
/// <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;//地图中的摆放位置
}