Repository navigation
Rendering and Layout Engine
This page explains the shared geometry rules that keep molecule drawing, export and Spin 3D consistent.
All molecule rendering math belongs in packages/layout-engine. That includes bond geometry, double- and triple-bond gaps, wedges and hashes, atom-label content and placement, stroke widths and depth cues. Desktop code and export code consume those plans; they must not keep local copies, even as temporary implementations.
This boundary matters chemically as well as visually. A misplaced wedge can communicate the wrong stereochemistry, and a label whose bond meets the wrong letter can suggest the wrong attachment atom. A rendering fix must preserve the graph while making its intended meaning visible.
The document stores atoms, bonds, coordinates and styles. layout-engine turns those into reusable geometry. The desktop chooses how to present the result, while export-engine uses the same underlying molecule plans for exported figures. Graphics have a separate home: art-engine owns art strokes, markers, arrow geometry and boolean operations.
Keep these responsibilities separate when fixing an issue:
| Question | Owner |
|---|---|
| Where does a double bond's second line sit? | layout-engine |
| Where does a group label meet its bond? | layout-engine |
| How does a graphical arrowhead look? | art-engine |
| How is a validated graph changed? |
chem-core patches and workflow code |
| How does document space map to screen space? |
viewport-engine and the relevant interaction contract |
| How are plans written into a PDF? | export-engine |
If a needed geometry helper is package-internal, export and reuse it. If a caller deliberately needs different behavior, give that behavior a distinct name and document why.
src/labelGrammar.ts contains the pure atom-label reading: elements, spelled labels, abbreviations, composites, placeholders, bare formulas and unrecognized text. The same reading tells chemistry which atom a group attaches through and tells the renderer how to anchor the label.
nativeGroupLabelDisplay and atomDisplayLabelPlacement place the attachment atom on the atom position. An OMe group may display as MeO when its bond approaches from the other side, but only when the turned text reads as the same group. The stored label and chemical meaning do not change. Explicit user label alignment retains its separate layout behavior.
document-workflow-core re-exports this grammar and builds validation and expansion on top of it. It must not contain a second parser. Bond clipping, CLI bounds and SVG/PDF output all need the planned label layout, otherwise a canvas fix can still leave cropped exports.
src/valence.ts provides shared element/charge valence rules and nativeBondOrderResolution. The latter resolves aromatic bonds to a Kekulé order map: an assignment of alternating chemical bond orders where a supported assignment exists. Labels, native formulas, growth admission and the native SMILES writer use this common resolution.
An unresolved environment is not a reason to invent a chemical order. In particular, MOL writing receives the order map explicitly; unresolved aromatic bonds remain aromatic in that format and return warnings. Unknown chemical bond orders must not silently become single bonds. Preserve the warning path when changing geometry or format code.
Spin 3D uses one ScreenPlacement contract across live projection, flattening, reopening, dragging and typed rotations. It is defined in apps/desktop/src/interaction/spinOverlay.ts with centerX, centerY and scale: the document-space center and document pixels per conformer unit.
projectSpin and flattenSpunMolecule(..., { placement }) must agree. A view that looks correct while dragging but shifts or changes scale when flattened violates this contract. Projection helpers stay in the interaction directory; flattening orchestration stays in documentWorkflow.
Shared molecule geometry also serves the overlay's projected labels and bonds. The overlay must not become another renderer with copied wedge or label mathematics. Flattening has separate chemical-identity and stereochemical checks; a difficult projection can warn or refuse instead of committing an ambiguous drawing.
Spin changes require the spin3dModel, spinFlatten, spinFlattenStereo, flattenRoundTrip, spinOverlay and rotation3d test families. Broader rendering work should check canvas/export parity, label bounds and chemical identity. Native interaction still needs hands-on macOS and Windows checks.
For compound layouts, planObjectArrangement plans translation-only Circle, Oval, Grid, Row and Column arrangements using visible bounds. Page-fit checks refuse a layout that cannot fit without scaling. Aesthetic arrangement must not resize molecular geometry or change chemistry. Read the current arrangement README before altering spacing defaults.
ChemDraft repository · Apache-2.0 · Home
- Features overview
- Installation
- Quick Start
- Your first molecule
- FAQ
- Troubleshooting
- Glossary
- macOS and Windows differences
- Drawing basics
- Atoms and labels
- Bonds and stereochemistry
- Rings and chains
- Selection and editing
- Charges, radicals, and dative bonds
- Copy, paste, and clipboard
- Keyboard shortcuts
- Toolbars and palettes
- Documents, pages, and tabs
- Arrows and mechanisms
- Art objects and styling
- Publication figures and style presets
- Compound layouts
- Templates and abbreviations
- Chemistry guarantees
- Analysis and properties
- NMR prediction
- Name from structure
- Name to structure
- Structure recognition
- Spin 3D