2010-03-23 2 views
9

Я использую рамки route-me для работы с местоположениями. В этом коде путь между двумя маркерами (точками) будет нарисован как строка.Рисование треугольника/стрелки на линии с CGContext

Мой вопрос: «Какой код следует добавить, если я хочу, чтобы добавить стрелку в середине (или сверху) линии, так что он указывает направление»

Благодарности



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

Я получил это некоторое время назад от http://www.codeguru.com/cpp/gm/gdi/article.php/c3683 Во всяком случае thansk для ответов Greetz – Pete

+0

Пит, это может быть хорошо, что вы отметьте ответ как принятый, тем не менее, или отправьте свой ответ в качестве ответа, а затем примите это. –

+0

@ Пойди, почему ты не заметил правильный ответ (я имею в виду Фридхельма)? – yas375

ответ

5

Рисунок фактического треугольника/стрелки прост, если у вас есть две точки на вашем пути.

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

Получение баллов немного сложнее. Вы сказали, что путь - это линия, в отличие от кривой или ряда кривых. Это облегчает работу.

Используйте CGPathApply, чтобы выбрать две точки на пути. Вероятно, это последние два момента, один из которых может быть kCGPathElementMoveToPoint, а другой будет kCGPathElementAddLineToPoint. Пусть mx, my - первая точка, а nx, ny - вторая, поэтому стрелка укажет от m к n.

Предполагая, что стрелка на кончике линии, bx, сверху, будет равна nx, ny на линии. Выберите точку dx, dy между mx, my и nx, ny, чтобы вычислить другие точки.

Теперь вычислите ax, ay и cx, cy так, чтобы они находились на линии с dx, dy и равноудалены от пути. Следующий должно быть близко, хотя я, вероятно, получил некоторые признаки неправильно:

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; 

Длина расстояние от кончика стрелки к основанию, а ширина расстояние от вала к заусеницам, или половине ширины стрелы.

Если путь - это кривая, то вместо того, чтобы находить mx, my как предыдущую точку или двигаться, это будет конечная контрольная точка конечной кривой. Каждая контрольная точка находится на линии, касательной к кривой и проходящей через соседнюю точку.

2

Я нашел этот вопрос, поскольку у меня было то же самое. Я взял drawnonward пример М., и это было так близко ... Но с листать соз и грех, я был в состоянии заставить его работать:

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; 

После того, как я сделал это, мои стрелы указывали именно неправильный путь , Поэтому я добавил, что вторая строка (r += M_PI;)

Спасибо, обратись!

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