2013-02-03 21 views
6

Sono nuovo di C# e sta avendo difficoltà a calcolare lo scafo convesso. C# ha una sorta di libreria matematica per questo? Altrimenti, suppongo che dovrò solo implementare il mio.Libreria scafo convesso

+0

Molto primo successo in google per 'C# convesso '- http://www.codeproject.com/Articles/29275/Convex-Hull. Hai fatto qualche ricerca? –

+1

sì, l'ho visto. La mia domanda era se C# ha una libreria già esistente per questo ... – Owen

risposta

3

Ecco un algoritmo di scafo convesso 2D che ho scritto utilizzando l'algoritmo Monotone Chain, a.k.a Algoritmo di Andrew.

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; 
} 

Essa si basa su alcune cose che si suppone che esistano, vedi il mio blog post per i dettagli.

1

Di seguito è una traslitterazione a C# della stessa sorgente Java utilizzata nella risposta di Qwertie ma senza una dipendenza da classi non standard oltre una classe Point con campi doppi.

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

Ho confrontato molti algoritmi/implementazioni di Scafo convesso con tutto il codice fornito. Tutto è incluso in un articolo CodeProject.

Algoritmo rispetto:

  • catena Monotono
  • MiConvexHull (triangolazioni di Delaunay e Voronoi maglie)
  • Graham scansione
  • Chan
  • Ouellet (la mia)

articoli:

+0

@ephraim, grazie mille per avermelo segnalato. Al momento sto guardando quel caso! –

+0

@ephraim, dove hai avuto il bug, in quale articolo? Non riesco a riprodurlo con il codice del mio ultimo articolo? Hai un suggerimento su come posso vedere il bug da solo? 1 000 000 test con 4 punti (che dovrebbe risultare in 1 punto per quadrante una volta ogni tanto) con tutti gli agloritmi di Ouellet e nessun errore/eccezione? –

+0

@ephraim, Trovato bug! Grazie mille! Era solo nel primo articolo. l'articolo con la correzione dovrebbe essere disponibile molto presto (sarà in cantiere tra 15 minuti e sarà disponibile se approvato da CodeProject ~ probabilmente oggi) –