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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>
<version>1.20.1</version>
<version>1.21.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.jsr107.EhcacheCachingProvider;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
Expand All @@ -33,6 +34,7 @@ public class CacheConfig {
public static final String ALL_PARAM_VOCABS = "parameter-vocabs";
public static final String ELASTIC_SEARCH_UUID_ONLY = "elastic-search-uuid-only";
public static final String STRING_TO_GEOMETRY = "string-to-geometry";
public static final String STRING_TO_PREPARE_GEOMETRY = "string-to-prepared-geometry";

@Bean
public CacheNoLandGeometry createCacheNoLandGeometry() {
Expand Down Expand Up @@ -89,6 +91,12 @@ public JCacheCacheManager cacheManager() throws IOException {
ResourcePoolsBuilder.heap(20000)
).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(24)))
)
.withCache(STRING_TO_PREPARE_GEOMETRY,
CacheConfigurationBuilder.newCacheConfigurationBuilder(
Map.class, PreparedGeometry.class,
ResourcePoolsBuilder.heap(20000)
).withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(24)))
)
.withCache(GET_CAPABILITIES_WMS_LAYERS,
CacheConfigurationBuilder.newCacheConfigurationBuilder(
Object.class, Object.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import au.org.aodn.ogcapi.features.model.*;
import au.org.aodn.ogcapi.server.core.model.CitationModel;
import au.org.aodn.ogcapi.server.core.model.AssetModel;
import au.org.aodn.ogcapi.server.core.model.ExtendedCollection;
import au.org.aodn.ogcapi.server.core.model.ExtendedLink;
import au.org.aodn.ogcapi.server.core.model.StacCollectionModel;
Expand All @@ -15,6 +14,7 @@
import lombok.Getter;
import lombok.Setter;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.opengis.filter.Filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -156,11 +156,11 @@ default <D extends StacCollectionModel> Collection getCollection(D m, Filter fil
Map<?, ?> noLand = m.getSummaries().getGeometryNoLand();
if (noLand != null) {
// Geometry from elastic search always store in EPSG4326
GeometryUtils.readGeometry(noLand)
GeometryUtils.readPreparedGeometry(noLand)
.ifPresent(input -> {
// filter have values if user CQL contains BBox, hence our centroid point needs to be
// the noland geometry intersect with BBox and centroid point will be within the BBox
Geometry g = filter != null ? (Geometry) filter.accept(visitor, input) : input;
Geometry g = filter != null ? ((PreparedGeometry) filter.accept(visitor, input)).getGeometry() : input.getGeometry();
collection.getProperties().put(
CollectionProperty.centroid,
createCentroid(g)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.geotools.filter.visitor.DefaultFilterVisitor;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.opengis.filter.spatial.*;

@Slf4j
Expand Down Expand Up @@ -116,14 +117,14 @@ public Object visit(Beyond filter, Object data) {
@Override
public Object visit(BBOX filter, Object data) {
if(filter instanceof BBoxImpl<?> impl) {
if(impl.getGeometry() != null && (data instanceof Polygon || data instanceof GeometryCollection)) {
Geometry input = (Geometry) data;
if(impl.getGeometry() != null && (data instanceof Polygon || data instanceof PreparedGeometry)) {
PreparedGeometry input = (PreparedGeometry) data;
// buffer is expensive
try {
return impl.getGeometry().intersection(input);
return input.getGeometry().intersection(impl.getGeometry());
}
catch(Exception e) {
return impl.getGeometry().intersection(input.buffer(0.0));
return impl.getGeometry().intersection(input.getGeometry().buffer(0.0));
}
//return impl.getGeometry().intersection(input.buffer(0.0));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
Expand All @@ -29,6 +31,7 @@
import java.util.concurrent.*;

import static au.org.aodn.ogcapi.server.core.configuration.CacheConfig.STRING_TO_GEOMETRY;
import static au.org.aodn.ogcapi.server.core.configuration.CacheConfig.STRING_TO_PREPARE_GEOMETRY;

public class GeometryUtils {

Expand Down Expand Up @@ -211,7 +214,26 @@ public static String convertToGeoJson(LiteralExpressionImpl literalExpression, C
return r;
}
}

/**
* Many code require static access to this function, hence we will init it somewhere as bean and then
* set it to the static instance for sharing
*
* @param input - A geometry text input
* @return - The converted geometry
*/
public static Optional<PreparedGeometry> readPreparedGeometry(Object input) {
return self.readCachedPreparedGeometry(input);
}
/**
* Please use this function as it contains the parser with enough decimal to make it work.
*
* @param input - A Json of GeoJson
* @return - A prepared geometry for fast intersect calculation
*/
@Cacheable(STRING_TO_PREPARE_GEOMETRY)
public Optional<PreparedGeometry> readCachedPreparedGeometry(Object input) {
return self.readCachedGeometry(input).map(PreparedGeometryFactory::prepare);
}
/**
* Many code require static access to this function, hence we will init it somewhere as bean and then
* set it to the static instance for sharing
Expand All @@ -222,7 +244,6 @@ public static String convertToGeoJson(LiteralExpressionImpl literalExpression, C
public static Optional<Geometry> readGeometry(Object input) {
return self.readCachedGeometry(input);
}

/**
* Please use this function as it contains the parser with enough decimal to make it work.
*
Expand All @@ -244,7 +265,6 @@ public Optional<Geometry> readCachedGeometry(Object input) {
}
return Optional.empty();
}

/**
* Normalize a polygon by adjusting longitudes to the range [-180, 180], and return both parts as a GeometryCollection.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.prep.PreparedGeometry;
import org.locationtech.jts.io.ParseException;
import org.opengis.filter.Filter;
import org.opengis.referencing.FactoryException;
Expand Down Expand Up @@ -74,7 +74,7 @@ public void verifyBBoxWorks1() throws CQLException, IOException, FactoryExceptio
StacCollectionModel model = mapper.readValue(json, StacCollectionModel.class);

Filter filter = CompilerUtil.parseFilter(Language.CQL, param.getFilter(), factory);
Optional<Geometry> geo = GeometryUtils.readGeometry(model.getSummaries().getGeometryNoLand());
Optional<PreparedGeometry> geo = GeometryUtils.readPreparedGeometry(model.getSummaries().getGeometryNoLand());

Assertions.assertTrue(geo.isPresent(), "Parse no land correct");
GeometryVisitor visitor = GeometryVisitor.builder()
Expand All @@ -83,7 +83,7 @@ public void verifyBBoxWorks1() throws CQLException, IOException, FactoryExceptio
// return value are geo applied the CQL, and in this case only INTERSECTS
Geometry g = (Geometry)filter.accept(visitor, geo.get());
Assertions.assertTrue(expected.isPresent(), "Expected parse correct");
Assertions.assertEquals(g, expected.get(), "They are equals");
Assertions.assertEquals(g.getGeometryN(0), expected.get(), "They are equals");
}
/**
* Test almost the same as the verifyIntersectionWorks2, since verifyIntersectionWorks1 create a polygon same as box
Expand All @@ -104,7 +104,7 @@ public void verifyBBoxWorks2() throws CQLException, IOException {
"score>=1.5 AND BBOX(geometry,-203.16603491348164,-60.248194404495756,-86.85117538227594,15.902738674628525)",
factory);

Optional<Geometry> geo = GeometryUtils.readGeometry(model.getSummaries().getGeometryNoLand());
Optional<PreparedGeometry> geo = GeometryUtils.readPreparedGeometry(model.getSummaries().getGeometryNoLand());

Assertions.assertTrue(geo.isPresent(), "Parse no land correct");
GeometryVisitor visitor = GeometryVisitor.builder()
Expand All @@ -114,7 +114,7 @@ public void verifyBBoxWorks2() throws CQLException, IOException {
Geometry g = (Geometry)filter.accept(visitor, geo.get());

Assertions.assertFalse(g.isEmpty());
Assertions.assertInstanceOf(Polygon.class, g);
Assertions.assertInstanceOf(GeometryCollection.class, g);

Assertions.assertEquals(168.30090846621448, g.getCentroid().getX(), 0.0000001, "getX()");
Assertions.assertEquals(-33.95984804960966, g.getCentroid().getY(), 0.0000001, "getY()");
Expand All @@ -138,7 +138,7 @@ public void verifyBBoxWorks3() throws CQLException, IOException {
"score>=1.5 AND BBOX(geometry,-209.8851491167079,-45.44715475181477,-149.06483661670887,-5.632766095762394)",
factory);

Optional<Geometry> geo = GeometryUtils.readGeometry(model.getSummaries().getGeometryNoLand());
Optional<PreparedGeometry> geo = GeometryUtils.readPreparedGeometry(model.getSummaries().getGeometryNoLand());

Assertions.assertTrue(geo.isPresent(), "Parse no land correct");
GeometryVisitor visitor = GeometryVisitor.builder()
Expand All @@ -147,15 +147,15 @@ public void verifyBBoxWorks3() throws CQLException, IOException {
// return value are geo applied the CQL, and in this case only BBOX intersected
Geometry g = (Geometry)filter.accept(visitor, geo.get());

Assertions.assertInstanceOf(MultiPolygon.class, g);
Assertions.assertInstanceOf(GeometryCollection.class, g);

MultiPolygon mp = (MultiPolygon)g;
GeometryCollection mp = (GeometryCollection)g;
Assertions.assertEquals(2, mp.getNumGeometries(), "Geometries correct");

Assertions.assertEquals(-159.53241830835444, mp.getGeometryN(1).getCentroid().getX(), 0.0000001, "getX() for 0");
Assertions.assertEquals(-19.5, mp.getGeometryN(1).getCentroid().getY(), 0.0000001, "getY() for 0");
Assertions.assertEquals(-159.53241830835444, mp.getGeometryN(0).getCentroid().getX(), 0.0000001, "getX() for 0");
Assertions.assertEquals(-19.5, mp.getGeometryN(0).getCentroid().getY(), 0.0000001, "getY() for 0");

Assertions.assertEquals(151.62121416760516, mp.getGeometryN(0).getCentroid().getX(), 0.0000001, "getX() for 1");
Assertions.assertEquals(-18.000822620336752, mp.getGeometryN(0).getCentroid().getY(), 0.0000001, "getY() for 1");
Assertions.assertEquals(151.62121416760516, mp.getGeometryN(1).getCentroid().getX(), 0.0000001, "getX() for 1");
Assertions.assertEquals(-18.000822620336752, mp.getGeometryN(1).getCentroid().getY(), 0.0000001, "getY() for 1");
}
}
Loading