jw_cad 外部変形 - (1286) 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 #1ln 線を指示してください
REM #bz
REM #e

#!この次の行からプログラムを書いてください
--ユーザー定義関数
function concat(a, ...) --配列を連結する
-- 例
-- concat({1,2},{3,4}) => {1,2,3,4}
  if #{...} == 0 then return a end
  if #flatten(a) > #a then
    local i
    local n = #a
    local y = ...
    for i = 1, #y do
      a[n + i] = y[i]
    end
    return a
  else
    return flatten({a, ...})
  end
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) --2点間の距離を返す
  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 lnlength(s) --線長を返す
  local x1, y1, x2, y2 = s[1], s[2], s[3], s[4]
  return math.sqrt( (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
end

function lnslope(s) --線の角度を返す
  local x1, y1, x2, y2 = s[1], s[2], s[3], s[4]
  return math.atan2(y2 - y1, x2 - x1)
end

function lnpoint(s, pm) --始点 pm=-1,  終点 pm=1 の座標を返す
  local x1, y1, x2, y2 = s[1], s[2], s[3], s[4]
  if pm == nil then pm = 0 end
  return pm == 0 and {(x1 + x2) / 2, (y1 + y2) / 2} or (pm < 0 and {x1, y1} or {x2, y2})
end

function ln_hpnear(s, p) --指示点の近傍端点を返す
  return lnpoint(s, ln_hpends(s, p))
end

function ln_hpends(s, p) --指示点の近傍端点の指標を返す(始点 pm=-1,  終点 pm=1)
  local l1, l2
  l1 = ptdist(p, lnpoint(s,-1))
  l2 = ptdist(p, lnpoint(s, 1))
  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("^hq") then print("bz") end
  if line:match("^hp1ln") then p1 = {F[2], F[3]} end
  if line:match("^ ") and #F == 4 then
    ptc = lnpoint(F)
    --直交線の位置を始点、中心点、終点で決めるときの補正
    ptc = ln_hpnear(concat(ln_hpnear(F, p1), ptc), p1)
    l = lnlength(F) / 2
    d = lnslope(F) + math.rad(90)
    echo(polarto(ptc, -l, d), polarto(ptc, l, d))
  end
end

 

 

作図用ライブラリ jw.lua を用意しておけば下記のようになります。

:luaで線に直交線を引く(jw.lua)
@echo off
set LUA_PATH=%~dp0jw.lua
for /f "delims=:" %%n in ('findstr /n "^#!" %0') do (
  copy jwc_temp.txt myfiles > nul
  more +%%n %0 | lua -ljw - myfiles > jwc_temp.txt
)
goto:eof

REM #jww
REM #1ln 線を指示してください
REM #bz
REM #e

#!この次の行からプログラムを書いてください
jw() --jwc_temp.txt の書き出しデータを取得する
bz()
l1 = ln(1) --指示線(1)
p1 = hp(1) --指示点(1)
ptc = lnpoint(l1, 0) --指示線(1)の中心点
--直交線の位置を始点、中心点、終点で決めるときの補正
ptc = ln_hpnear(concat(ln_hpnear(l1, p1), ptc), p1)
l = lnlength(l1) / 2
d = lnslope(l1) + rad(90)
echo(polarto(ptc, -l, d), polarto(ptc, l, d))