Symbols define all the non-geographic aspects of a graphic or feature's appearance, including color, size, border, and transparency. You can apply a symbol directly to individual graphics when you create them. You can also use symbols to create a renderer for graphics overlays or feature layers.
With a renderer, you can:
- Use one symbol for all features in a layer (or all graphics in an overlay), regardless of attribute values
- Symbolize features in a layer (or graphics in an overlay) differently based on one or more of their attribute values
The only way to set symbols on features is to use a renderer.
Remember that a symbol is not the thing being represented on the map. Instead, it controls how those things (graphics or features) display. The relationship is similar, for example, between the words you are reading now (the content) and the font that is used to display them (presentation). Changing the font style, size, and color will not change the meaning of the text, but is likely to have an impact on the effectiveness of the presentation. Likewise, the quality of a map's presentation can improve with the proper use of symbols to convey information.
Each symbol type can be used to symbolize specific geometry type(s). Whether you're applying a symbol directly to a graphic or using a symbol to create a renderer, ensure the geometry type of the graphic or feature being symbolized is compatible with the symbol you want to use.
ArcGIS Runtime uses two different symbol models depending on the data source and how you access that data source.
The simple symbol classes follow the web map specification. You access these symbols through the simple symbology API, or get these symbols from web maps and feature services when advanced symbology is turned off.
Advanced symbols, accessed through multilayer symbol classes, follow the ArcGIS Pro symbol model. These symbols come from feature services, mobile style files, the dictionary renderer, and mobile map packages.
Simple (web) symbols
The following is a table of the symbols available in the API with the compatible geometry types and a brief description:
Symbolizes points or multipoints with basic shapes.
Symbolizes points or multipoints with images.
Symbolizes polylines with pre-defined styles.
Fills polygons or envelopes with a color and pre-defined styles.
point, multipoint, polyline, polygon
Depending on the type of geometry you want to symbolize, you'll have different options available for defining your symbol. Points, lines, and polygons all have a basic symbol you can use: SimpleMarkerSymbol, SimpleLineSymbol, and SimpleFillSymbol respectively. You can also symbolize points using a PictureMarkerSymbol.
All marker symbols provide the ability to set an angle for rotating the symbol. This might be useful for showing things like direction (for wind measurements or moving vehicles, for example). In addition, marker symbols have an angle alignment property that specifies whether your marker symbol remains screen-aligned or map-aligned when the map rotates. The default for all marker symbols is screen-aligned, meaning that the symbol will not rotate with the map. Setting the angle alignment property to map-aligned, the symbol will rotate with the map. This is important in cases where the symbol's angle indicates a direction on the map. You may also have the ability to define an x or y offset, meaning the symbol displays at a specified distance from the location of the feature it represents. This can be especially useful when working with text.
The simple symbol types (SimpleMarkerSymbol, SimpleLineSymbol, and SimpleFillSymbol) give you the ability to quickly create a symbol by choosing a style (for example solid or cross hatched fill for polygons; solid or dashed line for polylines; square or circle marker for points), setting a color, and defining a size (for markers) or width (for lines). For markers and fills, you can also define an outline symbol (using a line symbol).
Picture symbols, such as PictureMarkerSymbol, allow you to use an image to symbolize a feature. The image may be stored locally, or come from an online source. The size of the image can be specified in your platforms device independent units in the same way as your other application resources.
Picture marker symbols can be created from an image on disk, such as a JPEG file, or from the URL to an image on a remote machine accessible without security. Remote images are downloaded once per application and cached for future use; for this reason they are loadable resources.
There are various ways to create picture marker symbols. For example:
You can create a picture marker symbol from a URL:
const QUrl pictureMarkerSymbolUrl("http://static.arcgis.com/images/Symbols/Basic/YellowStickpin.png");
PictureMarkerSymbol* pictureMarkerSymbol = new PictureMarkerSymbol(pictureMarkerSymbolUrl, this);
You can create a picture marker symbol from a QImage:
QImage image(filePath); // Full path to image file
PictureMarkerSymbol* picMarkSymb = new PictureMarkerSymbol(image, this);
Multilayer (advanced) symbols
Multilayer symbols are based on a subset of ArcGIS Pro's symbology model. These symbols have multiple layers and can contain different symbol types within each layer with definable behaviors to get advances cartographic effects. You can use ArcGIS Pro to author these complex symbol types and share them through feature services using the Use Advanced Symbology property, which by default is set to true. Multilayer symbols are also used in mobile map packages, mobile style files, and the dictionary renderer.
The MultilayerSymbol base class lets you get and set the color of your symbol. How the color value is returned or applied depends on how the symbol was authored.
The MultilayerPointSymbol class allows you to change the angle of the symbol and the angle alignment. Setting the angle will affect all symbol layers, but the resulting rotation will depend on how the symbol was authored. The default value for the angle alignment property also depends on how the symbol was authored, but can be changed.
The MultilayerPointSymbol class has a size property, and MultilayerLineSymbol has a width property. Changing these will affect all layers of the symbol proportionally.
Applying a symbol to a graphic
Graphics are in-memory features that provide a basic way to display geometry on the map. Graphics are unique in that they can be symbolized using a renderer for the overlay that contains them (described later in this topic) or by applying a symbol directly to the graphic. For a description of how to work with graphics, see Add graphics and text to graphics overlays.
The following example creates and applies a text symbol and a point to a graphic:
TextSymbol* textSymbol = new TextSymbol("Redlands", QColor(Qt::black), 12.0, HorizontalAlignment::Right, VerticalAlignment::Middle, this);
Graphic* graphic = new Graphic(point, textSymbol, this);
A symbol applied directly to the graphic overrides any symbols applied through the layer's renderer.
Working with simple and multilayer symbols
Simple symbology is the symbology of the web map. When authoring maps in ArcGIS Pro as web maps, it is important to note that your symbols will be converted to simple symbols. In general, point symbols are converted to picture marker symbols optimized for the web, and line and polygon symbols will be simplified while representing the original symbol as closely as possible.
If your app works primarily with web maps that you want to look the same throughout the platform, then your app should use the simple symbols API. If you use multilayer symbols and try to save your map as a web map, the save will fail, and forcing it to be saved will drop the symbols.
If your maps are used only with ArcGIS Runtime and ArcGIS Pro, then you can use multilayer symbols. Multilayer (advanced) symbols are vectorized in these environments, thereby scaling better on devices with high resolution screens.
As the name implies, a renderer is an object that determines how features or graphics in a layer should be rendered (drawn) on the display. The renderer then draws them using symbols. A renderer includes logic for applying the appropriate symbol to each feature in a layer or each graphic in an overlay. There are a variety of renderer types, each designed to use a different rendering logic. Most renderers use attribute values to determine which symbol should be applied.
In a typical workflow, renderers are used to symbolize features in a feature layer, where the features are all of same geometry type. It's up to you to create a renderer with symbols that can be applied to the geometry type of the layer (as listed the table above). A renderer can also be applied to a graphics overlay, but should not be used for an overlay that has graphics of mixed geometry types. For such a scenario, applying a symbol to each graphic as it's created is the preferred workflow.
There are several types of renderers you can create using the Runtime API including simple renderers and unique value renderers. Each is described below.
A simple renderer uses one symbol for all features in a layer (or all graphics in an overlay) regardless of attribute values.
The following code snippet shows how to create a simple renderer for a graphics overlay containing only points using a simple marker symbol:
SimpleMarkerSymbol* simpleMarker = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, QColor(Qt::blue), 16.0, this);
SimpleRenderer* simpleRenderer = new SimpleRenderer(simpleMarker, this);
GraphicsOverlay* graphicsOverlay = new GraphicsOverlay(this);
Unique value renderer
A unique value renderer symbolizes features in a layer (or graphics in an overlay) differently based one or more of their attribute values. It's particularly useful when symbolizing features based on an attribute whose values represent names or categories, usually referred to as nominal data. Unlike graphics, features do not have a symbol property and therefore cannot be assigned an individual symbol. However, you can use a unique value renderer to set symbology on a layer based on each feature's attribute values. (You can do this for graphics, too.)
ArcGIS map services allow up to three fields to be used for unique value renderers. An ArcGIS feature service allows only one. As a developer, you can specify as many fields as you like, ensuring that the order of the fields you specify corresponds to the order of the values you specify.
When applying a renderer that uses attribute values on a feature layer which is bound to a service feature table, you must ensure the required fields are specified in the tables outfields. When instantiating a service feature table in code, by default only the minimum set of fields required to render the features are requested (object id, geometry and renderer fields). When loading service feature tables from a map, by default all fields are requested. Be sure to override these defaults by setting the outfields before the table is loaded.
// Create the unique values for the different cities in California
UniqueValue* uniqueValue1 = new UniqueValue("Los Angeles", "The City of Los Angeles", QVariantList() << "Los Angeles", new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Triangle, QColor(Qt::green), 4.0, this), this);
UniqueValue* uniqueValue2 = new UniqueValue("San Francisco", "The City of San Francisco", QVariantList() << "San Francisco", new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Circle, QColor(Qt::red), 5.0, this), this);
UniqueValue* uniqueValue3 = new UniqueValue("San Diego", "The City of San Diego", QVariantList() << "San Diego", new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Cross, QColor(Qt::blue), 8.0, this), this);
UniqueValue* uniqueValue4 = new UniqueValue("San Jose", "The City of San Jose", QVariantList() << "San Jose", new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Diamond, QColor(Qt::yellow), 2.0, this), this);
// Add the unique values to the renderer
UniqueValueRenderer* uniqueRenderer = new UniqueValueRenderer("Unknown city", new SimpleMarkerSymbol(this), QStringList() << "CityName", QList<UniqueValue*>() << uniqueValue1 << uniqueValue2 << uniqueValue3 << uniqueValue4, this);
// Create a feature layer and apply the renderer to the layer
ServiceFeatureTable* featureTable = new ServiceFeatureTable(serviceUrl, this);
FeatureLayer* featureLayer = new FeatureLayer(featureTable, this);
Features whose attribute value falls outside the classes defined for the renderer are symbolized with the default symbol. If a default symbol is not defined, those features won't display.