diff --git a/Source/Framework/Classes/MKGeometry.h b/Source/Framework/Classes/MKGeometry.h index 0a93732..b6aac82 100644 --- a/Source/Framework/Classes/MKGeometry.h +++ b/Source/Framework/Classes/MKGeometry.h @@ -55,30 +55,30 @@ typedef struct { } MKMapRect; /* -// MKZoomScale provides a conversion factor between MKMapPoints and screen points. -// When MKZoomScale = 1, 1 screen point = 1 MKMapPoint. When MKZoomScale is -// 0.5, 1 screen point = 2 MKMapPoints. -typedef CGFloat MKZoomScale; - -// The map point for the coordinate (-90,180) -extern const MKMapSize MKMapSizeWorld; -// The rect that contains every map point in the world. -extern const MKMapRect MKMapRectWorld; - + // MKZoomScale provides a conversion factor between MKMapPoints and screen points. + // When MKZoomScale = 1, 1 screen point = 1 MKMapPoint. When MKZoomScale is + // 0.5, 1 screen point = 2 MKMapPoints. + typedef CGFloat MKZoomScale; + // The map point for the coordinate (-90,180) + extern const MKMapSize MKMapSizeWorld; + // The rect that contains every map point in the world. + extern const MKMapRect MKMapRectWorld; + */ + // Conversion between unprojected and projected coordinates extern MKMapPoint MKMapPointForCoordinate(CLLocationCoordinate2D coordinate); extern CLLocationCoordinate2D MKCoordinateForMapPoint(MKMapPoint mapPoint); -// Conversion between distances and projected coordinates -extern CLLocationDistance MKMetersPerMapPointAtLatitude(CLLocationDegrees latitude); -extern double MKMapPointsPerMeterAtLatitude(CLLocationDegrees latitude); - -extern CLLocationDistance MKMetersBetweenMapPoints(MKMapPoint a, MKMapPoint b); +/* + // Conversion between distances and projected coordinates + extern CLLocationDistance MKMetersPerMapPointAtLatitude(CLLocationDegrees latitude); + extern double MKMapPointsPerMeterAtLatitude(CLLocationDegrees latitude);*/ -extern const MKMapRect MKMapRectNull;*/ +extern CLLocationDistance MKMetersBetweenMapPoints(MKMapPoint a, MKMapPoint b); +/*extern const MKMapRect MKMapRectNull;*/ -// Geometric operations on MKMapPoint/Size/Rect. See CGGeometry.h for +// Geometric operations on MKMapPoint/Size/Rect. See CGGeometry.h for // information on the CGFloat versions of these functions. static inline MKMapPoint MKMapPointMake(double x, double y) { return (MKMapPoint){x, y}; @@ -145,22 +145,22 @@ static inline NSString *MKStringFromMapRect(MKMapRect rect) { return [NSString stringWithFormat:@"{%@, %@}", MKStringFromMapPoint(rect.origin), MKStringFromMapSize(rect.size)]; } /* -extern MKMapRect MKMapRectUnion(MKMapRect rect1, MKMapRect rect2); -extern MKMapRect MKMapRectIntersection(MKMapRect rect1, MKMapRect rect2); -extern MKMapRect MKMapRectInset(MKMapRect rect, double dx, double dy); -extern MKMapRect MKMapRectOffset(MKMapRect rect, double dx, double dy); -extern void MKMapRectDivide(MKMapRect rect, MKMapRect *slice, MKMapRect *remainder, double amount, CGRectEdge edge); - -extern BOOL MKMapRectContainsPoint(MKMapRect rect, MKMapPoint point); -extern BOOL MKMapRectContainsRect(MKMapRect rect1, MKMapRect rect2); -extern BOOL MKMapRectIntersectsRect(MKMapRect rect1, MKMapRect rect2); - -extern MKCoordinateRegion MKCoordinateRegionForMapRect(MKMapRect rect); - -extern BOOL MKMapRectSpans180thMeridian(MKMapRect rect); -// For map rects that span the 180th meridian, this returns the portion of the rect -// that lies outside of the world rect wrapped around to the other side of the -// world. The portion of the rect that lies inside the world rect can be -// determined with MKMapRectIntersection(rect, MKMapRectWorld). -extern MKMapRect MKMapRectRemainder(MKMapRect rect); - */ + extern MKMapRect MKMapRectUnion(MKMapRect rect1, MKMapRect rect2); + extern MKMapRect MKMapRectIntersection(MKMapRect rect1, MKMapRect rect2); + extern MKMapRect MKMapRectInset(MKMapRect rect, double dx, double dy); + extern MKMapRect MKMapRectOffset(MKMapRect rect, double dx, double dy); + extern void MKMapRectDivide(MKMapRect rect, MKMapRect *slice, MKMapRect *remainder, double amount, CGRectEdge edge); + + extern BOOL MKMapRectContainsPoint(MKMapRect rect, MKMapPoint point); + extern BOOL MKMapRectContainsRect(MKMapRect rect1, MKMapRect rect2); + extern BOOL MKMapRectIntersectsRect(MKMapRect rect1, MKMapRect rect2); + + extern MKCoordinateRegion MKCoordinateRegionForMapRect(MKMapRect rect); + + extern BOOL MKMapRectSpans180thMeridian(MKMapRect rect); + // For map rects that span the 180th meridian, this returns the portion of the rect + // that lies outside of the world rect wrapped around to the other side of the + // world. The portion of the rect that lies inside the world rect can be + // determined with MKMapRectIntersection(rect, MKMapRectWorld). + extern MKMapRect MKMapRectRemainder(MKMapRect rect); + */ \ No newline at end of file diff --git a/Source/Framework/Classes/MKGeometry.m b/Source/Framework/Classes/MKGeometry.m new file mode 100644 index 0000000..3abaa16 --- /dev/null +++ b/Source/Framework/Classes/MKGeometry.m @@ -0,0 +1,38 @@ +/* + * MKGeometry.m + * MapKit + * + * Created by Zach Drayer on 3/20/13. + * + */ + +#import "MKGeometry.h" + +#import + +#define MKEarthRadius 6396002.3421 // In meters. Approximation of the radius used by Apple. This gets us within 7 decimal points of precision in MKMetersBetweenMapPoints + +extern MKMapPoint MKMapPointForCoordinate(CLLocationCoordinate2D coordinate) +{ + return MKMapPointMake(coordinate.latitude, coordinate.longitude); +} + +extern CLLocationCoordinate2D MKCoordinateForMapPoint(MKMapPoint mapPoint) +{ + return CLLocationCoordinate2DMake(mapPoint.x, mapPoint.y); +} + +// Haversine formula +extern CLLocationDistance MKMetersBetweenMapPoints(MKMapPoint pointA, MKMapPoint pointB) +{ + CLLocationDegrees differenceInLatitude = ((M_PI / 180) * (pointB.x - pointA.x)); // convert values to radians + CLLocationDegrees differenceInLongitude = ((M_PI / 180) * (pointB.y - pointA.x)); + CLLocationDegrees firstLatitude = ((M_PI / 180) * pointA.x); + CLLocationDegrees secondLatitude = ((M_PI / 180) * pointB.x); + + // a: Square of half the chord length between the points + // c: Angular distance in radians + CGFloat a = sin(differenceInLatitude / 2) * sin(differenceInLatitude / 2) + sin(differenceInLongitude / 2) * sin(differenceInLongitude / 2) * cos(firstLatitude) * cos(secondLatitude); + CGFloat c = 2 * atan2(sqrt(a), sqrt(1 - a)); + return MKEarthRadius * c; +} \ No newline at end of file diff --git a/Source/Framework/Classes/MKMultiPoint.h b/Source/Framework/Classes/MKMultiPoint.h index d114b6f..2841a8b 100644 --- a/Source/Framework/Classes/MKMultiPoint.h +++ b/Source/Framework/Classes/MKMultiPoint.h @@ -12,12 +12,12 @@ #import @interface MKMultiPoint : MKShape { - CLLocationCoordinate2D *coordinates; - NSUInteger coordinateCount; + MKMapPoint *points; + NSUInteger pointCount; } -@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates; -@property (nonatomic, readonly) NSUInteger coordinateCount; +@property (nonatomic, readonly) MKMapPoint *points; +@property (nonatomic, readonly) NSUInteger pointCount; - (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range; diff --git a/Source/Framework/Classes/MKMultiPoint.m b/Source/Framework/Classes/MKMultiPoint.m index d95a584..c57b767 100644 --- a/Source/Framework/Classes/MKMultiPoint.m +++ b/Source/Framework/Classes/MKMultiPoint.m @@ -11,15 +11,15 @@ @implementation MKMultiPoint -@synthesize coordinates; -@synthesize coordinateCount; +@synthesize points; +@synthesize pointCount; - (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range { - for (int i = range.location; i < range.location+range.length; i++) + for (int i = range.location; i < MAX(range.location+range.length, pointCount); i++) { - coords[i] = coordinates[i]; + coords[i] = MKCoordinateForMapPoint(points[i]); } } diff --git a/Source/Framework/Classes/MKPolygon.m b/Source/Framework/Classes/MKPolygon.m index 35c9bc1..67681fa 100644 --- a/Source/Framework/Classes/MKPolygon.m +++ b/Source/Framework/Classes/MKPolygon.m @@ -36,7 +36,7 @@ - (CLLocationCoordinate2D) coordinate - (void)dealloc { - free(coordinates); + free(points); [interiorPolygons release]; [super dealloc]; } @@ -47,12 +47,12 @@ - (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)cou { if (self = [super init]) { - coordinates = malloc(sizeof(CLLocationCoordinate2D) * count); + points = malloc(sizeof(MKMapPoint) * count); for (int i = 0; i < count; i++) { - coordinates[i] = coords[i]; + points[i] = MKMapPointForCoordinate(coords[i]); } - coordinateCount = count; + pointCount = count; } return self; } diff --git a/Source/Framework/Classes/MKPolygonView.m b/Source/Framework/Classes/MKPolygonView.m index 60852f0..d099b43 100644 --- a/Source/Framework/Classes/MKPolygonView.m +++ b/Source/Framework/Classes/MKPolygonView.m @@ -89,12 +89,12 @@ - (void)draw:(WebScriptObject *)overlayScriptObject - (NSArray *)pathForPolygon:(MKPolygon *)aPolygon webScriptObject:(WebScriptObject *)webScriptObject { - CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * aPolygon.coordinateCount); - NSRange range = NSMakeRange(0, aPolygon.coordinateCount); + CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * aPolygon.pointCount); + NSRange range = NSMakeRange(0, aPolygon.pointCount); [aPolygon getCoordinates:coordinates range:range]; NSMutableArray *newPath = [NSMutableArray array]; - for (int i = 0; i< aPolygon.coordinateCount; i++) + for (int i = 0; i< aPolygon.pointCount; i++) { CLLocationCoordinate2D coordinate = coordinates[i]; NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", coordinate.latitude, coordinate.longitude]; diff --git a/Source/Framework/Classes/MKPolyline.h b/Source/Framework/Classes/MKPolyline.h index f9eb80b..ecc0ae3 100644 --- a/Source/Framework/Classes/MKPolyline.h +++ b/Source/Framework/Classes/MKPolyline.h @@ -13,6 +13,7 @@ @interface MKPolyline : MKMultiPoint + (MKPolyline *)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count; ++ (MKPolyline *)polylineWithPoints:(MKMapPoint *)points count:(NSUInteger)count; @end diff --git a/Source/Framework/Classes/MKPolyline.m b/Source/Framework/Classes/MKPolyline.m index b3a385f..3a488de 100644 --- a/Source/Framework/Classes/MKPolyline.m +++ b/Source/Framework/Classes/MKPolyline.m @@ -22,6 +22,11 @@ + (MKPolyline *)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:( return [[[MKPolyline alloc] initWithCoordinates:coords count:count] autorelease]; } ++ (MKPolyline *)polylineWithPoints:(MKMapPoint *)points count:(NSUInteger)count +{ + return [[[MKPolyline alloc] initWithPoints:points count:count] autorelease]; +} + - (CLLocationCoordinate2D) coordinate { return [super coordinate]; @@ -29,7 +34,7 @@ - (CLLocationCoordinate2D) coordinate - (void)dealloc { - free(coordinates); + free(points); [super dealloc]; } @@ -39,12 +44,26 @@ - (id)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)cou { if (self = [super init]) { - coordinates = malloc(sizeof(CLLocationCoordinate2D) * count); + points = malloc(sizeof(MKMapPoint) * count); + for (int i = 0; i < count; i++) + { + points[i] = MKMapPointForCoordinate(coords[i]); + } + pointCount = count; + } + return self; +} + +- (id)initWithPoints:(MKMapPoint *)coords count:(NSUInteger)count +{ + if (self = [super init]) + { + points = malloc(sizeof(MKMapPoint) * count); for (int i = 0; i < count; i++) { - coordinates[i] = coords[i]; + points[i] = coords[i]; } - coordinateCount = count; + pointCount = count; } return self; } diff --git a/Source/Framework/Classes/MKPolylineView.m b/Source/Framework/Classes/MKPolylineView.m index cab4356..4e3be6c 100644 --- a/Source/Framework/Classes/MKPolylineView.m +++ b/Source/Framework/Classes/MKPolylineView.m @@ -50,12 +50,12 @@ - (void)draw:(WebScriptObject *)overlayScriptObject { if (!path) { - CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * [self polyline].coordinateCount); - NSRange range = NSMakeRange(0, [self polyline].coordinateCount); + CLLocationCoordinate2D *coordinates = malloc(sizeof(CLLocationCoordinate2D) * [self polyline].pointCount); + NSRange range = NSMakeRange(0, [self polyline].pointCount); [[self polyline] getCoordinates:coordinates range:range]; NSMutableArray *newPath = [NSMutableArray array]; - for (int i = 0; i< [self polyline].coordinateCount; i++) + for (int i = 0; i< [self polyline].pointCount; i++) { CLLocationCoordinate2D coordinate = coordinates[i]; NSString *script = [NSString stringWithFormat:@"new google.maps.LatLng(%f, %f);", coordinate.latitude, coordinate.longitude]; diff --git a/Source/MapKit.xcodeproj/project.pbxproj b/Source/MapKit.xcodeproj/project.pbxproj index d869d5b..0d4a690 100644 --- a/Source/MapKit.xcodeproj/project.pbxproj +++ b/Source/MapKit.xcodeproj/project.pbxproj @@ -113,6 +113,9 @@ 5FE1308715E94B9600265D22 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FE1308615E94B9600265D22 /* CoreFoundation.framework */; }; 5FE8314812A60AF600728ECE /* MapKitPluginLibrary.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FE8314712A60AF600728ECE /* MapKitPluginLibrary.xib */; }; 5FE8314C12A60BFF00728ECE /* MKMapViewAttributeInspector.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5FE8314B12A60BFF00728ECE /* MKMapViewAttributeInspector.xib */; }; + E60096E51701809F00484C44 /* MKGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = E60096E41701809F00484C44 /* MKGeometry.m */; }; + E60096E6170180EC00484C44 /* MKGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = E60096E41701809F00484C44 /* MKGeometry.m */; }; + E60096E7170180EC00484C44 /* MKGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = E60096E41701809F00484C44 /* MKGeometry.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -269,6 +272,7 @@ 5FE8314712A60AF600728ECE /* MapKitPluginLibrary.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MapKitPluginLibrary.xib; sourceTree = ""; }; 5FE8314B12A60BFF00728ECE /* MKMapViewAttributeInspector.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MKMapViewAttributeInspector.xib; sourceTree = ""; }; D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; + E60096E41701809F00484C44 /* MKGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKGeometry.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -375,6 +379,7 @@ 5FB7407611F8C81800AB2079 /* MKMapView+WebViewIntegration.m */, 5FBAF7C711F1486D004753A9 /* MKTypes.h */, 5FBAF7C811F1486D004753A9 /* MKGeometry.h */, + E60096E41701809F00484C44 /* MKGeometry.m */, 5FBAF7C911F1486D004753A9 /* MapKit.h */, 5FBAF7CA11F1486D004753A9 /* MKUserLocation.h */, 5FBAF7CB11F1486D004753A9 /* MKUserLocation.m */, @@ -810,6 +815,7 @@ files = ( 5F6EF15011F13BCB0077E84F /* main.m in Sources */, 5F6EF16B11F13CB70077E84F /* DemoAppApplicationDelegate.m in Sources */, + E60096E51701809F00484C44 /* MKGeometry.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -850,6 +856,7 @@ 5F39D6FF12B5AB50001B32CD /* MKWebView.m in Sources */, 5F9CE3DB12D15F98006354EF /* MKGeocoder.m in Sources */, 5F96B22613BAB9F4000A1E4A /* MKMapView+Private.m in Sources */, + E60096E6170180EC00484C44 /* MKGeometry.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -860,6 +867,7 @@ 5FB7438411FE705E00AB2079 /* MapKitPlugin.m in Sources */, 5FB7438811FE70AC00AB2079 /* MKMapViewAttributeInspector.m in Sources */, 5F19A03E1208F6DE0083FE72 /* MKMapView+MapKitPlugin.m in Sources */, + E60096E7170180EC00484C44 /* MKGeometry.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };