This repository has been archived on 2022-09-04. You can view files and clone it, but cannot push or open issues or pull requests.
map-generator/generator/generator.go

174 lines
4.3 KiB
Go
Raw Normal View History

2020-06-22 12:09:39 +00:00
package generator
import (
"fmt"
"github.com/tribalwarshelp/shared/tw/twmodel"
2020-06-22 12:09:39 +00:00
"image"
2020-06-23 12:19:45 +00:00
"image/draw"
2020-06-23 14:33:52 +00:00
"image/jpeg"
2020-12-30 17:24:08 +00:00
"image/png"
2020-06-22 12:09:39 +00:00
"io"
2020-06-23 14:33:52 +00:00
"github.com/disintegration/imaging"
2020-06-22 12:09:39 +00:00
"github.com/pkg/errors"
)
const (
defaultBackgroundColor = "#000"
defaultGridLineColor = "#fff"
defaultContinentNumberColor = "#fff"
defaultMapSize = 1000
2020-12-30 15:51:44 +00:00
defaultQuality = 100
)
2020-06-22 12:09:39 +00:00
type Marker struct {
Larger bool
Villages []*twmodel.Village `json:"villages" gqlgen:"villages" xml:"villages"`
2020-08-24 09:42:14 +00:00
// Color in HEX format
Color string `json:"color" gqlgen:"color" xml:"color"`
2020-06-22 12:09:39 +00:00
}
type Config struct {
2020-08-24 09:42:14 +00:00
Markers []*Marker
Destination io.Writer
// Default 1000x1000
MapSize int
ContinentGrid bool
ContinentNumbers bool
// BackgroundColor in HEX format
BackgroundColor string
// GridLineColor in HEX format
GridLineColor string
// ContinentNumberColor in HEX format
ContinentNumberColor string
2020-06-23 12:19:45 +00:00
Scale float32
CenterX int
CenterY int
2020-12-30 17:24:08 +00:00
PNG bool
// Quality of image (1-100), only for JPEG format
2020-08-24 09:42:14 +00:00
Quality int
}
func (cfg *Config) init() {
if cfg.BackgroundColor == "" {
cfg.BackgroundColor = defaultBackgroundColor
}
if cfg.GridLineColor == "" {
cfg.GridLineColor = defaultGridLineColor
}
if cfg.ContinentNumberColor == "" {
cfg.ContinentNumberColor = defaultContinentNumberColor
}
if cfg.MapSize <= 0 {
cfg.MapSize = defaultMapSize
}
2020-08-24 09:42:14 +00:00
if cfg.Quality <= 0 || cfg.Quality > 100 {
2020-08-01 10:12:21 +00:00
cfg.Quality = defaultQuality
}
2020-06-23 12:21:06 +00:00
if cfg.Scale < 1 {
2020-06-23 12:19:45 +00:00
cfg.Scale = 1
}
if cfg.CenterX <= 0 {
cfg.CenterX = cfg.MapSize / 2
}
if cfg.CenterY <= 0 {
cfg.CenterY = cfg.MapSize / 2
}
cfg.CenterX = int(float32(cfg.CenterX) * cfg.Scale)
cfg.CenterY = int(float32(cfg.CenterY) * cfg.Scale)
2020-06-22 12:09:39 +00:00
}
func Generate(cfg Config) error {
cfg.init()
2020-06-22 12:09:39 +00:00
upLeft := image.Point{0, 0}
lowRight := image.Point{cfg.MapSize, cfg.MapSize}
img := image.NewRGBA(image.Rectangle{upLeft, lowRight})
2020-06-23 12:19:45 +00:00
mapSizeDividedBy10 := cfg.MapSize / 10
imgHalfWidth := cfg.MapSize / 2
imgHalfHeight := imgHalfWidth
2020-12-30 17:24:08 +00:00
//background
backgroundColor, err := parseHexColorFast(cfg.BackgroundColor)
if err != nil {
return errors.Wrap(err, "map-generator")
2020-06-22 12:09:39 +00:00
}
2020-12-30 17:24:08 +00:00
draw.Draw(img, img.Bounds(), &image.Uniform{backgroundColor}, image.Point{}, draw.Src)
2020-06-22 12:09:39 +00:00
2020-12-30 17:24:08 +00:00
//markers
2020-06-22 12:09:39 +00:00
for _, marker := range cfg.Markers {
m := marker
parsedColor, err := parseHexColorFast(m.Color)
if err != nil {
2020-12-30 15:51:44 +00:00
return errors.Wrap(err, "map-generator")
}
for _, village := range m.Villages {
2020-12-30 17:11:33 +00:00
limit := 0
if m.Larger {
2020-12-30 15:55:05 +00:00
limit = 2
}
2020-12-30 17:11:33 +00:00
rect := image.Rect(village.X-limit, village.Y-limit, village.X+limit+1, village.Y+limit+1)
2020-12-30 17:24:08 +00:00
draw.Draw(img, rect, &image.Uniform{parsedColor}, image.Point{}, draw.Over)
}
2020-06-22 12:09:39 +00:00
}
//Continents
if cfg.ContinentGrid {
gridLineColor, err := parseHexColorFast(cfg.GridLineColor)
if err != nil {
return errors.Wrap(err, "map-generator")
}
2020-06-23 12:19:45 +00:00
for y := mapSizeDividedBy10; y < cfg.MapSize; y += mapSizeDividedBy10 {
for x := 0; x < cfg.MapSize; x++ {
img.Set(x, y, gridLineColor)
2020-08-01 10:12:21 +00:00
img.Set(y, x, gridLineColor)
}
2020-06-22 12:09:39 +00:00
}
}
if cfg.ContinentNumbers {
continent := 0
continentNumberColor, err := parseHexColorFast(cfg.ContinentNumberColor)
if err != nil {
return errors.Wrap(err, "map-generator")
}
2020-06-23 12:19:45 +00:00
for y := mapSizeDividedBy10; y <= cfg.MapSize; y += mapSizeDividedBy10 {
for x := mapSizeDividedBy10; x <= cfg.MapSize; x += mapSizeDividedBy10 {
continentStr := fmt.Sprintf("%d", continent)
if continent < 10 {
continentStr = fmt.Sprintf("0%d", continent)
}
drawText(img, x-16, y-3, continentNumberColor, continentStr)
continent++
}
2020-06-22 12:09:39 +00:00
}
}
2020-06-23 12:19:45 +00:00
var resizedImg image.Image = img
if cfg.Scale != 1 {
2020-06-23 12:43:34 +00:00
width := int(float32(cfg.MapSize) * cfg.Scale)
2020-06-23 14:33:52 +00:00
resizedImg = imaging.Resize(img, width, width, imaging.NearestNeighbor)
2020-06-23 12:19:45 +00:00
}
b := resizedImg.Bounds()
centered := image.NewRGBA(image.Rectangle{upLeft, lowRight})
draw.Draw(centered, b, resizedImg, image.Point{
X: cfg.CenterX - imgHalfWidth,
Y: cfg.CenterY - imgHalfHeight,
}, draw.Src)
2020-12-30 17:24:08 +00:00
if cfg.PNG {
if err := png.Encode(cfg.Destination, centered); err != nil {
return errors.Wrap(err, "map-generator")
}
} else {
if err := jpeg.Encode(cfg.Destination, centered, &jpeg.Options{
Quality: cfg.Quality,
}); err != nil {
return errors.Wrap(err, "map-generator")
}
2020-06-22 12:09:39 +00:00
}
return nil
}