Ejemplo n.º 1
0
        /// <summary>
        /// Checks if this triangle contains the given point. This is
        /// never strict.
        /// </summary>
        /// <param name="tri">The triangle</param>
        /// <param name="pos">The position of the triangle</param>
        /// <param name="pt">The point to check</param>
        /// <returns>true if this triangle contains the point or the point
        /// is along an edge of this polygon</returns>
        public static bool Contains(Triangle2 tri, Vector2 pos, Vector2 pt)
        {
            Vector2 relPt = pt - pos - tri.Vertices[0];
            float   r     = tri.InvContainsBasis[0] * relPt.X + tri.InvContainsBasis[1] * relPt.Y;

            if (r < -Math2.DEFAULT_EPSILON)
            {
                return(false);
            }

            float t = tri.InvContainsBasis[2] * relPt.X + tri.InvContainsBasis[3] * relPt.Y;

            if (t < -Math2.DEFAULT_EPSILON)
            {
                return(false);
            }

            return((r + t) < 1 + Math2.DEFAULT_EPSILON);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Determines if the specified polygon at the specified position and rotation contains the specified point
        /// </summary>
        /// <param name="poly">The polygon</param>
        /// <param name="pos">Origin of the polygon</param>
        /// <param name="rot">Rotation of the polygon</param>
        /// <param name="point">Point to check</param>
        /// <param name="strict">True if the edges do not count as inside</param>
        /// <returns>If the polygon at pos with rotation rot about its center contains point</returns>
        public static bool Contains(Polygon2 poly, Vector2 pos, Rotation2 rot, Vector2 point, bool strict)
        {
            // The point is contained in the polygon iff it is contained in one of the triangles
            // which partition this polygon. Due to how we constructed the triangles, it will
            // be on the edge of the polygon if its on the first 2 edges of the triangle.

            for (int i = 0, len = poly.TrianglePartition.Length; i < len; i++)
            {
                var tri = poly.TrianglePartition[i];

                if (Triangle2.Contains(tri, pos, point))
                {
                    if (strict && (Line2.Contains(tri.Edges[0], pos, point) || Line2.Contains(tri.Edges[1], pos, point)))
                    {
                        return(false);
                    }
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Initializes a polygon with the specified vertices
        /// </summary>
        /// <param name="vertices">Vertices</param>
        /// <exception cref="ArgumentNullException">If vertices is null</exception>
        public Polygon2(Vector2[] vertices)
        {
            Vertices = vertices ?? throw new ArgumentNullException(nameof(vertices));

            Normals = new List <Vector2>();
            Vector2 tmp;

            for (int i = 1; i < vertices.Length; i++)
            {
                tmp = Math2.MakeStandardNormal(Vector2.Normalize(Math2.Perpendicular(vertices[i] - vertices[i - 1])));
                if (!Normals.Contains(tmp))
                {
                    Normals.Add(tmp);
                }
            }

            tmp = Math2.MakeStandardNormal(Vector2.Normalize(Math2.Perpendicular(vertices[0] - vertices[vertices.Length - 1])));
            if (!Normals.Contains(tmp))
            {
                Normals.Add(tmp);
            }

            var min = new Vector2(vertices[0].X, vertices[0].Y);
            var max = new Vector2(min.X, min.Y);

            for (int i = 1; i < vertices.Length; i++)
            {
                min.X = Math.Min(min.X, vertices[i].X);
                min.Y = Math.Min(min.Y, vertices[i].Y);
                max.X = Math.Max(max.X, vertices[i].X);
                max.Y = Math.Max(max.Y, vertices[i].Y);
            }
            AABB = new Rect2(min, max);

            _LongestAxisLength = -1;

            // Center, area, and lines
            TrianglePartition = new Triangle2[Vertices.Length - 2];
            float[] triangleSortKeys = new float[TrianglePartition.Length];
            float   area             = 0;

            Lines    = new Line2[Vertices.Length];
            Lines[0] = new Line2(Vertices[Vertices.Length - 1], Vertices[0]);
            var last = Vertices[0];

            Center = new Vector2(0, 0);
            for (int i = 1; i < Vertices.Length - 1; i++)
            {
                var next  = Vertices[i];
                var next2 = Vertices[i + 1];
                Lines[i] = new Line2(last, next);
                var tri = new Triangle2(new Vector2[] { Vertices[0], next, next2 });
                TrianglePartition[i - 1] = tri;
                triangleSortKeys[i - 1]  = -tri.Area;
                area   += tri.Area;
                Center += tri.Center * tri.Area;
                last    = next;
            }
            Lines[Vertices.Length - 1] = new Line2(Vertices[Vertices.Length - 2], Vertices[Vertices.Length - 1]);

            Array.Sort(triangleSortKeys, TrianglePartition);

            Area    = area;
            Center /= area;

            last = Vertices[Vertices.Length - 1];
            var centToLast            = (last - Center);
            var angLast               = Rotation2.Standardize((float)Math.Atan2(centToLast.Y, centToLast.X));
            var cwCounter             = 0;
            var ccwCounter            = 0;
            var foundDefinitiveResult = false;

            for (int i = 0; i < Vertices.Length; i++)
            {
                var curr       = Vertices[i];
                var centToCurr = (curr - Center);
                var angCurr    = Rotation2.Standardize((float)Math.Atan2(centToCurr.Y, centToCurr.X));


                var clockwise = (angCurr < angLast && (angCurr - angLast) < Math.PI) || (angCurr - angLast) > Math.PI;
                if (clockwise)
                {
                    cwCounter++;
                }
                else
                {
                    ccwCounter++;
                }

                Clockwise = clockwise;
                if (Math.Abs(angLast - angCurr) > Math2.DEFAULT_EPSILON)
                {
                    foundDefinitiveResult = true;
                    break;
                }

                last       = curr;
                centToLast = centToCurr;
                angLast    = angCurr;
            }
            if (!foundDefinitiveResult)
            {
                Clockwise = cwCounter > ccwCounter;
            }
        }