Mercury Geometry and Math Library
修訂. | 7ff29fb8f53f14a882d75b05af9a84155d2a317b |
---|---|
大小 | 8,274 bytes |
時間 | 2022-04-24 05:04:00 |
作者 | Emily Dioxideson |
Log Message | Use vectors to implement geometry2d
|
% Copyright (C) 2017-2020 AlaskanEmily
%
% This Source Code Form is subject to the terms of the Mozilla Public
% License, v. 2.0. If a copy of the MPL was not distributed with this
% file, You can obtain one at http://mozilla.org/MPL/2.0/.
:- module mmath.vector.vector2.
%==============================================================================%
% 2D vector implementation.
:- interface.
%==============================================================================%
:- type vector ---> vector(x::float, y::float).
%------------------------------------------------------------------------------%
:- instance vector(vector2).
%------------------------------------------------------------------------------%
:- func get_x(vector2) = float.
:- func get_y(vector2) = float.
%------------------------------------------------------------------------------%
:- func cross(vector2, vector2) = float.
%------------------------------------------------------------------------------%
:- func (vector2::in) + (vector2::in) = (vector2::uo) is det.
:- func (vector2::in) - (vector2::in) = (vector2::uo) is det.
:- func (vector2::in) * (vector2::in) = (vector2::uo) is det.
:- func (vector2::in) / (vector2::in) = (vector2::uo) is det.
%------------------------------------------------------------------------------%
:- pred foldl(pred(float, T, T), vector2, T, T).
:- mode foldl(pred(in, in, out) is det, in, in, out) is det.
:- mode foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode foldl(pred(in, di, uo) is det, in, di, uo) is det.
:- mode foldl(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
:- mode foldl(pred(in, mdi, muo) is det, in, mdi, muo) is det.
%------------------------------------------------------------------------------%
:- pred foldr(pred(float, T, T), vector2, T, T).
:- mode foldr(pred(in, in, out) is det, in, in, out) is det.
:- mode foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode foldr(pred(in, di, uo) is det, in, di, uo) is det.
:- mode foldr(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
:- mode foldr(pred(in, mdi, muo) is det, in, mdi, muo) is det.
%------------------------------------------------------------------------------%
:- pred foldl_field(pred(func(vector2)=(float), vector2, T, T), vector2, T, T).
:- mode foldl_field(pred(func(in)=(out) is det, in, in, out) is det, in, in, out) is det.
:- mode foldl_field(pred(func(in)=(out) is det, in, in, out) is semidet, in, in, out) is semidet.
%------------------------------------------------------------------------------%
:- pred foldr_field(pred(func(vector2)=(float), vector2, T, T), vector2, T, T).
:- mode foldr_field(pred(func(in)=(out) is det, in, in, out) is det, in, in, out) is det.
:- mode foldr_field(pred(func(in)=(out) is det, in, in, out) is semidet, in, in, out) is semidet.
%------------------------------------------------------------------------------%
:- pred map(pred(float, float), vector2, vector2).
:- mode map(pred(in, out) is det, in, out) is det.
:- mode map(pred(in, out) is semidet, in, out) is semidet.
:- mode map(pred(di, uo) is det, di, uo) is det.
:- mode map(pred(mdi, muo) is semidet, mdi, muo) is semidet.
:- mode map(pred(mdi, muo) is det, mdi, muo) is det.
%------------------------------------------------------------------------------%
:- pred map_field(pred(func(vector2)=(float), vector2, float), vector2, vector2).
:- mode map_field(pred(func(in)=(out) is det, in, out) is det, in, out) is det.
:- mode map_field(pred(func(in)=(out) is det, in, out) is semidet, in, out) is semidet.
%------------------------------------------------------------------------------%
:- pred map_foldl(pred(float, float, T, T), vector2, vector2, T, T).
:- mode map_foldl(pred(in, out, in, out) is det, in, out, in, out) is det.
:- mode map_foldl(pred(in, out, in, out) is semidet, in, out, in, out) is semidet.
:- mode map_foldl(pred(di, uo, in, out) is det, di, uo, in, out) is det.
:- mode map_foldl(pred(in, out, di, uo) is det, in, out, di, uo) is det.
:- mode map_foldl(pred(di, uo, di, uo) is det, di, uo, di, uo) is det.
:- mode map_foldl(pred(mdi, muo, in, out) is det, mdi, muo, in, out) is det.
:- mode map_foldl(pred(mdi, muo, in, out) is semidet, mdi, muo, in, out) is semidet.
:- mode map_foldl(pred(mdi, muo, mdi, muo) is semidet, mdi, muo, mdi, muo) is semidet.
:- mode map_foldl(pred(mdi, muo, mdi, muo) is det, mdi, muo, mdi, muo) is det.
:- mode map_foldl(pred(mdi, muo, di, uo) is det, mdi, muo, di, uo) is det.
%------------------------------------------------------------------------------%
:- pred map_foldr(pred(float, float, T, T), vector2, vector2, T, T).
:- mode map_foldr(pred(in, out, in, out) is det, in, out, in, out) is det.
:- mode map_foldr(pred(in, out, in, out) is semidet, in, out, in, out) is semidet.
:- mode map_foldr(pred(di, uo, in, out) is det, di, uo, in, out) is det.
:- mode map_foldr(pred(in, out, di, uo) is det, in, out, di, uo) is det.
:- mode map_foldr(pred(di, uo, di, uo) is det, di, uo, di, uo) is det.
:- mode map_foldr(pred(mdi, muo, in, out) is det, mdi, muo, in, out) is det.
:- mode map_foldr(pred(mdi, muo, in, out) is semidet, mdi, muo, in, out) is semidet.
:- mode map_foldr(pred(mdi, muo, mdi, muo) is semidet, mdi, muo, mdi, muo) is semidet.
:- mode map_foldr(pred(mdi, muo, mdi, muo) is det, mdi, muo, mdi, muo) is det.
:- mode map_foldr(pred(mdi, muo, di, uo) is det, mdi, muo, di, uo) is det.
%==============================================================================%
:- implementation.
%==============================================================================%
:- import_module float.
%------------------------------------------------------------------------------%
get_x(V) = V ^ x.
get_y(V) = V ^ y.
%------------------------------------------------------------------------------%
cross(vector(X1, Y1), vector(X2, Y2)) = (X1 * Y2) - (Y1 * X2).
%------------------------------------------------------------------------------%
(vector(X1, Y1)) + (vector(X2, Y2)) = (vector(X1+X2, Y1+Y2)).
(vector(X1, Y1)) - (vector(X2, Y2)) = (vector(X1-X2, Y1-Y2)).
(vector(X1, Y1)) * (vector(X2, Y2)) = (vector(X1*X2, Y1*Y2)).
(vector(X1, Y1)) / (vector(X2, Y2)) = (vector(X1/X2, Y1/Y2)).
%------------------------------------------------------------------------------%
:- instance vector(vector2) where [
magnitude_squared(vector(X, Y)) = ((X*X) + (Y*Y)),
scale(vector(X, Y), S) = vector(X*S, Y*S),
multiply(vector(X1, Y1), vector(X2, Y2)) = vector(X1*X2, Y1*Y2),
divide(vector(X1, Y1), vector(X2, Y2)) = vector(X1/X2, Y1/Y2),
add(vector(X1, Y1), vector(X2, Y2)) = vector(X1+X2, Y1+Y2),
sub(vector(X1, Y1), vector(X2, Y2)) = vector(X1-X2, Y1-Y2),
dot(vector(X1, Y1), vector(X2, Y2)) = ((X1*X2) + (Y1*Y2)),
reciprocal(vector(X, Y)) = vector(1.0/X, 1.0/Y)
].
%------------------------------------------------------------------------------%
foldl(Pred, vector(X, Y), !T) :- Pred(X, !T), Pred(Y, !T).
%------------------------------------------------------------------------------%
foldr(Pred, vector(X, Y), !T) :- Pred(Y, !T), Pred(X, !T).
%------------------------------------------------------------------------------%
foldl_field(Pred, Vec, !T) :- Pred(get_x, Vec, !T), Pred(get_y, Vec, !T).
%------------------------------------------------------------------------------%
foldr_field(Pred, Vec, !T) :- Pred(get_y, Vec, !T), Pred(get_x, Vec, !T).
%------------------------------------------------------------------------------%
map(Pred, vector(XIn, YIn), vector(XOut, YOut)) :-
Pred(XIn, XOut),
Pred(YIn, YOut).
%------------------------------------------------------------------------------%
map_field(Pred, Vec, vector(X, Y)) :-
Pred(get_x, Vec, X),
Pred(get_y, Vec, Y).
%------------------------------------------------------------------------------%
map_foldl(Pred, vector(XIn, YIn), vector(XOut, YOut), !T) :-
Pred(XIn, XOut, !T),
Pred(YIn, YOut, !T).
%------------------------------------------------------------------------------%
map_foldr(Pred, vector(XIn, YIn), vector(XOut, YOut), !T) :-
Pred(YIn, YOut, !T),
Pred(XIn, XOut, !T).
%------------------------------------------------------------------------------%