この掲示板は AutoCADマクロ屋本舗 の掲示板です。

【 注意 】最初に必ず ↓↓ 下記内容 ↓↓ を参照ください。
① マクロが分からない方は、まず 【 マクロ講座 】 を参照ください。
② 質問の前に 【 マクロ使用前の注意事項 】 をお読みください。
③ 質問する時は、新規投稿フォーム下の【 新規投稿時のお願い 】を必ずお読みください。

ブロック図形の座標について
おはようございます。
AutoCAD Mechanical2025についてご質問します。(多分無理だと思いますが。。。)
任意の点のX座標値と
ブロック図形(ネストされている)を分解したときの各線分の端点のX座標値が一致している点を
ブロックの分解をせずに探索したいです。
このようなことは、無理ですよね。
  • パン君
  • 2025/06/04 (Wed) 09:58:02
Re: ブロック図形の座標について
ブロック内の線分の端点座標を抽出することが出来れば良いのですよね?

ブロック内での座標を取得したら、ブロック自体の挿入位置、挿入尺度、回転角度を換算すれば
モデル上での座標は取得可能です。

その換算ルーチンを作るのが面倒なら、(私なら面倒なので、)
一旦分解して各線分の座標を取得したらUNDOコマンドで分解前に戻せば良いと思います。

各線分の座標が取得できたなら、任意の点のX座標値と一致しているのかの判定も簡単に出来ると思いますが、
「一致しているオブジェクトはコレですよ」と明示する方法はどうしましょう?。
  • Hamu
  • 2025/06/04 (Wed) 13:25:54
Re: ブロック図形の座標について
Hamuさんご助言ありがとうございます。

>ブロック内での座標を取得したら、ブロック自体の挿入位置、挿入尺度、回転角度を換算すれば
>モデル上での座標は取得可能です。
分解せずにできるのですか?
どこかのサイトにサンプルなどご存知ないでしょうか。

<その換算ルーチンを作るのが面倒なら、(私なら面倒なので、)
<一旦分解して各線分の座標を取得したらUNDOコマンドで分解前に戻せば良いと思います。
複数のブロック図名をまとめたブロック図形を複数分解(explode)すると
UNDOをどこまでするかわからなくなりませんでしょうか。


>各線分の座標が取得できたなら、任意の点のX座標値と一致しているのかの判定も簡単に出来ると思いますが、
>「一致しているオブジェクトはコレですよ」と明示する方法はどうしましょう?。
大き目の点(point)をプロットしようかなと思っています。
  • パン君
  • 2025/06/04 (Wed) 18:40:21
Re: ブロック図形の座標について
>どこかのサイトにサンプルなどご存知ないでしょうか。

trans 関数は、尺度、回転、平行移動の計算を内部的に処理してくれます。

(trans point from_coord_sys to_coord_sys [displacement_vector])

point: 変換したい点のリスト
from_coord_sys: 変換元の座標系。ブロック内のエンティティの場合、ブロックのローカル座標系を表すエンティティ名 (block_ename) を指定します。
to_coord_sys: 変換先の座標系。モデル空間のワールド座標系を表す場合は 1 を指定します。
displacement_vector: (オプション) 変位ベクトル。ブロック参照の場合、挿入点、尺度、回転角度が暗黙的に適用されるため、通常は指定しません。


具体的なAutoLISPコードは次の様になります。

(defun C:GetBlockLineCoordsNoExplode (/ ss i ent block_data block_name insertion_point block_def_ename
block_def_ent block_def_ent_data
line_start_mcs line_end_mcs
line_start_wcs line_end_wcs)
(vl-load-com) ; 必要に応じてロード

(princ "\n線分の座標を取得したいブロック参照を選択してください: ")
(setq ss (ssget '((0 . "INSERT")))) ; ブロック参照のみを選択

(if ss
(progn
(setq i 0)
(repeat (sslength ss)
(setq ent (ssname ss i)) ; 選択セットからブロック参照のエンティティ名を取得
(setq block_data (entget ent))
(setq block_name (cdr (assoc 2 block_data))) ; ブロック名を取得
(setq insertion_point (cdr (assoc 10 block_data))) ; 挿入点 (WCS)

(princ (strcat "\n--- ブロック名: " block_name " (ハンドル: " (cdr (assoc 5 block_data)) ") ---"))

; ブロック名からブロック定義のエンティティ名を取得
; (tblobjname "BLOCK" block_name) はブロック定義のエンティティ名を返します
(setq block_def_ename (tblobjname "BLOCK" block_name))

(if block_def_ename
(progn
; ブロック定義内のエンティティを走査
; (entnext block_def_ename) で最初のエンティティを取得
; その後 (entnext current_ent_in_block_def) で次のエンティティを取得
(setq block_def_ent (entnext block_def_ename))

(while (and block_def_ent (not (eq (cdr (assoc 0 (setq block_def_ent_data (entget block_def_ent)))) "ENDBLK")))
; 現在のエンティティが線分かどうかをチェック
(if (eq (cdr (assoc 0 block_def_ent_data)) "LINE")
(progn
; 線分の始点と終点の座標をブロックのローカル座標系で取得
(setq line_start_mcs (cdr (assoc 10 block_def_ent_data))
line_end_mcs (cdr (assoc 11 block_def_ent_data))
)

; trans関数を使ってモデル空間座標に変換
; 変換元の座標系としてブロック参照のエンティティ名 'ent' を指定
; これにより、挿入点、尺度、回転角度が自動的に適用される
(setq line_start_wcs (trans line_start_mcs ent 1))
(setq line_end_wcs (trans line_end_mcs ent 1))

(princ (strcat "\n 線分始点 (WCS): " (vl-princ-to-string line_start_wcs)))
(princ (strcat "\n 線分終点 (WCS): " (vl-princ-to-string line_end_wcs)))
)
)
; 次のエンティティへ
(setq block_def_ent (entnext block_def_ent))
)
)
(princ (strcat "\n ブロック定義 '" block_name "' が見つかりません。"))
)
(setq i (1+ i))
)
)
(princ "\nブロックが選択されませんでした。")
)
(princ)
)


このコードは、選択されたブロック参照(親ブロック)の直下の線分には対応できますが、
ネストされたブロック(ブロックの中にさらにブロックが含まれている場合) の中の線分には直接対応していません。

ネストされたブロック内の線分も取得したい場合は、親ブロック内のエンティティを走査中に、
別のブロック参照 (INSERT エンティティ) を見つけたら、そのネストされたブロック参照の情報を(挿入点、尺度、回転角度など)取得します。
そのネストされたブロックの定義を再帰的に走査します。
最下層の線分のローカル座標に、親ブロック、その中のネストされたブロック…というように、
全ての階層の変換行列(挿入点、尺度、回転)を累積的に適用していく 必要があります。
  • Hamu
  • 2025/06/05 (Thu) 09:28:23
Re: ブロック図形の座標について
>UNDOをどこまでするかわからなくなりませんでしょうか。

分解する前に、
UNDOコマンドの BE か M オプションでマーキングしておく。
分解してそれらのオブジェクト情報を取得したら、UNDOコマンドでマーキングした時点まで戻る。

BE でマーキングしたなら E オプションで記録を終了して U コマンドを実行して戻る
M でマーキングしたなら B オプションで戻れる。

分解後のオブジェクト取得は、分解前にENTLASTを取得しておき、
分解後にENTLASTで取得ておいたオブジェクトよりも後に作成されたオブジェクトを取得すれば良い。
  • Hamu
  • 2025/06/05 (Thu) 09:36:33
Re: ブロック図形の座標について
Hamuさん、とても詳しいご説明本当にありがとうございます。
UNDOにこのようなオプションがあったとは知りませんでした。(恥ずかしい。。。)
これを使えば、ご紹介いただいた換算ルーチンを使わづできるかなっと思ったのですが。。。。。
しかし、抽出した端点にポイント(POINT)を作成してUNDOで戻したら作成したポイントを消えちゃうので
やっぱり、根気よくAutoLISPでコーディングしないといけませんね。
  • パン君
  • 2025/06/05 (Thu) 19:00:16
Re: ブロック図形の座標について
Hamuさん、先程はUNDOで作成したポイントも消えちゃうと言いましたが
UNDOで戻ってからポイントすればいいですね。
すみませんでした。
UNDOを使ってコーディングします。
  • パン君
  • 2025/06/05 (Thu) 19:11:30
Re: ブロック図形の座標について
毎々お世話になっています。
コーディングを進めています。
また、難所がやってきてしまいました。

ブロック図形の[分解の許可がいいえ]のブロックは分解対象外にしたいのですが
SSGETでブロックなどを取得した場合、[分解の許可がいいえ]のブロックのDXFコードが
ネットで探していたのですがみつかりませんでした。
教えていただけませんでしょうか。

(ssget "X" (list (cons 0 "INSERT") (cons ** **))))
  • パン君
  • 2025/06/06 (Fri) 15:26:49
Re: ブロック図形の座標について
[分解の許可がいいえ]なら、分解コマンドを実行しても分解されないので、選択から除外する必要はないのでは?

分解前にentlastを取得しておいて、分解後にentlastを取得する。
前と、後で同じなら、分解は行われなかった。という事なので、分解以降の処理はスルーすれば良いと思います。
  • Hamu
  • 2025/06/06 (Fri) 16:33:49
Re: ブロック図形の座標について
Hamuさん、ご指導ありがとうございます。

分解するコードですが
以下のようにWhile文にしています
このままだと、[分解の許可がいいえ]のブロック図形がいつまで残ってしまい
無限ループになってしまうので
[分解の許可がいいえ]ブロックを外しかったのですが。。。
(setq Objs (ssget "X" '((0 . "INSERT"))))
(setq ObjNum (sslength Objs))
(while (/= ObjNum 0)
(command-s "EXPLODE" Objs 0)
)
  • パン君
  • 2025/06/08 (Sun) 08:45:31
Re: ブロック図形の座標について
とりあえずこれでお試しください。

(setq Objs (ssget "X" '((0 . "INSERT"))))
(setq ObjNum (sslength Objs))
(setq i 0)
(repeat objNum
(command-s "EXPLODE" (ssname Objs i))
(setq i (1+ i))
)

  • Hamu
  • 2025/06/09 (Mon) 12:22:32
Re: ブロック図形の座標について
ネストされているブロックまで根こそぎ分解したいのでしたら、

(setq Ent_L (entlast))
(setq Loop T)
(while Loop
(if (setq Objs (ssget "X" '((0 . "INSERT"))))
(progn
(initcommandversion 2)
(command "EXPLODE" Objs "")
(if (eq Ent_L (entlast)) (setq Loop nil) (setq Ent_L (entlast)))
)
(setq Loop nil)
)
)
  • Hamu
  • 2025/06/09 (Mon) 16:54:26
Re: ブロック図形の座標について
Hamuさん、度々ご教授ありがとうございます。
お昼過ぎにいただいたコードは最初にコーディングしていたのですが
ネストされているブロックを分解できず
(while (/= ObjNum 0)
にしていました。

16時過ぎに頂きましたコードですが
[分解の許可がいいえ]のブロックで無限ループになってしまいました。
やはり無理なのでしょうか
  • パン君
  • 2025/06/09 (Mon) 19:09:05
Re: ブロック図形の座標について
前回(2025/06/09 (Mon) 16:54:26)の投稿内容を書き換えました。

お試しください
  • Hamu
  • 2025/06/10 (Tue) 10:55:53
Re: ブロック図形の座標について
Hamuさん、いつもご返信ありがとうございます。
書き換えていただきましたコードを実行させていただきました。
[分解の許可がいいえ]のブロックをスロー処理できました。
お付き合いいただきまして
本当に感謝いたします。
あと、もう少し頑張ります。
  • パン君
  • 2025/06/10 (Tue) 16:03:57
Re: ブロック図形の座標について
いつもお世話になりありがとうございます。
以下の流れで作成しています。
①X座標入力
②UNDO > Mでマーク
③ブロック図形を全て分解(分解不許可はスルー)

④線の端点と入力したX座標が一致している点にポイント(POINT)
(setq Objs (ssget "X" '((0 . "LINE"))))
(if (/= Objs nil)
(progn
(setq ObjNum (sslength Objs)) ;選択セットに入った図形の数をObjNumに入れる
)
(progn
(princ "\n線図形が存在しません")
(exit)
)
)
(command-s "._UNDO" "B") ;マークの位置まで後退

(repeat ObjNum
(progn
(princ "\n同一点検索中")
(setq Obj (ssname Objs Cnt))
*
*
    (command-s "._POINT" "NONE" (cdr ed_pt))
)
)

repeatの中は割愛しましたが、
(setq Obj (ssname Objs Cnt))
上のコードでエラーとなります。

(command-s "._UNDO" "B")
UNDOで後退したら
(setq Objs (ssget "X" '((0 . "LINE"))))
で取得したデータも消えるのですね。
  • パン君
  • 2025/06/10 (Tue) 19:53:50
Re: ブロック図形の座標について
でしたら、ポイントを打つ座標のリストを作成して、その後にUndoで戻れば良いと思います。
リストはUndoしても残ります。
  • Hamu
  • 2025/06/11 (Wed) 07:51:15
Re: ブロック図形の座標について
Hamuさん、改めてありがとうございます。
リストを作成とは
Appendで一致している座標を追加していき
Undo>Bで後退後、
リストからpointするということでしょうか。
  • パン君
  • 2025/06/11 (Wed) 10:52:03
Re: ブロック図形の座標について
それを思いついたのでしたら、それでやってみましょう。
多分うまく行きます。

私が考えた方法と同じか、違うかは問題ではありません。
自分の思いついた方法でやってみて、それがうまく行ったのならそれが正解です。

私だって、初めから正解を知ってる訳じゃありません。どこかの教科書を調べた訳でもありません。
考えてみて、やってみて、うまく行きそうだな。と思ったことを書いているだけです。

素人のプログラミングってそんな物です。「希望通りに動けば何だって良い。」
  • Hamu
  • 2025/06/11 (Wed) 13:29:25
Re: ブロック図形の座標について
おはようございます。
Hameさん、昨夜から試行錯誤して
ようやくリスト生成のコードを完成することができました。
(なんかコードがすっきりしないけど。。。 まーいいっか笑)
長きにわたり低レベルなご質問にお付き合いいただきありがとうございました。
今後ともよろしくお願いいたします。
  • パン君
  • 2025/06/12 (Thu) 09:48:23

返信フォーム






プレビュー (投稿前に内容を確認)