14.3 円曲線の巾杭計算   [もくじへ] [トップページへ] [前ページへ]

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

プログラム例題29

中間点計算後の巾杭計算をおこなえ。

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

考え方

         

 

中間点計算の後は、巾杭点の計算を行います。この計算は各中間点ごとに

左右の巾を入力して、それぞれの中間点における接線の法線方向の座標と

方向角を求めるものです。

したがって、計算には中間点計算の接線方向角と、中間点の座標、それと、

左右の巾が必要です。

通常は各中間点ごとの左右巾を入力できるようにするのが実用的ですが、こ

こでは、簡単のために左右の巾はそれぞれ一定の値を入力するものとします。

 

計算式を次に示します。

   左巾を WL、右巾を WR、中間点の接線方向角を αS、中間点の座標を

   ( XC,YC ) とします。

   左の巾杭点の座標 ( XL,YL )

     XL = XC + WLcos(αS-90°)

     YL = YC + WLsin(αS-90°)

   右の巾杭点の座標 ( XR,YR )

     XR = XC + WRcos(αS+90°)

     YR = YC + WRsin(αS+90°)

 


プログラム

 

<HTML>
<HEAD>
   <TITLE>例題29(円曲線の巾杭計算)</TITLE>

<SCRIPT LANGUAGE="JavaScript">
<!--
// 入力データ
        var XBP,YBP;          // BPの座標
        var XIP,YIP;          // IPの座標
        var XEP,YEP;          // EPの座標
        var RR;               // R
//
        var SP;              // ステーションピッチ
        var DL;              // 等間隔長
        var FN;              // BP No.FN + SN
        var SN;              //
        var sta1, sta2;      // 追加距離をFNとSNに変換
        var BPT;             // BPの追加距離
        var BCT;             // BCの追加距離
        var ECT;             // ECの追加距離
        var EPT;             // EPの追加距離
        var n;               // 中間点数
//
        var WL;              // 左巾
        var WR;              // 右巾
//
        XBP = -51274.2779;
        YBP = -31305.5806;
        XIP = -51813.3467;
        YIP = -31423.3201;
        XEP = -52144.8230;
        YEP = -31551.5362;
        RR = 2000;
//
        SP = 100;
        DL = 20;
        FN = 0;
        SN = 0;
//
        WL = 10.0000;
        WR = 15.0000;
//
// 出力データ
        var XBC,YBC;         // BCの座標
        var XEC,YEC;         // ECの座標
        var XSP,YSP;         // SPの座標
        var XM,YM;           // Mの座標
        var IA;              // IA
        var CL;              // CL
        var AL1,AL2;         // α1,α2
        var L1,L2;           // L1,L2
        var TL;              // TL
        var SL;              // SL
//
        TK = new Array(500);   // 中間点の追加距離
        CX = new Array(500);   // 中間点のX座標
        CY = new Array(500);   // 中間点のY座標
        SA = new Array(500);   // 中間点の接線方向角
        GA = new Array(500);   // 中間点の弦方向角
        GL = new Array(500);   // 中間点間の直線距離
//
        XL = new Array(500);   // 左巾杭点のX座標
        YL = new Array(500);   // 左巾杭点のY座標
        XR = new Array(500);   // 右巾杭点のX座標
        YR = new Array(500);   // 右巾杭点のY座標
//
//
//
        var doo, fun, byo;     // 度分秒
        var fs, es;            // ステーションNo.
//
        function Dist(xa, ya, xb, yb) {
                var ss;
//
                ss = Math.sqrt(Math.pow((xb-xa),2) + Math.pow((yb - ya),2));
                return ss;
        }
//
//
        function Alph(xa, ya, xb, yb) {
                var dx, dy;
                var Thi;              // atan(dy/dx)
                var A;
//
                dx = xb - xa;
                dy = yb - ya;
//
                if (dx == 0) {
                     if (dy == 0) { A = 0; }
                     if (dy > 0) { A = Math.PI/2; }
                     if (dy < 0) { A = Math.PI*3/2; }
                }
//
                if (dx != 0) { Thi = Math.atan(dy/dx); }
//
                if (dx > 0) {  A = Thi + 2*Math.PI;  }
//
                if (dx < 0) {  A = Thi + Math.PI;  }
//
                if (A >= 2*Math.PI) { A = A - 2*Math.PI; }
                return A;
//
        }

//
//
//  角度の変換(秒を度分秒に)
//
        function Byodfb( x ) {
                if (x<0) {x = x + 1296000;}
                doo = Math.floor(x/3600);
                fun = Math.floor((x - doo*3600)/60);
                byo = x - doo*3600 - fun*60;
                if (byo<0) {byo = 0;}
        }
//
//
//  四捨五入
//
        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;
        }
//
//
//  追加距離をステーションNo.に変換
//
        function Sta(x) {
                sta1 = Math.floor(x/SP);
                sta2 = Rund(x - sta1*SP,4);
        }
//
//
                // 計算ボタンをクリック
//
        function onCAL( ) {
                var i, r;
                var x1,y1,x2,y2;
//
                // α1, α2, L1, L2
                x1 = XBP;
                y1 = YBP;
                x2 = XIP;
                y2 = YIP;
                AL1 = Alph(x1,y1,x2,y2);
                L1 = Dist(x1,y1,x2,y2);
                x1 = XIP;
                y1 = YIP;
                x2 = XEP;
                y2 = YEP;
                AL2 = Alph(x1,y1,x2,y2);
                L2 = Dist(x1,y1,x2,y2);
//
                // IA
                IA = AL2 - AL1;
                if (IA<0) { IA = IA + 2*Math.PI; }
//
                // TL
                TL = Math.abs(RR)*Math.tan(IA/2);
//
                // BC
                XBC = XBP + (L1-TL)*Math.cos(AL1);
                YBC = YBP + (L1-TL)*Math.sin(AL1);
//
                // EC
                XEC = XIP + TL*Math.cos(AL2);
                YEC = YIP + TL*Math.sin(AL2);
//
                // M
                if (RR>0) {
                   XM = XBC + RR*Math.cos(AL1+Math.PI/2);
                   YM = YBC + RR*Math.sin(AL1+Math.PI/2);
                }
                else {
                   XM = XBC + Math.abs(RR)*Math.cos(AL1-Math.PI/2);
                   YM = YBC + Math.abs(RR)*Math.sin(AL1-Math.PI/2);
                }
//
                // SL
                SL = Math.abs(RR)/Math.cos(IA/2) - Math.abs(RR);
//
                // SP
                if (RR>0) {
                   XSP = XIP + SL*Math.cos(AL1+Math.PI/2+IA/2);
                   YSP = YIP + SL*Math.sin(AL1+Math.PI/2+IA/2);
                }
                else {
                   XSP = XIP + SL*Math.cos(AL1-Math.PI/2-IA/2);
                   YSP = YIP + SL*Math.sin(AL1-Math.PI/2-IA/2);
                }
//
                // CL
                CL = Math.abs(RR)*IA;
//
//
//
//
//
//========================= 中間点計算 =====================================
//
//        TK[]          // 中間点の追加距離
//        CX[]          // 中間点のX座標
//        CY[]          // 中間点のY座標
//        SA[]          // 中間点の接線方向角
//        GA[]          // 中間点の弦方向角(後ろの点からの)
//        GL[]          // 中間点間の直線距離(後ろの点からの)
//
//      追加距離
                BPT = FN*SP + SN;
                BCT = BPT + L1 - TL;
                ECT = BCT + CL;
                EPT = ECT + L2 - TL;
//
//      BP
                Ls = BPT;
                i = 1;
                TK[i] = Ls;
                CX[i] = XBP;
                CY[i] = YBP;
                SA[i] = AL1;
                GA[i] = 0;
                GL[i] = 0;
//
//      BP<BC
                Ls = Math.floor(Ls/DL)*DL + DL;
//
                while (Ls<BCT) {
                   i++;
                   TK[i] = Ls;
                   CX[i] = XBP + (Ls - BPT)*Math.cos(AL1);
                   CY[i] = YBP + (Ls - BPT)*Math.sin(AL1);
                   SA[i] = AL1;
                   GA[i] = AL1;
                   GL[i] = TK[i]-TK[i-1];
                   Ls = Ls + DL;
                }
//
//      BC
                if (Ls != BCT) {
                   i++;
                   TK[i] = BCT;
                   CX[i] = XBC;
                   CY[i] = YBC;
                   SA[i] = AL1;
                   GA[i] = AL1;
                   GL[i] = TK[i]-TK[i-1];
                }
//
//      BC<EC (円区間)
                while (Ls<ECT) {
                   i++;
                   TK[i] = Ls;
                   if (RR>0) {
                      CX[i] = XM + RR*Math.cos(AL1 - Math.PI/2 + (Ls - BCT)/RR);
                      CY[i] = YM + RR*Math.sin(AL1 - Math.PI/2 + (Ls - BCT)/RR);
                   }
                   else {
                      CX[i] = XM + Math.abs(RR)*Math.cos(AL1 + Math.PI/2 + (Ls - BCT)/RR);
                      CY[i] = YM + Math.abs(RR)*Math.sin(AL1 + Math.PI/2 + (Ls - BCT)/RR);
                   }
                   SA[i] = AL1 + (Ls - BCT)/RR;
                   x1 = CX[i-1];
                   y1 = CY[i-1];
                   x2 = CX[i];
                   y2 = CY[i];
                   GA[i] = Alph(x1,y1,x2,y2);
                   GL[i] = Dist(x1,y1,x2,y2);
                   Ls = Ls + DL;
                }
//
//      EC
                if (Ls != ECT) {
                   i++;
                   TK[i] = ECT;
                   CX[i] = XEC;
                   CY[i] = YEC;
                   SA[i] = AL2;
                   x1 = CX[i-1];
                   y1 = CY[i-1]
                   x2 = CX[i];
                   y2 = CY[i];
                   GA[i] = Alph(x1,y1,x2,y2);
                   GL[i] = Dist(x1,y1,x2,y2);
                }
//
//      EC<EP
                while (Ls<EPT) {
                   i++;
                   TK[i] = Ls;
                   CX[i] = XEC + (Ls - ECT)*Math.cos(AL2);
                   CY[i] = YEC + (Ls - ECT)*Math.sin(AL2);
                   SA[i] = AL2;
                   GA[i] = AL2;
                   GL[i] = TK[i]-TK[i-1];
                   Ls = Ls + DL;
                }
//
//      EP
                if (Ls != EPT) {
                   Ls = EPT;
                   n = i + 1;
                   TK[n] = Ls;
                   CX[n] = XEP;
                   CY[n] = YEP;
                   SA[n] = AL2;
                   GA[n] = AL2;
                   GL[n] = TK[i]-TK[i-1];
                }
//
//
//
//
//
//========================= 巾杭点計算 =====================================
//
//       XL[]          左巾杭点のX座標
//       YL[]          左巾杭点のY座標
//       LA[]          左巾杭点の方向角
//       XR[]          右巾杭点のX座標
//       YR[]          右巾杭点のY座標
//       RA[]          右巾杭点の方向角
//
                for (i=1;i<=n;i++) {
                   XL[i] = CX[i] + WL*Math.cos(SA[i]-Math.PI/2);
                   YL[i] = CY[i] + WL*Math.sin(SA[i]-Math.PI/2);
                   XR[i] = CX[i] + WR*Math.cos(SA[i]+Math.PI/2);
                   YR[i] = CY[i] + WR*Math.sin(SA[i]+Math.PI/2);
                }
//
                En();
//
        }
//
//
//
function En() {
      var i, r;
//
//
//=================== 円曲線設置計算結果出力 ================================
//
      document.write ("<CENTER>","*** 円曲線設置計算 ***","</CENTER><BR>");
//
      document.write ("<CENTER><TABLE BORDER='0'>");
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='right'>","   IA","</TD>");
      r = Byodfb(IA*648000/Math.PI);
      byo = Rund(byo,2);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD>");
      document.write ("<TD ALIGN='right'>","    R","</TD>");
      document.write ("<TD ALIGN='right'>",RR,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='left'>","曲線の要素","</TD></TR>");
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   TL","</TD>");
      TL = Rund(TL,4);
      document.write ("<TD ALIGN='right'>",TL,"</TD>");
      document.write ("<TD ALIGN='right'>","  (M) X","</TD>");
      XM = Rund(XM,4);
      document.write ("<TD ALIGN='right'>",XM,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   CL","</TD>");
      CL = Rund(CL,4);
      document.write ("<TD ALIGN='right'>",CL,"</TD>");
      document.write ("<TD ALIGN='right'>","    Y","</TD>");
      YM = Rund(YM,4);
      document.write ("<TD ALIGN='right'>",YM,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","  CL/2","</TD>");
      r = Rund(CL/2,4);
      document.write ("<TD ALIGN='right'>",r,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   SL","</TD>");
      SL = Rund(SL,4);
      document.write ("<TD ALIGN='right'>",SL,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='left'>","曲線の主要点座標","</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","  NAME","</TD>");
      document.write ("<TD ALIGN='right'>","    X    ","</TD>");
      document.write ("<TD ALIGN='right'>","    Y    ","</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   BC","</TD>");
      XBC = Rund(XBC,4);
      document.write ("<TD ALIGN='right'>",XBC,"</TD>");
      YBC = Rund(YBC,4);
      document.write ("<TD ALIGN='right'>",YBC,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   SP","</TD>");
      XSP = Rund(XSP,4);
      document.write ("<TD ALIGN='right'>",XSP,"</TD>");
      YSP = Rund(YSP,4);
      document.write ("<TD ALIGN='right'>",YSP,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   EC","</TD>");
      XEC = Rund(XEC,4);
      document.write ("<TD ALIGN='right'>",XEC,"</TD>");
      YEC = Rund(YEC,4);
      document.write ("<TD ALIGN='right'>",YEC,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   IP","</TD>");
      XIP = Rund(XIP,4);
      document.write ("<TD ALIGN='right'>",XIP,"</TD>");
      YIP = Rund(YIP,4);
      document.write ("<TD ALIGN='right'>",YIP,"</TD></TR>");
//
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   α1","</TD>");
      r = Byodfb(AL1*648000/Math.PI);
      byo = Rund(byo,2);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD></TR>");
      document.write ("<TR ALIGN='CENTER'><TD ALIGN='right'>","   α2","</TD>");
      r = Byodfb(AL2*648000/Math.PI);
      byo = Rund(byo,2);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD></TR>");
      document.write ("</TABLE>");
      document.write ("<BR>");
      document.write ("<BR>");
//
//
//========================= 中間点計算出力 ==================================
//
      document.write ("<CENTER>","*** 中間点計算 ***","</CENTER><BR>");
//
      document.write ("<CENTER><TABLE BORDER='0'>");
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='left'>","STA.No.","</TD>");
      document.write ("<TD ALIGN='center'>","X","</TD>");
      document.write ("<TD ALIGN='center'>","Y","</TD>");
      document.write ("<TD ALIGN='right'>","S","</TD>");
      document.write ("<TD ALIGN='right'>","弦方向角","</TD>");
      document.write ("<TD ALIGN='right'>","接線方向角","</TD>");
      document.write ("</TR>");
//
      for (i=1;i<=n;i++) {
      document.write ("<TR ALIGN='CENTER'>");
      r = Sta(TK[i]);
      document.write ("<TD ALIGN='left'>",sta1 + "+" + sta2,"</TD>");
      CX[i] = Rund(CX[i],4);
      CY[i] = Rund(CY[i],4);
      document.write ("<TD ALIGN='right'>",CX[i],"</TD>");
      document.write ("<TD ALIGN='right'>",CY[i],"</TD>");
      GL[i] = Rund(GL[i],4);
      document.write ("<TD ALIGN='right'>",GL[i],"</TD>");
      r = Byodfb(GA[i]*648000/Math.PI,doo,fun,byo);
      byo = Rund(byo,1);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD>");
      r = Byodfb(SA[i]*648000/Math.PI,doo,fun,byo);
      byo = Rund(byo,1);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD></TR>");
      }
      document.write ("</TABLE>");
      document.write ("<BR>");
      document.write ("<BR>");
//
//
//========================= 巾杭点計算出力 ==================================
//
      document.write ("<CENTER>","*** 巾杭点計算 ***","</CENTER><BR>");
//
      document.write ("<CENTER><TABLE BORDER='0'>");
      document.write ("<TR ALIGN='CENTER'>");
      document.write ("<TD ALIGN='left'>","STA.No.","</TD>");
      document.write ("<TD ALIGN='right'>","弦方向角","</TD>");
      document.write ("<TD ALIGN='right'>","巾杭方向角","</TD>");
      document.write ("<TD ALIGN='right'>","左右巾","</TD>");
      document.write ("<TD ALIGN='center'>","X","</TD>");
      document.write ("<TD ALIGN='center'>","Y","</TD>");
      document.write ("</TR>");
//
      for (i=1;i<=n;i++) {
      document.write ("<TR ALIGN='CENTER'>");
      r = Sta(TK[i]);
      document.write ("<TD ALIGN='left'>",sta1 + "+" + sta2,"</TD>");
      r = Byodfb(GA[i]*648000/Math.PI,doo,fun,byo);
      byo = Rund(byo,1);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo,"</TD>");
      r = Byodfb((SA[i]-Math.PI/2)*648000/Math.PI,doo,fun,byo);
      byo = Rund(byo,1);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo + "L","</TD>");
      WL = Rund(WL,4);
      document.write ("<TD ALIGN='right'>",WL,"</TD>");
      XL[i] = Rund(XL[i],4);
      YL[i] = Rund(YL[i],4);
      document.write ("<TD ALIGN='right'>",XL[i],"</TD>");
      document.write ("<TD ALIGN='right'>",YL[i],"</TD></TR>");
//
      document.write ("<TD ALIGN='right'>"," ","</TD>");
      document.write ("<TD ALIGN='right'>"," ","</TD>");
      r = Byodfb((SA[i]+Math.PI/2)*648000/Math.PI,doo,fun,byo);
      byo = Rund(byo,1);
      document.write ("<TD ALIGN='right'>",doo + "-" + fun + "-" + byo + "R","</TD>");
      WR = Rund(WR,4);
      document.write ("<TD ALIGN='right'>",WR,"</TD>");
      XR[i] = Rund(XR[i],4);
      YR[i] = Rund(YR[i],4);
      document.write ("<TD ALIGN='right'>",XR[i],"</TD>");
      document.write ("<TD ALIGN='right'>",YR[i],"</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>


入力データと実行結果

     入力データ

      BPの座標
            XBP = -51274.2779
            YBP = -31305.5806
      IPの座標
            XIP = -51813.3467
            YIP = -31423.3201
      EPの座標
            XEP = -52144.8230
            YEP = -31551.5362
      半径
            RR = 2000.0000
          ステーションピッチ
        SP = 100
      等間隔長
            DL = 20
      計算開始点の追加距離
            No. 0 + 0
      左巾
            WL = 10
      右巾
            WL = 10

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

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

 

     計算結果の一部

  

 


プログラムの説明

前にも述べたように、JavaScript では、データファイルが作れないので、中間

点計算のプログラムに追加する形で作成してあります。

もし、データファイルに中間点計算のデータを記憶することが可能になれば、

プログラムも短く、計算時間もかなり短縮されるでしょう。

巾杭計算そのもののプログラムはそれほど難しいものではありません。

 

var WL;              // 左巾
var WR;              // 右巾
    ・
    ・
    ・
XL = new Array(500);   // 左巾杭点のX座標
YL = new Array(500);   // 左巾杭点のY座標
XR = new Array(500);   // 右巾杭点のX座標
YR = new Array(500);   // 右巾杭点のY座標

巾杭計算で追加した、グローバル変数です。

左右の巾は配列変数にして、各中間点ごとに異なる値も入力できるようにす

ると、より汎用性が増します。

//========================= 巾杭点計算 =====================================
//
//       XL[]          左巾杭点のX座標
//       YL[]          左巾杭点のY座標
//       LA[]          左巾杭点の方向角
//       XR[]          右巾杭点のX座標
//       YR[]          右巾杭点のY座標
//       RA[]          右巾杭点の方向角
//
for (i=1;i<=n;i++) {
   
XL[i] = CX[i] + WL*Math.cos(SA[i]-Math.PI/2);
   
YL[i] = CY[i] + WL*Math.sin(SA[i]-Math.PI/2);
   
XR[i] = CX[i] + WR*Math.cos(SA[i]+Math.PI/2);
   
YR[i] = CY[i] + WR*Math.sin(SA[i]+Math.PI/2);
}

巾杭点の座標計算です。中間点の座標も接線方向角も求められているので、

座標計算をするだけです。

計算結果の出力は、中間点計算の後に追加しました。そのため、さらに計算

時間が長くなりました。


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

 りょうかんのアドバイス

中間点計算で、必要なデータが求められているので、座標計算を行うだけでし

たね。プログラムは、ほとんど中間点計算で出来上がっていたようなものです。

実用的には、設置計算、中間点計算、巾杭計算を3つのモジュールに分けて、

データファイルにデータを書き込んでモジュール間でデータのやり取りをすれ

ば、もっとスマートになります。

実は、前にも述べたようにJavaScriptでは、クッキーというインターネット用の

ファイルを扱うことができます。これを計算のデータの書き込み用に利用すれ

ばなんとかなるかもしれません。りょうかんは、まだ勉強が足りなくてそこまで

ためしていませんが、この講座の最終回あたりに取り上げてみたいと思いま

す。

 

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

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

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

                                講師 りょうかん


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