From fb4ef2f52986dc1f36a72ccae0f8befed5ccc59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 01:06:09 +0200 Subject: [PATCH 01/26] link new geometries in api docs --- docs/API.md | 210 +++++++++++++++++++++++------------------------ docs/generate.js | 6 ++ 2 files changed, 111 insertions(+), 105 deletions(-) diff --git a/docs/API.md b/docs/API.md index 8621dd29..5026acaf 100644 --- a/docs/API.md +++ b/docs/API.md @@ -448,7 +448,7 @@ The resulting circle is also the minimum bounding circle of the box.

Returns:

-- a sphere2 +- a [sphere2](#affineplanesphere2) Aliases: [affineplane.box2.getSphere](#affineplanebox2getsphere) @@ -522,7 +522,7 @@ Get the four line segments of the box.

Returns:

-- array of segment2, each segment in the reference basis. +- array of [segment2](#affineplanesegment2), each segment in the reference basis. Source: [getSegments.js](https://github.com/axelpale/affineplane/blob/main/lib/box2/getSegments.js) @@ -1137,7 +1137,7 @@ The resulting sphere is also the minimum bounding sphere of the box.

Returns:

-- a sphere3 +- a [sphere3](#affineplanesphere3) Source: [getSphere.js](https://github.com/axelpale/affineplane/blob/main/lib/box3/getSphere.js) @@ -7580,9 +7580,9 @@ Test if scalars c, d are almost equal within the margin of tolerance.

Parameters:

- *c* - - a number, a scalar1 + - a number, a [scalar1](#affineplanescalar1) - *d* - - a number, a scalar1 + - a number, a [scalar1](#affineplanescalar1) - *tolerance* - optional number, default is [affineplane.epsilon](#affineplaneepsilon). Set to 0 for strict comparison. @@ -7625,9 +7625,9 @@ Test if scalars c, d are strictly equal.

Parameters:

- *c* - - a number, a scalar1 + - a number, a [scalar1](#affineplanescalar1) - *d* - - a number, a scalar1 + - a number, a [scalar1](#affineplanescalar1)

Returns:

@@ -7646,14 +7646,14 @@ to the reference basis.

Parameters:

- *scalar* - - a number, a scalar1 in the source basis. + - a number, a [scalar1](#affineplanescalar1) in the source basis. - *source* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the source basis, represented in the reference basis.

Returns:

-- a number, the same scalar1 but represented in the reference basis. +- a number, the same [scalar1](#affineplanescalar1) but represented in the reference basis. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar1/transitFrom.js) @@ -7668,14 +7668,14 @@ in the coordinate system of the target.

Parameters:

- *scalar* - - a number, a scalar1 in the reference basis. + - a number, a [scalar1](#affineplanescalar1) in the reference basis. - *target* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the target basis, represented in the reference basis.

Returns:

-- a number, a scalar1 in the target basis. +- a number, a [scalar1](#affineplanescalar1) in the target basis. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar1/transitTo.js) @@ -7683,8 +7683,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sca ## [affineplane](#affineplane).[scalar1](#affineplanescalar1).[validate](#affineplanescalar1validate)(s) -Check if the argument is a valid scalar1. -Valid scalar1 is a number and not NaN. +Check if the argument is a valid [scalar1](#affineplanescalar1). +Valid [scalar1](#affineplanescalar1) is a number and not NaN.

Parameters:

@@ -7694,7 +7694,7 @@ Valid scalar1 is a number and not NaN.

Returns:

-- a boolean, true if valid scalar1 +- a boolean, true if valid [scalar1](#affineplanescalar1) Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar1/validate.js) @@ -7702,7 +7702,7 @@ Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/scal ## [affineplane](#affineplane).[scalar2](#affineplanescalar2) -The scalar2 is a directionless measure of order 2. +The [scalar2](#affineplanescalar2) is a directionless measure of order 2. It is suitable for **area measurements** that undergo basis transitions. For example, let us have 1x1 square on a basis of scale 1. @@ -7737,9 +7737,9 @@ the margin of tolerance.

Parameters:

- *c* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2) - *d* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2) - *tolerance* - optional number, default is [affineplane.epsilon](#affineplaneepsilon). Set to 0 for strict comparison. @@ -7782,9 +7782,9 @@ Test if scalars c, d are strictly equal.

Parameters:

- *c* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2) - *d* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2)

Returns:

@@ -7803,14 +7803,14 @@ to the reference basis.

Parameters:

- *scalar* - - a number, a scalar2 in the source basis. + - a number, a [scalar2](#affineplanescalar2) in the source basis. - *source* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the source basis, represented in the reference basis.

Returns:

-- a number, the same scalar2 but represented in the reference basis. +- a number, the same [scalar2](#affineplanescalar2) but represented in the reference basis. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar2/transitFrom.js) @@ -7825,14 +7825,14 @@ in the coordinate system of the target.

Parameters:

- *scalar* - - a number, a scalar2 in the reference basis. + - a number, a [scalar2](#affineplanescalar2) in the reference basis. - *target* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the target basis, represented in the reference basis.

Returns:

-- a number, a scalar2 in the target basis. +- a number, a [scalar2](#affineplanescalar2) in the target basis. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar2/transitTo.js) @@ -7840,8 +7840,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sca ## [affineplane](#affineplane).[scalar2](#affineplanescalar2).[validate](#affineplanescalar2validate)(s) -Check if the argument is a valid scalar2. -Valid scalar2 is a number and not NaN. +Check if the argument is a valid [scalar2](#affineplanescalar2). +Valid [scalar2](#affineplanescalar2) is a number and not NaN.

Parameters:

@@ -7851,7 +7851,7 @@ Valid scalar2 is a number and not NaN.

Returns:

-- a boolean, true if valid scalar2 +- a boolean, true if valid [scalar2](#affineplanescalar2) Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar2/validate.js) @@ -7859,7 +7859,7 @@ Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/scal ## [affineplane](#affineplane).[scalar3](#affineplanescalar3) -The scalar3 is a directionless measure of order 3. +The [scalar3](#affineplanescalar3) is a directionless measure of order 3. It is suitable for **volume measurements** that undergo basis transitions. For example, let us have 1x1x1 box in a basis of scale 1. @@ -7895,9 +7895,9 @@ the margin of tolerance.

Parameters:

- *c* - - a number, a scalar3 + - a number, a [scalar3](#affineplanescalar3) - *d* - - a number, a scalar3 + - a number, a [scalar3](#affineplanescalar3) - *tolerance* - optional number, default is [affineplane.epsilon](#affineplaneepsilon). Set to 0 for strict comparison. @@ -7940,9 +7940,9 @@ Test if the third-order scalars c, d are strictly equal.

Parameters:

- *c* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2) - *d* - - a number, a scalar2 + - a number, a [scalar2](#affineplanescalar2)

Returns:

@@ -7961,14 +7961,14 @@ to the reference basis.

Parameters:

- *scalar* - - a number, a scalar3 in the source basis. + - a number, a [scalar3](#affineplanescalar3) in the source basis. - *source* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the source basis, represented in the reference basis.

Returns:

-- a number, the same scalar2 but represented in the reference basis. +- a number, the same [scalar2](#affineplanescalar2) but represented in the reference basis. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar3/transitFrom.js) @@ -7983,14 +7983,14 @@ in the coordinate system of the target.

Parameters:

- *scalar* - - a number, a scalar3 in the reference basis. + - a number, a [scalar3](#affineplanescalar3) in the reference basis. - *target* - a [plane2](#affineplaneplane2) or [plane3](#affineplaneplane3), the target basis, represented in the reference basis.

Returns:

-- a number, a scalar3 in the target basis. +- a number, a [scalar3](#affineplanescalar3) in the target basis. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar3/transitTo.js) @@ -7998,8 +7998,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sca ## [affineplane](#affineplane).[scalar3](#affineplanescalar3).[validate](#affineplanescalar3validate)(s) -Check if the argument is a valid scalar3. -Valid scalar3 is a number and not NaN. +Check if the argument is a valid [scalar3](#affineplanescalar3). +Valid [scalar3](#affineplanescalar3) is a number and not NaN.

Parameters:

@@ -8009,7 +8009,7 @@ Valid scalar3 is a number and not NaN.

Returns:

-- a boolean, true if valid scalar3 +- a boolean, true if valid [scalar3](#affineplanescalar3) Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/scalar3/validate.js) @@ -8043,9 +8043,9 @@ Test if two segments collide.

Parameters:

- *s0* - - a segment2 + - a [segment2](#affineplanesegment2) - *s1* - - a segment2 + - a [segment2](#affineplanesegment2)

Returns:

@@ -8070,7 +8070,7 @@ Create a segment from points.

Returns:

-- a segment2, an array. +- a [segment2](#affineplanesegment2), an array. Source: [create.js](https://github.com/axelpale/affineplane/blob/main/lib/segment2/create.js) @@ -8084,14 +8084,14 @@ transit the segment from the source basis to the reference basis.

Parameters:

- *seg* - - a segment2, represented on the source basis. + - a [segment2](#affineplanesegment2), represented on the source basis. - *source* - a [plane2](#affineplaneplane2), the source basis, represented on the reference basis.

Returns:

-- a segment2, represented on the reference basis. +- a [segment2](#affineplanesegment2), represented on the reference basis. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/segment2/transitFrom.js) @@ -8105,14 +8105,14 @@ transit the segment from the reference basis to the target basis.

Parameters:

- *seg* - - a segment2, represented on the reference basis. + - a [segment2](#affineplanesegment2), represented on the reference basis. - *target* - a [plane2](#affineplaneplane2), the target basis, represented on the reference basis.

Returns:

-- a segment2, represented in the target basis. +- a [segment2](#affineplanesegment2), represented in the target basis. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/segment2/transitTo.js) @@ -8120,8 +8120,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/seg ## [affineplane](#affineplane).[segment2](#affineplanesegment2).[validate](#affineplanesegment2validate)(seg) -Check if the object is a valid segment2. -A valid segment2 is an array of two valid [point2](#affineplanepoint2) objects. +Check if the object is a valid [segment2](#affineplanesegment2). +A valid [segment2](#affineplanesegment2) is an array of two valid [point2](#affineplanepoint2) objects.

Parameters:

@@ -8506,9 +8506,9 @@ Test if two spheres are almost equal by the margin of tolerance.

Parameters:

- *c* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *d* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *tolerance* - optional number, default to [affineplane.epsilon](#affineplaneepsilon). Set to 0 for strict comparison. @@ -8527,12 +8527,12 @@ Get area of the sphere.

Parameters:

-- a sphere2 +- a [sphere2](#affineplanesphere2)

Returns:

-- a scalar2, a number +- a [scalar2](#affineplanescalar2), a number Source: [area.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/area.js) @@ -8545,9 +8545,9 @@ Detect collision between two spheres.

Parameters:

- *c* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *cc* - - a sphere2 + - a [sphere2](#affineplanesphere2)

Returns:

@@ -8565,12 +8565,12 @@ Copy a sphere object.

Parameters:

- *p* - - a sphere2 + - a [sphere2](#affineplanesphere2)

Returns:

-- a sphere2 +- a [sphere2](#affineplanesphere2) Source: [copy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/copy.js) @@ -8578,7 +8578,7 @@ Source: [copy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/ ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[create](#affineplanesphere2create)(x, y, r) -Create a sphere2 object. +Create a [sphere2](#affineplanesphere2) object.

Parameters:

@@ -8592,7 +8592,7 @@ Create a sphere2 object.

Returns:

-- a sphere2 +- a [sphere2](#affineplanesphere2) Source: [create.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/create.js) @@ -8606,14 +8606,14 @@ their surfaces. The gap is zero or negative when the spheres collide.

Parameters:

- *c* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *cc* - - a sphere2 or a [point2](#affineplanepoint2) + - a [sphere2](#affineplanesphere2) or a [point2](#affineplanepoint2)

Returns:

-- a scalar1, a number, the closest distance between the sphere surfaces. +- a [scalar1](#affineplanescalar1), a number, the closest distance between the sphere surfaces. Source: [gap.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/gap.js) @@ -8626,7 +8626,7 @@ Detect collision between a sphere and a point.

Parameters:

- *c* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *point* - a [point2](#affineplanepoint2) @@ -8648,7 +8648,7 @@ so that the pivot point stays fixed.

Parameters:

- *sphere* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *origin* - a [point2](#affineplanepoint2), the transform origin, the pivot point - *ratio* @@ -8657,7 +8657,7 @@ so that the pivot point stays fixed.

Returns:

-- a sphere2 +- a [sphere2](#affineplanesphere2) Aliases: [affineplane.sphere2.scaleBy](#affineplanesphere2scaleby) @@ -8673,7 +8673,7 @@ See [affineplane.sphere2](#affineplanesphere2).translate to offset by a vector.

Parameters:

- *c* - - a sphere2 + - a [sphere2](#affineplanesphere2) - *dx* - a number, an offset along x-axis. - *dy* @@ -8682,7 +8682,7 @@ See [affineplane.sphere2](#affineplanesphere2).translate to offset by a vector.

Returns:

-- a sphere2, translated +- a [sphere2](#affineplanesphere2), translated Source: [offset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/offset.js) @@ -8697,20 +8697,20 @@ Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[transitFrom](#affineplanesphere2transitfrom)(sphere, source) -Transit a sphere2 from the source plane +Transit a [sphere2](#affineplanesphere2) from the source plane to the reference plane.

Parameters:

- *sphere* - - a sphere2 on the source plane. + - a [sphere2](#affineplanesphere2) on the source plane. - *source* - a [plane2](#affineplaneplane2), the source plane, represented on the reference plane.

Returns:

-- a sphere2, represented on the reference plane. +- a [sphere2](#affineplanesphere2), represented on the reference plane. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/transitFrom.js) @@ -8718,21 +8718,21 @@ Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/s ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[transitTo](#affineplanesphere2transitto)(sphere, target) -Transit a sphere2 to a target plane. +Transit a [sphere2](#affineplanesphere2) to a target plane. In other words, represent the sphere in the coordinate system of the target plane.

Parameters:

- *sphere* - - a sphere2 on the reference plane. + - a [sphere2](#affineplanesphere2) on the reference plane. - *target* - a [plane2](#affineplaneplane2), the target plane, represented on the reference plane.

Returns:

-- a sphere2, represented on the target plane. +- a [sphere2](#affineplanesphere2), represented on the target plane. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/transitTo.js) @@ -8740,8 +8740,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[validate](#affineplanesphere2validate)(p) -Check if the object is a valid sphere2. -A valid sphere2 has x, y, r properties that are valid numbers. +Check if the object is a valid [sphere2](#affineplanesphere2). +A valid [sphere2](#affineplanesphere2) has x, y, r properties that are valid numbers.

Parameters:

@@ -8751,7 +8751,7 @@ A valid sphere2 has x, y, r properties that are valid numbers.

Returns:

-- a boolean, true if valid sphere2 +- a boolean, true if valid [sphere2](#affineplanesphere2) Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/validate.js) @@ -8795,9 +8795,9 @@ Test if two spheres are almost equal by the margin of tolerance.

Parameters:

- *c* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *d* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *tolerance* - optional number, default to [affineplane.epsilon](#affineplaneepsilon). Set to 0 for strict comparison. @@ -8816,12 +8816,12 @@ Get surface area of the sphere.

Parameters:

-- a sphere3 +- a [sphere3](#affineplanesphere3)

Returns:

-- a scalar2, a number. The area. +- a [scalar2](#affineplanescalar2), a number. The area. Source: [area.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/area.js) @@ -8834,9 +8834,9 @@ Detect collision between two spheres.

Parameters:

- *c* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *cc* - - a sphere3 + - a [sphere3](#affineplanesphere3)

Returns:

@@ -8854,12 +8854,12 @@ Copy a sphere object.

Parameters:

- *p* - - a sphere3 + - a [sphere3](#affineplanesphere3)

Returns:

-- a sphere3 +- a [sphere3](#affineplanesphere3) Source: [copy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/copy.js) @@ -8867,7 +8867,7 @@ Source: [copy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/ ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[create](#affineplanesphere3create)(x, y, z, r) -Create a sphere3 object. +Create a [sphere3](#affineplanesphere3) object.

Parameters:

@@ -8883,7 +8883,7 @@ Create a sphere3 object.

Returns:

-- a sphere3 +- a [sphere3](#affineplanesphere3) Source: [create.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/create.js) @@ -8897,14 +8897,14 @@ their surfaces. The gap is zero or negative when the spheres collide.

Parameters:

- *c* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *cc* - - a sphere3 or a [point3](#affineplanepoint3) + - a [sphere3](#affineplanesphere3) or a [point3](#affineplanepoint3)

Returns:

-- a scalar1, a number, the closest distance between the sphere surfaces. +- a [scalar1](#affineplanescalar1), a number, the closest distance between the sphere surfaces. Source: [gap.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/gap.js) @@ -8917,7 +8917,7 @@ Detect collision between a sphere and a point.

Parameters:

- *c* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *point* - a [point2](#affineplanepoint2) @@ -8939,7 +8939,7 @@ so that the pivot point stays fixed.

Parameters:

- *sphere* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *origin* - a [point3](#affineplanepoint3), the transform origin, the pivot point - *ratio* @@ -8948,7 +8948,7 @@ so that the pivot point stays fixed.

Returns:

-- a sphere3 +- a [sphere3](#affineplanesphere3) Aliases: [affineplane.sphere3.scaleBy](#affineplanesphere3scaleby) @@ -8964,7 +8964,7 @@ See [affineplane.sphere3](#affineplanesphere3).translate to offset by a vector.

Parameters:

- *c* - - a sphere3 + - a [sphere3](#affineplanesphere3) - *dx* - a number, an offset along x-axis. - *dy* @@ -8975,7 +8975,7 @@ See [affineplane.sphere3](#affineplanesphere3).translate to offset by a vector.

Returns:

-- a sphere3, translated +- a [sphere3](#affineplanesphere3), translated Source: [offset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/offset.js) @@ -8996,7 +8996,7 @@ If the camera is undefined, project orthogonally.

Parameters:

- *sphere* - - a sphere3 in the reference space. + - a [sphere3](#affineplanesphere3) in the reference space. - *plane* - a [plane3](#affineplaneplane3) in the reference space. The target plane. - *camera* @@ -9005,7 +9005,7 @@ If the camera is undefined, project orthogonally.

Returns:

-- a sphere2 on the target plane. +- a [sphere2](#affineplanesphere2) on the target plane. Aliases: [affineplane.sphere3.projectTo](#affineplanesphere3projectto) @@ -9022,20 +9022,20 @@ Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[transitFrom](#affineplanesphere3transitfrom)(sphere, source) -Transit a sphere3 from the source plane +Transit a [sphere3](#affineplanesphere3) from the source plane to the reference plane.

Parameters:

- *sphere* - - a sphere3 on the source plane. + - a [sphere3](#affineplanesphere3) on the source plane. - *source* - a [plane3](#affineplaneplane3), the source plane, represented on the reference plane.

Returns:

-- a sphere3, represented on the reference plane. +- a [sphere3](#affineplanesphere3), represented on the reference plane. Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/transitFrom.js) @@ -9043,21 +9043,21 @@ Source: [transitFrom.js](https://github.com/axelpale/affineplane/blob/main/lib/s ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[transitTo](#affineplanesphere3transitto)(sphere, target) -Transit a sphere3 to a target plane. +Transit a [sphere3](#affineplanesphere3) to a target plane. In other words, represent the sphere in the coordinate system of the target plane.

Parameters:

- *sphere* - - a sphere3 on the reference plane. + - a [sphere3](#affineplanesphere3) on the reference plane. - *target* - a [plane3](#affineplaneplane3), the target plane, represented on the reference plane.

Returns:

-- a sphere3, represented on the target plane. +- a [sphere3](#affineplanesphere3), represented on the target plane. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/transitTo.js) @@ -9065,8 +9065,8 @@ Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[validate](#affineplanesphere3validate)(p) -Check if the object is a valid sphere3. -A valid sphere3 has x, y, z, r properties that are valid numbers. +Check if the object is a valid [sphere3](#affineplanesphere3). +A valid [sphere3](#affineplanesphere3) has x, y, z, r properties that are valid numbers.

Parameters:

@@ -9076,7 +9076,7 @@ A valid sphere3 has x, y, z, r properties that are valid numbers.

Returns:

-- a boolean, true if valid sphere3 +- a boolean, true if valid [sphere3](#affineplanesphere3) Source: [validate.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/validate.js) @@ -9088,12 +9088,12 @@ Get volume of the sphere.

Parameters:

-- a sphere3 +- a [sphere3](#affineplanesphere3)

Returns:

-- a scalar3, a number. The volume. +- a [scalar3](#affineplanescalar3), a number. The volume. Source: [volume.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/volume.js) diff --git a/docs/generate.js b/docs/generate.js index a69c5ecb..57ac0e33 100644 --- a/docs/generate.js +++ b/docs/generate.js @@ -76,8 +76,14 @@ yamdog.generate({ poly2: '#affineplanepoly2', quat4: '#affineplanequat4', rot2: '#affineplanerot2', + scalar1: '#affineplanescalar1', + scalar2: '#affineplanescalar2', + scalar3: '#affineplanescalar3', + segment2: '#affineplanesegment2', size2: '#affineplanesize2', size3: '#affineplanesize3', + sphere2: '#affineplanesphere2', + sphere3: '#affineplanesphere3', vec2: '#affineplanevec2', vec3: '#affineplanevec3', vec4: '#affineplanevec4', From cc6b8d0f3972b766892700b6dd0073fffad4e325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 02:11:30 +0200 Subject: [PATCH 02/26] improve point3.rotateBy docs --- lib/point3/rotateBy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/point3/rotateBy.js b/lib/point3/rotateBy.js index 95eb341f..19d2f49e 100644 --- a/lib/point3/rotateBy.js +++ b/lib/point3/rotateBy.js @@ -1,5 +1,5 @@ module.exports = function (p, origin, roll, pitch) { - // @affineplane.point3.rotateBy(p, origin, roll, pitch) + // @affineplane.point3.rotateBy(p, origin, roll[, pitch]) // // Rotate point around the given center point. // Roll is applied before pitch. From 41e038ac122501471377c9efabb6f2197bc7624b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 02:12:56 +0200 Subject: [PATCH 03/26] add missing sphere translate exports --- lib/sphere2/index.js | 1 + lib/sphere3/index.js | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index b7ef1ef2..f96a1e83 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -16,4 +16,5 @@ exports.offset = require('./offset') exports.scaleBy = exports.homothety exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') +exports.translate = require('./translate') exports.validate = require('./validate') diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index 327e524c..92049a28 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -18,5 +18,6 @@ exports.projectTo = exports.projectToPlane exports.scaleBy = exports.homothety exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') +exports.translate = require('./translate') exports.validate = require('./validate') exports.volume = require('./volume') From 6cb70f2390a123382e0535c2125e30e22bbdd10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 02:31:46 +0200 Subject: [PATCH 04/26] new test utility almostEqualSphere --- test/index.test.js | 1 + test/utils/almostEqualSphere.js | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/utils/almostEqualSphere.js diff --git a/test/index.test.js b/test/index.test.js index d2e0f437..bc97f4c1 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -47,6 +47,7 @@ test.Test.prototype.notAlmostEqual = require('./utils/notAlmostEqual') test.Test.prototype.transformEqual = require('./utils/transformEqual') test.Test.prototype.almostEqualBasis = require('./utils/almostEqualBasis') test.Test.prototype.almostEqualBox = require('./utils/almostEqualBox') +test.Test.prototype.almostEqualSphere = require('./utils/almostEqualSphere') test.Test.prototype.almostEqualVector = require('./utils/almostEqualVector') // Run test suite diff --git a/test/utils/almostEqualSphere.js b/test/utils/almostEqualSphere.js new file mode 100644 index 00000000..ed4be1a1 --- /dev/null +++ b/test/utils/almostEqualSphere.js @@ -0,0 +1,24 @@ +const sphere2 = require('../../lib/sphere2') +const sphere3 = require('../../lib/sphere3') + +module.exports = function (actual, expected, message) { + // Custom tape.js assertion. + + let isEqual = false + if (sphere3.validate(expected)) { + // Expect sphere3 + isEqual = sphere3.validate(actual) + isEqual = isEqual && sphere3.almostEqual(actual, expected) + } else if (sphere2.validate(expected)) { + // Expect sphere2 + isEqual = sphere2.validate(actual) + isEqual = isEqual && sphere2.almostEqual(actual, expected) + } + + this._assert(isEqual, { + message: message || 'sphere should have correct elements', + operator: 'almostEqualSphere', + actual, + expected + }) +} From 5a40fd3d9ea4de683643fc9c03fe1a2c0d09ee11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 02:32:07 +0200 Subject: [PATCH 05/26] implement sphere2.rotateBy --- lib/sphere2/index.js | 1 + lib/sphere2/rotateBy.js | 26 ++++++++++++++++++++++++++ test/sphere2/index.test.js | 1 + test/sphere2/rotateBy.test.js | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 lib/sphere2/rotateBy.js create mode 100644 test/sphere2/rotateBy.test.js diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index f96a1e83..72dbcca0 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -13,6 +13,7 @@ exports.gap = require('./gap') exports.hasPoint = require('./hasPoint') exports.homothety = require('./homothety') exports.offset = require('./offset') +exports.rotateBy = require('./rotateBy') exports.scaleBy = exports.homothety exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') diff --git a/lib/sphere2/rotateBy.js b/lib/sphere2/rotateBy.js new file mode 100644 index 00000000..8b70f1a3 --- /dev/null +++ b/lib/sphere2/rotateBy.js @@ -0,0 +1,26 @@ +const rotate = require('../point2/rotateBy') + +module.exports = function (sp, origin, radians) { + // @affineplane.sphere2.rotateBy(sp, origin, radians) + // + // Rotate a sphere about an origin point. + // + // Parameters + // sp + // a sphere2 + // origin + // a point2, the point around to rotate + // radians + // a number, angle in radians + // + // Return + // a sphere2, the rotated sphere + // + + // Reuse point rotation + const pole = rotate(sp, origin, radians) + // Patch radius + pole.r = sp.r + + return pole +} diff --git a/test/sphere2/index.test.js b/test/sphere2/index.test.js index 3838be0e..2c232dc0 100644 --- a/test/sphere2/index.test.js +++ b/test/sphere2/index.test.js @@ -6,6 +6,7 @@ const units = { hasPoint: require('./hasPoint.test'), homothety: require('./homothety.test'), offset: require('./offset.test'), + rotateBy: require('./rotateBy.test'), transitFrom: require('./transitFrom.test'), transitTo: require('./transitTo.test'), validate: require('./validate.test') diff --git a/test/sphere2/rotateBy.test.js b/test/sphere2/rotateBy.test.js new file mode 100644 index 00000000..99474ee2 --- /dev/null +++ b/test/sphere2/rotateBy.test.js @@ -0,0 +1,32 @@ +const sphere2 = require('../../lib/sphere2') +const PI = Math.PI + +module.exports = (ts) => { + ts.test('case: basic sphere rotate', (t) => { + t.deepEqual( + sphere2.rotateBy({ x: 0, y: 0, r: 0 }, { x: 0, y: 0 }, PI), + { x: 0, y: 0, r: 0 }, + 'origin at sphere center' + ) + + t.deepEqual( + sphere2.rotateBy({ x: 200, y: 200, r: 100 }, { x: 0, y: 0 }, 0), + { x: 200, y: 200, r: 100 }, + 'zero rotation should not alter' + ) + + t.almostEqualSphere( + sphere2.rotateBy({ x: 2, y: -2, r: 2 }, { x: 0, y: 0 }, PI), + { x: -2, y: 2, r: 2 }, + 'half turn around zero' + ) + + t.almostEqualSphere( + sphere2.rotateBy({ x: 2, y: 2, r: 2 }, { x: 2, y: 0 }, PI), + { x: 2, y: -2, r: 2 }, + 'half turn' + ) + + t.end() + }) +} From 753be5fdcd698fbf824ae4e0b08582aee787218b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 03:07:56 +0200 Subject: [PATCH 06/26] implement quat4.rotateVector --- lib/quat4/index.js | 1 + lib/quat4/rotateVector.js | 47 +++++++++++++++++++++++++++++++++ test/quat4/index.test.js | 3 ++- test/quat4/rotateVector.test.js | 38 ++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/quat4/rotateVector.js create mode 100644 test/quat4/rotateVector.test.js diff --git a/lib/quat4/index.js b/lib/quat4/index.js index c874b652..4de09c2e 100644 --- a/lib/quat4/index.js +++ b/lib/quat4/index.js @@ -13,3 +13,4 @@ exports.fromVector = require('./fromVector') exports.hamilton = require('./hamilton') exports.multiply = exports.hamilton exports.norm = require('./norm') +exports.rotateVector = require('./rotateVector') diff --git a/lib/quat4/rotateVector.js b/lib/quat4/rotateVector.js new file mode 100644 index 00000000..2901e5fa --- /dev/null +++ b/lib/quat4/rotateVector.js @@ -0,0 +1,47 @@ +module.exports = (quat, vec) => { + // @affineplane.quat4.rotateVector(quat, vec) + // + // Apply quaternion to rotate a vector. + // Note that the quaternion must rotate the vector twice to return it + // back to the 3D space. Therefore, if the quaternion was created using + // an angle like π/2, the vector will be rotated twice that amount, π. + // + // Parameters: + // quat + // a quat4, a quaternion. + // vec + // a vec3, the vector to rotate + // + // Return + // a vec3, the rotated vector. + // + + const a = quat.a + const b = quat.b + const c = quat.c + const d = quat.d + + const s = 2 / (a * a + b * b + c * c + d * d) + const bs = b * s + const cs = c * s + const ds = d * s + const ab = a * bs + const ac = a * cs + const ad = a * ds + const bb = b * bs + const bc = b * cs + const bd = b * ds + const cc = c * cs + const cd = c * ds + const dd = d * ds + + const x = vec.x + const y = vec.y + const z = vec.z + + return { + x: x * (1 - cc - dd) + y * (bc - ad) + z * (bd + ac), + y: x * (bc + ad) + y * (1 - bb - dd) + z * (cd - ab), + z: x * (bd - ac) + y * (cd + ab) + z * (1 - bb - cc) + } +} diff --git a/test/quat4/index.test.js b/test/quat4/index.test.js index 8b6d14aa..ee80f69f 100644 --- a/test/quat4/index.test.js +++ b/test/quat4/index.test.js @@ -6,7 +6,8 @@ const units = { fromAxisAngle: require('./fromAxisAngle.test'), fromVector: require('./fromVector.test'), hamilton: require('./hamilton.test'), - norm: require('./norm.test') + norm: require('./norm.test'), + rotateVector: require('./rotateVector.test') } module.exports = (t) => { diff --git a/test/quat4/rotateVector.test.js b/test/quat4/rotateVector.test.js new file mode 100644 index 00000000..08221c0a --- /dev/null +++ b/test/quat4/rotateVector.test.js @@ -0,0 +1,38 @@ +const affineplane = require('../../index') +const quat4 = affineplane.quat4 +const PI = Math.PI + +module.exports = (ts) => { + ts.test('case: basic rotateVector', (t) => { + let quat, vec + + quat = quat4.fromAxisAngle({ x: 1, y: 0, z: 0 }, PI / 4) + vec = { x: 0, y: 1, z: 0 } + + t.almostEqualVector( + quat4.rotateVector(quat, vec), + { x: 0, y: 0, z: 1 }, + 'should rotate 90 deg' + ) + + quat = quat4.fromAxisAngle({ x: 1, y: 1, z: 0 }, PI / 4) + vec = { x: 1, y: -1, z: 0 } + + t.almostEqualVector( + quat4.rotateVector(quat, vec), + { x: 0, y: 0, z: -Math.sqrt(2) }, + 'should rotate 90 deg awry' + ) + + quat = quat4.fromAxisAngle({ x: 1, y: 1, z: 0 }, PI / 4) + vec = { x: 1, y: 1, z: 0 } + + t.almostEqualVector( + quat4.rotateVector(quat, vec), + { x: 1, y: 1, z: 0 }, + 'should not rotate parallel' + ) + + t.end() + }) +} From 69995abfbce7523ee852e912b92646bda1c474ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 03:22:06 +0200 Subject: [PATCH 07/26] implement sphere3.rotateAroundLine --- lib/sphere3/index.js | 1 + lib/sphere3/rotateAroundLine.js | 35 +++++++++++++++++++++++++++ test/sphere3/index.test.js | 1 + test/sphere3/rotateAroundLine.test.js | 30 +++++++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 lib/sphere3/rotateAroundLine.js create mode 100644 test/sphere3/rotateAroundLine.test.js diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index 92049a28..24cbc519 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -15,6 +15,7 @@ exports.homothety = require('./homothety') exports.offset = require('./offset') exports.projectToPlane = require('./projectToPlane') exports.projectTo = exports.projectToPlane +exports.rotateAroundLine = require('./rotateAroundLine') exports.scaleBy = exports.homothety exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') diff --git a/lib/sphere3/rotateAroundLine.js b/lib/sphere3/rotateAroundLine.js new file mode 100644 index 00000000..4db34e78 --- /dev/null +++ b/lib/sphere3/rotateAroundLine.js @@ -0,0 +1,35 @@ +const fromAxisAngle = require('../quat4/fromAxisAngle') +const rotateVector = require('../quat4/rotateVector') +const pointDiff = require('../point3/difference') +const pointTranslate = require('../point3/translate') + +module.exports = function (sp, line, rads) { + // @affineplane.sphere3.rotateAroundLine(sp, line, rads) + // + // Rotate a sphere around the axis line by the given radians. + // + // Parameters + // sp + // a sphere3 + // line + // a line3, the rotation axis + // rads + // a number, angle in radians + // + // Return + // a sphere3, the rotated sphere + // + + // Convert to quaternion, note halved angle cuz will double. + const q = fromAxisAngle(line.span, rads / 2) + // Construct a vector to rotate. + const v = pointDiff(line.origin, sp) + const vv = rotateVector(q, v) + // Apply the rotated vector to origin + const p = pointTranslate(line.origin, vv) + + // Patch radius + p.r = sp.r + + return p +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index 28a570bd..15087855 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -7,6 +7,7 @@ const units = { homothety: require('./homothety.test'), offset: require('./offset.test'), projectToPlane: require('./projectToPlane.test'), + rotateAroundLine: require('./rotateAroundLine.test'), transitFrom: require('./transitFrom.test'), transitTo: require('./transitTo.test'), validate: require('./validate.test'), diff --git a/test/sphere3/rotateAroundLine.test.js b/test/sphere3/rotateAroundLine.test.js new file mode 100644 index 00000000..fde2824c --- /dev/null +++ b/test/sphere3/rotateAroundLine.test.js @@ -0,0 +1,30 @@ +const sphere3 = require('../../lib/sphere3') +const PI = Math.PI + +module.exports = (ts) => { + ts.test('case: basic rotate', (t) => { + let sphere, origin, span, line + + sphere = { x: 0, y: 0, z: 0, r: 0 } + origin = { x: 0, y: 0, z: 0 } + span = { x: 0, y: 0, z: 0 } + line = { origin, span } + t.deepEqual( + sphere3.rotateAroundLine(sphere, line, 0), + { x: 0, y: 0, z: 0, r: 0 }, + 'trivial zero' + ) + + sphere = { x: 0, y: 0, z: 2, r: 1 } + origin = { x: 0, y: 0, z: 1 } + span = { x: 0, y: 1, z: 0 } + line = { origin, span } + t.almostEqualSphere( + sphere3.rotateAroundLine(sphere, line, PI), + { x: 0, y: 0, z: 0, r: 1 }, + 'should rotate to zero around vertical line' + ) + + t.end() + }) +} From 2fa5f0490cb5c3df1577093cac5229361c87cb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 03:37:27 +0200 Subject: [PATCH 08/26] add algorithm source info --- lib/quat4/rotateVector.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/quat4/rotateVector.js b/lib/quat4/rotateVector.js index 2901e5fa..4a5d7ed8 100644 --- a/lib/quat4/rotateVector.js +++ b/lib/quat4/rotateVector.js @@ -21,6 +21,8 @@ module.exports = (quat, vec) => { const c = quat.c const d = quat.d + // Rotation matrix construction. + // Algorithm from A.Watt and M.Watt 1992 via Wikipedia. const s = 2 / (a * a + b * b + c * c + d * d) const bs = b * s const cs = c * s From a272d47899d24931a9a5915e404ebd09b6e27e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 03:38:10 +0200 Subject: [PATCH 09/26] new test utility almostEqualPoint --- test/index.test.js | 1 + test/utils/almostEqualPoint.js | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/utils/almostEqualPoint.js diff --git a/test/index.test.js b/test/index.test.js index bc97f4c1..886aea07 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -47,6 +47,7 @@ test.Test.prototype.notAlmostEqual = require('./utils/notAlmostEqual') test.Test.prototype.transformEqual = require('./utils/transformEqual') test.Test.prototype.almostEqualBasis = require('./utils/almostEqualBasis') test.Test.prototype.almostEqualBox = require('./utils/almostEqualBox') +test.Test.prototype.almostEqualPoint = require('./utils/almostEqualPoint') test.Test.prototype.almostEqualSphere = require('./utils/almostEqualSphere') test.Test.prototype.almostEqualVector = require('./utils/almostEqualVector') diff --git a/test/utils/almostEqualPoint.js b/test/utils/almostEqualPoint.js new file mode 100644 index 00000000..38d16973 --- /dev/null +++ b/test/utils/almostEqualPoint.js @@ -0,0 +1,24 @@ +const point2 = require('../../lib/point2') +const point3 = require('../../lib/point3') + +module.exports = function (actual, expected, message) { + // Custom tape.js assertion. + + let isEqual = false + if (point3.validate(expected)) { + // Expect point3 + isEqual = point3.validate(actual) + isEqual = isEqual && point3.almostEqual(actual, expected) + } else if (point2.validate(expected)) { + // Expect point2 + isEqual = point2.validate(actual) + isEqual = isEqual && point2.almostEqual(actual, expected) + } + + this._assert(isEqual, { + message: message || 'point should have correct elements', + operator: 'almostEqualPoint', + actual, + expected + }) +} From f8db544626ebc70110ced4622890e309e985b299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Sun, 12 Mar 2023 03:39:19 +0200 Subject: [PATCH 10/26] implement point3.rotateAroundLine --- lib/point3/index.js | 1 + lib/point3/rotateAroundLine.js | 32 ++++++++++++++++++++++++++++ test/point3/index.test.js | 1 + test/point3/rotateAroundLine.test.js | 30 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 lib/point3/rotateAroundLine.js create mode 100644 test/point3/rotateAroundLine.test.js diff --git a/lib/point3/index.js b/lib/point3/index.js index 3b725a82..2079b605 100644 --- a/lib/point3/index.js +++ b/lib/point3/index.js @@ -24,6 +24,7 @@ exports.offset = require('./offset') exports.polarOffset = require('./polarOffset') exports.projectToPlane = require('./projectToPlane') exports.projectTo = exports.projectToPlane +exports.rotateAroundLine = require('./rotateAroundLine') exports.rotateBy = require('./rotateBy') exports.round = require('./round') exports.toArray = require('./toArray') diff --git a/lib/point3/rotateAroundLine.js b/lib/point3/rotateAroundLine.js new file mode 100644 index 00000000..a87c5d23 --- /dev/null +++ b/lib/point3/rotateAroundLine.js @@ -0,0 +1,32 @@ +const fromAxisAngle = require('../quat4/fromAxisAngle') +const rotateVector = require('../quat4/rotateVector') +const pointDiff = require('./difference') +const pointTranslate = require('./translate') + +module.exports = function (p, line, rads) { + // @affineplane.point3.rotateAroundLine(p, line, rads) + // + // Rotate a point around the axis line by the given radians. + // + // Parameters + // p + // a point3 + // line + // a line3, the rotation axis + // rads + // a number, angle in radians + // + // Return + // a point3, the rotated point + // + + // Convert to quaternion, note halved angle cuz will double. + const q = fromAxisAngle(line.span, rads / 2) + // Construct a vector to rotate. + const v = pointDiff(line.origin, p) + const vv = rotateVector(q, v) + // Apply the rotated vector to origin + const pp = pointTranslate(line.origin, vv) + + return pp +} diff --git a/test/point3/index.test.js b/test/point3/index.test.js index a3138072..3d2b081e 100644 --- a/test/point3/index.test.js +++ b/test/point3/index.test.js @@ -12,6 +12,7 @@ const units = { offset: require('./offset.test'), polarOffset: require('./polarOffset.test'), projectToPlane: require('./projectToPlane.test'), + rotateAroundLine: require('./rotateAroundLine.test'), rotateBy: require('./rotateBy.test'), round: require('./round.test'), toArray: require('./toArray.test'), diff --git a/test/point3/rotateAroundLine.test.js b/test/point3/rotateAroundLine.test.js new file mode 100644 index 00000000..7cc82152 --- /dev/null +++ b/test/point3/rotateAroundLine.test.js @@ -0,0 +1,30 @@ +const point3 = require('../../lib/point3') +const PI = Math.PI + +module.exports = (ts) => { + ts.test('case: basic rotate', (t) => { + let point, origin, span, line + + point = { x: 0, y: 0, z: 0 } + origin = { x: 0, y: 0, z: 0 } + span = { x: 0, y: 0, z: 0 } + line = { origin, span } + t.deepEqual( + point3.rotateAroundLine(point, line, 0), + { x: 0, y: 0, z: 0 }, + 'trivial zero' + ) + + point = { x: 0, y: 0, z: 2 } + origin = { x: 0, y: 0, z: 1 } + span = { x: 0, y: 1, z: 0 } + line = { origin, span } + t.almostEqualPoint( + point3.rotateAroundLine(point, line, PI), + { x: 0, y: 0, z: 0 }, + 'should rotate to zero around vertical line' + ) + + t.end() + }) +} From 6ce1472713ff2acbc85b85066251044894e6de85 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:10:49 +0200 Subject: [PATCH 11/26] implement sphere3.rotateBy --- lib/sphere3/index.js | 1 + lib/sphere3/rotateBy.js | 28 ++++++++++++++++++++++++++++ test/sphere3/index.test.js | 1 + test/sphere3/rotateBy.test.js | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 lib/sphere3/rotateBy.js create mode 100644 test/sphere3/rotateBy.test.js diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index 24cbc519..93172e53 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -16,6 +16,7 @@ exports.offset = require('./offset') exports.projectToPlane = require('./projectToPlane') exports.projectTo = exports.projectToPlane exports.rotateAroundLine = require('./rotateAroundLine') +exports.rotateBy = require('./rotateBy') exports.scaleBy = exports.homothety exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') diff --git a/lib/sphere3/rotateBy.js b/lib/sphere3/rotateBy.js new file mode 100644 index 00000000..ba652649 --- /dev/null +++ b/lib/sphere3/rotateBy.js @@ -0,0 +1,28 @@ +const rotate = require('../point3/rotateBy') + +module.exports = function (sp, origin, radians) { + // @affineplane.sphere3.rotateBy(sp, origin, radians) + // + // Rotate a sphere about a line parallel to z-axis that goes through + // the origin point. The rotation direction follows the right hand rule + // about the positive z-axis. + // + // Parameters + // sp + // a sphere3 + // origin + // a point3, the point that defines the line around which to rotate + // radians + // a number, angle in radians + // + // Return + // a sphere3, the rotated sphere + // + + // Reuse point rotation + const pole = rotate(sp, origin, radians) + // Patch radius + pole.r = sp.r + + return pole +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index 15087855..00b64a1a 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -8,6 +8,7 @@ const units = { offset: require('./offset.test'), projectToPlane: require('./projectToPlane.test'), rotateAroundLine: require('./rotateAroundLine.test'), + rotateBy: require('./rotateBy.test'), transitFrom: require('./transitFrom.test'), transitTo: require('./transitTo.test'), validate: require('./validate.test'), diff --git a/test/sphere3/rotateBy.test.js b/test/sphere3/rotateBy.test.js new file mode 100644 index 00000000..916d71be --- /dev/null +++ b/test/sphere3/rotateBy.test.js @@ -0,0 +1,34 @@ +const sphere3 = require('../../lib/sphere3') +const PI = Math.PI + +module.exports = (ts) => { + ts.test('case: basic rotate by z', (t) => { + let sphere, origin + + sphere = { x: 0, y: 0, z: 0, r: 0 } + origin = { x: 0, y: 0, z: 0 } + t.deepEqual( + sphere3.rotateBy(sphere, origin, 0), + { x: 0, y: 0, z: 0, r: 0 }, + 'trivial zero' + ) + + sphere = { x: 0, y: 0, z: 2, r: 1 } + origin = { x: 0, y: 0, z: 1 } + t.almostEqualSphere( + sphere3.rotateBy(sphere, origin, PI), + { x: 0, y: 0, z: 2, r: 1 }, + 'should rotate around z axis, same origin' + ) + + sphere = { x: 0, y: 0, z: 2, r: 1 } + origin = { x: 0, y: 2, z: 1 } + t.almostEqualSphere( + sphere3.rotateBy(sphere, origin, PI), + { x: 0, y: 4, z: 2, r: 1 }, + 'should rotate around z axis' + ) + + t.end() + }) +} From 68b2925b87e2e53609866577fd43234949391eb6 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:30:46 +0200 Subject: [PATCH 12/26] upgrade nodemon --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4295d4e2..85fdfcfe 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "devDependencies": { "async": "^3.2.4", "genversion": "^3.1.1", - "nodemon": "^2.0.20", + "nodemon": "^2.0.21", "standard": "^17.0.0", "tap-arc": "^0.3.5", "tape": "^5.6.3", From 6c857a2733ece505890c0600e075995215ca4297 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:34:31 +0200 Subject: [PATCH 13/26] implement sphere2.boundingBox --- lib/sphere2/boundingBox.js | 21 +++++++++++++++++++++ lib/sphere2/index.js | 1 + test/sphere2/boundingBox.test.js | 19 +++++++++++++++++++ test/sphere2/index.test.js | 1 + 4 files changed, 42 insertions(+) create mode 100644 lib/sphere2/boundingBox.js create mode 100644 test/sphere2/boundingBox.test.js diff --git a/lib/sphere2/boundingBox.js b/lib/sphere2/boundingBox.js new file mode 100644 index 00000000..5d3a537e --- /dev/null +++ b/lib/sphere2/boundingBox.js @@ -0,0 +1,21 @@ +module.exports = (sphere) => { + // @affineplane.sphere2.boundingBox(sphere) + // + // Get outer rectangular boundary of the given sphere. + // + // Parameters + // sphere + // a sphere2, in the reference basis. + // + // Return + // a box2, in the reference basis. + // + + const r = sphere.r + const bx = sphere.x - r + const by = sphere.y - r + const dia = r + r + + // Construct the bounding rect. + return { a: 1, b: 0, x: bx, y: by, w: dia, h: dia } +} diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index 72dbcca0..bb49144b 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -6,6 +6,7 @@ // exports.almostEqual = require('./almostEqual') exports.area = require('./area') +exports.boundingBox = require('./boundingBox') exports.collide = require('./collide') exports.copy = require('./copy') exports.create = require('./create') diff --git a/test/sphere2/boundingBox.test.js b/test/sphere2/boundingBox.test.js new file mode 100644 index 00000000..2d19864b --- /dev/null +++ b/test/sphere2/boundingBox.test.js @@ -0,0 +1,19 @@ +const sphere2 = require('../../index').sphere2 + +module.exports = (ts) => { + ts.test('case: basic sphere bounding box', (t) => { + t.almostEqualBox( + sphere2.boundingBox({ x: 0, y: 0, r: 0 }), + { a: 1, b: 0, x: 0, y: 0, w: 0, h: 0 }, + 'trivial empty box' + ) + + t.almostEqualBox( + sphere2.boundingBox({ x: 2, y: 2, r: 2 }), + { a: 1, b: 0, x: 0, y: 0, w: 4, h: 4 }, + 'should have size double the radius' + ) + + t.end() + }) +} diff --git a/test/sphere2/index.test.js b/test/sphere2/index.test.js index 2c232dc0..181b17f7 100644 --- a/test/sphere2/index.test.js +++ b/test/sphere2/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + boundingBox: require('./boundingBox.test'), collide: require('./collide.test'), gap: require('./gap.test'), hasPoint: require('./hasPoint.test'), From 2afa6b5bf59e987fd19b3defcc547f54c44aa45e Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:34:41 +0200 Subject: [PATCH 14/26] implement sphere3.boundingBox --- lib/sphere3/boundingBox.js | 22 ++++++++++++++++++++++ lib/sphere3/index.js | 1 + test/sphere3/boundingBox.test.js | 19 +++++++++++++++++++ test/sphere3/index.test.js | 1 + 4 files changed, 43 insertions(+) create mode 100644 lib/sphere3/boundingBox.js create mode 100644 test/sphere3/boundingBox.test.js diff --git a/lib/sphere3/boundingBox.js b/lib/sphere3/boundingBox.js new file mode 100644 index 00000000..7ae654de --- /dev/null +++ b/lib/sphere3/boundingBox.js @@ -0,0 +1,22 @@ +module.exports = (sphere) => { + // @affineplane.sphere3.boundingBox(sphere) + // + // Get outer cuboid boundary of the given sphere. + // + // Parameters + // sphere + // a sphere3, in the reference basis. + // + // Return + // a box3, in the reference basis. + // + + const r = sphere.r + const bx = sphere.x - r + const by = sphere.y - r + const bz = sphere.z - r + const dia = r + r + + // Construct the bounding rect. + return { a: 1, b: 0, x: bx, y: by, z: bz, w: dia, h: dia, d: dia } +} diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index 93172e53..e79ea994 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -6,6 +6,7 @@ // exports.almostEqual = require('./almostEqual') exports.area = require('./area') +exports.boundingBox = require('./boundingBox') exports.collide = require('./collide') exports.copy = require('./copy') exports.create = require('./create') diff --git a/test/sphere3/boundingBox.test.js b/test/sphere3/boundingBox.test.js new file mode 100644 index 00000000..a10b7413 --- /dev/null +++ b/test/sphere3/boundingBox.test.js @@ -0,0 +1,19 @@ +const sphere3 = require('../../index').sphere3 + +module.exports = (ts) => { + ts.test('case: basic sphere bounding box', (t) => { + t.almostEqualBox( + sphere3.boundingBox({ x: 0, y: 0, z: 0, r: 0 }), + { a: 1, b: 0, x: 0, y: 0, z: 0, w: 0, h: 0, d: 0 }, + 'trivial empty box' + ) + + t.almostEqualBox( + sphere3.boundingBox({ x: 2, y: 2, z: 2, r: 2 }), + { a: 1, b: 0, x: 0, y: 0, z: 0, w: 4, h: 4, d: 4 }, + 'should have size double the radius' + ) + + t.end() + }) +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index 00b64a1a..9e0b9553 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + boundingBox: require('./boundingBox.test'), collide: require('./collide.test'), gap: require('./gap.test'), hasPoint: require('./hasPoint.test'), From a1fc8956ce5a9fef0b19f3e1d5a420a2a8f3bd81 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:59:26 +0200 Subject: [PATCH 15/26] implement sphere2.size --- lib/sphere2/index.js | 1 + lib/sphere2/size.js | 18 ++++++++++++++++++ test/sphere2/index.test.js | 1 + test/sphere2/size.test.js | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+) create mode 100644 lib/sphere2/size.js create mode 100644 test/sphere2/size.test.js diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index bb49144b..0f05ea02 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -16,6 +16,7 @@ exports.homothety = require('./homothety') exports.offset = require('./offset') exports.rotateBy = require('./rotateBy') exports.scaleBy = exports.homothety +exports.size = require('./size') exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') exports.translate = require('./translate') diff --git a/lib/sphere2/size.js b/lib/sphere2/size.js new file mode 100644 index 00000000..4531bfb5 --- /dev/null +++ b/lib/sphere2/size.js @@ -0,0 +1,18 @@ +module.exports = (sphere) => { + // @affineplane.sphere2.size(sphere) + // + // Get the rectangular size of the circle. + // + // Parameters: + // sphere + // a sphere2 in the reference basis. + // + // Return + // a size2 in the reference basis. + // + const diam = sphere.r + sphere.r + return { + w: diam, + h: diam + } +} diff --git a/test/sphere2/index.test.js b/test/sphere2/index.test.js index 181b17f7..3393313c 100644 --- a/test/sphere2/index.test.js +++ b/test/sphere2/index.test.js @@ -8,6 +8,7 @@ const units = { homothety: require('./homothety.test'), offset: require('./offset.test'), rotateBy: require('./rotateBy.test'), + size: require('./size.test'), transitFrom: require('./transitFrom.test'), transitTo: require('./transitTo.test'), validate: require('./validate.test') diff --git a/test/sphere2/size.test.js b/test/sphere2/size.test.js new file mode 100644 index 00000000..b1a48297 --- /dev/null +++ b/test/sphere2/size.test.js @@ -0,0 +1,19 @@ +const sphere2 = require('../../index').sphere2 + +module.exports = (ts) => { + ts.test('case: basic sphere size', (t) => { + t.deepEqual( + sphere2.size({ x: 0, y: 0, r: 0 }), + { w: 0, h: 0 }, + 'trivial null circle' + ) + + t.deepEqual( + sphere2.size({ x: 2, y: 2, r: 2 }), + { w: 4, h: 4 }, + 'should have size double the radius' + ) + + t.end() + }) +} From 8f39e91fb23681cb606d484ca29d4081132176ed Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 14:59:47 +0200 Subject: [PATCH 16/26] implement sphere3.size --- lib/sphere3/index.js | 1 + lib/sphere3/size.js | 19 +++++++++++++++++++ test/sphere3/index.test.js | 1 + test/sphere3/size.test.js | 19 +++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 lib/sphere3/size.js create mode 100644 test/sphere3/size.test.js diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index e79ea994..c2b0e468 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -19,6 +19,7 @@ exports.projectTo = exports.projectToPlane exports.rotateAroundLine = require('./rotateAroundLine') exports.rotateBy = require('./rotateBy') exports.scaleBy = exports.homothety +exports.size = require('./size') exports.transitFrom = require('./transitFrom') exports.transitTo = require('./transitTo') exports.translate = require('./translate') diff --git a/lib/sphere3/size.js b/lib/sphere3/size.js new file mode 100644 index 00000000..c42b0711 --- /dev/null +++ b/lib/sphere3/size.js @@ -0,0 +1,19 @@ +module.exports = (sphere) => { + // @affineplane.sphere3.size(sphere) + // + // Get the cuboid size of the sphere. + // + // Parameters: + // sphere + // a sphere3 in the reference basis. + // + // Return + // a size3 in the reference basis. + // + const diam = sphere.r + sphere.r + return { + w: diam, + h: diam, + d: diam + } +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index 9e0b9553..ebc1eea3 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -10,6 +10,7 @@ const units = { projectToPlane: require('./projectToPlane.test'), rotateAroundLine: require('./rotateAroundLine.test'), rotateBy: require('./rotateBy.test'), + size: require('./size.test'), transitFrom: require('./transitFrom.test'), transitTo: require('./transitTo.test'), validate: require('./validate.test'), diff --git a/test/sphere3/size.test.js b/test/sphere3/size.test.js new file mode 100644 index 00000000..92a16204 --- /dev/null +++ b/test/sphere3/size.test.js @@ -0,0 +1,19 @@ +const sphere3 = require('../../index').sphere3 + +module.exports = (ts) => { + ts.test('case: basic sphere size', (t) => { + t.deepEqual( + sphere3.size({ x: 0, y: 0, z: 0, r: 0 }), + { w: 0, h: 0, d: 0 }, + 'trivial null sphere' + ) + + t.deepEqual( + sphere3.size({ x: 2, y: 2, z: 2, r: 2 }), + { w: 4, h: 4, d: 4 }, + 'should have size double the radius' + ) + + t.end() + }) +} From 4cb5e34fe1eb31832c7ae67f91d08b49f3774016 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 20:00:51 +0200 Subject: [PATCH 17/26] implement sphere2 sphere3 .atCenter --- lib/sphere2/atCenter.js | 17 +++++++++++++++++ lib/sphere2/index.js | 1 + lib/sphere3/atCenter.js | 18 ++++++++++++++++++ lib/sphere3/index.js | 1 + test/sphere2/atCenter.test.js | 19 +++++++++++++++++++ test/sphere2/index.test.js | 1 + test/sphere3/atCenter.test.js | 19 +++++++++++++++++++ test/sphere3/index.test.js | 1 + 8 files changed, 77 insertions(+) create mode 100644 lib/sphere2/atCenter.js create mode 100644 lib/sphere3/atCenter.js create mode 100644 test/sphere2/atCenter.test.js create mode 100644 test/sphere3/atCenter.test.js diff --git a/lib/sphere2/atCenter.js b/lib/sphere2/atCenter.js new file mode 100644 index 00000000..7ee95b8a --- /dev/null +++ b/lib/sphere2/atCenter.js @@ -0,0 +1,17 @@ +module.exports = (sp) => { + // @affineplane.sphere2.atCenter(sp) + // + // Get the center point of the sphere. + // Note that the sphere2 object itself can act as a point2 in many cases. + // + // Parameters: + // a sphere2 + // + // Return + // a point2 + // + return { + x: sp.x, + y: sp.y + } +} diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index 0f05ea02..729d0dca 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -6,6 +6,7 @@ // exports.almostEqual = require('./almostEqual') exports.area = require('./area') +exports.atCenter = require('./atCenter') exports.boundingBox = require('./boundingBox') exports.collide = require('./collide') exports.copy = require('./copy') diff --git a/lib/sphere3/atCenter.js b/lib/sphere3/atCenter.js new file mode 100644 index 00000000..b9b7c27d --- /dev/null +++ b/lib/sphere3/atCenter.js @@ -0,0 +1,18 @@ +module.exports = (sp) => { + // @affineplane.sphere3.atCenter(sp) + // + // Get the center point of the sphere. + // Note that the sphere3 object itself can act as a point3 in many cases. + // + // Parameters: + // a sphere3 + // + // Return + // a point3 + // + return { + x: sp.x, + y: sp.y, + z: sp.z + } +} diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index c2b0e468..3e3542fa 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -6,6 +6,7 @@ // exports.almostEqual = require('./almostEqual') exports.area = require('./area') +exports.atCenter = require('./atCenter') exports.boundingBox = require('./boundingBox') exports.collide = require('./collide') exports.copy = require('./copy') diff --git a/test/sphere2/atCenter.test.js b/test/sphere2/atCenter.test.js new file mode 100644 index 00000000..1f6d8359 --- /dev/null +++ b/test/sphere2/atCenter.test.js @@ -0,0 +1,19 @@ +const sphere2 = require('../../index').sphere2 + +module.exports = (ts) => { + ts.test('case: basic sphere center', (t) => { + t.deepEqual( + sphere2.atCenter({ x: 0, y: 0, r: 0 }), + { x: 0, y: 0 }, + 'trivial zero' + ) + + t.deepEqual( + sphere2.atCenter({ x: 2, y: 2, r: 2 }), + { x: 2, y: 2 }, + 'should have correct props' + ) + + t.end() + }) +} diff --git a/test/sphere2/index.test.js b/test/sphere2/index.test.js index 3393313c..f0a445d0 100644 --- a/test/sphere2/index.test.js +++ b/test/sphere2/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + atCenter: require('./atCenter.test'), boundingBox: require('./boundingBox.test'), collide: require('./collide.test'), gap: require('./gap.test'), diff --git a/test/sphere3/atCenter.test.js b/test/sphere3/atCenter.test.js new file mode 100644 index 00000000..2d7bacaa --- /dev/null +++ b/test/sphere3/atCenter.test.js @@ -0,0 +1,19 @@ +const sphere3 = require('../../index').sphere3 + +module.exports = (ts) => { + ts.test('case: basic sphere center', (t) => { + t.deepEqual( + sphere3.atCenter({ x: 0, y: 0, z: 0, r: 0 }), + { x: 0, y: 0, z: 0 }, + 'trivial zero' + ) + + t.deepEqual( + sphere3.atCenter({ x: 2, y: 2, z: 2, r: 2 }), + { x: 2, y: 2, z: 2 }, + 'should have correct props' + ) + + t.end() + }) +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index ebc1eea3..6bb8206f 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + atCenter: require('./atCenter.test'), boundingBox: require('./boundingBox.test'), collide: require('./collide.test'), gap: require('./gap.test'), From ffc5dad91a75a9e758d69ebea0897a0749682e6e Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 20:10:45 +0200 Subject: [PATCH 18/26] implement plane2.at --- lib/plane2/at.js | 21 +++++++++++++++++++++ lib/plane2/index.js | 1 + test/plane2/at.test.js | 23 +++++++++++++++++++++++ test/plane2/index.test.js | 1 + 4 files changed, 46 insertions(+) create mode 100644 lib/plane2/at.js create mode 100644 test/plane2/at.test.js diff --git a/lib/plane2/at.js b/lib/plane2/at.js new file mode 100644 index 00000000..2a04e9dd --- /dev/null +++ b/lib/plane2/at.js @@ -0,0 +1,21 @@ +module.exports = (plane, x, y) => { + // @affineplane.plane2.at(plane, x, y) + // + // Take a point on the plane and transit it to the reference basis. + // + // Parameters + // plane + // a plane2, in the reference basis. + // x + // a number, the horizontal coordinate on the plane + // y + // a number, the vertical coordinate on the plane + // + // Return + // a point2 in the reference basis. + // + return { + x: plane.a * x - plane.b * y + plane.x, + y: plane.b * x + plane.a * y + plane.y + } +} diff --git a/lib/plane2/index.js b/lib/plane2/index.js index a097a7dd..26770de8 100644 --- a/lib/plane2/index.js +++ b/lib/plane2/index.js @@ -27,6 +27,7 @@ exports.I = { a: 1, b: 0, x: 0, y: 0 } exports.IDENTITY = exports.I exports.almostEqual = require('./almostEqual') +exports.at = require('./at') exports.between = require('./difference') exports.clone = require('./copy') exports.combine = require('./compose') diff --git a/test/plane2/at.test.js b/test/plane2/at.test.js new file mode 100644 index 00000000..93f248ba --- /dev/null +++ b/test/plane2/at.test.js @@ -0,0 +1,23 @@ +const plane2 = require('../../lib/plane2') + +module.exports = (ts) => { + ts.test('case: basic at', (t) => { + let plane + + plane = { a: 1, b: 0, x: 0, y: 0 } + t.almostEqualPoint( + plane2.at(plane, 2, 2), + { x: 2, y: 2 }, + 'apply to identity' + ) + + plane = { a: 0, b: 2, x: 1, y: 2 } + t.almostEqualPoint( + plane2.at(plane, 3, 3), + { x: -5, y: 8 }, + 'should scale and rotate accordingly' + ) + + t.end() + }) +} diff --git a/test/plane2/index.test.js b/test/plane2/index.test.js index 98f1d984..fefebbdd 100644 --- a/test/plane2/index.test.js +++ b/test/plane2/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + at: require('./at.test'), compose: require('./compose.test'), copy: require('./copy.test'), create: require('./create.test'), From b51f4150bef21229aa30839935ad06871af0f845 Mon Sep 17 00:00:00 2001 From: Akseli Palen Date: Sun, 12 Mar 2023 20:17:35 +0200 Subject: [PATCH 19/26] implement plane3.at --- lib/plane3/at.js | 27 +++++++++++++++++++++++++++ lib/plane3/index.js | 1 + test/plane3/at.test.js | 23 +++++++++++++++++++++++ test/plane3/index.test.js | 1 + 4 files changed, 52 insertions(+) create mode 100644 lib/plane3/at.js create mode 100644 test/plane3/at.test.js diff --git a/lib/plane3/at.js b/lib/plane3/at.js new file mode 100644 index 00000000..10002ba6 --- /dev/null +++ b/lib/plane3/at.js @@ -0,0 +1,27 @@ +module.exports = (plane, x, y, z) => { + // @affineplane.plane3.at(plane, x, y, z) + // + // Take a point relative to the plane and transit it to the reference basis. + // + // Parameters + // plane + // a plane3, in the reference basis. + // x + // a number, the horizontal coordinate on the plane + // y + // a number, the vertical coordinate on the plane + // z + // a number, the depth offset relative to the plane + // + // Return + // a point3 in the reference basis. + // + const a = plane.a + const b = plane.b + const m = Math.sqrt(a * a + b * b) + return { + x: a * x - b * y + plane.x, + y: b * x + a * y + plane.y, + z: m * z + plane.z + } +} diff --git a/lib/plane3/index.js b/lib/plane3/index.js index 89b24993..4700aaee 100644 --- a/lib/plane3/index.js +++ b/lib/plane3/index.js @@ -27,6 +27,7 @@ exports.I = { a: 1, b: 0, x: 0, y: 0, z: 0 } exports.IDENTITY = exports.I exports.almostEqual = require('./almostEqual') +exports.at = require('./at') exports.between = require('./difference') exports.clone = require('./copy') exports.compose = require('./compose') diff --git a/test/plane3/at.test.js b/test/plane3/at.test.js new file mode 100644 index 00000000..f255e705 --- /dev/null +++ b/test/plane3/at.test.js @@ -0,0 +1,23 @@ +const plane3 = require('../../lib/plane3') + +module.exports = (ts) => { + ts.test('case: basic at', (t) => { + let plane + + plane = { a: 1, b: 0, x: 0, y: 0, z: 0 } + t.almostEqualPoint( + plane3.at(plane, 2, 2, 2), + { x: 2, y: 2, z: 2 }, + 'apply to identity' + ) + + plane = { a: 0, b: 2, x: 1, y: 2, z: 3 } + t.almostEqualPoint( + plane3.at(plane, 3, 3, 3), + { x: -5, y: 8, z: 9 }, + 'should scale and rotate accordingly' + ) + + t.end() + }) +} diff --git a/test/plane3/index.test.js b/test/plane3/index.test.js index afbe231e..3560b231 100644 --- a/test/plane3/index.test.js +++ b/test/plane3/index.test.js @@ -1,6 +1,7 @@ // A unit for each method. const units = { almostEqual: require('./almostEqual.test'), + at: require('./at.test'), compose: require('./compose.test'), copy: require('./copy.test'), create: require('./create.test'), From 52c8e1e7a150e4878a549d076d8124a19b2d6a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 00:49:56 +0200 Subject: [PATCH 20/26] improve vec3.rotateAroundAxis docs --- lib/vec3/rotateAroundAxis.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/vec3/rotateAroundAxis.js b/lib/vec3/rotateAroundAxis.js index 5ab1b2d9..1c04c531 100644 --- a/lib/vec3/rotateAroundAxis.js +++ b/lib/vec3/rotateAroundAxis.js @@ -14,10 +14,10 @@ module.exports = function (v, axis, angle) { // v // a vec3 // axis - // a vec3, must not be zero vector + // a vec3, must not be a zero vector // angle - // a number, an angle in radians. - // .. Right-hand rotation around the given axis. + // a number, an angle in radians. Rotation around the axis. + // .. Rotation direction follows the right-hand rule. // // Return // a vec3 From cd4870bb72081ae4011ab7da92fe5700291e1b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:17:29 +0200 Subject: [PATCH 21/26] implement sphere2 sphere3 .polarOffset --- lib/sphere2/index.js | 1 + lib/sphere2/polarOffset.js | 27 +++++++++++++++++++++ lib/sphere3/index.js | 1 + lib/sphere3/polarOffset.js | 41 ++++++++++++++++++++++++++++++++ test/sphere2/index.test.js | 1 + test/sphere2/polarOffset.test.js | 19 +++++++++++++++ test/sphere3/index.test.js | 1 + test/sphere3/polarOffset.test.js | 19 +++++++++++++++ 8 files changed, 110 insertions(+) create mode 100644 lib/sphere2/polarOffset.js create mode 100644 lib/sphere3/polarOffset.js create mode 100644 test/sphere2/polarOffset.test.js create mode 100644 test/sphere3/polarOffset.test.js diff --git a/lib/sphere2/index.js b/lib/sphere2/index.js index 729d0dca..1d6650f1 100644 --- a/lib/sphere2/index.js +++ b/lib/sphere2/index.js @@ -15,6 +15,7 @@ exports.gap = require('./gap') exports.hasPoint = require('./hasPoint') exports.homothety = require('./homothety') exports.offset = require('./offset') +exports.polarOffset = require('./polarOffset') exports.rotateBy = require('./rotateBy') exports.scaleBy = exports.homothety exports.size = require('./size') diff --git a/lib/sphere2/polarOffset.js b/lib/sphere2/polarOffset.js new file mode 100644 index 00000000..2056bfaa --- /dev/null +++ b/lib/sphere2/polarOffset.js @@ -0,0 +1,27 @@ +const sin = Math.sin +const cos = Math.cos + +module.exports = (sp, dist, theta) => { + // @affineplane.sphere2.polarOffset(sphere, distance, theta) + // + // Offset a sphere by the given distance towards the direction given by + // the theta angles. + // + // Parameters: + // sphere + // a sphere2 + // distance + // a number, the distance from p. + // theta + // a number, the angle around z-axis, the azimuthal angle. + // .. Clockwise rotation, following the right-hand rule. + // + // Return + // a sphere2 + // + return { + x: sp.x + dist * cos(theta), + y: sp.y + dist * sin(theta), + r: sp.r + } +} diff --git a/lib/sphere3/index.js b/lib/sphere3/index.js index 3e3542fa..83794355 100644 --- a/lib/sphere3/index.js +++ b/lib/sphere3/index.js @@ -15,6 +15,7 @@ exports.gap = require('./gap') exports.hasPoint = require('./hasPoint') exports.homothety = require('./homothety') exports.offset = require('./offset') +exports.polarOffset = require('./polarOffset') exports.projectToPlane = require('./projectToPlane') exports.projectTo = exports.projectToPlane exports.rotateAroundLine = require('./rotateAroundLine') diff --git a/lib/sphere3/polarOffset.js b/lib/sphere3/polarOffset.js new file mode 100644 index 00000000..820fac3e --- /dev/null +++ b/lib/sphere3/polarOffset.js @@ -0,0 +1,41 @@ +const sin = Math.sin +const cos = Math.cos + +module.exports = (sp, dist, theta, phi) => { + // @affineplane.sphere3.polarOffset(sphere, distance, theta[, phi]) + // + // Offset a sphere by the given distance towards the direction given by + // the spherical theta and phi angles. + // + // Parameters: + // sphere + // a sphere3 + // distance + // a number, the distance from p. + // theta + // a number, the angle around z-axis, the azimuthal angle. + // .. Clockwise rotation, following the right-hand rule. + // phi + // optional number, default π/2. The polar angle in radians + // .. measured from the positive z-axis. + // + // Return + // a sphere3 + // + + if (typeof phi !== 'number') { + return { + x: sp.x + dist * cos(theta), + y: sp.y + dist * sin(theta), + z: sp.z, + r: sp.r + } + } + + return { + x: sp.x + dist * cos(theta) * sin(phi), + y: sp.y + dist * sin(theta) * sin(phi), + z: sp.z + dist * cos(phi), + r: sp.r + } +} diff --git a/test/sphere2/index.test.js b/test/sphere2/index.test.js index f0a445d0..70a09961 100644 --- a/test/sphere2/index.test.js +++ b/test/sphere2/index.test.js @@ -8,6 +8,7 @@ const units = { hasPoint: require('./hasPoint.test'), homothety: require('./homothety.test'), offset: require('./offset.test'), + polarOffset: require('./polarOffset.test'), rotateBy: require('./rotateBy.test'), size: require('./size.test'), transitFrom: require('./transitFrom.test'), diff --git a/test/sphere2/polarOffset.test.js b/test/sphere2/polarOffset.test.js new file mode 100644 index 00000000..f172360c --- /dev/null +++ b/test/sphere2/polarOffset.test.js @@ -0,0 +1,19 @@ +const sphere2 = require('../../lib/sphere2') + +module.exports = (ts) => { + ts.test('case: basic polar offset', (t) => { + t.deepEqual( + sphere2.polarOffset({ x: 0, y: 0, r: 1 }, 1, 0), + { x: 1, y: 0, r: 1 }, + 'should move towards x' + ) + + t.deepEqual( + sphere2.polarOffset({ x: 3, y: -3, r: 2 }, 2, Math.PI / 2), + { x: 3, y: -1, r: 2 }, + 'should move towards y, keep radius' + ) + + t.end() + }) +} diff --git a/test/sphere3/index.test.js b/test/sphere3/index.test.js index 6bb8206f..e70880e5 100644 --- a/test/sphere3/index.test.js +++ b/test/sphere3/index.test.js @@ -8,6 +8,7 @@ const units = { hasPoint: require('./hasPoint.test'), homothety: require('./homothety.test'), offset: require('./offset.test'), + polarOffset: require('./polarOffset.test'), projectToPlane: require('./projectToPlane.test'), rotateAroundLine: require('./rotateAroundLine.test'), rotateBy: require('./rotateBy.test'), diff --git a/test/sphere3/polarOffset.test.js b/test/sphere3/polarOffset.test.js new file mode 100644 index 00000000..6762a912 --- /dev/null +++ b/test/sphere3/polarOffset.test.js @@ -0,0 +1,19 @@ +const sphere3 = require('../../lib/sphere3') + +module.exports = (ts) => { + ts.test('case: basic polar offset', (t) => { + t.deepEqual( + sphere3.polarOffset({ x: 0, y: 0, z: 0, r: 1 }, 1, 0), + { x: 1, y: 0, z: 0, r: 1 }, + 'should move towards x' + ) + + t.deepEqual( + sphere3.polarOffset({ x: 3, y: -3, z: 3, r: 1 }, 1, 2, 0), + { x: 3, y: -3, z: 4, r: 1 }, + 'should move towards z, theta does not matter' + ) + + t.end() + }) +} From 692e2b0ff9469ed3d9e7f7dcc2827e5be037ece6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:42:15 +0200 Subject: [PATCH 22/26] reserve geometry: range1 --- lib/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/index.js b/lib/index.js index 72e8085e..22cf0180 100644 --- a/lib/index.js +++ b/lib/index.js @@ -51,6 +51,8 @@ exports.plane3 = exports.basis3 exports.point2 = require('./point2') exports.point3 = require('./point3') +// TODO exports.range1 = require('./range1') + // TODO Ray. A line but into one direction only. // exports.ray3 = require('./ray3') From 650908053c13c4b73bfedb890de169a1e66cf9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:51:20 +0200 Subject: [PATCH 23/26] implement box3.collide --- lib/box3/collide.js | 39 +++++++++++++++++++++++++++++++++++++++ lib/box3/index.js | 1 + test/box3/collide.test.js | 28 ++++++++++++++++++++++++++++ test/box3/index.test.js | 1 + 4 files changed, 69 insertions(+) create mode 100644 lib/box3/collide.js create mode 100644 test/box3/collide.test.js diff --git a/lib/box3/collide.js b/lib/box3/collide.js new file mode 100644 index 00000000..71041d9f --- /dev/null +++ b/lib/box3/collide.js @@ -0,0 +1,39 @@ +const collide2 = require('../box2/collide') + +module.exports = function (b, bb) { + // @affineplane.box3.collide(b, bb) + // + // Test if the two boxes collide. + // The boxes collide when the intersection of their solid cuboids + // is not empty. + // + // Parameters: + // b + // a box3, in the reference basis + // bb + // a box3, in the reference basis + // + // Return: + // a boolean, true if boxes collide. + // + + // The box3 can rotate only around z. Therefore we check z-collision first + // and then proceed to more throughout 2D collision check. + + // Build ranges + const bmin = b.z + const bmax = b.z + b.d + const bbmin = bb.z + const bbmax = bb.z + bb.d + + // Range collision check. + if ((bmin >= bbmin && bmin <= bbmax) || + (bmax >= bbmin && bmax <= bbmax) || + (bmin <= bbmin && bmax >= bbmin) || + (bmin <= bbmax && bmax >= bbmax)) { + // assert: one of the range ends is in the other + return collide2(b, bb) + } + // Else the boxes cannot hit regardless the position and orientation. + return false +} diff --git a/lib/box3/index.js b/lib/box3/index.js index 2f9472bc..6523f42f 100644 --- a/lib/box3/index.js +++ b/lib/box3/index.js @@ -13,6 +13,7 @@ exports.almostEqual = require('./almostEqual') exports.at = require('./at') exports.atBox = require('./atBox') exports.atNorm = require('./atNorm') +exports.collide = require('./collide') exports.create = require('./create') exports.fromPoints = require('./fromPoints') exports.getAngle = require('./getAngle') diff --git a/test/box3/collide.test.js b/test/box3/collide.test.js new file mode 100644 index 00000000..3b86bdd6 --- /dev/null +++ b/test/box3/collide.test.js @@ -0,0 +1,28 @@ +const box3 = require('../../index').box3 + +module.exports = (ts) => { + ts.test('case: basic box collision', (t) => { + let b, bb + + b = { a: 1, b: 0, x: 1, y: 1, z: 1, w: 2, h: 2, d: 2 } + bb = box3.translate(b, { x: 3, y: 0 }) + + t.true(box3.collide(b, b), 'should collide with self') + t.false(box3.collide(b, bb), 'should not collide translated') + + bb = box3.translate(b, { x: 2, y: 0 }) + t.true(box3.collide(b, bb), 'should collide if touching') + + bb = box3.translate(b, { x: 2, y: 0, z: 3 }) + t.false(box3.collide(b, bb), 'should not collide if z gap') + + b = { a: 1, b: 0, x: 0, y: 0, z: 0, w: 0, h: 0, d: 0 } + t.true(box3.collide(b, b), 'empty box should collide with self') + + b = { a: 1, b: 0, x: 0, y: 0, z: 0, w: 10, h: 10, d: 10 } + bb = { a: 1, b: 0, x: 2, y: 2, z: 2, w: 6, h: 6, d: 6 } + t.true(box3.collide(b, bb), 'nested should collide') + + t.end() + }) +} diff --git a/test/box3/index.test.js b/test/box3/index.test.js index 9a2fe735..9f8d99d5 100644 --- a/test/box3/index.test.js +++ b/test/box3/index.test.js @@ -4,6 +4,7 @@ const units = { at: require('./at.test'), atBox: require('./atBox.test'), atNorm: require('./atNorm.test'), + collide: require('./collide.test'), create: require('./create.test'), fromPoints: require('./fromPoints.test'), getAngle: require('./getAngle.test'), From 9e34e42fa1550e9e34bd888d836ec90998aecea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:51:37 +0200 Subject: [PATCH 24/26] allow vec2 in box3.translate --- lib/box3/translate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/box3/translate.js b/lib/box3/translate.js index df39764e..250791fa 100644 --- a/lib/box3/translate.js +++ b/lib/box3/translate.js @@ -8,7 +8,7 @@ module.exports = (box, vec) => { // box // a box3 // vec - // a vec3 + // a vec3 or vec2 // // Return // a box3 @@ -18,7 +18,7 @@ module.exports = (box, vec) => { b: box.b, x: box.x + vec.x, y: box.y + vec.y, - z: box.z + vec.z, + z: box.z + (vec.z || 0), w: box.w, h: box.h, d: box.d From c45491efd5ced460681d522669a122c883658f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:55:53 +0200 Subject: [PATCH 25/26] render docs --- docs/API.md | 409 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 403 insertions(+), 6 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5026acaf..de6d52ab 100644 --- a/docs/API.md +++ b/docs/API.md @@ -840,6 +840,7 @@ thus can be represented in any basis without loss of information. - [affineplane.box3.at](#affineplanebox3at) - [affineplane.box3.atBox](#affineplanebox3atbox) - [affineplane.box3.atNorm](#affineplanebox3atnorm) +- [affineplane.box3.collide](#affineplanebox3collide) - [affineplane.box3.create](#affineplanebox3create) - [affineplane.box3.fromPoints](#affineplanebox3frompoints) - [affineplane.box3.getAngle](#affineplanebox3getangle) @@ -962,6 +963,28 @@ Take a point on the box with coordinates normalized to box sizes. Source: [atNorm.js](https://github.com/axelpale/affineplane/blob/main/lib/box3/atNorm.js) + +## [affineplane](#affineplane).[box3](#affineplanebox3).[collide](#affineplanebox3collide)(b, bb) + +Test if the two boxes collide. +The boxes collide when the intersection of their solid cuboids +is not empty. + +

Parameters:

+ +- *b* + - a [box3](#affineplanebox3), in the reference basis +- *bb* + - a [box3](#affineplanebox3), in the reference basis + + +

Returns:

+ +- a boolean, true if boxes collide. + + +Source: [collide.js](https://github.com/axelpale/affineplane/blob/main/lib/box3/collide.js) + ## [affineplane](#affineplane).[box3](#affineplanebox3).[create](#affineplanebox3create)(basis, size) @@ -1382,7 +1405,7 @@ See [affineplane.box3](#affineplanebox3).offset to translate by scalars. - *box* - a [box3](#affineplanebox3) - *vec* - - a [vec3](#affineplanevec3) + - a [vec3](#affineplanevec3) or [vec2](#affineplanevec2)

Returns:

@@ -4661,6 +4684,7 @@ is located +20 units along x-axis of the reference plane. - [affineplane.plane2.IDENTITY](#affineplaneplane2identity) - [affineplane.plane2.almostEqual](#affineplaneplane2almostequal) +- [affineplane.plane2.at](#affineplaneplane2at) - [affineplane.plane2.between](#affineplaneplane2between) - [affineplane.plane2.compose](#affineplaneplane2compose) - [affineplane.plane2.copy](#affineplaneplane2copy) @@ -4726,6 +4750,28 @@ Test if two planes are almost equal. Source: [almostEqual.js](https://github.com/axelpale/affineplane/blob/main/lib/plane2/almostEqual.js) + +## [affineplane](#affineplane).[plane2](#affineplaneplane2).[at](#affineplaneplane2at)(plane, x, y) + +Take a point on the plane and transit it to the reference basis. + +

Parameters:

+ +- *plane* + - a [plane2](#affineplaneplane2), in the reference basis. +- *x* + - a number, the horizontal coordinate on the plane +- *y* + - a number, the vertical coordinate on the plane + + +

Returns:

+ +- a [point2](#affineplanepoint2) in the reference basis. + + +Source: [at.js](https://github.com/axelpale/affineplane/blob/main/lib/plane2/at.js) + ## [affineplane](#affineplane).[plane2](#affineplaneplane2).[between](#affineplaneplane2between) @@ -5264,6 +5310,7 @@ relative to its reference plane. - [affineplane.plane3.IDENTITY](#affineplaneplane3identity) - [affineplane.plane3.almostEqual](#affineplaneplane3almostequal) +- [affineplane.plane3.at](#affineplaneplane3at) - [affineplane.plane3.between](#affineplaneplane3between) - [affineplane.plane3.compose](#affineplaneplane3compose) - [affineplane.plane3.copy](#affineplaneplane3copy) @@ -5319,6 +5366,30 @@ Test if two planes are almost equal. Source: [almostEqual.js](https://github.com/axelpale/affineplane/blob/main/lib/plane3/almostEqual.js) + +## [affineplane](#affineplane).[plane3](#affineplaneplane3).[at](#affineplaneplane3at)(plane, x, y, z) + +Take a point relative to the plane and transit it to the reference basis. + +

Parameters:

+ +- *plane* + - a [plane3](#affineplaneplane3), in the reference basis. +- *x* + - a number, the horizontal coordinate on the plane +- *y* + - a number, the vertical coordinate on the plane +- *z* + - a number, the depth offset relative to the plane + + +

Returns:

+ +- a [point3](#affineplanepoint3) in the reference basis. + + +Source: [at.js](https://github.com/axelpale/affineplane/blob/main/lib/plane3/at.js) + ## [affineplane](#affineplane).[plane3](#affineplaneplane3).[between](#affineplaneplane3between) @@ -6478,6 +6549,7 @@ translation of the plane on which they are represented. - [affineplane.point3.polarOffset](#affineplanepoint3polaroffset) - [affineplane.point3.projectTo](#affineplanepoint3projectto) - [affineplane.point3.projectToPlane](#affineplanepoint3projecttoplane) +- [affineplane.point3.rotateAroundLine](#affineplanepoint3rotatearoundline) - [affineplane.point3.rotateBy](#affineplanepoint3rotateby) - [affineplane.point3.round](#affineplanepoint3round) - [affineplane.point3.toArray](#affineplanepoint3toarray) @@ -6789,8 +6861,30 @@ Aliases: [affineplane.point3.projectTo](#affineplanepoint3projectto) Source: [projectToPlane.js](https://github.com/axelpale/affineplane/blob/main/lib/point3/projectToPlane.js) + +## [affineplane](#affineplane).[point3](#affineplanepoint3).[rotateAroundLine](#affineplanepoint3rotatearoundline)(p, line, rads) + +Rotate a point around the axis line by the given radians. + +

Parameters:

+ +- *p* + - a [point3](#affineplanepoint3) +- *line* + - a [line3](#affineplaneline3), the rotation axis +- *rads* + - a number, angle in radians + + +

Returns:

+ +- a [point3](#affineplanepoint3), the rotated point + + +Source: [rotateAroundLine.js](https://github.com/axelpale/affineplane/blob/main/lib/point3/rotateAroundLine.js) + -## [affineplane](#affineplane).[point3](#affineplanepoint3).[rotateBy](#affineplanepoint3rotateby)(p, origin, roll, pitch) +## [affineplane](#affineplane).[point3](#affineplanepoint3).[rotateBy](#affineplanepoint3rotateby)(p, origin, roll[, pitch]) Rotate point around the given center point. Roll is applied before pitch. @@ -7000,6 +7094,7 @@ A quaternion `{ a, b, c, d }` - [affineplane.quat4.hamilton](#affineplanequat4hamilton) - [affineplane.quat4.multiply](#affineplanequat4multiply) - [affineplane.quat4.norm](#affineplanequat4norm) +- [affineplane.quat4.rotateVector](#affineplanequat4rotatevector) Source: [quat4/index.js](https://github.com/axelpale/affineplane/blob/main/lib/quat4/index.js) @@ -7181,6 +7276,29 @@ The length of quaternion. Also called the norm. Source: [norm.js](https://github.com/axelpale/affineplane/blob/main/lib/quat4/norm.js) + +## [affineplane](#affineplane).[quat4](#affineplanequat4).[rotateVector](#affineplanequat4rotatevector)(quat, vec) + +Apply quaternion to rotate a vector. +Note that the quaternion must rotate the vector twice to return it +back to the 3D space. Therefore, if the quaternion was created using +an angle like π/2, the vector will be rotated twice that amount, π. + +

Parameters:

+ +- *quat* + - a [quat4](#affineplanequat4), a quaternion. +- *vec* + - a [vec3](#affineplanevec3), the vector to rotate + + +

Returns:

+ +- a [vec3](#affineplanevec3), the rotated vector. + + +Source: [rotateVector.js](https://github.com/axelpale/affineplane/blob/main/lib/quat4/rotateVector.js) + ## [affineplane](#affineplane).[rect2](#affineplanerect2) @@ -8483,6 +8601,8 @@ Represented with an object `{ x, y, r }` for the origin and the radius. - [affineplane.sphere2.almostEqual](#affineplanesphere2almostequal) - [affineplane.sphere2.area](#affineplanesphere2area) +- [affineplane.sphere2.atCenter](#affineplanesphere2atcenter) +- [affineplane.sphere2.boundingBox](#affineplanesphere2boundingbox) - [affineplane.sphere2.collide](#affineplanesphere2collide) - [affineplane.sphere2.copy](#affineplanesphere2copy) - [affineplane.sphere2.create](#affineplanesphere2create) @@ -8490,9 +8610,13 @@ Represented with an object `{ x, y, r }` for the origin and the radius. - [affineplane.sphere2.hasPoint](#affineplanesphere2haspoint) - [affineplane.sphere2.homothety](#affineplanesphere2homothety) - [affineplane.sphere2.offset](#affineplanesphere2offset) +- [affineplane.sphere2.polarOffset](#affineplanesphere2polaroffset) +- [affineplane.sphere2.rotateBy](#affineplanesphere2rotateby) - [affineplane.sphere2.scaleBy](#affineplanesphere2scaleby) +- [affineplane.sphere2.size](#affineplanesphere2size) - [affineplane.sphere2.transitFrom](#affineplanesphere2transitfrom) - [affineplane.sphere2.transitTo](#affineplanesphere2transitto) +- [affineplane.sphere2.translate](#affineplanesphere2translate) - [affineplane.sphere2.validate](#affineplanesphere2validate) @@ -8537,6 +8661,42 @@ Get area of the sphere. Source: [area.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/area.js) + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[atCenter](#affineplanesphere2atcenter)(sp) + +Get the center point of the sphere. +Note that the [sphere2](#affineplanesphere2) object itself can act as a [point2](#affineplanepoint2) in many cases. + +

Parameters:

+ +- a [sphere2](#affineplanesphere2) + + +

Returns:

+ +- a [point2](#affineplanepoint2) + + +Source: [atCenter.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/atCenter.js) + + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[boundingBox](#affineplanesphere2boundingbox)(sphere) + +Get outer rectangular boundary of the given sphere. + +

Parameters:

+ +- *sphere* + - a [sphere2](#affineplanesphere2), in the reference basis. + + +

Returns:

+ +- a [box2](#affineplanebox2), in the reference basis. + + +Source: [boundingBox.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/boundingBox.js) + ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[collide](#affineplanesphere2collide)(c, cc) @@ -8668,7 +8828,7 @@ Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[offset](#affineplanesphere2offset)(c, dx, dy) Offset a sphere by scalars dx, dy. -See [affineplane.sphere2](#affineplanesphere2).translate to offset by a vector. +See [affineplane.sphere2.translate](#affineplanesphere2translate) to offset by a vector.

Parameters:

@@ -8687,6 +8847,51 @@ See [affineplane.sphere2](#affineplanesphere2).translate to offset by a vector. Source: [offset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/offset.js) + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[polarOffset](#affineplanesphere2polaroffset)(sphere, distance, theta) + +Offset a sphere by the given distance towards the direction given by +the theta angles. + +

Parameters:

+ +- *sphere* + - a [sphere2](#affineplanesphere2) +- *distance* + - a number, the distance from p. +- *theta* + - a number, the angle around z-axis, the azimuthal angle. Clockwise rotation, following the right-hand rule. + + +

Returns:

+ +- a [sphere2](#affineplanesphere2) + + +Source: [polarOffset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/polarOffset.js) + + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[rotateBy](#affineplanesphere2rotateby)(sp, origin, radians) + +Rotate a sphere about an origin point. + +

Parameters:

+ +- *sp* + - a [sphere2](#affineplanesphere2) +- *origin* + - a [point2](#affineplanepoint2), the point around to rotate +- *radians* + - a number, angle in radians + + +

Returns:

+ +- a [sphere2](#affineplanesphere2), the rotated sphere + + +Source: [rotateBy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/rotateBy.js) + ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[scaleBy](#affineplanesphere2scaleby) @@ -8694,6 +8899,24 @@ Alias of [affineplane.sphere2.homothety](#affineplanesphere2homothety) Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/homothety.js) + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[size](#affineplanesphere2size)(sphere) + +Get the rectangular size of the circle. + +

Parameters:

+ +- *sphere* + - a [sphere2](#affineplanesphere2) in the reference basis. + + +

Returns:

+ +- a [size2](#affineplanesize2) in the reference basis. + + +Source: [size.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/size.js) + ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[transitFrom](#affineplanesphere2transitfrom)(sphere, source) @@ -8737,6 +8960,27 @@ in the coordinate system of the target plane. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/transitTo.js) + +## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[translate](#affineplanesphere2translate)(c, vec) + +Translate the circle by the vector. Does not affect radius. +See [affineplane.sphere2.offset](#affineplanesphere2offset) to translate by scalars. + +

Parameters:

+ +- *c* + - a [sphere2](#affineplanesphere2) +- *vec* + - a [vec2](#affineplanevec2) + + +

Returns:

+ +- a [sphere2](#affineplanesphere2) + + +Source: [translate.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere2/translate.js) + ## [affineplane](#affineplane).[sphere2](#affineplanesphere2).[validate](#affineplanesphere2validate)(p) @@ -8769,6 +9013,8 @@ Represented with an object `{ x, y, z, r }` for the origin and the radius. - [affineplane.sphere3.almostEqual](#affineplanesphere3almostequal) - [affineplane.sphere3.area](#affineplanesphere3area) +- [affineplane.sphere3.atCenter](#affineplanesphere3atcenter) +- [affineplane.sphere3.boundingBox](#affineplanesphere3boundingbox) - [affineplane.sphere3.collide](#affineplanesphere3collide) - [affineplane.sphere3.copy](#affineplanesphere3copy) - [affineplane.sphere3.create](#affineplanesphere3create) @@ -8776,11 +9022,16 @@ Represented with an object `{ x, y, z, r }` for the origin and the radius. - [affineplane.sphere3.hasPoint](#affineplanesphere3haspoint) - [affineplane.sphere3.homothety](#affineplanesphere3homothety) - [affineplane.sphere3.offset](#affineplanesphere3offset) +- [affineplane.sphere3.polarOffset](#affineplanesphere3polaroffset) - [affineplane.sphere3.projectTo](#affineplanesphere3projectto) - [affineplane.sphere3.projectToPlane](#affineplanesphere3projecttoplane) +- [affineplane.sphere3.rotateAroundLine](#affineplanesphere3rotatearoundline) +- [affineplane.sphere3.rotateBy](#affineplanesphere3rotateby) - [affineplane.sphere3.scaleBy](#affineplanesphere3scaleby) +- [affineplane.sphere3.size](#affineplanesphere3size) - [affineplane.sphere3.transitFrom](#affineplanesphere3transitfrom) - [affineplane.sphere3.transitTo](#affineplanesphere3transitto) +- [affineplane.sphere3.translate](#affineplanesphere3translate) - [affineplane.sphere3.validate](#affineplanesphere3validate) - [affineplane.sphere3.volume](#affineplanesphere3volume) @@ -8826,6 +9077,42 @@ Get surface area of the sphere. Source: [area.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/area.js) + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[atCenter](#affineplanesphere3atcenter)(sp) + +Get the center point of the sphere. +Note that the [sphere3](#affineplanesphere3) object itself can act as a [point3](#affineplanepoint3) in many cases. + +

Parameters:

+ +- a [sphere3](#affineplanesphere3) + + +

Returns:

+ +- a [point3](#affineplanepoint3) + + +Source: [atCenter.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/atCenter.js) + + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[boundingBox](#affineplanesphere3boundingbox)(sphere) + +Get outer cuboid boundary of the given sphere. + +

Parameters:

+ +- *sphere* + - a [sphere3](#affineplanesphere3), in the reference basis. + + +

Returns:

+ +- a [box3](#affineplanebox3), in the reference basis. + + +Source: [boundingBox.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/boundingBox.js) + ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[collide](#affineplanesphere3collide)(c, cc) @@ -8959,7 +9246,7 @@ Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sph ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[offset](#affineplanesphere3offset)(c, dx, dy[, dz]) Offset a sphere by scalars dx, dy, dz. -See [affineplane.sphere3](#affineplanesphere3).translate to offset by a vector. +See [affineplane.sphere3.translate](#affineplanesphere3translate) to offset by a vector.

Parameters:

@@ -8980,6 +9267,31 @@ See [affineplane.sphere3](#affineplanesphere3).translate to offset by a vector. Source: [offset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/offset.js) + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[polarOffset](#affineplanesphere3polaroffset)(sphere, distance, theta[, phi]) + +Offset a sphere by the given distance towards the direction given by +the spherical theta and phi angles. + +

Parameters:

+ +- *sphere* + - a [sphere3](#affineplanesphere3) +- *distance* + - a number, the distance from p. +- *theta* + - a number, the angle around z-axis, the azimuthal angle. Clockwise rotation, following the right-hand rule. +- *phi* + - optional number, default π/2. The polar angle in radians measured from the positive z-axis. + + +

Returns:

+ +- a [sphere3](#affineplanesphere3) + + +Source: [polarOffset.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/polarOffset.js) + ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[projectTo](#affineplanesphere3projectto) @@ -9012,6 +9324,52 @@ Aliases: [affineplane.sphere3.projectTo](#affineplanesphere3projectto) Source: [projectToPlane.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/projectToPlane.js) + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[rotateAroundLine](#affineplanesphere3rotatearoundline)(sp, line, rads) + +Rotate a sphere around the axis line by the given radians. + +

Parameters:

+ +- *sp* + - a [sphere3](#affineplanesphere3) +- *line* + - a [line3](#affineplaneline3), the rotation axis +- *rads* + - a number, angle in radians + + +

Returns:

+ +- a [sphere3](#affineplanesphere3), the rotated sphere + + +Source: [rotateAroundLine.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/rotateAroundLine.js) + + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[rotateBy](#affineplanesphere3rotateby)(sp, origin, radians) + +Rotate a sphere about a line parallel to z-axis that goes through +the origin point. The rotation direction follows the right hand rule +about the positive z-axis. + +

Parameters:

+ +- *sp* + - a [sphere3](#affineplanesphere3) +- *origin* + - a [point3](#affineplanepoint3), the point that defines the line around which to rotate +- *radians* + - a number, angle in radians + + +

Returns:

+ +- a [sphere3](#affineplanesphere3), the rotated sphere + + +Source: [rotateBy.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/rotateBy.js) + ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[scaleBy](#affineplanesphere3scaleby) @@ -9019,6 +9377,24 @@ Alias of [affineplane.sphere3.homothety](#affineplanesphere3homothety) Source: [homothety.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/homothety.js) + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[size](#affineplanesphere3size)(sphere) + +Get the cuboid size of the sphere. + +

Parameters:

+ +- *sphere* + - a [sphere3](#affineplanesphere3) in the reference basis. + + +

Returns:

+ +- a [size3](#affineplanesize3) in the reference basis. + + +Source: [size.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/size.js) + ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[transitFrom](#affineplanesphere3transitfrom)(sphere, source) @@ -9062,6 +9438,27 @@ in the coordinate system of the target plane. Source: [transitTo.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/transitTo.js) + +## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[translate](#affineplanesphere3translate)(c, vec) + +Translate the sphere by the vector. Does not affect radius. +See [affineplane.sphere3.offset](#affineplanesphere3offset) to translate by scalars. + +

Parameters:

+ +- *c* + - a [sphere3](#affineplanesphere3) +- *vec* + - a [vec3](#affineplanevec3) + + +

Returns:

+ +- a [sphere3](#affineplanesphere3) + + +Source: [translate.js](https://github.com/axelpale/affineplane/blob/main/lib/sphere3/translate.js) + ## [affineplane](#affineplane).[sphere3](#affineplanesphere3).[validate](#affineplanesphere3validate)(p) @@ -10330,9 +10727,9 @@ it to each vector. - *v* - a [vec3](#affineplanevec3) - *axis* - - a [vec3](#affineplanevec3), must not be zero vector + - a [vec3](#affineplanevec3), must not be a zero vector - *angle* - - a number, an angle in radians. Right-hand rotation around the given axis. + - a number, an angle in radians. Rotation around the axis. Rotation direction follows the right-hand rule.

Returns:

From 7bb46d70f9d7def8791d719a91ff971a62a245e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Akseli=20Pal=C3=A9n?= Date: Mon, 13 Mar 2023 01:57:34 +0200 Subject: [PATCH 26/26] bump v2.13.0 --- docs/API.md | 2 +- lib/version.js | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/API.md b/docs/API.md index de6d52ab..a2860ec0 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,5 +1,5 @@ -# Affineplane API Documentation v2.12.0 +# Affineplane API Documentation v2.13.0 Welcome to affineplane API reference documentation. These docs are generated with [yamdog](https://axelpale.github.io/yamdog/). diff --git a/lib/version.js b/lib/version.js index 90230679..0d24b947 100644 --- a/lib/version.js +++ b/lib/version.js @@ -1,2 +1,2 @@ // Generated by genversion. -module.exports = '2.12.0' +module.exports = '2.13.0' diff --git a/package.json b/package.json index 85fdfcfe..01f95bdd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "affineplane", - "version": "2.12.0", + "version": "2.13.0", "description": "Affine plane geometry library", "keywords": [ "affine",