Ejemplo n.º 1
0
        /// <summary>
        /// Converts the specified BitMatrix into a list of Polygons.
        /// </summary>
        /// <param name='bm'>
        /// The BitMatrix to convert from.
        /// </param>
        public static Paths Polygonize(BitMatrix bm)
        {
            #region pixels grouping
            // group pixels into separate areas, keep in mind that a polygon only stores points here
            Paths areas = new Paths();

            // current scanline
            BitArray currLineBuf = new BitArray(bm.width);

            Path[] prevLine = new Path[bm.width];

            for (int i = 0; i < bm.width; i++)
            {
                prevLine[i] = null;
            }

            // the area that current pixel belongs to
            Path currArea, prevArea;

            int left;                                   // counter for checking pixels on the left side

            for (int y = 0; y < bm.height; y++)
            {
                // scan current line
                for (int x = 0; x < bm.width; x++)
                {
                    // store current pixel in the buffer
                    currLineBuf[x] = bm.Get(x, y);
                    // index of the left pixel
                    left = x - 1;

                    // pixel connects with the pixel above it
                    if (currLineBuf[x])
                    {
                        //Debug.WriteLine("{0}, {1}: active", y, x);
                        // check pixels on top of it
                        currArea = prevLine[x];
                        if (currArea != null)
                        {
                            //Debug.WriteLine("Join top");
                            // join current pixel into top area
                            currArea.Add(new IntPoint(x, y));
                            // Checks the pixels on the left side
                            // if they are connected to current pixel,
                            //   if they belong to different area
                            //	   change all of them to current area, and merge that area into current area
                            //	 else do nothing
                            // else do nothing

                            // merge left area into top one
                            if (left >= 0)
                            {
                                prevArea = prevLine[left];
                                if (prevArea != null && prevArea != currArea)
                                {
                                    //Debug.WriteLine("Merging left to top");
                                    prevArea = prevLine[left];
                                    while (left >= 0)
                                    {
                                        // update references of pixels on the left side
                                        if (prevLine[left] == prevArea)
                                        {
                                            prevLine[left] = currArea;
                                        }
                                        left--;
                                    }
                                    // merge area into current one
                                    areas.Remove(prevArea);
                                    currArea.AddRange(prevArea);
                                }
                            }
                        }
                        else
                        {
                            // Since no active pixel on top, check left side
                            // if left side is active
                            //	 simply join to the left area
                            // else
                            //	 create a new area
                            if (left >= 0 && prevLine[left] != null)
                            {
                                //Debug.WriteLine("Join left");
                                prevLine[left].Add(new IntPoint(x, y));
                                prevLine[x] = prevLine[left];
                            }
                            else
                            {
                                //Debug.WriteLine("Create new");
                                Path newArea = new Path();
                                newArea.Add(new IntPoint(x, y));
                                areas.Add(newArea);
                                prevLine[x] = newArea;
                            }
                        }
                        // pixel not activated
                    }
                    else
                    {
                        //Debug.WriteLine("{0},{1}: not active", x, y);
                        prevLine[x] = null;
                    }
                }
            }
            #endregion

            #region polygonize each group of pixels into contour pixels
            Path p;
            //Create Polygons from given areas
            for (int i = 0; i < areas.Count; i++)
            {
                // dequeue a group of points
                p = areas[0];
                areas.RemoveAt(0);
                // convert to contour
                p = Polygonizer.FromGroup(p);
                // enqueue back
                areas.Add(p);
            }
            #endregion

            return(areas);
        }