#region Copyright & License Information
/*
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
namespace OpenRA.Mods.Common.Pathfinder
{
///
/// Represents a simplistic grid of cells, where everything in the
/// top-to-bottom and left-to-right range is within the grid.
/// The grid can be restricted to a single layer, or allowed to span all layers.
///
///
/// This means in some cells within a grid may lay off the map.
/// Contrast this with which maintains the simplistic grid in map space -
/// ensuring the cells are therefore always within the map area.
/// The advantage of Grid is that it has straight edges, making logic for adjacent grids easy.
/// A CellRegion has jagged edges in RectangularIsometric, which makes that more difficult.
///
public readonly struct Grid
{
///
/// Inclusive.
///
public readonly CPos TopLeft;
///
/// Exclusive.
///
public readonly CPos BottomRight;
///
/// When true, the grid spans only the single layer given by the cells. When false, it spans all layers.
///
public readonly bool SingleLayer;
public Grid(CPos topLeft, CPos bottomRight, bool singleLayer)
{
if (topLeft.Layer != bottomRight.Layer)
throw new ArgumentException($"{nameof(topLeft)} and {nameof(bottomRight)} must have the same {nameof(CPos.Layer)}");
TopLeft = topLeft;
BottomRight = bottomRight;
SingleLayer = singleLayer;
}
public int Width => BottomRight.X - TopLeft.X;
public int Height => BottomRight.Y - TopLeft.Y;
///
/// Checks if the cell X and Y lie within the grid bounds. The cell layer must also match.
///
public bool Contains(CPos cell)
{
return
cell.X >= TopLeft.X && cell.X < BottomRight.X &&
cell.Y >= TopLeft.Y && cell.Y < BottomRight.Y &&
(!SingleLayer || cell.Layer == TopLeft.Layer);
}
///
/// Checks if the line segment from to
/// passes through the grid boundary. The cell layers are ignored.
/// A line contained wholly within the grid that doesn't cross the boundary is not counted as intersecting.
///
public bool IntersectsLine(CPos start, CPos end)
{
var s = new int2(start.X, start.Y);
var e = new int2(end.X, end.Y);
var tl = new int2(TopLeft.X, TopLeft.Y);
var tr = new int2(BottomRight.X, TopLeft.Y);
var bl = new int2(TopLeft.X, BottomRight.Y);
var br = new int2(BottomRight.X, BottomRight.Y);
return
Exts.LinesIntersect(s, e, tl, tr) ||
Exts.LinesIntersect(s, e, tl, bl) ||
Exts.LinesIntersect(s, e, bl, br) ||
Exts.LinesIntersect(s, e, tr, br);
}
public override string ToString()
{
return $"{TopLeft}->{BottomRight}";
}
}
}