今回からしばらくは描画用の計算サブルーチンを書いて行きます。


 角度でソートする場合など、角度を決まった範囲内に収めたい場合があります。例えば 0°〜360° や -180°〜+180° に収まるようにです。具体的には角度が下限より小さければ360を足し、上限以上なら360を引きます。


(* -------- 角度を指定した範囲に収める -------- *)


function NormalAngle360(ang, minAng: real): real; { 角度を指定した範囲内の角度にして返す。 }

{ 角度範囲は miniAng〜miniAng+360である。

  miniAng <= ang < maxAng となるようにangを調整する。 }

Const

dA = 360;

var

result, maxAng :real;

begin

maxAng:= minAng + dA;

if ang < minAng then

result:= ang + dA * (Trunc((miniAng - ang) / dA) + 1)

else if maxAng <= ang then

result:= ang - dA * (Trunc((maxAng - ang) / dA) + 1)

else

result:= ang;

NormalAngle360:= result;

end;{NormalAngle360}

(2022/09/30:修正 )



 直線の角度は始点と終点の順番によって180度変わるので、角度を180度の範囲に収めたい場合があります。例えば 0°〜180° や -90°〜+90° に収まるようにです。NormalAngle360との違いは定数dAの値だけです。


function NormalAngle180(ang, minAng: real): real; { 角度を指定した範囲内の角度にして返す。 }

{ 角度範囲はminiAng〜miniAng+180である。

  Tan(ang)を変えずに miniAng <= ang < maxAng となるようにangを調整する。 }

Const

dA = 180;

var

result, maxAng :real;

begin

maxAng:= minAng + dA;

if ang < minAng then

result:= ang + dA * (Trunc((miniAng - ang) / dA) + 1)

else if maxAng <= ang then

result:= ang - dA * (Trunc((maxAng - ang) / dA) + 1)

else

result:= ang;

NormalAngle180:= result;

end;{NormalAngle180}

(2022/09/30:修正 )



 ベクトル計算の組込みサブルーチンでは角度の単位は度なので、三角関数もラジアンでなく度のほうが都合が良いです。Sin(角度 * Pi / 180) や Sin(Deg2Rad(角度)) と書くのは面倒なので専用の関数を作りました。

 関数名は、結局は元の関数の名前の最後にDegreeのDを付けましたが、Ang2SinやSin2Angが最初の候補でした。新しく作ったサブルーチンの名前との整合性を取るか、元の関数からの類推のしやすさを取るかで悩みました。両方作ってしまうという最終手段がありますが、とりあえずはこれで我慢しておきます。


(* -------- 度を角度単位とした三角関数 -------- *)


function SinD(ang :real); { Sinを度で計算して返す }

begin

SinD:= Sin(ang * Pi / 180);

end;


function CosD(ang :real); { Cosを度で計算して返す }

begin

CosD:= Cos(ang * Pi / 180);

end;


function TanD(ang :real); { Tanを度で計算して返す }

begin

TanD:= Tan(ang * Pi / 180);

end;



function ArcSinD(sinA :real); { ArcSinを度で計算して返す }

begin

ArcSinD:= ArcSin(sinA) * 180 / Pi;

end;


function ArcCosD(cosA :real); { ArcCosを度で計算して返す }

begin

ArcCosD:= ArcCos(cosA) * 180 / Pi;

end;


function ArcTanD(tanA :real); { ArcTanを度で計算して返す }

begin

ArcTanD:= ArcTan(tanA) * 180 / Pi;

end;



 一度にSinとCosの値が欲しいことが良くあるので手続きにしました。


procedure Ang2SinCos(ang :real; var sinA, cosA :real);

{ Sin(ang)とCos(ang)を返す(角度の単位は度) }

var

v ;real;

begin

v:= Ang2Vec(ang, 1);

cosA:= v.x; sinA:= v.y;

end;



 ArcTan関数では垂直の角度は得られません。 組込み関数だけだと、

v.x:= dx;

v.y:= dy;

ang:= Vec2Ang(v);

のように書かなくてはなりません。以前に書いたベクトル変数の関数を使えば、

ang:= Vec2Ang(XY2Vec(dx, dy));

のようにひとつの文に出来ますが、もっと簡単に、

ang:= XY2Ang(dx, dy);

と書けるように新しい関数を作りました。


(* -------- dx, dy から角度(度)/長さを返す。 -------- *)


function XY2Ang(dx, dy :real): real; { dx, dy から角度(度)を返す。 }

var

v :vector;

begin

v.x:= dx; v.y:= dy; v.z:= 0;

XY2Ang:= Vec2Ang(v);

end;


 そういえば、手計算やExcelではTangentをいますが、プログラムではあまり使いませんね。±90度で答えが無限大になってエラーが出るので、条件分けの必要があって面倒です。




 dXとdYから長さを求めたいことは多いのですが、ピタゴラスの定理( dist:= Sqrt(dx * dx + dy * dy); )やベクトルに変換しての計算( dist:= Vec2Dist(XY2Dist(dx, dy); )をいちいち書くのは面倒なので関数にしました。


function XY2Dist(dx, dy :real): real; { dx, dy から長さを返す。 }

begin

XY2Dist:= Sqrt(dx * dx + dy * dy);

end;