Circular buffer zones around points in Icon Map: why you’d use them and how to implement them

Power BI maps often start as “pins on a map”. Useful, but limited. The moment you need to answer proximity questions such as “What’s within 5 km of this site?” or “Which customers fall inside our service coverage?”, you need a buffer.

In both Icon Map visuals, a practical way to create circular buffer zones around point locations is to render distance-based circles using real-world units. That gives you fast, interactive proximity analysis in Power BI, directly inside the report experience.

What a circular buffer zone is (and what it isn’t)

A circular buffer is an area drawn at a set distance from a point. In GIS terms it’s a zone of influence: everything inside the circle is “within X distance”.

  • It is a straight-line distance (“as the crow flies”).
  • It isn’t a drive-time or walk-time area. If you need travel-time isochrones, you’re solving a different problem.

That distinction matters because circular buffers are quick and clear, but they are not constrained by road networks, rivers, or access restrictions.

Why use circular buffers in Power BI reports?

Buffers help you move from “where things are” to “what this means”. Key reasons for using circular buffers include:

  • Proximity Analysis and Risk Management: Identifying all features within a certain distance, such as determining homes affected by flood zones, noise pollution, or zoning restrictions e.g. alcohol sales within X distance of a school).
  • Catchment Area Definition: Defining "as-the-crow-flies" service areas, such as a 5-minute walk radius around a public transport stop, assuming unobstructed access.
  • Environmental and Urban Studies: Measuring land use, green space access, or urban density around specific points of interest or individual addresses.
  • Flexibility in Visualization: They allow for multiple-ring buffers, enabling multi-level analysis of data e.g. 100m, 200m, 300m zones.
  • Performance: They are less complex to generate and computationally more efficient compared to complex network analysis, making them suitable for initial, rapid assessments.

While easy to generate, they should be used when direct, striaght-line distance is more important than actual travel time or path.

How Icon Map represents buffers: circles as distance-based zones

Icon Map Pro and Slicer includes a Circles data layer that can be driven from your model: you supply point coordinates and a numeric size, and the visual draws circles for you.

For circular buffer zones, the key is Size behaviour. Icon Map Pro supports three behaviours:

  • Relative (scaled between min and max size)
  • Size in pixels (stays visually consistent as you zoom)
  • Size in metres (stays consistent on the ground as you zoom)

To make a circle behave like a real buffer zone, use Size in metres.

In Icon Map Pro there is a setting called Rendering that turns WebGL Rendering Mode on or off. More information about this can be found in this blog article https://icon-map.com/blog/webgl-rendering-mode.html

If WebGL Rendering is turned off then the circle size in metres refers to the radius of the circle, whereas when WebGL Rendering is turned on the circle size refers to the diameter of the circle so it is important to know if this setting is turned on or off, when using the 'Size in metres' setting.

Implementation options: build a radius buffer around points

Assuming you already have a series of locations ( sites, stores, assets, customers etc. ) with longitude and latitude and you want to display 1 or more buffer zones around each point in Icon Map visuals then we have explained 3 options you can use to implement this.

For all 3 patterns, each location and associated buffer zones that are to be included on the same map, need to be separate rows of data in your data table.

In the downloadable PBIX file there are 2 locations: a centre point in both Oxford and London and 4 different buffer zones ( 5 km, 10 km, 15 km and 20 km ) so 10 rows of data in each data table.

Web GL Rendering is turned off in the Icon Map Pro visual in the downloadable PBIX so each buffer distance represents the straight line distance from each location to the circle edge on all 3 pages of the PBIX.

1. Locations and Buffer Zones as circles with different circle sizes

The locations and the buffer zones are represented by circles with different circle sizes on the map, depending on the circle size field in the data table.

This option is ideal when the circle size for each location is the same size, i.e. there is no requirement for the location size to be relative to the other locations. To make it easier to identify the locations, the circle fill colour fx option is used to specify 1 colour for locations and another colour for the buffer zones. The fill transparency fx option is used to increase the transparency for the larger circles on the map. This is key to avoid a solid blob of colour for the circles on the map.

2. Locations as images and Buffer Zones as circles with different circle sizes

The locations are represented as images and the buffer zones are represented by circles with different circle sizes on the map, depending on the circle size field in the data table.

This implementation would be useful when a clear distinction is required between locations and buffer zones. The location image is a DAX measure that contains SVG code to display a 'location pin'.

SVG_LocationPin = 
VAR _teardropcolour = "rgb(255,0,0)"
VAR _basecolour = "rgb(0,0,0)"

VAR _teardropformat =
    " fill='" & _teardropcolour & "' stroke='none' opacity='1'/>"

VAR _baseformat =
    " fill='" & _basecolour & "' stroke='none' opacity='1'/>"

VAR _teardropshape =
    "<path d='M 45 0 C 27.395 0 13.123 14.272 13.123 31.877 c 0 7.86 2.858 15.043 7.573 20.6 L 45 81.101 l 24.304 -28.624 c 4.716 -5.558 7.573 -12.741 7.573 -20.6 C 76.877 14.272 62.605 0 45 0 z M 45 43.889 c -7.24 0 -13.11 -5.869 -13.11 -13.11 c 0 -7.24 5.869 -13.11 13.11 -13.11 s 13.11 5.869 13.11 13.11 C 58.11 38.02 52.24 43.889 45 43.889 z'"

VAR _baseshape =
    "<path d='M 58.958 71.559 L 45 82.839 L 31.057 71.556 c -9.329 1.65 -15.682 4.901 -15.682 8.645 c 0 5.412 13.263 9.8 29.625 9.8 c 16.361 0 29.625 -4.388 29.625 -9.8 C 74.625 76.458 68.278 73.209 58.958 71.559 z'"

VAR _svgimage =
        "data:image/svg+xml;utf8," &
        "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 90 120'>" &
        _teardropshape &
        _teardropformat &
        _baseshape &
        _baseformat &
        "</svg>"
VAR result = _svgimage
RETURN
    result

The circle fill colour is used to specify the colour for the buffer zones. The fill transparency fx option is used to increase the transparency for the larger circles on the map, based on the FillTransparency field in the data table.

3. Locations as relative size circles and Buffer Zones as circles in metres

The locations are represented as circles, where the size changes relative to each other in the map. The buffer zones are represented by circles with different circle sizes in metres on the map.

This option would be useful when there is a requirement for the location circles to change size, relative to each other based on a particular metric in the Power BI report.

Both Icon Map visuals allow you to combine multiple layers in the same map and this is what makes this option possible.

https://icon-map.com/documentation/pro/data/combining/

The 'Locations' are configured as a 'Circle' data layer, while the 'Buffer Zones' are configured as a 'WKT / GeoJSON from data' data layer.

For each Location, the WKT polygons for each Buffer Zone are computed using a function in Power Query.

// Returns a WKT POLYGON approximating a circular buffer around a WGS84 lat/lon point.
// lat, lon in decimal degrees; radiusMeters in metres; steps is number of polygon vertices (e.g. 1000).
let
    Source = (lat as number, lon as number, radiusMeters as number, optional steps as nullable number) as text =>
let
    N = if steps = null then 1000 else steps,
    R = 6378137.0, // Earth radius in meters (WGS84 spheroid approx)
    latRad = lat * Number.PI / 180,
    lonRad = lon * Number.PI / 180,
    angDist = radiusMeters / R,

    // Build list of points around the circle (0..N), include last = first to close polygon
    idx = {0..N},
    pts =
        List.Transform(
            idx,
            (i) =>
            let
                bearing = 2 * Number.PI * i / N,
                lat2 = Number.Asin(Number.Sin(latRad) * Number.Cos(angDist) + Number.Cos(latRad) * Number.Sin(angDist) * Number.Cos(bearing)),
                lon2 = lonRad + Number.Atan2(Number.Sin(bearing) * Number.Sin(angDist) * Number.Cos(latRad),
                                              Number.Cos(angDist) - Number.Sin(latRad) * Number.Sin(lat2)),
                lat2Deg = lat2 * 180 / Number.PI,
                lon2Deg = lon2 * 180 / Number.PI,

                // Normalize lon to [-180, 180]
                lonNorm = Number.Mod(lon2Deg + 540, 360) - 180,

                // WKT uses "X Y" = "lon lat"
                pair = Text.Format("#{0} #{1}", { Number.ToText(lonNorm, "0.##########"), Number.ToText(lat2Deg, "0.##########") })
            in
                pair
        ),

    ring = Text.Combine(pts, ", "),
    wkt = "POLYGON((" & ring & "))"
in
    wkt
in
    Source

The circle fill colour is used to specify the colour for the locations. The WKT / GeoJSON formatting options are used to format the buffer zones, in a similar manner to the above 2 options.

Recommendations

  • Validate with a known distance. Pick a location where you can sanity-check the distance used (for example, a 1 km circle around a point and compare it to a familiar landmark distance).
  • Radius vs diameter: remember “Size in metres” is either diameter or radius depending on whether Web GL Rendering mode is turned on or not
  • Don’t oversell straight-line distance: for travel-time questions, label your buffers clearly (for example “5 km radius”).
  • Dense maps can get noisy: use transparency, zoom thresholds, and filtering to keep the map readable.
  • User Display Controls: allow users to control what is displayed on the map via slicers or what if parameters