Limit rotation change rate

This commit is contained in:
Drew Slobodnjak
2025-12-05 13:45:06 -08:00
parent efa577e186
commit 52d4c928e2
@@ -28,12 +28,13 @@ type nbodyConfig struct {
}
type circle struct {
x float64 // x position
y float64 // y position
vx float64 // x velocity
vy float64 // y velocity
radius float64 // radius
mass float64 // mass (proportional to radius^2 for simplicity)
x float64 // x position
y float64 // y position
vx float64 // x velocity
vy float64 // y velocity
radius float64 // radius
mass float64 // mass (proportional to radius^2 for simplicity)
rotation float64 // current rotation angle in degrees (0-360)
}
type nbodyState struct {
@@ -84,13 +85,20 @@ func (s *nbodySim) initialize() {
// Mass proportional to area (radius squared)
mass := radius * radius
// Initial rotation based on initial velocity
rotation := math.Atan2(vy, vx) * 180.0 / math.Pi
if rotation < 0 {
rotation += 360.0
}
s.state.circles[i] = circle{
x: x,
y: y,
vx: vx,
vy: vy,
radius: radius,
mass: mass,
x: x,
y: y,
vx: vx,
vy: vy,
radius: radius,
mass: mass,
rotation: rotation,
}
}
}
@@ -159,14 +167,6 @@ func (s *nbodySim) GetValues(t time.Time) map[string]any {
// Calculate velocity magnitude: sqrt(vx^2 + vy^2)
velocity := math.Sqrt(c.vx*c.vx + c.vy*c.vy)
// Calculate rotation angle from velocity vector (in degrees, 0-360)
// atan2(vy, vx) gives angle in radians, convert to degrees
rotation := math.Atan2(c.vy, c.vx) * 180.0 / math.Pi
// Normalize to 0-360 range
if rotation < 0 {
rotation += 360.0
}
// Center position
result[fmt.Sprintf("circle_%d_x", i)] = c.x
result[fmt.Sprintf("circle_%d_y", i)] = c.y
@@ -175,10 +175,10 @@ func (s *nbodySim) GetValues(t time.Time) map[string]any {
result[fmt.Sprintf("circle_%d_left", i)] = c.x - c.radius
result[fmt.Sprintf("circle_%d_top", i)] = c.y - c.radius
// Size, velocity, and rotation
// Size, velocity, and rotation (smoothed rotation from simulate)
result[fmt.Sprintf("circle_%d_diameter", i)] = c.radius * 2.0
result[fmt.Sprintf("circle_%d_velocity", i)] = velocity
result[fmt.Sprintf("circle_%d_rotation", i)] = rotation
result[fmt.Sprintf("circle_%d_rotation", i)] = c.rotation
}
return result
@@ -318,6 +318,46 @@ func (s *nbodySim) simulate(dt float64) {
}
}
}
// Update rotations smoothly based on velocity direction
// Maximum rotation change per sub-step (in degrees)
// At 60 sub-steps/sec, 1.5 degrees/step = 90 degrees/second max
const maxRotationChange = 5
for i := range s.state.circles {
c := &s.state.circles[i]
// Calculate target rotation from velocity vector
targetRotation := math.Atan2(c.vy, c.vx) * 180.0 / math.Pi
if targetRotation < 0 {
targetRotation += 360.0
}
// Calculate the shortest angular difference (handles wrap-around)
diff := targetRotation - c.rotation
if diff > 180.0 {
diff -= 360.0
} else if diff < -180.0 {
diff += 360.0
}
// Clamp the rotation change
if diff > maxRotationChange {
diff = maxRotationChange
} else if diff < -maxRotationChange {
diff = -maxRotationChange
}
// Apply the clamped rotation change
c.rotation += diff
// Keep rotation in 0-360 range
if c.rotation >= 360.0 {
c.rotation -= 360.0
} else if c.rotation < 0 {
c.rotation += 360.0
}
}
}
}