github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/geo/geomfn/geomfn.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 geomfn contains functions that are used for geometry-based builtins.
    12  package geomfn
    13  
    14  import (
    15  	"github.com/cockroachdb/cockroach/pkg/geo"
    16  	"github.com/cockroachdb/errors"
    17  	"github.com/twpayne/go-geom"
    18  )
    19  
    20  // flattenGeometry flattens a geo.Geometry object.
    21  func flattenGeometry(g *geo.Geometry, emptyBehavior geo.EmptyBehavior) ([]geom.T, error) {
    22  	f, err := g.AsGeomT()
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  	return flattenGeomT(f, emptyBehavior)
    27  }
    28  
    29  // flattenGeomT decomposes geom.T collections to individual geom.T components.
    30  func flattenGeomT(g geom.T, emptyBehavior geo.EmptyBehavior) ([]geom.T, error) {
    31  	if g.Empty() {
    32  		switch emptyBehavior {
    33  		case geo.EmptyBehaviorOmit:
    34  			return nil, nil
    35  		case geo.EmptyBehaviorError:
    36  			return nil, geo.NewEmptyGeometryError()
    37  		default:
    38  			return nil, errors.Newf("programmer error: unknown behavior")
    39  		}
    40  	}
    41  	switch g := g.(type) {
    42  	case *geom.Point:
    43  		return []geom.T{g}, nil
    44  	case *geom.LineString:
    45  		return []geom.T{g}, nil
    46  	case *geom.Polygon:
    47  		return []geom.T{g}, nil
    48  	case *geom.MultiPoint:
    49  		ret := make([]geom.T, g.NumPoints())
    50  		for i := 0; i < g.NumPoints(); i++ {
    51  			ret[i] = g.Point(i)
    52  		}
    53  		return ret, nil
    54  	case *geom.MultiLineString:
    55  		ret := make([]geom.T, g.NumLineStrings())
    56  		for i := 0; i < g.NumLineStrings(); i++ {
    57  			ret[i] = g.LineString(i)
    58  		}
    59  		return ret, nil
    60  	case *geom.MultiPolygon:
    61  		ret := make([]geom.T, g.NumPolygons())
    62  		for i := 0; i < g.NumPolygons(); i++ {
    63  			ret[i] = g.Polygon(i)
    64  		}
    65  		return ret, nil
    66  	case *geom.GeometryCollection:
    67  		ret := make([]geom.T, 0, g.NumGeoms())
    68  		for _, subG := range g.Geoms() {
    69  			if subG.Empty() {
    70  				switch emptyBehavior {
    71  				case geo.EmptyBehaviorOmit:
    72  					continue
    73  				case geo.EmptyBehaviorError:
    74  					return nil, geo.NewEmptyGeometryError()
    75  				default:
    76  					return nil, errors.Newf("programmer error: unknown behavior")
    77  				}
    78  			}
    79  			ret = append(ret, subG)
    80  		}
    81  		return ret, nil
    82  	}
    83  	return nil, errors.Newf("unknown geom: %T", g)
    84  }