/// <summary> /// Gives a new point that represents the /// first point multiplied by the second point /// component-wise. /// /// Since version 1.6 (Rect) /// Since version 1.7 (other) /// </summary> public PointyHexPoint Mul(PointyHexPoint otherPoint) { var x = X * otherPoint.X; var y = Y * otherPoint.Y; return(new PointyHexPoint(x, y)); }
public IEnumerable <PointyHexPoint> GetSpiralIterator(PointyHexPoint origin, int ringCount) { var hexPoint = origin; yield return(hexPoint); for (var k = 1; k < ringCount; k++) { hexPoint = new PointyHexPoint(0, 0); hexPoint = hexPoint + SpiralIteratorDirections[4] * (k); for (var i = 0; i < 6; i++) { for (var j = 0; j < k; j++) { if (Contains(hexPoint)) { yield return(hexPoint); } hexPoint = hexPoint + SpiralIteratorDirections[i]; } } } }
public PointyHexShapeInfo <TCell> Hexagon(int side) { var storageSize = 2 * side - 1; var storageBottomLeft = new PointyHexPoint(1 - side, 1 - side); return(Shape(storageSize, storageSize, x => IsInsideHex(x, side), storageBottomLeft)); }
/** * @since 1.7 */ public IEnumerable <PointyHexPoint> GetSpiralIterator(int N) { var hexPoint = new PointyHexPoint(0, 0); yield return(hexPoint); for (var k = 0; k < N; k++) { hexPoint = new PointyHexPoint(0, 0); hexPoint = hexPoint + HexDirections[4] * (k); for (var i = 0; i < 6; i++) { for (var j = 0; j < k; j++) { if (Contains(hexPoint)) { yield return(hexPoint); } hexPoint = hexPoint + HexDirections[i]; } } } }
/// <summary> /// Gives a new point that represents the /// first point divided by the second point /// component-wise. The division is integer /// division. /// /// Since version 1.6 (Rect) /// Since version 1.7 (other) /// </summary> public PointyHexPoint Div(PointyHexPoint otherPoint) { var x = GLMathf.FloorDiv(X, otherPoint.X); var y = GLMathf.FloorDiv(Y, otherPoint.Y); return(new PointyHexPoint(x, y)); }
/** * Makes an edge grid for this grid. */ public IGrid <TNewCell, PointyRhombPoint> MakeEdgeGrid <TNewCell>() { var edgeOffset = GridOrigin; var offset = new PointyHexPoint(1, 1); return(new PointyRhombGrid <TNewCell>(width + 2, height + 2, x => IsInsideEdgeGrid(x - offset), edgeOffset.GetEdgeAnchor().BasePoint - offset)); }
public PointyHexShapeInfo <TCell> FatRectangle(int width, int height) { int storageWidth = width + GLMathf.FloorDiv(height, 2); int storageHeight = height; var storageBottomLeft = new PointyHexPoint(-GLMathf.FloorDiv(height, 2), 0); return(Shape(storageWidth, storageHeight, x => IsInsideFatRectangle(x, width, height), storageBottomLeft)); }
private static bool IsInsideXYParallelogram(PointyHexPoint point, int width, int height) { return ((point.X >= 0) && (point.X < width) && (point.Y >= 0) && (point.Y < height)); }
public static bool DefaultContains(PointyHexPoint point, int width, int height) { ArrayPoint storagePoint = ArrayPointFromGridPoint(point); return (storagePoint.X >= 0 && storagePoint.X < width && storagePoint.Y >= 0 && storagePoint.Y < height); }
private static bool IsInsideFatRectangle(PointyHexPoint point, int width, int height) { int startX = -(GLMathf.FloorDiv(point.Y, 2)); return (point.X >= startX - GLMathf.FloorMod(point.Y, 2) && point.X < startX + width && point.Y >= 0 && point.Y < height); }
/** * Rotates a shape 180 degrees around the edge shared by the two given points. * * The two points must be neighbors. */ public static IEnumerable <PointyHexPoint> Rotate180About( IEnumerable <PointyHexPoint> shape, PointyHexPoint p1, PointyHexPoint p2) { var translation = p1.Translate(p2); var correction = translation.Subtract(translation.Rotate180()).ScaleDown(2); return(TransformShape <PointyHexPoint>(shape, point => point.Rotate180().Translate(correction)).ToList()); }
/** * Rotates a shape 120 degrees around the vertice shared by the three given points. * * The three points must form a close triangle (they must share a vertex). */ public static IEnumerable <PointyHexPoint> Rotate120About( IEnumerable <PointyHexPoint> shape, PointyHexPoint p1, PointyHexPoint p2, PointyHexPoint p3) { /* * If t = (p1 + p2 + p3)/3, then the result is p => (p - t).Rotate120() + t. * * This can be rewritten p => p.Rotate120() - t.Rotate120() + t * = p.Rotate120() (T - T.Rotate120())/3, * where T = p1 + p2 + p3. * * This is what this method calculates. This is done so that all coordinates in * intermediatary calculations stay integers. */ var translation = p1.Translate(p2.Translate(p3)); var correction = translation.Subtract(translation.Rotate120()).ScaleDown(3); return(TransformShape(shape, point => point.Rotate120().Translate(correction)).ToList()); }
/// <summary> /// Gives a coloring of the grid such that /// if a point p has color k, then all points /// p + m[ux, 0] + n[vx, vy] have the same color /// for any integers a and b. /// /// More information anout grid colorings: /// http://gamelogic.co.za/2013/12/18/what-are-grid-colorings/ /// /// Since version 1.7 /// </summary> public int __GetColor__ReferenceImplementation(int ux, int vx, int vy) { var u = new PointyHexPoint(ux, 0); var v = new PointyHexPoint(vx, vy); int colorCount = u.PerpDot(v); float a = PerpDot(v) / (float)colorCount; float b = -PerpDot(u) / (float)colorCount; int m = Mathf.FloorToInt(a); int n = Mathf.FloorToInt(b); int baseVectorX = m * u.X + n * v.X; int baseVectorY = n * u.Y + n * v.Y; int offsetX = GLMathf.FloorMod(X - baseVectorX, ux); int offsetY = Y - baseVectorY; int colorIndex = Mathf.FloorToInt(offsetX + offsetY * ux); return(colorIndex); }
/** * Whether this point is in the hexagon with the given radius * and given center. * * A single point is considered a hexagon with zero radius. * * @sa http://devmag.org.za/2013/08/31/geometry-with-hex-coordinates/ * * @since 1.3 */ public bool IsInsideHexagon(PointyHexPoint center, int radius) { return((this - center).Magnitude() <= radius); }
protected override CairoGrid <TCell> MakeShape(int x, int y, Func <CairoPoint, bool> isInside, PointyHexPoint offset) { return(new CairoGrid <TCell>(x, y, isInside, offset)); }
protected override ArrayPoint ArrayPointFromGridPoint(PointyHexPoint point) { return(CairoGrid <TCell> .ArrayPointFromGridPoint(point)); }
protected override PointyRhombGrid <TCell> MakeShape(int x, int y, Func <PointyRhombPoint, bool> isInside, PointyHexPoint offset) { return(new PointyRhombGrid <TCell>(x, y, isInside, offset)); }
protected override FlatTriGrid <TCell> MakeShape(int x, int y, Func <FlatTriPoint, bool> isInside, PointyHexPoint offset) { return(new FlatTriGrid <TCell>(x, y, isInside, offset)); }
protected override CairoPoint MakePoint(PointyHexPoint basePoint, int index) { return(new CairoPoint(basePoint.X, basePoint.Y, index)); }
/** * Construct a new grid whose cells are determined by the given test function. * * The function should only return true for points within the bounds of the rectangle when * the given transforms are applied to them. * * Normally, the static factory methods or shape building methods should be used to create grids. * These constructors are provided for advanced usage. * * @link_constructing_grids */ public PointyHexGrid(int width, int height, Func <PointyHexPoint, bool> isInside, PointyHexPoint offset) : this(width, height, isInside, x => x.MoveBy(offset), x => x.MoveBackBy(offset), PointyHexPoint.MainDirections) { }
public static ArrayPoint ArrayPointFromGridPoint(PointyHexPoint point) { return(PointyHexGrid <TCell> .ArrayPointFromGridPoint(point)); }
public InspectableVectorPoint(PointyHexPoint point) { x = point.X; y = point.Y; }
protected override PointyRhombPoint MakePoint(PointyHexPoint basePoint, int index) { return(new PointyRhombPoint(basePoint.X, basePoint.Y, index)); }
public static ArrayPoint ArrayPointFromGridPoint(PointyHexPoint point) { return(new ArrayPoint(point.X, point.Y)); }
override protected ArrayPoint ArrayPointFromPoint(PointyHexPoint hexPoint) { return(ArrayPointFromGridPoint(hexPoint)); }
/** * Use this function to create shapes to ensure they fit into memory. * * The test function can test shapes anywhere in space. If you specify the bottom corner * (in terms of the storage rectangle), the shape is automatically translated in memory * to fit, assuming memory width and height is big enough. * * Strategy for implementing new shapes: * - First, determine the test function. * - Next, draw a storage rectangle that contains the shape. * - Determine the storgae rectangle width and height. * - Finally, determine the grid-space coordinate of the left bottom corner of the storage rectangle. * * Then define your function as follows: * * \code{cs} * public PointyRhombShapeInfo<TCell> MyShape() * { * Shape(stargeRectangleWidth, storageRectangleHeight, isInsideMyShape, storageRectangleBottomleft); * } * \endcode * * \param width The widh of the storage rectangle * \param height The height of the storage rectangle * \param isInside A function that returns true if a passed point lies inside the shape being defined * \param bottomLeftCorner The grid-space coordinate of the bottom left corner of the storage rect. * */ public PointyRhombShapeInfo <TCell> Shape(int width, int height, Func <PointyRhombPoint, bool> isInside, PointyHexPoint bottomLeftCorner) { var shapeInfo = MakeShapeStorageInfo <PointyRhombPoint>(width, height, x => isInside(x + bottomLeftCorner)); return(new PointyRhombShapeInfo <TCell>(shapeInfo).Translate(bottomLeftCorner)); }
protected override FlatTriPoint MakePoint(PointyHexPoint basePoint, int index) { return(new FlatTriPoint(basePoint.X, basePoint.Y, index)); }
public int Dot(PointyHexPoint other) { return(x * other.X + y * other.Y); }
public CairoGrid(int width, int height, Func <CairoPoint, bool> isInside, PointyHexPoint offset) : this(width, height, isInside, x => x.Translate(offset), x => x.Translate(offset.Negate())) { }
public int PerpDot(PointyHexPoint other) { return(x * other.Y - y * other.x); }