Iphone 使用CGContext在直线上绘制三角形/箭头
我正在使用route me的框架处理位置。 在此代码中,两个标记(点)之间的路径将绘制为一条直线 我的问题:“如果我想在行的中间(或顶部)添加箭头,以便箭头指向方向,我应该添加什么代码?” 谢谢Iphone 使用CGContext在直线上绘制三角形/箭头,iphone,core-graphics,quartz-2d,cgcontext,Iphone,Core Graphics,Quartz 2d,Cgcontext,我正在使用route me的框架处理位置。 在此代码中,两个标记(点)之间的路径将绘制为一条直线 我的问题:“如果我想在行的中间(或顶部)添加箭头,以便箭头指向方向,我应该添加什么代码?” 谢谢 - (void)drawInContext:(CGContextRef)theContext { renderedScale = [contents metersPerPixel]; float scale = 1.0f / [contents metersPerPixel];
- (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);
}
一旦在路径上有两个点,实际三角形/箭头的绘制就很容易了
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,by,从上面看,等于线上的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;
长度是从箭头尖端到底部的距离,宽度是从轴到倒钩的距离,或者是箭头头宽度的一半
如果路径是曲线,则它将成为最终曲线的最终控制点,而不是查找mx、my作为上一个点或移动。每个控制点都位于与曲线相切并通过相邻点的直线上。我发现了这个问题,因为我有相同的问题。我举了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;
)
感谢来到drawnonward 这是Friedhelm brugge的Swift 4+版本回答:(我会在图片上画出来)
- (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);
}
不久前,我通过Anways thansk获得了答案GreetzPete,你最好将答案标记为已接受,或者将你的答案作为答案发布,然后接受。@Pete为什么不标记正确的答案(我是说Friedhlm的)?
func drawArrow(image: UIImage, ptSrc: CGPoint, ptDest: CGPoint) {
// create context with image size
UIGraphicsBeginImageContext(image.size)
let context = UIGraphicsGetCurrentContext()
// draw current image to the context
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
var slopY: CGFloat, cosY: CGFloat, sinY: CGFloat;
// Arrow size
let length: CGFloat = 35.0;
let width: CGFloat = 35.0;
slopY = atan2((ptSrc.y - ptDest.y), (ptSrc.x - ptDest.x));
cosY = cos(slopY);
sinY = sin(slopY);
//here is the tough part - actually drawing the arrows
//a total of 6 lines drawn to make the arrow shape
context?.setFillColor(UIColor.white.cgColor)
context?.move(to: CGPoint(x: ptSrc.x, y: ptSrc.y))
context?.addLine(to: CGPoint(x: ptSrc.x + ( -length * cosY - ( width / 2.0 * sinY )), y: ptSrc.y + ( -length * sinY + ( width / 2.0 * cosY ))))
context?.addLine(to: CGPoint(x: ptSrc.x + (-length * cosY + ( width / 2.0 * sinY )), y: ptSrc.y - (width / 2.0 * cosY + length * sinY )))
context?.closePath()
context?.fillPath()
context?.move(to: CGPoint(x: ptSrc.x, y: ptSrc.y))
context?.addLine(to: CGPoint(x: ptDest.x + (length * cosY - ( width / 2.0 * sinY )), y: ptDest.y + (length * sinY + ( width / 2.0 * cosY ))))
context?.addLine(to: CGPoint(x: ptDest.x + (length * cosY + width / 2.0 * sinY), y: ptDest.y - (width / 2.0 * cosY - length * sinY)))
context?.closePath()
context?.fillPath()
// draw current context to image view
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
//close context
UIGraphicsEndImageContext()
}