Skip to content

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.

js
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.

js
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 // 3

setDimension(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.

js
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.

js
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 ​

js
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.

PropertyPlane defined by
point and normalA point and a normal vector
point and directionsA point and two direction vectors
pointsThree points
equationA cartesian equation
coefficients[a, b, c, d] of ax + by + cz + d = 0
js
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=0

A configuration that matches none of the combinations throws a ParseError.

js
new Plane3({}) // throws ParseError

Relations ​

js
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}.

js
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)).

js
new Plane3({equation: 'z=0'}).angle(new Plane3({equation: 'x=0'})) // 90

Sphere3 ​

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.

js
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 // 3

radius 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.

js
new Sphere3('x^2+y^2=9') // throws MathError
new Sphere3().center // throws StateError

asDeveloped and asCenterRadius choose the output, and relativePosition(other) returns a Sphere3.RELATIVE_POSITION value.

js
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 // true

Random geometry in space ​

js
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

MemberDescription
fromPoints(A: Point, B: Point): Line3The line through two points.
fromPointAndDirection(A: Point, d: Vector): Line3The line through a point with a direction vector.

Properties and getters

MemberDescription
asParametric: Line3Output option for the next tex or display: a point and a direction vector (default). Chainable.
asSystem: Line3Output option for the next tex or display: the parametric system of x, y and z. Chainable.
asCartesian: Line3Output option for the next tex or display: the symmetric form (x-a)/p = (y-b)/q = (z-c)/r. Chainable.
tex: stringLaTeX rendering of the current state (terminal output, not chainable).
display: stringASCIIMath rendering of the current state (terminal output, not chainable).
OA: PointThe reference point of the line. The getter returns the point itself, not a copy.
d: VectorThe direction vector (a copy, see direction). Setting it replaces the direction.
direction: VectorThe direction vector, as a copy.
point: PointThe reference point, as a copy.

Methods

MemberDescription
parse(A: Point, B: Point): Line3
parse(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): Line3Copy 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(): Line3Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy.
withDigits(digits: number | null): Line3Show 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): RootDistance from this line to pt, as an exact Root (simplified radical).
hitSegment(A: Point, B: Point): booleanReturns true when this line intersects the closed segment [A, B].
intersection(line: Line3): LineIntersectionComputes 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): booleanTrue when the point is on the line.
isEqual(line: Line3): booleanTrue when both lines are the same line, whatever their reference point and direction vector.
isParallelTo(line: Line3): booleanTrue when the directions are parallel and the lines are not the same.
isOrthogonalTo(line: Line3): booleanReturns true when the direction vectors are orthogonal (90°), regardless of whether the lines intersect.
isPerpendicularTo(line: Line3): booleanReturns true when the lines are both orthogonal and intersecting (strict perpendicularity).
randomPoint(max?: number): PointA 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): PointA random point close to the line but not on it.
simplify(): Line3Give the direction vector the smallest integer coordinates, with a positive first coordinate.
project(pt: Point): PointOrthogonal projection of pt onto this line.
reflect(pt: Point): PointReflection of pt through this line (proj is the midpoint of [pt, reflect(pt)]).

Plane3 ​

Constructors

  • new Plane3(config?: Plane3Config)

Static members

MemberDescription
fromPointAndNormal(point: Point, normal: Vector): Plane3The plane through a point with a normal vector.
fromPointAndDirections(point: Point, v1: Vector, v2: Vector): Plane3The plane through a point, spanned by two direction vectors (the normal is their cross product).
fromEquation(value: InputAlgebra<Equation>): Plane3Builds a plane from a cartesian equation (string or Equation).
fromString(str: string): Plane3The plane of a cartesian equation written in a string, such as "x+2y+3z-6=0".
fromPoints(A: Point, B: Point, C: Point): Plane3The plane through three points.
fromCoefficients(a: InputValue<Fraction>, b: InputValue<Fraction>, c: InputValue<Fraction>, d: InputValue<Fraction>): Plane3Builds a plane from four cartesian coefficients [a, b, c, d] where the equation is ax + by + cz + d = 0.

Properties and getters

MemberDescription
tex: stringLaTeX rendering of the current state (terminal output, not chainable).
display: stringASCIIMath rendering of the current state (terminal output, not chainable).
a: FractionCoefficient of x in ax + by + cz + d = 0.
b: FractionCoefficient of y in ax + by + cz + d = 0.
c: FractionCoefficient of z in ax + by + cz + d = 0.
d: Fractiond such that n·p + d = 0 for any point p on the plane.
normal: VectorThe normal vector (a, b, c). Setting it replaces the vector.
point: PointA point of the plane. Setting it accepts a point or a vector.

Methods

MemberDescription
parse(config: Plane3Config): Plane3Routes a Plane3Config to the appropriate static factory method. Throws: {ParseError} if no valid property combination is found in config
copy(value: Plane3): Plane3Copy 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(): Plane3Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy.
withDigits(digits: number | null): Plane3Show 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): number
angle(line: Line3, sharp?: boolean, radian?: boolean): number
angle(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): RootEuclidean distance from a point to this plane, as an exact Root.
intersectWithLine(line: Line3): PlaneLineIntersectionIntersection 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): PlanePlaneIntersectionIntersection 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): booleanTrue when the point satisfies the equation of the plane.
isParallelTo(plane: Plane3): boolean
isParallelTo(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): boolean
isPerpendicularTo(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(): Plane3Reduces a, b, c (and implicitly d) by their GCD.
isEqual(plane: Plane3): booleanTrue when both planes are the same plane, whatever their normal vector and reference point.
project(pt: Point): PointOrthogonal projection of pt onto this plane.
reflect(pt: Point): PointReflection 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

MemberDescription
fromCenterRadius(center: Point, radius: InputValue<Fraction>, square?: boolean): Sphere3The sphere with the given center and radius.
fromEquation(value: InputAlgebra<Equation>): Sphere3Does 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): Sphere3The sphere of an equation written in a string. Throws: {MathError} if the equation is not the one of a sphere.
RELATIVE_POSITION: typeof Sphere3RelativePositionThe values returned by relativePosition.

Properties and getters

MemberDescription
center: PointThe center, as a point. Throws: {StateError} if the sphere is not defined.
squareRadius: FractionThe 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: EquationThe 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: Sphere3Output option: the form (x-a)^2+(y-b)^2+(z-c)^2=r^2 (default). Chainable, persistent.
asDeveloped: Sphere3Output option: the developed equation. Chainable, persistent.
tex: stringLaTeX rendering of the current state (terminal output, not chainable).
display: stringASCIIMath rendering of the current state (terminal output, not chainable).

Methods

MemberDescription
parse(...values: unknown[]): Sphere3Replace 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(): Sphere3Full duplicate of this instance, including display state (selected form and options set via as*** / with***). Distinct from copy.
withDigits(digits: number | null): Sphere3Show 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): Sphere3Copy 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): Sphere3RelativePositionThe relative position of two spheres, as a Sphere3.RELATIVE_POSITION value: interior, exterior, secant, tangent inside or outside, superposed, or concentric.
isPointOnSphere(P: Point): booleanTrue when the point satisfies the equation of the sphere.
isEqual(S: Sphere3): booleanTrue when both spheres have the same center and the same radius.

Released under the MIT License.