2

MKMapView の 2 つの緯度/経度ポイント間に大円線を描画しようとしています。これは、丸みを帯びて表示される線 (地球上の「直線」) であり、ここで視覚化するのが最適です。実際、この非常に奇妙な WordPress サイトは、これを行う方法を正確に説明し始めているように見えますが、最初の数ステップで突然終了します。

私が見るAppleのドキュメントを読む

iOS 4.0 以降では、地域の代わりに投影されたマップ座標を使用して値を指定することもできます。地球の曲面を平面に投影すると、経線が平行に見える 2 次元バージョンの地図が得られます。このマップ上の位置と距離は、MKMapPoint、MKMapSize、および MKMapRect データ型を使用して指定されます。これらのデータ タイプを使用して、マップの表示領域を指定したり、オーバーレイの位置を指定したりすることができます。

これを大円オーバーレイにどのように適用するかはわかりません。誰でも助けることができますか?

4

4 に答える 4

9

MKPolyline を使用して 2 つの空港間を移動する航空機の大円ルートを描画するために、これを実装しました。

+ (void)createGreatCircleMKPolylineFromPoint:(CLLocationCoordinate2D)point1 
                                     toPoint:(CLLocationCoordinate2D)point2
                                  forMapView:(MKMapView*)mapView
{
double lat1 = point1.latitude;
double lon1 = point1.longitude;
double lat2 = point2.latitude;
double lon2 = point2.longitude;
lat1 = lat1 * (PI/180);
lon1 = lon1 * (PI/180);
lat2 = lat2 * (PI/180);
lon2 = lon2 * (PI/180);
double d = 2 * asin( sqrt(pow(( sin( (lat1-lat2)/2) ), 2) + cos(lat1) * cos(lat2) * pow(( sin( (lon1-lon2)/2) ), 2)));
int numsegs = 100;
CLLocationCoordinate2D *coords = malloc(sizeof(CLLocationCoordinate2D) * numsegs);
double f = 0.0;
for(int i=1; i<=numsegs; i++)
{
    f += 1.0 / (float)numsegs;
    double A=sin((1-f)*d)/sin(d);
    double B=sin(f*d)/sin(d);
    double x = A*cos(lat1) * cos(lon1) +  B * cos(lat2) * cos(lon2);
    double y = A*cos(lat1) * sin(lon1) +  B * cos(lat2) * sin(lon2);
    double z = A*sin(lat1)           +  B*sin(lat2);
    double latr=atan2(z, sqrt(pow(x, 2) + pow(y, 2) ));
    double lonr=atan2(y, x);
    double lat = latr * (180/PI);
    double lon = lonr * (180/PI);
    //        NSLog(@"lat: %f lon: %f", lat, lon);
    CLLocationCoordinate2D loc = CLLocationCoordinate2DMake(lat, lon);
    coords[i - 1] = loc;
}

//check for circling west to east. If the plane is crossing 180, we need
//to draw two lines or else the polyline connects the dots and draws a straight
//line all the way across the map.
CLLocationCoordinate2D prevCoord;
BOOL twoLines = NO;
int numsegs2 = 0;
CLLocationCoordinate2D *coords2;

for(int i=0; i<numsegs; i++)
{
    CLLocationCoordinate2D coord = coords[i];
    if(prevCoord.longitude < -170 && prevCoord.longitude > -180  && prevCoord.longitude < 0 
       && coord.longitude > 170 && coord.longitude < 180 && coord.longitude > 0)
    {
        twoLines = YES;
        coords2 = malloc(sizeof(CLLocationCoordinate2D) * (numsegs - i));
        numsegs2 = numsegs - i;
        for(int j=0; j<numsegs2; j++)
        {
            coords2[j] = coords[i + j];
        }
        break;
    }
    prevCoord = coord;
}

//remove any previously added overlays
[mapView removeOverlays:mapView.overlays];

if(twoLines)
{
    MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:numsegs - numsegs2];
    free(coords);
    [mapView addOverlay:polyline];

    MKPolyline *polyline2 = [MKPolyline polylineWithCoordinates:coords2 count:numsegs2];
    free(coords2);
    [mapView addOverlay:polyline2];
}
else
{
    MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:numsegs];
    free(coords);
    [mapView addOverlay:polyline];
}

}

これでオーバーレイが作成されました。あとは mapView:viewForOverlay で MKOverlayView を指定するだけです。

- (MKOverlayView*)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
    MKPolyline *polyline = (MKPolyline*)overlay;
    MKPolylineView *view = [[[MKPolylineView alloc] initWithPolyline:polyline] autorelease];
    //choose your line params here
    view.lineWidth = 2;
    view.fillColor = [UIColor blueColor];
    return view;
}

お役に立てれば。

スクリーンショット http://s1-03.twitpicproxy.com/photos/large/489178500.png

于 2012-01-04T23:45:32.857 に答える
3

ゲームの後半ですが、MKGeodesicPolyline「地球の表面に沿って最短経路をたどる」という iOS 7.0 以降の新機能について言及する価値があります。

MKPolylineOverlayこれにより、測地ポリライン タイプの作成と追加が簡単になります。

points = [CLLocationCoordinate2DMake(27.123, 85.765),
                  CLLocationCoordinate2DMake(41.444, 106.987)]
geodesic = MKGeodesicPolyline(coordinates: points, count: 2)
mapView.add(geodesic)

レンダラーを含め、mapView にデリゲートを与えることを忘れないでください。

//MARK: - MKMapView Delegate Method
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if overlay is MKGeodesicPolyline {
        let polylineRenderer = MKPolylineRenderer(overlay: overlay)
        polylineRenderer.strokeColor = UIColor.white
        polylineRenderer.lineWidth = 2.5
        return polylineRenderer
    }
}
于 2017-05-19T16:19:02.350 に答える
0

numsegs パラメータは、マップのズーム レベルと 2 点の距離に応じて変更できる必要があります。2 点の緯度/経度座標は、ピクセル座標に変換できます。したがって、numsegs パラメータは、ピクセル差の関数と見なすことができます。

于 2013-08-09T01:48:22.580 に答える
0

これは、MKOverlayPathView クラスのサブクラスを作成することで実現できます。(void)createPath メソッドをオーバーライドする必要があります。基本的には UIBezierPath を使用して円弧を作成するか、直接パスとして円弧を作成できますが、これは可能ですが、まだ行っていません。

メソッドでパスを定義したら、新しく作成したパスを使用してクラスのパス プロパティを設定する必要があります。そうすれば、パスのレンダリングは自動的に行われます。

お役に立てれば。

于 2011-07-13T09:23:45.403 に答える