1

所以我试图生成一个NSBezierPath看起来像两点之间的箭头的箭头,它可以位于视图上的任何位置,因此 startPoint 可以大于或小于端点。

当用户像在绘图应用程序中一样拖动鼠标时,箭头会更新。

我已经想通了,我可能必须使用转换和一些数学来做三角函数,并提出了这个实现:

 +(NSBezierPath *)arrowWithStart:(NSPoint)startPoint andEnd:(NSPoint)endPoint{
        NSBezierPath* path = [NSBezierPath bezierPath];

        CGFloat width = endPoint.x - startPoint.x;
        CGFloat height = endPoint.y - startPoint.y;
        CGFloat angle = atan2(width, height);

        NSAffineTransform *tr = [NSAffineTransform transform];
        [tr translateXBy:startPoint.x yBy:startPoint.y];
        [tr scaleXBy:width yBy:height];
        [tr rotateByDegrees:angle];

        [path moveToPoint:CGPointZero];
        [path lineToPoint:CGPointMake(0.75, 0.7)];
        [path lineToPoint:CGPointMake(0.8, 0.65)];
        [path lineToPoint:CGPointMake(1, 1)];
        [path lineToPoint:CGPointMake(0.65, 0.8)];
        [path lineToPoint:CGPointMake(0.7, 0.75)];
        [path closePath];

        [path transformUsingAffineTransform:tr];

        return path;
    }

当点是某种对角线时,此代码会生成非常漂亮的箭头,例如

  • (0,0)
  • (-2,-2)

彼此,但是当这些点越来越接近水平或垂直线时,例如

  • (2,3)
  • (5,3)

结果变成一条没有箭头的直线。

所以我认为我在转换矩阵中做错了。

如果有人知道我在哪里犯了错误,那就太好了。

4

1 回答 1

1

您需要的是一个仿射变换,将点转换(0, 0)startPoint 和 。这个变换可以直接计算:(1, 1)endPoint

CGFloat tx = startPoint.x;
CGFloat ty = startPoint.y;
CGFloat a = ((endPoint.x - startPoint.x) + (endPoint.y - startPoint.y))/2.;
CGFloat b = (-(endPoint.x - startPoint.x) + (endPoint.y - startPoint.y))/2.;
NSAffineTransformStruct transformStruct = { a, b, -b, a, tx, ty };
NSAffineTransform *tr = [NSAffineTransform transform];
[tr setTransformStruct:transformStruct];

解释:

NSAffineTransformStruct transformStruct = { a, b, -b, a, tx, ty };

描述了平移、缩放和旋转的一般组合,即没有剪切的仿射变换。要求(0, 0) -> startPoint(1, 1) -> endPoint给出方程

startPoint.x = 0 * a + 0 * (-b) + tx
startPoint.y = 0 * b + 0 *   a  + ty
endPoint.x   = 1 * a + 1 * (-b) + tx
endPoint.y   = 1 * b + 1 *   a  + tx

a并为, b,求解这些方程txty给出上述解。(有关更多信息,请参阅“可可绘图指南”中的变换数学。)

您的原始代码的问题在于

  • atan2y作为第一个参数,因此将atan2(height, width)计算角度。
  • 对于水平线或垂直线,width或者height因此一个比例因子为零,这会导致直线没有箭头。
于 2012-12-28T12:11:59.903 回答