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)