/// <summary> /// Iterates over all elements in <paramref name="tsList"/> in the reverse order and calls /// <paramref name="handler"/> /// </summary> /// <typeparam name="T">Type to store in list</typeparam> /// <param name="tsList">A thread-safe list</param> /// <param name="handler">Called for each element</param> public static void IterateReverse <T>(this ThreadSafe.IList <T> tsList, IterateDelegate <T> handler) { tsList.Iterate(0, -1, true, handler); }
/// <summary> /// Calculate area prioritizing vertically /// </summary> /// <param name="block"></param> /// <param name="vert"></param> /// <param name="hori"></param> public GroupData CalcAreaVert(Block block, Direction vert, Direction hori) { Block place = block; Block current = null; Block cornerBlock = null; GroupData data = new GroupData(); int height = 0; int currentHeight = 0; int width = boundary.width + 1; int currentWidth = 0; switch (hori) { case Direction.left: IterateHori = SameLeft; break; case Direction.right: IterateHori = SameRight; break; default: return(data); } switch (vert) { case Direction.up: IterateVert = SameUp; break; case Direction.down: IterateVert = SameDown; break; default: return(data); } //Iterate prioritizing vertical while (place != null && place.IsGrouped() == false) { currentWidth = 0; current = place; //Check if current block is null,.IsGrouped(), or passed the width while (current != null && current.IsGrouped() == false && currentWidth < width) { //This currently priorites vertical rectangles if (currentWidth >= 2) { cornerBlock = current; } current = IterateHori(current); currentWidth++; } //Iterate vertically place = IterateVert(place); if (currentWidth >= 2) { height++; //Set height to shortest height if (width > currentWidth) { width = currentWidth; } } else { return(data); } currentHeight++; } if (width == boundary.width + 1 || width <= 1 || height <= 1) { return(data); } data.width = width; data.height = height; width = width - 1; height = height - 1; int x = block.X; int y = block.Y; //Corners will be opposite of the direction the data points (up and left means block is bottom right corner if (vert.Equals(Direction.up) && hori.Equals(Direction.left)) { data.topLeft = board.GetBlock(x - width, y + height); data.topRight = board.GetBlock(x, y + height); data.bottomLeft = board.GetBlock(x - width, y); data.bottomRight = block; } else if (vert.Equals(Direction.up) && hori.Equals(Direction.right)) { data.topLeft = board.GetBlock(x, y + height); data.topRight = board.GetBlock(x + width, y + height); data.bottomLeft = block; data.bottomRight = board.GetBlock(x + width, y); } else if (vert.Equals(Direction.down) && hori.Equals(Direction.left)) { data.topLeft = board.GetBlock(x - width, y); data.topRight = block; data.bottomLeft = board.GetBlock(x - width, y - height); data.bottomRight = board.GetBlock(x, y - height); } else if (vert.Equals(Direction.down) && hori.Equals(Direction.right)) { data.topLeft = block; data.topRight = board.GetBlock(x + width, y); data.bottomLeft = board.GetBlock(x, y - height); data.bottomRight = board.GetBlock(x + width, y - height); } return(data); }
/// <summary> /// Iterates over elements in <paramref name="tsList"/> and calls <paramref name="handler"/> /// </summary> /// <typeparam name="T">Type to store in list</typeparam> /// <param name="tsList">A thread-safe list</param> /// <param name="handler">Called for each element</param> /// <param name="startIndex">Start index</param> /// <param name="endIndex">End index. <c>-1</c> means <see cref="ThreadSafe.IList{T}.Count_NoLock"/></param> /// <param name="reverseOrder"><c>true</c> if we should iterate in the reverse order</param> public static void Iterate <T>(this ThreadSafe.IList <T> tsList, int startIndex, int endIndex, bool reverseOrder, IterateDelegate <T> handler) { tsList.ExecuteLocked <object, object>(null, (tsList2, arg) => { if (reverseOrder) { int i = (endIndex < 0 ? tsList2.Count_NoLock : endIndex) - 1; for (; i >= startIndex; i--) { if (!handler(tsList2, i, tsList2.Get_NoLock(i))) { break; } } } else { // Count property can change so check it each time in the loop for (int i = startIndex; i < (endIndex < 0 ? tsList2.Count_NoLock : endIndex); i++) { if (!handler(tsList2, i, tsList2.Get_NoLock(i))) { break; } } } return(null); }); }
public void Expand(Direction dir) { Block other1 = null; Block other2 = null; switch (dir) { case Direction.up: other1 = data.topLeft.SameAdjacent(Direction.up); other2 = data.topRight.SameAdjacent(Direction.up); if (other1 == null || other2 == null) { return; } data.topLeft = other1; data.topRight = other2; //Iterate from topLeft to topRight (right) OnIterate = IterateRight; OnExpand = IncrementHeight; break; case Direction.right: other1 = data.topRight.SameAdjacent(Direction.right); other2 = data.bottomRight.SameAdjacent(Direction.right); if (other1 == null || other2 == null) { return; } data.topRight = other1; data.bottomRight = other2; //Iterate from topRight to bottomRight (down) OnIterate = IterateDown; OnExpand = IncrementWidth; break; case Direction.down: other1 = data.bottomLeft.SameAdjacent(Direction.down); other2 = data.bottomRight.SameAdjacent(Direction.down); if (other1 == null || other2 == null) { return; } data.bottomLeft = other1; data.bottomRight = other2; //Iterate from bottomLeft to bottomRight (right) OnIterate = IterateRight; OnExpand = IncrementHeight; break; case Direction.left: other1 = data.topLeft.SameAdjacent(Direction.left); other2 = data.bottomLeft.SameAdjacent(Direction.left); if (other1 == null || other2 == null) { return; } data.topLeft = other1; data.bottomLeft = other2; //Iterate from topLeft to bottomLeft (down) OnIterate = IterateDown; OnExpand = IncrementWidth; break; default: return; } //Get blocks adjacent to the corners other2.groupable.SetGroup(this); blocks.Add(other2); while (!other1.Equals(other2) && other1 != null) { blocks.Add(other1); other1.groupable.SetGroup(this); other1 = OnIterate(other1); } OnExpand(); OnIterate = null; OnExpand = null; }