Example #1
0
        public static Shape reduceShapeToAreaAndRatio(Shape originalShape, Point? firstPoint, double ratioLimit, int areaLowerLimit, int areaHigherLimit)
        {
            int[] neighx = { -1, 0, 1, -1, 1, -1, 0, 1 };
            int[] neighy = { -1, -1, 1, 0, 0, 1, 1, 1 };
            if (ratioLimit <= 0)
            {
                return null;
            }
            double ratioLimitInv = 1 / ratioLimit;
            int px = 0, py = 0, nx, ny;
            Point? head, neighbour;

            Shape reducedShape = new Shape();
            int reducedArea = 0;
            double reducedRatio = 1.0;
            Queue<Point?> queue = new Queue<Point?>();
            if (originalShape == null)
            {
                return null;
            }
            if (!originalShape.contains(firstPoint))
            {
                return null;
            }
            queue.Enqueue(firstPoint);
            while (true)
            {
                head = queue.Dequeue();

                reducedShape.Add(head);
                reducedRatio = reducedShape.getAspectRatio();
                reducedArea = reducedShape.Set.Count;
                py = head.Value.Y;
                for (int i = 0; i < 8; i++)
                {
                    nx = px + neighx[i];
                    ny = py + neighy[i];
                    neighbour = new Point(nx, ny);
                    if ((originalShape.contains(neighbour))
                            && (!reducedShape.contains(neighbour)) && (!queue.Contains(neighbour))
                            && (reducedArea + queue.Count < areaHigherLimit))
                    {
                        queue.Enqueue(neighbour);
                    }
                }

                /*
                 * Stop condition. It's weird but it's faster
                 */
                if (!(queue.Count > 0))
                {
                    break;
                }
                else
                {
                    if (reducedArea < areaLowerLimit)
                    {
                        continue;
                    }
                    else if (reducedArea > areaHigherLimit)
                    {
                        break;
                    }
                    else
                    {
                        if ((ratioLimitInv < reducedRatio) && (reducedRatio < ratioLimit))
                        {
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            if ((reducedShape.Set.Count < areaLowerLimit) || ((ratioLimitInv < reducedRatio) && (reducedRatio < ratioLimit)))
            {
                return null;
            }
            return reducedShape;
        }