mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
feat: выбор граней окон для солнечных лучей (#577)
Issue: #577 User-Visible: yes
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
||||
import {
|
||||
OPENING_TYPES, VACUUM_TRAIL_MODES, ZERO_WALL_STYLES,
|
||||
} from '../test-build/types.js';
|
||||
import { BG_MODES } from '../test-build/sun.js';
|
||||
import { BG_MODES, SUN_RAY_ORIGINS } from '../test-build/sun.js';
|
||||
|
||||
const manifest = JSON.parse(readFileSync(
|
||||
new URL('../scripts/config-schema.json', import.meta.url), 'utf8')).fields;
|
||||
@@ -38,6 +38,7 @@ const PAIRS = [
|
||||
{ pair: 'vacuum.trail_mode', path: 'config.markers[].vacuum.trail_mode', front: VACUUM_TRAIL_MODES },
|
||||
{ pair: 'space.zero_wall_style', path: 'config.spaces[].zero_wall_style', front: ZERO_WALL_STYLES },
|
||||
{ pair: 'settings.bg_mode', path: 'config.settings.bg_mode', front: BG_MODES },
|
||||
{ pair: 'settings.sun_ray_origin', path: 'config.settings.sun_ray_origin', front: SUN_RAY_ORIGINS },
|
||||
];
|
||||
|
||||
test('#33 AC2: backend and frontend enums agree, divergences only via the allow-list', () => {
|
||||
|
||||
+42
-1
@@ -9,7 +9,7 @@ import {
|
||||
RAY_LENGTH_K, RAY_FADE_END, rayStops, RAY_MIN_COS,
|
||||
rimStops, rimPeakAlpha, rayRimEdges, RIM_MAX_ALPHA, RIM_COLOR,
|
||||
SKY_SNAP_DEG, skyNeedsSnap, skyElevation,
|
||||
northDegOf, bgModeOf, sunRaysOn, sunStateOf,
|
||||
northDegOf, bgModeOf, sunRaysOn, sunRayOriginOf, SUN_RAY_ORIGINS, sunStateOf,
|
||||
DAY_CYCLE_PALETTES, dayCycleSunOf, dayCyclePhaseFromSun,
|
||||
dayCyclePhaseFromMinutes, dayCyclePositionFromSun,
|
||||
dayCyclePositionFromMinutes, resolveDayCycle, dayCycleFingerprint,
|
||||
@@ -465,6 +465,47 @@ test('computeSunRays: a thick-wall ray starts at both room-side opening corners'
|
||||
}
|
||||
});
|
||||
|
||||
test('#577: outer rays start at the exterior corners and cross only the window tunnel', () => {
|
||||
const win = { id: 'wW', x: 100, y: 300, angle: 90, length: 80 };
|
||||
const inner = { r1: [[110, 110], [490, 110], [490, 490], [110, 490]] };
|
||||
const [inside] = computeSunRays(ROOMS, [win], 270, 60, 0, inner, { wW: 20 }, 'inner');
|
||||
const [outside] = computeSunRays(ROOMS, [win], 270, 60, 0, inner, { wW: 20 }, 'outer');
|
||||
|
||||
assert.ok(inside && outside, 'the west window is lit in both modes');
|
||||
assert.deepEqual(outside.a, [90, 260]);
|
||||
assert.deepEqual(outside.b, [90, 340]);
|
||||
assert.deepEqual(inside.a, [110, 260]);
|
||||
assert.deepEqual(inside.b, [110, 340]);
|
||||
assert.equal(outside.len, inside.len, 'origin selection does not change nominal reach');
|
||||
assert.deepEqual(outside.dir, inside.dir, 'origin selection does not change direction');
|
||||
assert.deepEqual(outside.normal, inside.normal, 'origin selection does not change fade axis');
|
||||
assert.equal(outside.depth, inside.depth, 'origin selection does not change fade depth');
|
||||
|
||||
const points = outside.polys.flat();
|
||||
assert.ok(points.some(([x]) => near(x, 90, 1e-6)), 'the visible shaft reaches the outer face');
|
||||
assert.ok(points.some(([x]) => x > 110 + 1e-6), 'the shaft continues from the tunnel into the room');
|
||||
for (const [x, y] of points) {
|
||||
if (x < 110 - 1e-6) {
|
||||
assert.ok(y >= 260 - 1e-6 && y <= 340 + 1e-6,
|
||||
'outside the clean floor, light exists only inside the physical opening tunnel');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('#577: zero-depth walls are identical and invalid values preserve the legacy inner default', () => {
|
||||
assert.deepEqual(SUN_RAY_ORIGINS, ['inner', 'outer']);
|
||||
assert.equal(sunRayOriginOf({}), 'inner');
|
||||
assert.equal(sunRayOriginOf({ sun_ray_origin: 'inner' }), 'inner');
|
||||
assert.equal(sunRayOriginOf({ sun_ray_origin: 'outer' }), 'outer');
|
||||
for (const invalid of [null, '', 'outside', 1, true, {}]) {
|
||||
assert.equal(sunRayOriginOf({ sun_ray_origin: invalid }), 'inner');
|
||||
}
|
||||
|
||||
const inner = computeSunRays(ROOMS, [WIN.west], 270, 60, 0, undefined, undefined, 'inner');
|
||||
const outer = computeSunRays(ROOMS, [WIN.west], 270, 60, 0, undefined, undefined, 'outer');
|
||||
assert.deepEqual(outer, inner, 'without wall depth the two source faces coincide exactly');
|
||||
});
|
||||
|
||||
test('grazing sun: the auditor\'s repro, fixed by a normal-axis fade (DEV-EB173-01)', () => {
|
||||
// The report's browser probe: a WEST window 80 render units long, elevation
|
||||
// 90 (so the nominal reach is 0.56 · 80 = 44.8 — «на 30 % короче»), azimuth
|
||||
|
||||
Reference in New Issue
Block a user