1package authoring23import (4 "testing"56 "github.com/FelineStateMachine/atlas/format/vnext"7)89func TestTransformGeometryAppliesAffineToEveryNestedPosition(t *testing.T) {10 geometry := vnext.Geometry{Kind: vnext.GeometryPolygon, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{11 {{1, 1}, {3, 1}, {3, 2}, {1, 1}},12 }}}}13 mapping := GeometryMap{14 Family: "area", SourceSpace: "source",15 Transform: CoordinateTransform{Kind: "affine", Matrix: [6]float64{10, 0, 5, 0, 20, 7}},16 }17 target := CoordinateSpace{Extent: [4]float64{0, 0, 100, 100}}18 got, err := transformGeometry(geometry, mapping, target)19 if err != nil {20 t.Fatal(err)21 }22 want := []vnext.Position{{15, 27}, {35, 27}, {35, 47}, {15, 27}}23 for index, position := range got.Parts[0].Rings[0] {24 if position != want[index] {25 t.Fatalf("position %d = %v, want %v", index, position, want[index])26 }27 }28}2930func TestTransformGeometryRefusesFamilyExtentAndRingViolations(t *testing.T) {31 target := CoordinateSpace{Extent: [4]float64{0, 0, 10, 10}}32 tests := []struct {33 name string34 geometry vnext.Geometry35 mapping GeometryMap36 }{37 {38 name: "family mismatch",39 geometry: vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{1, 1}}}}}},40 mapping: GeometryMap{Family: "path", Transform: CoordinateTransform{Kind: "identity"}},41 },42 {43 name: "outside extent",44 geometry: vnext.Geometry{Kind: vnext.GeometryPoint, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{11, 1}}}}}},45 mapping: GeometryMap{Family: "point", Transform: CoordinateTransform{Kind: "identity"}},46 },47 {48 name: "open polygon",49 geometry: vnext.Geometry{Kind: vnext.GeometryPolygon, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{{1, 1}, {2, 1}, {2, 2}, {1, 2}}}}}},50 mapping: GeometryMap{Family: "area", Transform: CoordinateTransform{Kind: "identity"}},51 },52 }53 for _, test := range tests {54 t.Run(test.name, func(t *testing.T) {55 if _, err := transformGeometry(test.geometry, test.mapping, target); err == nil {56 t.Fatal("transform accepted invalid geometry")57 }58 })59 }60}6162func TestTransformGeometryClipsCrossingPathsAndAreasToTheTarget(t *testing.T) {63 t.Parallel()64 target := CoordinateSpace{Extent: [4]float64{0, 0, 10, 10}}65 identity := CoordinateTransform{Kind: "identity"}6667 path := vnext.Geometry{Kind: vnext.GeometryLineString, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{68 {-5, 5}, {5, 5}, {15, 5},69 }}}}}70 clippedPath, err := transformGeometry(path, GeometryMap{Family: "path", Transform: identity}, target)71 if err != nil {72 t.Fatal(err)73 }74 if got := clippedPath.Parts[0].Rings[0]; len(got) != 3 || got[0] != (vnext.Position{0, 5}) || got[2] != (vnext.Position{10, 5}) {75 t.Fatalf("clipped path = %v", got)76 }7778 area := vnext.Geometry{Kind: vnext.GeometryPolygon, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{79 {-5, -5}, {15, -5}, {15, 15}, {-5, 15}, {-5, -5},80 }}}}}81 clippedArea, err := transformGeometry(area, GeometryMap{Family: "area", Transform: identity}, target)82 if err != nil {83 t.Fatal(err)84 }85 ring := clippedArea.Parts[0].Rings[0]86 if len(ring) != 5 || ring[0] != ring[len(ring)-1] {87 t.Fatalf("clipped area ring = %v", ring)88 }89 for _, position := range ring {90 if !inside(position, target.Extent) {91 t.Fatalf("clipped position %v leaves target", position)92 }93 }94}9596func TestTransformGeometryClampsFloatingPointDustAtTheClosedExtent(t *testing.T) {97 target := CoordinateSpace{Extent: [4]float64{0, 0, 10, 10}}98 mapping := GeometryMap{99 Family: "path",100 Transform: CoordinateTransform{Kind: "affine", Matrix: [6]float64{101 0.1, 0, -0.1,102 0, 0.1, -0.1,103 }},104 }105 geometry := vnext.Geometry{Kind: vnext.GeometryLineString, Parts: []vnext.GeometryPart{{Rings: [][]vnext.Position{{106 {1, 1}, {101, 101},107 }}}}}108 got, err := transformGeometry(geometry, mapping, target)109 if err != nil {110 t.Fatal(err)111 }112 for _, position := range got.Parts[0].Rings[0] {113 if position[0] < 0 || position[1] < 0 || position[0] > 10 || position[1] > 10 {114 t.Fatalf("clipped position escaped the exact extent: %v", position)115 }116 }117 if got.Parts[0].Rings[0][0] != (vnext.Position{0, 0}) || got.Parts[0].Rings[0][1] != (vnext.Position{10, 10}) {118 t.Fatalf("closed extent was not exact: %v", got.Parts[0].Rings[0])119 }120}