2023-08-11 14:32:44 +01:00
|
|
|
package imaging
|
2023-08-11 20:51:46 +01:00
|
|
|
|
|
|
|
import (
|
2023-08-11 21:38:14 +01:00
|
|
|
"fmt"
|
2023-08-11 20:51:46 +01:00
|
|
|
"image"
|
2023-08-11 21:38:14 +01:00
|
|
|
"math"
|
2023-08-11 20:51:46 +01:00
|
|
|
|
|
|
|
"git.fjla.uk/fred.boniface/map-dots/data"
|
|
|
|
"git.fjla.uk/fred.boniface/map-dots/log"
|
|
|
|
"github.com/fogleman/gg"
|
|
|
|
)
|
|
|
|
|
2023-08-11 21:38:14 +01:00
|
|
|
func mapCirclesToCanvas(img *image.RGBA, locations []data.LocationData) {
|
|
|
|
log.Msg.Debug("Mapping locations to canvas")
|
2023-08-11 20:51:46 +01:00
|
|
|
dc := gg.NewContextForRGBA(img)
|
|
|
|
dc.SetRGB(1, 1, 1) // Set canvas background color (white in this case)
|
|
|
|
|
2023-08-11 21:38:14 +01:00
|
|
|
circleRadius := 4 // Replace with your desired fixed radius
|
2023-08-11 20:51:46 +01:00
|
|
|
|
|
|
|
bounds := img.Bounds()
|
|
|
|
canvasWidth := bounds.Max.X - bounds.Min.X
|
|
|
|
canvasHeight := bounds.Max.Y - bounds.Min.Y
|
|
|
|
|
|
|
|
var minLat, maxLat, minLon, maxLon float64
|
2023-08-11 21:38:14 +01:00
|
|
|
for _, loc := range locations {
|
|
|
|
if loc.Latitude < minLat {
|
|
|
|
minLat = loc.Latitude
|
2023-08-11 20:51:46 +01:00
|
|
|
}
|
2023-08-11 21:38:14 +01:00
|
|
|
if loc.Latitude > maxLat {
|
|
|
|
maxLat = loc.Latitude
|
2023-08-11 20:51:46 +01:00
|
|
|
}
|
2023-08-11 21:38:14 +01:00
|
|
|
if loc.Longitude < minLon {
|
|
|
|
minLon = loc.Longitude
|
2023-08-11 20:51:46 +01:00
|
|
|
}
|
2023-08-11 21:38:14 +01:00
|
|
|
if loc.Longitude > maxLon {
|
|
|
|
maxLon = loc.Longitude
|
2023-08-11 20:51:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-11 21:38:14 +01:00
|
|
|
centerLat := (maxLat + minLat) / 2.0
|
|
|
|
centerLon := (maxLon + minLon) / 2.0
|
|
|
|
latRange := maxLat - minLat
|
|
|
|
lonRange := maxLon - minLon
|
|
|
|
|
|
|
|
for _, loc := range locations {
|
|
|
|
pixelX, pixelY := convertCoordinatesToPixels(loc.Latitude, loc.Longitude, centerLat, centerLon, latRange, lonRange, canvasWidth, canvasHeight)
|
2023-08-11 20:51:46 +01:00
|
|
|
|
|
|
|
// Draw the circle on the canvas using gg
|
|
|
|
dc.DrawCircle(float64(pixelX), float64(pixelY), float64(circleRadius))
|
|
|
|
dc.SetRGBA(1, 1, 1, 0.5) // Circle fill color (white with 50% opacity)
|
|
|
|
dc.Fill()
|
|
|
|
}
|
|
|
|
|
|
|
|
dc.Clip() // Apply clipping
|
|
|
|
|
|
|
|
// Optional: Save the canvas as an image file
|
|
|
|
err := dc.SavePNG("output.png")
|
|
|
|
if err != nil {
|
2023-08-11 21:38:14 +01:00
|
|
|
log.Msg.Error("Error saving file")
|
|
|
|
} else {
|
|
|
|
fmt.Println("Canvas saves to file")
|
2023-08-11 20:51:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-11 21:38:14 +01:00
|
|
|
func convertCoordinatesToPixels(latitude, longitude float64, centerLat, centerLon, latRange, lonRange float64, canvasWidth, canvasHeight int) (int, int) {
|
|
|
|
// Calculate normalized latitude and longitude distances from the center
|
|
|
|
latDist := (latitude - centerLat) / (latRange * 0.5)
|
|
|
|
lonDist := (longitude - centerLon) / (lonRange * 0.5)
|
|
|
|
|
|
|
|
// Calculate the maximum distance from the center as a proportion of canvas size
|
|
|
|
maxDistance := math.Max(math.Abs(latDist), math.Abs(lonDist))
|
|
|
|
|
|
|
|
// Adjust the normalized distances to match the canvas size with margins
|
|
|
|
adjustedLatDist := latDist / maxDistance * 0.45
|
|
|
|
adjustedLonDist := lonDist / maxDistance * 0.45
|
|
|
|
|
|
|
|
// Calculate pixel positions
|
|
|
|
pixelX := int((adjustedLonDist + 0.5) * float64(canvasWidth))
|
|
|
|
pixelY := int((0.5 - adjustedLatDist) * float64(canvasHeight))
|
2023-08-11 20:51:46 +01:00
|
|
|
|
|
|
|
return pixelX, pixelY
|
|
|
|
}
|