From cf0b63e2a7623a51c9e41abec429690553e53703 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Mon, 15 Jun 2020 16:33:55 -0700 Subject: [PATCH 01/25] Remove addCongestion --- MapboxNavigation/NavigationMapView.swift | 107 +++++++++++++---------- 1 file changed, 60 insertions(+), 47 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 4c4055f5525..a957352608a 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -448,7 +448,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { guard let style = style else { return } guard let mainRoute = routes.first else { return } self.routes = routes - + + let polylines = navigationMapViewDelegate?.navigationMapView(self, shapeFor: routes) ?? shape(for: routes, legIndex: legIndex) let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) @@ -768,7 +769,11 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { func shape(for routes: [Route], legIndex: Int?) -> MGLShape? { guard let firstRoute = routes.first else { return nil } - guard let congestedRoute = addCongestion(to: firstRoute, legIndex: legIndex) else { return nil } + + let mainRoute = MGLPolylineFeature(firstRoute.shape!) + mainRoute.attributes["isAlternateRoute"] = false + + //guard let congestedRoute = addCongestion(to: firstRoute, legIndex: legIndex) else { return nil } var altRoutes: [MGLPolylineFeature] = [] @@ -778,52 +783,54 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { altRoutes.append(polyline) } - return MGLShapeCollectionFeature(shapes: altRoutes + congestedRoute) +// return MGLShapeCollectionFeature(shapes: altRoutes + congestedRoute) + return MGLShapeCollectionFeature(shapes: altRoutes + [mainRoute]) } - func addCongestion(to route: Route, legIndex: Int?) -> [MGLPolylineFeature]? { - guard let coordinates = route.shape?.coordinates else { return nil } - - var linesPerLeg: [MGLPolylineFeature] = [] - - for (index, leg) in route.legs.enumerated() { - let lines: [MGLPolylineFeature] - // If there is no congestion, don't try and add it - if let legCongestion = leg.segmentCongestionLevels, legCongestion.count < coordinates.count { - // The last coord of the preceding step, is shared with the first coord of the next step, we don't need both. - let legCoordinates: [CLLocationCoordinate2D] = leg.steps.enumerated().reduce([]) { allCoordinates, current in - let index = current.offset - let step = current.element - let stepCoordinates = step.shape!.coordinates - - return index == 0 ? stepCoordinates : allCoordinates + stepCoordinates.suffix(from: 1) - } - - let mergedCongestionSegments = combine(legCoordinates, with: legCongestion) - - lines = mergedCongestionSegments.map { (congestionSegment: CongestionSegment) -> MGLPolylineFeature in - let polyline = MGLPolylineFeature(coordinates: congestionSegment.0, count: UInt(congestionSegment.0.count)) - polyline.attributes[MBCongestionAttribute] = String(describing: congestionSegment.1) - return polyline - } - } else { - lines = [MGLPolylineFeature(route.shape!)] - } - - for line in lines { - line.attributes["isAlternateRoute"] = false - if let legIndex = legIndex { - line.attributes[MBCurrentLegAttribute] = index == legIndex - } else { - line.attributes[MBCurrentLegAttribute] = index == 0 - } - } - - linesPerLeg.append(contentsOf: lines) - } - - return linesPerLeg - } +// func addCongestion(to route: Route, legIndex: Int?) -> [MGLPolylineFeature]? { +// guard let coordinates = route.shape?.coordinates else { return nil } +// +// var linesPerLeg: [MGLPolylineFeature] = [] +// +// for (index, leg) in route.legs.enumerated() { +// let lines: [MGLPolylineFeature] +// if let legCongestion = leg.segmentCongestionLevels, legCongestion.count < coordinates.count { +// // The last coord of the preceding step, is shared with the first coord of the next step, we don't need both. +// let legCoordinates: [CLLocationCoordinate2D] = leg.steps.enumerated().reduce([]) { allCoordinates, current in +// let index = current.offset +// let step = current.element +// let stepCoordinates = step.shape!.coordinates +// +// return index == 0 ? stepCoordinates : allCoordinates + stepCoordinates.suffix(from: 1) +// } +// +// let mergedCongestionSegments = combine(legCoordinates, with: legCongestion) +// +// lines = mergedCongestionSegments.map { (congestionSegment: CongestionSegment) -> MGLPolylineFeature in +// let polyline = MGLPolylineFeature(coordinates: congestionSegment.0, count: UInt(congestionSegment.0.count)) +// polyline.attributes[MBCongestionAttribute] = String(describing: congestionSegment.1) +// print(polyline.attributes) +// return polyline +// } +// } else { +// // If there is no congestion, don't try and add it +// lines = [MGLPolylineFeature(route.shape!)] +// } +// +// for line in lines { +// line.attributes["isAlternateRoute"] = false +// if let legIndex = legIndex { +// line.attributes[MBCurrentLegAttribute] = index == legIndex +// } else { +// line.attributes[MBCurrentLegAttribute] = index == 0 +// } +// } +// +// linesPerLeg.append(contentsOf: lines) +// } +// +// return linesPerLeg +// } func combine(_ coordinates: [CLLocationCoordinate2D], with congestions: [CongestionLevel]) -> [CongestionSegment] { var segments: [CongestionSegment] = [] @@ -841,7 +848,13 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } return segments } - + + /** + Creates a single route line for each route leg. + + A route with multiple legs (caused by adding more than one waypoint), + will cause linesPerLeg.count > 1. + */ func shape(forCasingOf route: Route, legIndex: Int?) -> MGLShape? { var linesPerLeg: [MGLPolylineFeature] = [] From 25fcd745327066369246c22693909e205e607403 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Mon, 15 Jun 2020 17:35:17 -0700 Subject: [PATCH 02/25] More testing --- MapboxNavigation/NavigationMapView.swift | 234 ++++++++++++++++++----- 1 file changed, 188 insertions(+), 46 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index a957352608a..3954c2c8645 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -452,19 +452,43 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let polylines = navigationMapViewDelegate?.navigationMapView(self, shapeFor: routes) ?? shape(for: routes, legIndex: legIndex) let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) - + + let shapeCollectionFeature = polylines as! MGLShapeCollectionFeature +// for shape in shapeCollectionFeature.shapes { +// print(shape.attributes) +// } + +// let mainRouteFeature = shapeCollectionFeature.shapes.first(where: { +// let isAlternateRoute = $0.attributes["isAlternateRoute"] as! Bool +// return isAlternateRoute == false +// }) + + + /** + If there is already an existing source for the congestion segments and + the simplified route line, then just update their shapes. + */ if let source = style.source(withIdentifier: SourceIdentifier.route) as? MGLShapeSource, let sourceSimplified = style.source(withIdentifier: SourceIdentifier.routeCasing) as? MGLShapeSource { source.shape = polylines sourceSimplified.shape = mainPolylineSimplified } else { + /** + Otherwise, create style layers for the sources. + */ let lineSource = MGLShapeSource(identifier: SourceIdentifier.route, shape: polylines, options: [.lineDistanceMetrics: true]) let lineCasingSource = MGLShapeSource(identifier: SourceIdentifier.routeCasing, shape: mainPolylineSimplified, options: [.lineDistanceMetrics: true]) style.addSource(lineSource) style.addSource(lineCasingSource) let line = navigationMapViewDelegate?.navigationMapView(self, routeStyleLayerWithIdentifier: StyleLayerIdentifier.route, source: lineSource) ?? routeStyleLayer(identifier: StyleLayerIdentifier.route, source: lineSource) - let lineCasing = navigationMapViewDelegate?.navigationMapView(self, routeCasingStyleLayerWithIdentifier: StyleLayerIdentifier.routeCasing, source: lineCasingSource) ?? routeCasingStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: lineSource) + + +// let lineCasing = navigationMapViewDelegate?.navigationMapView(self, routeCasingStyleLayerWithIdentifier: StyleLayerIdentifier.routeCasing, source: lineCasingSource) ?? routeCasingStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: lineSource) + + let lineCasing = navigationMapViewDelegate?.navigationMapView(self, routeCasingStyleLayerWithIdentifier: StyleLayerIdentifier.routeCasing, source: lineCasingSource) ?? TEST_routeStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: lineSource, route: mainRoute) + + for layer in style.layers.reversed() { if !(layer is MGLSymbolStyleLayer) && @@ -787,50 +811,50 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return MGLShapeCollectionFeature(shapes: altRoutes + [mainRoute]) } -// func addCongestion(to route: Route, legIndex: Int?) -> [MGLPolylineFeature]? { -// guard let coordinates = route.shape?.coordinates else { return nil } -// -// var linesPerLeg: [MGLPolylineFeature] = [] -// -// for (index, leg) in route.legs.enumerated() { -// let lines: [MGLPolylineFeature] -// if let legCongestion = leg.segmentCongestionLevels, legCongestion.count < coordinates.count { -// // The last coord of the preceding step, is shared with the first coord of the next step, we don't need both. -// let legCoordinates: [CLLocationCoordinate2D] = leg.steps.enumerated().reduce([]) { allCoordinates, current in -// let index = current.offset -// let step = current.element -// let stepCoordinates = step.shape!.coordinates -// -// return index == 0 ? stepCoordinates : allCoordinates + stepCoordinates.suffix(from: 1) -// } -// -// let mergedCongestionSegments = combine(legCoordinates, with: legCongestion) -// -// lines = mergedCongestionSegments.map { (congestionSegment: CongestionSegment) -> MGLPolylineFeature in -// let polyline = MGLPolylineFeature(coordinates: congestionSegment.0, count: UInt(congestionSegment.0.count)) -// polyline.attributes[MBCongestionAttribute] = String(describing: congestionSegment.1) -// print(polyline.attributes) -// return polyline -// } -// } else { -// // If there is no congestion, don't try and add it -// lines = [MGLPolylineFeature(route.shape!)] -// } -// -// for line in lines { -// line.attributes["isAlternateRoute"] = false -// if let legIndex = legIndex { -// line.attributes[MBCurrentLegAttribute] = index == legIndex -// } else { -// line.attributes[MBCurrentLegAttribute] = index == 0 -// } -// } -// -// linesPerLeg.append(contentsOf: lines) -// } -// -// return linesPerLeg -// } + func addCongestion(to route: Route, legIndex: Int?) -> [MGLPolylineFeature]? { + guard let coordinates = route.shape?.coordinates else { return nil } + + var linesPerLeg: [MGLPolylineFeature] = [] + + for (index, leg) in route.legs.enumerated() { + let lines: [MGLPolylineFeature] + if let legCongestion = leg.segmentCongestionLevels, legCongestion.count < coordinates.count { + // The last coord of the preceding step, is shared with the first coord of the next step, we don't need both. + let legCoordinates: [CLLocationCoordinate2D] = leg.steps.enumerated().reduce([]) { allCoordinates, current in + let index = current.offset + let step = current.element + let stepCoordinates = step.shape!.coordinates + + return index == 0 ? stepCoordinates : allCoordinates + stepCoordinates.suffix(from: 1) + } + + let mergedCongestionSegments = combine(legCoordinates, with: legCongestion) + + lines = mergedCongestionSegments.map { (congestionSegment: CongestionSegment) -> MGLPolylineFeature in + let polyline = MGLPolylineFeature(coordinates: congestionSegment.0, count: UInt(congestionSegment.0.count)) + polyline.attributes[MBCongestionAttribute] = String(describing: congestionSegment.1) + print(polyline.attributes) + return polyline + } + } else { + // If there is no congestion, don't try and add it + lines = [MGLPolylineFeature(route.shape!)] + } + + for line in lines { + line.attributes["isAlternateRoute"] = false + if let legIndex = legIndex { + line.attributes[MBCurrentLegAttribute] = index == legIndex + } else { + line.attributes[MBCurrentLegAttribute] = index == 0 + } + } + + linesPerLeg.append(contentsOf: lines) + } + + return linesPerLeg + } func combine(_ coordinates: [CLLocationCoordinate2D], with congestions: [CongestionLevel]) -> [CongestionSegment] { var segments: [CongestionSegment] = [] @@ -947,6 +971,124 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return lineCasing } + + func TEST_routeStyleLayer(identifier: String, source: MGLSource, route: Route) -> MGLStyleLayer { + let lineCasing = MGLLineStyleLayer(identifier: identifier, source: source) + + // Take the default line width and make it wider for the casing + lineCasing.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) + + lineCasing.lineColor = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), + trueExpression: NSExpression(forConstantValue: routeAlternateCasingColor), + falseExpression: NSExpression(forConstantValue: routeCasingColor)) + + lineCasing.lineCap = NSExpression(forConstantValue: "round") + lineCasing.lineJoin = NSExpression(forConstantValue: "round") + + lineCasing.lineOpacity = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), + trueExpression: NSExpression(forConstantValue: 1), + falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), trueExpression: NSExpression(forConstantValue: 1), falseExpression: NSExpression(forConstantValue: 0.85))) + + /** If traffic is enabled, set the gradient */ + // TODO: Only apply traffic gradient to main route + if let stops = generateTrafficGradientStops(for: route) { + lineCasing.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", stops) + } + + + return lineCasing + } + + func generateTrafficGradientStops(for route: Route) -> [CGFloat:UIColor]? { + typealias GradientStop = (percent: CGFloat, color: UIColor) + var stops = [GradientStop]() + var gradientDictionary = [CGFloat: UIColor]() + + let routeLength = route.distance + var distanceTraveled: CLLocationDistance = 0.0 + + // Individual polylines associated with a congestion level + guard let congestionSegments = addCongestion(to: route, legIndex: 0) else { return nil } + + /** + To create the stops dictionary that represents the route line expressed + as gradients, for every congestion segment we need one pair of dictionary + entries to represent the color to be displayed between that range. Depending + on the index of the congestion segment, the pair's first or second key + will have a buffer value added or subtracted to make room for a gradient + transition between congestion segments. + + green gradient red + transition + |-----------|~~~~~~~~~~~~|----------| + 0 0.499 0.501 1.0 + */ + + for (index, line) in congestionSegments.enumerated() { + line.getCoordinates(line.coordinates, range: NSMakeRange(0, Int(line.pointCount))) + let buffPtr = UnsafeMutableBufferPointer(start: line.coordinates, count: Int(line.pointCount)) + let lineCoordinates = Array(buffPtr) + + // Get congestion color + let congestionLevel = line.attributes["congestion"] as! String + let congestionColor = getCongestionColor(for: congestionLevel) + + // Measure the line length + let lineString = LineString(lineCoordinates) + let distance = lineString.distance() + + if index == congestionSegments.startIndex { + let segmentStartPercentTraveled = CGFloat.zero + stops.append(GradientStop(percent: segmentStartPercentTraveled, color: congestionColor)) + + distanceTraveled = distanceTraveled + distance + + let segmentEndPercentTraveled = CGFloat((distanceTraveled / routeLength)) + stops.append(GradientStop(percent: segmentEndPercentTraveled.nextDown, color: congestionColor)) + continue + } + + if index == congestionSegments.endIndex - 1 { + let segmentStartPercentTraveled = CGFloat((distanceTraveled / routeLength)) + stops.append(GradientStop(percent: segmentStartPercentTraveled.nextUp, color: congestionColor)) + + let segmentEndPercentTraveled = CGFloat(1.0) + stops.append(GradientStop(percent: segmentEndPercentTraveled, color: congestionColor)) + continue + } + + let segmentStartPercentTraveled = CGFloat((distanceTraveled / routeLength)) + stops.append(GradientStop(percent: segmentStartPercentTraveled.nextUp, color: congestionColor)) + + distanceTraveled = distanceTraveled + distance + + let segmentEndPercentTraveled = CGFloat((distanceTraveled / routeLength)) + stops.append(GradientStop(percent: segmentEndPercentTraveled.nextDown, color: congestionColor)) + } + + for stop in stops { + gradientDictionary[stop.percent] = stop.color + } + + return gradientDictionary + } + + // TODO: Return real traffic colors + func getCongestionColor(for congestionLevel: String) -> UIColor { + switch congestionLevel { + case "low": + return UIColor.green + case "moderate": + return UIColor.yellow + case "heavy": + return UIColor.red + case "severe": + return UIColor.black + default: + // Unknown + return UIColor.blue + } + } /** Attempts to localize road labels into the local language and other labels From 1d5bb1cefc34943e7f032e90820f88a1509a6a2b Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 17 Jun 2020 15:22:28 -0700 Subject: [PATCH 03/25] Vanish route line --- MapboxNavigation/NavigationMapView.swift | 82 ++++++++++++------- MapboxNavigation/RouteMapViewController.swift | 4 +- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 3954c2c8645..f14caad35b3 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -201,6 +201,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } private lazy var mapTapGesture = UITapGestureRecognizer(target: self, action: #selector(didRecieveTap(sender:))) + + private lazy var routeGradient = [CGFloat: UIColor]() //MARK: - Initalizers @@ -442,64 +444,86 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } /** - Adds or updates both the route line and the route line casing + Adds or updates both the route line and the route line casing. + + This method will be called multiple times: + • When the route preview map is shown, rendering alternative routes if necessary. + • When the navigation session starts, rendering only the single route line. */ public func show(_ routes: [Route], legIndex: Int = 0) { guard let style = style else { return } guard let mainRoute = routes.first else { return } self.routes = routes - let polylines = navigationMapViewDelegate?.navigationMapView(self, shapeFor: routes) ?? shape(for: routes, legIndex: legIndex) let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) - let shapeCollectionFeature = polylines as! MGLShapeCollectionFeature -// for shape in shapeCollectionFeature.shapes { -// print(shape.attributes) -// } - -// let mainRouteFeature = shapeCollectionFeature.shapes.first(where: { -// let isAlternateRoute = $0.attributes["isAlternateRoute"] as! Bool -// return isAlternateRoute == false -// }) - - /** - If there is already an existing source for the congestion segments and - the simplified route line, then just update their shapes. + If there is already an existing source that represents the routes, + just update their shapes. */ if let source = style.source(withIdentifier: SourceIdentifier.route) as? MGLShapeSource, let sourceSimplified = style.source(withIdentifier: SourceIdentifier.routeCasing) as? MGLShapeSource { source.shape = polylines sourceSimplified.shape = mainPolylineSimplified } else { - /** - Otherwise, create style layers for the sources. - */ - let lineSource = MGLShapeSource(identifier: SourceIdentifier.route, shape: polylines, options: [.lineDistanceMetrics: true]) - let lineCasingSource = MGLShapeSource(identifier: SourceIdentifier.routeCasing, shape: mainPolylineSimplified, options: [.lineDistanceMetrics: true]) - style.addSource(lineSource) - style.addSource(lineCasingSource) - - let line = navigationMapViewDelegate?.navigationMapView(self, routeStyleLayerWithIdentifier: StyleLayerIdentifier.route, source: lineSource) ?? routeStyleLayer(identifier: StyleLayerIdentifier.route, source: lineSource) + // Otherwise, create add them to the map for the first time. + // Source layer for main route + alternative routes + let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.route, shape: polylines, options: [.lineDistanceMetrics: true]) + style.addSource(allRoutesSource) -// let lineCasing = navigationMapViewDelegate?.navigationMapView(self, routeCasingStyleLayerWithIdentifier: StyleLayerIdentifier.routeCasing, source: lineCasingSource) ?? routeCasingStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: lineSource) + let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.route, source: allRoutesSource) + alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") + alternateRoutesLayer.lineColor = NSExpression(forConstantValue: UIColor.gray) + alternateRoutesLayer.lineWidth = NSExpression(forConstantValue: 8.0) - let lineCasing = navigationMapViewDelegate?.navigationMapView(self, routeCasingStyleLayerWithIdentifier: StyleLayerIdentifier.routeCasing, source: lineCasingSource) ?? TEST_routeStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: lineSource, route: mainRoute) + let mainRouteLayer = MGLLineStyleLayer(identifier: "main-route", source: allRoutesSource) + mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) + mainRouteLayer.lineWidth = NSExpression(forConstantValue: 8.0) + if let stops = generateTrafficGradientStops(for: mainRoute) { + routeGradient = stops + mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradient) + } - + // Add all the layers for layer in style.layers.reversed() { if !(layer is MGLSymbolStyleLayer) && layer.identifier != StyleLayerIdentifier.arrow && layer.identifier != StyleLayerIdentifier.arrowSymbol && layer.identifier != StyleLayerIdentifier.arrowCasingSymbol && layer.identifier != StyleLayerIdentifier.arrowStroke && layer.identifier != StyleLayerIdentifier.waypointCircle { - style.insertLayer(line, below: layer) - style.insertLayer(lineCasing, below: line) + style.insertLayer(mainRouteLayer, below: layer) + style.insertLayer(alternateRoutesLayer, below: mainRouteLayer) break } } } } + + func fadeRoute(_ fractionTraveled: Double) { + guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer else { return } + + let percentTraveled = CGFloat(fractionTraveled) + + // Filter out only the stops that are greater than or equal to + // the percent of the route traveled. + var filtered = routeGradient.filter { key, value in + return key >= percentTraveled + } + + // Then, get the lowest value from the above + // and fade the range from zero that lowest value, + // which represents the % of the route traveled. + if let minStop = filtered.min(by: { $0.0 < $1.0 }) { + filtered[0.0] = UIColor.white + filtered[percentTraveled.nextDown] = UIColor.white + filtered[percentTraveled] = minStop.value + } + + routeGradient = filtered + + mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradient) + } /** Removes route line and route line casing from map diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index eb935286e85..d896c0f87cc 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -452,7 +452,9 @@ extension RouteMapViewController: NavigationComponent { let route = progress.route let legIndex = progress.legIndex let stepIndex = progress.currentLegProgress.stepIndex - + + mapView.fadeRoute(progress.fractionTraveled) + mapView.updatePreferredFrameRate(for: progress) if currentLegIndexMapped != legIndex { mapView.showWaypoints(on: route, legIndex: legIndex) From ad51caea8d84521ff2a5b9dc993c34cf8b0b9746 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 17 Jun 2020 15:47:09 -0700 Subject: [PATCH 04/25] First refactor --- MapboxNavigation/NavigationMapView.swift | 113 +++++------------------ 1 file changed, 25 insertions(+), 88 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index f14caad35b3..710150ee571 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -106,12 +106,15 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { @objc dynamic public var routeAlternateCasingColor: UIColor = .defaultAlternateLineCasing @objc dynamic public var maneuverArrowColor: UIColor = .defaultManeuverArrow @objc dynamic public var maneuverArrowStrokeColor: UIColor = .defaultManeuverArrowStroke + + typealias RouteGradientStops = (line: [CGFloat: UIColor], casing: [CGFloat: UIColor]) var userLocationForCourseTracking: CLLocation? var animatesUserLocation: Bool = false var altitude: CLLocationDistance var routes: [Route]? var isAnimatingToOverheadMode = false + var routeGradientStops = RouteGradientStops(line: [:], casing: [:]) // TODO: Account for cases where traffic isn't enabled. var shouldPositionCourseViewFrameByFrame = false { didSet { @@ -467,7 +470,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { source.shape = polylines sourceSimplified.shape = mainPolylineSimplified } else { - // Otherwise, create add them to the map for the first time. + // Otherwise, create them for the first time. // Source layer for main route + alternative routes let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.route, shape: polylines, options: [.lineDistanceMetrics: true]) @@ -483,10 +486,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) mainRouteLayer.lineWidth = NSExpression(forConstantValue: 8.0) - if let stops = generateTrafficGradientStops(for: mainRoute) { - routeGradient = stops - mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradient) - } + generateTrafficGradientStops(for: mainRoute) + mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) // Add all the layers for layer in style.layers.reversed() { @@ -507,7 +508,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { // Filter out only the stops that are greater than or equal to // the percent of the route traveled. - var filtered = routeGradient.filter { key, value in + var filtered = routeGradientStops.line.filter { key, value in return key >= percentTraveled } @@ -520,9 +521,9 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { filtered[percentTraveled] = minStop.value } - routeGradient = filtered + routeGradientStops.line = filtered - mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradient) + mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) } /** @@ -820,8 +821,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let mainRoute = MGLPolylineFeature(firstRoute.shape!) mainRoute.attributes["isAlternateRoute"] = false - - //guard let congestedRoute = addCongestion(to: firstRoute, legIndex: legIndex) else { return nil } var altRoutes: [MGLPolylineFeature] = [] @@ -830,8 +829,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { polyline.attributes["isAlternateRoute"] = true altRoutes.append(polyline) } - -// return MGLShapeCollectionFeature(shapes: altRoutes + congestedRoute) + return MGLShapeCollectionFeature(shapes: altRoutes + [mainRoute]) } @@ -857,7 +855,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { lines = mergedCongestionSegments.map { (congestionSegment: CongestionSegment) -> MGLPolylineFeature in let polyline = MGLPolylineFeature(coordinates: congestionSegment.0, count: UInt(congestionSegment.0.count)) polyline.attributes[MBCongestionAttribute] = String(describing: congestionSegment.1) - print(polyline.attributes) return polyline } } else { @@ -960,79 +957,17 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return symbol } - - func routeStyleLayer(identifier: String, source: MGLSource) -> MGLStyleLayer { - let line = MGLLineStyleLayer(identifier: identifier, source: source) - line.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) - line.lineOpacity = NSExpression(forConditional: - NSPredicate(format: "isAlternateRoute == true"), - trueExpression: NSExpression(forConstantValue: 1), - falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), - trueExpression: NSExpression(forConstantValue: 1), - falseExpression: NSExpression(forConstantValue: 0))) - line.lineColor = NSExpression(format: "TERNARY(isAlternateRoute == true, %@, MGL_MATCH(congestion, 'low' , %@, 'moderate', %@, 'heavy', %@, 'severe', %@, %@))", routeAlternateColor, trafficLowColor, trafficModerateColor, trafficHeavyColor, trafficSevereColor, trafficUnknownColor) - line.lineJoin = NSExpression(forConstantValue: "round") - - return line - } - - func routeCasingStyleLayer(identifier: String, source: MGLSource) -> MGLStyleLayer { - let lineCasing = MGLLineStyleLayer(identifier: identifier, source: source) - - // Take the default line width and make it wider for the casing - lineCasing.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) - - lineCasing.lineColor = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), - trueExpression: NSExpression(forConstantValue: routeAlternateCasingColor), - falseExpression: NSExpression(forConstantValue: routeCasingColor)) - - lineCasing.lineCap = NSExpression(forConstantValue: "round") - lineCasing.lineJoin = NSExpression(forConstantValue: "round") - - lineCasing.lineOpacity = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), - trueExpression: NSExpression(forConstantValue: 1), - falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), trueExpression: NSExpression(forConstantValue: 1), falseExpression: NSExpression(forConstantValue: 0.85))) - - return lineCasing - } - - func TEST_routeStyleLayer(identifier: String, source: MGLSource, route: Route) -> MGLStyleLayer { - let lineCasing = MGLLineStyleLayer(identifier: identifier, source: source) - - // Take the default line width and make it wider for the casing - lineCasing.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) - - lineCasing.lineColor = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), - trueExpression: NSExpression(forConstantValue: routeAlternateCasingColor), - falseExpression: NSExpression(forConstantValue: routeCasingColor)) - lineCasing.lineCap = NSExpression(forConstantValue: "round") - lineCasing.lineJoin = NSExpression(forConstantValue: "round") - - lineCasing.lineOpacity = NSExpression(forConditional: NSPredicate(format: "isAlternateRoute == true"), - trueExpression: NSExpression(forConstantValue: 1), - falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), trueExpression: NSExpression(forConstantValue: 1), falseExpression: NSExpression(forConstantValue: 0.85))) - - /** If traffic is enabled, set the gradient */ - // TODO: Only apply traffic gradient to main route - if let stops = generateTrafficGradientStops(for: route) { - lineCasing.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", stops) - } - - - return lineCasing - } - - func generateTrafficGradientStops(for route: Route) -> [CGFloat:UIColor]? { + func generateTrafficGradientStops(for route: Route) { typealias GradientStop = (percent: CGFloat, color: UIColor) var stops = [GradientStop]() - var gradientDictionary = [CGFloat: UIColor]() +// var gradientDictionary = [CGFloat: UIColor]() let routeLength = route.distance var distanceTraveled: CLLocationDistance = 0.0 // Individual polylines associated with a congestion level - guard let congestionSegments = addCongestion(to: route, legIndex: 0) else { return nil } + guard let congestionSegments = addCongestion(to: route, legIndex: 0) else { return } /** To create the stops dictionary that represents the route line expressed @@ -1091,26 +1026,28 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } for stop in stops { - gradientDictionary[stop.percent] = stop.color + routeGradientStops.line[stop.percent] = stop.color + //gradientDictionary[stop.percent] = stop.color } - return gradientDictionary +// return gradientDictionary } - // TODO: Return real traffic colors - func getCongestionColor(for congestionLevel: String) -> UIColor { + /** + Given a congestion level, return its associated color. + */ + private func getCongestionColor(for congestionLevel: String) -> UIColor { switch congestionLevel { case "low": - return UIColor.green + return trafficLowColor case "moderate": - return UIColor.yellow + return trafficModerateColor case "heavy": - return UIColor.red + return trafficHeavyColor case "severe": - return UIColor.black + return trafficSevereColor default: - // Unknown - return UIColor.blue + return trafficUnknownColor } } From 48c28003f3eadcaee703858eae4098a4ac4e00af Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 17 Jun 2020 16:31:59 -0700 Subject: [PATCH 05/25] Add route casing back --- MapboxNavigation/NavigationMapView.swift | 31 ++++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 710150ee571..bf6de1572c5 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -478,23 +478,36 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.route, source: allRoutesSource) alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") - alternateRoutesLayer.lineColor = NSExpression(forConstantValue: UIColor.gray) + alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) alternateRoutesLayer.lineWidth = NSExpression(forConstantValue: 8.0) + let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: allRoutesSource) + alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") + alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) + alternateRoutesCasingLayer.lineWidth = NSExpression(forConstantValue: 12.0) + let mainRouteLayer = MGLLineStyleLayer(identifier: "main-route", source: allRoutesSource) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) mainRouteLayer.lineWidth = NSExpression(forConstantValue: 8.0) + let mainRouteCasingLayer = MGLLineStyleLayer(identifier: "main-route-casing", source: allRoutesSource) + mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) + mainRouteCasingLayer.lineWidth = NSExpression(forConstantValue: 16.0) + generateTrafficGradientStops(for: mainRoute) mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) + mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) // Add all the layers for layer in style.layers.reversed() { if !(layer is MGLSymbolStyleLayer) && layer.identifier != StyleLayerIdentifier.arrow && layer.identifier != StyleLayerIdentifier.arrowSymbol && layer.identifier != StyleLayerIdentifier.arrowCasingSymbol && layer.identifier != StyleLayerIdentifier.arrowStroke && layer.identifier != StyleLayerIdentifier.waypointCircle { style.insertLayer(mainRouteLayer, below: layer) + style.insertLayer(mainRouteCasingLayer, below: mainRouteLayer) style.insertLayer(alternateRoutesLayer, below: mainRouteLayer) + style.insertLayer(alternateRoutesCasingLayer, below: alternateRoutesLayer) break } } @@ -502,7 +515,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } func fadeRoute(_ fractionTraveled: Double) { - guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer else { return } + guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer, + let mainRouteCasingLayer = style?.layer(withIdentifier: "main-route-casing") as? MGLLineStyleLayer else { return } let percentTraveled = CGFloat(fractionTraveled) @@ -516,14 +530,18 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { // and fade the range from zero that lowest value, // which represents the % of the route traveled. if let minStop = filtered.min(by: { $0.0 < $1.0 }) { - filtered[0.0] = UIColor.white - filtered[percentTraveled.nextDown] = UIColor.white + filtered[0.0] = UIColor.clear // TODO: Pull color from user-defined preference + filtered[percentTraveled.nextDown] = UIColor.clear filtered[percentTraveled] = minStop.value } routeGradientStops.line = filtered + routeGradientStops.casing = filtered mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) + + // TODO: Figure out why fading isn't working for casing. + mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) } /** @@ -961,7 +979,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { func generateTrafficGradientStops(for route: Route) { typealias GradientStop = (percent: CGFloat, color: UIColor) var stops = [GradientStop]() -// var gradientDictionary = [CGFloat: UIColor]() let routeLength = route.distance var distanceTraveled: CLLocationDistance = 0.0 @@ -1027,10 +1044,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { for stop in stops { routeGradientStops.line[stop.percent] = stop.color - //gradientDictionary[stop.percent] = stop.color + routeGradientStops.casing[stop.percent] = UIColor.yellow // TODO: Replace with route casing color } - -// return gradientDictionary } /** From 055bd3e926d402385c634ca2142de3ec44929c76 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 17 Jun 2020 16:58:45 -0700 Subject: [PATCH 06/25] Fix vanishing route casing --- MapboxNavigation/NavigationMapView.swift | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index bf6de1572c5..6d8599cb03f 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -536,11 +536,20 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } routeGradientStops.line = filtered - routeGradientStops.casing = filtered - mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) - // TODO: Figure out why fading isn't working for casing. + // TODO: Refactor? We're doing the same work twice here... + var filteredCasing = routeGradientStops.casing.filter { key, value in + return key >= percentTraveled + } + + if let minStop = filteredCasing.min(by: { $0.0 < $1.0 }) { + filteredCasing[0.0] = UIColor.clear // TODO: Pull color from user-defined preference + filteredCasing[percentTraveled.nextDown] = UIColor.clear + filteredCasing[percentTraveled] = minStop.value + } + + routeGradientStops.casing = filteredCasing mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) } @@ -1044,7 +1053,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { for stop in stops { routeGradientStops.line[stop.percent] = stop.color - routeGradientStops.casing[stop.percent] = UIColor.yellow // TODO: Replace with route casing color + routeGradientStops.casing[stop.percent] = routeCasingColor // TODO: Replace with route casing color } } From 61c327841ab0377413b34700bcc86991cedd4d48 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 17 Jun 2020 17:31:19 -0700 Subject: [PATCH 07/25] Update NavigationMapView.swift --- MapboxNavigation/NavigationMapView.swift | 42 +++++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 6d8599cb03f..7461e4ca7e6 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -479,22 +479,51 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.route, source: allRoutesSource) alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) - alternateRoutesLayer.lineWidth = NSExpression(forConstantValue: 8.0) + alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) + alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") +// alternateRoutesLayer.lineOpacity = NSExpression(forConditional: +// NSPredicate(format: "isAlternateRoute == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConstantValue: 0))) let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: allRoutesSource) alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) - alternateRoutesCasingLayer.lineWidth = NSExpression(forConstantValue: 12.0) + alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) + alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") +// alternateRoutesCasingLayer.lineOpacity = NSExpression(forConditional: +// NSPredicate(format: "isAlternateRoute == true"), // TODO: If we know these layers are filtered already based on alternate route status, then I don't think we need to do this check here. +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConstantValue: 0))) let mainRouteLayer = MGLLineStyleLayer(identifier: "main-route", source: allRoutesSource) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) - mainRouteLayer.lineWidth = NSExpression(forConstantValue: 8.0) + mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) + mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") +// mainRouteLayer.lineOpacity = NSExpression(forConditional: +// NSPredicate(format: "isAlternateRoute == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConstantValue: 0))) let mainRouteCasingLayer = MGLLineStyleLayer(identifier: "main-route-casing", source: allRoutesSource) mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) - mainRouteCasingLayer.lineWidth = NSExpression(forConstantValue: 16.0) + mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) + mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") +// mainRouteCasingLayer.lineOpacity = NSExpression(forConditional: +// NSPredicate(format: "isAlternateRoute == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), +// trueExpression: NSExpression(forConstantValue: 1), +// falseExpression: NSExpression(forConstantValue: 0))) + generateTrafficGradientStops(for: mainRoute) mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) @@ -506,8 +535,11 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { layer.identifier != StyleLayerIdentifier.arrow && layer.identifier != StyleLayerIdentifier.arrowSymbol && layer.identifier != StyleLayerIdentifier.arrowCasingSymbol && layer.identifier != StyleLayerIdentifier.arrowStroke && layer.identifier != StyleLayerIdentifier.waypointCircle { style.insertLayer(mainRouteLayer, below: layer) style.insertLayer(mainRouteCasingLayer, below: mainRouteLayer) - style.insertLayer(alternateRoutesLayer, below: mainRouteLayer) + style.insertLayer(alternateRoutesLayer, below: mainRouteCasingLayer) style.insertLayer(alternateRoutesCasingLayer, below: alternateRoutesLayer) +// style.insertLayer(mainRouteCasingLayer, above: mainRouteLayer) +// style.insertLayer(alternateRoutesLayer, below: mainRouteCasingLayer) +// style.insertLayer(alternateRoutesCasingLayer, below: alternateRoutesLayer) break } } From b10879289bf7db21f36dbaa830bf67da7d03364a Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 14:16:28 -0700 Subject: [PATCH 08/25] Rename SourceIdentifier.route --- MapboxNavigation/NavigationMapView.swift | 44 ++++-------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 7461e4ca7e6..cb0d45b50fe 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -63,8 +63,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let sourceOptions: [MGLShapeSourceOption: Any] = [.maximumZoomLevel: 16] struct SourceIdentifier { - static let route = "\(identifierNamespace).route" - static let routeCasing = "\(identifierNamespace).routeCasing" + static let allRoutes = "\(identifierNamespace).allRoutes" static let waypoint = "\(identifierNamespace).waypoints" static let waypointCircle = "\(identifierNamespace).waypointsCircle" @@ -459,21 +458,19 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { self.routes = routes let polylines = navigationMapViewDelegate?.navigationMapView(self, shapeFor: routes) ?? shape(for: routes, legIndex: legIndex) - let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) + //let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) /** If there is already an existing source that represents the routes, just update their shapes. */ - if let source = style.source(withIdentifier: SourceIdentifier.route) as? MGLShapeSource, - let sourceSimplified = style.source(withIdentifier: SourceIdentifier.routeCasing) as? MGLShapeSource { + if let source = style.source(withIdentifier: SourceIdentifier.allRoutes) as? MGLShapeSource { source.shape = polylines - sourceSimplified.shape = mainPolylineSimplified } else { // Otherwise, create them for the first time. // Source layer for main route + alternative routes - let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.route, shape: polylines, options: [.lineDistanceMetrics: true]) + let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.allRoutes, shape: polylines, options: [.lineDistanceMetrics: true]) style.addSource(allRoutesSource) let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.route, source: allRoutesSource) @@ -481,49 +478,26 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") -// alternateRoutesLayer.lineOpacity = NSExpression(forConditional: -// NSPredicate(format: "isAlternateRoute == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConstantValue: 0))) + let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: allRoutesSource) alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") -// alternateRoutesCasingLayer.lineOpacity = NSExpression(forConditional: -// NSPredicate(format: "isAlternateRoute == true"), // TODO: If we know these layers are filtered already based on alternate route status, then I don't think we need to do this check here. -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConstantValue: 0))) + let mainRouteLayer = MGLLineStyleLayer(identifier: "main-route", source: allRoutesSource) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") -// mainRouteLayer.lineOpacity = NSExpression(forConditional: -// NSPredicate(format: "isAlternateRoute == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConstantValue: 0))) let mainRouteCasingLayer = MGLLineStyleLayer(identifier: "main-route-casing", source: allRoutesSource) mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") -// mainRouteCasingLayer.lineOpacity = NSExpression(forConditional: -// NSPredicate(format: "isAlternateRoute == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConditional: NSPredicate(format: "isCurrentLeg == true"), -// trueExpression: NSExpression(forConstantValue: 1), -// falseExpression: NSExpression(forConstantValue: 0))) - generateTrafficGradientStops(for: mainRoute) mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) @@ -537,9 +511,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { style.insertLayer(mainRouteCasingLayer, below: mainRouteLayer) style.insertLayer(alternateRoutesLayer, below: mainRouteCasingLayer) style.insertLayer(alternateRoutesCasingLayer, below: alternateRoutesLayer) -// style.insertLayer(mainRouteCasingLayer, above: mainRouteLayer) -// style.insertLayer(alternateRoutesLayer, below: mainRouteCasingLayer) -// style.insertLayer(alternateRoutesCasingLayer, below: alternateRoutesLayer) break } } @@ -598,8 +569,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { StyleLayerIdentifier.routeCasing, ].compactMap { style.layer(withIdentifier: $0) }) style.remove(Set([ - SourceIdentifier.route, - SourceIdentifier.routeCasing, + SourceIdentifier.allRoutes ].compactMap { style.source(withIdentifier: $0) })) } From 5cfe0b5ff125c541b8cb4f6775ce4e4a644a7c27 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 14:23:33 -0700 Subject: [PATCH 09/25] Rename StyleLayerIdentifier constants --- MapboxNavigation/NavigationMapView.swift | 26 +++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index cb0d45b50fe..9cc148b4cd4 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -78,7 +78,12 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { struct StyleLayerIdentifier { static let namespace = Bundle.mapboxNavigation.bundleIdentifier ?? "" - + + static let mainRoute = "\(identifierNamespace).mainRoute" + static let mainRouteCasing = "\(identifierNamespace).mainRouteCasing" + static let alternateRoutes = "\(identifierNamespace).alternateRoutes" + static let alternateRoutesCasing = "\(identifierNamespace).alternateRoutesCasing" + static let route = "\(identifierNamespace).route" static let routeCasing = "\(identifierNamespace).routeCasing" @@ -125,7 +130,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { var showsRoute: Bool { get { - return style?.layer(withIdentifier: StyleLayerIdentifier.route) != nil + return style?.layer(withIdentifier: StyleLayerIdentifier.mainRoute) != nil && + style?.layer(withIdentifier: StyleLayerIdentifier.mainRouteCasing) != nil } } @@ -473,27 +479,25 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.allRoutes, shape: polylines, options: [.lineDistanceMetrics: true]) style.addSource(allRoutesSource) - let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.route, source: allRoutesSource) + let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") - - let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.routeCasing, source: allRoutesSource) + let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") - - let mainRouteLayer = MGLLineStyleLayer(identifier: "main-route", source: allRoutesSource) + let mainRouteLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") - let mainRouteCasingLayer = MGLLineStyleLayer(identifier: "main-route-casing", source: allRoutesSource) + let mainRouteCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) @@ -565,8 +569,10 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } style.remove([ - StyleLayerIdentifier.route, - StyleLayerIdentifier.routeCasing, + StyleLayerIdentifier.mainRoute, + StyleLayerIdentifier.mainRouteCasing, + StyleLayerIdentifier.alternateRoutes, + StyleLayerIdentifier.alternateRoutesCasing ].compactMap { style.layer(withIdentifier: $0) }) style.remove(Set([ SourceIdentifier.allRoutes From 6d2d2343b43db5991f8aa81ca0d984875d25ae63 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 16:06:04 -0700 Subject: [PATCH 10/25] Implement mainRouteStyleLayerWithIdentifier delegate --- MapboxNavigation/NavigationMapView.swift | 24 +++++++++++++------ .../NavigationMapViewDelegate.swift | 13 ++++++++++ .../NavigationViewController.swift | 4 ++++ .../NavigationViewControllerDelegate.swift | 14 +++++++++++ MapboxNavigation/RouteMapViewController.swift | 4 ++++ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 9cc148b4cd4..5875cc45cca 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -491,11 +491,9 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") - let mainRouteLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) - mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") - mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) - mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) - mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") + generateTrafficGradientStops(for: mainRoute) + + let mainRouteLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteStyleLayerWithIdentifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) ?? mainRouteStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) let mainRouteCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") @@ -503,8 +501,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") - generateTrafficGradientStops(for: mainRoute) - mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) // Add all the layers @@ -521,6 +517,20 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } } + func mainRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + let mainRouteLayer = MGLLineStyleLayer(identifier: identifier, source: source) + mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) // TODO: What color do we fall back to if there is no traffic? + mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) + mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") + + if routeGradientStops.line.isEmpty == false { + mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) + } + + return mainRouteLayer + } + func fadeRoute(_ fractionTraveled: Double) { guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer, let mainRouteCasingLayer = style?.layer(withIdentifier: "main-route-casing") as? MGLLineStyleLayer else { return } diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index e638958eed8..748c55a7439 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -15,6 +15,11 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { - returns: An MGLStyleLayer that the map applies to all routes. */ func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + TODO: Docs + */ + func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Asks the receiver to return an MGLStyleLayer for waypoints, given an identifier and source. @@ -105,6 +110,14 @@ public extension NavigationMapViewDelegate { logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) return nil } + + /** + `UnimplementedLogging` prints a warning to standard output the first time this method is called. + */ + func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index 929a99b5b8a..a26798b612d 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -393,6 +393,10 @@ extension NavigationViewController: RouteMapViewControllerDelegate { public func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationViewController(self, routeStyleLayerWithIdentifier: identifier, source: source) } + + public func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationViewController(self, mainRouteStyleLayerWithIdentifier: identifier, source: source) + } public func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) { delegate?.navigationViewController(self, didSelect: route) diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index d6b9ac525f0..23dfa835bed 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -97,6 +97,12 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ If this method is unimplemented, the navigation view controller’s map view draws the route line using an `MGLLineStyleLayer`. */ func navigationViewController(_ navigationViewController: NavigationViewController, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + + /** + TODO: Docs + */ + func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Returns an `MGLStyleLayer` that determines the appearance of the route line’s casing. @@ -251,6 +257,14 @@ public extension NavigationViewControllerDelegate { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) return nil } + + /** + `UnimplementedLogging` prints a warning to standard output the first time this method is called. + */ + func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index d896c0f87cc..4ef0e5ebaf8 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -547,6 +547,10 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, routeStyleLayerWithIdentifier: identifier, source: source) } + func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationMapView(mapView, mainRouteStyleLayerWithIdentifier: identifier, source: source) + } + func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, routeCasingStyleLayerWithIdentifier: identifier, source: source) } From 5d3a00c8b6976d1d14f61822f55574de8ddd2505 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 16:30:38 -0700 Subject: [PATCH 11/25] Implement mainRouteCasingStyleLayerWithIdentifier delegate --- MapboxNavigation/NavigationMapView.swift | 23 ++++++++++++------- .../NavigationMapViewDelegate.swift | 9 ++++++++ .../NavigationViewController.swift | 4 ++++ .../NavigationViewControllerDelegate.swift | 6 +++++ MapboxNavigation/RouteMapViewController.swift | 4 ++++ 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 5875cc45cca..655f1849183 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -494,14 +494,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { generateTrafficGradientStops(for: mainRoute) let mainRouteLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteStyleLayerWithIdentifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) ?? mainRouteStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) - - let mainRouteCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) - mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") - mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) - mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) - mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") - - mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) + let mainRouteCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) ?? mainRouteCasingStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) // Add all the layers for layer in style.layers.reversed() { @@ -531,6 +524,20 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return mainRouteLayer } + func mainRouteCasingStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + let mainRouteCasingLayer = MGLLineStyleLayer(identifier: identifier, source: source) + mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) + mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) + mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") + + if routeGradientStops.casing.isEmpty { + mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) + } + + return mainRouteCasingLayer + } + func fadeRoute(_ fractionTraveled: Double) { guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer, let mainRouteCasingLayer = style?.layer(withIdentifier: "main-route-casing") as? MGLLineStyleLayer else { return } diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index 748c55a7439..0da43474cfe 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -20,6 +20,7 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { TODO: Docs */ func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Asks the receiver to return an MGLStyleLayer for waypoints, given an identifier and source. @@ -118,6 +119,14 @@ public extension NavigationMapViewDelegate { logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) return nil } + + /** + `UnimplementedLogging` prints a warning to standard output the first time this method is called. + */ + func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index a26798b612d..50425bbca2c 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -397,6 +397,10 @@ extension NavigationViewController: RouteMapViewControllerDelegate { public func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationViewController(self, mainRouteStyleLayerWithIdentifier: identifier, source: source) } + + public func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationViewController(self, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) + } public func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) { delegate?.navigationViewController(self, didSelect: route) diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index 23dfa835bed..f3b4197ca39 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -103,6 +103,7 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ TODO: Docs */ func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Returns an `MGLStyleLayer` that determines the appearance of the route line’s casing. @@ -265,6 +266,11 @@ public extension NavigationViewControllerDelegate { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) return nil } + + func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 4ef0e5ebaf8..7689a53ff91 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -551,6 +551,10 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, mainRouteStyleLayerWithIdentifier: identifier, source: source) } + func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationMapView(mapView, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) + } + func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, routeCasingStyleLayerWithIdentifier: identifier, source: source) } From e12a3e51fc23e0f998eb6d38e74ec29eec4dc344 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 17:47:16 -0700 Subject: [PATCH 12/25] Implement alternateRouteStyleLayerWithIdentifier delegate --- MapboxNavigation/NavigationMapView.swift | 15 ++++++++++----- MapboxNavigation/NavigationMapViewDelegate.swift | 9 +++++++++ MapboxNavigation/NavigationViewController.swift | 4 ++++ .../NavigationViewControllerDelegate.swift | 6 ++++++ MapboxNavigation/RouteMapViewController.swift | 4 ++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 655f1849183..bfdd3a91b13 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -479,11 +479,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.allRoutes, shape: polylines, options: [.lineDistanceMetrics: true]) style.addSource(allRoutesSource) - let alternateRoutesLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) - alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") - alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) - alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) - alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") + let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternateRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternateRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") @@ -538,6 +534,15 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return mainRouteCasingLayer } + func alternateRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + let alternateRoutesLayer = MGLLineStyleLayer(identifier: identifier, source: source) + alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") + alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) + alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) + alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") + return alternateRoutesLayer + } + func fadeRoute(_ fractionTraveled: Double) { guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer, let mainRouteCasingLayer = style?.layer(withIdentifier: "main-route-casing") as? MGLLineStyleLayer else { return } diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index 0da43474cfe..9e2191f3496 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -21,6 +21,7 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { */ func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Asks the receiver to return an MGLStyleLayer for waypoints, given an identifier and source. @@ -127,6 +128,14 @@ public extension NavigationMapViewDelegate { logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) return nil } + + /** + `UnimplementedLogging` prints a warning to standard output the first time this method is called. + */ + func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index 50425bbca2c..b0303450f81 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -401,6 +401,10 @@ extension NavigationViewController: RouteMapViewControllerDelegate { public func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationViewController(self, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) } + + public func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationViewController(self, alternateRouteStyleLayerWithIdentifier: identifier, source: source) + } public func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) { delegate?.navigationViewController(self, didSelect: route) diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index f3b4197ca39..31bec95fcc5 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -104,6 +104,7 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ */ func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Returns an `MGLStyleLayer` that determines the appearance of the route line’s casing. @@ -271,6 +272,11 @@ public extension NavigationViewControllerDelegate { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) return nil } + + func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 7689a53ff91..e44fb0aee07 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -559,6 +559,10 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, routeCasingStyleLayerWithIdentifier: identifier, source: source) } + func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationMapView(mapView, alternateRouteStyleLayerWithIdentifier: identifier, source: source) + } + func navigationMapView(_ mapView: NavigationMapView, waypointStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, waypointStyleLayerWithIdentifier: identifier, source: source) } From c6477f73718eb7889fd0a2a30fcfd0765f76adca Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 18:00:45 -0700 Subject: [PATCH 13/25] Implement alternateRouteCasingStyleLayerWithIdentifier delegate --- MapboxNavigation/NavigationMapView.swift | 19 ++++++++++++------- .../NavigationMapViewDelegate.swift | 9 +++++++++ .../NavigationViewController.swift | 4 ++++ .../NavigationViewControllerDelegate.swift | 6 ++++++ MapboxNavigation/RouteMapViewController.swift | 4 ++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index bfdd3a91b13..12a9153b29d 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -481,11 +481,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternateRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternateRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) - let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) - alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") - alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) - alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) - alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") + let alternateRoutesCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) ?? alternateRouteCasingStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) generateTrafficGradientStops(for: mainRoute) @@ -543,9 +539,18 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return alternateRoutesLayer } + func alternateRouteCasingStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: identifier, source: source) + alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") + alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) + alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) + alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") + return alternateRoutesCasingLayer + } + func fadeRoute(_ fractionTraveled: Double) { - guard let mainRouteLayer = style?.layer(withIdentifier: "main-route") as? MGLLineStyleLayer, - let mainRouteCasingLayer = style?.layer(withIdentifier: "main-route-casing") as? MGLLineStyleLayer else { return } + guard let mainRouteLayer = style?.layer(withIdentifier: StyleLayerIdentifier.mainRoute) as? MGLLineStyleLayer, + let mainRouteCasingLayer = style?.layer(withIdentifier: StyleLayerIdentifier.mainRouteCasing) as? MGLLineStyleLayer else { return } let percentTraveled = CGFloat(fractionTraveled) diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index 9e2191f3496..ad4bfaf1f31 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -22,6 +22,7 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Asks the receiver to return an MGLStyleLayer for waypoints, given an identifier and source. @@ -136,6 +137,14 @@ public extension NavigationMapViewDelegate { logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) return nil } + + /** + `UnimplementedLogging` prints a warning to standard output the first time this method is called. + */ + func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index b0303450f81..c8396789f79 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -405,6 +405,10 @@ extension NavigationViewController: RouteMapViewControllerDelegate { public func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationViewController(self, alternateRouteStyleLayerWithIdentifier: identifier, source: source) } + + public func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationViewController(self, alternateRouteCasingStyleLayerWithIdentifier: identifier, source: source) + } public func navigationMapView(_ mapView: NavigationMapView, didSelect route: Route) { delegate?.navigationViewController(self, didSelect: route) diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index 31bec95fcc5..b14f8cc4489 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -105,6 +105,7 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Returns an `MGLStyleLayer` that determines the appearance of the route line’s casing. @@ -277,6 +278,11 @@ public extension NavigationViewControllerDelegate { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) return nil } + + func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) + return nil + } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index e44fb0aee07..ee723728498 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -563,6 +563,10 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, alternateRouteStyleLayerWithIdentifier: identifier, source: source) } + func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationMapView(mapView, alternateRouteCasingStyleLayerWithIdentifier: identifier, source: source) + } + func navigationMapView(_ mapView: NavigationMapView, waypointStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, waypointStyleLayerWithIdentifier: identifier, source: source) } From b0295a0b28d1063193d0577b65f870c6f2adb524 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 18:05:42 -0700 Subject: [PATCH 14/25] Remove routeStyleLayerWithIdentifier/routeCasingStyleLayerWithIdentifier delegate methods --- .../NavigationMapViewDelegate.swift | 35 ------------------- .../NavigationViewController.swift | 7 ---- .../NavigationViewControllerDelegate.swift | 30 ---------------- MapboxNavigation/RouteMapViewController.swift | 7 ---- 4 files changed, 79 deletions(-) diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index ad4bfaf1f31..cb0ec7d5d81 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -6,15 +6,6 @@ import MapboxCoreNavigation The `NavigationMapViewDelegate` provides methods for configuring the NavigationMapView, as well as responding to events triggered by the NavigationMapView. */ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { - /** - Asks the receiver to return an MGLStyleLayer for routes, given an identifier and source. - This method is invoked when the map view loads and any time routes are added. - - parameter mapView: The NavigationMapView. - - parameter identifier: The style identifier. - - parameter source: The Layer source containing the route data that this method would style. - - returns: An MGLStyleLayer that the map applies to all routes. - */ - func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** TODO: Docs @@ -44,17 +35,6 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { */ func navigationMapView(_ mapView: NavigationMapView, waypointSymbolStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? - /** - Asks the receiver to return an MGLStyleLayer for route casings, given an identifier and source. - This method is invoked when the map view loads and anytime routes are added. - - note: Specify a casing to ensure good contrast between the route line and the underlying map layers. - - parameter mapView: The NavigationMapView. - - parameter identifier: The style identifier. - - parameter source: The Layer source containing the route data that this method would style. - - returns: An MGLStyleLayer that the map applies to the route. - */ - func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? - /** Tells the receiver that the user has selected a route by interacting with the map view. - parameter mapView: The NavigationMapView. @@ -106,13 +86,6 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { } public extension NavigationMapViewDelegate { - /** - `UnimplementedLogging` prints a warning to standard output the first time this method is called. - */ - func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) - return nil - } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. @@ -162,14 +135,6 @@ public extension NavigationMapViewDelegate { return nil } - /** - `UnimplementedLogging` prints a warning to standard output the first time this method is called. - */ - func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) - return nil - } - /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. */ diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index c8396789f79..44f93107440 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -386,13 +386,6 @@ open class NavigationViewController: UIViewController, NavigationStatusPresenter //MARK: - RouteMapViewControllerDelegate extension NavigationViewController: RouteMapViewControllerDelegate { - public func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationViewController(self, routeCasingStyleLayerWithIdentifier: identifier, source: source) - } - - public func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationViewController(self, routeStyleLayerWithIdentifier: identifier, source: source) - } public func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationViewController(self, mainRouteStyleLayerWithIdentifier: identifier, source: source) diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index b14f8cc4489..55998a5e919 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -90,13 +90,6 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ - parameter error: An error raised during the process of obtaining a new route. */ func navigationViewController(_ navigationViewController: NavigationViewController, didFailToRerouteWith error: Error) - - /** - Returns an `MGLStyleLayer` that determines the appearance of the route line. - - If this method is unimplemented, the navigation view controller’s map view draws the route line using an `MGLLineStyleLayer`. - */ - func navigationViewController(_ navigationViewController: NavigationViewController, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** @@ -107,13 +100,6 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? - /** - Returns an `MGLStyleLayer` that determines the appearance of the route line’s casing. - - If this method is unimplemented, the navigation view controller’s map view draws the route line’s casing using an `MGLLineStyleLayer` whose width is greater than that of the style layer returned by `navigationViewController(_:routeStyleLayerWithIdentifier:source:)`. - */ - func navigationViewController(_ navigationViewController: NavigationViewController, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? - /** Returns an `MGLShape` that represents the path of the route line. @@ -252,14 +238,6 @@ public extension NavigationViewControllerDelegate { func navigationViewController(_ navigationViewController: NavigationViewController, didFailToRerouteWith error: Error) { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) } - - /** - `UnimplementedLogging` prints a warning to standard output the first time this method is called. - */ - func navigationViewController(_ navigationViewController: NavigationViewController, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) - return nil - } /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. @@ -284,14 +262,6 @@ public extension NavigationViewControllerDelegate { return nil } - /** - `UnimplementedLogging` prints a warning to standard output the first time this method is called. - */ - func navigationViewController(_ navigationViewController: NavigationViewController, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) - return nil - } - /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. */ diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index ee723728498..32d06adc072 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -543,9 +543,6 @@ extension RouteMapViewController: NavigationViewDelegate { } //MARK: NavigationMapViewDelegate - func navigationMapView(_ mapView: NavigationMapView, routeStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationMapView(mapView, routeStyleLayerWithIdentifier: identifier, source: source) - } func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, mainRouteStyleLayerWithIdentifier: identifier, source: source) @@ -555,10 +552,6 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) } - func navigationMapView(_ mapView: NavigationMapView, routeCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationMapView(mapView, routeCasingStyleLayerWithIdentifier: identifier, source: source) - } - func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { return delegate?.navigationMapView(mapView, alternateRouteStyleLayerWithIdentifier: identifier, source: source) } From d07ac38417f627661f5a80e4e9027cb255760733 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 18:31:42 -0700 Subject: [PATCH 15/25] Fill out docs --- MapboxNavigation/NavigationMapView.swift | 2 +- .../NavigationMapViewDelegate.swift | 36 +++++++++++++++++-- .../NavigationViewControllerDelegate.swift | 24 +++++++++++-- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 12a9153b29d..bd7ffdc139f 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -505,7 +505,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { func mainRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { let mainRouteLayer = MGLLineStyleLayer(identifier: identifier, source: source) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") - mainRouteLayer.lineColor = NSExpression(forConstantValue: UIColor.blue) // TODO: What color do we fall back to if there is no traffic? + mainRouteLayer.lineColor = NSExpression(forConstantValue: trafficUnknownColor) mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index cb0ec7d5d81..e7dcfcf56e4 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -8,11 +8,43 @@ import MapboxCoreNavigation public protocol NavigationMapViewDelegate: class, UnimplementedLogging { /** - TODO: Docs - */ + Asks the receiver to return an MGLStyleLayer for the main route line, given an identifier and source. + This method is invoked when the map view loads and any time routes are added. + - parameter mapView: The NavigationMapView. + - parameter identifier: The style identifier. + - parameter source: The source containing the route data that this method would style. + - returns: An MGLStyleLayer that is applied to the main route line. + */ func navigationMapView(_ mapView: NavigationMapView, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Asks the receiver to return an MGLStyleLayer for the casing layer that surrounds main route line, given an identifier and source. + This method is invoked when the map view loads and any time routes are added. + - parameter mapView: The NavigationMapView. + - parameter identifier: The style identifier. + - parameter source: The source containing the route data that this method would style. + - returns: An MGLStyleLayer that is applied as a casing around the main route line. + */ func navigationMapView(_ mapView: NavigationMapView, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Asks the receiver to return an MGLStyleLayer for the alternative route lines, given an identifier and source. + This method is invoked when the map view loads and any time routes are added. + - parameter mapView: The NavigationMapView. + - parameter identifier: The style identifier. + - parameter source: The source containing the route data that this method would style. + - returns: An MGLStyleLayer that is applied to alternative routes. + */ func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Asks the receiver to return an MGLStyleLayer for the casing layer that surrounds alternative route lines, given an identifier and source. + This method is invoked when the map view loads and any time routes are added. + - parameter mapView: The NavigationMapView. + - parameter identifier: The style identifier. + - parameter source: The source containing the route data that this method would style. + - returns: An MGLStyleLayer that is applied as a casing around alternative route lines. + */ func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index 55998a5e919..7c52f359462 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -93,11 +93,31 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ /** - TODO: Docs - */ + Returns an `MGLStyleLayer` that determines the appearance of the main route line. + + If this method is unimplemented, the navigation view controller’s map view draws the route line using an `MGLLineStyleLayer`. + */ func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Returns an `MGLStyleLayer` that determines the appearance of the casing around the main route line. + + If this method is unimplemented, the navigation view controller’s map view draws the casing for the main route line using an `MGLLineStyleLayer`. + */ func navigationViewController(_ navigationViewController: NavigationViewController, mainRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Returns an `MGLStyleLayer` that determines the appearance of alternative route lines. + + If this method is unimplemented, the navigation view controller’s map view draws the alternative route lines using an `MGLLineStyleLayer`. + */ func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + + /** + Returns an `MGLStyleLayer` that determines the appearance of the casing around the alternative route lines. + + If this method is unimplemented, the navigation view controller’s map view draws the casing for the alternative route lines using an `MGLLineStyleLayer`. + */ func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** From 99f2c4fa4dc68ad8b99e23fcff3438c1193402e4 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 18:44:19 -0700 Subject: [PATCH 16/25] Refactor, make vanishing color customizable --- MapboxNavigation/DayStyle.swift | 1 + MapboxNavigation/NavigationMapView.swift | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index 4601ff83a80..af7c686b0e9 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -6,6 +6,7 @@ extension UIColor { class var defaultRouteLayer: UIColor { get { return #colorLiteral(red: 0.337254902, green: 0.6588235294, blue: 0.9843137255, alpha: 1) } } class var defaultAlternateLine: UIColor { get { return #colorLiteral(red: 0.6, green: 0.6, blue: 0.6, alpha: 1) } } class var defaultAlternateLineCasing: UIColor { get { return #colorLiteral(red: 0.5019607843, green: 0.4980392157, blue: 0.5019607843, alpha: 1) } } + class var defaultVanishingRouteColor: UIColor { get { return #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) } } class var defaultManeuverArrowStroke: UIColor { get { return .defaultRouteLayer } } class var defaultManeuverArrow: UIColor { get { return #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) } } diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index bd7ffdc139f..5f21c9f239c 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -108,6 +108,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { @objc dynamic public var routeCasingColor: UIColor = .defaultRouteCasing @objc dynamic public var routeAlternateColor: UIColor = .defaultAlternateLine @objc dynamic public var routeAlternateCasingColor: UIColor = .defaultAlternateLineCasing + @objc dynamic public var vanishingRouteColor: UIColor = .defaultVanishingRouteColor @objc dynamic public var maneuverArrowColor: UIColor = .defaultManeuverArrow @objc dynamic public var maneuverArrowStrokeColor: UIColor = .defaultManeuverArrowStroke @@ -464,7 +465,6 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { self.routes = routes let polylines = navigationMapViewDelegate?.navigationMapView(self, shapeFor: routes) ?? shape(for: routes, legIndex: legIndex) - //let mainPolylineSimplified = navigationMapViewDelegate?.navigationMapView(self, simplifiedShapeFor: mainRoute) ?? shape(forCasingOf: mainRoute, legIndex: legIndex) /** If there is already an existing source that represents the routes, @@ -479,16 +479,14 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let allRoutesSource = MGLShapeSource(identifier: SourceIdentifier.allRoutes, shape: polylines, options: [.lineDistanceMetrics: true]) style.addSource(allRoutesSource) - let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternateRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternateRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) - - let alternateRoutesCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) ?? alternateRouteCasingStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) - generateTrafficGradientStops(for: mainRoute) let mainRouteLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteStyleLayerWithIdentifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) ?? mainRouteStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) let mainRouteCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) ?? mainRouteCasingStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) + let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternateRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternateRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) + let alternateRoutesCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) ?? alternateRouteCasingStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) - // Add all the layers + // Add all the layers in the correct order for layer in style.layers.reversed() { if !(layer is MGLSymbolStyleLayer) && layer.identifier != StyleLayerIdentifier.arrow && layer.identifier != StyleLayerIdentifier.arrowSymbol && layer.identifier != StyleLayerIdentifier.arrowCasingSymbol && layer.identifier != StyleLayerIdentifier.arrowStroke && layer.identifier != StyleLayerIdentifier.waypointCircle { @@ -564,8 +562,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { // and fade the range from zero that lowest value, // which represents the % of the route traveled. if let minStop = filtered.min(by: { $0.0 < $1.0 }) { - filtered[0.0] = UIColor.clear // TODO: Pull color from user-defined preference - filtered[percentTraveled.nextDown] = UIColor.clear + filtered[0.0] = vanishingRouteColor + filtered[percentTraveled.nextDown] = vanishingRouteColor filtered[percentTraveled] = minStop.value } @@ -578,8 +576,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } if let minStop = filteredCasing.min(by: { $0.0 < $1.0 }) { - filteredCasing[0.0] = UIColor.clear // TODO: Pull color from user-defined preference - filteredCasing[percentTraveled.nextDown] = UIColor.clear + filteredCasing[0.0] = vanishingRouteColor + filteredCasing[percentTraveled.nextDown] = vanishingRouteColor filteredCasing[percentTraveled] = minStop.value } From 8440ff41f91c290206543a460977cd77b2a9a660 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 18:53:21 -0700 Subject: [PATCH 17/25] Update DayStyle.swift --- MapboxNavigation/DayStyle.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index af7c686b0e9..5625cdba43b 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -117,6 +117,7 @@ open class DayStyle: Style { NavigationMapView.appearance().maneuverArrowStrokeColor = .defaultManeuverArrowStroke NavigationMapView.appearance().routeAlternateColor = .defaultAlternateLine NavigationMapView.appearance().routeCasingColor = .defaultRouteCasing + NavigationMapView.appearance().vanishingRouteColor = .defaultVanishingRouteColor NavigationMapView.appearance().trafficHeavyColor = .trafficHeavy NavigationMapView.appearance().trafficLowColor = .trafficLow NavigationMapView.appearance().trafficModerateColor = .trafficModerate From 5007d44952904f166e9ebc368ac782b5e34b9f4c Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Thu, 18 Jun 2020 19:08:13 -0700 Subject: [PATCH 18/25] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 750bd18bcf9..bfeb392d7c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ * Merge instructions now indicate whether to merge to the left or the right, as when navigating online. ([valhalla/valhalla#1892](https://github.com/valhalla/valhalla/pull/1892), [valhalla/valhalla#1989](https://github.com/valhalla/valhalla/pull/1989)) * Fixed an issue where spoken and visual instructions sometimes omitted the cardinal direction after a route number in the United States. ([valhalla/valhalla#1917](https://github.com/valhalla/valhalla/pull/1917)) * A spoken instruction about an exit ramp no longer specifies the side of the road if the ramp branches off the slow lane (on the right side in regions that drive on the right). ([valhalla/valhalla#1990](https://github.com/valhalla/valhalla/pull/1990)) +* Removed `NavigationMapViewDelegate.navigationMapView(_:routeStyleLayerWithIdentifier:source:)`, `NavigationMapViewDelegate.navigationMapView(_:routeCasingStyleLayerWithIdentifier:source:)` in favor of four new delegate methods to customize the route styling ([#2377](https://github.com/mapbox/mapbox-navigation-ios/pull/2377)): + * `NavigationMapViewDelegate.navigationMapView(_:mainRouteStyleLayerWithIdentifier:source:)` to style the main route. + * `NavigationMapViewDelegate.navigationMapView(_:mainRouteCasingStyleLayerWithIdentifier:source:)` to style the casing of the main route. + * `NavigationMapViewDelegate.navigationMapView(_:alternativeRouteStyleLayerWithIdentifier:source:)` to style alternative routes. + * `NavigationMapViewDelegate.navigationMapView(_:alternativeRouteCasingStyleLayerWithIdentifier:source:)` to style the casing of alternative routes. +* Added the ability for the route line to disappear as the puck travels along a route during turn-by-turn navigation. ([#2377](https://github.com/mapbox/mapbox-navigation-ios/pull/2377)) +* Fixed an issue where the casing for the main route would not overlap alternative routes. ([#2377](https://github.com/mapbox/mapbox-navigation-ios/pull/2377)) ## v0.40.0 From a7589128bf6ee1ac5d18026249327539a764e9cc Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Mon, 22 Jun 2020 15:00:49 -0700 Subject: [PATCH 19/25] Little refactoring --- MapboxNavigation/NavigationMapView.swift | 78 +++++++++++++++++------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 5f21c9f239c..2c0e61cc88b 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -111,15 +111,20 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { @objc dynamic public var vanishingRouteColor: UIColor = .defaultVanishingRouteColor @objc dynamic public var maneuverArrowColor: UIColor = .defaultManeuverArrow @objc dynamic public var maneuverArrowStrokeColor: UIColor = .defaultManeuverArrowStroke - - typealias RouteGradientStops = (line: [CGFloat: UIColor], casing: [CGFloat: UIColor]) var userLocationForCourseTracking: CLLocation? var animatesUserLocation: Bool = false var altitude: CLLocationDistance var routes: [Route]? var isAnimatingToOverheadMode = false - var routeGradientStops = RouteGradientStops(line: [:], casing: [:]) // TODO: Account for cases where traffic isn't enabled. + + /** + A tuple that represents the dictionary of percentage/color pairs used to + calculate the color gradient transitions belonging to the main route line + and its casing. + */ + typealias RouteGradientStops = (line: [CGFloat: UIColor], casing: [CGFloat: UIColor]) + private var routeGradientStops = RouteGradientStops(line: [:], casing: [:]) // TODO: Account for cases where traffic isn't enabled. var shouldPositionCourseViewFrameByFrame = false { didSet { @@ -1019,13 +1024,23 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } func generateTrafficGradientStops(for route: Route) { - typealias GradientStop = (percent: CGFloat, color: UIColor) - var stops = [GradientStop]() - let routeLength = route.distance + /** + The resulting set of key/value stops that will be used + for the route's line gradient. + */ + var stops = [[CGFloat:UIColor]]() + + /** + We will keep track of this value as we iterate through + the various congestion segments. + */ var distanceTraveled: CLLocationDistance = 0.0 - // Individual polylines associated with a congestion level + /** + Begin by calculating individual congestion segments associated + with a congestion level, represented as `MGLPolylineFeature`s. + */ guard let congestionSegments = addCongestion(to: route, legIndex: 0) else { return } /** @@ -1044,50 +1059,67 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { for (index, line) in congestionSegments.enumerated() { line.getCoordinates(line.coordinates, range: NSMakeRange(0, Int(line.pointCount))) + // `UnsafeMutablePointer` is needed here to let buffPtr = UnsafeMutableBufferPointer(start: line.coordinates, count: Int(line.pointCount)) let lineCoordinates = Array(buffPtr) - // Get congestion color + // Get congestion color for the stop. let congestionLevel = line.attributes["congestion"] as! String let congestionColor = getCongestionColor(for: congestionLevel) - // Measure the line length + // Measure the line length of the traffic segment. let lineString = LineString(lineCoordinates) let distance = lineString.distance() + /** + If this is the first congestion segment, then the starting + percentage point will be zero. + */ if index == congestionSegments.startIndex { let segmentStartPercentTraveled = CGFloat.zero - stops.append(GradientStop(percent: segmentStartPercentTraveled, color: congestionColor)) + stops.append([segmentStartPercentTraveled: congestionColor]) distanceTraveled = distanceTraveled + distance - let segmentEndPercentTraveled = CGFloat((distanceTraveled / routeLength)) - stops.append(GradientStop(percent: segmentEndPercentTraveled.nextDown, color: congestionColor)) + let segmentEndPercentTraveled = CGFloat((distanceTraveled / route.distance)) + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor continue } + /** + If this is the last congestion segment, then the ending + percentage point will be 1.0, to represent 100%. + */ if index == congestionSegments.endIndex - 1 { - let segmentStartPercentTraveled = CGFloat((distanceTraveled / routeLength)) - stops.append(GradientStop(percent: segmentStartPercentTraveled.nextUp, color: congestionColor)) + let segmentStartPercentTraveled = CGFloat((distanceTraveled / route.distance)) + stops.append([segmentStartPercentTraveled.nextUp: congestionColor]) let segmentEndPercentTraveled = CGFloat(1.0) - stops.append(GradientStop(percent: segmentEndPercentTraveled, color: congestionColor)) + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor continue } - let segmentStartPercentTraveled = CGFloat((distanceTraveled / routeLength)) - stops.append(GradientStop(percent: segmentStartPercentTraveled.nextUp, color: congestionColor)) + /** + If this is not the first or last congestion segment, then + the starting and ending percent values traveled for this segment + will be a fractional amount more/less than the actual values. + */ + let segmentStartPercentTraveled = CGFloat((distanceTraveled / route.distance)) + routeGradientStops.line[segmentStartPercentTraveled.nextUp] = congestionColor distanceTraveled = distanceTraveled + distance - let segmentEndPercentTraveled = CGFloat((distanceTraveled / routeLength)) - stops.append(GradientStop(percent: segmentEndPercentTraveled.nextDown, color: congestionColor)) + let segmentEndPercentTraveled = CGFloat((distanceTraveled / route.distance)) + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor } - for stop in stops { - routeGradientStops.line[stop.percent] = stop.color - routeGradientStops.casing[stop.percent] = routeCasingColor // TODO: Replace with route casing color - } + /** + The casing layer around the route gradient is one single color, + so there's no need to give it the same stop/color combinations as + the main route stops dictionary. + */ + routeGradientStops.casing[0.0] = routeCasingColor + routeGradientStops.casing[1.0] = routeCasingColor } /** From 27a102de69e88527cb265c650dd9122b4bcddbf1 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Tue, 23 Jun 2020 16:46:16 -0700 Subject: [PATCH 20/25] Make vanishing route opt-in --- MapboxNavigation/NavigationMapView.swift | 13 +++++++++++++ MapboxNavigation/RouteMapViewController.swift | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 2c0e61cc88b..f210faa7540 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -45,6 +45,17 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { Maximum distance the user can tap for a selection to be valid when selecting an alternate route. */ public var tapGestureDistanceThreshold: CGFloat = 50 + + /** + Controls whether the route disappears as the user location + puck travels over it. Defaults to `false`. + + If `true`, the route line behind the user location puck + will fade to full transparancy. To customize the fade color that + appears behind the traveled section of a route, override the + `vanishingRouteColor` property for the `NavigationMapView.appearance()`. + */ + public var fadesRouteDuringNavigation: Bool = false /** The object that acts as the navigation delegate of the map view. @@ -508,6 +519,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { func mainRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { let mainRouteLayer = MGLLineStyleLayer(identifier: identifier, source: source) mainRouteLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + // Default color if no traffic is enabled mainRouteLayer.lineColor = NSExpression(forConstantValue: trafficUnknownColor) mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") @@ -522,6 +534,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { func mainRouteCasingStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { let mainRouteCasingLayer = MGLLineStyleLayer(identifier: identifier, source: source) mainRouteCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == false") + // Default color if no traffic is enabled mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 32d06adc072..f9cd57ec913 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -453,7 +453,9 @@ extension RouteMapViewController: NavigationComponent { let legIndex = progress.legIndex let stepIndex = progress.currentLegProgress.stepIndex - mapView.fadeRoute(progress.fractionTraveled) + if mapView.fadesRouteDuringNavigation { + mapView.fadeRoute(progress.fractionTraveled) + } mapView.updatePreferredFrameRate(for: progress) if currentLegIndexMapped != legIndex { From f8915e2abcd520aaacf1cbd705698855d0e90df0 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 24 Jun 2020 12:14:43 -0700 Subject: [PATCH 21/25] Update NavigationMapView.swift --- MapboxNavigation/NavigationMapView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index f5bdf98e8dd..c42d5764043 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -1082,7 +1082,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { // Measure the line length of the traffic segment. let lineString = LineString(lineCoordinates) - let distance = lineString.distance() + guard let distance = lineString.distance() else { return } /** If this is the first congestion segment, then the starting From fc8574f0ae60c33ae96cce8896b1fd09c9489eb1 Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 24 Jun 2020 15:29:38 -0700 Subject: [PATCH 22/25] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Minh Nguyễn --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee3205e0d1f..acd433507d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ * Fixed ungrammatical spoken instructions at sharp turns in English. ([valhalla/valhalla#2226](https://github.com/valhalla/valhalla/pull/2226)) * Fixed an issue where spoken and visual instructions sometimes omitted the cardinal direction after a route number in the United States. ([valhalla/valhalla#1917](https://github.com/valhalla/valhalla/pull/1917)) * A spoken instruction about an exit ramp no longer specifies the side of the road if the ramp branches off the slow lane (on the right side in regions that drive on the right). ([valhalla/valhalla#1990](https://github.com/valhalla/valhalla/pull/1990)) +## Map + * Removed `NavigationMapViewDelegate.navigationMapView(_:routeStyleLayerWithIdentifier:source:)`, `NavigationMapViewDelegate.navigationMapView(_:routeCasingStyleLayerWithIdentifier:source:)` in favor of four new delegate methods to customize the route styling ([#2377](https://github.com/mapbox/mapbox-navigation-ios/pull/2377)): * `NavigationMapViewDelegate.navigationMapView(_:mainRouteStyleLayerWithIdentifier:source:)` to style the main route. * `NavigationMapViewDelegate.navigationMapView(_:mainRouteCasingStyleLayerWithIdentifier:source:)` to style the casing of the main route. From 32e0d3205883acb0140b9aafdb2702d6fff19daf Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 24 Jun 2020 15:32:16 -0700 Subject: [PATCH 23/25] =?UTF-8?q?Change=20property=20name=20from=20vanishi?= =?UTF-8?q?ngRouteColor=20=E2=86=92=20traversedRouteColor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MapboxNavigation/DayStyle.swift | 4 ++-- MapboxNavigation/NavigationMapView.swift | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MapboxNavigation/DayStyle.swift b/MapboxNavigation/DayStyle.swift index 5625cdba43b..088a5b23089 100644 --- a/MapboxNavigation/DayStyle.swift +++ b/MapboxNavigation/DayStyle.swift @@ -6,7 +6,7 @@ extension UIColor { class var defaultRouteLayer: UIColor { get { return #colorLiteral(red: 0.337254902, green: 0.6588235294, blue: 0.9843137255, alpha: 1) } } class var defaultAlternateLine: UIColor { get { return #colorLiteral(red: 0.6, green: 0.6, blue: 0.6, alpha: 1) } } class var defaultAlternateLineCasing: UIColor { get { return #colorLiteral(red: 0.5019607843, green: 0.4980392157, blue: 0.5019607843, alpha: 1) } } - class var defaultVanishingRouteColor: UIColor { get { return #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) } } + class var defaultTraversedRouteColor: UIColor { get { return #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) } } class var defaultManeuverArrowStroke: UIColor { get { return .defaultRouteLayer } } class var defaultManeuverArrow: UIColor { get { return #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) } } @@ -117,7 +117,7 @@ open class DayStyle: Style { NavigationMapView.appearance().maneuverArrowStrokeColor = .defaultManeuverArrowStroke NavigationMapView.appearance().routeAlternateColor = .defaultAlternateLine NavigationMapView.appearance().routeCasingColor = .defaultRouteCasing - NavigationMapView.appearance().vanishingRouteColor = .defaultVanishingRouteColor + NavigationMapView.appearance().traversedRouteColor = .defaultTraversedRouteColor NavigationMapView.appearance().trafficHeavyColor = .trafficHeavy NavigationMapView.appearance().trafficLowColor = .trafficLow NavigationMapView.appearance().trafficModerateColor = .trafficModerate diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index c42d5764043..19b449f8886 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -53,7 +53,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { If `true`, the route line behind the user location puck will fade to full transparancy. To customize the fade color that appears behind the traveled section of a route, override the - `vanishingRouteColor` property for the `NavigationMapView.appearance()`. + `traversedRouteColor` property for the `NavigationMapView.appearance()`. */ public var fadesRouteDuringNavigation: Bool = false @@ -119,7 +119,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { @objc dynamic public var routeCasingColor: UIColor = .defaultRouteCasing @objc dynamic public var routeAlternateColor: UIColor = .defaultAlternateLine @objc dynamic public var routeAlternateCasingColor: UIColor = .defaultAlternateLineCasing - @objc dynamic public var vanishingRouteColor: UIColor = .defaultVanishingRouteColor + @objc dynamic public var traversedRouteColor: UIColor = .defaultTraversedRouteColor @objc dynamic public var maneuverArrowColor: UIColor = .defaultManeuverArrow @objc dynamic public var maneuverArrowStrokeColor: UIColor = .defaultManeuverArrowStroke @@ -580,8 +580,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { // and fade the range from zero that lowest value, // which represents the % of the route traveled. if let minStop = filtered.min(by: { $0.0 < $1.0 }) { - filtered[0.0] = vanishingRouteColor - filtered[percentTraveled.nextDown] = vanishingRouteColor + filtered[0.0] = traversedRouteColor + filtered[percentTraveled.nextDown] = traversedRouteColor filtered[percentTraveled] = minStop.value } @@ -594,8 +594,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { } if let minStop = filteredCasing.min(by: { $0.0 < $1.0 }) { - filteredCasing[0.0] = vanishingRouteColor - filteredCasing[percentTraveled.nextDown] = vanishingRouteColor + filteredCasing[0.0] = traversedRouteColor + filteredCasing[percentTraveled.nextDown] = traversedRouteColor filteredCasing[percentTraveled] = minStop.value } From 3da9452bae57c543426faf155c88f995d8fdb3ce Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 24 Jun 2020 15:37:21 -0700 Subject: [PATCH 24/25] =?UTF-8?q?Rename=20fadesRouteDuringNavigation=20?= =?UTF-8?q?=E2=86=92=20routeLineTracksTraversal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + MapboxNavigation/NavigationMapView.swift | 10 +++++----- MapboxNavigation/RouteMapViewController.swift | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acd433507d7..5f6fcc16e6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ * Fixed ungrammatical spoken instructions at sharp turns in English. ([valhalla/valhalla#2226](https://github.com/valhalla/valhalla/pull/2226)) * Fixed an issue where spoken and visual instructions sometimes omitted the cardinal direction after a route number in the United States. ([valhalla/valhalla#1917](https://github.com/valhalla/valhalla/pull/1917)) * A spoken instruction about an exit ramp no longer specifies the side of the road if the ramp branches off the slow lane (on the right side in regions that drive on the right). ([valhalla/valhalla#1990](https://github.com/valhalla/valhalla/pull/1990)) + ## Map * Removed `NavigationMapViewDelegate.navigationMapView(_:routeStyleLayerWithIdentifier:source:)`, `NavigationMapViewDelegate.navigationMapView(_:routeCasingStyleLayerWithIdentifier:source:)` in favor of four new delegate methods to customize the route styling ([#2377](https://github.com/mapbox/mapbox-navigation-ios/pull/2377)): diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 19b449f8886..3adf50c0a3f 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -50,12 +50,12 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { Controls whether the route disappears as the user location puck travels over it. Defaults to `false`. - If `true`, the route line behind the user location puck - will fade to full transparancy. To customize the fade color that - appears behind the traveled section of a route, override the + If `true`, the part of the route that has been traversed will be + rendered will full transparency. To customize the color that + appears on the traversed section of a route, override the `traversedRouteColor` property for the `NavigationMapView.appearance()`. */ - public var fadesRouteDuringNavigation: Bool = false + public var routeLineTracksTraversal: Bool = false /** The object that acts as the navigation delegate of the map view. @@ -135,7 +135,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { and its casing. */ typealias RouteGradientStops = (line: [CGFloat: UIColor], casing: [CGFloat: UIColor]) - private var routeGradientStops = RouteGradientStops(line: [:], casing: [:]) // TODO: Account for cases where traffic isn't enabled. + private var routeGradientStops = RouteGradientStops(line: [:], casing: [:]) var shouldPositionCourseViewFrameByFrame = false { didSet { diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index 8e8020e0fb0..f3a0a0cf506 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -453,7 +453,7 @@ extension RouteMapViewController: NavigationComponent { let legIndex = progress.legIndex let stepIndex = progress.currentLegProgress.stepIndex - if mapView.fadesRouteDuringNavigation { + if mapView.routeLineTracksTraversal { mapView.fadeRoute(progress.fractionTraveled) } From 86b6862f6276a1c8f9e1accfa19b713e0a90183a Mon Sep 17 00:00:00 2001 From: Nadia Barbosa Date: Wed, 24 Jun 2020 16:36:26 -0700 Subject: [PATCH 25/25] Final feedback edits --- MapboxNavigation/NavigationMapView.swift | 43 +++++++++++-------- .../NavigationMapViewDelegate.swift | 4 +- .../NavigationViewController.swift | 4 +- .../NavigationViewControllerDelegate.swift | 4 +- MapboxNavigation/RouteMapViewController.swift | 4 +- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/MapboxNavigation/NavigationMapView.swift b/MapboxNavigation/NavigationMapView.swift index 3adf50c0a3f..8641f796968 100644 --- a/MapboxNavigation/NavigationMapView.swift +++ b/MapboxNavigation/NavigationMapView.swift @@ -47,13 +47,14 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { public var tapGestureDistanceThreshold: CGFloat = 50 /** - Controls whether the route disappears as the user location - puck travels over it. Defaults to `false`. + Controls whether the main route style layer and its casing disappears + as the user location puck travels over it. Defaults to `false`. If `true`, the part of the route that has been traversed will be - rendered will full transparency. To customize the color that - appears on the traversed section of a route, override the - `traversedRouteColor` property for the `NavigationMapView.appearance()`. + rendered will full transparency, to give the illusion of a + disappearing route. To customize the color that appears on the + traversed section of a route, override the `traversedRouteColor` property + for the `NavigationMapView.appearance()`. */ public var routeLineTracksTraversal: Bool = false @@ -499,8 +500,8 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { let mainRouteLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteStyleLayerWithIdentifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) ?? mainRouteStyleLayer(identifier: StyleLayerIdentifier.mainRoute, source: allRoutesSource) let mainRouteCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) ?? mainRouteCasingStyleLayer(identifier: StyleLayerIdentifier.mainRouteCasing, source: allRoutesSource) - let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternateRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternateRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) - let alternateRoutesCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) ?? alternateRouteCasingStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) + let alternateRoutesLayer = navigationMapViewDelegate?.navigationMapView(self, alternativeRouteStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) ?? alternativeRouteStyleLayer(identifier: StyleLayerIdentifier.alternateRoutes, source: allRoutesSource) + let alternateRoutesCasingLayer = navigationMapViewDelegate?.navigationMapView(self, mainRouteCasingStyleLayerWithIdentifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) ?? alternativeRouteCasingStyleLayer(identifier: StyleLayerIdentifier.alternateRoutesCasing, source: allRoutesSource) // Add all the layers in the correct order for layer in style.layers.reversed() { @@ -523,6 +524,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { mainRouteLayer.lineColor = NSExpression(forConstantValue: trafficUnknownColor) mainRouteLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) mainRouteLayer.lineJoin = NSExpression(forConstantValue: "round") + mainRouteLayer.lineCap = NSExpression(forConstantValue: "round") if routeGradientStops.line.isEmpty == false { mainRouteLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.line) @@ -538,6 +540,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { mainRouteCasingLayer.lineColor = NSExpression(forConstantValue: routeCasingColor) mainRouteCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) mainRouteCasingLayer.lineJoin = NSExpression(forConstantValue: "round") + mainRouteCasingLayer.lineCap = NSExpression(forConstantValue: "round") if routeGradientStops.casing.isEmpty { mainRouteCasingLayer.lineGradient = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($lineProgress, 'linear', nil, %@)", routeGradientStops.casing) @@ -546,21 +549,25 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { return mainRouteCasingLayer } - func alternateRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + func alternativeRouteStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { let alternateRoutesLayer = MGLLineStyleLayer(identifier: identifier, source: source) alternateRoutesLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesLayer.lineColor = NSExpression(forConstantValue: routeAlternateColor) alternateRoutesLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel) alternateRoutesLayer.lineJoin = NSExpression(forConstantValue: "round") + alternateRoutesLayer.lineCap = NSExpression(forConstantValue: "round") + return alternateRoutesLayer } - func alternateRouteCasingStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { + func alternativeRouteCasingStyleLayer(identifier: String, source: MGLSource) -> MGLLineStyleLayer { let alternateRoutesCasingLayer = MGLLineStyleLayer(identifier: identifier, source: source) alternateRoutesCasingLayer.predicate = NSPredicate(format: "isAlternateRoute == true") alternateRoutesCasingLayer.lineColor = NSExpression(forConstantValue: routeAlternateCasingColor) alternateRoutesCasingLayer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", MBRouteLineWidthByZoomLevel.multiplied(by: 1.5)) alternateRoutesCasingLayer.lineJoin = NSExpression(forConstantValue: "round") + alternateRoutesCasingLayer.lineCap = NSExpression(forConstantValue: "round") + return alternateRoutesCasingLayer } @@ -1072,13 +1079,13 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { for (index, line) in congestionSegments.enumerated() { line.getCoordinates(line.coordinates, range: NSMakeRange(0, Int(line.pointCount))) - // `UnsafeMutablePointer` is needed here to + // `UnsafeMutablePointer` is needed here to get the line’s coordinates. let buffPtr = UnsafeMutableBufferPointer(start: line.coordinates, count: Int(line.pointCount)) let lineCoordinates = Array(buffPtr) // Get congestion color for the stop. let congestionLevel = line.attributes["congestion"] as! String - let congestionColor = getCongestionColor(for: congestionLevel) + let associatedCongestionColor = congestionColor(for: congestionLevel) // Measure the line length of the traffic segment. let lineString = LineString(lineCoordinates) @@ -1090,12 +1097,12 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { */ if index == congestionSegments.startIndex { let segmentStartPercentTraveled = CGFloat.zero - stops.append([segmentStartPercentTraveled: congestionColor]) + stops.append([segmentStartPercentTraveled: associatedCongestionColor]) distanceTraveled = distanceTraveled + distance let segmentEndPercentTraveled = CGFloat((distanceTraveled / route.distance)) - routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = associatedCongestionColor continue } @@ -1105,10 +1112,10 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { */ if index == congestionSegments.endIndex - 1 { let segmentStartPercentTraveled = CGFloat((distanceTraveled / route.distance)) - stops.append([segmentStartPercentTraveled.nextUp: congestionColor]) + stops.append([segmentStartPercentTraveled.nextUp: associatedCongestionColor]) let segmentEndPercentTraveled = CGFloat(1.0) - routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = associatedCongestionColor continue } @@ -1118,12 +1125,12 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { will be a fractional amount more/less than the actual values. */ let segmentStartPercentTraveled = CGFloat((distanceTraveled / route.distance)) - routeGradientStops.line[segmentStartPercentTraveled.nextUp] = congestionColor + routeGradientStops.line[segmentStartPercentTraveled.nextUp] = associatedCongestionColor distanceTraveled = distanceTraveled + distance let segmentEndPercentTraveled = CGFloat((distanceTraveled / route.distance)) - routeGradientStops.line[segmentEndPercentTraveled.nextDown] = congestionColor + routeGradientStops.line[segmentEndPercentTraveled.nextDown] = associatedCongestionColor } /** @@ -1138,7 +1145,7 @@ open class NavigationMapView: MGLMapView, UIGestureRecognizerDelegate { /** Given a congestion level, return its associated color. */ - private func getCongestionColor(for congestionLevel: String) -> UIColor { + private func congestionColor(for congestionLevel: String) -> UIColor { switch congestionLevel { case "low": return trafficLowColor diff --git a/MapboxNavigation/NavigationMapViewDelegate.swift b/MapboxNavigation/NavigationMapViewDelegate.swift index e7dcfcf56e4..1a5d11f7099 100644 --- a/MapboxNavigation/NavigationMapViewDelegate.swift +++ b/MapboxNavigation/NavigationMapViewDelegate.swift @@ -35,7 +35,7 @@ public protocol NavigationMapViewDelegate: class, UnimplementedLogging { - parameter source: The source containing the route data that this method would style. - returns: An MGLStyleLayer that is applied to alternative routes. */ - func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationMapView(_ mapView: NavigationMapView, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Asks the receiver to return an MGLStyleLayer for the casing layer that surrounds alternative route lines, given an identifier and source. @@ -138,7 +138,7 @@ public extension NavigationMapViewDelegate { /** `UnimplementedLogging` prints a warning to standard output the first time this method is called. */ - func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + func navigationMapView(_ mapView: NavigationMapView, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { logUnimplemented(protocolType: NavigationMapViewDelegate.self, level: .debug) return nil } diff --git a/MapboxNavigation/NavigationViewController.swift b/MapboxNavigation/NavigationViewController.swift index 44f93107440..e8b4f7000da 100644 --- a/MapboxNavigation/NavigationViewController.swift +++ b/MapboxNavigation/NavigationViewController.swift @@ -395,8 +395,8 @@ extension NavigationViewController: RouteMapViewControllerDelegate { return delegate?.navigationViewController(self, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) } - public func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationViewController(self, alternateRouteStyleLayerWithIdentifier: identifier, source: source) + public func navigationMapView(_ mapView: NavigationMapView, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationViewController(self, alternativeRouteStyleLayerWithIdentifier: identifier, source: source) } public func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { diff --git a/MapboxNavigation/NavigationViewControllerDelegate.swift b/MapboxNavigation/NavigationViewControllerDelegate.swift index 7c52f359462..726302c7c09 100644 --- a/MapboxNavigation/NavigationViewControllerDelegate.swift +++ b/MapboxNavigation/NavigationViewControllerDelegate.swift @@ -111,7 +111,7 @@ public protocol NavigationViewControllerDelegate: VisualInstructionDelegate{ If this method is unimplemented, the navigation view controller’s map view draws the alternative route lines using an `MGLLineStyleLayer`. */ - func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? + func navigationViewController(_ navigationViewController: NavigationViewController, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? /** Returns an `MGLStyleLayer` that determines the appearance of the casing around the alternative route lines. @@ -272,7 +272,7 @@ public extension NavigationViewControllerDelegate { return nil } - func navigationViewController(_ navigationViewController: NavigationViewController, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + func navigationViewController(_ navigationViewController: NavigationViewController, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { logUnimplemented(protocolType: NavigationViewControllerDelegate.self, level: .debug) return nil } diff --git a/MapboxNavigation/RouteMapViewController.swift b/MapboxNavigation/RouteMapViewController.swift index f3a0a0cf506..0daceafb42e 100644 --- a/MapboxNavigation/RouteMapViewController.swift +++ b/MapboxNavigation/RouteMapViewController.swift @@ -554,8 +554,8 @@ extension RouteMapViewController: NavigationViewDelegate { return delegate?.navigationMapView(mapView, mainRouteCasingStyleLayerWithIdentifier: identifier, source: source) } - func navigationMapView(_ mapView: NavigationMapView, alternateRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { - return delegate?.navigationMapView(mapView, alternateRouteStyleLayerWithIdentifier: identifier, source: source) + func navigationMapView(_ mapView: NavigationMapView, alternativeRouteStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? { + return delegate?.navigationMapView(mapView, alternativeRouteStyleLayerWithIdentifier: identifier, source: source) } func navigationMapView(_ mapView: NavigationMapView, alternateRouteCasingStyleLayerWithIdentifier identifier: String, source: MGLSource) -> MGLStyleLayer? {