jw_cad 外部変形 - (1285) 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 slice(a, st, ed)
  if type(a) ~= "table" then return x end
  if st == nil then st = 1 end
  if ed == nil then ed = #a end
  if ed < 0 then ed = #a + ed + 1 end
  local i
  local s = {}
  for i = st, ed do
    table.insert(s, a[i])
  end
  return s
end

function join(a, FS)
  if type(a) ~= "table" then return a end
  if FS == nil then FS = " " end
  return table.concat(flatten(a), FS)
end

function flatten(a)
  local i, j, k
  local c = {}
  for i in pairs(a) do
    if type(a[i]) == "table" then
      --while #a[i] == 1 do a[i] = a[i][1] end
      for j in pairs(a[i]) do
        if type(a[i][j]) == "table" then
          --while #a[i][j] == 1 do a[i][j] = a[i][j][1] end
          for k in pairs(a[i][j]) do
            table.insert(c, a[i][j][k])
          end
        else
          table.insert(c, a[i][j])
        end
      end
    else
      table.insert(c, a[i])
    end
  end
  return c
end

function echo(...)
  if #{...} == 0 then return end
  return print(join({select(1, ...)}))
end

function polar(r, d, w) --方向余弦のセット
  if r == "" or r == nil then r = 1 end
  if d == "" or d == nil then d = 0 end
  if w == "" or w == nil then w = 1 end
  return {r * math.cos(d), r * math.sin(d) * w}
end

function moveto(x, y) --点x を 相対距離 y [ a, b ] へ移動
  return y and ptcalc("+", x, y) or x
end

function polarto(x, r, d, w) --点x を 極座標 [ r, d ] で相対的に移動する
  return moveto(x, polar(r, d, w))
end

function ptcalc(p, x, y) --点データの数値演算(加減乗除)
  local zz
  zz = {x[1], x[2], y[1], y[2]}
  if p == "+" then
    return zz and {zz[1] + zz[3], zz[2] + zz[4]} or {0, 0}
  elseif p == "-" then
    return zz and {zz[1] - zz[3], zz[2] - zz[4]} or {0, 0}
  elseif p == "*" then
    return zz and {zz[1] * zz[3], zz[2] * zz[4]} or {0, 0}
  elseif p == "/" then
    return zz and {zz[1] / zz[3], zz[2] / zz[4]} or {0, 0}
  elseif p == "ave" then
    return zz and {(zz[1] + zz[3]) / 2, (zz[2] + zz[4]) / 2} or {0, 0}
  else
    return {0, 0}
  end
end

function ptdist(x, y)
  local x1, y1 = x[1], x[2]
  local x2, y2 = y[1], y[2]
  return math.sqrt( (x2 - x1) ^ 2 + (y2 - y1) ^ 2)
end

function rot(x, d)
  if d == nil then return x end
  local x1, y1 = x[1], x[2]
  local co = math.cos(d)
  local si = math.sin(d)
  if type(x) == "table" then
    if type(x[1]) == "table" then
      local i
      for i = 1, #x do x[i] = rot(x[i], d) end
      return x
    end
  end
  return {x1 * co - y1 * si, x1 * si + y1 * co}
end

function cipoint(c, pm)
  local x, y, r, p1, p2, w, d
  local q
  x = c[1]
  y = c[2]
  if pm == 0 or pm == nil then return {x, y} end
  r = c[3]
  p1 = c[4] or 0
  p2 = c[5] or 360
  w = c[6] or 1
  d = c[7] or 0
  q = pm == -1 and p1 or p2
  return moveto({x, y}, rot(polar(r, math.rad(q), w), math.rad(d))), q
end

function arrow(pt1, d, size, xang, xan2)
  if d == nil then d = 0 end
  if size == nil then size = 3 end
  if xang == nil then xang = 45 end
  if xan2 == nil then xan2 = 120 end
  local l, a, pt2, pt3, pt4, c
  l = size
  a = math.rad(xang) / 2
  pt2 = polarto(pt1, l, d - a)
  pt4 = polarto(pt1, l, d + a)
  if xan2 == 180 then
    echo("sl", pt1, pt2, pt4)
  else
    c = math.cos(a) - math.sin(a) * math.tan(math.rad(90 - xan2 / 2))
    pt3 = polarto(pt1, l * c, d)
    echo("sl", pt1, pt2, pt3, pt4)
  end
end

function ci_hpends(c, p) --指示点近傍の円弧の端点の判別値を返す
  local pt1, pt2, l1, l2
  pt1 = cipoint(c,-1)
  pt2 = cipoint(c, 1)
  l1 = ptdist(p, pt1)
  l2 = ptdist(p, pt2)
  return l1 < l2 and -1 or 1
end

for line in io.lines("myfiles") do
  F = {}
  string.gsub(line, "%S+", function (x) table.insert(F, x) end)
  if line:match("^hp1ci") then
    p1 = {F[2], F[3]}
  end
  if line:match("^ci") then
    ci = slice(F, 2)
    size = 5 --矢印の長さ( 図寸 )
    xang = 45 --矢印の交角( ゚ )
    xan2 = 120 --矢尻の交角( ゚ )
    pm = ci_hpends(ci, p1) --始点(pm = -1)、終点(pm = 1)
    pt, q = cipoint(ci, pm) --端点(pm)の座標と離心角(゚)
    r = ci[3]
    w = ci[6] or 1
    d = ci[7] or 0
    x = math.cos(math.rad(q)) * r
    y = math.sin(math.rad(q)) * r * w
    a = math.atan2(y / w, x * w) + math.rad(d) + math.pi / 2 --接線角(rad)
    print("bz")
    arrow(pt, a, -pm*size, xang, xan2)
  end
end