2016-11-10 3 views
0

Ich habe eine Sammlung von StreamGeometrys. Jede StreamGeometry kann eine beliebige Form haben. Ich möchte nur die StreamGeometrys abholen, die Linien sind. Wie kann ich wissen, dass eine StreamGeometry eine Linie ist?Wie man eine StreamGeometry kennt ist eine Linie

Hintergrund: Ich bekomme Sammlung von StreamGeometrys von einer Schnittstelle. Die Schnittstelle wird von einem anderen Team gegeben und gibt nicht die Information zurück, was die Geometrie ist. (Ich kann mit ihnen diskutieren, um ein Update zu machen, aber es beinhaltet die Änderung der Architektur.) Ich habe eine Funktion, um die Geometrien zu gruppieren und die Umrisse der Gruppe zu erhalten. Ursprünglich füge ich sie zu einer GeometryGroup hinzu und verwende dann Geometry.GetOutlinedPathGeometry, um den Umriss der GeometryGroup zu erhalten. Das Verhalten ist gut.

Problem: Wenn die Geometrys Zahl jedoch auf mehr als 200 erhöht wird, wird GetOutlinedPathGeometry extrem langsam.

Aktuelle Lösung: Dann muss ich einen Kompromiss machen, um eine Kontur nicht so genau zu bekommen. Anstelle von GetOutlinedPathGeometry verwende ich Geometry.Combine, um die Geometry zu kombinieren. Geometry.Combine wird hauptsächlich für geschlossene Geometrie verwendet. Wenn eine Geometrie nicht geschlossen ist, findet sie die nächsten Punkte, um sie zu schließen. Dieses Verhalten reduziert die Komplexität der gesamten Gliederung, dass GetOutlinedPathGeometry ein Ergebnis schneller erhalten kann.

Wie ich auf diese Frage bekommen: Aber ein Problem ist, dass Geometry.Combine wird Linienformen wegzulassen. Nach dem Kombinieren aller Geometrien sind Linien nicht in der Gruppe. Also möchte ich diese Linien finden und GetOutlinedPathGeometry verwenden, um zuerst ihre Umrisse zu erhalten. Dann benutze ihre Umrisse, um sie mit anderen zu kombinieren.

Auch, auch ich habe die Geometrie Typ Informationen, es konnte nicht zu viel helfen. Da in "Geometry.Combine" keine Linienformen enthalten sind, die aus einem beliebigen Geometrietyp erstellt werden können. Line, Path even Rectangle können alle eine Linienform haben.

Andere Versuche: Ich habe versucht, GetOutlinedPathGeometry zu verwenden, um Kontur für jede Geometrie zuerst zu erhalten, dann zu kombinieren. Die Leistung verbessert sich ein wenig, aber immer noch sehr langsam.

+2

Zu wenig Kontext. Woher kommen Ihre 'StreamGeometry' Objekte? Warum weißt du nicht schon welche Linien? Warum ist es wichtig, dass Sie wissen, welche Linien sind? Sie scheinen das [XY-Problem] zu haben (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) ...Was versuchst du eigentlich zu tun, und wie hast du dich in eine Situation gebracht, in der du Informationen brauchst, die das Objekt normalerweise nicht bietet? Bearbeiten Sie Ihre Frage so, dass sie eine gute [mcve] enthält, die den Kontext anzeigt und _speziell_ erklärt, was Sie versucht haben und warum das nicht funktioniert hat. –

+1

Ich bin wirklich hart gedrängt, irgendwelche Fragen zu finden, die @PeterDuniho nicht ausgelöst hat, außer vielleicht, was deine Lieblingsfarbe ist ... – Noctis

+1

Meine Lieblingsfarbe ist transparent. Kannst du mir jetzt helfen? –

Antwort

1

Geben Sie diesen Code einfach ein und Sie können StreamGeometry.IsLine() verwenden, um nach Zeilen zu suchen.

public static class StreamGeometryExtensions 
{ 
    public static bool IsLine(this StreamGeometry sg, double sampleRate = 0.2, decimal tolerance = 0 
    { 
     PathGeometry g = sg.GetFlattenedPathGeometry(); 
     if (g.MayHaveCurves()) 
     { 
      return false; 
     } 

     Point origin, originTangent; 
     Point end, endTangent; 
     g.GetPointAtFractionLength(0, out origin, out originTangent); 
     g.GetPointAtFractionLength(1, out end, out endTangent); 

     Vector originToEnd = end - origin; 

     for (double i = 0; i < 1; i += sampleRate) 
     { 
      Point current, currentTangent; 
      g.GetPointAtFractionLength(i, out current, out currentTangent); 

      Vector currentToEnd = end - current; 
      Vector originTocurrent = current - origin; 

      decimal l1 = (decimal)(originTocurrent.Length + currentToEnd.Length); 
      decimal l2 = (decimal)originToEnd.Length; 

      if (Math.Abs(l2 - l1) > (l2 * tolerance)) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
} 

der Code „samples“ der Weg jedes X% (Beispiel 0,2 = 20%) und überprüft, ob der Ursprung, das Ende und die aktuellen Abtastpunkt auf einer Linie.

Der Code ist eine sehr allgemeine Lösung des Problems und kann für bestimmte Szenarien optimiert werden, in denen die Leistung wichtig ist.

gemessen ich die Leistung für folgende Strecken: (sample = 0,2, Toleranz = 0)

<Path Data="M 217,172 L 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300"></Path> 
    <Path Data="M 217,172 L 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20"></Path> 
    <Path Data="M 217,172 L 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300"></Path> 
    <Path Data="M 217,172 L 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300"></Path> 
    <Path Data="M 217,172 L 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300, 10 50, 50 30, 70 40, 100 300 10 50, 50 30, 70 40, 100 300"></Path> 
    <Path Data="M 217,172 L 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20, 20 20"></Path> 

Auf einem i7 4790 bekam ich diese Zeiten:

80µs - False 
390µs - True 
86µs - False 
82µs - False 
69µs - False 
355µs - True 
+0

Danke. Es scheint die einzige Möglichkeit zu sein, StreamGeometry auf eine Zeile zu prüfen. –

Verwandte Themen