gpt4 book ai didi

swift - 如何在不使 CPU 使用率最大化的情况下显示大量 GMSPolylines?

转载 作者:可可西里 更新时间:2023-11-01 01:49:36 25 4
gpt4 key购买 nike

我正在开发一个应用,它使用 NextBus API 和 Google map 显示公交路线。但是,我遇到了 CPU 使用问题,我认为这是由 map 上的 GMSPolylines 数量引起的。路线由一组折线显示,这些折线由 NextBus 为给定路线给出的点组成。当折线被添加到 map 并且 GMSCamera 正在概览整条路线时,模拟器 (iPhone X) 上的 CPU 达到 100%。然而,当放大路线的特定部分时,CPU 使用率下降到 ~2%。

map 截图:https://i.imgur.com/jLmN26e.png性能:https://i.imgur.com/nUbIv5w.png

NextBus API 返回路线信息,包括特定巴士路径的路线。这是我正在处理的数据的一个小例子:

Route: {
"path": [Path]
}

Path: {
"points:" [Coordinate]
}

Coordinate: {
"lat": Float,
"lon": Float
}

这是我根据数据创建多段线的方法。总而言之,一条路线平均有约 700 个坐标分布在约 28 条折线(每个路径对象)上。请记住,我不会在一个页面上显示多条路线,我一次只显示一条路线。

func buildRoute(routePath: [Path?]) -> [GMSPolyline] {
var polylines: [GMSPolyline] = []

for path in routePath {
let path = GMSMutablePath()
guard let coords = path?.points else {continue}

for coordinate in coords {
// Safely unwrap latitude strings and convert them to doubles.
guard let latStr = coordinate?.lat,
let lonStr = coordinate?.lon else {
continue
}

guard let latOne = Double(latStr),
let lonOne = Double(lonStr) else {
continue
}

// Create location coordinates.
let pointCoordinatie = CLLocationCoordinate2D(latitude: latOne, longitude: lonOne)
path.add(pointCoordinatie)
}

let line = GMSPolyline(path: path)
line.strokeWidth = 6
line.strokeColor = UIColor(red: 0/255, green: 104/255, blue: 139/255, alpha: 1.0)
polylines.append(line)
}

return polylines
}

最后,这是我将多段线添加到 map 的方法:

fileprivate func buildRoute(routeConfig: RouteConfig?) {
if let points = routeConfig?.route?.path {
let polylines = RouteBuiler.shared.buildRoute(routePath: points)

DispatchQueue.main.async {
// Remove polylines from map if there are any.
for line in self.currentRoute {
line.map = nil
}

// Set new current route and add it to the map.
self.currentRoute = polylines
for line in self.currentRoute {
line.map = self.mapView
}
}
}
}

我构建多段线的方式有问题吗?还是坐标太多了?

最佳答案

我遇到了这个确切的问题。这是一个非常奇怪的错误——当您超过某个折线阈值时,CPU 突然固定到 100%。

我发现 GMSPolygon 没有这个问题。所以我将所有的 GMSPolyline 都切换到了 GMSPolygon。

为了获得正确的笔划宽度,我使用以下代码创建一个多边形,该多边形以给定的笔划宽度追踪多段线的轮廓。我的计算需要 LASwift 线性代数库。

https://github.com/AlexanderTar/LASwift

import CoreLocation
import LASwift
import GoogleMaps

struct Segment {
let from: CLLocationCoordinate2D
let to: CLLocationCoordinate2D
}

enum RightLeft {
case right, left
}

// Offset the given path to the left or right by the given distance
func offsetPath(rightLeft: RightLeft, path: [CLLocationCoordinate2D], offset: Double) -> [CLLocationCoordinate2D] {
var offsetPoints = [CLLocationCoordinate2D]()
var prevSegment: Segment!

for i in 0..<path.count {
// Test if this is the last point
if i == path.count-1 {
if let to = prevSegment?.to {
offsetPoints.append(to)
}
continue
}

let from = path[i]
let to = path[i+1]

// Skip duplicate points
if from.latitude == to.latitude && from.longitude == to.longitude {
continue
}

// Calculate the miter corner for the offset point
let segmentAngle = -atan2(to.latitude - from.latitude, to.longitude - from.longitude)
let sinA = sin(segmentAngle)
let cosA = cos(segmentAngle)
let rotate =
Matrix([[cosA, -sinA, 0.0],
[sinA, cosA, 0.0],
[0.0, 0.0, 1.0]])
let translate =
Matrix([[1.0, 0.0, 0.0 ],
[0.0, 1.0, rightLeft == .left ? offset : -offset ],
[0.0, 0.0, 1.0]])
let mat = inv(rotate) * translate * rotate

let fromOff = mat * Matrix([[from.x], [from.y], [1.0]])
let toOff = mat * Matrix([[to.x], [to.y], [1.0]])

let offsetSegment = Segment(
from: CLLocationCoordinate2D(latitude: fromOff[1,0], longitude: fromOff[0,0]),
to: CLLocationCoordinate2D(latitude: toOff[1,0], longitude: toOff[0,0]))

if prevSegment == nil {
prevSegment = offsetSegment
offsetPoints.append(offsetSegment.from)
continue
}

// Calculate line intersection
guard let intersection = getLineIntersection(line0: prevSegment, line1: offsetSegment, segment: false) else {
prevSegment = offsetSegment
continue
}

prevSegment = offsetSegment
offsetPoints.append(intersection)
}

return offsetPoints
}

// Returns the intersection point if the line segments intersect, otherwise nil
func getLineIntersection(line0: Segment, line1: Segment, segment: Bool) -> CLLocationCoordinate2D? {
return getLineIntersection(p0: line0.from, p1: line0.to, p2: line1.from, p3: line1.to, segment: segment)
}

// https://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
// Returns the intersection point if the line segments intersect, otherwise nil
func getLineIntersection(p0: CLLocationCoordinate2D, p1: CLLocationCoordinate2D, p2: CLLocationCoordinate2D, p3: CLLocationCoordinate2D, segment: Bool) -> CLLocationCoordinate2D? {
let s1x = p1.longitude - p0.longitude
let s1y = p1.latitude - p0.latitude
let s2x = p3.longitude - p2.longitude
let s2y = p3.latitude - p2.latitude

let numerator = (s2x * (p0.latitude - p2.latitude) - s2y * (p0.longitude - p2.longitude))
let denominator = (s1x * s2y - s2x * s1y)
if denominator == 0.0 {
return nil
}
let t = numerator / denominator

if segment {
let s = (s1y * (p0.longitude - p2.longitude) + s1x * (p0.latitude - p2.latitude)) / (s1x * s2y - s2x * s1y)
guard (s >= 0 && s <= 1 && t >= 0 && t <= 1) else {
return nil
}
}

return CLLocationCoordinate2D(latitude: p0.latitude + (t * s1y), longitude: p0.longitude + (t * s1x))
}


// The path from NextBus
let path: CLLocationCoordinate2D = pathFromNextBus()

// The desired width of the polyline
let strokeWidth: Double = desiredPolylineWidth()

let polygon: GMSPolygon
do {
let polygonPath = GMSMutablePath()
let w = strokeWidth / 2.0
for point in offsetPath(rightLeft: .left, path: route.offsetPath, offset: w) {
polygonPath.add(CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude))
}
for point in offsetPath(rightLeft: .right, path: route.offsetPath, offset: w).reversed() {
polygonPath.add(CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude))
}
polygon = GMSPolygon(path: polygonPath)
polygon.strokeWidth = 0.0
}

关于swift - 如何在不使 CPU 使用率最大化的情况下显示大量 GMSPolylines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55554856/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com