15 クロソイド   [もくじへ] [トップページへ] [前ページへ]

直線部から円曲線に進む場合、カーブの変化を緩やかにするために緩和曲

線を設置します。通常、道路ではクロソイド曲線を緩和曲線として用います。

15.1 クロソイド曲線

クロソイド曲線は、曲線長 L と半径 R が反比例する曲線で、

   R×L = A2 (Aは定数)

と表されます。

定数Aをパラメーターといいます。また、A = 1 のときのクロソイド曲線を単位

クロソイド曲線といいます。したがって、単位クロソイド曲線の各要素を A

すると、実際の値を求めることができます。

           

上図において、KA から KE 間がクロソイド曲線で、KE から円曲線が接続しま

す。

KA での接線 X 軸と、 KE での接線のなす角τをらせん角といいます。

任意点でのクロソイド曲線長 L、半径 R、そしてτとの間には、

   τ = L/2R

の関係があります。このτより、クロソイド曲線上の座標 (X,Y) が次のべき級

数により求められます。

   

それでは、この式を使ってクロソイド曲線の座標を求めるプログラムを考えて

みましょう。

===================================================

プログラム例題30

クロソイド曲線上の任意点までの距離 L、半径 R、そしてパラメータ A より、

その点の座標を求めよ。

=========================================================

考え方

まず、τを計算します。

次に、X座標を求めますが、この式の( )内の第 k 項を一般式で表すと、次

のようになります。

   

この式の値を、求めたい座標の精度(例えば小数第3位)になるまで順次計算

します。

(1) 各項の符号

   第1項を 1 にして、第2項以下に -1 を掛けます。

(2)1/ {2(k-1)}! の計算

  分母は、

   0! = 1, 2!=2×1,4!=4×3×2×1, 6!=6×5×4×3×2×1,・・・

  ですから、

  第1項・・・ 1

  第2項・・・ 第1項×2

  第3項・・・ 第2項×3×4

  第4項・・・ 第3項×5×6

  のように、第k項は第k−1項に、(2k-2)×(2k-3) を掛けます。

(3)1/ (4k-3) の計算

  これはそのままです。

(4)τ2(k-1) の計算

  第1項を1にして、第k項は第k−1項に、τ2 を掛けます。

 

(1)から(4)をまとめます。

第k−1項の(1)(2)(4)の積の部分を Pk−1、第k−1項を Qk−1 とします。

第k項をもとめるには、

  (@) P = Pk−1×(-1)/((2k-2)×(2k-3))×τ2

  (A) Q = P/(4k-3)

(@)(A)を繰り返して( )内の各項を合計します。

このようにして、( )内を第k−1項まで計算したときと、第k項まで計算したと

きのX座標をそれぞれ Xk-1Xk とすると、|Xk−Xk-1|<0.001 のとき計

算を終了させます。

 

Y座標も同様に考えます。Y座標の計算における P Q は次のようになり

ます。

  (B) P = Pk−1×(-1)/((2k-1)×(2k-2))×τ2

  (C) Q = P/(4k-1)

 

また、半径 R(右カーブ:正、左カーブ:負)の符号によってY座標の符号は変

化することも考慮します。


プログラム

 

<HTML>
<HEAD>
   <TITLE>例題30(クロソイド曲線)</TITLE>

<SCRIPT LANGUAGE="JavaScript">
<!--
// 入力データ
        var Li;              // クロソイド曲線長
        var Ri;              // 半径
        var Pa;              // パラメータ
        var Er;              // 制限値
//
        Li = 50;
        Ri = 200;
        Pa = 100;
        Er = 0.001;
//
// 出力データ
        var Xi,Yi;           // クロソイド座標
//
        function Cloxy(l,r,a) {
                var s;             // ()内の各項の合計
                var pk;            //
X: (-1)/((2k-2)×(2k-3))×τ^2
                                   //
Y: (-1)/((2k-1)×(2k-2))×τ^2
                var qk;            //
X: pk/(4k-3)
                                   //
Y: pk/(4k-1)
                var tau;           //
τ
                var k;             //
第k項のk
                var xk;            //
第k項までの座標値
                var xo;            //
第k-1項までの座標値
                var sg;            //
rの符号
//
                if (r>=0) {
                   sg = 1;
                }
                else {
                   sg =-1;
                }
//    X座標
                s = 1;
                pk = 1;
                k = 1;
                tau = l/(2*Math.abs(r));
                xk = a*Math.sqrt(2*tau);
                xo = 0;
                x = xk;
                while (Math.abs(x-xo)>=Er) {
                   xo = x;
                   k = k + 1;
                   
pk = pk*(-1)/((2*k-2)*(2*k-3))*tau*tau;
                   
qk = pk/(4*k-3);
                   
s = s + qk;
                   
x = xk*s;
                }
                Xi = Rund(x,3);
//    Y座標
                s = 1/3;
                pk = 1;
                k = 1;
                xk = a*tau*Math.sqrt(2*tau);
                xo = 0;
                y = xk*s;
                while (Math.abs(y-xo)>=Er) {
                   xo = y;
                   k = k + 1;
                   
pk = pk*(-1)/((2*k-1)*(2*k-2))*tau*tau;
                   
qk = pk/(4*k-1);
                   
s = s + qk;
                   
y = xk*s;
                }
                Yi = sg*Rund(y,3);
        }
//
//
//  四捨五入
//
        function Rund(x,y) {
                var sg, r;
                if (x>=0) {sg = 1;}
                else {sg =-1;}
                r = sg*Math.floor(Math.abs(x)*Math.pow(10,y) + 0.5)/Math.pow(10,y);
                return r;
        }
//
                // 計算ボタンをクリック
//
        function onCAL( ) {
                var ret;
//
                ret = Cloxy(Li,Ri,Pa)
                Cloprt();
//
        }
//
//
//
function Cloprt() {
//
//
//=================== クロソイド曲線計算結果出力 =============================
//
      document.write ("<CENTER>","*** クロソイド曲線 ***","</CENTER><BR>");
//
      document.write ("<CENTER><TABLE BORDER='0'>");
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='right'>","   L = ","</TD>");
      document.write ("<TD ALIGN='right'>",Li,"</TD></TR>");
      document.write ("<TD ALIGN='right'>","   R = ","</TD>");
      document.write ("<TD ALIGN='right'>",Ri,"</TD></TR>");
      document.write ("<TD ALIGN='right'>","   A = ","</TD>");
      document.write ("<TD ALIGN='right'>",Pa,"</TD></TR>");
      document.write ("<TD ALIGN='right'>","</TD></TR>");
//
      document.write ("<TD ALIGN='right'>","   X = ","</TD>");
      document.write ("<TD ALIGN='right'>",Xi,"</TD></TR>");
      document.write ("<TD ALIGN='right'>","   Y = ","</TD>");
      document.write ("<TD ALIGN='right'>",Yi,"</TD></TR>");
      document.write ("</TABLE>");
}
//
// -->
</SCRIPT>

</HEAD>


<BODY>


<FORM NAME="Form1">
 *** クロソイド曲線 ***<BR>
<BR>
<INPUT TYPE="button" NAME="CAL" VALUE="計 算" onClick="onCAL( )">
<HR>

</FORM>



</BODY>
</HTML>


入力データと実行結果

     入力データ

      クロソイド曲線長
            L = 50
      半径
            R = 200
      パラメータ
            A = 100

     ※データ入力は、代入文で直接代入しています。

     ※ボタンをクリックして実行します。

 

     計算結果

*** クロソイド曲線 ***

   L = 50
   R = 200
   A = 100
 
   X = 49.922
   Y = 2.081

プログラムの説明

このような級数計算を行うには、なるべく誤差を少なくしたり、計算速度を速く

する方法等がプログラミング技法として考えられますが、ここではオーソドック

スに計算式をそのままプログラミングすることにします。

 

function Cloxy(l,r,a) {
        
var s;             // ()内の各項の合計
        
var pk;            // X: (-1)/((2k-2)×(2k-3))×τ^2
                           // Y: (-1)/((2k-1)×(2k-2))×τ^2
        
var qk;            // X: pk/(4k-3)
                           // Y: pk/(4k-1)
        
var tau;           // τ
        
var k;             // 第k項のk
        
var xk;            // 第k項までの座標値
        
var xo;            // 第k-1項までの座標値
        
var sg;            // rの符号
//
        
if (r>=0) {  
@
           
sg = 1;
        
}
        
else {
           
sg =-1;
        
}
// X座標
        
s = 1;
        
pk = 1;
        
k = 1;
        
tau = l/(2*Math.abs(r));
        
xk = a*Math.sqrt(2*tau);
        
xo = 0;
        
x = xk;
        
while (Math.abs(x-xo)>=Er) {  
A
           
xo = x;
           
k = k + 1;
           
pk = pk*(-1)/((2*k-2)*(2*k-3))*tau*tau;
           
qk = pk/(4*k-3);
           
s = s + qk;
           
x = xk*s;  
B
        
}
        
Xi = Rund(x,3);
// Y座標
   ・
   ・
   ・
}

@ 半径 R の符号を調べ、変数 sg に代入します。

A 第k-1項まで計算したX座標と、第k項のX座標の差が制限値 Er より

   小さくなるまで計算を繰り返します。

B 第k項までのX座標です。変数 は、級数の( )内の第k項までの和で

   す

座標も同様です。


[もくじへ] [トップページへ]

 りょうかんのアドバイス

級数というのは、数列の各項を和・差の符号で結んだものです。これをプログ

ラミングするには、合計、階乗、そしてべき乗を求める方法を知らなければな

りません。

合計を S、各データを X とすると、

  S = 0 として

  S = S + X をデータの個数繰り返します。

N! ( N の階乗 )を NK、カウントする変数を i とすると、

  NK = 1i = 1 として

  NK = NK × ii = i + 1N 回繰り返します。

Ak を求めるには、べき乗の関数を使ってもいいですが、

  Ak-1 まで求められている場合、

  Ak = Ak-1 ×A で計算します。

 

次回は、『基本型クロソイド曲線の設置』の予定です。(11月20日ごろ)

この講座に対する、ご意見やご要望はメールでお願いします。

      『JavaScriptによる測量計算プログラミング入門』 

                                講師 りょうかん


[もくじへ] [トップページへ] [次ページへ]