mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-20 20:03:44 +00:00
139 lines
3.1 KiB
Mathematica
139 lines
3.1 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module vector.
|
|
% a 3D vector module.
|
|
|
|
:- interface.
|
|
|
|
:- import_module float, pair.
|
|
|
|
:- type real == float.
|
|
:- type vector ---> point(real, real, real).
|
|
:- type position == point.
|
|
:- type point == vector.
|
|
|
|
:- func '+'(vector, vector) = vector.
|
|
|
|
:- func '-'(vector, vector) = vector.
|
|
|
|
:- func '-'(vector) = vector.
|
|
|
|
:- func dot(vector, vector) = real.
|
|
|
|
% Dot product, but zeroed if not positive.
|
|
:- func positive_dot(vector, vector) = real.
|
|
|
|
:- func cross(vector, vector) = vector.
|
|
|
|
:- func mag(vector) = real.
|
|
|
|
% The square of the magnitude.
|
|
:- func mag2(vector) = real.
|
|
|
|
% The square of the distance between two points.
|
|
:- func distance_squared(point, point) = real.
|
|
|
|
:- func unit(vector) = vector.
|
|
|
|
:- func scale(real, vector) = vector.
|
|
|
|
:- func angle(vector, vector) = real.
|
|
|
|
% ProjectedV1 = project(V1, V2)
|
|
% Find the projection of V1 onto V2
|
|
:- func project(vector, vector) = vector.
|
|
|
|
% Project vector onto XY plane.
|
|
:- func projectXY(vector) = vector.
|
|
|
|
:- func projectXZ(vector) = vector.
|
|
|
|
:- func projectZY(vector) = vector.
|
|
|
|
% Return a pair containing the X and Y coords of the vector.
|
|
:- func xy(vector) = pair(real).
|
|
|
|
:- func xz(vector) = pair(real).
|
|
|
|
:- func zy(vector) = pair(real).
|
|
|
|
% Some useful constants.
|
|
:- func zero = vector.
|
|
:- func i = vector.
|
|
:- func j = vector.
|
|
:- func k = vector.
|
|
|
|
:- func real_epsilon = real.
|
|
:- func real_max = real.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module math.
|
|
|
|
point(Ax, Ay, Az) + point(Bx, By, Bz) = point(Ax+Bx, Ay+By, Az+Bz).
|
|
|
|
point(Ax, Ay, Az) - point(Bx, By, Bz) = point(Ax-Bx, Ay-By, Az-Bz).
|
|
|
|
-point(X, Y, Z) = point(-X, -Y, -Z).
|
|
|
|
dot(point(Ax, Ay, Az), point(Bx, By, Bz)) = Ax*Bx + Ay*By + Az*Bz.
|
|
|
|
positive_dot(A, B) = PosDot :-
|
|
dot(A, B) = Dot,
|
|
( Dot < 0.0 ->
|
|
PosDot = 0.0
|
|
;
|
|
PosDot = Dot
|
|
).
|
|
|
|
cross(point(Ax, Ay, Az), point(Bx, By, Bz)) = point(Cx, Cy, Cz) :-
|
|
Cx = Ay*Bz - Az*By,
|
|
Cy = Az*Bx - Ax*Bz,
|
|
Cz = Ax*By - Ay*Bx.
|
|
|
|
mag(V) = math__sqrt(mag2(V)).
|
|
|
|
:- pragma inline(func(mag2/1)).
|
|
mag2(point(Ax, Ay, Az)) = Ax*Ax + Ay*Ay + Az*Az.
|
|
|
|
distance_squared(point(X1, Y1, Z1), point(X2, Y2, Z2)) = DistanceSquared :-
|
|
DX = X1 - X2,
|
|
DY = Y1 - Y2,
|
|
DZ = Z1 - Z2,
|
|
DistanceSquared = DX * DX + DY * DY + DZ * DZ.
|
|
|
|
:- pragma inline(func(unit/1)).
|
|
unit(point(Ax, Ay, Az)) = point(Ax/Mag, Ay/Mag, Az/Mag) :-
|
|
Mag = mag(point(Ax, Ay, Az)).
|
|
|
|
scale(S, point(Ax, Ay, Az)) = point(S*Ax, S*Ay, S*Az).
|
|
|
|
% calculate angle between 2 vectors
|
|
angle(V1, V2) = math__acos(dot(V1, V2) / mag(V1) / mag(V2)).
|
|
|
|
project(V1, V2) = Projection :-
|
|
UnitV2 = unit(V2),
|
|
Projection = scale(dot(V1, UnitV2), UnitV2).
|
|
|
|
projectXY(point(X, Y, _)) = point(X, Y, 0.0).
|
|
|
|
projectXZ(point(X, _, Z)) = point(X, 0.0, Z).
|
|
|
|
projectZY(point(_, Y, Z)) = point(0.0, Y, Z).
|
|
|
|
xy(point(X, Y, _)) = X - Y.
|
|
|
|
xz(point(X, _, Z)) = X - Z.
|
|
|
|
zy(point(_, Y, Z)) = Z - Y.
|
|
|
|
zero = point(0.0, 0.0, 0.0).
|
|
i = point(1.0, 0.0, 0.0).
|
|
j = point(0.0, 1.0, 0.0).
|
|
k = point(0.0, 0.0, 1.0).
|
|
|
|
real_epsilon = float__epsilon.
|
|
real_max = float__max.
|