Skip to content

Commit c41ce20

Browse files
committed
Present all three projection modes together in the docs
Tidy the documentation for oblique projection: - README: list oblique alongside orthographic and perspective. - rendering.rst: present all three projection modes under one Projection section (they had drifted into separate Perspective and Oblique headings), and add a perovskite oblique example image beside the orthographic and perspective ones. - api.rst: add the Oblique autoclass entry and list it in the Projection base note. - Drop the "cavalier"/"cabinet" terms from the docstrings, examples, and docs; the angle and foreshortening parameters are self-describing. - generate_images.py: render the perovskite oblique example.
1 parent 56c96d9 commit c41ce20

6 files changed

Lines changed: 41 additions & 31 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ hofmann renders crystal and molecular structures as depth-sorted ball-and-stick
2222
- Coordination polyhedra with configurable shading and slab clipping
2323
- Unit cell wireframe rendering
2424
- Interactive viewer with mouse rotation, zoom, and keyboard controls
25-
- Orthographic and perspective projection
25+
- Orthographic, perspective, and oblique (axonometric) projection
2626

2727
## Installation
2828

docs/_static/generate_images.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from hofmann import (
99
AtomLegendItem, AtomStyle, AxesStyle, BondSpec, CellEdgeStyle,
10-
Composition, Frame, LegendStyle, PolygonLegendItem,
10+
Composition, Frame, LegendStyle, Oblique, PolygonLegendItem,
1111
PolyhedronLegendItem, PolyhedronSpec, RenderStyle, StructureScene,
1212
ViewState,
1313
)
@@ -645,7 +645,7 @@ def generate_docs_images() -> None:
645645
)
646646
print(f" wrote {OUT / 'octahedron_no_half_bonds.svg'}")
647647

648-
# 5. Perspective: orthographic vs perspective (perovskite)
648+
# 5. Projection: orthographic, perspective, oblique (perovskite)
649649
perov_plain.render_mpl(
650650
OUT / "perovskite_ortho.svg",
651651
figsize=(3, 3), dpi=150,
@@ -657,6 +657,12 @@ def generate_docs_images() -> None:
657657
figsize=(3, 3), dpi=150,
658658
)
659659
print(f" wrote {OUT / 'perovskite_perspective.svg'}")
660+
perov_plain.view.projection = Oblique(45.0, 0.5)
661+
perov_plain.render_mpl(
662+
OUT / "perovskite_oblique.svg",
663+
figsize=(3, 3), dpi=150,
664+
)
665+
print(f" wrote {OUT / 'perovskite_oblique.svg'}")
660666
perov_plain.view.set_orthographic() # Reset
661667

662668
# 6–9. Per-atom colouring examples: ring of atoms.

docs/api.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,14 @@ Data model
4949
.. autoclass:: Perspective
5050
:members:
5151

52+
.. autoclass:: Oblique
53+
:members:
54+
5255
.. autoclass:: Projection
5356

5457
The abstract base of the projection modes (:class:`Orthographic`,
55-
:class:`Perspective`); use it to annotate code that accepts any
56-
projection.
58+
:class:`Perspective`, :class:`Oblique`); use it to annotate code that
59+
accepts any projection.
5760

5861
.. autoclass:: hofmann.model.atom_data.AtomData
5962
:members: n_atoms, ranges, labels

docs/rendering.rst

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Controlling the view
1212
--------------------
1313

1414
The :class:`~hofmann.ViewState` controls rotation, zoom, and
15-
perspective.
15+
projection.
1616

1717
Rotation
1818
~~~~~~~~
@@ -37,16 +37,32 @@ Zoom
3737
3838
scene.view.zoom = 1.5 # Zoom in
3939
40-
Perspective
41-
~~~~~~~~~~~
40+
Projection
41+
~~~~~~~~~~
42+
43+
The projection mode is set on :attr:`~hofmann.ViewState.projection`,
44+
which takes one of three modes:
45+
46+
- :class:`~hofmann.Orthographic` (the default) — a parallel projection
47+
with no foreshortening.
48+
- :class:`~hofmann.Perspective` — foreshortens with distance from the
49+
eye; *strength* sets the amount and *view_distance* the eye distance.
50+
- :class:`~hofmann.Oblique` — parallel, but draws the third axis receding
51+
at an angle (axonometric), so depth reads without the distortion of
52+
perspective. *angle* (degrees, anticlockwise from +x) sets the
53+
on-screen direction of the receding axis, and *foreshortening* how far
54+
a unit step along it is drawn: ``1.0`` full length, ``0.5`` half,
55+
``0.0`` orthographic. Atoms, bonds, cell edges, and the axis triad all
56+
shear together.
4257

4358
.. code-block:: python
4459
45-
scene.view.set_perspective(0.3) # Mild perspective
46-
scene.view.set_orthographic() # Parallel projection (default)
60+
scene.view.set_orthographic() # Parallel (the default)
61+
scene.view.set_perspective(0.3) # Mild perspective
62+
scene.view.projection = Oblique(45.0, 0.5) # Oblique
4763
4864
.. list-table::
49-
:widths: 50 50
65+
:widths: 33 33 34
5066

5167
* - .. figure:: _static/perovskite_ortho.svg
5268

@@ -56,24 +72,9 @@ Perspective
5672

5773
Perspective (``set_perspective(0.5)``)
5874

75+
- .. figure:: _static/perovskite_oblique.svg
5976

60-
Oblique
61-
~~~~~~~
62-
63-
An oblique (axonometric) projection is parallel, like orthographic, but
64-
draws the third axis receding at an angle, so depth reads without the
65-
distortion of perspective. Assign an :class:`~hofmann.Oblique`:
66-
67-
.. code-block:: python
68-
69-
scene.view.projection = Oblique(45.0, 0.5) # "cabinet"
70-
scene.view.projection = Oblique(45.0, 1.0) # "cavalier"
71-
72-
``angle`` (degrees, anticlockwise from the +x axis) is the on-screen
73-
direction of the receding axis; ``foreshortening`` is how far a unit
74-
step along it is drawn — ``1.0`` for cavalier, ``0.5`` for cabinet,
75-
``0.0`` for orthographic. Atoms, bonds, cell edges, and the axis triad
76-
all shear together.
77+
Oblique (``Oblique(45, 0.5)``)
7778

7879

7980
Render styles

src/hofmann/model/projection.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ class Oblique(Projection):
182182
183183
A depth-proportional shear draws two axes undistorted and the third
184184
receding towards *angle* on screen, foreshortened by
185-
*foreshortening*. ``foreshortening = 1.0`` is the classical
186-
"cavalier" projection, ``0.5`` "cabinet", ``0.0`` orthographic.
185+
*foreshortening*: ``1.0`` draws a unit receding step at full length,
186+
``0.5`` at half length, ``0.0`` recovers the orthographic projection.
187187
188188
Attributes:
189189
angle: On-screen direction of the receding axis, in degrees

tests/test_rendering/test_projection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_perspective_increases_extent(self):
6565
def test_oblique_extent_grows_by_shear_allowance(self):
6666
"""The shear can enlarge the bounding radius by sqrt(1 + f^2), so
6767
_scene_extent widens by that factor via max_magnification;
68-
cavalier (f = 1) grows by sqrt(2)."""
68+
f = 1 grows by sqrt(2)."""
6969
scene = StructureScene(
7070
species=["C", "C"],
7171
frames=[Frame(coords=np.array([

0 commit comments

Comments
 (0)