2009-05-19 1 views
0

その長さ(その座標によって知られている)の行を制限する機能が必要ですが、は一定の長さに限定されるものでIは を(その座標によって知られている)ラインを取り、<strong>同じ</strong>角度でラインを返す関数が必要

私のコードは、正しい値を与えるのみラインが「正しい」(唯一の経験的に実証され、申し訳ありません)
になっているとき。

何か不足していますか?

public static double getAngleOfLine(int x1, int y1, int x2, int y2) { 
    double opposite = y2 - y1; 
    double adjacent = x2 - x1; 

    if (adjacent == Double.NaN) { 
    return 0; 
    } 

    return Math.atan(opposite/adjacent); 
} 

// returns newly calculated destX and destY values as int array 
public static int[] getLengthLimitedLine(int startX, int startY, 
    int destX, int destY, int lengthLimit) { 

    double angle = getAngleOfLine(startX, startY, destX, destY); 

    return new int[]{ 
     (int) (Math.cos(angle) * lengthLimit) + startX, 
     (int) (Math.sin(angle) * lengthLimit) + startY 
     }; 
} 

はところで:私は、Javaでの配列を返すことは愚かであることを知っている が、それは単なる例のためです。

+0

何が今までNaNに等しいではないとしてNaNのためのあなたのチェックは常にfalseを返します。また、0は有効な角度であるため、エラーの場合は0を返します。 –

+0

ああ、そうだよ!それは古いコードからのものです。 –

答えて

2

::ちょうど相似三角形を使用

import math 

def getLengthLimitedLine(x1, y1, x2, y2, lengthLimit): 
    length = math.sqrt((x2-x1)**2 + (y2-y1)**2) 
    if length > lengthLimit: 
     shrink_factor = lengthLimit/length 
     x2 = x1 + (x2-x1) * shrink_factor 
     y2 = y1 + (y2-y1) * shrink_factor 
    return x2, y2 

print getLengthLimitedLine(10, 20, 25, -5, 12) 
# Prints (16.17, 9.71) which looks right to me 8-) 
+0

+1 - 私は、Pythonの簡潔さと優雅さを高く評価し始めています。ニース。長さの "if"チェックの必要はありません - 長さ== 0以外のすべての状況で有効です。これはあなたが作る必要があるチェックです。 abs()も必要ありません。なぜなら、正方形は常に正であるからです。 – duffymo

+0

@duffymo:abs()についての良い点 - 私はそれを削除しました。しかし、私は 'if'が必要だと思っています。そうでなければ、限界よりも短いときにラインを成長させます。 – RichieHindle

+0

はい、それは間違った結果であるとは限りません。それは、ポスターによって定められた狭い要件を満たすことができないだけです。別のユースケースで行を拡張することも同じように有効です。 – duffymo

0

ただ、そうのように、Pythagorean theoremを使用します。

public static int[] getLengthLimitedLine(int start[], int dest[], int lengthLimit) { 
    int xlen = dest[0] - start[0] 
    int ylen = dest[1] - start[1] 
    double length = Math.sqrt(xlen * xlen + ylen * ylen) 

    if (length > lengthLimit) { 
     return new int[] {start[0], start[1], 
       start[0] + xlen/lengthLimit, 
       start[1] + ylen/lengthLimit} 
    } else { 
     return new int[] {start[0], start[1], dest[0], dest[1];} 
    } 
} 
1

あなたがベクトルについて何かを理解していればそれは簡単な問題です。

考えると二つの点(x1、y1)と(x2、y2)と、あなたは2にポイント1からベクトルを計算することができます。

V12 =(X2-X1)を私は+(Y2-Y2)をJ

ここで、iとjはx方向とy方向の単位ベクトルです。

あなたは部品の二乗和の平方根を取ることによって、vの大きさを計算することができます。

V =のSQRT((X2-X2)^ 2 +(Y2-Y1)^ 2)

ポイント1からポイント2までの単位ベクトルは、v12をその大きさで割ったものに等しくなります。 、あなたは乗算単位ベクトル倍の長さだけ離れた所望の距離です単位ベクトルに沿ってポイントを計算し、ポイント1

3

にちょうどとしてそれを処理するために容易になるだろうと付け加えたことを考えると

ベクター。自分の大きさを除算して正規化し、次に希望の長さの係数を掛けます。

ただし、例ではMath.atan2を試してみてください。

+0

まさにatan2がここで使う方法です。別の引数としてxとyを取得し、-πから+πまでの角度を正しく返すことができるため、より多くの情報が得られます。 atanは、-π/ 2〜π/ 2の範囲をカバーするのに十分な情報しか持っていません。 – erickson

1

クラスのラインをカプセル化し、ユニットメソッドとスケールメソッドを追加します。

public class Line { 
private float x; 
private float y; 

public Line(float x1, float x2, float y1, float y2) { 
    this(x2 - x1, y2 - y1); 
} 

public Line(float x, float y) { 
    this.x = x; 
    this.y = y; 
} 

public float getLength() { 
    return (float) Math.sqrt((x * x) + (y * y)); 
} 

public Line unit() { 
    return scale(1/getLength()); 
} 

public Line scale(float scale) { 
    return new Line(x * scale, y * scale); 

} 
} 

今、あなたはいくつかの厄介なエッジケースを持つことができTRIGを、使用する必要はありませ

Line result = new Line(x1, x2, y1, y2).unit().scale(l); 
1

を呼び出していないことで、任意の長さlのラインを取得することができます。私はJavaコンパイラは手元にありませんので、Pythonで

public static int[] getLengthLimitedLine(int startX, int startY, 
    int destX, int destY, int lengthLimit) 
{ 
    int deltaX = destX - startX; 
    int deltaY = destY - startY; 
    int lengthSquared = deltaX * deltaX + deltaY * deltaY; 
    // already short enough 
    if(lengthSquared <= lengthLimit * lengthLimit) 
     return new int[]{destX, destY}; 

    double length = Math.sqrt(lengthSquared); 
    double newDeltaX = deltaX * lengthLimit/length; 
    double newDeltaY = deltaY * lengthLimit/length; 

    return new int[]{(int)(startX + newDeltaX), (int)(startY + newDeltaY)}; 
} 
関連する問題