Select to view content in your preferred language

How to use ENCMarinerSettings to set depth units with iOS/Swift

1643
15
Jump to solution
01-14-2024 08:23 AM
ChrisPelon
Emerging Contributor

Can someone help me set the depth units to feet? Here's my code, I am displaying the ENC chart successfully.

 

 

import SwiftUI
import ArcGIS

struct ContentView: View {
    @State private var map = AGSMap(basemapStyle: .arcGISOceans)

    var body: some View {
        MapView(map: map)
            .edgesIgnoringSafeArea(.all)
            .onAppear {
                map.initialViewpoint = AGSViewpoint(latitude: 45.318063, longitude: -85.2584, scale: 30055)
                loadENCExchangeSet()
            }
    }

    private func loadENCExchangeSet() {
        
        let depthUnits = AGSENCMarinerSettings.shared()
        

        // Load ENC Exchange Set
        if let catalogURL = Bundle.main.url(forResource: "CATALOG", withExtension: "031", subdirectory: "/ENC_ROOT") {
            let encExchangeSet = AGSENCExchangeSet(fileURLs: [catalogURL])
            
            encExchangeSet.load { error in
                if let error = error {
                    print("Error loading ENC Exchange Set: \(error.localizedDescription)")
                } else {
                    
                    let encLayers = encExchangeSet.datasets.map { AGSENCLayer(cell: AGSENCCell(dataset: $0)) }
                    DispatchQueue.main.async {
                        self.map.operationalLayers.addObjects(from: encLayers)
                        // Adjust this viewpoint to match where your ENC data is
                        self.map.initialViewpoint = AGSViewpoint(latitude: 45.318063, longitude: -85.2584, scale: 30055)
                    }
                }
            }
        } else {
            print("Error: CATALOG.031 file not found in bundle.")
        }
    }

}

struct MapView: UIViewRepresentable {
    let map: AGSMap
    let graphicsOverlay = AGSGraphicsOverlay()

    func makeUIView(context: Context) -> AGSMapView {
        let mapView = AGSMapView()
        mapView.map = map
        mapView.graphicsOverlays.add(graphicsOverlay)
        return mapView
    }

    func updateUIView(_ uiView: AGSMapView, context: Context) {
        // Perform any necessary updates to the UIView
    }

}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 

 

0 Kudos
1 Solution

Accepted Solutions
rolson_esri
Regular Contributor

The API has changed. Load doesn't take a completion block like the 100 SDK. The Swift SDK was redesigned from the ground up to take advantage of all the features of swift, including Swift Concurrency.  That means that loading an exchange set is now an async method:

 

try await encExchangeSet.load()

 

adding operational layers is also different. There are add methods directly on the map (see doc here) .

 

So that code should probably look something like:

self.map.addOperationalLayers(encLayers)

 

View solution in original post

15 Replies
ChrisPelon
Emerging Contributor

I have this line, but does not seem to work.  colorScheme is working, but not displayDepthUnits.

// Set up ENC environment
        let hydrographyDirectory = Bundle.main.url(forResource: "S57DataDictionary", withExtension: "xml", subdirectory: "hydrography")!.deletingLastPathComponent()
        let environmentSettings = AGSENCEnvironmentSettings.shared()
        environmentSettings.resourceDirectory = hydrographyDirectory
        environmentSettings.sencDataDirectory = FileManager.default.temporaryDirectory
        
        environmentSettings.displaySettings.marinerSettings.displayDepthUnits = .feet
        
        environmentSettings.displaySettings.marinerSettings.colorScheme = .day

 

0 Kudos
RonaldHaug
Frequent Contributor

Hi Chris,

I may be out of my depth here, but I recommend you google "ENCMarinerSettings".

From the listings:

1) ArcGIS delevopers has Class EncMarinerSettings . Checking the ClassEncMariner Settings, color scheme default is day, so I don't know whether your coding is steering the ship.

2) There is a post similar to yours posted in Esri Community "Issue with 'EncDisplaySettings' in ArcGIS Runtime SDK for Qt" . This one the answer is solved by starting with #include "EncDisplaySettings.h" in the code.

Hope this leads you a bit further down the path to solving your coding and getting your display panel operating the way you want it to. What's a pirate's favorite letter? "Aaaaarrrgh"

0 Kudos
ChrisPelon
Emerging Contributor

Hi Ron,

Thanks for taking a look. EncMarinerSettings.colorscheme is working well. I can switch between day/dusk/night. What is not working is EncMarinerSettings.displayDepthUnits. No matter what I do, the chart always shows depths in meters. I have searched online for many hours and even went round and round with chatGPT 🙂 to no avail. Must be something simple I am missing.

0 Kudos
RonaldHaug
Frequent Contributor

Hi Chris,

I'm sure it's staring us both in the face.

What's up with that line 18 of code?  let depthUnits = AGSENCMarinerSettings.shared()

Have you run the code for errors?

0 Kudos
ChrisPelon
Emerging Contributor

I've removed line 18 since I posted the code, I was just playing with ways to get displayDepthUnits to work.

0 Kudos
rolson_esri
Regular Contributor

This line in your code should do it:

        environmentSettings.displaySettings.marinerSettings.displayDepthUnits = .feet

 

One of my colleagues is going to check to see if we have a bug here. I can get back to you after that.

Also, I see that you are using our 100.x SDK and using it with SwiftUI. Is there a reason why you haven't migrated to our 200 series with the Swift SDK? It has out of the box support for SwiftUI: https://developers.arcgis.com/swift/

0 Kudos
ChrisPelon
Emerging Contributor

Thank you for pointing out I was not using 200. I have updated to 200 sdk. but now this code does not work. 

private func loadENCExchangeSet() {
        // Load ENC Exchange Set
        if let catalogURL = Bundle.main.url(forResource: "CATALOG", withExtension: "031", subdirectory: "/ENC_ROOT") {
            let encExchangeSet = ENCExchangeSet(fileURLs: [catalogURL])

            encExchangeSet.load { error in
                if let error = error {
                    print("Error loading ENC Exchange Set: \(error.localizedDescription)")
                } else {
                    let encLayers = encExchangeSet.datasets.map { ENCLayer(cell: ENCCell(dataset: $0)) }
                    
                    DispatchQueue.main.async {
// I am getting error here
                        self.map.operationalLayers.addObjects(from: encLayers)
                        print("ENC layers added to the map.")
                    }
                }
            }
        } else {
            print("Error: CATALOG.031 file not found in bundle.")
        }
    }
0 Kudos
rolson_esri
Regular Contributor

Why are you using a dispatch async to add the operational layers? I don't think you need to do that. Nevertheless, I don't think that should be an issue. What error are you seeing or what is failing?

0 Kudos
ChrisPelon
Emerging Contributor

Screenshot 2024-01-16 at 6.51.46 PM.png

0 Kudos