2013-02-03 67 views
6

私はC#を初めて使用しており、凸包を計算するのに苦労しています。 C#にはこれのための何らかの種類の数学ライブラリがありますか?そうでなければ、私は自分自身を実装しなければならないと思う。凸包のライブラリ

+0

'C#の凸包のためのGoogleでの非常に最初のヒットを' - http://www.codeproject.com/Articles/29275/Convex-Hull。あなたはどんな研究をしましたか? –

+1

はい、私はそれを見ました。私の質問は、C#にそれのためのライブラリが組み込まれている場合でした... – Owen

答えて

3

ここでは、Monotone Chainアルゴリズム、a.k.a Andrew's Algorithmを使用して書いた2D凸包アルゴリズムです。それが存在すると仮定されているいくつかのものに依存している

public static IListSource<Point> ComputeConvexHull(List<Point> points, bool sortInPlace = false) 
{ 
    if (!sortInPlace) 
     points = new List<Point>(points); 
    points.Sort((a, b) => 
     a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); 

    // Importantly, DList provides O(1) insertion at beginning and end 
    DList<Point> hull = new DList<Point>(); 
    int L = 0, U = 0; // size of lower and upper hulls 

    // Builds a hull such that the output polygon starts at the leftmost point. 
    for (int i = points.Count - 1; i >= 0 ; i--) 
    { 
     Point p = points[i], p1; 

     // build lower hull (at end of output list) 
     while (L >= 2 && (p1 = hull.Last).Sub(hull[hull.Count-2]).Cross(p.Sub(p1)) >= 0) { 
      hull.RemoveAt(hull.Count-1); 
      L--; 
     } 
     hull.PushLast(p); 
     L++; 

     // build upper hull (at beginning of output list) 
     while (U >= 2 && (p1 = hull.First).Sub(hull[1]).Cross(p.Sub(p1)) <= 0) 
     { 
      hull.RemoveAt(0); 
      U--; 
     } 
     if (U != 0) // when U=0, share the point added above 
      hull.PushFirst(p); 
     U++; 
     Debug.Assert(U + L == hull.Count + 1); 
    } 
    hull.RemoveAt(hull.Count - 1); 
    return hull; 
} 

は、私のblog post詳細については参照してください。

1

以下は、Qwertieの回答で使用された同じJavaソースのC#への翻字ですが、非標準クラスには依存しません。

class ConvexHull 
{ 
    public static double cross(Point O, Point A, Point B) 
    { 
     return (A.X - O.X) * (B.Y - O.Y) - (A.Y - O.Y) * (B.X - O.X); 
    } 

    public static List<Point> GetConvexHull(List<Point> points) 
    { 
     if (points == null) 
      return null; 

     if (points.Count() <= 1) 
      return points; 

     int n = points.Count(), k = 0; 
     List<Point> H = new List<Point>(new Point[2 * n]); 

     points.Sort((a, b) => 
      a.X == b.X ? a.Y.CompareTo(b.Y) : a.X.CompareTo(b.X)); 

     // Build lower hull 
     for (int i = 0; i < n; ++i) 
     { 
      while (k >= 2 && cross(H[k - 2], H[k - 1], points[i]) <= 0) 
       k--; 
      H[k++] = points[i]; 
     } 

     // Build upper hull 
     for (int i = n - 2, t = k + 1; i >= 0; i--) 
     { 
      while (k >= t && cross(H[k - 2], H[k - 1], points[i]) <= 0) 
       k--; 
      H[k++] = points[i]; 
     } 

     return H.Take(k - 1).ToList(); 
    } 
} 
1

私は提供されたすべてのコードで多くの凸包アルゴリズム/実装を比較しました。すべてはCodeProjectの記事に含まれています。

アルゴリズムを比較:

  • グラハムが
  • チャンをスキャン

    • モノトーンチェーン
    • MiConvexHull(ドロネー三角形分割をし、ボロノイメッシュ)
    • Ouellet(鉱山)

    の記事:

  • +0

    @ephraim、ありがとう、それを私に報告してくれました。私は現在その場合を見ている! –

    +0

    @ephraim、どこの記事でバグがありましたか?私は最新の記事のコードでそれを再現できないのですか?どのように自分自身でバグを見ることができるかについてのヒントはありますか?すべてのOuelletアルゴリズムで、エラー/例外なしで4点(1分に1点ずつ)を1 000 000テストしますか? –

    +0

    @ephraim、バグが見つかりました!どうもありがとうございます!それは最初の記事にすぎませんでした。訂正の記事はすぐに利用可能になるはずです(15分でパイプラインに入り、CodeProjectによって承認されたときに利用可能になります〜今日) –

    関連する問題