You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
6.1 KiB
Python

#
import scipy.interpolate
import numpy as np
import copy
import math
repose_angle=34 #angle of repose of sand
repose_slope=1/math.tan(math.radians(repose_angle))
def insertZerochainage(chainage, elevation):
#this inserts a 0 every time the profile crosses the axis
#need to update the chainage elevation for every point that drops below the required chainage
ii=0
while ii<len(elevation):
if ii==0 and elevation[ii]<0:
while elevation[ii]<0:
ii=ii+1
try:
beachslope = 1/((elevation[ii-1] - elevation[ii])/(chainage[ii] - chainage[ii-1]))
except:
beachslope= 999
chainageX= (elevation[ii-1]-0)*beachslope+chainage[ii-1]
elevation.insert(ii,0)
chainage.insert(ii,chainageX)
ii=ii+1
if elevation[ii]<0:
try:
beachslope = 1/((elevation[ii-1] - elevation[ii])/(chainage[ii] - chainage[ii-1]))
except ZeroDivisionError:
beachslope= 999
chainageX= (elevation[ii-1]-0)*beachslope+chainage[ii-1]
elevation.insert(ii,0)
chainage.insert(ii,chainageX)
ii=ii+1
try:
#finding where it crosses back over zero. If you reach the end of the list, return the list
while elevation[ii]<0:
ii=ii+1
try:
beachslope = 1/((elevation[ii-1] - elevation[ii])/(chainage[ii] - chainage[ii-1]))
except ZeroDivisionError:
beachslope= 999
chainageX= (elevation[ii-1]-0)*beachslope+chainage[ii-1]
elevation.insert(ii,0)
chainage.insert(ii,chainageX)
ii=ii+1
except IndexError:
return chainage, elevation
else:
ii=ii+1
return chainage, elevation
def custom_trap_rule(elevation,chainage):
#so that it doesn't count any volume below zero as a negative
#add a zero point every time the profile crosses the axis (note that the seaward zero has already been inserted)
x,y=insertZerochainage(copy.copy(chainage), copy.copy(elevation))
# add the final 0
x,y = findZerochainage(x,y)
i=1
area=0
while i<len(y):
if y[i]>=0 and y[i-1]>=0:
area=area+0.5*(x[i]-x[i-1])*(y[i]+y[i-1])
i=i+1
return area
def findIntersection(x11,y11,x12,y12,x21,y21,x22,y22):
#find the intersection of a two lines defined by four points
try:
m1=(y12-y11)/(x12-x11)
b1=y11-m1*x11
except (ZeroDivisionError,FloatingPointError):
x_inter=x11
m2=(y22-y21)/(x22-x21)
b2=y21-m2*x21
y_inter=m2*x_inter+b2
return x_inter, y_inter
try:
m2=(y22-y21)/(x22-x21)
b2=y21-m2*x21
except (ZeroDivisionError, FloatingPointError):
x_inter=x21
y_inter=m1*x_inter +b1
return x_inter, y_inter
x_inter=(b2-b1)/(m1-m2)
y_inter=m1*x_inter+b1
return x_inter, y_inter
def findZerochainage(chainage0, elevation0, max_beach_slope=5, min_beach_slope=50):
#often the photogrammetry has a repeated point at the end. Check for this and remove extra if required
while chainage0[-1]==chainage0[-2] and elevation0[-1]==elevation0[-2]:
chainage0 = chainage0[:-1]
elevation0 = elevation0[:-1]
#check if the profile ever goes below zero
ii=len(elevation0)-1
below_0=False
while ii>len(elevation0)/2:
if elevation0[ii]<0:
below_0=True
while elevation0[ii]<0:
ii=ii-1
j=ii+1 #so you don't have to search for this again
ii=0
else:
ii=ii-1
# if Below_0 = True, we can use the actual zero value
if below_0==True:
chainage0=chainage0[0:j+1]
elevation0=elevation0[0:j+1]
elevation_inter=scipy.interpolate.interp1d(elevation0[-2:],chainage0[-2:])
chainage_0=float(elevation_inter(0))
chainage0[j]=chainage_0
elevation0[j]=0
#otherwise need to extrapolate
else:
#find the slope between the last two points
try:
np.seterr(all='ignore')
beachslope = 1/((elevation0[-2] - elevation0[-1])/(chainage0[-1] - chainage0[-2]))
np.seterr(all=None)
except ZeroDivisionError:
beachslope= 999
if beachslope>min_beach_slope:
beachslope = min_beach_slope
elif beachslope<max_beach_slope:
beachslope = max_beach_slope
chainageX=(elevation0[-1])*beachslope+chainage0[-1]
if chainageX!=chainage0[-1]:
chainage0.append(chainageX)
elevation0.append(0)
return chainage0,elevation0
def insert_LL(chainage, elevation, LL):
# insert an additional element to make LL an actual point
elev_intr=scipy.interpolate.interp1d(chainage, elevation, fill_value='extrapolate')
elev_LL=float(elev_intr(LL))
data=[[chainage[i], elevation[i]] for i in range(0, len(chainage))]
data.append([LL,elev_LL])
data.sort()
chainage=[data[i][0] for i in range(0, len(data))]
elevation=[data[i][1] for i in range(0, len(data))]
return chainage, elevation, elev_LL
def volume_available (chainage, elevation, LL):
chainage, elevation, LL_z = insert_LL(chainage, elevation, LL)
index_LL=0
while chainage[index_LL]!=LL:
index_LL=index_LL+1
bottom_ZSA_x = LL + LL_z/repose_slope
bottom_ZSA_y=0
mid_ZWI_x= LL+(LL_z - 2)/(2*math.tan(math.radians(repose_angle)))
mid_ZWI_y = 2
bottom_ZWI_x=mid_ZWI_x+ mid_ZWI_y*10
bottom_ZWI_y = 0
x,y=findIntersection(LL,LL_z,bottom_ZSA_x,bottom_ZSA_y, mid_ZWI_x, mid_ZWI_y, bottom_ZWI_x, bottom_ZWI_y )
V1=custom_trap_rule(elevation[index_LL:], chainage[index_LL:])
V2=custom_trap_rule([ LL_z,mid_ZWI_y, bottom_ZWI_y],[LL,mid_ZWI_x,bottom_ZWI_x])
volume=V1-V2
return volume