github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/geo/geoprojbase/geoprojbase.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 geoprojbase is a minimal dependency package that contains
    12  // basic metadata and data structures for SRIDs and their CRS
    13  // transformations.
    14  package geoprojbase
    15  
    16  import (
    17  	"bytes"
    18  	"sort"
    19  
    20  	"github.com/cockroachdb/cockroachdb-parser/pkg/geo/geopb"
    21  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode"
    22  	"github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror"
    23  	"github.com/cockroachdb/errors"
    24  	"github.com/golang/geo/s1"
    25  	"github.com/golang/geo/s2"
    26  )
    27  
    28  // Proj4Text is the text representation of a PROJ4 transformation.
    29  type Proj4Text struct {
    30  	cStr []byte
    31  }
    32  
    33  // MakeProj4Text returns a new Proj4Text with spec based on the given string.
    34  func MakeProj4Text(str string) Proj4Text {
    35  	return Proj4Text{
    36  		cStr: []byte(str + "\u0000"),
    37  	}
    38  }
    39  
    40  // String returns the string representation of the given proj text.
    41  func (p *Proj4Text) String() string {
    42  	return string(p.cStr[:len(p.cStr)-1])
    43  }
    44  
    45  // Bytes returns the raw bytes for the given proj text.
    46  func (p *Proj4Text) Bytes() []byte {
    47  	return p.cStr
    48  }
    49  
    50  // Equal returns whether the two Proj4Texts are equal.
    51  func (p *Proj4Text) Equal(o Proj4Text) bool {
    52  	return bytes.Equal(p.cStr, o.cStr)
    53  }
    54  
    55  // Bounds represents the projected or lat/lng bounds.
    56  type Bounds struct {
    57  	MinX float64
    58  	MaxX float64
    59  	MinY float64
    60  	MaxY float64
    61  }
    62  
    63  // ProjInfo is a struct containing metadata related to a given SRID.
    64  type ProjInfo struct {
    65  	// SRID is the SRID of the projection.
    66  	SRID geopb.SRID
    67  	// AuthName is the authority who has provided this projection (e.g. ESRI, EPSG).
    68  	AuthName string
    69  	// AuthSRID is the SRID the given AuthName interprets the SRID as.
    70  	AuthSRID int
    71  	// SRText is the WKT representation of the projection.
    72  	SRText string
    73  	// Proj4Text is the PROJ4 text representation of the projection.
    74  	Proj4Text Proj4Text
    75  	// Bounds defines the bounds (projected or lat/lng) of the given coordinate system.
    76  	Bounds Bounds
    77  
    78  	// Denormalized fields.
    79  
    80  	// IsLatLng stores whether the projection is a LatLng based projection (denormalized from above)
    81  	IsLatLng bool
    82  	// The spheroid represented by the SRID.
    83  	Spheroid Spheroid
    84  }
    85  
    86  // Spheroid represents a spheroid object.
    87  type Spheroid interface {
    88  	Inverse(a, b s2.LatLng) (s12, az1, az2 float64)
    89  	InverseBatch(points []s2.Point) float64
    90  	AreaAndPerimeter(points []s2.Point) (area float64, perimeter float64)
    91  	Project(point s2.LatLng, distance float64, azimuth s1.Angle) s2.LatLng
    92  	Radius() float64
    93  	Flattening() float64
    94  	SphereRadius() float64
    95  }
    96  
    97  // ErrProjectionNotFound indicates a project was not found.
    98  var ErrProjectionNotFound error = errors.Newf("projection not found")
    99  
   100  // Projection returns the ProjInfo for the given SRID, as well as an
   101  // error if the projection does not exist.
   102  func Projection(srid geopb.SRID) (ProjInfo, error) {
   103  	projections := getProjections()
   104  	p, exists := projections[srid]
   105  	if !exists {
   106  		return ProjInfo{}, errors.Mark(
   107  			pgerror.Newf(pgcode.InvalidParameterValue, "projection for SRID %d does not exist", srid),
   108  			ErrProjectionNotFound,
   109  		)
   110  	}
   111  	return p, nil
   112  }
   113  
   114  // MustProjection returns the ProjInfo for the given SRID, panicking if the
   115  // projection does not exist.
   116  func MustProjection(srid geopb.SRID) ProjInfo {
   117  	ret, err := Projection(srid)
   118  	if err != nil {
   119  		panic(err)
   120  	}
   121  	return ret
   122  }
   123  
   124  // AllProjections returns a sorted list of all projections.
   125  func AllProjections() []ProjInfo {
   126  	projections := getProjections()
   127  	ret := make([]ProjInfo, 0, len(projections))
   128  	for _, p := range projections {
   129  		ret = append(ret, p)
   130  	}
   131  	sort.Slice(ret, func(i, j int) bool {
   132  		return ret[i].SRID < ret[j].SRID
   133  	})
   134  	return ret
   135  }