2

MkMapView に線を描画していますが、その幅をメートル単位で指定したいと考えています。

私はこのようなことを試しました:

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>) overlay
{
    if([overlay isKindOfClass:[MKPolyline class]])
    {
        MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
        double ppm = MKMapPointsPerMeterAtLatitude(myLatitude);
        renderer.lineWidth = ppm * myMetersValue;
       ...

これにより、myMetersValue よりもはるかに広い線が生成され、ズームインおよびズームアウトしてもスケーリングされません。

ppmは約で一定のままです。地図を拡大縮小しても9.49。myLatitude が有効な緯度 (約 45 度) であることを確認しました。myMetersValue が妥当な # (約 18m) であることを確認しました。

(編集)

MKMapPointsPerMeterAtLatitude によって返される MapPoints がスクリーン ポイントではないことを発見したため、その関数を使用できません。

したがって、私の基本的な問題は、mkMapView でメーターをスクリーン ポイントに変換する方法です。もっと簡潔に言うと、コードで ppm の値を取得するにはどうすればよいですか? 私はこれを試しました(SOの他の場所にあります):

    MKCoordinateRegion myRegion = MKCoordinateRegionMakeWithDistance(mapView.centerCoordinate, 400, 0);
    CGRect myRect = [mapView convertRegion: myRegion toRectToView: nil];
    double ppm = myRect.size.width / 400.0;

それはうまくいきませんでした。

それから私はこれを試しました:

    CLLocationCoordinate2D l1 = [mapView convertPoint:CGPointMake(0,0) toCoordinateFromView:mapView];
    CLLocation *ll1 = [[CLLocation alloc] initWithLatitude:l1.latitude longitude:l1.longitude];
    CLLocationCoordinate2D l2 = [mapView convertPoint:CGPointMake(0,500) toCoordinateFromView:mapView];
    CLLocation *ll2 = [[CLLocation alloc] initWithLatitude:l2.latitude longitude:l2.longitude];
    double ppm = 500.0 / [ll1 distanceFromLocation:ll2];

ここでの考え方は、500 スクリーン ポイント離れた 2 つのポイントの緯度/経度を取得することです。次に、それらの間の距離をメートル単位で取得して、ppm を計算できるようにします。この種の動作はしましたが、結果の ppm が正しくないように見えるので、これが正しいとは確信できません。また、マップをズームすると、マップ上の既存の線が再レンダリングされないため、ズーム後も同じ幅のままになります (ただし、これは別の問題です)。

(編集)

私のppmの計算は正しいようです。問題は、ユーザーがズームを終了する前にレンダラーが呼び出されるため、線が最終的なズーム スケールでレンダリングされないことです。最終的なズームスケールが決定されたら再レンダリングを強制すると、ppm が正しくなり、コードが機能します。

4

2 に答える 2

0

以下は、メートル単位で特定の幅の MkPolyline を描画する方法の 1 つです。線がマップ上に描画されると、ユーザーがズームしても再レンダリングされない場合があることに注意してください。または、その場合、ユーザーがズームを終了する前に再レンダリングされる可能性があります。この場合、ズーム後の幅は、希望するメートル単位の幅を反映しなくなります。これに対処する 1 つの方法は、regionDidChangeAnimated をオーバーライドし、オーバーレイを削除して再度追加することです。この方法は私の特定のケースでは問題なく機能しますが、アンナの提案された解決策を検討する必要があると思います。これはより良い一般的なアプローチかもしれないからです。

-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>) overlay
{

if([overlay isKindOfClass:[MKPolyline class]])
{
    // the following are two methods of calculating PPM (screen points per meter).

    // method 1: requires that you have access to a latitude that is near to the line you are drawing
    CLLocationCoordinate2D l1 = CLLocationCoordinate2DMake(myLatitude, 0);
    CLLocationCoordinate2D l2 = CLLocationCoordinate2DMake(myLatitude + 1.0, 0);
    CGPoint p1 = [mapView convertCoordinate:l1 toPointToView:mapView];
    CGPoint p2 = [mapView convertCoordinate:l2 toPointToView:mapView];
    double ppm = (p1.y - p2.y) / (60.0 * METERS_PER_NAUTICALMILE);

    // method 2:
    CLLocationCoordinate2D l1 = [mapView convertPoint:CGPointMake(0,0) toCoordinateFromView:mapView];
    CLLocation *ll1 = [[CLLocation alloc] initWithLatitude:l1.latitude longitude:l1.longitude];
    CLLocationCoordinate2D l2 = [mapView convertPoint:CGPointMake(0,500) toCoordinateFromView:mapView];
    CLLocation *ll2 = [[CLLocation alloc] initWithLatitude:l2.latitude longitude:l2.longitude];
    ppm = 500.0 / [ll1 distanceFromLocation:ll2];

    MKPolyline *l = (MKPolyline *) overlay;
    MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
    renderer.lineWidth = ppm * myMetersValue;
    renderer.strokeColor = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:.3];
    renderer.lineCap = CGLineCap::kCGLineCapButt;
    return renderer;
}

return nil;

}
于 2014-07-18T18:14:26.617 に答える