IOS - 在ios中googlemaps polyutils等效类

时间:2018-05-22 05:52:06

标签: ios objective-c google-maps google-maps-sdk-ios

我正在尝试在IOS google maps util Library中找到PolyUtils.distanceToLine等效函数。

函数distanceToLine能够计算点和线段之间的距离,而且我无法在Google地图IOS utils库中找到类似的东西。

Link to android utils library

Link to IOS utils library

3 个答案:

答案 0 :(得分:1)

好吧即使我遇到了同样的问题,所以我将PolyUtils Android Library转换为Objective-C

- (double) distanceOfPointToLine :(double)currentLocationX currentLocationY:(double)currentLocationY x1:(double)x1 y1:(double)y1 x2:(double)x2 y2:(double)y2 {
    if (x1 == x2) {
        [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x2 toLong:y2];
    } else {
        double s0lat = [self degreeToRadians:currentLocationX];
        double s0lng = [self degreeToRadians:currentLocationY];
        double s1lat = [self degreeToRadians:x1];
        double s1lng = [self degreeToRadians:y1];
        double s2lat = [self degreeToRadians:x2];
        double s2lng = [self degreeToRadians:y2];
        double s2s1lat = s2lat - s1lat;
        double s2s1lng = s2lng - s1lng;
        double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng) / (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
        if (u <= 0.0) {
             NSLog(@"%f",[self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x1 toLong:y1]);
             return [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x1 toLong:y1];
        } else if (u >= 1.0) {
             NSLog(@"%f",[self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x2 toLong:y2]);
            return [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x2 toLong:y2];
        } else {
            CLLocation* sa = [[CLLocation alloc]initWithLatitude:currentLocationX-x1 longitude:currentLocationY-y1];
            CLLocation* sb = [[CLLocation alloc]initWithLatitude:u*x2-x1 longitude:u*y2-y1];
            NSLog(@"%f",[self computeDistanceBetween:sa.coordinate.latitude fromLong:sa.coordinate.longitude toLat:sb.coordinate.latitude toLong:sb.coordinate.longitude]);
            return [self computeDistanceBetween:sa.coordinate.latitude fromLong:sa.coordinate.longitude toLat:sb.coordinate.latitude toLong:sb.coordinate.longitude];
        }
    }
    return 0;
}
- (double)computeDistanceBetween :(double)fromLat fromLong:(double)fromLong toLat:(double)toLat toLong:(double)toLong {
        return [self computeAngleBetween:fromLat lng1:fromLong lat2:toLat lng2:toLong] * 6371009.0;
}
- (double)computeAngleBetween :(double)lat1 lng1:(double)lng1 lat2:(double)lat2 lng2:(double)lng2 {
    return [self distanceRadians:[self degreeToRadians:lat1] lng1:[self degreeToRadians:lng1] lat2:[self degreeToRadians:lat2] lng2:[self degreeToRadians:lng2]];
}
- (double)degreeToRadians :(double)paramDegree {
    return paramDegree * M_PI/180;
}

- (double)distanceRadians :(double)lat1 lng1:(double)lng1 lat2:(double)lat2 lng2:(double)lng2 {
    return [self arcHav:[self havDistance:lat1 lat2:lat2 differenceBetweenLongitudes:lng1-lng2]];
}

- (double)arcHav :(double)x {
    return 2.0* asin(sqrt(x));
}
- (double)havDistance :(double)lat1 lat2:(double)lat2 differenceBetweenLongitudes:(double)differenceBetweenLongitudes {
    double sum = [self hav:lat1-lat2] + [self hav:differenceBetweenLongitudes] * cos(lat1) *cos(lat2);
    return sum;
}
- (double)hav :(double)x  {
    double sinHalf = sin(x*0.5);
    return sinHalf*sinHalf;
}

距离以米为单位。我希望这有用。

答案 1 :(得分:1)

我已经在Swift中创建了一个CLLocation扩展,可以这样使用:

let distance = location.distanceToLine(from: start, to: end)
extension CLLocation {

    /// Returns the shortest distance (measured in meters) from the current object's location to the imaginary line running between the two specified locations.
    ///
    /// - Parameters:
    ///   - start: The first location that makes up the imaginary line.
    ///   - end: The second location that makes up the imaginary line.
    /// - Returns: The shortest distance (in meters) between the current object's location and the imaginary line.
    func distanceToLine(from start: CLLocation, to end: CLLocation) -> CLLocationDistance {
        let s0lat = degreesToRadians(coordinate.latitude)
        let s0lng = degreesToRadians(coordinate.longitude)
        let s1lat = degreesToRadians(start.coordinate.latitude)
        let s1lng = degreesToRadians(start.coordinate.longitude)
        let s2lat = degreesToRadians(end.coordinate.latitude)
        let s2lng = degreesToRadians(end.coordinate.longitude)
        let s2s1lat = s2lat - s1lat
        let s2s1lng = s2lng - s1lng
        let u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng) / (s2s1lat * s2s1lat + s2s1lng * s2s1lng)
        if u <= 0.0 {
            return distance(from: start)
        } else if u >= 1.0 {
            return distance(from: end)
        } else {
            let sa = CLLocation(latitude: coordinate.latitude - start.coordinate.latitude,
                                longitude: coordinate.longitude - start.coordinate.longitude)
            let sb = CLLocation(latitude: u * (end.coordinate.latitude - start.coordinate.latitude),
                                longitude: u * (end.coordinate.longitude - start.coordinate.longitude))
            return sa.distance(from: sb)
        }
    }

    private func degreesToRadians(_ degrees: Double) -> Double { return degrees * .pi / 180.0 }

}

Gist

答案 2 :(得分:0)

上面的一个答案有一些错误 - 我在下面的代码中修复了它们。

  - (double) distanceOfPointToLine :(double)currentLocationX currentLocationY:(double)currentLocationY x1:(double)x1 y1:(double)y1 x2:(double)x2 y2:(double)y2 {
    if (x1 == x2 && y1 == y2) {
      return  [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x2 toLong:y2];
    } else {
        double s0lat = [self degreeToRadians:currentLocationX];
        double s0lng = [self degreeToRadians:currentLocationY];
        double s1lat = [self degreeToRadians:x1];
        double s1lng = [self degreeToRadians:y1];
        double s2lat = [self degreeToRadians:x2];
        double s2lng = [self degreeToRadians:y2];
        double s2s1lat = s2lat - s1lat;
        double s2s1lng = s2lng - s1lng;
        double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng) / (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
        if (u <= 0.0) {
             return [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x1 toLong:y1];
        } else if (u >= 1.0) {
            return [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x2 toLong:y2];
        } else {
            return [self computeDistanceBetween:currentLocationX fromLong:currentLocationY toLat:x1 + u * (x2-x1) toLong:y1 + u * (y2-y1)];
        }
    }
   
}