github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/geo/geogfn/segmentize_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 geogfn 12 13 import ( 14 "fmt" 15 "testing" 16 17 "github.com/cockroachdb/cockroach/pkg/geo" 18 "github.com/stretchr/testify/require" 19 "github.com/twpayne/go-geom" 20 ) 21 22 func TestSegmentize(t *testing.T) { 23 segmentizeTestCases := []struct { 24 wkt string 25 maxSegmentLength float64 26 expectedWKT string 27 }{ 28 { 29 wkt: "POINT(1.0 1.0)", 30 maxSegmentLength: 10000.0, 31 expectedWKT: "POINT(1.0 1.0)", 32 }, 33 { 34 wkt: "LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 35 maxSegmentLength: 100000.0, 36 expectedWKT: "LINESTRING (1 1, 1.4998857365616758 1.5000570914791973, 2 2, 2.4998094835255658 2.500095075163195, 3 3)", 37 }, 38 { 39 wkt: "LINESTRING EMPTY", 40 maxSegmentLength: 10000.0, 41 expectedWKT: "LINESTRING EMPTY", 42 }, 43 { 44 wkt: "LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 45 maxSegmentLength: 500000.0, 46 expectedWKT: "LINESTRING(1.0 1.0, 2.0 2.0, 3.0 3.0)", 47 }, 48 { 49 wkt: "POLYGON((0.0 0.0, 1.0 0.0, 1.0 1.0, 0.0 0.0))", 50 maxSegmentLength: 100000.0, 51 expectedWKT: "POLYGON ((0 0, 0.5 0, 1 0, 1 0.4999999999999999, 1 1, 0.4999619199226218 0.5000190382261059, 0 0))", 52 }, 53 { 54 wkt: "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))", 55 maxSegmentLength: 50000.0, 56 expectedWKT: "POLYGON ((0 0, 0.25 0, 0.5 0, 0.75 0, 1 0, 0.9999999999999998 0.25, 1 0.4999999999999999, 0.9999999999999998 0.7499999999999999, 1 1, 0.7499666792978344 0.7500166590029188, 0.4999619199226218 0.5000190382261059, 0.24997620022356357 0.2500118986534327, 0 0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))", 57 }, 58 { 59 wkt: "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))", 60 maxSegmentLength: 1000000.0, 61 expectedWKT: "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))", 62 }, 63 { 64 wkt: "POLYGON EMPTY", 65 maxSegmentLength: 10000.0, 66 expectedWKT: "POLYGON EMPTY", 67 }, 68 { 69 wkt: "MULTIPOINT((1.0 1.0), (2.0 2.0))", 70 maxSegmentLength: 100000.0, 71 expectedWKT: "MULTIPOINT((1.0 1.0), (2.0 2.0))", 72 }, 73 { 74 wkt: "MULTILINESTRING((1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", 75 maxSegmentLength: 100000.0, 76 expectedWKT: "MULTILINESTRING ((1 1, 1.4998857365616758 1.5000570914791973, 2 2, 2.4998094835255658 2.500095075163195, 3 3), (6 6, 6.5 6.000226803574719, 7 6))", 77 }, 78 { 79 wkt: "MULTILINESTRING (EMPTY, (1.0 1.0, 2.0 2.0, 3.0 3.0), (6.0 6.0, 7.0 6.0))", 80 maxSegmentLength: 100000.0, 81 expectedWKT: "MULTILINESTRING (EMPTY, (1 1, 1.4998857365616758 1.5000570914791973, 2 2, 2.4998094835255658 2.500095075163195, 3 3), (6 6, 6.5 6.000226803574719, 7 6))", 82 }, 83 { 84 wkt: "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)))", 85 maxSegmentLength: 100000.0, 86 expectedWKT: "MULTIPOLYGON (((3 3, 3.500000000000001 3.0001140264716564, 4 3, 3.999999999999999 3.5, 4 4, 3.4997331141752333 3.5001329429928956, 3 3)), ((0 0, 0.5 0, 1 0, 1 0.4999999999999999, 1 1, 0.4999619199226218 0.5000190382261059, 0 0), (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)))", 87 }, 88 { 89 wkt: "GEOMETRYCOLLECTION (POINT (40 10),LINESTRING (10 10, 20 20, 10 40),POLYGON ((40 40, 20 45, 45 30, 40 40)))", 90 maxSegmentLength: 1000000.0, 91 expectedWKT: "GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 14.88248913028353 15.054670903122675, 20 20, 17.84783705611024 25.063693381403255, 15.510294720403053 30.09369304154877, 12.922758839587525 35.07789165618019, 10 40), POLYGON ((40 40, 30.404184608679003 42.93646050008845, 20 45, 27.258698904670663 41.785178536245354, 33.78296512799812 38.158856049677816, 39.6629587979805 34.20684491196235, 45 30, 42.6532474552537 35.02554212454631, 40 40)))", 92 }, 93 { 94 wkt: "MULTIPOINT((0 0), (1 1))", 95 maxSegmentLength: -1, 96 expectedWKT: "MULTIPOINT((0 0), (1 1))", 97 }, 98 } 99 for _, test := range segmentizeTestCases { 100 t.Run(fmt.Sprintf("%s, maximum segment length: %v", test.wkt, test.maxSegmentLength), func(t *testing.T) { 101 geog, err := geo.ParseGeography(test.wkt) 102 require.NoError(t, err) 103 modifiedGeog, err := Segmentize(geog, test.maxSegmentLength) 104 require.NoError(t, err) 105 expectedGeog, err := geo.ParseGeography(test.expectedWKT) 106 require.NoError(t, err) 107 require.Equal(t, expectedGeog, modifiedGeog) 108 }) 109 } 110 // Test for segment maximum length as negative for geometry collection. 111 t.Run(fmt.Sprintf("%s, maximum segment length: %v", segmentizeTestCases[9].wkt, 0.0), func(t *testing.T) { 112 geog, err := geo.ParseGeography(segmentizeTestCases[9].wkt) 113 require.NoError(t, err) 114 _, err = Segmentize(geog, 0) 115 require.EqualError(t, err, "maximum segment length must be positive") 116 }) 117 } 118 119 func TestSegmentizeCoords(t *testing.T) { 120 testCases := []struct { 121 desc string 122 a geom.Coord 123 b geom.Coord 124 segmentMaxLength float64 125 resultantCoordinates []float64 126 }{ 127 { 128 desc: `Coordinate(0, 0) to Coordinate(85, 85), 0.781600222084459`, 129 a: geom.Coord{0, 0}, 130 b: geom.Coord{85, 85}, 131 segmentMaxLength: 0.781600222084459, 132 resultantCoordinates: []float64{0, 0, 4.924985039227315, 44.568038920632105}, 133 }, 134 { 135 desc: `Coordinate(0, 0) to Coordinate(85, 85), 0.7816000651234446`, 136 a: geom.Coord{0, 0}, 137 b: geom.Coord{85, 85}, 138 segmentMaxLength: 0.7816000651234446, 139 resultantCoordinates: []float64{0, 0, 2.0486953806277866, 22.302074138733936, 4.924985039227315, 44.568038920632105, 11.655816669136822, 66.66485041602017}, 140 }, 141 { 142 desc: `Coordinate(85, 85) to Coordinate(0, 0), 0.29502092024628396`, 143 a: geom.Coord{85, 85}, 144 b: geom.Coord{0, 0}, 145 segmentMaxLength: 0.29502092024628396, 146 resultantCoordinates: []float64{85, 85, 22.871662720021178, 77.3609628116894, 11.655816669136824, 66.66485041602017, 7.329091976767396, 55.658764687902504, 4.924985039227315, 44.56803892063211, 3.299940624127866, 33.443216802941045, 2.048695380627787, 22.302074138733943, 0.9845421446758968, 11.1527721155093}, 147 }, 148 { 149 desc: `Coordinate(85, 85) to Coordinate(0, 0), -1`, 150 a: geom.Coord{85, 85}, 151 b: geom.Coord{0, 0}, 152 segmentMaxLength: -1, 153 resultantCoordinates: []float64{85, 85}, 154 }, 155 } 156 for _, test := range testCases { 157 t.Run(test.desc, func(t *testing.T) { 158 convertedPoints := segmentizeCoords(test.a, test.b, test.segmentMaxLength) 159 require.Equal(t, test.resultantCoordinates, convertedPoints) 160 }) 161 } 162 }