Parking Data

Example extract from SharedStreets CurbLR using DDOT's parking zone Python script

About

Creating a rich and detailed parking zone GIS has long been a goal of both the GIS and Planning teams in DDOT.  But there have been a number of problems which present considerable challenges: 

  1. Accounting for change over time.  As the signs change on each block, there must be a corresponding change/update to any parking zone information.  
  2. Properly matching signs.  In an urban environment, the parking information can be quite dense and confusing.  Because of the density of information, matching signs to each other is only half the battle.  
  3. Properly matching time/day.  One must also match timebands, which are the day/time combinations that define the time aspect of the restriction or permission.  
  4. Flagging mismatches.  You may be shocked to discover that sometimes, the information on signs sometimes doesn't match up correctly!  No DOT is perfect, but we must have an ability to catch these problems in an automated, data-driven way so that we can discover and fix the problems prior to causing problems for constituents.
  5. Flagging conflicts.  When two opposing types of parking signs (a parking sign and a no parking sign) try to describe the same place in the same, this is a sign conflict.

In spite of these challenges, DDOT has endeavored to harness our GIS-based sign inventory and create a highly detailed GIS parking zone database which can be utilized by planners and the public at-large.  The goals of this project are as follows:

  1. Harness the original GIS Sign Inventory (collected circa 2016).
  2. Dynamically generate linearly referenced GIS lines which represent parking zones.
  3. Retain the rich attribute data of sign timebands
  4. Analyze and compare/overlay zones to gain insight on existing curbside regulations.
  5. Dynamically generate easier to understand parking schedule infographics, similar to the work of Nikki Sylianteng.

Sign Inventory

In order to derive parking zones, it's best to go to the source (if you have it):  a GIS-based parking sign inventory.  Many cities have invested a large amount of time to maintaining a segment/line inventory of the parking restrictions.  The time and effort taken to create and maintain this information would likely require a full-time staff member to maintain and keep the data current.  

In 2016, DDOT captured over 203,000 street signs within the District of Columbia.  Over 30% of the signage was related to parking (permissive or restrictive).  That's a lot of parking signs!   Here's a bit more about what we have:

Data

Our sign inventory GIS relational data model is structured like so:

  • A Sign Support can have one or more
    • Signs, which, individually can have multiple
      • Timeband(s)

Dataset Name: ParkingZones

Field Name

Type

Description

Alias Name

Domain / Lookup

Example

ZONEID

String

Unique ID for each parking zone. Structure is “SubBlockKey-Side of the street-Count

ZONEID


1245633d0d3822d95dc48807d61c4ee9-left-4

SIGNCODE

String

This is the code for the type of sign that makes up the parking zone.

SignType


R-NS-011

SIGNTEXT

Integer

Any relevant text on the sign is stored here

SIGNTEXT


IF TOWED 727-5000

ROUTEID

String

The RouteID of the SubBlock that this parking zone exists on.

ROUTEID


11025152

SIDE

String

The side of the SubBlock that this parking zone exists on (if looking towards digitizing direction)

SIDE


left

MEAS_FROM

Double

At which measure along the Route the parking zone begins at.

MEAS_FROM


4988.919922

MEAS_TO

Double

At which measure along the Route the parking zone ends at.

MEAS_TO


5127.36377

STARTDAY

Long

The start day of the parking restriction timeband (Monday if Mon-Friday)

STARTDAY

SignWorks_Days

8 (ANYTIME)

ENDDAY

Long

The end day of the parking restriction timeband (Friday if Mon-Friday)

ENDDAY

SignWorks_Days

8 (ANYTIME)

STARTTIME

Long

The start time of the parking restriction timeband (12pm if 12pm-5pm)

STARTTIME

SignWorks_Hours_2

100 (ANYTIME)

ENDTIME

Long

The end time of the parking restriction timeband (5pm if 12pm-5pm)

ENDTIME

SignWorks_Hours_2

100 (ANYTIME)

EXCEPTION

String

If there is an exception to the parking restriction, it will be stored here

EXCEPTION


<Null>

SIGNS

String

A comma separated string listing all signs that participate in the creation of this particular parking zone

PARTICIPATING SIGN


9E09D365,C04E466A

OFFSET

Double

Offset value that only exists to space out the zones and make each one visible on the map.

OFFSET


-5

BLOCKFACEKEY

String

The unique key of the blockface on which this parking zone exists.

BLOCKFACEKEY


1245633d0d3822d95dc48807d61c4ee9

SHAPE.LEN

Double

Length of the parking zone

SHAPE.LEN


138.444474


Sign Supports

This is the primary GIS point feature which represents where the sign post is located, geographically.  Important fields to note:

  1. GlobalID (primary key)
  2. SupportType
  3. Side  (side of the street this support is on, relative to the centerline geometry)

Map Service:  https://dcdot.esriemcs.com/server/rest/services/Signs/SignWorks_ReadOnly/FeatureServer/0

Signs

Signs is a tabular (non-spatial) table related to the Support feature class above.  Thus, the location of a sign is derived from the support it is associated to.  When possible, each sign type code references the USDOT MUTCD guide.  However, there are many parking-type signs which are the creations of DDOT.  We call these 'Non-standard' signs and the listing of these signs are available on the attached document below.

Important fields to note:

  1. SupportID  (foreign key to GlobalID in SignSupports table above)
  2. Sign Type (field:  MUTCD)
  3. Arrow direction (field:  SIGNARROWDIRECTION)
  4. Geographic zone (field:  ZONE_ID)

Map Service:  https://dcdot.esriemcs.com/server/rest/services/Signs/SignWorks_ReadOnly/FeatureServer/1

TimeBands

Each day/time span shown on a specific sign is called a Timeband.  Each of these time bands is stored in the below table.  Important fields to note:

  1. SignID:  (foreign key to GlobalID in Signs table above)
  2. StartDay/EndDay:  The domain index for the day
  3. StartTime/EndTime:  The domain index for the time (15 min increments)
  4. HourLimit:  If a parking hourly limit applies.

Map Service:  https://dcdot.esriemcs.com/server/rest/services/Signs/SignWorks_ReadOnly/FeatureServer/2

Creating Zones

The main challenge has been:  how do we know which signs are logically connected, creating zones of parking/no parking?  More importantly, how can we connect these signs, make them into zones and store them into a data model which allows us to query and ask questions of the data?

The sections below will provide detail on how we accomplished this.

Linear Referencing

<Developing>

Basic example of process illustrated in poster below

Python Scripting

CheckSupportSigns, BuildTIntersections, LoadSigns, MergeZones, ZoneGroups

The Parking Zones are built through a sequence of several python scripts. The purpose and methodology of each script is summarized below:

Step 1: Checking the Supports and Signs

In the first stage of building the Parking zones, we scan the Supports feature class (FC) and the Signs FC to make sure that the data was collected properly, and produces an error table to log any red flags. It checks to make sure that these standards are met in each row of data:

  1. Every sign should have a support with a matching SupportID (GlobalID in the Supports FC)
  2. Every sign should have s SupportID
  3. Signs that require arrows have one logged
  4. Signs that require an hour limit have one logged
  5. Speed limit signs have a valid, recorded speed limit
  6. Sign types that require restrictions have the necessary data (day restrictions, time restrictions, etc.) and that they were logged properly

Step 2: Building a T-intersection Table

This step allows us to take T-intersections into account when building our Parking Zones. This allows parking zones to stretch across multiple SubBlocks, as long as it isn't interrupted by an intersecting roadway/alley. We call these uninterrupted adjacent segments Block Faces. 

The script finds all 3-way intersections in the city, and logs the RouteIDs and SubBlockIDs of the SubBlocks that participate in that intersection. Each row of data in the table represents one 3-way intersection.


Step 3: Loading all parking type signs into a dedicated table

This step can be the lengthiest one as it can actually serve two purposes. One of those purposes is loading all parking type signs into a dedicated table (SignTableDetail). This is the most commonly run portion of the script, as the second part is optional.  The second part refreshes the SignSupport FC, and updates the LRS data associated to them. The RouteID, SubBlockID and Measure values are all updated to reflect the present.

Part 1: This part builds us a table that we can use to actually start building the Parking Zones. It utilizes the T-Intersection table created in the last Step to build Block Faces, and then insert the BlockFaceKey into SignTableDetail. Each row in SignTableDetail represents one parking type sign, and has the necessary Route, Block Face and Measure information to help in the Parking Zone building process.

Part 2: This part just allows us to push updates back up into the SignSupports FC, which is the collected data that we have.


Step 4: Building the Parking Zones

Finally, we get to the most exciting step. This is where the Parking Zones are actually created. 

First, SignTableDetail is sorted ascending, prioritizing in this order: BlockFaceKey, Side, MUTCD, TimeID, Measure

This allows us to iterate through adjacent signs of the same type on the same side of a single Block Face. It loops through each sign, creating zones as it goes. The step by step process is laid out below:

  1. We are on the first type A sign on this side of the Block Face. 
    1. If the arrow points left, the parking zone is created between the sign and the intersection adjacent to it. This is because there are no other signs in between, the zone is closed out.
    2. If the arrow points right, a parking zone begin point is created.
  2. We are on the next type A sign on this side of the Block Face.
    1. If the arrow points left, a parking zone is created between the first type A sign, and this type A sign. The arrows point at each other, and therefore create a zone between them.
    2. If the arrow is bidirectional, a parking zone mid-point is created (stored in a dictionary). This is to let the script know that this sign is a part of the same zone, but is not the end-point.

This loops through each sign type on each Block Face until all the Parking Zones have been created. Every parking zone created on the same Block Face has an offset value incremented by 1, so that we can offset the zones and be able to view them spread out on a map.


Step 5: Building Segmented Parking Zones

The Segmented Parking Zones are zones between two adjacent supports. The supports at the end also create a Segmented Parking Zone with the adjacent intersection/dead end. The resulting SegmentedParkingZones FC contains a field that lists all of the Parking Zones that exist between any two supports. 

Basic example of process illustrated in poster below



  File Modified

PNG File Sign Data Diagram.png

29 Jan, 2022 by James Graham

File Sign Data Diagram

29 Jan, 2022 by James Graham

PNG File parkingzones_SS.png

29 Jan, 2022 by James Graham

ZIP Archive PetworthParkingZoneSample_BasicZones.zip

29 Jan, 2022 by James Graham

PDF File ParkingZonesPosterFinal.pdf

29 Jan, 2022 by James Graham

PDF File DC_NonStandardSignCodes_1.9.pdf

29 Jan, 2022 by James Graham