Skip to content

Commit

Permalink
Merge release-2.4
Browse files Browse the repository at this point in the history
Release 2.4
  • Loading branch information
axelpale authored Sep 12, 2022
2 parents 8695038 + 0c00f1a commit 6fa6d82
Show file tree
Hide file tree
Showing 50 changed files with 1,311 additions and 688 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ node_js:
- 10
- 12
- lts/*
branches:
only:
- main
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ The functions are grouped in *namespaces*, each focusing on a certain geometry.

## Coordinate systems and directions

Affineplane uses right-handed coordinate system where the axes are perpendicular to each other. All rotations happen around z-axis and the rotation angle grows from the positive x-axis towards positive y-axis. Because affineplane is primarily intented for web applications, it is customary that, under zero rotation, the x-axis grows right, y-axis grows down, and z-axis grows away from the viewer, as illustrated below.
Affineplane uses right-handed, orthonormal coordinate system. Due to orthonormality the axes are perpendicular to each other. All rotations happen around z-axis and the rotation angle grows from the positive x-axis towards positive y-axis. Because affineplane is primarily intented for web applications, it is customary that, under zero rotation, the x-axis grows right, y-axis grows down, and z-axis grows away from the viewer, as illustrated below.

![Right-handed coordinate system](docs/coordinates-directions-3d.png)

Expand Down Expand Up @@ -127,11 +127,11 @@ Vectors and other movements can only be projected orthogonally. This is because

## Type safety

Affineplane is very loose on types and requires you to ensure you feed the functions what they minimally expect. This has a benefit: you can input objects that have extra properties. For example `{ color: 'ff00ff', x: 2, y: 3 }` is a valid affineplane [point2](https://axelpale.github.io/affineplane/docs/API.html#affineplanepoint2). Note that while all affineplane operations return new objects, the extra properties are not carried to them.
Affineplane is very loose on types and requires you to ensure you feed the functions what they minimally expect. This has two benefits: the functions are fast and you can input objects that have extra properties. For example `{ color: 'ff00ff', x: 2, y: 3 }` is a valid affineplane [point2](https://axelpale.github.io/affineplane/docs/API.html#affineplanepoint2). Note that while all affineplane operations return new objects, the extra properties are not carried to them.

To check validity of an object, each geometry type has `validate` function, for example [point2.validate](https://axelpale.github.io/affineplane/docs/API.html#affineplanepoint2validate). We could have included validity checking into each function but that would have caused excess of checking for this kind of low-level math functions. Instead, use `validate` when you need it.

We might have TypeScript bindings in the future.
To avoid unefficient type checking, optional parameters and default values are used sparsingly. Keep this in mind especially when making contributions.

## Contribute

Expand Down
1,369 changes: 766 additions & 603 deletions docs/API.md

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion docs/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ yamdog.generate({
// Main title of the document
title: 'Affineplane API Documentation v' + version,
// Introduction; the initial paragraph
intro: 'Welcome to affineplane API reference documentation.',
intro: 'Welcome to affineplane API reference documentation. ' +
'See also [Usage](https://axelpale.github.io/affineplane/) and ' +
'[GitHub](https://github.com/axelpale/affineplane) for ' +
'introduction and source code. The docs are generated with ' +
'[yamdog](https://axelpale.github.io/yamdog/).',
// Styling; decorate the docs
decorators: [
decor.aliases(),
Expand Down
Binary file added docs/geometry_direction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/geometry_point.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/geometry_vector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/projection_distance_2d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions lib/dir2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// When a direction is transited between planes, only the rotation of
// the coordinate space affects the direction.
//
// ![Direction angle](docs/geometry_direction.png)
//
exports.create = require('./create')
exports.transitFrom = require('./transitFrom')
exports.transitTo = require('./transitTo')
2 changes: 2 additions & 0 deletions lib/dist2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// affects the distance. Rotation or translation of the plane does not
// change the distance measure.
//
// ![Distance transited between planes](docs/projection_distance_2d.png)
//

exports.create = require('./create')
exports.transitFrom = require('./transitFrom')
Expand Down
3 changes: 3 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ exports.plane3 = require('./plane3')
exports.point2 = require('./point2')
exports.point3 = require('./point3')

// TODO Ray. A line but into one direction only.
// exports.ray3 = require('./ray3')

// TODO Rectangle on a two-dimensional plane.
// exports.rect2 = require('./rect2')

Expand Down
16 changes: 16 additions & 0 deletions lib/plane3/getNormal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// affineplane.plane3.getNormal(plane)
//
// Get a unit vector perpendicular to the plane.
//
// Parameters:
// plane
// a plane3 on the reference plane
//
// Return:
// a vec3, the plane normal vector.
//
module.exports = function (plane) {
// Because all planes are on xy, there is one
// normal vector shared by all the planes.
return { x: 0, y: 0, z: 1 }
}
1 change: 1 addition & 0 deletions lib/plane3/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ exports.create = require('./create')
exports.difference = exports.between
exports.equal = require('./equal')
exports.fromFeatures = require('./fromFeatures')
exports.getNormal = require('./getNormal')
exports.getScale = require('./getScale')
exports.inverse = require('./invert')
exports.invert = exports.inverse
Expand Down
1 change: 1 addition & 0 deletions lib/point2/difference.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = (p, q) => {
// affineplane.point2.difference(p, q)
// affineplane.point2.diff
// affineplane.point2.delta
//
// A vector from point p to point q.
Expand Down
3 changes: 3 additions & 0 deletions lib/point2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// although the distance between and their mean can be computed.
// An affine space does not have origin; { x:0, y:0 } is not an origin.
//
// ![A point](docs/geometry_point.png)
//

// exports.add
// Points cannot be added because no origin.
Expand All @@ -18,6 +20,7 @@ exports.copy = require('./copy')
exports.create = require('./create')

exports.delta = require('./difference')
exports.diff = exports.delta
exports.difference = exports.delta

exports.distance = require('./distance')
Expand Down
12 changes: 11 additions & 1 deletion lib/point3/difference.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// affineplane.point3.difference(p, q)
// affineplane.point3.diff
// affineplane.point3.delta
//
// A vector from point p to point q.
Expand All @@ -12,4 +13,13 @@
// Return
// a vec3
//
module.exports = require('../vec3/difference')
module.exports = (p, q) => {
// Inverse of vector subtraction -(p - q)
return {
x: q.x - p.x,
y: q.y - p.y,
z: q.z - p.z
}
}

require('../vec3/difference')
1 change: 1 addition & 0 deletions lib/point3/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ exports.copy = require('./copy')
exports.clone = exports.copy
exports.create = require('./create')
exports.delta = require('./difference')
exports.diff = exports.delta
exports.difference = exports.delta
exports.distance = require('./distance')
exports.equal = require('./equal')
Expand Down
2 changes: 1 addition & 1 deletion lib/vec2/difference.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = (v, w) => {
// affineplane.vec2.difference(v, w)
//
// A vector between v and w.
// A vector between v and w, in other words, v - w.
//
// Parameters:
// v
Expand Down
28 changes: 28 additions & 0 deletions lib/vec2/divide.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module.exports = (vec, divisor) => {
// affineplane.vec2.divide(vec, divisor)
//
// The division of a vector.
// Equivalent to multiplying the vector by the inverse of the divisor.
// The direction of the vector does not change.
//
// Parameters:
// vec
// a vec2
// divisor
// a number
//
// Return
// a vec2
//
// Throws:
// if zero divisor
//

if (divisor === 0) {
throw new Error('Cannot divide vector by zero. Vectors must be finite.')
}
return {
x: vec.x / divisor,
y: vec.y / divisor
}
}
3 changes: 2 additions & 1 deletion lib/vec2/dot.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module.exports = (v, w) => {
// affineplane.vec2.dot(v, w)
//
// Dot product of two vectors.
// The dot product of two vectors,
// also called the scalar product.
//
// Parameters:
// v
Expand Down
15 changes: 14 additions & 1 deletion lib/vec2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//
// Vector is a two dimensional dynamic movent between points.
//
// ![A vector](docs/geometry_vector.png)
//

exports.add = require('./add')

Expand All @@ -16,13 +18,18 @@ exports.create = require('./create')

exports.cross = require('./cross')

exports.difference = require('./difference')
exports.diff = require('./difference')
exports.difference = exports.diff

exports.divide = require('./divide')

// exports.distance
// Vectors do not have distance. See magnitude.

exports.dot = require('./dot')

exports.equal = require('./equal')

exports.fromArray = require('./fromArray')

exports.fromPolar = require('./fromPolar')
Expand All @@ -43,6 +50,8 @@ exports.negate = exports.inverse

exports.norm = exports.magnitude

exports.normalize = require('./unit')

exports.opposite = exports.negation

// exports.polarAverage
Expand All @@ -56,6 +65,8 @@ exports.rotateTo = require('./rotateTo')
exports.scaleBy = require('./scaleBy')
exports.scaleTo = require('./scaleTo')

exports.subtract = exports.diff

exports.sum = require('./sum')

exports.toArray = require('./toArray')
Expand All @@ -65,4 +76,6 @@ exports.toPolar = require('./toPolar')
exports.transitFrom = require('./transitFrom')
exports.transitTo = require('./transitTo')

exports.unit = exports.normalize

exports.validate = require('./validate')
1 change: 1 addition & 0 deletions lib/vec2/scaleBy.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = (vec, multiplier) => {
// affineplane.vec2.scaleBy(vec, multiplier)
//
// The scalar multiplication of a vector.
// Scale the vector by a multiplier.
// The direction of the vector does not change.
//
Expand Down
2 changes: 1 addition & 1 deletion lib/vec2/scaleTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = (vec, magnitude) => {
// vec
// a vec2, non-zero vector.
// magnitude
// a number, the target vector length
// a number, the target vector length.
//
// Return
// a vec2
Expand Down
30 changes: 30 additions & 0 deletions lib/vec2/unit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const magnitude = require('./magnitude')

module.exports = (v) => {
// affineplane.vec2.unit(v)
// affineplane.vec2.normalize
//
// Get unit vector parallel to the given vector.
// The magnitude of unit vector is equal to one.
// If zero vector is given, assume direction towards positive x.
//
// Parameters:
// v
// a vec2
//
// Return
// a vec2, magnitude of one.
//
const m = magnitude(v)

if (m > 0) {
return {
x: v.x / m,
y: v.y / m
}
}
return {
x: 1,
y: 0
}
}
11 changes: 6 additions & 5 deletions lib/vec3/difference.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module.exports = (v, w) => {
// affineplane.vec3.difference(v, w)
// affineplane.vec3.diff(v, w)
// affineplane.vec3.subtract
//
// Get the vector w - v. In other words, if we place v, w
// Get the vector v - w. In other words, if we place v, w
// to begin from the same point then the result is a vector
// from the end of v to the end of w.
// from the end of w to the end of v.
//
// Parameters:
// v
Expand All @@ -16,8 +17,8 @@ module.exports = (v, w) => {
// a vec3
//
return {
x: w.x - v.x,
y: w.y - v.y,
z: w.z - v.z
x: v.x - w.x,
y: v.y - w.y,
z: v.z - w.z
}
}
25 changes: 25 additions & 0 deletions lib/vec3/divide.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = (vec, divisor) => {
// affineplane.vec3.divide(vec, divisor)
//
// The division of a vector.
// Equivalent to multiplying the vector by the inverse of the divisor.
// The direction of the vector does not change.
//
// Parameters:
// vec
// a vec3
// divisor
// a number. If zero, will result a vector having infinite length.
//
// Return
// a vec3
//
if (divisor === 0) {
throw new Error('Cannot divide vector by zero. Vectors must be finite.')
}
return {
x: vec.x / divisor,
y: vec.y / divisor,
z: vec.z / divisor
}
}
3 changes: 2 additions & 1 deletion lib/vec3/dot.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module.exports = (v, w) => {
// affineplane.vec3.dot(v, w)
//
// Dot product of two vectors.
// Dot product of two vectors,
// also called the scalar product.
//
// Parameters:
// v
Expand Down
9 changes: 7 additions & 2 deletions lib/vec3/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ exports.average = require('./average')
exports.copy = require('./copy')
exports.create = require('./create')
exports.cross = require('./cross')
exports.difference = require('./difference')
exports.diff = exports.difference
exports.diff = require('./difference')
exports.difference = exports.diff
exports.divide = require('./divide')
exports.dot = require('./dot')
exports.equal = require('./equal')
exports.fromArray = require('./fromArray')
Expand All @@ -20,15 +21,19 @@ exports.invert = require('./invert')
exports.inverse = exports.invert
exports.magnitude = require('./magnitude')
exports.negate = exports.invert
exports.norm = exports.magnitude
exports.normalize = require('./unit')
exports.projectTo = require('./projectTo')
exports.rotateBy = require('./rotateBy')
exports.rotateTo = require('./rotateTo')
exports.scaleBy = require('./scaleBy')
exports.scaleTo = require('./scaleTo')
exports.subtract = exports.diff
exports.sum = require('./sum')
exports.toArray = require('./toArray')
exports.toPolar = require('./toPolar')
exports.toSpherical = require('./toSpherical')
exports.transitFrom = require('./transitFrom')
exports.transitTo = require('./transitTo')
exports.unit = exports.normalize
exports.validate = require('./validate')
Loading

0 comments on commit 6fa6d82

Please sign in to comment.