Distance composite symbol

View on GitHub
Sample viewer app

Change a graphic's symbol based on the camera's proximity to it.

Distance composite symbol sample

Use case

When showing dense datasets, it is beneficial to reduce the detail of individual points when zooming out to avoid visual clutter and to avoid data points overlapping and obscuring each other.

How to use the sample

The sample starts looking at a plane. Zoom out from the plane to see it turn into a cone. Keeping zooming out and it will turn into a point.

How it works

  1. Create an AGSGraphicsOverlay object and add it to an AGSSceneView object.
  2. Create an AGSDistanceCompositeSceneSymbol object.
  3. Create AGSDistanceSymbolRange objects specifying an AGSSymbol and the min and max distance within which the symbol should be visible.
  4. Add the ranges to the ranges array of the distance composite scene symbol.
  5. Create an AGSGraphic object with the distance composite scene symbol at a location and add it to the graphics overlay.

Relevant API

  • AGSDistanceCompositeSceneSymbol
  • AGSDistanceSymbolRange
  • AGSOrbitGeoElementCameraController

Tags

3D, data, graphic

Sample Code

DistanceCompositeSymbolViewController.swift
                                                                               
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//
// Copyright 2017 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import UIKit
import ArcGIS

class DistanceCompositeSymbolViewController: UIViewController {
    @IBOutlet var sceneView: AGSSceneView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add the source code button item to the right of navigation bar
        (self.navigationItem.rightBarButtonItem as! SourceCodeBarButtonItem).filenames = ["DistanceCompositeSymbolViewController"]

        // initialize scene with topographic basemap
        let scene = AGSScene(basemap: .imagery())
        // assign scene to the scene view
        self.sceneView.scene = scene

        // add base surface for elevation data
        let surface = AGSSurface()
        /// The url of the Terrain 3D ArcGIS REST Service.
        let worldElevationServiceURL = URL(string: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer")!
        let elevationSource = AGSArcGISTiledElevationSource(url: worldElevationServiceURL)
        surface.elevationSources.append(elevationSource)
        scene.baseSurface = surface

        let graphicsOverlay = AGSGraphicsOverlay()
        graphicsOverlay.sceneProperties?.surfacePlacement = .relative
        self.sceneView.graphicsOverlays.add(graphicsOverlay)

        // set up the different symbols
        let circleSymbol = AGSSimpleMarkerSymbol(style: .circle, color: .red, size: 10.0)

        let coneSymbol = AGSSimpleMarkerSceneSymbol.cone(with: .red, diameter: 200, height: 600)
        coneSymbol.pitch = -90.0

        let modelSymbol = AGSModelSceneSymbol(name: "Bristol", extension: "dae", scale: 100.0)
        modelSymbol.load { [weak self] (error) in
            if let error = error {
                self?.presentAlert(error: error)
                return
            }

            // set up the distance composite symbol
            let compositeSymbol = AGSDistanceCompositeSceneSymbol()
            compositeSymbol.ranges.append(AGSDistanceSymbolRange(symbol: modelSymbol, minDistance: 0, maxDistance: 10000))
            compositeSymbol.ranges.append(AGSDistanceSymbolRange(symbol: coneSymbol, minDistance: 10001, maxDistance: 30000))
            compositeSymbol.ranges.append(AGSDistanceSymbolRange(symbol: circleSymbol, minDistance: 30001, maxDistance: 0))

            // create graphic
            let aircraftPosition = AGSPoint(x: -2.708471, y: 56.096575, z: 5000, spatialReference: .wgs84())
            let aircraftGraphic = AGSGraphic(geometry: aircraftPosition, symbol: compositeSymbol, attributes: nil)

            // add graphic to graphics overlay
            graphicsOverlay.graphics.add(aircraftGraphic)

            // add an orbit camera controller to lock the camera to the graphic
            let cameraController = AGSOrbitGeoElementCameraController(targetGeoElement: aircraftGraphic, distance: 4000)
            cameraController.cameraPitchOffset = 80
            cameraController.cameraHeadingOffset = -30
            self?.sceneView.cameraController = cameraController
        }
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.