Skip to content

Mesh geometry import#3197

Draft
Luochenghuang wants to merge 2 commits intoNanoComp:masterfrom
Luochenghuang:mesh-geometry-import
Draft

Mesh geometry import#3197
Luochenghuang wants to merge 2 commits intoNanoComp:masterfrom
Luochenghuang:mesh-geometry-import

Conversation

@Luochenghuang
Copy link
Copy Markdown
Contributor

@Luochenghuang Luochenghuang commented Apr 7, 2026

Summary

Adds Python support for the new MESH geometric object type from Luochenghuang/libctl#mesh-geometry-import. This enables importing arbitrary triangulated 3D surfaces (e.g., from STL/OBJ files) directly into meep simulations.

Depends on libctl with MESH support (NanoComp/libctl#74).
Closes #138.

Changes

python/geom.pyMesh class and file parsers:

  • Mesh(vertices, triangles, center=None, material=...) — triangulated surface geometry
  • Mesh.from_stl(filename, ...) — binary and ASCII STL import with vertex welding
  • Mesh.from_obj(filename, ...) — Wavefront OBJ import with quad triangulation
  • No external dependencies (parsers are pure Python using struct and re)

python/typemap_utils.cpp — C++ binding:

  • pymesh_to_mesh — extracts vertices and triangles from Python, calls make_mesh_with_center
  • "Mesh" case added to py_gobj_to_gobj dispatch

Usage

import meep as mp

# From STL file
teapot = mp.Mesh.from_stl("model.stl", scale=0.1,
                           material=mp.Medium(epsilon=12))

# From vertices and triangles directly
cube = mp.Mesh(
    vertices=[(-0.5,-0.5,-0.5), (0.5,-0.5,-0.5), ...],
    triangles=[(0,2,1), (0,3,2), ...],
    material=mp.Medium(epsilon=12),
)

sim = mp.Simulation(cell_size=cell, geometry=[teapot], resolution=10)

Subpixel smoothing, epsilon grid queries, and all other meep features work automatically.

Test plan

5 integration tests in python/tests/test_mesh.py:

Test What it verifies
test_stl_import Binary STL parse + vertex welding (8 verts, 12 faces)
test_point_in_mesh Known points inside/outside a cube mesh
test_volume Fill fraction from grid sampling matches analytic
test_eps_averaging Smoothing produces intermediate epsilon at interfaces
test_mesh_vs_block Cube mesh epsilon grid matches native Block exactly

- Mesh class in geom.py: vertices + triangles, optional center,
  from_stl() and from_obj() classmethods with built-in parsers
  (binary/ASCII STL with vertex welding, OBJ with quad triangulation)
- pymesh_to_mesh in typemap_utils.cpp: extracts vertices and triangles
  from Python, calls make_mesh_with_center from libctl
- Mesh exported from meep.__init__ (requires manual addition to
  generated __init__.py until codegen is updated)

Requires libctl with MESH support (Luochenghuang/libctl#mesh-geometry-import).
Two tests (~1s total):
1. Geometric convergence: mesh icosphere L2 error vs native Sphere
   decreases with subdivision (20 faces -> 5120 faces -> exact match)
2. Subpixel smoothing: eps_averaging=True produces intermediate
   epsilon values at mesh-air interfaces, confirming Kottke averaging
   works for mesh objects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

STL import

1 participant