Source code for svcco.collision.collision

import numpy as np
import numba as nb
import vtk
import time
from .sphere_proximity import *
from copy import deepcopy
from .obb import *
"""
@nb.jit(nopython=True)
def separating_axis(position,plane,U1,V1,W1,U2,V2,W2,U1_scale,
                    V1_scale,W1_scale,U2_scale,V2_scale,W2_scale):
    return np.abs(np.dot(position,plane)) > (np.abs(np.dot(U1*U1_scale,plane))+
                                             np.abs(np.dot(V1*V1_scale,plane))+
                                             np.abs(np.dot(W1*W1_scale,plane))+
                                             np.abs(np.dot(U2*U2_scale,plane))+
                                             np.abs(np.dot(V2*V2_scale,plane))+
                                             np.abs(np.dot(W2*W2_scale,plane)))
"""
"""
#@nb.jit(nopython=True)
def obb2(data,edge):
    C1 = (edge[0:3] + edge[3:6]) / 2
    C2 = (data[:,0:3] + data[:,3:6]) / 2
    Position = C2 - C1

    # Basis vector construction
    edge[12:15] = ((edge[3:6] - edge[0:3]) /
                   np.linalg.norm(edge[3:6] -
                                  edge[0:3]))
    if edge[14] == -1:
        edge[6:9] = np.array([-1,0,0])
        edge[9:12] = np.array([0,-1,0])
    else:
        edge[6:9] = np.array([1-edge[12]**2/(1+edge[14]),
                              (-edge[12]*edge[13])/(1+edge[14]),
                              -edge[12]])
        edge[9:12] = np.array([(-edge[12]*edge[13])/(1+edge[14]),
                               1 - edge[13]**2/(1+edge[14]),
                               -edge[13]])
    result = []
    for i in range(data.shape[0]):
        # U1 axis
        if separating_axis(Position[i,:],edge[6:9],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # V1 axis
        if separating_axis(Position[i,:],edge[9:12],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # W1 axis
        if separating_axis(Position[i,:],edge[12:15],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # U2 axis
        if separating_axis(Position[i,:],data[i,6:9],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # V2 axis
        if separating_axis(Position[i,:],data[i,9:12],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # W2 axis
        if separating_axis(Position[i,:],data[i,12:15],edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # Mixed Plane Separation Tests
        # U1 X U2
        plane = np.cross(edge[6:9],data[i,6:9])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # U1 X V2
        plane = np.cross(edge[6:9],data[i,9:12])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # U1 X W2
        plane = np.cross(edge[6:9],data[i,12:15])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # V1 X U2
        plane = np.cross(edge[9:12],data[i,6:9])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # V1 X V2
        plane = np.cross(edge[9:12],data[i,9:12])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # V1 X W2
        plane = np.cross(edge[9:12],data[i,12:15])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # W1 X U2
        plane = np.cross(edge[12:15],data[i,6:9])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # W1 X V2
        plane = np.cross(edge[12:15],data[i,9:12])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        # W1 X W2
        plane = np.cross(edge[12:15],data[i,12:15])
        if separating_axis(Position[i,:],plane,edge[6:9],edge[9:12],edge[12:15],
                           data[i,6:9],data[i,9:12],data[i,12:15],edge[21],edge[21],
                           edge[20]/2,data[i,21],data[i,21],data[i,20]/2):
            result.append(False)
            continue
        else:
            pass
            #return True
    return False
"""

[docs]def collision_free(data,results,idx,terminal,vessel,radius_buffer): # proximal = 0 # distal = 1 # terminal = 2 new_vessels = np.ones((3,data.shape[1]))*-1 new_vessels[0,0:3] = data[vessel,0:3] new_vessels[0,3:6] = results[5][idx] new_vessels[0,-1] = data[vessel,-1] if vessel == 0: new_vessels[0,21] = results[0][idx] + radius_buffer else: new_vessels[0,21] = results[0][idx]*results[4][idx] + radius_buffer new_vessels[0,17] = data[vessel,17] new_vessels[1,0:3] = results[5][idx] new_vessels[1,3:6] = data[vessel,3:6] new_vessels[1,21] = results[0][idx]*results[3][idx] + radius_buffer new_vessels[1,15:17] = data[vessel,15:17] new_vessels[1,17] = np.float(vessel) new_vessels[2,0:3] = results[5][idx] new_vessels[2,3:6] = terminal new_vessels[2,21] = results[0][idx]*results[2][idx] + radius_buffer new_vessels[2,17] = np.float(vessel) #print(new_vessels[:,-1]) vessel_parent = data[vessel,17] vessel_child1 = data[vessel,15] vessel_child2 = data[vessel,16] vessel_sister_i = data[int(vessel_parent),15] vessel_sister_j = data[int(vessel_parent),16] for i in range(new_vessels.shape[0]): ##Check Self #start = time.time() n = sphere_proximity(data,new_vessels[i,:]) #print(time.time()-start) if len(np.argwhere(n==vessel)) > 0: n = np.delete(n,np.argwhere(n==vessel).flatten()) if len(np.argwhere(n==int(vessel_parent))) > 0: n = np.delete(n,np.argwhere(n==int(vessel_parent)).flatten()) if len(np.argwhere(n==int(vessel_child1))) > 0: n = np.delete(n,np.argwhere(n==int(vessel_child1)).flatten()) if len(np.argwhere(n==int(vessel_child2))) > 0: n = np.delete(n,np.argwhere(n==int(vessel_child2)).flatten()) if len(np.argwhere(n==int(vessel_sister_i))) > 0: n = np.delete(n,np.argwhere(n==int(vessel_sister_i)).flatten()) if len(np.argwhere(n==int(vessel_sister_j))) > 0: n = np.delete(n,np.argwhere(n==int(vessel_sister_j)).flatten()) if len(np.argwhere(n==int(new_vessels[i,-1]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,-1])).flatten()) #print('self') #Check Parent if len(np.argwhere(n==int(new_vessels[i,17]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,17])).flatten()) #print('parent') #Check Children if len(np.argwhere(n==int(new_vessels[i,15]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,15])).flatten()) #print('children') if len(np.argwhere(n==int(new_vessels[i,16]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,16])).flatten()) #print('children') #Check Sister if int(new_vessels[i,17]) != -1: parent = int(new_vessels[i,17]) if len(np.argwhere(n==int(data[parent,15]))) > 0: n = np.delete(n,np.argwhere(n==int(data[parent,15])).flatten()) if len(np.argwhere(n==int(data[parent,16]))) > 0: n = np.delete(n,np.argwhere(n==int(data[parent,16])).flatten()) #print('sister') #else: # if len(np.argwhere(n==int(new_vessels[i,-1]))) > 0: # n = np.delete(n,np.argwhere(n==int(new_vessels[i,-1])).flatten()) if len(n) == 0: continue else: if obb(data[n,:],new_vessels[i,:]): #print(n) #print(new_vessels[:,-1]) """ colors = vtk.vtkNamedColors() models = [] actors = [] background_color='white' resolution=100 center = tuple((new_vessels[i,0:3] + new_vessels[i,3:6])/2) radius = new_vessels[i,21] direction = tuple(new_vessels[i,12:15]) vessel_length = new_vessels[i,20] cyl = vtk.vtkTubeFilter() line = vtk.vtkLineSource() line.SetPoint1(new_vessels[i,0],new_vessels[i,1],new_vessels[i,2]) line.SetPoint2(new_vessels[i,3],new_vessels[i,4],new_vessels[i,5]) cyl.SetInputConnection(line.GetOutputPort()) cyl.SetRadius(radius) cyl.SetNumberOfSides(resolution) models.append(cyl) mapper = vtk.vtkPolyDataMapper() actor = vtk.vtkActor() mapper.SetInputConnection(cyl.GetOutputPort()) actor.SetMapper(mapper) actor.GetProperty().SetColor(colors.GetColor3d('green')) actors.append(actor) for edge in n: center = tuple((data[edge,0:3] + data[edge,3:6])/2) radius = data[edge,21] direction = tuple(data[edge,12:15]) vessel_length = data[edge,20] cyl = vtk.vtkTubeFilter() line = vtk.vtkLineSource() line.SetPoint1(data[edge,0],data[edge,1],data[edge,2]) line.SetPoint2(data[edge,3],data[edge,4],data[edge,5]) cyl.SetInputConnection(line.GetOutputPort()) cyl.SetRadius(radius) cyl.SetNumberOfSides(resolution) models.append(cyl) mapper = vtk.vtkPolyDataMapper() actor = vtk.vtkActor() mapper.SetInputConnection(cyl.GetOutputPort()) actor.SetMapper(mapper) if edge in n: #print('True') actor.GetProperty().SetColor(colors.GetColor3d('blue')) if edge == int(new_vessels[i,-1]): print(edge) actor.GetProperty().SetColor(colors.GetColor3d('green')) else: actor.GetProperty().SetColor(colors.GetColor3d('red')) actors.append(actor) renderer = vtk.vtkRenderer() renderer.SetBackground(colors.GetColor3d(background_color)) render_window = vtk.vtkRenderWindow() render_window.AddRenderer(renderer) render_window.SetWindowName('SimVascular Vessel Collision') interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(render_window) for actor in actors: renderer.AddActor(actor) render_window.Render() interactor.Start() """ return False return True
[docs]def no_outside_collision(tree,outside_vessels,radius_buffer=0): outside_vessels[:,21] += radius_buffer for i in range(outside_vessels.shape[0]): n = sphere_proximity(tree.data,outside_vessels[i,:]) if len(n) == 0: continue else: if obb(tree.data[n,:],outside_vessels[i,:]): return False return True
[docs]def collision_free_fd(data,vessel): ii = np.array(list(range(data.shape[0]-2))) ii = ii[ii!=vessel] tree = data[:-2,:] new = data[-2:,:] proximal = data[vessel,:] new_vessels = np.vstack((new,proximal)) for i in range(new_vessels.shape[0]): ##Check Self n = sphere_proximity(tree,new_vessels[i,:]) if len(np.argwhere(n==int(new_vessels[i,-1]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,-1])).flatten()) #Check Parent if len(np.argwhere(n==int(new_vessels[i,17]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,17])).flatten()) #Check Children if len(np.argwhere(n==int(new_vessels[i,15]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,15])).flatten()) if len(np.argwhere(n==int(new_vessels[i,16]))) > 0: n = np.delete(n,np.argwhere(n==int(new_vessels[i,16])).flatten()) #Check Sister if int(new_vessels[i,17]) != -1: parent = int(new_vessels[i,17]) if len(np.argwhere(n==int(data[parent,15]))) > 0: n = np.delete(n,np.argwhere(n==int(data[parent,15])).flatten()) if len(np.argwhere(n==int(data[parent,16]))) > 0: n = np.delete(n,np.argwhere(n==int(data[parent,16])).flatten()) #else: # if len(np.argwhere(n==int(new_vessels[i,-1]))) > 0: # n = np.delete(n,np.argwhere(n==int(new_vessels[i,-1])).flatten()) if len(n) == 0: continue else: if obb(tree[n,:],new_vessels[i,:]): """ colors = vtk.vtkNamedColors() models = [] actors = [] background_color='white' resolution=100 for edge in range(new_vessels.shape[0]): center = tuple((new_vessels[edge,0:3] + new_vessels[edge,3:6])/2) radius = new_vessels[edge,21] direction = tuple(new_vessels[edge,12:15]) vessel_length = new_vessels[edge,20] cyl = vtk.vtkTubeFilter() line = vtk.vtkLineSource() line.SetPoint1(new_vessels[edge,0],new_vessels[edge,1],new_vessels[edge,2]) line.SetPoint2(new_vessels[edge,3],new_vessels[edge,4],new_vessels[edge,5]) cyl.SetInputConnection(line.GetOutputPort()) cyl.SetRadius(radius) cyl.SetNumberOfSides(resolution) models.append(cyl) mapper = vtk.vtkPolyDataMapper() actor = vtk.vtkActor() mapper.SetInputConnection(cyl.GetOutputPort()) actor.SetMapper(mapper) actor.GetProperty().SetColor(colors.GetColor3d('red')) actors.apend(actor) for edge in n: center = tuple((data[edge,0:3] + data[edge,3:6])/2) radius = data[edge,21] direction = tuple(data[edge,12:15]) vessel_length = data[edge,20] cyl = vtk.vtkTubeFilter() line = vtk.vtkLineSource() line.SetPoint1(data[edge,0],data[edge,1],data[edge,2]) line.SetPoint2(data[edge,3],data[edge,4],data[edge,5]) cyl.SetInputConnection(line.GetOutputPort()) cyl.SetRadius(radius) cyl.SetNumberOfSides(resolution) models.append(cyl) mapper = vtk.vtkPolyDataMapper() actor = vtk.vtkActor() mapper.SetInputConnection(cyl.GetOutputPort()) actor.SetMapper(mapper) if edge in n: actor.GetProperty().SetColor(colors.GetColor3d('blue')) if edge == int(new_vessels[i,-1]): actor.GetProperty().SetColor(colors.GetColor3d('green')) else: actor.GetProperty().SetColor(colors.GetColor3d('red')) actors.append(actor) renderer = vtk.vtkRenderer() renderer.SetBackground(colors.GetColor3d(background_color)) render_window = vtk.vtkRenderWindow() render_window.AddRenderer(renderer) render_window.SetWindowName('SimVascular Vessel Collision') interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(render_window) for actor in actors: renderer.AddActor(actor) render_window.Render() interactor.Start() """ return False return True
[docs]def line_distance(data,edge): a = np.sum((data[:,3:6]-data[:,0:3])*(data[:,3:6]-data[:,0:3]),axis=1) b = np.dot(data[:,3:6]-data[:,0:3],edge[3:6].T-edge[0:3].T) c = np.dot(edge[3:6]-edge[0:3],edge[3:6].T-edge[0:3].T) d = np.sum((data[:,3:6]-data[:,0:3])*(data[:,0:3]-edge[0:3]),axis=1) e = np.dot(edge[3:6]-edge[0:3],(data[:,0:3]-edge[0:3]).T) f00 = d f10 = f00 + a f01 = f00 + b f11 = f10 - b g00 = -e g10 = g00 - b g01 = g00 + c g11 = g10 + c p0 = np.zeros((len(f00),3)) p1 = np.zeros((len(f00),3)) dist = np.zeros((len(f00),1)) for j in range(len(f00)): if a[j] > 0 and c > 0: s = [0,0] s[0] = clamped_root(a[j],f00[j],f10[j]) s[1] = clamped_root(a[j],f01[j],f11[j]) idd = [0,0] parameters = [0,0] for ii in range(2): if s[ii] <= 0: idd[ii] = -1 elif s[ii] >= 1: idd[ii] = 1 else: idd[ii] = 0 if idd[0] == -1 and idd[1] == -1: parameters[0] = 0 parameters[1] = clamped_root(c,g00[j],g01[j]) elif idd[0] == 1 and idd[0] == 1: parameters[0] = 1 parameters[1] = clamped_root(c,g10[j],g11[j]) else: ed,M = line_intersection(s,idd,f10=f10[j],f00=f00[j],b=b[j]) parameters = find_minimum(ed,M,b=b[j],c=c,e=e[j],g00=g00[j], g01=g01[j],g10=g10[j],g11=g11[j]) else: if a[j] > 0: parameters[0] = clamped_root(a[j],f00[j],f10[j]) parameters[1] = 0 elif c > 0: parameters[0] = 0 parameters[1] = clamped_root(c,g00[j],g01[j]) else: parameters[0] = 0 parameters[0] = 0 p0[j,:] = (1 - parameters[0])*data[j,0:3] + parameters[0]*data[j,3:6] p1[j,:] = (1 - parameters[1])*edge[0:3] + parameters[1]*edge[3:6] dist[j] = np.sqrt(np.sum(np.square(p0[j,:]-p1[j,:]))) return p0,p1,dist
[docs]def clamped_root(slope,h0,h1): if h0 < 0: if h1 > 0: r = -h0/slope if r > 1: r = 0.5 else: r = 1 else: r = 0 return r
[docs]def line_intersection(s,id,f10=None,f00=None,b=None): edge = [0,0] M = np.zeros((2,2)) if id[0] < 0: edge[0] = 0 M[0,0] = 0 M[0,1] = f00/b if M[0,1] < 0 or M[0,1] > 1: M[0,1] = 0.5 if id[1] == 0: edge[1] = 3 M[1,0] = s[1] M[1,1] = 1 else: edge[1] = 1 M[1,0] = 1 M[1,1] = f10/b if M[1,1] < 0 or M[1,1] > 1: M[1,1] = 0.5 elif id[0] == 0: edge[0] = 2 M[0,0] = s[0] M[0,1] = 0 if id[1] < 0: edge[1] = 0 M[1,0] = 0 M[1,1] = f00/b if M[1,1] < 0 or M[1,1] > 1: M[1,1] = 0.5 elif id[1] == 0: edge[1] = 3 M[1,0] = s[1] M[1,1] = 1 else: edge[1] = 1 M[1,0] = 1 M[1,1] = f10/b if M[1,1] < 0 or M[1,1] > 1: M[1,1] = 0.5 else: edge[0] = 1 M[0,0] = 1 M[0,1] = f10/b if M[0,1] < 0 or M[0,1] > 1: M[0,1] = 0.5 if id[1] == 0: edge[1] = 3 M[1,0] = s[1] M[1,1] = 1 else: edge[1] = 0 M[1,0] = 0 M[1,1] = f00/b if M[1,1] < 0 or M[1,1] > 1: M[1,1] = 0.5 return edge, M
[docs]def find_minimum(edge,M,b=None,c=None,e=None, g00=None,g01=None,g10=None,g11=None): delta = M[1,1] - M[0,1] h0 = delta * (-b * M[0,0] + c*M[0,1] - e) parameters = [0,0] if h0 >= 0: if edge[0] == 0: parameters[0] = 0 parameters[1] = clamped_root(c,g00,g01) elif edge[0] == 1: parameters[0] = 1 parameters[1] = clamped_root(c,g10,g11) else: parameters[0] = M[0,0] parameters[1] = M[0,1] else: h1 = delta*(-b * M[1,0] + c*M[1,1] - e) if h1 <= 0: if edge[1] == 0: parameters[0] = 0 parameters[1] = clamped_root(c,g00,g01) elif edge[1] == 1: parameters[0] = 1 parameters[1] = clamped_root(c,g10,g11) else: parameters[0] = M[1,0] parameters[1] = M[1,1] else: k = min(max(h0/(h0-h1),0),1) mk = 1 - k parameters[0] = mk*M[0,0]+k*M[1,0] parameters[1] = mk*M[0,1]+k*M[1,1] return parameters
[docs]def pairwise_tree_collisions(tree1_data,tree2_data,radius_buffer=0): outside_vessels = deepcopy(tree2_data) outside_vessels[:,21] += radius_buffer pairs = [] for i in range(outside_vessels.shape[0]): n = sphere_proximity(tree1_data,outside_vessels[i,:]) if len(n) == 0: continue else: results = obbc(tree1_data[n,:],outside_vessels[i,:]) if len(results) == 0: continue else: for r in results: pairs.append([r,i]) return pairs
[docs]def fix_suggestions(tree1_data,tree2_data,radius_buffer=0): pairs = pairwise_tree_collisions(tree1_data,tree2_data,radius_buffer=radius_buffer) pair_points = [] pair_lengths = [] pair_adjustment = [] pair_vectors = [] for pr in pairs: p0,p1,length = line_distance(tree1_data[pr[0],:].reshape(1,-1),tree2_data[pr[1],:]) pair_points.append([p0,p1]) pair_lengths.append(length) pair_adjustment.append([abs(tree1_data[pr[0],21]+tree2_data[pr[1],21]+radius_buffer)/2, abs(tree1_data[pr[0],21]+tree2_data[pr[1],21]+radius_buffer)/2]) pair_vectors.append([(p0-p1)/np.linalg.norm(p0-p1),(p1-p0)/np.linalg.norm(p1-p0)]) return pairs,pair_points,pair_lengths,pair_adjustment,pair_vectors