Planar camera API
Development native sessions now support common nonzero planar pitch. See native pitched maps for the complete script, capability scope and actual pixel acceptance. Matching WASM/main/strict Worker maps now support it too; see web pitched maps. The desktop facade now connects the same scene; see desktop pitched maps.
This page describes the SQSAPI-06.2/06.3 development source. Shared calculations now drive real map sessions, C ABI, WASM, and browser SDK bindings. It does not mean an older npm package has acquired these methods. The desktop console and local web workbench now connect the shared planar sqsmap facade. Application scripts still require a project.read / map.write permission header; the calls below use the same syntax.
Names and argument conventions reference the MapLibre Map API. The shared core implements the calculations, defaults, and errors without using MapLibre code. An explicit difference: authoritative queries return promises in the standalone native module and SDK. Use await. Writes return the map for chaining; flush confirms application. Main-thread and Worker rendering use the same syntax.
Methods and units
| Method | Arguments or result | Current scope |
|---|---|---|
getCenter() | { lng, lat } | WGS84; longitude selects an explicit world copy |
getZoom() | Number | World zoom defined by 512 logical pixels |
getBearing() | Number | Clockwise degrees normalized to [-180, 180) |
getPitch() | Degrees | Native/WASM/main/strict Worker Mercator and globe support 0–65; geographic uses zero; desktop Mercator supports 0–65, see Globe API |
getPadding() | { top, right, bottom, left } | Nonnegative logical pixels |
getBounds() | [[west,south],[east,north]] | Contains all rotated viewport corners |
getProjection() | { type } | Native session and WASM/SDK: geographic or mercator depending on the basemap |
project(position) | { x, y } | Accepts [lng,lat] or {lng,lat}; returns logical pixels |
unproject(point) | { lng, lat } | Accepts [x,y] or {x,y}; invalid ground latitudes fail |
jumpTo(options) | Map | center, zoom, bearing, pitch, roll, padding; unknown options fail |
fitBounds(bounds, options?) | Map | Four numbers or two endpoints; east < west crosses the date line |
cameraForBounds(bounds, options?) | Camera pose | Calculation only; no mutation or write submission |
setCenter/setZoom/setBearing/setPitch/setPadding | Map | Uses the same complete validation and application path |
resetNorth/zoomIn/zoomOut | Map | North reset or one zoom level; preserves the padded camera center |
Padding can be a uniform number or a partial edge object; omitted edges are zero. Omitting padding preserves the current value. The viewport must exceed padding totals. When resize makes existing padding invalid, it is cleared while preserving the displayed raw view; view/resize notifications expose the change.
Bounds-fitting options are padding, offset, bearing, minZoom, maxZoom, animate, duration, and linear. The default fitting zoom interval is 0–24. Camera animation is connected: fitting defaults to 300 ms; animate:false or duration:0 applies immediately, and linear:true uses linear progress. A flush confirms application or a subsequent frame, not animation completion.
All arguments are validated before mutation. Geometry calculations use double precision, but renderer scale and shaders retain single-precision boundaries. Mathematical tolerances are not arbitrary-device pixel guarantees. Native offscreen maps use DPR=1; WASM converts at the actual DPR boundary. Legacy direct WASM setView/view remains a canvas-pixel compatibility entry; new SDK setView/getView uses shared logical pixels. See camera calculations.
Browser SDK
Use JS, Worker, WASM, and declarations generated from the same commit. The published npm dependency on /example does not acquire methods from development-source changes.
// view comes from MapView.create(...) in the matching SDK.
view.jumpTo({ center: [116.4, 39.9], zoom: 8, bearing: 30,
padding: { left: 240 } }).setZoom(9);
await view.flush({ render: true });
const center = await view.getCenter();
const pixel = await view.project(center);
const position = await view.unproject(pixel);
view.fitBounds([[170, -10], [-170, 10]], { padding: 40, animate: false });
await view.flush();
console.log(await view.cameraState(), position);
Camera writes join the same command journal on the main thread and Worker. Read requests cannot secretly mutate the camera outside that journal. Queries execute in actual receipt order; flush watermarks provide explicit confirmation. Frames and receipts may include publicCamera while preserving raw camera data. View state and scale calculations use the padded center.
Native library and scripting
High-level ABI stays at version 1. Detect the added capability using sqsm_map_runtime_flags() & SQSM_MAP_PLANAR_CAMERA (bit value 16). Pure native libraries expose the camera C entry; QuickJS remains an optional feature.
sqsm_map_bytes_t out = { NULL, 0, 0 };
const char *request = "{\"method\":\"jumpTo\",\"args\":[{\"center\":[116.4,39.9],\"zoom\":8}]}";
int32_t status = sqsm_map_camera_json(map,
(const uint8_t *)request, strlen(request), &out);
if (status == SQSM_MAP_OK) sqsm_map_bytes_free(out.allocation);
Requests contain exactly method (string) and args (array), up to 64 KiB. Reads return JSON data; writes return JSON null and enter the shared confirmation journal. Existing creator-thread, stale-handle, error, and output-buffer rules apply. Failure clears output and does not promise rollback of earlier applied changes. Check every status and free every successful allocation.
Complete C host, complete native script, native declarations. The same complete script runs through one-shot and retained sessions of the native library. Its authoritative combined camera query is map.sqs.cameraState(); the SDK uses view.cameraState().
Verification and remaining work
Real C and QuickJS one-shot/retained sessions on Linux NVIDIA GeForce RTX 4060 / Vulkan verified round trips, padded centers, atomic argument rejection, date-line fitting, failure history/recovery, new rendered receipts, and actual polygon pixels. C11 host, C++17 header, shared math, dependency boundaries, paired WASM builds, SDK types, and website checks are recorded in the task list.
Globe immediate commands and projection switching have separate 14.1 software GPU and browser main-thread/Worker checks; see Globe API. Globe animation and anchors are connected; Windows/macOS devices and mobile hosts remain separate work.
The 06.3 empty desktop basemap cannot yet move its padded raw focus beyond the north/south Mercator limits. GIS-specific CRSs and planar 3D views retain dedicated APIs. Globe uses the shared spherical model, without substituting planar calculations. Queries wait for preceding shared camera writes and support real Promise methods. Omitting flush cannot hide a failed write. To recover, capture the failure watermark and use an explicit flush({since}). See the shared map facade for an application example.
Native styles and resource hosts: native libraries now provide set_style_json, request polling, and response submission. Optional native scripts support chainable map.setStyle(url, {diff:false}) and sqs.resourceschange. Styles enable Mercator display; clearing restores geographic display. The shared style facade is documented in style scripts; common setProjection({type}) is connected with the limits described in Globe API.
Standalone SDK snapshots and legacy APIs: cached camera, pitch, CSS ground scale and compatibility state reads.
Native Rust display density: logical input, actual physical textures and common camera binding.