ezdxfを使ってみよう#4～寸法編～

この章では寸法線の描画についてまとめます。

前章はこちら：[#3～レイヤー・dxfattribs 図形の属性・描画の補足編～](https://qiita.com/Rai-see/items/294a36b84ae13eb1077f)
次章はこちら：[#5～実践！自動作図編～](https://qiita.com/Rai-see/items/51dcea8f496b58c41989)

1. **寸法の注意点**
1. **直線の寸法**
1. **半径・直径の寸法**
1. **角度の寸法**
1. **弧の長さの寸法**

## 寸法の注意点 ##
寸法の文字や矢印の大きさ・位置・種類は下記の様に**dimstyles**で定義されます。
```Python:dimstyles.add
doc.dimstyles.add("my_radiusdim", dxfattribs={"dimtxt":20, "dimtad":1, "dimtmove":2, "dimatfit":1, "dimfxl":10})
```
属性は
とても種類が多い上、寸法は環境により再現が左右されるので、各リンクを参照していただきたいです。


matplotlibで寸法線を確認するためには **.render()** が必要になります。他の図形とは異なりますね。

## 直線の寸法 ##
### Liner Dimension ###
```Python:linear_dim
dim1 = msp.add_linear_dim(
    base=(1, 2), #寸法線の位置
    p1=(0, 0), #1点目
    p2=(3, 1), #2点目
    angle=0, #角度
    dimstyle="EZDXF", #寸法線のスタイル
).render()

dim2 = msp.add_linear_dim(
    base=(4, 4), 
    p1=(3, 0), 
    p2=(3, 4),  
    angle=90,
    dimstyle="EZDXF", 
).render()

dim3 = msp.add_linear_dim(
    base=(6, 6),  
    p1=(2, 0),  
    p2=(5, 4),  
    angle=45,
    dimstyle="EZDXF",  
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/e2e35825-c0f8-24a4-4d27-30b25c6ce607.png)


標準的な寸法線ができましたね、**水平垂直部はこのメソッドで十分**かと思われます。
しかし、以下の留意点があるため部分的に次のメソッド**add_aligned_dim**を用いるのが良いかなと考えられます。

### Linerの留意点 ###
- 寸法線の位置を指定するbaseは絶対座標です。**水平垂直以外ではコントロールしにくい**難点がありますし、def関数などで量産する場合は、変数を交える必要があります。
- baseに表現不可能な座標値が与えられ場合は可能な範囲で表示される
（例えば水平な寸法線のbaseに(1,2)を設定してもy軸の2のみしか採用されません※angle=0の場合）
- Linerは**対象の角度の変更に追随できない上、水平垂直以外は計測対象の角度を正確にangleに入力する必要があります。** それに加えて正確な絶対座標にbaseを設定する必要があります。例えば32.5°の直線に対して文字をオフセットできる(x,y)は？という計算が発生してしまいます。
（そこに手計算や計算用コードを書いて対応するよりも、CADで書いた方が正直早い場合もあるかと）

なお、寸法線のスタイルについては[#1:dimstyles　寸法線は12種類](https://qiita.com/Rai-see/items/aebf4587f7a9b30e3ab1#dimstyles%E5%AF%B8%E6%B3%95%E7%B7%9A%E3%81%AF12%E7%A8%AE%E9%A1%9E)を参照ください。

## Aligned Dimension ##
```Python:aligned_dim
dim = msp.add_aligned_dim(
    p1=(0, 5),  # 1点目
    p2=(2, 3),  # 2点目t
    distance=2, #寸法線の離れ
    dimstyle="EZDXF",  # 寸法線のスタイル
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/4bf95439-42e3-9422-4b7e-34138d57c6ae.png)

Liner Dimensionとの違いは、**p1とp2を結ぶ線に平行な寸法線を描画する**点です。
その特徴により以下の点において異なる部分がでてきます。
- **角度の変更に追随できるので**、斜辺長の計測が容易である(Linerは斜辺の角度を取得しないと正確に計測できない上に変更に追随できない)
- 斜線に対してAlignedは**斜辺長のみを計測する**（Linerは同一の２点を抑えて寸法線を描画した場合、angleによって底辺・高さ・斜辺長を計測できる）
- Linerの様に**足の長さの異なる寸法線は描画できない**
### 文字列や固定値の表示 ###

寸法線に文字列や固定した数値の表示などもできます。正確な寸法を表示できない大人の事情にも対応できます。

```Python:文字列や固定値の表示
dim = msp.add_aligned_dim(
    p1=(0, 5),  # 1点目
    p2=(2, 3),  # 2点目t
    distance=2, #寸法線の離れ
    dimstyle="EZDXF",  # 寸法線のスタイル
    text="Hello ezdxf 123m" #表示したい文字列
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/289d51b1-4e5d-72d7-97c7-17a8dbd5d347.png)

### 直線の寸法まとめ ###
Liner Aligned双方の特徴として、形状が複雑になると寸法線同士を揃えづらくなることがあげられます。
仕様上仕方がないのですが、それぞれのメソッドで描画される寸法線の高さを全て計算して揃えるくらいなら、
大量生産しない限り**最後にCADで手動で寸法線を調整した方がいいかなと思います。**
なお、グリッド的に連続的な寸法線を作れるメソッドがありますが、あまり実用性が感じられないので、リンクだけ張っておきます。
[チュートリアル：Tutorial for Ordinate Dimensions](https://ezdxf.readthedocs.io/en/stable/tutorials/ordinate_dimension.html)

寸法線は他にも微細な設定が可能ですが、手作業で最終調整が必要だったりCADによって設定が吹き飛んだりする寸法では、あまり出番がなさそうなので割愛しますの。こちらもリンクをご覧ください。
[チュートリアル：Tutorial for Linear Dimensions](https://ezdxf.readthedocs.io/en/stable/tutorials/linear_dimension.html#tutorial-for-linear-dimensions)

## 半径・直径の寸法 ##
### 半径 ###
```Python:add_radius_dim
msp.add_circle((0, 0), radius=3) #比較用の円を描画
msp.add_radius_dim(
    center=(0, 0),
    radius=3,
    angle=45,
    dimstyle="EZ_RADIUS"
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/2443ecc4-67ab-f6b4-1af0-83f96c1f8137.png)

円の書き方とほとんど一緒の考えですね。angleで寸法の表示位置を指定します。

同様に微細な設定については[チュートリアル：Tutorial for Radius Dimensions](https://ezdxf.readthedocs.io/en/stable/tutorials/radius_dimension.html#tutorial-for-radius-dimensions)をご覧ください。

### 直径 ###
```Python:add_diameter_dim
msp.add_circle((0, 0), radius=3) #比較用の円を描画  
msp.add_diameter_dim(
    center=(0, 0),
    radius=3,
    angle=45,
    dimstyle="EZ_RADIUS"
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/7a9d0a0a-829f-21ed-a78e-dfe95de64b2a.png)

半径とメソッド以外は同じですが、寸法値の描画されるところに違いがあるようです。45°が起点で対極の終点に寸法値が来るイメージでしょうか。

同様に微細な設定については[チュートリアル：Tutorial for Diameter Dimensions](https://ezdxf.readthedocs.io/en/stable/tutorials/diameter_dimension.html#tutorial-for-diameter-dimensions)をご覧ください。

## 角度の寸法 ##

### CRA:中心点・半径・起点角・終点角を指定する ###
```Python:add_angular_dim_cra（公式引用）
msp.add_angular_dim_cra(
    center=(5, 5),  # center point of the angle
    radius= 7,  # distance from center point to the start of the extension lines
    start_angle=60,  # start angle in degrees
    end_angle=120,  # end angle in degrees
    distance=3,  # distance from start of the extension lines to the dimension line
    dimstyle="EZ_CURVED",  # default angular dimension style
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/11326263-0c26-8364-dc8a-431fd503ac86.png)

### ２線内角Angle by 2 Lines ###
```Python:msp.add_angular_dim_2l
base = (5.8833, -6.3408)  # location of the dimension line
p1 = (2.0101, -7.5156)  # start point of 1st leg
p2 = (2.7865, -10.4133)  # end point of 1st leg
p3 = (6.7054, -7.5156)  # start point of 2nd leg
p4 = (5.9289, -10.4133)  # end point of 2nd leg

dim = msp.add_angular_dim_2l(
    base=base,  # defines the location of the dimension line
    line1=(p1, p2),  # start leg of the angle
    line2=(p3, p4),  # end leg of the angle
    dimstyle="EZ_CURVED",  # default angular dimension style
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/42d23016-2a8d-1c1f-5a06-2ccc4d565444.png)

### ３点内角Angle by 3 Points ###
```Python:add_angular_dim_3p
msp.add_angular_dim_3p(
    base=(0, 7),  # location of the dimension line
    center=(0, 0),  # center point
    p1=(-3, 5),  # end point of 1st leg = start angle
    p2=(3, 5),  # end point of 2nd leg = end angle
).render()
```
Auto-CADでは正常に表現されますが、別のCADやmatplotlibでは意図しない寸法になることもあるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/77142a1a-6d8a-09fd-978a-ea15c7dabb0f.png)
成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/64cc3661-3f68-a3d0-a389-50296ab8004c.png)
同じdxfでもなぜか変換できない
### 既存の弧の角度Angle from ConstructionArc ###
```Python:add_angular_dim_arc
#参照用の弧の描画
arc = msp.add_arc(
    center=(0, 0),
    radius=5,
    start_angle = 60,
    end_angle = 120,
)
#弧を読み込み角度寸法を描画
msp.add_angular_dim_arc(
    arc.construction_tool(),
    distance=2,
).render()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/4cbe57a6-2609-657b-b6ca-4e4334d36b5f.png)

既存の弧から寸法が作れるとコーディングが楽ですね。

### 角度寸法まとめ ###

どれも状況に応じて使い分けできるのですが、
強いて違いを書くなら、２線内角と３点内角にはbase（面倒くさい）が採用されています。
**可能な限りCRAかAngle from ConstructionArcを選んで、寸法の離れをdistanceで指定できれば作業しやすい**と思います。
うまく作図されない現象もbaseが関わっている感じがあります。

[チュートリアル：Tutorial for Angular Dimensions](https://ezdxf.readthedocs.io/en/stable/tutorials/angular_dimension.html#tutorial-for-angular-dimensions)

## 弧の長さの寸法 ## 
### CRA:中心点・半径・起点角・終点角を指定する ###
```Python:arc_dim_cra
msp.add_arc_dim_cra(
    center=(5, 5),  # center point of the angle
    radius=5,  # distance from center point to the start of the extension lines
    start_angle=60,  # start angle in degrees
    end_angle=120,  # end angle in degrees
    distance=2,  # distance from start of the extension lines to the dimension line
    dimstyle="EZ_CURVED",  # default angular dimension style
).render()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/b630ff09-7c3a-9c60-74a1-821ad1308c1d.png)

### ３点：中心点と弧の起終点を指定する ###
```Python:add_arc_dim_3p
msp.add_arc_dim_3p(
    base=(0, 7),  # location of the dimension line
    center=(0, 0),  # center point
    p1=(2.5, 4.330127018922193),  # 1st point of arc defines start angle and radius
    p2=(-2.5, 4.330127018922194),  # 2nd point defines the end angle
).render()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/b630ff09-7c3a-9c60-74a1-821ad1308c1d.png)


### 既存の弧を指定する ###
```Python:add_arc_dim_arc
arc = msp.add_arc(
    center=(0, 0),
    radius=5,
    start_angle = 60,
    end_angle = 120,
    dxfattribs={"color":2})

msp.add_arc_dim_arc(
    arc.construction_tool(),
    distance=2,
).render()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705528/6386f4d6-a3d0-d6a6-b8af-803852dbfbf5.png)

### 弧の長さ寸法まとめ ###
角度寸法ととても似ていますね。そして同様に**寸法の離れをdistanceで指定できれば作業しやすい**と思います。

## 寸法まとめ ##

寸法の特徴として、何もないところにはあまり寸法線は生まれないと考えると、**既存の図形や座標の有効活用するコーディング**がスムーズさのカギとなりそうです。

次章では作図編のまとめとして、規格の異なる構造物を連続で作図して、寸法線を配置するコードを作成してみます。

https://qiita.com/Rai-see/items/aebf4587f7a9b30e3ab1

https://qiita.com/Rai-see/items/eb74fcbac53f6a749355

https://qiita.com/Rai-see/items/294a36b84ae13eb1077f

https://qiita.com/Rai-see/items/04a5733e77f791cdaa09

https://qiita.com/Rai-see/items/51dcea8f496b58c41989

https://qiita.com/Rai-see/items/713b106a058da50d7d43