comp.cad.autocad AutoLISP FAQ 日本語

原文に関する説明
Title: comp.cad.autocad AutoLISP FAQ
Archive-name: CAD/autolisp-faq
Japanized URL: http://www.bekkoame.or.jp/~masaani/autocad/autolisp.html
Version: 1.11
Last-modified: 26.Dec 1997
Posted-By: Reini Urban 
Posting Frequency: bi-weekly
Copyright: see Appendix [A]

翻訳文に関する説明

Title: Japanized comp.cad.autocad AutoLISP FAQ
Archive-name: CAD/autolisp-faq
Japanized URL: http://www.bekkoame.or.jp/~masaani/autocad/autolisp.html
Version: 1.11j

comp.cad.autocad AutoLISP FAQにようこそ!

AutoLISPは有名なCADソフトであるAutoCADのスクリプト言語です。 このAutoLISP FAQは、comp.cad.autocadとalt.cad.autocadとその 答えのニュースグループ(*.answers)に隔週で投稿されています。
Peter Sheerinが書いたAutoCAD FAQは http://www.cadence-mag.com/library/FAQ にありますが、comp.cad.autocadには投稿されていません。

(訳注:AutoCADのFAQは http://www.autodesk.com/support/faqs/faqs.htm にもありますが、comp.cad.autocadには投稿されていません。)

内容と例題はRelease 10のAutoLISPから利用可能なものです。 サードパーティのAutoLISPコンパイラであるACOMPやVital Lispでも利用 できるものです。R14での変更はまだ完全に含まれていません。

これらはAutoLISPニュースグループの中では特別なことではありません。

このFAQのすべての関数のソースコードは、FAQ-CODE.LSPにあります (場所は付録[A.1]を見てください)。 ここには、Windowsヘルプ形式のファイルもあります。

すべての協力者に感謝の意を示します。修正と協力はいつでも歓迎します。 (宛先は rurban@sbox.tu-graz.ac.atです)

(この投稿の中で| 赤色は変更があった部分で + 紫色は新規に追加した部分です。 私見や不確かなことは<..>で括られています)
(訳注は緑色であらわしています)


目次


第1部: 一般
[0] AutoLISPの将来はどうなるの? 代わりにVB勉強したほうがいいか?
[1] AutoLISPルーチンをインターネットで探すならどこ?
[1.1] comp.cad.autocadの過去の記事はどこにありますか?
[1.2] AutoDESKのSDK
[2] AutoLISPの勉強でもっともよいは何?
[2.1] オンラインのAutoLISPの文書やWindowsヘルプ
[2.2] AutoLISPのコーディングスタイルについて
[3] どのようにしてAutoLISPプログラムをデバッグしたらよいですか?
[3.1] AutoLISP自身で記述されたデバッガ
[3.2] モジュラースタイルとTRACEについて
[3.3] break関数とデバッグプリントについて
[4] AutoLISPプログラムにプロテクトをかける方法
[4.1] Kelvinate
[4.2] Protect
[4.3] Kelvinate and Protect
[4.4] Convert 3.5
[4.5] acomp
[4.6] Vital Lisp Professional
[4.7] Lisp2C
[5] AutoLISPのコンパイラについて
[5.1] acomp
[5.2] Vital Lisp Professional
[6] AutoLISPエディタや他のツールについて
[6.1] AutoLISPエディタ
[6.2] 括弧のチェック
[6.3] プリティプリンタ
[7] AutoLISPの問題や不具合について(とりわけR13)
[8] AutoLISPによるソート
[9] 再帰
[10] mapcarなどを使った繰り返し
[11] 起動時に私のプログラムをロードできない
[12] どのようにして私のプログラムをオートロードさせるか?
[13] どのようにして引数の数が変更できる関数を書くか?
[14] どのようにしてスタックオーバーフローを禁止させるか?
[15] (command "ROTATE3D")が動作しないのはなぜ?
[16] Lispプログラムを複数の図面にわたって実行させるには

第2部: 例題とコード
[20] 一般的な役に立つ関数について
[20.1] リスト操作
[20.2] 文字列操作
[20.3] シンボルから文字列に変換する
[20.4] AutoCAD図形操作
[21] Lispプログラムの例:
[21.1] 文字列をまとめて変更する,ポリラインや画層や日付について
[21.2] Lispを使って印刷設定ダイアログを操作する DDEを使う
[21.3] (command "_LAYER"...)を使わないで(entmod)や(entmake)で画層を扱う
[21.4] Lispで複数のファイルを選択するには? (FILES-Unlockとして)
[21.5] 複数のブロックを置換する
[21.6] (vports)関数,VIEWPORTエンティティ,点の変換
[21.7] すべての表示できるオブジェクトを選択する: ズーム座標
[21.8] 選択した図形のXYZデータをどのようにしてファイルに書き込むか?
[22] ブロック属性
[22.1] ブロック属性にアクセスするには?
[22.2] ブロック属性を変更するには? DATESTAMP.LSP
[22.3] ブロック属性を更新するには?
[22.4] AutoLISPで属性を含む複雑なブロックを(entmake)で作成するには?
[23] ポリライン
[23.1] ポリラインの頂点へのアクセスの仕方
[23.2] 複数の線分をポリラインに結合する方法
[23.3] 複数のポリラインの幅を変更する方法
[23.4] ポリラインやスプラインを(ENTMAKE)や(COMMAND)で作成する方法
[23.5] ポリラインの長さを計算する方法
[23.6] ポリラインの方向を反転する方法
[24] 円や円弧: BULGE変換といくつかのtrigonometry
[25] DCL: タブやmonotextフォントを使ったリストボックス
[26] EED 拡張データ: 入手と保存の方法
[26.1] (ssget "X")を使って拡張データのついたエンティティを選ぶには
[26.2] オブジェクトのEEDを得るには
[27] LISPのなかでコマンドを中断させるには?
[28] LISPでACIS内部ジオメトリを解析するには
  --
[A] Disclaimer, 作者の注記
[A.1] FAQ のありか
[B] 謝辞
[C] 変更履歴


[0] AutoLISPの将来はどうなるの? 代わりにVB勉強したほうがいいか?

AutoLISPは将来のリリースでも継続してサポートされるでしょう。 AutoLISPの位置づけは安定しているものと見えます。 VBはオフィスオートメーション(ACADとExcelやAccessとの連携)を手軽にする ために導入されました。

それぞれの言語には長所と短所があります。あなたは両方をよく見てください。 VBはより視覚的であり、AutoLISPはより論理的に見えるかもしれません。 VBAのオブジェクト指向によって、より簡単で覚えやすくしようとしています。 しかし、AutoLISPのようにコマンドとして実行させることはできません。
新しいVBA(R14.01)では格段に早くなるでしょう。 [5.2]を見て下さい 次のリリースで準備中の、オートデスクによる新しいLISP処理系 (コードネームは"Zoomer"とか、"Visual Lisp"と呼ばれています)は LISPプログラムのコンパイルをサポートし、とてもよくなるでしょう。


[1]AutoLISPルーチンをインターネットで探すならどこ?

有名なAutoLISPによるAutoCADシェアウェアのサイトは

CADalog - The AutoCAD Shareware Clearinghouse
http://www.cadalog.com (Mike Clark)
Rolling Stock Software (David Whynot)
http://www.buildingweb.com/cadsyst/
PIRS Online (tm)
http://Biz.rtd.com/insa/
これらはAutoCAD関連ソフトウェアに特化しており、AutoLISPのコレクションとして とてもよいです。その他のAutoLISPのシェアウェアのサイトは、ニュースグループに URLが紹介されることがあります。

AutoLISPが集められたその他のサイトは:

xarch AutoCAD Info & Tools (Reini Urban)
http://xarch.tu-graz.ac.at/autocad/ (検索あり)
CADENCE magazine code (Peter Sheerin)
http://www.cadence-mag.com/code 検索あり
CADalyst magazine code (compiled by "Hot Tip Harry" Art Liddle)
http://www.cadonline.com/96code.htm
AutoCAD Tech Journal code (Peter Sheerin)
http://www.atj.com
The CADshack (Jeff Foster)
http://www.cadshack.com/lispfile.htm
SimTel - Coast To Coast - Archive (とても昔からある)
http://www.coast.net/SimTel/msdos/autocad.html
http://www.coast.net/SimTel/win3/cad.html
Bob Jones
http://www.io.com/~bcjones/files.html
Henry Francis
http://www.ez-sys.net/~coopfra/
Owen Wengerd
http://www.manusoft.com
Desi Moreno
http://www.invsn.com/desmos/autolisp.htm
Dr.Lisp Utilities (Alexander Medwedew)
http://tribeca.ios.com:80/~compvent/drlutils.html
UCCB AutoCAD and AutoLISP page (Paul Standing)
http://ucad1.uccb.ns.ca/acad/cad.htm
Theo L.A. Groenenberg [移動しました]
http://xoom.com/acadvice/autolisp.htm
McNeel
ftp://ftp.mcneel.com/lisp/
http://www.autodesk.com/support/techdocs/techdocs.htm には、オートデスク製品サポートによる技術的な質問に対する文書があります。 (彼らの FAQ's)

[1.1] comp.cad.autocadの過去の記事はどこにありますか?

comp.cad.autocadには過去の記事を保存するようなところはありません。 しかし、ニュースの記事を保存するいくつかのサーチマシンには、存在します。 一部をあげると:

http://www.dejanews.com/もっとも大きなニュースアーカイブ
直接見るには http://search.dejanews.com/dnquery.xp?query=~g%20comp.cad.autocad
http://www.altavista.com/
http://www.altavista.digital.com/cgi-bin/query?pg=aq&what=news
http://www.excite.com/
http://www.excite.com/search.gw?collection=news
http://www.phoaks.com/phoaks/comp/cad/autocad/
ウェブリソースの見出し
特定のニュース投稿はここにも置かれています http://xarch.tu-graz.ac.at/autocad/news/contents.html


[1.2] AutoDESKのSDK

R12になってAutoDESKにおいてSDK(ソフトウェア開発キット)が利用可能になりました。 SDK2は国際版のR12に無料で同封されていました。 その中にはADSやAutoLISPのソースコードやライブラリがたくさんはいっています。

R13ではAutoDESKはマイクロソフトがやっているような、特別な開発者のための ネットワークを準備しました。ADNといいます。昔のSDKのようにCD-ROMを配布して います。しかし中心になっているのはADSやARXの開発者向けの情報です。
あなたの地域のAutoDESKの事務所に参加のしかたを問い合わせてください。

AutoDESKのSDKに添付されたリスププログラムのいくつかは http://xarch.tu-graz.ac.at/autocad/code/adesk/SDK2にあります。

アメリカでは、ADNの年会費は$495.00です。The CDs don't include any SDK per se, but most of the stuff in the original SDKs is included in one form or another. (Owen)


[2] AutoLISPの勉強でもっともよい本は何?

"AutoLISPリファレンスマニュアル"
AutoDESK出版
R12では別冊のマニュアルになりました。R14ではWinHELPファイルになりました。

"Maximizing AutoLISP"
Rusty Gesner, Tony and Mark Middlebrook, Tony Tanzillo共著
新しいMaximizing AutoLISP R13は今月中には発行されるでしょう。 R12の本は売り切れのため入手困難です。
詳しくは http://www.group-a.com/~rusty

AutoLISPに関する本もまだたくさんあります。

もっともよいLisp(AutoLISPではなく)の本はAutoLISPプログラマに とっても有益なものでしょう。

"Lisp"
Winston, Horn which 共著


[2.1]オンラインのAutoLISPの文書やWindowsヘルプはどこにありますか

R14は完全なマニュアルをWindows形式のヘルプファイルとして配布しています。

AutoLISPに関するWindowsヘルプファイルは次の通り:

DOS版ではメモリ常駐型の LISPHLP.EXE
というものがあります。 (Ctrl-右Shift-Rで起動します。1988年からあります)

LSPDOC.PL: http://xarch.tu-graz.ac.at/autocad/lsp_tools/#lspdocにあるツールは、 LISPプログラムから自動的にWinHELPファイルを作成するものです。


[2.2] AutoLISPのコーディングスタイルについて

雑誌やさまざまなウェブサイトにあるサンプルコードの多くは、 非常に悪い書きかたをされています。 AutoLISPプログラムを理解することがとても難しいと感じてしまう理由は、 決まりごとが少なすぎることと、勘定できない括弧の数の多さにあります。 従って、誰もがきれいで読みやすいコードを求めています。 AutoDeskのサンプルコードはとてもよく書いています。しかしたまには彼らも 似たようなことをしていまいます。:)

プリティプリンタとかビューティファイアとよばれるソフトが( [6.3]を見てください)あなたが書いたコードを自動的に 整えてくれます。

コーディングに関するAutoDESKの非常によくまとめられた文書があります。 Lispプログラムを読みやすくするコメントの付け方や字下げの仕方の標準があります。 それは R12 CD-ROMの中のSDK2 ACG.DOCか、 http://xarch.tu-graz.ac.at/autocad/docs/acg.txtにあります。

重要なことがらは:


[3]どのようにしてAutoLISPプログラムをデバッグしたらよいですか?

[3.1]AutoLISPの3つのネイティブデバッガ

[5] AutoLISPコンパイラも見てください

[3.2] モジュラースタイルとTRACEについて

デバッグにおいてもっともよい方法は、あなたがよいデザインのソフトを書くこと につきる。モジュラースタイルで、機能を関数に分割し、ネストされた関数呼び出し でそれらを呼び出して機能を実現することだ。 (trace)関数はエラーの発生個所を追跡するのにやくにたつ。

[3.3] break関数とデバッグプリントについて

例を示す:

;;; Debugging functions (defun break (s) (if *BREAK* (progn (princ "BREAK>> (stop with <Enter>)\nBREAK>> ")(princ s) (while (/= (setq s (getstring "\nBREAK>> ")) "") (print (eval (read s))))))) ;bugfix from v1.3! (defun dbg-print (s) ;accepts atoms and lists (if *DEBUG* (if (listp s) (mapcar 'print s) (print s)))) (defun C:DEBUG () (setq *DEBUG* (not *DEBUG*))) ;switch it on and off (defun C:BREAK () (setq *BREAK* (not *BREAK*))) (defun CONT () (setq *BREAK* nil)) ;continue without any interruption ;;;Example (setq *BREAK* T *DEBUG* T) (defun C:TEST () (foreach x '("1" "1.0" "1e-3") (break "in foreach") ; stops evaluation if *BREAK* is on, you can ; enter x and the value of x is printed ; until you enter Enter (setq x (atof x)) ; this is some code which manipulates x (dbg-print x) ; this prints the new value of x ; if *DEBUG* is on ) ) Command: TEST BREAK>> (stop with <Enter>) BREAK>> in foreach BREAK>> x 1.0 BREAK>> (CONT) ; turn off the break nil BREAK>> <Enter> 1.0 1.0 0.001 あなたは上位のループの中で次のように入力すれば、デバッグ出力をしないように 切り替えられる。 BREAK>> (setq *DEBUG* nil)


[4] AutoLISPプログラムにプロテクトをかける方法

"あなたは本当にプロテクトをかける必要があるのですか? あなたの友人と処理を 共有したいと思ったとき、なぜコードをあげられないのですか? 他の人と一緒に仕事をすることは、新しいアイデアやよりよいアプリケーションを得る よい方法です。
いくつかの優れたユーティリティは私の友人が作ったものだし、 また私が提供したものが彼らのユーティリティにもなっています"

[4.1] Kelvinate
kelv.exeはR12 CD-ROMやAutoLISPサイト[1]に あります。プリティプリンタによってDe-Kelvinateされた プログラムを見ることができますが、シンボル名は書き換えられ、コメントは 失われます。
[4.2] Protect
protect.exeは、R12 CD-ROMやAutoLISPサイト[1]に あります。
注意。プロテクトを解除するコマンドもあります。
[4.3] Kelvinate and Protect
最初kelvinateがLISPプログラムを読めなくします。それからprotectをかけます。
[4.4] Convert 3.5
Maciej LukasiewiczによるLispの暗号化・複号化のシェアウェアです。
Decryptor v2.0は今は使うべきではありません。Convert 3.5によって暗号化された "プロテクトのかかったLispプログラム"は、他のプログラムからは 複号できなくなります。でもConvertでならできるそうです。
[4.5] acomp
AutoLISPコンパイラacomp.exeはR12各国語版かAutoLISPサイトにあります。 acompの詳細は http://xarch.tu-graz.ac.at/autocad/bi4
にあります。 [5.1] AutoLISPコンパイラも見てください。
[4.6] Vital Lisp Pro
http://www.basissoftware.com/vill.htm
"ViLL"といわれます。とても高いです。[5.2] AutoLISPコンパイラ も見てください。
[4.7] Lisp2C
LispをCに変換します。R12とR13のDosおよびWin用です。(Watcom, Metaware, MSVC に対応しています。)
これらのCコンパイラも必要になります。
http://www.basic.si
まとめ:
本物の暗号化はVital Lispでしかできません
Kelvinateを使うとプログラムを読めなくし、ロード時間を早くします。
ProtectによるLISPファイルは簡単にもとに戻せます。
他のは元に戻せません。
Convertプログラムで-e$GUARDオプションをつけてプロテクトをかけると、 Convertだけがプロテクト解除することができます


[5] AutoLISPのコンパイラについて

2つのAutoLISPコンパイラがあります

[5.1] acomp
AcompはR12の各国語版でサポートされたものです。無料です。 R13や米国国内版のR12/Winでは動作しません。
拡張子が.BI4というファイルを生成します。ACADLC.EXPという、特別なAutoLISPの実行モジュールが必要になります。詳しくは、 http://xarch.tu-graz.ac.at/autocad/bi4を見てください。

[5.2] Vital Lisp Professional
Basis Software Inc. USAによるものです。簡単で最もよいです。 ランタイムモジュールはライセンスフリーで、R12/R13/R14 DOS/Windows/NT用が 用意されています。
http://www.basissoftware.com/vill.htmを見てください。 ここには無料のデモがあります。現在のバージョンは3.2です。
R14版(ViLL 3.0)はActiveX(VBのような)機能とリアクタ機能を持ちます。 [6.1][4.6]を見てください。

まとめ:
AutoLISPコンパイラや他のLispコンパイラはバイトコードコンパイラです。 バイトコードコンパイラはランタイムシステムを必要とします。 あなたは単独のプログラムを作ることはできません。 Villを使うとあなたは単独のARXを作ることができます。 また、シンボル名は隠されてしまいます。


[6] AutoLISPエディタや他のツールについて

[6.1] AutoLISPエディタ

Vital Lisp
エディタ機能のみのライト版が$50で、デバッガが付いたスタンダード版が $350です。コンパイラやエクステンションがついたプロフェッショナル版は $675します。スタンダード版をつかうと、よいツールになるでしょう。
[5.2] AutoLISPコンパイラを見てください。
LispPad
Tony TanzilloによるNifty Windows Lisp Editorです。 http://ourworld.compuserve.com/homepages/tonyt/LispPad.htm 初期バージョンがMaximizing AutoCAD R14の付録になっていました。 http://www.group-a.com/~rusty
製品版が1997年の第一四半期に発表され、ニュースグループでもお知らせする といわれていました
LispLink 商用のAutoLispエディタです。 http://www.flash.net/~caelink/ll14_desc.htmlを見てください。
Visual Lisp
とてもよいWindows Lisp EditorでVersion 1.0もまだ無料です。 [1]を見てください。
WCEDIT 2.02
DOS R12のADSエディタでエディタの中でLispコードを評価できます。 無料です。
[1]見てください。
MultiEdit Pro 7.01g
これはDosとWindowsで動作する高価なプログラミングエディタです。 Lispの構文チェックもしなければプリティプリンティングもおこないません。しかし 何もかもが違います。
詳しくは http://xarch.tu-graz.ac.at/autocad/adge/CAMP_Adge96_lisp.htmlを見てください。 ホームページは http://www.amcyber.com/です。
CODEKEY
古い商用のDOS版のIDEを持ち、内部のプリティプリンタと、protectとunprotectと kelvinatorがついてきます。{価値は?}
ALLY 3.0 and CADET
Lispの構文チェックと編集機能があるシェアウェアです。
[6.2]を見てください。
pred
無料です。小さなdosのエディタで括弧の対応がハイライト表示してくれます
ftp://xarch.tu-graz.ac.at/pub/autocad/lsp_tools/pred.zipにあります。
Emacs (for NT)
大きなエディタで、覚えるのがとても難しいです。しかしLispで書かれており、 Lispによってカスタマイズも可能です。無料で、すべてのプラットホームに 対応しています。 http://xarch.tu-graz.ac.at/autocad/lsp_tools/ntemacs.htmlをチェック してください。
ほかにもありますが、いいか悪いかはわかりません

[6.2] 括弧のチェック

括弧のチェックソフトはあまりつかわれていないかもしれません。 エディタが肩代わりするようになってきています。
ALLY30.ZIP
シェアウェアでLispの構文チェックをします。構文をチェックし、分析結果を 出力します。(関数の依存関係をツリー表示する)[1]を 見てください。
lck21b.zip
LCK Lisp Checker 2.1bグラフィカルに表示します。
paran.zip
単純です。
PARNCH.ZIP
単純です。
いくつかのAutoLISPプログラムにはカッコを数えるものがあります。

[6.3] プリティプリンタ

外部:
FMT202S.ZIP
Lisp, DCLと FRMソースコード整形してくれます。
LB.EXE
AutoDESKのソースコード整形ソフトです。
[1]で示したSDK2のにあります
PPRINT.LSP
[1]のSDK2の中にあります。
内部:
EmacsやVital LispやCodekeyは内部に整形機能があります。 私はこれを使っています

すべてのツールに関する事柄は http://xarch.tu-graz.ac.at/autocad/lsp_tools/ か、[1]で示したあなたの近くのAutoLISPサイトに あります。


[7] AutoLISPの問題や不具合について(とりわけR13)

よく知られていないAutoLISPの不具合があります。 AutoLISPインタープリタ自身(ACADL.EXE/.EXP)はだいたいよく動いています。 しかしいくつかの問題がCADやプロテウス(DCL)エンジンに存在します。 それからDDMODIFY.LSPのようなサポートリスププログラムによってもおきます。

(entget) LWPOLYLINE
(caddr (getval 10 ele))で得られるZ座標値はいいかげんな値で、 数値として大きすぎか小さすぎの浮動小数点例外を発生させることがあります。
状況:第2部の[23.1]を見てください。
acad_strlsort: Windowsで奇妙な順番にソートされる
Windows環境で文字列がその(ascii)表現の通りにソートされません

Windows: (acad_strlsort '("-1" "+1")) -> ("-1" "+1"), DOS: (acad_strlsort '("-1" "+1")) -> ("+1" "-1") But for both: (mapcar 'ascii ("-" "+")) -> (45 43) 詳しくは http://xarch.tu-graz.ac.at/autocad/docs/strlsort-bug.htmlを見てください。

ai_propchk
(ai_propchk)はR13c3更新パッチによるC:AI_PROPに変更されました。 理由はEnterキーの押下によって繰り返し実行できるようにです。
"AutoLISP関数ai_propchkはc:ai_propに変更されました。 それは他のコマンドと同じような動作をしてほしいからです。 ツールバーから選択されたときにもリターンキーを押したときのようにDDMODIFY コマンドが再度実行されるようになりました。"
http://www.autodesk.com/support/techdocs/acadce/td111682.htmを見てください。

R13のDCLの異常なアクションコールバックはAutoCADをクラッシュさせる
R13のバグで、ダイアログボックスのスクロールバーよりアクション コールバックが発生しているときに、AutoLISPプログラムにエラーが発生すると AutoCADがファイタルエラーになってクラッシュします。 実際に、null関数をコールバックから評価させようとすると、AutoCADは簡単に クラッシュしてしまいます。 技術的にはこれはAutoLispインタプリターのバグではありません。しかし 私たちはこれをAutoLispのバグと今でも呼んでいます。

あなたはシンボルテーブルの70フラグのビット値64に依存したプログラムを R13では書くことができません。以前のリリースでは可能でした。R14もおなじです。

その他には、Steve Johnsonが提供している非公式のAutoCADのバグリストの 中に、AutoLISPプログラムや状況に関する問題点が示されています。 http://www.awa.com/nct/software/13bug04.html (特に: 33, 124, 126, 127, 139, 153, 158, 165, 176, 182, 192, 193, 238, 240, 254, 272, 295)

プロテクトを掛けたLispファイル
プレリリースのR13c4の不具合のために、プロテクトをかけたLispファイルが メモリの中ではプロテクトがかかっていない状態であることがわかりました。 私たちの意見では、この問題は全ての人に周知させる必要があります。 so that developers don't inadvertently assume their protected code is safe from prying eyes. このFAQの話題はAutoDeskの管理しているCISフォーラムの中で非常に大きな 問題になりました。

使用中の選択セットの数の制限(シンボルに結び付けられた)
これらは一時ファイルに書き込まれます。選択セットが不要になったときには、 シンボルをnilに設定し、(gc)を実行しなければなりません。 (gc)は、ガベージコレクションをするプログラムで、これが実際にそのような 一時ファイルをクローズします。
最大数はオペレーティングシステムに依存します。たとえばDOSでは、 CONFIG.SYSのFILESの値になります。
R13は数が増えました。

数値: 範囲, 誤差
整数値は内部では倍長整数で表現されています(符号付きの32ビット)。 しかしAutoLISPからAutoCADに値を返すときは、符号付きの16ビット整数しか 受け入れられません。-32766から+32767までです。 なぜならAutoCADは16ビット整数しか必要としないからです。

浮動小数点数は倍精度の精度を持っています(32-bit IEEE)。すべての内部AutoLISPと AutoCADの数値演算はこの倍精度形式によって行われます。それは十分なものです。 最低最初の14桁の精度が保証されています。

しかしながら多くの幾何学的な比較において、しばしば数値の丸め誤差が発生します。 そこで点の比較を行うときには次のようにします。 (equal pt1 pt2 1e-6) ; 0.000001 rounding error tolerance (equal pt1 pt2)のかわりに、角度の比較でも同じです。
http://www.autodesk.com/support/techdocs/acadfc/td301207.htm を見てください。

acompの(eq)の動作の不一致
[5.1] acompでコンパイルされたコードに対して、あなたは注意を 払わなければなりません。 BI4の(eq)とAutoLISPの(eq)の挙動が違います。 AutoLISPでは(eq "1" "1")Tを返しますが、acompは nilを返します。

以下のものは厳密には不具合とはいえません。しかしそれはAutoLISPをクラッシュさせたり、間違った結果を返したりします。これらはLisp言語として悪い実装というしかない。

(and)(or)はTの代わりにnilでない引数の値を返すべきだ。 http://xarch.tu-graz.ac.at/autocad/docs/and-bug.html

<と>が文字列でも利用できるのだから、(max)(min)は文字列 を処理できるようにすべきだ。

acad_strlsortを見てほしい


[8] AutoLISPによるソート

私はAutoLISPおけるソートの概要を http://xarch.tu-graz.ac.at/autocad/lisp/#sortに用意した。

LISPにおいて、もっともよく使われるソートの方法は、マージソートと よばれるものである。(AutoDeskのTABLES.LSPのサンプルの中で(str-sort) 関数のなかでも使われている。) なぜなら、この方法はリストに対するソートとして自然な方法だからである。 通常(C言語などで)、あなたはヒープソート(をどんなデータに対しても)か クイックソート(をランダムな並びのデータに対して)か、挿入ソートを小さな リスト(7件以下)か部分リストのソートのなかでアルゴリズムとして使うだろう。

これはLispによるどんなデータやリストのリストやリストへのインデックスに 対して利用できるシェルソート、バブルソート、挿入ソート、クイックソートで ある。lispではあなたはソートのための関数を、実行時に決めることができる。 (ここではmethod引数で渡している) それがいろいろなデータ型(数値とか、座標値とか文字など)でも1つのソート関数で 済む理由である。

(sort data method) ;method: 項目の比較に使う関数 ;数値に使うデフォルトの関数は: '< 所用時間について http://xarch.tu-graz.ac.at/autocad/lisp/sort/ur_sort.lspを見ると 100の要素のソート: バブルソート : 13.639008 sec/ 30.08% 挿入ソート : 13.368042 sec/ 29.48% (並んでいるデータははやい) シェルソート : 13.478973 sec/ 29.73% (いいかげんに作ったので) マージソート : 2.232971 sec/ 4.92% クイックソート: 2.433960 sec/ 5.37% vlx-sort : 0.099976 sec/ 0.22% (Vital Lispが提供する) acad_strlsort : 0.089996 sec/ 0.20% (AutoLISPが提供する。文字列に限る)


[9] 再帰

これはあまり聞かれない質問だが興味ある質問である なぜならLisp自身が再帰によって定義されており、しかもそれが問題を もっとも簡潔に記述することができるからである

再帰に関するよい参考文書は以下にある http://xarch.tu-graz.ac.at/autocad/lisp とりわけ http://xarch.tu-graz.ac.at/autocad/lisp/recursive.html にDennis Shinnによって書かれたチュートリアルがある。

(defun fact (n) (cond ((zerop n) 1) (T (* n (fact (1- n))))))

注意: この関数の自習用の例が http://xarch.tu-graz.ac.at/autocad/lisp/self-mod.lspにある。


[10] mapcarを使った繰り返し

再帰と同じでこれもあまり聞かれない質問だが、理解するのは同じように難しい。
AutoLISPで繰り返しの構文を作るには(while),(repeat),(foreach),(mapcar)がある。 私たちはこのFAQのサンプルコードでは繰り返し構文をよく使っている。なぜなら、 コーディングの信条にあっているからである。

Vladimir Nesterowskyは、LAMBDAやQUOTEやMAPCARとは抜け道のようなものである。 と言っています。

>> there are 14 paths and 12 pigs. >> How can there be 24 ducks? >> Is there a lisp command that will allow me to pick these >> lines of text, and recognize the number(s) in each line, >> in order to, say, raise each number by two? >> Leaving the sentence structure, etc, intact? これは1つの方法です。(他にも方法があることはわかっています) (defun mult2 (strng) ; (c) by Vladimir Nesterowsky (strlgather (mapcar '(lambda (s / n) (if (zerop (setq n (atof s))) s (rtos (* n 2)))) (strlparse strng " ")) ; parse by spaces " ")) ; gather back with spaces

詳細は http://xarch.tu-graz.ac.at/autocad/lisp/transpose.001.htmlにあります。

(defun transpose(l) ; (c) by Doug Wilson (apply 'mapcar (cons 'list l)))

詳細は http://xarch.tu-graz.ac.at/autocad/lisp/transpose.002.htmlにあります。 よりよい説明は http://members.tripod.com/~vnestr/mapcar.txtにあります。


[11] 起動時に私のプログラムをロードできない

Lispファイルを起動時に読み込まれるようにするには、ACAD.LSPに記述するとよい。 カスタマイズされたメニューと一緒に動作するリスプファイルはメニューリスプ ファイルに記述するとよい。メニューリスプファイルはACAD.MNLファイルを起動時に ロードする。

ACAD.LSPの中にS::STARTUPという関数を定義する。 この関数は起動時の初期化処理の後に自動的に呼びだされる。 言い換えると"コマンドリスト割り込み(6 . 2)"エラーを取得できる ようになる。

(load)は絶対パスや拡張子がなくてもAutoCAD検索パスからプログラムを 検索してくれる。それは、 1) カレントディレクトリ
2) acad.exeがあるディレクトリ
3) ACAD環境変数によって定義されたその他すべてのディレクトリ
(ウィンドウズでは環境設定ダイアログボックスのサポートパスに定義された すべてのディレクトリ)

もしプログラムが読み込まれないようであれば、まずAutoCADの検索パスの設定が どうなっているか確認すべきだ。

AutoCADのロード処理の技術的側面については、異なるプラットフォーム、 全てのリスプファイルにおいて、以下にまとめられている。 http://xarch.tu-graz.ac.at/autocad/urban/urban-eng.html#Loading_Explicitly

acadlc(acomp)とUS版のAutoCAD R12では、ACAD.LSPは自動的には読み込まれない。 従ってあなたはACAD.MNLファイルに(load "ACAD" -1)と追加しなければならない。

ACAD.LSPの例:

;;;ACAD.LSP ;;; Fred the Beaver, 12/12/94 (load "init" -1) ; this loads some tools of mine (defun S::STARTUP () (load "new-end" -1) ; this redefines the END command )

(load)関数がエラーを起こしたときのLISPインタプリタの割り込み処理を 止めるために-1が使われている。 ロードする際にエラーが発生したら、-1が返される。しかし評価は継続する。 -1は他のどんなアトムであってもかまわない。

S::STARTUPをあなたのコードで拡張するときの例である。 (Vital Lispではこれはコンパイルすると動かなくなる。かならずコンパイル しないで使わなければならない)

(defun MY::STARTUP () ;your startup code goes here .. (princ) ) (setq S::STARTUP (if (and S::STARTUP (listp S::STARTUP)) ;already defined in ACAD.LSP ; or elsewhere (append S::STARTUP (cdr MY::STARTUP)) ;append your code MY:STARTUP)) ;just your code

またはより単純に

(if (and S::STARTUP (listp S::STARTUP)) (setq S::STARTUP (append S::STARTUP (list func '(princ)))) (setq S::STARTUP (list nil func '(princ))))

[12] どのようにして私のプログラムをオートロードさせるか? もみてください。


[12] どのようにして私のプログラムをオートロードさせるか?

どのようにしたら自分のプログラムを自動的にロードできるか?
あなたは起動時にプログラムを読み込ませることもできる([11] 起動時に私のプログラムをロードできないを見てください)。 その場合多くのメモリを必要とし、起動時間が多くなってしまう。 さもなければオートローディング機構によっても実現できる。
R14 ARXプログラムは新しいオートローディングの方法を使っている。これには レジストリの設定が必要であり、ACADR14.LSPは必要ではなくなる。

ACADR12.LSPやACADR13.LSPの終わりのほうをみてほしい。AutoCADが自身の プログラムに対してオートローディングを使っている。

;;;===== AutoLoad LISP Applications ===== ... (autoload "dline" '("dline" "dl")) ...

これはリストの中にあるDLINEとDLはDLINE.LSPの中で定義されたコマンド名である。 ユーザがDLINEまたはDLというコマンドを最初に使用したときにDLINE.LSPファイルを ロードするように指示している。 以前はこのような機能は簡潔に次のように記されていた。

(defun C:DL () (load "DLINE")(C:DL))

実際の定義はエラー処理を考慮すると、もっと複雑になる。

この関数の最初の呼び出しによって、この関数はロードされたプログラムの中の 定義に書き換えられてしまう。

オートローディングの利点:
起動処理が早くなる。あなたは必要なすべてのLISPファイルを起動時にロードする 必要がなくなるからだ。あなたは単純な上の例にあるようなラッパーを定義 するだけでよい。これは(autoload)関数の呼び出しだけで済む。

少ないメモリで済む

オートトーディングのよくない点:
あなたのプログラムでエラーが起きたときに、無限ループに陥ることがある。 その場合、スタックオーバーフローかCtrl-Cによる中断でしか止められない。
注意: acompでコンパイルするとCtrl-Cも聞かなくなってしまう 呼び出すときはどこかにコンパイルしていない(princ)を挿入すること

あなたはあなたのプログラムのすべてのコマンド名をオートローダ定義の部分で 定義し保守する必要が生じること。Lispのファイル名やコマンド名の変更が、 先ほどのエラーを引き起こす原因になる

どこに(autoload)定義を書くべきか?
ACADR13.LSPには置くべきではない 私たちは初期処理用のファイルを別に用意することが望ましいと考える。 ACAD.LSPにそれをおくのはよくない。なぜならACAD.LSPはしばしば別の アプリケーションによって書き換えられてしまうためと、ACAD.LSP自身は 小さくしておくべきだからである。

その代わりにAUTOLOAD.LSPないしINIT.LSPというファイルを用意し、それを ACAD.LSPからロードさせることが望ましい。 このことについては[11]も参考のこと。

ユーザはACADR13.LSPを修正するのは望ましくない。(ACADR12.LSPもだ) ACAD.LSPはアップグレードに際し書き換えられることはない。 このファイルは安全に残されることが保証されている。 それに加えて、(私たちがR13c4aパッチで見たように)もしACADR13.LSPが 変更された場合、パッチプロセスは更新されることを拒否するだろう。 thus resulting in program malfunctions.


[13] どのようにして引数の数が変更できる関数を書くか?

AutoLISPではこれは不可能だ。

あなたは全ての引数をリストによって与えることができる。 このようにして:

;;; print a variable number of arguments (of any type) (defun my-princ (x) ;; simple version, for better stuff look at the SDK2: PRINTF.LLB (if (listp x) (mapcar 'princ x) (princ x)))

またはADSARXで関数を定義して、AutoLISPから利用することだ。 そうするとあなたはどのようにでも書くことができるようになる。

(ads-print "Hello " "World " 1 2 3) or even (ads-printf "Hello %s %i %i" "World" 2 3)

Reini UrbanとVladimir NesterovskyのADSで上のような関数を作る方法について 例が載っている。 http://xarch.tu-graz.ac.at/autocad/ads

AutoDeskへの公式な要望として、頭に&をつけた引数は省略可能にできるよう にAutoLISPの言語を拡張してほしいと希望したが、R14でも実現していない。


[14] どのようにしてスタックオーバーフローを禁止させるか?

AutoLISPではスタックサイズはソフトウェア自身によって決められている。 スタックサイズは拡張することはできない。しかしそのサイズは大抵の用途なら十分 まかないきれるはずである。
もっとも多いスタックオーバーフローエラーはあなたのプログラムエラーによって 起こる。無限ループにおちいったり、大きなリストに対して再帰関数をつかったとき などだ。200を超える要素を持つリストに対して再帰関数をしないようにしたほうが よい。

ローカル変数を再帰関数の中で使用してもスタックサイズの軽減にはならない。 APPLYやEVALやMAPCARを再帰的に使うのもいけない。なぜならそれらはスタックを 多く使うからだ。Tail recursionを使っても役に立たない。

あなたは再帰関数を繰り返しのものに変更するほうがよいだろう。 (これは数学的なセオリーである。すべての再帰関数は繰り返しに変換する ことができる、Tail recursionのものは自動的に繰り返しになる) 繰り返しを使ったものは、スタックを(push)や(pop)を使ったように消費していく しかしこれらのスタックはヒープから確保される。(ヒープとはAutoLISPのノード 空間のことだ)このサイズはあなたの使用可能な仮想メモリの量の制約しか 受けない。

あなたはスタックオーバーフローをこの簡単な関数でテストできる

;;; create a list of n numbers (zero based) (defun intlst (l n) (cond ((zerop n) l) (T (intlst (cons (1- n) l) (1- n))))) and try: (setq n 100)(while (intlst nil (setq n (+ 10 n)))(print n)) R12のDOS版のAutoLISPでは、スタックの限界に(intlst nil 138)で届いた。 R13のWin版では(intlst nil 240)で、acomp bi4では(intlst nil 1240)だった。 Vital Lisp IDEでは(intlst nil 984)であった。 Vital Lisp ランタイムではスタックサイズは制限がなくなる
R10c10という最初のDOS-EXPANDERを使ったものでは、あなたはLISPSTACK環境変数に よってスタックサイズを拡張することができた。R10のacompではCOMPSTACKがあった。 これは今では利用できなくなっている

繰り返しを使うプログラムで同様の結果を得るには:

(defun intlst (n / l) (repeat n (setq l (cons (setq n (1- n)) l)))) ;変だがきちんと動きます 物理的にスタックサイズを拡張する方法としては、acompかかVital Lispを使うと いった方法に限られる。(Vital Lispは[5]を見て)


[15] (command "ROTATE3D")が動作しないのはなぜ?

いくつかのコマンドはAutoCADの内部コマンドではありません。 それらはC:から始まる単純なAutoLISPコマンドであったり、 ADSによって定義されたコマンドであったりします。 ARXで作成したアプリケーションだけが真のコマンドを提供できます。

これらのコマンドのすべてのリストはACADR13.LSPのオートロード部分に 定義されています([12]も見てください)
これらのコマンドは(command "ROTATE3D")ではなく、 (C:ROTATE3D)のようにして呼び出してください。

しかしながらADS関数はオプションの引数を利用できる場合があります。 詳しくはカスタマイズガイドを見てください。
たとえば(c:rotate3d ss p1 p2 angle)というのが有効です。 (rotate3d ...)というのも有効です。


[16] Lispプログラムを複数の図面にわたって実行させるには

"私はLispファイルに問題があります。図面を開いて実行を続けます。 いったん新しい図面がオープンされるとLispファイルはAutoCADのメモリから 取り除かれてしまいます。それは再ロードとコマンドの認識が必要という ことです。"
LISPメモリは基本的に図面を開くたびに再ロードされます。 以下はLISPを複数の図面に対して実行させる方法です。
  1. スクリプトを使って、複数のファイルに対して実行する。 MYSCRIPT.SCR. (load "mylisp") _QSAVE _OPEN !nextdwg (load "mylisp") _QSAVE _OPEN !nextdwg ...
  2. RunLispやDDSCRIPTといったサードパーティソフトウェアを利用する
  3. R14には'LISPの常駐'といった新しい機能がある
    基本設定コマンドの互換性で設定可能
  4. Vital LispはLispの常駐と同じように動作する変数を独自に用意している
    (setq *VILL-NEW-FULL-INIT* nil) ;keep symbols between sessions


第2部: 例題とコード


[20] 一般的な役に立つ関数について

他のLisp処理系のような基本的なリストや文字列についての無料のライブラリ は今でも存在しません。あなたはみずからこれらを集める必要があります。 [1]で示したAutoLISPのサイトや [1.2]で示したAutoDESKのSDKには有益なプログラムがあります。

私はここにとても使いやすい役に立つ関数を収めました。ネット上で短い サンプルコードの答えとして用意した関数です。
あなたはこれらの関数は共通の知識として受け取ることができます。 有名なDXF関数として、それは次のように定義されます。
(defun dxf (grp ele) (cdr (assoc grp ele))) それからエンティティ名や、図形の仮想配列のどちらにも利用できる (getval)関数を紹介します。

[20.1] List操作

リスト操作で役立つ関数といえばこのようなものがあります ;;; CONSP - リストが空でないことを確認 (defun consp (x) (and x (listp x))) ;;; POSITION - リストの最初の要素が現れる位置を返す ;;; 最初は0で、nilは要素が存在しない ;;; (position x '(a b c)) -> nil, (position b '(a b c d)) -> 1 (defun position (x lst / ret) (if (not (zerop (setq ret (length (member x lst))))) (- (length lst) ret))) ;;; REMOVE - リストから要素を削除する(重複する要素も削除できる) ;;; (remove 0 '(0 1 2 3 0)) -> (1 2 3) (defun remove (ele lst) ; (c) by Serge Volkov (apply 'append (subst nil (list ele) (mapcar 'list lst)))) ;;; REMOVE-IF - 平らなリストからの条件付き削除 ;;; 引数のfun 関数名は引数を1つしか使わないものに限る ;;; (remove-if 'zerop '(0 1 2 3 0)) -> (1 2 3) ;;; (remove-if 'numberp '(0 (0 1) "")) -> ((0 1) "") (defun remove-if (fun from) (cond ((atom from) from) ;nil or symbol (return that) ((apply fun (list (car from))) (remove-if fun (cdr from))) (t (cons (car from) (remove-if fun (cdr from)))) ) ) ;;; REMOVE-IF-NOT - 条件に適うすべての要素を残すものです ;;; これは再帰的に定義する必要はありません (defun remove-if-not (pred lst) ; by Vladimir Nesterowsky (apply 'append (mapcar '(lambda(e) (if(pred e)(list e))) lst))) ;;; ADJOIN - 要素がリストになければ追加します ;;; ウラ技: クォートされたリストでも利用できます。こんな感じのもの ;;; (setq l '(1 2 3) (adjoin 0 'l) ;;; -> !l (0 1 2 3) (defun adjoin (ele lst / tmp) (if (= (type lst) 'SYM) (setq tmp lst lst (eval tmp))) (setq lst (cond ((member ele lst) lst) (t (cons ele lst)))) (if tmp (set tmp lst) lst) )
  ;;; ROT1 - 最初の要素を最後にまわします。
  ;;; 単純なものです
  ;;;        (rotate by one)
  (defun rot1 (lst) (append (cdr lst) (list (car lst))))

  ;;; BUTLAST - 最後の要素を除いたリストを返します
  (defun butlast (lst)
    (reverse (cdr (reverse lst))))

[20.2] 文字列操作

文字列操作で役立つ関数といえばこのようなものがあります:
それらは http://xarch.tu-graz.ac.at/autocad/code/vnestr/strtok.lsp か、あなたの AI_UTILS.LSP の中にあります。あなたはDCLを使うときに、これら の関数を重宝するでしょう。

[20.3] シンボルを文字列に変換する

(read)の逆関数は(symbol-name)となるでしょう。 なぜそうなのかは聞かないでほしいが、それは次の定石しかない: ;;; SYMBOL-NAME - シンボル名を文字列として返す ;;; どんなLisp表現でもその画面表示の表現に変換する ;;; (symbol-name a) -> "a", (symbol-name '(0 1 2 a)) -> "(0 1 2 A)" (defun symbol-name (sym / f str tmp) (setq tmp "$sym.tmp") ;temp. filename, should be deleted (setq f (open tmp "w"))(princ sym f) (close f) (setq f (open tmp "r") str (read-line f) f (close f)) str ) 純粋なシンボルを文字列に変換する方法についてはChristoph Candidoが ウラ技を紹介している http://xarch.tu-graz.ac.at/autocad/news/symbol-string.txt

[20.4] AutoCADのエンティティを操作する

;;; エンティティの最初のDXFグループコードの値を返す ;;; 有名な(dxf)関数と同じ機能、しかしこれはすべての図形の表現 ;;; を渡しても機能する(図形名,entgetが返すリスト,entselが返すリスト) ;;; 注意: LWPOLYLINEの頂点(DXF=10)を得るには使えない! (defun GETVAL (grp ele) ;どんな図形表現を渡してもよい (cond ((= (type ele) 'ENAME) ;eleが図形名のとき (cdr (assoc grp (entget ele)))) ((not ele) nil) ;eleがnilのとき ((not (listp ele)) nil) ;eleがおかしな時 ((= (type (car ele)) 'ENAME) ;entselが返すリストのとき (cdr (assoc grp (entget (car ele))))) (T (cdr (assoc grp ele))))) ;entgetが返すリストのとき ;;; 例:図形の種類を返す (gettyp pline) => "POLYLINE" (defun ENTITY (ele) ;図形名に変換する (cond ;次の種類について処理する ((= (type ele) 'ENAME) ele) ; 図形名ならそのまま返す ((not (listp ele)) nil) ; リストでなければおかしいのでnil ((= (type (car ele)) 'ENAME) (car ele)) ; entselが返すリストのとき ((cdr (assoc -1 ele))) ; entgetが返すリストのとき ) ) ;;; 図形名を返す ;;; いくつかのエンティティの表現から図形名を返す (defun ENTITY (ele) ;convert to element name (cond ;accepts the following types: ((= (type ele) 'ENAME) ele) ; ENAME ((not (listp ele)) nil) ; error: no list ((= (type (car ele)) 'ENAME) (car ele)) ; entsel-list ((cdr (assoc -1 ele))) ; entget-list or nil ) ) ;不具合を修正したgetval (defun getval (grp ele) (cdr (assoc grp (entget (entity ele))))) ;;; 例: (istypep ele "TEXT") ;;; データは塗りつぶし図形"SOLID"かどうかを判定 (defun istypep (ele typ) ;check type (= (gettyp ele) typ)) ;;; 例: (istypep ele '("TEXT" "ATTDEF")) ;;; データは文字ないし属性定義か? (defun ISTYPEP (ele typ) ;引数にリストも使えるほうが便利だろう (cond ((listp typ) (member (gettyp ele) typ)) ;bugfixed ((stringp typ) (= (gettyp ele) typ)) ;assume typ uppercase (T nil))) ;;; 例: (getpt (entsel)) => ( 0.1 10.0 24) (defun GETPT (ele) ;どんな図形種類でも始点を返す (getval 10 ele)) ;始点はDXFコード10である ;;; 例: (getflag pline) => 閉じたポリラインなら1を返す (defun GETFLAG (ele) (getval 70 ele)) ;図形フラグを返すのと同じ ;;; 図形フラグの特定のビットがたっているか? ;;; Ex: (flagsetp 1 pline) => 閉じたポリラインはTを返す ;;; Ex: (flagsetp 16 vertex) => スプライン曲線の制御点であればTを返す (defun FLAGSETP (val ele) (bitsetp val (getflag ele))) ;;; Ex: (bitsetp 4 12) => T ;あるデータ(12)のビットフラグ(4)が立っているか (defun BITSETP (val flag) (= (logand val flag) val)) ;;; 選択セットをリストに変換する ;;; 記事: ai_ssgetを使用することも検討してください。ai_ssgetは ;;; 図形にロックがかかっているかどうかをチェックしてくれる ;;; 例: (sslist (ai_ssget (ssget))) => ロックされていない図形のリストを返す ;;; or (mapcar 'entupd (sslist (ssget "X" '((8 . "TEMP"))))) ;;; - TEMP画層のすべての図形の再描画をかける (defun SSLIST (ss / n lst) (if (= (type ss) 'PICKSET) (repeat (setq n (sslength ss)) (setq n (1- n) lst (cons (ssname ss n) lst))))) ;;; 選択セットのそれぞれの図形に特定の関数を実行させる ;;; 実行は逆順である、処理は早いが、その分理解しにくい ;;; [22.2]も見てください ;;; 例: (ssapply 'entupd (ssget)) ; いくつかの図形のみ再描画 (defun SSAPPLY (fun ss / n) (if (= 'PICKSET (type ss)) (repeat (setq n (sslength ss)) (apply fun (list (ssname ss (setq n (1- n))))))))


[21] Lispプログラムの例:

[21.1] 文字列をまとめて変更する,ポリラインや画層や日付について

AutoCADのサンプルディレクトリの中にあるCHTEXT.LSPは文字のプロパティを まとめて変更できる

ポリラインの属性をまとめて変更したり、選択した図形の所属する画層をフリーズ したり、他の似たような処理を行わせるには、いろいろなAutoLISPのサイトにある 無料のツールを探してください。 [1][22], [23][24]を参照してください。

日付を書き込んだり、自動的にその他のものを図面に追加したいときには しかもプロッタがHPGL/2言語をサポートしている場合には、AutoCADが用意した HPGL/2ドライバを使用し、HPCONFIGコマンドで日付を図面につける設定をするとよい

DATESTAMP.LSP: 図面のヘッダの属性を自分自身で変更するためのプログラム が[22.2]にあります。 それは http://ourworld.compuserve.com/homepages/tonyt/plotstmp.htm にあります。

[21.2] Lispを使って印刷設定ダイアログを操作する。DDEを使う

AutoLISPより印刷設定ダイアログボックスを呼び出すのは、Windows環境だけが 可能である。Mike Dickasonが書いたLISPPLOTを使います。これはキー入力を キーボードバッファに送りだします http://www.cadalog.com/cadalog/files/lispd-l/lspplw.zip または、 ftp://ftp.mcwi.com/pub/mcwi/lisp/winplt.lsp
別の方法ではスクリプトを作成し、それをあなたのリスプの最後で呼び出すように して実行します。これはダイアログボックスを表示させることはできません

Xiang Zhu: あなたはWindows版のR12とR13ではddelisp.exeを次のようにして何かの処理をさせることができます:

(defun DDECMD (str / tmp) (if (not initiate) (xload "ddelisp")) (if (not (zerop (setq tmp (initiate "autocad.r13.dde" "system")))) (progn (execute tmp (strcat "[" str "]")) (terminate tmp) str)))) R12ではサーバー名に"autocad.dde"を利用します。それから、あなたが作成 したLISPやスクリプトの中で、(ddecmd "_plot ")を実行させます。 DDECMD関数は何か問題があるか、キーボードからコマンドプロンプトに対して 入力したものをうまく送れたときにnilを返してくれます。 それから空白や改行を必要とする場合には"^13"を文字列の最後につけて ください。

さて、この関数は次の状況において非常に便利なものです: もしLISPプログラムの中で、AutoCADの割込み可能名コマンド、たとえばLAYER などを呼び出したいとき、通常は(command "_layer")と使います。 しかし、この行を使ってしまうと、あなたの作ったLISPプログラムは割り込みで きないものになってしまいます。DDECMDを使うことで、割り込み状態で使いたい という問題を解決できます。

ただし ACADはDDEコマンドをコマンドラインが利用できるときしか受け取れません。 つまりAutoCADのダイアログボックスが開いていないときしか利用できません。

[21.3] (command "_LAYER"...)を使わないで(entmod)や(entmake)で画層を扱う

画層にENTMODを使う
LISPプログラムの中でCOMMAND関数を使わないで画層のプロパティを変更できないか 挑戦してみました。

R13では次のリスプを使ってできました。

(setq tbl_lst (entget (tblobjname "LAYER" "ANY_LAYER")) clr_grp (assoc 62 tbl_lst) ) (entmod (subst (cons 62 (- (cdr clr_grp))) clr_grp tbl_lst)) あなたはANY_LAYERを表示Onや表示Offに切り替えることができます。 ANY_LAYERが現在層であっても可能です

しかしAutoCADは画層テーブルが変更されたことをあなたがツールバーなどにある 画層管理コントロールをクリックするまではわかりません。 つまり、割り込みでDDLMODESを画層の表示切り替えをしたときと同じです
同じようにして画層をフリーズすると、あなたは画面ではそれらの画層に書かれた 図形は表示されたままになっています。しかしそれを選択することはできません。 その状態は画層の設定に関係する操作をAutoCADのコマンドで行うまで続きます。 AutoCADで画層の設定に関係する操作を行ってはじめて、これらの図形を非表示に します。

画層にENTMAKEを使う
あなたはentmakeの引数として渡す仮想リストに、テーブルオブジェクト名を かならず使う必要があります。 画層のテーブルオブジェクト名はTBLOBJNAME関数を使って読み出せます。: (entget (tblobjname "LAYER" "ANY_LAYER_NAME")) ;;; このプログラムはあなたが入力した画層名で画層を作成する (defun c:mlay () ; by Reinaldo Togores <rtogores@mundivia.es> (setq laynam (getstring "\nLayer name: ")) (entmake (list '(0 . "LAYER") '(5 . "28") '(100 . "AcDbSymbolTableRecord") '(100 . "AcDbLayerTableRecord") (cons 2 laynam) '(70 . 64) '(62 . 7) '(6 . "CONTINUOUS") ) ) )
[21.4] Lispで複数のファイルを選択するには? (FILES-Unlockとして)

http://xarch.tu-graz.ac.at/autocad/progs/MGETFILD.ZIP はDCLで複数のファイルを選ぶための便利なプログラムです。
McNeelよりDOSLIBを入手してください。DOSLIBはDOSで行うようなディレクトリ 操作を行う関数です。入手先は、 http://www.mcneel.com/mcneel/doslib.htmlです。 (訳注.R14の各国語版にはDOSLIBはついています)

[21.5] 複数のブロックを置換する

ヒントを元にISPプログラムを検索することができます:
Cadalyst: http://www.cadonline.com/search.phtml
=> 97code.htm それから無料で自動的に検索してくれます。
xarch: http://xarch.tu-graz.ac.at/autocad/code で。"BLOCK;REPLACE"で検索します。
=> http://xarch.tu-graz.ac.at/autocad/code/cadalyst/94-02/replace.lsp
Cadalogでも探すことができます:
http://www.cadalog.com/find.htm キーワードに"Block Replace"と指定します。
=> http://www.cadalog.com/cadalog/files/lispr-z/replace.zip (これがもっともよいものです)

[21.6] (vports)関数,VIEWPORTエンティティ,ピクセルの変換
VIEWPORTエンティティ:
答えは"VIEWPORTの図形名で(entget)したリストから、左下点(DXFコード=10)と 右上点(DXFコード=20)を入手できる。しかしこれらの座標はペーパー空間座標系 で表現されています。私が探していたものは現在ビューポートが表示している 実際の範囲(モデル空間の範囲)でした。それは http://xarch.tu-graz.ac.at/autocad/news/vports.lsp でわかりました。

AutoLISPでビューポートを変更するには (setvar "CVPORT" vport-id)を使います http://xarch.tu-graz.ac.at/autocad/news/change_vports.html

を見てください。 次の関数はピクセルと作図の単位の変換を行います。

;;; ピクセルを作図の単位に変換する (defun PIX2UNITS (pix) (* pix (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE"))))) ;;; 作図の単位をピクセル数に変換する (defun UNITS2PIX (units) (* units (/ (cadr (getvar "SCREENSIZE"))(getvar "VIEWSIZE"))))

[21.7] すべての表示できるオブジェクトを選択する: ズーム座標
(ssget)は表示されているオブジェクトしか選択できません。 なぜなら、(entsel,ssget,osnap)といった関数は画面を元に動作しているからです (ssget "X")なら表示されていないオブジェクトも選択することができます ;;; ビューポートのWCSでの頂点のリストを返す (defun ZOOMPTS ( / ctr h screen ratio size size_2) (setq ctr (xy-of (getvar "VIEWCTR")) ;3D -> 2D h (getvar "VIEWSIZE") ;real screen (getvar "SCREENSIZE") ;2D: Pixel x,y ratio (/ (float (car screen)) ;aspect ratio (cadr screen)) size (list (* h ratio) h) ;screensize in coords size_2 (mapcar '/ size '(2.0 2.0))) (list (mapcar '- ctr size_2) (mapcar '+ ctr size_2))) (defun XY-OF (pt) (list (car pt)(cadr pt))) ;assure 2D coords 記事: エンティティからの座標値はWCSで返ります。これはまぁいいでしょう。 なぜならssget関数で"CP" "WP" "P"オプションを使うときはWCSを使います。 ("W" "C"オプションはUCSが必要です - なぜ違うのかは私にはわかりません) ;;;この関数の定義の方法 (defun SSALL-VISIBLE (/ l) (ssget "C" (car (setq l (maptrans0-1 (zoompts)))) (cadr l))) ;;; 別の方法 (defun SSALL-VISIBLE-1 () ;combine "C" and (p1 p2) to one list (apply 'ssget (append '("C") (maptrans0-1 (zoompts))))) ;;; いくつかの点をUCSからWCSに変換します 1つの引数で済む方法です (defun MAPTRANS0-1 (pts)(mapcar '(lambda (pt)(trans pt 0 1)) pts))
[21.8]選択した図形のXYZデータをどのようにしてファイルに書き込むか?

;;; CDF - カンマ区切り文字にする (defun cdf-point (pt) (strcat (car pt) ", " (cadr pt) ", " (caddr pt))) ;;; SDF - 空白区切りにするAutoCADに読ませるのはより簡単になる (defun sdf-point (pt) (strcat (car pt) " " (cadr pt) " " (caddr pt))) ;;; 上の空白区切りの座標値をAutoCADに点リストとして戻す方法 (defun str->point (s) (eval (read (strcat "(" s ")")))) ;;; 選んだ図形のすべてのXYZ値をファイルに書く (defun C:XYZ (/ ss fname f) (if (and (setq ss (ssget)) (setq fname (getfiled "Write XYZ to file" (strcat (getvar "DWGNAME") ".XYZ") "XYZ" 7)) (setq f (open fname "w"))) (foreach ele (sslist ss) ; -> [20.4] (foreach pt (getpts ele) ; -> [23.1] (write-line (cdf-point pt) f) ) ) ) (if f (close f)) ) ;;; => <fname>.xyz ;;; 0.45, 12.3, -34.0 すべてのXYZ値を空白区切りのテキストファイルにするのは簡単な変更ですむ

テキストのX,Y値が入ったファイルからポリラインを作成するのにもっともよい方法は 次のようなスクリプトファイルにしてしまうことだ:

PLINE 300.2,10 350.4,10.4


[22] ブロック属性

[22.1] ブロック属性にアクセスするには?
ブロック挿入図形(INSERT)の後のすべての従属エンティティをチェックすると、 属性が見つかる。 http://www.autodesk.com/support/techdocs/acadcdi/td300518.htm ->"AutoLISPを使った複合エンティティや従属エンティティの読み出しかた" も参照のこと ;;; 図形リストの中の属性名attnameで示した属性の図形リストかnilを返す関数 ;;; or nil if not found (defun ATTELE (ele attname / rslt) (if (and (istypep ele "INSERT") (= (getval 66 ele) 1)) (progn (setq ele (entnext (entity ele))) (while (istypep ele "ATTRIB") (if (= (strcase (getval 2 ele)) (strcase attname)) (setq rslt (entget ele) ele nil) ;break the loop (setq ele (entnext ele)))))) rslt ) ;;;例: (attele (entsel) "TEST") ; ブロック挿入図形が属性名"TEST"が ; 定義されていればそれを返す ところで: Vladimir Nesterowskyが作ったGETとEDLGETENTはDXFのグループコード を得る風変わりな関数である ;;;使い方の例 ;;; 2,1,-1グループの値を返す (defun GET-ATTRIBS-LOOK-UP( block-ename ) (get '(2 1 -1) (cdr(edlgetent block-ename)))) (defun ALL-VERTICIES-AND-BULGES( pline-ename ) (get '(10 42) (cdr(edlgetent pline-ename)))) GETとEDLGETENTは http://xarch.tu-graz.ac.at/autocad/code/vnestr/から入手できる。

[22.2] ブロック属性を変更するには? DATESTAMP
前出の(attele)関数から返されたリストは単純にentmodしてよい。 ;;; 属性値をnew引数の内容に変更する (defun ATTCHG (ele attname new / b) (if (setq b (attele ele attname)) (entmod (subst (cons 1 new) (getval 1 b) b)))) ;;; 挿入されたPLOT*ブロックのすべてのDATESTAMP属性を更新する (defun C:DATESTAMP () (ssapply ;fixed by Alan Williams, wrong arg order '(lambda (ele) (attchg ele "DATESTAMP" (today)) (entupd ele) ) (ssget "X" '((0 . "INSERT")(2 . "PLOT*"))))) ;;;今日の日付を返す。DIESELでもこの文字列変換でも日付の文字列に変換できる (defun TODAY (/ s) (setq s (rtos (getvar "CDATE") 2)) ;ジュリアン日付を得る (strcat (substr s 5 2) "-" (substr s 7 2)"-"(substr s 3 2)))
[22.3] ブロック属性を更新するには?
SUPPORTにあるATTREDEF.LSPは、すでに挿入されているブロック挿入図形の属性の プロパティを更新するものである。

複合図形において、entupd関数を主エンティティに実行しなければ、 変更結果を画面で確認することができない。(図形の再作図を行う)

;;; 例: (setq s (getstring "Change Attribute to: ")) (attchg (attele (setq b (entsel "of block: ")) s))) (entupd (car b)) ; ブロック図形に対して行う ;;; 頂点や属性から主エンティティを入手する便利な関数 ;;; (defun MAIN-ENTITY (ele) (setq b (entity b)) ;force ENAME (while (istypep b '("ATTRIB" "ATTDEF" "VERTEX")) (setq b (entnext b))) ;従属図形のある限り (if (istypep b '("SEQEND" "ENDBLK")) (getval -2 b) ;ヘッダを得る b ;複合図形でなかった ) )

[22.4] AutoLISPで属性を含む複雑なブロックを(entmake)で作成するには?>
http://www.autodesk.com/support/techdocs/acadcdi/td300515.htm を見てください。

これは(entmake)関数を複数回呼び出して属性を含む複合エンティティをどのように して使うかを示した例題です。 ブロックヘッダを作成し、図形要素を作成し、ブロックの終端を作成します。 それから、ブロック挿入図形を作成しています。

無名のブロックを作成するには次のようにします。 (setq bn (entmake '((0 . "ENDBLK")))) そのブロック名を得るには次のようにします。 (entmake (list '(0 . "INSERT")(cons 2 bn) ...))


[23] ポリライン

R14のLWPOLYLINEは複数の頂点を1つのエンティティに収納できるようになった。
[23.1] ポリラインの頂点へのアクセスの仕方 [R14で変更]
ポリラインの頂点(VERTEX)はポリライン図形(POLYLINE)の従属図形である。 (INSERTにおけるATTRIB,BLOCKにおけるATTDEFと同じである) したがって[22.1]-[22.3]にある同じような関数が利用できる。 ;;; リストの中の同じassocの値を複数返す(LWPOLYLINE用) (defun GROUP-ONLY (grp lst) (mapcar 'cdr (remove-if-not '(lambda(pair)(= grp (car pair))) lst))) ;;; ポリラインや他の図形の頂点のリストを返す ;;; [22.1]にあったedlgetentを使う (defun GETPTS (ele / pts) (setq ele (entity ele)) ;図形名にする (cond ((istypep ele "POLYLINE") (while (istypep (setq ele (entnext ele)) "VERTEX") ;; フィットカーブやスプラインの制御点を除く(昔の方法) (if (not (or (flagsetp 1 ele) (flagsetp 8 ele))) ;bugfix! (setq pts (cons (trans (getpt ele) ele 0) pts))) (reverse pts))) ;; 特例: assocは最初の一つのデータを返すだけである ;; R14のLWPOLYLINEの不具合を修正: 内部では2D点として保管されている ;; (entget)はいい加減なZ値を返す ((istypep ele "LWPOLYLINE") (mapcar '(lambda(pt)(trans (list (car pt)(cadr pt) 0.0) ele 0)) (group-only 10 (entget ele)))) ;; 他の図形種類の処理を追加した ((istypep ele '("TEXT" "CIRCLE")) (list (getpt ele))) ;; 他の図形種類の処理(serge's way) (T (apply 'append (mapcar '(lambda (n / p) (if (setq p (getval n ele)) (list p))) '(10 11 12 13))) ) ;; 他の図形種類の処理(昔の方法) ;;(T (foreach n '(10 11 12 13) ;; (if (setq p (getval n ele)) (setq pts (cons p pts)))) ;; pts ;;) ) ) 別の頂点の構造に関するVladimir Nesteroswkyの提案 [22.1]も見てください。 (defun VERTICES-AND-BULGES (pline-ename) (mapcar 'cdr (remove-if-not '(lambda (ele) (bitsetp 9 x)) (get '(70 10 42) (cdr (edlgetent pline-ename)) => ポリラインのグループコード10と42をリストにした

ポリラインのエッジに付いては[23.5]も見て下さい。

[23.2] 複数の線分をポリラインに結合する方法 [修正しました]
選択した図形要素を結合しようとしたが、すでに結合されたものは結合する ことはできない、なぜなら、結合のときに図形削除されるからである。 ;;; この例はすべての選択した図形要素をポリラインに変換し、 ;;; これからも結合に使えるようにしたものである (defun C:JOINPOLY (/ ele ss) (foreach ele (sslist (setq ss (ssget))) ;よりよいリスト処理 (if (entget ele) ;すでに結合したものでなければ (cond ;(結合済みならnilを返す) ((istypep ele '("ARC" "LINE")) ;; 実際にはここで線のZ座標やUCS座標をチェックすべきだ (command "_PEDIT" ele "_Y" "_J" ss "" ""); 変換と結合 ) ((and (istypep ele '("POLYLINE" "LWPOLYLINE")) ;bugfix (not (flagsetp 1 ele)) ;閉じていなければ (< (rem (getflag ele) 128) 8)) ;メッシュは無視する (command "_PEDIT" ele "_J" ss "" "");UCSのチェックをしていない ) ) ) ) )
[23.3] 複数のポリラインの幅を変更する方法
今までに紹介した関数を使うと、これは短いものになる: (defun C:POLYWID (/ wid ele) (initget 5)(setq wid (getdist "New Polyline Width: ")) ;負の値をとらない (foreach ele (sslist (ssget '((0 . "*POLYLINE")))) ;ポリラインのみ選ぶ (command "_PEDIT" ele "_W" wid "")))
[23.4] ポリラインやスプラインを(ENTMAKE)や(COMMAND)で作成する方法
  1. LISPプログラムを使ってスクリプトファイルを作成し、それを実行させる。 これはもっとも簡単な方法のようだが、スクリプトの読み書きにI/Oエラーが おきる可能性がある、もし商用のソフトなら、エラー処理を行うこと。
  2. 2つめの方法はENTMAKE関数を使って図形を作成すること 利点: 早い,WCSで処理できる,現在設定されているOスナップに影響されない
    http://www.autodesk.com/support/techdocs/acadcdi/td300510.htmを見なさい。
  3. 3つめの方法はcommand関数とmapcar関数によるもの。これはポリライン、 スプライン、複数の線分に利用できる。欠点はUCSで処理することとOスナップの影響 を受けること ;;; POLYLINEを点のリストから作図する(スプラインや線分でも同じ) ;;; 現在のUCSの設定とOスナップの影響を受ける (defun DRAW-PLINE (pts) (command "_PLINE") (mapcar 'command pts) (command "")) (defun DRAW-SPLINE (pts) (command "_SPLINE") (mapcar 'command pts) ; 点はフィット点に限る (command "" "" ""))

[23.5] ポリラインの長さを計算する方法 [新しい関数]
2つの方法がある:
  1. AREAコマンドを使う方法。画面に結果が表示されるのでとてもうっとおしい。 しかしスプラインも計測できる ;;; 全ての選択した図形の長さの合計を求める。 ;;; 最後の行を(getvar "AREA")にすれば面積の合計ができる (defun C:LEN-OF () (command "_AREA" "_A" "_E") ;R12+13の加算オプションを使う (ssapply 'command (ssget)) ;選択した図形をAutoCADに渡す (command "" "") ;リターン2回でAREAコマンドを抜ける (getvar "PERIMETER")) ;長さの合計を表示させる
  2. ちょっと計算させる。ただし単純な図形に限る。これは今までの関数を使った もっともよいやり方。次の節[24]の前振りにもなっている。 湾曲している線の長さも求めている。

    ;;; ポリラインの長さを求める。静かだ。 (defun POLY-LENGTH (poly / seg) (apply '+ ; 全ての部分の長さの合計を求める (mapcar '(lambda (seg) ;1つの部分の長さ (if (zerop (car seg)) ;まっすぐか (distance (cadr seg) (caddr seg)) ;真っ直ぐなときの長さか (abs (arclen seg)))) ;曲がったときの長さ[24] (pline-segs poly)))) ;それぞれの点のリストを持つ(膨らみ p1 p2) ;;; 複合図形(頂点や属性)のすべてのグループコードをリストとして返す ;;; (edlgetent)と同じ (defun CPLX-LIST (grp ele / lst) (if (= 1 (getval 66 ele)) (progn (setq ele (entnext (entity ele))) (while (and ele (not (istypep ele "SEQEND"))) (setq lst (cons (getval grp ele) lst) ele (entnext ele))) (reverse lst)))) ;;; PLINE-SEGS - ポリラインの図形名からそれぞれの頂点間の長さを求めるための ;;; リストを作成する'(bulge p1 p2). 直線では膨らみは 0.0である ;;; 図形名の図形座標系の頂点リストを計算する ;;; LWPOLYLINEにも使えるようにした (defun pline-segs (pname / pts segs) (setq segs (mapcar 'list (if (istypep pname "LWPOLYLINE") (group-only 42 (entget pname)) (cplx-list 42 pname)) (setq pts (getpts pname)) ; ->[23.1] (rot1 pts))) ; ->[20.1] (if (flagsetp 1 pname) segs ;閉じている (butlast segs))) ;開いている 最後のセグメントはない ->[20.1] ;;; 例: (a bit optimized for brevity :) ;;; 選択したすべてのポリラインの長さの合計を求める。静かである。 ;;; 他の図形も利用できるためには、pline-segs関数にそれらの処理を追加する (defun C:POLYLEN () (apply '+ (ssapply 'poly-length (ssget '((0 . "*POLYLINE"))))))
面積の合計を求めるには、にぎやかなAREAコマンドを使うか、 ヘロンの公式をポリゴン図形に実行することでできる(単純な閉じたポリゴンに対して)

[23.6] ポリラインの方向を反転する方法
Sergei Komarovは円弧の膨らみや線の幅を維持しながらポリラインの方向を反転する REVPOLY.LSPを作成した。それは http://xarch.tu-graz.ac.at/autocad/news/lisp_pro/revpoly.lspにある。


[24] 円や円弧: 膨らみの計算

ポリラインの中の膨らみとは何か?

膨らみとは湾曲している2点がなす角のtan1/4θである。 膨らみ0.0は直線であることを示す 始点と終点と膨らみを使うことで、湾曲している2点のすべての他の必要な 値はすばやく計算することができるので、膨らみは効果的な情報である。

    円弧の長さ= 半径*角度
    膨らみ    = tan(角度/4)           (反時計周り: +, 時計周り: -)
    角度      = 4*atan(膨らみ)
    膨らみ    = (2*弧の長さ) / 弦の長さ  (反時計周り: +, 時計周り: -)

http://www.autodesk.com/support/techdocs/lisp/fax797.htmも見てほしい。

サンプルプログラムは"Maximizing AutoLISP" [2]にもある。

(不具合修正した。式に問題があった。Sergei Komarovに感謝)

;;; SEG2CIR - ポリラインの膨らみ情報(bulge pt1 pt2)を円(ctr rad)に変換する ;;; 円弧の開始角と終了角は次のようになる(angle ctr pt1)(angle ctr pt2) ;;; 直線の情報のときはnilを返す (defun seg2cir (seg / bulge p1 p2 cot x y rad dummy) (if (zerop (car seg)) ;直線のときは、円にならない nil (setq bulge (car seg) p1 (cadr seg) p2 (caddr seg) cot (* 0.5 (- (/ 1.0 bulge) bulge)) x (/ (- (+ (car p1) (car p2)) (* (- (cadr p2) (cadr p1)) cot)) 2.0) y (/ (+ (+ (cadr p1) (cadr p2)) (* (- (car p2) (car p1)) cot)) 2.0) rad (distance (list (car p1) (cadr p1)) (list x y)) dummy (list (list x y) rad)))) ; こうしたのはprognが嫌いだから ;;; ARC2SEG - 逆変換 ;;; 円(ctr rad)と開始角・終了角から膨らみ情報を計算する (defun arc2seg (cir ang1 ang2 / p1 p2) (setq p1 (polar (car cir) ang1 (cadr cir)) p2 (polar (car cir) ang2 (cadr cir))) (list (arc2bul p1 p2 cir) p1 p2)) ;;; ARC2BUL - 円弧の膨らみを円弧の点と円(ctr rad)から求める (defun arc2bul (p1 p2 circle / ang) (tan (/ (- (angle (car cir) p2) (angle (car cir) p1)) 4.0))) ;;; BUL2ANG - 円弧の角度を膨らみ情報から返す (defun bul2ang (seg / ctr) (- (angle (setq ctr (car (seg2cir seg))) (cadr seg)) (angle ctr (caddr seg)))) ;;; ARC2ANG ;;; 弦の長さと半径から円弧の角度を計算する (defun arc2ang (chord rad) (* 2.0 (atan (/ chord 2.0 (sqrt (- (expt rad 2) (expt (/ chord 2.0) 2) ) ) ) ) ) ) ;カッコの表記法 ;;; ARCLEN - 円弧の長さ = radius*angle, ;;; 注意: 符号があるので距離を求めるときは絶対値にする必要あり ;;; (abs (arclen seg)) (defun arclen (seg) (* (cadr (seg2cir seg)) ;半径 4.0 (atan (car seg)))) ;角度 = 4*atan(膨らみ) (defun tan (x) (/ (sin x)(cos x))) (defun dtr (ang)(* pi (/ ang 180.0))) ;度をラジアンにする (defun rtd (ang)(/ (* ang 180.0) pi)) ;ラジアンを度にする


[25] DCL: タブや等幅フォントを使ったリストボックス

Windowsでは文字のレイアウトはフォントの幅が一定でないので難しい。

list_boxタイルのtab属性を使ってレイアウトをする方法を考える。たとえば、

tabs = "0 20 40"; and (set_tile "listbox" "Layer:\t0\twhite") また、等幅フォントを使うには次のようにする : list_box { label = "Drawing"; key = "dwglist"; width = 50; fixed_width_font = true; // <- monotext } タブとりルーチンは次を見てください。 http://xarch.tu-graz.ac.at/autocad/news/detab.lsp


[26] EED 拡張データ: 入手と保存の方法

[26.1] (ssget "X")を使って拡張データのついたエンティティを選ぶには ;;; アプリケーション名と区切り文字を定義する(4文字をアプリケーション名 ;;; に割り当てる AAIG, AutoDESK Application Interoperation Guidelines ;;; に準拠して) (setq appname "HUBU-") ;;; 自分が作ったすべてのアプリケーションにマッチさせる名前を定義する (setq allappnames (strcat appname "*")) ;;; eg: HUBU-LIST1, HUBU-LIST2 ;;; 一つの図形から最初の拡張データリストを入手する方法 (defun get-eed-1st (ele) (cdadr (assoc -3 (entget (entity ele) (list allappnames))))) ;;; アプリケーション名typを持つすべての図形の入手兵法 ;;; (アプリケーションにワイルドカードを使ってもよい) (defun ssget-app (typ) ;fast (ssget "X" (list (list -3 (list typ)))) ;;; あなたの定義したアプリケーションのデータを持っている図形だけを取る (defun ssget-hubu (typ) ;早い (ssget "X" (list (list -3 (list (strcat appname typ))))) (ssget-hubu "*") ; 全てのあなたの図形を得る
[26.2] オブジェクトのEEDを得るには

すべての拡張データをチェックするには: (entget (car (entsel)) '("*"))

すべてのアプリケーション名が一致した拡張データを返すものと、拡張データの コードの値が一致したものを返すもの。

;;; GETXDATA - 図形のすべての拡張データリストを得る ;;; ;;; (-3 ("HUBU-1" (1000 ."ASSHATCH")(1002 ."{") ;;; (1070 . 1)(1002 ."}"))) ;;; =>(("HUBU-1" (1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}"))) (defun getxdata (e apnlst) (cdr (assoc -3 (entget e apnlst)))) ;;; GETXDATA-ALL - アプリケーション名を除いたすべてのデータを得る ;;; => ((1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}")) (defun getxdata-all (e apnlst) (apply 'append (mapcar 'cdr (getxdata e apnlst)))) アプリケーション名はここでは捨てられている。これは処理のスピードを上げる 方法である。別のアプリケーションは、別の(1000 . name)によって 分けられる。

図形に拡張データを保存する方法については、XDATA.LSPやXED.LSPの例を見てほしい。

拡張データのトリックについて、ADSのresbufの形式をLispのリスト形式に変換したり、 ADSのresbuf形式に戻すには、 http://xarch.tu-graz.ac.at/autocad/news/eed_retrieval.txt を参考にするとよい。


[27] LISPのなかでコマンドを中断させるには?

"AutoLISPでどのようにして中断させるか?"も参照のこと

引数なしで(command)関数を実行すると、R12のCTRL-CやR13のEscキーをコマンド プロンプトで入力したのと同じように働く。しかしダイアログボックス表示中 には無効である。それから、スクリプトの中でも使えない。 (command nil)は引数なしの(command)と同じである。

(command)はコマンド関数の中断ができるだけだ。 AutoLISPの中で寸法図形コマンド"DIM"を使っているときは、 寸法図形のサブコマンドが終了したあとで(command)による中断をしなければならない。

しかしLisp処理から中断するには(command)ではきちんと動作しない。 (exit)と(quit)関数 - これらは同じ - はLispプログラムをただちに中断する。

例:

(while T ; do ; 無限ループ (princ "\nEnter a=") (setq a (getint)) (if (zerop a)(exit)) ; Lispを中断しコマンドモードに戻る ) この例では(command)は動作しない。(exit)は確かにCTRL-Cとして働く。 (exit)は"error: quit / exit abort"と表示し、すべてのネストされた関数を 表示してくれる。 エラーメッセージを抑制するためには次のエラー処理関数を作成する必要がある: (setq olderr *error* *error* my_error) (defun my_error (s) (if (not (member s ; 英語のメッセージ '("Function cancelled" "console break" "quit / exit abort"))) (princ (strcat "\nError: " s)) ) (setq *error* olderr) )

スクリプトではLispで(cancel)関数を定義する必要がある。これは簡単に、

(defun cancel() (command) (command "resume") ) SCRIPT.SCRでは次のようにする: .. [script commands] (cancel) [more script commands] ..


[28]LISPでACIS内部ジオメトリを解析するには

すべてのACISオブジェクト(3DSOLID)はSpatialによって文書化されている。 しかしながら(entget)によって入手できる内部表現については、今なお 暗号化されている。 しかしこの暗号化の方法はハックされている。(XOR 95)

例とコードについて: http://xarch.tu-graz.ac.at/autocad/news/acis_decrypt と、 http://xarch.tu-graz.ac.at/autocad/news/acis_decode.lsp



[A] Disclaimer, 作者による注記

もしこのFAQに追加したい質問や、答えとして増やしたいことがあれば、 Reini Urbanまでメールをください。 ただし返事は期待しないでください。 This AutoLISP FAQ is (c) 1996,97 by Reini Urban. All rights reserved. このFAQは内容に変更を加えたり、この著作権の表示を削除しない限り 自由に再配布してかまいません。 著作権保持者の書面による許諾がない限り、販売したり商用の文書に掲載し てはなりません。 Permission is expressly granted for this document to be made available for file transfer from installations offering unrestricted anonymous file transfer on the Internet and esp. to be included into the official AutoCAD FAQ. 特に作者が示されていないサンプルコードは、 (c) 1996,97 by Reini Urban によるもので自由に使用してもかまいませんが、 販売してはいけません。 [20]にある基本関数で特に示されていないものは、 (c) 1991-97 by Reini Urbanによるもので自由に使用してもかまいません。 このFAQをオフラインメディアに掲載するときは (たとえば, CD-ROM, 印刷したもの,など),その複製物をReini Urbanに送って ください。 X-RAY, Rechbauerstr. 38, 8010 Graz, Austria この中で扱われている内容とサンプルコードはそのままの状態で提供され、何の 保証もありません。 これは公式のAutoCAD FAQに含まれるものです。 AutoCAD FAQは現在Peter Sheerinが保守を行っています。 http://www.cadence-mag.com/library/FAQ 新しいAutoCAD FAQが作成されたら(うち合わせのものを見てください)、 それもその一部になります。AutoCAD FAQは近い将来いくらか変更されるでしょう。 暫定的な新しいAutoCADのFAQはここで見ることができます。 http://xarch.tu-graz.ac.at/autocad/news/faq/new-acad/ このAutoLISP FAQはcomp.cad.autocadとalt.cad.autocadと*.answersに、隔週で 投稿されます。(2度目の土曜日) AutoCAD FAQ が発展していくことを望みます。

[A.1] FAQの場所

HTML化されたFAQが置かれているホームページ:
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
投稿されたテキスト版(常に最新のものです)の位置はThe posted ascii versions
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.1
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.2
Windowsヘルプ版(FAQとサンプルコードが入っている)は
ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/autolisp.zip
FAQ usenet archive
ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/cad/autocad/comp.cad.autocad_AutoLISP_FAQ またはhttp://www.faqs.org/faqs/CAD/autolisp-faq/part1/
このFAQに出てくるLispプログラム
ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/faq-code.lsp
ccaの用語集も見てください
http://xarch.tu-graz.ac.at/autocad/news/faq/glossary.html
新しいAutoCAD FAQについては
http://xarch.tu-graz.ac.at/autocad/news/faq/new-acad
Roger Rosecによってフランス語に翻訳されたFAQは
http://www.newz.net/acadplus/page5101.htm
AutoDeskが出しているR13 FAQは
http://www.autodesk.com/support/faqs/cad13q.htm
AutoDeskがだしているR14 FAQは
http://www.autodesk.com/support/techdocs/cad14faq.htm
AutoDeskによるR14 FAQはここに投稿されます news://adesknews.autodesk.com/autodesk.autocad.r14general しかし私はこれをウェブで見たことはありません。


[B] 謝辞

このFAQはcomp.cad.autocadコミュニティの協力の元に作成されました。 とりわけ:

Adi Buturovic <af.buturovic@berwanger.com>
Christoph Candido <h8540418@edv1.boku.ac.at>
Mike Clark http://www.cadalog.com/ <webmaster@cadalog.com>
Miles Constable <miles@triumf.ca>
Cara Denko <cara.denko@autodesk.com>
T.J. DiTullio <tditullio@goldner.com>
Jeff Foster http://www.cadshack.com
Rusty Gesner http://www.group-a.com/~rusty
William Kiernan <WKiernan@concentric.net>
Paul Kohut <paulk2@seanet.com>
Sergei M. Komarov <komarov@mailcom.lviv.ua>
Joseph M. Liston <smoker@fs.cei.net>
Lu <learly@ix.netcom.com>
Georg Mischler http://www.schorsch.com/
Desi Moreno http://www.invsn.com/desmos
Vladimir Nesterovsky http://members.tripod.com/~vnestr/
Dennis Shinn http://www.halcyon.com/jeeper
Tony Tanzillo http://ourworld.compuserve.com/homepages/tonyt
Reinaldo Togores http://personales.mundivia.es/personales/rtogores/
Reini Urban http://xarch.tu-graz.ac.at/home/rurban
Serge Volkov http://www.basissoftware.com/vill.htm
Morten Warankov <mortenw@abacus.no>
Owen Wengerd http://www.manusoft.com
Alan Williams <alan@awol.demon.co.uk>
Doug Wilson <dougw@amgen.com>
Ian A. White <waiwhite@zip.com.au>
David Whynot http://www.buildingweb.com/cadsyst
Darren Young http://www.mcwi.com
Xiang Zhu <xzhu@whale.st.usm.edu>

それからここにのっていないコードや答えを送ってくれた他のすべての人に 感謝します。これは私の個人的なリストです。


[C] 最近の変更

11.Jan.98
[2] The R13 lisp manual is in the cust. manual not only on the cd. sorry
8.Jan.98
Vladimir Nesterowsky's new web url
24.Nov.97
fixed some typos
v1.11 15.Nov.97
changed header.
AutoDESK AutoCAD FAQ URL's. see [A.1]
LispLink editor. see [6.1]
Zoomer rumors: [0]
23.Oct.97
Roger Rosec provided a french translation of the entire FAQ. see [A.1]
13.Sep 97
Alan Williams detected a stupid error in DATESTAMP in [22.2] but in FAQ-CODE.LSP it was okay.
28.Aug 97
added the (entget) LWPLOYLINE bug to [7],
changed my mail address to rurban@xarch.tu-graz.ac.at to be prepared for the after-student area. :)
v1.10 22.Jul 97
some LWPOLYLINE fixes, R14 Lisp debugger Vital Lisp 3.0 shipped, Convert 3.3 update [4.4], fixed cronjob for bi-weekly posting: every 2nd Monday, 11.30 MET
20.Jul 97
Vital Lisp 3.0 shipped
12.Jul 97
Convert 3.3 update [4.4], fixed cronjob for bi-weekly posting: every 2nd Monday, 18.00 MET
2.July 97
fixed URL in [10],
30.June 97
fixed (istypep) in [20.4], changed title of [16], light changes in (getpts) in [23.1]
v1.9 26.June 97
[5.2] confirmed Vill3 release date, added DDE sample from Xiang Zhu to [21.2], provided detab.lsp [25]
17.June 97
bugfix in [20.4]: short (getval), [12] R14 ARX autoloading, [23.5] (pline-segs) is now R14-save but still not compatible, new [23.6] revpoly.lsp, [A.1], [5.2] Vill 3 will have reactor support.
9.June 97
new symbol-string trick by Christoph Candido [20.3]
21.May 97
some minor corrections.
v1.8 15.May 97
added [0] Future of AutoLISP?
changed VERTECES to VERTICES, fixed mail address of af.buturovic@berwanger.com,
added SSAPPLY: [20.4], [23.5],
started to R14'ify some code for LWPOLYLINE's [23], not finished yet, (pline-segs) is missing
9.May 97
[2.1] R14 winhelps, [5.2]: new basis url, Vill Lite [6.1]
added [16]: Lisp over mult. dwg's
added some short comments to [6.1](ntemacs), [14], [21.8]
21.April 97
added [[28] ACIS decryption
v1.7 9.April 97
added [[21.8] C:XYZ,
added [[15] (command "ROTATE3D") does not work! Why?
HTML version chapter numbers match the posted version,
added [27]: (command) as ctrl-c, Sergei Komarov improved [27], Adi Buturovic improved [27] for scripts.
v1.6 13.Feb 97
moved the intro to the very beginning for the curious.
another lisp plot lisp [21.2], a third lisp debugger [3.1], [A.1]: the gd.tuwien uunet mirror is faster than the official ones, fixed cadence FAQ url, applied digest format partially, html will be created automatically soon, wrong (old) chapter numbering from the v1.5 version, [7] 64 in flag 70 in symbol tables,
v1.5 5.Feb 97
added get and edlgetent samples by Vladimir, removed the sort code instead,
changed [11] title and added string funcnames,
bugfix in getpts [23.1], basic funcs should be free [A],
added DATESTAMP to [22.2], added a "s" to [A] title,
added [20] DCL, [21] EED, [21.1-21.7] samples,
Serguei Komarov found a bug in seg2cir,arclen,arc2bul [24],
added arc2ang and (corrected) arclen,
bugfixes in sslist, getval, all predicates with "p" postfix now,
prepared a FAQ-CODE.LSP, Convert supercedes Decrypt [4.4], added scripts and (command) to [23.4], AREA to [23.5],
v1.4 24.Jan 97
important news with Decrypt [4.4],
moved [11] "bugs" to [7] "problems",
added [11] "How do I (sym, list)" instead,
added the "Approved" header for news.answers processing,
added [22]-[24]: some examples for subentities and bulge stuff,
Serge found a bug/feature in acad_strlsort [7],
added number accuracy and ss limitation to [7],
added break code and samples to [3.3],
added a short lisp style guide at [2.2], instead of [6.4]
v1.3 17.Jan 97
added [16] stack overflow (thanks Serge), [4.7] Lisp2C,
updated [8] fastest sort (sample, benches),
received the news.anwsers approval
v1.2 11.Jan 97
added Phoaks to news archive
fixed (break) in [3.3] (Thanks Tony),
added a sorting example to [8], improved (my-princ) in [15]
changed posting frequency from weekly to bi-weekly
v1.1 4.Jan 97
R13 bugs, S::STARTUP code by Owen Wengerd,
homepages instead of e-mail adresses where appropriate, (people get enough junk mail these days)
more links, and some bugfixes
v1.0 22.Dec 96
First version, posted on 28.Dec 96
as a discussion basis
--
Reini Urban, 26.Dec 97