Download the runnable example here
Step 1: Calculate the undirectional minimum distances
Definition: the undirectional minimum distance between any two reference sites is the minimum distance consists of a number of links connecting these two reference sites, regardless of their directions.
Notation: umd_{rsirsj}  undirectional minimum distance between reference site rs_{i} and reference site rs_{j}
Method: Dijkstra minimum distance algorithm.
Step 2: Determine a given reference site's relative position
Given a link of interests [FT], the table below shows all possible positions that a random reference site rs_{i} can be relative to link [FT]:
Relative Position 
Explanation 
Conditions 
Upstream 
(rs_{i})
(F)=====>(T) 
umd_{rsiF} < umd_{rsiT} AND length(FT) < umd_{rsiT} 
Overlap F 
(F/rs_{i})
(F/rs_{i})===>(T) 
umd_{rsiF} = 0 
In Between 
(rs_{i})
(F)=====>(T) 
umd_{rsiF} + umd_{rsiT} <= length(FT) 
Overlap T 
(T/rs_{i})
(F)===>(T/rs_{i}) 
umd_{rsiT} = 0 
Downstream 
(rs_{i})
(F)=====>(T) 
umd_{rsiF} > umd_{rsiT} AND length(FT) < umd_{rsiF} 
Step 3: Determine a given link's relative position
Given another link [F_{i}T_{i}], its position can be of the following 25 cases relative to link [FT]:
Step 4: Determine the direction and the distance between two crashes
When calculating the distance from a current primary crash crash_{cur} (occurred on link [FT]) to a potential secondary crash crash_{i} (occurred on link [F_{i}T_{i}]), the following equation is used:
d = sign_{1}*(sign_{2}*umd_{FiF}  offset_{crashcur}) + offset_{crashi}.
where,
umd_{FiF}, offset_{crashi}, and offset_{crashcur} are all nonnegative distances. When d > 0, crash_{i} is downstream of crash_{cur} in either direction; when d < 0, crash_{i} is upstream of crash_{cur} in either direction. When link [F_{i}T_{i}], is in the same direction to link [FT], sign_{1} = 1, otherwise sign_{1} = 1. When F_{i} is upstream of link [FT], sign_{2} = 1; when F_{i} overlaps with F, sign_{2} = 0; otherwise, sign_{2} = 1. Below is a summary matrix:

F_{i}'s relative position to link [FT] 

Upstream 
Overlap F 
In Between 
Overlap T 
Downstream 
T_{i}'s relative position to link [FT]

Upstream 
Case1
if umd_{FiF} > umd_{TiF}, sign_{1} = 1,
if umd_{FiF} < umd_{TiF}, sign_{1} = 1;
sign_{2} = 1

Case2
sign_{1} = 1; sign_{2} = 0; 
Case3
sign_{1} = 1; sign_{2} = 1; 
Case4
sign_{1} = 1; sign_{2} = 1; 
Case5
sign_{1} = 1; sign_{2} = 1; 
Overlap F 
Case6
sign_{1} = 1; sign_{2} = 1; 
Case7 not exist 
Case8
sign_{1} = 1; sign_{2} = 1; 
Case9
sign_{1} = 1; sign_{2} = 1; 
Case10
sign_{1} = 1; sign_{2} = 1; 
In Between 
Case11
sign_{1} = 1; sign_{2} = 1; 
Case12
sign_{1} = 1; sign_{2} = 0; 
Case13
if umd_{FiF} < umd_{TiF}, sign_{1} = 1,
if umd_{FiF} > umd_{TiF}, sign_{1} = 1;
sign_{2} = 1

Case14
sign_{1} = 1; sign_{2} = 1; 
Case15
sign_{1} = 1; sign_{2} = 1; 
Overlap T 
Case16
sign_{1} = 1; sign_{2} = 1; 
Case17
sign_{1} = 1; sign_{2} = 0; 
Case18
sign_{1} = 1; sign_{2} = 1; 
Case19 not exist 
Case20
sign_{1} = 1; sign_{2} = 1; 
Downstream 
Case21
sign_{1} = 1; sign_{2} = 1; 
Case22
sign_{1} = 1; sign_{2} = 0; 
Case23
sign_{1} = 1; sign_{2} = 1; 
Case24
sign_{1} = 1; sign_{2} = 1; 
Case25
if umd_{FiF} < umd_{TiF}, sign_{1} = 1,
if umd_{FiF} > umd_{TiF}, sign_{1} = 1;
sign_{2} = 1

Appendix A: Enumeration of All Cases
Subcases
>(F_{i})=>(T_{i})>(F)=>(T)>:
This case is true when umd_{FiF} > umd_{TiF}. In this case, link [F_{i}T_{i}] is upstream of link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashcur}  offset_{crashcur}.
<(T_{i})<=(F_{i})<
>(F)=>(T)>:
This case is true when umd_{FiF} < umd_{TiF}. In this case, link [F_{i}T_{i}] is upstream of link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(T_{i})<===(F/F_{i})<
>(F/F_{i})=>(T)>:
In this case, link [F_{i}T_{i}] is upstream of link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(offset_{crashi}  offset_{crashcur}).
<(T_{i})<==========(F_{i})<
>(F)======>(T)>:
In this case, link [F_{i}T_{i}] is overlapped with link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(T_{i})<===============(T/F_{i})<
>(F)===>(T/F_{i})>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(T_{i})<=================(F_{i})<
>(F)===>(T)>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
>(F_{i})=>(F/T_{i})=>(T)>:
In this case, link [F_{i}T_{i}] is upstream of link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
Such case doen't exist since F_{i} and T_{i} overlap.
<(F/T_{i})<====(F_{i})<
>(F/T_{i})==============>(T)>:
In this case, link [F_{i}T_{i}] is contained by link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(F/T_{i})<========(T/F_{i})<
>(F/T_{i})========>(T/F_{i})>:
In this case, link [F_{i}T_{i}] is paired link of link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(F/T_{i})<=========(F_{i})<
>(F/T_{i})=====>(T)>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
>(F_{i})==========>(T_{i})>
>(F)=======>(T)>:
In this case, link [F_{i}T_{i}] is overlapped with link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
>(F/F_{i})====>(T_{i})>
>(F/F_{i})=========>(T)>:
In this case, link [F_{i}T_{i}] is contained by link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = offset_{crashi}  offset_{crashcur}.
Subcases
>(F_{i})==>(T_{i})>
>(F)=================>(T)>:
This case is true when umd_{FiF} < umd_{TiF}. In this case, link [F_{i}T_{i}] is contained by link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
<(T_{i})<==(F_{i})<
>(F)=================>(T)>:
This case is true when umd_{FiF} > umd_{TiF}. In this case, link [F_{i}T_{i}] is contained by link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(T_{i})<=====(T/F_{i})<
>(F)==========>(T/F_{i})>:
In this case, link [F_{i}T_{i}] is contained by link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<(T_{i})<=======(F_{i})<
>(F)======>(T)>:
In this case, link [F_{i}T_{i}] is overlapped with link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
>(F_{i})================>(T/T_{i})>
>(F)====>(T/T_{i})>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
>(F/F_{i})========>(T/T_{i})>
>(F/F_{i})========>(T/T_{i})>:
In this case, link [F_{i}T_{i}] is matching link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = offset_{crashi}  offset_{crashcur}.
>(F_{i})====>(T/T_{i})>
>(F)==============>(T/T_{i})>:
In this case, link [F_{i}T_{i}] is contained by link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
Such case doen't exist since F_{i} and T_{i} overlap.
<(T/T_{i})<===(F_{i})<
>(F)======>(T/T_{i})>:
In this case, link [F_{i}T_{i}] is downstream of link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
>(F_{i})==============>(T_{i})>
>(F)===>(T)>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
>(F/F_{i})============>(T_{i})>
>(F/F_{i})======>(T)>:
In this case, link [F_{i}T_{i}] is containing link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = offset_{crashi}  offset_{crashcur}.
>(F_{i})======>(T_{i})>
>(F)=======>(T)>:
In this case, link [F_{i}T_{i}] is overlapped with link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
>(T/F_{i})==>(T_{i})>
>(F)======>(T/F_{i})>:
In this case, link [F_{i}T_{i}] is downstream of link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
Subcases
>(F_{i})=>(T_{i})>
>(F)=>(T)>:
This case is true when umd_{FiF} < umd_{TiF}. In this case, link [F_{i}T_{i}] is downstream of link [FT] and in the same direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = umd_{FiF} + offset_{crashi}  offset_{crashcur}.
<(T_{i})<=(F_{i})<
>(F)=>(T)>:
This case is true when umd_{FiF} > umd_{TiF}. In this case, link [F_{i}T_{i}] is downstream of link [FT] and in the opposite direction.
The distance from crash_{cur} on [FT] to crash_{i} on [F_{i}T_{i}] can be calculated as d = (1)*(umd_{FiF}  offset_{crashi}  offset_{crashcur}).
<