Skip to content
Open
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
17 changes: 12 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
module github.com/Willyham/hashfill

go 1.12
go 1.20

require (
github.com/mmcloughlin/geohash v0.9.0
github.com/paulsmith/gogeos v0.1.2
github.com/stretchr/testify v1.3.0
github.com/twpayne/go-geom v1.0.5
github.com/engelsjk/polygol v0.0.3
github.com/mmcloughlin/geohash v0.10.0
github.com/stretchr/testify v1.8.4
github.com/twpayne/go-geom v1.5.3
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/engelsjk/splay-tree v0.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
53 changes: 17 additions & 36 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,40 +1,21 @@
github.com/DATA-DOG/go-sqlmock v1.3.2/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/alecthomas/assert/v2 v2.4.0 h1:/ZiZ0NnriAWPYYO+4eOjgzNELrFQLaHNr92mHSHFj9U=
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mmcloughlin/geohash v0.9.0 h1:FihR004p/aE1Sju6gcVq5OLDqGcMnpBY+8moBqIsVOs=
github.com/mmcloughlin/geohash v0.9.0/go.mod h1:oNZxQo5yWJh0eMQEP/8hwQuVx9Z9tjwFUqcTB1SmG0c=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/paulsmith/gogeos v0.1.2 h1:PASLPRO7sjXZLERnQ98EKqY4l9zjQW+irDD5FFRms8I=
github.com/paulsmith/gogeos v0.1.2/go.mod h1:7GN4vaVO09zFKjDPYsAoeA1j+8GuSicOlnbKo+A0AZM=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/engelsjk/polygol v0.0.3 h1:EG+yyPd/sPLNYUQ1KzlBz6OHfa0+EgAHQYLwsSgxF4k=
github.com/engelsjk/polygol v0.0.3/go.mod h1:I11mpyToT6JcjiEYf7TtRjX326/rLxSNfT5MI1W6cy4=
github.com/engelsjk/splay-tree v0.0.1 h1:9jWYhlLxSTubl8+Lgk/4mSe8iMQITwbRu+eVMkNTsUM=
github.com/engelsjk/splay-tree v0.0.1/go.mod h1:5TalkXJDy1DjM0Dj1g4WcZ5bn1Y3YwUnPYH+XWtAXFY=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/mmcloughlin/geohash v0.10.0 h1:9w1HchfDfdeLc+jFEf/04D27KP7E2QmpDu52wPbJWRE=
github.com/mmcloughlin/geohash v0.10.0/go.mod h1:oNZxQo5yWJh0eMQEP/8hwQuVx9Z9tjwFUqcTB1SmG0c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/twpayne/go-geom v1.0.5 h1:XZBfc3Wx0dj4p17ZfmzqxnU9fTTa3pY4YG5RngKsVNI=
github.com/twpayne/go-geom v1.0.5/go.mod h1:gO3i8BeAvZuihwwXcw8dIOWXebCzTmy3uvXj9dZG2RA=
github.com/twpayne/go-kml v1.0.0/go.mod h1:LlvLIQSfMqYk2O7Nx8vYAbSLv4K9rjMvLlEdUKWdjq0=
github.com/twpayne/go-polyline v1.0.0/go.mod h1:ICh24bcLYBX8CknfvNPKqoTbe+eg+MX1NPyJmSBo7pU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twpayne/go-geom v1.5.3 h1:UdH93XzTwpwPiAV38DJ74yg+9/YV9/WCGbKN+NmSvVA=
github.com/twpayne/go-geom v1.5.3/go.mod h1:scDv/u90MVD6K+/7cA44kQt9fD6M/n+VuLddERxWYR8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
104 changes: 62 additions & 42 deletions predicates.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package hashfill

import (
"github.com/engelsjk/polygol"
"github.com/mmcloughlin/geohash"
"github.com/paulsmith/gogeos/geos"
geom "github.com/twpayne/go-geom"
)

Expand Down Expand Up @@ -30,58 +30,78 @@ func (f intersectsFunc) Intersects(p *geom.Polygon, hash string) (bool, error) {
return f(p, hash)
}

// Intersects tests if the geofence contains the hash by doing a geos intersection.
// Intersects tests if the geofence contains the hash.
var Intersects = intersectsFunc(func(geofence *geom.Polygon, hash string) (bool, error) {
hashGeo := hashToGeometry(hash)
fence := polygonToGeometry(geofence)
return fence.Intersects(hashGeo)
hashGeom := hashToGeom(hash)
out, err := polygol.Intersection(hashGeom, g2p(geofence))
if err != nil {
return false, err
}
if len(out) == 0 {
return false, nil
} else {
return true, nil
}
})

// Contains tests if the geofence contains the hash by doing a geos contains.
// Contains tests if the geofence contains the hash.
var Contains = containsFunc(func(geofence *geom.Polygon, hash string) (bool, error) {
hashGeo := hashToGeometry(hash)
fence := polygonToGeometry(geofence)
return fence.Contains(hashGeo)
})

func geomToGeosCoord(coord geom.Coord) geos.Coord {
return geos.Coord{
X: coord.X(),
Y: coord.Y(),
hashGeom := hashToGeom(hash)
fenceGeom := g2p(geofence)
out, err := polygol.Intersection(fenceGeom, hashGeom)
if err != nil {
return false, err
}
}

func geomToGeosCoords(coords []geom.Coord) []geos.Coord {
out := make([]geos.Coord, len(coords))
for i := 0; i < len(coords); i++ {
out[i] = geomToGeosCoord(coords[i])
if len(out) == 0 {
return false, nil
} else {
o, err := polygol.XOR(hashGeom, out)
if err != nil {
return false, err
}
if len(o) == 0 {
return true, err
}
return false, nil
}
return out
}
})

// hashToGeometry converts a a geohash to a geos polygon by taking its bounding box.
func hashToGeometry(hash string) *geos.Geometry {
func hashToGeom(hash string) polygol.Geom {
bounds := geohash.BoundingBox(hash)
return geos.Must(geos.NewPolygon([]geos.Coord{
geos.NewCoord(bounds.MinLng, bounds.MinLat),
geos.NewCoord(bounds.MinLng, bounds.MaxLat),
geos.NewCoord(bounds.MaxLng, bounds.MaxLat),
geos.NewCoord(bounds.MaxLng, bounds.MinLat),
geos.NewCoord(bounds.MinLng, bounds.MinLat),
}))
return polygol.Geom{{{
{bounds.MinLng, bounds.MinLat},
{bounds.MinLng, bounds.MaxLat},
{bounds.MaxLng, bounds.MaxLat},
{bounds.MaxLng, bounds.MinLat},
{bounds.MinLng, bounds.MinLat},
}}}
}

func polygonToGeometry(geofence *geom.Polygon) *geos.Geometry {
// Convert the outer shell to geos format.
shell := geofence.LinearRing(0).Coords()
shellGeos := geomToGeosCoords(shell)
func g2p(g geom.T) [][][][]float64 {

var coords [][][]geom.Coord

switch v := g.(type) {
case *geom.Polygon:
coords = [][][]geom.Coord{v.Coords()}
case *geom.MultiPolygon:
coords = v.Coords()
}

// Convert each hole to geos format.
numHoles := geofence.NumLinearRings() - 1
holes := make([][]geos.Coord, numHoles)
for i := 0; i < numHoles; i++ {
holes[i] = geomToGeosCoords(geofence.LinearRing(i).Coords())
p := make([][][][]float64, len(coords))

for i := range coords {
p[i] = make([][][]float64, len(coords[i]))
for j := range coords[i] {
p[i][j] = make([][]float64, len(coords[i][j]))
for k := range coords[i][j] {
coord := coords[i][j][k]
pt := make([]float64, 2)
pt[0], pt[1] = coord.X(), coord.Y()
p[i][j][k] = pt
}
}
}

return geos.Must(geos.NewPolygon(shellGeos, holes...))
return p
}