#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Diagnostics; using Microsoft.Xna.Framework; namespace Nuclex.Geometry.Areas { /// Two-dimensional Plane public class Plane3 : IArea3 { /// Initializes a new Plane /// Offset of the plane from the coordinate system's center /// Vector that is exactly perpendicular to the plane [DebuggerStepThrough] public Plane3(Vector3 offset, Vector3 normal) { this.Offset = offset; this.Normal = normal; } /// Initializes a new Plane /// Distance of the plane from the coordinate system's center /// Vector that is exactly perpendicular to the plane [DebuggerStepThrough] public Plane3(float distance, Vector3 normal) : this(normal * distance, normal) { } /// Determines which side of a plane a point is on /// Offset of the plane /// Normal vector of the plane /// Location of the point to be checked /// Which side of the plane the point is on public static Side GetSide(Vector3 planeOffset, Vector3 planeNormal, Vector3 point) { float side = Vector3.Dot(point - planeOffset, planeNormal); // We don't do neutral. The plane is infinitely thin, so the chance of hitting // the plane with an infinitely small point is about 0. The point is either // in front of the plane or behind the plane. if(side >= 0.0) { return Side.Positive; } else { return Side.Negative; } } /// Surface area that the shape contains public float Area { get { return float.PositiveInfinity; } } /// The total length of the area's circumference public float CircumferenceLength { get { return float.PositiveInfinity; } } /// The center of mass within the shape public Vector3 CenterOfMass { get { return this.Offset; } } /// Smallest rectangle that encloses the shape in its entirety public Volumes.AxisAlignedBox3 BoundingBox { get { // A plane perfectly resting on the Y/Z axes has zero thickness on the X axis if(this.Normal.X == 1.0f) { return new Volumes.AxisAlignedBox3( new Vector3(this.Offset.X, float.NegativeInfinity, float.NegativeInfinity), new Vector3(this.Offset.X, float.PositiveInfinity, float.PositiveInfinity) ); } // A plane perfectly resting on the X/Z axes has zero thickness on the Y axis if(this.Normal.Y == 1.0f) { return new Volumes.AxisAlignedBox3( new Vector3(float.NegativeInfinity, this.Offset.Y, float.NegativeInfinity), new Vector3(float.PositiveInfinity, this.Offset.Y, float.PositiveInfinity) ); } // A plane perfectly resting on the X/Y axes has zero thickness on the Z axis if(this.Normal.Z == 1.0f) { return new Volumes.AxisAlignedBox3( new Vector3(float.NegativeInfinity, float.NegativeInfinity, this.Offset.Z), new Vector3(float.PositiveInfinity, float.PositiveInfinity, this.Offset.Z) ); } // Any plane not perfectly aligned to two coordinate axes can only fit into a // bounding box of infinite size in all 3 dimensions. return new Volumes.AxisAlignedBox3( new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity), new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity) ); } } /// Locates the nearest point in the shape to some arbitrary location /// Location to which the closest point is determined /// The closest point in the shape to the specified location public Vector3 ClosestPointTo(Vector3 location) { float distance = Vector3.Dot(this.Normal, location - this.Offset); return location - distance * this.Normal; } /// Returns a random point on the area's perimeter /// Random number generator that will be used /// A random point on the area's perimeter public Vector3 RandomPointOnPerimeter(IRandom randomNumberGenerator) { Vector3 planePoint = PointGenerators.Plane3PointGenerator.RandomPointOnPerimeter( randomNumberGenerator, this.Normal ); return planePoint + this.Offset; } /// Returns a random point inside the area /// Random number generator that will be used /// A random point inside the area public Vector3 RandomPointWithin(IRandom randomNumberGenerator) { Vector3 planePoint = PointGenerators.Plane3PointGenerator.RandomPointWithin( randomNumberGenerator, this.Normal ); return planePoint + this.Offset; } /// Offset of the plane from the coordinate system's center public Vector3 Offset; /// Direction that is exactly perpendicular to the plane public Vector3 Normal; } } // namespace Nuclex.Geometry.Areas