Mycetozoa 開発記録 #4

ナビゲーションメッシュの生成 その②

前回メッシュからTriangleのリストを生成したので、今回はさらにユニークなEdgeのハッシュセットを生成します。

ユニークな辺のハッシュセットを生成する

NavigationMeshGenerator.cs

/// <summary>
/// 生成したTriangleのリストからユニークなEdgeのハッシュセットを生成する
/// </summary>
/// <returns>キャンセルしたか</returns>
private bool CreateEdgeSet()
{
    EditorCommonUtility.ProcessDelegate p = (ref int i) =>
     {
     // sourceEdgeSet は HashSet<Edge>型のメンバ
         foreach (var edge in sourceTriangles[i++].Edges)
             sourceEdgeSet.Add(edge);
     };

    return EditorCommonUtility.ExecuteProcess(p, sourceTriangles.Count, "Creating edge set...", 10);
}

ここで生成したEdgeを格納しているsourceEdgeSetは始点、終点を区別しない比較方法で生成しています。

NavigationMeshGenerator.cs

・・・

/// <summary>
/// 辺の等価性を比較する比較演算子
/// </summary>
private static PositionsEqualityCompare<Edge> edgeLooseCompare = new PositionsEqualityCompare<Edge>(3);

・・・

private HashSet<Edge> sourceEdgeSet;

・・・


/// <summary>
/// コンストラクタ
/// </summary>
public NavigationMeshGenerator()
{

・・・

    sourceEdgeSet = new HashSet<Edge>(edgeLooseCompare);


・・・


}

ここでLooseがついているのはMeshによっては頂点が微妙にずれていることがあるため、ある精度を落として比較しています。

で、PositionsEqualityCompareの実装です。


PositionsEqualityCompare.cs

/// <summary>
/// 点群の位置が等しいかで比較する比較演算子
/// IPositionsEquatable<T>のPositionsEqualsメソッドで比較を行う
/// </summary>
/// <typeparam name="T"></typeparam>
public class PositionsEqualityCompare<T> : IEqualityComparer<T> where T : IPositionsEquatable<T>
{
    /// <summary>
    /// 有効数字
    /// </summary>
    public int SignificantFigures { get; private set; }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="significantFigures"></param>
    public PositionsEqualityCompare(int significantFigures = 0)
    {
        SignificantFigures = significantFigures;
    }

    /// <summary>
    /// 点群の位置が等しいか
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public bool Equals(T x, T y)
    {
        return x.PositionsEquals(y, SignificantFigures);
    }

    /// <summary>
    /// IPositionEquatableのGetPositionsHashCodeメソッドが呼ばれる
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public int GetHashCode(T obj)
    {
        return obj.GetPositionsHashCode(SignificantFigures);
    }
}

ついでにPositionsEqualityCompareの制約となっているIPositionsEquatableの実装です。
これは複数の点群をその性質を問わず座標だけを見て比較する方法を実装します。


IPositionsEquatable.cs

/// <summary>
/// 点群の位置を比較する方法を実装するインターフェース
/// 辺や三角形の方向を考慮せず、全ての座標が一致するかで判定する
/// 有効桁数を指定することが可能
/// </summary>
public interface IPositionsEquatable<in T>
{
    /// <summary>
    /// 点群の位置を比較する
    /// </summary>
    /// <param name="other">比較対象</param>
    /// <param name="significantFigures">有効桁数 デフォルトで0(指定なし)</param>
    /// <returns>等価かどうか</returns>
    bool PositionsEquals(T other, int significantFigures = 0);
    /// <summary>
    /// 点群の位置からハッシュ値を生成する
    /// </summary>
    /// <param name="significantFigures">有効数字</param>
    /// <returns>ハッシュ値</returns>
    int GetPositionsHashCode(int significantFigures = 0);
}


次回は生成したユニークな辺上に分割する点を挿入する処理を書きます。