1package arcgismap23import (4 "math"5 "testing"6)78func squareRings(west, south, size float64) [][][][]float64 {9 return [][][][]float64{{{10 {west, south}, {west + size, south}, {west + size, south + size}, {west, south + size}, {west, south},11 }}}12}1314func TestPointInRings(t *testing.T) {15 holed := [][][][]float64{{16 {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}},17 {{4, 4}, {6, 4}, {6, 6}, {4, 6}, {4, 4}},18 }}19 cases := []struct {20 lon, lat float6421 want bool22 }{23 {5, 2, true}, // on the ground24 {5, 5, false}, // in the hole25 {15, 5, false}, // outside26 {-1, -1, false},27 }28 for _, tc := range cases {29 if got := pointInRings(tc.lon, tc.lat, holed); got != tc.want {30 t.Fatalf("pointInRings(%v,%v) = %v", tc.lon, tc.lat, got)31 }32 }33}3435func TestFeatureAnchor(t *testing.T) {36 lon, lat, ok := featureAnchor(Geometry{Type: GeometryRings, Rings: squareRings(2, 4, 2)})37 if !ok || math.Abs(lon-3) > 1e-9 || math.Abs(lat-5) > 1e-9 {38 t.Fatalf("square anchors at (%v,%v), %v", lon, lat, ok)39 }40 // Two polygons: the larger one's centroid answers.41 both := append(squareRings(0, 0, 1), squareRings(10, 10, 3)...)42 lon, lat, ok = featureAnchor(Geometry{Type: GeometryRings, Rings: both})43 if !ok || math.Abs(lon-11.5) > 1e-9 || math.Abs(lat-11.5) > 1e-9 {44 t.Fatalf("the larger polygon should anchor, got (%v,%v)", lon, lat)45 }46 // The longest line's middle vertex answers.47 lon, lat, ok = featureAnchor(Geometry{Type: GeometryLines, Lines: [][][]float64{48 {{0, 0}, {0.1, 0}},49 {{5, 5}, {6, 5}, {7, 5}},50 }})51 if !ok || lon != 6 || lat != 5 {52 t.Fatalf("line anchors at (%v,%v), %v", lon, lat, ok)53 }54 if _, _, ok := featureAnchor(Geometry{Type: GeometryRings}); ok {55 t.Fatal("an empty geometry anchored")56 }57}5859func TestLocateFindsTheHoldingUnit(t *testing.T) {60 index := &hydroIndex{units: []hydroUnit{61 {code: "101900030301", name: "Walnut Creek", rings: squareRings(0, 0, 1)},62 {code: "101900030304", name: "Big Dry Creek", rings: squareRings(1, 0, 1)},63 }}64 unit, found := index.locate(1.5, 0.5)65 if !found || unit.name != "Big Dry Creek" {66 t.Fatalf("located %+v, %v", unit, found)67 }68 if _, found := index.locate(5, 5); found {69 t.Fatal("a point in no unit located one")70 }71 var none *hydroIndex72 if _, found := none.locate(0, 0); found {73 t.Fatal("a nil index located a unit")74 }75}7677func TestClaimPositionsSamplesTheBoundary(t *testing.T) {78 // A long line: the anchor plus an even sample, never the whole ring.79 line := make([][]float64, 100)80 for at := range line {81 line[at] = []float64{float64(at), 0}82 }83 positions := claimPositions(Geometry{Type: GeometryLines, Lines: [][][]float64{line}})84 if len(positions) < 2 || len(positions) > claimSamples+2 {85 t.Fatalf("%d positions sampled", len(positions))86 }87}8889func TestBuildHydroIndexReadsTheCapturedSubwatersheds(t *testing.T) {90 capture := fixtureCapture()91 index := buildHydroIndex(&capture)92 if index == nil || len(index.units) != 2 {93 t.Fatalf("index is %+v", index)94 }95 without := fixtureCapture()96 kept := without.Datasets[:0]97 for _, dataset := range without.Datasets {98 if dataset.Slug != SlugSubwatersheds {99 kept = append(kept, dataset)100 }101 }102 without.Datasets = kept103 if buildHydroIndex(&without) != nil {104 t.Fatal("a capture without subwatersheds built an index")105 }106}