Beispiel #1
0
def testCreateTriPrismMesh():
    poly = g.Mesh(2)
    n0 = poly.createNode(0.0, 0.0, 0.)
    n1 = poly.createNode(1.0, 0.0, 0.)
    n2 = poly.createNode(0.0, 1.0, 0.)
    n3 = poly.createNode(1.0, 1.0, 0.)
    poly.createEdge(n0, n1)
    poly.createEdge(n1, n3)
    poly.createEdge(n3, n2)
    poly.createEdge(n2, n0)

    mesh2 = g.Mesh(2)
    g.TriangleWrapper(poly, mesh2, "-pzeAfa0.01q34")

    mesh3 = g.createMesh3D(mesh2, g.asvector(np.arange(0, -1, -0.1)))
    mesh3.setCellAttributes(g.asvector(range(0, mesh3.cellCount())))

    mesh3.save("prism")
    mesh3.exportVTK("prism")
Beispiel #2
0
    def createMesh(self, quality=34.6, maxarea=0.1, addpoints=None):
        """Create (inversion) mesh by circumventing PLC"""
        data = self.dataContainer
        sx = list(pg.x(data.sensorPositions()))
        sz = list(pg.y(data.sensorPositions()))

        if addpoints is not None:
            for po in addpoints:
                sx.append(po[0])
                sz.append(po[1])

        iS = np.argsort(np.arctan2(sx - np.mean(sx), sz - np.mean(sz)))
        plc = pg.Mesh(2)
        nodes = [plc.createNode(sx[i], sz[i], 0) for i in iS]
        for i in range(len(nodes) - 1):
            plc.createEdge(nodes[i], nodes[i + 1])

        plc.createEdge(nodes[-1], nodes[0])
        tri = pg.TriangleWrapper(plc)
        tri.setSwitches("-pzFq" + str(quality) + "a" + str(maxarea))
        self.setMesh(tri.generate())
Beispiel #3
0
def createMesh(poly,
               quality=30,
               area=0.0,
               smooth=None,
               switches=None,
               verbose=False,
               **kwargs):
    """Create a mesh for a given geometry polygon.

    The mesh is created by :term:`triangle` or :term:`tetgen` if the
    gimli support for these mesh generators are installed.
    The geometry needs to contain nodes and boundaries and should be valid
    in the sense that the boundaries are non intersecting.

    If poly is a list of coordinates a simple Delaunay mesh of the convex hull
    will be created.
    TODO: Tetgen support need to be implemented

    Parameters
    ----------
    poly: :gimliapi:`GIMLI::Mesh` or list
        * 2D or 3D gimli mesh that contains the PLC.
        * 2D mesh needs edges
        * 3D mesh needs ... to be implemented
        * List of x y pairs [[x0, y0], ... ,[xN, yN]]
        * PLC or list of PLC
    quality: float
        2D triangle quality sets a minimum angle constraint.
        Be careful with values above 34 degrees.
    area: float
        2D maximum triangle size in m*m
    smooth: tuple
        [smoothing algorithm, number of iterations]
        0, no smoothing
        1, node center
        2, weighted node center
    switches: str
        Force triangle to use the gives command switches.

    Returns
    -------
    mesh: :gimliapi:`GIMLI::Mesh`

    Examples
    --------
    >>> # no need to import matplotlib. pygimli's show does
    >>> import pygimli as pg
    >>> import pygimli.meshtools as mt
    >>> rect = mt.createRectangle(start=[0, 0], end=[4, 1])
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=10))
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=33))
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=33, area=0.01))
    >>> pg.wait()
    """
    #  poly == [pg.Mesh, ]
    if isinstance(poly, list):
        if isinstance(poly[0], pg.Mesh):
            return createMesh(pg.meshtools.mergePLC(poly), quality, area,
                              smooth, switches, verbose)
    # poly == [pos, pos, ]
    if isinstance(poly, list) or isinstance(poly, type(zip)):
        delPLC = pg.Mesh(2)
        for p in poly:
            delPLC.createNode(p[0], p[1], 0.0)
        return createMesh(delPLC, switches='-zeY')

    # poly == Mesh
    if poly.dim() == 2:
        if poly.nodeCount() == 0:
            raise Exception("No nodes in poly to create a valid mesh")

        tri = pg.TriangleWrapper(poly)

        if switches is None:
            # -D Conforming delaunay
            # -F Uses Steven Fortune's sweepline algorithm
            # no -a here ignores per region area
            switches = 'pazeA'

            if area > 0:
                switches += 'a' + str(area)
                pass
            else:
                switches += 'a'

            # switches = switches.replace('.', ',')
            switches += 'q' + str(quality)

        if not verbose:
            switches += 'Q'

        if verbose:
            print(switches)

        tri.setSwitches(switches)
        mesh = tri.generate()

        if smooth is not None:
            mesh.smooth(nodeMoving=kwargs.pop('node_move', False),
                        edgeSwapping=False,
                        smoothFunction=smooth[0],
                        smoothIteration=smooth[1])
        return mesh

    else:
        raise Exception('not yet implemented')
Beispiel #4
0
nodes = pg.utils.unique_rows(nodes)  # remove duplicate nodes
poly = pg.Mesh(2)

for node in nodes:
    poly.createNode(node[0], node[1], 0.0)

for i in range(poly.nodeCount() - 1):
    poly.createEdge(poly.node(i), poly.node(i + 1))

poly.createEdge(poly.node(poly.nodeCount() - 1), poly.node(0))

###############################################################################
# We call the TriangleWrapper to generate the mesh and set the x values as the
# data for a color transition.

tri = pg.TriangleWrapper(poly)
mesh = pg.Mesh(2)
tri.setSwitches('-pzeAfa5q33')
tri.generate(mesh)

data = []
for cell in mesh.cells():
    data.append(cell.center().x())

###############################################################################
# Last, we create a BERT caption, visualize the mesh and fine-tune the figure.

fig, ax = plt.subplots(figsize=(4, 3))
ax.axis('off')
offset = -10
t = ax.text(1.7, offset, 'BERT', fontsize=37, fontweight='bold')
Beispiel #5
0
def createMesh(poly,
               quality=30,
               area=0.0,
               smooth=None,
               switches=None,
               verbose=False,
               **kwargs):
    """Create a mesh for a given geometry polygon.

    The mesh is created by :term:`triangle` or :term:`tetgen` if the
    gimli support for these mesh generators are installed.
    The geometry needs to contain nodes and boundaries and should be valid
    in the sense that the boundaries are non intersecting.

    If poly is a list of coordinates a simple Delaunay mesh of the convex hull
    will be created.
    TODO: Tetgen support need to be implemented

    Parameters
    ----------
    poly: :gimliapi:`GIMLI::Mesh` or list or ndarray
        * 2D or 3D gimli mesh that contains the PLC.
        * 2D mesh needs edges
        * 3D mesh needs a plc and tetgen as system component
        * List of x y pairs [[x0, y0], ... ,[xN, yN]]
        * ndarray [x_i, y_i]
        * PLC or list of PLC
    quality: float
        2D triangle quality sets a minimum angle constraint.
        Be careful with values above 34 degrees.
    area: float
        2D maximum triangle size in m*m
    smooth: tuple
        [smoothing algorithm, number of iterations]
        0, no smoothing
        1, node center
        2, weighted node center
    switches: str
        Force triangle to use the gives command switches.

    Returns
    -------
    mesh: :gimliapi:`GIMLI::Mesh`

    Examples
    --------
    >>> # no need to import matplotlib. pygimli's show does
    >>> import pygimli as pg
    >>> import pygimli.meshtools as mt
    >>> rect = mt.createRectangle(start=[0, 0], end=[4, 1])
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=10))
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=33))
    >>> ax, _ = pg.show(mt.createMesh(rect, quality=33, area=0.01))
    >>> pg.wait()
    """
    #  poly == [pg.Mesh, ]
    if isinstance(poly, list):
        if isinstance(poly[0], pg.Mesh):
            return createMesh(pg.meshtools.mergePLC(poly), quality, area,
                              smooth, switches, verbose)
    # poly == [pos, pos, ]
    if isinstance(poly, list) or \
        isinstance(poly, type(zip)) or \
        type(poly) == pg.stdVectorRVector3 or \
        (isinstance(poly, np.ndarray) and poly.ndim == 2):
        delPLC = pg.Mesh(2)
        for p in poly:
            delPLC.createNode(p[0], p[1], 0.0)
        return createMesh(delPLC, switches='-zeY')

    # poly == Mesh
    if poly.dim() == 2:
        if poly.nodeCount() == 0:
            raise Exception("No nodes in poly to create a valid mesh")

        tri = pg.TriangleWrapper(poly)

        if switches is None:
            # -D Conforming delaunay
            # -F Uses Steven Fortune's sweepline algorithm
            # no -a here ignores per region area
            switches = 'pzeA'

            if area > 0:
                #switches += 'a' + str(area)
                # The str function turns everything smaller
                # than 0.0001 into the scientific notation 1e-5
                # which can not be read by triangle. The following
                # avoids this even for very small numbers
                switches += 'a' + '{:.20f}'.format(area)
                pass
            else:
                switches += 'a'

            # switches = switches.replace('.', ',')
            switches += 'q' + str(quality)

        if not verbose:
            switches += 'Q'

        if verbose:
            print(switches)

        tri.setSwitches(switches)
        mesh = tri.generate()

        if smooth is not None:
            mesh.smooth(nodeMoving=kwargs.pop('node_move', True),
                        edgeSwapping=False,
                        smoothFunction=smooth[0],
                        smoothIteration=smooth[1])
        return mesh

    else:

        tmp = pg.optImport('tempfile')
        _, namePLC = tmp.mkstemp(suffix='.poly')

        pg.meshtools.exportPLC(poly, namePLC)
        mesh = pg.meshtools.syscallTetgen(namePLC,
                                          quality,
                                          area,
                                          verbose=verbose)

        try:
            os.remove(namePLC)
        except:
            print("can't remove:", namePLC)

        return mesh
Beispiel #6
0
def appendTriangleBoundary(mesh, xbound=10, ybound=10, marker=1, quality=34.0,
                           area=0.0, smooth=False, markerBoundary=1,
                           isSubSurface=False, verbose=False):
    """Add a triangle mesh boundary to a given mesh.

    Returns a new mesh that contains a triangulated box around a given mesh
    suitable for geo-simulation (surface boundary at top).

    Parameters
    ----------
    mesh : mesh object
        Mesh to which the triangle boundary should be appended.
    xbound : float, optional
        Horizontal prolongation distance. Minimal mesh 0.5 x extension.
    ybound : float, optional
        Vertical prolongation distance. Minimal mesh 0.5 y extension.
    marker : int, optional
        Marker of new cells.
    markerBoundary : int, optional
        Marker of the inner boundary edges between mesh and new boundary.
    quality : float, optional
        Triangle quality.
    area: float, optional
        Triangle max size within the boundary.
    smooth : boolean, optional
        Apply mesh smoothing.
    isSubSurface : boolean, optional
        Apply boundary conditions suitable for geo-simulation and prolongate
        mesh to the surface if necessary.
    verbose : boolean, optional
        Be verbose.

    Examples
    --------
    >>> import matplotlib.pyplot as plt
    >>> import pygimli as pg
    >>> from pygimli.mplviewer import drawMesh, drawModel
    >>> from pygimli.meshtools import appendTriangleBoundary
    >>> inner = pg.createGrid(range(5), range(5), marker=1)
    >>> mesh = appendTriangleBoundary(inner, xbound=3, ybound=6, marker=2)

    >>> fig, (ax1, ax2) = plt.subplots(1,2)
    >>> p1 = drawMesh(ax1, inner)
    >>> p2 = drawModel(ax2, mesh, mesh.cellMarkers(), label='marker')
    >>> p3 = drawMesh(ax2, mesh)
    >>> txt1 = ax1.set_title("a) Input grid")
    >>> txt2 = ax2.set_title("b) With triangle boundary")

    See Also
    --------
    appendTetrahedronBoundary
    """
    surface = 0.0

    # find boundaries on left/right/bottom/top side
    le = [b for b in mesh.boundaries() if b.center().x() == mesh.xmin()]
    bo = [b for b in mesh.boundaries() if b.center().y() == mesh.ymin()]
    ri = [b for b in mesh.boundaries() if b.center().x() == mesh.xmax()]
    top = [b for b in mesh.boundaries() if b.center().y() == mesh.ymax()]

    # gather all right boundary nodes after sorting in boundaryNodes
    tmp = []
    for b in ri:
        if b.node(0) not in tmp:
            tmp.append(b.node(0))
        if b.node(1) not in tmp:
            tmp.append(b.node(1))

    tmp.sort(key=lambda n: n.pos().y())
    tmp.reverse()
    boundaryNodes = tmp

    # gather all bottom boundary nodes and add them to boundaryNodes
    boNode = []
    for b in bo:
        if b.node(0) not in boNode + boundaryNodes:
            boNode.append(b.node(0))
        if b.node(1) not in boNode + boundaryNodes:
            boNode.append(b.node(1))

    boNode.sort(key=lambda n: n.pos().x())
    boNode.reverse()
    boundaryNodes = boundaryNodes + boNode

    # gather all left boundary nodes and add them to boundaryNodes
    tmp = []
    for b in le:
        if b.node(0) not in tmp + boundaryNodes:
            tmp.append(b.node(0))
        if b.node(1) not in tmp + boundaryNodes:
            tmp.append(b.node(1))

    tmp.sort(key=lambda n: n.pos().y())
    boundaryNodes = boundaryNodes + tmp

    if isSubSurface:
        # gather all top boundary nodes and add them to boundaryNodes
        topNodes = []
        for boundary in top:
            if boundary.node(0) not in topNodes + boundaryNodes:
                topNodes.append(boundary.node(0))
            if boundary.node(1) not in topNodes + boundaryNodes:
                topNodes.append(boundary.node(1))
        topNodes.sort(key=lambda n: n.pos().x())
        boundaryNodes = boundaryNodes + topNodes

    poly = pg.Mesh()

    preserveSwitch = ''

    if isSubSurface:
        # add all boundary nodes
        for n in boundaryNodes:
            poly.createNode(n.pos())

        # and connect them by a closed polygon
        for i in range(0, poly.nodeCount()):
            poly.createEdge(
                poly.node(i), poly.node((i + 1) % poly.nodeCount()),
                markerBoundary)

        # add four corners of the world box
        xtLen = 12
        # x bottom boundary sampling points
        # xBottom = pg.asvector(np.linspace(mesh.xmin() - xbound,
        #                                   mesh.xmax() + xbound, xtLen))

        n1 = poly.createNode(pg.RVector3(mesh.xmax() + xbound, surface, 0.0))
        n2 = poly.createNode(pg.RVector3(mesh.xmin() - xbound, surface, 0.0))
        n3 = poly.createNode(pg.RVector3(mesh.xmin() - xbound, mesh.ymin() -
                                         ybound, 0.0))
        n4 = poly.createNode(pg.RVector3(mesh.xmax() + xbound, mesh.ymin() -
                                         ybound, 0.0))

        # and connect them by a closed polygon
        poly.createEdge(n1, n2, pg.MARKER_BOUND_HOMOGEN_NEUMANN)
        poly.createEdge(n2, n3, pg.MARKER_BOUND_MIXED)
        poly.createEdge(n3, n4, pg.MARKER_BOUND_MIXED)
        poly.createEdge(n4, n1, pg.MARKER_BOUND_MIXED)

    else:  # no isSubSurface
        xbound = max(xbound, 0.5 * (mesh.xmax() - mesh.xmin()))
        ybound = max(ybound, 0.5 * (mesh.ymax() - mesh.ymin()))
        # add top right node and boundary nodes

        dxMin = boNode[0].pos().distance(boNode[1].pos()) * 1.1
        xtLen = max(5, int(xbound / dxMin / 2.))

        # x top boundary sampling points
        xTop = pg.increasingRange(dxMin, xbound, xtLen)
        # y boundary sampling points
        yLeft = pg.increasingRange(xTop[len(xTop) - 1] - xTop[len(xTop) - 2],
                                   abs(mesh.ymin() - ybound), xtLen)

        xtLen = max(5, int((mesh.xmax() - mesh.xmin()) / dxMin / 2.))

        # x bottom boundary sampling points
        xBottom = pg.RVector(np.linspace(mesh.xmin() - xbound, mesh.xmax() +
                                         xbound, 2 * xtLen))

        for i, val in enumerate(pg.fliplr(xTop)(0, len(xTop) - 1)):
            poly.createNode([mesh.xmax() + val, mesh.ymax(), 0.0])

        for n in boundaryNodes:
            poly.createNode(n.pos())

        # add top left, bottom left and bottom right node

        for t in xTop(1, len(xTop)):
            poly.createNode([mesh.xmin() - t, mesh.ymax(), 0.0])

        for t in yLeft(1, len(yLeft)):
            poly.createNode([mesh.xmin() - xbound, mesh.ymax() - t, 0.0])

        for t in xBottom(1, len(xBottom) - 1):
            poly.createNode([t, mesh.ymin() - ybound, 0.0])

        for t in pg.fliplr(yLeft)(0, len(yLeft) - 1):
            poly.createNode([mesh.xmax() + xbound, mesh.ymax() - t, 0.0])

        # create a closed polygon through all new nodes
        for i in range(0, poly.nodeCount()):
            poly.createEdge(
                poly.node(i), poly.node((i + 1) % poly.nodeCount()),
                markerBoundary)

        preserveSwitch = 'Y'
    # poly.exportVTK('out.poly')

    mesh2 = pg.Mesh(2)

    # call triangle mesh generation
    triswitches = '-pzeAfa' + preserveSwitch + 'q' + str(quality)

    if area > 0:
        triswitches += 'a' + str(area)

    if not verbose:
        triswitches += 'Q'

    if isSubSurface:
        margin = 0.0001
        poly.addHoleMarker(pg.RVector3(mesh.xmin() + margin, mesh.ymax() -
                                       margin))
        tri = pg.TriangleWrapper(poly)
        tri.setSwitches(triswitches)
        tri.generate(mesh2)
    else:
        pg.TriangleWrapper(poly, mesh2, triswitches)

    if smooth:
        mesh2.smooth(nodeMoving=True, edgeSwapping=True, smoothFunction=1,
                     smoothIteration=2)

    mesh2.setCellMarkers([marker] * mesh2.cellCount())

    # map copy the cell not the reference, this should not happen
    # map( lambda cell: mesh2.copyCell( cell ), mesh2.cells() )
    for cell in mesh.cells():
        mesh2.copyCell(cell)

    # old neighbor infos need to be cleaned since the new cells are added
    mesh2.createNeighbourInfos(force=True)

    for b in mesh2.boundaries():
        if b.leftCell() is None or b.rightCell() is None:
            if b.center().y() == mesh2.ymax():
                b.setMarker(pg.MARKER_BOUND_HOMOGEN_NEUMANN)
            else:
                b.setMarker(pg.MARKER_BOUND_MIXED)

    return mesh2
nodes.append(plc.createNode(xmax, -zlay * 2, 0.))  # 4
nodes.append(plc.createNode(xmin, -zlay * 2, 0.))  # 5
nodes.append(plc.createNode(xmin, -zlay, 0.))  # 6

###############################################################################
# The nodes are connected from from 0 to 6 and back to 0.
# An additional edge is drawn from 6 to 3. Node/edge markers do not matter.
for i in range(6):
    plc.createEdge(nodes[i], nodes[i + 1])

plc.createEdge(nodes[6], nodes[0])
plc.createEdge(nodes[6], nodes[3])

###############################################################################
# We insert region markers (0 and 1) into the two layers and generate the mesh.
tri = pg.TriangleWrapper(plc)
plc.addRegionMarker(pg.RVector3(0., -zlay + .1), 0, 3.)  # 10m^2 max area
plc.addRegionMarker(pg.RVector3(0., -zlay - .1), 1, 10.)
tri.setSwitches('-pzeAfaq34.6')
mesh = pg.Mesh(2)
tri.generate(mesh)
mesh.createNeighbourInfos()
print(mesh)

###############################################################################
# Next we generate a velocity model from the markers by using a map.
# The values are associated to the markers and stored as attributes.
v = [1000., 3000.]
slomap = pg.stdMapF_F()  # mapping markers to real slowness values
for i, vi in enumerate(v):
    slomap.insert(i, 1. / vi)