public ExplicitOutlineShape(OutlineShape template, InsideShapeDelegate isReserved)
     : this(template.XSize, template.YSize)
 {
     for (int x = 0; x < this.XSize; x++)
     {
         for (int y = 0; y < this.YSize; y++)
         {
             this.SetValue(x, y, (template[x, y] && (isReserved == null || !isReserved(x, y))));
         }
     }
 }
        /// <summary>
        /// Returns the largest subset of the template shape whose squares are all connected to each other.
        /// </summary>
        /// <param name="template"></param>
        /// <param name="isReserved">defines the maze's reserved areas</param>
        /// <returns></returns>
        public static OutlineShape ConnectedSubset(OutlineShape template, InsideShapeDelegate isReserved)
        {
            ExplicitOutlineShape result = new ExplicitOutlineShape(template, isReserved);

            #region Scan the shape for connected areas.

            byte subsetId        = 1;
            int  largestAreaSize = 0;
            byte largestAreaId   = 0;

            for (int x = 0; x < result.XSize; x++)
            {
                for (int y = 0; y < result.YSize; y++)
                {
                    if (result.squares[x, y] == 1 && subsetId < byte.MaxValue)
                    {
                        int areaSize = result.FillSubset(x, y, ++subsetId);
                        if (areaSize > largestAreaSize)
                        {
                            largestAreaSize = areaSize;
                            largestAreaId   = subsetId;
                        }
                    }
                }
            }

            #endregion

            #region Leave only the largest subset, eliminate all others.

            for (int x = 0; x < result.XSize; x++)
            {
                for (int y = 0; y < result.YSize; y++)
                {
                    result.SetValue(x, y, (result.squares[x, y] == largestAreaId));
                }
            }

            #endregion

            return(result);
        }
Example #3
0
        public OutlineShape RotatedOrFlipped(RotateFlipType rft)
        {
            // Note: flipX and flipY will be evaluated after swapping X and Y.
            bool swapXY = false, flipX = false, flipY = false;

            // Note: There are eight different rotate/flip operations but 16 names in the RotateFlipType.
            //       Every operation has two names which give the same enum value.
            switch (rft)
            {
            default:
            case RotateFlipType.RotateNoneFlipNone:
                //case RotateFlipType.Rotate180FlipXY:
                break;

            case RotateFlipType.RotateNoneFlipX:
                //case RotateFlipType.Rotate180FlipY:
                flipX = true;
                break;

            case RotateFlipType.RotateNoneFlipY:
                //case RotateFlipType.Rotate180FlipX:
                flipX = true;
                break;

            case RotateFlipType.Rotate90FlipNone:
                //case RotateFlipType.Rotate270FlipXY:
                swapXY = flipX = true;
                break;

            case RotateFlipType.Rotate270FlipNone:
                //case RotateFlipType.Rotate90FlipXY:
                swapXY = flipY = true;
                break;

            case RotateFlipType.RotateNoneFlipXY:
                //case RotateFlipType.Rotate180FlipNone:
                flipX = flipY = true;
                break;

            case RotateFlipType.Rotate90FlipX:
                //case RotateFlipType.Rotate270FlipY:
                swapXY = true;
                break;

            case RotateFlipType.Rotate90FlipY:
                //case RotateFlipType.Rotate270FlipX:
                swapXY = flipX = flipY = true;
                break;
            }

            int resultXSize, resultYSize;

            if (swapXY)
            {
                resultXSize = this.ySize; resultYSize = this.xSize;
            }
            else
            {
                resultXSize = this.xSize; resultYSize = this.ySize;
            }

            InsideShapeDelegate test = delegate(int x, int y)
            {
                int xx, yy;

                if (swapXY)
                {
                    xx = y; yy = x;
                }
                else
                {
                    xx = x; yy = y;
                }
                if (flipX)
                {
                    xx = this.xSize - 1 - xx;
                }
                if (flipY)
                {
                    yy = this.ySize - 1 - yy;
                }

                return(this[xx, yy]);
            };

            // Note: We return an ExplicitOutlineShape because that is more efficiently evaluated.
            //       The TilesOutelineShape also requires an ExplicitOutlineShape for its tile pattern.
            return(new ExplicitOutlineShape(new DelegateOutlineShape(resultXSize, resultYSize, test)));
        }
Example #4
0
        public OutlineShape Inverse()
        {
            InsideShapeDelegate test = delegate(int x, int y) { return(!this[x, y]); };

            return(new DelegateOutlineShape(this.XSize, this.YSize, test));
        }
Example #5
0
 /// <summary>
 /// Returns this shape, augmented by all totally enclosed areas.
 /// Reserved areas define additional borders around enclosed areas.
 /// </summary>
 /// <param name="isReserved">defines the maze's reserved areas</param>
 /// <returns></returns>
 public OutlineShape Closure(InsideShapeDelegate isReserved)
 {
     return(ExplicitOutlineShape.Closure(this, isReserved));
 }
Example #6
0
 /// <summary>
 /// Returns the largest subset of this shape whose squares are all connected to each other.
 /// </summary>
 /// <returns></returns>
 public OutlineShape ConnectedSubset(InsideShapeDelegate isReserved)
 {
     return(ExplicitOutlineShape.ConnectedSubset(this, isReserved));
 }
 public DelegateOutlineShape(int xSize, int ySize, InsideShapeDelegate test)
     : base(xSize, ySize)
 {
     this.test = test;
 }
        /// <summary>
        /// Returns the template shape, augmented by all totally enclosed areas.
        /// </summary>
        /// <param name="template"></param>
        /// <param name="isReserved">defines the maze's reserved areas</param>
        /// <returns></returns>
        public static OutlineShape Closure(OutlineShape template, InsideShapeDelegate isReserved)
        {
            ExplicitOutlineShape result = new ExplicitOutlineShape(template.Inverse());

            #region Scan and mark the reserved areas.

            if (isReserved != null)
            {
                byte reservedId = 3;

                for (int x = 0; x < result.XSize; x++)
                {
                    for (int y = 0; y < result.YSize; y++)
                    {
                        if (isReserved(x, y))
                        {
                            result.squares[x, y] = reservedId;
                        }
                    }
                }
            }

            #endregion

            #region Scan all outside areas.

            byte outsideId = 2;
            int  x0 = 0, x1 = result.XSize - 1, y0 = 0, y1 = result.YSize - 1;

            for (int x = 0; x < result.XSize; x++)
            {
                if (result.squares[x, y0] == 1)
                {
                    result.FillSubset(x, y0, outsideId);
                }
                if (result.squares[x, y1] == 1)
                {
                    result.FillSubset(x, y1, outsideId);
                }
            }
            for (int y = 0; y < result.YSize; y++)
            {
                if (result.squares[x0, y] == 1)
                {
                    result.FillSubset(x0, y, outsideId);
                }
                if (result.squares[x1, y] == 1)
                {
                    result.FillSubset(x1, y, outsideId);
                }
            }

            #endregion

            #region Add the areas which were not reached.

            for (int x = 0; x < result.XSize; x++)
            {
                for (int y = 0; y < result.YSize; y++)
                {
                    // 0: square is part of the template (not part of its inverse)
                    // 1: square is not part of the template, but was not reached
                    result.SetValue(x, y, (result.squares[x, y] <= 1));
                }
            }

            #endregion

            return(result);
        }