github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/geo/geomfn/unary_operators_test.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 12 13 import ( 14 "testing" 15 16 "github.com/cockroachdb/cockroach/pkg/geo" 17 "github.com/stretchr/testify/require" 18 "github.com/twpayne/go-geom" 19 ) 20 21 func TestCentroid(t *testing.T) { 22 testCases := []struct { 23 wkt string 24 expected string 25 }{ 26 {"POINT(1.0 1.0)", "POINT (1.0 1.0)"}, 27 {"SRID=4326;POINT(1.0 1.0)", "SRID=4326;POINT (1.0 1.0)"}, 28 {"LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", "POINT (2.0 2.0)"}, 29 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0))", "POINT (0.666666666666667 0.333333333333333)"}, 30 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))", "POINT (0.671717171717172 0.335353535353535)"}, 31 {"MULTIPOINT((1.0 1.0), (2.0 2.0))", "POINT (1.5 1.5)"}, 32 {"MULTILINESTRING((1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", "POINT (3.17541743733684 3.04481549985497)"}, 33 {"MULTIPOLYGON(((3.0 3.0, 4.0 3.0, 4.0 4.0, 3.0 3.0)), ((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)))", "POINT (2.17671691792295 1.84187604690117)"}, 34 {"GEOMETRYCOLLECTION (POINT (40 10),LINESTRING (10 10, 20 20, 10 40),POLYGON ((40 40, 20 45, 45 30, 40 40)))", "POINT (35 38.3333333333333)"}, 35 } 36 37 for _, tc := range testCases { 38 t.Run(tc.wkt, func(t *testing.T) { 39 g, err := geo.ParseGeometry(tc.wkt) 40 require.NoError(t, err) 41 ret, err := Centroid(g) 42 require.NoError(t, err) 43 44 retAsGeomT, err := ret.AsGeomT() 45 require.NoError(t, err) 46 47 expected, err := geo.ParseGeometry(tc.expected) 48 require.NoError(t, err) 49 expectedAsGeomT, err := expected.AsGeomT() 50 require.NoError(t, err) 51 52 // Ensure points are close in terms of precision. 53 require.InEpsilon(t, expectedAsGeomT.(*geom.Point).X(), retAsGeomT.(*geom.Point).X(), 2e-10) 54 require.InEpsilon(t, expectedAsGeomT.(*geom.Point).Y(), retAsGeomT.(*geom.Point).Y(), 2e-10) 55 require.Equal(t, expected.SRID(), ret.SRID()) 56 }) 57 } 58 } 59 60 func TestLength(t *testing.T) { 61 testCases := []struct { 62 wkt string 63 expected float64 64 }{ 65 {"POINT(1.0 1.0)", 0}, 66 {"LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 2.8284271247461903}, 67 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0))", 0}, 68 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))", 0}, 69 {"MULTIPOINT((1.0 1.0), (2.0 2.0))", 0}, 70 {"MULTILINESTRING((1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", 3.8284271247461903}, 71 {"MULTIPOLYGON(((3.0 3.0, 4.0 3.0, 4.0 4.0, 3.0 3.0)), ((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)))", 0}, 72 {"GEOMETRYCOLLECTION (POINT (40 10),LINESTRING (10 10, 20 20, 10 40),POLYGON ((40 40, 20 45, 45 30, 40 40)))", 36.50281539872885}, 73 } 74 75 for _, tc := range testCases { 76 t.Run(tc.wkt, func(t *testing.T) { 77 g, err := geo.ParseGeometry(tc.wkt) 78 require.NoError(t, err) 79 ret, err := Length(g) 80 require.NoError(t, err) 81 require.Equal(t, tc.expected, ret) 82 }) 83 } 84 } 85 86 func TestPerimeter(t *testing.T) { 87 testCases := []struct { 88 wkt string 89 expected float64 90 }{ 91 {"POINT(1.0 1.0)", 0}, 92 {"LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 0}, 93 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0))", 3.414213562373095}, 94 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))", 3.7556349186104043}, 95 {"MULTIPOINT((1.0 1.0), (2.0 2.0))", 0}, 96 {"MULTILINESTRING((1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", 0}, 97 {"MULTIPOLYGON(((3.0 3.0, 4.0 3.0, 4.0 4.0, 3.0 3.0)), ((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)))", 7.169848480983499}, 98 {"GEOMETRYCOLLECTION (POINT (40 10),LINESTRING (10 10, 20 20, 10 40),POLYGON ((40 40, 20 45, 45 30, 40 40)))", 60.950627489813755}, 99 } 100 101 for _, tc := range testCases { 102 t.Run(tc.wkt, func(t *testing.T) { 103 g, err := geo.ParseGeometry(tc.wkt) 104 require.NoError(t, err) 105 ret, err := Perimeter(g) 106 require.NoError(t, err) 107 require.Equal(t, tc.expected, ret) 108 }) 109 } 110 } 111 112 func TestArea(t *testing.T) { 113 testCases := []struct { 114 wkt string 115 expected float64 116 }{ 117 {"POINT(1.0 1.0)", 0}, 118 {"LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 0}, 119 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0))", 0.5}, 120 {"POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))", 0.495}, 121 {"MULTIPOINT((1.0 1.0), (2.0 2.0))", 0}, 122 {"MULTILINESTRING((1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", 0}, 123 {"MULTIPOLYGON(((3.0 3.0, 4.0 3.0, 4.0 4.0, 3.0 3.0)), ((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)))", 0.995}, 124 {"GEOMETRYCOLLECTION (POINT (40 10),LINESTRING (10 10, 20 20, 10 40),POLYGON ((40 40, 20 45, 45 30, 40 40)))", 87.5}, 125 } 126 127 for _, tc := range testCases { 128 t.Run(tc.wkt, func(t *testing.T) { 129 g, err := geo.ParseGeometry(tc.wkt) 130 require.NoError(t, err) 131 ret, err := Area(g) 132 require.NoError(t, err) 133 require.Equal(t, tc.expected, ret) 134 }) 135 } 136 }