Exemple #1
0
        /// <summary>
        /// Check if a shape specified by the set of points fits a convex polygon
        /// specified by the set of corners.
        /// </summary>
        ///
        /// <param name="edgePoints">Shape's points to check.</param>
        /// <param name="corners">Corners of convex polygon to check fitting into.</param>
        ///
        /// <returns>Returns <see langword="true"/> if the specified shape fits
        /// the specified convex polygon or <see langword="false"/> otherwise.</returns>
        ///
        /// <remarks><para>The method checks if the set of specified points form the same shape
        /// as the set of provided corners.</para></remarks>
        ///
        public bool CheckIfPointsFitShape(List <IntPoint> edgePoints, List <IntPoint> corners)
        {
            int cornersCount = corners.Count;

            // lines coefficients (for representation as y(x)=k*x+b)
            double[] k      = new double[cornersCount];
            double[] b      = new double[cornersCount];
            double[] div    = new double[cornersCount]; // precalculated divisor
            bool[]   isVert = new bool[cornersCount];

            for (int i = 0; i < cornersCount; i++)
            {
                IntPoint currentPoint = corners[i];
                IntPoint nextPoint    = (i + 1 == cornersCount) ? corners[0] : corners[i + 1];

                if (!(isVert[i] = nextPoint.X == currentPoint.X))
                {
                    k[i]   = (double)(nextPoint.Y - currentPoint.Y) / (nextPoint.X - currentPoint.X);
                    b[i]   = currentPoint.Y - k[i] * currentPoint.X;
                    div[i] = Math.Sqrt(k[i] * k[i] + 1);
                }
            }

            // calculate distances between edge points and polygon sides
            float meanDistance = 0;

            for (int i = 0, n = edgePoints.Count; i < n; i++)
            {
                float minDistance = float.MaxValue;

                for (int j = 0; j < cornersCount; j++)
                {
                    float distance = 0;

                    if (!isVert[j])
                    {
                        distance = (float)Math.Abs((k[j] * edgePoints[i].X + b[j] - edgePoints[i].Y) / div[j]);
                    }
                    else
                    {
                        distance = Math.Abs(edgePoints[i].X - corners[j].X);
                    }

                    if (distance < minDistance)
                    {
                        minDistance = distance;
                    }
                }

                meanDistance += minDistance;
            }
            meanDistance /= edgePoints.Count;

            // get bounding rectangle of the corners list
            IntPoint minXY, maxXY;

            PointsCloud.GetBoundingRectangle(corners, out minXY, out maxXY);
            IntPoint rectSize = maxXY - minXY;

            float maxDitance = Math.Max(minAcceptableDistortion,
                                        ((float)rectSize.X + rectSize.Y) / 2 * relativeDistortionLimit);

            return(meanDistance <= maxDitance);
        }
Exemple #2
0
 // Get optimized quadrilateral area
 private List <IntPoint> GetShapeCorners(List <IntPoint> edgePoints)
 {
     return(shapeOptimizer.OptimizeShape(PointsCloud.FindQuadrilateralCorners(edgePoints)));
 }
Exemple #3
0
        /// <summary>
        /// Check sub type of a convex polygon.
        /// </summary>
        ///
        /// <param name="corners">Corners of the convex polygon to check.</param>
        ///
        /// <returns>Return detected sub type of the specified shape.</returns>
        ///
        /// <remarks><para>The method check corners of a convex polygon detecting
        /// its subtype. Polygon's corners are usually retrieved using <see cref="IsConvexPolygon"/>
        /// method, but can be any list of 3-4 points (only sub types of triangles and
        /// quadrilateral are checked).</para>
        ///
        /// <para>See <see cref="AngleError"/> and <see cref="LengthError"/> properties,
        /// which set acceptable errors for polygon sub type checking.</para>
        /// </remarks>
        ///
        public PolygonSubType CheckPolygonSubType(List <IntPoint> corners)
        {
            PolygonSubType subType = PolygonSubType.Unknown;

            // get bounding rectangle of the points list
            IntPoint minXY, maxXY;

            PointsCloud.GetBoundingRectangle(corners, out minXY, out maxXY);
            // get cloud's size
            IntPoint cloudSize = maxXY - minXY;

            float maxLengthDiff = lengthError * (cloudSize.X + cloudSize.Y) / 2;

            if (corners.Count == 3)
            {
                // get angles of the triangle
                double angle1 = GeometryTools.GetAngleBetweenVectors(corners[0], corners[1], corners[2]);
                double angle2 = GeometryTools.GetAngleBetweenVectors(corners[1], corners[2], corners[0]);
                double angle3 = GeometryTools.GetAngleBetweenVectors(corners[2], corners[0], corners[1]);

                // check for equilateral triangle
                if ((Math.Abs(angle1 - 60) <= angleError) &&
                    (Math.Abs(angle2 - 60) <= angleError) &&
                    (Math.Abs(angle3 - 60) <= angleError))
                {
                    subType = PolygonSubType.EquilateralTriangle;
                }
                else
                {
                    // check for isosceles triangle
                    if ((Math.Abs(angle1 - angle2) <= angleError) ||
                        (Math.Abs(angle2 - angle3) <= angleError) ||
                        (Math.Abs(angle3 - angle1) <= angleError))
                    {
                        subType = PolygonSubType.IsoscelesTriangle;
                    }

                    // check for rectangled triangle
                    if ((Math.Abs(angle1 - 90) <= angleError) ||
                        (Math.Abs(angle2 - 90) <= angleError) ||
                        (Math.Abs(angle3 - 90) <= angleError))
                    {
                        subType = (subType == PolygonSubType.IsoscelesTriangle) ?
                                  PolygonSubType.RectangledIsoscelesTriangle : PolygonSubType.RectangledTriangle;
                    }
                }
            }
            else if (corners.Count == 4)
            {
                // get angles between 2 pairs of opposite sides
                double angleBetween1stPair = GeometryTools.GetAngleBetweenLines(corners[0], corners[1], corners[2], corners[3]);
                double angleBetween2ndPair = GeometryTools.GetAngleBetweenLines(corners[1], corners[2], corners[3], corners[0]);

                // check 1st pair for parallelism
                if (angleBetween1stPair <= angleError)
                {
                    subType = PolygonSubType.Trapezoid;

                    // check 2nd pair for parallelism
                    if (angleBetween2ndPair <= angleError)
                    {
                        subType = PolygonSubType.Parallelogram;

                        // check angle between adjacent sides
                        if (Math.Abs(GeometryTools.GetAngleBetweenVectors(corners[1], corners[0], corners[2]) - 90) <= angleError)
                        {
                            subType = PolygonSubType.Rectangle;
                        }

                        // get length of 2 adjacent sides
                        float side1Length = (float)corners[0].DistanceTo(corners[1]);
                        float side2Length = (float)corners[0].DistanceTo(corners[3]);

                        if (Math.Abs(side1Length - side2Length) <= maxLengthDiff)
                        {
                            subType = (subType == PolygonSubType.Parallelogram) ?
                                      PolygonSubType.Rhombus : PolygonSubType.Square;
                        }
                    }
                }
                else
                {
                    // check 2nd pair for parallelism - last chence to detect trapezoid
                    if (angleBetween2ndPair <= angleError)
                    {
                        subType = PolygonSubType.Trapezoid;
                    }
                }
            }

            return(subType);
        }