【AutoCAD LISP】文字を線や曲線に沿わせて配置する|SAの使い方

図面に対して斜めに延びる通路や、平行・直角ではない通り芯、壁などに文字の角度を合わせるのは、意外と手間がかかります。

RO(ROTATE)で文字を回転させる場合は、基準にする線に合わせて文字を一つずつ調整します。文字が何か所もあると、その繰り返しに少しずつ時間を取られます。

AutoLISP「SA」は、文字と基準にする線・曲線を選ぶことで、その向きに文字を沿わせて配置できるLISPです。

SA
文字を線・曲線の向きに合わせて配置
SA_TextOnLine.lsp

※音はありません

💡このLISPでできること

  • TEXTまたはMTEXTを1つ選び、線分・円弧・ポリライン・スプラインの向きに沿わせて配置する
  • マウスを動かすと、文字が選択した線や曲線に沿って滑らかに追従する
フクロウ
フクロウ

マウスを動かすと、文字が線や曲線にぬるぬるついてきます。
SAは、S(線)にA(合わせる)で「線に合わせる」が名前の由来です。

🛠️SAの使い方

  1. コマンドラインへSAと入力し、EnterまたはSpaceで確定します。
  2. 配置したい文字(TEXTまたはMTEXT)を1つ選択します。
  3. 文字を沿わせたい線や曲線を選択します。
  4. マウスを動かし、文字の位置と角度を確認します。
  5. 配置したい位置で左クリックして終了します。

選択した文字はハイライト表示され、マウスを動かすと線や曲線の向きに沿って追従します。角度が合う位置で確定し、必要に応じてM(MOVE)で位置を微調整します。

⚠️使う前に知っておきたいこと

  • SAは、選択した元の文字を直接移動・回転します。元の位置に文字を残したり、コピーを作成したりする機能ではありません。
  • 同じ向きにそろえたい文字が複数ある場合は、SAで1つの文字を整えたあと、MA(MATCHPROP)で残りの文字の角度をそろえると効率的です。

💾 ダウンロードとコード

LISPファイルをダウンロード

収録ファイル:SA_TextOnLine.lsp
※ダウンロード後、「すべて展開(解凍)」してから使用してください。

LISPを初めて使う方は、読み込み方法をこちらの記事で確認できます。
AutoCADでLISPをロードする3つの方法

このLISPはECW_Utilityがなくても基本機能を使用できます。ECW_Utilityを導入している環境では、共通のUNDO・エラー処理と連携します。
ECW_Utilityの役割と導入方法

🔤コードのコピーは+をクリック↓

Lisp
;;; Support: https://easycadwork.com
;;; X(follow me!): https://x.com/easycadwork
;;; 概要: 選択した文字を曲線(線/円弧/ポリライン等)に沿わせてリアルタイムに移動・回転(ハイライト表示対応)

(defun c:sa (/ txtSel txtEnt txtData txtType crvSel crvEnt vlaCrv scale loop code ptCur ptCurW ptNearW param deriv dist ptPosW ptPosO angO angNorm SA_Error)

  (vl-load-com)

  ;; --- 専用エラーハンドラ ---
  ;; Escや異常終了時、ハイライトを確実に解除してからECW_Error(あれば)へ引き継ぐ
  (defun SA_Error (msg)
    (if txtEnt (redraw txtEnt 4)) ; ハイライト解除を最優先で実行
    (if (type ECW_Error)
      (ECW_Error msg)
      (progn
        (if (not (member msg '("Function cancelled" "quit / exit abort")))
          (princ (strcat "\n** SA_Error: " msg " **"))
        )
        (setq *error* nil)
        (princ)
      )
    )
  )
  (setq *error* SA_Error)

  (if (type ECW_Start) (ECW_Start)) ; 設定退避・UNDO開始(ECW_Utility.lsp導入時のみ)

  ;; --- 1. ユーザー入力と図形の検証 ---
  (if (and (setq txtSel (entsel "\n文字(TEXT/MTEXT)を選択: "))
           (setq txtEnt (car txtSel))
           (setq txtData (entget txtEnt))
           (setq txtType (cdr (assoc 0 txtData)))
           (wcmatch txtType "*TEXT")
           (progn (redraw txtEnt 3) T) ; 選択した文字をハイライト
           (setq crvSel (entsel "\n沿わせる曲線を選択: "))
           (setq crvEnt (car crvSel))
           (not (vl-catch-all-error-p (vl-catch-all-apply 'vlax-curve-getEndParam (list crvEnt)))))
    (progn
      ;; --- 2. 文字の基点設定と初期化 ---
      (command "_.justifytext" txtEnt "" "_MC")

      (setq vlaCrv (vlax-ename->vla-object crvEnt)
            scale  (getvar "DIMSCALE")
            loop   T)
      (if (or (= scale nil) (= scale 0.0)) (setq scale 1.0))

      (princ "\nマウスで配置位置を決定 (左クリック:確定 / 右クリック:中止): ")

      ;; --- 3. マウス追従ループ (grread) ---
      (while loop
        (setq code (grread T 13 0))
        (cond
          ((= (car code) 5)
            (setq ptCur  (cadr code)
                  ptCurW (trans ptCur 1 0))

            (if (not (vl-catch-all-error-p (setq ptNearW (vl-catch-all-apply 'vlax-curve-getClosestPointTo (list vlaCrv ptCurW)))))
              (progn
                (setq param (vlax-curve-getParamAtPoint vlaCrv ptNearW)
                      deriv (vlax-curve-getFirstDeriv vlaCrv param))

                (setq dist (distance ptNearW ptCurW))
                (if (> dist 0.0)
                  (setq ptPosW (polar ptNearW (angle ptNearW ptCurW) (* 2.0 scale)))
                  (setq ptPosW ptNearW)
                )

                (setq ptPosO (trans ptPosW 0 txtEnt))

                (setq angO (angle '(0 0 0) (trans deriv 0 txtEnt T)))
                (setq angNorm (rem (+ angO (* pi 2.0)) (* pi 2.0)))
                (if (and (> angNorm (/ pi 2.0)) (<= angNorm (* pi 1.5)))
                  (setq angNorm (- angNorm pi))
                )

                (setq txtData (entget txtEnt))
                (if (= txtType "TEXT")
                  (setq txtData (subst (cons 11 ptPosO) (assoc 11 txtData) txtData))
                  (setq txtData (subst (cons 10 ptPosO) (assoc 10 txtData) txtData))
                )
                (setq txtData (subst (cons 50 angNorm) (assoc 50 txtData) txtData))
                (entmod txtData)
                (entupd txtEnt) ; 変更結果を確実に画面へ反映
              )
            )
          )
          ((= (car code) 3) (setq loop nil))
          ((or (= (car code) 11) (= (car code) 25)) (setq loop nil))
        )
      )
      (redraw txtEnt 4)
    )
    (progn
      (if txtEnt (redraw txtEnt 4))
      (princ "\n※文字または有効な曲線が選択されませんでした。")
    )
  )

  (if (type ECW_End) (ECW_End)) ; 設定復元・UNDO終了(ECW_Utility.lsp導入時のみ)
  (setq *error* nil)
  (princ)
)

✏️まとめ:文字が線に揃うと、やっぱり気持ちいい

SAは、私がCADを触り始めた頃に先輩からもらい、仕事に合わせて少しずつ直しながら、30年ほど使ってきたLISPです。会社全体でも共有してきました。最新版はAIにも手伝ってもらい、さらに使いやすくなっています。

斜めの道路や通り芯に文字を合わせるとき、「だいたいこの角度」で回転させても、線と少しずれていると何となく気持ち悪い。図面描きなら、この感覚は分かってもらえるはずです。

文字が線にきっちり沿うと、図面もすっきり見え、気持ちまですっきりします。

道路名やL型街渠などの構造物名も、道路の向きに沿わせた方が読みやすく、限られたスペースにも収めやすいと感じています。

フクロウ
フクロウ

長い間、当たり前のように使ってきたので、今さらSAなしで同じ作業をするのは、正直しんどすぎます(笑)。

コメント