Here are some useful calculations for validating that LR Routes are simple.
Create a Long field called Parts and use the following advanced calculation to determine how many parts make up your route (I allow gaps when building routes so that I can cross minor jogs at intersections. Branches always result in at least 3 parts to a route):
Parser: Python
Pre-Logic Script Code:
def Output(PartCount):
return PartCount
Expression:
Output(float(!SHAPE.PARTCOUNT!))
Create a field of type Long called MMONOTONIC and use the following advanced calculation to determine the M Monotonicity of the LR Route (A value of 1 indicates measures are continuously increasing, which means the route has no branches and is simple. Any other value indicates combinations of measures that are increasing, decreasing or unchanging, which means the LR Route has branches, full loops or other complex route configurations. This is the value reported descriptively in the Identify Route Locations tool and you can create a domain that replicates those descriptions if you like):
Parser: VB Script
Pre-Logic Script Code:
Dim Output As Long
Dim l As Long
Dim pCurve As ICurve
Dim pSegmentCollection As IMSegmentation3
Set pCurve = [Shape]
Set pSegmentCollection = pCurve
Output = pSegmentCollection.MMonotonicity
Expression:
Output
Once you have created routes you can get Rooute ID values and measures assigned to your intersection points by using the "Locate Features Along Routes" tool in the Linear Referencing toolbox. Below is a sample of the fields I have in the intersection pair event table to use as joins and value transfers to subsequently derived event tables. I use these fields for validation of the subsequent events and updating the derived events in response to changes in my routes, such as realignments, road renaming, etc.:
RID: VIA LOS VENTOS SWAP ' Route ID created by the Locate Feature Along Route tool. In this case the Street name is VIA LOS VENTOS in the Southwest Area Plan (SWAP)
MEAS: 5023.8725 ' Measure created by the Locate Feature Along Route tool.
Distance: 0 ' Field created by the Locate Features Along Route tool. Typically 0.
STNAMES: {LOS GATOS RD}{VIA LOS VENTOS}{VISTA DEL MAR} ' All names listed alphabetically
X_COORD: 6231383.346493 ' transferrred to subsequent events so offsets can be compared.
Y_COORD: 2315384.464358 ' transferrred to subsequent events so offsets can be compared.
X_Y_LINK: {6231383.3465}{2315384.4644} ' Useful relate value for when route name changes
WAYS_COUNT: 4 ' Number of Centerline segments that link at intersection
STNAME_WAYS: {1}{1}{2} ' number of segments associated with the STNAME field street order
POINT_ID: 26638 ' Numeric value representing the Point X/Y value
STNAME: VIA LOS VENTOS ' Primary Street Name often used as a relate
CROSS_NAME: LOS GATOS RD ' Cross Street Name often used as a relate
X_Y_ROUTE: {6231383.3465}{2315384.4644}{VIA LOS VENTOS SWAP} ' Best final join for the RID and Meas values.
PAIR_STNAMES: {VIA LOS VENTOS}{LOS GATOS RD} ' First level join field
X_Y_PAIR: {6231383.3465}{2315384.4644}{W CHURCH ST}{IOWA AVE} ' Best Final Join for the name pair value
The above X/Y point would have 6 entries in my intersection pair table so that I could relate to any combination and order of the three (3) street names that meet at the above intersection.
Typically my derived events have the following fields:
PRIMARY: VIA LOS VENTOS
CROSS: LOS GATOS RD
DIST: 100
DIR: W
FACING: E ' FACING representing the direction of travel of a driver on the road looking at the sign, not the sign itself in my data.
PAIR_STNAMES: {VIA LOS VENTOS}{LOS GATOS RD} 'First level join or relate to intersection pair table
INT_X_Y: {6231383.3465}{2315384.4644} ' FROM X_Y_LINK. Useful as a relate
INT_X: 6231383.346493 ' Intersection X value from X_COORD. Useful for validating offset.
INT_Y: 2315384.464358 ' Intersection X value from Y_COORD. Useful for validating offset.
X_Y_PAIR: {6231383.3465}{2315384.4644}{W CHURCH ST}{IOWA AVE} ' Best Final Join for the name pair
X_Y_ROUTE: {6231383.3465}{2315384.4644}{VIA LOS VENTOS SWAP} ' Best final join for the RID and Meas values.
INT_MEAS: 5023.8725 ' From Meas value of the intersection
OFFSET_MULT: -1 ' Multiplier for offset representing the direction of offset.
OFFSET_DIST: 100 ' Repeats or adjust absolute offset distance so that it stays on the route
ROUTE_ID: VIA LOS VENTOS SWAP
EVENT_MEAS: 4923.8725 ' Actual measure of derived event. Equals INT_MEAS + OFFSET_MULT * OFFSET_DIST
CL_X: # ' Calculate Geometry on an event without a side offset. Can be compared to INT_X to make sure offset went in correct direction.
CL_Y: # ' Calculate Geometry on an event without a side offset. Can be compared to INT_Y to make sure offset went in correct direction.
SIDE_MULT: 1 ' Multiplier representing side offset direction related to FACING
SIDE_DIST: 30 ' Holds value of Side offset distance. Recaled as SIDE_MULT * ABS(SIDE_DIST)
INT_ANGLE: # ' Calced from LOC_ANGLE (the event angle) when event is at Intersection Measure. Tells you angle of your route at the intersection to help predict offset.
CALC_ANGLE: # ' Calced from LOC_ANGLE (the event angle) when event is at Offset Measure. Tells you angle at final event location to help predict side offset.
ROTATION: # ' Calced to give final rotation of FACING relative to the CALC_ANGLE value with 90 degree adjustments. I have a calcuation for doing this.
EVENT_X: # ' Use Calculate Geometry to get final event location X coordinate. Can be compared to CL_X to make sure side offset went in correct direction.
EVENT_Y: # ' Use Calculate Geometry to get final event location Y coordinate. Can be compared to CL_Y to make sure side offset went in correct direction.
I hope this helps.