summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2016-11-21 15:56:30 +0000
committerFelix Hanley <felix@userspace.com.au>2016-11-21 15:56:30 +0000
commit98da73fe927ee67b62c1f286b0adb649a20c373c (patch)
tree9c5598bee6a0445868b6d6be3191aa0c92309d8e
parent610d9c7a41362b90380e99c70af486c8a89d4641 (diff)
downloadcrjw-maps-98da73fe927ee67b62c1f286b0adb649a20c373c.tar.gz
crjw-maps-98da73fe927ee67b62c1f286b0adb649a20c373c.tar.bz2
Add main source
-rw-r--r--location.go95
-rw-r--r--main.go117
2 files changed, 212 insertions, 0 deletions
diff --git a/location.go b/location.go
new file mode 100644
index 0000000..a9cc351
--- /dev/null
+++ b/location.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "fmt"
+ "github.com/flopp/go-staticmaps"
+ "github.com/fogleman/gg"
+ "github.com/golang/geo/s2"
+ qrcode "github.com/skip2/go-qrcode"
+ "image/color"
+ "log"
+ "os"
+ "path/filepath"
+)
+
+type Location struct {
+ Number string `csv:"number"`
+ Name string `csv:"name"`
+ AltName string `csv:"altname"`
+ Latitude float64 `csv:"latitude"`
+ Longitude float64 `csv:"longitude"`
+ Comments string `csv:"comments"`
+}
+
+func (l *Location) getQRCode() string {
+ log.Printf("Getting QR code for %s", l.Number)
+ path := filepath.Join(c.cache, fmt.Sprintf("%s-qrc.png", l.Number))
+ old := true
+ fi, err := os.Stat(path)
+ if err == nil && fi.ModTime().After(c.cDate) {
+ old = false
+ if c.debug {
+ log.Printf("Using existing map file %s", path)
+ }
+ }
+ if old {
+ url := fmt.Sprintf("geo://%s,%s", l.Latitude, l.Longitude)
+ qrcode, err := qrcode.New(url, qrcode.Medium)
+ if err != nil {
+ log.Fatal("Failed to create QR code: %s", err)
+ }
+ err = qrcode.WriteFile(100, path)
+ if err != nil {
+ log.Fatal("Failed to write QR code: %s", err)
+ }
+ }
+ return path
+}
+
+func (l *Location) getMap() string {
+ log.Printf("Getting map for %s", l.Number)
+ // Flag
+ old := true
+ path := filepath.Join(c.cache, fmt.Sprintf("%s-map.png", l.Number))
+ fi, err := os.Stat(path)
+ if err == nil && fi.ModTime().After(c.cDate) {
+ old = false
+ if c.debug {
+ log.Printf("Using existing map file %s", path)
+ }
+ }
+
+ if old {
+ if c.debug {
+ log.Printf("Creating new map file %s", path)
+ }
+ ctx := sm.NewContext()
+ ctx.SetSize(640, 513)
+ // ctx.SetSize(1280, 1026)
+ pos := s2.LatLngFromDegrees(l.Latitude, l.Longitude)
+ kh := s2.LatLngFromDegrees(19.89830, 99.81805)
+ ctx.AddMarker(sm.NewMarker(pos, color.RGBA{0xff, 0, 0, 0xff}, 16.0))
+ ctx.AddMarker(sm.NewMarker(kh, color.RGBA{0, 0, 0xff, 0xff}, 16.0))
+ // ctx.SetCenter(s2.LatLngFromDegrees(19.89830, 99.81805))
+ // ctx.SetCenter(pos)
+ // ctx.SetTileProvider(sm.NewTileProviderOpenTopoMap())
+ ctx.SetTileProvider(sm.NewTileProviderThunderforestOutdoors())
+ // ctx.SetTileProvider(sm.NewTileProviderThunderforestLandscape())
+
+ if c.debug {
+ log.Printf("Rendering map for %s", l.Number)
+ }
+ img, err := ctx.Render()
+ if err != nil {
+ log.Fatal("Failed to render map: ", err)
+ }
+ if c.debug {
+ log.Printf("Saving map for %s", l.Number)
+ }
+ err = gg.SavePNG(path, img)
+ if err != nil {
+ log.Fatal("Failed to create image: ", err)
+ }
+ }
+ return path
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..9aa8517
--- /dev/null
+++ b/main.go
@@ -0,0 +1,117 @@
+package main
+
+import (
+ "flag"
+ "github.com/gocarina/gocsv"
+ "github.com/jung-kurt/gofpdf"
+ "log"
+ "os"
+ "time"
+)
+
+const (
+ pWidth = 148
+ pHeight = 105
+)
+
+var c struct {
+ in string
+ out string
+ cache string
+ cDate time.Time
+ debug bool
+}
+
+func main() {
+ flag.StringVar(&c.in, "in", "", "Input CSV file")
+ flag.StringVar(&c.out, "out", "", "Output PDF file")
+ flag.StringVar(&c.cache, "cache", "cache", "Cache path")
+ flag.BoolVar(&c.debug, "debug", false, "Debug output")
+ // flag.StringVar(&c.outPrefix, "outPrefix", "", "Output file prefix")
+
+ flag.Parse()
+
+ if c.in == "" {
+ log.Fatal("Missing input file")
+ }
+ if c.out == "" {
+ c.out = "output.pdf"
+ }
+
+ if c.debug {
+ log.Printf("Reading file %s", c.in)
+ }
+ f, err := os.Open(c.in)
+ if err != nil {
+ log.Fatal("Error opening file: %s", err)
+ }
+ defer f.Close()
+ locations := []*Location{}
+
+ err = gocsv.UnmarshalFile(f, &locations)
+ if err != nil {
+ log.Fatal("Error parsing CSV: ", err)
+ }
+ fi, err := os.Stat(c.in)
+ if err != nil {
+ log.Fatal("Error statting CSV: ", err)
+ }
+ c.cDate = fi.ModTime()
+
+ log.Printf("Processing %d locations", len(locations))
+
+ err = os.MkdirAll(c.cache, os.ModePerm)
+ if err != nil {
+ log.Fatal("Failed to create cache: ", err)
+ }
+
+ // Generate the PDF
+ pdf := gofpdf.NewCustom(&gofpdf.InitType{
+ OrientationStr: "L",
+ UnitStr: "mm",
+ Size: gofpdf.SizeType{Wd: pHeight, Ht: pWidth},
+ })
+ pdf.AddFont("Norasi", "", "Norasi.json")
+ pdf.SetFont("Norasi", "", 16)
+ pdf.SetTextColor(0, 0, 0)
+ tr := pdf.UnicodeTranslatorFromDescriptor("cp874")
+
+ // Generate the PDF
+ for i := range locations {
+ loc := locations[i]
+ log.Printf("Processing map number %s %s", loc.Number, loc.Name)
+ pdf.AddPage()
+
+ imageOpts := gofpdf.ImageOptions{"PNG", true}
+
+ // QR Code
+ qrPath := loc.getQRCode()
+ // qrInfo := pdf.RegisterImageOptions(qrPath, imageOpts)
+
+ // Map
+ smPath := loc.getMap()
+ // mapInfo := pdf.RegisterImageOptions(smPath, imageOpts)
+
+ // Name
+ if loc.Name != "" {
+ pdf.TransformBegin()
+ pdf.TransformRotate(90, 5, pHeight-5)
+ pdf.SetFontSize(40)
+ pdf.Text(5, pHeight+5, loc.Number)
+ pdf.SetFontSize(20)
+ pdf.Text(5, pHeight+5+7, tr(loc.Name))
+ pdf.ImageOptions(qrPath, pHeight-27, pHeight-10, 0, 0, false, imageOpts, 0, "")
+ pdf.TransformEnd()
+ }
+
+ pdf.ImageOptions(smPath, 25, 5, 0, pHeight-10, false, imageOpts, 0, "")
+ if c.debug {
+ log.Printf("Added map %s", smPath)
+ }
+ }
+
+ err = pdf.OutputFileAndClose(c.out)
+ if err != nil {
+ log.Fatal("Error generating PDF: ", err)
+ }
+}