Developers

Mapping complex data with multipart geometries using the ArcGIS Maps SDKs for Native Apps

Do you have an application that requires mapping of complex geometries and data, such as a network of interconnected pipes, complex railroad system, lakes within islands, or mapping multiple islands, but don’t know where to start? You’ve come to the right place. These types of complex geometries are termed multipart geometries, which is a collection of simpler geometries combined to form a more complex shape. 

In this blog, we will explore the concept of multipart geometries using the ArcGIS Maps SDKs for Native Apps and describe multipart geometry types, how to create them, their applications and the benefits of using them. The code snippets for this blog are written using the ArcGIS Maps SDK for Kotlin but all the concepts apply to the ArcGIS Maps SDKs for .NET, Qt, Java and Swift.

Let’s get started with some terminologies we will be using in this blog. 

Feature, Geometry and Hosted table 

The developer glossary defines features as a representation of a real-world object on a map. A feature will store its geographic representation, which could be a point, line, or polygon, that has both geometry (e.g. the length of the line or area of the polygon) and attribute data (e.g. the number of people, the temperature, ID number).  

Geometry refers to the spatial aspects of a feature. It is used to define the shape and position of the feature. 

An ArcGIS hosted table contains information about a set of geographic features. Each row represents a feature, and each column represents one feature attribute. 

Shown below is highlighted demographic data of USA states in a hosted table.

What are multipart geometries?  

Multipart geometries allow users to represent complex spatial features using simpler geometry types. These complex features can be composed of multiple points, lines or polygons that are combined to form a more complex shape. Multipart geometries are categorized as multipoints, multipart lines and multipart polygons, as seen in the image below.

As these geometries are composed of multiple simpler geometries grouped into one complex geometry, we can represent them as a single entry in a hosted table, rather than having multiple entries for each single geometry. 

Multipoint geometry 

Multipoint geometry is a type of geometry which represents features that consist of clusters of points, such as weather station networks, lidar point clusters, a collection of trees in a forest or a prairie dog underground den which has multiple entry and exit points. 

For example, the image below shows a collection of trees on the Esri Redlands campus. Each individual tree could be represented as a single point feature on a map, or since each tree is of the same species, each point could be represented in a multipoint geometry to represent the entire collection of trees on the campus.  

In this example, choosing a single multipoint geometry (uses a single row in the database) over many single point geometries (uses many rows) has many advantages. For example, it allows efficient management and analysis of the spatial data such as location and characteristics of individual trees on the campus. In addition, calculating the density of trees in different areas of the campus or determining the distance between trees, could be performed on multipoint geometry. Such analysis helps with the campus planning and development.  

Esri campus in Redlands, California

The code snippet below demonstrates creating a multipoint geometry using ArcGIS Maps SDK for Kotlin. It adds a collection of trees on the Esri campus in Redlands, California. Each individual tree is a point feature which is combined to form a multipoint geometry.

⊕ Show code …

// Create Multipoint geometry using collection of points 
// representing each individual tree
        val multipoint = Multipoint(
            listOf(
                Point(-13046198.211, 4036513.863),
                Point(-13046194.120, 4036524.953),
                Point(-13046188.702, 4036519.410),
                Point(-13046198.404, 4036504.248)
                ...
                ...
            ),
            SpatialReference.webMercator()
        )
        lifecycleScope.launch {
            // create a tree symbol
            val treeSymbol = createPinSymbol()
            // creates a graphic with the tree point and symbol
            val treeGraphic =
                Graphic(multipoint, treeSymbol)
            graphicsOverlay.graphics.add(treeGraphic)
        }
    }

View the complete code on GitHub.

Multipart line geometry
 

Multipart line geometry is a type of geometry that represents a set of two or more individual line features combined to form a more complex feature. It is used to represent linear features that cannot be shown as a single line feature. These individual line features can be disconnected, which means that they do not share endpoints with adjacent line features.  

An example of a multipart line geometry would be a braided river composed of multiple river channels that form part of the same river. Other examples include a complex railroad system or a pipeline network. 

Shown below is an aerial image of the Brahmaputra River, Bangladesh. There are many channels forming this river, and they share the same attribute since collectively the channels/streams make up the Brahmaputra River.  

The different streams that are highlighted in blue connect to the Brahmaputra River which eventually joins the Indian Ocean. 

Brahmaputra River, Bangladesh

Representing this complex river system as a single multipart line geometry helps in efficient data analysis like computing the length and width of the complete river system. One can easily manage, analyze and visualize the spatial data related with the entire system, rather than having to work with individual segments of the river.

The code snippet below demonstrates creating complex multipart polylines using ArcGIS Maps SDK for Kotlin. This code creates different river streams which connect to the main river. The four river streams constituting a single river which eventually connects to the ocean are represented as one multipart polyline feature.

⊕ Show code …

//create river streams and add graphics to display these polylines in an overlay
private fun constructRiverStream() {

        // create first river stream which is basically a Mutable Part and connects to the ocean
        val riverstream1 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-13431206.32, 5131073.67),
                Point(-13431209.45, 5131072.27),
                Point(-13431212.87, 5131071.16),
            ),
            SpatialReference.webMercator()
        )

        // create second river stream which is basically a Mutable Part and connects to the first river stream
        val riverstream2 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-13431212.87, 5131071.16),
                Point(-13431214.08, 5131068.29),
                Point(-13431216.15, 5131064.61),
                ...
            ),
            SpatialReference.webMercator()
        )

        // create third river stream which is basically a Mutable Part and connects to the first river stream
        val riverstream3 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-13431212.87, 5131071.16),
                Point(-13431216.00, 5131068.84),
                Point(-13431217.36, 5131065.42),
                ...
            ),
            SpatialReference.webMercator()
        )

        // create fourth river stream which is basically a Mutable Part and connects to the first river stream
        val riverstream4 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-13431211.06, 5131071.87),
                Point(-13431219.33, 5131070.76),
                Point(-13431225.88, 5131066.53),
                ...
            ),
            SpatialReference.webMercator()
        )

        // create fifth river stream which is basically a Mutable Part and connects to the first river stream
        val riverstream5 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-13431209.30, 5131072.27),
                Point(-13431219.33, 5131075.44),
                Point(-13431225.88, 5131072.17),
                ...
            ),
            SpatialReference.webMercator()
        )

        // add all the parts created above to a List
        var parts = listOf(riverstream1, riverstream2, riverstream3, riverstream4, riverstream5)

        // Create a Polyline geometry using the list of parts created above. This Polyline Builder is essentially a MultipartPolyline geometry comprising of the river streams which are ultimately part of a main river which connects to the ocean
        var polylineBuilder = PolylineBuilder(parts)

        // define a line symbol which will represent the river stream with its width defined.
        val riverSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.blue, 4f)

        // create a Graphic using the polyline geometry and the riverSymbol and add it to the GraphicsOverlay
        graphicsOverlay.graphics.add(Graphic(polylineBuilder.toGeometry(), riverSymbol))

    }

View complete code on GitHub.

Multipart polygon geometry 

 In GIS, when a path encloses an area, it is called a ring. The ring starts and ends at the same place. A collection of one or more such rings make a polygon. A multipart polygon is composed of many such individual polygons that combine to form a complex shape. Each polygon in the multipart polygon is termed as a part, and each part has its own size and shape. They also represent areas that are completely contained within another area, like an island in a lake.  

For example, agricultural fields with complex shapes and multiple sections can be represented as a multipart polygon geometry that permits the farmers to understand and analyze the agricultural output. Complex geologic formations such as mountains, ridges and canyons, can be represented as multipart polygons to help geologists analyze the structure of the Earth’s crust and its formation process. 

Another example as shown in the image below, is the state of Hawaii which can be represented as a multipart polygon as it is made of eight main islands, each with its own shape and size. Hawaii can be stored as a single multipart polygon feature in the database table. This allows for a detailed and accurate representation of the state’s geography in GIS applications like land use planning or disaster response. 

State of Hawaii with its eight main islands

The code snippet below demonstrates creating complex multipart polygons by adding a couple of islands and a lake within an island on the map using ArcGIS Maps SDK for Kotlin.

⊕ Show code … 
//create input polygons and add graphics to display these polygons in an overlay
private fun createPolygons() {

        // create an island which is the first polygon part
        val island1 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-16983394.627, 1725046.488),
                Point(-16967695.178, 1741475.672),
                Point(-16939145.948, 1736705.524),
                ...
            ),
            SpatialReference.webMercator()
        )

        // create a another island which is the second polygon part
        val island2 = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-16858450.243, 1742851.240),
                Point(-16855023.117, 1750367.747),
                Point(-16851622.565, 1754465.787), 
                ...
            ),
            SpatialReference.webMercator()
        )

        // create a another island which is the third polygon part and acts as an outer ring
        val outerIsland = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-16894265.768, 1780130.116),
                Point(-16888215.299, 1785870.657),
                Point(-16877750.891, 1783166.995)
                ...
            ),
            SpatialReference.webMercator()
        )

        // create a lake which is a polygon part and an iner ring to the above outer ring
        val innerLake = MutablePart.createWithPoints(
            listOf(
                // add points to the point collection
                Point(-16895378.882, 1773374.994),
                Point(-16887986.287, 1772724.682),
                Point(-16883906.162, 1768680.088),
                ...
            ),
            SpatialReference.webMercator()
        )

        // add all the parts created above to a List
        var parts = listOf(island1, island2, outerIsland, innerLake)

        // Create a PolygonBuilder using the list of parts created above
        var polygonBuilder = PolygonBuilder(parts)

        // define a line symbol which will represent the boundary of the polygon
        val lineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(153, 221, 255), 2f)

        // create and add a green graphic to fill color of the Polygon Builder.
        val greenFill = SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.fromRgba(128, 255, 170 ), lineSymbol)
        graphicsOverlay.graphics.add(Graphic(polygonBuilder.toGeometry(), greenFill))

    }

View complete code on GitHub.

Interesting Fact:  Did you know that the largest lake on an island is Nettilling Lake on Baffin Island, Canada – 5,542 km2 (2,140 sq mi)? This is a perfect example of a real-world feature which we can represent using a multipart polygon.  

Nettilling Lake on Baffin Island, Canada

Applications of multipart geometries 

Let’s see some other real-life examples of multipart geometry. 

Multipart geometries can be used to represent complex road and transportation networks, like highways with multiple lanes, ramps, and intersections, which help to analyze the connections between different parts of the network. 

Complex urban features such as city blocks, neighborhoods, complex building structures can be represented as multipart geometries which help the users to understand the relationship between different city zones. 

They can also be used to represent complex environmental features such as national forests, nature conservancy land, wildlife sanctuary and various water bodies which are important in environmental assessments and planning. 

Benefits of multipart geometries: 

Using multipart geometry over multiple individual geometries has many benefits. One of the important benefits is enhanced performance. The amount of memory required to store these geometries is reduced significantly when multiple related parts or features are stored as a single multipart geometry object, which in turn boosts the efficiency of spatial queries and analysis. 

Multipart geometries help simplify data management. If a map feature consists of multiple polylines, we can store them as a single multipart polyline geometry. Which means, you only need to update a single geometry object, instead of many individual geometries. This makes it easier to update the feature and maintain its integrity. 

Another benefit of multipart geometries is increased flexibility in representing complex spatial features. By representing features as a single multipart geometry, you can very easily visualize and analyze the feature as a whole, rather than treating each part as a separate feature. 

Conclusion: 

In summary, using multipart geometries in your mapping applications is an efficient way of representing a wide range of complex features in geographic data. From water bodies and land masses to buildings and transportation networks, multipart geometries allow for a detailed representation of complex features, which helps in urban and town planning, environmental resource planning, and other fields.  

We also showcased how the ArcGIS Maps SDK for Kotlin can be used to map such complex features. If you’re interested to know more about adding attributes to a feature, check out this sample app which creates and adds features whose attribute values satisfy a predefined set of contingencies. To learn further about the capabilities of the ArcGIS Maps SDKs for Kotlin, check out our GitHub samples code repo. 

If you’re new to developing ArcGIS Maps SDKs for Native Apps, each SDK (.NET, Qt, Java, Kotlin and Swift) has rich guide documentation, API Reference, Tutorials, and samples. Simply sign up for a free ArcGIS Developer account and you’ll be able to access everything you need to develop your app. 

About the author

Priyanka Rupani

I'm a product engineer on the ArcGIS Maps SDKs for Native Apps team. I develop android samples showcasing the Native SDKs features for the users.

Next Article

Accessibility essentials for GIS and mapping

Read this article