AutoLISP入門講座

AutoLISP入門講座-1 準備編

この記事は2014年頃に作成されたものの転載です。AutoLISPを初めて体験してみる方のための記事です。

AutoLISPの勧め

私はプログラマーではなく、建築関係の図面を書くという仕事をしています。
ちょうど3年前のこと、どうしてもAutoCADカスタマイズする必要に迫られ、アマゾンで書籍を2冊購入し、AutoLISPの勉強を開始しました。37歳のときです。
半年くらい、AutoLISPに没頭しました。毎日が、喜びの連続でした。
あれほど自分には手が出せないと思い込んでいたAutoLISPというものが、意外なことに、非常に簡単で、扱いやすいものだということが分かりました。
私はすべてのCADの仕事をされている人に、AutoLISPへの挑戦を勧めます。
AutoLISPというものは、AutoCADを使っている人なら、今この瞬間からでも、会得に向けて勉強を開始することができます。それにはなんの追加投資も必要としません。
たとえプログラムをやったことがない人でも、大丈夫です。
むしろ、「プログラムが専門だけれども、普段、図面を書かない人」に頼むよりも、普段図面を書いている人がプログラムを書いたほうが、はるかに使いやすいものができる可能性があります。
だからこそ、すべてのCADオペレータに、AutoLISPの習得をお勧めします。

AutoLISPを会得すると、どうなるか。

  1. ただのCADオペから一味違うCADオペになることができます。
  2. 社内で尊敬されます。宇宙人扱いされます。しょっちゅう呼ばれます。
  3. あなたがもし派遣社員ならば、派遣切りにあわなくなります。「頼むから正社員になってくれ」といわれます。
  4. あなたと、その廻りの人の業務効率が飛躍的に向上し、残業時間が減ります。
  5. AutoLISPを使っていない人を見ると、「え、そんなこといちいち手で書いているの?」と思うようになります。
  6. AutoCADに対する深い知識が身につきます。
  7. テレビや北斗の拳に興味がなくなります。
  8. 奥さんや彼女の話を聞いているフリをして、頭の中ではプログラミングを考えるようになります。
  9. ペンと紙切れが手放せなくなります。

日本では非常にマイナーなこのAutoLISPと呼ばれるプログラムですが、欧米ではかなりメジャーなのか、AutoDESKのディスカッショングループと呼ばれる掲示板では、かなり盛んにやり取りが行われています。
ところが日本では、現在入手できるAutoLISPに関する書籍はたったの2冊。他の言語はズラーーーっと書棚に並んでいるのに、さびしい限りです。アメリカなどに負けて入られません。

AutoLISPとは

AutoLISPとは、AutoCADにカスタマイズを加えるために用意された言語です。
AutoCADにカスタマイズを加えるには、

  • ObjectARXによる方法
  • AutoLISPによる方法
  • VBAによる方法
  • DIESELマクロによる方法

というように4通りの方法が用意されています。
この中でメリット・デメリットを大雑把に比較するとこんな感じです。

  メリット デメリット
ObjectARX(C++) 速い。神のレベル 難しい。エラーで突然CADが落ちる。CADのバージョンアップのたびに、書き換える必要がある。
AutoLISP 速い簡単。
落ちない。
バージョンアップしても、ほぼ関係なし。
ノートパッドで作れる。
他のソフトとの連携が苦手
VBA 簡単(?)他のソフトとの連携が得意(らしい) もっさい(動作があまり早くない)

DIESEL 普通に速い 難しい。完成したコードを見ただけでは内容が分かリづらい。
複雑なことができない。

普段はCADの仕事をしながら習得するには、AutoLISPはちょうど良い言語であるといえます。

AutoLISPをはじめるのに、用意したほうがいいもの

AutoLISPはタダのテキストファイルを、***.lspというファイル名で保存して、AutoCADに読ませるだけです。
なので、極端に言えば、ノートパッドでも、メモ帳でも作ることができますが、ぜひ、効率的にプログラムを作成するために、以下のものを揃えることを強く推奨します。

  • 秀丸エディタ
  • デュアル・モニター

秀丸エディタは、あまりにも有名なテキストエディタです。
これをAutoLISP用に、カスタマイズします。
デュアル・モニターは、パソコンにディスプレイを2つ接続し、右の画面でプログラムやAutoCADのコマンドラインを表示させ、左の画面でCADの画面を出して動きを確認する、という使い方をしよう、ということです。
AutoCADでは、AutoLISPをつくるための専用エディタとして、Visual LISP Editorというものが内蔵されています。お手持ちのAutoCADのコマンドラインに、”vlide”と打ち込むと立ち上がります。
本来、このVisual LISP EditorでAutoLISPを作成するのですが、このソフトウェアは使い方が難しいので、ここでは簡単なテキストエディタでのプログラミングを解説します。

秀丸エディタをAutoLISP仕様に改造

 

秀丸エディタをAutoLISP仕様にすることで、

  1. 見やすくなる
  2. コマンドを正しいスペルで入力すると太字になるため、スペルミスがなくなる
  3. ファンクションキーに、よく使うコマンドを記憶させておくことで、チェックが容易になる。

というようになります。
よく、「AutoLISPはカッコだらけで、カッコの数を合わせるのに一苦労、という話を耳にしますが、秀丸のようにいまどきのエディタは普通、カッコの対応強調表示をしてくれるので、カッコの数で苦労するということは、現実的にはほとんどありません。
すでに秀丸エディタをお使いの方は、設定を上書きしてしまう可能性があるので、注意してください。

  1. まず秀丸エディタをダウンロードしインストール。
  2. 秀丸はファイルの拡張子ごとに細かい設定をできますので、LSPという拡張子を登録して、そこに設定を行います。
  3. LSPの設定画面に入ります
  4. 強調表示などの設定を行います。
    AutoLISP.hilight を右クリックでダウンロード。Hidemaruフォルダに保存。
    下記のようにして、読み込み。

これで、AutoLISPのコマンド730個をエディタが認識します。正しいスペルで入力した時点で、太字強調されたり、””で囲まれた文字を赤く強調表示したり、defunを含む行をグレー背景にしたりといった設定が入っています。
コマンド数は本当はもっとあるのですが、秀丸の機能の限界なのか、730個までしかセットできませんでした。一度も使わないようなコマンドまで入っていますので、これで困ることは無いと思います。
色はユーザーがあとで自由に変更できます。
秀丸のカスタマイズはもう少し続きます。次はファンクションキーの設定です。

ファンクションキーにショートカットを登録します。

これにより、プログラムのチェックが早くなります。

  1. AutoLISP_Macro.lzh を右クリックでダウンロード、解凍し、Hidemaru フォルダに置く。
    下記のファイルが含まれています。
    AutoLISP.KEY がどのキーにどのマクロを割り当てるかを設定したファイル、
    ***.Mac が実際のマクロの内容です。
  2. 秀丸で、下記のようにして、AutoLISP.KEYを読み込みます。

これでカスタマイズは終わりです。実際に、秀丸を使って、ショートカットが動くか確かめます。

ショートカットの動作確認

  1. 秀丸で空のファイルを開く。
  2. 「名前を付けて保存」で aaa.lsp で保存する。
    これで、秀丸はこのファイルがLISPであると判断し、今までの設定が生きてきます。
  3. どこでもよいので aaa  と記入し、それをマウスでダブルクリックし反転表示させ、[Ctrl + C] でコピー。
  4. [F-2] ~[F-6]まで押してみて、文字が打ち込まれればOK
    aaa
    (princ “n “)
    (princ “n aaa : “)
    (princ aaa)
    (mapcar ‘print aaa)
    (checkcircle aaa 1.0 “0”)
    (mapcar ‘(lambda(x)(checkcircle x 1.0 “0”)) aaa)
  5. 以下が各ファンクションキーの内容です
  出力 使い道
F1 1行削除  
F2 (princ “n “) nのあとに行番号を記入することで、デバッグに使う。 
どの行までAutoLISPが動作したかを確認する原始的な方法
F3 (princ “n aaa : “)(princ aaa) LISPを実行したときに、気になる変数の値を表示させる。デバッグに使う。
F4 (mapcar ‘print aaa) 上と同じだが、改行しながら表示させる。
F5 (checkcircle aaa 1.0 “A21″) LISPを実行したときに、ある点が、実際に画面上でどこにあるのかを確認するための丸を打つ。(別途、ファイルが必要)
F6 (mapcar ‘(lambda(x)(checkcircle x 1.0 “a11″)) aaa) 上記と同じだが、変数が、(点 点 点・・・)というリストになっているときに使う。全ての点に丸を打つ。(別途、ファイルが必要)
F7 ; を行頭に挿入 秀丸ライブラリからいただきました
F8 ; を行頭から削除 秀丸ライブラリからいただきました

使い方については、プログラミングのところで詳しく書きます。
次は、何かを書いてロードさせる方法です。

書いたプログラムをロードする

AutoLISPをやるなら、デュアル・モニターをぜひお勧めします。

  • 左の画面にAutoCADを表示させる
  • 右の画面には、秀丸・AutoCADのテキストスクリーン・エクスプローラなどを表示させる
  • 複数のウインドウを表示させるときは、どのウインドウをアクティブにしても、全てのウインドウがちょろっとずつ見えるように、「ちょいずらし」で置くと、切り替えが便利です。

デュアル・モニターを使うには

モニターを接続するコネクタを2つ持つビデオカードが必要です。最近のパソコンでは、標準で2基接続できるようになっているようですが、もし1つしか接続できないパソコンであれば、2基接続できるビデオカードを買ってきて拡張スロットに挿すことでデュアル・モニターを使うことができます。
OSはWindows2000からデュアル・モニターに対応しているので、ソフトウェアは不要です。
また、デジタル(白いコネクタ)とアナログ(青いコネクタ)があります。デジタルのほうが鮮明ですので、デジタルをお勧めします。今ではHDMIが標準ですね。

秀丸アイコンをAutoCADにドラッグしてロード

秀丸エディタで何かプログラムを作成したら、左上のアイコンをAutoCADの画面上にサクっとドラッグさせる事で、プログラムを読ませることができます。この方法は意外に知られていませんが、大変便利です。

教科書的にはコマンドラインに (load “***.lsp”)などと打ち込むのですが、面倒くさくてやってられませんので、私は開発中はすべてこのドラッグでロード・実行させ、開発が終わった時点でツールバーに組み込むという方法をとりました。

AutoLISPのルール

プログラム上のルールをいくつか書きます。

AutoLISPにはほとんどルールがないので、非常に簡単です。

ルール1 英文法と同じで、動詞+目的語+目的語+・・という形をとる。

(動詞 目的語1 目的語2 目的語3 目的語4 ・・・)
カッコの中は必ず、英文法で言う、”動詞(=AutoLISP関数)”で始まり、その動詞の後には必ず、英文法で言う”目的語(=引数)”が続きます。
一つの文章はカッコで始まりカッコで終わります。
動詞や目的語の間は、半角スペースで区切ります。スペースの数は1個以上であれば何個でも可。
1つの文章を2行に渡って書いても全然OK。
英語と同じように、文章の中に文章が入り込んだりします。すなわち
(動詞 目的語1 目的語2 (動詞 目的語1 目的語2))
とか
(動詞 目的語1 目的語2 (動詞 目的語1 (動詞 目的語1 目的語2)))
のように、2重構造になったり、3重構造になったりします。
ここでは、下線を引いた部分が目的語3の役割をしています。なので、めを細めてみると
(動詞 目的語1 目的語2 目的語3
という形に見えるようになります。
重層化してくるとカッコの数がややこしくなってきますが、秀丸エディタでは、対応するカッコを閉じた瞬間に、相手のカッコを強調表示するので、慣れれば特に問題ありません。

ルール2返り値について

殆どのAutoLISP関数は、返り値をもちます。

(動詞1 目的語1 目的語2)

この一つの文章は、実行後、一つの値を残します。たとえが悪いですが、鳥が飛び立ったあと、フンを残していくような感じです。
この文章が仮に”100”というフン(=返り値)を残すとすると、

(動詞2 目的語1 目的語2 (動詞1 目的語1 目的語2))

という文章は

(動詞2  目的語1 目的語2 100)

という文章と同じ、ということになります。
どの関数が、どんなフンを残すのかというのはヘルプファイルにすべてかかれています。

画像は英語版なのでアレですが、「開発者ヘルプ」→「AutoLISPリファレンス」→「各コマンドを選択」で、返り値を知ることができます。
この返り値というのはプログラミング上非常に重要ですので、ヘルプファイルで常にチェックする必要があります。

ルール3 ” ; ”のあとは実行されない。

これはコメントアウトといい、”;”の後に書いた文字は、その行の終わりまで、一切無視されます。
この機能を利用して、プログラム中に説明を書き加えたり、動作確認中に、ある部分を意図的に読ませなくしたりします。
準備編で、秀丸エディタをカスタマイズしてありますので、簡単にコメント記号を行頭に挿入できます。

  • コメントアウトさせる行を選択
  • [F7]キーを押す


逆に”;”をいっぺんに削除するには、

  • ”;”を削除させたい行を選択
  • F8キーを押し、3を選択

ルール4 行の頭から、実行できるものは片っ端から実行される

簡単なコードを書いてみます。

  • 秀丸エディタで新規ファイルを開く
  • (princ “aaa”) といきなり書く
  • (princ “aaa”)
  • [Ctrl + S ] で名前をつけて保存。例えば test.lsp という名前で保存する
  • 秀丸アイコンをAutoCAD上にドラッグ
  • (princ “aaa”) が実行され、コマンドラインに、aaa と出ました。

また、直接AutoCADのコマンドラインに(princ “aaa”)と打っても、同じ事が行われます。
AutoCADでは、()で囲った文章を打ち込むと、勝手にAutoLISPであると判断して実行してくれます。
ですので、ちょっとした動きを確かめたいが、いちいち秀丸エディタを起動して・・・というほどでもない場合は、コマンドラインに直接打ち込むことができます。

AutoLISPのルールは以上です。ほんとにこれ以上、何もないのです。

AutoLISPを作る、読ませる、直す、の手順

私がやっている、AutoLISPを作る、読ませる、直す、の手順です。
一つ一つのコマンドの解説よりも、こういう実際的な話の方が、初学者には大事だったりします。

AutoLISPを作る

  • (defun は関数定義のコマンドで、とにかく下のように式を好きなだけ書く。
  • 最後に、定義した関数を呼び出すことで、読み込むと同時に実行されるようになる。こうしておいた方が、AutoLISP作成に、コマンドラインに関数名を打ち込む必要が無いので楽。
(defun test_1 () ;test_1というオリジナル関数を定義
(プログラム)
(プログラム)
(プログラム)
(プログラム)
(プログラム)
)
(test_1) ;test_1というオリジナル関数を呼び出して実行

AutoLISPを読ませる

“秀”ちゃんマークをドラッグ。

エラーの場合はこうなる

「XXXという関数は定義されていませんです。」使った関数が、AutoCADには読まれていない、ということです。

「形がおかしいです。」 カッコの対応がおかしいことがほとんど。

文法がおかしいです。(setq のあとに変数を3つ書いちゃったとか、そういう類の間違いです。

どこで引っかかっているのかわからないとき。

こういうときは、とにかく(princ “/n 行番号) をプログラム中のあちこちに書き込んでから走らせ、どこまで実行されているかを突き止めます。
すごく原始的ですが、なれちゃうとなんとも無い。
秀丸をカスタマイズした人なら、[F-2] を押すだけで(princ “/n )まで書いてくれるので、行番号を書き込むだけでOK。

(defun test_1 ()
(princ "n 2") ;[f-2]を押して挿入
(ここにプログラムを書く)
(princ "n 4") ;[f-2]を押して挿入
(ここにプログラムを書く)
(princ "n 6") ;[f-2]を押して挿入
(ここにプログラムを書く)
(princ "n 8") ;[f-2]を押して挿入
(ここにプログラムを書く)
(princ "n 10") ;[f-2]を押して挿入
(ここにプログラムを書く)
)
(test_1)

実行途中での変数の値を確かめたいとき

実行中に、変数の値を確かめたいときがけっこうあります。これもすごく原始的です。

(defun test_1 ()
(setq aaa 100)
(princ "n aaa :  ")(princ aaa)  ;aaaを反転コピー後、[F-3]で挿入
)
(test_1)

秀丸をカスタマイズした人なら、変数をダブルクリックしCtrl-Cでクリップボードにコピーした後、[F-3] を押すだけで(princ “n AAA : “)(princ AAA)と書いてくれるので、2秒くらいで挿入できます。

実行途中で、点の位置を画面上で確かめたいとき

これはかな~り必須です。

  • 「与えられた点を中心に、ある半径の円を書く関数」を共通ファイルにあらかじめ用意しておきます。(共通ファイルについては、次で書きます。)
  • 位置を知りたい変数を、ダブルクリックし、Ctrl-Cでクリップボードにコピーした後、[F-5] を押すだけで(checkcircle Pt 1.0 “0″) と書いてくれるので、2秒くらいで挿入できます。
  • あとはプログラムを実行させれば、そこに円がかかれます。
(defun test_1 ()
(setq aaa '(1000 1000)) ;(1000,1000)という座標をaaaにセット
(checkcircle aaa 1.0 "0")   ;aaaの位置に半径1の円をレイヤー0で描く
                        ;aaaを反転コピー後、[F-5]で挿入
)
(test_1)

以上の方法で、デバッグ作業はかなり高速になると思います。

共通ファイルをつくる。

今後AutoLISPをいくつも作ろう!と意気込んじゃっているのなら、最初から共通ファイルを用意したほうが良いです。ライブラリのようなものです。

共通ユーティリティファイルとはこんなものです。
”A_Utility.lsp”で保存してください。

;共通コマンド
(defun A_start ()
(setq OldCmdEcho (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(command "undo" "be")
(setq OldOsmode (getvar "OSMODE"))
(setq OldLayer (getvar "CLAYER"))
(setq OldLType (getvar "CeLType"))
(setq OldColor (getvar "CeColor"))
(setq OldOrtho (getvar "ORTHOMODE"))
(setq OldDStyle (getvar "DIMSTYLE"))
(princ)
)
;****
(defun A_end ()
(setvar "OSMODE" OldOsmode)
(command "undo" "end")
(setvar "CLAYER" OldLayer)
(setvar "CeLType" OldLType)
(setvar "CeColor" OldColor)
(setvar "ORTHOMODE" OldOrtho)
(if (and (/= (getvar "DIMSTYLE") OldDStyle)(tblsearch "DIMSTYLE" OldDStyle))
(command "-dimstyle" "Restore" OldDStyle)
)
(setvar "CMDECHO" OldCmdEcho)
(princ)
)
;****
(defun myerror (msg)
(setq error nil)
(SD2056)
(princ "n Error in your LISP")
(princ)
)
;CheckCircle**
;;;点に確認用の円を作図する
;;;【引き数】点A
(defun CheckCircle ( Point CircleRad TempLayer / )
(setq NowLayer (getvar "CLAYER"))
(command "layer" "S" TempLayer "")
(setq OldOsmode2 (getvar "OSMODE"))
(setvar "OSMODE" 0)
(command "circle" Point (* (getvar "DIMSCALE") CircleRad))
(setvar "OSMODE" OldOsmode2)
(command "layer" "S" NowLayer "")
(princ)
)
;DXFを取得
(defun A_dxf (g e)
(cond
((= (type e) 'ename) (cdr (assoc g (entget e))))
((= (type e) 'list) (cdr (assoc g e)))
)
)
(princ)

一方、新しく作るプログラムは、毎回、この状態から始めます。

いくつプログラムを作ってもこの形は変わりませんので、どこかに保存しておいて、毎回コピペして使えばよいです。

(defun test_1 () ;test_1というオリジナル関数を定義
;共通ユーティリティファイルを読みこむ
(load "A_Utility")
;エラーがおきたらとにかく独自エラールーチンである、*myerror*へ行かせる。
;この関数は"A_Utility"の中にある。
(setq *error* *myerror*)

;ユーザーの設定を退避保存。
;この関数は"A_Utility"の中にある。
(A_start)

(ここにプログラムをかく)
(ここにプログラムをかく)
(ここにプログラムをかく)
(ここにプログラムをかく)
(ここにプログラムをかく)

;退避しておいたユーザーの設定を復元
;この関数は"A_Utility"の中にある。
(A_end)

;独自エラールーチンをメモリから消去
(setq *error* nil)
)
(test_1) ;test_1というオリジナル関数を呼び出して実行

こうすることで、下記のことが実現できます

  1. Oスナップの設定や、現在画層のセッティングをプログラムの冒頭で全て記憶する。
  2. プログラムの最後の部分で記憶した設定を復元する。これによりユーザーの設定が元に戻る。
  3. エラーで終了した場合でも、強制的に元に戻す部分を読ませるので、安心。
  4. よって、ユーザーに怒られない。

また、汎用性が高いと思われる関数をこのファイルにどんどん書き足していって、ライブラリにすることができます。
例えば、前回のCheckCircleという関数がこの共通ファイルに含まれているので、(CheckCircle という関数をプログラム中に使うことができます。
相当な数の関数を突っ込んでも、AutoLISPは高速なので、どうってことありません。

 

コメント

この記事へのコメントはありません。

TOP