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);
        }