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  }