如何检查 CLLocationCoordinate2D 是否在四个 CLLocationCoordinate2D 正方形内?在 Objective C 和 Google 地图中
How can I check if a CLLocationCoordinate2D is inside four CLLocationCoordinate2D Square? in Objective C with Google Maps
我想测试 CLLocationCoordinate2D 是否在由其他四个 CLLocationCoordinate2D 创建的 Square 中
我有这样的结构:
typedef struct {
CLLocationCoordinate2D southWest;
CLLocationCoordinate2D southEast;
CLLocationCoordinate2D northEast;
CLLocationCoordinate2D northWest;
} Bounds;
还有一个 CLLocationCoordinate2D 坐标作为参数传递。我想测试坐标是否在边界内。我该如何测试?
- (BOOL) isCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds { ... }
您只需创建一个 CLregion
或 CLCircularRegion
并检查坐标是否包含在该区域内...
像这样
CLCircularRegion *myRegion = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(22, -111) radius:500 identifier:@"myRegion"];
if ([myRegion containsCoordinate:CLLocationCoordinate2DMake(22.45, -111.1)]) {
//Do what you want here
}
如果你有四个点,你可以制作一个 CGRect 并使用 CGRectContainsPoint()
如果4个点不是代表矩形或圆形,而是地图上的任意4个点,则需要您自己创建系统。对于位于由 4 个定向点表示的形状内部的点,最简单的方法是检查中心与每对连续的边界点之间的叉积。对于点在边界内的顺时针顺序,所有结果都必须为正。第二件事是你需要将坐标转换为笛卡尔系统并定位它们......让代码说明一切:
- (double)crossProductZCoordinateForCenter:(CLLocationCoordinate2D)center left:(CLLocationCoordinate2D)left right:(CLLocationCoordinate2D)right {
CLLocationCoordinate2D A = CLLocationCoordinate2DMake(left.latitude-center.latitude, left.longitude-center.longitude);
CLLocationCoordinate2D B = CLLocationCoordinate2DMake(right.latitude-center.latitude, right.longitude-center.longitude);
return B.latitude*A.longitude - A.latitude*B.longitude;
}
- (BOOL)isCartesianCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds {
// Now we will break the system into 4 triangles and check their orientation by using a z component of the cross product. If one of them if negative the coordinate is not inside the region
if([self crossProductZCoordinateForCenter:coordinate left:bounds.southWest right:bounds.northWest] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.northWest right:bounds.northEast] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.northEast right:bounds.southEast] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.southEast right:bounds.southWest] < .0) return NO;
return YES;
}
- (BOOL)isCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds {
// We may treat the coordinates as cartesian but east should always be larger then west and north should be larger then south
// Those smaller must be increased by 360 degrees
if(bounds.southEast.latitude < bounds.southWest.latitude) bounds.southEast.latitude += 360.0;
if(bounds.northEast.latitude < bounds.northWest.latitude) bounds.northEast.latitude += 360.0;
if(bounds.northEast.longitude < bounds.southEast.longitude) bounds.northEast.longitude += 360.0;
if(bounds.northWest.longitude < bounds.southWest.longitude) bounds.northWest.longitude += 360.0;
// Check if any of the combination coordinates are cartesicly inside the bounds
// We need to increase the longitude and the latitude by 360 and check all 4 combinations
if([self isCartesianCoordinate:coordinate insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude+360.0, coordinate.longitude) insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude+360.0) insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude+360.0, coordinate.longitude+360.0) insideBounds:bounds]) return YES;
return NO;
}
一些简单的测试可能会派上用场:
- (void)resampleCoordinate:(CLLocationCoordinate2D *)coordinate {
if(coordinate->latitude < -180.0) coordinate->latitude += 360.0;
if(coordinate->latitude > 180.0) coordinate->latitude -= 360.0;
if(coordinate->longitude < -180.0) coordinate->longitude += 360.0;
if(coordinate->longitude > 180.0) coordinate->longitude -= 360.0;
}
- (void)testLocationSystem {
NSInteger numberOfTests = 0;
NSInteger numberOfTestsCheckedOut = 0;
for(double latitude = -180.0; latitude <= 180.0; latitude++) {
for(double longitude = -180.0; longitude <= 180.0; longitude++) {
Bounds bounds;
bounds.southWest = CLLocationCoordinate2DMake(latitude-15.0, longitude-15.0);
bounds.northEast = CLLocationCoordinate2DMake(latitude+15.0, longitude+15.0);
bounds.northWest = CLLocationCoordinate2DMake(latitude-15.0, longitude+15.0);
bounds.southEast = CLLocationCoordinate2DMake(latitude+15.0, longitude-15.0);
[self resampleCoordinate:&(bounds.northWest)];
[self resampleCoordinate:&(bounds.northEast)];
[self resampleCoordinate:&(bounds.southEast)];
[self resampleCoordinate:&(bounds.southWest)];
numberOfTests++;
BOOL success = [self isCoordinate:CLLocationCoordinate2DMake(latitude, longitude) insideBounds:bounds];
if(success) {
numberOfTestsCheckedOut++;
}
else {
NSLog(@"Failed");
}
}
}
NSLog(@"%d/%d succeeded", (int)numberOfTestsCheckedOut, (int)numberOfTests);
}
- (void)testLocationFailSystem {
NSInteger numberOfTests = 0;
NSInteger numberOfTestsCheckedOut = 0;
for(double latitude = -180.0; latitude <= 180.0; latitude++) {
for(double longitude = -180.0; longitude <= 180.0; longitude++) {
Bounds bounds;
bounds.southWest = CLLocationCoordinate2DMake(latitude-15.0, longitude-15.0);
bounds.northEast = CLLocationCoordinate2DMake(latitude+15.0, longitude+15.0);
bounds.northWest = CLLocationCoordinate2DMake(latitude-15.0, longitude+15.0);
bounds.southEast = CLLocationCoordinate2DMake(latitude+15.0, longitude-15.0);
[self resampleCoordinate:&(bounds.northWest)];
[self resampleCoordinate:&(bounds.northEast)];
[self resampleCoordinate:&(bounds.southEast)];
[self resampleCoordinate:&(bounds.southWest)];
for(double angle = .0f; angle < M_PI; angle+=M_PI/10.0) {
CLLocationCoordinate2D coordiunate = CLLocationCoordinate2DMake(latitude+cos(angle)*20.0, longitude+sin(angle)*20.0);
[self resampleCoordinate:&coordiunate];
numberOfTests++;
BOOL success = [self isCoordinate:coordiunate insideBounds:bounds]; // must fail
if(success == NO) {
numberOfTestsCheckedOut++;
}
else {
NSLog(@"Failed");
}
}
}
}
NSLog(@"%d/%d succeeded", (int)numberOfTestsCheckedOut, (int)numberOfTests);
}
这些对我来说都过去了。如果您发现情况不可行但应该或其他方式请联系我。
我想测试 CLLocationCoordinate2D 是否在由其他四个 CLLocationCoordinate2D 创建的 Square 中
我有这样的结构:
typedef struct {
CLLocationCoordinate2D southWest;
CLLocationCoordinate2D southEast;
CLLocationCoordinate2D northEast;
CLLocationCoordinate2D northWest;
} Bounds;
还有一个 CLLocationCoordinate2D 坐标作为参数传递。我想测试坐标是否在边界内。我该如何测试?
- (BOOL) isCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds { ... }
您只需创建一个 CLregion
或 CLCircularRegion
并检查坐标是否包含在该区域内...
像这样
CLCircularRegion *myRegion = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(22, -111) radius:500 identifier:@"myRegion"];
if ([myRegion containsCoordinate:CLLocationCoordinate2DMake(22.45, -111.1)]) {
//Do what you want here
}
如果你有四个点,你可以制作一个 CGRect 并使用 CGRectContainsPoint()
如果4个点不是代表矩形或圆形,而是地图上的任意4个点,则需要您自己创建系统。对于位于由 4 个定向点表示的形状内部的点,最简单的方法是检查中心与每对连续的边界点之间的叉积。对于点在边界内的顺时针顺序,所有结果都必须为正。第二件事是你需要将坐标转换为笛卡尔系统并定位它们......让代码说明一切:
- (double)crossProductZCoordinateForCenter:(CLLocationCoordinate2D)center left:(CLLocationCoordinate2D)left right:(CLLocationCoordinate2D)right {
CLLocationCoordinate2D A = CLLocationCoordinate2DMake(left.latitude-center.latitude, left.longitude-center.longitude);
CLLocationCoordinate2D B = CLLocationCoordinate2DMake(right.latitude-center.latitude, right.longitude-center.longitude);
return B.latitude*A.longitude - A.latitude*B.longitude;
}
- (BOOL)isCartesianCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds {
// Now we will break the system into 4 triangles and check their orientation by using a z component of the cross product. If one of them if negative the coordinate is not inside the region
if([self crossProductZCoordinateForCenter:coordinate left:bounds.southWest right:bounds.northWest] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.northWest right:bounds.northEast] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.northEast right:bounds.southEast] < .0) return NO;
if([self crossProductZCoordinateForCenter:coordinate left:bounds.southEast right:bounds.southWest] < .0) return NO;
return YES;
}
- (BOOL)isCoordinate:(CLLocationCoordinate2D)coordinate insideBounds:(Bounds)bounds {
// We may treat the coordinates as cartesian but east should always be larger then west and north should be larger then south
// Those smaller must be increased by 360 degrees
if(bounds.southEast.latitude < bounds.southWest.latitude) bounds.southEast.latitude += 360.0;
if(bounds.northEast.latitude < bounds.northWest.latitude) bounds.northEast.latitude += 360.0;
if(bounds.northEast.longitude < bounds.southEast.longitude) bounds.northEast.longitude += 360.0;
if(bounds.northWest.longitude < bounds.southWest.longitude) bounds.northWest.longitude += 360.0;
// Check if any of the combination coordinates are cartesicly inside the bounds
// We need to increase the longitude and the latitude by 360 and check all 4 combinations
if([self isCartesianCoordinate:coordinate insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude+360.0, coordinate.longitude) insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude+360.0) insideBounds:bounds]) return YES;
if([self isCartesianCoordinate:CLLocationCoordinate2DMake(coordinate.latitude+360.0, coordinate.longitude+360.0) insideBounds:bounds]) return YES;
return NO;
}
一些简单的测试可能会派上用场:
- (void)resampleCoordinate:(CLLocationCoordinate2D *)coordinate {
if(coordinate->latitude < -180.0) coordinate->latitude += 360.0;
if(coordinate->latitude > 180.0) coordinate->latitude -= 360.0;
if(coordinate->longitude < -180.0) coordinate->longitude += 360.0;
if(coordinate->longitude > 180.0) coordinate->longitude -= 360.0;
}
- (void)testLocationSystem {
NSInteger numberOfTests = 0;
NSInteger numberOfTestsCheckedOut = 0;
for(double latitude = -180.0; latitude <= 180.0; latitude++) {
for(double longitude = -180.0; longitude <= 180.0; longitude++) {
Bounds bounds;
bounds.southWest = CLLocationCoordinate2DMake(latitude-15.0, longitude-15.0);
bounds.northEast = CLLocationCoordinate2DMake(latitude+15.0, longitude+15.0);
bounds.northWest = CLLocationCoordinate2DMake(latitude-15.0, longitude+15.0);
bounds.southEast = CLLocationCoordinate2DMake(latitude+15.0, longitude-15.0);
[self resampleCoordinate:&(bounds.northWest)];
[self resampleCoordinate:&(bounds.northEast)];
[self resampleCoordinate:&(bounds.southEast)];
[self resampleCoordinate:&(bounds.southWest)];
numberOfTests++;
BOOL success = [self isCoordinate:CLLocationCoordinate2DMake(latitude, longitude) insideBounds:bounds];
if(success) {
numberOfTestsCheckedOut++;
}
else {
NSLog(@"Failed");
}
}
}
NSLog(@"%d/%d succeeded", (int)numberOfTestsCheckedOut, (int)numberOfTests);
}
- (void)testLocationFailSystem {
NSInteger numberOfTests = 0;
NSInteger numberOfTestsCheckedOut = 0;
for(double latitude = -180.0; latitude <= 180.0; latitude++) {
for(double longitude = -180.0; longitude <= 180.0; longitude++) {
Bounds bounds;
bounds.southWest = CLLocationCoordinate2DMake(latitude-15.0, longitude-15.0);
bounds.northEast = CLLocationCoordinate2DMake(latitude+15.0, longitude+15.0);
bounds.northWest = CLLocationCoordinate2DMake(latitude-15.0, longitude+15.0);
bounds.southEast = CLLocationCoordinate2DMake(latitude+15.0, longitude-15.0);
[self resampleCoordinate:&(bounds.northWest)];
[self resampleCoordinate:&(bounds.northEast)];
[self resampleCoordinate:&(bounds.southEast)];
[self resampleCoordinate:&(bounds.southWest)];
for(double angle = .0f; angle < M_PI; angle+=M_PI/10.0) {
CLLocationCoordinate2D coordiunate = CLLocationCoordinate2DMake(latitude+cos(angle)*20.0, longitude+sin(angle)*20.0);
[self resampleCoordinate:&coordiunate];
numberOfTests++;
BOOL success = [self isCoordinate:coordiunate insideBounds:bounds]; // must fail
if(success == NO) {
numberOfTestsCheckedOut++;
}
else {
NSLog(@"Failed");
}
}
}
}
NSLog(@"%d/%d succeeded", (int)numberOfTestsCheckedOut, (int)numberOfTests);
}
这些对我来说都过去了。如果您发现情况不可行但应该或其他方式请联系我。