IOS - 相当于 ios 中的 class 的 googlemaps polyutils

IOS - googlemaps polyutils equivalent class in ios

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

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

Link to android utils library

Link to IOS utils library

好吧,即使我遇到了同样的问题,所以我将 PolyUtils Android 库转换为 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;
}

距离以米为单位。希望对您有所帮助。

我在 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

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

  - (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)];
        }
    }
   
}