{
  "id": "exp-003",
  "slug": "exp-003-door-swing-interference",
  "algorithm": "2.0.0",
  "legacyAlgorithm": "1.0.0",
  "geometrySha256": "313c4fd15b13941f5b189a75e732cbb03aef2a9c75d65f1a1b7d581d925b7976",
  "generated": "2026-11-07",
  "generator": "tools/run_experiments.mjs",
  "verifier": "tools/verify_experiments.py",
  "kind": "simulation",
  "cases": [
    {
      "id": "chair-start-in",
      "label": {
        "ko": "의자, 왼쪽 경첩·안쪽 열림",
        "en": "Chair, left hinge, opens in"
      },
      "preset": "x3chairStartIn",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "chair",
            "x": 175,
            "y": 230,
            "w": 55,
            "h": 55
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "start",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          110,
          350
        ],
        "radius": 80,
        "closedEnd": [
          190,
          350
        ],
        "openEnd": [
          110,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          false
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 80,
          "step": 5,
          "tight": 0,
          "items": [
            "connected"
          ],
          "pathPoints": 3,
          "path": [
            [
              140,
              320
            ],
            [
              125,
              305
            ],
            [
              125,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          false
        ],
        "sampleArea": [
          0.0
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": false,
          "actual": false,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "chair-end-in",
      "label": {
        "ko": "의자, 오른쪽 경첩·안쪽 열림",
        "en": "Chair, right hinge, opens in"
      },
      "preset": "x3chairEndIn",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "chair",
            "x": 175,
            "y": 230,
            "w": 55,
            "h": 55
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "end",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          190,
          350
        ],
        "radius": 80,
        "closedEnd": [
          110,
          350
        ],
        "openEnd": [
          190,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          true
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 80,
          "step": 5,
          "tight": 0,
          "items": [
            "connected"
          ],
          "pathPoints": 3,
          "path": [
            [
              140,
              320
            ],
            [
              125,
              305
            ],
            [
              125,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          true
        ],
        "sampleArea": [
          218.0
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": true,
          "actual": true,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "chair-end-out",
      "label": {
        "ko": "의자, 오른쪽 경첩·바깥 열림",
        "en": "Chair, right hinge, opens out"
      },
      "preset": "x3chairEndOut",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "chair",
            "x": 175,
            "y": 230,
            "w": 55,
            "h": 55
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "end",
          "swing": "out"
        }
      },
      "arc": {
        "hinge": [
          190,
          350
        ],
        "radius": 80,
        "closedEnd": [
          110,
          350
        ],
        "openEnd": [
          190,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": false
      },
      "actual": {
        "hits": [
          false
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 80,
          "step": 5,
          "tight": 0,
          "items": [
            "connected"
          ],
          "pathPoints": 3,
          "path": [
            [
              140,
              320
            ],
            [
              125,
              305
            ],
            [
              125,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          false
        ],
        "sampleArea": [
          0.0
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": false,
          "actual": false,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "wardrobe-jamb",
      "label": {
        "ko": "옷장이 문틀 선에 맞닿음",
        "en": "Wardrobe flush with the door jamb"
      },
      "preset": "x3wardrobeJamb",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "wardrobe",
            "x": 190,
            "y": 290,
            "w": 100,
            "h": 60
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "end",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          190,
          350
        ],
        "radius": 80,
        "closedEnd": [
          110,
          350
        ],
        "openEnd": [
          190,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          false
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 80,
          "step": 5,
          "tight": 0,
          "items": [
            "connected"
          ],
          "pathPoints": 2,
          "path": [
            [
              140,
              320
            ],
            [
              140,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          false
        ],
        "sampleArea": [
          0.0
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": false,
          "actual": false,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "wardrobe-10cm",
      "label": {
        "ko": "옷장이 문 앞으로 10cm 들어옴",
        "en": "Wardrobe 10 cm into the doorway"
      },
      "preset": "x3wardrobe10cm",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "wardrobe",
            "x": 180,
            "y": 290,
            "w": 100,
            "h": 60
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "start",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          110,
          350
        ],
        "radius": 80,
        "closedEnd": [
          190,
          350
        ],
        "openEnd": [
          110,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          true
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 80,
          "step": 5,
          "tight": 0,
          "items": [
            "connected"
          ],
          "pathPoints": 2,
          "path": [
            [
              140,
              320
            ],
            [
              140,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          true
        ],
        "sampleArea": [
          261.5
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": true,
          "actual": true,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "tangent",
      "label": {
        "ko": "선반 모서리가 문짝 궤적에 정확히 닿음",
        "en": "Shelf corner exactly on the arc"
      },
      "preset": "x3tangent",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "shelf",
            "x": 158,
            "y": 246,
            "w": 40,
            "h": 40
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "start",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          110,
          350
        ],
        "radius": 80,
        "closedEnd": [
          190,
          350
        ],
        "openEnd": [
          110,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          false
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 76.942,
          "step": 5,
          "tight": 3,
          "items": [
            "connected"
          ],
          "pathPoints": 9,
          "path": [
            [
              140,
              320
            ],
            [
              135,
              320
            ],
            [
              130,
              316
            ],
            [
              128,
              315
            ],
            [
              125,
              310
            ],
            [
              120,
              305
            ],
            [
              120,
              295
            ],
            [
              115,
              290
            ],
            [
              115,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          false
        ],
        "sampleArea": [
          0.0
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": false,
          "actual": false,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "tangent-1cm",
      "label": {
        "ko": "같은 선반을 1cm씩 문 쪽으로",
        "en": "Same shelf, 1 cm closer each way"
      },
      "preset": "x3tangent1cm",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "shelf",
            "x": 157,
            "y": 247,
            "w": 40,
            "h": 40
          }
        ],
        "door": {
          "wall": "bottom",
          "offset": 110,
          "width": 80,
          "hinge": "start",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          110,
          350
        ],
        "radius": 80,
        "closedEnd": [
          190,
          350
        ],
        "openEnd": [
          110,
          270
        ],
        "box": {
          "x": 110,
          "y": 270,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          true
        ],
        "route": {
          "status": "connected",
          "reason": "ok",
          "bottleneck": 74.087,
          "step": 5,
          "tight": 9,
          "items": [
            "connected"
          ],
          "pathPoints": 9,
          "path": [
            [
              140,
              320
            ],
            [
              135,
              317
            ],
            [
              130,
              315
            ],
            [
              127,
              310
            ],
            [
              125,
              310
            ],
            [
              120,
              305
            ],
            [
              120,
              290
            ],
            [
              115,
              285
            ],
            [
              115,
              95
            ]
          ]
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          true
        ],
        "sampleArea": [
          2.06
        ],
        "routeStart": true,
        "route": "connected",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": true,
          "actual": true,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "connected",
          "actual": "connected",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": true,
          "actual": true,
          "pass": true
        }
      ],
      "pass": true
    },
    {
      "id": "left-wall",
      "label": {
        "ko": "왼쪽 벽 문, 책상이 문 앞",
        "en": "Door in the left wall, desk in front"
      },
      "preset": "x3leftWall",
      "input": {
        "room": {
          "w": 300,
          "h": 350
        },
        "items": [
          {
            "type": "desk",
            "x": 50,
            "y": 30,
            "w": 105,
            "h": 50
          }
        ],
        "door": {
          "wall": "left",
          "offset": 20,
          "width": 80,
          "hinge": "start",
          "swing": "in"
        }
      },
      "arc": {
        "hinge": [
          0,
          20
        ],
        "radius": 80,
        "closedEnd": [
          0,
          100
        ],
        "openEnd": [
          80,
          20
        ],
        "box": {
          "x": 0,
          "y": 20,
          "w": 80,
          "h": 80
        },
        "swingsIn": true
      },
      "actual": {
        "hits": [
          true
        ],
        "route": {
          "status": "blocked",
          "reason": "door-blocked",
          "bottleneck": null,
          "step": 5,
          "tight": 0,
          "items": [
            "blocked"
          ],
          "pathPoints": 0,
          "path": []
        }
      },
      "legacy": {
        "note": "v1 had a fixed door and no swing check"
      },
      "expected": {
        "hits": [
          true
        ],
        "sampleArea": [
          1003.19
        ],
        "routeStart": false,
        "route": "blocked",
        "method": "0.25 cm interior sampling of the quarter disc + 1 cm raster flood"
      },
      "checks": [
        {
          "name": "swing hits piece 1",
          "expected": true,
          "actual": true,
          "pass": true
        },
        {
          "name": "route = raster",
          "expected": "blocked",
          "actual": "blocked",
          "pass": true
        },
        {
          "name": "door start free",
          "expected": false,
          "actual": false,
          "pass": true
        }
      ],
      "pass": true
    }
  ],
  "verification": {
    "cases": 8,
    "passed": 8,
    "failed": 0,
    "checks": 24
  }
}
