private void RecursiveApply(int[] tracker, int[] voronoi, int idx, Point p, int width, int height)
        {
            int ox = this.EdgeSampling;
            int oy = this.EdgeSampling;
            int rw = width + this.EdgeSampling * 2;
            int rh = height + this.EdgeSampling * 2;

            if (p.Inside(-ox, -oy, rw, rh) && voronoi[(p.X + ox) + (p.Y + oy) * rw] != 2 /* edge */ && tracker[(p.X + ox) + (p.Y + oy) * rw] == 0 /* not hit */)
                tracker[(p.X + ox) + (p.Y + oy) * rw] = idx + MAPPING_OFFSET;
            else
                return;
            this.RecursiveApply(tracker, voronoi, idx, p.Left, width, height);
            this.RecursiveApply(tracker, voronoi, idx, p.Right, width, height);
            this.RecursiveApply(tracker, voronoi, idx, p.Up, width, height);
            this.RecursiveApply(tracker, voronoi, idx, p.Down, width, height);
        }
        private int FindValueNearOpposite(int[] tracker, int[] data, int x, int y, int i, int j, int width, int height)
        {
            Point p = new Point(i, j);
            int ox = this.EdgeSampling;
            int oy = this.EdgeSampling;
            int rw = width + this.EdgeSampling * 2;
            int rh = height + this.EdgeSampling * 2;

            if (p.Inside(width, height) && tracker[(i + ox) + (j + oy) * rw] != 0)
                return data[i + j * width];
            Random r = this.GetCellRNG(x + i, y + j);
            if (p.Right.Inside(width, height) && (p.Down.Inside(width, height) || r.Next(2) == 0))
                return this.FindValueNearOpposite(tracker, data, x, y, i + 1, j, width, height);
            else if (p.Down.Inside(width, height))
                return this.FindValueNearOpposite(tracker, data, x, y, i, j + 1, width, height);
            return 0;
        }