package binary import ( "code.google.com/p/goprotobuf/proto" "github.com/omniscale/imposm3/element" ) const COORD_FACTOR float64 = 11930464.7083 // ((2<<31)-1)/360.0 func CoordToInt(coord float64) uint32 { return uint32((coord + 180.0) * COORD_FACTOR) } func IntToCoord(coord uint32) float64 { return float64((float64(coord) / COORD_FACTOR) - 180.0) } func Marshal(elem interface{}) ([]byte, error) { switch typedElem := elem.(type) { case element.Node: return MarshalNode(&typedElem) default: panic("invalid elem to marshal") } } func MarshalNode(node *element.Node) ([]byte, error) { pbfNode := &Node{} pbfNode.fromWgsCoord(node.Long, node.Lat) pbfNode.Tags = tagsAsArray(node.Tags) return proto.Marshal(pbfNode) } func UnmarshalNode(data []byte) (node *element.Node, err error) { pbfNode := &Node{} err = proto.Unmarshal(data, pbfNode) if err != nil { return nil, err } node = &element.Node{} node.Long, node.Lat = pbfNode.wgsCoord() node.Tags = tagsFromArray(pbfNode.Tags) return node, nil } func deltaPack(data []int64) { if len(data) < 2 { return } lastVal := data[0] for i := 1; i < len(data); i++ { data[i], lastVal = data[i]-lastVal, data[i] } } func deltaUnpack(data []int64) { if len(data) < 2 { return } for i := 1; i < len(data); i++ { data[i] = data[i] + data[i-1] } } func MarshalWay(way *element.Way) ([]byte, error) { // TODO reuse Way to avoid make(Tags) for each way in tagsAsArray pbfWay := &Way{} deltaPack(way.Refs) pbfWay.Refs = way.Refs pbfWay.Tags = tagsAsArray(way.Tags) return proto.Marshal(pbfWay) } func UnmarshalWay(data []byte) (way *element.Way, err error) { pbfWay := &Way{} err = proto.Unmarshal(data, pbfWay) if err != nil { return nil, err } way = &element.Way{} deltaUnpack(pbfWay.Refs) way.Refs = pbfWay.Refs way.Tags = tagsFromArray(pbfWay.Tags) return way, nil } func MarshalRelation(relation *element.Relation) ([]byte, error) { pbfRelation := &Relation{} pbfRelation.MemberIds = make([]int64, len(relation.Members)) pbfRelation.MemberTypes = make([]Relation_MemberType, len(relation.Members)) pbfRelation.MemberRoles = make([]string, len(relation.Members)) for i, m := range relation.Members { pbfRelation.MemberIds[i] = m.Id pbfRelation.MemberTypes[i] = Relation_MemberType(m.Type) pbfRelation.MemberRoles[i] = m.Role } pbfRelation.Tags = tagsAsArray(relation.Tags) return proto.Marshal(pbfRelation) } func UnmarshalRelation(data []byte) (relation *element.Relation, err error) { pbfRelation := &Relation{} err = proto.Unmarshal(data, pbfRelation) if err != nil { return nil, err } relation = &element.Relation{} relation.Members = make([]element.Member, len(pbfRelation.MemberIds)) for i, _ := range pbfRelation.MemberIds { relation.Members[i].Id = pbfRelation.MemberIds[i] relation.Members[i].Type = element.MemberType(pbfRelation.MemberTypes[i]) relation.Members[i].Role = pbfRelation.MemberRoles[i] } //relation.Nodes = pbfRelation.Node relation.Tags = tagsFromArray(pbfRelation.Tags) return relation, nil }