Skip to content

Commit e7eefe0

Browse files
authored
Default route line layer positioning skips circle layers being used as symbol layers. (#4084)
1 parent 974e932 commit e7eefe0

File tree

4 files changed

+361
-247
lines changed

4 files changed

+361
-247
lines changed

MapboxNavigation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@
383383
B4A78D32261FD47700FDF212 /* sthlm-double-back.json in Resources */ = {isa = PBXBuildFile; fileRef = B47C1AFE261FD0A30078546C /* sthlm-double-back.json */; };
384384
B4BB0AD52704D1D7006F502D /* short_route.json in Resources */ = {isa = PBXBuildFile; fileRef = B4BB0AD42704D1D7006F502D /* short_route.json */; };
385385
B4BB0AD72704D1E6006F502D /* multileg_route.json in Resources */ = {isa = PBXBuildFile; fileRef = B4BB0AD62704D1E6006F502D /* multileg_route.json */; };
386+
B4C4FFA028ADB19600C7C253 /* RouteLineLayerPositionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4C4FF9F28ADB19600C7C253 /* RouteLineLayerPositionTests.swift */; };
386387
B4C8E39E286B72FA004D3EDD /* FeedbackViewControllerSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4C8E39D286B72FA004D3EDD /* FeedbackViewControllerSnapshotTests.swift */; };
387388
B4E19C47268114840011581F /* NavigationLocationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E19C46268114840011581F /* NavigationLocationProvider.swift */; };
388389
B4E6711F27BB09D6004EE9C1 /* SpriteInfoCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E6711E27BB09D6004EE9C1 /* SpriteInfoCacheTests.swift */; };
@@ -981,6 +982,7 @@
981982
B4B61B9627A882E200AA127E /* SpriteRepositoryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpriteRepositoryTests.swift; sourceTree = "<group>"; };
982983
B4BB0AD42704D1D7006F502D /* short_route.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = short_route.json; sourceTree = "<group>"; };
983984
B4BB0AD62704D1E6006F502D /* multileg_route.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = multileg_route.json; sourceTree = "<group>"; };
985+
B4C4FF9F28ADB19600C7C253 /* RouteLineLayerPositionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouteLineLayerPositionTests.swift; sourceTree = "<group>"; };
984986
B4C8E39D286B72FA004D3EDD /* FeedbackViewControllerSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackViewControllerSnapshotTests.swift; sourceTree = "<group>"; };
985987
B4D4291826260D5900EE92A8 /* MBXInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = MBXInfo.plist; sourceTree = "<group>"; };
986988
B4E19C46268114840011581F /* NavigationLocationProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationLocationProvider.swift; sourceTree = "<group>"; };
@@ -1633,6 +1635,7 @@
16331635
169A9709216440820082A6A0 /* NavigationViewControllerTestDoubles.swift */,
16341636
B40B1C60270380EC0065F57D /* VanishingRouteLineTests.swift */,
16351637
B473E900278651DD00D9E821 /* NavigationLocationProviderTests.swift */,
1638+
B4C4FF9F28ADB19600C7C253 /* RouteLineLayerPositionTests.swift */,
16361639
);
16371640
name = Navigation;
16381641
sourceTree = "<group>";
@@ -2848,6 +2851,7 @@
28482851
8AB316CB26BCA72300C3AC76 /* CGSize.swift in Sources */,
28492852
AE291FFF20975A7E00F23DFC /* NavigationViewControllerTests.swift in Sources */,
28502853
8A379B1127B5EADB00CE0A23 /* InstructionsCardViewControllerTests.swift in Sources */,
2854+
B4C4FFA028ADB19600C7C253 /* RouteLineLayerPositionTests.swift in Sources */,
28512855
16EF6C1E21193A9600AA580B /* CarPlayManagerTests.swift in Sources */,
28522856
8AF23ED527AA0B9C0038B40D /* CarPlayManagerSpec.swift in Sources */,
28532857
DADD82802161EC0300B8B47D /* UIViewAnimationOptionsTests.swift in Sources */,

Sources/MapboxNavigation/NavigationMapView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,8 @@ open class NavigationMapView: UIView {
18051805
!sourceLayer.isEmpty {
18061806
if layerInfo.type.rawValue == "circle",
18071807
let isPersistentCircle = try? mapView.mapboxMap.style.isPersistentLayer(id: layerInfo.id),
1808-
!isPersistentCircle {
1808+
let pitchAlignment = mapView.mapboxMap.style.layerProperty(for: layerInfo.id, property: "circle-pitch-alignment").value as? String,
1809+
isPersistentCircle || (pitchAlignment == "viewport") {
18091810
continue
18101811
}
18111812
targetLayer = layerInfo.id

Tests/MapboxNavigationTests/NavigationMapViewTests.swift

Lines changed: 0 additions & 246 deletions
Original file line numberDiff line numberDiff line change
@@ -487,250 +487,4 @@ class NavigationMapViewTests: TestCase {
487487
NavigationMapView.AnnotationIdentifier.finalDestinationAnnotation,
488488
"Point annotation identifiers should be equal.")
489489
}
490-
491-
func testRouteLineLayerPosition() {
492-
493-
let navigationMapView = NavigationMapView(frame: UIScreen.main.bounds)
494-
495-
let styleJSONObject: [String: Any] = [
496-
"version": 8,
497-
"center": [
498-
-122.385563, 37.763330
499-
],
500-
"zoom": 15,
501-
"sources": [
502-
"composite": [
503-
"url": "mapbox://mapbox.mapbox-streets-v8,mapbox.mapbox-terrain-v2",
504-
"type": "vector"
505-
],
506-
"custom": [
507-
"url": "http://api.example.com/tilejson.json",
508-
"type": "raster"
509-
]
510-
],
511-
"layers": []
512-
]
513-
514-
let styleJSON: String = ValueConverter.toJson(forValue: styleJSONObject)
515-
XCTAssertFalse(styleJSON.isEmpty, "ValueConverter should create valid JSON string.")
516-
517-
let mapLoadingErrorExpectation = expectation(description: "Map loading error expectation")
518-
mapLoadingErrorExpectation.assertForOverFulfill = false
519-
520-
navigationMapView.mapView.mapboxMap.onNext(event: .mapLoadingError, handler: { event in
521-
mapLoadingErrorExpectation.fulfill()
522-
})
523-
524-
navigationMapView.mapView.mapboxMap.loadStyleJSON(styleJSON)
525-
526-
wait(for: [mapLoadingErrorExpectation], timeout: 1.0)
527-
528-
let mainRouteIdentifier = route.identifier(.route(isMainRoute: true))
529-
let mainRouteCasingIdentifier = route.identifier(.routeCasing(isMainRoute: true))
530-
531-
navigationMapView.show([route])
532-
533-
// Style doesn't contain any layers besides main route layer and its casing. In case if
534-
// layer position wasn't provided main route line casing layer should be placed below the
535-
// main route line layer.
536-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 0]?.id,
537-
mainRouteCasingIdentifier,
538-
"Route line casing layer identifiers should be equal.")
539-
540-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 1]?.id,
541-
mainRouteIdentifier,
542-
"Route line layer identifiers should be equal.")
543-
544-
navigationMapView.removeRoutes()
545-
546-
// After removing all routes there should be no layers in style.
547-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers.count,
548-
0,
549-
"Unexpected number of layer identifiers in style.")
550-
551-
var source = GeoJSONSource()
552-
source.data = .geometry(.point(.init(.init(latitude: 0.0, longitude: 0.0))))
553-
554-
let sourceIdentifier = "test_source"
555-
try? navigationMapView.mapView.mapboxMap.style.addSource(source, id: sourceIdentifier)
556-
557-
let layerIdentifier = "test_dentifier"
558-
var layer = LineLayer(id: layerIdentifier)
559-
layer.source = sourceIdentifier
560-
try? navigationMapView.mapView.mapboxMap.style.addLayer(layer)
561-
562-
navigationMapView.show([route], layerPosition: .above(layerIdentifier))
563-
564-
// In case if layer position was provided to be placed above specific layer,
565-
// main route line casing layer should be placed above that specific layer followed by the
566-
// main route line layer.
567-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 0]?.id,
568-
layerIdentifier,
569-
"Custom line layer identifiers should be equal.")
570-
571-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 1]?.id,
572-
mainRouteCasingIdentifier,
573-
"Route line casing layer identifiers should be equal.")
574-
575-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 2]?.id,
576-
mainRouteIdentifier,
577-
"Route line layer identifiers should be equal.")
578-
579-
navigationMapView.removeRoutes()
580-
581-
navigationMapView.show([route], layerPosition: .below(layerIdentifier))
582-
583-
// In case if layer position was provided to be placed below specific layer,
584-
// main route line casing layer should be placed below that specific layer followed by the
585-
// main route line layer.
586-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 0]?.id,
587-
mainRouteCasingIdentifier,
588-
"Route line casing layer identifiers should be equal.")
589-
590-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 1]?.id,
591-
mainRouteIdentifier,
592-
"Route line layer identifiers should be equal.")
593-
594-
XCTAssertEqual(navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers[safe: 2]?.id,
595-
layerIdentifier,
596-
"Custom line layer identifiers should be equal.")
597-
598-
navigationMapView.removeRoutes()
599-
}
600-
601-
func testLayerPosition() {
602-
let multilegRoute = Fixture.route(from: "multileg-route", options: routeOptions)
603-
604-
let navigationMapView = NavigationMapView(frame: UIScreen.main.bounds)
605-
606-
let buildingLayer: [String: String] = [
607-
"id": "building-outline",
608-
"type": "line",
609-
"source": "composite",
610-
"source-layer": "building"
611-
]
612-
let roadTrafficLayer: [String: String] = [
613-
"id": "road-traffic",
614-
"type": "line",
615-
"source": "composite",
616-
"source-layer": "road"
617-
]
618-
let roadLabelLayer: [String: String] = [
619-
"id": "road-label",
620-
"type": "symbol",
621-
"source": "composite",
622-
"source-layer": "road"
623-
]
624-
let roadExitLayer: [String: String] = [
625-
"id": "road-exit-label",
626-
"type": "symbol",
627-
"source": "composite",
628-
"source-layer": "road-exit"
629-
]
630-
let poiLabelLayer: [String: String] = [
631-
"id": "poi-label",
632-
"type": "symbol",
633-
"source": "composite",
634-
"source-layer": "poi"
635-
]
636-
let poiLabelCircleLayer: [String: String] = [
637-
"id": "poi-label copy",
638-
"type": "circle",
639-
"source": "composite",
640-
"source-layer": "poi"
641-
]
642-
643-
let styleJSONObject: [String: Any] = [
644-
"version": 8,
645-
"center": [
646-
-122.385563, 37.763330
647-
],
648-
"zoom": 15,
649-
"sources": [
650-
"composite": [
651-
"url": "mapbox://mapbox.mapbox-streets-v8,mapbox.mapbox-terrain-v2",
652-
"type": "vector"
653-
],
654-
"custom": [
655-
"url": "http://api.example.com/tilejson.json",
656-
"type": "raster"
657-
]
658-
],
659-
"layers": [
660-
buildingLayer,
661-
roadTrafficLayer,
662-
roadLabelLayer,
663-
roadExitLayer,
664-
poiLabelLayer,
665-
poiLabelCircleLayer
666-
]
667-
]
668-
669-
let styleJSON: String = ValueConverter.toJson(forValue: styleJSONObject)
670-
XCTAssertFalse(styleJSON.isEmpty, "ValueConverter should create valid JSON string.")
671-
672-
let mapLoadingErrorExpectation = expectation(description: "Map loading error expectation")
673-
mapLoadingErrorExpectation.assertForOverFulfill = false
674-
675-
navigationMapView.mapView.mapboxMap.onNext(event: .mapLoadingError, handler: { event in
676-
mapLoadingErrorExpectation.fulfill()
677-
})
678-
679-
navigationMapView.mapView.mapboxMap.loadStyleJSON(styleJSON)
680-
681-
wait(for: [mapLoadingErrorExpectation], timeout: 1.0)
682-
683-
navigationMapView.show([multilegRoute])
684-
navigationMapView.showsRestrictedAreasOnRoute = true
685-
navigationMapView.showWaypoints(on: multilegRoute)
686-
navigationMapView.addArrow(route: multilegRoute, legIndex: 0, stepIndex: 1)
687-
688-
var allLayerIds = navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers.map({ $0.id })
689-
var expectedLayerSequence = [
690-
buildingLayer["id"]!,
691-
roadTrafficLayer["id"]!,
692-
multilegRoute.identifier(.routeCasing(isMainRoute: true)),
693-
multilegRoute.identifier(.route(isMainRoute: true)),
694-
multilegRoute.identifier(.restrictedRouteAreaRoute),
695-
roadLabelLayer["id"]!,
696-
NavigationMapView.LayerIdentifier.arrowStrokeLayer,
697-
NavigationMapView.LayerIdentifier.arrowLayer,
698-
NavigationMapView.LayerIdentifier.arrowSymbolCasingLayer,
699-
NavigationMapView.LayerIdentifier.arrowSymbolLayer,
700-
roadExitLayer["id"]!,
701-
poiLabelLayer["id"]!,
702-
poiLabelCircleLayer["id"]!,
703-
NavigationMapView.LayerIdentifier.waypointCircleLayer,
704-
NavigationMapView.LayerIdentifier.waypointSymbolLayer
705-
]
706-
XCTAssertEqual(allLayerIds, expectedLayerSequence, "Failed to add route line layers below bottommost symbol layer.")
707-
708-
// When custom layer position for route line provided, use the custom layer position.
709-
let customRouteLineLayerPosition = MapboxMaps.LayerPosition.below("road-traffic")
710-
navigationMapView.show([multilegRoute], layerPosition: customRouteLineLayerPosition)
711-
navigationMapView.removeWaypoints()
712-
navigationMapView.showsRestrictedAreasOnRoute = false
713-
714-
expectedLayerSequence = [
715-
buildingLayer["id"]!,
716-
multilegRoute.identifier(.routeCasing(isMainRoute: true)),
717-
multilegRoute.identifier(.route(isMainRoute: true)),
718-
roadTrafficLayer["id"]!,
719-
roadLabelLayer["id"]!,
720-
NavigationMapView.LayerIdentifier.arrowStrokeLayer,
721-
NavigationMapView.LayerIdentifier.arrowLayer,
722-
NavigationMapView.LayerIdentifier.arrowSymbolCasingLayer,
723-
NavigationMapView.LayerIdentifier.arrowSymbolLayer,
724-
roadExitLayer["id"]!,
725-
poiLabelLayer["id"]!,
726-
poiLabelCircleLayer["id"]!
727-
]
728-
allLayerIds = navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers.map({ $0.id })
729-
XCTAssertEqual(allLayerIds, expectedLayerSequence, "Failed to apply custom layer position for route line.")
730-
731-
navigationMapView.addArrow(route: multilegRoute, legIndex: 0, stepIndex: 0)
732-
navigationMapView.show(continuousAlternatives: [])
733-
allLayerIds = navigationMapView.mapView.mapboxMap.style.allLayerIdentifiers.map({ $0.id })
734-
XCTAssertEqual(allLayerIds, expectedLayerSequence, "Failed to keep layer positions in active navigation.")
735-
}
736490
}

0 commit comments

Comments
 (0)