有效地找到给定点所在的NSManagedObject(Polygon)

时间:2015-12-25 19:32:46

标签: ios swift core-data

我正在尝试查找给定点(CLLocationCoordinate2D)是否在Polygon NSManagedObject中。

我的Polygon对象定义为:

public class Polygon: NSManagedObject {
    @NSManaged var points: NSOrderedSet?
    @NSManaged var centroid: Point?
    @NSManaged var computed : NSNumber!
}

Point对象:

public class Point: NSManagedObject {
    @NSManaged var longitude: NSNumber!
    @NSManaged var latitude: NSNumber!
}

我当前的方法使用它来为Polygon对象创建谓词:

public static func nearbyPredicate(offset offset: Double, nearLocation location: CLLocationCoordinate2D) -> NSPredicate {
    let maxLat = location.latitude + offset
    let minLat = location.latitude - offset
    let maxLong = location.longitude - offset
    let minLong = location.longitude + offset
    return NSPredicate(format: "(centroid.latitude <= %@) && (centroid.latitude >= %@) && (centroid.longitude >= %@) && (centroid.longitude <= %@) && (computed == false)", argumentArray: [maxLat, minLat, maxLong, minLong])

}

offset是任意搜索'半径'。 {I}属性是我设置为computed的布尔值,一旦我试图检测true是否包含给定点,以便后续的提取调用排除对象(如谓词中所示) )。对于检测,我首先使用上面的谓词获取Polygon s,然后使用:

Polygon

这可能在计算上很重。我正在测试的多边形可能非常大且形状奇特。

是否有使用Core Data提高此流程的效率?有没有办法抵消计算let location : CLLocationCoordinate2D // ... point to test for poly in polysFetched { poly.computed = NSNumber(bool: true) let path = UIBezierPath() path.moveToPoint(CGPoint(x: (poly.points!.array as! [Point]).first!.longitude.doubleValue, y: (poly.points!.array as! [Point]).first!.latitude.doubleValue)) //set initial point for pt in poly.points!.array as! [Point] { path.addLineToPoint(CGPoint(x: pt.longitude.doubleValue, y: pt.latitude.doubleValue)) } if (CGPathContainsPoint(path.CGPath, nil, CGPoint(x: location.longitude, y: location.latitude), false)) { print("Poly \(poly) matches location \(location)") return } } 或其他方面的一个点的包含计算?

1 个答案:

答案 0 :(得分:2)

我最终以一些方式解决了这个问题并大大加快了这个过程。由于Point NSManagedObject仅存在于通过Polygon关系获取它们并计算UIBezierPath的路径(Polygon),因此我只计算了创建Polygon对象并将其存储为属性。我还将Centriod关系更改为两个属性c_latc_long并完全删除了Point类!索引c_latc_long属性也可以加快获取请求的速度。

新的Polygon课程是:

public class Polygon: NSManagedObject {
    @NSManaged internal var pathData : NSData!
    @NSManaged internal var c_lat : NSNumber!
    @NSManaged internal var c_long : NSNumber!
    @NSManaged var computed : NSNumber!

    var path : UIBezierPath {
        get {
            return NSKeyedUnarchiver.unarchiveObjectWithData(pathData) as! UIBezierPath
        }
        set {
            pathData = NSKeyedArchiver.archivedDataWithRootObject(newValue)
        }
    }

    var centroid : CLLocationCoordinate2D {
        get {
            return CLLocationCoordinate2D(latitude: c_lat.doubleValue, longitude: c_long.doubleValue)
        }
        set {
            c_lat = newValue.latitude
            c_long = newValue.longitude
        }
   }

    func containsLocation(location : CLLocationCoordinate2D) -> Bool {
        return self.path.containsPoint(CGPoint(x: location.latitude, y: location.longitude))
    }

}

Code不同的评论我原来的帖子建议维基百科页面检测多边形中的点,但方便的是用UIBezierPath从我身上抽象出来,并且存在一个函数CGPathContainsPoint一个布尔值作为其最后一个参数,用于在维基百科文章中提到的用于检测多边形中的点的两种算法之间进行选择。

对于遇到与我相同或类似问题的人,我建议内联关系并使用计算属性来访问您希望存储在Core Data中的非原始数据类型。