C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

板状に分割したい2

こちらの続きです。
板状に分割したい1 - C#ATIA

あのスクリプトは、もうちょっと汎用的にしようかな?とは
思っているのですが、とりあえず前回の忘れ物です。



処理出来るボディに制限をかけているのですが、そちらを
先に説明します。
"全ての面が平らな面で構成されている事" ですが、こちらは
全ての面のタイプを調べれば良いですね。

    def isAllPlanarFace(body: adsk.fusion.BRepBody) -> bool:
        planeType = adsk.core.Plane.classType()
        if all([f.geometry.classType() == planeType for f in body.faces]):
            return True

        return False

all関数はリスト内の全ての要素が "true" の場合にtrueを返します。
・・・最近覚えました。

もう一つの条件の "完全中空なボディな事" はちょっと言葉の表現
自体が怪しくて申し訳ないのですが、他の表現が思い付かなかった
ので・・・。
添付されているデータの様に、内部の空間が外部の空間と繋がって
いないような形状の事を示したつもりです。

シェル後の形状でも、こんな感じに一部開放している形状は
不都合に感じており、処理対象から外したかったため判断する事に
しました。

    # 完全な中空形状チェック
    if not body.shells.count == 2:
        return

ここのBRepBody.shellsはシェルコマンドとは異なります。
こちらで説明されているBRepShellになります。
Fusion 360 Help
BRepBody.shells.countが2の場合は、内部に1個の空間が
存在して要る事がわかります。

BRepShellの面積を比較して大きい方が外側となりますよね?
シェルで出来上がった形状で、内側の方が面積が大きく
なるパターンを思いつかないので、恐らく大丈夫ですよね。



さて、問題の外面-内面の組み合わせの見つけ方です。
Componentオブジェクトは盛んに利用するのですが、
findBRepUsingRayメソッドを利用すると見つける事が
出来ます。
Fusion 360 Help

名称に"Ray"と付いているので、最初は表示に関する
メソッドの様に感じていました。

正しくは、指定した点から指定したベクトル方向に
ズバッと線を引いた時に、干渉する要素(今回は面)を
返してくれるメソッドです。

返ってくるObjectCollection順番は点から近い順に
なっています。
簡単に言えば、外面で処理すれば一番最初のものが
内側の面になってます。

外側の面上からユニークな点を取得し

            pnt: adsk.core.Point3D = face.pointOnFace

面の法線(ベクトル)をチェックする方向として取得

            geo: adsk.core.Plane = face.geometry
            vec: adsk.core.Vector3D = geo.normal

実際は、法線が外向きになっているはずなので
逆向きにします。

            vec.scaleBy(-1)

Matrix3Dオブジェクトの場合、逆行列用のinvertメソッドが
用意されているのですが、"Vector3Dは逆ベクトル用の
メソッド無いじゃん!" って最初は思ったのですが、
-1倍すれば良いだけなんですよね・・・さすがに覚えました。

但し、あちらのサンプルデータなのですが、底面の一枚だけ
面の法線の向きが逆でした。(理由不明)

これに対応する為、getPairFaces関数内がちょっとゴチャゴチャに
なってます。

CATIA V5だと面の表裏が、先頭の面の向きで都合良くなる様に
整うのですけどね。