Add origin offset to attenuate_all for translation-invariant bucketing - #50
Merged
Conversation
attenuate_all floors rotated coordinates onto a 1x1 lattice for the shadow-bucketing plane sweep. Because floor is phase-dependent, the same physical canopy gives different irradiance depending on where its coordinates start, so a sub-window of a larger domain cannot reproduce a whole-domain run even though the algorithm is otherwise deterministic. Add an `origin=(ox, oy)` parameter (default (0, 0), fully backward compatible) that is added to the leaf-area, terrain, and sensor coordinates before rotation only. Since the rotation is linear, a constant world offset before rotating shifts all rotated coordinates consistently, anchoring the floor lattice to a shared global frame. Outputs remain in the input's local frame. Closes #48
Collaborator
|
Looks good to me. Planning to merge this first then get the second PR in |
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.
Closes #48.
What
Adds an
origin=(ox, oy)parameter toattenuate_allso the shadow-bucketingplane sweep is anchored to a shared global frame, making the algorithm
translation-invariant.
Why
The sweep floors rotated coordinates onto a 1×1 lattice
(
plane_sweep,general.py:27/:33).flooris a phase-dependent quantizer, so the same physical canopy producesdifferent irradiance depending on where its coordinates start. A sub-window of a
larger domain therefore cannot reproduce a single whole-domain run — which
blocks tiling a large domain into parallel per-tile runs.
How
The offset is added to the leaf-area, terrain, and sensor coordinates before
rotation only. Because the rotation is linear, a constant world offset before
rotating shifts every rotated coordinate consistently, so two sub-windows of the
same global domain floor into the same lattice. Outputs stay in the input's
local frame — only the shadow grouping is re-anchored. To tile: give each window
the offset of its lower-left corner in the global frame.
Default
origin=(0.0, 0.0)is a no-op that reproduces the un-anchored resultexactly.
Tests (TDD)
Written before the implementation:
test_origin_default_matches_no_arg—origin=(0, 0)reproduces the no-argresult byte-for-byte across canopy, terrain, and sensors.
test_origin_makes_canopy_translation_invariant— the same canopy expressed ata shifted origin gives identical irradiance when
origincancels the shift(0% of cells differ), with a guard asserting the shift genuinely perturbs the
bucketing when not re-anchored (so the test can't pass vacuously).
Full suite: 57 passed. The stored-result
assert_equaltests confirm thedefault path is unchanged.
Scope
Kept to
attenuate_all, the path the tiling consumer (FastFuelstreevox) uses.attenuate_surfaceis left unchanged. Independent of #49 (voxel_dimanisotropy), but the two interact: correcting that geometry would change shadow
reach, and hence the up-sun halo a tiling caller supplies.