Geometry in space
Three classes describe lines, planes and spheres in space, next to Point and Vector which work in 2D and 3D. Everything is exact.
import {Point, Vector, Line3, Plane3, Sphere3} from 'pimath'Plane geometry is described in geometry in the plane.
Points and vectors in space
A third coordinate makes a 3D point or vector. z, cross and the 3D classes need it.
const A = new Point(1, 2, 3)
const v = new Vector(1, 0, 2)
A.display // (1;2;3)
A.dimension // 3
v.cross(new Vector(0, 1, 0)).display // ((-2,0,1))
new Vector(1, 2, 3).dot(new Vector(4, 5, 6)).display // 32
new Point(0, 0, 0).distanceTo(new Point(1, 2, 2)).display // 3setDimension(n) adds zero coordinates or removes the last ones.
Line3
A Line3 is stored by a point and a direction vector. It is built from two points, or from a point and a vector.
const d = new Line3(new Point(1, 0, 0), new Vector(1, 2, 3))
d.display // ((x,y,z)) = ((1,0,0)) + k\cdot ((1,2,3))
d.point.display // (1;0;0)
d.direction.display // ((1,2,3))
d.isPointOnLine(new Point(2, 2, 3)) // true
new Line3(new Point(0, 0, 0), new Point(1, 1, 1)).direction.display // ((1,1,1))Output forms
asSystem and asCartesian select another form for the next tex or display only.
const d = new Line3(new Point(1, 0, 0), new Vector(1, 2, 3))
d.asSystem.display // {(x,=,1+k),(y,=,2k),(z,=,3k):}
d.asCartesian.display // (x-1)/1 = (y)/2 = (z)/3
d.display // ((x,y,z)) = ((1,0,0)) + k\cdot ((1,2,3))Relations
const d1 = new Line3(new Point(0, 0, 0), new Vector(1, 0, 0))
const d2 = new Line3(new Point(1, 0, 0), new Vector(0, 1, 0))
const d3 = new Line3(new Point(0, 1, 0), new Vector(1, 0, 0))
const d4 = new Line3(new Point(0, 0, 1), new Vector(0, 1, 0))
d1.intersection(d2).point.display // (1;0;0)
d1.intersection(d3).isParallel // true
d1.intersection(d4).hasIntersection // false
d1.isParallelTo(d3) // true
d1.isOrthogonalTo(d4) // true
d1.isPerpendicularTo(d4) // false
d1.distanceTo(new Point(0, 3, 4)).display // 5
d1.project(new Point(2, 3, 4)).display // (2;0;0)
d1.reflect(new Point(2, 3, 4)).display // (2;-3;-4)intersection returns {point, hasIntersection, isParallel, isSame}. The lines are skew when all of the flags are false. isOrthogonalTo compares the directions only, while isPerpendicularTo also asks the lines to meet.
Plane3
A Plane3 is built from a configuration object. Give one of these combinations.
| Property | Plane defined by |
|---|---|
point and normal | A point and a normal vector |
point and directions | A point and two direction vectors |
points | Three points |
equation | A cartesian equation |
coefficients | [a, b, c, d] of ax + by + cz + d = 0 |
const P = new Plane3({equation: 'x+2y+3z-6=0'})
P.display // x+2y+3z-6=0
P.tex // x+2y+3z-6=0
P.normal.display // ((1,2,3))
P.a.display // 1
P.d.display // -6
new Plane3({coefficients: [1, 2, 3, -6]}).isEqual(P) // true
new Plane3({points: [new Point(6, 0, 0), new Point(0, 3, 0), new Point(0, 0, 2)]}).isEqual(P) // true
Plane3.fromPointAndNormal(new Point(0, 0, 2), new Vector(1, 2, 3)).display // x+2y+3z-6=0A configuration that matches none of the combinations throws a ParseError.
new Plane3({}) // throws ParseErrorRelations
const P = new Plane3({equation: 'x+2y+3z-6=0'})
const L = new Line3(new Point(0, 0, 0), new Vector(1, 1, 1))
P.isPointOnPlane(new Point(0, 0, 2)) // true
P.isParallelTo(new Plane3({equation: 'x+2y+3z+1=0'})) // true
P.isPerpendicularTo(new Plane3({equation: '2x-y=0'})) // true
P.distanceTo(new Point(0, 0, 0)).display // (3sqrt(14))/7
P.intersectWithLine(L).point.display // (1;1;1)
P.project(new Point(0, 0, 0)).display // (3/7;6/7;9/7)intersectWithLine returns {point, hasIntersection, isParallel, isOnPlane}, and intersectWithPlane returns {line, hasIntersection, isParallel, isEqual}.
const Q = new Plane3({equation: 'x-y=0'})
new Plane3({equation: 'x+2y+3z-6=0'}).intersectWithPlane(Q).line.display // ((x,y,z)) = ((2,2,0)) + k\cdot ((3,3,-3))angle gives the angle between two planes, or between a plane and a line or a vector, in degrees (angle(value, sharp, radian)).
new Plane3({equation: 'z=0'}).angle(new Plane3({equation: 'x=0'})) // 90Sphere3
A Sphere3 is stored by its center and the square of its radius. It is built from an equation, or from a center and a radius.
const S = new Sphere3('(x-1)^2+y^2+(z+2)^2=9')
S.center.display // (1;0;-2)
S.squareRadius.display // 9
S.radius.display // 3
S.isPointOnSphere(new Point(1, 3, -2)) // true
new Sphere3(new Point(0, 0, 0), 3).isEqual(new Sphere3('x^2+y^2+z^2=9')) // true
new Sphere3(new Point(0, 0, 0), 2).radius.display // 2
new Sphere3(new Point(0, 0, 0), 9, true).radius.display // 3radius is an object with tex, display and value. An equation that is not the one of a sphere throws a MathError, and reading a sphere that was never defined throws a StateError.
new Sphere3('x^2+y^2=9') // throws MathError
new Sphere3().center // throws StateErrorasDeveloped and asCenterRadius choose the output, and relativePosition(other) returns a Sphere3.RELATIVE_POSITION value.
const S = new Sphere3(new Point(0, 0, 0), 3)
S.display // x^2+y^2+z^2=9
S.asDeveloped.display // x^(2)+y^(2)+z^(2)-9=0
S.relativePosition(new Sphere3(new Point(10, 0, 0), 1)) === Sphere3.RELATIVE_POSITION.EXTERIOR // trueRandom geometry in space
PiMath.Random.point3().tex // e.g. \left(1;-2;3\right)
PiMath.Random.vector3().tex // e.g. \begin{pmatrix} 1 \\ 2 \\ -3 \end{pmatrix}
PiMath.Random.line3().tex // e.g. \begin{pmatrix} x \\ y \\ z \end{pmatrix} = ...See random generators for the options.
Members
Line3
Constructors
new Line3()new Line3(A: Point, B: Point)new Line3(A: Point, d: Vector)
Static members
| Member | Description |
|---|---|
fromPoints(A: Point, B: Point): Line3 | The line through two points. |
fromPointAndDirection(A: Point, d: Vector): Line3 | The line through a point with a direction vector. |
Properties and getters
| Member | Description |
|---|---|
asParametric: Line3 | Output option for the next tex or display: a point and a direction vector (default). Chainable. |
asSystem: Line3 | Output option for the next tex or display: the parametric system of x, y and z. Chainable. |
asCartesian: Line3 | Output option for the next tex or display: the symmetric form (x-a)/p = (y-b)/q = (z-c)/r. Chainable. |
tex: string | LaTeX rendering of the current state (terminal output, not chainable). |
display: string | ASCIIMath rendering of the current state (terminal output, not chainable). |
OA: Point | The reference point of the line. The getter returns the point itself, not a copy. |
d: Vector | The direction vector (a copy, see direction). Setting it replaces the direction. |
direction: Vector | The direction vector, as a copy. |
point: Point | The reference point, as a copy. |
Methods
| Member | Description |
|---|---|
parse(A: Point, B: Point): Line3parse(A: Point, d: Vector): Line3 | Replace the line with the line through two points, or through a point with a direction vector. |
copy(value: Line3): Line3 | Copy the mathematical state of another instance into this (display state is NOT transferred — the receiver keeps its own formatting). Entry point used when constructing/parsing from a same-type input. Distinct from clone. Classes without a real implementation throw NotImplementedError. |
clone(): Line3 | Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy. |
withDigits(digits: number | null): Line3 | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
distanceTo(pt: Point): Root | Distance from this line to pt, as an exact Root (simplified radical). |
hitSegment(A: Point, B: Point): boolean | Returns true when this line intersects the closed segment [A, B]. |
intersection(line: Line3): LineIntersection | Computes the relationship between this line and line. - isSame: coincident lines (infinitely many common points). - isParallel: parallel non-coincident lines. - hasIntersection + point: lines meet at exactly one point. - all false: skew lines (non-coplanar, no intersection). |
isPointOnLine(pt: Point): boolean | True when the point is on the line. |
isEqual(line: Line3): boolean | True when both lines are the same line, whatever their reference point and direction vector. |
isParallelTo(line: Line3): boolean | True when the directions are parallel and the lines are not the same. |
isOrthogonalTo(line: Line3): boolean | Returns true when the direction vectors are orthogonal (90°), regardless of whether the lines intersect. |
isPerpendicularTo(line: Line3): boolean | Returns true when the lines are both orthogonal and intersecting (strict perpendicularity). |
randomPoint(max?: number): Point | A random point of the line: the reference point moved along the direction vector by a non-zero integer between -max and max. |
randomNearPoint(k?: number): Point | A random point close to the line but not on it. |
simplify(): Line3 | Give the direction vector the smallest integer coordinates, with a positive first coordinate. |
project(pt: Point): Point | Orthogonal projection of pt onto this line. |
reflect(pt: Point): Point | Reflection of pt through this line (proj is the midpoint of [pt, reflect(pt)]). |
Plane3
Constructors
new Plane3(config?: Plane3Config)
Static members
| Member | Description |
|---|---|
fromPointAndNormal(point: Point, normal: Vector): Plane3 | The plane through a point with a normal vector. |
fromPointAndDirections(point: Point, v1: Vector, v2: Vector): Plane3 | The plane through a point, spanned by two direction vectors (the normal is their cross product). |
fromEquation(value: InputAlgebra<Equation>): Plane3 | Builds a plane from a cartesian equation (string or Equation). |
fromString(str: string): Plane3 | The plane of a cartesian equation written in a string, such as "x+2y+3z-6=0". |
fromPoints(A: Point, B: Point, C: Point): Plane3 | The plane through three points. |
fromCoefficients(a: InputValue<Fraction>, b: InputValue<Fraction>, c: InputValue<Fraction>, d: InputValue<Fraction>): Plane3 | Builds a plane from four cartesian coefficients [a, b, c, d] where the equation is ax + by + cz + d = 0. |
Properties and getters
| Member | Description |
|---|---|
tex: string | LaTeX rendering of the current state (terminal output, not chainable). |
display: string | ASCIIMath rendering of the current state (terminal output, not chainable). |
a: Fraction | Coefficient of x in ax + by + cz + d = 0. |
b: Fraction | Coefficient of y in ax + by + cz + d = 0. |
c: Fraction | Coefficient of z in ax + by + cz + d = 0. |
d: Fraction | d such that n·p + d = 0 for any point p on the plane. |
normal: Vector | The normal vector (a, b, c). Setting it replaces the vector. |
point: Point | A point of the plane. Setting it accepts a point or a vector. |
Methods
| Member | Description |
|---|---|
parse(config: Plane3Config): Plane3 | Routes a Plane3Config to the appropriate static factory method. Throws: {ParseError} if no valid property combination is found in config |
copy(value: Plane3): Plane3 | Copy the mathematical state of another instance into this (display state is NOT transferred — the receiver keeps its own formatting). Entry point used when constructing/parsing from a same-type input. Distinct from clone. Classes without a real implementation throw NotImplementedError. |
clone(): Plane3 | Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy. |
withDigits(digits: number | null): Plane3 | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
angle(vector: Vector, sharp?: boolean, radian?: boolean): numberangle(line: Line3, sharp?: boolean, radian?: boolean): numberangle(plane: Plane3, sharp?: boolean, radian?: boolean): number | Angle between this plane and another plane, line, or vector. - Plane3 → dihedral angle (angle between normals). - Line3 / Vector → angle between the line/vector and the plane (complement of the angle with the normal). Throws: {DimensionError} if value is a Vector that is not 3D |
distanceTo(point: Point): Root | Euclidean distance from a point to this plane, as an exact Root. |
intersectWithLine(line: Line3): PlaneLineIntersection | Intersection of this plane with a line. - hasIntersection: line meets the plane at exactly one point. - isOnPlane: line lies entirely on the plane (direction ⊥ normal AND base point satisfies the equation). - isParallel: direction ⊥ normal but base point is NOT on the plane. |
intersectWithPlane(plane: Plane3): PlanePlaneIntersection | Intersection of this plane with another plane. - hasIntersection: planes meet in a unique line. - isEqual: planes are the same (infinitely many common points). - isParallel: planes are parallel but distinct. |
isPointOnPlane(pt: Point): boolean | True when the point satisfies the equation of the plane. |
isParallelTo(plane: Plane3): booleanisParallelTo(line: Line3): boolean | True when the plane is parallel to another plane (the normals are parallel) or to a line (the direction is perpendicular to the normal). A plane is parallel to itself. |
isPerpendicularTo(plane: Plane3): booleanisPerpendicularTo(line: Line3): boolean | True when the plane is perpendicular to another plane (the normals are perpendicular) or to a line (the direction is parallel to the normal). |
simplify(): Plane3 | Reduces a, b, c (and implicitly d) by their GCD. |
isEqual(plane: Plane3): boolean | True when both planes are the same plane, whatever their normal vector and reference point. |
project(pt: Point): Point | Orthogonal projection of pt onto this plane. |
reflect(pt: Point): Point | Reflection of pt through this plane (proj is the midpoint of [pt, reflect(pt)]). |
Sphere3
Constructors
new Sphere3()new Sphere3(equation: string \| Equation)new Sphere3(sphere: Sphere3)new Sphere3(center: Point, radius: InputValue<Fraction>, square?: boolean)
Static members
| Member | Description |
|---|---|
fromCenterRadius(center: Point, radius: InputValue<Fraction>, square?: boolean): Sphere3 | The sphere with the given center and radius. |
fromEquation(value: InputAlgebra<Equation>): Sphere3 | Does not mutate the input. Throws: {MathError} if the input is not a valid sphere equation (degree ≠ 2 in x/y/z, or unequal leading coefficients) |
fromString(str: string): Sphere3 | The sphere of an equation written in a string. Throws: {MathError} if the equation is not the one of a sphere. |
RELATIVE_POSITION: typeof Sphere3RelativePosition | The values returned by relativePosition. |
Properties and getters
| Member | Description |
|---|---|
center: Point | The center, as a point. Throws: {StateError} if the sphere is not defined. |
squareRadius: Fraction | The square of the radius, as an exact fraction. Throws: {StateError} if the sphere is not defined. |
radius: { tex: string; display: string; value: number; } | The radius, as an object with its tex, its display and its decimal value. It is written as a number when the square of the radius is a perfect square, and as a root otherwise. Throws: {StateError} if the sphere is not defined. |
equation: Equation | The equation (x-a)^2+(y-b)^2+(z-c)^2-r^2=0, as an Equation. Throws: {StateError} if the sphere is not defined. |
asCenterRadius: Sphere3 | Output option: the form (x-a)^2+(y-b)^2+(z-c)^2=r^2 (default). Chainable, persistent. |
asDeveloped: Sphere3 | Output option: the developed equation. Chainable, persistent. |
tex: string | LaTeX rendering of the current state (terminal output, not chainable). |
display: string | ASCIIMath rendering of the current state (terminal output, not chainable). |
Methods
| Member | Description |
|---|---|
parse(...values: unknown[]): Sphere3 | Replace the sphere with an equation, another sphere, or a center and a radius. Arguments that do not match any form leave the sphere unchanged. |
clone(): Sphere3 | Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy. |
withDigits(digits: number | null): Sphere3 | Show every numeric value as a decimal with digits digits after the point (exact values included: 3/2 becomes 1.50 with 2 digits). |
copy(sphere: Sphere3): Sphere3 | Copy the mathematical state of another instance into this (display state is NOT transferred — the receiver keeps its own formatting). Entry point used when constructing/parsing from a same-type input. Distinct from clone. Classes without a real implementation throw NotImplementedError. |
relativePosition(S: Sphere3): Sphere3RelativePosition | The relative position of two spheres, as a Sphere3.RELATIVE_POSITION value: interior, exterior, secant, tangent inside or outside, superposed, or concentric. |
isPointOnSphere(P: Point): boolean | True when the point satisfies the equation of the sphere. |
isEqual(S: Sphere3): boolean | True when both spheres have the same center and the same radius. |