Label Features

Label Features

Rene Rubalcava | April 26, 2021

I used to work in local county government. I cut my teeth in annexations, which is when new developments connect to county services, like sewers. This meant I spent lots of time writing tedious legal descriptions and preparing CAD drawings to go along with them. I've done hundreds of these. Hundreds. Then I had to add these into the GIS. I only mention this, because some of the users of the apps I wrote were used to seeing these parcels a certain way. Lots of times they wanted quick measurements of a parcel, without using built-in measurement tools of course. So I had implemented some features that let a user click on a parcel and they got quick measurements of the edges. They don't need to be exact, rough numbers were usually just fine for what users needed.

Here is an example of what this looked like.

label features

Pretty basic.

Making it work

The bulk of this work can be done using the geometryEngine. Along with some manual parsing of polygon geometry.

The key here is to remember that Polygon geometries are made up of rings. They look something like this.

[
    [ // polygon shape
        // A  -> B  ->  C  ->  A
        [...], [...], [...], [...]
    ]
]

You can see the rings are made up of coordinates where the last coordinate should be the same as the first, to close up the Polygon. Things get a little trickier when you have holes, but I'm not going down that route.

If I wanted to break this Polygon up into line segments, I basically need to grab the coordinates from the edges to do something like this.

[[A -> B], [B -> C], [C -> A]]

That gives me three line segments. These are called Polyline paths. Once I have those Polylines, I can measure and label them!

Here's how this might look in an application.

// generalize the geometry
const geometry = generalize(graphic.geometry, 0.0001, false);
// place to save Polyline centers
// use for labels
const mids = [];
// assume I have one polygon
const xys = polygon.rings[0];
const len = xys.length;
for (let i = 0; i < len - 1; i++) {
    // create a path
    const paths = [xys[i], xys[i + 1]];
    // create a Polyline
    const line = new Polyline({ paths });
    // measure the Polyline
    const len = geodesicLength(line, "feet");
    // save the Polyline center to label later
    mids.push({
        attribute: {},
        geometry: line.extent.center,
    });
}

This little snippet is going to do a few things. First, it will generalize the Polygon to eliminate some line segments. If not, we could have some extra segments that we don't need for simple labeling. It's going to iterate over the coordinates in Polygon rings and create some Polyline segments used for measurement and to find a center to place the label.

That's not too bad. Once you've worked with arrays and pulling stuff from locations in the array, you'll get the hang of it. You could even go through and create Points for each vertex of the Polygon and do some client-side topology rules and validation... whaaaaat.

You can see a demo of this application here.

You can watch a video where I go into more detail below!

Enjoy!