Failed to generate and mesh model with Python API

Provides a system for patient-specific cardiovascular modeling and simulation.
POST REPLY
User avatar
Florian Gartner
Posts: 12
Joined: Tue Dec 12, 2023 7:13 am

Failed to generate and mesh model with Python API

Post by Florian Gartner » Mon Jun 17, 2024 5:36 pm

Hello,
I would like to study the effect of small changes of vessel geometry using the Python API but face problems generating a model and mesh.

For example, as a simple test case I tried the tetgen-set-model.py code on GitHub (https://github.com/SimVascular/SimVascu ... t-model.py). Running the code on Simvascular's Python console and visualizing the mesh either with the new-api-tests/graphics package or within the GUI with 'sv.dmg.add_mesh()' it shows a mesh that looks very weird and malformed (see screenshot).

If instead I create the cylinder model in the GUI and use 'sv.dmg.get_model()' to read the model and mesh it with the Python script, I get a nice looking mesh (see screenshot). So the problem seems to be with creating the model with the Python API, rather than with the meshing. What is going wrong here? I also got a similar problem with the 'create_vessel_model()' as I described in this post (viewtopicPhpbb.php?f=188&t=15368&p=0&st ... cf3e7dc5ef), except that here mesh generation failed completely. I would appreciate any help on this. Thank you!


Here is the exact code that I used (adopted from tetgen-set-model.py):

Code: Select all

'''Test creating a solid model and using set_model from the TetGen class interface.

   Writes: 'cylinder-mesh.vtu'

   Note: Be careful with global_edge_size, must match model Remesh Size resolution.
'''
import os
from pathlib import Path
import sv
import sys
import vtk

## Set some directory paths. 
script_path = Path('C:/Users/flori/OneDrive/Desktop/Simvascular_Simulations/new-api-tests/meshing')
parent_path = script_path.parent
data_path = parent_path / 'data'

try:
    sys.path.insert(1, str(parent_path / 'graphics'))
    import graphics as gr
except:
    print("Can't find the new-api-tests/graphics package.")

## Create a solid model of a cylinder.
print("Create a cylinder ...")
modeler = sv.modeling.Modeler(sv.modeling.Kernel.POLYDATA)
center = [0.0, 0.0, 0.0]
axis = [0.0, 1.0, 0.0]
axis = [1.0, 0.0, 0.0]
radius = 1.0
length = 6.0
cylinder = modeler.cylinder(center=center, axis=axis, radius=radius, length=length)
face_ids = cylinder.compute_boundary_faces(angle=60.0)
print("Model face IDs: " + str(face_ids))

sv.dmg.add_model(name = 'cylinder_model', model = cylinder)


# instead create cylinder_model' in GUI and import it here
# cylinder = sv.dmg.get_model('cylinder_model')

## Create a TetGen mesher.
#
mesher = sv.meshing.TetGen()
mesher.set_model(cylinder)

## Set the face IDs for model walls.
face_ids = [1]
mesher.set_walls(face_ids)

## Compute model boundary faces.
face_ids = mesher.get_model_face_ids()
print("Mesh face ids: " + str(face_ids))

## Set meshing options.
#
# Note: Be careful with global_edge_size, must match model Remesh Size resolution.
print("Set meshing options ... ")
options = sv.meshing.TetGenOptions(global_edge_size=0.4, surface_mesh_flag=True, volume_mesh_flag=True)

## Generate the mesh. 
mesher.generate_mesh(options)

## Get the mesh as a vtkUnstructuredGrid. 
mesh = mesher.get_mesh()
print("Mesh:");
print("  Number of nodes: {0:d}".format(mesh.GetNumberOfPoints()))
print("  Number of elements: {0:d}".format(mesh.GetNumberOfCells()))

## Write the mesh.
file_name = str(script_path / 'cylinder-mesh.vtu')
mesher.write_mesh(file_name)

## Show the mesh.
#
show_mesh = True
if show_mesh:
    ## Create renderer and graphics window.
    win_width = 500
    win_height = 500
    renderer, renderer_window = gr.init_graphics(win_width, win_height)

    #mesh_polydata = gr.convert_ug_to_polydata(mesh)
    mesh_surface = mesher.get_surface()
    gr.add_geometry(renderer, mesh_surface, color=[1.0, 1.0, 1.0], wire=True, edges=True)
    #gr.add_geometry(renderer, mesh_polydata, color=[1.0, 1.0, 1.0], wire=False, edges=True)

    #mesh_model_polydata = mesher.get_model_polydata()
    #gr.add_geometry(renderer, mesh_model_polydata, color=[0.0, 1.0, 1.0], wire=True, edges=True)

    face1_polydata = mesher.get_face_polydata(1)
    gr.add_geometry(renderer, face1_polydata, color=[1.0, 0.0, 0.0], wire=False, edges=True)

    face2_polydata = mesher.get_face_polydata(2)
    gr.add_geometry(renderer, face2_polydata, color=[0.0, 1.0, 0.0], wire=False, edges=True)

    face3_polydata = mesher.get_face_polydata(3)
    gr.add_geometry(renderer, face3_polydata, color=[0.0, 0.0, 1.0], wire=False, edges=True)

gr.display(renderer_window)
sv.dmg.add_mesh(name='cylinder_mesh', volume=mesher.get_mesh(), surface=mesher.get_surface(), model='cylinder_model')
Attachments
failed_mesh.png
model and mesh generated with Python API
failed_mesh.png (414.2 KiB) Viewed 265 times
mesh_succeeded.png
model generated with GUI and mesh generated with Python API
mesh_succeeded.png (242.67 KiB) Viewed 265 times

User avatar
David Parker
Posts: 1651
Joined: Tue Aug 23, 2005 2:43 pm

Re: Failed to generate and mesh model with Python API

Post by David Parker » Tue Jun 18, 2024 3:56 pm

Hello,

The tetgen-set-model.py script is used just to test the mesher.set_model() method, it does not reproduce all of the steps used by SV.

The SV Python API sv.modeling.Modeler(sv.modeling.Kernel.POLYDATA) class typically produces a poor triangulation for some reason, needs to be remeshed it seems.

You can add

Code: Select all

remesh_cylinder = sv.mesh_utils.remesh(cylinder.get_polydata(), hmin=0.4, hmax=0.4)
cylinder = sv.modeling.PolyData(surface=remesh_cylinder)
to the tetgen-set-model.py script to remesh the model surface to create a better triangulation.

Cheers,
Dave

POST REPLY