github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/geo/encode.go (about) 1 // Copyright 2020 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package geo 12 13 import ( 14 "bytes" 15 "encoding/binary" 16 "fmt" 17 "strings" 18 19 "github.com/cockroachdb/cockroach/pkg/geo/geopb" 20 "github.com/twpayne/go-geom/encoding/ewkb" 21 "github.com/twpayne/go-geom/encoding/geojson" 22 "github.com/twpayne/go-geom/encoding/kml" 23 "github.com/twpayne/go-geom/encoding/wkb" 24 "github.com/twpayne/go-geom/encoding/wkbhex" 25 "github.com/twpayne/go-geom/encoding/wkt" 26 ) 27 28 // EWKBToWKT transforms a given EWKB to WKT. 29 func EWKBToWKT(b geopb.EWKB) (geopb.WKT, error) { 30 // twpayne/go-geom doesn't seem to handle POINT EMPTY just yet. Add this hack in. 31 // Remove after #49209 is resolved. 32 if bytes.Equal(b, []byte{0x01, 0x01, 0x00, 0x00, 0x00}) { 33 return geopb.WKT("POINT EMPTY"), nil 34 } 35 t, err := ewkb.Unmarshal([]byte(b)) 36 if err != nil { 37 return "", err 38 } 39 ret, err := wkt.Marshal(t) 40 return geopb.WKT(ret), err 41 } 42 43 // EWKBToEWKT transforms a given EWKB to EWKT. 44 func EWKBToEWKT(b geopb.EWKB) (geopb.EWKT, error) { 45 // twpayne/go-geom doesn't seem to handle POINT EMPTY just yet. Add this hack in. 46 // Remove after #49209 is resolved. 47 if bytes.Equal(b, []byte{0x01, 0x01, 0x00, 0x00, 0x00}) { 48 return geopb.EWKT("POINT EMPTY"), nil 49 } 50 t, err := ewkb.Unmarshal([]byte(b)) 51 if err != nil { 52 return "", err 53 } 54 ret, err := wkt.Marshal(t) 55 if err != nil { 56 return "", err 57 } 58 if t.SRID() != 0 { 59 ret = fmt.Sprintf("SRID=%d;%s", t.SRID(), ret) 60 } 61 return geopb.EWKT(ret), err 62 } 63 64 // EWKBToWKB transforms a given EWKB to WKB. 65 func EWKBToWKB(b geopb.EWKB, byteOrder binary.ByteOrder) (geopb.WKB, error) { 66 t, err := ewkb.Unmarshal([]byte(b)) 67 if err != nil { 68 return nil, err 69 } 70 ret, err := wkb.Marshal(t, byteOrder) 71 return geopb.WKB(ret), err 72 } 73 74 // EWKBToGeoJSON transforms a given EWKB to GeoJSON. 75 func EWKBToGeoJSON(b geopb.EWKB) ([]byte, error) { 76 t, err := ewkb.Unmarshal([]byte(b)) 77 if err != nil { 78 return nil, err 79 } 80 f := geojson.Feature{ 81 // TODO(otan): add features once we have spatial_ref_sys. 82 Geometry: t, 83 } 84 return f.MarshalJSON() 85 } 86 87 // EWKBToWKBHex transforms a given EWKB to WKBHex. 88 func EWKBToWKBHex(b geopb.EWKB) (string, error) { 89 t, err := ewkb.Unmarshal([]byte(b)) 90 if err != nil { 91 return "", err 92 } 93 ret, err := wkbhex.Encode(t, DefaultEWKBEncodingFormat) 94 return strings.ToUpper(ret), err 95 } 96 97 // EWKBToKML transforms a given EWKB to KML. 98 func EWKBToKML(b geopb.EWKB) (string, error) { 99 t, err := ewkb.Unmarshal([]byte(b)) 100 if err != nil { 101 return "", err 102 } 103 kmlElement, err := kml.Encode(t) 104 if err != nil { 105 return "", err 106 } 107 var buf bytes.Buffer 108 if err := kmlElement.Write(&buf); err != nil { 109 return "", err 110 } 111 return buf.String(), nil 112 } 113 114 // StringToByteOrder returns the byte order of string. 115 func StringToByteOrder(s string) binary.ByteOrder { 116 switch strings.ToLower(s) { 117 case "ndr": 118 return binary.LittleEndian 119 case "xdr": 120 return binary.BigEndian 121 default: 122 return DefaultEWKBEncodingFormat 123 } 124 }