Skip to content

Commit

Permalink
Got the basics of the snap program working.
Browse files Browse the repository at this point in the history
  • Loading branch information
gdey committed Oct 11, 2018
1 parent 1add701 commit 6f347a4
Show file tree
Hide file tree
Showing 14 changed files with 961 additions and 69 deletions.
49 changes: 49 additions & 0 deletions cmd/snap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Raster
Raster is a raster tile server that takes a mapbox style files and generates raster tiles for it.


# URLs that are supported by the application.



## Raster Tile Server API

```
/styles/${style-name:string}/tiles/[${tilesize:int}/]${z:int}/${x:int}/${y:int}[@2x][.${file-extention:enum(jpg,png)}]
```

* style-name [required] : the name of the style. If loaded via the command line the style name will be "default" (currently this
the only thing that is supported.)
* tilesize [optional] : Default is 512, valid valus are positive multiples of 256.
* z [required] : the zoom
* x [required] : the x coordinate (column) in the slippy tile scheme.
* y [required] : the y coordinate (row) in the slippy tile scheme.
* @2x [optional] : to serve hight definition (retina) tiles. Omit to serve standard definition tiles.
* file-extension [optional] : the file type to encode the raster image in. Currently supported formats png, jpg. Default is jpg.

## Static map server
For generating an image of a map at a given point and zoom use the following url.

```
/styles/${style-name:string}/static/${lon:float},${lat:float},${zoom:float},[${bearing:float],[${pitch:float}]]/${width:int}x${height:int}[@2x][.${file-extention:enum(jpg,png)}]
```

* style-name [required] : the name of the style. If loaded via the command line the style name will be "default" (currently this
the only thing that is supported.)
* lon [optional] : Default is 512, valid valus are positive multiples of 256.
* lat [required] : the zoom
* zoom [required] : the x coordinate (column) in the slippy tile scheme.
* bearing [required] : the y coordinate (row) in the slippy tile scheme.
* @2x [optional] : to serve hight definition (retina) tiles. Omit to serve standard definition tiles.
* file-extension [optional] : the file type to encode the raster image in. Currently supported formats png, jpg. Default is jpg.

## Health check

If the server is up this url will return a 200.

```
/health
```



101 changes: 101 additions & 0 deletions cmd/snap/cmd/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package cmd

import (
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"

"github.com/spf13/cobra"
)

var cmdGenerateWidth int
var cmdGenerateHeight int
var cmdGeneratePPIRatio float64
var cmdGeneratePitch float64
var cmdGenerateBearing float64
var cmdGenerateFormat string

var cmdGenerate = &cobra.Command{
Use: "generate",
Short: "generate an image for given map coordinates.",
Aliases: []string{"gen"},
}

func ValidateGenerateParams() error {
if cmdGenerateWidth < 1 {
return errors.New("--width must be greater then or equal to 1")
}
if cmdGenerateHeight < 1 {
return errors.New("--height must be greater then or equal to 1")
}
if cmdGeneratePitch < 0 {
return errors.New("--pitch must be greater then or equal to 0")
}
if cmdGenerateBearing < 0 {
return errors.New("--bearing must be greater then or equal to 0")
}
cmdGenerateFormat = strings.ToLower(cmdGenerateFormat)
if cmdGenerateFormat != "" && (cmdGenerateFormat != "jpg" || cmdGenerateFormat != "png") {
return errors.New("--format must be jpg or png")
}
return nil

}

func IsValidLngString(lng string) bool {

f64, err := strconv.ParseFloat(strings.TrimSpace(lng), 64)
if err != nil {
return false
}
return -180.0 <= f64 && f64 <= 190.0
}

func IsValidLatString(lat string) bool {

f64, err := strconv.ParseFloat(strings.TrimSpace(lat), 64)
if err != nil {
return false
}
return -90.0 <= f64 && f64 <= 90.0
}

func genImage(center [2]float64, zoom float64, output string) error {
ext, err := getFormatString(output)
if err != nil {
return err
}
var out io.Writer

if output == "" {
out = os.Stdout
} else {
file, err := os.Create(output)
if err != nil {
return fmt.Errorf("error creating output file: %v -- %v\n", output, err)
}
defer file.Close()
out = file
}

if _, err := generateZoomCenterImage(out, RootStyle, cmdGenerateWidth, cmdGenerateHeight, cmdGeneratePPIRatio, cmdGeneratePitch, cmdGenerateBearing, center, zoom, ext); err != nil {
return fmt.Errorf("failed to generate image: %v", err)
}
return nil
}

func init() {
pf := cmdGenerate.PersistentFlags()
pf.IntVar(&cmdGenerateWidth, "width", 512, "Width of the image to generate.")
pf.IntVar(&cmdGenerateHeight, "height", 512, "Height of the image to generate.")
pf.Float64Var(&cmdGeneratePPIRatio, "ppiratio", 1.0, "The pixel per inch ratio.")
pf.Float64Var(&cmdGeneratePitch, "pitch", 0.0, "The pitch of the map.")
pf.Float64Var(&cmdGenerateBearing, "bearing", 0.0, "The bearing of the map.")
pf.StringVar(&cmdGenerateFormat, "format", "", "Defaults to the ext of the output file, or jpg if not provided.")

cmdGenerate.AddCommand(cmdGenerateBounds)
cmdGenerate.AddCommand(cmdGenerateCenter)
}
67 changes: 67 additions & 0 deletions cmd/snap/cmd/generate_bounds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"
"strconv"
"strings"

"github.com/go-spatial/geom/spherical"
"github.com/go-spatial/go-mbgl/internal/bounds"
mbgl "github.com/go-spatial/go-mbgl/mbgl/simplified"
"github.com/spf13/cobra"
)

var cmdGenerateBounds = &cobra.Command{
Use: "bounds lng lat lng lat [output_file.jpg]",
Short: "generate image using bounds",
Long: `use a bounds described as (lng lat lng lat) set of coordinates to generate the image.`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 4 {
return errors.New("requres at bounds( lng lat lng lat )")
}
if len(args) > 5 {
return errors.New("extra values provided")
}
if !IsValidLngString(args[0]) {
return fmt.Errorf("Longitude must be between -180.0 and 180.0 : given %v", args[0])
}
if !IsValidLatString(args[1]) {
return fmt.Errorf("Latitude must be between -90.0 and 90.0 : given %v", args[1])
}
if !IsValidLngString(args[2]) {
return fmt.Errorf("Longitude must be between -180.0 and 80.0 : given %v", args[2])
}
if !IsValidLatString(args[3]) {
return fmt.Errorf("Latitude must be between -90.0 and 90.0 : given %v", args[3])
}
return nil
},
Run: commandGenerateBounds,
}

func commandGenerateBounds(cmd *cobra.Command, args []string) {

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

mbgl.StartSnapshotManager(ctx)

// Already checked in the Args validation function
lng1, _ := strconv.ParseFloat(strings.TrimSpace(args[0]), 64)
lat1, _ := strconv.ParseFloat(strings.TrimSpace(args[1]), 64)
lng2, _ := strconv.ParseFloat(strings.TrimSpace(args[2]), 64)
lat2, _ := strconv.ParseFloat(strings.TrimSpace(args[3]), 64)
hull := spherical.Hull([2]float64{lat1, lng1}, [2]float64{lat2, lng2})
center, zoom := bounds.CenterZoom(hull, float64(cmdGenerateWidth), float64(cmdGenerateHeight))
output := ""
if len(args) == 5 {
output = args[4]
}
if err := genImage(center, zoom, output); err != nil {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)
}
}
77 changes: 77 additions & 0 deletions cmd/snap/cmd/generate_center.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

mbgl "github.com/go-spatial/go-mbgl/mbgl/simplified"
"github.com/spf13/cobra"
)

var cmdGenerateCenter = &cobra.Command{
Use: "center lng lat zoom [output_file.jpg]",
Short: "generate image using center and zoom",
Long: `use a center point (lng lat) and a zoom to generate the image.`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 3 {
return errors.New("requres a center (lng lat) and a zoom.")
}
if len(args) > 4 {
return errors.New("extra values provided")
}
if !IsValidLngString(args[0]) {
return fmt.Errorf("Longitude must be between -180.0 and 180.0 : given %v", args[0])
}
if !IsValidLatString(args[1]) {
return fmt.Errorf("Latitude must be between -90.0 and 90.0 : given %v", args[1])
}
z64, err := strconv.ParseFloat(strings.TrimSpace(args[2]), 64)
if err != nil || z64 < 0 || z64 > 22 {
return fmt.Errorf("zoom (%v) must be a number from 0 - 22", args[2])
}

return nil
},
Run: commandGenerateCenter,
}

func getFormatString(file string) (ext string, err error) {
if cmdGenerateFormat != "" {
ext = cmdGenerateFormat
} else {
ext = strings.ToLower(strings.TrimPrefix(filepath.Ext(file), "."))
if ext == "" {
ext = "jpg"
} else if ext != "jpg" && ext != "png" {
return "jpg", fmt.Errorf("output format(%v) must be jpg or png", ext)
}
}
return ext, nil
}

func commandGenerateCenter(cmd *cobra.Command, args []string) {

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

mbgl.StartSnapshotManager(ctx)

// Already checked in the Args validation function
lng, _ := strconv.ParseFloat(strings.TrimSpace(args[0]), 64)
lat, _ := strconv.ParseFloat(strings.TrimSpace(args[1]), 64)
zoom, _ := strconv.ParseFloat(strings.TrimSpace(args[2]), 64)

output := ""
if len(args) == 4 {
output = args[3]
}
if err := genImage([2]float64{lng, lat}, zoom, output); err != nil {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)
}
}
22 changes: 22 additions & 0 deletions cmd/snap/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cmd

import "github.com/spf13/cobra"

var RootCmd = &cobra.Command{
Use: "snap",
Short: "snap is a raster tile server",
Long: `snap is a raster tile server version: ` + Version,
}

const DefaultRootStyle = "https://raw.githubusercontent.com/go-spatial/tegola-web-demo/master/styles/hot-osm.json"

var RootStyle string = DefaultRootStyle

func init() {

RootCmd.PersistentFlags().StringVarP(&RootStyle, "style", "s", DefaultRootStyle, "style to use. Style name will be default")

RootCmd.AddCommand(cmdServer)
RootCmd.AddCommand(cmdVersion)
RootCmd.AddCommand(cmdGenerate)
}
Loading

0 comments on commit 6f347a4

Please sign in to comment.