-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
49722: geo/geomfn: implement ST_Buffer r=summerbhola a=otan Implemented ST_Buffer. Had to write our own parsing logic to make it compatible with C. Also ran clang-format and fixed up a few bad infos. Resolves #48890 Resolves #48891 Resolves #48802 Resolves #48803 Resolves #48804 Release note (sql change): Implement ST_Buffer for geometry and string variants. Co-authored-by: Oliver Tan <[email protected]>
- Loading branch information
Showing
9 changed files
with
728 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright 2020 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package geomfn | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/geo" | ||
"github.com/cockroachdb/cockroach/pkg/geo/geos" | ||
"github.com/cockroachdb/errors" | ||
) | ||
|
||
// BufferParams is a wrapper around the geos.BufferParams. | ||
type BufferParams struct { | ||
p geos.BufferParams | ||
} | ||
|
||
// MakeDefaultBufferParams returns the default BufferParams/ | ||
func MakeDefaultBufferParams() BufferParams { | ||
return BufferParams{ | ||
p: geos.BufferParams{ | ||
EndCapStyle: geos.BufferParamsEndCapStyleRound, | ||
JoinStyle: geos.BufferParamsJoinStyleRound, | ||
SingleSided: false, | ||
QuadrantSegments: 8, | ||
MitreLimit: 5.0, | ||
}, | ||
} | ||
} | ||
|
||
// WithQuadrantSegments returns a copy of the BufferParams with the quadrantSegments set. | ||
func (b BufferParams) WithQuadrantSegments(quadrantSegments int) BufferParams { | ||
ret := b | ||
ret.p.QuadrantSegments = quadrantSegments | ||
return ret | ||
} | ||
|
||
// ParseBufferParams parses the given buffer params from a SQL string into | ||
// the BufferParams form. | ||
// The string must be of the same format as specified by https://postgis.net/docs/ST_Buffer.html. | ||
// Returns the BufferParams, as well as the modified distance. | ||
func ParseBufferParams(s string, distance float64) (BufferParams, float64, error) { | ||
p := MakeDefaultBufferParams() | ||
fields := strings.Fields(s) | ||
for _, field := range fields { | ||
fParams := strings.Split(field, "=") | ||
if len(fParams) != 2 { | ||
return BufferParams{}, 0, errors.Newf("unknown buffer parameter: %s", fParams) | ||
} | ||
f, val := fParams[0], fParams[1] | ||
switch strings.ToLower(f) { | ||
case "quad_segs": | ||
valInt, err := strconv.ParseInt(val, 10, 64) | ||
if err != nil { | ||
return BufferParams{}, 0, errors.Wrapf(err, "invalid int for %s: %s", f, val) | ||
} | ||
p.p.QuadrantSegments = int(valInt) | ||
case "endcap": | ||
switch strings.ToLower(val) { | ||
case "round": | ||
p.p.EndCapStyle = geos.BufferParamsEndCapStyleRound | ||
case "flat", "butt": | ||
p.p.EndCapStyle = geos.BufferParamsEndCapStyleFlat | ||
case "square": | ||
p.p.EndCapStyle = geos.BufferParamsEndCapStyleSquare | ||
default: | ||
return BufferParams{}, 0, errors.Newf("unknown endcap: %s (accepted: round, flat, square)", val) | ||
} | ||
case "join": | ||
switch strings.ToLower(val) { | ||
case "round": | ||
p.p.JoinStyle = geos.BufferParamsJoinStyleRound | ||
case "mitre", "miter": | ||
p.p.JoinStyle = geos.BufferParamsJoinStyleMitre | ||
case "bevel": | ||
p.p.JoinStyle = geos.BufferParamsJoinStyleBevel | ||
default: | ||
return BufferParams{}, 0, errors.Newf("unknown join: %s (accepted: round, mitre, bevel)", val) | ||
} | ||
case "mitre_limit", "miter_limit": | ||
valFloat, err := strconv.ParseFloat(val, 64) | ||
if err != nil { | ||
return BufferParams{}, 0, errors.Wrapf(err, "invalid float for %s: %s", f, val) | ||
} | ||
p.p.MitreLimit = valFloat | ||
case "side": | ||
switch strings.ToLower(val) { | ||
case "both": | ||
p.p.SingleSided = false | ||
case "left": | ||
p.p.SingleSided = true | ||
case "right": | ||
p.p.SingleSided = true | ||
distance *= -1 | ||
default: | ||
return BufferParams{}, 0, errors.Newf("unknown side: %s (accepted: both, left, right)", val) | ||
} | ||
default: | ||
return BufferParams{}, 0, errors.Newf("unknown field: %s (accepted fields: quad_segs, endcap, join, mitre_limit, side)", f) | ||
} | ||
} | ||
return p, distance, nil | ||
} | ||
|
||
// Buffer buffers a given Geometry by the supplied parameters. | ||
func Buffer(g *geo.Geometry, params BufferParams, distance float64) (*geo.Geometry, error) { | ||
bufferedGeom, err := geos.Buffer(g.EWKB(), params.p, distance) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return geo.ParseGeometryFromEWKB(bufferedGeom) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright 2020 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package geomfn | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/geo/geos" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestParseBufferParams(t *testing.T) { | ||
testCases := []struct { | ||
s string | ||
d float64 | ||
|
||
expected BufferParams | ||
expectedD float64 | ||
}{ | ||
{ | ||
s: "", | ||
d: 100, | ||
expected: BufferParams{p: geos.BufferParams{ | ||
EndCapStyle: geos.BufferParamsEndCapStyleRound, | ||
JoinStyle: geos.BufferParamsJoinStyleRound, | ||
SingleSided: false, | ||
QuadrantSegments: 8, | ||
MitreLimit: 5.0, | ||
}}, | ||
expectedD: 100, | ||
}, | ||
{ | ||
s: "endcap=flat join=mitre quad_segs=4", | ||
d: 100, | ||
expected: BufferParams{p: geos.BufferParams{ | ||
EndCapStyle: geos.BufferParamsEndCapStyleFlat, | ||
JoinStyle: geos.BufferParamsJoinStyleMitre, | ||
SingleSided: false, | ||
QuadrantSegments: 4, | ||
MitreLimit: 5.0, | ||
}}, | ||
expectedD: 100, | ||
}, | ||
{ | ||
s: "side=left", | ||
d: 100, | ||
expected: BufferParams{p: geos.BufferParams{ | ||
EndCapStyle: geos.BufferParamsEndCapStyleRound, | ||
JoinStyle: geos.BufferParamsJoinStyleRound, | ||
SingleSided: true, | ||
QuadrantSegments: 8, | ||
MitreLimit: 5.0, | ||
}}, | ||
expectedD: 100, | ||
}, | ||
{ | ||
s: "side=right", | ||
d: 100, | ||
expected: BufferParams{p: geos.BufferParams{ | ||
EndCapStyle: geos.BufferParamsEndCapStyleRound, | ||
JoinStyle: geos.BufferParamsJoinStyleRound, | ||
SingleSided: true, | ||
QuadrantSegments: 8, | ||
MitreLimit: 5.0, | ||
}}, | ||
expectedD: -100, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.s, func(t *testing.T) { | ||
s, d, err := ParseBufferParams(tc.s, tc.d) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expected, s) | ||
require.Equal(t, tc.expectedD, d) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.