math.plane.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { DeepImmutable } from '../types';
  2. import { Vector3, Matrix } from './math.vector';
  3. /**
  4. * Represens a plane by the equation ax + by + cz + d = 0
  5. */
  6. export class Plane {
  7. private static _TmpMatrix = Matrix.Identity();
  8. /**
  9. * Normal of the plane (a,b,c)
  10. */
  11. public normal: Vector3;
  12. /**
  13. * d component of the plane
  14. */
  15. public d: number;
  16. /**
  17. * Creates a Plane object according to the given floats a, b, c, d and the plane equation : ax + by + cz + d = 0
  18. * @param a a component of the plane
  19. * @param b b component of the plane
  20. * @param c c component of the plane
  21. * @param d d component of the plane
  22. */
  23. constructor(a: number, b: number, c: number, d: number) {
  24. this.normal = new Vector3(a, b, c);
  25. this.d = d;
  26. }
  27. /**
  28. * @returns the plane coordinates as a new array of 4 elements [a, b, c, d].
  29. */
  30. public asArray(): number[] {
  31. return [this.normal.x, this.normal.y, this.normal.z, this.d];
  32. }
  33. // Methods
  34. /**
  35. * @returns a new plane copied from the current Plane.
  36. */
  37. public clone(): Plane {
  38. return new Plane(this.normal.x, this.normal.y, this.normal.z, this.d);
  39. }
  40. /**
  41. * @returns the string "Plane".
  42. */
  43. public getClassName(): string {
  44. return "Plane";
  45. }
  46. /**
  47. * @returns the Plane hash code.
  48. */
  49. public getHashCode(): number {
  50. let hash = this.normal.getHashCode();
  51. hash = (hash * 397) ^ (this.d | 0);
  52. return hash;
  53. }
  54. /**
  55. * Normalize the current Plane in place.
  56. * @returns the updated Plane.
  57. */
  58. public normalize(): Plane {
  59. var norm = (Math.sqrt((this.normal.x * this.normal.x) + (this.normal.y * this.normal.y) + (this.normal.z * this.normal.z)));
  60. var magnitude = 0.0;
  61. if (norm !== 0) {
  62. magnitude = 1.0 / norm;
  63. }
  64. this.normal.x *= magnitude;
  65. this.normal.y *= magnitude;
  66. this.normal.z *= magnitude;
  67. this.d *= magnitude;
  68. return this;
  69. }
  70. /**
  71. * Applies a transformation the plane and returns the result
  72. * @param transformation the transformation matrix to be applied to the plane
  73. * @returns a new Plane as the result of the transformation of the current Plane by the given matrix.
  74. */
  75. public transform(transformation: DeepImmutable<Matrix>): Plane {
  76. const invertedMatrix = Plane._TmpMatrix;
  77. transformation.invertToRef(invertedMatrix);
  78. const m = invertedMatrix.m;
  79. var x = this.normal.x;
  80. var y = this.normal.y;
  81. var z = this.normal.z;
  82. var d = this.d;
  83. var normalX = x * m[0] + y * m[1] + z * m[2] + d * m[3];
  84. var normalY = x * m[4] + y * m[5] + z * m[6] + d * m[7];
  85. var normalZ = x * m[8] + y * m[9] + z * m[10] + d * m[11];
  86. var finalD = x * m[12] + y * m[13] + z * m[14] + d * m[15];
  87. return new Plane(normalX, normalY, normalZ, finalD);
  88. }
  89. /**
  90. * Compute the dot product between the point and the plane normal
  91. * @param point point to calculate the dot product with
  92. * @returns the dot product (float) of the point coordinates and the plane normal.
  93. */
  94. public dotCoordinate(point: DeepImmutable<Vector3>): number {
  95. return ((((this.normal.x * point.x) + (this.normal.y * point.y)) + (this.normal.z * point.z)) + this.d);
  96. }
  97. /**
  98. * Updates the current Plane from the plane defined by the three given points.
  99. * @param point1 one of the points used to contruct the plane
  100. * @param point2 one of the points used to contruct the plane
  101. * @param point3 one of the points used to contruct the plane
  102. * @returns the updated Plane.
  103. */
  104. public copyFromPoints(point1: DeepImmutable<Vector3>, point2: DeepImmutable<Vector3>, point3: DeepImmutable<Vector3>): Plane {
  105. var x1 = point2.x - point1.x;
  106. var y1 = point2.y - point1.y;
  107. var z1 = point2.z - point1.z;
  108. var x2 = point3.x - point1.x;
  109. var y2 = point3.y - point1.y;
  110. var z2 = point3.z - point1.z;
  111. var yz = (y1 * z2) - (z1 * y2);
  112. var xz = (z1 * x2) - (x1 * z2);
  113. var xy = (x1 * y2) - (y1 * x2);
  114. var pyth = (Math.sqrt((yz * yz) + (xz * xz) + (xy * xy)));
  115. var invPyth;
  116. if (pyth !== 0) {
  117. invPyth = 1.0 / pyth;
  118. }
  119. else {
  120. invPyth = 0.0;
  121. }
  122. this.normal.x = yz * invPyth;
  123. this.normal.y = xz * invPyth;
  124. this.normal.z = xy * invPyth;
  125. this.d = -((this.normal.x * point1.x) + (this.normal.y * point1.y) + (this.normal.z * point1.z));
  126. return this;
  127. }
  128. /**
  129. * Checks if the plane is facing a given direction
  130. * @param direction the direction to check if the plane is facing
  131. * @param epsilon value the dot product is compared against (returns true if dot <= epsilon)
  132. * @returns True is the vector "direction" is the same side than the plane normal.
  133. */
  134. public isFrontFacingTo(direction: DeepImmutable<Vector3>, epsilon: number): boolean {
  135. var dot = Vector3.Dot(this.normal, direction);
  136. return (dot <= epsilon);
  137. }
  138. /**
  139. * Calculates the distance to a point
  140. * @param point point to calculate distance to
  141. * @returns the signed distance (float) from the given point to the Plane.
  142. */
  143. public signedDistanceTo(point: DeepImmutable<Vector3>): number {
  144. return Vector3.Dot(point, this.normal) + this.d;
  145. }
  146. // Statics
  147. /**
  148. * Creates a plane from an array
  149. * @param array the array to create a plane from
  150. * @returns a new Plane from the given array.
  151. */
  152. static FromArray(array: DeepImmutable<ArrayLike<number>>): Plane {
  153. return new Plane(array[0], array[1], array[2], array[3]);
  154. }
  155. /**
  156. * Creates a plane from three points
  157. * @param point1 point used to create the plane
  158. * @param point2 point used to create the plane
  159. * @param point3 point used to create the plane
  160. * @returns a new Plane defined by the three given points.
  161. */
  162. static FromPoints(point1: DeepImmutable<Vector3>, point2: DeepImmutable<Vector3>, point3: DeepImmutable<Vector3>): Plane {
  163. var result = new Plane(0.0, 0.0, 0.0, 0.0);
  164. result.copyFromPoints(point1, point2, point3);
  165. return result;
  166. }
  167. /**
  168. * Creates a plane from an origin point and a normal
  169. * @param origin origin of the plane to be constructed
  170. * @param normal normal of the plane to be constructed
  171. * @returns a new Plane the normal vector to this plane at the given origin point.
  172. * Note : the vector "normal" is updated because normalized.
  173. */
  174. static FromPositionAndNormal(origin: DeepImmutable<Vector3>, normal: DeepImmutable<Vector3>): Plane {
  175. var result = new Plane(0.0, 0.0, 0.0, 0.0);
  176. normal.normalize();
  177. result.normal = normal;
  178. result.d = -(normal.x * origin.x + normal.y * origin.y + normal.z * origin.z);
  179. return result;
  180. }
  181. /**
  182. * Calculates the distance from a plane and a point
  183. * @param origin origin of the plane to be constructed
  184. * @param normal normal of the plane to be constructed
  185. * @param point point to calculate distance to
  186. * @returns the signed distance between the plane defined by the normal vector at the "origin"" point and the given other point.
  187. */
  188. static SignedDistanceToPlaneFromPositionAndNormal(origin: DeepImmutable<Vector3>, normal: DeepImmutable<Vector3>, point: DeepImmutable<Vector3>): number {
  189. var d = -(normal.x * origin.x + normal.y * origin.y + normal.z * origin.z);
  190. return Vector3.Dot(point, normal) + d;
  191. }
  192. }