CadQuery / cadquery

A python parametric CAD scripting framework based on OCCT
https://cadquery.readthedocs.io
Other
3.12k stars 288 forks source link

GMSH integration #1346

Closed adam-urbanczyk closed 1 year ago

adam-urbanczyk commented 1 year ago

With OCP 7.7.1 it should be possible to import OCCT shapes from memory

import cq
import gmsh

gmsh.initialize()

gmsh.model.occ.importShapesNativePointer(cq.Workplane().box(1,1,1).val()._address())
shimwell commented 1 year ago

I have added a few line to the end of the above example that mesh the geometry and write a .msh file. The .msh file can then be opened in the gmsh gui and inspected.

import gmsh
import cadquery as cq
result = cq.Workplane("XY").box(3, 3, 0.5).edges("|Z").fillet(0.5)
topods = result.toOCC()
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 1)
volumes = gmsh.model.occ.importShapesNativePointer(topods._address())
gmsh.model.occ.synchronize()
gmsh.option.setNumber("Mesh.Algorithm", 1)
gmsh.option.setNumber("Mesh.MeshSizeMin", 20)
gmsh.option.setNumber("Mesh.MeshSizeMax", 30)
gmsh.model.mesh.generate(2)
gmsh.write("gmsh_of_cadquery_in_memory.msh")
shimwell commented 1 year ago

Running the above (recently updated) script works over here.. Screenshot from 2023-06-13 22-41-49

shimwell commented 1 year ago

When exporting workplanes that have surfaces in contact it is nice to merge those surfaces together. This allows the meshing to be conformal at the surface boundary between the two workplanes.

I think this code does the same as above but works for two workplanes that contact on a surface.

import cadquery as cq
import OCP
import gmsh
workplane1 = cq.Workplane("XY").cylinder(height=10, radius=4)
workplane2 = cq.Workplane("XY").cylinder(height=10, radius=5).cut(workplane1)
bldr = OCP.BOPAlgo.BOPAlgo_Splitter()
bldr.AddArgument(workplane1.val().wrapped)
bldr.AddArgument(workplane2.val().wrapped)
bldr.SetNonDestructive(True)
bldr.Perform()
bldr.Images()
merged_surface_compound = cq.Compound(bldr.Shape())
# it looks like cq.Compound does not have a toOCC method like cq.workplane does
# however it has a val().wrapped which returns a OCP.TopoDS.TopoDS_Solid
topods = merged_surface_compound.wrapped
gmsh.initialize()
gmsh.option.setNumber("General.Terminal", 1)
volumes = gmsh.model.occ.importShapesNativePointer(topods._address())
gmsh.model.occ.synchronize()
gmsh.option.setNumber("Mesh.Algorithm", 1)
gmsh.option.setNumber("Mesh.MeshSizeMin", 0.1)
gmsh.option.setNumber("Mesh.MeshSizeMax", 2)
gmsh.model.mesh.generate(2)
gmsh.write("gmsh_of_cadquery_compound_in_memory.msh")

I shall confirm if this works or not soon

shimwell commented 1 year ago

Confirming that the surface merge and mesh worked

As we can see from this screenshot the resulting gmsh has just 6 surfaces instead of the 7 surfaces made in cadquery because the contact surface has been merged Screenshot from 2023-06-14 20-51-07

adam-urbanczyk commented 1 year ago

Great! Thanks for the investigation @shimwell .