Skip to content

Project North direction: data-model property + viewport compass #362

Description

@marcelgruber

Problem or motivation

Pascal has no first-class North in its data model. The word "north"
appears only as informal English in template comments, and the two
templates that use it don't even agree:

There's no northDirection, northDeg, compass, or any other
orientation primitive anywhere in the schema. So:

This is what surfaced #337 in the first place — building geometry
programmatically from a surveyor's report (every wall a bearing from
True North) means chasing the rotation manually, because the editor
has nothing to anchor it against.

Proposed solution

A tiered approach so the maintainer can pick a starting point. Tier 1
on its own would close the gap meaningfully; Tier 2 makes it complete.

Tier 1 — minimum viable (a property, a widget, a default)

  • Add northDirection: number (radians, CCW from world +X to match
    Pascal's existing rotation conventions) to Site or Building.
    Default to whatever the current templates implicitly assume so
    existing scenes don't move.
  • Render a small north-arrow widget in viewport corners (or near the
    existing camera-mode button in
    apps/editor/components/viewer-toolbar.tsx),
    rotating with the camera so it always points to true north on screen.
  • Clean up the conflicting template comments while in the area.

Tier 2 — high-leverage follow-ups

  • "Rotate to north-up" view command — orbits the 3-D top-down camera so
    north faces screen-up, and adjusts FLOORPLAN_VIEW_ROTATION_DEG /
    the floor-plan SVG group rotation so 2-D plan view does the same.
  • Surface northDirection over MCP (settable via apply_patch /
    readable from get_scene). Agents authoring from a survey can drop
    the value in once and have everything else line up — closes the loop
    the README PR opens.

Tier 3 — explicitly out of scope for v1, mentioned so it doesn't
get baked into the wrong place

  • Revit-style True North vs Project North separation (Project
    North = aligned to a building facade for drawing clarity, True North
    = the cardinal). Worth considering if Pascal ever wants sun-studies
    • multi-building campuses, but not necessary for the immediate gap.
  • Sun / shadow studies tied to northDirection + lat/long + date/time.

Alternatives considered

  • Document the gap only (what PR docs(mcp): document plan↔world coordinate convention #356 does). Helpful but doesn't
    solve the underlying issue: even after reading the docs an author
    still has to verify orientation against a guide image every time.
  • Per-template / per-author conventions (status quo). Already
    visibly broken — the two-bedroom template says +Z is south and the
    garden-house template says the garden is to the north without
    saying which axis.
  • Skip the data-model change; add only a UI compass that points to
    world +Z (or +X) regardless.
    Tempting but doesn't help anyone
    authoring from a real-world bearings source; it just relabels the
    existing world axes.

Additional context

Every comparable tool has this:

Tool What they do
Revit Distinct True North vs Project North; sun/shadow studies, energy modelling key off it
ArchiCAD Project north in Project Preferences
SketchUp Solar North toolbar with a settable north angle
Vectorworks Plan rotation to true north as a project setting
Civil 3D / AutoCAD North angle on the drawing; standard in civil/site work
Floorplanner / Roomstyler / similar SaaS Rotatable north-arrow widget
QGIS / ArcGIS / any GIS layout North arrow as a first-class layout primitive

So Pascal not exposing this is the unusual position rather than the
ask being unusual.

Open questions

  1. Site or Building? Site is the outermost container and
    multiple buildings could share a site's north. Building already
    has a rotation: [x,y,z], so Building.rotation[1] is roughly "this
    building's facade angle relative to site axes". Storing north on
    Site keeps these orthogonal; storing on Building lets each building
    have its own. My instinct says Site, but you may have a reason to
    put it on Building.
  2. Default value? Defaulting to "true north = +Z" matches the
    two-bedroom.ts template's stated convention ("+Z = south" inverted)
    and is the most common assumption in north-up site plans. Worth
    defaulting explicitly rather than leaving it implicit as today.
  3. Widget UI? A separate corner widget is the obvious choice, but
    could also be a small N marker on the existing camera-mode button,
    or a compass overlay near the orthographic-camera toggle in
    viewer-toolbar.tsx:438.
    Likely a design call.

Happy to take a stab at Tier 1 if there's interest; want to confirm
the schema placement and widget direction first.

Related: #337, #356.

Activity

  1. Aymericr commented on Jul 19, 2026

    @Aymericr
    Contributor

    Status update: the viewport portion has shipped. #478 added the live compass and align-to-north behavior, and #487 fixed 3D-only compass synchronization. The requested first-class north model is still absent—there is no northDirection/project-north field on Site or Building, nor the corresponding MCP contract—so I’m keeping this issue open for that durable data-model work.

  2. Aymericr commented on Aug 4, 2026

    @Aymericr
    Contributor

    Re-checked this against current main. The core ask stands, with one correction to the original write-up.

    Still true: there is no first-class North. grep for northDirection / projectNorth / northDeg / trueNorth across packages/core/src/schema/ and packages/mcp/src/ returns nothing. Site and Building carry no orientation field, and the MCP contract has nothing to anchor a real-world bearing against. The viewport half shipped (#478 compass + align-to-north, #487 3D sync), so what's left is exactly the durable data-model work this issue is named for.

    Correction: the two templates don't actually disagree. Reading the geometry rather than the prose, both use −z = north:

    • two-bedroom.ts — wall_n spans [X_MIN, Z_MIN] → [X_MAX, Z_MIN], wall_s spans Z_MAX. So positive z points south, as its header states.
    • garden-house.ts — wall_n is at -HOUSE_D, wall_s at +HOUSE_D, and zone_garden extends to -HOUSE_D - GARDEN_DEPTH, i.e. further into −z. The garden is at −z, which is north under the same convention.

    So the convention is consistent in the code; garden-house.ts just never writes it down, which is why it reads like a contradiction. That's a smaller and different problem than "templates pick their own convention silently" — worth knowing before someone starts, since it means there's no existing inconsistency to migrate, just an undocumented assumption to make explicit and then to promote into the schema.

    That splits this into two independently shippable pieces:

    1. Documentation-sized: copy the coordinate-system paragraph from two-bedroom.ts:13-14 into garden-house.ts, so both templates state −z = north. Genuine good-first-issue: one comment, no behaviour change.
    2. The actual work: an orientation field on Site (or Building), an MCP contract for it, and the compass reading from it rather than from world axes. This needs a design call first — degrees vs vector, which node owns it, what happens to existing scenes that have no value (treat absent as "−z is north" to stay backward-compatible with every scene and template written so far), and whether the 2D panel's 90° rotation and the 3D top-down snap offset should then be derived from it.

    Labeling enhancement + help wanted. Piece 2 is a schema change, so it wants agreement on the shape before code — if you or anyone else wants to take it, propose the field on this issue first and we'll settle it there rather than in review.

  3. FenjuFu commented on Sep 10, 2026

    @FenjuFu
    Contributor

    I checked current main: the compass/align-to-north UI and the garden-house coordinate documentation are already present. I'd like to work on the remaining durable orientation contract, with this concrete shape for agreement before implementation:

    • Store northDirection on SiteNode, since one site's buildings should share north independently of each building's existing rotation.
    • Use a finite angle in radians about world +Y, with 0 meaning world -Z. The corresponding north vector is [-sin(northDirection), 0, -cos(northDirection)]; this makes the angle directly compatible with the existing camera azimuth convention. Missing values default to 0, preserving saved scenes and templates.
    • Treat it as orientation metadata: changing north never rotates geometry. The existing 2D/3D compass and align action read the selected building's parent site and use this angle; building-local rotations remain independent.
    • Support the field through the existing validated apply_patch/get_scene path, with coverage for legacy scenes, non-finite values, serialization/patch round trips, and rotated buildings. No separate true/project-north or sun-study model in this change.

    Would this Site-owned, radians-from-minus-Z shape work for you, or would you prefer the original radians-from-plus-X representation? I will keep the durable schema change separate from the already-shipped compass work while this is settled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededready-for-humanNeeds human input during execution

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions