Skip to main content

Spherical circle layers and screen queries

Shared GeoJSON circles can now be created, recoloured, filtered, shown and hidden on the sphere using the same MapLibre-shaped syntax as planar maps. Projection changes preserve camera and layer identities; circles do not need to be removed first. Browser main-thread/strict Worker, desktop and embedded native scripts share circle projection and query rules.

import { map } from 'sqsmap';
const caps = await map.sqs.getCapabilities();
if (!caps.globeGeoJsonCircleLayers || !caps.globeGeoJsonCircleQueries)
  throw new Error('This map version does not support spherical circles');
map.setProjection({ type: 'mercator' });
map.jumpTo({ center: [181, 40], zoom: 3, bearing: 33 });
map.addSource('places', { type: 'geojson', data: {
  type: 'Feature', id: 7, properties: { color: '#ff0000', radius: 40 },
  geometry: { type: 'Point', coordinates: [181, 40] }
}});
map.setProjection({ type: 'globe' });
map.addLayer({ id: 'places-circle', type: 'circle', source: 'places', paint: {
  'circle-color': ['get', 'color'], 'circle-radius': ['get', 'radius']
}});
const drawn = await map.sqs.flush({ render: true });
const point = await map.project([181, 40]);
const hits = await map.queryRenderedFeatures(point, { layers: ['places-circle'] });
console.log(drawn.cameraState, hits);

Circles and queries use logical pixels. Higher density increases actual framebuffer pixels without shrinking the radius or applying the old spherical marker's 24-pixel cap. Circles retain original coordinates, including both poles and world copies such as 181°. They are not first clamped to Mercator. Back-hemisphere anchors are neither drawn nor reported as planar hits. Queries preserve original Feature/GeometryCollection, properties, state, source and layer identity. Paint changes do not rewrite source properties.

Without a user style, the map owns a separate spherical background. It is not a caller source/layer and adds no third-party credit. Current-frame checks compare pose, density, layer content, imagery and lighting. flush({render:true}) certifies an actual current frame while motion can still run. Applied commands and old planar textures cannot stand in for drawing. Native synchronous readback finishes bounded geometry without advancing the chosen camera sample; browser and desktop hosts wait for the current target.

CapabilityCurrent scope
globeGeoJsonCircleLayersShared circles rendered from original coordinates
globeGeoJsonCircleQueriesPoint/MultiPoint/collection parent identity; screen points/boxes; layer selection/filter; topmost first
Spherical line/fill screen queriesConnected through original-coordinate shared surface triangles; see spherical surfaces
Spherical terrain, clouds, complete 3D occlusion and unified queries over all geometryStill pending; circle tests do not establish these capabilities

Shared scan, result-byte and option budgets still apply. Actual Linux windows, native QuickJS and GPU pole/world-copy/radius/paint checks are recorded; browser and Worker acceptance uses the matched development SDK. Software GPU does not establish Windows/macOS, mobile-device, hardware-performance or formal-release acceptance.

See spherical camera, display density and the shared-map script reference.