While it’s not your actual problem, I did a subroutine to find crossings between two lines that don’t share the same x values. Maybe it can be helpful for someone looking at this topic for that case and can find it helpful
type :: cross
real(pr) :: x
real(pr) :: y
integer :: i
integer :: j
end type cross
subroutine find_cross(x_values1, x_values2, y_values1, y_values2, crossings)
!! Find crossings between two given lines
!!
!! Returns an array of crossigns, containings the crosses found. Each row
!! contains the data from each found cross
!!
!! | --------| ------- | ---------------- | ----------------- |
!! | x_cross | y_cross | first_line_index | second_line_index |
!! | --------| ------- | ---------------- | ----------------- |
!!
real(pr), allocatable, intent(in) :: x_values1(:) !! First line x values
real(pr), allocatable, intent(in) :: x_values2(:) !! Second line x values
real(pr), allocatable, intent(in) :: y_values1(:) !! First line y values
real(pr), allocatable, intent(in) :: y_values2(:) !! Second line y values
type(cross), allocatable :: crossings(:) !! Array of crossings
type(cross) :: current_cross
real(pr) :: x11, x12, x21, x22, y11, y12, y21, y22
real(pr) :: x_cross, y_cross, m1, b1, m2, b2, xlow, xup, ylow, yup
real(pr), dimension(2) :: xpair_1, xpair_2, ypair_1, ypair_2
integer :: i, j, n
if (allocated(crossings)) then
deallocate (crossings)
end if
allocate (crossings(0))
n = 0
do i = 2, size(x_values1)
xpair_1 = x_values1(i - 1:i)
ypair_1 = y_values1(i - 1:i)
x11 = xpair_1(1)
x12 = xpair_1(2)
y11 = ypair_1(1)
y12 = ypair_1(2)
m1 = (y12 - y11)/(x12 - x11)
b1 = y11 - m1*x11
do j = 2, size(x_values2)
xpair_2 = x_values2(j - 1:j)
ypair_2 = y_values2(j - 1:j)
x21 = xpair_2(1)
x22 = xpair_2(2)
y21 = ypair_2(1)
y22 = ypair_2(2)
m2 = (y22 - y21)/(x22 - x21)
b2 = y21 - m2*x21
x_cross = (b1 - b2)/(m2 - m1)
y_cross = m1*x_cross + b1
xlow = max(minval(xpair_1), minval(xpair_2))
xup = min(maxval(xpair_1), maxval(xpair_2))
ylow = max(minval(ypair_1), minval(ypair_2))
yup = min(maxval(ypair_1), maxval(ypair_2))
if ( &
(xlow <= x_cross) .and. (x_cross <= xup) .and. &
(ylow <= y_cross) .and. (y_cross <= yup) &
) then
print *, "CROSS:", i, j, x_cross, y_cross
if ((abs(x_cross - crossings(n)%x) < 0.1) .and. &
(abs(y_cross - crossings(n)%y) < 0.1)) then
print *, "CROSS: Repeated cross, skipping..."
cycle
end if
current_cross = cross(x_cross, y_cross, i, j)
n = n + 1
crossings = [crossings, current_cross]
end if
end do
end do
end subroutine find_cross