はじめる前の予備知識

ファイルの拡張子

AutoLISP と Visual LISP を使う上で、遭遇するファイルの拡張子は次のようなものがあります。

拡張子 形式 説明
LSP テキスト AutoLISP のプログラムファイルです。AutoCAD にロードできます。
FAS バイナリー コンパイルされたプログラムファイルです。AutoCAD にロードできます。
VLX バイナリー コンパイルされた【アプリケーション】ファイルです。AutoCAD にロードできます。
DCL テキスト ダイアログボックスの定義ファイルです。
PRJ テキスト Visual LISP の【プロジェクト】ファイルです。【プロジェクト】機能を利用することによって、複数のファイルにまたがるプログラムの管理が容易になります。
PRV テキスト Visual LISP の【アプリケーション】作成ファイルです。【プロジェクト】に似ていますが、DCL ファイルなどのリソースをまとめ、一つのパッケージにした【アプリケーション】を作成できます。
SLD バイナリー 【AutoCADスライド】と呼ばれる、作図ウィンドウのスナップショットファイルです。作図ウィンドウとダイアログに表示することができます。
LOG テキスト Visual LISP の【コンソール】や【トレース】のログファイルです。
OB バイナリー プログラムをコンパイルする過程で一時的に生成される、オブジェクトファイルです。
PBD バイナリー プログラムをコンパイルする過程で一時的に生成される、オブジェクトファイルです。

その他、バックアップファイルは、例えば「LSP」の場合は「_LS」となります。

名前空間

開発するプログラムは、既に稼働している AutoCAD のシステムプログラム群に組み込み、拡張するものですから、既存のプログラムの動作と干渉しないよう関数名や変数名を独自のものにする必要があります。このように、変数名などの名前がお互いに干渉や重複しないか配慮しなければならない範囲を名前空間と呼びます。

そのようなことから、プログラムの名前や開発者の略号などから自由に「foo:」のような接頭辞を関数名やグローバル変数につけることによって、既存の名前空間内で重複を避けるようプログラミングを書いていくことをお勧めします。

【アプリケーション】を作成すると、コンパイルオプションにより独自の名前空間をもった独立性の高いプログラムとすることができます。独立した名前空間で実行する【アプリケーション】では、それをロードした環境に対して、必要な関数だけを見せることができ、その他の必要の無いものは【アプリケーション】の中に隠すことができます。

名前空間は、図面ごとに独立しています。言い換えると、図面ごとに AutoLISP の実行環境を持っています。例えば、AutoCAD で同時に図面を二つ開いていたとします。プログラムのロードを行うと、その時アクティブになっている図面の AutoLISP の実行環境に読み込まれます。アクティブでなかった方の図面の AutoLISP の実行環境にはロードされていません。

AutoLisp Enviroment

プログラムをテストしている間は、何度もロードを繰り返すことになります。時には、不要な変数や関数が定義された状態になります。このとき、一度図面を閉じることで、図面の AutoLISP の実行環境も消してしまうことができます。AutoCAD アプリケーション自体を終了させる必要はありません。新しく図面を開けば、図面の AutoLISP の実行環境も新しくなりますので、改めてプログラムのロードを行って、テストを再開します。

関数を無効化する

プログラムをテストしている間は、無駄な関数や変数を定義してしまって、図面の AutoLISP の実行環境から消してしまいたいときもあるかもしれません。その場合は、関数名や変数名に「nil」を代入します。

_$ (setq c:enclosedNumber nil)⏎

システム内蔵の関数に対しても同じことが行えます。Visual LISP を開いている場合は、システム内蔵の関数は保護されてはいますが、その保護は解除することができるので、上の方法で無効化できます。Visual LISP を開いていなかった場合は、システム内蔵の関数は特段に保護はされていません。元に戻すには、図面を開き直して図面の AutoLISP の実行環境を初期化してください。

拡張 AutoLISP 関数

通常の AutoLISP 関数以外に、より幅広くプログラミンをおこなえるように「拡張 AutoLISP 関数」が用意されています。これらは主に ActiveX を介して AutoCAD にアクセスするために使用されます。

拡張 AutoLISP 関数は、AutoLISP 標準では自動的にロードされないとされています。そのため、これらを使うプログラムの先頭に「(vl-load-com)」と書き、明示的にロードを行います。この関数は、拡張 AutoLISP 関数が既にロードされているかどうかをチェックし、既にロードされている場合は何も行わず、そうでない場合に限ってロードを行います。重複していても問題は起こらないので、拡張 AutoLISP 関数を使用しているプログラムファイルの先頭、あるいは関数の先頭には、この「(vl-load-com)」をおまじないのように書いておいてください。

実際は、AutoCAD が起動するときの標準のプログラム群のロードの際に、拡張 AutoLISP 関数もロードされ、既に実行可能になっていることがほとんどであり、仮に vl-load-com を忘れていてもエラーが起こることは少ないかもしれません。しかし、書いておきましょう。

これらの関数は、関数名の先頭に vla-、vlax-、vlr- が付いたものを指します。この「vla-」で始まる関数はF1キーを押して表示される AutoCAD ヘルプ内の AutoLISP 関数に含まれていないものがあります。これに関しては、先頭の「vla-」を除いた以降の関数名でヘルプを検索すると、情報が得られます。ただし、それでも古いバージョンの AutoCAD ヘルプの場合は見つからないことがあります。その場合は VisualBasic 用に書かれたヘルプが別途インストールされているので、そちらを参照して関数の使い方を確認してください。このヘルプは通常下記のところにインストールされます。

C:\Program Files\Common Files\Autodesk Shared\acadauto.chm

このヘルプでの関数の検索も「vla-」を除いた以降の関数名で検索します。しかしながら、現在では AutoCAD のヘルプはオンラインで提供されているので、インターネット経由で最新のものを参照する方がよいでしょう。

ここで挙げた vla- などの接頭辞が付く関数以外に、vl- が付く関数も多く用意されています。これらは ActiveX とは関係なく、AutoLISP を拡張した関数という位置づけです。

AutoCAD にアクセスする三つの方法

AutoLISP から AutoCAD に図形などを描画するには次の三つの方法があります。

  1. command 関数を使用する
  2. entmake、entget 関数と DXF グループコードを使用する
  3. ActiveX を利用する
三つの方法の概要は以下の通りです。

1 のコマンドを使用する方法が最も古くから提供され、今でも使われています。その方法は「(command “LINE” “0,0” “100,100” “”)」と、command 関数を使って AutoCAD の【コマンドライン】に入力する形式によく似た引数を渡すものです。AutoCADユーザーならば、引数をイメージしやすく command 関数一つで一通りの事が行えるので使いやすいでしょう。3次元オブジェクトの中には、スイープ図形などコマンドを使って生成するものもあり、command 関数を使わなければならない局面もあります。

2 の AutoLISP の関数と DXF グループコードで図形を作成する方法は 1 に比べてきめ細かく高速に処理を行うことができます。具体的には、「(entmake (list (cons 0 “LINE”) (cons 10 ‘(0 0)) (cons 11 ‘(100 100))))」といった図形データを DXF グループコードで関連付けた LISP のリストにして entmake 関数に渡すことによって AutoCAD 内部の図面データベースとやり取りし、図形を描画します。図形データの取り出しでは entget 関数を使用しますが、こちらも DXF コードで装飾されたリストが返り値になります。図形データは LISP で処理しやすいリストになっているので、その点は違和感なく扱うことができます。しかし、DXF グループコードは無味乾燥な数値で、その意味はいちいちヘルプを検索して確認しなければなりません。また相互に関係するパラメータを的確に理解して設定しないとうまくいかない事もあります。複合図形では後続する従属図形を確認するために、連続して図面データベースを見ていかなければならず煩わしさがあります。

3 の ActiveX を利用する方法は LISP 一般の関数よりも、オブジェクト指向言語のアプローチに近く、AutoLISP に不慣れでもオブジェクト指向に慣れていれば、親しみを覚えやすいでしょう。具体的には「(vla-addLine *ModelSpace* (vlax-3d-point 0 0 0) (vlax-3d-point 100 100 0))」のように書きます(ここでの「*ModelSpace*」はモデル空間内の図形要素をまとめた「コレクション」を指しており、この一行だけでは実行できません。ここでは、このコレクションに線分オブジェクトを新たに加えるという意味になります)。メソッドやプロパティのアクセスなど関数が行き届いており、DXF グループコードに頼らない関数名を使うことによって、何をやっているか比較的分かりやすいプログラムになります。また、複合図形では、従属図形の情報を含んだ一つのオブジェクトとして扱えるのでハンドリングもしやすいものです。しかし、ActiveX 用の関数を使うにあたって、LISP のデータタイプから ActiveX 用のデータタイプにわざわざ変換しなければならない場合があり、覚えることと手間が少しだけ増えます。

以上のような方法があるわけですが、それではどの方法を使うのが賢明なのでしょうか。最終的な答えは、一つに絞るスタイルは賢明ではない、です。そしてそれは次のような段階的な選択を経て決まります。

  1. command 関数から AutoCAD のコマンドを組み合わせて実現できるものならば、command 関数で済ませてしまうべきです。AutoCAD の図面データベースの内容は複雑です。それに直接触らないで済むのは何より幸運です。コマンドを使用する方法が処理速度の点では最も遅くなりますが、AutoCAD ユーザーのスピードに比べると問題になることは少ないでしょう。
  2. コマンドでは扱いきれない複雑な処理、処理の多さからくる実行時間の短縮の必要性があるとき、残りの二つの方法を使うことが検討されます。実行速度の点では 2 の DXF グループコードを使う方法が最も優れています。
    しかし、実はこの方法には意外な欠点が隠れています。AutoCAD の図面データベース仕様上、この方法で繰り返し処理を行うとメリットであった実行速度があるとき極端に落ちるのです。この現象が起こると、ActiveX を使う方法よりも遅くなります。ヘルプファイルにも少しだけ注意がありましたが、なぜこのような事になるのかはまったく解りません。この現象が起こるのは、実験したケースでは数十万回の図面データベースへのアクセスと通常では起こりにくい条件ですが、プログラムの側から見れば、それは数十秒で上限に達します。そしてこういう現象が発生したら、きちんとリセットするためには AutoCAD アプリケーションを再起動する必要があるようです。
    AutoCAD ユーザーにとっては欠陥としか見えない、不可解極まりない現象が発生する可能性があるわけですが、速度が出ている場合の実行速度の面ではこの方法が素晴らしく優れています。
    もう一つこの方法のメリットを上げておきますと、一度に図形のすべてのデータが得られることです。他の方法では、画層は、線種は、と一つずつ値を取り出す必要がありますが、二つの図形を比較する際など、この方法ではリストの形で一度に比較できるので、とても簡単です。
  3. 上記のような実行速度の極端な低下は避けたい、また無味乾燥な DXF グループコードを扱いたくない場合は ActiveX を利用します。この方法は DXF グループコードを使う方法に比べて多少速度は遅くなりますが、command 関数よりも十分高速です。そして繰り返し処理を行っても速度低下のような現象は起こらず安定しています。オブジェクト指向的なアプローチのわかりやすさも含めると、ActiveX を使う方法が総合的に優れていると思います。
  4. 以上のことから、通常、図面データーベースにアクセスするのは ActiveX の方法が良さそうだと感じますが、図形の細かい情報が ActiveX のプロパティから取れないケースもあります。その際は DXF グループコードを使う方法に立ち戻ると、値が得られるケースがあります。

AutoCAD の内部仕様は膨大です。その中で、どの方法を選択するのが良いとは言えずケースバイケースです。決して command 関数が原始的で初歩的だから劣っているわけではありません。むしろ AutoCAD のコマンドで実装できることは信頼性の点で優れているとも言えます。一つのプログラムの中で、どれか一つの方法に絞る必要はありません。つぎはぎに見えるかもしれませんが、その時々に応じた最適な方法を選ぶようにしてください。