🤖
節点が同一座標にあるか判定する(C#)
動機
- 節点が同一座標にあることが判定できると、フリーエッジを特定したり、ソリッド表面にNullシェルを自動で作成できたり何かと便利です。
- ただ当然NodeクラスとかShellクラスなんて言う、CAEでよく使う概念はありません。
- ユーザー定義でつくればいいわけですが、ユーザー定義は参照型だから値型のintやfloatみたいにいきません。
- 例:1==1はtrue 1==2はfalse だけど
class Node:
{
public int ID {get;set;}
public Vector3 Crd {get; set;}
public Node(int _ID,Vector3 _Crd)
{
this.ID=_ID;
this.Crd=_Crd;
}
}
- みたいにNodeクラスを作って
var P1 = new Node(1,Vector3(1,1,0));
var P2 = new Node(2,Vector3(1,1,0));
- P1==P2はfalseになります。(別のインスタンスなので)
今回やること
- 3次元空間にある点P1と点P2が同一座標にあるか判別できるようにする。
- イメージ:P1(1,1,0)==P2(1,1,0)ならtrue 、P1(1,1,0)==P2(1,2,1)ならfalseになる
- これを実現するために、上に書いたNodeクラスのEqualsメッソドとGetHashCodeメッソドをオーバーライドします。
public override bool Equals(object other)
{
if (other == null || this.GetType() != other.GetType())
{
return false;
}
var _other = other as NODE;
return this.Crd.X == _other.Crd.X &&
this.Crd.Y == _other.Crd.Y &&
this.Crd.Z == _other.Crd.Z;
}
public override int GetHashCode()
{
return this.Crd.X.GetHashCode() ^
this.Crd.Y.GetHashCode() ^
this.Crd.Z.GetHashCode();
}
- Equalsメソッドは、そのクラスのインスタンスがどのようなときに等価になるかを設定しています。
- GetHashCodeメソッドや詳しい内容については、こちらで詳しく書かれています。https://dobon.net/vb/dotnet/beginner/equals.html
- これでp1.Equals(p2)はtrueになります。しかしやりたいのは、p1==P2です。
- そのためには==と!= オペレーターもオーバーライドする必要があります。
public static bool operator == (EAGE lhs, EAGE rhs)
{
if (lhs is null)
{
if (rhs is null)
{
return true;
}
// Only the left side is null.
return false;
}
// Equals handles case of null on right side.
return lhs.Equals(rhs);
}
public static bool operator !=(EAGE lhs, EAGE rhs) => !(lhs == rhs);
- 上のコードはこちらからそのまま持ってきました。https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/how-to-define-value-equality-for-a-type
- これでようやくP1==P2でtureになります。
- ただ、並進や回転して座標変換すると数値誤差で一致しなくなってしまいます。
なのでEqualsメソッドを私は、こんな感じにしてます。
public override bool Equals(object other)
{
if (other == null || this.GetType() != other.GetType())
{
return false;
}
var _other = other as NODE;
//閾値の0.001は適当な値にしてください
return this.Crd.X - _other.Crd.X < 0.001 &&
this.Crd.Y - _other.Crd.Y < 0.001 &&
this.Crd.Z - _other.Crd.Z < 0.001;
}
今後
- 今回の方法を使っていけば、ShellメッシュのフリーエッジやSolidメッシュの表面メッシュを取り出すことができますので、今後紹介していこうと思います。
Discussion