private int[] ExpandRegions(int maxIter, int level, ref int[] srcReg, ref int[] srcDist, ref int[] dstReg, ref int[] dstDist, ref IntArray stack) { int w = Width; int h = Height; stack.Resize(0); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { CompactCell c = Cells[x + y * w]; for (int i = (int)c.Index, ni = (int)(c.Index + c.Count); i < ni; i++) { if (Dist[i] >= level && srcReg[i] == 0 && Areas[i] != HeightField.NullArea) { stack.Push(x); stack.Push(y); stack.Push(i); } } } } int iter = 0; while (stack.Size > 0) { int failed = 0; Buffer.BlockCopy(srcReg, 0, dstReg, 0, sizeof(int) * SpanCount); Buffer.BlockCopy(srcDist, 0, dstDist, 0, sizeof(int) * SpanCount); //Array.Copy(srcReg, dstReg, SpanCount); //Array.Copy(srcDist, dstDist, SpanCount); for (int j = 0; j < stack.Size; j += 3) { int x = stack[j + 0]; int y = stack[j + 1]; int i = stack[j + 2]; if (i < 0) { failed++; continue; } int r = srcReg[i]; int d2 = short.MaxValue; uint area = Areas[i]; CompactSpan s = Spans[i]; for (int dir = 0; dir < 4; dir++) { if (s.GetCon(dir) == NotConnected) { continue; } int ax = x + Helper.GetDirOffsetX(dir); int ay = y + Helper.GetDirOffsetY(dir); int ai = (int)Cells[ax + ay * w].Index + s.GetCon(dir); if (Areas[ai] != area) { continue; } if (srcReg[ai] > 0 && (srcReg[ai] & BorderReg) == 0) { if (srcDist[ai] + 2 < d2) { r = srcReg[ai]; d2 = srcDist[ai] + 2; } } } if (r != 0) { stack[j + 2] = -1; dstReg[i] = r; dstDist[i] = d2; } else { failed++; } } int[] temp = srcReg; srcReg = dstReg; dstReg = temp; temp = srcDist; srcDist = dstDist; dstDist = temp; if (failed * 3 == stack.Size) { break; } if (level > 0) { ++iter; if (iter >= maxIter) { break; } } } return(srcReg); }
private bool FloodRegion(int x, int y, int i, int level, int r, ref int[] srcReg, ref int[] srcDist, ref IntArray stack) { int w = Width; uint area = Areas[i]; stack.Resize(0); stack.Push(x); stack.Push(y); stack.Push(i); srcReg[i] = r; srcDist[i] = 0; int lev = level >= 2 ? level - 2 : 0; int count = 0; while (stack.Size > 0) { int ci = stack.Pop(); int cy = stack.Pop(); int cx = stack.Pop(); CompactSpan cs = Spans[ci]; int ar = 0; for (int dir = 0; dir < 4; dir++) { if (cs.GetCon(dir) != NotConnected) { int ax = cx + Helper.GetDirOffsetX(dir); int ay = cy + Helper.GetDirOffsetY(dir); int ai = (int)Cells[ax + ay * w].Index + cs.GetCon(dir); if (Areas[ai] != area) { continue; } int nr = srcReg[ai]; if ((nr & BorderReg) != 0) { continue; } if (nr != 0 && nr != r) { ar = nr; } CompactSpan aspan = Spans[ai]; int dir2 = (dir + 1) & 0x3; if (aspan.GetCon(dir2) != NotConnected) { int ax2 = ax + Helper.GetDirOffsetX(dir2); int ay2 = ay + Helper.GetDirOffsetY(dir2); int ai2 = (int)Cells[ax2 + ay2 * w].Index + aspan.GetCon(dir2); if (Areas[ai2] != area) { continue; } int nr2 = srcReg[ai2]; if (nr2 != 0 && nr2 != r) { ar = nr2; } } } } if (ar != 0) { srcReg[ci] = 0; continue; } count++; for (int dir = 0; dir < 4; dir++) { if (cs.GetCon(dir) != NotConnected) { int ax = cx + Helper.GetDirOffsetX(dir); int ay = cy + Helper.GetDirOffsetY(dir); int ai = (int)Cells[ax + ay * w].Index + cs.GetCon(dir); if (Areas[ai] != area) { continue; } if (Dist[ai] >= lev && srcReg[ai] == 0) { srcReg[ai] = r; srcDist[ai] = 0; stack.Push(ax); stack.Push(ay); stack.Push(ai); } } } } return(count > 0); }