From 7912f32f25bbf43c748cecd29c6c2944067e7595 Mon Sep 17 00:00:00 2001 From: Giuseppe Broccolo Date: Sun, 17 May 2020 19:20:08 +0100 Subject: [PATCH] Add extended points type align naming of test cases variable for point types to the rest of tests modules --- geom.go | 42 +++++++++++++++++++++ point_test.go | 4 +- pointm.go | 41 ++++++++++++++++++++ pointm_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++ pointms.go | 39 +++++++++++++++++++ pointms_test.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ points.go | 39 +++++++++++++++++++ points_test.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ pointz.go | 42 +++++++++++++++++++++ pointz_test.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++ pointzm.go | 43 +++++++++++++++++++++ pointzm_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++ pointzms.go | 39 +++++++++++++++++++ pointzms_test.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ pointzs.go | 39 +++++++++++++++++++ pointzs_test.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ set_geom.go | 42 +++++++++++++++++++++ 17 files changed, 1046 insertions(+), 2 deletions(-) create mode 100644 pointm.go create mode 100644 pointm_test.go create mode 100644 pointms.go create mode 100644 pointms_test.go create mode 100644 points.go create mode 100644 points_test.go create mode 100644 pointz.go create mode 100644 pointz_test.go create mode 100644 pointzm.go create mode 100644 pointzm_test.go create mode 100644 pointzms.go create mode 100644 pointzms_test.go create mode 100644 pointzs.go create mode 100644 pointzs_test.go diff --git a/geom.go b/geom.go index deb2b525..8a88b1f4 100644 --- a/geom.go +++ b/geom.go @@ -16,6 +16,48 @@ type Pointer interface { XY() [2]float64 } +// PointZer is a 3D point. +type PointZer interface { + Geometry + XYZ() [3]float64 +} + +// PointMer is a 2D+1D point. +type PointMer interface { + Geometry + XYM() [3]float64 +} + +// PointZMer is a 3D+1D point. +type PointZMer interface { + Geometry + XYZM() [4]float64 +} + +// PointSer is a 2D point + SRID +type PointSer interface { + Geometry + XYS() struct {Srid uint32; Xy Point} +} + +// PointZSer is a 3D point + SRID +type PointZSer interface { + Geometry + XYZS() struct {Srid uint32; Xyz PointZ} +} + +// PointMSer is a 2D+1D point + SRID +type PointMSer interface { + Geometry + XYMS() struct {Srid uint32; Xym PointM} +} + +// PointZMSer is a 3D+1D point + SRID +type PointZMSer interface { + Geometry + XYZMS() struct {Srid uint32; Xyzm PointZM} +} + // MultiPointer is a geometry with multiple points. type MultiPointer interface { Geometry diff --git a/point_test.go b/point_test.go index 9cafd973..d4dfa266 100644 --- a/point_test.go +++ b/point_test.go @@ -44,7 +44,7 @@ func TestPointSetter(t *testing.T) { } } - testcases := []tcase{ + tests := []tcase{ { point: [2]float64{10, 20}, setter: &geom.Point{15, 20}, @@ -56,7 +56,7 @@ func TestPointSetter(t *testing.T) { }, } - for i, tc := range testcases { + for i, tc := range tests { t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) } } diff --git a/pointm.go b/pointm.go new file mode 100644 index 00000000..ec7f7214 --- /dev/null +++ b/pointm.go @@ -0,0 +1,41 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointM is thrown when a point is null but shouldn't be +var ErrNilPointM = errors.New("geom: nil PointM") + +// Point describes a simple 2D+1D point +type PointM [3]float64 + +// XYM returns an array of 2D+1D coordinates +func (p PointM) XYM() [3]float64 { + return p +} + +// XY returns an array of 2D coordinates +func (p PointM) XY() [2]float64 { + return Point{ + p[0], + p[1], + } +} + +// M returns the metric related to the 2D point +func (p PointM) M() float64 { + return p[2] +} + +// SetXYM sets the three coordinates +func (p *PointM) SetXYM(xym [3]float64) (err error) { + if p == nil { + return ErrNilPointM + } + + p[0] = xym[0] + p[1] = xym[1] + p[2] = xym[2] + return +} diff --git a/pointm_test.go b/pointm_test.go new file mode 100644 index 00000000..a70a7cc2 --- /dev/null +++ b/pointm_test.go @@ -0,0 +1,95 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointMSetter(t *testing.T) { + type tcase struct { + point [3]float64 + setter geom.PointMSetter + expected geom.PointMSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYM(tc.point) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xym := tc.setter.XYM() + if !reflect.DeepEqual(tc.point, xym) { + t.Errorf("XYM, expected %v, got %v", tc.point, xym) + } + } + } + tests := []tcase{ + { + point: [3]float64{10, 20, 1000.}, + setter: &geom.PointM{15, 20, 1000.}, + expected: &geom.PointM{10, 20, 1000.}, + }, + { + setter: (*geom.PointM)(nil), + err: geom.ErrNilPointM, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointM(t *testing.T) { + fn := func(pt geom.PointM) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xy", func(t *testing.T) { + xy := pt.XY() + exp_xy := geom.Point{pt[0], pt[1]} + if xy != exp_xy { + t.Errorf("xy, expected %v got %v", exp_xy, xy) + } + }) + t.Run("xym", func(t *testing.T) { + xym := pt.XYM() + exp_xym := pt + if xym != exp_xym { + t.Errorf("xym, expected %v got %v", exp_xym, xym) + } + }) + t.Run("m", func(t *testing.T) { + m := pt.M() + exp_m := pt[2] + if m != exp_m { + t.Errorf("m, expected %v got %v", exp_m, m) + } + }) + } + } + tests := []geom.PointM{ + {0, 1, 1000.}, {2, 2, 1000.}, {1, 2, 1000.}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/pointms.go b/pointms.go new file mode 100644 index 00000000..149bbef7 --- /dev/null +++ b/pointms.go @@ -0,0 +1,39 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointMS is thrown when a point is null but shouldn't be +var ErrNilPointMS = errors.New("geom: nil PointMS") + +// Point describes a simple 3D point with SRID +type PointMS struct { + Srid uint32 + Xym PointM } + +// XYMS returns the struct itself +func (p PointMS) XYMS() struct {Srid uint32; Xym PointM} { + return p +} + +// XYM returns 3D+1D point +func (p PointMS) XYM() PointM { + return p.Xym +} + +// S returns the srid as uint32 +func (p PointMS) S() uint32 { + return p.Srid +} + +// SetXYMS sets the XYM coordinates and the SRID +func (p *PointMS) SetXYMS(srid uint32, xym PointM) (err error) { + if p == nil { + return ErrNilPointMS + } + + p.Srid = srid + p.Xym = xym + return +} diff --git a/pointms_test.go b/pointms_test.go new file mode 100644 index 00000000..8821b8da --- /dev/null +++ b/pointms_test.go @@ -0,0 +1,98 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointMSSetter(t *testing.T) { + type tcase struct { + point_srid uint32 + point_xym geom.PointM + setter geom.PointMSSetter + expected geom.PointMSSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYMS(tc.point_srid, tc.point_xym) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xyms := tc.setter.XYMS() + tc_xyms := struct {Srid uint32; Xym geom.PointM}{tc.point_srid, geom.PointM{tc.point_xym[0], tc.point_xym[1], tc.point_xym[2]}} + if !reflect.DeepEqual(tc_xyms, xyms) { + t.Errorf("XYZS, expected %v, got %v", tc_xyms, xyms) + } + } + } + tests := []tcase{ + { + point_srid: 4326, + point_xym: geom.PointM{10, 20, 1000}, + setter: &geom.PointMS{4326, geom.PointM{15, 20, 1000}}, + expected: &geom.PointMS{4326, geom.PointM{10, 20, 1000}}, + }, + { + setter: (*geom.PointMS)(nil), + err: geom.ErrNilPointMS, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointMS(t *testing.T) { + fn := func(pt geom.PointMS) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xym", func(t *testing.T) { + xym := pt.XYM() + exp_xym := pt.Xym + if xym != exp_xym { + t.Errorf("xym, expected %v got %v", exp_xym, xym) + } + }) + t.Run("s", func(t *testing.T) { + s := pt.S() + exp_s := pt.Srid + if s != exp_s { + t.Errorf("srid, expected %v got %v", exp_s, s) + } + }) + t.Run("xyms", func(t *testing.T) { + xyms := pt.XYMS() + exp_xyms := pt + if xyms != exp_xyms { + t.Errorf("xyms, expected %v got %v", exp_xyms, xyms) + } + }) + } + } + tests := []geom.PointMS{ + {4326, geom.PointM{0, 1, 1000}}, {4326, geom.PointM{2, 2, 300}}, {4326, geom.PointM{1, 2, 1000}}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/points.go b/points.go new file mode 100644 index 00000000..c2742efe --- /dev/null +++ b/points.go @@ -0,0 +1,39 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointS is thrown when a point is null but shouldn't be +var ErrNilPointS = errors.New("geom: nil PointS") + +// Point describes a simple 2D point with SRID +type PointS struct { + Srid uint32 + Xy Point } + +// XYS returns the struct itself +func (p PointS) XYS() struct {Srid uint32; Xy Point} { + return p +} + +// XY returns 2D point +func (p PointS) XY() Point { + return p.Xy +} + +// S returns the srid as uint32 +func (p PointS) S() uint32 { + return p.Srid +} + +// SetXYS sets the XY coordinates and the SRID +func (p *PointS) SetXYS(srid uint32, xy Point) (err error) { + if p == nil { + return ErrNilPointS + } + + p.Srid = srid + p.Xy = xy + return +} diff --git a/points_test.go b/points_test.go new file mode 100644 index 00000000..617b132e --- /dev/null +++ b/points_test.go @@ -0,0 +1,98 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointSSetter(t *testing.T) { + type tcase struct { + point_srid uint32 + point_xy geom.Point + setter geom.PointSSetter + expected geom.PointSSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYS(tc.point_srid, tc.point_xy) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xys := tc.setter.XYS() + tc_xys := struct {Srid uint32; Xy geom.Point}{tc.point_srid, geom.Point{tc.point_xy[0], tc.point_xy[1]}} + if !reflect.DeepEqual(tc_xys, xys) { + t.Errorf("XYZ, expected %v, got %v", tc_xys, xys) + } + } + } + tests := []tcase{ + { + point_srid: 4326, + point_xy: geom.Point{10, 20}, + setter: &geom.PointS{4326, geom.Point{15, 20}}, + expected: &geom.PointS{4326, geom.Point{10, 20}}, + }, + { + setter: (*geom.PointS)(nil), + err: geom.ErrNilPointS, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointS(t *testing.T) { + fn := func(pt geom.PointS) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xy", func(t *testing.T) { + xy := pt.XY() + exp_xy := pt.Xy + if xy != exp_xy { + t.Errorf("xy, expected %v got %v", exp_xy, xy) + } + }) + t.Run("s", func(t *testing.T) { + s := pt.S() + exp_s := pt.Srid + if s != exp_s { + t.Errorf("srid, expected %v got %v", exp_s, s) + } + }) + t.Run("xys", func(t *testing.T) { + xys := pt.XYS() + exp_xys := pt + if xys != exp_xys { + t.Errorf("xys, expected %v got %v", exp_xys, xys) + } + }) + } + } + tests := []geom.PointS{ + {4326, geom.Point{0, 1}}, {4326, geom.Point{2, 2}}, {4326, geom.Point{1, 2}}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/pointz.go b/pointz.go new file mode 100644 index 00000000..88d0b726 --- /dev/null +++ b/pointz.go @@ -0,0 +1,42 @@ +package geom + +import ( + "errors" + "math" +) + +// ErrNilPointZ is thrown when a point is null but shouldn't be +var ErrNilPointZ = errors.New("geom: nil PointZ") + +// Point describes a simple 3D point +type PointZ [3]float64 + +// XYZ returns an array of 3D coordinates +func (p PointZ) XYZ() [3]float64 { + return p +} + +// XY returns an array of 2D coordinates +func (p PointZ) XY() [2]float64 { + return Point{ + p[0], + p[1], + } +} + +// SetXYZ sets the three coordinates +func (p *PointZ) SetXYZ(xyz [3]float64) (err error) { + if p == nil { + return ErrNilPointZ + } + + p[0] = xyz[0] + p[1] = xyz[1] + p[2] = xyz[2] + return +} + +// Magnitude of the point is the size of the point +func (p PointZ) Magnitude() float64 { + return math.Sqrt((p[0] * p[0]) + (p[1] * p[1]) + (p[2] * p[2])) +} diff --git a/pointz_test.go b/pointz_test.go new file mode 100644 index 00000000..80f0ecff --- /dev/null +++ b/pointz_test.go @@ -0,0 +1,96 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + "math" + + "github.com/go-spatial/geom" +) + +func TestPointZSetter(t *testing.T) { + type tcase struct { + point [3]float64 + setter geom.PointZSetter + expected geom.PointZSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYZ(tc.point) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xyz := tc.setter.XYZ() + if !reflect.DeepEqual(tc.point, xyz) { + t.Errorf("XYZ, expected %v, got %v", tc.point, xyz) + } + } + } + tests := []tcase{ + { + point: [3]float64{10, 20, 30}, + setter: &geom.PointZ{15, 20, 30}, + expected: &geom.PointZ{10, 20, 30}, + }, + { + setter: (*geom.PointZ)(nil), + err: geom.ErrNilPointZ, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointZ(t *testing.T) { + fn := func(pt geom.PointZ) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xy", func(t *testing.T) { + xy := pt.XY() + exp_xy := geom.Point{pt[0], pt[1]} + if xy != exp_xy { + t.Errorf("xy, expected %v got %v", exp_xy, xy) + } + }) + t.Run("xyz", func(t *testing.T) { + xyz := pt.XYZ() + exp_xyz := pt + if xyz != exp_xyz { + t.Errorf("xyz, expected %v got %v", exp_xyz, xyz) + } + }) + t.Run("magnitude", func(t *testing.T) { + m := pt.Magnitude() + exp_m := math.Sqrt((pt[0] * pt[0]) + (pt[1] * pt[1]) + (pt[2] * pt[2])) + if m != exp_m { + t.Errorf("magnitude, expected %v got %v", exp_m, m) + } + }) + } + } + tests := []geom.PointZ{ + {0, 1, 2}, {2, 2, 3}, {1, 2, 3}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/pointzm.go b/pointzm.go new file mode 100644 index 00000000..7f18377e --- /dev/null +++ b/pointzm.go @@ -0,0 +1,43 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointZM is thrown when a point is null but shouldn't be +var ErrNilPointZM = errors.New("geom: nil PointZM") + +// Point describes a simple 3D+1D point +type PointZM [4]float64 + +// XYZM returns an array of 3D+1D coordinates +func (p PointZM) XYZM() [4]float64 { + return p +} + +// XYZ returns an array of 3D coordinates +func (p PointZM) XYZ() [3]float64 { + return PointZ{ + p[0], + p[1], + p[2], + } +} + +// M returns the metric related to the 2D point +func (p PointZM) M() float64 { + return p[3] +} + +// SetXYZM sets the three coordinates +func (p *PointZM) SetXYZM(xyzm [4]float64) (err error) { + if p == nil { + return ErrNilPointZM + } + + p[0] = xyzm[0] + p[1] = xyzm[1] + p[2] = xyzm[2] + p[3] = xyzm[3] + return +} diff --git a/pointzm_test.go b/pointzm_test.go new file mode 100644 index 00000000..6676adec --- /dev/null +++ b/pointzm_test.go @@ -0,0 +1,95 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointZMSetter(t *testing.T) { + type tcase struct { + point [4]float64 + setter geom.PointZMSetter + expected geom.PointZMSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYZM(tc.point) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xyzm := tc.setter.XYZM() + if !reflect.DeepEqual(tc.point, xyzm) { + t.Errorf("XYZM, expected %v, got %v", tc.point, xyzm) + } + } + } + tests := []tcase{ + { + point: [4]float64{10, 20, 30, 1000.}, + setter: &geom.PointZM{15, 20, 30, 1000.}, + expected: &geom.PointZM{10, 20, 30, 1000.}, + }, + { + setter: (*geom.PointZM)(nil), + err: geom.ErrNilPointZM, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointZM(t *testing.T) { + fn := func(pt geom.PointZM) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xyz", func(t *testing.T) { + xyz := pt.XYZ() + exp_xyz := geom.PointZ{pt[0], pt[1], pt[2]} + if xyz != exp_xyz { + t.Errorf("xyz, expected %v got %v", exp_xyz, xyz) + } + }) + t.Run("xyzm", func(t *testing.T) { + xyzm := pt.XYZM() + exp_xyzm := pt + if xyzm != exp_xyzm { + t.Errorf("xyzm, expected %v got %v", exp_xyzm, xyzm) + } + }) + t.Run("m", func(t *testing.T) { + m := pt.M() + exp_m := pt[3] + if m != exp_m { + t.Errorf("m, expected %v got %v", exp_m, m) + } + }) + } + } + tests := []geom.PointZM{ + {0, 1, 2, 1000.}, {2, 2, 3, 1000.}, {1, 2, 3, 1000.}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/pointzms.go b/pointzms.go new file mode 100644 index 00000000..154a99b0 --- /dev/null +++ b/pointzms.go @@ -0,0 +1,39 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointZMS is thrown when a point is null but shouldn't be +var ErrNilPointZMS = errors.New("geom: nil PointZMS") + +// Point describes a simple 3D+1D point with SRID +type PointZMS struct { + Srid uint32 + Xyzm PointZM } + +// XYZMS returns the struct itself +func (p PointZMS) XYZMS() struct {Srid uint32; Xyzm PointZM} { + return p +} + +// XYZM returns 3D+1D point +func (p PointZMS) XYZM() PointZM { + return p.Xyzm +} + +// S returns the srid as uint32 +func (p PointZMS) S() uint32 { + return p.Srid +} + +// SetXYZMS sets the XYZM coordinates and the SRID +func (p *PointZMS) SetXYZMS(srid uint32, xyzm PointZM) (err error) { + if p == nil { + return ErrNilPointZMS + } + + p.Srid = srid + p.Xyzm = xyzm + return +} diff --git a/pointzms_test.go b/pointzms_test.go new file mode 100644 index 00000000..dc23417b --- /dev/null +++ b/pointzms_test.go @@ -0,0 +1,98 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointZMSSetter(t *testing.T) { + type tcase struct { + point_srid uint32 + point_xyzm geom.PointZM + setter geom.PointZMSSetter + expected geom.PointZMSSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYZMS(tc.point_srid, tc.point_xyzm) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xyzms := tc.setter.XYZMS() + tc_xyzms := struct {Srid uint32; Xyzm geom.PointZM}{tc.point_srid, geom.PointZM{tc.point_xyzm[0], tc.point_xyzm[1], tc.point_xyzm[2], tc.point_xyzm[3]}} + if !reflect.DeepEqual(tc_xyzms, xyzms) { + t.Errorf("XYZS, expected %v, got %v", tc_xyzms, xyzms) + } + } + } + tests := []tcase{ + { + point_srid: 4326, + point_xyzm: geom.PointZM{10, 20, 30, 1000}, + setter: &geom.PointZMS{4326, geom.PointZM{15, 20, 30, 1000}}, + expected: &geom.PointZMS{4326, geom.PointZM{10, 20, 30, 1000}}, + }, + { + setter: (*geom.PointZMS)(nil), + err: geom.ErrNilPointZMS, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointZMS(t *testing.T) { + fn := func(pt geom.PointZMS) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xyzm", func(t *testing.T) { + xyzm := pt.XYZM() + exp_xyzm := pt.Xyzm + if xyzm != exp_xyzm { + t.Errorf("xyzm, expected %v got %v", exp_xyzm, xyzm) + } + }) + t.Run("s", func(t *testing.T) { + s := pt.S() + exp_s := pt.Srid + if s != exp_s { + t.Errorf("srid, expected %v got %v", exp_s, s) + } + }) + t.Run("xyzms", func(t *testing.T) { + xyzms := pt.XYZMS() + exp_xyzms := pt + if xyzms != exp_xyzms { + t.Errorf("xyzms, expected %v got %v", exp_xyzms, xyzms) + } + }) + } + } + tests := []geom.PointZMS{ + {4326, geom.PointZM{0, 1, 2, 1000}}, {4326, geom.PointZM{2, 2, 3, 1000}}, {4326, geom.PointZM{1, 2, 3, 1000}}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/pointzs.go b/pointzs.go new file mode 100644 index 00000000..f4e227fc --- /dev/null +++ b/pointzs.go @@ -0,0 +1,39 @@ +package geom + +import ( + "errors" +) + +// ErrNilPointZS is thrown when a point is null but shouldn't be +var ErrNilPointZS = errors.New("geom: nil PointZS") + +// Point describes a simple 3D point with SRID +type PointZS struct { + Srid uint32 + Xyz PointZ } + +// XYZS returns the struct itself +func (p PointZS) XYZS() struct {Srid uint32; Xyz PointZ} { + return p +} + +// XYZ returns 3D point +func (p PointZS) XYZ() PointZ { + return p.Xyz +} + +// S returns the srid as uint32 +func (p PointZS) S() uint32 { + return p.Srid +} + +// SetXYZS sets the XYZ coordinates and the SRID +func (p *PointZS) SetXYZS(srid uint32, xyz PointZ) (err error) { + if p == nil { + return ErrNilPointZS + } + + p.Srid = srid + p.Xyz = xyz + return +} diff --git a/pointzs_test.go b/pointzs_test.go new file mode 100644 index 00000000..cd4fefa2 --- /dev/null +++ b/pointzs_test.go @@ -0,0 +1,98 @@ +package geom_test + +import ( + "fmt" + "reflect" + "strconv" + "testing" + + "github.com/go-spatial/geom" +) + +func TestPointZSSetter(t *testing.T) { + type tcase struct { + point_srid uint32 + point_xyz geom.PointZ + setter geom.PointZSSetter + expected geom.PointZSSetter + err error + } + + fn := func(tc tcase) func(*testing.T) { + return func(t *testing.T) { + err := tc.setter.SetXYZS(tc.point_srid, tc.point_xyz) + if tc.err == nil && err != nil { + t.Errorf("error, expected nil got %v", err) + return + } + if tc.err != nil { + if tc.err.Error() != err.Error() { + t.Errorf("error, expected %v got %v", tc.err, err) + } + return + } + + // compare the results + if !reflect.DeepEqual(tc.expected, tc.setter) { + t.Errorf("setter, expected %v got %v", tc.expected, tc.setter) + return + } + xyzs := tc.setter.XYZS() + tc_xyzs := struct {Srid uint32; Xyz geom.PointZ}{tc.point_srid, geom.PointZ{tc.point_xyz[0], tc.point_xyz[1], tc.point_xyz[2]}} + if !reflect.DeepEqual(tc_xyzs, xyzs) { + t.Errorf("XYZS, expected %v, got %v", tc_xyzs, xyzs) + } + } + } + tests := []tcase{ + { + point_srid: 4326, + point_xyz: geom.PointZ{10, 20, 30}, + setter: &geom.PointZS{4326, geom.PointZ{15, 20, 30}}, + expected: &geom.PointZS{4326, geom.PointZ{10, 20, 30}}, + }, + { + setter: (*geom.PointZS)(nil), + err: geom.ErrNilPointZS, + }, + } + + for i, tc := range tests { + t.Run(strconv.FormatInt(int64(i), 10), fn(tc)) + } +} + +func TestPointZS(t *testing.T) { + fn := func(pt geom.PointZS) (string, func(*testing.T)) { + return fmt.Sprintf("%v", pt), + func(t *testing.T) { + t.Run("xyz", func(t *testing.T) { + xyz := pt.XYZ() + exp_xyz := pt.Xyz + if xyz != exp_xyz { + t.Errorf("xyz, expected %v got %v", exp_xyz, xyz) + } + }) + t.Run("s", func(t *testing.T) { + s := pt.S() + exp_s := pt.Srid + if s != exp_s { + t.Errorf("srid, expected %v got %v", exp_s, s) + } + }) + t.Run("xyzs", func(t *testing.T) { + xyzs := pt.XYZS() + exp_xyzs := pt + if xyzs != exp_xyzs { + t.Errorf("xyzs, expected %v got %v", exp_xyzs, xyzs) + } + }) + } + } + tests := []geom.PointZS{ + {4326, geom.PointZ{0, 1, 2}}, {4326, geom.PointZ{2, 2, 3}}, {4326, geom.PointZ{1, 2, 3}}, + } + for _, pt := range tests { + t.Run(fn(pt)) + } +} diff --git a/set_geom.go b/set_geom.go index 4fa1cdad..db179a26 100644 --- a/set_geom.go +++ b/set_geom.go @@ -10,6 +10,48 @@ type PointSetter interface { SetXY([2]float64) error } +// PointZSetter is a mutable PointZer +type PointZSetter interface { + PointZer + SetXYZ([3]float64) error +} + +// PointMSetter is a mutable PointMer +type PointMSetter interface { + PointMer + SetXYM([3]float64) error +} + +// PointZMSetter is a mutable PointZMer +type PointZMSetter interface { + PointZMer + SetXYZM([4]float64) error +} + +// PointSSetter is a mutable PointSer +type PointSSetter interface { + PointSer + SetXYS(srid uint32, xy Point) error +} + +// PointZSSetter is a mutable PointZSer +type PointZSSetter interface { + PointZSer + SetXYZS(srid uint32, xyz PointZ) error +} + +// PointMSSetter is a mutable PointMer +type PointMSSetter interface { + PointMSer + SetXYMS(srid uint32, xym PointM) error +} + +// PointZMSSetter is a mutable PointZMer +type PointZMSSetter interface { + PointZMSer + SetXYZMS(srid uint32, xyzm PointZM) error +} + // MultiPointSetter is a mutable MultiPointer. type MultiPointSetter interface { MultiPointer