static Vector3 RandomPointOutsideShape <T>(IShapeOps <T> h, T obj, Random random) { Vector3 p1 = h.RandomInteriorPoint(random); Vector3 p2 = h.RandomInteriorPoint(random); for (; ;) { // move p2 on a line away from p1 until it's outside p2 = p1 + (p2 - p1) * 1.1f; if (!h.ContainsPoint(p2)) { return(p2); } } }
/// <summary> /// Test containment and intersection between randomly created shapes of type T1 and T2. /// </summary> void TestRandomObjects <T1, T2>(Random random, IShapeOps <T1> h1, IShapeOps <T2> h2, Func <T1, T2, ContainmentType> contains, Func <T1, T2, bool> intersects) { // Create a random shape of each type h1.CreateRandomShape(random, (float)Math.Exp(random.NextDouble() * 4 - 2)); h2.CreateRandomShape(random, (float)Math.Exp(random.NextDouble() * 4 - 2)); // First ensure that the shapes are intersecting (or one is inside the other), by picking a point within each // and translating so they coincide. Vector3 p1 = h1.RandomInteriorPoint(random); Vector3 p2 = h2.RandomInteriorPoint(random); h2.Translate(p1 - p2); Check("Contains", h1, h2, contains, c => c != ContainmentType.Disjoint); Check("Intersects", h1, h2, intersects); // Next ensure that shape2 is intersecting (not contained or disjoint), by picking another point // in shape2, and scaling around p1 until the new point is outside of shape1. p2 = h2.RandomInteriorPoint(random); while (h1.ContainsPoint(p2)) { p2 = p1 + (p2 - p1) * 1.1f; h2.Translate(-p1); h2.Scale(1.1f); h2.Translate(p1); } Check("surface Intersects", h1, h2, contains, c => c == ContainmentType.Intersects); Check("Intersects", h1, h2, intersects); // Ensure that shape2 is fully contained within shape1 by scaling it down // around a point in shape1, until its hull is inside shape1 for (; ;) { Vector3[] hull = h2.GetHull(); bool allInside = true; foreach (Vector3 point in hull) { if (!h1.ContainsPoint(point)) { allInside = false; break; } } if (allInside) { break; } p1 = h1.RandomInteriorPoint(random); h2.Translate(-p1); h2.Scale(0.9f); h2.Translate(p1); } // Ensure that shape2 is fully disjoint from shape1 by picking a random plane and // translating the shapes to opposite sides of it Plane plane; plane.Normal = Vector3.Normalize(random.PointInSphere()); plane.D = (float)(random.NextDouble() * 2 - 1) * 100; h1.Translate((-h1.MinimumDistanceFromPlane(plane) + .001f) * plane.Normal); plane.D = -plane.D; plane.Normal = -plane.Normal; h2.Translate((-h2.MinimumDistanceFromPlane(plane) + .001f) * plane.Normal); Check("Disjoint", h1, h2, contains, c => c == ContainmentType.Disjoint); Check("!Intersects", h1, h2, intersects, r => !r); }