/// <inheritdoc />
        public IBoundedIndexable <Index2D, T> Rasterize(
            float cellLength, Func <Index2D, T> internalValueFactory, Func <Index2D, T> externalValueFactory)
        {
            IRasterizableMaskContracts.Rasterize(cellLength, internalValueFactory, externalValueFactory);

            T[,] array = MaskArrayFactory.Create <T>(this.Diameter, this.Diameter, cellLength);
            int size = array.GetLength(0);

            // mask tracks what slots are inside and outside of the circle
            bool[,] mask = MaskArrayFactory.CreateCircleMask(size);

            // for each cell in the array, fill in according to the mask
            for (int iX = 0; iX < size; iX++)
            {
                for (int iY = 0; iY < size; iY++)
                {
                    if (mask[iX, iY])
                    {
                        // inside the circle
                        array[iX, iY] = internalValueFactory(new Index2D(iX, iY));
                    }
                    else
                    {
                        // outside the circle
                        array[iX, iY] = externalValueFactory(new Index2D(iX, iY));
                    }
                }
            }

            return(new Array2D <T>(array));
        }
        /// <inheritdoc />
        public IBoundedIndexable <Index3D, T> Rasterize(
            float cellLength, Func <Index3D, T> internalValueFactory, Func <Index3D, T> externalValueFactory)
        {
            IRasterizableMaskContracts.Rasterize(cellLength, internalValueFactory, externalValueFactory);

            T[,,] array = MaskArrayFactory.Create <T>(this.Diameter, this.Height, this.Diameter, cellLength);
            int sizeBase   = array.GetLength(0);
            int sizeHeight = array.GetLength(1);

            // mask tracks what slots are inside and outside of the circle base in order to fill in the columns
            bool[,] mask = MaskArrayFactory.CreateCircleMask(sizeBase);

            // for each slot in the circular base
            for (int iX = 0; iX < sizeBase; iX++)
            {
                for (int iZ = 0; iZ < sizeBase; iZ++)
                {
                    // choose fill function depending on if it's inside or outside the circle base
                    Func <Index3D, T> value = mask[iX, iZ] ? internalValueFactory : externalValueFactory;

                    // fill in the column with the chosen function
                    for (int iY = 0; iY < sizeHeight; iY++)
                    {
                        array[iX, iY, iZ] = value(new Index3D(iX, iY, iZ));
                    }
                }
            }

            return(new Array3D <T>(array));
        }
        /// <inheritdoc />
        public IBoundedIndexable <Index3D, T> Rasterize(
            float cellLength, Func <Index3D, T> internalValueFactory, Func <Index3D, T> externalValueFactory)
        {
            IRasterizableMaskContracts.Rasterize(cellLength, internalValueFactory, externalValueFactory);

            T[,,] array = MaskArrayFactory.Create <T>(this.Diameter, this.Diameter, this.Diameter, cellLength);

            if (array.Length == 0)
            {
                return(new Array3D <T>(array));
            }

            int   max      = array.GetLength(0) - 1;
            int   mid      = max / 2;
            float radius   = array.GetLength(0) / 2f;
            float distance = radius * radius;

            for (int iX = 0; iX <= mid; iX++)
            {
                for (int iY = 0; iY <= mid; iY++)
                {
                    for (int iZ = 0; iZ <= mid; iZ++)
                    {
                        int mX = max - iX;
                        int mY = max - iY;
                        int mZ = max - iZ;

                        if (DistanceCheck(iX - mid, iY - mid, iZ - mid, distance))
                        {
                            array[iX, iY, iZ] = internalValueFactory(new Index3D(iX, iY, iZ));
                            array[mX, iY, iZ] = internalValueFactory(new Index3D(mX, iY, iZ));
                            array[iX, mY, iZ] = internalValueFactory(new Index3D(iX, mY, iZ));
                            array[iX, iY, mZ] = internalValueFactory(new Index3D(iX, iY, mZ));
                            array[mX, mY, iZ] = internalValueFactory(new Index3D(mX, mY, iZ));
                            array[iX, mY, mZ] = internalValueFactory(new Index3D(iX, mY, mZ));
                            array[mX, iY, mZ] = internalValueFactory(new Index3D(mX, iY, mZ));
                            array[mX, mY, mZ] = internalValueFactory(new Index3D(mX, mY, mZ));
                        }
                        else
                        {
                            array[iX, iY, iZ] = externalValueFactory(new Index3D(iX, iY, iZ));
                            array[mX, iY, iZ] = externalValueFactory(new Index3D(mX, iY, iZ));
                            array[iX, mY, iZ] = externalValueFactory(new Index3D(iX, mY, iZ));
                            array[iX, iY, mZ] = externalValueFactory(new Index3D(iX, iY, mZ));
                            array[mX, mY, iZ] = externalValueFactory(new Index3D(mX, mY, iZ));
                            array[iX, mY, mZ] = externalValueFactory(new Index3D(iX, mY, mZ));
                            array[mX, iY, mZ] = externalValueFactory(new Index3D(mX, iY, mZ));
                            array[mX, mY, mZ] = externalValueFactory(new Index3D(mX, mY, mZ));
                        }
                    }
                }
            }

            return(new Array3D <T>(array));
        }
        /// <inheritdoc />
        public IBoundedIndexable <Index2D, T> Rasterize(
            float cellLength, Func <Index2D, T> internalValueFactory, Func <Index2D, T> externalValueFactory)
        {
            IRasterizableMaskContracts.Rasterize(cellLength, internalValueFactory, externalValueFactory);

            T[,] array = MaskArrayFactory.Create <T>(this.LengthX, this.LengthY, cellLength);
            int xSize = array.GetLength(0);
            int ySize = array.GetLength(1);

            // populate the array with internal values
            for (int iX = 0; iX < xSize; iX++)
            {
                for (int iY = 0; iY < ySize; iY++)
                {
                    array[iX, iY] = internalValueFactory(new Index2D(iX, iY));
                }
            }

            return(new Array2D <T>(array));
        }