public void BoxVolume() { var s = new BoxShape(1, 2, 3); Assert.AreEqual(1 * 2 * 3, s.GetVolume(0.0001f, 10)); var m = s.GetMesh(0.001f, 4); Assert.AreEqual(1 * 2 * 3, m.GetVolume()); }
public void ConvexHullOfPointsTest() { var s = new BoxShape(1, 2, 3); var v0 = s.GetVolume(0.001f, 10); var s1 = new ConvexHullOfPoints(s.GetMesh(0.1f, 1).Vertices); var v1 = s1.GetVolume(0.001f, 10); Assert.IsTrue(Numeric.AreEqual(v0, v1, 0.01f * (1 + v0))); // 1% error is allowed. }
private static Shape ComputeAxisAlignedBoundingShape(MeshContent mesh) { Debug.Assert(mesh.Positions.Count > 0); List <Vector3> points = mesh.Positions.Select(position => (Vector3)position).ToList(); var boundingShape = GeometryHelper.CreateBoundingShape(points); // Compute minimal sphere. Vector3 center; float radius; GeometryHelper.ComputeBoundingSphere(points, out radius, out center); SphereShape sphere = new SphereShape(radius); float sphereVolume = sphere.GetVolume(); // Compute minimal AABB. Aabb aabb = new Aabb(points[0], points[0]); for (int i = 1; i < points.Count; i++) { aabb.Grow(points[i]); } var boxPose = new Pose(aabb.Center); var box = new BoxShape(aabb.Extent); float boxVolume = box.GetVolume(); // Return the object with the smallest volume. // A TransformedShape is used if the shape needs to be translated. if (sphereVolume < boxVolume) { if (center.IsNumericallyZero) { boundingShape = sphere; } else { boundingShape = new TransformedShape(new GeometricObject(sphere, new Pose(center))); } } else { if (!boxPose.HasTranslation) { boundingShape = box; } else { boundingShape = new TransformedShape(new GeometricObject(box, boxPose)); } } return(boundingShape); }
/// <summary> /// Computes a minimum bounding shape that contains all given points. /// </summary> /// <param name="points">The points.</param> /// <returns>A minimum bounding shape that contains all given points.</returns> /// <remarks> /// The returned shape will be a <see cref="SphereShape"/>, a <see cref="CapsuleShape"/>, /// a <see cref="BoxShape"/>, or a <see cref="TransformedShape"/> (containing a sphere, capsule, /// or a box). The bounding shape is not guaranteed to be optimal, it is only guaranteed that /// the bounding shape includes all given points. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="points"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="points"/> is empty. /// </exception> public static Shape CreateBoundingShape(IList <Vector3> points) { if (points == null) { throw new ArgumentNullException("points"); } if (points.Count == 0) { throw new ArgumentException("The list of 'points' is empty."); } // Compute minimal sphere. Vector3 center; float radius; ComputeBoundingSphere(points, out radius, out center); SphereShape sphere = new SphereShape(radius); float sphereVolume = sphere.GetVolume(); // Compute minimal capsule. float height; Pose capsulePose; ComputeBoundingCapsule(points, out radius, out height, out capsulePose); CapsuleShape capsule = new CapsuleShape(radius, height); float capsuleVolume = capsule.GetVolume(); // Compute minimal box. Vector3 boxExtent; Pose boxPose; ComputeBoundingBox(points, out boxExtent, out boxPose); var box = new BoxShape(boxExtent); float boxVolume = box.GetVolume(); // Return the object with the smallest volume. // A TransformedShape is used if the shape needs to be translated or rotated. if (sphereVolume < boxVolume && sphereVolume < capsuleVolume) { if (center.IsNumericallyZero) { return(sphere); } return(new TransformedShape(new GeometricObject(sphere, new Pose(center)))); } else if (capsuleVolume < boxVolume) { if (!capsulePose.HasTranslation && !capsulePose.HasRotation) { return(capsule); } return(new TransformedShape(new GeometricObject(capsule, capsulePose))); } else { if (!boxPose.HasTranslation && !boxPose.HasRotation) { return(box); } return(new TransformedShape(new GeometricObject(box, boxPose))); } }
public void Volume() { var box = new BoxShape(2, 3, 7); Assert.AreEqual(2 * 3 * 7, box.GetVolume(0.1f, 1)); }