// ParsePathString parses a string and returns a path func ParsePathString(s string) ([]*Path, error) { paths := make([]*Path, 0, 0) currentPath := new(Path) currentPath.Color = color.RGBA{0xff, 0, 0, 0xff} currentPath.Weight = 5.0 for _, ss := range strings.Split(s, "|") { if ok, suffix := hasPrefix(ss, "color:"); ok { var err error if currentPath.Color, err = ParseColorString(suffix); err != nil { return nil, err } } else if ok, suffix := hasPrefix(ss, "weight:"); ok { var err error if currentPath.Weight, err = strconv.ParseFloat(suffix, 64); err != nil { return nil, err } } else if ok, suffix := hasPrefix(ss, "gpx:"); ok { gpxData, err := gpx.ParseFile(suffix) if err != nil { return nil, err } for _, trk := range gpxData.Tracks { for _, seg := range trk.Segments { p := new(Path) p.Color = currentPath.Color p.Weight = currentPath.Weight for _, pt := range seg.Points { p.Positions = append(p.Positions, s2.LatLngFromDegrees(pt.GetLatitude(), pt.GetLongitude())) } if len(p.Positions) > 0 { paths = append(paths, p) } } } } else { lat, lng, err := coordsparser.Parse(ss) if err != nil { return nil, err } currentPath.Positions = append(currentPath.Positions, s2.LatLngFromDegrees(lat, lng)) } } if len(currentPath.Positions) > 0 { paths = append(paths, currentPath) } return paths, nil }
// ParseMarkerString parses a string and returns an array of markers func ParseMarkerString(s string) ([]*Marker, error) { markers := make([]*Marker, 0, 0) var color color.Color = color.RGBA{0xff, 0, 0, 0xff} size := 16.0 label := "" for _, ss := range strings.Split(s, "|") { if ok, suffix := hasPrefix(ss, "color:"); ok { var err error color, err = ParseColorString(suffix) if err != nil { return nil, err } } else if ok, suffix := hasPrefix(ss, "label:"); ok { label = suffix } else if ok, suffix := hasPrefix(ss, "size:"); ok { var err error size, err = parseSizeString(suffix) if err != nil { return nil, err } } else { lat, lng, err := coordsparser.Parse(ss) if err != nil { return nil, err } m := NewMarker(s2.LatLngFromDegrees(lat, lng), color, size) m.Label = label markers = append(markers, m) } } return markers, nil }
// create cells for point from the minLevel to maxLevel both inclusive. func indexCellsForPoint(p *geom.Point, minLevel, maxLevel int) (s2.CellUnion, s2.CellUnion) { if maxLevel < minLevel { log.Fatalf("Maxlevel should be greater than minLevel") } ll := s2.LatLngFromDegrees(p.Y(), p.X()) c := s2.CellIDFromLatLng(ll) cells := make([]s2.CellID, maxLevel-minLevel+1) for l := minLevel; l <= maxLevel; l++ { cells[l-minLevel] = c.Parent(l) } return cells, []s2.CellID{c.Parent(maxLevel)} }
// ParseAreaString parses a string and returns an area func ParseAreaString(s string) (*Area, error) { area := new(Area) area.Color = color.RGBA{0xff, 0, 0, 0xff} area.Fill = color.Transparent area.Weight = 5.0 for _, ss := range strings.Split(s, "|") { if ok, suffix := hasPrefix(ss, "color:"); ok { var err error area.Color, err = ParseColorString(suffix) if err != nil { return nil, err } } else if ok, suffix := hasPrefix(ss, "fill:"); ok { var err error area.Fill, err = ParseColorString(suffix) if err != nil { return nil, err } } else if ok, suffix := hasPrefix(ss, "weight:"); ok { var err error area.Weight, err = strconv.ParseFloat(suffix, 64) if err != nil { return nil, err } } else { lat, lng, err := coordsparser.Parse(ss) if err != nil { return nil, err } area.Positions = append(area.Positions, s2.LatLngFromDegrees(lat, lng)) } } return area, nil }
func pointFromCoord(r geom.Coord) s2.Point { // The geojson spec says that coordinates are specified as [long, lat] // We assume that any data encoded in the database follows that format. ll := s2.LatLngFromDegrees(r.Y(), r.X()) return s2.PointFromLatLng(ll) }
func main() { var opts struct { // ClearCache bool `long:"clear-cache" description:"Clears the tile cache"` Width int `long:"width" description:"Width of the generated static map image" value-name:"PIXELS" default:"512"` Height int `long:"height" description:"Height of the generated static map image" value-name:"PIXELS" default:"512"` Output string `short:"o" long:"output" description:"Output file name" value-name:"FILENAME" default:"map.png"` Type string `short:"t" long:"type" description:"Select the map type; list possible map types with '--type list'" value-name:"MAPTYPE"` Center string `short:"c" long:"center" description:"Center coordinates (lat,lng) of the static map" value-name:"LATLNG"` Zoom int `short:"z" long:"zoom" description:"Zoom factor" value-name:"ZOOMLEVEL"` Markers []string `short:"m" long:"marker" description:"Add a marker to the static map" value-name:"MARKER"` Paths []string `short:"p" long:"path" description:"Add a path to the static map" value-name:"PATH"` Areas []string `short:"a" long:"area" description:"Add an area to the static map" value-name:"AREA"` } parser := flags.NewParser(&opts, flags.HelpFlag|flags.PassDoubleDash) parser.LongDescription = `Creates a static map` _, err := parser.Parse() if parser.FindOptionByLongName("help").IsSet() { parser.WriteHelp(os.Stdout) os.Exit(0) } ctx := sm.NewContext() if parser.FindOptionByLongName("type").IsSet() { tp := getTileProviderOrExit(opts.Type) if tp != nil { ctx.SetTileProvider(tp) } } ctx.SetSize(opts.Width, opts.Height) if parser.FindOptionByLongName("zoom").IsSet() { ctx.SetZoom(opts.Zoom) } if parser.FindOptionByLongName("center").IsSet() { lat, lng, err := coordsparser.Parse(opts.Center) if err != nil { log.Fatal(err) } else { ctx.SetCenter(s2.LatLngFromDegrees(lat, lng)) } } for _, markerString := range opts.Markers { markers, err := sm.ParseMarkerString(markerString) if err != nil { log.Fatal(err) } else { for _, marker := range markers { ctx.AddMarker(marker) } } } for _, pathString := range opts.Paths { paths, err := sm.ParsePathString(pathString) if err != nil { log.Fatal(err) } else { for _, path := range paths { ctx.AddPath(path) } } } for _, areaString := range opts.Areas { area, err := sm.ParseAreaString(areaString) if err != nil { log.Fatal(err) } else { ctx.AddArea(area) } } img, err := ctx.Render() if err != nil { log.Fatal(err) return } if err = gg.SavePNG(opts.Output, img); err != nil { log.Fatal(err) return } }