示例#1
0
 /// <summary>
 /// creates a circle shape
 /// </summary>
 /// <param name="centre_x">
 /// centre x coordinate of the circle <see cref="System.Single"/>
 /// </param>
 /// <param name="centre_y">
 /// centre y coordinate of the circle <see cref="System.Single"/>
 /// </param>
 /// <param name="radius">
 /// radius of teh circle <see cref="System.Single"/>
 /// </param>
 /// <param name="circumference_steps">
 /// number of steps to use when drawing the circle <see cref="System.Int32"/>
 /// </param>
 /// <returns>
 /// polygon representing a circle <see cref="polygon2D"/>
 /// </returns>
 public static polygon2D CreateCircle(float centre_x, float centre_y,
                                      float radius, int circumference_steps)
 {
     polygon2D circle = new polygon2D();
     for (int i = 0; i < circumference_steps; i++)
     {
         float angle = i * (float)Math.PI * 2 / circumference_steps;
         float x = centre_x + (radius * (float)Math.Sin(angle));
         float y = centre_y + (radius * (float)Math.Cos(angle));
         circle.Add(x, y);
     }
     return(circle);
 }
示例#2
0
        /// <summary>
        /// detects a square around the centre dot on the calibration pattern
        /// </summary>
        /// <param name="dots">detected dots</param>
        /// <param name="centredots">returned dots belonging to the centre square</param>
        /// <returns>centre square</returns>
        private static polygon2D GetCentreSquare(hypergraph dots,
                                                 ref List<calibrationDot> centredots)
        {
            centredots = new List<calibrationDot>();

            // find the centre dot
            calibrationDot centre = null;
            int i = 0;
            while ((i < dots.Nodes.Count) && (centre == null))
            {
                calibrationDot dot = (calibrationDot)dots.Nodes[i];
                if (dot.centre) centre = dot;
                i++;
            }

            // look for the four surrounding dots
            List<calibrationDot> centre_dots = new List<calibrationDot>();
            List<double> distances = new List<double>();
            i = 0;
            for (i = 0; i < dots.Nodes.Count; i++)
            {
                calibrationDot dot = (calibrationDot)dots.Nodes[i];
                if (!dot.centre)
                {
                    double dx = dot.x - centre.x;
                    double dy = dot.y - centre.y;
                    double dist = Math.Sqrt(dx * dx + dy * dy);
                    if (distances.Count == 4)
                    {
                        int index = -1;
                        double max_dist = 0;
                        for (int j = 0; j < 4; j++)
                        {
                            if (distances[j] > max_dist)
                            {
                                index = j;
                                max_dist = distances[j];
                            }
                        }
                        if (dist < max_dist)
                        {
                            distances[index] = dist;
                            centre_dots[index] = dot;
                        }
                    }
                    else
                    {
                        distances.Add(dist);
                        centre_dots.Add(dot);
                    }
                }
            }

            polygon2D centre_square = null;
            if (centre_dots.Count == 4)
            {
                centre_square = new polygon2D();
                for (i = 0; i < 4; i++)
                    centre_square.Add(0, 0);

                double xx = centre.x;
                double yy = centre.y;
                int index = 0;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x < xx) &&
                        (centre_dots[i].y < yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[0] = (float)xx;
                        centre_square.y_points[0] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x > xx) &&
                        (centre_dots[i].y < yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[1] = (float)xx;
                        centre_square.y_points[1] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x > xx) &&
                        (centre_dots[i].y > yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[2] = (float)xx;
                        centre_square.y_points[2] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x < xx) &&
                        (centre_dots[i].y > yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[3] = (float)xx;
                        centre_square.y_points[3] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);
            }
            return (centre_square);
        }
示例#3
0
        /// <summary>
        /// returns an ideally spaced grid over the actual detected spots
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private static grid2D OverlayIdealGrid(calibrationDot[,] grid,
                                               List<calibrationDot> corners,
                                               ref int grid_offset_x, ref int grid_offset_y,
                                               int random_seed)
        {
            grid2D overlay_grid = null;
            int grid_tx = -1;
            int grid_ty = -1;
            int grid_bx = -1;
            int grid_by = -1;

            int offset_x = 0;
            int offset_y = 0;

            bool found = false;
            int max_region_area = 0;

            // try searching horizontally and vertically
            // then pick the result with the greatest area
            for (int test_orientation = 0; test_orientation < 2; test_orientation++)
            {
                bool temp_found = false;

                int temp_grid_tx = -1;
                int temp_grid_ty = -1;
                int temp_grid_bx = -1;
                int temp_grid_by = -1;

                int temp_offset_x = 0;
                int temp_offset_y = 0;

                switch (test_orientation)
                {
                    case 0:
                        {
                            while ((temp_offset_y < 5) && (!temp_found))
                            {
                                temp_offset_x = 0;
                                while ((temp_offset_x < 3) && (!temp_found))
                                {
                                    temp_grid_tx = temp_offset_x;
                                    temp_grid_ty = temp_offset_y;
                                    temp_grid_bx = grid.GetLength(0) - 1 - temp_offset_x;
                                    temp_grid_by = grid.GetLength(1) - 1 - temp_offset_y;

                                    if ((temp_grid_bx < grid.GetLength(0)) &&
                                        (temp_grid_tx < grid.GetLength(0)) &&
                                        (temp_grid_by < grid.GetLength(1)) &&
                                        (temp_grid_ty < grid.GetLength(1)) &&
                                        (temp_grid_ty >= 0) &&
                                        (temp_grid_by >= 0) &&
                                        (temp_grid_tx >= 0) &&
                                        (temp_grid_bx >= 0))
                                    {
                                        if ((grid[temp_grid_tx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_by] != null) &&
                                            (grid[temp_grid_tx, temp_grid_by] != null))
                                        {
                                            temp_found = true;
                                        }
                                    }

                                    temp_offset_x++;
                                }
                                temp_offset_y++;
                            }
                            break;
                        }
                    case 1:
                        {
                            while ((temp_offset_x < 3) && (!temp_found))
                            {
                                temp_offset_y = 0;
                                while ((temp_offset_y < 5) && (!temp_found))
                                {
                                    temp_grid_tx = temp_offset_x;
                                    temp_grid_ty = temp_offset_y;
                                    temp_grid_bx = grid.GetLength(0) - 1 - temp_offset_x;
                                    temp_grid_by = grid.GetLength(1) - 1 - temp_offset_y;

                                    if ((temp_grid_bx < grid.GetLength(0)) &&
                                        (temp_grid_tx < grid.GetLength(0)) &&
                                        (temp_grid_by < grid.GetLength(1)) &&
                                        (temp_grid_ty < grid.GetLength(1)) &&
                                        (temp_grid_ty >= 0) &&
                                        (temp_grid_by >= 0) &&
                                        (temp_grid_tx >= 0) &&
                                        (temp_grid_bx >= 0))
                                    {
                                        if ((grid[temp_grid_tx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_by] != null) &&
                                            (grid[temp_grid_tx, temp_grid_by] != null))
                                        {
                                            temp_found = true;
                                        }
                                    }

                                    temp_offset_y++;
                                }
                                temp_offset_x++;
                            }
                            break;
                        }
                }

                temp_offset_y = temp_grid_ty - 1;
                while (temp_offset_y >= 0)
                {
                    if ((temp_offset_y < grid.GetLength(1)) &&
                        (temp_offset_y >= 0))
                    {
                        if ((grid[temp_grid_tx, temp_offset_y] != null) &&
                            (grid[temp_grid_bx, temp_offset_y] != null))
                        {
                            temp_grid_ty = temp_offset_y;
                            temp_offset_y--;
                        }
                        else break;
                    }
                    else break;
                }

                temp_offset_y = temp_grid_by + 1;
                while (temp_offset_y < grid.GetLength(1))
                {
                    if ((temp_offset_y < grid.GetLength(1)) &&
                        (temp_offset_y >= 0))
                    {
                        if ((grid[temp_grid_tx, temp_offset_y] != null) &&
                            (grid[temp_grid_bx, temp_offset_y] != null))
                        {
                            temp_grid_by = temp_offset_y;
                            temp_offset_y++;
                        }
                        else break;
                    }
                    else break;
                }

                if (temp_found)
                {
                    int region_area = (temp_grid_bx - temp_grid_tx) * (temp_grid_by - temp_grid_ty);
                    if (region_area > max_region_area)
                    {
                        max_region_area = region_area;
                        found = true;

                        grid_tx = temp_grid_tx;
                        grid_ty = temp_grid_ty;
                        grid_bx = temp_grid_bx;
                        grid_by = temp_grid_by;

                        offset_x = temp_offset_x;
                        offset_y = temp_offset_y;
                    }
                }
            }

            if (found)
            {
                // record the positions of the corners
                corners.Add(grid[grid_tx, grid_ty]);
                corners.Add(grid[grid_bx, grid_ty]);
                corners.Add(grid[grid_bx, grid_by]);
                corners.Add(grid[grid_tx, grid_by]);

                double dx, dy;

                double x0 = grid[grid_tx, grid_ty].x;
                double y0 = grid[grid_tx, grid_ty].y;
                double x1 = grid[grid_bx, grid_ty].x;
                double y1 = grid[grid_bx, grid_ty].y;
                double x2 = grid[grid_tx, grid_by].x;
                double y2 = grid[grid_tx, grid_by].y;
                double x3 = grid[grid_bx, grid_by].x;
                double y3 = grid[grid_bx, grid_by].y;

                polygon2D perimeter = new polygon2D();
                perimeter.Add((float)x0, (float)y0);
                perimeter.Add((float)x1, (float)y1);
                perimeter.Add((float)x3, (float)y3);
                perimeter.Add((float)x2, (float)y2);

                int grid_width = grid_bx - grid_tx;
                int grid_height = grid_by - grid_ty;

                int min_hits = 0;
                double min_dx = 0, min_dy = 0;

                // try various perimeter sizes
                double min_dist = double.MaxValue;
                int max_perim_size_tries = 100;
                polygon2D best_perimeter = perimeter;
                MersenneTwister rnd = new MersenneTwister(random_seed);
                for (int perim_size = 0; perim_size < max_perim_size_tries; perim_size++)
                {
                    // try a small range of translations
                    for (int nudge_x = -10; nudge_x <= 10; nudge_x++)
                    {
                        for (int nudge_y = -5; nudge_y <= 5; nudge_y++)
                        {
                            // create a perimeter at this scale and translation
                            polygon2D temp_perimeter = perimeter.Scale(1.0f + (perim_size * 0.1f / max_perim_size_tries));
                            temp_perimeter = temp_perimeter.ScaleSideLength(0, 0.95f + ((float)rnd.NextDouble() * 0.1f));
                            temp_perimeter = temp_perimeter.ScaleSideLength(2, 0.95f + ((float)rnd.NextDouble() * 0.1f));
                            for (int i = 0; i < temp_perimeter.x_points.Count; i++)
                            {
                                temp_perimeter.x_points[i] += nudge_x;
                                temp_perimeter.y_points[i] += nudge_y;
                            }

                            // create a grid based upon the perimeter
                            grid2D temp_overlay_grid = new grid2D(grid_width, grid_height, temp_perimeter, 0, false);

                            // how closely does the grid fit the actual observations ?
                            double temp_min_dist = min_dist;
                            BestFit(grid_tx, grid_ty, grid,
                                    temp_overlay_grid, ref min_dist,
                                    ref min_dx, ref min_dy, ref min_hits,
                                    ref grid_offset_x, ref grid_offset_y);

                            // record the closest fit
                            if (temp_min_dist < min_dist)
                            {
                                best_perimeter = temp_perimeter;
                                overlay_grid = temp_overlay_grid;
                            }
                        }
                    }
                }

                if (min_hits > 0)
                {
                    dx = min_dx;
                    dy = min_dy;

                    Console.WriteLine("dx: " + dx.ToString());
                    Console.WriteLine("dy: " + dy.ToString());

                    x0 += dx;
                    y0 += dy;
                    x1 += dx;
                    y1 += dy;
                    x2 += dx;
                    y2 += dy;
                    x3 += dx;
                    y3 += dy;

                    perimeter = new polygon2D();
                    perimeter.Add((float)x0, (float)y0);
                    perimeter.Add((float)x1, (float)y1);
                    perimeter.Add((float)x3, (float)y3);
                    perimeter.Add((float)x2, (float)y2);
                    overlay_grid = new grid2D(grid_width, grid_height, perimeter, 0, false);
                }
            }

            return (overlay_grid);
        }
示例#4
0
        /// <summary>
        /// finds the interception points between grid lines
        /// </summary>
        private void poltLineIntercepts()
        {
            if (line != null)
            {
                // create an array to store the line intercepts
                int intercepts_x = line[0].Count/4;
                int intercepts_y = line[1].Count/4;
                line_intercepts = new float[intercepts_x, intercepts_y, 2];

                for (int i = 0; i < line[0].Count; i += 4)
                {
                    // get the first line coordinates
                    ArrayList lines0 = line[0];
                    float x0 = (float)lines0[i];
                    float y0 = (float)lines0[i + 1];
                    float x1 = (float)lines0[i + 2];
                    float y1 = (float)lines0[i + 3];

                    for (int j = 0; j < line[1].Count; j += 4)
                    {
                        // get the second line coordinates
                        ArrayList lines1 = line[1];
                        float x2 = (float)lines1[j];
                        float y2 = (float)lines1[j + 1];
                        float x3 = (float)lines1[j + 2];
                        float y3 = (float)lines1[j + 3];

                        // find the interception between the two lines
                        float ix = 0, iy = 0;
                        geometry.intersection(x0, y0, x1, y1, x2, y2, x3, y3, ref ix, ref iy);

                        // store the intercept position
                        line_intercepts[i/4, j/4, 0] = ix;
                        line_intercepts[i/4, j/4, 1] = iy;
                    }
                }

                // update the perimeter
                border_perimeter = new polygon2D();
                float xx = line_intercepts[0, 0, 0];
                float yy = line_intercepts[0, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, 0, 0];
                yy = line_intercepts[intercepts_x - 1, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, intercepts_y - 1, 0];
                yy = line_intercepts[intercepts_x - 1, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[0, intercepts_y - 1, 0];
                yy = line_intercepts[0, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
            }
        }
示例#5
0
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="dimension_x">number of cells across the grid</param>
        /// <param name="dimension_y">number of cells down the grid</param>
        /// <param name="cx">centre of the grid</param>
        /// <param name="cy">centre of the grid</param>
        /// <param name="orientation">orientation of the grid in radians</param>
        /// <param name="average_spacing_x">grid spacing in the x axis</param>
        /// <param name="average_spacing_y">grid spacing in the y axis</param>
        /// <param name="phase_offset_x">phase offset in the x axis</param>
        /// <param name="phase_offset_y">phase offset in the y axis</param>
        /// <param name="border_cells">number of cells to use as a border around the grid</param>
        public grid2D(int dimension_x, int dimension_y,
                      float cx, float cy,
                      float orientation,
                      float average_spacing_x, float average_spacing_y,
                      float phase_offset_x, float phase_offset_y,
                      int border_cells,
                      bool orientation_simple)
        {
            // create a perimeter region
            polygon2D perimeter = new polygon2D();

            float length_x = average_spacing_x * dimension_x;
            float length_y = average_spacing_y * dimension_y;
            float half_length_x = length_x / 2;
            float half_length_y = length_y / 2;

            // adjust for phase
            cx += (average_spacing_x * phase_offset_x / (2 * (float)Math.PI)) * (float)Math.Sin(orientation);
            cy -= (average_spacing_y * phase_offset_y / (2 * (float)Math.PI)) * (float)Math.Cos(orientation);

            // find the mid point of the top line
            float px1 = cx + (half_length_y * (float)Math.Sin(orientation));
            float py1 = cy + (half_length_y * (float)Math.Cos(orientation));

            // find the top left vertex
            float x0 = px1 + (half_length_x * (float)Math.Sin(orientation - (float)(Math.PI / 2)));
            float y0 = py1 + (half_length_x * (float)Math.Cos(orientation - (float)(Math.PI / 2)));

            // find the top right vertex
            float x1 = px1 + (half_length_x * (float)Math.Sin(orientation + (float)(Math.PI / 2)));
            float y1 = py1 + (half_length_x * (float)Math.Cos(orientation + (float)(Math.PI / 2)));

            // find the bottom vertices by mirroring around the centre
            float x2 = cx + (cx - x0);
            float y2 = cy + (cy - y0);
            float x3 = cx - (x1 - cx);
            float y3 = cy - (y1 - cy);

            // update polygon with the perimeter vertices
            perimeter.Add(x0, y0);
            perimeter.Add(x1, y1);
            perimeter.Add(x2, y2);
            perimeter.Add(x3, y3);

            int dim_x = dimension_x;
            int dim_y = dimension_y;
            float first_side_length = perimeter.getSideLength(0);
            float second_side_length = perimeter.getSideLength(1);
            if (((dimension_x > dimension_y + 2) &&
                 (second_side_length > first_side_length)) ||
                 ((dimension_y > dimension_x + 2) &&
                 (first_side_length > second_side_length)))
            {
                dim_x = dimension_y;
                dim_y = dimension_x;
            }

            // initialise using this perimeter
            init(dim_x, dim_y, perimeter, border_cells, orientation_simple);
        }
示例#6
0
        /// <summary>
        /// simple function used to test grid creation
        /// </summary>
        /// <param name="filename">filename of the test image to be created</param>
        public static void Test(string filename)
        {
            int image_width = 640;
            int image_height = 480;
            int dimension_x = 10;
            int dimension_y = 10;

            Bitmap bmp = new Bitmap(image_width, image_height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            byte[] img = new byte[image_width * image_height * 3];

            polygon2D test_poly;
            grid2D grid;

            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 40 / 100);
            test_poly.Add(image_width * 15 / 100, image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            int half_width = image_width / 2;
            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 35 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 40 / 100), image_height * 40 / 100);
            test_poly.Add(half_width + (image_width * 15 / 100), image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);
            
            int half_height = image_height / 2;
            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 24 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 20 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 40 / 100));
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), half_height + (image_height * 24 / 100));
            test_poly.Add(half_width + (image_width * 35 / 100), half_height + (image_height * 20 / 100));
            test_poly.Add(half_width + (image_width * 40 / 100), half_height + (image_height * 40 / 100));
            test_poly.Add(half_width + (image_width * 15 / 100), half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);            

            BitmapArrayConversions.updatebitmap_unsafe(img, bmp);
            bmp.Save(filename);
        }
示例#7
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);
        }
示例#8
0
        /// <summary>
        /// returns a copy of the polygon
        /// </summary>
        /// <returns></returns>
        public polygon2D Copy()
        {
            polygon2D new_poly = new polygon2D();
            new_poly.name = name;
            new_poly.type = type;
            new_poly.occupied = occupied;

            if (x_points != null)
            {
                for (int i = 0; i < x_points.Count; i++)
                {
                    float x = x_points[i];
                    float y = y_points[i];
                    new_poly.Add(x, y);
                }
            }
            return (new_poly);
        }
示例#9
0
        /// <summary>
        /// scale the polygon to a new image size
        /// </summary>
        /// <param name="original_image_width"></param>
        /// <param name="original_image_height"></param>
        /// <param name="new_image_width"></param>
        /// <param name="new_image_height"></param>
        /// <returns></returns>
        public polygon2D Scale(int original_image_width, int original_image_height,
                               int new_image_width, int new_image_height)
        {
            polygon2D rescaled = new polygon2D();

            for (int i = 0; i < x_points.Count; i++)
            {
                float x = x_points[i] * new_image_width / original_image_width;
                float y = y_points[i] * new_image_height / original_image_height;
                rescaled.Add(x, y);
            }
            return (rescaled);
        }
示例#10
0
        /// <summary>
        /// return a scaled version of the polygon
        /// </summary>
        /// <param name="factor"></param>
        /// <returns></returns>
        public polygon2D Scale(float factor)
        {
            polygon2D rescaled = new polygon2D();

            float centre_x = 0, centre_y = 0;
            getCentreOfGravity(ref centre_x, ref centre_y);

            for (int i = 0; i < x_points.Count; i++)
            {
                float dx = x_points[i] - centre_x;
                float dy = y_points[i] - centre_y;
                float x = (float)(centre_x + (dx * factor));
                float y = (float)(centre_y + (dy * factor));
                rescaled.Add(x, y);
            }
            return (rescaled);
        }
示例#11
0
        /// <summary>
        /// snaps the vertices of the polygon to a grid having the given spacing
        /// </summary>
        /// <param name="grid_spacing">spacing of the grid</param>
        /// <returns>fitted polygon</returns>
        public polygon2D SnapToGrid(float grid_spacing)
        {
            polygon2D result = new polygon2D();
            if (x_points != null)
            {
                for (int i = 0; i < x_points.Count; i++)
                {
                    float x = x_points[i] / grid_spacing;
                    x = (float)Math.Round(x) * grid_spacing;
                    float y = y_points[i] / grid_spacing;
                    y = (float)Math.Round(y) * grid_spacing;
                    result.Add(x, y);
                }
            }
            return (result);
示例#12
0
 /// <summary>
 /// returns a copy of this polygon with each vetex randomly perturbed
 /// </summary>
 /// <param name="max_displacement">
 /// maximum perturbation <see cref="System.Single"/>
 /// </param>
 /// <param name="rnd">
 /// random number generator <see cref="Random"/>
 /// </param>
 /// <returns>
 /// polygon object <see cref="polygon2D"/>
 /// </returns>
 public polygon2D Jiggle(float max_displacement, Random rnd)
 {
     polygon2D result = null;
     
     if (x_points != null)
     {
         result = new polygon2D();
         float max = max_displacement*2;
         for (int i = 0; i < x_points.Count; i++)
         {
             float jiggled_x = x_points[i] + ((float)rnd.NextDouble() * max) - max_displacement;
             float jiggled_y = x_points[i] + ((float)rnd.NextDouble() * max) - max_displacement;
             result.Add(jiggled_x, jiggled_y);
         }
     }
     return(result);
 }