Exemplo n.º 1
0
def loadMsh(filename, crs, outputdir):
    progress = QtWidgets.QProgressDialog("Converting GMSH mesh...", "Abort", 0,
                                         100)
    progress.setMinimumDuration(1000)
    progress.setWindowModality(Qt.WindowModal)
    QDir().mkpath(outputdir)
    fin = open(filename, "r")
    l = fin.readline()
    useFormat3 = False
    vertices = {}
    physicalNames = {}
    entityPhysical = {}
    physicalWriter = {}
    entityWriter = {}

    def abort():
        for writer in physicalWriter.values():
            QgsVectorFileWriter.deleteShapeFile(writer.path + ".shp")
            QFile.remove(writer.path + ".cpg")

    while l != "":
        w = l.split()
        if w[0] == "$MeshFormat":
            l = fin.readline().split()
            if int(float(l[0])) == 3:
                useFormat3 = True
            elif int(float(l[0])) == 2:
                useFormat3 = False
            else:
                raise ValueError("cannot read mesh format " + l[0])
            l = fin.readline()
        elif w[0] == "$PhysicalNames":
            n = int(fin.readline())
            for i in range(n):
                dim, tag, name = fin.readline().split()
                physicalNames[(int(dim), int(tag))] = name[1:-1]
            fin.readline()
        elif w[0] == "$Entities" and useFormat3:
            ns = list(int(fin.readline()) for i in range(4))
            for dim in range(4):
                for i in range(ns[dim]):
                    l = fin.readline().split()
                    j, nbnd = int(l[0]), int(l[1])
                    nphys = int(l[2 + nbnd])
                    entityPhysical[(dim,
                                    j)] = int(l[2 + nbnd +
                                                nphys]) if nphys > 0 else None
        elif w[0] == "$Nodes":
            n = int(fin.readline())
            for i in range(n):
                if i % 1000 == 0:
                    QtWidgets.QApplication.processEvents()
                    progress.setValue((7 * i) / n)
                    if progress.wasCanceled():
                        abort()
                        return
                if useFormat3:
                    j, x, y, z = fin.readline().split()[:4]
                else:
                    (j, x, y, z) = fin.readline().split()
                vertices[int(j)] = [float(x), float(y), float(z), int(j)]
        elif w[0] == "$Elements":
            n = int(fin.readline())
            for i in range(n):
                if i % 100 == 0:
                    QtWidgets.QApplication.processEvents()
                    if progress.wasCanceled():
                        abort()
                        return
                if i % 1000 == 0:
                    progress.setValue(7 + (93 * i) / n)
                l = fin.readline().split()
                if useFormat3:
                    j, t, e, nf = int(l[0]), int(l[1]), int(l[2]), int(l[3])
                    nv = gmshType.Type[t].numVertices
                    evertices = [vertices[int(i)] for i in l[4:4 + nv]]
                    partition = [
                        int(i) for i in l[5 + nv:5 + nv + int(l[4 + nv])]
                    ] if nf > nv else []
                else:
                    j, t, nf, p, e = int(l[0]), int(l[1]), int(l[2]), int(
                        l[3]), int(l[4])
                    evertices = [vertices[int(i)] for i in l[3 + nf:]]
                    partition = [int(i)
                                 for i in l[6:6 +
                                            int(l[5])]] if nf > 2 else []
                edim = gmshType.Type[t].baseType.dimension
                writer = entityWriter.get((edim, e), None)
                if writer is None:
                    if useFormat3:
                        if (edim, e) in entityPhysical:
                            p = entityPhysical[(edim, e)]
                        else:
                            p = 0
                    writer = physicalWriter.get((edim, p), None)
                    if writer is None:
                        fields = QgsFields()
                        ltype = [
                            QgsWkbTypes.Point, QgsWkbTypes.LineString,
                            QgsWkbTypes.Polygon
                        ][edim]
                        name = physicalNames.get((edim, p), None)
                        if name is None:
                            name = ["points", "lines", "elements"
                                    ][edim] + ("_" + str(p) if p >= 0 else "")
                            physicalNames[(edim, p)] = name
                        path = os.path.join(outputdir, name)
                        writer = QgsVectorFileWriter(
                            path,
                            "system",
                            fields,
                            ltype,
                            crs,
                            driverName="ESRI Shapefile")
                        writer.path = path
                        physicalWriter[(edim, p)] = writer
                    entityWriter[(edim, e)] = writer
                points = list([QgsPointXY(v[0], v[1]) for v in evertices])
                if edim == 0:
                    geom = QgsGeometry.fromPointXY(points[0])
                elif edim == 1:
                    geom = QgsGeometry.fromPolylineXY(points)
                elif edim == 2:
                    v = evertices[0]
                    points.append(QgsPointXY(v[0], v[1]))
                    geom = QgsGeometry.fromPolygonXY([points])
                feature = QgsFeature()
                feature.setGeometry(geom)
                writer.addFeature(feature)
        l = fin.readline()

    group = QgsProject.instance().layerTreeRoot().addGroup("mesh")
    paths = []
    for writer in physicalWriter.values():
        paths.append(writer.path + ".shp")
        del writer
    QThread.sleep(1)
    progress.setValue(100)
    for path in paths:
        l = QgsVectorLayer(path, QFileInfo(path).baseName(), "ogr")
        QgsProject.instance().addMapLayer(l, False)
        group.addLayer(l)