package odometry

import "math"

// rotateGray rotates a grayscale matrix by angleDeg (positive = clockwise)
// around its center, using bilinear interpolation. The output has the same
// dimensions as the input.
func rotateGray(g [][]float64, size int, angleDeg float64) [][]float64 {
	theta := angleDeg * math.Pi / 180.0
	cosT := math.Cos(theta)
	sinT := math.Sin(theta)
	cy := float64(size-1) / 2.0
	cx := float64(size-1) / 2.0

	out := make([][]float64, size)
	for i := range out {
		out[i] = make([]float64, size)
	}

	for oy := 0; oy < size; oy++ {
		for ox := 0; ox < size; ox++ {
			// Map output pixel to input coordinates via inverse rotation.
			dy := float64(oy) - cy
			dx := float64(ox) - cx
			sx := cx + dx*cosT + dy*sinT
			sy := cy - dx*sinT + dy*cosT

			// Bilinear interpolation with clamp at borders.
			x0 := int(math.Floor(sx))
			y0 := int(math.Floor(sy))
			fx := sx - float64(x0)
			fy := sy - float64(y0)

			x0 = clampInt(x0, 0, size-1)
			y0 = clampInt(y0, 0, size-1)
			x1 := clampInt(x0+1, 0, size-1)
			y1 := clampInt(y0+1, 0, size-1)

			out[oy][ox] = (1-fy)*(1-fx)*g[y0][x0] +
				(1-fy)*fx*g[y0][x1] +
				fy*(1-fx)*g[y1][x0] +
				fy*fx*g[y1][x1]
		}
	}
	return out
}

func absf(x float64) float64 {
	if x < 0 {
		return -x
	}
	return x
}
