使用CGContext在一条线上绘制三角形/箭头

Pet*_*ete 11 iphone core-graphics cgcontext quartz-2d

我正在使用route-me的框架来处理位置.在此代码中,两个标记(点)之间的路径将绘制为一条线.

我的问题:"如果我想在线条的中间(或顶部)添加箭头,我应该添加什么代码,以便它指向"

谢谢



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

Run Code Online (Sandbox Code Playgroud)

小智 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);
}
Run Code Online (Sandbox Code Playgroud)


dra*_*ard 6

一旦在路径上有两个点,就可以轻松绘制实际的三角形/箭头.

CGContextMoveToPoint( context , ax , ay );
CGContextAddLineToPoint( context , bx , by );
CGContextAddLineToPoint( context , cx , cy );
CGContextClosePath( context ); // for triangle
Run Code Online (Sandbox Code Playgroud)

获得积分有点棘手.你说路径是一条线,而不是一条曲线或一系列曲线.这使得它更容易.

使用CGPathApply在路径​​上选择两个点.可能这是最后两点,其中一个可能是kCGPathElementMoveToPoint,另一个是kCGPathElementAddLineToPoint.设mx,我是第一个点和nx,ny是第二个,所以箭头将从m指向n.

假设您希望箭头位于线的顶端,bx,从上方开始将等于线上的nx,ny.选择mx,my和nx,ny之间的点dx,dy来计算其他点.

现在计算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;
Run Code Online (Sandbox Code Playgroud)

长度是从箭头尖端到底座的距离,宽度是从轴到倒钩的距离,或箭头头宽度的一半.

如果path是一条曲线,那么它不是找到mx,而是作为前一个点或移动,它将是最终曲线的最终控制点.每个控制点位于与曲线相切并穿过相邻点的直线上.