@ue-too/math 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  class J{static addVector(j,B){if(j.z==null&&B.z==null)return{x:j.x+B.x,y:j.y+B.y};if(j.z==null||B.z==null){if(j.z==null)j.z=0;if(B.z==null)B.z=0}return{x:j.x+B.x,y:j.y+B.y,z:j.z+B.z}}static subVector(j,B){if(j.z==null&&B.z==null)return{x:j.x-B.x,y:j.y-B.y};if(j.z==null||B.z==null){if(j.z==null)j.z=0;if(B.z==null)B.z=0}return{x:j.x-B.x,y:j.y-B.y,z:j.z-B.z}}static multiplyVectorByScalar(j,B){if(j.z==null)return{x:j.x*B,y:j.y*B};return{x:j.x*B,y:j.y*B,z:j.z*B}}static divideVectorByScalar(j,B){if(B==0)return{x:j.x,y:j.y};if(j.z==null)return{x:j.x/B,y:j.y/B};return{x:j.x/B,y:j.y/B,z:j.z/B}}static magnitude(j){if(j.z==null)j.z=0;return Math.sqrt(j.x*j.x+j.y*j.y+j.z*j.z)}static unitVector(j){if(j.z==null)j.z=0;return this.magnitude(j)!=0?{x:j.x/this.magnitude(j),y:j.y/this.magnitude(j),z:j.z/this.magnitude(j)}:{x:0,y:0,z:0}}static dotProduct(j,B){if(j.z==null&&B.z==null)return j.x*B.x+j.y*B.y;if(j.z==null||B.z==null){if(j.z==null)j.z=0;if(B.z==null)B.z=0}return j.x*B.x+j.y*B.y+j.z*B.z}static crossProduct(j,B){if(j.z==null||B.z==null){if(j.z==null)j.z=0;if(B.z==null)B.z=0}return{x:j.y*B.z-j.z*B.y,y:j.z*B.x-j.x*B.z,z:j.x*B.y-j.y*B.x}}static unitVectorFromA2B(j,B){return this.unitVector(this.subVector(B,j))}static rotatePoint(j,B){return{x:j.x*Math.cos(B)-j.y*Math.sin(B),y:j.x*Math.sin(B)+j.y*Math.cos(B)}}static transform2NewAxis(j,B){return{x:j.x*Math.cos(B)+j.y*Math.sin(B),y:-j.x*Math.sin(B)+j.y*Math.cos(B)}}static angleFromA2B(j,B){return Math.atan2(j.x*B.y-j.y*B.x,j.x*B.x+j.y*B.y)}static transformPointWRTAnchor(j,B,G){let H=this.rotatePoint(this.subVector(j,B),G);return this.addVector(H,B)}static distanceBetweenPoints(j,B){return this.magnitude(this.subVector(j,B))}static flipYAxis(j){return{x:j.x,y:-j.y,z:j.z}}static linearInterpolation(j,B,G){if(j.z==null||B.z==null)return{x:j.x+(B.x-j.x)*G,y:j.y+(B.y-j.y)*G};else return{x:j.x+(B.x-j.x)*G,y:j.y+(B.y-j.y)*G,z:j.z+(B.z-j.z)*G}}static isEqual(j,B){if(j.z==null)j.z=0;if(B.z==null)B.z=0;return j.x==B.x&&j.y==B.y&&j.z==B.z}static getLineIntersection(j,B,G,H){let L=(H.x-G.x)*(j.y-G.y)-(H.y-G.y)*(j.x-G.x),M=(H.y-G.y)*(B.x-j.x)-(H.x-G.x)*(B.y-j.y);if(M===0)return{intersects:!1};let K=L/M;if(K>=0&&K<=1)return{intersects:!0,intersection:J.linearInterpolation(j,B,K),offset:K};else return{intersects:!1}}}function Q(j){return j=j%(Math.PI*2),j=(j+Math.PI*2)%(Math.PI*2),j}function W(j,B){j=Q(j),B=Q(B);let G=B-j;if(G>Math.PI)G=-(Math.PI*2-G);if(G<-Math.PI)G+=Math.PI*2;return G}function R(j,B,G){return Math.abs(j-B)<=(G||0.000001)}function X(j,B,G=0.001){let H=J.unitVector(j),L=J.unitVector(B);return V(H,L,G)}function Y(j,B){let G=J.unitVector(j),H=J.unitVector(B),L={x:-B.x,y:-B.y,z:B.z},M=J.angleFromA2B(G,H),K=J.angleFromA2B(G,L);return M<Math.PI/2&&M>-Math.PI/2&&(K>Math.PI/2||K<-Math.PI/2)}function V(j,B,G){if(R(j.x,B.x,G)&&R(j.y,B.y,G))return!0;return!1}export{V as samePoint,X as sameDirection,Q as normalizeAngleZero2TwoPI,Y as directionAlignedToTangent,R as approximatelyTheSame,W as angleSpan,J as PointCal};
2
2
 
3
3
  //# debugId=E7FBAB931781982464756E2164756E21
4
+
5
+ //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts"],
3
+ "sources": [
4
+ "index.ts"
5
+ ],
4
6
  "sourcesContent": [
5
7
  "/**\n * @packageDocumentation\n * Mathematical utilities for 2D and 3D point operations, vector calculations, and transformations.\n *\n * @remarks\n * This package provides essential mathematical operations for canvas applications including:\n * - Vector arithmetic (add, subtract, multiply, divide)\n * - Vector operations (dot product, cross product, magnitude, unit vectors)\n * - Geometric transformations (rotation, axis transformation)\n * - Angle calculations and normalization\n * - Point comparisons and interpolation\n * - Line intersection detection\n *\n * All operations support both 2D and 3D coordinates, with the z-axis being optional.\n *\n * @example\n * Basic vector operations\n * ```typescript\n * import { PointCal, Point } from '@ue-too/math';\n *\n * const a: Point = { x: 1, y: 2 };\n * const b: Point = { x: 3, y: 4 };\n *\n * // Add vectors\n * const sum = PointCal.addVector(a, b); // { x: 4, y: 6 }\n *\n * // Calculate magnitude\n * const mag = PointCal.magnitude(a); // 2.236...\n *\n * // Get unit vector\n * const unit = PointCal.unitVector(a); // { x: 0.447..., y: 0.894... }\n * ```\n *\n * @example\n * Rotation and transformation\n * ```typescript\n * import { PointCal, Point } from '@ue-too/math';\n *\n * const point: Point = { x: 10, y: 0 };\n * const angle = Math.PI / 2; // 90 degrees\n *\n * // Rotate point around origin\n * const rotated = PointCal.rotatePoint(point, angle); // { x: 0, y: 10 }\n *\n * // Rotate around a custom anchor\n * const anchor: Point = { x: 5, y: 5 };\n * const rotatedAroundAnchor = PointCal.transformPointWRTAnchor(point, anchor, angle);\n * ```\n */\n\n/**\n * Represents a 2D or 3D point with optional z-coordinate.\n *\n * @remarks\n * This is a lowercase variant maintained for backward compatibility.\n * Use {@link Point} for new code.\n *\n * @deprecated Use {@link Point} instead for better TypeScript conventions.\n */\nexport type point = {\n /** X-coordinate */\n x: number;\n /** Y-coordinate */\n y: number;\n /** Optional Z-coordinate for 3D operations */\n z?: number;\n}\n\n/**\n * Represents a 2D or 3D point with optional z-coordinate.\n *\n * @remarks\n * When z is undefined, operations treat the point as 2D (z = 0).\n * This type is used throughout the library for all point and vector operations.\n *\n * @example\n * ```typescript\n * // 2D point\n * const p2d: Point = { x: 10, y: 20 };\n *\n * // 3D point\n * const p3d: Point = { x: 10, y: 20, z: 30 };\n * ```\n */\nexport type Point = {\n /** X-coordinate */\n x: number;\n /** Y-coordinate */\n y: number;\n /** Optional Z-coordinate for 3D operations */\n z?: number;\n}\n\n\n/**\n * Utility class for point and vector calculations.\n *\n * @remarks\n * PointCal provides static methods for common 2D and 3D mathematical operations\n * used in canvas applications. All methods handle both 2D and 3D coordinates seamlessly.\n *\n * @example\n * ```typescript\n * import { PointCal, Point } from '@ue-too/math';\n *\n * const v1: Point = { x: 1, y: 2 };\n * const v2: Point = { x: 3, y: 4 };\n *\n * const sum = PointCal.addVector(v1, v2);\n * const dot = PointCal.dotProduct(v1, v2);\n * ```\n */\nexport class PointCal {\n\n /**\n * Adds two vectors together.\n *\n * @param a - First vector\n * @param b - Second vector\n * @returns The sum of vectors a and b\n *\n * @remarks\n * If either vector lacks a z-coordinate, it's treated as 0.\n * The result will include a z-coordinate if either input has one.\n *\n * @example\n * ```typescript\n * const a = { x: 1, y: 2 };\n * const b = { x: 3, y: 4 };\n * const sum = PointCal.addVector(a, b); // { x: 4, y: 6 }\n *\n * // With 3D coordinates\n * const a3d = { x: 1, y: 2, z: 3 };\n * const b3d = { x: 4, y: 5, z: 6 };\n * const sum3d = PointCal.addVector(a3d, b3d); // { x: 5, y: 7, z: 9 }\n * ```\n *\n * @group Vector Arithmetic\n */\n static addVector(a: point, b: point): Point {\n if (a.z == null && b.z == null) return {x: a.x + b.x, y: a.y + b.y};\n if (a.z == null || b.z == null) {\n if (a.z == null) a.z = 0;\n if (b.z == null) b.z = 0;\n }\n return {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z}; \n }\n\n /**\n * Subtracts vector b from vector a.\n *\n * @param a - Vector to subtract from\n * @param b - Vector to subtract\n * @returns The difference (a - b)\n *\n * @remarks\n * If either vector lacks a z-coordinate, it's treated as 0.\n *\n * @example\n * ```typescript\n * const a = { x: 5, y: 7 };\n * const b = { x: 2, y: 3 };\n * const diff = PointCal.subVector(a, b); // { x: 3, y: 4 }\n * ```\n *\n * @group Vector Arithmetic\n */\n static subVector(a: point, b: point): Point {\n if (a.z == null && b.z == null) return {x: a.x - b.x, y: a.y - b.y};\n if (a.z == null || b.z == null) {\n if (a.z == null) a.z = 0;\n if (b.z == null) b.z = 0;\n }\n return {x: a.x - b.x, y: a.y - b.y, z: a.z - b.z};\n }\n\n /**\n * Multiplies a vector by a scalar value.\n *\n * @param a - Vector to multiply\n * @param b - Scalar multiplier\n * @returns The scaled vector\n *\n * @example\n * ```typescript\n * const v = { x: 2, y: 3 };\n * const scaled = PointCal.multiplyVectorByScalar(v, 2.5); // { x: 5, y: 7.5 }\n * ```\n *\n * @group Vector Arithmetic\n */\n static multiplyVectorByScalar(a: point, b: number): Point {\n if (a.z == null) return {x: a.x * b, y: a.y * b};\n return {x: a.x * b, y: a.y * b, z: a.z * b};\n }\n\n /**\n * Divides a vector by a scalar value.\n *\n * @param a - Vector to divide\n * @param b - Scalar divisor\n * @returns The divided vector, or the original vector if b is 0\n *\n * @remarks\n * Division by zero returns the original vector unchanged to prevent NaN values.\n *\n * @example\n * ```typescript\n * const v = { x: 10, y: 20 };\n * const divided = PointCal.divideVectorByScalar(v, 2); // { x: 5, y: 10 }\n * ```\n *\n * @group Vector Arithmetic\n */\n static divideVectorByScalar(a: point, b: number): Point {\n if (b == 0) return {x: a.x, y: a.y};\n if (a.z == null) return {x: a.x / b, y: a.y / b};\n return {x: a.x / b, y: a.y / b, z: a.z / b};\n }\n\n /**\n * Calculates the magnitude (length) of a vector.\n *\n * @param a - Vector to measure\n * @returns The magnitude of the vector\n *\n * @remarks\n * Uses the Euclidean distance formula: √(x² + y² + z²)\n *\n * @example\n * ```typescript\n * const v = { x: 3, y: 4 };\n * const mag = PointCal.magnitude(v); // 5\n *\n * const v3d = { x: 1, y: 2, z: 2 };\n * const mag3d = PointCal.magnitude(v3d); // 3\n * ```\n *\n * @group Vector Operations\n */\n static magnitude(a: point): number {\n if (a.z == null) a.z = 0;\n return Math.sqrt(a.x * a.x + a.y * a.y + a.z * a.z);\n }\n\n /**\n * Converts a vector to its unit vector (normalized to length 1).\n *\n * @param a - Vector to normalize\n * @returns Unit vector in the same direction, or zero vector if magnitude is 0\n *\n * @remarks\n * A unit vector has magnitude 1 and preserves the original direction.\n * Returns {x: 0, y: 0, z: 0} if the input vector has zero magnitude.\n *\n * **Performance note**: This method calls `magnitude()` twice. For better performance\n * when you need both magnitude and unit vector, calculate magnitude once and divide manually.\n *\n * @example\n * ```typescript\n * const v = { x: 3, y: 4 };\n * const unit = PointCal.unitVector(v); // { x: 0.6, y: 0.8 }\n * ```\n *\n * @group Vector Operations\n */\n static unitVector(a: point): Point {\n if (a.z == null) a.z = 0;\n return this.magnitude(a) != 0 ? {x: a.x / this.magnitude(a), y: a.y / this.magnitude(a), z: a.z / this.magnitude(a)} : {x: 0, y: 0, z: 0};\n }\n\n /**\n * Calculates the dot product of two vectors.\n *\n * @param a - First vector\n * @param b - Second vector\n * @returns The dot product (scalar value)\n *\n * @remarks\n * The dot product is: a.x * b.x + a.y * b.y + a.z * b.z\n *\n * **Use cases:**\n * - Determine if vectors are perpendicular (dot = 0)\n * - Calculate angle between vectors: θ = acos(dot / (|a| * |b|))\n * - Project one vector onto another\n *\n * @example\n * ```typescript\n * const a = { x: 1, y: 0 };\n * const b = { x: 0, y: 1 };\n * const dot = PointCal.dotProduct(a, b); // 0 (perpendicular vectors)\n *\n * const c = { x: 2, y: 3 };\n * const d = { x: 4, y: 5 };\n * const dot2 = PointCal.dotProduct(c, d); // 23\n * ```\n *\n * @group Vector Operations\n */\n static dotProduct(a: point, b: point): number {\n if (a.z == null && b.z == null) return a.x * b.x + a.y * b.y;\n if (a.z == null || b.z == null) {\n if (a.z == null) a.z = 0;\n if (b.z == null) b.z = 0;\n }\n return a.x * b.x + a.y * b.y + a.z * b.z;\n }\n\n /**\n * Calculates the cross product of two vectors.\n *\n * @param a - First vector\n * @param b - Second vector\n * @returns The cross product vector perpendicular to both inputs\n *\n * @remarks\n * The cross product is perpendicular to both input vectors, following the right-hand rule.\n * For 2D vectors (z undefined), z is treated as 0.\n *\n * **Properties:**\n * - Result is perpendicular to both input vectors\n * - Magnitude equals area of parallelogram formed by vectors\n * - Direction follows right-hand rule\n *\n * @example\n * ```typescript\n * const a = { x: 1, y: 0, z: 0 };\n * const b = { x: 0, y: 1, z: 0 };\n * const cross = PointCal.crossProduct(a, b); // { x: 0, y: 0, z: 1 }\n * ```\n *\n * @group Vector Operations\n */\n static crossProduct(a: point, b: point): Point {\n if (a.z == null || b.z == null) {\n if (a.z == null) a.z = 0;\n if (b.z == null) b.z = 0;\n }\n return {x: a.y * b.z - a.z * b.y, y: a.z * b.x - a.x * b.z, z: a.x * b.y - a.y * b.x};\n }\n\n /**\n * Calculates the unit vector pointing from point a to point b.\n *\n * @param a - Starting point\n * @param b - Ending point\n * @returns Unit vector in the direction from a to b\n *\n * @remarks\n * Equivalent to calling unitVector(subVector(b, a))\n *\n * @example\n * ```typescript\n * const a = { x: 0, y: 0 };\n * const b = { x: 3, y: 4 };\n * const direction = PointCal.unitVectorFromA2B(a, b); // { x: 0.6, y: 0.8 }\n * ```\n *\n * @group Geometric Calculations\n */\n static unitVectorFromA2B(a: point, b: point): Point {\n return this.unitVector(this.subVector(b, a));\n }\n\n /**\n * Rotates a point around the origin.\n *\n * @param point - Point to rotate\n * @param angle - Rotation angle in radians (counter-clockwise)\n * @returns Rotated point\n *\n * @remarks\n * Rotation is performed around the origin (0, 0).\n * Positive angles rotate counter-clockwise, negative angles rotate clockwise.\n * For rotation around a custom anchor, use {@link transformPointWRTAnchor}.\n *\n * **Performance**: Uses trigonometric functions (sin/cos). For many rotations with\n * the same angle, pre-calculate sin/cos values and apply the transformation manually.\n *\n * @example\n * ```typescript\n * const point = { x: 1, y: 0 };\n * const rotated = PointCal.rotatePoint(point, Math.PI / 2); // { x: 0, y: 1 }\n * ```\n *\n * @group Transformations\n */\n static rotatePoint(point: point, angle: number): Point {\n return {x: point.x * Math.cos(angle) - point.y * Math.sin(angle), y: point.x * Math.sin(angle) + point.y * Math.cos(angle)};\n }\n\n /**\n * Transforms a point's coordinates to a new rotated axis system.\n *\n * @param point - Point in original coordinate system\n * @param angleFromOriginalAxis2DestAxis - Rotation angle from original to destination axis (radians, CCW positive)\n * @returns Point coordinates in the new axis system\n *\n * @remarks\n * This performs an axis rotation transformation, converting coordinates from one\n * reference frame to another rotated by the specified angle.\n *\n * @example\n * ```typescript\n * const point = { x: 10, y: 0 };\n * const angle = Math.PI / 4; // 45 degrees\n * const transformed = PointCal.transform2NewAxis(point, angle);\n * ```\n *\n * @group Transformations\n */\n static transform2NewAxis(point: point, angleFromOriginalAxis2DestAxis: number): Point {\n // angle is the angle from the original axis to the destination axis ccw is positive as always\n return {x: point.x * Math.cos(angleFromOriginalAxis2DestAxis) + point.y * Math.sin(angleFromOriginalAxis2DestAxis), y: -point.x * Math.sin(angleFromOriginalAxis2DestAxis) + point.y * Math.cos(angleFromOriginalAxis2DestAxis)};\n }\n\n /**\n * Calculates the signed angle from vector a to vector b.\n *\n * @param a - First vector (starting direction)\n * @param b - Second vector (ending direction)\n * @returns The signed angle in radians, range: (-π, π]\n *\n * @remarks\n * - Positive angles indicate counter-clockwise rotation from a to b\n * - Negative angles indicate clockwise rotation from a to b\n * - Uses atan2 for proper quadrant handling\n *\n * @example\n * ```typescript\n * const right = { x: 1, y: 0 };\n * const up = { x: 0, y: 1 };\n * const angle = PointCal.angleFromA2B(right, up); // π/2 (90 degrees CCW)\n *\n * const down = { x: 0, y: -1 };\n * const angleDown = PointCal.angleFromA2B(right, down); // -π/2 (90 degrees CW)\n * ```\n *\n * @group Angle Utilities\n */\n static angleFromA2B(a: point, b: point): number {\n return Math.atan2(a.x * b.y - a.y * b.x, a.x * b.x + a.y * b.y);\n }\n\n /**\n * Rotates a point around a custom anchor point.\n *\n * @param point - Point to rotate\n * @param anchor - Anchor point to rotate around\n * @param angle - Rotation angle in radians (counter-clockwise)\n * @returns Rotated point\n *\n * @remarks\n * This is equivalent to:\n * 1. Translate point by -anchor\n * 2. Rotate around origin\n * 3. Translate back by +anchor\n *\n * @example\n * ```typescript\n * const point = { x: 10, y: 5 };\n * const anchor = { x: 5, y: 5 };\n * const angle = Math.PI / 2; // 90 degrees\n * const rotated = PointCal.transformPointWRTAnchor(point, anchor, angle);\n * // Rotates point around anchor (5, 5)\n * ```\n *\n * @group Transformations\n */\n static transformPointWRTAnchor(point: point, anchor: point, angle: number): Point {\n // angle is in radians\n let newPoint = this.rotatePoint(this.subVector(point, anchor), angle);\n return this.addVector(newPoint, anchor);\n }\n\n /**\n * Calculates the Euclidean distance between two points.\n *\n * @param a - First point\n * @param b - Second point\n * @returns The distance between the two points\n *\n * @remarks\n * Equivalent to calculating the magnitude of the vector from a to b.\n *\n * @example\n * ```typescript\n * const a = { x: 0, y: 0 };\n * const b = { x: 3, y: 4 };\n * const distance = PointCal.distanceBetweenPoints(a, b); // 5\n * ```\n *\n * @group Geometric Calculations\n */\n static distanceBetweenPoints(a: point, b: point): number {\n return this.magnitude(this.subVector(a, b));\n }\n\n /**\n * Flips a point's y-coordinate (mirrors across the x-axis).\n *\n * @param point - Point to flip\n * @returns Point with negated y-coordinate\n *\n * @remarks\n * Useful for converting between coordinate systems where the y-axis direction differs.\n * Common when converting between screen coordinates (y-down) and mathematical coordinates (y-up).\n *\n * @example\n * ```typescript\n * const point = { x: 10, y: 20 };\n * const flipped = PointCal.flipYAxis(point); // { x: 10, y: -20 }\n * ```\n *\n * @group Transformations\n */\n static flipYAxis(point: point): Point{\n return {x: point.x, y: -point.y, z: point.z};\n }\n\n /**\n * Performs linear interpolation between two points.\n *\n * @param a - Starting point (t = 0)\n * @param b - Ending point (t = 1)\n * @param t - Interpolation parameter (0 to 1)\n * @returns Interpolated point\n *\n * @remarks\n * - t = 0 returns point a\n * - t = 1 returns point b\n * - t = 0.5 returns the midpoint\n * - Values outside [0, 1] perform extrapolation\n *\n * **Performance**: Suitable for animation loops and real-time interpolation.\n *\n * @example\n * ```typescript\n * const a = { x: 0, y: 0 };\n * const b = { x: 10, y: 20 };\n * const mid = PointCal.linearInterpolation(a, b, 0.5); // { x: 5, y: 10 }\n * const quarter = PointCal.linearInterpolation(a, b, 0.25); // { x: 2.5, y: 5 }\n * ```\n *\n * @group Geometric Calculations\n */\n static linearInterpolation(a: point, b: point, t: number): point{\n if (a.z == null || b.z == null) {\n return {x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t};\n } else {\n return {x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t, z: a.z + (b.z - a.z) * t};\n }\n }\n\n /**\n * Checks if two points are exactly equal.\n *\n * @param a - First point\n * @param b - Second point\n * @returns True if all coordinates are exactly equal\n *\n * @remarks\n * Uses strict equality (===) for comparison.\n * For approximate equality with tolerance, use {@link samePoint} instead.\n * Missing z-coordinates are treated as 0.\n *\n * @example\n * ```typescript\n * const a = { x: 1, y: 2 };\n * const b = { x: 1, y: 2 };\n * PointCal.isEqual(a, b); // true\n *\n * const c = { x: 1.0000001, y: 2 };\n * PointCal.isEqual(a, c); // false (use samePoint for tolerance)\n * ```\n *\n * @group Geometric Calculations\n */\n static isEqual(a: point, b: point): boolean{\n if (a.z == null){\n a.z = 0;\n }\n if (b.z == null){\n b.z = 0;\n }\n return a.x == b.x && a.y == b.y && a.z == b.z;\n }\n\n /**\n * Calculates the intersection point of two line segments.\n *\n * @param startPoint - Start of first line segment\n * @param endPoint - End of first line segment\n * @param startPoint2 - Start of second line segment\n * @param endPoint2 - End of second line segment\n * @returns Object containing intersection status and details\n *\n * @remarks\n * Returns an object with:\n * - `intersects`: Boolean indicating if segments intersect\n * - `intersection`: The intersection point (only if intersects is true)\n * - `offset`: Parameter t where intersection occurs on first segment (0 to 1)\n *\n * The segments must actually cross within their bounds (not just their infinite extensions).\n *\n * **Use cases:**\n * - Collision detection between line segments\n * - Ray casting and visibility checks\n * - Path intersection detection\n *\n * @example\n * ```typescript\n * const line1Start = { x: 0, y: 0 };\n * const line1End = { x: 10, y: 10 };\n * const line2Start = { x: 0, y: 10 };\n * const line2End = { x: 10, y: 0 };\n *\n * const result = PointCal.getLineIntersection(line1Start, line1End, line2Start, line2End);\n * // { intersects: true, intersection: { x: 5, y: 5 }, offset: 0.5 }\n * ```\n *\n * @group Geometric Calculations\n */\n static getLineIntersection(startPoint: Point, endPoint: Point, startPoint2: Point, endPoint2: Point):{\n intersects: boolean,\n intersection?: Point,\n offset?: number\n }{\n const numerator = (endPoint2.x - startPoint2.x) * (startPoint.y - startPoint2.y) - (endPoint2.y - startPoint2.y) * (startPoint.x - startPoint2.x);\n const denominator = (endPoint2.y - startPoint2.y) * (endPoint.x - startPoint.x) - (endPoint2.x - startPoint2.x) * (endPoint.y - startPoint.y);\n \n if (denominator === 0){\n return {intersects: false};\n }\n const t = numerator / denominator;\n if (t >= 0 && t <= 1){\n return {\n intersects: true, \n intersection: PointCal.linearInterpolation(startPoint, endPoint, t),\n offset: t\n }\n } else {\n return {\n intersects: false,\n }\n }\n \n }\n \n}\n\n/**\n * Normalizes an angle to the range [0, 2π).\n *\n * @param angle - Angle in radians (can be any value)\n * @returns Normalized angle between 0 and 2π\n *\n * @remarks\n * This function wraps any angle to the range [0, 2π) by taking the modulo\n * and ensuring the result is positive.\n *\n * @example\n * ```typescript\n * normalizeAngleZero2TwoPI(Math.PI * 3); // π (180 degrees)\n * normalizeAngleZero2TwoPI(-Math.PI / 2); // 3π/2 (270 degrees)\n * normalizeAngleZero2TwoPI(0); // 0\n * ```\n *\n * @category Angle\n */\nexport function normalizeAngleZero2TwoPI(angle: number){\n // reduce the angle \n angle = angle % (Math.PI * 2);\n\n // force it to be the positive remainder, so that 0 <= angle < 2 * Math.PI \n angle = (angle + Math.PI * 2) % (Math.PI * 2); \n return angle;\n}\n\n/**\n * Calculates the smallest angular difference between two angles.\n *\n * @param from - Starting angle in radians\n * @param to - Ending angle in radians\n * @returns The smallest angle span from 'from' to 'to', in range (-π, π]\n *\n * @remarks\n * This function accounts for wrapping around 2π and always returns the shorter path.\n * Positive result means counter-clockwise rotation, negative means clockwise.\n *\n * @example\n * ```typescript\n * // From 0° to 90°\n * angleSpan(0, Math.PI / 2); // π/2 (90 degrees CCW)\n *\n * // From 350° to 10° (shorter to go CCW through 0°)\n * angleSpan(350 * Math.PI / 180, 10 * Math.PI / 180); // ≈ 20 degrees\n *\n * // From 10° to 350° (shorter to go CW through 0°)\n * angleSpan(10 * Math.PI / 180, 350 * Math.PI / 180); // ≈ -20 degrees\n * ```\n *\n * @category Angle\n */\nexport function angleSpan(from: number, to: number): number{\n // in radians\n from = normalizeAngleZero2TwoPI(from);\n to = normalizeAngleZero2TwoPI(to);\n let angleDiff = to - from;\n \n if(angleDiff > Math.PI){\n angleDiff = - (Math.PI * 2 - angleDiff);\n }\n\n if(angleDiff < -Math.PI){\n angleDiff += (Math.PI * 2);\n }\n return angleDiff;\n}\n\n/**\n * Checks if two numbers are approximately equal within a tolerance.\n *\n * @param a - First number\n * @param b - Second number\n * @param precision - Optional tolerance (defaults to 0.000001)\n * @returns True if the absolute difference is within the precision threshold\n *\n * @remarks\n * Useful for floating-point comparisons where exact equality is unreliable.\n *\n * @example\n * ```typescript\n * approximatelyTheSame(1.0, 1.0000001); // true (within default epsilon)\n * approximatelyTheSame(1.0, 1.1); // false\n * approximatelyTheSame(1.0, 1.01, 0.02); // true (within custom precision)\n * ```\n *\n * @category Comparison\n */\nexport function approximatelyTheSame(a: number, b: number, precision?: number): boolean {\n const epsilon = 0.000001\n return Math.abs(a - b) <= (precision || epsilon);\n}\n\n/**\n * Checks if two vectors point in the same direction.\n *\n * @param a - First vector\n * @param b - Second vector\n * @param precision - Tolerance for comparison (defaults to 0.001)\n * @returns True if vectors have the same direction (after normalization)\n *\n * @remarks\n * Normalizes both vectors to unit vectors and compares them.\n * Magnitude does not matter, only direction.\n *\n * @example\n * ```typescript\n * const a = { x: 1, y: 0 };\n * const b = { x: 10, y: 0 }; // Same direction, different magnitude\n * sameDirection(a, b); // true\n *\n * const c = { x: 1, y: 1 };\n * sameDirection(a, c); // false (different direction)\n * ```\n *\n * @category Comparison\n */\nexport function sameDirection(a: Point, b: Point, precision: number = 0.001): boolean{\n const aNormalized = PointCal.unitVector(a);\n const bNormalized = PointCal.unitVector(b);\n return samePoint(aNormalized, bNormalized, precision);\n}\n\n/**\n * Checks if a direction vector is aligned with a tangent vector.\n *\n * @param direction - Direction vector to check\n * @param tangent - Tangent vector reference\n * @returns True if direction aligns with tangent (within 90 degrees)\n *\n * @remarks\n * Returns true if the direction is within 90 degrees of either the tangent\n * or its reverse. Useful for determining if movement is along a path.\n *\n * @example\n * ```typescript\n * const direction = { x: 1, y: 0 };\n * const tangent = { x: 1, y: 0.1 }; // Slightly rotated\n * directionAlignedToTangent(direction, tangent); // true\n *\n * const perpendicular = { x: 0, y: 1 };\n * directionAlignedToTangent(perpendicular, tangent); // false\n * ```\n *\n * @category Comparison\n */\nexport function directionAlignedToTangent(direction: Point, tangent: Point): boolean {\n const directionNormalized = PointCal.unitVector(direction);\n const tangentNormalized = PointCal.unitVector(tangent);\n const reversedTangent = {x: -tangent.x, y: -tangent.y, z: tangent.z};\n const angle = PointCal.angleFromA2B(directionNormalized, tangentNormalized);\n const angle2 = PointCal.angleFromA2B(directionNormalized, reversedTangent);\n return (angle < Math.PI / 2 && angle > -Math.PI / 2) && (angle2 > Math.PI / 2 || angle2 < -Math.PI / 2);\n}\n\n/**\n * Checks if two points are approximately at the same location.\n *\n * @param a - First point\n * @param b - Second point\n * @param precision - Optional tolerance for coordinate comparison\n * @returns True if both x and y coordinates are within precision\n *\n * @remarks\n * Uses {@link approximatelyTheSame} for coordinate comparison.\n * For exact equality, use {@link PointCal.isEqual} instead.\n *\n * @example\n * ```typescript\n * const a = { x: 1.0, y: 2.0 };\n * const b = { x: 1.0000001, y: 2.0000001 };\n * samePoint(a, b); // true (within default precision)\n *\n * const c = { x: 1.1, y: 2.0 };\n * samePoint(a, c); // false\n * ```\n *\n * @category Comparison\n */\nexport function samePoint(a: Point, b: Point, precision?: number): boolean {\n if(approximatelyTheSame(a.x, b.x, precision) && approximatelyTheSame(a.y, b.y, precision)){\n return true;\n }\n return false;\n}\n"
6
8
  ],
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@ue-too/math",
3
3
  "author": "niuee",
4
4
  "type": "module",
5
- "version": "0.13.0",
5
+ "version": "0.14.1",
6
6
  "description": "Math utilities for uē-tôo",
7
7
  "license": "MIT",
8
8
  "repository": {