示例#1
0
        /// <summary>
        /// Returns if a point lies inside a triangle.
        /// </summary>
        public static bool Intersect(Vector2 point, Triangle triangle)
        {
            // Adapted from C code by Eric Haines, from http://www.graphicsgems.org/.

            // Shoot a test ray along +X axis.  The strategy is to compare vertex Y values
            // to the testing point's Y and quickly discard edges which are entirely to one
            // side of the test ray.
            Vector2 p1 = triangle.P1;
            Vector2 p2 = triangle.P2;
            Vector2 p3 = triangle.P3;
            bool yflag1 = p1.Y >= point.Y;
            bool yflag2 = p2.Y >= point.Y;
            bool yflag3 = p3.Y >= point.Y;
            bool inside_flag = false;
            if (yflag1 != yflag2 &&
                yflag2 == ((p2.Y - point.Y) * (p1.X - p2.X) >= (p2.X - point.X) * (p1.Y - p2.Y)))
                inside_flag = !inside_flag;
            if (yflag2 != yflag3 &&
                yflag3 == ((p3.Y - point.Y) * (p2.X - p3.X) >= (p3.X - point.X) * (p2.Y - p3.Y)))
                inside_flag = !inside_flag;
            if (yflag3 != yflag1 &&
                yflag1 == ((p1.Y - point.Y) * (p3.X - p1.X) >= (p1.X - point.X) * (p3.Y - p1.Y)))
                inside_flag = !inside_flag;
            return inside_flag;
        }
示例#2
0
        /// <summary>
        /// Returns the squared distance from a point to a triangle.
        /// If the point is inside the triangle, the distance is zero.
        /// </summary>
        public static float DistanceSquared(Vector2 point, Triangle triangle)
        {
            // First, test corners for being the closest points on the triangle.
            // This should cover the most probable cases, assuming the triangle
            // is small relative to the distance 'p' is from 't' on average
            // over several calls to this method.
            // The second most probable case is that the closest point lies
            // on an edge of 't'.
            // The least probable case is that 'p' lies inside 't'.

            Vector2 p1 = triangle.P1;
            Vector2 p2 = triangle.P2;
            Vector2 p3 = triangle.P3;

            // Is 'p1' the closest point?
            Vector2 p1p = point - p1;
            Vector2 e12 = p2 - p1;
            Vector2 e13 = p3 - p1;
            float halfplane12 = Vector2.Dot(p1p, e12);
            float halfplane13 = Vector2.Dot(p1p, e13);
            if (halfplane12 <= 0 && halfplane13 <= 0)
                return Vector2.DistanceSquared(point, p1);

            // Is 'p2' the closest point?
            Vector2 p2p = point - p2;
            Vector2 e23 = p3 - p2;
            float halfplane21 = -Vector2.Dot(p2p, e12);
            float halfplane23 = Vector2.Dot(p2p, e23);
            if (halfplane21 <= 0 && halfplane23 <= 0)
                return Vector2.DistanceSquared(point, p2);

            // Is 'p3' the closest point?
            Vector2 p3p = point - p3;
            float halfplane31 = -Vector2.Dot(p3p, e13);
            float halfplane32 = -Vector2.Dot(p3p, e23);
            if (halfplane31 <= 0 && halfplane32 <= 0)
                return Vector2.DistanceSquared(point, p3);

            // Is the closest point on the edge between 'p2' and 'p3'?
            float distance23 = Vector2.Dot(triangle.Normal23, p2p);
            if (distance23 >= 0 && halfplane23 >= 0 && halfplane32 >= 0)
                return distance23 * distance23;

            // Is the closest point on the edge between 'p1' and 'p3'?
            float distance13 = Vector2.Dot(triangle.Normal13, p1p);
            if (distance13 >= 0 && halfplane13 >= 0 && halfplane31 >= 0)
                return distance13 * distance13;

            // Is the closest point on the edge between 'p1' and 'p2'?
            float distance12 = Vector2.Dot(triangle.Normal12, p1p);
            if (distance12 >= 0 && halfplane12 >= 0 && halfplane21 >= 0)
                return distance12 * distance12;

            // Otherwise 'p' lies inside 't'.
            return 0;
        }
示例#3
0
        public void TestDistancePointTriangle()
        {
            var q1 = new Vector2(30, 30);
            var q2 = new Vector2(-20, 20);
            var q3 = new Vector2(10, -30);
            var p1 = new Vector2(10, 10);
            var p2 = new Vector2(30, 30);
            var p3 = new Vector2(5, 25);
            var p4 = new Vector2(50, 50);
            var p5 = new Vector2(5 - 10, 25 + 50);
            var t1 = new Triangle(q1, q2, q3);
            var delta = 0.0001f; // amount of acceptable error

            // Point in triangle
            Assert.AreEqual(0, Geometry.Distance(p1, t1), delta); // interior
            Assert.AreEqual(0, Geometry.Distance(p2, t1), delta); // vertex
            Assert.AreEqual(0, Geometry.Distance(p3, t1), delta); // edge

            // Point outside triangle
            Assert.AreEqual(20 * Math.Sqrt(2), Geometry.Distance(p4, t1), delta); // closest to vertex
            Assert.AreEqual(Math.Sqrt(10 * 10 + 50 * 50), Geometry.Distance(p5, t1), delta); // closest to edge
        }
示例#4
0
 public void TestIntersectPointTriangle()
 {
     var p1 = new Vector2(0f, 0f);
     var p2 = new Vector2(19.9999f, 49.9999f);
     var p3 = new Vector2(10f, 0f);
     var p4 = new Vector2(0f, -20f);
     var v1 = new Vector2(0f, -10f);
     var v2 = new Vector2(20f, 50f);
     var v3 = new Vector2(-50f, 70f);
     var t1 = new Triangle(v1, v2, v3);
     Assert.IsTrue(Geometry.Intersect(p1, t1));
     Assert.IsTrue(Geometry.Intersect(p2, t1));
     Assert.IsFalse(Geometry.Intersect(p3, t1));
     Assert.IsFalse(Geometry.Intersect(p4, t1));
 }
示例#5
0
 private void CreateCollisionAreas()
 {
     #if !VERY_SMALL_TRIANGLES_ARE_COLLIDABLE
     var verySmallTriangles = _indexMap.GetVerySmallTriangles(); // sorted in increasing order
     #else
     var verySmallTriangles = new List<int>();
     #endif
     TriangleCount = _indexData.Length / 3 - verySmallTriangles.Count();
     _collisionAreas = new CollisionArea[_indexData.Length / 3];
     var smallTriangleEnumerator = verySmallTriangles.GetEnumerator();
     var smallTrianglesRemaining = smallTriangleEnumerator.MoveNext();
     for (int i = 0; i + 2 < _indexData.Length; i += 3)
     {
         if (smallTrianglesRemaining && smallTriangleEnumerator.Current == i / 3)
         {
             smallTrianglesRemaining = smallTriangleEnumerator.MoveNext();
             continue;
         }
         var v1 = _vertexData[_indexData[i + 0]];
         var v2 = _vertexData[_indexData[i + 1]];
         var v3 = _vertexData[_indexData[i + 2]];
         var triangleArea = new Triangle(v1.ProjectXY(), v2.ProjectXY(), v3.ProjectXY());
         _collisionAreas[i / 3] = new CollisionArea("General", triangleArea, this, CollisionAreaType.Static, CollisionMaterialType.Rough);
     }
 }