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

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

 

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

:luaで楕円弧の長さ(表示画面のスケール)を計測表示する
@echo off
for /f "delims=:" %%n in ('findstr /n "^#!" %0') do (
  copy jwc_temp.txt myfiles > nul
  more +%%n %0 | lua > jwc_temp.txt
)
goto:eof

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

#!この次の行からプログラムを書いてください
function sprintf(...)
  if #{...} == 0 then return end
  if #{...} == 1 then return ... end
  return string.format(...)
end

function printf(...)
  return print(sprintf(...))
end

function int(a) return a < 0 and math.ceil(a) or math.floor(a) end

function apa(o, p)
  return (90 * (int( (o + 1) / 2) * 2 - 1) - p) * (-1) ^ (o - 1)
end

function fx(x, k)
  return math.sqrt(1 - (k * math.sin(x)) ^ 2)
end

function arc_l(r, p1, p2, w)
  local k, Ek, lp, n1, n2, n3
  --r  半径
  --p1 始角 ゚
  --p2 終角 ゚
  --w  扁平率
  --k  離心率
  --Ek 第二種完全楕円積分の値
  if w > 1 then
    w = 1 / w
    r = r / w
    p1 = p1 - 90
    p2 = p2 - 90
  end
  k = math.sqrt(1 - w * w)
  Ek = E(math.rad(90), k)
  lp = int(math.abs(p2 - p1) / 360) * 4 * Ek
  if angle_eql(p1, p2) then lp = 4 * Ek end
  while p1 <  0   do p1 = p1 + 360 end
  while p1 >= 360 do p1 = p1 - 360 end
  while p2 <  0   do p2 = p2 + 360 end
  while p2 >= 360 do p2 = p2 - 360 end
    if angle_eql(p1, p2) then return r * lp end
    --if angle_eql(math.rad(360 - (p1 - p2) % 360), 0) then return r * lp end
  n1 = int(p1 / 90) + 1
  if n1 > 4 then n1 = 4 end
  lp = lp + Ek * ( (n1 + 1) % 2) + E(math.rad(apa(n1, p1)), k) * (-1) ^ (n1 - 1)
  n2 = int(p2 / 90) + 1
  if n2 > 4 then n2 = 4 end
  if n1 == n2 then n1 = n1 + 4 end
  n3 = 2 * int( (n2 - 1) / 2) + 5
  lp = lp + Ek * ( (n3 - n1) % 4) + E(math.rad(apa(n2, p2)), k) * (-1) ^ n2
  if lp < 0 then lp = lp + 4 * Ek end
    if lp > 4 * Ek then lp = lp - 4 * Ek end
  return r * lp
end

function E(p, k)
  local i, l, M
  if k == 0 then
    return p
  end
  if k == "" or k == nil then k = p; p = math.pi / 2 end
  l = 0
  if N > 1 then
    for i = 1, int(N / 2) do l = l + __h__[i] * fx(__e__[i] * p, k) end
  end
  if N % 2 == 1 then
    M = int(N / 2) + N % 2
    l = l + __h__[M] * fx(__e__[M] * p, k) / 2
  end -- 奇数個の場合
  return l * p
end

function gear(bpa)
  local ww
  ww = bpa; if bpa > 1 then ww = 1 / bpa end
  if bpa < 0 then
    N = int(math.abs(bpa))
  else
    if ww == 0 or ww == "" then ww = 1 end
    N = int(12 * (1.5 / ww))
    if N > 300 then N = 300 end
  end
  eh(N)
  return bpa
end

function eh(N) -- 積分点デ-タ
  local I, J, E1, T, X0, PKM1, PK, T1, PKP1, PKM1
  local DEN, D1, DPN, D2PN, D3PN, D4PN
  local U, V, H, PP, DP, XI, FX, WI
  local M = int(N / 2) + N % 2
  __e__ = {}
  __h__ = {}
  E1 = N * (N + 1)
  for I = 1, M do --DO 1
    T   = (4 * I - 1) * math.pi / (4 * N + 2)
    X0  = (1. - (1. - 1. / N) / (8. * N * N)) * math.cos(T)
    PKM1= 1.
    PK  = X0
    for K = 2, N do --DO 3
      T1  = X0 * PK
      PKP1= T1 - PKM1 - (T1 - PKM1) / K + T1
      PKM1= PK
      PK  = PKP1
    end -- 3
    DEN = 1. - X0 * X0
    D1  = N * (PKM1 - X0 * PK)
    DPN = D1 / DEN
    D2PN= (2. * X0 * DPN - E1 * PK) / DEN
    D3PN= (4. * X0 * D2PN + (2. - E1) * DPN) / DEN
    D4PN= (6. * X0 * D3PN + (6. - E1) * D2PN) / DEN
    U   = PK / DPN
    V   = D2PN / DPN
    H   = -U * (1. + .5 * U * (V + U * (V * V - D3PN / (3. * DPN))))
    P   = PK + H * (DPN + .5 * H * (D2PN + H / 3. * (D3PN + .25 * H * D4PN)))
    DP  = DPN + H * (D2PN + .5 * H * (D3PN + H * D4PN / 3.))
    H   = H - P / DP
    XI  = -(X0 + H)
    FX  = D1 - H * E1 * (PK + .5 * H * (DPN + H / 3. * (D2PN + .25 * H * (D3PN + .2 * H * D4PN))))
    WI  = 2. * (1. - XI * XI) / (FX * FX)
    __e__[I] = XI
    __h__[I] = WI
  end -- 1
end

function angle_eql(d1, d2, eps) --JW_CAD 線角コマンドに準ずる
  local dd
  if eps == "" or eps == nil then eps = 1e-15 end
  dd = math.abs(d1 - d2)
  while dd > math.pi - eps do dd = dd - math.pi end
  return math.abs(dd) < eps and true or false
end

hs = {}; lg = ""
for line in io.lines("myfiles") do
  F = {}
  string.gsub(line, "%S+", function (x) table.insert(F, x) end)
  if line:match("^hs") then
    for i = 0, 15 do
      hs[sprintf("%x", i)] = F[i+2]
    end
  end
  if line:match("^lg[0-9a-f]") then
    plg = line:sub(3); if lg == "" then lg = plg end
  end
  if line:match("^ci") then -- 指示円
    r = F[4] * hs[lg]
    p1 = F[5] and F[5] * 1 or 0
    p2 = F[6] and F[6] * 1 or 360
    w = F[7] and F[7] * 1 or 1
    printf("h#円弧長 L = %.03f", arc_l(r, p1, p2, gear(w)))
  end
end