admin管理员组

文章数量:1321416

I am trying to generate a 3D mesh from a three-dimensional graph-like structure by fusing spheres and cylinders, to do that I am using the Gmsh Python API. To reduce the workload I divide the structure into different layers to generate all the layers separately and then fuse them all together (the idea behind that is also to try to parallelize the meshing of each layer but this is further work).

The problem comes when the surfaces are getting meshed, it throws this error "Error : The 1D mesh seems not to be forming a closed loop" and I don't know how to solve this or even what it means. I have dug into the issue but I didn't find anything valuable, there is a lack of examples of using Gmsh Python API. I also tried different approaches to solve the problem like removing possible duplicate nodes but didn't work either and I am running out of ideas. Does anyone have some experience using Gmsh Python API or Gmsh?

I am using this code:

import pickle
import os
import numpy as np
import gmsh
from collections import defaultdict
import trimesh

class STLGen():

    def __init__(self, sphere_radius, cylinder_radius, graph_path, output_path):
        
        self.sphere_radius = sphere_radius
        self.cylinder_radius = cylinder_radius
        self.polygons = pickle.load(open(os.path.join(graph_path, "tetra.pickle"), 'rb'))
        self.output_path = output_path

    @staticmethod
    def build_tetrahedron(tetra_list, layer, sphere_radius, cylinder_radius, output_path):
        gmsh.initialize()
        gmsh.model.add(f"layer_{layer}")
        gmsh.option.setNumber("Mesh.CharacteristicLengthMin", 0.5)
        gmsh.option.setNumber("Mesh.CharacteristicLengthMax", 1)

        entities = []
        for tetra_dict in tetra_list:
            apex = tetra_dict["apex"]
            base_points = tetra_dict["base_points"]

            for node in np.vstack((apex, base_points)):
                sphere = gmsh.model.occ.addSphere(node[0], node[1], node[2], sphere_radius)
                entities.append((3, sphere))  # (dimension, tag)

            for start in base_points:
                dx, dy, dz = apex - start
                cylinder = gmsh.model.occ.addCylinder(
                    start[0], start[1], start[2], dx, dy, dz, cylinder_radius
                )
                entities.append((3, cylinder))  # (dimension, tag)

        gmsh.model.occ.synchronize()
        fused = gmsh.model.occ.fuse(entities, entities)
        gmsh.model.occ.synchronize()

        gmsh.model.occ.removeAllDuplicates()
        gmsh.model.mesh.generate(3)

        tmp_file = os.path.join(output_path, f"tmp_{layer}.stl")
        gmsh.write(tmp_file)
        gmsh.finalize()

        return tmp_file
        
    def process_layer(self, args):

        layer, layer_tetra = args
        return self.build_tetrahedron(layer_tetra, layer, self.sphere_radius, self.cylinder_radius, self.output_path)

    def generate_stl(self):
        
        layers = defaultdict(list)
        for key, value in self.polygons.items():
            layers[key.split("_")[0]].append(value)

        tmp_paths = []
        for layer, layer_tetra in layers.items():
            self.process_layer((layer, layer_tetra))
            tmp_paths.append(os.path.join(self.output_path, f"layer_{layer}.stl"))

        combined_mesh = trimesh.util.concatenate([trimesh.load(file) for file in tmp_paths])
        combined_mesh.export(os.path.join(self.output_path, "mesh.stl"))


if __name__ == "__main__":
    stl = STLGen(3, 2, "graph_path", "output_path")
    stl.generate_stl()

self.polygons is a nested dictionary with the following structure

self.polygons = { ...,
"1_123" : {'base_points': numpy.array dim (n,3)),
  'apex': numpy.array dim (1,3)}

Where "1" represents the layer number which the polygon "123" belongs to. If anyone is interested I could share my files.

Thank you all for your time!

本文标签: Gmsh Python API meshing error The 1D mesh seems not to be forming a closed loopStack Overflow