Extrude building footprints based on real world heights
Note: Support for 3D on mobile devices may vary, view the system requirements for more information.
This sample demonstrates how to extrude building footprints (polygon features) in 3D based on a real-world height stored in an attribute field. In some cases users only want to know where features are located, such as project areas, roads, buildings, etc. The data may be stored in a single layer where all features must be visualizaed with the same symbol or as unique types.
In this case, we'll use a UniqueValueRenderer to shade each feature based on it's building type. We'll also use visual variables to extrude each feature based on a numeric attribute.
Prior to completing the following steps, you should be familiar with views, Map, and FeatureLayer. If necessary, complete the following tutorials first:
The basic components of this app, such as creating instances of the Map and MapView classes and understanding HTML and CSS structure will not be reviewed. See the tutorials listed above if you need to familiarize yourself with those components in this application. As a general rule the introductory principles discussed in the tutorials above apply to most samples in the documentation.
1. Create a symbol for each type
While all symbol types are supported in 3D SceneViews, it is recommended to only use 3D symbols when working in SceneViews.
Because features in the building footprints layer are polygons, we need to create a PolygonSymbol3D for each type of building that will have a different color. PolygonSymbol3D along with all other 3D symbols is a container that holds one or more symbol layers. It is the Symbol3DLayer classes that define the color and size of 3D symbols.
In this case we need to add an ExtrudeSymbol3DLayer to the PolygonSymbol3D so that we can extrude the polygons from the surface. To better distinguish the 3D shape of the extrusion we set the edges property on ExtrudeSymbol3DLayer, to render the contour edges.
To read more in depth about 3D symbols and their relationship to symbol layers, see the documentation for Symbol3D, Symbol3DLayer, and their subclasses. An example is provided below.
// 3D polygon symbol for residential buildings
var resSym = {
type: "polygon-3d", // autocasts as new PolygonSymbol3D()
// add an ExtrudeSymbol3DLayer to the symbolLayers array and set the color
symbolLayers: [{
type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()
material: {
color: "#FC921F" // orange
},
edges: { // add edges of type solid
type: "solid",
color: "#AF6515" // dark orange
}
}]
};
// 3D polygon symbol for condos
var condoSym = {
type: "polygon-3d", // autocasts as new PolygonSymbol3D()
// add an ExtrudeSymbol3DLayer to the symbolLayers array and set the color
symbolLayers: [{
type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()
material: {
color: "#9E559C" // purple
},
edges: {
type: "solid", // add edges of type solid
color: "#60345F" // dark purple
}
}]
};
2. Create an instance of UniqueValueRenderer
We must use a UniqueValueRenderer when defining how features should be visualized based on field values. Up to three fields may be used to create various combinations of types. In this case we're shading features with different colors based on one field: DESCLU
.
var renderer = {
type: "unique-value", // autocasts as new UniqueValueRenderer()
// the default symbol indidates all other building types
defaultSymbol: {
type: "polygon-3d", // autocasts as new PolygonSymbol3D()
symbolLayers: [{
type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()
material: {
color: "#A7C636" // green
},
edges: {
type: "solid", // add edges of type solid
color: "#56661C" // dark green
}
}]
},
defaultLabel: "Other",
field: "DESCLU" // building type
};
3. Match unique values with each symbol
You can match symbols with unique field values in one of two ways: Using uniqueValueInfos in the constructor...
var renderer = {
type: "unique-value", // autocasts as new UniqueValueRenderer()
// the default symbol indidates all other building types
defaultSymbol: {
type: "polygon-3d", // autocasts as new PolygonSymbol3D()
symbolLayers: [{
type: "extrude", // autocasts as new ExtrudeSymbol3DLayer()
material: {
color: "#A7C636" // green
}
}]
},
defaultLabel: "Other",
field: "DESCLU",
// match symbols to unique values here
uniqueValueInfos: [{
value: "Residential",
symbol: resSym,
label: "Residential"
}, {
value: "Residential Condominium",
symbol: condoSym,
label: "Condominium"
}]
};
Or with the addUniqueValueInfo() method.
hwyRenderer.addUniqueValueInfo("Residential", resSym);
4. Add a size visual variable to extrude real-world heights
Finally, to extrude the real-world heights of each building, we'll add a size visual variable to the visualVariables array in the renderer. This requires only three properties: the type
, field
name, and valueUnit
if the extrusion value is in any unit other than meters. Since values were measured in feet, we must indicate that in the variable.
var renderer = {
type: "unique-value", // autocasts as new UniqueValueRenderer()
// set properties from previous steps here
// define size visual variable based on heigh values in a field
visualVariables: [{
type: "size",
field: "ELEVATION",
valueUnit: "feet" // converts and extrudes all data values in feet
}]
};
5. Summary
Once the renderer is defined, you can set it on the layer and the view will automatically update. Click the sandbox button below to see the full code of this app.
6. Additional visualization tutorials and samples
- Scale feature sizes based on real world sizes (2D)
- Visualize features with realistic 3D symbols
- Visualize data with rotation
- Visualize features by type
- Data-driven continuous color
- Data-driven continuous size
- ArcGIS blog - Using attributes to represent real-world sizes of features