Exemple #1
0
        /// <summary>
        /// Checks if polygon is valid for use in Box2d engine.
        /// Last ditch effort to ensure no invalid polygons are
        /// added to world geometry.
        ///
        /// Performs a full check, for simplicity, convexity,
        /// orientation, minimum angle, and volume.  This won't
        /// be very efficient, and a lot of it is redundant when
        /// other tools in this section are used.
        ///
        /// From Eric Jordan's convex decomposition library
        /// </summary>
        /// <param name="printErrors"></param>
        /// <returns></returns>
        public PolygonError CheckPolygon()
        {
            PolygonError error = PolygonError.None;

            if (Count < 3 || Count > Point2DList.kMaxPolygonVertices)
            {
                error |= PolygonError.NotEnoughVertices;
                // no other tests will be valid at this point, so just return
                return(error);
            }
            if (IsDegenerate())
            {
                error |= PolygonError.Degenerate;
            }
            //bool bIsConvex = IsConvex();
            //if (!IsConvex())
            //{
            //    error |= PolygonError.NotConvex;
            //}
            if (!IsSimple())
            {
                error |= PolygonError.NotSimple;
            }
            if (GetArea() < MathUtil.EPSILON)
            {
                error |= PolygonError.AreaTooSmall;
            }

            // the following tests don't make sense if the polygon is not simple
            if ((error & PolygonError.NotSimple) != PolygonError.NotSimple)
            {
                bool             bReversed            = false;
                WindingOrderType expectedWindingOrder = WindingOrderType.CCW;
                WindingOrderType reverseWindingOrder  = WindingOrderType.CW;
                if (WindingOrder == reverseWindingOrder)
                {
                    WindingOrder = expectedWindingOrder;
                    bReversed    = true;
                }

                //Compute normals
                Point2D[]   normals  = new Point2D[Count];
                Point2DList vertices = new Point2DList(Count);
                for (int i = 0; i < Count; ++i)
                {
                    vertices.Add(new Point2D(this[i].X, this[i].Y));
                    int     i1   = i;
                    int     i2   = NextIndex(i);
                    Point2D edge = new Point2D(this[i2].X - this[i1].X, this[i2].Y - this[i1].Y);
                    normals[i] = Point2D.Perpendicular(edge, 1.0);
                    normals[i].Normalize();
                }

                //Required side checks
                for (int i = 0; i < Count; ++i)
                {
                    int iminus = PreviousIndex(i);

                    //Parallel sides check
                    double cross = Point2D.Cross(normals[iminus], normals[i]);
                    cross = MathUtil.Clamp(cross, -1.0f, 1.0f);
                    float angle = (float)Math.Asin(cross);
                    if (Math.Abs(angle) <= Point2DList.kAngularSlop)
                    {
                        error |= PolygonError.SidesTooCloseToParallel;
                        break;
                    }

                    // For some reason, the following checks do not seem to work
                    // correctly in all cases - they return false positives.
                    //    //Too skinny check - only valid for convex polygons
                    //    if (bIsConvex)
                    //    {
                    //        for (int j = 0; j < Count; ++j)
                    //        {
                    //            if (j == i || j == NextIndex(i))
                    //            {
                    //                continue;
                    //            }
                    //            Point2D testVector = vertices[j] - vertices[i];
                    //            testVector.Normalize();
                    //            double s = Point2D.Dot(testVector, normals[i]);
                    //            if (s >= -Point2DList.kLinearSlop)
                    //            {
                    //                error |= PolygonError.TooThin;
                    //            }
                    //        }

                    //        Point2D centroid = vertices.GetCentroid();
                    //        Point2D n1 = normals[iminus];
                    //        Point2D n2 = normals[i];
                    //        Point2D v = vertices[i] - centroid;

                    //        Point2D d = new Point2D();
                    //        d.X = Point2D.Dot(n1, v); // - toiSlop;
                    //        d.Y = Point2D.Dot(n2, v); // - toiSlop;

                    //        // Shifting the edge inward by toiSlop should
                    //        // not cause the plane to pass the centroid.
                    //        if ((d.X < 0.0f) || (d.Y < 0.0f))
                    //        {
                    //            error |= PolygonError.TooThin;
                    //        }
                    //    }
                }

                if (bReversed)
                {
                    WindingOrder = reverseWindingOrder;
                }
            }

            //if (error != PolygonError.None)
            //{
            //    Console.WriteLine("Found invalid polygon: {0} {1}\n", Point2DList.GetErrorString(error), this.ToString());
            //}

            return(error);
        }