سؤال

I'm defining two functions:

In mkgeometry_additions.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

MKMapRect MKMapRectForCoordinateRegion(MKCoordinateRegion region);

MKCoordinateRegion MKCoordinateRegionForSouthWestAndNorthEast(CLLocationCoordinate2D sw, CLLocationCoordinate2D ne);

In mkgeometry_additions.m (.m, even though they're c functions)

MKMapRect MKMapRectForCoordinateRegion(MKCoordinateRegion region)
{
    CLLocationCoordinate2D center = region.center;
    MKCoordinateSpan span = region.span;
    CLLocationCoordinate2D topLeft =
        CLLocationCoordinate2DMake(center.latitude - span.latitudeDelta / 2.0,
                                   center.longitude - span.longitudeDelta / 2.0);
    CLLocationCoordinate2D bottomRight =
    CLLocationCoordinate2DMake(center.latitude - span.latitudeDelta / 2.0,
                               center.longitude - span.longitudeDelta / 2.0);
    MKMapPoint mapPointTopLeft = MKMapPointForCoordinate(topLeft);
    MKMapPoint mapPointBottomRight = MKMapPointForCoordinate(bottomRight);
    double width = mapPointTopLeft.x - mapPointBottomRight.x;
    double height = mapPointTopLeft.y - mapPointBottomRight.y;

    return MKMapRectMake(mapPointTopLeft.x, mapPointTopLeft.y, width, height);
}

MKCoordinateRegion MKCoordinateRegionForSouthWestAndNorthEast(CLLocationCoordinate2D sw, CLLocationCoordinate2D ne)
{
    MKCoordinateSpan span =
        MKCoordinateSpanMake(ne.latitude - sw.latitude, ne.longitude - sw.longitude);
    CLLocationCoordinate2D topLeft = CLLocationCoordinate2DMake(ne.latitude, sw.longitude);
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(topLeft.latitude + span.latitudeDelta * 0.5, topLeft.longitude + span.longitudeDelta * 0.5);
    return MKCoordinateRegionMake(center, span);
}

That's pretty much the entirety of the two files.

In my unit test with XCTests:

- (void)testMKMapRectForCoordinateRegionAfterReverseConversion
{
    CLLocationCoordinate2D fremont = CLLocationCoordinate2DMake(37.54827, -121.98857);
    MKCoordinateRegion region = MKCoordinateRegionMake(fremont, MKCoordinateSpanMake(0.05, 0.05));
    MKMapRect mapRect = MKMapRectForCoordinateRegion(region);
    MKCoordinateRegion derivedRegion = MKCoordinateRegionForMapRect(mapRect);

    double accuracy = 0.0001;

    XCTAssertEqualWithAccuracy(region.center.latitude, derivedRegion.center.latitude,
                               accuracy, @"Latitude is equal");
    XCTAssertEqualWithAccuracy(region.center.longitude, derivedRegion.center.longitude,
                               accuracy, @"Latitude is equal");
    XCTAssertEqualWithAccuracy(region.span.latitudeDelta, derivedRegion.span.latitudeDelta,
                               accuracy, @"Latitude delta is equal");
    XCTAssertEqualWithAccuracy(region.span.longitudeDelta, derivedRegion.span.longitudeDelta,
                               accuracy, @"Latitude delta is equal");
}

- (void)testMKCoordinateRegionForSouthWestAndNorthEast
{
    CLLocationCoordinate2D taipeiWanHua = CLLocationCoordinate2DMake(25.02946, 121.49652);
    CLLocationCoordinate2D taipeiSongShan = CLLocationCoordinate2DMake(25.06640, 121.56166);

    /* When the following line is called, the first test fails */
    MKCoordinateRegionForSouthWestAndNorthEast(taipeiWanHua, taipeiSongShan);

   /* I have the rest of the lines in this test commented out */
}

Now, I have empty setup and teardown for this test class. When I run the test. The first test fails if the third line of the second test is in the test. A closer look shows that when it fails, it's that the values are still similar but falling outside of the given accuracy: enter image description here

If I commented that third line of the second test out, the first test would pass. Why is that?

هل كانت مفيدة؟

المحلول

The problem is not with unit testing - for me it fails even if I comment out entirely the second test - it is with the MKMapRectForCoordinateRegion implementation. I think the correct implementation is:

MKMapRect MKMapRectForCoordinateRegion(MKCoordinateRegion region)
{
    CLLocationCoordinate2D center = region.center;
    MKCoordinateSpan span = region.span;
    CLLocationCoordinate2D topLeft =
    CLLocationCoordinate2DMake(center.latitude + span.latitudeDelta / 2.0,
                               center.longitude - span.longitudeDelta / 2.0);
    CLLocationCoordinate2D bottomRight =
    CLLocationCoordinate2DMake(center.latitude - span.latitudeDelta / 2.0,
                               center.longitude + span.longitudeDelta / 2.0);
    MKMapPoint mapPointTopLeft = MKMapPointForCoordinate(topLeft);
    MKMapPoint mapPointBottomRight = MKMapPointForCoordinate(bottomRight);
    double width = mapPointBottomRight.x - mapPointTopLeft.x;
    double height = mapPointBottomRight.y - mapPointTopLeft.y;

    MKMapRect ret = MKMapRectMake(mapPointTopLeft.x, mapPointTopLeft.y, width, height);
    return ret;
}

check out this: Mercator Projection

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top