示例#1
0
        /// <summary>
        /// returns a polygon representing the periphery of a square region
        /// </summary>
        /// <param name="edges">
        /// edges within the square region <see cref="List`1"/>
        /// </param>
        /// <param name="erode_dilate">
        /// erosion or dilation level <see cref="System.Int32"/>
        /// </param>
        /// <param name="perim">
        /// returned periphery <see cref="polygon2D"/>
        /// </param>
        /// <returns>
        /// set of edges around the periphery <see cref="List`1"/>
        /// </returns>
        private static List<List<int>> GetSquarePeriphery(List<int> edges,
                                                          int erode_dilate,
                                                          ref polygon2D perim)
        {
            List<List<int>> result = new List<List<int>>();
            perim = new polygon2D();
            
            // find the bounding box for all edges
            int tx = 99999;
            int ty = 99999;
            int bx = -99999;
            int by = -99999;            
            for (int i = edges.Count-2; i >= 0; i -= 2)
            {
                int x = edges[i];
                int y = edges[i+1];
                if (x < tx) tx = x;
                if (y < ty) ty = y;
                if (x > bx) bx = x;
                if (y > by) by = y;
            }

            int w = bx - tx;
            int h = by - ty;
            
            if ((w > 0) && (h > 0))
            {                
                int[] left = new int[h+1];
                int[] right = new int[h+1];
                int[] top = new int[w+1];
                int[] bottom = new int[w+1];
                for (int i = edges.Count - 2; i >= 0; i -= 2)
                {
                    int x = edges[i];
                    int x2 = x - tx;
                    int y = edges[i+1];
                    int y2 = y - ty;
                    
                    // left side
                    if ((left[y2] == 0) ||
                        (x < left[y2]))
                        left[y2] = x;

                    // right side
                    if ((right[y2] == 0) ||
                        (x > right[y2]))
                        right[y2] = x;
                    
                    // top
                    if ((top[x2] == 0) ||
                        (y < top[x2]))
                        top[x2] = y;

                    // bottom
                    if ((bottom[x2] == 0) ||
                        (y > bottom[x2]))
                        bottom[x2] = y;
                }

#if SHOW_TIMINGS
                stopwatch timer_best_fit = new stopwatch();
                timer_best_fit.Start();
#endif

                // find a best fit line for the left side
                int best_start = 0;
                int best_end = 0;
                int hits = BestFitLine(left, ref best_start, ref best_end);
                float left_x0 = left[best_start];
                float left_y0 = ty + best_start;
                float left_x1 = left[best_end];
                float left_y1 = ty + best_end;
                /*
                BestFitLineAverage(left, 
                                   ref left_x0, ref left_y0, 
                                   ref left_x1, ref left_y1);
                left_y0 += ty;
                left_y1 += ty;
                */

                // find a best fit line for the right side
                best_start = 0;
                best_end = 0;
                hits = BestFitLine(right, ref best_start, ref best_end);
                float right_x0 = right[best_start];
                float right_y0 = ty + best_start;
                float right_x1 = right[best_end];
                float right_y1 = ty + best_end;

                /*
                BestFitLineAverage(right,
                                   ref right_x0, ref right_y0,
                                   ref right_x1, ref right_y1);
                right_y0 += ty;
                right_y1 += ty;
                 */

                // find a best fit line for the top side
                best_start = 0;
                best_end = 0;
                hits = BestFitLine(top, ref best_start, ref best_end);
                float top_x0 = tx + best_start;
                float top_y0 = top[best_start];
                float top_x1 = tx + best_end;
                float top_y1 = top[best_end];

                /*
                BestFitLineAverage(top,
                                   ref top_x0, ref top_y0,
                                   ref top_x1, ref top_y1);
                top_x0 += tx;
                top_x1 += tx;
                */

                // find a best fit line for the bottom side
                best_start = 0;
                best_end = 0;
                hits = BestFitLine(bottom, ref best_start, ref best_end);
                float bottom_x0 = tx + best_start;
                float bottom_y0 = bottom[best_start];
                float bottom_x1 = tx + best_end;
                float bottom_y1 = bottom[best_end];

                /*
                BestFitLineAverage(bottom,
                                   ref bottom_x0, ref bottom_y0,
                                   ref bottom_x1, ref bottom_y1);
                bottom_x0 += tx;
                bottom_x1 += tx;
                 */

#if SHOW_TIMINGS
                timer_best_fit.Stop();
                if (timer_best_fit.time_elapsed_mS > 20)
                    Console.WriteLine("GetSquarePeriphery: best fit  " + timer_best_fit.time_elapsed_mS.ToString() );
#endif                
                
                // find the intersection between the left side and the top side
                float ix=0;
                float iy = 0;
                geometry.intersection(left_x1, left_y1, left_x0, left_y0,
                                      top_x1, top_y1, top_x0, top_y0,
                                      ref ix, ref iy);
                perim.Add(ix, iy);

                // find the intersection between the right side and the top side
                ix = 0;
                iy = 0;
                geometry.intersection(right_x1, right_y1, right_x0, right_y0,
                                      top_x0, top_y0, top_x1, top_y1,
                                      ref ix, ref iy);
                perim.Add(ix, iy);

                // find the intersection between the right side and the bottom side
                ix = 0;
                iy = 0;
                geometry.intersection(right_x1, right_y1, right_x0, right_y0,
                                      bottom_x0, bottom_y0, bottom_x1, bottom_y1,
                                      ref ix, ref iy);
                perim.Add(ix, iy);

                // find the intersection between the left side and the bottom side
                ix = 0;
                iy = 0;
                geometry.intersection(left_x1, left_y1, left_x0, left_y0,
                                      bottom_x0, bottom_y0, bottom_x1, bottom_y1,
                                      ref ix, ref iy);
                perim.Add(ix, iy);
                                
                // left and right
                List<int> left_edges = new List<int>();
                List<int> right_edges = new List<int>();
                for (int y = h; y >= 0; y--)
                {
                    if (left[y] != 0)
                    {
                        left_edges.Add(left[y]);
                        left_edges.Add(ty + y);
                    }
                    if (right[y] != 0)
                    {
                        right_edges.Add(right[y]);
                        right_edges.Add(ty + y);
                    }
                }
                
                // top and bottom
                List<int> top_edges = new List<int>();
                List<int> bottom_edges = new List<int>();
                for (int x = w; x >= 0; x--)
                {
                    if (top[x] != 0)
                    {
                        top_edges.Add(tx + x);
                        top_edges.Add(top[x]);
                    }
                    if (bottom[x] != 0)
                    {
                        bottom_edges.Add(tx + x);
                        bottom_edges.Add(bottom[x]);
                    }
                }
                
                float aspect_check = perim.getShortestSide() / perim.getLongestSide();
                if (aspect_check > 0.2f)
                {                
                    result.Add(left_edges);
                    result.Add(right_edges);
                    result.Add(top_edges);
                    result.Add(bottom_edges);
                }
                else perim = null;
            }

            // shrink the perimeter according to the erosion/dilation value
            if ((perim != null) && (erode_dilate != 0))
            {
                if (perim.x_points != null)
                {
                    float shrink_percent = (erode_dilate*2) / (perim.getPerimeterLength()/4.0f);
                    perim = perim.Scale(1.0f - shrink_percent);
                }
                else perim = null;
            }
            
            return(result);
        }