func (ex *Excavator) dredge() { util.Info("Starting dredger") defer ex.dredgers.Done() for { if val, err := ex.pbf.Decode(); err == io.EOF { break } else if err != nil { ex.errs <- err break } else { switch val := val.(type) { case *osmpbf.Node: o := &Node{val} if o.Valid() { ex.nodes <- o } case *osmpbf.Way: o := &Way{val} if o.Valid() { ex.ways <- o } case *osmpbf.Relation: ex.relations <- &Relation{val} default: ex.errs <- util.Errorf("Unknown OSM Type %T %v", val, val) } } } util.Info("Closing dredger") }
func NewBox(min, max Coordinate) (box Box, err error) { if min.Lat > max.Lat || min.Lon > max.Lon { err = util.Errorf("Min %v > Max %v", min, max) } else { box = Box{min: min, max: max} } return }
func (s *Shape) Insert(i int, p Point) (err error) { if i >= len(s.points) || i < 0 { return util.Errorf("Insert index out of range %v @ %d", s.points, i) } else { a := s.points s.points = append(a[:i], append([]Point{p}, a[i:]...)...) //s.points[i] = p } return }
func (c *CsvSource) featureAdapter(line []string) (feature *geo.Feature, err error) { props := make(map[string]interface{}, len(c.headers)) //biggest malloc for k, i := range c.headers { props[k] = line[i] } switch { case c.fields.HasCoordinates(): feature = geo.NewPointFeature() feature.Properties = props lat, err := strconv.ParseFloat(line[c.headers[c.fields["lat"]]], 64) if err != nil { return nil, err } lon, err := strconv.ParseFloat(line[c.headers[c.fields["lon"]]], 64) if err != nil { return nil, err } point := geo.NewShape(geo.Coordinate{Lat: lat, Lon: lon}) feature.AddShape(point) case c.fields.HasShape(): g := line[c.headers[c.fields["shape"]]] shp, err := geo.ShapeFromString(g) if err != nil { return nil, util.Errorf("Invalid shape format %+v", g) } switch { case len(shp.Coordinates) == 0: feature = geo.NewPointFeature() case len(shp.Coordinates) == 1: feature = geo.NewPointFeature() case shp.Coordinates[0] == shp.Coordinates[len(shp.Coordinates)-1]: //closed feature = geo.NewPolygonFeature() default: feature = geo.NewLineFeature() } feature.Properties = props feature.AddShape(shp) default: err = util.Errorf("Invalid line") } return }
func flushCommands(chunk []*command) (geom []uint32, err error) { if len(chunk) < 1 { err = util.Errorf("Flushing Zero-Length command chunk") } else { cid := chunk[0].cid cnt := uint(len(chunk)) cint := writeCmdInt(cid, cnt) geom = append(geom, cint) for _, cmd := range chunk { if cmd.cid != cid { msg := "Non contiguous CommandInteger in command chunk: %v" err = util.Errorf(msg, chunk) return } for _, param := range cmd.params { pint := writePrmInt(param) geom = append(geom, pint) } } } return }
func getSource(c *cli.Context) (source FeatureSource, err error) { path := c.Args()[0] var filter []string if len(c.String("filter")) > 0 { filter = strings.Split(c.String("filter"), ",") } ext := filepath.Ext(path)[1:] switch ext { case CsvExt: delim := c.String("csv-delimiter") fields := GeoFields{"lat": c.String("csv-lat"), "lon": c.String("csv-lon"), "shape": c.String("csv-shape")} if !fields.Validate() { err = util.Errorf("csv-lat/csv-lon or csv-shape required") break } source = NewCsvSource(path, filter, delim, fields) case GeojsonExt: source = NewGeojsonSource(path, filter) default: err = util.Errorf("Invalid source file extension %s %s", ext, strings.Join(exts, "|")) } return }
// [[lon,lat]...] func ShapeFromString(raw string) (shp *Shape, err error) { var points [][]float64 err = json.Unmarshal([]byte(raw), &points) if err != nil { return } shp = MakeShape(len(points)) for i, p := range points { if len(p) != 2 { shp = nil err = util.Errorf("Coordinate string len != 2 @ %d %s", i, raw) return } shp.Coordinates[i] = Coordinate{Lat: p[1], Lon: p[0]} } return }
func vtShapes(geom []uint32) (shapes []*Shape, gtype vt.Tile_GeomType, err error) { cur := Point{X: 0, Y: 0} blocks := vtCommands(geom) shapes = make([]*Shape, len(blocks)) for i, commands := range blocks { length := len(commands) if commands[len(commands)-1].cid == ClosePath { length-- } shape := MakeShape(length) shapes[i] = shape for c, cmd := range commands { switch cmd.cid { case MoveTo: x := cmd.params[0] y := cmd.params[1] cur = cur.Increment(x, y) shape.points[c] = cur gtype = vt.Tile_POINT //shape := NewPointShape(cur) //shapes[i] = shape //i++ case LineTo: x := cmd.params[0] y := cmd.params[1] cur = cur.Increment(x, y) shape.points[c] = cur gtype = vt.Tile_LINESTRING //shape := shapes[i-1] //shape.Append(cur) case ClosePath: gtype = vt.Tile_POLYGON //shape := shapes[len(shapes)-1] //start := shape.points[0] //shape.Append(start) default: err = util.Errorf("Invalid CommandInteger %d", cmd.cid) break } } } return }
func getVtValue(val interface{}) (vt_val *vt.Tile_Value) { vt_val = &vt.Tile_Value{} switch v := val.(type) { case string: vt_val.StringValue = &v case float32: vt_val.FloatValue = &v case float64: vt_val.DoubleValue = &v case int: intv := int64(v) vt_val.IntValue = &intv case int32: intv := int64(v) vt_val.IntValue = &intv case int64: vt_val.IntValue = &v case uint: uintv := uint64(v) vt_val.UintValue = &uintv case uint32: uintv := uint64(v) vt_val.UintValue = &uintv case uint64: vt_val.UintValue = &v case bool: vt_val.BoolValue = &v case nil: // nothing default: //TODO, flatten maps err := util.Errorf("Bad interface{} for vt.Tile_Value %v", val) util.Warn(err, "attempting to cast value to json string") if b, err := json.Marshal(v); err == nil { s := string(b) vt_val.StringValue = &s } else { util.Warn(err, "json cast failed, skipping...") } } return }
// Flatten all the points of a feature into single list. This can hel in identifying which tiles are going to be // created func GeojsonFeatureAdapter(gj *geojson.Feature) (feature *Feature, err error) { // TODO: This sucks... I just want to switch on Coordinates.(type) igeom, err := gj.GetGeometry() if igeom == nil || err != nil { err = util.Errorf("Invalid geojson feature %q", gj) return } feature = NewFeature(igeom.GetType()) //TODO filter properties feature.Properties = gj.Properties if feature.Properties != nil { feature.Properties["id"] = gj.Id } //TODO if id == nil assign a fake one feature.Type = igeom.GetType() switch geom := igeom.(type) { case *geojson.Point: shape := coordinatesAdapter(geojson.Coordinates{geom.Coordinates}) feature.AddShape(shape) case *geojson.LineString: shape := coordinatesAdapter(geom.Coordinates) feature.AddShape(shape) case *geojson.MultiPoint: shape := coordinatesAdapter(geom.Coordinates) feature.AddShape(shape) case *geojson.MultiLineString: for _, line := range geom.Coordinates { shape := coordinatesAdapter(line) feature.AddShape(shape) } case *geojson.Polygon: // mvt need exterior ring to be clockwise // and interior rings to counter-clockwise exterior := true for _, line := range geom.Coordinates { shape := coordinatesAdapter(line) if exterior { if !shape.IsClockwise() { shape.Reverse() } exterior = false } else { if shape.IsClockwise() { shape.Reverse() } } feature.AddShape(shape) } case *geojson.MultiPolygon: for _, multiline := range geom.Coordinates { exterior := true for _, line := range multiline { shape := coordinatesAdapter(line) if exterior { if !shape.IsClockwise() { shape.Reverse() } exterior = false } else { if shape.IsClockwise() { shape.Reverse() } } feature.AddShape(shape) } } default: feature = nil err = util.Errorf("Invalid Coordinate Type in GeoJson %q", geom) } return }