Vision Zero Polygon Maintenance
GIS workflow for updating the Vision Zero Location Polygons layer
Project background and goals
The Vision Zero Location Polygons are used by the Vision Zero team to capture crashes on Austin streets and analyze the factors involved to determine if appropriate safety interventions are needed. The polygons provide complete coverage of all Austin roads in the Austin Strategic Mobility Plan Street Network.
The Project can be found on the network here ..._GIS\Vision_Zero\Polygon_Updates\
Digitizing New Polygons
The dimensions of each polygon are determined by the road's street level as specified below:
Road Segmentation
Level 1 or 2 streets: 150 feet
Level 3 or 4 streets: 250 feet
Buffer width
The distances below are the actual distances in feet to type into the buffer geoprocess tool
Street levels 1 or 2: 40 feet
Street level 3: 50 feet
Street level 4: 75 feet
Given that roads are typically longer than the length of the polygon, we set the length of the polygons by tracing along the ASMP streets and buffering these to the appropriate width. The following example can serve as a guide for digitizing new polygons in most scenarios.
Henneman Drive Example
In this example, we are tasked with digitizing Henneman Drive, along with all the streets that are missing polygon coverage:
When the polygons were first generated, this subdivision had not been completed. To cover this area, we must prep existing polygons to be compatible with new ones, trace polygon-length lines along the ASMP starting at intersections, dissolving intersection lines, buffering to the appropriate width, and appending them to the authoritative layer.
Prep existing polygons
Start by removing the rounded end points of the polygon so that are squared off and ready to join other polygons:
The easiest way to do this is to keep the circled vertices and lasso-deleting the vertices in between:
Tracing along the ASMP
Trace lines along the ASMP streets with the Trace Limit Length set to match the street level.
Trace options are accessed by pressing the letter O after clicking on the starting point of your trace.
Trace all intersections and all L sections first, starting with the middle point, and working your way outwards
Set your trace limit to half the corresponding street level/segment length. For example, set the trace limit to 75 for street levels 1&2
Merge each intersection and L sections
This will ensure that the buffers are drawn correctly and will minimize buffering errors.
Draw in the rest of the segments at full length, according to street level
If some segments are shorter, that is okay, but try to not let them get too small
If a segment is going to be too small (~10 -20 feet), it is best to draw/edit a nearby segment the necessary length to cover it
Tracing along the CTN
If the ASMP does not have good geometry to digitize from, use the CTN - it is updated frequently. If the CTN is missing data, or the polylines do not follow the actual centerline of the street, request that the CTN is fixed before tracing any new edit lines. We want the best data possible, and we don't want to duplicate our work. Drawing new edit lines while leaving the CTN in bad shape would create more work for the future, and it is unlikely to be ever fixed.
Buffering Polygons
Polygons have rounded ends and square joins to each other. For this reason, we run the buffer geoprocessing tool on our segment-lines twice. Currently, we overwrite each buffer output. This means that each buffering session deletes the previous content of the feature, and writes in the new buffers for your current edit session.
This will require the editor to append their buffered polygons before moving on to the next area to digitize. The main logic behind overwriting the data is to allow for the subsequent Append step to run quickly - if we save each buffer output as its own feature class, eventually the Append tool will begin to run slowly because it has to read a long list of un-indexed items to find the correct features to append from the file geo database (FGDB)*.
*NOTE: The issue is not the size of the FGDB, as there's no size limit, but rather finding the data. It's like tossing dirty laundry into a large hamper. Tossing dirty clothes into it is no problem, as you can toss the whole load into the wash, but finding a single sock would be difficult. We recently ran into this issue with the iMOPED data. In that project, it may be important to keep all update data, so we create quarterly file geodatabases, so that the outputs of the weekly update only reach about 12-15 features each before starting a new FGDB. This may work well in this project if keeping update data is important for the QA process.
Select all segment lines that will result in square-end polygons (all segments that connect to other segments)
In the buffering tool, select the appropriate buffer width
Do not dissolve
Save the output as
flat_polygons
Select all segment lines that will result in found-end polygons (all segments that are the end of a street, or a cul-de-sac)
In the buffering tool, select the appropriate buffer width
Do not dissolve
Save the output as
round_polygons
Appending Polygons
Once all segments have been properly buffered, do a final close-up inspection to ensure no slivers are present.
Open the Append geoprocessing tool
In the append tool, select both
flat_polygons
andround_polygons
as your inputsFor the target dataset, select the polygons layer from MAINT
Use the field mapper to remove all attribute matching
Run the append tool
Attribute edits
Now that the polygons are all in the MAINT layer, you'll notice that all new polygons have a Polygon Sequece ID and a Global ID, but no other attributes.
Fill in Road Name
Fill in Street Level
Select In Use - Yes
Polygon Hex IDs
The Polygon Hex IDs will be calculated from the Global ID. Create a model that does the following:
Remove all special characters
Select the first 10 digits of the Global ID
Field-calculate this selection into the Polygon Hex ID field
Bonus Points if this makes it into the model, but it can be done by hand:
Run unique field tool on Polygon Hex ID field
If all are unique, you're done!
If some duplicates exist, randomly change some characters and run again
Publishing to AGOL
Once all edits are in the MAINT layer, publish to AGOL
Merging Polygons
Merging polygons should maintain the original Hex IDs from the parent polygons. We do this by ensuring that both (or however many more) polygons' IDs are copied into the legacy ID fields. For example, if we're merging polygon A1 with polygon B2, the attribute table should look like this:
A1
A1
B2
B2
A1
B2
Once the polygons are merged, the original IDs are preserved in the legacy fields, allowing the Vision Zero team to compare historical crashes with new data at the same location. The new polygon will have a global ID
and polygon sequence ID
automatically generated
Removing Polygons
Because Polygon Hex IDs are tied to historical crash data, it is important to not delete any polygons, even if they were drawn incorrectly, or if the street has been reconfigured. For any polygons that no longer serve their function, we simply switch the In Use
value to No.
Tips for resolving issues
Due to the complexity of this project, it is impossible for documentation to give direct instructions on how to solve every problem. However, when in doubt, let the guiding principles of this project guide your decision-making. The most important function of the polygons is to cover the entirety of our roadways so that we can collect geotagged crash reports accurately. This allows us to analyze whether certain design elements (difficult intersections, lack of sidewalks, lack of lighting, etc) are contributing to crashes, in order to make appropriate and targeted safety interventions.
Prioritize Intersections
Understanding that crashes are more common at intersections than mid-block gives the intersection priority while digitizing. Because no two streets are the same, it can be difficult to get consistent results while digitizing. This invariably results in polygons being of different dimensions than the specs indicate. If sticking to the specs in every scenario is impossible, the best we can do is ensure that polygons that are likeliest to be the sites of crash to follow the specifications as closely as possible - thus intersections should go first.
Funky polygons
When digitizing, you may find that certain new polygons would be really small. As stated in the Tracing the ASMP section, It is preferable to extend the length of adjacent polygons than creating a new tiny polygon. Other steps of digitization may result in self-intersecting polygons. Whenever these are found, make sure to simplify them and to maintain coverage. The cleaner the data, the easier it is to use.
Solve the root cause of the issue
It is sometimes difficult to decide when to stop an edit. In the Hanneman Dr example, many other streets had been added that needed polygon coverage. As we scanned the neighborhood, we noticed several more subdivisions were beginning to connect through new level 1 streets. While our aim is to cover every street, we are assigned issues to prioritize locations where polygon maintenance work is needed. There are no set rules for when to stop digitizing, but there is no need to keep digitizing new street endlessly that have not been requested when there are other streets in our queue. If while editing, you notice areas that need digitzing, create a github issue about it, place it in the backlog, and decide how to prioritize these through sprint planning. For reference, the Hanneman Drive issue (which included surrounding streets in the request) took about 2 hours to digitize. Hanneman Dr was used to develop this workflow, and it is entirely possible it could be done faster. However, no issue should take longer than 2 hours to finish, if this workflow is followed (and hopefully improved upon!). If you find issues/requests that seem longer than that, break it up into smaller pieces at sprint planning, and ask the VZ team to submit smaller/more targeted requests.
Legacy Documentation
The documentation below details the algorithm used to create the initial set of polygons
Definitions and environment
Street Level: The designated street level as found in the ASMP network's attribute
street_lev
or similar. These are coded as 1 for the smallest, residential streets up to 5 for the major, on-system roads.Data Projection: All operations described below were executed in SRID 2277, the state plane projection for our portion of Texas which provides for measuring distance in our customary, US foot.
Road segments: A linestring between two intersections, but not extending over or through an intersection.
Intersections: Where road segments
touch
in the GIS sense or meet in the human sense. Roads can cross each other and not intersect, such as the case when one road goes over or under another without opportunity for drivers to switch between them. One is reliant on the topology of the street network used as input to sort these two cases out.Legs: The length of a road segment, emanating from an intersection, which ends up being part of an intersection polygon. A leg can be thought of as "one of the arms of the plus-shaped polygons for an intersection."
Intermediate segments & polygons: Where legs are created at intersections, the remaining "middle" portion of the road's linestring is the intermediate segment. When divided up and on a street without curves, these become the simplest, rectangular polygons.
A note on measuring distance along linestrings
When measuring distance along linestrings, one must avoid measuring "as the crow flies" and instead find a way to measure along the linestring. I found success in computing this by mapping (in the computer science sense) the a line segment's length to the interval between 0 and 1. PostGIS offers functions to find a point along an arbitrarily shaped linestring that n% along that linestring, and these two constructs allow for you to find the point an arbitrary number of feet along a linestring.
Polygon creation algorithm
Create a set of points,
intersections
, which are derived from the intersections of two or more street line segments.Create a set of
legs
, being linestrings that emanate out from eachintersection
point a certain distance along the road linestrings which contributed to eachintersection
. The length of theselegs
is defined as follows:If the road is either level 1 or 2, the length of the
leg
is 150 feet. The intent here is that an intersection of small roads will have proportionally smaller storage lanes and small area of influence.If the road is either level 3 or 4, the length of the
leg
is 250 feet. Larger roads, longer storage lanes, and thus a longerleg
length.A
downtown special case
is cut out for the downtown streets due to their highly regular grid formation and short road segment lengths, and aleg
length is defined downtown as being as long as needed to reach exactly half way to down the road segment to the nextintersection
.A
too-close-intersections special case
is called out when twointersections
are closer than the sum of the twolegs
that would reach toward each other on a road segment. In this case, theleg
length is 1/2 of the length of the road segment, such that thelegs
meet in the middle similar to the downtown case.A
no intermediate slivers special case
is called out when there is enough length along a linestring to create full lengthlegs
but the intermediate length left between them would result in an overly thin polygon. In this case, the legs are extended out so they meet and eliminate the need for the thin, intermediate sliver. The percentage of the ideal length of an intermediate polygon which is deemed "too thin" is a parameter to the algorithm and is currently set to.7
.
With each road segment's linestring now having a
leg
which covers the beginning and the end of the linestring, the remaining, central portion of the line string is deemed the intermediate segment. This segment is divided evenly into n segments such that the segment length is as close to the ideal polygon length as possible. The ideal polygon length is defined as:Level 1 or 2 streets: 150 feet
Level 3 or 4 streets: 250 feet
As it is unlikely that the intermediate segment of the road segment's linestring will divide evenly by the ideal intermediate polygon length, the number of intermediate polygon's is adjusted to the nearest integer value which results in polygon lengths closest to the ideal length.
With the entire road network now divided into segments, each segment is buffered out a certain distance. This distance is determined by the street level as follows:
Street levels 1 or 2: 40 feet
Street level 3: 50 feet
Street level 4: 75 feet
The buffer operation is done using postGIS'
ST_Buffer(<input linestring>, 'endcap=flat join=round')
such that polygons meet with square ends but roads with dead-ends are given a rounded terminus.Polygons generated from
leg
linestrings will overlap in the middle of the intersection. For eachintersection
, all polygons which are generated from thelegs
emanating from that particular intersection areunion
ed together in the GIS sense.The set of polygons must now be "deoverlapped." In the cases of particularly dense areas of roads and/or when roads come close to each other but do not actually touch, there may be points (GIS sense) which are contained in two or more polygons. Doing this in a way which is most sensical to representing a road network in areal geography is particularly difficult, and I experimented with a process (similar, but not exactly like the diagram shown here) which would use Voronoi diagrams and Delaunay triangles to define the a line which divides the overlap of two areas such that each contributing area receives an approximately equal amount of the area and the dividing line remains centered between the edges of the overlapping area. This worked well in the cases of only two polygons overlapping, but did not produce suitable results in particularly dense areas of roadways. In the interest of time, I settled on using a naïve approach:
Populate metadata for each polygon keeping track of the road segment in the input road network layer that contributed to each intermediate polygon. For intersections, one must keep an array of road segments which contributed to the
legs
of an intersection, deduplicate this list, and generate metadata in the form of comma separated lists or similar, depending on the particular metadata.
Last updated