Feature layer extrusion

View inJavaKotlin
View on GitHub
Sample viewer app

Extrude features based on their attributes.

Image of feature layer extrusion

Use case

Extrusion is the process of stretching a flat, 2D shape vertically to create a 3D object in a scene. For example, you can extrude building polygons by a height value to create three-dimensional building shapes.

How to use the sample

Tap the toggle to switch between using population density and total population for extrusion. Higher extrusion directly corresponds to higher attribute values.

How it works

  1. Create a ServiceFeatureTable from a URL.
  2. Create a feature layer from the service feature table.
    • Make sure to set the rendering mode to dynamic, statesFeatureLayer.renderingMode = RenderingMode.DYNAMIC.
  3. Apply a SimpleRenderer to the feature layer.
  4. Set the ExtrusionMode of the renderer with renderer.sceneProperties.extrusionMode = SceneProperties.ExtrusionMode.BASE_HEIGHT.
  5. Set the extrusion expression of the renderer with renderer.sceneProperties.extrusionExpression = "[POP2007]/ 10".

Relevant API

  • FeatureLayer
  • Renderer.SceneProperties
  • ServiceFeatureTable
  • SimpleRenderer

Tags

3D, extrude, extrusion, extrusion expression, height, renderer, scene

Sample Code

MainActivity.kt
Use dark colors for code blocksCopy
                                                                                                                                    
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* 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.
 *
 */

package com.esri.arcgisruntime.sample.featurelayerextrusion

import android.graphics.Color
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.data.ServiceFeatureTable
import com.esri.arcgisruntime.geometry.Point
import com.esri.arcgisruntime.geometry.SpatialReferences
import com.esri.arcgisruntime.layers.FeatureLayer
import com.esri.arcgisruntime.mapping.ArcGISScene
import com.esri.arcgisruntime.mapping.BasemapStyle
import com.esri.arcgisruntime.mapping.view.Camera
import com.esri.arcgisruntime.mapping.view.OrbitLocationCameraController
import com.esri.arcgisruntime.mapping.view.SceneView
import com.esri.arcgisruntime.symbology.Renderer
import com.esri.arcgisruntime.symbology.SimpleFillSymbol
import com.esri.arcgisruntime.symbology.SimpleLineSymbol
import com.esri.arcgisruntime.symbology.SimpleRenderer
import com.esri.arcgisruntime.sample.featurelayerextrusion.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    // set flag for showing total population or population density
    private var showTotalPopulation = true

    private val activityMainBinding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }

    private val sceneView: SceneView by lazy {
        activityMainBinding.sceneView
    }

    private val toggleButton: Button by lazy {
        activityMainBinding.toggleButton
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(activityMainBinding.root)

        // authentication with an API key or named user is required to access basemaps and other
        // location services
        ArcGISRuntimeEnvironment.setApiKey(BuildConfig.API_KEY)

        // get us census data as a service feature table
        val statesServiceFeatureTable =
            ServiceFeatureTable(resources.getString(R.string.us_census_feature_service))

        // add the service feature table to a feature layer
        val statesFeatureLayer = FeatureLayer(statesServiceFeatureTable)
        // set the feature layer to render dynamically to allow extrusion
        statesFeatureLayer.renderingMode = FeatureLayer.RenderingMode.DYNAMIC

        // create a scene and add it to the scene view
        val scene = ArcGISScene(BasemapStyle.ARCGIS_IMAGERY)
        sceneView.scene = scene

        // add the feature layer to the scene
        scene.operationalLayers.add(statesFeatureLayer)

        // define line and fill symbols for a simple renderer
        val lineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLACK, 1.0f)
        val fillSymbol = SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.BLUE, lineSymbol)
        val renderer = SimpleRenderer(fillSymbol)
        // set renderer extrusion mode to base height, which includes base height of each vertex in calculating z values
        renderer.sceneProperties.extrusionMode = Renderer.SceneProperties.ExtrusionMode.BASE_HEIGHT

        // set the simple renderer to the feature layer
        statesFeatureLayer.renderer = renderer

        // define a look at point for the camera at geographical center of the continental US
        val lookAtPoint = Point(-10974490.0, 4814376.0, 0.0, SpatialReferences.getWebMercator())
        // add a camera and set it to orbit the look at point
        val camera = Camera(lookAtPoint, 20000000.0, 0.0, 55.0, 0.0)
        val orbitCamera = OrbitLocationCameraController(lookAtPoint, 20000000.0)
        sceneView.cameraController = orbitCamera
        sceneView.setViewpointCamera(camera)

        // set button listener
        toggleButton.setOnClickListener {
            if (showTotalPopulation) {
                // divide total population by 10 to make data legible
                renderer.sceneProperties.extrusionExpression = "[POP2007] / 10"
                // change text of button to total pop
                toggleButton.text = resources.getString(R.string.total_pop)
                showTotalPopulation = false
            } else {
                // multiple population density by 5000 to make data legible
                renderer.sceneProperties.extrusionExpression = "[POP07_SQMI] * 5000"
                // change text of button to pop density
                toggleButton.text = resources.getString(R.string.density_pop)
                showTotalPopulation = true
            }
        }
        // click to set initial state
        toggleButton.performClick()
    }

    override fun onPause() {
        super.onPause()
        sceneView.pause()
    }

    override fun onResume() {
        super.onResume()
        sceneView.resume()
    }

    override fun onDestroy() {
        super.onDestroy()
        sceneView.dispose()
    }
}

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