Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NGD Feature Collection Items results is completely random? #65

Open
wwwhatley opened this issue Jun 11, 2024 · 1 comment
Open

NGD Feature Collection Items results is completely random? #65

wwwhatley opened this issue Jun 11, 2024 · 1 comment

Comments

@wwwhatley
Copy link

I've tested this endpoint a bunch of different ways:

https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?key=${apiKey}&bbox=${extent.join(',')}&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/3857

The results are completely random? Attaching image from OS' code sandbox:

image

Not understanding why only some buildings are selected, it should be all within the bounding box, limited to 100, not sporadic.

@tmnnrs
Copy link

tmnnrs commented Jun 28, 2024

Hi @wwwhatley. The image you have provided demonstrates a vanilla JS call to the NGD Features API (there are a separate set of examples which use the osdatahub-js wrapper).

By default the API will only return a maximum of 100 features per request. In order to receive all the features within the bounding box you would need to send multiple requests (in a process referred to as "paging"). Each GeoJSON response will have a links property to define the self [current set of 100 features] + next [next set of 100 features] + prev [previous set of 100 features] URIs to help with this process.

NOTE: The prev URI will only appear from the second page of results. The next URI will not appear on the final page of results (to indicate that the full set of requests have been made).

The example shown demonstrates a single request for the first 100 features (without any paging).

The follow code snippet demonstrates how you could page through the requests (up to a limit of 5000 features):

const apiKey = 'INSERT_API_KEY_HERE';

const collectionId = 'bld-fts-buildingpart-1';

const maxFeatures = 5000;

// Initialize the map object.
const map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: `https://api.os.uk/maps/raster/v1/zxy/Light_3857/{z}/{x}/{y}.png?key=${apiKey}`
            })
        })
    ],
    target: 'map',
    view: new ol.View({
        projection: 'EPSG:3857',
        extent: ol.proj.transformExtent([ -10.76418, 49.528423, 1.9134116, 61.331151 ], 'EPSG:4326', 'EPSG:3857'),
        minZoom: 7,
        maxZoom: 20,
        center: ol.proj.fromLonLat([ -3.541809, 50.727589 ]),
        zoom: 18
    })
});

// Add a source + layer for rendering the GeoJSON features on the map.
const geojsonSource = new ol.source.Vector();
const geojsonLayer = new ol.layer.Vector({
    source: geojsonSource
});
map.addLayer(geojsonLayer);

// Define a bounding box (BBOX) based on the map view extent + the inital request URL.
let bbox = ol.proj.transformExtent(map.getView().calculateExtent(map.getSize()), 'EPSG:3857', 'EPSG:4326').toString();
let url = `https://api.os.uk/features/ngd/ofa/v1/collections/${collectionId}/items?bbox=${bbox}`;

// Create an empty GeoJSON FeatureCollection.
const geoJson = {
    "type": "FeatureCollection",
    "features": []
};

// Make a series of asynchronous fetch requests to the NGD Features API (to return everything within the BBOX).
const request = async () => {
    const features = await fetch(url, {
        headers: {
            'Accept': 'application/geo+json',
            'key': apiKey
        }
    }).then((response) => response.json());

    let linkNext = features.links.find( ({ rel }) => rel === 'next' );
    url = linkNext !== undefined ? linkNext.href : null;

    geoJson.features = geoJson.features.concat(features.features);

    if( url && geoJson.features.length < maxFeatures ) {
        request();
    }
    else {
        geojsonSource.addFeatures(
            new ol.format.GeoJSON().readFeatures(geoJson, {
                featureProjection: 'EPSG:3857'
            })
        );
    }
};

request();

The osdatahub-js wrapper acts in a similar manner where it will automatically page through the requests until 1) all the features have been returned; or 2) you hit your predefined limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants