==================================================発行部数1017=====
     AutoCADカスタマイズ入門講座              No.28 1999/12/12
===================================================================
 AutoCADカスタマイズ入門講座をご購読頂きありがとうございます。
さて、皆さんの職場や家庭ではもう2000年問題への対応はお済みですか?。
既に会社規模のシステムでは対応なされていると思いますが、例えばあなた
が日頃会社や家庭で使用しているパソコンはどうでしょうか?。ハード/ソ
フトとももう一度確認してみる事をお勧めします。家の中にもよく見ると日
付を管理している電化製品っていっぱいありますよね?。私の家で使ってい
るVTRはもう古いのでかなり心配です。え、メーカーのHPとかで調べろって
。確かにそうなのですが、めんどくさくて...^^;。
 という訳で、私もプログラマの端くれなので年末2000年対応モードに入ら
なければなりません。まぁ、きっと何にも起こらないと思いますが、備えあ
れば憂い無しという感じです。この様な事から本年中の発行は今回で最後と
させて頂きます。年明けは1/16日からの発行を予定しています。

--------------------------------------------------------------------
 1.直線の重なり方を考える
--------------------------------------------------------------------
 さて、今回は始めに直線の重なり方を考えてみましょう。直線の重なり方
には次の様な重なり方があると思います。
 @一方の直線の始点、終点間にもう一方の直線の始点終点が完全に入って
  しまうパターン。
 A2直線が完全に重なるパターン。
 B一方の直線の始点、終点間にもう一方の直線の始点または終点の一方の
  みが入るパターン。
 C一方の直線の始点、終点どちらか一方と、もう一方の直線の始点、終点
  のどちらか一方の座標が完全に一致する場合。

 2直線のマージを行う場合は上記のパターンを考慮する必要があります。
まず@、Aのパターンの2直線をマージする場合は簡単です。そう、@の場
合は短いほうの直線を、Aの場合はどちらか一方の直線を削除するだけです
。Bのパターンの2直線をマージする場合には、マージする2直線を最初に削
除した後、2直線の交わっていないほうの端点を始点、終点として直線を引
けば良いでしょう。または、2直線の交わっていないほうの端点と、2直線の
交点を使用して2直線を引くという方法も考えられます。Cのパターンにつ
いてですが(Bのパターンについても言える事ですが)、これを一つの直線
にするかどうかは皆さんの考え方によります。設計者の意図によって2つの
直線に分割されているという可能性は十分あると思います。

--------------------------------------------------------------------
 2.最後に
--------------------------------------------------------------------
 前回添付したプログラムから2つの直線を選択すると、2直線の重なり具合
を示すメッセージがプロンプト領域に表示されます。このプロンプトを良く
見るとどの様に2つの直線が重なっているのかが良く分かります。
 申し訳ございませんが、実際にマージを行う部分の作成については皆さん
の方でチャレンジしてみて下さい。上で示したパターンに従って実装してい
けば、それほど難しくはないと思います。2つの直線をマージするプログラ
ムが出来れば、後は複数の直線同士の比較を行う処理を加えるだけです。複
数の直線の扱いについては、以前作成したmchange.lspなどが参考になると
思います。もちろん、複数の直線同士を比較する場合はwhile文等でループ
を作りうまく直線同士を比較する必要があります。

 中途半端なプログラムになってしまい非常に残念なのですが、merge.lsp
の解説は今回で最後になります。私もマガジンの発行を休んでいる間に実際
にマージする部分を作ってみようと思いますので、ぜひ皆さんも挑戦してみ
て下さい。

 それではまた来年お会いしましょう (^_-)/ 。

○ちょっとだけ変更してあります。
(defun C:merge()
  ; 2つのエンティティを選択
  (setq name1 (car (entsel "最初の直線を選択して下さい:")))
  (setq name2 (car (entsel "2本目の直線を選択して下さい:")))

  ; 2直線の始点、終点を得る
  (setq p10 (cdr (getprop name1 10)))
  (setq p11 (cdr (getprop name1 11)))
  (setq p20 (cdr (getprop name2 10)))
  (setq p21 (cdr (getprop name2 11)))

  ; 2直線の作図角度を得る
  (setq ang1 (angle p10 p11))
  (setq ang2 (angle p20 p21))

  ; 求めた2直線の作図角度を補正する
  ; 作図角度 < π
  (setq ang1 (mangle ang1))
  (setq ang2 (mangle ang2))

  (setq eps 1e-3)   ; 許容値
  
  ; 作図角度の判定
  (if ( < (abs (- ang1 ang2)) eps)
    (progn
    (print "作図角度は同一です")
    ; 2直線に直行する直線の準備
    ; 始点p10、終点p30の直線を設定する
    (setq p30 (polar p10 (+ ang1 (/ pi 2.0)) 1.0))

    ; 2直線と垂線の交点を求める
    (setq intp1 (inters p10 p11 p10 p30 nil))
    (setq intp2 (inters p20 p21 p10 p30 nil))

    ; 交点間の距離を求め、許容値以下か判定
    (if (< (distance intp1 intp2) eps)
      (progn
        (print "直線間の距離は許容値以下です")
        ; チェック用変数を初期化
        (setq ch01 0)
        (setq ch02 0)
        (setq ck1 0)
        (setq ck2 0)
        (setq ck3 0)
        (setq ck4 0)
        ; 直線1のx座標の範囲を求める
        (if (< (car p10) (car p11))
           (progn
              (setq max1 (car p11))
              (setq min1 (car p10))
           )
           (progn
              (setq max1 (car p10))
              (serq min1 (car p11))
           )
       )
       ; 直線2のx座標の範囲を求める
        (if (< (car p20) (car p21))
           (progn
              (setq max2 (car p21))
              (setq min2 (car p20))
           )
           (progn
              (setq max2 (car p20))
              (serq min2 (car p21))
           )
       )

       ;直線1,2の端点同士が完全に一致するかどうかをチェック
       ;しておく
       (if (< (abs (- min1 min2)) eps)
           (progn
	      (setq ck01 1)
              (print "2直線の始点は完全に一致しています")
           )
       )
       (if (< (abs (- max1 max2)) eps)
           (progn
               (setq ck02 1)
               (print "2直線の終点は完全に一致しています")
           )
       )

       ; 直線1のx座標の範囲に、直線2の始点、終点のx座標が
       ; 入るかどうかをチェックする
       (if (and (= ck01 0) (= ck02 0))
       (progn 
       (if (and (< min1 min2) (< min2 max1))
          (progn
             (setq ck1 1)
             (print "min2はマージ後の直線に使われません")
          )
          (print "min2をマージ後の直線に使用します")
       )
       (if (and (< min1 max2) (< max2 max1))
          (progn
             (setq ck2 1)
             (print "max2はマージ後の直線に使われません")
          )
          (print "max2をマージ後の直線に使用します")
       )
       ; 直線2のx座標の範囲に、直線1の始点、終点のx座標が
       ; 入るかどうかをチェックする
       (if (and (< min2 min1) (< min1 max2))
          (progn
             (setq ck3 1)
             (print "min1はマージ後の直線に使われません")
          )
          (print "min1をマージ後の直線に使用します")
       )
       (if (and (< min2 max1) (< max1 max2))
          (progn
             (setq ck4 1)
             (print "max1はマージ後の直線に使われません")
          )
          (print "max1をマージ後の直線に使用します")
        )
        )
       )
      )
    )
    )
  )
  (terpri)
)

;---------------------------
; 属性取得関数
;---------------------------
(defun getprop(entname grpcode / elist)
  (setq elist (entget entname))
  (assoc grpcode elist)
)

;------------------------------------------
; π以上の角度をπ以下の角度に補正する関数
;------------------------------------------
(defun mangle(angle / i)
  (setq i 0)
  (while (= i 0)
    (if (> angle pi)
      (setq angle (- angle pi))
      (setq i 1)
    )
  )
  (setq angle angle)
)



●バックナンバーは下記のURLで参照する事が出来ます。
http://www2u.biglobe.ne.jp/~Saturn5/alisp.htm
====================================================================
■登録/解除の方法
http://www2u.biglobe.ne.jp/~Saturn5/alisp.htm
「AutoCADカスタマイズ入門講座」は、上記URLよりいつでも
登録/解除可能です。
====================================================================
●広告の問い合わせ
広告のお問い合わせは以下のメールアドレスへお願いします。
wankichi@mba.nifty.ne.jp
====================================================================
■「AutoCADカスタマイズ入門講座」No.26
発行責任者 :わんきち(wankichi@mba.nifty.ne.jp)
発行システム:インターネットの本屋さん『まぐまぐ』
              http://www.mag2.com/
              マガジンID:0000011579
====================================================================