# Wayfinding Floorplan Configuration Guide

This document describes how to generate a valid JSON configuration file for the [Revel Digital Wayfinding App](https://RevelDigital.github.io/wayfinding-app/). The configuration defines building locations (rooms, offices, amenities) and a waypoint navigation graph overlaid on floor plan images so the app can render 3D wayfinding routes.

**JSON Schema:** <https://RevelDigital.github.io/wayfinding-app/floorplan-schema.json>

---

## Overview

A configuration file has two top-level arrays:

```json
{
  "locations": [ ... ],
  "floors": [ ... ]
}
```

- **`locations`** — The destinations visitors can search for and navigate to (rooms, offices, etc.).
- **`floors`** — One entry per floor, each containing a floor plan image URL and a waypoint graph used for route calculation.

The app renders each floor as a textured 3D plane with the floor plan image, stacked vertically. A ribbon path is drawn along the waypoint graph from the visitor's current position ("You Are Here") to the selected destination.

---

## Step-by-step generation process

### Step 1: Obtain floor plan images

You need one image per floor. The image should be an architectural floor plan in SVG or PNG format showing room layouts, corridors, and labels.

- The user will provide the floor plan image(s). There will be one image per floor.
- Images must be hosted at a publicly accessible URL (e.g. S3, CDN, or any static host).
- Note the pixel dimensions of each image — you will need them for the `imageSize` field.
- **Visually inspect each floor plan image** to understand the room layout, corridor structure, and spatial relationships before placing waypoints.

### Step 2: Identify locations from the floor plan

Examine each floor plan image and identify every labeled room, office, or area. For each one, create a location entry:

```json
{
  "id": "1",
  "name": "Main Lobby",
  "category": "Common",
  "floor": "1",
  "room": "100",
  "description": "Welcome desk and visitor check-in. Open 24 hours.",
  "icon": "🏥",
  "tags": ["entrance", "reception"],
  "waypointId": "f1-lobby"
}
```

**Field details:**

| Field | Required | Description |
|-------|----------|-------------|
| `id` | Yes | Unique string identifier (e.g. `"1"`, `"2"`, ...). |
| `name` | Yes | Display name shown to visitors. |
| `category` | Yes | One of: `Common`, `Office`, `Conference`, `Dining`, `Amenity`, `Restricted`. Determines color coding and grouping in the UI. |
| `floor` | Yes | Must exactly match the `floor` value of one entry in the `floors` array. |
| `room` | Yes | Room number or code as shown on the floor plan. |
| `description` | Yes | Brief visitor-facing description (hours, services, capacity, etc.). |
| `icon` | Yes | A single emoji representing the location. |
| `tags` | No | Array of lowercase search keywords. Helps visitors find the location. |
| `waypointId` | No | The ID of the waypoint in the floor's navigation graph that sits at or near this room's entrance. Required for route rendering. |

**Category guidelines:**
- `Common` — Public-facing: lobbies, pharmacies, information desks
- `Office` — Workspaces, departments, nurse stations
- `Conference` — Meeting and conference rooms
- `Dining` — Cafeterias, break rooms, kitchens
- `Amenity` — Waiting rooms, wellness rooms, gift shops, gyms
- `Restricted` — Badge-access areas: server rooms, labs, security

### Step 3: Build the waypoint navigation graph for each floor

The waypoint graph is the most critical part. It defines walkable paths overlaid on the floor plan image. The app uses this graph to compute and render routes.

**Waypoint types:**

1. **Room waypoints** — Placed at or near a room's entrance/doorway. These are referenced by a location's `waypointId`.
2. **Corridor waypoints** — Placed at corridor intersections, turns, and junctions. These are not directly tied to locations but connect the graph together.
3. **Entrance waypoints** — The building entrance where visitors start. Referenced by the floor's `youAreHere` field.
4. **Transport waypoints** — Elevators and stairwells that connect floors. These have `isTransport: true` and their `connections` array includes a waypoint ID on another floor.

**How to place waypoints:**

Waypoint coordinates are in **image-pixel space** where `(0, 0)` is the **top-left** corner of the image.

1. **Identify corridors** in the floor plan image. Place corridor waypoints at every intersection, bend, or junction along the corridors. Use consistent naming like `f1-cor-l`, `f1-cor-m`, `f1-cor-r` (floor-corridor-position).

2. **Place room waypoints** at each room's entrance point — where a person would step from the corridor into the room. The waypoint's `(x, y)` should be the pixel coordinates of that doorway on the image.

3. **Connect waypoints** to form walkable paths. Each waypoint lists the IDs of waypoints it directly connects to. **Connections are bidirectional** — if waypoint A lists B in its connections, then B must also list A.

4. **Place an entrance waypoint** at the building entrance (ground floor) or elevator landing (upper floors). Set the floor's `youAreHere` to this waypoint's ID.

5. **For multi-floor buildings**, add transport waypoints at elevators and stairwells. These must:
   - Have `"isTransport": true`
   - Have a `"transportName"` (e.g. `"Main Elevator"`)
   - Include the corresponding transport waypoint ID on the other floor in their `connections` array

**Waypoint entry format:**

```json
{ "id": "f1-lobby", "x": 100, "y": 195, "connections": ["f1-cor-bl"] }
```

Transport waypoint example:
```json
{ "id": "f1-elev", "x": 240, "y": 250, "connections": ["f1-cor-l", "f2-elev"], "isTransport": true, "transportName": "Main Elevator" }
```

### Step 4: Assemble the floor entries

Each floor entry ties together the image, dimensions, starting point, and waypoint graph:

```json
{
  "floor": "1",
  "label": "Floor 1 — Ground",
  "image": "https://example.com/images/floorplan-f1.svg",
  "imageSize": [1000, 500],
  "youAreHere": "f1-entrance",
  "waypoints": [ ... ]
}
```

| Field | Required | Description |
|-------|----------|-------------|
| `floor` | Yes | Floor identifier string (e.g. `"1"`, `"2"`, `"B1"`). Referenced by locations. |
| `label` | Yes | Display label (e.g. `"Floor 1 — Ground"`, `"Floor 2 — Medical"`). |
| `image` | Yes | Absolute URL to the floor plan image (SVG or PNG). |
| `imageSize` | Yes | `[width, height]` in pixels. Must match the actual image dimensions. This controls the scale of the 3D floor plane. |
| `youAreHere` | Yes | Waypoint ID for the visitor's starting position. On the ground floor, this is typically the entrance. On upper floors, this is typically the elevator or stairwell landing. |
| `waypoints` | Yes | Array of waypoint objects forming the navigation graph for this floor. |

---

## Coordinate system

- Origin `(0, 0)` is the **top-left** corner of the floor plan image.
- `x` increases to the **right**.
- `y` increases **downward**.
- Units are **pixels** matching the source image dimensions specified in `imageSize`.
- Waypoint positions should correspond to actual walkable positions on the floor plan (corridors, doorways, elevator landings).

---

## Multi-floor routing

For buildings with multiple floors:

1. Each floor gets its own entry in the `floors` array with its own image and waypoint graph.
2. Floors are connected via transport waypoints (elevators, stairwells).
3. A transport waypoint on floor 1 includes the ID of its counterpart on floor 2 in its `connections` array, and vice versa.
4. Both paired transport waypoints must have `"isTransport": true` and a matching `"transportName"`.
5. The app renders a vertical connector between floors when the route crosses floor boundaries.

**Example — elevator connecting floors 1 and 2:**

Floor 1:
```json
{ "id": "f1-elev", "x": 240, "y": 250, "connections": ["f1-cor-l", "f2-elev"], "isTransport": true, "transportName": "Main Elevator" }
```

Floor 2:
```json
{ "id": "f2-elev", "x": 240, "y": 250, "connections": ["f2-cor-l", "f1-elev"], "isTransport": true, "transportName": "Main Elevator" }
```

---

## Validation checklist

Before submitting the configuration:

- [ ] Every location's `floor` value matches exactly one floor entry's `floor` value.
- [ ] Every location's `waypointId` matches exactly one waypoint `id` in the corresponding floor's waypoints array.
- [ ] Every floor's `youAreHere` matches exactly one waypoint `id` in that floor's waypoints array.
- [ ] All waypoint connections are bidirectional (if A connects to B, B connects to A).
- [ ] Transport waypoints have `isTransport: true` and a `transportName`.
- [ ] Transport waypoint pairs reference each other across floors.
- [ ] `imageSize` matches the actual pixel dimensions of the floor plan image.
- [ ] All image URLs are publicly accessible.
- [ ] The waypoint graph is fully connected — every room waypoint can be reached from the `youAreHere` starting point via corridor waypoints.
- [ ] Waypoint `(x, y)` positions fall within the image bounds (`0 ≤ x < width`, `0 ≤ y < height`).

---

## Complete example

A two-floor hospital with 14 locations, elevator, and stairwell:

```json
{
  "locations": [
    { "id": "1",  "name": "Main Lobby",      "category": "Common",     "floor": "1", "room": "100", "description": "Welcome desk and visitor check-in. Open 24 hours.", "icon": "🏥", "tags": ["entrance", "reception"], "waypointId": "f1-lobby" },
    { "id": "2",  "name": "Cafeteria",        "category": "Dining",     "floor": "1", "room": "110", "description": "Hot meals, salad bar, and coffee. Open 6 AM - 8 PM.", "icon": "🍽️", "tags": ["food", "lunch"], "waypointId": "f1-cafe" },
    { "id": "3",  "name": "Security Office",  "category": "Restricted", "floor": "1", "room": "120", "description": "Building security and badge services.", "icon": "🛡️", "tags": ["security", "badges"], "waypointId": "f1-security" },
    { "id": "4",  "name": "Gift Shop",        "category": "Amenity",    "floor": "1", "room": "105", "description": "Flowers, cards, magazines, and personal care items.", "icon": "🎁", "tags": ["gifts", "flowers"], "waypointId": "f1-gift" },
    { "id": "5",  "name": "Pharmacy",         "category": "Common",     "floor": "1", "room": "115", "description": "Prescription pickup. Open 7 AM - 9 PM.", "icon": "💊", "tags": ["prescriptions", "medicine"], "waypointId": "f1-pharmacy" },
    { "id": "6",  "name": "Waiting Room",     "category": "Amenity",    "floor": "1", "room": "125", "description": "Comfortable seating, TV, and complimentary Wi-Fi.", "icon": "🛋️", "tags": ["waiting", "visitors"], "waypointId": "f1-waiting" },
    { "id": "7",  "name": "Admin Office",     "category": "Office",     "floor": "1", "room": "130", "description": "Hospital administration. Appointments only.", "icon": "💼", "tags": ["administration"], "waypointId": "f1-admin" },
    { "id": "8",  "name": "Radiology",        "category": "Restricted", "floor": "2", "room": "200", "description": "X-ray, CT, MRI. Appointment required.", "icon": "🩻", "tags": ["x-ray", "MRI", "imaging"], "waypointId": "f2-radiology" },
    { "id": "9",  "name": "Laboratory",       "category": "Restricted", "floor": "2", "room": "210", "description": "Blood draws and specimen processing.", "icon": "🔬", "tags": ["blood work", "labs"], "waypointId": "f2-lab" },
    { "id": "10", "name": "Cardiology",       "category": "Office",     "floor": "2", "room": "220", "description": "Outpatient heart care. EKG and stress testing.", "icon": "❤️", "tags": ["heart", "cardiac"], "waypointId": "f2-cardio" },
    { "id": "11", "name": "Nurse Station",    "category": "Office",     "floor": "2", "room": "230", "description": "24-hour nursing station.", "icon": "👩‍⚕️", "tags": ["nurses", "help"], "waypointId": "f2-nurse" },
    { "id": "12", "name": "Physical Therapy", "category": "Amenity",    "floor": "2", "room": "240", "description": "Rehab gym with equipment and treatment tables.", "icon": "🏋️", "tags": ["rehab", "PT"], "waypointId": "f2-pt" },
    { "id": "13", "name": "Conference Room B","category": "Conference",  "floor": "2", "room": "250", "description": "Seats 16. AV system and video conferencing.", "icon": "📊", "tags": ["meeting", "conference"], "waypointId": "f2-conf" },
    { "id": "14", "name": "Break Room",       "category": "Dining",     "floor": "2", "room": "260", "description": "Staff kitchen with microwave, fridge, and coffee.", "icon": "☕", "tags": ["kitchen", "staff", "coffee"], "waypointId": "f2-break" }
  ],
  "floors": [
    {
      "floor": "1",
      "label": "Floor 1 — Ground",
      "image": "https://reveldigital-common.s3.us-east-1.amazonaws.com/wayfinding/images/floorplan-f1.svg",
      "imageSize": [1000, 500],
      "youAreHere": "f1-entrance",
      "waypoints": [
        { "id": "f1-entrance", "x": 100, "y": 480, "connections": ["f1-cor-bl"] },
        { "id": "f1-cor-bl",   "x": 100, "y": 305, "connections": ["f1-entrance", "f1-lobby", "f1-gift", "f1-cor-l"] },
        { "id": "f1-lobby",    "x": 100, "y": 195, "connections": ["f1-cor-bl"] },
        { "id": "f1-gift",     "x": 100, "y": 400, "connections": ["f1-cor-bl"] },
        { "id": "f1-cor-l",    "x": 240, "y": 250, "connections": ["f1-cor-bl", "f1-elev", "f1-cor-m"] },
        { "id": "f1-elev",     "x": 240, "y": 250, "connections": ["f1-cor-l", "f2-elev"], "isTransport": true, "transportName": "Main Elevator" },
        { "id": "f1-cor-m",    "x": 490, "y": 250, "connections": ["f1-cor-l", "f1-cafe", "f1-pharmacy", "f1-waiting", "f1-cor-r"] },
        { "id": "f1-cafe",     "x": 490, "y": 100, "connections": ["f1-cor-m"] },
        { "id": "f1-pharmacy", "x": 385, "y": 400, "connections": ["f1-cor-m"] },
        { "id": "f1-waiting",  "x": 595, "y": 400, "connections": ["f1-cor-m"] },
        { "id": "f1-cor-r",    "x": 740, "y": 250, "connections": ["f1-cor-m", "f1-security", "f1-admin", "f1-stair"] },
        { "id": "f1-stair",    "x": 740, "y": 250, "connections": ["f1-cor-r", "f2-stair"], "isTransport": true, "transportName": "East Stairwell" },
        { "id": "f1-security", "x": 890, "y": 100, "connections": ["f1-cor-r"] },
        { "id": "f1-admin",    "x": 890, "y": 400, "connections": ["f1-cor-r"] }
      ]
    },
    {
      "floor": "2",
      "label": "Floor 2 — Medical",
      "image": "https://reveldigital-common.s3.us-east-1.amazonaws.com/wayfinding/images/floorplan-f2.svg",
      "imageSize": [1000, 500],
      "youAreHere": "f2-elev",
      "waypoints": [
        { "id": "f2-elev",     "x": 240, "y": 250, "connections": ["f2-cor-l", "f1-elev"], "isTransport": true, "transportName": "Main Elevator" },
        { "id": "f2-cor-l",    "x": 240, "y": 250, "connections": ["f2-elev", "f2-radiology", "f2-pt", "f2-cor-m"] },
        { "id": "f2-radiology","x": 100, "y": 100, "connections": ["f2-cor-l"] },
        { "id": "f2-pt",       "x": 100, "y": 400, "connections": ["f2-cor-l"] },
        { "id": "f2-cor-m",    "x": 490, "y": 250, "connections": ["f2-cor-l", "f2-lab", "f2-cardio", "f2-conf", "f2-cor-r"] },
        { "id": "f2-lab",      "x": 385, "y": 100, "connections": ["f2-cor-m"] },
        { "id": "f2-cardio",   "x": 595, "y": 100, "connections": ["f2-cor-m"] },
        { "id": "f2-conf",     "x": 490, "y": 400, "connections": ["f2-cor-m"] },
        { "id": "f2-cor-r",    "x": 740, "y": 250, "connections": ["f2-cor-m", "f2-nurse", "f2-break", "f2-stair"] },
        { "id": "f2-stair",    "x": 740, "y": 250, "connections": ["f2-cor-r", "f1-stair"], "isTransport": true, "transportName": "East Stairwell" },
        { "id": "f2-nurse",    "x": 890, "y": 100, "connections": ["f2-cor-r"] },
        { "id": "f2-break",    "x": 890, "y": 400, "connections": ["f2-cor-r"] }
      ]
    }
  ]
}
```

---

## Input requirements

When invoking this skill, the user must provide:

1. **Floor plan image(s)** — One image per floor. The agent must visually inspect each image to identify rooms, corridors, entrances, elevators, and stairwells, and to determine accurate pixel coordinates for waypoint placement.
2. **Building context** (optional) — Room names, departments, hours, or other details not visible on the floor plan.

The agent should:

1. Fetch and visually analyze each floor plan image.
2. Determine the image dimensions (`imageSize`).
3. Identify all labeled rooms and map them to locations with appropriate categories.
4. Trace corridors and place waypoints at intersections and room entrances using pixel coordinates from the image.
5. Build bidirectional connections between waypoints to form a connected navigation graph.
6. For multi-floor buildings, identify and connect elevator/stairwell transport waypoints across floors.
7. Validate the output against the checklist above.
8. Return the complete JSON configuration.
