2020-06-22 12:09:39 +00:00
|
|
|
package generator
|
|
|
|
|
|
|
|
import (
|
2020-06-22 13:42:19 +00:00
|
|
|
"fmt"
|
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-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"
|
|
|
|
"github.com/tribalwarshelp/shared/models"
|
|
|
|
)
|
|
|
|
|
2020-06-22 13:42:19 +00:00
|
|
|
const (
|
2020-06-22 15:30:51 +00:00
|
|
|
defaultBackgroundColor = "#000"
|
|
|
|
defaultGridLineColor = "#fff"
|
|
|
|
defaultContinentNumberColor = "#fff"
|
|
|
|
defaultMapSize = 1000
|
2020-12-30 15:51:44 +00:00
|
|
|
defaultQuality = 100
|
2020-06-22 13:42:19 +00:00
|
|
|
)
|
|
|
|
|
2020-06-22 12:09:39 +00:00
|
|
|
type Marker struct {
|
2020-07-31 19:30:13 +00:00
|
|
|
Larger bool
|
2020-06-22 15:24:58 +00:00
|
|
|
Villages []*models.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
|
2020-06-22 15:30:51 +00:00
|
|
|
ContinentNumberColor string
|
2020-06-23 12:19:45 +00:00
|
|
|
Scale float32
|
|
|
|
CenterX int
|
|
|
|
CenterY int
|
2020-08-24 09:42:14 +00:00
|
|
|
// Quality of image (1-100)
|
|
|
|
Quality int
|
2020-06-22 13:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (cfg *Config) init() {
|
|
|
|
if cfg.BackgroundColor == "" {
|
|
|
|
cfg.BackgroundColor = defaultBackgroundColor
|
|
|
|
}
|
2020-06-22 15:30:51 +00:00
|
|
|
if cfg.GridLineColor == "" {
|
|
|
|
cfg.GridLineColor = defaultGridLineColor
|
|
|
|
}
|
|
|
|
if cfg.ContinentNumberColor == "" {
|
|
|
|
cfg.ContinentNumberColor = defaultContinentNumberColor
|
|
|
|
}
|
2020-06-22 13:42:19 +00:00
|
|
|
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 {
|
2020-06-22 13:42:19 +00:00
|
|
|
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-06-22 13:42:19 +00:00
|
|
|
|
2020-08-01 10:12:21 +00:00
|
|
|
if cfg.BackgroundColor != defaultBackgroundColor {
|
|
|
|
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 15:51:44 +00:00
|
|
|
draw.Draw(img, img.Bounds(), &image.Uniform{backgroundColor}, image.Point{}, draw.Src)
|
2020-06-22 12:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, marker := range cfg.Markers {
|
2020-07-31 19:30:13 +00:00
|
|
|
m := marker
|
2020-08-01 11:36:21 +00:00
|
|
|
parsedColor, err := parseHexColorFast(m.Color)
|
|
|
|
if err != nil {
|
2020-12-30 15:51:44 +00:00
|
|
|
return errors.Wrap(err, "map-generator")
|
2020-08-01 11:36:21 +00:00
|
|
|
}
|
|
|
|
for _, village := range m.Villages {
|
2020-12-30 13:47:31 +00:00
|
|
|
limit := 1
|
2020-08-01 11:36:21 +00:00
|
|
|
if m.Larger {
|
2020-12-30 15:55:05 +00:00
|
|
|
limit = 2
|
2020-07-31 19:30:13 +00:00
|
|
|
}
|
2020-12-30 15:51:44 +00:00
|
|
|
rect := image.Rect(village.X-limit, village.Y-limit, village.X+limit, village.Y+limit)
|
|
|
|
draw.Draw(img, rect, &image.Uniform{parsedColor}, image.Point{}, draw.Src)
|
2020-08-01 11:36:21 +00:00
|
|
|
}
|
2020-06-22 12:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Continents
|
2020-06-22 13:42:19 +00:00
|
|
|
if cfg.ContinentGrid {
|
2020-06-22 15:30:51 +00:00
|
|
|
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 {
|
2020-06-22 13:42:19 +00:00
|
|
|
for x := 0; x < cfg.MapSize; x++ {
|
2020-06-22 15:30:51 +00:00
|
|
|
img.Set(x, y, gridLineColor)
|
2020-08-01 10:12:21 +00:00
|
|
|
img.Set(y, x, gridLineColor)
|
2020-06-22 13:42:19 +00:00
|
|
|
}
|
2020-06-22 12:09:39 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-22 13:42:19 +00:00
|
|
|
|
|
|
|
if cfg.ContinentNumbers {
|
|
|
|
continent := 0
|
2020-06-22 15:30:51 +00:00
|
|
|
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 {
|
2020-06-22 13:42:19 +00:00
|
|
|
continentStr := fmt.Sprintf("%d", continent)
|
|
|
|
if continent < 10 {
|
|
|
|
continentStr = fmt.Sprintf("0%d", continent)
|
|
|
|
}
|
2020-06-22 15:30:51 +00:00
|
|
|
drawText(img, x-16, y-3, continentNumberColor, continentStr)
|
2020-06-22 13:42:19 +00:00
|
|
|
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-06-23 14:33:52 +00:00
|
|
|
if err := jpeg.Encode(cfg.Destination, centered, &jpeg.Options{
|
2020-08-01 10:12:21 +00:00
|
|
|
Quality: cfg.Quality,
|
2020-06-23 14:33:52 +00:00
|
|
|
}); err != nil {
|
2020-06-22 12:09:39 +00:00
|
|
|
return errors.Wrap(err, "map-generator")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|