1

そのため、2つのポイント間の矢印のように見えるを生成しようとして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

そして、これらの方程式を、、、について解くとab上記の解が得られますtxty(詳細については、「Cocoa描画ガイド」の変換数学を参照してください。)

元のコードの問題は、

  • atan2y最初の引数として取るので、atan2(height, width)角度を計算します。
  • 水平線または垂直線のwidth場合height、つまり1つのスケーリング係数がゼロの場合、これにより矢印のない直線が作成されます。
于 2012-12-28T12:11:59.903 に答える