/// <summary>Performs an operation on a rectangle of grid squares and the squares areound them.</summary> /// <param name="upperLeft">The upper-left corner of the rectangle in world-coordinates.</param> /// <param name="lowerRight">The lower-right corner of the rectangle in world coordinates.</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to perform on the grid</param> public void RectExpand(VectorF upperLeft, VectorF lowerRight, object data, gridOperation action) { int col1 = (int)(upperLeft.X / SqrWidth) - 1; int row1 = (int)(upperLeft.Y / SqrHeight) - 1; int col2 = (int)(lowerRight.X / SqrWidth) + 1; int row2 = (int)(lowerRight.Y / SqrHeight) + 1; Rect(col1, row1, col2, row2, data, action); }
/// <summary>Performs an operation on a rectangle of grid squares.</summary> /// <param name="col1">The left-most column</param> /// <param name="row1">The top-most row</param> /// <param name="col2">The right-most column</param> /// <param name="row2">The bottom row</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to perform on the grid</param> public void Rect(int col1, int row1, int col2, int row2, object data, gridOperation action) { // check range col1 = Math.Max(col1, 0); row1 = Math.Max(row1, 0); col2 = Math.Min(col2, NumCols - 1); row2 = Math.Min(row2, NumRows - 1); // run tests CancelOperation = false; for (int col; row1 <= row2 && !CancelOperation; row1++) { for (col = col1; col <= col2 && !CancelOperation; col++) { action(Squares[row1, col], data, CurTime, OperationID); } } OperationID++; }
/// <summary>Performs an operation on a point's grid square and those surrounding it</summary> /// <param name="point">The point</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to run</param> public void PointExpand(VectorF point, object data, gridOperation action) { int col = (int)(point.X / SqrSize.X); int row = (int)(point.Y / SqrSize.Y); if (col < 0 || row < 0 || col >= NumCols || row >= NumRows) return; int endCol = (col < NumCols - 1) ? col + 2 : NumCols; int endRow = (row < NumRows - 1) ? row + 2 : NumRows; int begRow = (row != 0) ? (row - 1) : row; CancelOperation = false; for (col = (col != 0) ? (col - 1) : col; col < endCol && !CancelOperation; col++) { for (row = begRow; row < endRow && !CancelOperation; row++) { action(Squares[row, col], data, CurTime, OperationID); } } OperationID++; }
/// <summary>Runs an operation on a single grid square.</summary> /// <param name="point1">The point in the grid.</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to run</param> public void Point(VectorF point, object data, gridOperation action) { int col = (int)(point.X / SqrSize.X); int row = (int)(point.Y / SqrSize.Y); if (col >= 0 && row >= 0 && col < NumCols && row < NumRows) { CancelOperation = false; action(Squares[row, col], data, CurTime, OperationID); OperationID++; } }
/// <summary>Runs an operation on each gridsquare in a line and the gridsquares around them</summary> /// <param name="point1">The first point of the line</param> /// <param name="point2">The second point of the line</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to run</param> public void LineExpand(VectorF point1, VectorF point2, object data, gridOperation action) { // draw expanded line Line(point1, point2, null, ActivatePoint); // find corners int col1, row1, col2, row2; if (point1.X < point2.X) { col1 = (int)(point1.X / SqrSize.X); col2 = (int)(point2.X / SqrSize.X); } else { col2 = (int)(point1.X / SqrSize.X); col1 = (int)(point2.X / SqrSize.X); } if (point1.Y < point2.Y) { row1 = (int)(point1.Y / SqrSize.Y); row2 = (int)(point2.Y / SqrSize.Y); } else { row2 = (int)(point1.Y / SqrSize.Y); row1 = (int)(point2.Y / SqrSize.Y); } col1 -= (col1 != 0) ? 1 : 0; row1 -= (row1 != 0) ? 1 : 0; col2 += (col2 != NumCols - 1) ? 1 : 0; row2 += (row2 != NumRows - 1) ? 1 : 0; // run operation for (int col = col1, row; col <= col2; col++) { for (row = row1; row <= row2; row++) { if (Squares[row, col].Active || (col > 0 && (Squares[row, col - 1].Active || (row > 0 && Squares[row - 1, col - 1].Active))) || (row > 0 && Squares[row - 1, col].Active) || (col < NumCols - 1 && (Squares[row, col + 1].Active || (row < NumRows - 1 && Squares[row + 1, col + 1].Active))) || (row < NumRows - 1 && Squares[row + 1, col].Active)) { if (!CancelOperation) action(Squares[row, col], data, CurTime, OperationID); Squares[row, col].Active = false; } } } OperationID++; }
/// <summary>Runs an operation on each grid square in a line</summary> /// <param name="point1">The first point of the line</param> /// <param name="point2">The second point of the line</param> /// <param name="data">Any data associated with the operation</param> /// <param name="action">The operation to run</param> public void Line(VectorF point1, VectorF point2, object data, gridOperation action) { // find first square int col = (int)(point1.X / SqrSize.X); int row = (int)(point1.Y / SqrSize.Y); // find last square int fCol = (int)(point2.X / SqrSize.X); int fRow = (int)(point2.Y / SqrSize.Y); // if outside boundaries... if (fCol < 0 || fRow < 0 || col >= NumCols || row >= NumRows) return; // correct values col = Math.Max(col, 0); row = Math.Max(row, 0); col = Math.Min(col, NumCols - 1); row = Math.Min(row, NumRows - 1); fCol = Math.Max(fCol, 0); fRow = Math.Max(fRow, 0); fCol = Math.Min(fCol, NumCols - 1); fRow = Math.Min(fRow, NumRows - 1); // general direction bool right; bool down; // increment direction int cold; int rowd; // grid offsets; used when finding y & x intercepts int colo; int rowo; if (right = fCol > col) { cold = colo = 1; } else { cold = -1; colo = 0; } if (down = fRow > row) { rowd = rowo = 1; } else { rowd = -1; rowo = 0; } // if both points are in the same column if (col == fCol) { if (down) Rect(col, row, col, fRow, data, action); else Rect(col, fRow, col, row, data, action); return; } // if both points are in the same row if (row == fRow) { if (right) Rect(col, row, fCol, row, data, action); else Rect(fCol, row, col, row, data, action); return; } // get the slope FInt slope = (point2.Y - point1.Y) / ((point2.X == point1.X) ? FInt.F0 : (point2.X - point1.X)); // run the line CancelOperation = false; while (!CancelOperation && (col != fCol || row != fRow)) { action(Squares[row, col], data, CurTime, OperationID); FInt hCost = Calc.Abs(((col + colo) * SqrSize.X - point1.X) * slope); // the cost of moving left or right FInt vCost = Calc.Abs((row + rowo) * SqrSize.Y - point1.Y); // the cost of moving up or down if (hCost == vCost) { if (col != fCol) col += cold; if (row != rowd) row += rowd; } else if (hCost < vCost) { col += cold; // move left or right } else { row += rowd; // move up or down } } // run operation on last grid square if (!CancelOperation) action(Squares[fRow, fCol], data, CurTime, OperationID); OperationID++; }