Ich zeichne viele Trapeze, die mit einem NSGradient gefüllt sind. Ich erwarte, dass sie sich nahtlos anschließen, was nicht der Fall ist. In diesem Fall würde ich lieber Clipping verwenden, anstatt einen NSBezierPath explizit mit einem Farbverlauf zu füllen.Lücken zwischen den Clipping-Regionen
Hier ist der inkriminierten Code:
-(void)drawRect:(NSRect)dirtyRect {
[[NSColor blackColor]set];
NSRectFill(self.bounds);
NSPoint v0 = NSMakePoint(100,100);
NSPoint v1 = NSMakePoint(200,100);
NSPoint v2 = NSMakePoint(100,200);
NSPoint v3 = NSMakePoint(200,200);
NSPoint v4 = NSMakePoint(150, 150);
NSBezierPath * triangle0 = [NSBezierPath bezierPath];
[triangle0 moveToPoint:v0];
[triangle0 lineToPoint:v1];
[triangle0 lineToPoint:v2];
[triangle0 closePath];
NSBezierPath * triangle1 = [NSBezierPath bezierPath];
[triangle1 moveToPoint:v1];
[triangle1 lineToPoint:v2];
[triangle1 lineToPoint:v3];
[triangle1 closePath];
NSGradient * gradient = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],1.0,nil];
[NSGraphicsContext saveGraphicsState];
[triangle0 addClip];
[gradient drawFromPoint:v0 toPoint:v4 options:NSGradientDrawsAfterEndingLocation|NSGradientDrawsBeforeStartingLocation];
// [gradient drawFromPoint:v0 toPoint:v4 options:0];
[NSGraphicsContext restoreGraphicsState];
[NSGraphicsContext saveGraphicsState];
[triangle1 addClip];
[gradient drawFromPoint:v3 toPoint:v4 options:NSGradientDrawsAfterEndingLocation|NSGradientDrawsBeforeStartingLocation];
//[gradient drawFromPoint:v3 toPoint:v4 options:0];
[NSGraphicsContext restoreGraphicsState];
Was soll ich tun, um die Lücke zwischen den beiden Dreiecken zu vermeiden?
Bearbeiten: Hier ist ein Versuch, dieses Problem zu umgehen, indem Sie NSBezierPath explizit füllen.
-(void)drawRect:(NSRect)dirtyRect {
[[NSColor blackColor]set];
NSRectFill([self bounds]);
CGContextRef c = [[NSGraphicsContext currentContext] graphicsPort];
CGContextTranslateCTM(c, 0.5, 0.5);
NSPoint v0 = NSMakePoint(100,100);
NSPoint v1 = NSMakePoint(200,100);
NSPoint v2 = NSMakePoint(100,200);
NSPoint v3 = NSMakePoint(200,200);
NSBezierPath * triangle0 = [NSBezierPath bezierPath];
[triangle0 moveToPoint:v0];
[triangle0 lineToPoint:v1];
[triangle0 lineToPoint:v2];
[triangle0 closePath];
NSBezierPath * triangle1 = [NSBezierPath bezierPath];
[triangle1 moveToPoint:v1];
[triangle1 lineToPoint:v2];
[triangle1 lineToPoint:v3];
[triangle1 closePath];
[[NSColor whiteColor]set];
NSGradient * gradient = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],1.0,nil];
[gradient drawInBezierPath:triangle0 angle:45];
[gradient drawInBezierPath:triangle1 angle:45+180];
NSBezierPath * seam = [ NSBezierPath bezierPath]; [seam moveToPoint:v1]; [seam lineToPoint:v2];
[[NSColor orangeColor]set]; [seam stroke];
NSGradient * gradient2 = [[NSGradient alloc] initWithColorsAndLocations:[NSColor whiteColor],0.0,[NSColor orangeColor],0.5,[NSColor whiteColor],1.0,nil];
NSBezierPath * squarePath = [NSBezierPath bezierPath];
[squarePath moveToPoint:v0];
[squarePath lineToPoint:v1];
[squarePath lineToPoint:v3];
[squarePath lineToPoint:v2];
[squarePath closePath];
CGContextTranslateCTM(c, 200, 0);
[gradient2 drawInBezierPath:squarePath angle:45];
}
Auf der linken Seite zwei Dreiecke mit dem gleichen NSGradient gefüllt. Auf der rechten Seite, ein Quadrat mit einem NSGradient gefüllt, das Ziel, das ich versuche zu erreichen. Die Naht ist ein Versuch, die schwarze Linie zwischen den beiden NSBezierPath zu verstecken, aber es funktioniert nicht wirklich. In diesem Fall ist es kaum sichtbar, aber es wird sichtbar, wenn ich eine große Anzahl solcher Dreiecke zeichne.
Edit für Rengers Antwort:
Hier ist, wie es ohne Anti-Aliasing aussieht:
Technisch gesehen ist dies die gute Antwort, aber jetzt ist das Problem ist, dass, wenig überraschend, die Kanten des Polygons sind nicht mehr antialiasiert. Irgendeine Idee, wie ich die Lücke zwischen den Clipping-Bereichen entfernen könnte, ohne das Antialiasing an den Kanten zu verlieren?
Was ist der Grund, Clipping zu verwenden statt: 1. Zeichnen in Bezier Pfade - oder - 2. Erstellen eines Pfades mit einem Gradienten? Vielleicht gibt es einen anderen Ansatz, um dieses Problem besser zu lösen. – Rengers
Mein erstes Problem war dieses: Ich habe eine planare 2D-Oberfläche, die mit zwei 2 Variablenfunktionen definiert ist: x (u, v) und y (u, v). Ich möchte diese Oberfläche mit einem 2d Gradienten füllen. Um dies zu tun, unterteile ich die Oberfläche entlang von u und v, was zu einer 2D-Anordnung von Vierecken oder Dreiecken führt. An dieser Stelle fülle ich diese Polygone mit einem Gradienten, der aus dem ursprünglichen 2d-Gradienten berechnet wurde, so dass gemeinsame Kanten die gleiche Farbe haben. Ich habe versucht beide Ansätze mit diesem einfachen Fall (2 Dreiecke) und jeder hat sein eigenes Problem, wie Sie sehen können. – alecail
Rendern Sie Ihr Polygon in einen Offscreen-Bitmap-Kontext * mit einer Skalierung von 2.0 *. Rendern Sie den Inhalt des Bitmap-Kontexts mit 0,5 Skalierung in Ihren regulären Kontext. Sie werden effektiv 4x Multisampling implementieren. –