Unit UVector;
 INTERFACE
type
  pVec = ^tVec;
  tVec = record
    x, y, z : double;
  end;

CONST
  EPS : double = 1e-6;
  INF : double = 1e30;
  ZEROVEC : tVec = (X:0;Y:0;Z:0);

 Function Max(a,b:double):double; {}
 Function vCos(a,b:tVec):double; {Cos(a^b) || 0, если a^b > 90}
 Function aCos(a,b:tVec):double; {|Cos(a^b)|}
 Function rCos(a,b:tVec):double; {Cos(a^b)}
 Function Tan(a:double):double;
 Function ArcCos(x:real):real;

 Function Pow(a:double;N:double):double; {a ^ N}

 Procedure VSet(var aR:tVec;x,y,z : double); {И так понятно}
 Procedure VNorm(var aV:tVec;aLen:double); {Нормализация вектора}
 Function  VDot(aV1,aV2:tVec):double; {v1.v2 Скалярное произведение}
 Procedure VCross(var R : tVec;aV1,aV2:tVec); {v1 X v2 Векторное произведение}
 Procedure VLinear(var V:tVec;V1,V2:tVec;k1,k2:double);
 Function  VLength(aV:tVec):double;
   {Линейная продукция (V=V1*k1+V2*K2}

 Procedure VRandomize(var aN:tVec;C:double); {Небольшое случайное
                                              изменение вектора}

IMPLEMENTATION

Procedure VLinear; {Линейная продукция (V=V1*k1+V2*K2}
begin
 V.x:= V1.x*k1 + V2.x*K2;
 V.y:= V1.y*k1 + V2.y*K2;
 V.z:= V1.z*k1 + V2.z*K2;
end;{Linear}
{--------------------------------------------------------------------}
Function  VDot; {v1.v2 Скалярное произведение}
begin
  VDot := aV1.X*aV2.X + aV1.Y*aV2.Y + aV1.Z*aV2.Z;
end;{DotMul}
{--------------------------------------------------------------------}
Procedure  VCross; {v1 X v2 Векторное произведение}
begin
     R.X := av1.y*av2.z - av1.z*av2.y;
     R.Y := av1.z*av2.x - av1.x*av2.z;
     R.Z := av1.x*av2.y - av1.y*av2.x;
end;{XMul}
{--------------------------------------------------------------------}
Procedure VSet; {И так понятно}
begin
  aR.x := x;aR.y := y;aR.z := z;
end;
{--------------------------------------------------------------------}
Procedure VNorm(var aV:tVec;aLen:double); {Нормализация вектора}
{By IE}
var len : double;
begin
  Len := sqrt(VDot(aV,aV));
  aV.X := aV.X*aLen / Len;
  aV.Y := aV.Y*aLen / Len;
  aV.z := aV.z*aLen / Len;
end;{VNorm}
Function Max;
begin
  if A > B then Max:=a
  else Max:=b;
end;{Max}
{--------------------------------------------------------------------}
Function vCos(a,b:tVec):double; {Cos(a^b) || 0, если a^b > 90}
begin
 vCos:=Max(VDot(a, b), 0) / sqrt(VDot(a, a) * VDot(b, b));
end;{vCos}
{------------------------------------------}
Function aCos(a,b:tVec):double; {|Cos(a^b)|}
begin
 aCos:=abs(VDot(a, b)) / sqrt(VDot(a, a) * VDot(b, b));
end;{vCos}
{------------------------------------------}
Function rCos(a,b:tVec):double; {Cos(a^b)}
begin
 rCos:=VDot(a, b) / sqrt(VDot(a, a) * VDot(b, b));
end;{vCos}
{------------------------------------------}
Function Tan(a:double):double;
begin
  if Frac(2*a/pi) <> 0 then Tan:=sin(a)/cos(a)
  else Tan := INF;
end;
{------------------------------------------}
Function Pow(a:double;N:double):double; {a ^ N}
begin
  if a <> 0 then
     Pow:=Exp(Ln(a)*n)
  else Pow:=0;
end;
{------------------------------------------}
Function  ArcCos(x:real):real;
begin
  if abs(x) > 1 then exit;
  if x=0 then ArcCos := PI / 2
  else
   ArcCos := ArcTan(sqrt(1-x*x)/X);
end;
{------------------------------------------}
Function VLength;
begin
  VLength := sqrt(aV.X*aV.X + aV.Y*aV.Y + aV.z*aV.z);
end;
{------------------------------------------}
Procedure VRandomize;
begin
 with aN do begin
   X := X + (-1+Random(2)*2) * Random * C;
   Y := Y + (-1+Random(2)*2) * Random * C;
   Z := Z + (-1+Random(2)*2) * Random * C;
 end;
end;
END.
