Refactor using method expressions, to avoid repeating code.

This commit is contained in:
Alex Roitman 2019-06-13 10:56:33 -07:00
parent 81f57ba6f6
commit 3ded4e3a44
1 changed files with 48 additions and 104 deletions

View File

@ -29,6 +29,7 @@ type areaExpression struct {
type children []*areaExpression type children []*areaExpression
// String representation, helpful in logging.
func (e *areaExpression) String() (res string) { func (e *areaExpression) String() (res string) {
if e.obj != nil { if e.obj != nil {
res = e.obj.String() res = e.obj.String()
@ -63,21 +64,25 @@ func (e *areaExpression) maybeNegate(val bool) bool {
} }
// Methods for testing an areaExpression against the spatial object // Methods for testing an areaExpression against the spatial object
func (e *areaExpression) rawIntersects(o geojson.Object) bool { func (e *areaExpression) testObject(
o geojson.Object,
objObjTest func(o1, o2 geojson.Object) bool,
exprObjTest func(ae *areaExpression, ob geojson.Object) bool,
) bool {
if e.obj != nil { if e.obj != nil {
return e.obj.Intersects(o) return objObjTest(e.obj, o)
} }
switch e.op { switch e.op {
case AND: case AND:
for _, c := range e.children { for _, c := range e.children {
if !c.Intersects(o) { if !exprObjTest(c, o) {
return false return false
} }
} }
return true return true
case OR: case OR:
for _, c := range e.children { for _, c := range e.children {
if c.Intersects(o) { if exprObjTest(c, o) {
return true return true
} }
} }
@ -86,50 +91,16 @@ func (e *areaExpression) rawIntersects(o geojson.Object) bool {
return false return false
} }
func (e *areaExpression) rawIntersects(o geojson.Object) bool {
return e.testObject(o, geojson.Object.Intersects, (*areaExpression).Intersects)
}
func (e *areaExpression) rawContains(o geojson.Object) bool { func (e *areaExpression) rawContains(o geojson.Object) bool {
if e.obj != nil { return e.testObject(o, geojson.Object.Contains, (*areaExpression).Contains)
return e.obj.Contains(o)
}
switch e.op {
case AND:
for _, c:= range e.children {
if !c.Contains(o) {
return false
}
}
return true
case OR:
for _, c:= range e.children {
if c.Contains(o) {
return true
}
}
return false
}
return false
} }
func (e *areaExpression) rawWithin(o geojson.Object) bool { func (e *areaExpression) rawWithin(o geojson.Object) bool {
if e.obj != nil { return e.testObject(o, geojson.Object.Within, (*areaExpression).Within)
return e.obj.Within(o)
}
switch e.op {
case AND:
for _, c:= range e.children {
if !c.Within(o) {
return false
}
}
return true
case OR:
for _, c:= range e.children {
if c.Within(o) {
return true
}
}
return false
}
return false
} }
func (e *areaExpression) Intersects(o geojson.Object) bool { func (e *areaExpression) Intersects(o geojson.Object) bool {
@ -145,26 +116,31 @@ func (e *areaExpression) Within(o geojson.Object) bool {
} }
// Methods for testing an areaExpression against another areaExpression // Methods for testing an areaExpression against another areaExpression
func (e *areaExpression) rawIntersectsExpr(oe *areaExpression) bool { func (e *areaExpression) testExpression(
oe *areaExpression,
exprObjTest func(ae *areaExpression, ob geojson.Object) bool,
rawExprExprTest func(ae1, ae2 *areaExpression) bool,
exprExprTest func(ae1, ae2 *areaExpression) bool,
) bool {
if oe.negate { if oe.negate {
e2 := &areaExpression{negate:!e.negate, obj:e.obj, op: e.op, children:e.children} e2 := &areaExpression{negate: !e.negate, obj: e.obj, op: e.op, children: e.children}
oe2 := &areaExpression{negate:false, obj:oe.obj, op:oe.op, children:oe.children} oe2 := &areaExpression{negate: false, obj: oe.obj, op: oe.op, children: oe.children}
return e2.IntersectsExpr(oe2) return exprExprTest(e2, oe2)
} }
if oe.obj != nil { if oe.obj != nil {
return e.rawIntersects(oe.obj) return exprObjTest(e, oe.obj)
} }
switch oe.op { switch oe.op {
case AND: case AND:
for _, c := range oe.children { for _, c := range oe.children {
if !e.rawIntersectsExpr(c) { if !rawExprExprTest(e, c) {
return false return false
} }
} }
return true return true
case OR: case OR:
for _, c := range oe.children { for _, c := range oe.children {
if e.rawIntersectsExpr(c) { if rawExprExprTest(e, c) {
return true return true
} }
} }
@ -173,60 +149,28 @@ func (e *areaExpression) rawIntersectsExpr(oe *areaExpression) bool {
return false return false
} }
func (e *areaExpression) rawIntersectsExpr(oe *areaExpression) bool {
return e.testExpression(
oe,
(*areaExpression).rawIntersects,
(*areaExpression).rawIntersectsExpr,
(*areaExpression).IntersectsExpr)
}
func (e *areaExpression) rawWithinExpr(oe *areaExpression) bool { func (e *areaExpression) rawWithinExpr(oe *areaExpression) bool {
if oe.negate { return e.testExpression(
e2 := &areaExpression{negate:!e.negate, obj:e.obj, op: e.op, children:e.children} oe,
oe2 := &areaExpression{negate:false, obj:oe.obj, op:oe.op, children:oe.children} (*areaExpression).rawWithin,
return e2.WithinExpr(oe2) (*areaExpression).rawWithinExpr,
} (*areaExpression).WithinExpr)
if oe.obj != nil {
return e.rawWithin(oe.obj)
}
switch oe.op {
case AND:
for _, c:= range oe.children {
if !e.rawWithinExpr(c) {
return false
}
}
return true
case OR:
for _, c:= range oe.children {
if e.rawWithinExpr(c) {
return true
}
}
return false
}
return false
} }
func (e *areaExpression) rawContainsExpr(oe *areaExpression) bool { func (e *areaExpression) rawContainsExpr(oe *areaExpression) bool {
if oe.negate { return e.testExpression(
e2 := &areaExpression{negate:!e.negate, obj:e.obj, op: e.op, children:e.children} oe,
oe2 := &areaExpression{negate:false, obj:oe.obj, op:oe.op, children:oe.children} (*areaExpression).rawContains,
return e2.ContainsExpr(oe2) (*areaExpression).rawContainsExpr,
} (*areaExpression).ContainsExpr)
if oe.obj != nil {
return e.rawContains(oe.obj)
}
switch oe.op {
case AND:
for _, c:= range oe.children {
if !e.rawContainsExpr(c) {
return false
}
}
return true
case OR:
for _, c:= range oe.children {
if e.rawContainsExpr(c) {
return true
}
}
return false
}
return false
} }
func (e *areaExpression) IntersectsExpr(oe *areaExpression) bool { func (e *areaExpression) IntersectsExpr(oe *areaExpression) bool {