Ejemplo n.º 1
0
        // From Eric Jordan's convex decomposition library

        /// <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.
        /// </summary>
        /// <returns></returns>
        public bool CheckPolygon()
        {
            int error = -1;

            if (Count < 3 || Count > Settings.MaxPolygonVertices)
            {
                error = 0;
            }
            if (!IsConvex())
            {
                error = 1;
            }
            if (!IsSimple())
            {
                error = 2;
            }
            if (GetArea() < Settings.Epsilon)
            {
                error = 3;
            }

            //Compute normals
            Vector2[] normals  = new Vector2[Count];
            Vertices  vertices = new Vertices(Count);

            for (int i = 0; i < Count; ++i)
            {
                vertices.Add(new Vector2(this[i].X, this[i].Y));
                int     i1   = i;
                int     i2   = i + 1 < Count ? i + 1 : 0;
                Vector2 edge = new Vector2(this[i2].X - this[i1].X, this[i2].Y - this[i1].Y);
                normals[i] = MathUtils.Cross(edge, 1.0f);
                normals[i].Normalize();
            }

            //Required side checks
            for (int i = 0; i < Count; ++i)
            {
                int iminus = (i == 0) ? Count - 1 : i - 1;

                //Parallel sides check
                float cross = MathUtils.Cross(normals[iminus], normals[i]);
                cross = MathUtils.Clamp(cross, -1.0f, 1.0f);
                float angle = ( float )Math.Asin(cross);
                if (angle <= Settings.AngularSlop)
                {
                    error = 4;
                    break;
                }

                //Too skinny check
                for (int j = 0; j < Count; ++j)
                {
                    if (j == i || j == (i + 1) % Count)
                    {
                        continue;
                    }
                    float s = Vector2.Dot(normals[i], vertices[j] - vertices[i]);
                    if (s >= -Settings.LinearSlop)
                    {
                        error = 5;
                    }
                }


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

                Vector2 d = new Vector2();
                d.X = Vector2.Dot(n1, v);                   // - toiSlop;
                d.Y = Vector2.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 = 6;
                }
            }

            if (error != -1)
            {
                Debug.WriteLine("Found invalid polygon, ");
                switch (error)
                {
                case 0:
                    Debug.WriteLine(string.Format("must have between 3 and {0} vertices.\n",
                                                  Settings.MaxPolygonVertices));
                    break;

                case 1:
                    Debug.WriteLine("must be convex.\n");
                    break;

                case 2:
                    Debug.WriteLine("must be simple (cannot intersect itself).\n");
                    break;

                case 3:
                    Debug.WriteLine("area is too small.\n");
                    break;

                case 4:
                    Debug.WriteLine("sides are too close to parallel.\n");
                    break;

                case 5:
                    Debug.WriteLine("polygon is too thin.\n");
                    break;

                case 6:
                    Debug.WriteLine("core shape generation would move edge past centroid (too thin).\n");
                    break;

                default:
                    Debug.WriteLine("don't know why.\n");
                    break;
                }
            }
            return(error != -1);
        }
Ejemplo n.º 2
0
        // From Eric Jordan's convex decomposition library

        /// <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.
        /// </summary>
        /// <returns></returns>
        public bool CheckPolygon(out int error, out string errorMessage)
        {
            error        = -1;
            errorMessage = null;

            if (Count < 3 || Count > Settings.MaxPolygonVertices)
            {
                error = 0;
            }
            if (!IsConvex())
            {
                error = 1;
            }
            if (!IsSimple())
            {
                error = 2;
            }
            if (GetArea() < Settings.Epsilon)
            {
                error = 3;
            }

            //Compute normals
            Vector2[] normals  = new Vector2[Count];
            Vertices  vertices = new Vertices(Count);

            for (int i = 0; i < Count; ++i)
            {
                vertices.Add(new Vector2(this[i].x, this[i].y));
                int     i1   = i;
                int     i2   = i + 1 < Count ? i + 1 : 0;
                Vector2 edge = new Vector2(this[i2].x - this[i1].x, this[i2].y - this[i1].y);
                normals[i] = MathUtils.Cross(edge, 1.0f);
                normals[i].Normalize();
            }

            //Required side checks
            for (int i = 0; i < Count; ++i)
            {
                int iminus = (i == 0) ? Count - 1 : i - 1;

                //Parallel sides check
                float cross = MathUtils.Cross(normals[iminus], normals[i]);
                cross = MathUtils.Clamp(cross, -1.0f, 1.0f);
                float angle = Mathf.Asin(cross);
                if (angle <= Settings.AngularSlop)
                {
                    error = 4;
                    break;
                }

                //Too skinny check
                for (int j = 0; j < Count; ++j)
                {
                    if (j == i || j == (i + 1) % Count)
                    {
                        continue;
                    }
                    float s = Vector2.Dot(normals[i], vertices[j] - vertices[i]);
                    if (s >= -Settings.LinearSlop)
                    {
                        error = 5;
                    }
                }


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

                Vector2 d = new Vector2();
                d.x = Vector2.Dot(n1, v); // - toiSlop;
                d.y = Vector2.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 = 6;
                }
            }

            if (error != -1)
            {
                switch (error)
                {
                case 0:
                    errorMessage = string.Format("Polygon error: must have between 3 and {0} vertices.",
                                                 Settings.MaxPolygonVertices);
                    break;

                case 1:
                    errorMessage = "Polygon error: must be convex.";
                    break;

                case 2:
                    errorMessage = "Polygon error: must be simple (cannot intersect itself).";
                    break;

                case 3:
                    errorMessage = "Polygon error: area is too small.";
                    break;

                case 4:
                    errorMessage = "Polygon error: sides are too close to parallel.";
                    break;

                case 5:
                    errorMessage = "Polygon error: polygon is too thin.";
                    break;

                case 6:
                    errorMessage = "Polygon error: core shape generation would move edge past centroid (too thin).";
                    break;

                default:
                    errorMessage = "Polygon error: error " + error.ToString();
                    break;
                }
            }
            return(error != -1);
        }