我想在距离当前位置的距离上排序很多位置(航点)。 当然,当前位置是移动目标,因此对于每个位置更新,重新计算每个位置的距离是必要的。但只有重新计算附近的位置就足够了。
我目前使用核心数据,并在configurecell:atindexpath:方法中将距离存储为当前位置作为表中的属性(但仅在更改时更新)。 这类工作,但应用程序没有响应,而核心数据自动更新所有距离。这适用于250个位置,但是5000个崩溃。 我需要它才能在10.000个位置工作,尽管我可能只需要距离最近的1000个位置。
我还没试过的想法: 将所有距离存储在单独的内存数组中,只记录记录ID和距离。然后按距离对数组进行排序。问题是我不能使用FetchedResultsController,因为数据库中没有排序字段。
使用谓词根据纬度和经度过滤位置。然后只显示过滤后的位置。
在单独的线程中重新计算距离。
这些想法似乎都不容易尝试。
有人提出建议,不同的想法,对我的想法有所不同吗?
答案 0 :(得分:1)
听起来你需要将你的位置转换为希尔伯特曲线上的位置 - 然后点“靠近”你是一个简单的减法?
Mapping N-dimensional value to a point on Hilbert curve
不能说我知道里面的技术,但那是我开始看的地方
答案 1 :(得分:1)
如果重要的是顺序(而不是准确的距离),您可以在移动窗口中对航点序列的切片进行排序(即,将项目 i 排序到 i + n ,其中 i 更改)。从航点序列的开头开始。排序 n 项目(n = 10是一个很好的起点)。如果任何项目改变位置,则向前移动窗口 n / 2 (尝试使用不同的偏移或算法来选择偏移)并重复。根据航点在当前位置附近的密集程度,我预计这只会在几种情况下停止。
请注意,我没有想过这么长时间来说明这是否真的有效。
在你提到的三个选项中,我最喜欢使用线程。这是处理无响应用户界面的经典方式,当它被大量计算阻止时。
答案 2 :(得分:0)
我将我的位置作为纬度/经度坐标存储在数据模型中。然后我写了一些辅助扩展来找到lat / lon坐标的半矩形区域并通过它进行查询。这是我正在使用的代码。我知道这个问题是针对Objective-C的,但问题是陈旧的,现在大多数人都在寻找Swift的答案。
Swift 3
extension CLLocationDistance {
var feet: Double {
return self * 3.28084
}
var miles: Double {
return self.feet / 5280.0
}
}
extension CLLocationDegrees {
static var north: CLLocationDegrees {
return 90.0
}
static var south: CLLocationDegrees {
return -90.0
}
static var east: CLLocationDegrees {
return 180.0
}
static var west: CLLocationDegrees {
return -180.0
}
var radians: Double {
return Double.pi * self / 180.0
}
}
extension CLLocationCoordinate2D {
static var origin: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
}
static var northPole: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: 90.0, longitude: 0.0)
}
static var southPole: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: 90.0, longitude: 0.0)
}
var metersPerDegreeLatitude: CLLocationDistance {
return 111319.4907932736
}
var metersPerDegreeLongitude: CLLocationDistance {
return max(0.0, cos(self.latitude.radians) * self.metersPerDegreeLatitude)
}
}
extension CLCircularRegion {
var northernmostLatitude: CLLocationDegrees {
let longitude = self.center.latitude + self.radius / self.center.metersPerDegreeLatitude
return min(longitude, .north)
}
var southernmostLatitude: CLLocationDegrees {
let longitude = self.center.latitude - self.radius / self.center.metersPerDegreeLatitude
return max(longitude, .south)
}
var easternmostLongitude: CLLocationDegrees {
guard self.northernmostLatitude <= .north else {
return .east
}
guard self.southernmostLatitude >= .south else {
return .east
}
return min(.east, self.center.longitude + self.radius / (self.center.metersPerDegreeLongitude + 0.0001))
}
var westernmostLongitude: CLLocationDegrees {
guard self.northernmostLatitude <= .north else {
return .west
}
guard self.southernmostLatitude >= .south else {
return .west
}
return max(.west, self.center.longitude - self.radius / (self.center.metersPerDegreeLongitude + 0.0001))
}
func buildPredicate(latitudeName: String = "latitude", longitudeName: String = "longitude") -> NSPredicate {
let args = [self.southernmostLatitude, self.northernmostLatitude, self.westernmostLongitude, self.easternmostLongitude]
return NSPredicate(format: "\(latitudeName) >= %@ && \(latitudeName) <= %@ && \(longitudeName) >= %@ && \(longitudeName) <= %@", argumentArray: args)
}
}