crystal-geometry

Generate 3D crystal geometry from CDL descriptions using half-space intersection and crystallographic symmetry operations.

pip install crystal-geometry

Functions

# cdl_to_geometry(description: CrystalDescription) → CrystalGeometry

Convert a parsed CDL description into 3D geometry.

from cdl_parser import parse_cdl
from crystal_geometry import cdl_to_geometry

desc = parse_cdl("cubic[m3m]:{111}@1.0 + {100}@1.3")
geom = cdl_to_geometry(desc)

print(f"Vertices: {len(geom.vertices)}")  # 14
print(f"Faces: {len(geom.faces)}")        # 14

Parameters:

  • description - Parsed CrystalDescription from cdl-parser

Returns: CrystalGeometry object with vertices, faces, and normals

# apply_symmetry(planes: list[Plane], point_group: str) → list[Plane]

Apply point group symmetry operations to generate all equivalent planes.

from crystal_geometry import apply_symmetry, Plane

# Single {111} plane
planes = [Plane(normal=(1, 1, 1), distance=1.0)]

# Apply m3m symmetry -> 8 equivalent planes
all_planes = apply_symmetry(planes, "m3m")
print(len(all_planes))  # 8
# halfspace_intersection(planes: list[Plane]) → CrystalGeometry

Compute the convex polyhedron defined by the intersection of half-spaces.

from crystal_geometry import halfspace_intersection, Plane

# Define a cube with 6 planes
planes = [
    Plane(normal=(1, 0, 0), distance=1.0),
    Plane(normal=(-1, 0, 0), distance=1.0),
    Plane(normal=(0, 1, 0), distance=1.0),
    Plane(normal=(0, -1, 0), distance=1.0),
    Plane(normal=(0, 0, 1), distance=1.0),
    Plane(normal=(0, 0, -1), distance=1.0),
]

geom = halfspace_intersection(planes)
print(len(geom.vertices))  # 8
print(len(geom.faces))     # 6
# apply_twin(geometry: CrystalGeometry, twin_law: str) → CrystalGeometry

Apply a twin law to create twinned crystal geometry.

from crystal_geometry import cdl_to_geometry, apply_twin

geom = cdl_to_geometry(desc)
twinned = apply_twin(geom, "spinel_law")

Supported twin laws:

  • spinel_law - Cubic {111} contact twin
  • dauphine - Quartz 180° rotation about c-axis
  • brazil - Quartz reflection twin
  • japan_law - Quartz {11-22} contact twin
  • carlsbad - Feldspar twin

Classes

CrystalGeometry

Container for 3D crystal geometry data.

AttributeTypeDescription
vertices np.ndarray Nx3 array of vertex coordinates
faces list[Face] List of Face objects
normals np.ndarray Nx3 array of face normals
face_miller_indices list[MillerIndex] Miller indices for each face
center tuple[float, float, float] Centroid of the geometry
bounds tuple[tuple, tuple] Bounding box (min, max)

Methods

# Transform the geometry
geom.translate(dx, dy, dz)
geom.scale(factor)
geom.rotate(axis, angle)

# Get geometry info
volume = geom.volume()
surface_area = geom.surface_area()

# Export to different formats
geom.to_mesh()     # Returns vertices, faces arrays
geom.to_trimesh()  # Returns trimesh.Trimesh object

Face

Represents a single crystal face.

AttributeTypeDescription
vertex_indices list[int] Indices into vertices array (CCW order)
normal tuple[float, float, float] Outward-facing normal vector
miller_index MillerIndex Miller indices for this face
area float Surface area of the face
centroid tuple[float, float, float] Center point of the face

Plane

Represents a half-space boundary plane.

from crystal_geometry import Plane

# Create from normal and distance
plane = Plane(normal=(1, 1, 1), distance=1.0)

# Create from Miller indices
plane = Plane.from_miller(h=1, k=1, l=1, distance=1.0)

Symmetry Operations

# get_symmetry_matrices(point_group: str) → list[np.ndarray]

Get the 3x3 rotation/reflection matrices for a point group.

from crystal_geometry import get_symmetry_matrices

matrices = get_symmetry_matrices("m3m")
print(len(matrices))  # 48 operations

matrices = get_symmetry_matrices("-3m")
print(len(matrices))  # 12 operations

Unit Cells

# get_unit_cell(system: CrystalSystem, a: float, b: float, c: float, alpha: float, beta: float, gamma: float) → UnitCell

Create a unit cell with specified parameters.

from crystal_geometry import get_unit_cell
from cdl_parser import CrystalSystem

# Quartz unit cell
cell = get_unit_cell(
    system=CrystalSystem.TRIGONAL,
    a=4.913, b=4.913, c=5.405,
    alpha=90, beta=90, gamma=120
)

# Get transformation matrix
transform = cell.cartesian_matrix()