2010-03-23 19 views
9

Estoy utilizando el marco de route-me para trabajar con ubicaciones. En este código, la ruta entre dos marcadores (puntos) se dibujará como una línea.Dibujando triángulo/flecha en una línea con CGContext

mi pregunta: "¿Qué código debo añadir que, si quiero añadir una flecha en el medio (o superior) de la línea, de modo que señale la dirección"

Gracias



- (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

lo tengo hace un tiempo por http://www.codeguru.com/cpp/gm/gdi/article.php/c3683 De todos modos thansk de las respuestas Greetz – Pete

+0

Pete, puede ser amable de su parte marque una respuesta como aceptada, o publique su respuesta como respuesta y luego acepte eso. –

+0

@Pete ¿por qué no marcó la respuesta correcta (me refiero a Friedhelm)? – yas375

Respuesta

5

El dibujo del triángulo/flecha real es fácil una vez que tienes dos puntos en tu camino.

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

Obtener los puntos es un poco más complicado. Dijiste que el camino era una línea, a diferencia de una curva o serie de curvas. Eso lo hace más fácil.

Utilice CGPathApply para elegir dos puntos en la ruta. Probablemente, estos son los dos últimos puntos, uno de los cuales puede ser kCGPathElementMoveToPoint y el otro será kCGPathElementAddLineToPoint. Deje que mx, my sea el primer punto y nx, ny sea el segundo, así que la flecha apuntará de m hacia n.

Suponiendo que desea la flecha en la punta de la línea, bx, por desde arriba igualará nx, ny en la línea. Elija un punto dx, dy entre mx, my y nx, ny para calcular los otros puntos.

Ahora calcule ax, ay y cx, cy de modo que estén en línea con dx, dy equidistantes de la ruta. Lo siguiente debe estar cerca, aunque probablemente Tengo algunos signos 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; 

longitud es la distancia desde la punta de la flecha a la base, y la anchura es la distancia desde el eje de las púas, o la mitad de la amplitud de la punta de la flecha.

Si la ruta es una curva, en lugar de encontrar mx, my como el punto o movimiento anterior, será el punto de control final de la curva final. Cada punto de control está en una línea tangente a la curva y que pasa por el punto adyacente.

2

Encontré esta pregunta porque tenía lo mismo. de Tomé drawnonward ejemplo y que estaba tan cerca ... Pero con un volteo de cos y sen, yo era capaz de conseguir que funcione:

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; 

Una vez que lo hice, mis flechas apuntaban exactamente el camino equivocado . Así que agregué esa segunda línea (r += M_PI;)

¡Gracias van a dibujado hacia adelante!

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); 
} 
Cuestiones relacionadas