Skip to content

Commit

Permalink
Intersecting each feature in a compound site with spatial too expensive
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisala committed Jul 5, 2024
1 parent 5597b1a commit 54ac69e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 34 deletions.
18 changes: 8 additions & 10 deletions grails-app/services/au/org/ala/ecodata/SiteService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -864,20 +864,18 @@ class SiteService {
geographicFacets = spatialService.intersectPid(site.extent.geometry.pid as String, fid, fidsToLookup)
break
default:
Map geom
if (site.type == Site.TYPE_COMPOUND) {
geographicFacets = [:].withDefault{[]}
site.features.each { Map feature ->
Map featureIntersection = spatialService.intersectGeometry(feature.geometry, fidsToLookup)
featureIntersection.each{k, v ->
geographicFacets[k] += v
geographicFacets[k] = geographicFacets[k].unique()
}
}
geom = [
'type':'GeometryCollection',
'geometries': site.features.collect{it.geometry} ?: []

]
}
else {
Map geom = geometryAsGeoJson(site)
geographicFacets = spatialService.intersectGeometry(geom, fidsToLookup)
geom = geometryAsGeoJson(site)
}
geographicFacets = spatialService.intersectGeometry(geom, fidsToLookup)
break
}
geographicFacets ?: [:]
Expand Down
51 changes: 32 additions & 19 deletions grails-app/services/au/org/ala/ecodata/SpatialService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import groovy.json.JsonParserType
import groovy.json.JsonSlurper
import org.locationtech.jts.geom.Coordinate
import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.GeometryCollection
import org.locationtech.jts.geom.GeometryFactory
import org.locationtech.jts.io.WKTReader

Expand Down Expand Up @@ -76,12 +77,26 @@ class SpatialService {
}

start = end
filterOutObjectsInBoundary(result, geo)
end = System.currentTimeMillis()
log.info("Time taken to filter out objects in boundary: ${end-start}ms")

start = end
Map geographicFacets = convertResponsesToGeographicFacets(result)
Map geographicFacets
if (geo.geometryType == 'GeometryCollection') {
geographicFacets = [:].withDefault{[]}
GeometryCollection geometryCollection = (GeometryCollection)geo
for (int i=0; i<geometryCollection.numGeometries; i++) {

Map filtered = filterOutObjectsInBoundary(result, geometryCollection.getGeometryN(i))
start = end
Map geographicFacetsForGeometry = convertResponsesToGeographicFacets(filtered)
geographicFacetsForGeometry.each { k, v ->
geographicFacets[k] += v
geographicFacets[k] = geographicFacets[k].unique()
}
}
}
else {
Map filtered = filterOutObjectsInBoundary(result, geometryCollection.getGeometryN(i))
geographicFacets = convertResponsesToGeographicFacets(filtered)
}
end = System.currentTimeMillis()
log.info("Time taken to convert responses to geographic facets: ${end-start}ms")
geographicFacets
Expand Down Expand Up @@ -118,11 +133,11 @@ class SpatialService {

fillMissingDetailsOfObjects(result)
Map pidGeoJson = getGeoJsonForPidToMap(pid)
filterOutObjectsInBoundary(result, pidGeoJson)
result = filterOutObjectsInBoundary(result, pidGeoJson)
convertResponsesToGeographicFacets(result)
}

private void filterOutObjectsInBoundary(Map response, Map mainObjectGeoJson) {
private Map filterOutObjectsInBoundary(Map response, Map mainObjectGeoJson) {
Geometry mainGeometry = GeometryUtils.geoJsonMapToGeometry(mainObjectGeoJson)
filterOutObjectsInBoundary(response, mainGeometry)
}
Expand All @@ -134,15 +149,16 @@ class SpatialService {
* @param response - per layer/fid intersection values - [ "cl34" : [[pid: 123, name: "ACT", fid: "cl34", id: "ACT" ...], ...]
* @param mainObjectGeoJson - GeoJSON object that is used to intersect with layers.
*/
private void filterOutObjectsInBoundary(Map response, Geometry mainGeometry) {
private Map filterOutObjectsInBoundary(Map response, Geometry mainGeometry) {

if (!mainGeometry.isValid()) {
log.info("Main geometry invalid. Cannot check intersection is near boundary.")
return
return response
}

Map filteredResponse = [:]
response?.each { String fid, List<Map> matchingObjects ->
List pidToFilter = []
filteredResponse[fid] = []
//List pidToFilter = []
matchingObjects.each { Map obj ->
String boundaryPid = obj.pid
if (boundaryPid) {
Expand All @@ -157,8 +173,10 @@ class SpatialService {
if (boundaryGeometry.isValid()) {
// check if intersection should be ignored
start = end
if (!isValidGeometryIntersection(mainGeometry, boundaryGeometry)) {
pidToFilter.add(boundaryPid)
if (isValidGeometryIntersection(mainGeometry, boundaryGeometry)) {
filteredResponse[fid].add(obj)
}
else {
log.debug("Filtered out ${obj.fieldname}(${fid}) - ${obj.name}")
}

Expand All @@ -170,13 +188,8 @@ class SpatialService {
}
}
}

matchingObjects.removeAll {
def result = pidToFilter.contains(it.pid)
result ? log.debug("Filtered out ${it.pid} object") : null
result
}
}
filteredResponse
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/test/groovy/au/org/ala/ecodata/SiteServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ class SiteServiceSpec extends MongoSpec implements ServiceUnitTest<SiteService>
service.populateLocationMetadataForSite(site)
then:
2 * spatialServiceMock.intersectGeometry(_, _) >> ["electorate":["Bean"], "state":["ACT"]]
1 * spatialServiceMock.intersectGeometry({it.type == 'GeometryCollection'}, _) >> ["electorate":["Bean"], "state":["ACT"]]
site.extent.geometry.aream2 == 4938.9846950349165d
site.extent.geometry.electorate == ["Bean"]
site.extent.geometry.state == ["ACT"]
Expand Down
8 changes: 4 additions & 4 deletions src/test/groovy/au/org/ala/ecodata/SpatialServiceSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ class SpatialServiceSpec extends Specification implements ServiceUnitTest<Spatia
!boundaryIntersection
}

def "filterOutObjectsInBoundary should remove intesection below threshold" () {
def "filterOutObjectsInBoundary should remove intersection below threshold" () {
setup:
def response = ["cl22": [[name: "ACT", pid: "123", fid:"cl22"], [name: "NSW", pid: "456", fid:"cl22"]]]
def mainObject = [type: "Polygon", coordinates: [[[10, 0], [10, 10], [0, 10], [0, 0], [10, 0]]]]

when:
service.filterOutObjectsInBoundary(response, mainObject)
Map filteredResponse = service.filterOutObjectsInBoundary(response, mainObject)

then:
response["cl22"].size() == 1
response["cl22"][0].name == "ACT"
filteredResponse["cl22"].size() == 1
filteredResponse["cl22"][0].name == "ACT"
1 * webService.get("/ws/shapes/wkt/123") >> GeometryUtils.geoJsonMapToGeometry([type: "Polygon", coordinates: [[[5, 0], [5, 5], [0, 5], [0, 0], [5, 0]]]])
1 * webService.get("/ws/shapes/wkt/456") >> GeometryUtils.geoJsonMapToGeometry([type: "Polygon", coordinates: [[[11.5, 9.5], [11.5, 11.5], [9.5, 11.5], [9.5, 9.5], [11.5, 9.5]]]])
}
Expand Down

0 comments on commit 54ac69e

Please sign in to comment.