# Railway Layout Creator

A visual drag-and-drop editor for creating railway track layouts that generate JSON files compatible with the railway.js simulator.

## Features

- **Visual Track Placement** - Click to place tracks, drag to reposition
- **Multiple Track Types** - Support for buffers, pass nodes, points (switches), signals
- **Connection Management** - Visual connection lines with bidirectional validation
- **Pan & Zoom** - Navigate large layouts easily
- **Grid Snapping** - Optional snap-to-grid for precise alignment
- **Import/Export** - Load existing layouts or export to JSON
- **Validation** - Check for errors and connectivity issues
- **Undo/Redo** - Full history support (Ctrl+Z / Ctrl+Shift+Z)

## Getting Started

1. Open `index.html` in your web browser
2. Select a tool from the toolbar
3. Click on the canvas to place track elements
4. Use the connection tool to link tracks together
5. Export to JSON when finished

## Tools

### Select Tool (S)
- Click to select tracks
- Drag to reposition selected tracks
- View and edit properties in the properties panel

### Pass Node (P)
- Creates a pass-through track node
- Used for simple track segments
- Should have exactly 1 connection

### Buffer (B)
- Creates a buffer (end of line)
- Should have exactly 1 connection

### Point/Switch (W)
- Creates a railway point (switch/junction)
- Should have exactly 3 connections
- Supports coacting points

### Signal (G)
- Creates a standard signal
- Should have exactly 1 connection
- Can be standalone or tied to a point (pointsignal)

### Point Signal
- Signal tied to a specific point
- Should have NO connections (uses triggernode instead)
- Controls entry to the point leg

### Connect (C)
- Click first track, then click second track to connect
- Creates bidirectional connections
- Shown as dashed gray lines

### Delete (D)
- Click any track to delete it
- Automatically removes all connections

## Keyboard Shortcuts

- **S** - Select tool
- **P** - Pass node tool
- **B** - Buffer tool
- **W** - Point/switch tool
- **G** - Signal tool
- **C** - Connection tool
- **D** - Delete tool
- **F** - Fit to view
- **+/=** - Zoom in
- **-/_** - Zoom out
- **Ctrl+Z** - Undo
- **Ctrl+Shift+Z** - Redo
- **Delete/Backspace** - Delete selected track
- **Shift+Drag** - Pan canvas
- **Mouse Wheel** - Zoom in/out

## View Controls

- **Pan**: Hold Shift and drag, or use middle mouse button
- **Zoom**: Mouse wheel or +/- buttons
- **Fit to View**: Auto-zoom to show all tracks
- **Grid Snapping**: Toggle snap-to-grid (default: enabled)
- **Grid Size**: Adjust grid spacing in meters (default: 5m)

## Properties Panel

When a track is selected, you can edit:

- **ID**: Unique identifier (e.g., N1, B1, P1, S1)
- **Type**: Track type (can be changed)
- **Label**: Optional display label
- **Position**: X and Y coordinates in meters
- **Connections**: List of connected track IDs

### Type-Specific Properties

**Points**:
- **Coacting**: Comma-separated list of point IDs that work together
- **Connection Order**: CRITICAL! The order matters:
  - **Connection 1**: Always live leg (the through route)
  - **Connections 2 & 3**: Switchable legs (forming the diverging routes)
  - Use ▲▼ buttons to manually reorder connections
  - Click "♻ Auto-order by Angle" to automatically detect the correct order based on geometry
  - The auto-order finds the two legs forming an acute angle (switchable) and puts the other leg first (always live)

**Signals**:
- **Trigger Node**: Node ID to monitor (optional)
- **Direction Vector**: For arrow drawing (optional, e.g., "N1-N2")

**Point Signals**:
- **Point**: Associated point ID
- **Point Leg**: Target node ID for the signal
- **Direction Vector**: For arrow drawing (e.g., "N1-N2")
- **Trigger Node**: Node that triggers the signal
- **Leg Labels**: JSON object mapping leg IDs to display labels (e.g., `{"N2":"P","N1":"S"}`)

## JSON Structure

The layout creator generates JSON files with this structure:

```json
{
  "compass": "N",
  "comments": "Optional description",
  "tracks": {
    "N1": {
      "type": "pass",
      "position": [100, 50],
      "connections": ["N2", "P1"]
    },
    "B1": {
      "type": "buffer",
      "label": "Platform 1",
      "position": [200, 50],
      "connections": ["N2"]
    },
    "P1": {
      "type": "point",
      "label": "6A",
      "position": [150, 75],
      "connections": ["N1", "N3", "N4"],
      "coacting": ["P2"]
    },
    "S1": {
      "type": "signal",
      "label": "Signal 1",
      "position": [200, 50],
      "connections": ["N1"],
      "triggernode": "N1",
      "directionvector": "N1-N2"
    },
    "S2": {
      "type": "pointsignal",
      "label": "Point Signal",
      "position": [180, 60],
      "point": "P1",
      "pointleg": "N3",
      "directionvector": "N3-P1",
      "triggernode": "N3",
      "leglabels": {"N3": "M", "N4": "H"}
    }
  }
}
```

## Workflow

### Creating a New Layout

1. Click "New" to start fresh
2. Use placement tools to add tracks
3. Use the connection tool to link tracks
4. Adjust positions by dragging in select mode
5. Set labels and properties as needed
6. Click "Validate" to check for errors
7. Click "Export JSON" to save

### Editing an Existing Layout

1. Click "Import JSON" and select your layout file
2. Layout will load and auto-fit to view
3. Make changes using the tools
4. Re-validate and export when done

### Inserting Layouts

1. Click "➕ Insert JSON" and select a layout file
2. Set the insert position (X, Y coordinates)
3. Choose rotation (0°, 90°, 180°, 270°)
4. Set ID offset to avoid conflicts (e.g., +10 for N1→N11)
5. Preview shows what will be inserted
6. Click "Insert Layout" to add to current layout

**Insert Features:**
- **Position**: Place at cursor position or specify coordinates
- **Rotation**: Rotate the entire layout by 90° increments
- **ID Offset**: Automatically renumber tracks to avoid conflicts
- **Smart ID Mapping**: Updates all connections and references
- **Preview**: See exactly what will be inserted before applying

### Testing Your Layout

1. Export the layout from the creator
2. Save as `mylayout.json` in the railway simulator directory
3. Load in simulator: `index.html?layout=mylayout.json`

## Validation

The validator checks for:

### Errors (Must Fix)
- Invalid position formats
- References to non-existent tracks
- Missing required properties
- Invalid coacting or pointsignal references

### Warnings (Should Review)
- Non-bidirectional connections
- **Buffers**: Should have exactly 1 connection
- **Pass nodes**: Should have exactly 1 connection  
- **Points**: Should have exactly 3 connections
- **Signals**: Should have exactly 1 connection
- **Point signals**: Should have NO connections (use triggernode instead)
- Orphaned tracks (no connections)

## Point Connection Ordering

Railway points (switches) require a specific connection order to work correctly:

1. **First connection** - The "always live" leg (main through route)
2. **Second & third connections** - The switchable legs (diverging routes)

### Auto-Ordering Algorithm

When you add the third connection to a point, the tool automatically orders them using geometry:

1. Calculates the angle from the point to each connected track
2. Finds the pair of connections with the smallest angle between them (acute angle)
3. These two form the **switchable legs**
4. The remaining connection is the **always live leg** and is placed first

**Example:**
```
      N2 (siding)
       /
N1 --- P1 --- N3 (main line)
```

- Angle N1→P1 to N3: ~180° (straight through)
- Angle N1→P1 to N2: ~45° (diverging)
- Angle N2→P1 to N3: ~135°

The smallest angle is between N1 and N2 (~45°), so:
- **Always live**: N3 (the through route)
- **Switchable**: N1 and N2 (the diverging routes)
- **Correct order**: [N3, N1, N2]

### Manual Adjustment

If the auto-order doesn't match your layout:
1. Select the point
2. Use the ▲▼ buttons in the connections list to reorder
3. The order shown (1, 2, 3) matches the railway.js requirements

## Tips

- **Start with the main line**: Place buffers at each end, add pass nodes between them
- **Add junctions carefully**: Points need exactly 3 connections
- **Use meaningful IDs**: Rename IDs to match your layout (e.g., "StationPlatform1")
- **Check point ordering**: After connecting a point, verify the connection order is correct
- **Use auto-order**: The "♻ Auto-order by Angle" button usually gets it right
- **Validate often**: Catch errors early before the layout gets complex
- **Save frequently**: Export JSON backups as you work
- **Use grid snapping**: Keep tracks aligned to standard spacing
- **Test early**: Import into the simulator to verify connectivity

## Coordinate System

- Origin (0,0) is at the top-left
- Units are in meters (real-world scale)
- Positive X goes right
- Positive Y goes down
- Compass setting adjusts display orientation in the simulator

## Track Types

### Pass Node (type: "pass")
- Simple track node for straight or curved sections
- Can have any number of connections (usually 2)
- No special properties required

### Buffer (type: "buffer")
- End of track (terminus)
- Should have exactly 1 connection
- Usually has a label (e.g., "Platform 1")

### Point (type: "point")
- Railway switch/junction for diverging routes
- Must have exactly 3 connections
- Can specify coacting points that move together
- Usually has a label (e.g., "6A")

### Signal (type: "signal")
- Standard trackside signal
- Has connections like a pass node
- Usually has a label showing signal number

### Point Signal (type: "pointsignal")
- Signal tied to a specific point
- Controls entry to the point leg
- Requires: point, pointleg, directionvector, triggernode

## Common Patterns

### Simple Platform
```
B1 (Platform 1) --- N1 --- N2 --- B2 (Platform 2)
```

### Junction
```
        B1 (Siding)
         |
    N1 - P1 - N2 - B2 (Main Line)
         |
        N3 - B3 (Branch)
```

### Passing Loop
```
B1 --- N1 --- P1 ========= P2 --- N4 --- B2
                \         /
                 N2 - N3
```

## Troubleshooting

**Tracks won't connect**
- Make sure both tracks are placed
- Use the connection tool (C key)
- Click first track, then second track

**Can't see my layout**
- Click "Fit to View" button
- Try zooming out with mouse wheel
- Check that tracks have valid positions

**Export doesn't work**
- Check browser console for errors
- Try a different browser (Chrome/Firefox recommended)
- Make sure layout has at least one track

**Import fails**
- Verify JSON syntax is correct
- Check that "tracks" object exists
- Look for trailing commas or syntax errors

## Browser Compatibility

- Chrome/Edge: Full support
- Firefox: Full support
- Safari: Full support
- Mobile: Limited (desktop recommended)

## Known Limitations

- No curved track visualization (tracks shown as straight connections)
- No 3D view (use railway.js simulator for that)
- No multi-select or copy/paste
- No background image import
- No auto-routing between tracks

## Future Enhancements

Planned features:
- Template library for common junction patterns
- Auto-routing with curves
- Background image tracing
- Batch operations
- Track type conversion
- Connection suggestions based on proximity

## Support

For issues or questions about the railway simulator, contact Dial Solutions.

## Version History

- v1.0 (2025) - Initial release
  - Basic track placement and connection
  - Import/export JSON
  - Validation
  - Undo/redo support

