Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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