0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ふくらみを持ったポリラインから、円弧情報を得る

Last updated at Posted at 2023-10-19

ふくらみを持ったポリラインとは?

AutoCAD では、ポリラインに円弧の曲線を含ませることができます。
「ポリラインって通常は連続直線の事でしょ?」
と思われるかもしれませんが、そういう事が出来る仕組みなのです。

ふくらみを持ったポリラインの実物

ふくらみを持ったポリラインで作図された図形の例は、下図の通り。
image.png
このふくらみを持ったポリラインのエンティティ情報は、下記の通りです。

ふくらみを持ったポリラインのエンティティ情報
(0 . "LWPOLYLINE")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbPolyline")
(90 . 4)
(70 . 0)
(43 . 0.0)
(38 . 0.0)
(39 . 0.0)
(10 8.45388 11.8955); 1点目座標
(40 . 0.0)
(41 . 0.0);  ↑
(42 . 0.0); ← ふくらみ(bulge)がゼロなので、この間は直線
(91 . 0);   ↓
(10 15.2163 13.7794); 2点目座標
(40 . 0.0)
(41 . 0.0);     ↑
(42 . -0.279508); ← ふくらみ(bulge)がゼロではないので、この間は円弧
(91 . 0);      ↓
(10 21.081 12.1347); 3点目座標
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(10 26.1977 5.88499); 4点目座標
(40 . 0.0)
(41 . 0.0)
(42 . 0.0)
(91 . 0)
(210 0.0 0.0 1.0)

エンティティ名やハンドル等の、オブジェクト固有のエンティティは、削除しています。
ふくらみを持ったポリラインの円弧部分の情報は

  • 始点座標
  • 終点座標
  • ふくらみ

の3つです。
この始終点とふくらみの情報を元に、円弧のエンティティを生成したいのです。

円弧のエンティティ情報

対する円弧オブジェクトの情報について。
実際にarcコマンドで円弧を作図する際は

  • 始点、中間点、終点の3点を指定する方法
  • 中心点、始点、終点の3点を指定する方法(終点の代りに角度や弦長で指定も可能)

等がありますが、作図方法に関わらず実際の図形のエンティティ情報は、下記の様になっています。

円弧のエンティティ情報
(0 . "ARC")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbCircle")
(10 36.4711 12.3291 0.0); 中心点
(40 . 3.64553); 半径
(210 0.0 0.0 1.0)
(100 . "AcDbArc")
(50 . 2.72348); 中心点から見た円弧始点の角度(ラジアン)
(51 . 6.22984); 中心点から見た円弧終点の角度(ラジアン)

始点から終点に向けて、反時計回りで作図されます。
円弧を作図するうえで必要なデータは

  • 中心点
  • 半径
  • 始点角度
  • 終点角度

の4つです。

ふくらみとは?

ふくらみとは何ぞや? という問いに答えられるほど、私の知識は豊富ではありません。
算数を少しかじった程度です。
ですので、下記の情報が非常に参考になりました。

ふくらみとは何ぞや?はこのサイトで理解して頂ければと思います(無責任ですみません)。
少なくとも私が理解できたのは
ふくらみがマイナスの場合は時計回りの円弧になるから、始終点を入れ替えないと正しい円弧情報にならない
ということぐらいです。

実際に円弧情報を取得してみよう

最初に考えた、頭悪いやり方

という訳で、いきなり LISP のコードです。
引数として

  • 始点座標
  • 終点座標
  • ふくらみ

を渡すことで

  • 中心座標
  • 半径
  • 始点角度
  • 終点角度

をリストで返します。

始終点とふくらみから円弧情報を取得(旧版)
;始終点とふくらみから円弧情報(中心座標、半径、開始角度、終了角度)を取得
(defun bulge_to_arc (
  s_point ;始点座標
  e_point ;終点座標
  bulge ;ふくらみ
  /
  s_temp
  e_temp
  ang_temp
  dist_temp
  r_dist
  d_point
  c_point
  )

  (if (minusp bulge)
    (setq s_temp e_point e_temp s_point)
    (setq s_temp s_point e_temp e_point)
  );if
  (setq
    ang_temp (atan (abs bulge))
    dist_temp (/ (distance s_temp e_temp) 2.0)
    r_dist (/ (* dist_temp (+ 1.0 (expt bulge 2.0))) (* 2.0 (abs bulge)))
  );setq
  ;円弧の中心座標取得
  (setq
    d_point (inters s_temp (polar s_temp (- (angle s_temp e_temp) ang_temp) 1.0) e_temp (polar e_temp (+ (angle e_temp s_temp) ang_temp) 1.0) nil)
    c_point (polar d_point (+ (angle s_temp e_temp) (/ PI 2.0)) r_dist)
  );setq
  (list c_point r_dist (angle c_point s_temp) (angle c_point e_temp))

);defun

なんかもっとスマートに算出できる方法がありそうですが、私の頭ではこれが限界でした・・・
半径「r」の算出は、先の参考サイトの式をそのまま流用しています。
面倒だったのは中心座標を求める所。参考サイトの「D点」を求めてから、始終点角度に垂直な「r」の距離の点を求める方法で算出しています。
ここはもっと上手いやり方が有りそうです。
始終点角度は中心座標が分かれば簡単です。

もっと良いやり方

先に紹介したサイトにもっとスマートに算出するヒントがあったのに、私が理解していませんでした。
反省も込めて、解説。
image.png図1
先ず、大前提として「ふくらみ(bulge 以下 b)」の定義ですが
b = tan ( θ / 4 ) ・・・①
となります。
半径 r は先の参考サイトにある通りなので省略します。
先の頭の悪いやり方AD 方向の長さが適当な線分と、BD 方向の長さが適当な線分の交点座標をintersで求め、そこからpolarで中心座標を求めるやり方でしたが、交点を求めるというのが如何にも頭が悪いやり方だと思ったのです。
しかし、DE の距離が分かれば、EC の距離もわかるので、その方法で中心座標を求めた方がスマートです。
で、DE 間の距離は既に参考サイトに s として記載されているんですが
tan ( θ / 4 ) = DE / AE ・・・②
①と②から
b = DE / AE
DE = b * AE
AE の長さは、AB の長さの半分、E の座標は AB の中点
どちらも AB の座標が分かっていれば簡単に求められます。
距離は三平方の定理を使わずとも、AutoLISP ならdistance で簡単に求められます。
EC 間の距離は
EC = r - DE
ですから、ここまでわかればpolarで中心座標が求められます。
という訳で、改修したコードです。

始終点とふくらみから円弧情報を取得
;始終点とふくらみから円弧情報(中心座標、半径、開始角度、終了角度)を取得
(defun bulge_to_arc (
  s_point ;始点座標
  e_point ;終点座標
  bulge ;ふくらみ
  /
  s_temp
  e_temp
  ang_temp
  dist_temp
  r_dist
  d_point
  d_dist
  c_point
  )

  (if (minusp bulge) ;ふくらみがマイナスの場合、時計回りなので始点と終点を入れ替える
    (setq s_temp e_point e_temp s_point)
    (setq s_temp s_point e_temp e_point)
  );if
  (setq
    ang_temp (atan (abs bulge)) ; θ/4 を求める
    dist_temp (/ (distance s_temp e_temp) 2.0) ; AE 間の距離を求める
    r_dist (/ (* dist_temp (+ 1.0 (expt bulge 2.0))) (* 2.0 (abs bulge))) ; 半径を求める
  );setq
  ;円弧の中心座標取得
  (setq
    d_dist (* (abs bulge) dist_temp) ; DE 間の距離を求める
    ; E の座標を求める
    d_point (list (/ (+ (car s_temp) (car e_temp)) 2.0) (/ (+ (cadr s_temp) (cadr e_temp)) 2.0))
    c_point (polar d_point (+ (angle s_temp e_temp) (/ PI 2.0)) (- r_dist d_dist)) ;中心点座標を求める
  );setq
  (list c_point r_dist (angle c_point s_temp) (angle c_point e_temp))

);defun

もやもやしてた部分が、ようやくスッキリしました。

終わりに

今までふくらみってよく分からないな、と思っていたのですが、今回なんとなく理解できてよかったです。
まだ完全に理解しきれていないので、もっと精進しないといけないと思いました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?