交点--幾何学的に線分の交点を判断する問題
23122 ワード
0x01.に質問
2つの線分(始点
入力例:line 1={0,0},{3,3}line 2={1,1},{2,2}出力例:{1,1}
『プログラマー面接金典』16.03より
0x02.簡単な分析
初めて見ると、数学の幾何学の問題で、難易度が低いと思っていたが、よく考えてみると、直線の交点ではなく、線分の交点であることが分かった.具体的な考え方は以下の通りです.は、2つの線分が位置する直線が平行であるか否かを先に判断する(傾きで判断する). 平行であれば、直線が重なるかどうかを考慮します. 重ならなければ、交点はないに違いない. が重なると、各直線の端点が別の直線上の線分上にあるかどうかを順次判断し、交点を最小値に更新し続ける.
が平行でなければ、パラメータ方程式を用いてパラメータ
0x03.解決コード–分類ディスカッション
私は山を越えて、水を渡って、万物が蘇るのを見たことがあります.水は__で、万物は_です.心の中は少し清明で、やはり_.
ATFWUS --Writing By 2020–04-12
2つの線分(始点
start = {X1, Y1}
と終点end = {X2, Y2}
として表される)を指定し、交点がある場合はその交点を計算し、交点がない場合は空の値を返します.浮動小数点型誤差は10^-6
を超えません.複数の交点がある場合は(線分が重なる)はX値が最も小さい点、X座標が同じであればY値が最も小さい点を返します.座標の絶対値は2^7
を超えず、入力した座標はいずれも有効な2次元座標です.入力例:line 1={0,0},{3,3}line 2={1,1},{2,2}出力例:{1,1}
『プログラマー面接金典』16.03より
public double[] intersection(int[] start1, int[] end1, int[] start2, int[] end2)
0x02.簡単な分析
初めて見ると、数学の幾何学の問題で、難易度が低いと思っていたが、よく考えてみると、直線の交点ではなく、線分の交点であることが分かった.具体的な考え方は以下の通りです.
t1
とt2
を算出し、t1,t2
が[0,1]
に属するかどうかを判断して交点があり、交点を算出し、属さなければ交点がない.0x03.解決コード–分類ディスカッション
class Solution {
private boolean inside(int x1,int y1,int x2,int y2,int x,int y){
// x ,y ,
return (x1 == x2 || (Math.min(x1, x2) <= x && x <= Math.max(x1, x2)))
&& (y1 == y2 || (Math.min(y1, y2) <= y && y <= Math.max(y1, y2)));
}
private void up(double[]result,double x,double y){
if((result[0]==Integer.MAX_VALUE)||x<result[0]||(x==result[0]&&y<result[1])){
result[0]=x;
result[1]=y;
}
}
public double[] intersection(int[] start1, int[] end1, int[] start2, int[] end2) {
int x1=start1[0],y1=start1[1];
int x2=end1[0],y2=end1[1];
int x3=start2[0],y3=start2[1];
int x4=end2[0],y4=end2[1];
double[] result=new double[2];
result[0]=Integer.MAX_VALUE;
result[1]=Integer.MAX_VALUE;
//
if ((y4 - y3) * (x2 - x1) == (y2 - y1) * (x4 - x3)) {
//
if ((y2 - y1) * (x3 - x1) == (y3 - y1) * (x2 - x1)){
// (x3, y3) 「 」(x1, y1)~(x2, y2)
if (inside(x1, y1, x2, y2, x3, y3)) {
up(result,(double)x3,(double)y3);
}
// (x4, y4) 「 」(x1, y1)~(x2, y2)
if (inside(x1, y1, x2, y2, x4, y4)) {
up(result, (double)x4, (double)y4);
}
// (x1, y1) 「 」(x3, y3)~(x4, y4)
if (inside(x3, y3, x4, y4, x1, y1)) {
up(result, (double)x1, (double)y1);
}
// (x2, y2) 「 」(x3, y3)~(x4, y4)
if (inside(x3, y3, x4, y4, x2, y2)) {
up(result, (double)x2, (double)y2);
}
}
}else{
//
double t1 = (double)(x3 * (y4 - y3) + y1 * (x4 - x3) - y3 * (x4 - x3)
- x1 * (y4 - y3)) / ((x2 - x1) * (y4 - y3) - (x4 - x3) * (y2 - y1));
double t2 = (double)(x1 * (y2 - y1) + y3 * (x2 - x1) - y1 * (x2 - x1)
- x3 * (y2 - y1)) / ((x4 - x3) * (y2 - y1) - (x2 - x1) * (y4 - y3));
// [0,1]
if (t1 >= 0.0 && t1 <= 1.0 && t2 >= 0.0 && t2 <= 1.0) {
result[0] = x1 + t1 * (x2 - x1);
result[1] = y1+ t1 * (y2 - y1);
}
}
return result[0]==Integer.MAX_VALUE?new double[]{}:result;
}
}
私は山を越えて、水を渡って、万物が蘇るのを見たことがあります.水は__で、万物は_です.心の中は少し清明で、やはり_.
ATFWUS --Writing By 2020–04-12