From b01ef2af1baf6cc909a3e0d18886dc8bbf61819c Mon Sep 17 00:00:00 2001 From: Bissbert <43237892+Bissbert@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:27:41 +0700 Subject: [PATCH] docs: rewrite documentation pages for CDL v1.3 Comprehensive rewrite of all 10 documentation pages to reflect the current state of the codebase and CDL v1.3 syntax: - cdl.astro: Full CDL specification with v1.3 features (phenomena, feature annotations, doc comments, grouping, labels, references) - cdl-examples.astro: Updated examples gallery with correct syntax - installation.astro: Corrected package names and version numbers - quickstart.astro: Fixed API function names and import paths - cli.astro: Restructured for all 3 CLIs (cdl, mineral-db, cdl-lsp) - cli-options.astro: Full rewrite with actual CLI flags and options - api/cdl-parser.astro: Correct types and new v1.3 model classes - api/crystal-geometry.astro: Actual geometry API documentation - api/mineral-database.astro: Synthetic/simulant query documentation - api/crystal-renderer.astro: Actual renderer API documentation Refs: CDL v1.3 documentation audit --- src/pages/docs/api/cdl-parser.astro | 427 ++++++++++--- src/pages/docs/api/crystal-geometry.astro | 272 +++++---- src/pages/docs/api/crystal-renderer.astro | 381 ++++++------ src/pages/docs/api/mineral-database.astro | 374 ++++++++---- src/pages/docs/cdl-examples.astro | 161 +++-- src/pages/docs/cdl.astro | 703 +++++++++++++++++++--- src/pages/docs/cli-options.astro | 297 +++++---- src/pages/docs/cli.astro | 249 ++++---- src/pages/docs/installation.astro | 58 +- src/pages/docs/quickstart.astro | 97 +-- 10 files changed, 2087 insertions(+), 932 deletions(-) diff --git a/src/pages/docs/api/cdl-parser.astro b/src/pages/docs/api/cdl-parser.astro index f1e9fca..84ca504 100644 --- a/src/pages/docs/api/cdl-parser.astro +++ b/src/pages/docs/api/cdl-parser.astro @@ -4,16 +4,56 @@ import { Breadcrumb, CodeBlock, APISignature, PropsTable, PageNav } from '../../ import { Container } from '../../../components/ui-astro'; const crystalDescriptionAttrs = [ - { name: 'system', type: 'CrystalSystem', description: 'Crystal system enum' }, - { name: 'point_group', type: 'str', description: 'Point group symbol' }, - { name: 'forms', type: 'list[Form]', description: 'List of crystal forms' }, - { name: 'twin_law', type: 'str | None', description: 'Optional twin law name' }, - { name: 'modifiers', type: 'dict[str, Any]', description: 'Optional modifiers (elongate, etc.)' }, + { name: 'system', type: 'str', description: 'Crystal system name (e.g., "cubic", "trigonal")' }, + { name: 'point_group', type: 'str', description: 'Hermann-Mauguin point group symbol (e.g., "m3m")' }, + { name: 'forms', type: 'list[FormNode]', description: 'List of form nodes (CrystalForm or FormGroup)' }, + { name: 'modifications', type: 'list[Modification]', description: 'Morphological modifications (elongate, flatten, etc.)' }, + { name: 'twin', type: 'TwinSpec | None', description: 'Optional twin specification' }, + { name: 'phenomenon', type: 'PhenomenonSpec | None', description: 'Optional optical phenomenon' }, + { name: 'definitions', type: 'list[Definition] | None', description: 'Named definitions (@name = expression)' }, + { name: 'doc_comments', type: 'list[str] | None', description: 'Doc comments (#! Key: Value)' }, ]; -const formAttrs = [ - { name: 'miller_indices', type: 'MillerIndex', description: 'Miller indices for this form' }, - { name: 'distance', type: 'float', description: 'Distance from origin (default 1.0)' }, +const crystalFormAttrs = [ + { name: 'miller', type: 'MillerIndex', description: 'Miller index defining the form' }, + { name: 'scale', type: 'float', description: 'Distance scale (default 1.0, larger = more truncated)' }, + { name: 'name', type: 'str | None', description: 'Original name if using named form (e.g., "octahedron")' }, + { name: 'features', type: 'list[Feature] | None', description: 'Per-form feature annotations' }, + { name: 'label', type: 'str | None', description: 'Optional label (e.g., "prism" in prism:{10-10})' }, +]; + +const formGroupAttrs = [ + { name: 'forms', type: 'list[FormNode]', description: 'Child form nodes in this group' }, + { name: 'features', type: 'list[Feature] | None', description: 'Shared features applied to all children' }, + { name: 'label', type: 'str | None', description: 'Optional group label' }, +]; + +const featureAttrs = [ + { name: 'name', type: 'str', description: 'Feature type (phantom, trigon, silk, colour, etc.)' }, + { name: 'values', type: 'list[int | float | str]', description: 'Feature values (numbers, identifiers, color specs)' }, +]; + +const twinSpecAttrs = [ + { name: 'law', type: 'str | None', description: 'Named twin law (spinel, brazil, japan, etc.)' }, + { name: 'axis', type: 'tuple | None', description: 'Custom twin axis [x, y, z]' }, + { name: 'angle', type: 'float', description: 'Rotation angle in degrees (default 180)' }, + { name: 'twin_type', type: 'str', description: 'Type: "contact", "penetration", or "cyclic"' }, + { name: 'count', type: 'int', description: 'Number of twin individuals (default 2)' }, +]; + +const modificationAttrs = [ + { name: 'type', type: 'str', description: 'Type: "elongate", "truncate", "taper", "bevel", or "flatten"' }, + { name: 'params', type: 'dict[str, Any]', description: 'Parameters (e.g., {"axis": "c", "ratio": 1.5})' }, +]; + +const phenomenonSpecAttrs = [ + { name: 'type', type: 'str', description: 'Phenomenon type (asterism, chatoyancy, etc.)' }, + { name: 'params', type: 'dict[str, int | float | str]', description: 'Parameters (e.g., {"value": 6})' }, +]; + +const definitionAttrs = [ + { name: 'name', type: 'str', description: 'Definition name (from @name = expression)' }, + { name: 'body', type: 'list[FormNode]', description: 'Parsed form nodes for the definition body' }, ]; --- @@ -33,19 +73,20 @@ const formAttrs = [

Parse and validate Crystal Description Language (CDL) expressions. - Zero external dependencies. + Zero external dependencies. Version 1.3.0.

- +

Functions

-

Parse a CDL expression string into a structured CrystalDescription object.

+

Parse a CDL string into a structured CrystalDescription object. + Handles comments, definitions, forms, modifications, twins, and phenomena.

Parameters:

    -
  • expression - CDL expression string
  • +
  • text - CDL expression string

Returns: CrystalDescription object

-

Raises: CDLParseError if the expression is invalid

+

Raises:

+
    +
  • ParseError - if the expression has a syntax error
  • +
  • ValidationError - if semantically invalid (e.g., wrong point group for system)
  • +
-

Validate a CDL expression without fully parsing it. Returns detailed error information.

+

Validate a CDL expression without raising exceptions. Returns a tuple of + (is_valid, error_message).

-

Tokenize a CDL expression into a list of tokens. Useful for syntax highlighting.

+

Strip comments from CDL text. Extracts doc comments (#!), + removes block comments (/* ... */) and line comments (#).

Classes

CrystalDescription

-

Represents a parsed CDL expression.

+

The main output of CDL parsing, containing all information needed + to generate a crystal visualization.

-

Form

+

Methods

+ + + +

CrystalForm

+ +

Represents a single crystal form (set of symmetry-equivalent faces) + with an optional distance scale for truncation.

+ + + +

FormGroup

+ +

A parenthesized group of forms with optional shared features and label. + Syntax: (form + form)[shared_features]

+ + + +

FormNode

+ +

Type alias: FormNode = CrystalForm | FormGroup. + Used as the element type for CrystalDescription.forms.

+ +

Feature

+ +

Describes growth patterns, surface markings, inclusions, or colour properties + on a crystal form.

+ + + + + +

TwinSpec

+ +

Defines how crystal twinning should be applied.

+ + + + + +

Modification

-

Represents a single crystal form (set of Miller indices with distance).

+

Represents a morphological transformation applied to the crystal shape.

+ + + +

PhenomenonSpec

+ +

Optical phenomenon specification (asterism, chatoyancy, etc.).

+ + + + + +

Definition

+ +

A named definition that allows reuse via @name = expression + and $name references.

+ +

MillerIndex

@@ -144,65 +339,155 @@ for token in tokens: # 3-index notation mi = MillerIndex(1, 1, 1) -print(mi) # {111} +print(mi) # {111} +print(mi.as_tuple()) # (1, 1, 1) # 4-index notation (Miller-Bravais) -mi = MillerIndex(1, 0, -1, 0) -print(mi) # {10-10} - -# Convert between notations -mi_3 = mi.to_3index() -mi_4 = mi.to_4index()`} +mi = MillerIndex(1, 0, 1, i=-1) +print(mi) # {10-11} +print(mi.as_tuple()) # (1, 0, -1, 1) +print(mi.as_3index()) # (1, 0, 1)`} /> -

CrystalSystem

+

Exceptions

+ +

CDLError

+ +

Base exception for all CDL-related errors.

-

Enum of the seven crystal systems.

+

ParseError

+ +

Raised when CDL parsing fails due to a syntax error. Contains position information.

-

Exceptions

- -

CDLParseError

+

ValidationError

-

Raised when parsing fails. Contains detailed error information.

+

Raised when CDL is syntactically valid but semantically incorrect + (e.g., invalid point group for the given crystal system).

Constants

+

CRYSTAL_SYSTEMS

+ +

Set of the seven crystal system names.

+ + +

POINT_GROUPS

-

Dictionary mapping crystal systems to valid point groups.

+

Dictionary mapping crystal system names to their valid point groups.

+ +

DEFAULT_POINT_GROUPS

+ +

Dictionary mapping each crystal system to its default (highest symmetry) point group.

+ + + +

NAMED_FORMS

+ +

Dictionary mapping form names to Miller indices (h, k, l).

+ + + +

TWIN_LAWS

+ +

Set of recognised twin law names.

+ + + +

FEATURE_NAMES

+ +

Set of recognised feature annotation names (phantom, trigon, silk, colour, etc.).

+ +

PHENOMENON_TYPES

+ +

Set of recognised phenomenon types (asterism, chatoyancy, adularescence, etc.).

+ +

MODIFICATION_TYPES

+ +

Set of recognised modification types: elongate, truncate, taper, bevel, flatten.

+ +

Lexer/Parser Internals

+ +

For advanced use cases (syntax highlighting, custom processing):

+ + diff --git a/src/pages/docs/api/crystal-geometry.astro b/src/pages/docs/api/crystal-geometry.astro index 127b051..b0cb788 100644 --- a/src/pages/docs/api/crystal-geometry.astro +++ b/src/pages/docs/api/crystal-geometry.astro @@ -5,19 +5,20 @@ import { Container } from '../../../components/ui-astro'; const geometryAttrs = [ { name: 'vertices', type: 'np.ndarray', description: 'Nx3 array of vertex coordinates' }, - { name: 'faces', type: 'list[Face]', description: 'List of Face objects' }, - { name: 'normals', type: 'np.ndarray', description: 'Nx3 array of face normals' }, - { name: 'face_miller_indices', type: 'list[MillerIndex]', description: 'Miller indices for each face' }, - { name: 'center', type: 'tuple[float, float, float]', description: 'Centroid of the geometry' }, - { name: 'bounds', type: 'tuple[tuple, tuple]', description: 'Bounding box (min, max)' }, + { name: 'faces', type: 'list[list[int]]', description: 'List of faces (each face is a list of vertex indices)' }, + { name: 'face_normals', type: 'list[np.ndarray]', description: 'Normal vectors for each face' }, + { name: 'face_millers', type: 'list[tuple]', description: 'Miller indices for each face' }, + { name: 'face_forms', type: 'list[int]', description: 'Form index for each face (for color-by-form rendering)' }, + { name: 'twin', type: 'TwinMetadata | None', description: 'Twin metadata if geometry is twinned' }, ]; -const faceAttrs = [ - { name: 'vertex_indices', type: 'list[int]', description: 'Indices into vertices array (CCW order)' }, - { name: 'normal', type: 'tuple[float, float, float]', description: 'Outward-facing normal vector' }, - { name: 'miller_index', type: 'MillerIndex', description: 'Miller indices for this face' }, - { name: 'area', type: 'float', description: 'Surface area of the face' }, - { name: 'centroid', type: 'tuple[float, float, float]', description: 'Center point of the face' }, +const latticeAttrs = [ + { name: 'a', type: 'float', description: 'Unit cell parameter a' }, + { name: 'b', type: 'float', description: 'Unit cell parameter b' }, + { name: 'c', type: 'float', description: 'Unit cell parameter c' }, + { name: 'alpha', type: 'float', description: 'Angle alpha in degrees' }, + { name: 'beta', type: 'float', description: 'Angle beta in degrees' }, + { name: 'gamma', type: 'float', description: 'Angle gamma in degrees' }, ]; --- @@ -37,19 +38,20 @@ const faceAttrs = [

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

- + -

Functions

+

Core Functions

-

Convert a parsed CDL description into 3D geometry.

+

Convert a parsed CDL description into 3D geometry. Uses desc.flat_forms() + internally to handle FormGroup nodes.

@@ -71,178 +73,198 @@ print(f"Faces: {len(geom.faces)}") # 14`}

Returns: CrystalGeometry object with vertices, faces, and normals

-

Apply point group symmetry operations to generate all equivalent planes.

+

Convenience function that parses a CDL string and generates geometry in one call.

8 equivalent planes -all_planes = apply_symmetry(planes, "m3m") -print(len(all_planes)) # 8`} +geom = cdl_string_to_geometry("cubic[m3m]:{111}") +print(len(geom.vertices)) # 6 +print(len(geom.faces)) # 8`} /> -

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

+

Compute the convex polyhedron defined by half-space intersection. + Returns vertices and faces.

+ +

Convenience Constructors

+

Symmetry Operations

+ -

Apply a twin law to create twinned crystal geometry.

+

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

-

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

+

Generate all symmetry-equivalent face normals from a single Miller index.

-

CrystalGeometry

+ -

Container for 3D crystal geometry data.

+

Convert Miller indices to a Cartesian normal vector using lattice parameters.

- + +

Get default lattice parameters for a crystal system.

+ +

Modification Functions

+ + -

Methods

+

Apply morphological modifications (elongate, flatten, taper) to vertices.

-

Face

+

Twin System

-

Represents a single crystal face.

+ +# List all available twin laws +laws = list_twin_laws() +print(laws) # ['spinel', 'iron_cross', 'brazil', ...] + +# Get a specific twin law +law = get_twin_law("spinel") +print(law.name) # 'spinel' +print(law.axis) # Twin axis +print(law.angle) # Rotation angle -

Plane

+# Get all twin laws for a specific gemstone +twins = get_gemstone_twins("quartz") +print(twins) # ['dauphine', 'brazil', 'japan']`} + /> -

Represents a half-space boundary plane.

+

Habit System

+# List all registered habits +habits = list_habits() +print(habits) # ['octahedron', 'cube', 'hexagonal_prism', ...] -

Symmetry Operations

+# Get a specific habit +habit = get_habit("hexagonal_prism") +geom = habit.generate() - -

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

+

Classes

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

Container for 3D crystal geometry data.

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

Unit Cells

+

LatticeParams

- Unit cell lattice parameters.

+ + -

Create a unit cell with specified parameters.

+

Backend Acceleration

diff --git a/src/pages/docs/api/crystal-renderer.astro b/src/pages/docs/api/crystal-renderer.astro index a7a1583..3e532d8 100644 --- a/src/pages/docs/api/crystal-renderer.astro +++ b/src/pages/docs/api/crystal-renderer.astro @@ -3,35 +3,39 @@ import BaseLayout from '../../../layouts/BaseLayout.astro'; import { Breadcrumb, CodeBlock, APISignature, PropsTable, PageNav } from '../../../components/docs'; import { Container } from '../../../components/ui-astro'; -const svgOptions = [ - { option: 'width', type: 'int', default: '400', description: 'SVG width in pixels' }, - { option: 'height', type: 'int', default: '400', description: 'SVG height in pixels' }, - { option: 'elevation', type: 'float', default: '30', description: 'View elevation in degrees' }, - { option: 'azimuth', type: 'float', default: '-45', description: 'View azimuth in degrees' }, - { option: 'zoom', type: 'float', default: '1.0', description: 'Zoom factor' }, - { option: 'face_color', type: 'str', default: '"#0ea5e9"', description: 'Face fill color (hex)' }, - { option: 'edge_color', type: 'str', default: '"#0369a1"', description: 'Edge stroke color' }, - { option: 'edge_width', type: 'float', default: '1.5', description: 'Edge stroke width' }, - { option: 'opacity', type: 'float', default: '0.85', description: 'Face opacity (0-1)' }, - { option: 'gradient', type: 'bool', default: 'True', description: 'Apply lighting gradient' }, - { option: 'show_axes', type: 'bool', default: 'False', description: 'Show crystallographic axes' }, - { option: 'show_labels', type: 'bool', default: 'False', description: 'Show Miller index labels' }, - { option: 'title', type: 'str', default: 'None', description: 'Title text below crystal' }, +const cdlSvgParams = [ + { option: 'cdl_string', type: 'str', default: 'Required', description: 'CDL notation string' }, + { option: 'output_path', type: 'str | Path', default: 'Required', description: 'Output SVG file path' }, + { option: 'show_axes', type: 'bool', default: 'True', description: 'Show crystallographic axes' }, + { option: 'elev', type: 'float', default: '30', description: 'Elevation angle in degrees' }, + { option: 'azim', type: 'float', default: '-45', description: 'Azimuth angle in degrees' }, + { option: 'color_by_form', type: 'bool', default: 'False', description: 'Color faces by which form they belong to' }, + { option: 'show_grid', type: 'bool', default: 'True', description: 'Show background grid and panes' }, + { option: 'face_labels', type: 'bool', default: 'False', description: 'Show Miller index labels on visible faces' }, + { option: 'info_properties', type: 'dict | None', default: 'None', description: 'Dictionary of properties for info panel' }, + { option: 'info_position', type: 'str', default: '"top-right"', description: 'Info panel position' }, + { option: 'info_style', type: 'str', default: '"compact"', description: 'Panel style: compact, detailed, or minimal' }, + { option: 'info_fontsize', type: 'int', default: '10', description: 'Font size for info panel' }, + { option: 'figsize', type: 'tuple[int, int]', default: '(10, 10)', description: 'Figure size in inches' }, + { option: 'dpi', type: 'int', default: '150', description: 'Output resolution in DPI' }, + { option: 'c_ratio', type: 'float | None', default: 'None', description: 'c/a ratio for non-cubic systems (default 1.1 for trigonal/hexagonal)' }, ]; -const stlOptions = [ - { option: 'scale', type: 'float', default: '10.0', description: 'Scale factor (output size)' }, - { option: 'binary', type: 'bool', default: 'True', description: 'Use binary format' }, - { option: 'units', type: 'str', default: '"mm"', description: 'Units: "mm", "cm", "in"' }, -]; - -const gltfOptions = [ - { option: 'scale', type: 'float', default: '1.0', description: 'Scale factor' }, - { option: 'color', type: 'tuple', default: '(0.05, 0.65, 0.91)', description: 'Base color RGB (0-1)' }, - { option: 'metallic', type: 'float', default: '0.0', description: 'Metallic factor (0-1)' }, - { option: 'roughness', type: 'float', default: '0.3', description: 'Roughness factor (0-1)' }, - { option: 'opacity', type: 'float', default: '1.0', description: 'Opacity (0-1)' }, - { option: 'binary', type: 'bool', default: 'auto', description: 'Use GLB format' }, +const geometrySvgParams = [ + { option: 'vertices', type: 'np.ndarray', default: 'Required', description: 'Nx3 array of vertex positions' }, + { option: 'faces', type: 'list[list[int]]', default: 'Required', description: 'List of faces (vertex index lists)' }, + { option: 'output_path', type: 'str | Path', default: 'Required', description: 'Output SVG file path' }, + { option: 'face_normals', type: 'list | None', default: 'None', description: 'Optional face normal vectors' }, + { option: 'show_axes', type: 'bool', default: 'True', description: 'Show crystallographic axes' }, + { option: 'elev', type: 'float', default: '30', description: 'Elevation angle in degrees' }, + { option: 'azim', type: 'float', default: '-45', description: 'Azimuth angle in degrees' }, + { option: 'show_grid', type: 'bool', default: 'True', description: 'Show background grid and panes' }, + { option: 'face_color', type: 'str', default: '"#81D4FA"', description: 'Face fill color (hex)' }, + { option: 'edge_color', type: 'str', default: '"#0277BD"', description: 'Edge stroke color (hex)' }, + { option: 'title', type: 'str | None', default: 'None', description: 'Optional title text' }, + { option: 'info_properties', type: 'dict | None', default: 'None', description: 'Properties for info panel' }, + { option: 'figsize', type: 'tuple[int, int]', default: '(10, 10)', description: 'Figure size in inches' }, + { option: 'dpi', type: 'int', default: '150', description: 'Output resolution in DPI' }, ]; --- @@ -51,246 +55,281 @@ const gltfOptions = [

Render crystal geometry to SVG for visualization, STL for 3D printing, - and glTF for web/AR/VR applications. + and glTF for web/AR/VR applications. Version 1.0.1.

- +

SVG Rendering

-

Render crystal geometry to SVG format.

+

Generate an SVG visualization directly from a CDL string. This is the primary + rendering function - it parses the CDL, generates geometry, and renders to SVG + in one call.

-

SVG Options

+

Parameters

-

Convenience function to render directly from a CDL string.

+

Generate an SVG from raw geometry data (vertices and faces). Use this when you + already have computed geometry and want control over face/edge colours.

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

Parameters

-# With options -generate_cdl_svg( - "cubic[m3m]:{111}@1.0 + {100}@1.3", - "truncated.svg", - face_color="#8b5cf6" -)`} +

3D Export

-

Export crystal geometry to STL format for 3D printing.

+

Export crystal geometry to STL format for 3D printing. Takes raw vertices + and faces, not a geometry object.

+# Binary STL (smaller file) +export_stl(geom.vertices, geom.faces, "crystal.stl") -

STL Options

+# ASCII STL (human-readable) +export_stl(geom.vertices, geom.faces, "crystal.stl", binary=False)`} + /> - +

Convert geometry to STL format in memory, returning the file content as bytes.

+ -

Export crystal geometry to glTF 2.0 format for web, AR, and VR applications.

+

Export crystal geometry to glTF 2.0 format for web, AR, and VR applications. + Stores original polygon edges in extras.crystalEdges for accurate + edge rendering.

-# Binary format (single file) -export_gltf(geom, "crystal.glb") # Auto-detects from extension`} + -

glTF Options

+

Convert geometry to glTF format in memory, returning the glTF JSON structure.

- +

Format Conversion

-

Export to GEMCAD .asc format for gem cutting design.

+

Convert an SVG file to raster format (PNG, JPG, or BMP). Requires the + raster optional dependencies.

-

Batch Rendering

+ -

Render multiple crystals efficiently.

+

Generate a crystal visualization in any supported format. Wraps a generator + function, automatically converting through SVG for raster outputs.

- Info Panel -print(f"Generated {len(output_files)} files")`} + -

View Utilities

+

Render a properties info panel on a matplotlib axes.

-

Create a camera for consistent view angles.

+

Create an FGA-style info panel dictionary from a mineral preset.

- Rendering Primitives -camera = create_camera( - elevation=35, # degrees from horizontal - azimuth=-45, # rotation around vertical - distance=5.0 # distance from origin -) +

Low-level drawing functions for building custom visualizations:

-# Use same camera for multiple renders -generate_svg(geom1, "crystal1.svg", camera=camera) -generate_svg(geom2, "crystal2.svg", camera=camera)`} + - +

Projection Utilities

-

Project 3D geometry to 2D for custom rendering.

+

Functions for 3D-to-2D projection and visibility calculations:

-camera = create_camera(elevation=30, azimuth=-45) -projected = project_to_2d(geom, camera) +

Constants

-# Access 2D data -for face in projected.faces: - print(face.vertices_2d) # [(x, y), ...] - print(face.depth) # Z-order for painting - print(face.brightness) # Lighting intensity`} + diff --git a/src/pages/docs/api/mineral-database.astro b/src/pages/docs/api/mineral-database.astro index 7dca402..e0f25cc 100644 --- a/src/pages/docs/api/mineral-database.astro +++ b/src/pages/docs/api/mineral-database.astro @@ -3,22 +3,34 @@ import BaseLayout from '../../../layouts/BaseLayout.astro'; import { Breadcrumb, CodeBlock, APISignature, PropsTable, PageNav } from '../../../components/docs'; import { Container, Card } from '../../../components/ui-astro'; -const presetAttrs = [ - { name: 'name', type: 'str', description: 'Mineral name' }, +const mineralAttrs = [ + { name: 'id', type: 'str', description: 'Preset ID (e.g., "diamond-octahedron")' }, + { name: 'name', type: 'str', description: 'Display name' }, { name: 'cdl', type: 'str', description: 'CDL expression' }, { name: 'system', type: 'str', description: 'Crystal system' }, { name: 'point_group', type: 'str', description: 'Point group symbol' }, - { name: 'formula', type: 'str | None', description: 'Chemical formula' }, - { name: 'hardness', type: 'float | None', description: 'Mohs hardness' }, - { name: 'specific_gravity', type: 'tuple[float, float] | None', description: 'SG range' }, - { name: 'ri_range', type: 'tuple[float, float] | None', description: 'Refractive index range' }, + { name: 'chemistry', type: 'str', description: 'Chemical formula' }, + { name: 'hardness', type: 'int | float | str', description: 'Mohs hardness (may be range like "6-7")' }, + { name: 'sg', type: 'float | str | None', description: 'Specific gravity' }, + { name: 'ri', type: 'float | str | None', description: 'Refractive index' }, { name: 'birefringence', type: 'float | None', description: 'Maximum birefringence' }, - { name: 'optic_sign', type: 'str | None', description: '"+" or "-" or None (isotropic)' }, - { name: 'optic_character', type: 'str | None', description: '"uniaxial" or "biaxial" or None' }, + { name: 'optical_character', type: 'str | None', description: 'Optical character' }, { name: 'dispersion', type: 'float | None', description: 'Dispersion value' }, - { name: 'colors', type: 'list[str]', description: 'Common colors' }, + { name: 'colors', type: 'list[str]', description: 'Common colours' }, { name: 'cleavage', type: 'str | None', description: 'Cleavage description' }, - { name: 'varieties', type: 'list[str]', description: 'Named varieties' }, + { name: 'twin_law', type: 'str | None', description: 'Twin law name' }, + { name: 'origin', type: 'str', description: 'Origin: natural, synthetic, simulant, or composite' }, +]; + +const familyAttrs = [ + { name: 'id', type: 'str', description: 'Family ID (e.g., "diamond")' }, + { name: 'name', type: 'str', description: 'Display name (e.g., "Diamond")' }, + { name: 'crystal_system', type: 'str', description: 'Crystal system' }, + { name: 'point_group', type: 'str | None', description: 'Point group symbol' }, + { name: 'chemistry', type: 'str | None', description: 'Chemical formula' }, + { name: 'origin', type: 'str', description: 'Origin: natural, synthetic, simulant, composite' }, + { name: 'growth_method', type: 'str | None', description: 'Synthesis method (synthetics only)' }, + { name: 'natural_counterpart_id', type: 'str | None', description: 'ID of natural equivalent' }, ]; --- @@ -37,20 +49,20 @@ const presetAttrs = [

mineral-database

- SQLite database of 94+ mineral presets with CDL definitions, crystal system data, - and gemmological properties. + SQLite database of 96 mineral families (68 natural + 15 synthetic + 9 simulant + 4 composite) + with 128 CDL expressions, crystal system data, and gemmological properties. Version 1.8.1.

- + -

Functions

+

Core Query Functions

-

Get a mineral preset by name (case-insensitive).

+

Get a mineral preset by name (case-insensitive). Returns a dictionary.

+ + -

Parameters:

-
    -
  • name - Mineral name (case-insensitive)
  • -
+

Get a Mineral object by name. Returns a typed dataclass instead of a dict.

-

Returns: MineralPreset or None if not found

+ -

List all available preset names.

+

List all available preset names, optionally filtered by crystal system or category.

-

Search presets by name, formula, or properties.

+

Search presets using full-text search across name, chemistry, and description.

-# Search by crystal system -results = search("cubic")`} + +

Filter minerals by various criteria.

+ + + +

RI/SG Lookup

+ -

Get all presets for a specific crystal system.

+

Find minerals matching a measured refractive index, sorted by closest match.

-# Valid systems: cubic, hexagonal, trigonal, tetragonal, -# orthorhombic, monoclinic, triclinic`} + +

Find minerals matching a specific gravity value, sorted by closest match.

+ +

Synthetic and Simulant Queries

+ -

Get presets within a hardness range.

+

List all synthetic mineral family IDs, optionally filtered by growth method.

-

Find minerals matching a measured refractive index.

+

List all simulant mineral family IDs, optionally filtered by what they imitate.

-

Classes

+ -

MineralPreset

+

Get all synthetic and simulant counterparts for a natural mineral.

-

Complete mineral data including CDL and gemmological properties.

+ + + + +

List all mineral family IDs filtered by origin type.

+ + + + -

Methods

+

Get a MineralFamily object by ID, including synthetic-specific fields.

-

Database Information

+

Calculator Utilities

-

Get database metadata.

+

Classify a gemmological value based on standard thresholds.

+ + -

Custom Database

+

Get cut shape factors for carat weight estimation.

-

Load a custom SQLite database with additional presets:

+ + +

Get minerals with heat treatment temperature data.

+ +

Database Configuration

+ + + +

Override the default database path for all queries.

+ +

Classes

+ +

Mineral

-# Load custom database -db = MineralDatabase("/path/to/custom.db") +

Dataclass representing a mineral preset with all gemmological properties.

-# Use same API -preset = db.get_preset("custom_mineral") -all_presets = db.list_presets()`} + -

Included Presets

+

MineralFamily

-

The database includes 94 mineral presets organized by crystal system:

+

Dataclass representing a mineral family (normalized structure). Includes + synthetic-specific fields like growth_method, manufacturer, + and diagnostic_synthetic_features.

-
- -

Cubic (18)

-

Diamond, Spinel, Garnet group, Pyrite, Fluorite...

-
- -

Hexagonal (12)

-

Beryl varieties, Apatite, Zincite...

-
+ + +

Included Data

+ +

The database includes 96 mineral families with 128 CDL expressions:

+ +
-

Trigonal (15)

-

Quartz varieties, Corundum, Tourmaline, Calcite...

+

Natural (68)

+

Diamond, Ruby, Emerald, Quartz, Garnet...

- -

Tetragonal (8)

-

Zircon, Rutile, Cassiterite, Vesuvianite...

+ +

Synthetic (15)

+

CVD Diamond, Flux Ruby, Hydrothermal Emerald...

- -

Orthorhombic (14)

-

Topaz, Peridot, Chrysoberyl, Tanzanite...

+ +

Simulant (9)

+

CZ, Moissanite, YAG, Glass...

- -

Monoclinic (12)

-

Orthoclase, Jadeite, Spodumene, Malachite...

+ +

Composite (4)

+

Garnet-Topped Doublet, Opal Triplet...

diff --git a/src/pages/docs/cdl-examples.astro b/src/pages/docs/cdl-examples.astro index 2d6f3dd..f3ee67d 100644 --- a/src/pages/docs/cdl-examples.astro +++ b/src/pages/docs/cdl-examples.astro @@ -6,55 +6,108 @@ import { Container, Button, Card } from '../../components/ui-astro'; const examples = [ { - category: 'Gemstones', + category: 'Basic Crystals', + description: 'Single-form crystal habits using Miller indices or named forms.', items: [ - { name: 'Diamond', cdl: 'cubic[m3m]:{111}@1.0', description: 'Classic octahedral habit' }, - { name: 'Ruby/Sapphire', cdl: 'trigonal[-3m]:{10-10}@1.0 + {0001}@1.2 + {10-11}@0.8', description: 'Hexagonal prism with pinacoid and rhombohedron' }, - { name: 'Emerald', cdl: 'hexagonal[6/mmm]:{10-10}@1.0 + {0001}@1.5', description: 'Beryl structure with prism and pinacoid' }, - { name: 'Spinel', cdl: 'cubic[m3m]:{111}@1.0 + {110}@1.5', description: 'Octahedron modified by dodecahedron' }, - { name: 'Garnet', cdl: 'cubic[m3m]:{110}@1.0 + {211}@1.2', description: 'Rhombic dodecahedron with trapezohedron' }, + { name: 'Diamond Octahedron', cdl: 'cubic[m3m]:{111}', description: 'Classic octahedral habit' }, + { name: 'Fluorite Cube', cdl: 'cubic[m3m]:{100}', description: 'Perfect cubic habit' }, + { name: 'Garnet Dodecahedron', cdl: 'cubic[m3m]:{110}', description: 'Rhombic dodecahedron' }, + { name: 'Garnet Trapezohedron', cdl: 'cubic[m3m]:{211}', description: 'Icositetrahedron habit' }, + { name: 'Hexagonal Prism', cdl: 'hexagonal[6/mmm]:{10-10}', description: 'Basic hexagonal prism (beryl, apatite)' }, + { name: 'Calcite Rhomb', cdl: 'trigonal[-3m]:{10-11}', description: 'Rhombohedral cleavage form' }, + { name: 'Pyritohedron', cdl: 'cubic[m-3]:{210}', description: 'Pentagonal dodecahedron (pyrite)' }, + { name: 'Ruby Tabular', cdl: 'trigonal[-3m]:{10-11}@1.0 + {0001}@0.4', description: 'Tabular habit with dipyramid and pinacoid' }, + ], + }, + { + category: 'Multi-form Combinations', + description: 'Crystals with multiple forms combined using the + operator.', + items: [ + { name: 'Diamond (Octahedron + Dodecahedron)', cdl: 'cubic[m3m]:{111}@1.0 + {110}@0.2', description: 'Octahedron with minor dodecahedron truncation' }, + { name: 'Fluorite Cuboctahedron', cdl: 'cubic[m3m]:{100}@1.0 + {111}@1.0', description: 'Equal cube and octahedron development' }, + { name: 'Garnet Combination', cdl: 'cubic[m3m]:{110}@1.0 + {211}@0.6', description: 'Dodecahedron with trapezohedron' }, + { name: 'Beryl Hexagonal Prism', cdl: 'hexagonal[6/mmm]:{10-10}@1.0 + {0001}@1.0', description: 'Prism with basal pinacoid' }, + { name: 'Beryl Tabular', cdl: 'hexagonal[6/mmm]:{0001}@1.0 + {10-10}@0.6 + {11-20}@0.2', description: 'Tabular habit with dominant pinacoid' }, + { name: 'Quartz (Short Prismatic)', cdl: 'trigonal[32]:{10-10}@0.4 + {10-11}@1.2 + {01-11}@1.0', description: 'Short prism with rhombohedral terminations' }, + { name: 'Tourmaline Prismatic', cdl: 'trigonal[3m]:{10-10}@1.0 + {10-11}@0.8', description: 'Hemimorphic prismatic habit' }, { name: 'Zircon', cdl: 'tetragonal[4/mmm]:{110}@1.0 + {101}@0.9 + {100}@1.3', description: 'Tetragonal bipyramid with prism' }, - { name: 'Topaz', cdl: 'orthorhombic[mmm]:{110}@1.0 + {120}@1.1 + {011}@0.9', description: 'Orthorhombic prism habit' }, + { name: 'Topaz', cdl: 'orthorhombic[mmm]:{110}@1.0 + {120}@1.1 + {011}@0.9', description: 'Orthorhombic prismatic habit' }, + { name: 'Chrysoberyl Tabular', cdl: 'orthorhombic[mmm]:{110}@1.0 + {010}@0.8 + {111}@0.5', description: 'Tabular orthorhombic crystals' }, + { name: 'Moonstone', cdl: 'monoclinic[2/m]:{010}@1.0 + {110}@0.8 + {001}@0.7 + {100}@0.5', description: 'Monoclinic feldspar habit' }, + ], + }, + { + category: 'Modifications', + description: 'Crystal shapes modified by elongation, flattening, or tapering.', + items: [ + { name: 'Quartz (Elongated Prism)', cdl: 'trigonal[32]:{10-10}@0.5 + {10-11}@1.2 + {01-11}@1.0 | elongate(c:2.0)', description: 'Classic elongated quartz crystal' }, + { name: 'Sapphire (Barrel-shaped)', cdl: 'trigonal[-3m]:{10-10}@1.0 + {10-11}@0.7 | elongate(c:1.8)', description: 'Elongated barrel-shaped corundum' }, + { name: 'Tourmaline (Elongated)', cdl: 'trigonal[32]:{10-10}@1.0 + {10-11}@0.8 | elongate(c:2.5)', description: 'Strongly elongated prismatic tourmaline' }, + { name: 'Flattened Tabular', cdl: 'cubic[m3m]:{111} | flatten(a:0.5)', description: 'Flattened octahedral crystal' }, + ], + }, + { + category: 'Twin Laws', + description: 'Crystal twinning using the | twin(law) syntax.', + items: [ + { name: 'Diamond Macle', cdl: 'cubic[m3m]:{111}@1.0 + {100}@0.3 | twin(spinel_law)', description: 'Flattened triangular spinel-law contact twin' }, + { name: 'Spinel Macle', cdl: 'cubic[m3m]:{111}@1.0 + {100}@0.25 | twin(spinel_law)', description: 'Classic spinel law twin' }, + { name: 'Fluorite Interpenetrating', cdl: 'cubic[m3m]:{100}@1.0 | twin(fluorite)', description: 'Two cubes at 60 degree rotation around [111]' }, + { name: 'Fluorite Twin (with Octahedron)', cdl: 'cubic[m3m]:{100}@1.0 + {111}@0.8 | twin(fluorite)', description: 'Interpenetrating twin with octahedron modification' }, + { name: 'Quartz Japan Law', cdl: 'trigonal[32]:{10-10}@0.5 + {10-11}@1.2 + {01-11}@1.0 + {0001}@2.0 | elongate(c:2.0) | twin(japan)', description: 'Heart-shaped contact twin at ~84.5 degrees' }, + { name: 'Quartz Dauphine', cdl: 'trigonal[32]:{10-10}@0.5 + {10-11}@1.2 + {01-11}@1.0 + {0001}@2.0 | elongate(c:2.0) | twin(dauphine)', description: 'Penetration twin with 180 degree c-axis rotation' }, + { name: 'Quartz Brazil Law', cdl: 'trigonal[32]:{10-10}@0.5 + {10-11}@1.2 + {01-11}@1.0 + {0001}@2.0 | elongate(c:2.0) | twin(brazil)', description: 'Optical twin (left/right hand interpenetration)' }, + { name: 'Staurolite 90 Degree Cross', cdl: 'orthorhombic[mmm]:{110}@1.0 + {010}@0.7 + {001}@0.2 | twin(staurolite_90)', description: 'Cruciform penetration twin' }, + { name: 'Staurolite 60 Degree Cross', cdl: 'orthorhombic[mmm]:{110}@1.0 + {010}@0.6 + {001}@0.3 | twin(staurolite_60)', description: 'X-shaped "fairy cross" twin' }, + { name: 'Chrysoberyl Trilling', cdl: 'orthorhombic[mmm]:{1-10}@1.0 + {110}@0.9 + {010}@0.5 + {001}@0.2 | twin(trilling)', description: 'Cyclic pseudohexagonal triplet twin' }, ], }, { - category: 'Quartz Varieties', + category: 'Features', + version: 'v1.2', + description: 'Surface markings, growth patterns, and inclusions annotated on forms.', items: [ - { name: 'Alpha Quartz', cdl: 'trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8', description: 'Standard low quartz' }, - { name: 'Dauphine Twin', cdl: 'trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8 twin:dauphine', description: 'Common quartz twin law' }, - { name: 'Japan Law Twin', cdl: 'trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8 twin:japan_law', description: 'Heart-shaped twin' }, - { name: 'Amethyst Scepter', cdl: 'trigonal[-3m]:{10-10}@1.0 + {10-11}@0.6 + {01-11}@0.7', description: 'Well-developed rhombohedra' }, + { name: 'Diamond with Trigons', cdl: 'cubic[m3m]:{111}@1.0[trigon:dense] + {110}@0.2', description: 'Octahedron with dense triangular etch pits' }, + { name: 'Diamond Cube with Etch Pits', cdl: 'cubic[m3m]:{100}[etch_pit:square]', description: 'Cube faces with square dissolution features' }, + { name: 'Quartz with Striations', cdl: 'trigonal[32]:{10-10}@0.5[striation:horizontal] + {10-11}@1.2 + {01-11}@1.0 | elongate(c:2.0)', description: 'Prism faces with horizontal growth lines' }, + { name: 'Sapphire with Silk', cdl: 'trigonal[-3m]:{10-10}@1.0[striation:horizontal] + {10-11}@0.7 | elongate(c:1.8)', description: 'Barrel-shaped with horizontal striations' }, + { name: 'Tourmaline with Striations', cdl: 'trigonal[32]:{10-10}@1.0[striation:parallel] + {10-11}@0.8 | elongate(c:2.5)', description: 'Parallel vertical striations on prism faces' }, + { name: 'Garnet with Curved Striations', cdl: 'cubic[m3m]:{110}[striation:curved]', description: 'Dodecahedral faces with characteristic curved lines' }, + { name: 'Watermelon Tourmaline', cdl: 'trigonal[32]:{10-10}@1.0 + {10-11}@0.8 | elongate(c:1.5)', description: 'Colour-zoned pink core with green rim' }, ], }, { - category: 'Cubic System', + category: 'Phenomena', + version: 'v1.2', + description: 'Optical phenomena like asterism, chatoyancy, and adularescence.', items: [ - { name: 'Cube', cdl: 'cubic[m3m]:{100}@1.0', description: 'Hexahedron - pyrite, galena, halite' }, - { name: 'Octahedron', cdl: 'cubic[m3m]:{111}@1.0', description: 'Diamond, magnetite, spinel' }, - { name: 'Dodecahedron', cdl: 'cubic[m3m]:{110}@1.0', description: 'Rhombic dodecahedron - garnet' }, - { name: 'Cube-Octahedron', cdl: 'cubic[m3m]:{100}@1.0 + {111}@1.2', description: 'Truncated cube' }, - { name: 'Cubo-Octahedron', cdl: 'cubic[m3m]:{100}@1.0 + {111}@1.0', description: 'Equal development' }, - { name: 'Pyritohedron', cdl: 'cubic[m3]:{210}@1.0', description: 'Pentagonal dodecahedron' }, + { name: 'Star Sapphire (6-Ray)', cdl: 'trigonal[-3m]:{10-11}@1.0 | phenomenon[asterism:6]', description: 'Six-rayed star from oriented rutile silk' }, + { name: 'Star Sapphire (with Silk)', cdl: 'trigonal[-3m]:{10-11}@1.0[silk:dense] | phenomenon[asterism:6]', description: 'Asterism with silk feature on form' }, + { name: 'Cat\'s Eye Chrysoberyl', cdl: 'orthorhombic[mmm]:{110}@1.0 | phenomenon[chatoyancy:sharp]', description: 'Sharp chatoyant band from parallel silk' }, + { name: 'Star Sapphire (Strong)', cdl: 'trigonal[-3m]:{10-11} | phenomenon[asterism:6, intensity:strong]', description: 'Asterism with intensity parameter' }, ], }, { - category: 'Hexagonal/Trigonal', + category: 'Grouping and Labels', + version: 'v1.3', + description: 'Parenthesized groups for shared features and labeled forms.', items: [ - { name: 'Hex Prism', cdl: 'hexagonal[6/mmm]:{10-10}@1.0', description: 'Basic hexagonal prism' }, - { name: 'Hex Bipyramid', cdl: 'hexagonal[6/mmm]:{10-11}@1.0', description: 'Pointed termination' }, - { name: 'Beryl', cdl: 'hexagonal[6/mmm]:{10-10}@1.0 + {0001}@1.2 + {10-11}@1.5', description: 'Prism with pinacoid and bipyramid' }, - { name: 'Tourmaline', cdl: 'trigonal[3m]:{10-10}@1.0 + {10-11}@0.8 + {01-11}@0.9 + {0001}@1.3', description: 'Hemimorphic prism' }, - { name: 'Calcite Scalenohedron', cdl: 'trigonal[-3m]:{21-31}@1.0', description: '"Dogtooth" calcite' }, - { name: 'Calcite Rhomb', cdl: 'trigonal[-3m]:{10-11}@1.0', description: 'Rhombohedral cleavage' }, + { name: 'Grouped with Shared Feature', cdl: 'cubic[m3m]:({111}@1.0 + {100}@1.3)[phantom:3]', description: 'Both forms share phantom feature' }, + { name: 'Group + Standalone Form', cdl: 'cubic[m3m]:({111} + {100})[phantom:3] + {110}@0.8', description: 'Group alongside an ungrouped form' }, + { name: 'Merged Features', cdl: 'cubic[m3m]:({111}[trigon:dense] + {100})[phantom:3]', description: 'Own features merge with group features' }, + { name: 'Labeled Forms', cdl: 'cubic[m3m]:core:{111}@1.0 + rim:{100}@1.3', description: 'Forms labeled as core and rim' }, + { name: 'Labeled Group', cdl: 'cubic[m3m]:core:({111} + {100})[phantom:3]', description: 'Named group with shared feature' }, ], }, { - category: 'Tetragonal', + category: 'Definitions', + version: 'v1.3', + description: 'Named form definitions for reuse with @name and $reference syntax.', items: [ - { name: 'Tetragonal Prism', cdl: 'tetragonal[4/mmm]:{100}@1.0', description: 'Square prism' }, - { name: 'Tetragonal Bipyramid', cdl: 'tetragonal[4/mmm]:{101}@1.0', description: 'Pointed form' }, - { name: 'Vesuvianite', cdl: 'tetragonal[4/mmm]:{110}@1.0 + {100}@1.2 + {101}@0.9', description: 'Complex prismatic' }, - { name: 'Rutile', cdl: 'tetragonal[4/mmm]:{110}@1.0 + {101}@0.8 + {100}@1.5', description: 'Prismatic with pyramids' }, + { name: 'Simple Definition', cdl: '@oct = {111}@1.0\ncubic[m3m]:$oct + {100}@1.3', description: 'Define octahedron form, reference with $oct' }, + { name: 'Quartz Definitions', cdl: '@prism = {10-10}@1.0\n@rhomb = {10-11}@0.8\ntrigonal[-3m]:$prism + $rhomb', description: 'Named prism and rhombohedron' }, + { name: 'Chained Definitions', cdl: '@a = {111}@1.0\n@b = {100}@1.3\n@combo = $a + $b\ncubic[m3m]:$combo', description: 'Definitions referencing other definitions' }, + { name: 'With Doc Comments', cdl: '#! Mineral: Diamond\n@oct = {111}@1.0\ncubic[m3m]:$oct', description: 'Definitions work alongside doc comments' }, ], }, ]; @@ -78,9 +131,25 @@ const examples = [ Click any example to open it in the Playground.

+ + {examples.map((section) => ( -
-

{section.category}

+
+

+ {section.category} + {section.version && {section.version}} +

+ {section.description &&

{section.description}

}
{section.items.map((item) => ( @@ -96,7 +165,7 @@ const examples = [
- + {item.cdl} @@ -112,13 +181,31 @@ const examples = [ +cubic[m3m]:{111}@1.5 + {100}@0.8 # More cube + +# Add features to specific forms +cubic[m3m]:{111}@1.0[trigon:dense] + {100}@1.3 + +# Apply a modification +trigonal[32]:{10-10}@0.5 + {10-11}@1.2 | elongate(c:2.0) + +# Add a twin law +cubic[m3m]:{111}@1.0 | twin(spinel_law) + +# Annotate a phenomenon +trigonal[-3m]:{10-11}@1.0[silk:dense] | phenomenon[asterism:6] + +# Full example with comments, definitions, features, and twin +#! Mineral: Diamond +#! Habit: Macle twin +@oct = {111}@1.0[trigon:sparse] +cubic[m3m]:$oct + {100}@0.3 | twin(spinel_law)`} />

Try These Examples

diff --git a/src/pages/docs/cdl.astro b/src/pages/docs/cdl.astro index 97119bf..db2f1e1 100644 --- a/src/pages/docs/cdl.astro +++ b/src/pages/docs/cdl.astro @@ -20,15 +20,27 @@ import { Container, Button, Card } from '../../components/ui-astro';

CDL is a domain-specific language for describing crystal morphology using crystallographic - notation. It combines crystal systems, point groups, and Miller indices to precisely - define crystal forms. + notation. It combines crystal systems, point groups, Miller indices, and optional modifiers + to precisely define crystal forms for 3D visualization.

-

Syntax Overview

+
+

Current version

+

CDL v1.3

+

+ Includes comments (v1.1), features and phenomena (v1.2), grouping, labels, and definitions (v1.3). +

+
+ + + + -

A CDL expression follows this general format:

+

Basic Syntax

- +

A CDL expression follows this general structure:

+ +

Components

@@ -36,6 +48,7 @@ import { Container, Button, Card } from '../../components/ui-astro'; Component + Required Description Example @@ -43,166 +56,710 @@ import { Container, Button, Card } from '../../components/ui-astro'; system + Yes Crystal system - cubic, hexagonal, trigonal + cubic, trigonal [point_group] - Point group symmetry - [m3m], [6/mmm], [-3m] + No + Point group symmetry (defaults per system) + [m3m], [-3m] + + + : + Yes + Separator between header and forms + {'{'}hkl{'}'} - Miller indices + Yes + Miller index defining a crystal form {'{'}111{'}'}, {'{'}10-10{'}'} - @distance - Distance from origin + @scale + No + Distance from origin (default 1.0) @1.0, @0.8 + + + + No + Combine multiple forms + + -

Crystal Systems

+

+ When the point group is omitted, the default for the system is used (e.g., cubic defaults to m3m). +

-

CDL supports all seven crystal systems:

+ -
- {['cubic', 'hexagonal', 'trigonal', 'tetragonal', 'orthorhombic', 'monoclinic', 'triclinic'].map((system) => ( -
- {system} -
- ))} -
+ + + + +

+ The @scale value controls how far each form sits from the crystal centre. + Larger values push the form outward, reducing its face area relative to other forms. + Smaller values bring it closer, making faces more prominent. +

-

Point Groups

+ + + -

Point groups define the symmetry operations applied to Miller indices. Each crystal system has specific valid point groups:

+

Crystal Systems and Point Groups

+ +

CDL supports all seven crystal systems and all 32 crystallographic point groups:

+ - - + + + - - + + + - + + - + + - + + - + + - + +
SystemDefault Point Groups
Cubicm3m, 432, -43m, m3, 23cubicm3mm3m, 432, -43m, m-3, 23
Hexagonal6/mmm, 622, 6mm, -62m, 6/m, 6, -6hexagonal6/mmm6/mmm, 622, 6mm, -6m2, 6/m, 6, -6
Trigonaltrigonal-3m -3m, 32, 3m, -3, 3
Tetragonaltetragonal4/mmm 4/mmm, 422, 4mm, -42m, 4/m, 4, -4
Orthorhombicorthorhombicmmm mmm, 222, mm2
Monoclinicmonoclinic2/m 2/m, 2, m
Triclinictriclinic-1 -1, 1
-

Miller Indices

+ + + + +

Miller Indices

+ +

Miller indices define crystal face orientations using curly braces. CDL supports several notations:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FormatExampleDescription
Condensed 3-index{'{'}111{'}'}Single-digit indices concatenated
Separated 3-index{'{'}1 1 1{'}'}Space-separated (for multi-digit indices)
4-index (Miller-Bravais){'{'}10-10{'}'}For hexagonal and trigonal systems
Negative indices{'{'}10-11{'}'}Minus sign before the digit
-

Miller indices define crystal planes. Use curly braces with comma-separated values:

+

+ In 4-index Miller-Bravais notation {'{'}hkil{'}'}, the third index i is + redundant (i = -(h+k)) but included for clarity in hexagonal and trigonal systems. +

-
    -
  • Three indices: {'{'}h,k,l{'}'} for most systems
  • -
  • Four indices: {'{'}h,k,i,l{'}'} for hexagonal/trigonal (Miller-Bravais)
  • -
  • Negative values: Use minus sign, e.g., {'{'}10-10{'}'}
  • -
+

Named Forms

-

Common Forms

+

Common crystal forms can be referenced by name instead of Miller indices:

- - + + - - + + - - + + + - - - + + + + + + + + + + + + - - + + + + + + +
IndicesForm NameNameMiller Index System
{'{'}111{'}'}Octahedroncube{'{'}100{'}'} Cubic
{'{'}100{'}'}Cubeoctahedron{'{'}111{'}'} Cubic
dodecahedron {'{'}110{'}'}Rhombic dodecahedron Cubic
{'{'}10-10{'}'}Hexagonal prismtrapezohedron{'{'}211{'}'}Cubic
prism{'{'}100{'}'}Hexagonal/Trigonal
pinacoid / basal{'{'}001{'}'} Hexagonal/Trigonal
{'{'}0001{'}'}Basal pinacoidrhombohedron{'{'}101{'}'}Trigonal
dipyramid{'{'}101{'}'} Hexagonal/Trigonal
-

Combining Forms

+ + + + + + + + +

Combining Forms

+ +

Use + to combine multiple crystal forms into a single crystal:

+ + + + + + + +

Twin Laws

+ +

+ Crystal twinning is specified with the | twin(law) syntax after + the form list. The pipe | separates the forms from the twin specification. +

+ + + +

Named Twin Laws

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LawDescription
spinel / spinel_lawContact twin on {'{'}111{'}'} (diamond, spinel)
brazilOptical twin in quartz (left/right hand)
dauphinePenetration twin in quartz (180° about c-axis)
japanContact twin in quartz (~84.5°)
carlsbadPenetration twin in feldspar
bavenoContact twin in feldspar
manebachContact twin in feldspar
albitePolysynthetic twin in plagioclase
periclinePolysynthetic twin in plagioclase
fluoriteInterpenetrating cube twin
iron_crossPyrite cross twin
trillingCyclic triplet twin (chrysoberyl)
staurolite_6060° cross twin
staurolite_9090° cross twin
gypsum_swallowSwallowtail twin in gypsum
+ + + + + +

Modifications

+ +

+ Morphological modifications alter the crystal shape. They follow the form list, + separated by a pipe |. Each takes the form type(param:value). +

+ + + +

Modification Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeSyntaxDescription
elongateelongate(axis:ratio)Stretch along an axis (a, b, or c)
flattenflatten(axis:ratio)Compress along an axis
truncatetruncate(form:depth)Cut corners or edges by a form
tapertaper(direction:factor)Narrow in one direction
bevelbevel(edges:width)Add beveled edges
+ + + + + +

Comments (v1.1)

+ +

CDL supports three comment styles, stripped before parsing:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StyleSyntaxPurpose
Line comment# textIgnored during parsing
Block comment/* text */Multi-line ignored content
Doc comment#! Key: ValueExtracted as structured metadata
+ +

+ Doc comments (#!) are preserved in the parsed output as structured metadata + and can carry mineral names, habits, or other descriptive information. +

+ + + + + +

Features (v1.2)

+ +

+ Features annotate individual crystal forms with surface markings, growth patterns, + inclusions, or colour properties. Features are placed in square brackets [...] + immediately after the form's Miller index and optional scale. +

+ + + +

Feature Types

+ +
+
+

Growth

+

phantom, sector, zoning, skeletal, dendritic

+
+
+

Surface

+

striation, trigon, etch_pit, growth_hillock

+
+
+

Inclusions

+

inclusion, needle, silk, fluid, bubble

+
+
+

Colour

+

colour, colour_zone, pleochroism, lamellar, banding

+
+
+ + + + + +

Phenomena (v1.2)

+ +

+ Optical phenomena are crystal-level annotations (not per-form). + They follow the form list (and any modifications or twin), separated by |, + using the syntax phenomenon[type:value]. +

+ + + +

Phenomenon Types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescriptionExample Gems
asterismStar effect (4, 6, or 12 rays)Star sapphire, star ruby
chatoyancyCat's eye bandChrysoberyl cat's eye
adularescenceBillowy internal glowMoonstone
labradorescenceSpectral colour play on cleavage planesLabradorite
play_of_colorSpectral flashes from diffractionOpal
colour_changeHue shift under different lightingAlexandrite
aventurescenceSpangled glitter from inclusionsSunstone, aventurine
iridescenceRainbow colours from thin-film interferenceRainbow quartz
+ + + + + +

Grouping (v1.3)

+ +

+ Parenthesized groups allow shared features to be applied to multiple forms at once. + Features placed after the closing parenthesis apply to all forms in the group. +

+ + + +

+ When flat_forms() is called on the parsed result, group features are + merged into each child form. In the last example above, the {'{'}111{'}'} form + would have both trigon:dense (its own) and phantom:3 (from the group). +

+ + + + + +

Labels (v1.3)

+ +

+ Labels assign descriptive names to forms or groups using a label: prefix. + This is useful for documenting which form plays what role in the crystal. +

+ + + +

+ Named forms (like octahedron, prism) are not treated as + labels — they are resolved to their Miller indices directly. Labels must be identifiers + that are not known named forms. +

+ + + + + +

Definitions (v1.3)

+ +

+ Named definitions let you assign a form expression to a name with @name = expr, + then reference it with $name. Definitions are resolved by text substitution + before parsing. They must appear on their own lines before the main CDL expression. +

+ + + +

+ Referencing an undefined name raises a parse error. + Definitions are stored on the parsed result for inspection by tools. +

-

Use + to combine multiple crystal forms:

+ + + - Full Grammar -# Quartz with prism and rhombohedra -trigonal[-3m]:{10-10}@1.0 + {10-11}@0.8 + {01-11}@0.9`} /> +

The complete CDL grammar, expressed as a production rule summary:

-

The @distance value controls how "developed" each form is. Smaller distances result in larger face areas.

+ Diamond (Octahedron) - +form = (named_form | '{' miller '}') ['@' scale] features? +features = '[' feature (',' feature)* ']' +feature = name ':' value (',' value)* -

Fluorite (Cube with Octahedron)

- +modifiers = ('|' modification_list)? ('|' twin)? ('|' phenomenon)? +modification_list = modification (',' modification)* +modification = type '(' param ':' value ')' +twin = 'twin' '(' (law [',' count] | '[' axis ']' ',' angle) ')' +phenomenon = 'phenomenon' '[' type [':' value] (',' param ':' value)* ']' -

Beryl (Hexagonal Prism with Pinacoid)

- +label = IDENTIFIER ':' +miller = INTEGER{3..4} +scale = NUMBER +name, type = IDENTIFIER +value = NUMBER | IDENTIFIER`} /> -

Quartz

- + + + -

Extensions

+

Processing Order

-

Twin Laws

-

Add twin laws with the twin: modifier:

- +

CDL text is processed through these stages:

-

Modifications

-

Apply modifications like elongation or flattening:

- +
    +
  1. Doc comment extraction#! lines are captured as metadata
  2. +
  3. Comment stripping# and /* */ are removed
  4. +
  5. Definition pre-processing@name = ... lines are extracted and $name references are resolved by text substitution
  6. +
  7. Lexing — remaining text is tokenized
  8. +
  9. Parsing — tokens are parsed into the AST: system, point group, form tree, modifications, twin, phenomenon
  10. +
  11. Validation — point group checked against system
  12. +

Try it yourself

diff --git a/src/pages/docs/cli-options.astro b/src/pages/docs/cli-options.astro index 9a08bc4..2e6f440 100644 --- a/src/pages/docs/cli-options.astro +++ b/src/pages/docs/cli-options.astro @@ -7,7 +7,7 @@ import { Container, Button } from '../../components/ui-astro'; Complete reference for all command-line flags and options available in the - crystal-render command. + cdl and mineral-db commands.

-

Basic Usage

+

cdl Command

- [OUTPUT_FILE]`} /> + -

Input Options

+

Commands

- + - + - - - - - - - - + + + - - - - - - - - + + +
OptionCommand DescriptionDefaultExample
CDL_EXPRESSIONCDL expression to render (positional argument)Required
-p, --preset NAMEUse a preset from mineral database instead of CDL-parseParse a CDL expression and display the resultcdl parse "cubic[m3m]:{'{'}111{'}'}"
-f, --file PATHRead CDL expression from file-
--list-presetsList all available mineral presets-validateValidate a CDL expression (exit code 0 = valid)cdl validate "cubic[m3m]:{'{'}111{'}'}"
-

Output Options

+

Options

- - - - - - - - - + + - - - - - -
Option DescriptionDefault
OUTPUT_FILEOutput file path (positional argument)crystal.svg
--format FORMATOutput format: svg, stl, gltf, gemcadInferred from extension--jsonOutput parsed result as JSON (with parse command)
--stdoutWrite output to stdout instead of filefalse
- -

View Options

- - - - - - - + + - - - - - + + - - - + + - - - + + - - - + + - - - + +
OptionDescriptionDefault--list-systemsList all 7 crystal systems with their default point groups
--elevation DEGREESView elevation angle (0-90)30--list-point-groupsList all 32 point groups organized by crystal system
--azimuth DEGREESView azimuth angle (-180 to 180)-45--list-formsList all named forms with their Miller indices
--zoom FACTORZoom factor (0.5-5.0)1.0--list-twinsList all registered twin laws
--orthoUse orthographic projectiontrue--versionShow cdl-parser version
--perspectiveUse perspective projectionfalse--helpShow help message
-

SVG Options

+

Parse Output

+ +

The parse command displays:

+
    +
  • Crystal system and point group
  • +
  • Forms with Miller indices and scale values
  • +
  • Modifications (if any)
  • +
  • Twin specification (if any)
  • +
  • Reconstructed CDL string
  • +
+ + + +

With --json, the output is a structured JSON object:

+ + + +

mineral-db Command

+ + + +

Query Options

- + - - - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - + + +
Option DescriptionDefaultExample
--width PIXELSSVG width400
--height PIXELSSVG height400--list [CATEGORY]List all presets, or filter by crystal systemmineral-db --list cubic
--face-color COLORFace fill color (hex or name)#0ea5e9--info NAMEShow detailed info for a presetmineral-db --info diamond-octahedron
--edge-color COLOREdge stroke color#0369a1--search QUERYSearch presets by name, mineral, or chemistrymineral-db --search beryl
--edge-width PIXELSEdge stroke width1.5--json NAMEOutput preset data as JSONmineral-db --json quartz
--opacity VALUEFace opacity (0.0-1.0)0.85--categoriesList all preset categories with countsmineral-db --categories
--gradientApply lighting gradient to facestrue
--no-gradientUse flat shading---countShow total number of presetsmineral-db --count
-

Display Options

+

Synthetic and Simulant Options

- + - - - + + + - - - + + + - - - + + + - - - + + +
Option DescriptionDefaultExample
--axesShow crystallographic axesfalse--synthetics [METHOD]List synthetic minerals, optionally filtered by growth method (flux, cvd, hpht, etc.)mineral-db --synthetics flux
--gridShow reference gridfalse--simulants [TARGET]List simulant minerals, optionally filtered by target mineralmineral-db --simulants diamond
--labelsShow face labels (Miller indices)false--counterparts NAMEShow all synthetics and simulants for a natural mineralmineral-db --counterparts diamond
--title TEXTAdd title below crystal---origin TYPEFilter --list by origin: natural, synthetic, simulant, compositemineral-db --list --origin synthetic
-

3D Export Options

+

Other Options

- - - - - - - - - + + - - - - - - - - + +
Option DescriptionDefault
--scale FACTORScale factor for STL/glTF output10.0
--units UNITSTL units: mm, cm, inmm--versionShow mineral-database version
--binaryUse binary STL formattrue
--asciiUse ASCII STL formatfalse--helpShow help message

Examples

-

Basic rendering

- - CDL Parser -# Render preset to SVG -crystal-render --preset quartz quartz.svg`} /> + Custom styling +# Parse combination with JSON output +cdl parse "cubic[m3m]:{111}@1.0 + {100}@1.3" --json - +# List all named forms +cdl --list-forms -

3D export

+# List twin laws +cdl --list-twins`} /> - Mineral Database -# Export for web visualization -crystal-render --preset zircon zircon.gltf`} /> + View angles +# Get detailed info +mineral-db --info ruby-hexagonal - +# Find diamond counterparts +mineral-db --counterparts diamond -

Batch processing

+# List composites +mineral-db --list --origin composite - +# Export as JSON for scripting +mineral-db --json diamond-octahedron | python -c "import sys,json; d=json.load(sys.stdin); print(d['cdl'])"`} />