Skip to Content
AdvancedFiltering Data

MapsGL Android - Filtering Data

When working with data on your map, you may want to filter the data to only show relevant information for your particular use case. There are different ways to filter data in MapsGL depending on the type of data you are working with.

Filtering Raster Data

When working with raster data, only layers associated with encoded raster data sources can be filtered.

To filter encoded raster data, set the drawRange on the layer’s sample paint. Only values inside the range are drawn. The values must be in the same units as the data source.

Filtering Raster Weather Data

To filter a built-in weather layer, set drawRange on the layer’s paint before you add the layer to the map.

For example, to show only temperatures between 50°F and 80°F, convert the range to degrees Celsius, the units temperature data is stored in. FtoC from com.xweather.mapsgl.utils does the conversion:

import com.xweather.mapsgl.style.SampleLayerPaint import com.xweather.mapsgl.utils.FtoC import com.xweather.mapsgl.weather.WeatherLayerConfiguration import com.xweather.mapsgl.weather.WeatherService val config = WeatherService.Temperatures(controller.service) as WeatherLayerConfiguration<*, *> val paint = config.layer.paint as SampleLayerPaint paint.sample.drawRange = FtoC(50.0)..FtoC(80.0) controller.addWeatherLayer(config)

Only temperatures between 10°C and 26.67°C are drawn.

To limit only one end, use BoundedRange. The open end is filled in from the data source’s own range. To show only temperatures above 80°F:

import com.xweather.mapsgl.types.math_type.BoundedRange paint.sample.drawRange = BoundedRange.atLeast(FtoC(80.0))

Similarly, to show temperatures below 50°F:

paint.sample.drawRange = BoundedRange.atMost(FtoC(50.0))

On a sample layer such as temperatures, drawRange is read when the layer is added. To change it, remove the layer and add it again with the new range.

The same filtering works for other layers on encoded raster data sources, such as the wind-particles layer. Wind speed is stored in meters per second (m/s), so convert the drawRange values with mphToMs. Particles slower or faster than the range are not drawn:

import com.xweather.mapsgl.style.ParticleLayerPaint import com.xweather.mapsgl.utils.mphToMs val config = WeatherService.WindParticles(controller.service) as WeatherLayerConfiguration<*, *> (config.layer.paint as ParticleLayerPaint).sample.drawRange = BoundedRange.atLeast(mphToMs(20.0)) controller.addWeatherLayer(config)

A particle layer’s draw range can also be changed after the layer is on the map, with setPaintProperty:

controller.setPaintProperty(layerId, "sample.drawRange.min", mphToMs(30.0))

Filtering Vector Data

Vector data, which includes data from GeoJSON or vector tile sources, can be filtered with the filter property on a layer descriptor. A filter is an Expression that is evaluated for each feature, and only features for which it is true are drawn. Filters compare a feature’s properties with values using the decision and comparison expressions.

To filter data, you need to know the properties of the features you are working with.

For example, if you set up a data source of cities from Natural Earth  and want to show only cities with a population greater than 1 million, you need the name of the property that stores population. Each Natural Earth city feature stores it in POP_MAX:

{ "type": "Feature", "properties": { "SCALERANK": 1, "LABELRANK": 1, "FEATURECLA": "Populated place", "NAME": "Houston", "SOV0NAME": "United States", "SOV_A3": "USA", "ADM0NAME": "United States of America", "ADM0_A3": "USA", "ADM1NAME": "Texas", "ISO_A2": "US", "LATITUDE": 29.82192, "LONGITUDE": -95.341925, "POP_MAX": 4459000, "POP_MIN": 3647574, "POP_OTHER": 3607616, "RANK_MAX": 12, "RANK_MIN": 12 }, "geometry": { "type": "Point", "coordinates": [ -95.348436, 29.741273 ] } }

Then use a “greater than” expression as the layer’s filter:

import androidx.compose.ui.graphics.Color import com.xweather.mapsgl.layers.spec.CircleLayerDescriptor import com.xweather.mapsgl.style.CircleLayerPaint import com.xweather.mapsgl.style.CirclePaint import com.xweather.mapsgl.style.Expression import com.xweather.mapsgl.style.FillPaint import com.xweather.mapsgl.style.StyleValue controller.addLayer( CircleLayerDescriptor( id = "cities", source = "cities", paint = CircleLayerPaint( fill = FillPaint(color = StyleValue.Constant(Color(0xFF4E00C1))), circle = CirclePaint(radius = StyleValue.Constant(6.0)), ), filter = Expression.greaterThan(Expression.get("POP_MAX"), 1_000_000), ), beforeID = null, )

You can also combine expressions to build more complex filters.

For example, suppose you have added a vector tile source of OpenStreetMap road data and want a layer that shows only major bridges. This filter uses Expression.and to require that a road’s brunnel property equals bridge and its class property is one of motorway, trunk, or primary. Expression.contains checks a property against a list of values:

import com.xweather.mapsgl.layers.spec.LineLayerDescriptor import com.xweather.mapsgl.style.LineLayerPaint import com.xweather.mapsgl.style.StrokePaint controller.addLayer( LineLayerDescriptor( id = "bridges", source = "roads", sourceLayer = "transportation", paint = LineLayerPaint( stroke = StrokePaint( color = StyleValue.Constant(Color(0xFFFF0000)), thickness = StyleValue.Constant(2.0), ), ), filter = Expression.and( listOf( Expression.equals(Expression.get("brunnel"), "bridge"), Expression.contains(Expression.get("class"), listOf("motorway", "trunk", "primary")), ), ), ), beforeID = null, )

A filter can compare a feature’s time with the timeline position using Expression.mapTime, so features appear as the timeline moves. See Using Map Time. Filters can’t use the map’s zoom level. To vary a layer by zoom, use a zoom expression in its paint instead.

Filtering Vector Weather Data

Built-in vector weather layers are filtered with the same expressions. Set the filter on the layer configuration before you add the layer.

For example, to show only wind reports on the stormreports layer:

val config = WeatherService.Stormreports(controller.service) config.layer.filter = Expression.equals(Expression.get("report.cat"), "wind") controller.addWeatherLayer(config)

Filtering weather alerts by category is another common use. On the alerts layer, you can filter on each alert’s VTEC code. To show only severe thunderstorm warnings:

val config = WeatherService.Alerts(controller.service) config.layer.filter = Expression.equals(Expression.get("VTEC"), "SV.W") controller.addWeatherLayer(config)

Use Expression.contains to match several VTEC codes, such as a “severe” category with severe thunderstorm and tornado watches and warnings:

config.layer.filter = Expression.contains(Expression.get("VTEC"), listOf("SV.A", "SV.W", "TO.A", "TO.W"))

Changing a Filter at Runtime

To change the filter of a layer that is already on the map, use MapController.setLayerFilter. Pass null to draw every feature again:

controller.setLayerFilter(layerId, Expression.contains(Expression.get("VTEC"), listOf("FW.A", "FW.W"))) controller.setLayerFilter(layerId, null)

Use setLayerFilter rather than assigning filter on a layer that is already on the map. It rebuilds the layer’s geometry for the new filter and redraws the map.

© 2026 Xweather (opens in a new tab)Terms of Service (opens in a new tab)Privacy Policy (opens in a new tab)