Improve phase trail and correlation controls

This commit is contained in:
Mikei386
2026-07-27 18:13:07 +02:00
parent 00fb59f643
commit a4fa0ceb47
13 changed files with 268 additions and 41 deletions
+50 -12
View File
@@ -29,6 +29,8 @@ const PHASE_RADIUS_TAU_S = 0.085;
const PHASE_TRAIL_FADE_MS = 2000;
const PHASE_TRAIL_MIN_STEP_MS = 1000 / 45;
const PHASE_TRAIL_MIN_DIST_PX = 1.5;
const PHASE_TRAIL_MAX_ANGLE_STEP_RAD = (2 * Math.PI) / 180;
const PHASE_TRAIL_MAX_POINTS = 1024;
const PHASE_SECTORS = [
{ startDeg: -30, endDeg: 30, color: 'rgba(72,210,150,0.3)' },
{ startDeg: 30, endDeg: 60, color: 'rgba(255,214,120,0.25)' },
@@ -517,31 +519,64 @@ function updatePhaseTrail(state, wheel, CONFIG, now) {
}
const radiusNorm = Math.max(0, Number(state?.smoothRadius) || 0);
if (radiusNorm > 0.002 && Number.isFinite(state?.smoothPhase)) {
const length = radiusNorm * wheel.radius;
const x = wheel.cx + Math.cos(state.smoothPhase) * length;
const y = wheel.cy + Math.sin(state.smoothPhase) * length;
const color = trailColorForAngle(state.smoothPhase);
const phase = wrapAngle(state.smoothPhase);
const point = createPhaseTrailPoint(wheel, phase, radiusNorm, now);
const last = state.phaseTrail.length ? state.phaseTrail[state.phaseTrail.length - 1] : null;
if (!last) {
state.phaseTrail.push({ x, y, t: now, color });
state.phaseTrail.push(point);
} else {
const dt = now - last.t;
const dx = x - last.x;
const dy = y - last.y;
const dx = point.x - last.x;
const dy = point.y - last.y;
const dist2 = dx * dx + dy * dy;
if (dt >= PHASE_TRAIL_MIN_STEP_MS || dist2 >= PHASE_TRAIL_MIN_DIST_PX * PHASE_TRAIL_MIN_DIST_PX || last.color !== color) {
state.phaseTrail.push({ x, y, t: now, color });
if (dt >= PHASE_TRAIL_MIN_STEP_MS || dist2 >= PHASE_TRAIL_MIN_DIST_PX * PHASE_TRAIL_MIN_DIST_PX || last.color !== point.color) {
appendPhaseTrailSegment(state.phaseTrail, wheel, last, phase, radiusNorm, now);
} else {
last.x = x;
last.y = y;
last.x = point.x;
last.y = point.y;
last.t = now;
last.color = color;
last.color = point.color;
last.phase = phase;
last.radiusNorm = radiusNorm;
}
}
}
trimPhaseTrail(state, CONFIG, now);
}
function createPhaseTrailPoint(wheel, phase, radiusNorm, timestamp) {
const length = radiusNorm * wheel.radius;
return {
x: wheel.cx + Math.cos(phase) * length,
y: wheel.cy + Math.sin(phase) * length,
t: timestamp,
color: trailColorForAngle(phase),
phase,
radiusNorm,
};
}
function appendPhaseTrailSegment(trail, wheel, last, phase, radiusNorm, timestamp) {
const startPhase = Number.isFinite(last?.phase) ? last.phase : phase;
const startRadius = Number.isFinite(last?.radiusNorm) ? last.radiusNorm : radiusNorm;
const phaseDelta = wrapAngle(phase - startPhase);
const steps = Math.max(1, Math.ceil(Math.abs(phaseDelta) / PHASE_TRAIL_MAX_ANGLE_STEP_RAD));
const startTime = Number.isFinite(last?.t) ? last.t : timestamp;
for (let step = 1; step <= steps; step++) {
const fraction = step / steps;
const interpolatedPhase = wrapAngle(startPhase + phaseDelta * fraction);
const interpolatedRadius = lerp(startRadius, radiusNorm, fraction);
const interpolatedTime = lerp(startTime, timestamp, fraction);
trail.push(createPhaseTrailPoint(
wheel,
interpolatedPhase,
interpolatedRadius,
interpolatedTime,
));
}
}
function trimPhaseTrail(state, CONFIG, now) {
if (!state.phaseTrail) state.phaseTrail = [];
if (!CONFIG?.PHASE_TRAIL_ENABLED) {
@@ -557,6 +592,9 @@ function trimPhaseTrail(state, CONFIG, now) {
}
}
state.phaseTrail.length = write;
if (state.phaseTrail.length > PHASE_TRAIL_MAX_POINTS) {
state.phaseTrail.splice(0, state.phaseTrail.length - PHASE_TRAIL_MAX_POINTS);
}
}
function drawPhaseTrail(g, wheel, state, CONFIG, now) {