2009-05-08 11 views
18

Ich habe einen Quad-Kurven-Pfad mit der Methode CGPathAddQuadCurveToPoint gemacht. Ich habe den Weg perfekt gefunden. Aber ich möchte alle Koordinatenpunkte kennen, die am Pfad beteiligt sind.Wie bekomme ich alle Punkte in CGPath-Kurve oder Quad-Kurve

Gibt es eine Möglichkeit, alle Koordinatenpunkte in einem Pfad abzurufen?

Wenn nicht, haben Sie eine andere Lösung zum mathematischen Abrufen aller Punkte in einer Kurve.

Vielen Dank im Voraus, Vamshi

+0

Hier ... http://stackoverflow.com/questions/4854035/how-do-i-detect-a-touch-on-a-uibezierpath-and-move-a-ball-along-that/ 4855932 # 4855932 – Fattie

Antwort

0

Eine quadratische Kurve ist genau das - eine Kurve. Es ist unmöglich, eine Liste von der Punkte zu bekommen, weil es unendlich viele Punkte gibt, und es ist kein einfaches Liniensegment.

Eine Liste der Funktionen, mit denen Sie ein Objekt CGPath abfragen können, finden Sie unter Getting Information about Quartz Paths. Leider scheint es, als ob die nützlichste Information, die Sie bekommen werden, ist mit CGPathContainsPoint(), die Ihnen nur sagt, wenn ein bestimmter Punkt innerhalb des Bereichs des Pfades enthalten ist.

+0

Danke für die Antwort .. Ich habe den CGPathContainsPoint() verwendet. Um diese Methode nutzen zu können, müssen wir unseren Weg definitiv schließen. Aber in meinem Fall, wenn ich den Pfad schließe, werde ich nicht den erwarteten Pfad bekommen. Wenn wir alle Punkte zwischen zwei Punkten finden wollen (es wird eine gerade Linie), dann gibt es eine Lösung mit mathematischen Gleichungen. Gibt es eine Lösung für Kurven mit mathematischen Gleichungen oder einem Algorithmus –

1

Wenn Sie an den Elementen moveto, lineto und curveto des Pfads arbeiten möchten, verwenden Sie CGPathApply. Sie übergeben dies einen Zeiger auf eine Funktion in Ihrem Programm, und es ruft diese Funktion einmal pro Element des Pfads auf.

Leider gibt es keine Möglichkeit, einfach nach jedem Element zu fragen, wie es mit AppKits NSBezierPath. Die Funktion ist der einzige Weg.

Wenn Sie jedes durch den Pfad geschnittene Pixel bestimmen möchten, schade - das ist nicht praktikabel, und ich kann nicht einmal daran denken, warum Sie diese Information wollen. Einige Kontexte wie PDF contexts haben nicht einmal Pixel; in diesen Fällen ist jede Frage, die Pixel mit einbezieht, ein Sequitur.

0

Wenn nicht, haben Sie eine andere Lösung zum mathematischen Abrufen aller Punkte in einer Kurve.

Wozu brauchen Sie sie, d. H. Welches Problem versuchen Sie zu lösen? Wenn es zwei Kurven schneiden soll, können Sie dies mathematisch tun. Setzen Sie die beiden Kurvengleichungen gleich und lösen Sie das Unbekannte.

+0

Danke für die Antwort .. Ich habe ein Problem, wo ich ein Objekt (z. B. Person) auf dem Weg verschieben möchte. Ich kann CAKeyFrameAnimation verwenden, um mein Problem zu lösen, wo es die Dauer benötigt. Aber ich habe keine Dauer in meinem Fall. Während das Objekt sich bewegt, muss ich noch andere Operationen an Objekten wie Springen oder Zurückbewegen usw. durchführen. Wenn ich also alle Punkte auf dem Weg kenne, kann ich ihn dazu bringen, sich auf die Punkte zu bewegen, die meine Anforderung erfüllen. –

+0

Ich verstehe das Problem nicht vollständig, aber vielleicht hilft Ihnen der zeitbasierte Weg, dieses Problem zu lösen. Das heißt, bei t = 0 setzt die Pfadgleichung das Objekt auf (x0, y0). Bei t = 1 setzt der Pfad das Objekt auf (x1, y1). Und so weiter. Dann müssen Sie sich nicht an alle Punkte erinnern, sondern berechnen einfach (xi, yi) für den Zeitpunkt t = i. –

0

Ich denke, Sie sind nach etwas ähnlich der Klasse Java2D FlatteningPathIterator. Zum Beispiel gibt Java2Ds path.getPathIterator(null, 1.0) einen Iterator nur von 'lineTo'-Segmenten zurück, selbst wenn der ursprüngliche Pfad curveTo und quadTo hatte, steuert das Doppelargument die' Planheit 'und gibt Ihnen eine einfache Möglichkeit, jeden Punkt auf der Kurve zu berechnen. Ich suche das gleiche in Cocoa, habe aber nichts gefunden. Wenn Sie eine Lösung finden, lassen Sie es mich wissen. Es gibt Kurvenimplementationen (z. B. http://sourceforge.net/projects/curves/), die portiert werden könnten, aber es besteht immer das Risiko, dass, wenn Sie nicht denselben Algorithmus wie Cocoa verwenden, Fehler zwischen Ihrer Interpolation und dem strichenen NSBezierPath/CGPath auftreten können.

14

Sie können dies mit der Wykobi C++ - Bibliotheksroutine für kubische Bezierkurven tun. Wykobis Bibliothek unterstützt auch quadratische Bezier-Kurven.

Natürlich als jemand darauf hingewiesen, dass Sie nicht alle Punkte wollen (obwohl nicht unmöglich, würde es einfach unendlich dauern :).Wykobi macht es einfach, eine bestimmte Anzahl von Punkten zu erhalten - wenn Ihre Startpunkte, c1, c2 und Endpunkte (wo c1, c2 die Kontrollpunkte sind) genau dieselben sind wie die, die CGContextAddCurveToPoint gegeben werden, dann werden die Punkte perfekt liegen auf der von Core-Grafiken gezeichneten Linie - so können Sie beispielsweise ein Muster an mehreren Punkten auf dem Pfad zeichnen.

See: http://www.codeproject.com/Articles/22568/Computational-Geometry-C-and-Wykobi

Auch nachdem ich mit begann wykobi ich gehört, dass es eine ähnliche, vielleicht sogar bessere Bibliothek, die Teil von Boost ist, aber es noch nicht ausgecheckt.

Ich habe eine C++ Class WPoint als Brücke zwischen Wykobi-Punkten und CGPoints (C++ Spaß!) Erstellt. Hier ist ein Code (ohne WPOINT, aber man kann sich vorstellen, dass es genau das gleiche Layout wie ein CGPoint so, wenn Sie die richtige Besetzung tun können Sie leicht umwandeln

 NSMutableArray* result = [[NSMutableArray alloc] init]; 
     wykobi::cubic_bezier<CGFloat,2> bezier; 
     bezier[0] = (WPoint)p1; // start point, in CG we did a CGMoveToPoint 
     bezier[1] = (WPoint)b1i; // control 1 
     bezier[2] = (WPoint)b2i; // control 2 
     bezier[3] = (WPoint)p2; // end point 

     std::vector<WPoint> point_list; 
     int numPoints = p2.dist(p3) * pointDensity; 
     // *** here's the magic *** 
     wykobi::generate_bezier(bezier,std::back_inserter(point_list), numPoints); 

     for (int i=0; i<numPoints; i++) { 
      CGPoint p = (CGPoint)(point_list[i]); 
      [result addObject:[NSValue valueWithCGPoint:p]]; 
     } 

// result has your points! 

Hier ist ein Link auf die Boost-Geometrie Bibliothek. http://www.boost.org/doc/libs/1_47_0/libs/geometry/doc/html/geometry/introduction.html

2

verwenden CGContextSetLineDash

der Zweck dieser Funktion ist es, eine gestrichelte Linie zu erstellen, aber Sie können es verwenden, um kleinere Segmente zu bekommen. Ausgangspunkt jedes Segments als Punkte behandelt werden.

CGSize bbSize = CGPathGetBoundingBox(path).size; 
UIGraphicsBeginImageContext(bbSize); 
CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGContextSetLineWidth(ctx, 1.0); 
CGContextAddPath(ctx, path); 
CGContextSetLineDash(ctx, phase, lengths, count); 
CGContextReplacePathWithStrokedPath(ctx); 
result = CGContextCopyPath(ctx); 
UIGraphicsEndImageContext(); 
+0

Das hat mir geholfen. Ich musste auch CGApplyPath verwenden, um die Punkte aus den Elementen heraus zu bekommen ... Ich muss noch etwas tun, aber das funktioniert ziemlich gut. Mit Tuning möchte ich verschiedene Einstellungen des Längenparameters ausprobieren. – Jonny

+1

Warum nicht 'CGPathCreateCopyByDashingPath' verwenden? – Ilya

Verwandte Themen