jw_cad 外部変形 - (1342) mshtaで楕円弧の長さ(表示画面のスケール)を計測表示する -

外部変形は データのやり取りをテキストファイルで行うので プログラム言語は 自由に選ぶことができます。図形は機能的かつシンプルなため、数多くのユーザーに受け入れられています。

 

mshtaで楕円弧の長さ(表示画面のスケール)を計測表示する

:mshtaで楕円弧の長さ(表示画面のスケール)を計測表示する
@echo off
if exist jwc_temp.txt (
  copy jwc_temp.txt myfiles > nul
  mshta %~f0 < myfiles > jwc_temp.txt
)
goto:eof

REM #jww
REM #1ci 長さを計測する円・円弧を指示してください
REM #bz
REM #e

<script>
/*
    JScript による JW_CAD 外部変形
*/

//ユーザー定義関数
function int(a) { return a < 0 ? Math.ceil(a) : Math.floor(a) }

function sgn(x) { return x == 0 ? x : ( x > 0 ? 1 : -1 ) }

function fx(x, k) {
  return Math.sqrt(1.0 - Math.pow(k * Math.sin(x), 2))
}

function apa(o, p) {
  return (90.0 * (2 * int( (o + 1) / 2) - 1) - p) * Math.pow(-1, o - 1)
}

function eh(n, m, ee, hh) {
  var pi = Math.PI
  var i, j, e1, t, x0, pkm1, pk, t1, pkp1, pkm1
  var den, d1, dpn, d2pn, d3pn, d4pn
  var u, v, h, pp, dp, xi, fx, wi

  e1 = n * (n + 1.0)
  for (var i = 1; i <= m; i++) {
    t   = (4.0 * i - 1.0) * pi / (4.0 * n + 2.0)
    x0  = (1.0 - (1.0 - 1.0 / n) / (8.0 * n * n)) * Math.cos(t)
    pkm1= 1.0
    pk  = x0
    for (var j = 2; j <= n; j++) {
      t1   = x0 * pk
      pkp1 = t1 - pkm1 - (t1 - pkm1) / j + t1
      pkm1 = pk
      pk   = pkp1
    }
    den  = 1.0 - x0 * x0
    d1   = n * (pkm1 - x0 * pk)
    dpn  = d1 / den
    d2pn = (2.0 * x0 * dpn - e1 * pk) / den
    d3pn = (4.0 * x0 * d2pn + (2.0 - e1) * dpn) / den
    d4pn = (6.0 * x0 * d3pn + (6.0 - e1) * d2pn) / den
    u  = pk / dpn
    v  = d2pn / dpn
    h  = -1.0 * u * (1.0 + 0.5 * u * (v + u * (v * v - d3pn / (3.0 * dpn))))
    pp = pk + h * (dpn + 0.5 * h * (d2pn + h / 3.0 * (d3pn + 0.25 * h * d4pn)))
    dp = dpn + h * (d2pn + 0.5 * h * (d3pn + h * d4pn / 3.0))
    h -= pp / dp
    xi = x0 + h
    fx = d1 - h * e1 * (pk + 0.5 * h * (dpn + h / 3.0 * (d2pn + 0.25 * h * (d3pn + 0.2 * h * d4pn))))
    wi = 2.0 * (1.0 - xi * xi) / (fx * fx)
    ee[i] = xi
    hh[i] = wi
  }
}

function E2(p, k, n, m, ee, hh) {
  if (k == 0 || n < 1) {
    return p
  }
  var l = 0.0
  for (var i = 1; i <= int(n / 2.0); i++) {
    l += hh[i] * fx(ee[i] * p, k)
  }
  if( m == int(n / 2.0) + 1 ){ //奇数個の場合
    l += hh[m] * fx(ee[m] * p, k) / 2.0
  }
  return l * p
}

function arc_l(rc, p1, p2, w) {
  var pi = Math.PI
  var p, lp, lr, lrp
  p = p2 - p1
  while (p <= 0 ) { p += 360 }
  while (p > 360) { p -= 360 }

  if (w == 1) {
    lr = p * pi / 180.0 * rc
  } else{
    lrp = p * pi / 180.0 * rc

    if (w > 1) {
      w = 1.0 / w
      rc = rc / w
      p1 = p1 - 90.0
      p2 = p2 - 90.0
    }
    var n = 150 //ガウス積分点の数 60~150 程度
    var m = (n + n % 2) / 2
    var k = Math.sqrt(1.0 - w * w)

    var ee = new Array(1)
    var hh = new Array(1)
    eh(n, m, ee, hh)

    var ek = E2(pi / 2.0, k, n, m, ee, hh)
    // 弧長をガウス積分(第2種楕円積分)を利用して計算する
    while (p1 <  0  ) { p1 += 360 }
    while (p1 >= 360) { p1 -= 360 }
    while (p2 <  0  ) { p2 += 360 }
    while (p2 >= 360) { p2 -= 360 }

    if (p1 == p2) {
      lp = 4.0 * ek
    } else {
      n1 = 1 + int(p1 / 90.0)
      if (n1 > 4) n1 = 4;
      lp = ek * ( (n1 + 1.0) % 2) + E2(apa(n1, p1) * pi / 180, k, n, m, ee, hh) * Math.pow(-1.0, n1 - 1)
      n2 = 1 + int(p2 / 90.0)
      if (n2 > 4) n2 = 4;
      if (n1 == n2) n1 += 4;
      n3 = 5 + 2 * int( (n2 - 1.0) / 2.0)
      lp += ek * ( (n3 - n1) % 4) + E2(apa(n2, p2) * pi / 180, k, n, m, ee, hh) * Math.pow(-1.0, n2)
      if (lp < 0.0) lp += 4.0 * ek;
    }
    lr = lp * rc
  }
  return lr
}

function hex(x) { return x < 10 ? x : x.toString(16) }

hs =
hp =

ci = []
cin = 0
lg = ""
with (new ActiveXObject("Scripting.FileSystemObject")) {
  f = GetStandardStream(0) //stdin
  g = GetStandardStream(1) //stdout
  while (! f.AtEndOfStream) {
    F = ($_ = f.ReadLine()).split(/\s+/)
    if (/^hk/i.test($_)) { //hk 軸角
      hk = F[1]*1.0; continue
    }
    if (/^hs/i .test($_)) { //hs スケール
      for (i = 0; i <= 15; i++) hs[hex(i)] = F[i + 1] * 1.0;
      continue
    }
    if (/^hp[1-9][0-9]?/i .test($_)) { //hp 指示点
      hp[ F[0].match(/[0-9]+/) ] = [ F[1] * 1.0, F[2] * 1.0 ]
      continue
    }
    if (/^lg[A-F0-9]/i .test($_)) { //lg レイヤグループ
      plg = $_.substr(2, 1).toLowerCase(); if (lg == "") lg = plg;
      continue
    }
    if (/^hhp([1-9][0-9]?)ci/i .test($_)) { cin = RegExp.$1; continue }
    if (/^ci/i .test($_)) { //ci 指示円
      p = hs[lg]
//      p = hs[lg] / hs[plg]
      for (i = 1; i <= 3; i++) F[i] *= p;
      ci[cin] = F.slice(1, F.length)
      if (F.length == 4) {
        ci[cin] = ci[cin].concat([0, 360, 1, hk])
      }
    }
  }
  f.close()
  r  = ci[1][2]
  p1 = ci[1][3]
  p2 = ci[1][4]
  w  = ci[1][5]
  lr = arc_l(r, p1, p2, w)
  g.WriteLine("h#円弧長 L = " + lr.toFixed(3))
}
close()
</script>

 


スクリプト言語は jscript を使用しています。楕円積分はガウス-ルジャンドルの方法によっています。積分点の係数は対称性を利用しています。