Data Driven Styling (SDK version 2.1.0)

As of the release of the Deep Map™ SDK version 2.1.0, it is possible to assign data-driven values in Deep Map™ Style. This can be done in two different ways: either by data field properties or by property rules. This tutorial will give you an understanding of how to use data-driven styling, as well as when to use each method.

Data Field Properties

It is often the case that style properties should differ between two objects of the same featuretype. For example, the rotation of labels should ideally match the orientation of the underlying geometry. Assume that there are numerous labeled polygons of the type “room” in our map, and each label should have a different rotation. In this case, we could attach a tag to each object which contains the angle of the label. Let’s say the name of the tag is “label_rotation”, then we can assign its value to the property “label-rotate” by writing the tag’s name in curly brackets in the style definition:

feature room : polygon {
        /*
                other properties
        */
        label-rotate : {label_rotation};        //read label_rotation from tags and assign it to label-rotate
}

Other properties could be changed in the same way. The important thing to note is that the value of the tag is a string with the value, as specified in the style specifications. The value is ignored if it cannot be assigned to the property.

Property Rules

Property rules are very similar to data-field properties at first glance, but they behave very differently. A property rule is defined by assigning a rule query enclosed by [“ and “] . The rule query is essentially a SQL “SELECT” clause without the “SELECT” keyword, and the selected data field will be the value assigned to the property. A minimal query, which simply selects the data field “customColor” for the property fill-color would look like this:

feature room : polygon {
        fill-color: ["customColor"];  //evaluate customColor dynamically and set the value to fill-color
}

However, property rules are much more powerful than simply selecting a data field. The query can be as complex as you want, as long as the selected value is valid for the property. For example:

feature room : polygon {
        fill-color: ["CASE WHEN distance() < 100 THEN '#ff0000' ELSE '#00ff00' END"]; //makes room red if it is closer than 100m, otherwise it is green
}

Another notable difference between data field properties and property rules is the frequency of evaluation. A data-field is only evaluated once, when the object is loaded, whereas the property rules are executed very frequently. This distinction is important when changes in the data source should be shown. To see the data changes for data fields, it is necessary to call reloadStyle() after the change is made. The property rules are affected by this immediately and no reload is necessary. However, the constant evaluation of the property rules makes them less efficient than data field properties, so use them only when the queried data field changes frequently.

Usage

Data field properties should always be used when a data field is directly assigned to a property, and the data never changes during the runtime of the app. On the contrary, if the data field changes frequently, using a property rule will probably be more efficient. There is no fixed rule on when to use which one of the two approaches, but unless the data changes very often (in the range of seconds), the combination between data field properties and reloadStyle() is very likely to be faster. Profiling your app is key in this decision.

If the evaluation of a property is more complex than a simple assignment, then there is no way around the property rules. However, in many cases a normal rule might be more efficient, or there is a property that already handles this case. For example, setting the color of a selected polygon can be done in three different ways:

// Version 1: direct property
feature typeA : polygon {
        fill-color: #00ff00;
        fill-color-selected: #ff0000;
}

// Version 2: rule property
feature typeB : polygon {
        fill-color: ["CASE WHEN selected() THEN '#ff0000' ELSE '#00ff00' END"];
}

// Version 3: normal rule
feature typeC : polygon {
        fill-color: #00ff00;
}

rule selectTypeC(typeC) ["isSelected()"]
{
        fill-color: #ff0000;
}

Each version does the same task, but with different performance footprints. Version 1 is the fastest, because there is no rule evaluation involved and it is only triggered when an actual selection is done. Version 3 is the second fastest. Only the evaluation of the isSelection() function is required. Since it is known that the new fill-color is a valid field, it is set directly. Version 2 is the slowest variant, because like in version 3, it is necessary to execute the isSelected() function, but additionally the return value of the query has to be parsed and checked if it is valid.

When deciding between normal rules and property rules, the question is how many rules it takes to realize the property rule. If multiple rules are needed, then you should use a property rule. This is typically the case when there are multiple options for a single data field, or the value is even determined by the app. Also, property rules might be more convenient in some cases, and can be used if performance is not an issue.