興味があろうがなかろうが。

なるべく役に立つ、とがった内容を記していきたいと思います。

【FreeCADプログラミング】要素同士の最近距離取得

本日のお題は『要素同士の最近距離取得』です。

ここ最近はかなり特殊なAPIの説明が多くなってきましたが、今回も相当なものです。

1. 環境

  • FreeCAD 0.18

2. 要素同士の最近距離を取得する場面

まさにタイトル通りですが、とある要素同士の最近距離(最短距離)がどの程度か確認する際に使用します。

3. 使用するAPI

Toposhape APIのdistToShapeメソッドを使用します。

4. どうやって使うのか?

以前使用したisSameメソッドと同様、Toposhape APIは継承関係的には、EdgeやFaceの親に当たるもののようなので、『Edge.distToShape(最近距離を測りたい要素)』、『Face.distToShape(最近距離を測りたい要素)』のように書くことで使用することができます。

5. プログラムを書いてみよう

今回は以前使用したGetSelectionExメソッドを使用して2つの要素を選択し、その要素間の最近距離を確認していきます。

# -*- coding: utf-8 -*-

import ptvsd
print("Waiting for debugger attach")
# 5678 is the default attach port in the VS Code debug configurations
ptvsd.enable_attach(address=('localhost', 5678), redirect_output=True)
ptvsd.wait_for_attach()

import FreeCAD
import FreeCADGui

sel = FreeCADGui.Selection.getSelectionEx()

if(len(sel) == 2):
	firstObj = sel[0].SubObjects[0]
	secondObj = sel[1].SubObjects[0]

	result = firstObj.distToShape(secondObj)
	FreeCAD.Console.PrintMessage("①最近距離: " + str(result[0]) + "\n")
	FreeCAD.Console.PrintMessage("②最近距離の計測元位置: " + str(result[1]) + "\n")
	FreeCAD.Console.PrintMessage("③最近距離の計測元のSubShapeとパラメータ: " + str(result[2]) + "\n")

www.interested-or-not.com

6. 実行結果

今回はFreeCADのサンプルデータとして用意されているPartDesignExample.FCStdに少し加工を加えてテストしてみました。

以下のように元々配置されているソリッドの真横に球体を1つ配置しました。

f:id:appli-get:20211209215251p:plain

テストモデルのイメージ

このモデルの『左側の円筒フェース』と『球体のフェース』を両方選択(※)して、マクロを実行します。

※ フェースを複数選択するときはCtrlキーを押しながら選択してください。

マクロの実行結果は以下の通りです。

①最近距離: 219.06293149491046
②最近距離の計測元位置: [(Vector (81.14455690073774, 13.185535227237938, 49.99999999203486), Vector (300.099024931802, 6.292866340840797, 50.000001216277155))]
③最近距離の計測元のSubShapeとパラメータ: [(b'Face', 0, (6.251715785889117, -49.99999999203486), b'Face', 0, (3.1101231279347448, 6.081385769568932e-09))]

②の結果に最近の位置を表す座標が表記されているので、モデル上に点を置いて確認してみましょう。以下のようになりました。

すいません。相当小さくて見づらいですが、円筒面の中心位置と球体の左側に黄色い点があるのが見えますか?

どうやら成功のようです。普通に考えるとここがお互いから見た最近の位置ですね。

そして、この点間の距離が『219.06293149491046mm』となるわけです。

f:id:appli-get:20211209215236p:plain

最近位置として出力された座標に点を置いてみた結果

7. 複数の要素が最近位置になる場合は、結果も複数になる

偶然分かりましたが、APIを実行した際に複数の要素が最近位置になる場合は、②・③の結果が複数になります。

例えば以下のようなモデルを用意します。

f:id:appli-get:20211209221126p:plain

複数の最近位置が取得される例

これで処理を実行すると、以下のような結果が出力されます。

①最近距離: 219.06293149491046
②最近距離の計測元位置: [(Vector (300.0990249318874, 6.292866343553993, 0.0), Vector (81.14455689632862, 13.18553508717689, 0.0)), (Vector (300.09902493361, 6.292866398274115, -5.343411234701294e-07), Vector (81.14455689381991, 13.185535007484166, 1.4070081688653918e-07))]
③最近距離の計測元のSubShapeとパラメータ: [(b'Face', 0, (3.110123127921172, 0.0), b'Edge', 2, 6.251715781510965), (b'Face', 0, (3.110123127647436, -2.671705617350647e-09), b'Face', 0, (6.25171577901986, -1.4070081688653918e-07))]

あえて色を変えましたが、赤色・黄色の2つの結果が出力されているのが分かります。

なぜ2つ出力されたかですが、下記2つの最近距離が同一になるからだと考えています。

  1. 球体フェースと円筒フェースの端部
  2. 球体フェースと円筒フェースの端部のエッジ

8. 3つ目のパラメータは何に使用するか不明

要素同士の最近距離を取得するという命題は解決したわけですが、本APIの3つ目のパラメータ(上の実行結果の③が該当)が何なのか、まだ分かっていません。

公式のAPIリファレンスには以下のように書かれていますが、『list<nearest subshapes & parameters』の部分が現状どうもよく分かりません。

(以下『TopoShape API - FreeCAD Documentation』より引用。

Description: Calculates the minimum distance between this and a given TopoShape.
Returns: float<minimum distance>,list<nearest points>,list<nearest subshapes & parameters>

こちらについては、分かり次第追記します。

おそらく、以前フェースの法線ベクトルを取得する際にUVパラメータを取得しましたが、そのパラメータが入っているのではないかと睨んでいます。ただ、b'Face'の次の0はなんだろう・・・。

www.interested-or-not.com

9. まとめ

  • 要素同士の最近距離を取得するには、distToShapeメソッドを使う。
  • distToShapeは最近距離以外にも、最近の位置と判断された座標も取得できる。
  • distToShapeで出力される最近の位置は複数になることがある。

10. 最後に

いかがでしたか。

最近距離が必要になる場面なんてなかなか想像がつかないかもしれませんが、結構役に立つことがありますので、頭の片隅に入れておいてください。

今度distToShapeを使う演習課題を作ってみたいと思います。お楽しみに。

更なる情報をお探しの方は!

下記のリンクから、FreeCADプログラミングのトップページに飛びます。

よろしければご参照くださいませ。

www.interested-or-not.com