Repository navigation
Cast shadows at the physical solar angle for non-cubic voxels - #51
Merged
Merged
Conversation
attenuate_all rotates grid-index coordinates so the sun points straight down, then floors onto a 1x1 lattice for the shadow sweep. Index space is only physically proportioned when the voxel is cubic, so voxel_dim was ignored in the geometry (it only fed the path-length scalar d) and shadows landed at the wrong angle for any non-cubic voxel. Scale the index coordinates by the voxel aspect ratio, normalized by the x-resolution, before rotation. Cubic voxels and voxel_dim=None normalize to (1, 1, 1) and are unchanged; an anisotropic voxel is stretched to physical proportions so the shadow angle is correct. Applied to the leaf, terrain, and sensor rotation inputs; outputs stay in index coordinates. This changes results for any non-cubic voxel_dim (previously wrong). Closes #49
Contributor
Author
The test covered aspect 1 (cubic/None) and aspect 3, but not aspect < 1 — the shipping treevox voxel is 2 m wide and 1 m tall (dz/dx = 1/2), whose shadow should reach HALF as far as the cubic case. Add a third ground sensor at that offset and assert 2x2x1 lands there. Verified the new assertion fails on the pre-fix geometry (it shadowed the cubic cell).
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 #49.
What
Makes
attenuate_allcast shadows at the physical solar angle for the voxeldimensions in
env.voxel_dim, instead of assuming cubic voxels.Why
attenuate_allrotates grid-index coordinates so the sun points straightdown, then floors onto a 1×1 lattice for the shadow sweep. Index space is only
physically proportioned when the voxel is cubic, so
voxel_dimnever entered thegeometry — it only fed the scalar path length
d(
_calculate_d). For any non-cubic voxel(e.g. a canopy 2 m wide but 1 m tall) the horizontal shadow displacement was
tan(zenith)cells per vertical cell regardless of the true dz/dx ratio, soshadows landed in the wrong cells.
How
Scale the index coordinates by the voxel aspect ratio, normalized by the
x-resolution (
voxel_dim / dx), before rotation. The rotation then acts onphysically-proportioned space, so the shadow angle is correct. Applied to the
leaf, terrain, and sensor rotation inputs; outputs stay in index coordinates.
voxel_dim=Nonenormalize to(1, 1, 1)→ no scaling, nochange.
dx != dythe shadow angle is still physical; only the sweep's cellbuckets become non-square (documented in the docstring).
Tests (TDD)
Written before the implementation —
test_voxel_dim_sets_shadow_geometry: asingle elevated occluder over two ground sensors, 45° sun in the x–z plane. The
shadowed ground cell must sit at offset
z_top · (dz/dx)cells:None,(1,1,1),(2,2,2)→ offsetz_top(unchanged),(1,1,3),(2,2,6)→ offset3·z_top.Before the fix the cubic/None cases passed and the anisotropic cases failed
(
5 != 9); after, all pass. Full suite: 56 passed — the stored-resultassert_equaltests confirm the cubic/None path is byte-for-byte unchanged.Results change for any non-cubic
voxel_dim(they were previously wrong).Cubic-voxel and
voxel_dim=Noneresults are unaffected.Scope / interaction
Kept to
attenuate_all(the path the FastFuelstreevoxconsumer uses);attenuate_surfaceis unchanged. Independent of #48/#50 (originoffset) butthey touch the same three rotation lines, so expect a small merge conflict — the
combined form is
(coords + origin_offset) * voxel_scale, which is compatible(the global offset is applied before scaling, preserving tile invariance).