import {DEFAULT_LINEAR_TOLERANCE, DEFAULT_ANGULAR_TOLERANCE} from "../constants";
import oc from "../opencascade/initializer";
/**
* Represents a 3D vector.
* @memberof math
* @alias Vector
*/
export class Vector {
#wrapped;
/**
* Creates a new `Vector` instance.
* @param {Object} [parameters] - The parameters for the vector.
* @param {number} [parameters.x=0] - The X component of the vector.
* @param {number} [parameters.y=0] - The Y component of the vector.
* @param {number} [parameters.z=0] - The Z component of the vector.
*/
constructor({x = 0, y = 0, z = 0, wrapped = undefined} = {}) {
if (wrapped) {
this.#wrapped = wrapped;
} else {
this.#wrapped = new oc.gp_Vec_4(x, y, z);
}
}
/**
* Returns the wrapped OpenCascade object.
* @private
*/
get wrapped() {
return this.#wrapped;
}
/**
* Gets the X component of this vector.
*/
get x() {
return this.#wrapped.X();
}
/**
* Gets the Y component of this vector.
*/
get y() {
return this.#wrapped.Y();
}
/**
* Gets the Z component of this vector.
*/
get z() {
return this.#wrapped.Z();
}
/**
* Sets the X component of this vector.
*/
set x(value) {
this.#wrapped.SetX(value);
}
/**
* Sets the Y component of this vector.
*/
set y(value) {
this.#wrapped.SetY(value);
}
/**
* Sets the Z component of this vector.
*/
set z(value) {
this.#wrapped.SetZ(value);
}
/**
* Gets the length (magnitude) of this vector.
* @returns {number} The length of the vector.
*/
get length() {
return this.#wrapped.Magnitude();
}
/**
* Adds another vector to this vector.
* @param {Vector} other - The vector to add.
* @returns {Vector} A new `Vector` representing the result.
*/
add(other) {
return new Vector({wrapped: this.#wrapped.Added(other.wrapped)});
}
/**
* Subtracts another vector from this vector.
* @param {Vector} other - The vector to subtract.
* @returns {Vector} A new `Vector` representing the result.
*/
subtract(other) {
return new Vector({wrapped: this.#wrapped.Subtracted(other.wrapped)});
}
/**
* Multiplies this vector by a scalar.
* @param {number} scalar - The scalar to multiply by.
* @returns {Vector} A new `Vector` representing the result.
*/
multiply(scalar) {
return new Vector({wrapped: this.#wrapped.Multiplied(scalar)});
}
/**
* Divides this vector by a scalar.
* @param {number} scalar - The scalar to divide by.
* @returns {Vector} A new `Vector` representing the result.
*/
divide(scalar) {
return new Vector({wrapped: this.#wrapped.Divided(scalar)});
}
/**
* Computes the cross product of this vector with another vector.
* @param {Vector} other - The other vector.
* @returns {Vector} A new `Vector` representing the result.
*/
cross(other) {
return new Vector({wrapped: this.#wrapped.Crossed(other.wrapped)});
}
/**
* Computes the dot product of this vector with another vector.
* @param {Vector} other - The other vector.
* @returns {number} The dot product of the two vectors.
*/
dot(other) {
return this.#wrapped.Dot(other.wrapped);
}
/**
* Rotates this vector around a specified axis by a given angle.
* @param {Object} parameters - Rotation parameters.
* @param {Axis} parameters.axis - The axis to rotate around.
* @param {number} parameters.angle - The rotation angle in radians.
* @returns {Vector} A new `Vector` representing the result.
*/
rotate({axis, angle}) {
// For vectors, the rotation is applied around the direction of the axis, and the origin does not influence the rotation.
// This is because vectors represent directions without a fixed position in space.
// That's why we use a point to perform the rotation.
const result = new oc.gp_Pnt_3(this.#wrapped.X(), this.#wrapped.Y(), this.#wrapped.Z()).Rotated(axis.wrapped, angle);
return new Vector({
x: result.X(),
y: result.Y(),
z: result.Z(),
});
}
/**
* Scales this vector by a scalar.
* @param {number} scalar - The scaling factor.
* @returns {Vector} A new `Vector` representing the result.
*/
scale(scalar) {
return new Vector({wrapped: this.#wrapped.Scaled(scalar)});
}
/**
* Mirrors this vector across a specified plane.
* @param {Plane} plane - The plane to mirror across.
* @returns {Vector} A new `Vector` representing the mirrored result.
*/
mirror(plane) {
return new Vector({wrapped: this.#wrapped.Mirrored_3(plane.wrapped.Position().Ax2())});
}
/**
* Computes the distance between this vector and another vector.
* @param {Vector} other - The other vector.
* @returns {number} The distance between the vectors.
*/
distance(other) {
return this.#wrapped.Subtracted(other.wrapped).Magnitude();
}
/**
* Computes the angle between this vector and another vector.
* @param {Vector} other - The other vector.
* @returns {number} The angle between the vectors in radians.
*/
angle(other) {
return this.#wrapped.Angle(other.wrapped);
}
/**
* Normalizes this vector to have a length of 1.
* @returns {Vector} A new `Vector` representing the result.
*/
normalize() {
return new Vector({wrapped: this.#wrapped.Normalized()});
}
/**
* Checks if this vector is equal to another vector.
* @param {Vector} other - The other vector.
* @returns {boolean} `true` if the vectors are equal, `false` otherwise.
*/
isEqual(other) {
return this.#wrapped.IsEqual(other.wrapped, DEFAULT_LINEAR_TOLERANCE, DEFAULT_ANGULAR_TOLERANCE);
}
/**
* Checks if this vector is perpendicular (normal) to another vector.
* @param {Vector} other - The other vector.
* @returns {boolean} `true` if the vectors are perpendicular, `false` otherwise.
*/
isPerpendicular(other) {
return this.#wrapped.IsNormal(other.wrapped, DEFAULT_ANGULAR_TOLERANCE);
}
/**
* Checks if this vector is parallel to another vector.
* @param {Vector} other - The other vector.
* @returns {boolean} `true` if the vectors are parallel, `false` otherwise.
*/
isParallel(other) {
return this.#wrapped.IsParallel(other.wrapped, DEFAULT_ANGULAR_TOLERANCE);
}
/**
* The ZERO vector is an empty vector.
* @static
*/
static ZERO = new Vector();
/**
* The X vector is a unit vector pointing in the positive x direction.
* @static
*/
static X = new Vector({x: 1});
/**
* The NEGATIVE_X vector is a unit vector pointing in the negative x direction.
* @static
*/
static NEGATIVE_X = new Vector({x: -1});
/**
* The Y vector is a unit vector pointing in the positive y direction.
* @static
*/
static Y = new Vector({y: 1});
/**
* The NEGATIVE_Y vector is a unit vector pointing in the negative y direction.
* @static
*/
static NEGATIVE_Y = new Vector({y: -1});
/**
* The Z vector is a unit vector pointing in the positive z direction.
* @static
*/
static Z = new Vector({z: 1});
/**
* The NEGATIVE_Z vector is a unit vector pointing in the negative z direction.
* @static
*/
static NEGATIVE_Z = new Vector({z: -1});
}