Spatial Service

OpenGPEX operates in three distinct coordinate spaces. Understanding them is critical for writing correct interaction handlers, overlays, and rendering code.


Three Coordinate Spaces

Space Origin Unit Use Case
Screen Browser viewport top-left CSS pixels Mouse events, DOM positioning
World Canvas (0,0) at zoom=1 Image pixels Layer positioning, canvas math
Local Layer's own top-left corner Layer pixels Mask coordinates, brush strokes

Transform Chain

Screen → (inverse camera matrix) → World → (inverse layer matrix) → Local
Local  → (layer matrix) → World → (camera matrix) → Screen

GeometryService API

Method From → To Usage
screenToWorld(screenX, screenY) Screen → World Convert mouse position to canvas coords
worldToScreen(worldX, worldY) World → Screen Position DOM overlays
worldToLocal(worldX, worldY, layer) World → Local Brush coordinate within layer
localToWorld(localX, localY, layer) Local → World Convert mask point to global
getProjectionMatrix(layer) Full 3×3 transform matrix
getBoundsInWorld(layer) Axis-aligned bounding box in world

The pixels Facade

For common operations, use the high-level pixels API:

const { pixels } = useEditorServices().services;

// Get mouse position in world coordinates
const worldPos = pixels.screenToWorld(event.clientX, event.clientY);

// Get layer bounds in screen space (for overlay positioning)
const screenBounds = pixels.getScreenBounds(layer);

// Check if a world point is inside a layer
const isInside = pixels.hitTest(worldX, worldY, layer);

Usage Rules

⚠️ Never cache coordinate transforms — they change whenever the camera moves or a layer transforms.

  1. Always recompute transforms from the latest state
  2. Inside React components, use props/state as the source of truth
  3. Inside interaction handlers, query fast.latestCamera() for live values
  4. For overlays, use useFastSync() to get 60fps-accurate screen positions

Next Steps


Last updated: 2026-06-14