Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions cmp/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"github.com/go-spatial/geom"
)

// Compare holds the tolerances for the comparsion functions
// Compare holds the tolerances for the comparison functions
type Compare struct {
// Tolerance is the epsilon value used in comparing floats with zero
Tolerance float64
// BitTolerance is the epsilon value for comaparing float bit-patterns.
// BitTolerance is the epsilon value for comparing float bit-patterns.
BitTolerance int64
}

Expand Down Expand Up @@ -81,7 +81,7 @@ func (cmp Compare) FloatSlice(f1, f2 []float64) bool {
return true
}

// Extent will check to see if the Extents's are the same.
// Extent will check to see if the Extents' are the same.
func (cmp Compare) Extent(extent1, extent2 [4]float64) bool {
return cmp.Float(extent1[0], extent2[0]) && cmp.Float(extent1[1], extent2[1]) &&
cmp.Float(extent1[2], extent2[2]) && cmp.Float(extent1[3], extent2[3])
Expand Down Expand Up @@ -275,7 +275,7 @@ func (cmp Compare) MultiPolygonerEqual(geo1, geo2 geom.MultiPolygoner) bool {
}

// CollectionerEqual will check if the two collections are equal based on length
// then if each geometry inside is equal. Therefor order matters.
// then if each geometry inside is equal. Therefore order matters.
func (cmp Compare) CollectionerEqual(col1, col2 geom.Collectioner) bool {
if colNil, col2Nil := col1 == NilCollection, col2 == NilCollection; colNil || col2Nil {
return colNil && col2Nil
Expand Down Expand Up @@ -328,3 +328,9 @@ func (cmp Compare) GeometryEqual(g1, g2 geom.Geometry) bool {
}
return false
}

// Empty functions
func (Compare) IsEmptyPoint(pt [2]float64) bool { return IsEmptyPoint(pt) }
func (Compare) IsEmptyPoints(pts [][2]float64) bool { return IsEmptyPoints(pts) }
func (Compare) IsEmptyLines(lns [][][2]float64) bool { return IsEmptyLines(lns) }
func (Compare) IsEmptyGeo(geo geom.Geometry) bool { return IsEmptyGeo(geo) }
87 changes: 37 additions & 50 deletions cmp/empty.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package cmp

import (
"fmt"
"reflect"

"github.com/go-spatial/geom"
)

Expand Down Expand Up @@ -31,124 +28,114 @@ func IsEmptyLines(lns [][][2]float64) bool {
return true
}

func IsNil(a interface{}) bool {
defer func() { recover() }()
return a == nil || reflect.ValueOf(a).IsNil()
}

func IsEmptyGeo(geo geom.Geometry) (isEmpty bool, err error) {
if IsNil(geo) {
return true, nil
func IsEmptyGeo(geo geom.Geometry) (isEmpty bool) {
if geom.IsNil(geo) {
return true
}

switch g := geo.(type) {
case [2]float64:
return IsEmptyPoint(g), nil
return IsEmptyPoint(g)

case geom.Point:
return IsEmptyPoint(g.XY()), nil
return IsEmptyPoint(g.XY())

case *geom.Point:
if g == nil {
return true, nil
return true
}

return IsEmptyPoint(g.XY()), nil
return IsEmptyPoint(g.XY())

case [][2]float64:
return IsEmptyPoints(g), nil
return IsEmptyPoints(g)

case geom.MultiPoint:
return IsEmptyPoints(g.Points()), nil
return IsEmptyPoints(g.Points())

case *geom.MultiPoint:
if g == nil {
return true, nil
return true
}

return IsEmptyPoints(g.Points()), nil
return IsEmptyPoints(g.Points())

case geom.LineString:
return IsEmptyPoints(g.Vertices()), nil
return IsEmptyPoints(g.Vertices())

case *geom.LineString:
if g == nil {
return true, nil
return true
}
return IsEmptyPoints(g.Vertices()), nil
return IsEmptyPoints(g.Vertices())

case geom.MultiLineString:
return IsEmptyLines(g.LineStrings()), nil
return IsEmptyLines(g.LineStrings())

case *geom.MultiLineString:
if g == nil {
return true, nil
return true
}
return IsEmptyLines(g.LineStrings()), nil

return IsEmptyLines(g.LineStrings())

case geom.Polygon:
return IsEmptyLines(g.LinearRings()), nil
return IsEmptyLines(g.LinearRings())

case *geom.Polygon:
if g == nil {
return true, nil
return true
}
return IsEmptyLines(g.LinearRings()), nil
return IsEmptyLines(g.LinearRings())

case geom.MultiPolygon:
for _, v := range g.Polygons() {
if !IsEmptyLines(v) {
return false, nil
return false
}
}

return true, nil
return true

case *geom.MultiPolygon:
if g == nil {
return true, nil
return true
}

for _, v := range g.Polygons() {
if !IsEmptyLines(v) {
return false, nil
return false
}
}

return true, nil
return true

case geom.Collection:
// if one item in the geometries list is not empty
// then the whole list is not empty
for _, v := range g.Geometries() {
isEmpty, err := IsEmptyGeo(v)
if err != nil {
return false, err
}
if !isEmpty {
return false, nil
if !IsEmptyGeo(v) {
return false
}
}

return true, nil
return true

case *geom.Collection:
if g == nil {
return true, nil
return true
}

for _, v := range g.Geometries() {
isEmpty, err := IsEmptyGeo(v)
if err != nil {
return false, err
}
if !isEmpty {
return false, nil
// if one item in the geometries list is not empty
// then the whole list is not empty
if !IsEmptyGeo(v) {
return false
}
}

return true, nil
return true

default:
return false, fmt.Errorf("unknown geometry %T", geo)
return false
}
}
58 changes: 24 additions & 34 deletions cmp/empty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,11 @@ func TestIsEmptyGeo(t *testing.T) {
type tcase struct {
geo geom.Geometry
isEmpty bool
err string
}

fn := func(tc tcase) func(t *testing.T) {
return func(t *testing.T) {
isEmpty, err := IsEmptyGeo(tc.geo)
if err != nil {
if err.Error() != tc.err {
t.Errorf("expected error %v, got %v", tc.err, err)
}
return
} else if tc.err != "" {
t.Errorf("expected error %v, got nil", tc.err)
return
}

isEmpty := IsEmptyGeo(tc.geo)
if isEmpty != tc.isEmpty {
t.Errorf("expected isEmpty %v, got %v", tc.isEmpty, isEmpty)
}
Expand All @@ -43,23 +32,23 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: true,
},
"nil point": {
geo: (*geom.Point)(nil),
geo: (*geom.Point)(nil),
isEmpty: true,
},
"non-nil point": {
geo: &geom.Point{},
geo: &geom.Point{},
isEmpty: false,
},
"multipoint": {
geo: geom.MultiPoint{geom.Point{}},
geo: geom.MultiPoint{geom.Point{}},
isEmpty: false,
},
"empty multipoint": {
geo: geom.MultiPoint{},
geo: geom.MultiPoint{},
isEmpty: true,
},
"empty multipoint 1": {
geo: geom.MultiPoint{geom.Point{math.NaN(), math.NaN()}},
geo: geom.MultiPoint{geom.Point{math.NaN(), math.NaN()}},
isEmpty: true,
},
"non empty multipoint": {
Expand All @@ -70,19 +59,19 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil multipoint": {
geo: (*geom.MultiPoint)(nil),
geo: (*geom.MultiPoint)(nil),
isEmpty: true,
},
"linestring": {
geo: geom.LineString{geom.Point{}},
geo: geom.LineString{geom.Point{}},
isEmpty: false,
},
"empty linestring": {
geo: geom.LineString{},
geo: geom.LineString{},
isEmpty: true,
},
"empty linestring 1": {
geo: geom.LineString{geom.Point{math.NaN(), math.NaN()}},
geo: geom.LineString{geom.Point{math.NaN(), math.NaN()}},
isEmpty: true,
},
"non empty linestring": {
Expand All @@ -93,7 +82,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil linestring": {
geo: (*geom.LineString)(nil),
geo: (*geom.LineString)(nil),
isEmpty: true,
},
"multilinestring": {
Expand All @@ -105,7 +94,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"empty multilinestring": {
geo: geom.MultiLineString{},
geo: geom.MultiLineString{},
isEmpty: true,
},
"empty multilinestring 1": {
Expand Down Expand Up @@ -155,7 +144,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil multilinestring": {
geo: (*geom.MultiLineString)(nil),
geo: (*geom.MultiLineString)(nil),
isEmpty: true,
},
"polygon": {
Expand All @@ -167,7 +156,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"empty polygon": {
geo: geom.Polygon{},
geo: geom.Polygon{},
isEmpty: true,
},
"empty polygon 1": {
Expand Down Expand Up @@ -217,7 +206,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil polygon": {
geo: (*geom.Polygon)(nil),
geo: (*geom.Polygon)(nil),
isEmpty: true,
},
"multipolygon": {
Expand All @@ -231,7 +220,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"empty multipolygon": {
geo: geom.MultiPolygon{},
geo: geom.MultiPolygon{},
isEmpty: true,
},
"empty multipolygon 1": {
Expand Down Expand Up @@ -338,7 +327,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil multipolygon": {
geo: (*geom.Polygon)(nil),
geo: (*geom.Polygon)(nil),
isEmpty: true,
},
"collection": {
Expand All @@ -348,7 +337,7 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"empty collection": {
geo: geom.Collection{},
geo: geom.Collection{},
isEmpty: true,
},
"empty collection 1": {
Expand Down Expand Up @@ -390,20 +379,21 @@ func TestIsEmptyGeo(t *testing.T) {
isEmpty: false,
},
"nil collection": {
geo: (*geom.Collection)(nil),
geo: (*geom.Collection)(nil),
isEmpty: true,
},
"type check": {
geo: int(0),
err: "unknown geometry int",
// unknown geometry is always return that false.
geo: 0,
isEmpty: false,
},
// non-nil pointers
"*point": {
geo: &geom.Point{},
geo: &geom.Point{},
isEmpty: false,
},
"empty *point": {
geo: &geom.Point{math.NaN(), math.NaN()},
geo: &geom.Point{math.NaN(), math.NaN()},
isEmpty: true,
},
"*multipoint": {
Expand Down
Loading