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 sliceMesh(polyline, IKLE, MESHX, MESHY, tree=None): """ A new method to slice through a triangular mesh (replaces crossMesh) """ from matplotlib.tri import Triangulation xys = [] douplets = [] # ~~> Calculate the minimum mesh resolution dxy = math.sqrt(min(np.square(np.sum(np.fabs(MESHX[IKLE]-MESHX[np.roll(IKLE,1)]),axis=1)/3.0) + \ np.square(np.sum(np.fabs(MESHY[IKLE]-MESHY[np.roll(IKLE,1)]),axis=1)/3.0))) accuracy = np.power(10.0, -8 + np.floor(np.log10(dxy))) xyo = np.array(polyline[0]) for i in range(len(polyline) - 1): xyi = np.array(polyline[i + 1]) dio = math.sqrt(sum(np.square(xyo - xyi))) # ~~> Resample the line to that minimum mesh resolution rsmpline = np.dstack((np.linspace(xyo[0], xyi[0], num=int(dio / dxy)), np.linspace(xyo[1], xyi[1], num=int(dio / dxy))))[0] nbpoints = len(rsmpline) nbneighs = min(8, len(IKLE)) # ~~> Filter closest 8 elements (please create a good mesh) as a halo around the polyline halo = np.zeros((nbpoints, nbneighs), dtype=np.int) for i in range(nbpoints): d, e = tree.query(rsmpline[i], nbneighs) halo[i] = e halo = np.unique(halo) # ~~> Get the intersecting halo (on a smaller mesh connectivity) edges = Triangulation(MESHX, MESHY, IKLE[halo]).get_cpp_triangulation().get_edges() # ~~> Last filter, all nodes that are on the polyline olah = [] nodes = np.unique(edges) for node in nodes: # TODO(jcp): replace by numpy calcs if getDistancePointToLine( (MESHX[node], MESHY[node]), xyo, xyi) < accuracy: olah.append(node) ijsect = zip(olah, olah) xysect = [(MESHX[i], MESHY[i]) for i in olah] lmsect = [(1.0, 0.0) for i in range(len(ijsect))] mask = np.zeros((len(edges), 2), dtype=bool) for i in olah: mask = np.logical_or(edges == i, mask) edges = np.compress(np.logical_not(np.any(mask, axis=1)), edges, axis=0) # ~~> Intersection with remaining edges for edge in edges: xyj = getSegmentIntersection((MESHX[edge[0]], MESHY[edge[0]]), (MESHX[edge[1]], MESHY[edge[1]]), xyo, xyi) if xyj != []: ijsect.append(edge) # nodes from the mesh xysect.append(tuple(xyj[0])) # intersection (xo,yo) lmsect.append((xyj[1], 1.0 - xyj[1])) # weight along each each # ~~> Final sorting along keys x and y xysect = np.array(xysect, dtype=[('x', '<f4'), ('y', '<f4')]) xysort = np.argsort(xysect, order=('x', 'y')) # ~~> Move on to next point for i in xysort: xys.append(xysect[i]) douplets.append((ijsect[i], lmsect[i])) xyo = xyi return xys, douplets
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 sliceMesh(polyline,IKLE,MESHX,MESHY,tree=None): """ A new method to slice through a triangular mesh (replaces crossMesh) """ from matplotlib.tri import Triangulation xys = [] douplets = [] # ~~> Calculate the minimum mesh resolution dxy = math.sqrt(min(np.square(np.sum(np.fabs(MESHX[IKLE]-MESHX[np.roll(IKLE,1)]),axis=1)/3.0) + \ np.square(np.sum(np.fabs(MESHY[IKLE]-MESHY[np.roll(IKLE,1)]),axis=1)/3.0))) accuracy = np.power(10.0, -8+np.floor(np.log10(dxy))) xyo = np.array(polyline[0]) for i in range(len(polyline)-1): xyi = np.array(polyline[i+1]) dio = math.sqrt(sum(np.square(xyo-xyi))) # ~~> Resample the line to that minimum mesh resolution rsmpline = np.dstack((np.linspace(xyo[0],xyi[0],num=int(dio/dxy)),np.linspace(xyo[1],xyi[1],num=int(dio/dxy))))[0] nbpoints = len(rsmpline) nbneighs = min( 8,len(IKLE) ) # ~~> Filter closest 8 elements (please create a good mesh) as a halo around the polyline halo = np.zeros((nbpoints,nbneighs),dtype=np.int) for i in range(nbpoints): d,e = tree.query(rsmpline[i],nbneighs) halo[i] = e halo = np.unique(halo) # ~~> Get the intersecting halo (on a smaller mesh connectivity) edges = Triangulation(MESHX,MESHY,IKLE[halo]).get_cpp_triangulation().get_edges() # ~~> Last filter, all nodes that are on the polyline olah = [] nodes = np.unique(edges) for node in nodes: # TODO(jcp): replace by numpy calcs if getDistancePointToLine((MESHX[node],MESHY[node]),xyo,xyi) < accuracy: olah.append(node) ijsect = zip(olah,olah) xysect = [(MESHX[i],MESHY[i]) for i in olah] lmsect = [ (1.0,0.0) for i in range(len(ijsect)) ] mask = np.zeros((len(edges),2),dtype=bool) for i in olah: mask = np.logical_or( edges == i , mask ) edges = np.compress(np.logical_not(np.any(mask,axis=1)),edges,axis=0) # ~~> Intersection with remaining edges for edge in edges: xyj = getSegmentIntersection( (MESHX[edge[0]],MESHY[edge[0]]),(MESHX[edge[1]],MESHY[edge[1]]),xyo,xyi ) if xyj != []: ijsect.append(edge) # nodes from the mesh xysect.append(tuple(xyj[0])) # intersection (xo,yo) lmsect.append((xyj[1],1.0-xyj[1])) # weight along each each # ~~> Final sorting along keys x and y xysect = np.array(xysect, dtype=[('x', '<f4'), ('y', '<f4')]) xysort = np.argsort(xysect, order=('x','y')) # ~~> Move on to next point for i in xysort: xys.append( xysect[i] ) douplets.append( (ijsect[i],lmsect[i]) ) xyo = xyi return xys,douplets