Assigning Address Ranges from nearby Address Points

7623
22
Jump to solution
08-05-2013 05:31 AM
LangdonSanders3
New Contributor II
Hello,

I am a GIS Tech at a city gov. with our own 911 dispatch.  I am working to update our street centerline ranges for use in our dispatch software.  The geography is accurate; however, the address ranges are model types and do not fit reality, i.e. range 1-100, when there are only 4 houses on the block from 101 - 116.  I would like to use dynamic segmentation to help fix these ranges.

I came across this white paper by Kelly Bigley (2003) http://proceedings.esri.com/library/userconf/proc03/p1077.pdf
Which has a process I would like to replicate: 

Of course it is possible that an address point may be closer to a road that it is not addressed off of. An ArcINFO
AML script can be used to loop through each street name. For each name it creates a subset of the streets and
address points with that street name. It performs a NEAR command on those subset coverages and transfers the
unique street coverage COVER-ID to the address points. Then it appends the resulting point coverages into one.
The resulting coverage is basically the original address coverage with a few additional attributes, including the
COVER-ID of the street centerline and the X and Y coordinate along the closest arc.
- Kelly Bigley


I'm new to python and eager to learn so I am asking to be pointed in the right direction to write a similar script - comparing address point street names to centerline street names before performing the NEAR analysis.  Thank you.

Once the NEAR is complete for Address --> Roads, I want to dynamically segment the roads based on those address points, with each segment having an address range determined by the address points along it.

Langdon
Tags (2)
22 Replies
RichardFairhurst
MVP Honored Contributor
Having done a few more of these I have found that some additional data preparations and address analysis that pays off and a way to get the Cul-de-sac ends to be correct after the other procedures I described.

After getting the original address points located along the routes and then converted to line events, I added a field called ASC_DESC and made it a 17 character text field.  Then I selected and calculated the ASC_DESC to "Ascending" for all segments that meet the criteria:

"MIN_MEAS" <> "MAX_MEAS" AND "FROM_HOUSE_NUMBER" < "TO_HOUSE_NUMBER"

I selected and calculated the ASC_DESC to "Descending" for all segments that met the criteria:

"MIN_MEAS" <> "MAX_MEAS" AND "FROM_HOUSE_NUMBER" > "TO_HOUSE_NUMBER"

I selected and calculated the ASC_DESC to "Same House Number" for all segments that met the criteria:

"MIN_MEAS" <> "MAX_MEAS" AND "FROM_HOUSE_NUMBER" = "TO_HOUSE_NUMBER"

Finally, I selected and calculated the ASC_DESC to "Same Measure" for all segments that met the criteria:

"MIN_MEAS" = "MAX_MEAS"


For all of the segments that had the same measure (which are normally at line ends and often tied to cul-de-sacs) I performed a Summary Statistics with the following summary fields and case fields:

Summary Fields:
FROM_HOUSE_NUMBER Min
FROM_HOUSE_NUMBER Max
TO_HOUSE_NUMBER Min
TO_HOUSE_NUMBER Max

Case Field(s):
RID
MIN_MEAS

In this result I added two double fields called MIN_HOUSE and MAX_HOUSE.  I selected and calculated the MIN_HOUSE value to be the lower of the Min_FROM_HOUSE_NUMBER and Min_TO_HOUSE_NUMBER values and the MAX_HOUSE was calculated to be the higher of the Max_FROM_HOUSE_NUMBER and Max_TO_HOUSE_NUMBER values.

In another post I will describe how I used this to get the ideal range set on the segment that had a change of measure values and touched the end with multiple stacking house numbers.  That ultimately fixes most of the cul-de-sac problems (except when a houe is on the wrong side of the bulb, but that is for another discussion).


Once the individual house address pair segments are categorized I unselected all records and did the Summary that generated the overall Min and Max measures and House Numbers for all address points and categorized their ASC_DESC characteristics.  I made both the individual segments and the overall address segments into Route Event layers.  Then I set up a relate between those two layers through the common RID values.

Now I selected all of the overall address events that were "Ascending" and performed the relate to the individual house pairs.  I then selected from the current selection of individual house pair events all segments that had ASC_DESC values of "Descending".  Then I reversed the relate twice to see just the individual house pair events for segments with mixed Ascending and Descending events within an overall Ascending address set.

Examining these events revealed out lying address with messed up house numbers (in one case 14735 had been mistyped as 71435, which really screws up a range).  I fixed obvious errors in the data and looked at clusters of addresses that switch direction only because of houses being closer or further away from the road.  If a address trend reversal would affect a centerline end point I paid particular attention to those house pairs and in some cases overrode the actual addresses (rarely, but small reversals were often due to flag lots).  This analysis resolved some of the previously Mixed range sets and also reveals jurisdictional number changes and ranges that should be divided and handled separately.

Performing this analysis before doing the steps where the overlay of actual centerlines to the address points and assignment of centerline ranges resulted in fewer anomalies.  With the corrections of the overlapping measure house numbers (for a later post) the cul-de-sacs were able to be completed through the normal range assignment process.
0 Kudos
RichardFairhurst
MVP Honored Contributor
I found another mistake in the calculation that determined House Numbers outside of the actual first and last address points.  I multiplied by the HOUSE_INTERVAL when I should have divided.  A corrected calculation is below for the From and To measures respectively:

From House Numbers
If [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Ascending" AND [CL_ENDS_LINES.MIN_MEAS] < [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS] Then
  Raw = ([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
  If Output < Raw Then Output = Output + 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Ascending" AND [CL_ENDS_LINES.MIN_MEAS] > [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS] Then
  Raw = ([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER] 
  If Output < Raw Then Output = Output + 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Descending" AND [CL_ENDS_LINES.MIN_MEAS] < [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS] Then
  Raw = ([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER] 
  If Output > Raw Then Output = Output - 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Descending" AND [CL_ENDS_LINES.MIN_MEAS] > [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS] Then
  Raw = ([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MIN_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER] 
  If Output > Raw Then Output = Output - 2
Else
  Output = ""
End If


To House Numbers
If [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Ascending" AND [CL_ENDS_LINES.MAX_MEAS] < [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS] Then
  Raw = ([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
  If Output > Raw Then Output = Output - 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Ascending" AND [CL_ENDS_LINES.MAX_MEAS] > [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS] Then
  Raw = ([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER] 
  If Output > Raw Then Output = Output - 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Descending" AND [CL_ENDS_LINES.MAX_MEAS] < [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS] Then
  Raw = ([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER] 
  If Output < Raw Then Output = Output + 2
ElseIf [ADDRESS_ODD_RIGHT_Full.ASC_DESC] = "Descending" AND [CL_ENDS_LINES.MAX_MEAS] > [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS] Then
  Raw = ([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]  + [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER] 
  Output = Round(([CL_ENDS_LINES.MAX_MEAS] - [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]) / [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]/2, 0) * 2  + [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER] 
  If Output < Raw Then Output = Output + 2
Else
  Output = ""
End If
0 Kudos
RichardFairhurst
MVP Honored Contributor
I am rewriting the last set of calculations again.  I found that I need to do too many replace updates with the table names as I do each direction and side (and even subarea for my large County).  Even the field names need to be replaced sometimes if I do not do the process exactly the same each time.  So I am making it easier to edit the input fields and increasing the readability of the calculations:

From House Numbers
Min_Meas = [CL_ENDS_LINES.MIN_MEAS]
Asc_Desc = [ADDRESS_ODD_RIGHT_Full.ASC_DESC]
Min_Min_Meas = [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]
Max_Max_Meas = [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]
House_Interval = [ADDRESS_ODD_RIGHT_Full.HOUSE_INTERVAL]
Min_From_House_Number = [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
Max_To_House_Number = [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER]
Max_From_House_Number = [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER]
Min_To_House_Number = [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER]

If Asc_Desc = "Ascending" AND Min_Meas < Min_Min_Meas Then
  Raw = (Min_Meas - Min_Min_Meas) / House_Interval + Min_From_House_Number 
  Output = Round((Min_Meas - Min_Min_Meas) / House_Interval/2, 0) * 2 + Min_From_House_Number 
  If Output < Raw Then Output = Output + 2
ElseIf Asc_Desc = "Ascending" AND Min_Meas > Max_Max_Meas Then
  Raw = (Min_Meas - Max_Max_Meas) / House_Interval + Max_To_House_Number 
  Output = Round((Min_Meas - Max_Max_Meas) / House_Interval/2, 0) * 2 + Max_To_House_Number 
  If Output < Raw Then Output = Output + 2
ElseIf Asc_Desc = "Descending" AND Min_Meas < Min_Min_Meas Then
  Raw = (Min_Meas - Min_Min_Meas) / House_Interval + Max_From_House_Number 
  Output = Round((Min_Meas - Min_Min_Meas) / House_Interval/2, 0) * 2 + Max_From_House_Number 
  If Output > Raw Then Output = Output - 2
ElseIf Asc_Desc = "Descending" AND Min_Meas > Max_Max_Meas Then
  Raw = (Min_Meas - Max_Max_Meas) / House_Interval + Min_To_House_Number 
  Output = Round((Min_Meas - Max_Max_Meas) / House_Interval/2, 0) * 2 + Min_To_House_Number 
  If Output > Raw Then Output = Output - 2
Else
  Output = ""
End If


To House Numbers
Max_Meas = [CL_ENDS_LINES.MAX_MEAS]
Asc_Desc = [ADDRESS_ODD_RIGHT_Full.ASC_DESC]
Min_Min_Meas = [ADDRESS_ODD_RIGHT_Full.MIN_MIN_MEAS]
Max_Max_Meas = [ADDRESS_ODD_RIGHT_Full.MAX_MAX_MEAS]
House_Interval = [ADDRESS_ODD_RIGHT_Full.HOUSE_IINTERVAL]
Min_From_House_Number = [ADDRESS_ODD_RIGHT_Full.MIN_FROM_HOUSE_NUMBER] 
Max_To_House_Number = [ADDRESS_ODD_RIGHT_Full.MAX_TO_HOUSE_NUMBER]
Max_From_House_Number = [ADDRESS_ODD_RIGHT_Full.MAX_FROM_HOUSE_NUMBER]
Min_To_House_Number = [ADDRESS_ODD_RIGHT_Full.MIN_TO_HOUSE_NUMBER]

If Asc_Desc = "Ascending" AND Max_Meas < Min_Min_Meas Then
  Raw = (Max_Meas - Min_Min_Meas) / House_Interval + Min_From_House_Number 
  Output = Round((Max_Meas - Min_Min_Meas) / House_Interval/2, 0) * 2 + Min_From_House_Number 
  If Output > Raw Then Output = Output - 2
ElseIf Asc_Desc = "Ascending" AND Max_Meas > Max_Max_Meas Then
  Raw = (Max_Meas - Max_Max_Meas) / House_Interval + Max_To_House_Number 
  Output = Round((Max_Meas - Max_Max_Meas) / House_Interval/2, 0) * 2 + Max_To_House_Number 
  If Output > Raw Then Output = Output - 2
ElseIf Asc_Desc = "Descending" AND Max_Meas < Min_Min_Meas Then
  Raw = (Max_Meas - Min_Min_Meas) / House_Interval + Max_From_House_Number 
  Output = Round((Max_Meas - Min_Min_Meas) / House_Interval/2, 0) * 2 + Max_From_House_Number 
  If Output < Raw Then Output = Output + 2
ElseIf Asc_Desc = "Descending" AND Max_Meas > Max_Max_Meas Then
  Raw = (Max_Meas - Max_Max_Meas) / House_Interval + Min_To_House_Number 
  Output = Round((Max_Meas - Max_Max_Meas) / House_Interval/2, 0) * 2 + Min_To_House_Number 
  If Output < Raw Then Output = Output + 2
Else
  Output = ""
End If
0 Kudos