web-dev-qa-db-ja.com

Lat、Lngポイントが円の中に含まれているかどうかはどうすればわかりますか?

かなり自明です。私はグーグルマップを使用していて、緯度の長い点が半径の円内にあるかどうかを調べようとしています(xはユーザーが選択します)。

バウンディングボックスはこれでは機能しません。私はすでに次のコードを使用してみました:

distlatLng = new google.maps.LatLng(dist.latlng[0],dist.latlng[1]);
var latLngBounds = circle.getBounds();
if(latLngBounds.contains(distlatLng)){
      dropPins(distlatLng,dist.f_addr);
}

これでも、マーカーは円の外側に配置されます。

これは曲率や面積の計算が必要な簡単な計算だと思いますが、どこから始めればよいのかわかりません。助言がありますか?

15
Stuart Beard

私は本当に少しばかげています。それについて考えると、ピタゴラスの定理を使用できます。

ポイントからの最大距離(Xマイル)、2つの緯度と2つの経度があります。これらを使用して三角形を形成すると、点からの距離を解くことができます。

つまり、座標が_point1_の_lat1,lng1_が円の中心であり、座標が_point2_の_lat2,lng2_が円の中にあるかどうかを判断しようとしている点であることがわかっているとします。

_point1_と_point2_によって決定される点を使用して直角三角形を形成します。これ、_point3_の座標は_lat1,lng2_または_lat2,lng1_になります(どちらでも構いません)。次に、距離の差(または必要に応じて)を計算します-_latDiff = lat2-lat1_および_lngDiff = lng2-lng1_

次に、ピタゴラスを使用して中心からの距離を計算します-dist=sqrt(lngDiff^2+latDiff^2)

マイルが1609(約)で乗算され、緯度/経度が111000(約)で乗算されるように、Googleマップで正しく機能するように、すべてをメートルに変換する必要があります。これは正確ではありませんが、適切に機能します。

すべてが理にかなっていることを願っています。

1
Stuart Beard

ドラッグ可能なセンターマーカーを使用した実用的なソリューション

contains を試したことはありますか? LatLngBoundsコンストラクターを見てください。

私はそれについての記事を書きました、それは働くことへのリンクを含みます JSFiddle.netの例

Screenshot of jsFiddle


更新バージョン

16
kaiser

残念ながら、ピタゴラスは球体では役に立ちません。したがって、スチュアートビアードの答えは正しくありません。経度の違いはメートルに対して一定の比率ではありませんが、緯度によって異なります。

正しい方法は、大円距離の式を使用することです。球体地球を想定した場合の適切な近似は、次のとおりです(C++の場合)。

/** Find the great-circle distance in metres, assuming a spherical earth, between two lat-long points in degrees. */
inline double GreatCircleDistanceInMeters(double aLong1,double aLat1,double aLong2,double aLat2)
    {
    aLong1 *= KDegreesToRadiansDouble;
    aLat1 *= KDegreesToRadiansDouble;
    aLong2 *= KDegreesToRadiansDouble;
    aLat2 *= KDegreesToRadiansDouble;
    double cos_angle = sin(aLat1) * sin(aLat2) + cos(aLat1) * cos(aLat2) * cos(aLong2 - aLong1);

    /*
    Inaccurate trig functions can cause cos_angle to be a tiny amount
    greater than 1 if the two positions are very close. That in turn causes
    acos to give a domain error and return the special floating point value
    -1.#IND000000000000, meaning 'indefinite'. Observed on VS2008 on 64-bit Windows.
    */
    if (cos_angle >= 1)
        return 0;

    double angle = acos(cos_angle);
    return angle * KEquatorialRadiusInMetres;
    }

どこ

const double KPiDouble = 3.141592654;
const double KDegreesToRadiansDouble = KPiDouble / 180.0;

そして

/**
A constant to convert radians to metres for the Mercator and other projections.
It is the semi-major axis (equatorial radius) used by the WGS 84 datum (see http://en.wikipedia.org/wiki/WGS84).
*/
const int32 KEquatorialRadiusInMetres = 6378137;
10
Graham Asher

とても簡単です。中心と指定された点の間の距離を計算し、それを半径と比較するだけです。 ここ から2つの緯度言語間の距離を計算するためのヘルプを取得できます

5
Ashutosh

Google Maps APIジオメトリライブラリを使用して、円の中心とマーカーの間の距離を計算し、それを半径と比較します。

var pointIsInsideCircle = google.maps.geometry.spherical.computeDistanceBetween(circle.getCenter(), point) <= circle.getRadius();
5
zavidovych

次のコードが機能します。マーカーを円の外側にドラッグすることはできません。代わりに、マーカーはそのエッジ(任意の方向)にぶら下がっており、最後の有効な位置が保持されます。

この関数は、マーカーの「ドラッグ」イベントのイベントハンドラーです。

_markerDragged : function() {
    var latLng = this.marker.getPosition();
    var center = this.circle.getCenter();
    var radius = this.circle.getRadius();
    if (this.circleBounds.contains(latLng) &&
        (google.maps.geometry.spherical.computeDistanceBetween(latLng, center) <= radius)) {
        this.lastMarkerPos = latLng;
        this._geocodePosition(latLng);
    } else {
        // Prevent dragging marker outside circle
        // see (comments of) http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/
        // see http://www.mvjantzen.com/blog/?p=3190 and source code of http://mvjantzen.com/cabi/trips4q2012.html
        this.marker.setPosition(this.lastMarkerPos);
    }
},

おかげで http://unserkaiser.com/code/google-maps-marker-check-if-in-circle/ そして http://www.mvjantzen.com/blog/ ?p = 319

4
Risadinha