Пример #1
0
        public static double ComputeSignedArea(Polygon polygon)
        {
            int i;
            double area = 0;

            Vertices vertices = polygon.Vertices;

            for (i = 0; i < vertices.Count; i++)
            {
                int j = (i + 1)%vertices.Count;
                area += vertices[i].X*vertices[j].Y;
                area -= vertices[i].Y*vertices[j].X;
            }
            area /= 2.0;
            return area;
        }
Пример #2
0
        /// <summary>
        /// Winding number test for a point in a polygon.
        /// </summary>
        /// See more info about the algorithm here: http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm
        /// <param name="point">The point to be tested.</param>
        /// <returns>-1 if the winding number is zero and the point is outside
        /// the polygon, 1 if the point is inside the polygon, and 0 if the point
        /// is on the polygons edge.</returns>
        public static int PointInPolygon(Polygon polygon, Vector2D point)
        {
            // Winding number
            int wn = 0;

            Vertices polyVertices = polygon.Vertices;
            // Iterate through polygon's edges
            for (int i = 0; i < polyVertices.Count; i++)
            {
                // Get points
                Vector2D p1 = polyVertices[i];
                Vector2D p2 = polyVertices[polyVertices.NextIndex(i)];

                // Test if a point is directly on the edge
                Vector2D edge = p2 - p1;
                double area = MathHelper.Area(ref p1, ref p2, ref point);
                if (Math.Abs(area - 0f) < MathHelper.EpsilonD && Vector2D.Dot(point - p1, edge) >= 0 && Vector2D.Dot(point - p2, edge) <= 0)
                {
                    return 0;
                }
                // Test edge for intersection with ray from point
                if (p1.Y <= point.Y)
                {
                    if (p2.Y > point.Y && area > 0)
                    {
                        ++wn;
                    }
                }
                else
                {
                    if (p2.Y <= point.Y && area < 0)
                    {
                        --wn;
                    }
                }
            }
            return wn;
        }
Пример #3
0
        public static bool PolygonHitTest(Polygon polygon, Vector2D p)
        {
            double angle = 0;
            Vector2D p1 = new Vector2D();
            Vector2D p2 = new Vector2D();

            for (int i = 0; i < polygon.Vertices.Count; i++)
            {
                p1.X = polygon.Vertices[i].X - p.X;
                p1.Y = polygon.Vertices[i].Y - p.Y;
                p2.X = polygon.Vertices[(i + 1)%polygon.Vertices.Count].X - p.X;
                p2.Y = polygon.Vertices[(i + 1)%polygon.Vertices.Count].Y - p.Y;

                angle += Angle2D(p1.X, p1.Y, p2.X, p2.Y);
            }

            if (Math.Abs(angle) < Math.PI)
                return false;
            else
                return true;
        }
Пример #4
0
        public static Vector2D ComputeCentroid(Polygon polygon)
        {
            Vector2D centroid = new Vector2D(0, 0);
            double signedArea = 0.0f;
            double x0; // Current vertex X
            double y0; // Current vertex Y
            double x1; // Next vertex X
            double y1; // Next vertex Y
            double a; // Partial signed area
            Vector2D[] vertices = polygon.Vertices.ToArray();

            // For all vertices except last
            int i;
            for (i = 0; i < polygon.Vertices.Count - 1; ++i)
            {
                x0 = vertices[i].X;
                y0 = vertices[i].Y;
                x1 = vertices[i + 1].X;
                y1 = vertices[i + 1].Y;
                a = x0*y1 - x1*y0;
                signedArea += a;
                centroid.X += (x0 + x1)*a;
                centroid.Y += (y0 + y1)*a;
            }

            // Do last vertex
            x0 = vertices[i].X;
            y0 = vertices[i].Y;
            x1 = vertices[0].X;
            y1 = vertices[0].Y;
            a = x0*y1 - x1*y0;
            signedArea += a;
            centroid.X += (x0 + x1)*a;
            centroid.Y += (y0 + y1)*a;

            signedArea *= 0.5f;
            centroid.X /= (6*signedArea);
            centroid.Y /= (6*signedArea);

            return centroid;
        }
Пример #5
0
        public static bool ConvexityTest(Polygon polygon)
        {
            if (polygon.Vertices.Count < 3) return false;

            int xCh = 0, yCh = 0;

            Vector2D a = polygon.Vertices[0] - polygon.Vertices[polygon.Vertices.Count - 1];
            for (int i = 0; i < polygon.Vertices.Count - 1; ++i)
            {
                Vector2D b = polygon.Vertices[i] - polygon.Vertices[i + 1];

                if (Math.Sign(a.X) != Math.Sign(b.X)) ++xCh;
                if (Math.Sign(a.Y) != Math.Sign(b.Y)) ++yCh;

                a = b;
            }

            return (xCh <= 2 && yCh <= 2);
        }
Пример #6
0
        public static ushort[] TriangulateBrute(IList<Vector2D> vertex)
        {
            int n = vertex.Count;
            bool pointValid;
            List<ushort> indices = new List<ushort>();
            for (int i = 0;i < n - 2; i++)
            {
                for (int j = i + 1; j < n - 1; j++)
                {
                    for (int k = j + 1; k < n; k++)
                    {
                        Circle circle = Circle.CircumCircle(vertex[i], vertex[j], vertex[k]);

                        pointValid = true;
                        for (int l = 0; l < n; l++)
                        {
                            if(l == i || l == j || l == k) continue;

                            if(!circle.IsInside(vertex[l])) continue;

                            pointValid = false;
                            break;
                        }

                        if(pointValid)
                        {
                            // Add triangle as graph links
                            Polygon t = new Polygon(new[] {vertex[i],vertex[j], vertex[k]} );
                            double a = Polygon.ComputeSignedArea(t);

                            if (a > 0)
                                indices.AddRange(new[] { (ushort)k, (ushort)j, (ushort)i });
                            else
                                indices.AddRange(new[] { (ushort)i, (ushort)j, (ushort)k });
                        }
                    }
                }
            }
            return indices.ToArray();
        }