Skip to main content

Working with shapes from databases

Icon Map Pro provides the ability to display shapes that are stored, or referenced via the Power BI semantic model. These shapes are stored either as WKT (Well-known Text) or GeoJSON features. Many popular databases provide the ability to store shapes using the native 'Geography' or 'Geometry' data types, which are then surfaced in Power BI as WKT or geoJSON. Examples of databases providing this capability include, SQL Server, Azure SQL, Fabric SQL, Fabric Warehouse (stored in text fields), Oracle, KustoDB / Eventhouse (stored in text fields), PostgreSQL, Snowflake etc.

Benefits of using shapes from data

There are a number of reasons why you might want to source your shapes from data:

Single source of the truth

Your organization may provide a single repository for geospatial boundaries, such as assets, sales areas etc. Using this single source then ensures that all geospatial visualizations are using the same set of shapes.

Performance

When using shapes from sources such as uploaded files, it's necessary to relate the shapes in the file to the Power BI data using the Feature Reference field. This process has a performance overhead. When using shapes provided as part of the Power BI dataset, this mapping process isn't required, as the shapes are included in the dataset itself.

Changes over time

Some assets are not static. Their shape, position or composition may change over time. By loading the shapes from source data, the Power BI report will always show the latest version of these shapes, as the Power BI dataset is refreshed, or in near-realtime when using a direct query connection.

Challenges using shapes from data

Power BI truncates data to 32766 characters

As some shapes may be large and complex containing many points, this can result in WKT or GeoJSON text that has a large number of characters. Power BI on the other hand can only store text in a single column up to 32766 characters. This can result in your shapes being truncated and no longer valid WKT or GeoJSON, resulting in them not displaying on the map. There are a number of approaches to tackling this that are described later in this page.

Nuances of different databases

Different databases may surface geospatial data in different ways. For example, when including a field of type geography in SQL Server, Power BI automatically represents this field as Well-Known Text, whilst when using PostgreSQL, it is necessary to use the ST_AsText() function to manually convert the WKB data to WKT.

Approaches for exceeding Power BI's character limit

There are a few main approaches for dealing with the 32766 character limit, which can be used independently or together:

  • Reduce the complexity of the shapes before loading them in Power BI
  • Reduce the number of decimal places used to store coordinates
  • Split the shapes into multiple rows and columns as they're being loaded into Power BI, then use DAX to join them back together

This section looks in detail at these different approaches.

Reduce the complexity of the shapes

If your loading in the shapes using Power Query from a static file, then you will need to use an external tool such as QGIS or mapshaper.org to simplify the shapes before selecting them as a source in Power BI. However if you're using a database as the source, you may be able to use the spatial functions provided by the database engine to simplify the shapes. This could be done as a query (SELECT statement), a view or a function that returns a table, depending on the type of system you're connecting to.

The commands and syntax for differs between providers.

SQL Server provides the Reduce function to simplify shapes. Eg:

SELECT shape_name, wkb_geometry.MakeValid().Reduce(100) AS geom

A recursive query can be created that will iteratively reduce the complexity of shapes until they are under Power BI's limit. The following example assumes three fields:

shape_code (a reference for the shape), shape_name (name of the shape), wkb_geometry (the shape as a geography data type)

WITH GeometryReduction AS (
-- Anchor member
SELECT
shape_name,
shape_code,
wkb_geometry.MakeValid() AS geom,
CAST(0.0 AS FLOAT) AS tolerance,
LEN(wkb_geometry.MakeValid().STAsText()) AS length
FROM shapes

UNION ALL

-- Recursive member
SELECT
shape_name,
shape_code,
geom.Reduce(CAST(tolerance + 100.0 AS FLOAT)) AS geom,
CAST(tolerance + 100.0 AS FLOAT) AS tolerance,
LEN(geom.Reduce(CAST(tolerance + 100.0 AS FLOAT)).STAsText()) AS length
FROM GeometryReduction
WHERE length > 32766 AND tolerance < 10000 -- safeguard
)

SELECT
shape_name,
shape_code,
geom.STAsText() AS reduced_text
FROM (
SELECT
shape_name,
shape_code,
geom,
ROW_NUMBER() OVER (PARTITION BY shape_code ORDER BY tolerance ASC) AS rn
FROM GeometryReduction
WHERE length <= 32766
) AS FinalReduced
WHERE rn = 1;

The result of running this query will be the shape_name, shape_code and reduced_text (the shape in WKT format simplified to under 32766 characters)

Reduce the number of decimal places

Many geospatial servers store coordinates with a large number of decimal places. Whilst this results in highly accurate coordinates, it can also result in a coordinates taking up much more space than necessary for most Power BI maps.

Unfortunately SQL Server / Azure SQL / Fabric SQL and Oracle don't provide a built-in spatial function for achieving this.

However in PostgreSQL, the ST_SnapToGrid function can be used:

SELECT 
shape_name,
ST_AsText(ST_SnapToGrid(geom, 0.001)) as geom
FROM shapes;

Split the shapes into multiple columns / rows

Whilst Power BI can only store text up to 32766 characters, in DAX it is possible represent up to around 2 million characters in a measure. Therefore, it is possible to split the shape upon loading it into Power BI, then use DAX to join the shape back together again, before being passed into Icon Map Pro.

The following approaches split the shapes into multiple rows, then use the CONCATENATEX DAX function in a measure. The rows can be split using PowerQuery during the import, or beforehand in the originating database. It's recommended that this is used in conjunction with the other approaches to reduce the complexity of the shapes as too many large shapes may exceed memory or resource limits within Power BI.

Starting with the Shapes query:

alt text

ensure the wkb_geometry column is highlighted, then select "Split Column" then "By Number of Characters" from the "Transform" menu:

alt text

Enter 32000 as the number of characters, and select "Rows" in the Advanced options section:

alt text

This will split the wkb_geometry column into multiple rows for those items where the length was over 32000.

alt text

To ensure that the rows are combined in the correct order, we create an index column to use as the sort order later:

alt text

alt text

Then click the "Close and Apply" button to load the data.

Create the following measure:

alt text

Combined WKT =
CONCATENATEX ( Shapes, Shapes[geom], "", Shapes[chunk_order] )

Then in Icon Map Pro, use the shape_code or shape_name field for 'ID' and the 'Combined WKT' field for 'Image / WKT / GeoJSON'