カスタム入力関数

リアルタイム画面描画

AutoLISP関数
(grdraw from to color [highlight])
from,to:リスト
color:整数
highlight:整数
現在のビューポートに線分を描画します。
戻り値:nil

grdraw 関数は作図領域に一つの線分を描きます。これは画面表示上の描画で、図面データベースとは関係ありません。

線分は from と to の端点の座標を表すリストで表され、端点は UCS 座標で 2D 点でも 3D 点でも構いません。線分の色は color にインデックスカラーで指定します。色に -1 を指定すると XOR 描画になります。highlight を 0 以外の整数に設定すると、ハイライト描画になります。

下の例は、grread 関数でカーソルの位置をリアルタイムで読み取り、原点からカーソルまで線分を描画します。AutoCAD にロードすると実行されます。

描画は XOR 描画を使用しています。XOR 描画は、同じ位置に描画すると以前の描画を消せる描画の仕方です。ゴミが残ってしまった場合は、AutoCAD の REDRAW コマンドか、redraw 関数を引数なしで呼び出します。

(setq pt1  '(0.0 0.0 0.0)
      flag nil
)
(grdraw '(0.0 0.0 0.0) pt1 -1)
(prompt "\ngrdraw関数のサンプル(クリックで終了)\n")
(while (null flag)
  (setq device (grread T)
        code   (car device)
        data   (cadr device)
  )
  (cond ((= code 5)                     ; on mouse move
         (grdraw '(0.0 0.0 0.0) pt1 -1) ; XOR描画で以前の線を消す
         (setq pt1 data)
         (grdraw '(0.0 0.0 0.0) pt1 -1) ; 再描画
        )
        ((= code 3)                     ; on left click
         (setq flag T)
        )
  )
)
(redraw)

実行すると原点からカーソルまで線分が引かれます。

autolisp grdraw

次は三次元の描画の例です。基準となる正三角錐の描画データを用意し、カーソル位置に描画します。AutoCAD にロードすると実行されます。

今度の一回ごとの描画は、redraw 関数を引数なしで呼び出すことで一度描画をクリアし、改めて全体の描画を行っています。描画モードは、現在のコンピュータの速度を考えると、XOR ではなくて、redraw 関数で一度すべて消してから通常に再描画する方が、画面上のゴミが発生しません。

(setq EquilateralPyramid
       '(((50.00 -28.87 0.00) (0.00 57.74 0.00))
         ((0.00 57.74 0.00) (-50.00 -28.87 0.00))
         ((-50.00 -28.87 0.00) (50.00 -28.87 0.00))
         ((0.00 0.00 81.65) (50.00 -28.87 0.00))
         ((0.00 0.00 81.65) (0.00 57.74 0.00))
         ((0.00 0.00 81.65) (-50.00 -28.87 0.00))
        )
      flag nil
)

(prompt "\ngrdraw関数のサンプル(クリックで終了)\n")
(while (null flag)
  (setq device (grread T)
        code   (car device)
        data   (cadr device)
  )
  (cond ((= code 5)                     ; on mouse move
         (redraw)
         (mapcar
           (function (lambda (line)
                       (grdraw (mapcar '+ data (car line)) (mapcar '+ data (cadr line)) 1)
                     )
           )
           EquilateralPyramid
         )
        )
        ((= code 3)                     ; on left click
         (setq flag T)
        )
  )
)
(redraw)

実行すると、カーソル位置に正三角錐が描画されます。

autolisp grdraw
AutoLISP関数
(grvecs vlist [trans])
vlist:リスト
trans:リスト
作図領域に複数の線分を描きます。
戻り値:nil

grvecs 関数は、作図領域に複数の線分を一度に描きます。これは画面表示上の描画で、図面データベースとは関係ありません。

vlist 引数は、線の色と線分の端点の情報を含んだリストです。vlist のリストは以下のような構造になっています。

(
    [color0] (x0 y0 z0) (x1 y1 z1)        ;一つ目の線分
    [color1] (x1 y1 z1) (x2 y2 z2)        ;二つ目の線分
    [color2] (x2 y2 z2) (x3 y3 z3)        ;三つ目の線分
    …                                     ;必要な数だけ
)

色情報 color[0…] は省略できます。色は整数型で、0~255 のインデックスカラーで指定しますが、256 以上の値を指定すると、描画が XOR で描画されます。XOR 描画は、値に関わらず白色の描画になります。また負のインデックスカラーを指定すると、描画線がハイライト表示になります。1 (red) に対する -1 は red のハイライト表示という具合です。

端点の座標は、2D 点でも 3D 点でも構いません。

vlist 引数の座標系は、trans 引数を指定しない場合は UCS として、trans 引数が指定された場合は DCS として解釈されます。DCS の Z 軸は常にスクリーンの視線方向を向いているため、斜めからUCS を見ている場合でも、作図ウィンドウのスクリーンに正面から見た図が描画されます。そのため、trans 引数を使う場合は、作図ウィンドウのスクリーン表示や UCS と DCS との関係を調べなければなりません。DCS は、今現在作図ウィンドウに表示されている画面表示と間接的に連動していますが、UCS との関係は時々によって変化するからです。

まずは、単純な、trans 引数を使用しない、UCS に描画する例を確認します。例では、マウスカーソルの位置に半径100の星を描きます。星型のデータは、前出の StarData 関数を使用します。

StarData 関数から得られるデータは、頂点を順に並べただけのリストでしたので、grvecs 関数に合うように、頂点のリストを変換します。

(defun grvecs:DrawData:sub (plist / pt1 pt2)
  (if (and plist
           (setq pt1 (car plist))
           (setq pt2 (if (cadr plist)
                       (cadr plist)
                       (if closed
                         startPoint
                         nil
                       )
                     )
           )
      )
    (cons (list color pt1 pt2) (grvecs:DrawData:sub (cdr plist)))
    nil
  )
)

(defun grvecs:DrawData (plist color closed / startPoint)
  (setq startPoint (car plist))
  (apply 'append (grvecs:DrawData:sub plist))
)

これらを使って、grread 関数で、マウスカーソルの位置をリアルタイムに読み取りながら、半径 100 の星の図形を描画します。描画モードは、現在のコンピュータの速度を考えると、XOR ではなくて redraw 関数で一度すべて消してから通常に再描画する方が画面上のゴミが発生しません。

(prompt "\n左クリックで終了\n")
(setq flag T)
(while flag
  (setq device (grread T)
        code   (car device)
        data   (cadr device)
  )
  (cond ((= code 3)                     ; on left click
         (setq flag nil)
        )
        ((= code 5)                     ; on mouse move
         (redraw)
         (grvecs (grvecs:DrawData (StarData data 100.0) acRed T))
        )
  )
)
(redraw)

UCS の平面に沿った形で、図形が描画されます。AutoCAD ユーザーが画面をズームすると、描画される図形の見かけの大きさも変化します。

autolisp grvecs

次は trans 引数を使用した DCS に描画する例です。スクリーンのサイズはシステム変数 SCREENSIZE よりピクセル単位のものが得られるます。作図単位ベースではシステム変数 VIEWSIZE でスクリーンの高さが得られます。スクリーンに PixelSize で描きたい図形と、実際に grvecs 関数に渡す図形のサイズDrawSize との関係は、次のように求まります。

autolisp grvecs

描画位置は、UCS の座標を DCS の座標へと trans 関数で変換することによって決めることができます。なお、変換後の DCS の Z 座標は、スクリーンが正投影の場合は影響を与えません。

単純な例として、trans 引数に単位行列を指定し、半径 100 ピクセルの星形の図形を描画するものを以下に示します。

(prompt "\n左クリックで終了\n")
(setq flag T)
(while flag
  (setq device (grread T)
        code   (car device)
        data   (cadr device)
  )
  (cond
    ((= code 3)                         ; on left click
     (setq flag nil)
    )
    ((= code 5)                         ; on mouse move
     (redraw)
     (grvecs (grvecs:DrawData
               (StarData (trans data acUcs acDisplayDCS)
                         (* 100 (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE"))))
               )
               acRed
               T
             )
             '((1.0 0.0 0.0 0.0) (0.0 1.0 0.0 0.0) (0.0 0.0 1.0 0.0) (0.0 0.0 0.0 1.0))
     )
    )
  )
)
(redraw)

DCS によって描かれるため、正面から見た星形が描かれます。また、システム変数 VIEWSIZE と SCREENSIZE を参照して描画する図形の大きさを決めているので、AutoCAD ユーザーが画面をズームしても描画される図形の見た目の大きさは変わりません。

autolisp grvecs

上の例では、trans 引数が単位行列であり、仕事をしていません。描画データの方を動的に変更していました。次は、描画データを固定して、trans 引数の方を動的に変更する例です。

次の関数は、図形を scale 引数で指示される値で拡大し、原点を origin 引数によるものに平行移動する変換マトリックスを生成します。

(defun grvecs:TransformMatrix (origin scale)
  (setq origin (trans origin acUcs acDisplayDCS)
        scale  (* scale (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE"))))
  )
  (list (list scale 0.0 0.0 (car origin))
        (list 0.0 scale 0.0 (cadr origin))
        (list 0.0 0.0 scale (caddr origin))
        '(0.0 0.0 0.0 1.0)
  )
)

この変換マトリックスと半径を 1 とする基準となる星形の固定データを grvecs 関数で作用させて、先ほどと同じことができます。下の例では UnitStarData に基準となる図形描画用のデータを格納し、このデータは変化しません。そして、grvecs:TransformMatrix 関数で、描画したい位置と大きさを指定した変換マトリックスを生成して trans 引数に渡しています。

(prompt "\n左クリックで終了\n")
(setq flag T
      UnitStarData
       (grvecs:DrawData (StarData '(0.0 0.0) 1.0) acRed T)
)
(while flag
  (setq device (grread T)
        code   (car device)
        data   (cadr device)
  )
  (cond ((= code 3)                     ; on left click
         (setq flag nil)
        )
        ((= code 5)                     ; on mouse move
         (redraw)
         (grvecs UnitStarData (grvecs:TransformMatrix data 100))
        )
  )
)
(redraw)

実行結果は先の例と同じです。こちらの場合は基準となる描画テータを用意しておけば変換マトリックスの変更だけで対応できるので、単純で明快です。