Move projection maths onto the projection variants - #86
Merged
Conversation
Projection is now the ABC base rather than a union alias, so api.rst uses autoclass. The abstract-enforcement test previously used an empty subclass, which stays abstract while any one method is abstract -- so it did not catch a single method losing @AbstractMethod, despite its docstring claiming "missing any method". Assert the exact abstract set instead, which fails if any of the five is no longer abstract.
- Qualify the cross-module `project_camera` reference in `Perspective.to_screen`'s comment, now that it lives in a different module from `ViewState`. - Note on `Perspective.eye_distance` that `view_distance` is the true eye only at full strength (the eye sits at `view_distance / strength`). - Split the projection-variant contract test per variant, so a first failure no longer masks the rest.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #85. That PR introduced the
Orthographic | Perspectivesum typebut left the projection maths as
match/isinstancedispatch spread acrossViewStateand three renderers. This moves that maths onto the variants behinda
Projectionabstract base class, so adding a third variant is a one-classchange rather than an edit to every dispatch site.
Why
Projectionwas data only, so every question about a projection -- how acamera point maps to the screen, a sphere's silhouette radius, the worst-case
magnification, the bond-cap eye distance, whether a point reaches the eye plane
-- was answered by a
matchoutside the type. There were four such dispatchsites plus
assert_neverguards. Those are all projection concepts, so theybelong on the projection.
Projectionbecomes an ABC (the existingLegendItempattern) with fiveabstract methods;
OrthographicandPerspectiveimplement them. The dispatchsites collapse to method calls, the
assert_neverguards are replaced bydefinition-time enforcement (an incomplete variant cannot be instantiated), and
the types move into a new
hofmann/model/projection.py-- returningview_state.pyto being aboutViewState(434 to 254 lines).Behaviour
Rendered output is unchanged, bit-for-bit, verified with a vertex-level harness
against
mainafter every commit. Two internal cleanups ride along, bothbehaviour-neutral:
project_cameranow returnsxyonly (thescaleitreturned was discarded by every caller), and the duplicated
_foreshortening_distancehelper collapses to aneye_distanceproperty.Notes for review
assert isinstance(proj, Perspective)sites sit insideif proj.reaches_eye_plane(...), which onlyPerspectivereturnsTruefrom -- so they are unreachable for a parallel variant and narrow the type
for the warning's f-string. They are not dispatch a third variant would edit.
Projection.__abstractmethods__is pinned by a test, so a method silentlylosing
@abstractmethodfails rather than letting an incomplete variantthrough.
eye_distanceis a scalar z-axis distance, which a genuinely obliqueprojection could not express. Left as-is deliberately rather than reshaped for
an unwritten variant; the follow-up oblique work will generalise it.