예제 #1
0
        private Rectangle FindCoveringRectangle(List <Pixel> boundary)
        {
            if (boundary == null)
            {
                return(null);
            }

            int[] min = new int[2] {
                _image.LenX - 1, _image.LenY - 1
            };
            int[] max = new int[2] {
                0, 0
            };

            foreach (var pix in boundary)
            {
                if (pix.X < min[0])
                {
                    min[0] = pix.X;
                }
                if (pix.X > max[0])
                {
                    max[0] = pix.X;
                }
                if (pix.Y < min[1])
                {
                    min[1] = pix.Y;
                }
                if (pix.Y > max[1])
                {
                    max[1] = pix.Y;
                }
            }

            var coveringRectangle = new Rectangle(
                _image.GetArrayElement(min[0], min[1]),
                _image.GetArrayElement(max[0], max[1]),
                _image.GetArrayElement(min[0], max[1]),
                _image.GetArrayElement(max[0], min[1])
                );

            return(coveringRectangle);
        }
예제 #2
0
        private ClockWise _direction;   // index to keep where are we in the clock-wise clock
                                        // 0 - w, 1 - nw, 2 - n, 3 - ne, 4 - e, 5 - se, 6 - s, 7 - sw

        private Pixel GetClockWisePixel(Pixel input, ImageMatrix img)
        {
            int newX, newY;

            do
            {
                var x_offset = _directionOffset[(int)_direction, 0];
                var y_offset = _directionOffset[(int)_direction, 1];

                _direction = (ClockWise)((int)(_direction + 1) % 8);

                newX = input.X + x_offset;
                newY = input.Y + y_offset;
            }
            // if edge pixels, move to next clockwise
            while (newX < 0 || newX >= img.LenX || newY < 0 || newY >= img.LenY);

            return(img.GetArrayElement(newX, newY));
        }
예제 #3
0
        public IEnumerator <Pixel> GetEnumerator()
        {
            // use local variables to be restarted in the next foreach statement
            var upperBound  = _upperBound;
            var bottomBound = _bottomBound;
            var leftBound   = _leftBound;
            var rightBound  = _rightBound;
            var counter     = _counter;
            var x           = _x;
            var y           = _y;

            upperBound++; // initial increase of boundary so

            while (counter > 0)
            {
                // go right until you hit boundary
                while (y < rightBound)
                {
                    yield return(_image.GetArrayElement(x, y));

                    y++;
                    counter--;
                }

                rightBound--;

                // go down until you hit boundary
                while (x < bottomBound)
                {
                    yield return(_image.GetArrayElement(x, y));

                    x++;
                    counter--;
                }

                bottomBound--;

                // go left until you hit boundary
                while (y > leftBound)
                {
                    yield return(_image.GetArrayElement(x, y));

                    y--;
                    counter--;
                }

                leftBound++;

                // go up until you hit boundary
                while (x > upperBound)
                {
                    yield return(_image.GetArrayElement(x, y));

                    x--;
                    counter--;
                }

                upperBound++;
            }

            yield return(_image.GetArrayElement(x, y)); // last element when all bounds are same...
        }
예제 #4
0
        public List <Pixel> Trace(ImageMatrix img)
        {
            Pixel firstHolePixel;

            for (int i = 0; i < img.LenX; i++)
            {
                for (int j = 0; j < img.LenY; j++)
                {
                    firstHolePixel = img.GetArrayElement(i, j);
                    if (firstHolePixel.Value == -1)
                    {
                        // while goto statements are not highly approved of, as they create hard-to-read spaghetti code,
                        // this (breaking out of nested loops) is one of the rare cases where they should be used,
                        // as they are more coherent than setting up multiple flags, or using sub-methods that will return.
                        goto Hole_Exists;
                    }
                }
            }

            // if here - no hole was found, simply return null
            return(null);

Hole_Exists:
            ClockWise _start;            // how we first start the trip

            _direction = ClockWise.West; // initial position
            var holePixel = firstHolePixel;

            // What if hole is in (x,0) ? We'll go around it clockwise until we find a non-hole pixel
            if (holePixel.Y == 0)
            {
                var nextPixel = GetClockWisePixel(holePixel, img);
                while (nextPixel.Value == -1)
                {
                    Backtrack();
                    holePixel = nextPixel;
                    nextPixel = GetClockWisePixel(holePixel, img);

                    if (holePixel == firstHolePixel) // entire image is one big hole
                    {
                        return(null);
                    }
                }
                _direction = (ClockWise)((int)(_direction + 7) % 8);
            }

            _start = _direction;

            var Boundary = new List <Pixel>();

            var firstPixel = GetClockWisePixel(holePixel, img);

            Boundary.Add(firstPixel);

            var boundaryPixel = GetClockWisePixel(holePixel, img);

            // stop condition:
            //      A. reach the same first pixel we started from
            //      B. in cases of enclaves with 1 space gap, this might cause a premature stop
            //          we can make sure we are reaching it while completeing the full circle of the circle-wise turning
            //          (also called Jacob's stopping criteria)
            while (!(boundaryPixel == firstPixel && _direction - 1 == _start))
            {
                if (boundaryPixel.Value != -1)
                {
                    if (!Boundary.Contains(boundaryPixel))
                    {
                        Boundary.Add(boundaryPixel);
                    }
                }
                else
                {
                    Backtrack();
                    holePixel = boundaryPixel;
                }
                boundaryPixel = GetClockWisePixel(holePixel, img);
            }

            return(Boundary);
        }