def nearLocateMesh(xyo, IKLE, MESHX, MESHY, tree=None): """ Requires the scipy.spatial and the matplotlib.tri packages to be loaded. - Will use already computed tree or re-create it if necessary. - Will use already computed neighbourhood or re-create it if necessary. This function return the element number for the triangle including xyo=(xo,yo) or -1 if the (xo,yo) is outside the mesh Return: the element, the barycentric weights, and the tree and the neighbourhood if computed """ # ~~> Create the KDTree of the iso-barycentres if tree == None: isoxy = np.column_stack((np.sum(MESHX[IKLE], axis=1) / 3.0, np.sum(MESHY[IKLE], axis=1) / 3.0)) tree = cKDTree(isoxy) # ~~> Find the indices corresponding to the nearest elements to the points inear = -1 for d, i in zip(*tree.query(xyo, 8)): ax, bx, cx = MESHX[IKLE[i]] ay, by, cy = MESHY[IKLE[i]] w = isInsideTriangle(xyo, (ax, ay), (bx, by), (cx, cy), nomatter=True) if w != []: return i, w, tree if inear < 0: inear = i dnear = d if dnear > d: inear = i dnear = d # ~~> Find the indices and weights corresponding to the element containing the point ax, bx, cx = MESHX[IKLE[inear]] ay, by, cy = MESHY[IKLE[inear]] return inear, isInsideTriangle(xyo, (ax, ay), (bx, by), (cx, cy), nomatter=False), tree
def nearLocateMesh(xyo,IKLE,MESHX,MESHY,tree=None): """ Requires the scipy.spatial and the matplotlib.tri packages to be loaded. - Will use already computed tree or re-create it if necessary. - Will use already computed neighbourhood or re-create it if necessary. This function return the element number for the triangle including xyo=(xo,yo) or -1 if the (xo,yo) is outside the mesh Return: the element, the barycentric weights, and the tree and the neighbourhood if computed """ # ~~> Create the KDTree of the iso-barycentres if tree == None: isoxy = np.column_stack((np.sum(MESHX[IKLE],axis=1)/3.0,np.sum(MESHY[IKLE],axis=1)/3.0)) tree = cKDTree(isoxy) # ~~> Find the indices corresponding to the nearest elements to the points inear = -1 for d,i in zip(*tree.query(xyo,8)): ax,bx,cx = MESHX[IKLE[i]] ay,by,cy = MESHY[IKLE[i]] w = isInsideTriangle( xyo,(ax,ay),(bx,by),(cx,cy),nomatter=True ) if w != []: return i,w,tree if inear < 0: inear = i dnear = d if dnear > d: inear = i dnear = d # ~~> Find the indices and weights corresponding to the element containing the point ax,bx,cx = MESHX[IKLE[inear]] ay,by,cy = MESHY[IKLE[inear]] return inear,isInsideTriangle( xyo,(ax,ay),(bx,by),(cx,cy),nomatter=False ),tree
def traceRay2XY(IKLE,MESHX,MESHY,neighbours,ei,xyi,en,xyn): """ This assumes that you cannot go back on your ray. """ # ~~> latest addition to the ray ax,bx,cx = MESHX[IKLE[en]] ay,by,cy = MESHY[IKLE[en]] bi = getBarycentricWeights( xyi,(ax,ay),(bx,by),(cx,cy) ) pnt = {'n':1, 'xy':[xyi], 'e':[en], 'b':[bi], 'd':[np.power(xyi[0]-xyn[0],2) + np.power(xyi[1]-xyn[1],2)]} # ~~> convergence on distance to target xyn accuracy = np.power(10.0, -5+np.floor(np.log10(abs(ax+bx+cx+ay+by+cy)))) if pnt['d'][0] < accuracy: return True,pnt # ~~> get the ray through to the farthest neighbouring edges ks = []; ds = [] for k in [0,1,2]: xyj = getSegmentIntersection( (MESHX[IKLE[en][k]],MESHY[IKLE[en][k]]),(MESHX[IKLE[en][(k+1)%3]],MESHY[IKLE[en][(k+1)%3]]),xyi,xyn ) if xyj == []: continue # there are no intersection with that edges ej = neighbours[en][k] if ej == ei: continue # you should not back track on your ray xyj = xyj[0] dij = np.power(xyi[0]-xyj[0],2) + np.power(xyi[1]-xyj[1],2) ks.append(k) ds.append(dij) if ds != []: k = ks[np.argmax(ds)] ej = neighbours[en][k] xyj = getSegmentIntersection( (MESHX[IKLE[en][k]],MESHY[IKLE[en][k]]),(MESHX[IKLE[en][(k+1)%3]],MESHY[IKLE[en][(k+1)%3]]),xyi,xyn )[0] djn = np.power(xyn[0]-xyj[0],2) + np.power(xyn[1]-xyj[1],2) # ~~> Possible recursive call if True or djn > accuracy: # /!\ this may be a problem if ej < 0: # you have reach the end of the line bj = getBarycentricWeights( xyj,(ax,ay),(bx,by),(cx,cy) ) pnt['n'] += 1; pnt['xy'].insert(0,xyj); pnt['e'].insert(0,en); pnt['b'].insert(0,bj); pnt['d'].insert(0,djn) return djn<accuracy,pnt else: found,ray = traceRay2XY(IKLE,MESHX,MESHY,neighbours,en,xyj,ej,xyn) ray['n'] += 1; ray['xy'].append(xyi); ray['e'].append(en); ray['b'].append(bi); ray['d'].append(dij) return found,ray # ~~> convergence on having found the appropriate triangle bn = isInsideTriangle( xyn,(ax,ay),(bx,by),(cx,cy) ) if bn != []: pnt['n'] += 1; pnt['xy'].insert(0,xyn); pnt['e'].insert(0,en); pnt['b'].insert(0,bn); pnt['d'].insert(0,0.0) return True,pnt # ~~> you should not be here ! return False,pnt
def traceRay2XY(IKLE, MESHX, MESHY, neighbours, ei, xyi, en, xyn): """ This assumes that you cannot go back on your ray. """ # ~~> latest addition to the ray ax, bx, cx = MESHX[IKLE[en]] ay, by, cy = MESHY[IKLE[en]] bi = getBarycentricWeights(xyi, (ax, ay), (bx, by), (cx, cy)) pnt = { 'n': 1, 'xy': [xyi], 'e': [en], 'b': [bi], 'd': [np.power(xyi[0] - xyn[0], 2) + np.power(xyi[1] - xyn[1], 2)] } # ~~> convergence on distance to target xyn accuracy = np.power( 10.0, -5 + np.floor(np.log10(abs(ax + bx + cx + ay + by + cy)))) if pnt['d'][0] < accuracy: return True, pnt # ~~> get the ray through to the farthest neighbouring edges ks = [] ds = [] for k in [0, 1, 2]: xyj = getSegmentIntersection( (MESHX[IKLE[en][k]], MESHY[IKLE[en][k]]), (MESHX[IKLE[en][(k + 1) % 3]], MESHY[IKLE[en][(k + 1) % 3]]), xyi, xyn) if xyj == []: continue # there are no intersection with that edges ej = neighbours[en][k] if ej == ei: continue # you should not back track on your ray xyj = xyj[0] dij = np.power(xyi[0] - xyj[0], 2) + np.power(xyi[1] - xyj[1], 2) ks.append(k) ds.append(dij) if ds != []: k = ks[np.argmax(ds)] ej = neighbours[en][k] xyj = getSegmentIntersection( (MESHX[IKLE[en][k]], MESHY[IKLE[en][k]]), (MESHX[IKLE[en][(k + 1) % 3]], MESHY[IKLE[en][(k + 1) % 3]]), xyi, xyn)[0] djn = np.power(xyn[0] - xyj[0], 2) + np.power(xyn[1] - xyj[1], 2) # ~~> Possible recursive call if True or djn > accuracy: # /!\ this may be a problem if ej < 0: # you have reach the end of the line bj = getBarycentricWeights(xyj, (ax, ay), (bx, by), (cx, cy)) pnt['n'] += 1 pnt['xy'].insert(0, xyj) pnt['e'].insert(0, en) pnt['b'].insert(0, bj) pnt['d'].insert(0, djn) return djn < accuracy, pnt else: found, ray = traceRay2XY(IKLE, MESHX, MESHY, neighbours, en, xyj, ej, xyn) ray['n'] += 1 ray['xy'].append(xyi) ray['e'].append(en) ray['b'].append(bi) ray['d'].append(dij) return found, ray # ~~> convergence on having found the appropriate triangle bn = isInsideTriangle(xyn, (ax, ay), (bx, by), (cx, cy)) if bn != []: pnt['n'] += 1 pnt['xy'].insert(0, xyn) pnt['e'].insert(0, en) pnt['b'].insert(0, bn) pnt['d'].insert(0, 0.0) return True, pnt # ~~> you should not be here ! return False, pnt