Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch implements ST_Snap. Resolves #49040 Release justification: low risk, high benefit changes to existing functionality Release note (sql change): ST_Snap is now available.
- Loading branch information
Abdullah Islam
committed
Mar 5, 2021
1 parent
46dd319
commit 9ae5e22
Showing
9 changed files
with
209 additions
and
1 deletion.
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
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,27 @@ | ||
// Copyright 2021 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 ( | ||
"github.com/cockroachdb/cockroach/pkg/geo" | ||
"github.com/cockroachdb/cockroach/pkg/geo/geos" | ||
) | ||
|
||
// Snap returns the input geometry with the vertices snapped to the target | ||
// geometry. Tolerance is used to control where snapping is performed. | ||
// If no snapping occurs then the input geometry is returned unchanged. | ||
func Snap(input, target geo.Geometry, tolerance float64) (geo.Geometry, error) { | ||
snappedEWKB, err := geos.Snap(input.EWKB(), target.EWKB(), tolerance) | ||
if err != nil { | ||
return geo.Geometry{}, err | ||
} | ||
return geo.ParseGeometryFromEWKB(snappedEWKB) | ||
} |
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,87 @@ | ||
// Copyright 2021 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" | ||
"github.com/stretchr/testify/require" | ||
"github.com/twpayne/go-geom" | ||
) | ||
|
||
func TestSnap(t *testing.T) { | ||
testCases := []struct { | ||
desc string | ||
input geom.T | ||
target geom.T | ||
tolerance float64 | ||
expected geom.T | ||
}{ | ||
{ | ||
desc: "Test snap on two linestrings with tolerance of 0", | ||
input: geom.NewLineStringFlat(geom.XY, []float64{20, 25, 30, 35}), | ||
target: geom.NewLineStringFlat(geom.XY, []float64{10, 15, 20, 25}), | ||
tolerance: 0, | ||
expected: geom.NewLineStringFlat(geom.XY, []float64{20, 25, 30, 35}), | ||
}, | ||
{ | ||
desc: "Test snapping a polygon on a linestring with tolerance of 150", | ||
input: geom.NewLineStringFlat(geom.XY, []float64{10, 55, 78, 84, 100, 200}), | ||
target: geom.NewPolygonFlat(geom.XY, []float64{26, 125, 26, 200, 126, 200, 126, 125, 26, 125}, []int{10}), | ||
tolerance: 150, | ||
expected: geom.NewLineStringFlat(geom.XY, []float64{10, 55, 26, 125, 26, 200, 126, 200, 126, 125}), | ||
}, | ||
{ | ||
desc: "Test snapping a linestring on a polygon with tolerance of 150", | ||
target: geom.NewLineStringFlat(geom.XY, []float64{10, 55, 78, 84, 100, 200}), | ||
input: geom.NewPolygonFlat(geom.XY, []float64{26, 125, 26, 200, 126, 200, 126, 125, 26, 125}, []int{10}), | ||
tolerance: 150, | ||
expected: geom.NewPolygonFlat(geom.XY, []float64{10, 55, 26, 200, 100, 200, 78, 84, 10, 55}, []int{10}), | ||
}, | ||
{ | ||
desc: "Test snapping a linestring on a multipolygon with tolerance of 200", | ||
input: geom.NewLineStringFlat(geom.XY, []float64{5, 107, 54, 84, 101, 100}), | ||
target: geom.NewMultiPolygonFlat(geom.XY, []float64{1, 1, 2, 2, 3, 3, 1, 1, 4, 4, 5, 5, 6, 6, 4, 4}, [][]int{{8}, {16}}), | ||
tolerance: 200, | ||
expected: geom.NewLineStringFlat(geom.XY, []float64{5, 107, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 101, 100}), | ||
}, | ||
{ | ||
desc: "Test snapping a multipolygon on a linestring with tolerance of 200", | ||
input: geom.NewMultiPolygonFlat(geom.XY, []float64{1, 1, 2, 2, 3, 3, 1, 1, 4, 4, 5, 5, 6, 6, 4, 4}, [][]int{{8}, {16}}), | ||
target: geom.NewLineStringFlat(geom.XY, []float64{5, 107, 54, 84, 101, 100}), | ||
tolerance: 200, | ||
expected: geom.NewMultiPolygonFlat(geom.XY, []float64{1, 1, 2, 2, 5, 107, 54, 84, 101, 100, 1, 1, 4, 4, 5, 5, 5, 107, 54, 84, 101, 100, 4, 4}, [][]int{{8}, {16}}), | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
input, err := geo.MakeGeometryFromGeomT(tc.input) | ||
require.NoError(t, err) | ||
target, err := geo.MakeGeometryFromGeomT(tc.target) | ||
require.NoError(t, err) | ||
|
||
actual, err := Snap(input, target, tc.tolerance) | ||
require.NoError(t, err) | ||
|
||
// Compare FlatCoords and assert they are within epsilon. | ||
// This is because they exact matches may encounter rounding issues. | ||
actualGeomT, err := actual.AsGeomT() | ||
|
||
require.NoError(t, err) | ||
require.Equal(t, tc.expected.SRID(), actualGeomT.SRID()) | ||
require.Equal(t, tc.expected.Layout(), actualGeomT.Layout()) | ||
require.IsType(t, tc.expected, actualGeomT) | ||
require.InEpsilonSlice(t, tc.expected.FlatCoords(), actualGeomT.FlatCoords(), 0.00001) | ||
}) | ||
} | ||
} |
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
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
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