2010-03-23 5 views
9

J'utilise le cadre de route-moi pour travailler avec des emplacements. Dans ce code, le chemin entre deux marqueurs (points) sera tracé comme une ligne.Dessin triangle/flèche sur une ligne avec CGContext

Ma question: « Quel est le code dois-je ajouter si je veux ajouter une flèche au milieu (ou supérieure) de la ligne, de sorte qu'il pointe la direction »

Merci



- (void)drawInContext:(CGContextRef)theContext 
{ 
    renderedScale = [contents metersPerPixel]; 

    float scale = 1.0f/[contents metersPerPixel]; 

    float scaledLineWidth = lineWidth; 
    if(!scaleLineWidth) { 
     scaledLineWidth *= renderedScale; 
    } 
    //NSLog(@"line width = %f, content scale = %f", scaledLineWidth, renderedScale); 

    CGContextScaleCTM(theContext, scale, scale); 

    CGContextBeginPath(theContext); 
    CGContextAddPath(theContext, path); 

    CGContextSetLineWidth(theContext, scaledLineWidth); 
    CGContextSetStrokeColorWithColor(theContext, [lineColor CGColor]); 
    CGContextSetFillColorWithColor(theContext, [fillColor CGColor]); 

    // according to Apple's documentation, DrawPath closes the path if it's a filled style, so a call to ClosePath isn't necessary 
    CGContextDrawPath(theContext, drawingMode); 
} 

+0

Je l'ai tout à l'heure par http://www.codeguru.com/cpp/gm/gdi/article.php/c3683 Quoi qu'il en soit thansk pour les réponses Greetz – Pete

+0

Pete, il peut être agréable de vous marquez une réponse comme acceptée, ou affichez votre réponse comme une réponse, puis acceptez-la. –

+0

@Pete pourquoi n'avez-vous pas marqué la bonne réponse (je veux dire celle de Friedhelm)? – yas375

Répondre

5

Le dessin du triangle/flèche réel est facile une fois que vous avez deux points sur votre chemin.

CGContextMoveToPoint(context , ax , ay); 
CGContextAddLineToPoint(context , bx , by); 
CGContextAddLineToPoint(context , cx , cy); 
CGContextClosePath(context); // for triangle 

Obtenir les points est un peu plus délicat. Vous avez dit que le chemin était une ligne, par opposition à une courbe ou une série de courbes. Cela le rend plus facile.

Utilisez CGPathApply pour sélectionner deux points sur le chemin. Probablement, ce sont les deux derniers points, dont l'un peut être kCGPathElementMoveToPoint et l'autre sera kCGPathElementAddLineToPoint. Soit mx, mon soit le premier point et nx, ny soit le second, ainsi la flèche pointera de m vers n.

En supposant que vous vouliez la flèche à l'extrémité de la ligne, bx, de par le haut sera égal à nx, ny sur la ligne. Choisissez un point dx, dy entre mx, my et nx, ny pour calculer les autres points.

Calculez maintenant ax, ay et cx, cy de sorte qu'ils soient sur une ligne avec dx, dy et équidistants du chemin. Ce qui suit devrait être proche, bien que je doute eu quelques signes de mal:

r = atan2(ny - my , nx - mx); 
bx = nx; 
by = ny; 
dx = bx + sin(r) * length; 
dy = by + cos(r) * length; 
r += M_PI_2; // perpendicular to path 
ax = dx + sin(r) * width; 
ay = dy + cos(r) * width; 
cx = dx - sin(r) * width; 
cy = dy - cos(r) * width; 

La longueur est la distance de la pointe de la flèche à la base, et la largeur est la distance de l'arbre aux ardillons, ou la moitié de la largeur de la tête de la flèche.

Si le chemin est une courbe, alors au lieu de trouver mx, my comme le point ou le déplacement précédent, ce sera le point de contrôle final de la courbe finale. Chaque point de contrôle est sur une ligne tangente à la courbe et passant par le point adjacent.

2

J'ai trouvé cette question car j'avais le même. J'ai pris l'exemple de drawnonward et il était si proche ... Mais avec un retournement de cos et le péché, j'ai pu le faire fonctionner:

r = atan2(ny - my , nx - mx); 
r += M_PI; 
bx = nx; 
by = ny; 
dx = bx + cos(r) * length; 
dy = by + sin(r) * length; 
r += M_PI_2; // perpendicular to path 
ax = dx + cos(r) * width; 
ay = dy + sin(r) * width; 
cx = dx - cos(r) * width; 
cy = dy - sin(r) * width; 

Une fois que je l'ai fait, mes flèches ont été signalées exactement dans le mauvais sens . J'ai donc ajouté cette deuxième ligne (r += M_PI;)

Merci de vous rendre à drawnonward!

20
- (void) drawLine: (CGContextRef) context from: (CGPoint) from to: (CGPoint) to 
{ 
    double slopy, cosy, siny; 
    // Arrow size 
    double length = 10.0; 
    double width = 5.0; 

    slopy = atan2((from.y - to.y), (from.x - to.x)); 
    cosy = cos(slopy); 
    siny = sin(slopy); 

    //draw a line between the 2 endpoint 
    CGContextMoveToPoint(context, from.x - length * cosy, from.y - length * siny); 
    CGContextAddLineToPoint(context, to.x + length * cosy, to.y + length * siny); 
    //paints a line along the current path 
    CGContextStrokePath(context); 

    //here is the tough part - actually drawing the arrows 
    //a total of 6 lines drawn to make the arrow shape 
    CGContextMoveToPoint(context, from.x, from.y); 
    CGContextAddLineToPoint(context, 
         from.x + (- length * cosy - (width/2.0 * siny)), 
         from.y + (- length * siny + (width/2.0 * cosy))); 
    CGContextAddLineToPoint(context, 
         from.x + (- length * cosy + (width/2.0 * siny)), 
         from.y - (width/2.0 * cosy + length * siny)); 
    CGContextClosePath(context); 
    CGContextStrokePath(context); 

    /*/-------------similarly the the other end-------------/*/ 
    CGContextMoveToPoint(context, to.x, to.y); 
    CGContextAddLineToPoint(context, 
         to.x + (length * cosy - (width/2.0 * siny)), 
         to.y + (length * siny + (width/2.0 * cosy))); 
    CGContextAddLineToPoint(context, 
         to.x + (length * cosy + width/2.0 * siny), 
         to.y - (width/2.0 * cosy - length * siny)); 
    CGContextClosePath(context); 
    CGContextStrokePath(context); 
}