public static IEnumerable <Point> Enumerate(int radiusX, int radiusY, bool filled = false)
        {
            // preliminary check - zero point
            if (radiusX == 0 || radiusY == 0)
            {
                return(Enumerable.Empty <Point>());
            }

            // preliminary check - horizontal line
            if (radiusY == 1 || radiusY == -1)
            {
                return(LineRasterizer.EnumerateHorizontalLine(radiusX));
            }

            // preliminary check - vertical line
            if (radiusX == 1 || radiusX == -1)
            {
                return(LineRasterizer.EnumerateVerticalLine(radiusY));
            }

            // potencial problem - negative radius X
            if (radiusX < 0)
            {
                radiusX = -radiusX;
            }

            // potencial problem - negative radius Y
            if (radiusY < 0)
            {
                radiusY = -radiusY;
            }

            // enumerates ellipse
            return(EnumerateEllipse(radiusX, radiusY, filled));
        }
        /// <summary>
        /// If you wonder why I didn't use some faster algorithm (bresenham, mid-point..) it's because it wouldn't match
        /// the outline of drawn ellipse via Graphics.DrawEllipse. So the obstacle looks elsewhere then the drawn ellipse.
        /// TODO revisit in a few years.
        /// </summary>
        private static IEnumerable <Point> EnumerateEllipse(int radiusX, int radiusY, bool filled = false)
        {
            double anomaly   = HalfPi;
            Point  lastPoint = Point.Empty;

            List <Point> result = new List <Point>
            {
                new Point(-radiusX, radiusY),
                new Point(radiusX, radiusY)
            };

            if (filled)
            {
                result.Add(Point.Empty);
            }

            while (anomaly >= 0.0)
            {
                int shiftX = Convert.ToInt32(radiusX * Math.Cos(anomaly));
                int shiftY = Convert.ToInt32(radiusY * Math.Sin(anomaly));

                int x = radiusX + shiftX;
                int y = radiusY + shiftY;

                if (x != lastPoint.X || y != lastPoint.Y)
                {
                    Point topLeft     = new Point(radiusX - shiftX, radiusY - shiftY);
                    Point topRight    = new Point(radiusX + shiftX, radiusY - shiftY);
                    Point bottomLeft  = new Point(radiusX - shiftX, radiusY + shiftY);
                    Point bottomRight = new Point(radiusX + shiftX, radiusY + shiftY);

                    result.Add(topLeft);
                    if (filled)
                    {
                        result.AddRange(LineRasterizer.EnumerateHorizontalLine(radiusX - shiftX + 1, radiusX + shiftX - 1, radiusY - shiftY));
                    }
                    result.Add(topRight);

                    result.Add(bottomLeft);
                    if (filled)
                    {
                        result.AddRange(LineRasterizer.EnumerateHorizontalLine(radiusX - shiftX + 1, radiusX + shiftX - 1, radiusY + shiftY));
                    }
                    result.Add(bottomRight);

                    lastPoint = bottomRight;
                }

                anomaly -= Step;
            }

            return(result);
        }