A route through the model.
A check you can keep.
Passage is a private furniture movement studio. It searches for one connected, three-dimensional movement through a supplied space. The useful result is a route you can inspect, edit, replay and take away.
A checked route is conditional on the model. The furniture consists of rigid boxes, the obstacles consist of fixed boxes, and the room has six rectangular boundaries. The check establishes separation for those supplied measurements. It does not establish a safe or successful physical move.
Bring the whole connected space.
Measure the piece's widest rigid points, including attached legs, handles and fittings. If parts come off, model the configuration you will actually carry. A sofa can be a union of seat, back and arm boxes. Individual parts let you keep meaningful gaps instead of filling them with an oversized enclosing box.
For the space, measure clear openings rather than nominal door sizes. Include the area where you turn or tip, both before and after an opening. An adjoining wall, ceiling drop, handrail or radiator can decide a route that the doorway alone appears to allow.
- Choose an example close to your route. Replace the room size, wall positions and furniture dimensions.
- In Space, add or edit walls and objects. A doorway adds two side sections and a lintel. Raised boxes can represent beams; stacked boxes can represent steps. Everything shares the same coordinates.
- In Move, set a start and finish that already clear the model. Across, up and along are the furniture origin's coordinates from the room's near-left corner. Up is the centre height, not the height of its underside.
- Choose a clearance buffer. It applies to the floor and ceiling as well as obstacles. The furniture must be modeled lifted above the floor by that buffer. The button in Move places the currently oriented piece just above it.
- Search, or add your own waypoints and check their connected transitions. Inspect the closest sampled moment alongside the independently computed continuous lower bound.
Measurement error accumulates. A buffer is a user-selected allowance, not a statistical confidence interval. Account for uncertain dimensions and anything that protrudes. Passage does not infer a missing measurement or know how accurate your tape measure is.
What the search does.
The search tries direct movements, orientation and lift maneuvers, and a seeded bidirectional motion tree. Each accepted connection is checked continuously. The piece can translate along three axes and rotate about three axes. The route keeps the transition between obstacles; it does not reset the furniture upright at each door.
A search stops at its time or work budget. No route found means this search did not find a checked route, not that no route exists. Try a longer search, different valid start and finish poses, or your own intermediate waypoints. A manually guided route receives the same independent check.
The displayed examples use assumed geometry. They are demonstrations, not measurements or solutions for the actual homes described in the demand sources below. The 74.5 cm doorway example uses an idealized 1 mm buffer and is particularly sensitive to measurement differences.
Why the check covers between frames.
For two boxes, projecting their points onto a unit direction gives two intervals. If the intervals have a positive gap, that gap is a lower bound on the distance between the boxes. The checker looks at world axes, furniture axes, and their cross-product directions. It does this for every rigid component and every obstacle, and also checks the six room boundaries.
For a movement segment, let r be the furthest furniture vertex from its origin, including component offsets. Moving between the midpoint and either end displaces every point by no more than half of:
Hold a separating direction found at the midpoint fixed. If its gap, minus half that movement bound and a numerical allowance, exceeds the requested buffer, the entire segment clears. Otherwise the checker bisects and repeats. A collision rejects the route; reaching a proof budget returns inconclusive. Sampling alone never becomes a continuous check.
The lower bound may be smaller than the actual closest surface distance. The Closest moment button locates the smallest bound among sampled playback poses; it helps inspect a tight area but is not the continuous certificate. The number labeled continuous clearance comes from certified subsegments.
The rotation convention is part of the route.
Coordinates use metres and radians in the project file. A pose is [x, y, z, rx, ry, rz], with rotation Ry × Rx × Rz, also called YXZ. Translation is linear. Each angle follows its shortest arc in (−π, π]; an exact half-turn follows the positive arc. The renderer, planner and independent checker use this same convention. A different interpolation between the same endpoints is a different route and is not covered.
Numbers, boundaries and physical limits.
This is a floating-point JavaScript geometry check, not a formally verified interval-arithmetic proof. It subtracts a conservative numerical allowance proportional to model scale. Projects with invalid numbers or unsupported sizes are rejected; continuous subdivision and geometry-work budgets prevent unbounded checks. A budget limit returns inconclusive.
The workspace supports a room up to 100 metres per dimension, 256 obstacle boxes, 32 rigid component boxes and 4,096 route poses. It accepts up to 128 manual waypoints. The standalone checker accepts a somewhat wider format, with its own finite validation and work limits. It does not silently repair malformed geometry.
All obstacle faces are axis-aligned. Curved walls and furniture, sloping ceilings, ramps and complex stairwells require a conservative box approximation. The app does not model furniture bending, cushion compression, doors moving during the route, detachable parts automatically, hands and bodies, carrying strength, appliance orientation restrictions, structural loading, balance, friction or collision forces. Add space for the people doing the carrying and consult the item's handling instructions separately.
A route with a millimetre-scale margin is a geometric illustration. A practical move needs trustworthy measurements and sufficient allowance for the real surroundings. A plan should help inspect the problem, not turn an approximate model into an assurance.
Displayed clearance lower bounds round down in the selected units. The independent checker returns the unrounded numerical bound for the full supplied project.
Your project can leave the site.
Save a copy downloads a complete .passage.json project with the space, rigid parts, poses, manual waypoints and any independently checked route. Opening that copy checks the route again; an imported green claim is never trusted. Your browser also stores the project when local storage is available. Browser data clearing can remove that copy, so use the download before moving devices.
Take the moving plan downloads a self-contained HTML report with the route map, ordered positions and rotations, all modeled obstacles and rigid parts, and the embedded full project. Open it offline. Its buttons save the project or print the report, including printing to PDF where your browser supports it. The report needs no website fonts or scripts to read.
Download checker.mjs into the same folder as your project. With Node.js installed, run node checker.mjs your-project.passage.json. It imports no packages and makes no network requests. A successful exit verifies the serialized model and path; an altered wall or route can make it fail. The file is an independent implementation, not a wrapper around the solver.
Project geometry, names and measurements stay in the browser. Exporting a project does not upload it. The Wasteland's ordinary site infrastructure may receive page visits and aggregate analytics; those requests do not contain project inputs. You control whether to share a saved project or report.
Demand, and what already exists.
People have already asked this connected-space question with their own measurements. One hallway and sofa request supplies a 226 × 93 × 74 cm sofa, a 74.5 cm doorway, and a 99.5 cm hallway. Another measured entry problem separates clearing the doorway from clearing the adjoining wall and ceiling. A 97-inch sofa and landing question adds stairs and the space needed before making a purchase. These requests demonstrate the task, not adoption of Passage.
This category has real alternatives. Meadow Tools already offers a free private 3D furniture fit calculator with shaped pieces, clearance and replay. Its published assumptions treat steps separately, with a fixed tilt through turns and long adjoining corridors. MoveClear advertises upright geometry with replay; Room to Spare also offers three-dimensional movement estimation. Passage's contribution is the editable connected scene, simultaneous three-axis movement, portable complete projects and separate continuous checker. No first-or-only claim is made, and these are descriptions, not an accuracy comparison of competing tools.
The release checks.
The engine regression suite passed 84 substantive assertions, including hint-free searches through all six examples and mirrored, scaled and widened narrow sofa corners. It also tests collisions between clear endpoints, rotational sweeps, floor and ceiling limits, offset parts, hollow shapes, half-turn direction, edits and bounded searches. The separately written checker suite passed 242 assertions across 16 named cases, 50 seeded routes and 18 malformed models. It exposed seven deliberately planted defects, including missing translation or rotation bounds and checking only sampled midpoints.
To reproduce the suites in a fresh folder, download engine.mjs, checker.mjs and the two suite files linked above. Run node engine-tests.mjs --engine=./engine.mjs --checker=./checker.mjs and node verify-checker.mjs --checker=./checker.mjs. These need Node.js and no installed packages. The checker suite writes its generated fixtures and results beside itself; the optional LP oracle reads those fixtures.
A further oracle uses convex combinations of independently rotated box vertices and a linear program to test intersections. It follows a different mathematical route from separating axes. It checked 6,666 poses across 56 accepted routes without finding an intersecting pose, and found sampled intersections in seven rejected cases. Its sampled agreement can expose a bug; it does not prove continuity. The midpoint displacement bounds supply the continuous argument. The oracle needs Python with NumPy and SciPy; the app and portable checker do not.
The browser acceptance runner covers edited models, searches, cancellation, stale results, touch and keyboard controls, project save/reopen, the offline report and checker, reduced motion, absent WebGL and multiple viewport widths. It accepts a public base URL to exercise the deployed bytes. It needs an existing Playwright and Chromium installation. The release evidence record distinguishes the mathematical tests from browser observations. These are test results, not evidence of successful physical moves or user adoption.
Three-dimensional rendering uses a self-hosted MIT-licensed Three.js 0.180.0 bundle. The geometry engine and independent checker have no external dependencies.