import View from 'ol/View.js';
import OSM from 'ol/source/OSM.js';
import TileLayer from 'ol/layer/Tile.js';
-import { fromLonLat, getPointResolution } from 'ol/proj.js';
+import { fromLonLat, getPointResolution, transformExtent } from 'ol/proj.js';
import VectorSource from 'ol/source/Vector.js';
import Feature from 'ol/Feature.js';
import { Point } from 'ol/geom.js';
import MapPart from './MapPart.js';
+import { bbox } from 'ol/loadingstrategy';
+
/** OpenLayers implementation of MapPart. */
export default class OpenLayersMapPart extends MapPart {
/** The OpenLayers Map. */
// transition: 0,
// }),
],
- // view: new View({
- // center: [0, 0],
- // zoom: 2,
- // }),
+ // view: new View({
+ // projection: 'EPSG:4326',
+ // center: [0, 0],
+ // zoom: 2,
+ // }),
target: this.getMapName(),
});
+ //this.#map.getView().set('projection', 'EPSG:4326', true);
}
/* GEOGRAPHICAL METHODS */
});
vectorLayer.setStyle(olStyleFunction);
}
-}
\ No newline at end of file
+
+ //
+ // BBOX
+ //
+ applyBboxStrategy(layerName) {
+ const layer = this.getLayerByName(layerName);
+ const vectorSource = layer.getSource();
+ const baseUrl = vectorSource.getUrl();
+ if (typeof baseUrl === 'function')
+ throw new Error('A strategy was already applied to layer ' + layerName);
+
+ const loadFunction = function(extent, resolution, projection, success, failure) {
+
+ const proj = projection.getCode();
+ var bbox = transformExtent(extent, proj, 'EPSG:4326');
+
+ const url = baseUrl + '&' +
+ 'bbox=' + bbox.join(',') ;
+// 'bbox=' + extent.join(',') + ',' + proj;
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', url);
+ const onError = function() {
+ vectorSource.removeLoadedExtent(extent);
+ failure();
+ }
+ xhr.onerror = onError;
+ xhr.onload = function() {
+ if (xhr.status == 200) {
+ const features = vectorSource.getFormat().readFeatures(xhr.responseText);
+ vectorSource.addFeatures(features);
+ success(features);
+ } else {
+ onError();
+ }
+ }
+ xhr.send();
+ }
+
+ vectorSource.setLoader(loadFunction);
+ }
+}
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
import GeoJSON from 'ol/format/GeoJSON.js';
+import {bbox} from 'ol/loadingstrategy';
// PSEUDO PACKAGE
if (typeof globalThis.argeo === 'undefined')
globalThis.argeo.tp.ol.VectorSource = VectorSource;
globalThis.argeo.tp.ol.VectorLayer = VectorLayer;
globalThis.argeo.tp.ol.GeoJSON = GeoJSON;
+globalThis.argeo.tp.ol.bbox = bbox;
"use strict";
return jsObject.newJs();
else
return jsObject.getJsReference();
+ } else if (o instanceof JsReference jsReference) {
+ return jsReference.get();
} else
return '\'' + o.toString() + '\'';
}
--- /dev/null
+package org.argeo.app.ux.js;
+
+import java.util.function.Supplier;
+
+/** Plain JS reference, to be directly serialised. */
+public class JsReference implements Supplier<String> {
+ private final String reference;
+
+ public JsReference(String reference) {
+ this.reference = reference;
+ }
+
+ public String get() {
+ return reference;
+ }
+
+}
} catch (IOException e) {
throw new UncheckedIOException("Cannot add geometry " + name + " to " + c, e);
}
- updateBoundingBox(c);
+ // updateBoundingBox(c);
}
public static <T extends Geometry> T getGeometry(Content c, QNamed name, Class<T> clss) {
if (c.hasContentClass(EntityType.geopoint)) {
Double lat = c.get(WGS84PosName.lat, Double.class).orElseThrow();
Double lon = c.get(WGS84PosName.lon, Double.class).orElseThrow();
- Double alt = c.get(WGS84PosName.alt, Double.class).orElse(null);
- return JTS.GEOMETRY_FACTORY_WGS84
- .createPoint(alt != null ? new Coordinate(lat, lon, alt) : new Coordinate(lat, lon));
+ return JTS.GEOMETRY_FACTORY_WGS84.createPoint(new Coordinate(lat, lon));
+// Double alt = c.get(WGS84PosName.alt, Double.class).orElse(null);
+// return JTS.GEOMETRY_FACTORY_WGS84
+// .createPoint(alt != null ? new Coordinate(lat, lon, alt) : new Coordinate(lat, lon));
}
return null;
}
entity.put(EntityName.maxLon, bbox.getMaxY());
}
+ public static void updateBoundingBox(Content entity, QName prop) {
+ Geometry geom = getGeometry(entity, prop, Geometry.class);
+ if (geom == null)
+ return;
+ entity.addContentClasses(EntityType.geobounded.qName());
+
+ Envelope bbox = geom.getEnvelopeInternal();
+ entity.put(EntityName.minLat, bbox.getMinX());
+ entity.put(EntityName.minLon, bbox.getMinY());
+ entity.put(EntityName.maxLat, bbox.getMaxX());
+ entity.put(EntityName.maxLon, bbox.getMaxY());
+ }
+
/** singleton */
private GeoEntityUtils() {
}
import org.argeo.cms.http.HttpHeader;
import org.argeo.cms.http.server.HttpServerUtils;
import org.argeo.cms.util.LangUtils;
-import org.argeo.cms.util.StreamUtils;
import org.geotools.data.DataUtilities;
import org.geotools.data.geojson.GeoJSONWriter;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
+import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.wfs.GML;
import org.geotools.wfs.GML.Version;
import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.Name;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
final static String OUTPUT_FORMAT = "outputFormat";
final static String TYPE_NAMES = "typeNames";
final static String CQL_FILTER = "cql_filter";
+ final static String BBOX = "bbox";
private final Map<QName, FeatureAdapter> featureAdapters = new HashMap<>();
ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange);
// Content content = session.get(path);
+ // PARAMETERS
Map<String, List<String>> parameters = HttpServerUtils.parseParameters(exchange);
String cql = getKvpParameter(parameters, CQL_FILTER);
String typeNamesStr = getKvpParameter(parameters, TYPE_NAMES);
if (outputFormat == null) {
outputFormat = "application/json";
}
+ String bboxStr = getKvpParameter(parameters, BBOX);
+ log.debug(bboxStr);
+ final Envelope bbox;
+ if (bboxStr != null) {
+ String srs;
+ String[] arr = bboxStr.split(",");
+ // TODO check SRS and convert to WGS84
+ double minLat = Double.parseDouble(arr[0]);
+ double minLon = Double.parseDouble(arr[1]);
+ double maxLat = Double.parseDouble(arr[2]);
+ double maxLon = Double.parseDouble(arr[3]);
+ if (arr.length == 5) {
+ srs = arr[4];
+ } else {
+ srs = null;
+ }
+
+ if (srs != null) {
+ try {
+ CoordinateReferenceSystem sourceCRS = CRS.decode(srs);
+ CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326");
+ MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
+ bbox = org.geotools.geometry.jts.JTS.transform(
+ new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)), transform);
+ } catch (FactoryException | TransformException e) {
+ throw new IllegalArgumentException("Cannot convert bounding box", e);
+ // bbox = null;
+ }
+ } else {
+ bbox = new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon));
+ }
+ } else {
+ bbox = null;
+ }
switch (outputFormat) {
case "application/json" -> {
if (typeNames.size() > 1)
throw new UnsupportedOperationException("Only one type name is currently supported");
+ // QUERY
Stream<Content> res = session.search((search) -> {
if (cql != null) {
CqlUtils.filter(search.from(path), cql);
} else {
search.from(path);
}
-// search.getWhere().any((f) -> {
for (QName typeName : typeNames) {
FeatureAdapter featureAdapter = featureAdapters.get(typeName);
if (featureAdapter == null)
// f.isContentClass(typeName);
featureAdapter.addConstraintsForFeature((AndFilter) search.getWhere(), typeName);
}
-// });
+
+ if (bbox != null) {
+ search.getWhere().gte(EntityName.minLat, bbox.getMinX());
+ search.getWhere().gte(EntityName.minLon, bbox.getMinY());
+ search.getWhere().lte(EntityName.maxLat, bbox.getMaxX());
+ search.getWhere().lte(EntityName.maxLon, bbox.getMaxY());
+ }
});
exchange.sendResponseHeaders(200, 0);
if (featureId != null)
generator.write("id", featureId);
-// GeoJson.writeBBox(generator, defaultGeometry);
+ GeoJson.writeBBox(generator, defaultGeometry);
generator.writeStartObject(GeoJson.GEOMETRY);
GeoJson.writeGeometry(generator, defaultGeometry);
generator.writeEnd();// geometry object
executeMethod(getMethodName(), layerName, styledLayerName);
}
+ public void applyBboxStrategy(String layerName) {
+ executeMethod(getMethodName(), layerName);
+ }
+
public Layer getLayer(String name) {
// TODO deal with not found
String reference = "getLayerByName('" + name + "')";
package org.argeo.app.ol;
+import org.argeo.app.ux.js.JsReference;
+
public class VectorSource extends Source {
public VectorSource(Object... args) {
}
public VectorSource(String url, FeatureFormat format) {
- setUrl(url);
+ this(url, format, false);
+ }
+
+ public VectorSource(String url, FeatureFormat format, boolean bboxStrategy) {
setFormat(format);
+ if (bboxStrategy) {
+ setUrl(url);
+ getNewOptions().put("strategy", new JsReference(getJsPackage() + ".bbox"));
+ } else {
+ setUrl(url);
+ }
}
public void setUrl(String url) {
else
executeMethod(getMethodName(), zoom);
}
+
+// public void setProjection(String projection) {
+// doSetValue(getMethodName(), "projection", projection);
+// }
}