Quick Start

Generate your first crystal visualization in just a few lines of Python code.

Your First Crystal

Create a simple diamond (octahedron) SVG:

from cdl_parser import parse_cdl
from crystal_geometry import cdl_to_geometry
from crystal_renderer import generate_cdl_svg

# One-liner from CDL to SVG
generate_cdl_svg("cubic[m3m]:{111}", "diamond.svg")

This creates diamond.svg - an octahedral crystal commonly seen in natural diamonds.

Understanding the Code

Step 1: Parse the CDL expression

from cdl_parser import parse_cdl

desc = parse_cdl("cubic[m3m]:{111}")
print(desc.system)       # 'cubic'
print(desc.point_group)  # 'm3m'
print(desc.forms)        # [CrystalForm({111}, scale=1.0)]

The CDL expression breaks down as:

  • cubic - Crystal system
  • [m3m] - Point group (highest cubic symmetry)
  • {111} - Miller indices for octahedral form

Step 2: Generate 3D geometry

from crystal_geometry import cdl_to_geometry

geom = cdl_to_geometry(desc)
print(len(geom.vertices))  # 6
print(len(geom.faces))     # 8

This computes vertices and faces using half-space intersection, applying the symmetry operations from the point group.

Step 3: Render to SVG

from crystal_renderer import generate_cdl_svg

generate_cdl_svg("cubic[m3m]:{111}", "diamond.svg")

Generates a matplotlib-based SVG file with orthographic projection and crystallographic axes.

Combining Crystal Forms

Most real crystals show multiple forms. Use + to combine them:

# Fluorite: cube with octahedron corners
generate_cdl_svg("cubic[m3m]:{100}@1.0 + {111}@1.4", "fluorite.svg")

The @distance value controls form development - lower values produce larger faces.

Using Mineral Presets

For common minerals, use the built-in presets:

from mineral_database import get_preset, list_presets
from crystal_renderer import generate_cdl_svg

# Get quartz preset
preset = get_preset("quartz")
if preset:
    print(preset['name'])    # "Quartz"
    print(preset['cdl'])     # CDL expression string
    generate_cdl_svg(preset['cdl'], "quartz.svg")

# List all available presets
names = list_presets()
print(len(names))  # 128 expressions

Customizing Output

View angle and styling

generate_cdl_svg("cubic[m3m]:{111}@1.0 + {100}@1.3", "crystal.svg",
    elev=30,            # degrees from horizontal
    azim=-45,           # rotation around vertical axis
    show_axes=True,     # crystallographic axes
    color_by_form=True, # color faces by form
    show_grid=False,    # hide background grid
    figsize=(10, 10),   # figure size in inches
    dpi=150             # output resolution
)

Exporting to Other Formats

from crystal_geometry import cdl_to_geometry
from crystal_renderer import export_stl, export_gltf
from cdl_parser import parse_cdl

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

# Export for 3D printing
export_stl(geom.vertices, geom.faces, "crystal.stl")

# Export for web/AR/VR
export_gltf(geom.vertices, geom.faces, "crystal.gltf")

Using the CDL CLI

# Parse a CDL expression
cdl parse "cubic[m3m]:{111}@1.0 + {100}@1.3"

# Validate a CDL expression
cdl validate "cubic[m3m]:{111}"

# Output as JSON
cdl parse "cubic[m3m]:{111}" --json

# List reference data
cdl --list-systems
cdl --list-point-groups
cdl --list-forms
cdl --list-twins

Try it Interactively

CDL Playground

Experiment with CDL expressions directly in your browser - no installation needed.

Open Playground