/// <summary> /// 指定範囲に接触するアイテムを列挙する /// </summary> /// <param name="volume">境界ボリューム</param> /// <param name="excludes">列挙から除外するアイテム一覧、一度列挙されたものはこれに登録される</param> /// <returns>列挙子</returns> public IEnumerable <T> Query(obb volume, HashSet <T> excludes) { var isAabb1 = volume.IsAabb; var cells = _Cells; foreach (var i in EnumCellIndices(volume, true)) { var items = cells[i]; for (int j = items.Count - 1; j != -1; j--) { var item = items[j]; var obb2 = item.GetVolume(); if (obb2.IsAabb && isAabb1) { var aabb2 = new aabb(obb2.Center, obb2.Extents); if (volume.IntersectsAsAabb(aabb2)) { yield return(item); } } else { if (volume.Intersects(obb2)) { yield return(item); } } } } }
public bool Intersects(volume obb2) { volume obb1; if (this.IsAabb) { obb1 = obb2; obb2 = this; } else { obb1 = this; } var d = new vector(); var v = obb1.Center - obb2.Center; var eax = obb2.Ax * obb2.Extents.X; var eay = obb2.Ay * obb2.Extents.Y; var e1 = eax + eay; var e2 = eay - eax; d.X = Math.Abs(obb1.Ax.Dot(e1)); d.Y = Math.Abs(obb1.Ax.Dot(e2)); if (obb1.Extents.X + d.Max() < Math.Abs(obb1.Ax.Dot(v))) { return(false); } d.X = Math.Abs(obb1.Ay.Dot(e1)); d.Y = Math.Abs(obb1.Ay.Dot(e2)); if (obb1.Extents.Y + d.Max() < Math.Abs(obb1.Ay.Dot(v))) { return(false); } eax = obb1.Ax * obb1.Extents.X; eay = obb1.Ay * obb1.Extents.Y; e1 = eax + eay; e2 = eay - eax; d.X = Math.Abs(obb2.Ax.Dot(e1)); d.Y = Math.Abs(obb2.Ax.Dot(e2)); if (obb2.Extents.X + d.Max() < Math.Abs(obb2.Ax.Dot(v))) { return(false); } d.X = Math.Abs(obb2.Ay.Dot(e1)); d.Y = Math.Abs(obb2.Ay.Dot(e2)); if (obb2.Extents.Y + d.Max() < Math.Abs(obb2.Ay.Dot(v))) { return(false); } return(true); }
/// <summary> /// 指定された範囲に接触するセルインデックスを列挙する /// </summary> /// <param name="obb">範囲</param> /// <param name="skipNullCell">アイテム数ゼロのセルを無視するかどうか</param> /// <returns>セルインデックス一覧</returns> IEnumerable <int> EnumCellIndices(obb obb, bool skipNullCell) { var cr = CellRange(obb.Range); var cells = _Cells; var stride = _Division.X; var iy = cr.Min.X + cr.Min.Y * stride; var invs = _InvTransformScale; var invt = _CellExtent - _TransformTranslate; var isAabb = obb.IsAabb; var aabb2 = new aabb(new vector(), _CellExtent); for (int y = cr.Min.Y; y <= cr.Max.Y; iy += stride, y++) { aabb2.Center.Y = y * invs.Y; aabb2.Center.Y += invt.Y; for (int x = cr.Min.X, ix = iy; x <= cr.Max.X; ix++, x++) { if (skipNullCell) { var c = cells[ix]; if (c == null || c.Count == 0) { continue; } } aabb2.Center.X = x * invs.X; aabb2.Center.X += invt.X; if (isAabb) { if (obb.IntersectsAsAabb(aabb2)) { yield return(ix); } } else { var obb2 = new obb(aabb2); if (obb.Intersects(obb2)) { yield return(ix); } } } } }
/// <summary> /// 指定範囲に接触するアイテムを列挙する /// </summary> /// <param name="volume">境界ボリューム</param> /// <returns>列挙子</returns> public IEnumerable <T> Query(obb volume) { return(Query(volume, new HashSet <T>())); }