4

検索しましたが、完全な答えが見つかりませんでした。可能であればC#で。球(正確には地球)上のWGSポイントとWGSポイントで定義された線分の間の最短距離が必要です。

float DistanceInKilometres(PointF LineStartA, PointF LineEndB, PointF ThePoint)

編集:おそらくイラストが役立つでしょう

ここに画像の説明を入力してください

これは理想的な例であることに注意してください。「ポイント」は、球の表面のどこにあっても、セグメントの開始と終了になります。明らかに、私は球を通る距離を探していません。数学は私の強みではないので、正規化デカルト座標を理解していません。たぶん、パスABが可能な限り最短であり、距離?も可能な限り最短であることに注意する必要があります。

4

2 に答える 2

4

余弦定理の球面法則を使用できます。

計算には地球の半径を使用する必要があります。

EARTH_RADIUS_KM = 6371;

ここで、openstreetmap.orgからのOsmMercator.javaへの私の貢献から:

/**
 * Gets the distance using Spherical law of cosines.
 *
 * @param la1 the Latitude in degrees
 * @param lo1 the Longitude in degrees
 * @param la2 the Latitude from 2nd coordinate in degrees
 * @param lo2 the Longitude from 2nd coordinate in degrees
 * @return the distance
 */
public static double getDistance(double la1, double lo1, double la2, double lo2) {
    double aStartLat = Math.toRadians(la1);
    double aStartLong = Math.toRadians(lo1);
    double aEndLat =Math.toRadians(la2);
    double aEndLong = Math.toRadians(lo2);

    double distance = Math.acos(Math.sin(aStartLat) * Math.sin(aEndLat)
            + Math.cos(aStartLat) * Math.cos(aEndLat)
            * Math.cos(aEndLong - aStartLong));

    return (EARTH_RADIUS_KM * distance);
}

あなたがする必要があるのは、内積で最も近い点を見つけて、それを距離方程式で使用することです。

最も近いポイントの例は次のとおりです。

double[] nearestPointSegment (double[] a, double[] b, double[] c)
{
   double[] t= nearestPointGreatCircle(a,b,c);
   if (onSegment(a,b,t))
     return t;
   return (distance(a,c) < distance(b,c)) ? a : c;
}

ユニットは明示的に宣言されていないことに注意してください。空間内のポイントを処理する場合、位置を決定するさまざまな方法があります。主なことは、ユニットを一貫したタイプに釘付けにする必要があるということです。

地球上の位置を操作するとき、私は主に緯度/経度の座標と大きさ/方向のベクトルを使用します。ベクトルと地球の位置に使用する既知のタイプがいくつかあります。それらの中には次のものがあります。

  • 地球中心の地球固定(ECEF)座標系
  • ノースイーストダウン(NED)
  • 測地座標系

あなたの例として、私は測地学に固執することを検討するかもしれません。

これをまとめると、次のような擬似コードが作成される可能性があります。

Where a Vector is made up of Geodetic coordinates:
class Vector {
 double x=0.0; //latitude
 double y=0.0; //longitude
 double h=0.0; //height
...
}

public Vector closestPoint(Vector lineStartA, Vector lineEndB, final Vector thePoint ) {
    Vector w = thePoint.subtract(lineStartA);
    double proj = w.dot(lineEndB);
    // endpoint 0 is closest point
    if ( proj <= 0.0f )
        return lineStartA;
    else
    {
        //Vector square 
        double vsq = lineEndB.dot(lineEndB);
        // endpoint 1 is closest point
        if ( proj >= vsq )
            return lineStartA.add(lineEndB);
        else
            return lineStartA.add(lineEndB.multiply(proj/vsq));
    }
}      

double DistanceInKilometres(Vector lineStartA, Vector lineEndB, Vector thePoint) {
  Vector cp=closestPoint(lineStartA, lineEndB, thePoint);
  return getDistance(cp.x, cp.y, thePoint.x, thePoint.y);
}
于 2012-04-19T16:46:53.040 に答える
0

ポイントがラインセグメントのエンドポイントによって定義されたコリドー内にあり、ラインに垂直である場合、この回答で問題ありません。

ポイントがそのコリドーの外側にある場合は、ポイントから線分の両端までの距離を計算し、小さい方を取ります。

于 2012-04-06T19:30:05.650 に答える