Esempio n. 1
0
def voronoi(geometry, **kwargs):
    r"""
    Use the Voronoi verts and throat normals to work out the area
    """
    Nt = geometry.num_throats()
    verts = geometry['throat.offset_vertices']
    normals = geometry['throat.normal']
    area = _sp.ndarray(Nt)
    for i in range(Nt):
        if len(verts[i]) > 2:
            verts_2D = tr.rotate_and_chop(verts[i], normals[i], [0, 0, 1])
            area[i] = vo.PolyArea2D(verts_2D)
        else:
            area[i] = 0.0

    return area
Esempio n. 2
0
def voronoi(geometry,
            **kwargs):
    r"""
    Use the Voronoi verts and throat normals to work out the perimeter
    """
    Nt = geometry.num_throats()    
    verts = geometry['throat.offset_vertices']
    normals = geometry['throat.normal']
    perimeter = _sp.ndarray(Nt)
    for i in range(Nt):
        if len(verts[i]) > 2:
            verts_2D = tr.rotate_and_chop(verts[i],normals[i],[0,0,1])
            perimeter[i] = vo.PolyPerimeter2D(verts_2D)
        else:
            perimeter[i] = 0.0
    return perimeter
Esempio n. 3
0
def voronoi(geometry, **kwargs):
    r"""
    Use the Voronoi verts and throat normals to work out the perimeter
    """
    Nt = geometry.num_throats()
    verts = geometry['throat.offset_vertices']
    normals = geometry['throat.normal']
    perimeter = _sp.ndarray(Nt)
    for i in range(Nt):
        if len(verts[i]) > 2:
            verts_2D = tr.rotate_and_chop(verts[i], normals[i], [0, 0, 1])
            # Get in hull order
            hull = ConvexHull(verts_2D, qhull_options='QJ Pp')
            verts_2D = verts_2D[hull.vertices]
            perimeter[i] = vo.PolyPerimeter2D(verts_2D)
        else:
            perimeter[i] = 0.0
    return perimeter
Esempio n. 4
0
def print_throat(geom, throats_in):
    r"""
    Print a given throat or list of throats accepted as [1,2,3,...,n]
    e.g geom.print_throat([34,65,99])
    Original vertices plus offset vertices are rotated to align with
    the z-axis and then printed in 2D
    """
    import matplotlib.pyplot as plt
    throats = []
    for throat in throats_in:
        if throat in range(geom.num_throats()):
            throats.append(throat)
        else:
            print("Throat: " + str(throat) + " not part of geometry")
    if len(throats) > 0:
        verts = geom['throat.vertices'][throats]
        offsets = geom['throat.offset_vertices'][throats]
        #image_offsets = geom['throat.image_analysis'][throats]
        normals = geom['throat.normal'][throats]
        coms = geom['throat.centroid'][throats]
        incentre = geom['throat.incentre'][throats]
        inradius = 0.5 * geom['throat.indiameter'][throats]
        for i in range(len(throats)):
            fig = plt.figure()
            vert_2D = tr.rotate_and_chop(verts[i], normals[i], [0, 0, 1])
            hull = ConvexHull(vert_2D, qhull_options='QJ Pp')
            for simplex in hull.simplices:
                plt.plot(vert_2D[simplex, 0],
                         vert_2D[simplex, 1],
                         'k-',
                         linewidth=2)
            plt.scatter(vert_2D[:, 0], vert_2D[:, 1])
            #centroid = vo.PolyWeightedCentroid2D(vert_2D[hull.vertices])
            offset_2D = tr.rotate_and_chop(offsets[i], normals[i], [0, 0, 1])
            offset_hull = ConvexHull(offset_2D, qhull_options='QJ Pp')
            for simplex in offset_hull.simplices:
                plt.plot(offset_2D[simplex, 0],
                         offset_2D[simplex, 1],
                         'g-',
                         linewidth=2)
            plt.scatter(offset_2D[:, 0], offset_2D[:, 1])
            " Make sure the plot looks nice by finding the greatest range of points and setting the plot to look square"
            xmax = vert_2D[:, 0].max()
            xmin = vert_2D[:, 0].min()
            ymax = vert_2D[:, 1].max()
            ymin = vert_2D[:, 1].min()
            x_range = xmax - xmin
            y_range = ymax - ymin
            if (x_range > y_range):
                my_range = x_range
            else:
                my_range = y_range
            lower_bound_x = xmin - my_range * 0.5
            upper_bound_x = xmin + my_range * 1.5
            lower_bound_y = ymin - my_range * 0.5
            upper_bound_y = ymin + my_range * 1.5
            plt.axis(
                (lower_bound_x, upper_bound_x, lower_bound_y, upper_bound_y))
            plt.grid(b=True, which='major', color='b', linestyle='-')
            centroid = tr.rotate_and_chop(coms[i], normals[i], [0, 0, 1])
            incent = tr.rotate_and_chop(incentre[i], normals[i], [0, 0, 1])
            plt.scatter(centroid[0][0], centroid[0][1])
            #plt.scatter(centroid2[0],centroid2[1],c='r')
            "Plot incircle"
            t = np.linspace(0, 2 * np.pi, 200)
            u = inradius[i] * np.cos(t) + incent[0][0]
            v = inradius[i] * np.sin(t) + incent[0][1]
            plt.plot(u, v, 'r-')
            fig.show()
    else:
        print("Please provide throat indices")
Esempio n. 5
0
def plot_pore(geometry, pores, fig=None, axis_bounds=None, include_points=False):
    r"""
    Print all throats around a given pore or list of pores accepted
    as [1, 2, 3, ..., n]
    e.g vo.print_pore(geom, [34, 65, 99])
    Original vertices plus offset vertices used to create faces and
    then printed in 3D
    To print all pores (n)
    pore_range = np.arange(0,n-1,1)
    vo.print_pore(geom, pore_range)
    """
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    if len(pores) > 0:
        net_pores = geometry.map_pores(geometry._net, pores)
        centroids = geometry['pore.centroid'][pores]
        coords = geometry._net['pore.coords'][net_pores]
        net_throats = geometry._net.find_neighbor_throats(pores=net_pores)
        throats = geometry._net.map_throats(geometry,
                                            net_throats,
                                            return_mapping=True)['target']
        tcentroids = geometry["throat.centroid"][throats]
        # Can't create volume from one throat
        if 1 <= len(throats):
            verts = geometry['throat.vertices'][throats]
            normals = geometry['throat.normal'][throats]
            # Get verts in hull order
            ordered_verts = []
            for i in range(len(verts)):
                vert_2D = tr.rotate_and_chop(verts[i], normals[i], [0, 0, 1])
                hull = ConvexHull(vert_2D, qhull_options='QJ Pp')
                ordered_verts.append(verts[i][hull.vertices])
            offsets = geometry['throat.offset_vertices'][throats]
            ordered_offs = []
            for i in range(len(offsets)):
                offs_2D = tr.rotate_and_chop(offsets[i], normals[i], [0, 0, 1])
                offs_hull = ConvexHull(offs_2D, qhull_options='QJ Pp')
                ordered_offs.append(offsets[i][offs_hull.vertices])
            # Get domain extents for setting axis
            if axis_bounds is None:
                [xmin, xmax, ymin, ymax, zmin, zmax] = \
                    vertex_dimension(geometry._net, pores, parm='minmax')
            else:
                [xmin, xmax, ymin, ymax, zmin, zmax] = axis_bounds
            if fig is None:
                fig = plt.figure()
            ax = fig.gca(projection='3d')
            outer_items = Poly3DCollection(ordered_verts, linewidths=1,
                                           alpha=0.2, zsort='min')
            outer_face_colours = [(1, 0, 0, 0.01)]
            outer_items.set_facecolor(outer_face_colours)
            ax.add_collection(outer_items)
            inner_items = Poly3DCollection(ordered_offs, linewidths=1,
                                           alpha=0.2, zsort='min')
            inner_face_colours = [(0, 0, 1, 0.01)]
            inner_items.set_facecolor(inner_face_colours)
            ax.add_collection(inner_items)
            ax.set_xlim(xmin, xmax)
            ax.set_ylim(ymin, ymax)
            ax.set_zlim(zmin, zmax)
            if include_points:
                ax.scatter(centroids[:, 0], centroids[:, 1], centroids[:, 2], c='y')
                ax.scatter(tcentroids[:, 0], tcentroids[:, 1], tcentroids[:, 2],
                           c='r')
                ax.scatter(coords[:, 0], coords[:, 1], coords[:, 2], c='b')
            ax.ticklabel_format(style='sci', scilimits=(0, 0))

        else:
            plot_throat(geometry, throats, fig)
    else:
        print('Please provide pore indices')
    return fig
Esempio n. 6
0
def plot_throat(geometry, throats, fig=None):
    r"""
    Print a given throat or list of throats accepted as [1, 2, 3, ..., n]
    Original vertices plus offset vertices are rotated to align with
    the z-axis and then printed in 2D
    e.g vo.print_throat(geom, [34, 65, 99])
    """
    import matplotlib.pyplot as plt
    throat_list = []
    for throat in throats:
        if throat in range(geometry.num_throats()):
            throat_list.append(throat)
        else:
            print('Throat: ' + str(throat) + ' not part of geometry')
    if len(throat_list) > 0:
        verts = geometry['throat.vertices'][throat_list]
        offsets = geometry['throat.offset_vertices'][throat_list]
        normals = geometry['throat.normal'][throat_list]
        coms = geometry['throat.centroid'][throat_list]
        incentre = geometry['throat.incentre'][throat_list]
        inradius = 0.5*geometry['throat.indiameter'][throat_list]
        row_col = np.ceil(np.sqrt(len(throat_list)))
        for i in range(len(throat_list)):
            if fig is None:
                fig = plt.figure()
            ax = fig.add_subplot(row_col, row_col, i+1)
            vert_2D = tr.rotate_and_chop(verts[i], normals[i], [0, 0, 1])
            hull = ConvexHull(vert_2D, qhull_options='QJ Pp')
            for simplex in hull.simplices:
                plt.plot(vert_2D[simplex, 0], vert_2D[simplex, 1], 'k-', linewidth=2)
            plt.scatter(vert_2D[:, 0], vert_2D[:, 1])
            offset_2D = tr.rotate_and_chop(offsets[i], normals[i], [0, 0, 1])
            offset_hull = ConvexHull(offset_2D, qhull_options='QJ Pp')
            for simplex in offset_hull.simplices:
                plt.plot(offset_2D[simplex, 0], offset_2D[simplex, 1],
                         'g-', linewidth=2)
            plt.scatter(offset_2D[:, 0], offset_2D[:, 1])
            # Make sure the plot looks nice by finding the greatest range of points
            # and setting the plot to look square
            xmax = vert_2D[:, 0].max()
            xmin = vert_2D[:, 0].min()
            ymax = vert_2D[:, 1].max()
            ymin = vert_2D[:, 1].min()
            x_range = xmax - xmin
            y_range = ymax - ymin
            if (x_range > y_range):
                my_range = x_range
            else:
                my_range = y_range
            lower_bound_x = xmin - my_range*0.5
            upper_bound_x = xmin + my_range*1.5
            lower_bound_y = ymin - my_range*0.5
            upper_bound_y = ymin + my_range*1.5
            plt.axis((lower_bound_x, upper_bound_x, lower_bound_y, upper_bound_y))
            plt.grid(b=True, which='major', color='b', linestyle='-')
            centroid = tr.rotate_and_chop(coms[i], normals[i], [0, 0, 1])
            incent = tr.rotate_and_chop(incentre[i], normals[i], [0, 0, 1])
            plt.scatter(centroid[0][0], centroid[0][1])
            # Plot incircle
            t = np.linspace(0, 2*np.pi, 200)
            u = inradius[i]*np.cos(t)+incent[0][0]
            v = inradius[i]*np.sin(t)+incent[0][1]
            plt.plot(u, v, 'r-')
            ax.ticklabel_format(style='sci', scilimits=(0, 0))

    else:
        print("Please provide throat indices")
    return fig
Esempio n. 7
0
def incircle(geometry,
             **kwargs):
    r"""
    Calculate the incircle diameter by linear programming and the simplex search algorithm using the offset vertices
    generated by the voronoi diagram offsetting routine
    """
    import warnings
    try:
        import pulp as pu
        Nt = geometry.num_throats()    
        verts = geometry['throat.offset_vertices']
        normals = geometry['throat.normal']
        value = _sp.zeros(Nt)
        for i in range(Nt):
            if len(verts[i]) > 2:
                pts = tr.rotate_and_chop(verts[i],normals[i],[0,0,1])
                "Work out central point to use as initial guess"
                C = np.mean(pts,axis=0)
                "Compute convex hull to find points lying on the hull in order"
                hull = ConvexHull(pts, qhull_options='QJ Pp')
                "For each simplex making up the hull collect the end points"
                A = pts[hull.vertices]
                B = pts[np.roll(hull.vertices,-1)]
                I = np.array([[0,1],[-1,0]])
                "Normal of the simplices"
                N = np.dot((B-A),I)
                #L = np.sqrt(np.sum(np.square(N),axis=1))
                "Normalize the normal vector"
                L = np.linalg.norm(N,axis=1)
                F = np.vstack((L,L)).T
                N /= F
                "Mid-points of the simplex"
                M = (B+A)/2
                #C = np.mean(A)
                "If normals point out of hull change sign to point in"
                pointing_out = (np.sum((M-C)*N,axis=1)>0)
                N[pointing_out]*= -1
                "Define Linear Program Variables"
                "The centre of the incircle adjustment"
                cx = pu.LpVariable("cx",None,None,pu.LpContinuous)
                cy = pu.LpVariable("cy",None,None,pu.LpContinuous)
                "Radius of the incircle"
                R = pu.LpVariable("R",0,None,pu.LpContinuous)
                "Slack variables for shortest distance between centre and simplices" 
                S = pu.LpVariable.dict("SlackVariable",range(len(A)),0,None,pu.LpContinuous)
                "Set up LP problem"
                prob = pu.LpProblem("FindInRadius",pu.LpMaximize)
                "Objective Function"
                prob += R
                for j in range(len(A)):
                    " Ni.(C-Ai)-Si = 0"
                    prob += N[j][0]*(C[0]+cx) + N[j][1]*(C[1]+cy) - N[j][0]*A[j][0] - N[j][1]*A[j][1] - S[j] == 0
                    "Si >= R"
                    prob += S[j] >= R
                "Solve the LP"
                with warnings.catch_warnings():
                    warnings.simplefilter("ignore")
                    prob.solve()
                "As the radius is the objective function we can get it from the objective or as R.value()"
                value[i] = 2*R.value()
            else:
                value[i] = 0.0
        
        return value
    except ImportError:
        print("Cannot use incircle method without installing pulp package")
Esempio n. 8
0
def print_pore(geom,pores,fig=None,axis_bounds=None):
    r"""
    Print all throats around a given pore or list of pores accepted as [1,2,3,...,n]
    e.g geom.print_pore([34,65,99])
    Original vertices plus offset vertices used to create faces and
    then printed in 3D
    To print all pores (n)
    pore_range = np.arange(0,n-1,1)
    geom.print_pore(pore_range)
    """
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    return_fig=False
    if len(pores) > 0:
        net_pores = geom.map_pores(geom._net,pores)
        centroids = geom["pore.centroid"][pores]
        #centroids2 = self["pore.com"][pores]
        #for i,pore in enumerate(pores):
        #    centroids[i]=self["pore.centroid"][pore]
        #coords = self._net["pore.coords"][net_pores]
        net_throats = geom._net.find_neighbor_throats(pores=net_pores)
        #for net_throat in net_throats:
        #    try:
        #        throats.append(geom['throat.map'].tolist().index(net_throat))
        #    except ValueError:
        #        " Throat not in this geometry "
        throats = geom._net.map_throats(geom,net_throats,return_mapping=True)["target"]
        "Can't create volume from one throat"
        if len(throats)>=1:
            verts = geom['throat.vertices'][throats]
            normals = geom['throat.normal'][throats]
            " Get verts in hull order "
            ordered_verts=[]
            for i in range(len(verts)):
                vert_2D = tr.rotate_and_chop(verts[i],normals[i],[0,0,1])
                hull = ConvexHull(vert_2D,qhull_options='QJ Pp')
                ordered_verts.append(verts[i][hull.vertices])
            offsets = geom['throat.offset_vertices'][throats]
            ordered_offs=[]
            for i in range(len(offsets)):
                offs_2D = tr.rotate_and_chop(offsets[i],normals[i],[0,0,1])
                offs_hull = ConvexHull(offs_2D,qhull_options='QJ Pp')
                ordered_offs.append(offsets[i][offs_hull.vertices])
            "Get domain extents for setting axis "
            if axis_bounds is None:
                [xmin,xmax,ymin,ymax,zmin,zmax]= vertex_dimension(geom._net,pores,parm='minmax')
            else:
                [xmin,xmax,ymin,ymax,zmin,zmax]=axis_bounds
            if fig is None:
                fig = plt.figure()
            else:
                return_fig==True
            ax = fig.gca(projection='3d')
            outer_items = Poly3DCollection(ordered_verts,linewidths=1, alpha=0.2, zsort='min')
            outer_face_colours=[(1, 0, 0, 0.01)]
            outer_items.set_facecolor(outer_face_colours)
            ax.add_collection(outer_items)
            inner_items = Poly3DCollection(ordered_offs,linewidths=1, alpha=0.2, zsort='min')
            inner_face_colours=[(0, 0, 1, 0.01)]
            inner_items.set_facecolor(inner_face_colours)
            ax.add_collection(inner_items)
            ax.set_xlim(xmin,xmax)
            ax.set_ylim(ymin,ymax)
            ax.set_zlim(zmin,zmax)
            #ax.scatter(coords[:,0],coords[:,1],coords[:,2])
            ax.scatter(centroids[:,0],centroids[:,1],centroids[:,2],c='y')
            #ax.scatter(centroids2[:,0],centroids2[:,1],centroids2[:,2],c='g')
            plt.show()
        else:
            print_throat(throats)
    else:
        print("Please provide pore indices")
    if return_fig == True:
        return fig
Esempio n. 9
0
def print_throat(geom,throats_in):
    r"""
    Print a given throat or list of throats accepted as [1,2,3,...,n]
    e.g geom.print_throat([34,65,99])
    Original vertices plus offset vertices are rotated to align with
    the z-axis and then printed in 2D
    """
    import matplotlib.pyplot as plt
    throats = []
    for throat in throats_in:
        if throat in range(geom.num_throats()):
            throats.append(throat)
        else:
            print("Throat: "+str(throat)+ " not part of geometry")
    if len(throats) > 0:
        verts = geom['throat.vertices'][throats]
        offsets = geom['throat.offset_vertices'][throats]
        #image_offsets = geom['throat.image_analysis'][throats]
        normals = geom['throat.normal'][throats]
        coms = geom['throat.centroid'][throats]
        incentre = geom['throat.incentre'][throats]
        inradius = 0.5*geom['throat.indiameter'][throats]
        for i in range(len(throats)):
            fig = plt.figure()
            vert_2D = tr.rotate_and_chop(verts[i],normals[i],[0,0,1])
            hull = ConvexHull(vert_2D,qhull_options='QJ Pp')
            for simplex in hull.simplices:
                plt.plot(vert_2D[simplex,0], vert_2D[simplex,1], 'k-',linewidth=2)
            plt.scatter(vert_2D[:,0], vert_2D[:,1])
            #centroid = vo.PolyWeightedCentroid2D(vert_2D[hull.vertices])
            offset_2D = tr.rotate_and_chop(offsets[i],normals[i],[0,0,1])
            offset_hull = ConvexHull(offset_2D,qhull_options='QJ Pp')
            for simplex in offset_hull.simplices:
                plt.plot(offset_2D[simplex,0], offset_2D[simplex,1], 'g-',linewidth=2)
            plt.scatter(offset_2D[:,0], offset_2D[:,1])
            " Make sure the plot looks nice by finding the greatest range of points and setting the plot to look square"
            xmax = vert_2D[:,0].max()
            xmin = vert_2D[:,0].min()
            ymax = vert_2D[:,1].max()
            ymin = vert_2D[:,1].min()
            x_range = xmax - xmin
            y_range = ymax - ymin
            if (x_range > y_range):
                my_range = x_range
            else:
                my_range = y_range
            lower_bound_x = xmin - my_range*0.5
            upper_bound_x = xmin + my_range*1.5
            lower_bound_y = ymin - my_range*0.5
            upper_bound_y = ymin + my_range*1.5
            plt.axis((lower_bound_x,upper_bound_x,lower_bound_y,upper_bound_y))
            plt.grid(b=True, which='major', color='b', linestyle='-')
            centroid = tr.rotate_and_chop(coms[i],normals[i],[0,0,1])
            incent = tr.rotate_and_chop(incentre[i],normals[i],[0,0,1])
            plt.scatter(centroid[0][0],centroid[0][1])
            #plt.scatter(centroid2[0],centroid2[1],c='r')
            "Plot incircle"
            t = np.linspace(0,2*np.pi,200)
            u = inradius[i]*np.cos(t)+incent[0][0]
            v = inradius[i]*np.sin(t)+incent[0][1]
            plt.plot(u,v,'r-')
            fig.show()
    else:
        print("Please provide throat indices")