delete historic mapping and client

This commit is contained in:
Daniel Roth 2026-05-05 15:45:36 +00:00
parent 452d7512df
commit d3ca6bc7ff
12 changed files with 0 additions and 2433 deletions

View file

@ -1,51 +0,0 @@
import requests
from backend.magic_plan.models import (
MagicPlanPlan,
MagicPlanSummary,
MagicPlanXMLDetail,
MagicPlanXMLSummary,
)
from backend.magic_plan.xml_parser import parse_magicplan_xml
def _parse_xml_summary(data: dict[str, object]) -> MagicPlanXMLSummary:
return MagicPlanXMLSummary(
id=str(data.get("id", "")),
project_id=str(data.get("project_id", "")),
name=str(data.get("name", "")),
address=str(data.get("address", "")),
creation_date=str(data.get("creation_date", "")),
update_date=str(data.get("update_date", "")),
workgroup_id=str(data.get("workgroup_id", "")),
team_id=str(data.get("team_id", "")),
created_by=str(data.get("created_by", "")),
thumbnail_url=str(data.get("thumbnail_url", "")),
public_url=str(data.get("public_url", "")),
cloud_url=str(data.get("cloud_url", "")),
url_3d=str(data.get("3d_url", "")),
)
class MagicPlanClient:
BASE_URL = "https://cloud.magicplan.app/api/v2"
def __init__(self, api_key: str) -> None:
self._session = requests.Session()
self._session.headers.update({"Authorization": f"Bearer {api_key}"})
def get_plans(self, _project_id: str) -> list[MagicPlanSummary]:
raise NotImplementedError
def get_plan_xml(self, plan_id: str) -> MagicPlanXMLDetail:
resp = self._session.get(f"{self.BASE_URL}/plans/get/{plan_id}")
resp.raise_for_status()
data: dict[str, object] = resp.json()["data"]
plan_data = data["plan"] # type: ignore[index]
detail_data = data["plan_detail"] # type: ignore[index]
summary = _parse_xml_summary(plan_data) # type: ignore[arg-type]
plan_xml = parse_magicplan_xml(detail_data["magicplan_format_xml"]) # type: ignore[index]
return MagicPlanXMLDetail(summary=summary, plan_xml=plan_xml)
def get_plan(self, _plan_id: str) -> MagicPlanPlan:
raise NotImplementedError

View file

@ -1,417 +0,0 @@
import re
from dataclasses import dataclass
from typing import Any, Optional
def _camel_to_snake(name: str) -> str:
return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
def parse_displayable_fields(fields: list[dict[str, Any]]) -> dict[str, str]:
result: dict[str, str] = {}
for f in fields:
if f.get("type_as_string") == "sectionTitle":
continue
v: dict[str, Any] = f.get("value") or {}
if not v.get("has_value"):
continue
result[_camel_to_snake(str(f["id"]))] = str(v["value"])
return result
# ---------------------------------------------------------------------------
# XML dataclasses (sourced from MagicPlan Exchange XML format)
# ---------------------------------------------------------------------------
@dataclass
class MagicPlanXMLRoomPoint:
snapped_x: float
snapped_y: float
height: float
uid: str
values: dict[str, str]
@dataclass
class MagicPlanXMLWallPoint:
"""Point in <exploded><wall> — absolute coords, no uid or values."""
x: float
y: float
height: float
@dataclass
class MagicPlanXMLDoor:
"""Door in <floorRoom> context — wall-relative position."""
wall_point_index: int
type: str
u: float
width: float
depth: float
height: float
orientation: int
snapped_type: str
snapped_position: float
snapped_width: float
snapped_depth: float
snapped_height: float
snapped_orientation: int
inset_x: float
inset_y: float
inset_z: float
symbol_instance: str
twin_wall_item_uid: Optional[str] = None
@dataclass
class MagicPlanXMLWindow:
"""Window in <floorRoom> context — wall-relative position."""
wall_point_index: int
type: str
u: float
width: float
depth: float
height: float
orientation: int
snapped_type: str
snapped_position: float
snapped_width: float
snapped_depth: float
snapped_height: float
snapped_orientation: int
inset_x: float
inset_y: float
inset_z: float
symbol_instance: str
@dataclass
class MagicPlanXMLExplodedOpening:
"""Door or window in <exploded> context — absolute coords, no snapped* fields."""
type: str
x1: float
y1: float
x2: float
y2: float
width: float
depth: float
height: float
inset_x: float
inset_y: float
orientation: int
symbol_instance: str
@dataclass
class MagicPlanXMLFurniture:
type: str
x: float
y: float
snapped_x: float
snapped_y: float
angle: float
width: float
depth: float
height: float
snapped_width: float
snapped_depth: float
snapped_height: float
size_lock_0: str
size_lock_1: str
size_lock_2: str
symbol_instance: str
@dataclass
class MagicPlanXMLMainDimension:
from_point: int
to_point: int
dir_x: float
dir_y: float
value: float
actual_value: float
is_set: bool
@dataclass
class MagicPlanXMLExplodedWall:
wall_type: str
points: list[MagicPlanXMLWallPoint]
@dataclass
class MagicPlanXMLExploded:
walls: list[MagicPlanXMLExplodedWall]
doors: list[MagicPlanXMLExplodedOpening]
windows: list[MagicPlanXMLExplodedOpening]
furniture: list[MagicPlanXMLFurniture]
@dataclass
class MagicPlanXMLSymbolInstance:
id: str
uid: str
parent_uid: str
symbol: str
values: dict[str, str]
@dataclass
class MagicPlanXMLRoom:
uid: str
type: str
x: float
y: float
rotation: float
was_modified: bool
linked_room_0: str
linked_room_1: str
area: float
perimeter: float
values: dict[str, str]
points: list[MagicPlanXMLRoomPoint]
doors: list[MagicPlanXMLDoor]
windows: list[MagicPlanXMLWindow]
furniture: list[MagicPlanXMLFurniture]
main_dimensions: list[MagicPlanXMLMainDimension]
@dataclass
class MagicPlanXMLFloor:
uid: str
name: str
floor_type: str
rotation: float
compass_angle: float
area_without_walls: float
area_with_interior_walls_only: float
area_with_walls: float
symbol_instance: MagicPlanXMLSymbolInstance
rooms: list[MagicPlanXMLRoom]
furniture: list[MagicPlanXMLFurniture]
exploded: MagicPlanXMLExploded
@dataclass
class MagicPlanXMLSummary:
"""Plan metadata returned by the list-plans API endpoint (old string-address format)."""
id: str
project_id: str
name: str
address: str
creation_date: str
update_date: str
workgroup_id: str
team_id: str
created_by: str
thumbnail_url: str
public_url: str
cloud_url: str
url_3d: str
@dataclass
class MagicPlanXMLDetail:
"""Full plan response: summary metadata + parsed XML plan."""
summary: MagicPlanXMLSummary
plan_xml: "MagicPlanXMLPlan"
@dataclass
class MagicPlanXMLPlan:
id: str
uid: str
name: str
type: str
interior_wall_width: float
exterior_wall_width: float
schematic: bool
has_land_survey_address: bool
last_patch_identifier: str
last_roll_identifier: str
values: dict[str, str]
floors: list[MagicPlanXMLFloor]
interior_room_floors: list[MagicPlanXMLFloor]
# ---------------------------------------------------------------------------
# JSON dataclasses (sourced from GET Plan API JSON response)
# ---------------------------------------------------------------------------
@dataclass
class MagicPlanWall:
uid: str
symbol_id: str
length: float
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanWallItem:
"""Door or window — distinguished by symbol_id."""
uid: str
symbol_id: str
symbol_name: str
width: float
depth: float
height: float
pos_x: float
pos_y: float
pos_z: float
rotation_z: float
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanFurniture:
uid: str
symbol_id: str
symbol_name: str
width: float
depth: float
height: float
pos_x: float
pos_y: float
pos_z: float
rotation_z: float
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanRoom:
uid: str
name: str
area: float
perimeter: float
height: float
width: float
volume: float
dimensions: str
door_count: int
window_count: int
walls_surface: float
walls_surface_without_openings: float
doors_surface: float
windows_surface: float
wall_items: list[MagicPlanWallItem]
furnitures: list[MagicPlanFurniture]
walls: list[MagicPlanWall]
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanFloor:
uid: str
name: str
floor_type: str
area: float
perimeter: float
area_without_walls: float
area_with_interior_walls_only: float
area_with_walls: float
wall_count: int
wall_count_with_interior_walls: int
door_count: int
window_count: int
room_count: int
furniture_count: int
doors_surface: float
walls_surface: float
walls_surface_without_openings: float
windows_surface: float
volume: float
rooms: list[MagicPlanRoom]
furnitures: list[MagicPlanFurniture]
symbol_instances: list[MagicPlanFurniture]
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanPlan:
"""GET /plans/{id} — merged data.plan + data.plan_detail.plan."""
id: str
project_id: str
uid: str
name: str
area: float
perimeter: float
area_without_walls: float
area_with_interior_walls_only: float
area_with_walls: float
wall_count: int
door_count: int
window_count: int
room_count: int
furniture_count: int
floor_count: int
doors_surface: float
walls_surface: float
walls_surface_without_openings: float
windows_surface: float
volume: float
living_area: float
below_grade_living_area: float
above_grade_living_area: float
address_street: Optional[str]
address_postal_code: Optional[str]
address_city: Optional[str]
address_country: Optional[str]
address_longitude: Optional[float]
address_latitude: Optional[float]
creation_date: str
update_date: str
workgroup_id: str
team_id: str
created_by_id: str
created_by_firstname: Optional[str]
created_by_lastname: Optional[str]
created_by_email: str
thumbnail_url: str
public_url: str
cloud_url: str
url_3d: str
floors: list[MagicPlanFloor]
fields: dict[str, str]
custom_fields: dict[str, str]
@dataclass
class MagicPlanSummary:
"""GET /plans list — lightweight, flat address and creator fields."""
id: str
project_id: str
name: str
address_street: Optional[str]
address_postal_code: Optional[str]
address_city: Optional[str]
address_country: Optional[str]
address_longitude: Optional[float]
address_latitude: Optional[float]
creation_date: str
update_date: str
workgroup_id: str
team_id: str
created_by_id: str
created_by_firstname: Optional[str]
created_by_lastname: Optional[str]
created_by_email: str
thumbnail_url: str
public_url: str
cloud_url: str
url_3d: str

View file

@ -1,195 +0,0 @@
import json
import xml.etree.ElementTree as ET
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
import requests
from backend.magic_plan.magic_plan_client import MagicPlanClient
from backend.magic_plan.models import MagicPlanXMLDetail, MagicPlanXMLPlan, MagicPlanXMLSummary
FIXTURES = Path(__file__).parent.parent
API_KEY = "test-api-key"
PLAN_ID = "b66bb427-33fe-4865-8d57-bad7d9d3f2e5"
PROJECT_ID = "test-project-123"
BASE_URL = "https://cloud.magicplan.app/api/v2"
def _load_xml() -> str:
content = (FIXTURES / "xml_example.xml").read_text().strip()
try:
ET.fromstring(content)
return content
except ET.ParseError:
return json.loads(content) # type: ignore[return-value]
def _summary_payload(plan_id: str = PLAN_ID, index: int = 0) -> dict[str, str]:
return {
"id": plan_id,
"project_id": PROJECT_ID,
"name": f"Plan {index}",
"address": f"Address {index}",
"creation_date": "2026-04-20",
"update_date": "2026-04-20",
"workgroup_id": "wg-123",
"team_id": "team-123",
"created_by": "user-123",
"thumbnail_url": "https://example.com/thumb.jpg",
"public_url": "https://example.com/plan",
"cloud_url": "https://example.com/cloud",
"3d_url": "https://example.com/3d",
}
def _get_plan_response(xml_str: str) -> dict: # type: ignore[type-arg]
return {
"message": "success",
"data": {
"plan": _summary_payload(),
"plan_detail": {
"magicplan_format_xml": xml_str,
},
},
}
def _get_plans_response(plan_ids: list[str]) -> dict: # type: ignore[type-arg]
return {
"message": "success",
"data": [_summary_payload(pid, i) for i, pid in enumerate(plan_ids)],
}
@pytest.fixture
def mock_session() -> MagicMock:
with patch("backend.magic_plan.magic_plan_client.requests.Session") as MockSession:
session: MagicMock = MagicMock()
MockSession.return_value = session
yield session
@pytest.fixture
def client(mock_session: MagicMock) -> MagicPlanClient:
return MagicPlanClient(api_key=API_KEY)
# ---------------------------------------------------------------------------
# Initialisation
# ---------------------------------------------------------------------------
class TestInit:
def test_sets_bearer_auth_header(self, mock_session: MagicMock) -> None:
MagicPlanClient(api_key=API_KEY)
mock_session.headers.update.assert_called_once_with(
{"Authorization": f"Bearer {API_KEY}"}
)
# ---------------------------------------------------------------------------
# get_plan_xml
# ---------------------------------------------------------------------------
class TestGetPlanXml:
def test_calls_correct_url(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
client.get_plan_xml(PLAN_ID)
mock_session.get.assert_called_once_with(f"{BASE_URL}/plans/get/{PLAN_ID}")
def test_calls_raise_for_status(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
client.get_plan_xml(PLAN_ID)
mock_session.get.return_value.raise_for_status.assert_called_once()
def test_returns_magic_plan_detail(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert isinstance(result, MagicPlanXMLDetail)
def test_detail_contains_summary(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert isinstance(result.summary, MagicPlanXMLSummary)
def test_detail_summary_id(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert result.summary.id == PLAN_ID
def test_detail_summary_project_id(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert result.summary.project_id == PROJECT_ID
def test_detail_contains_parsed_plan(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert isinstance(result.plan_xml, MagicPlanXMLPlan)
def test_plan_xml_id_matches_xml(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert result.plan_xml.id == PLAN_ID
def test_plan_xml_floor_count(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plan_response(_load_xml())
result = client.get_plan_xml(PLAN_ID)
assert len(result.plan_xml.floors) == 2
def test_raises_on_http_error(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.raise_for_status.side_effect = requests.HTTPError("404")
with pytest.raises(requests.HTTPError):
client.get_plan_xml(PLAN_ID)
# ---------------------------------------------------------------------------
# get_plans
# ---------------------------------------------------------------------------
class TestGetPlans:
def test_calls_correct_url(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([])
client.get_plans(PROJECT_ID)
mock_session.get.assert_called_once_with(
f"{BASE_URL}/plans", params={"project_id": PROJECT_ID}
)
def test_calls_raise_for_status(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([])
client.get_plans(PROJECT_ID)
mock_session.get.return_value.raise_for_status.assert_called_once()
def test_returns_list_of_summaries(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([PLAN_ID, "other-id"])
result = client.get_plans(PROJECT_ID)
assert len(result) == 2
assert all(isinstance(s, MagicPlanXMLSummary) for s in result)
def test_summary_id(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([PLAN_ID])
result = client.get_plans(PROJECT_ID)
assert result[0].id == PLAN_ID
def test_summary_project_id(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([PLAN_ID])
result = client.get_plans(PROJECT_ID)
assert result[0].project_id == PROJECT_ID
def test_summary_name(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([PLAN_ID])
result = client.get_plans(PROJECT_ID)
assert result[0].name == "Plan 0"
def test_returns_empty_list_when_no_plans(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.json.return_value = _get_plans_response([])
result = client.get_plans(PROJECT_ID)
assert result == []
def test_raises_on_http_error(self, client: MagicPlanClient, mock_session: MagicMock) -> None:
mock_session.get.return_value.raise_for_status.side_effect = requests.HTTPError("401")
with pytest.raises(requests.HTTPError):
client.get_plans(PROJECT_ID)

View file

@ -1,50 +0,0 @@
import pytest
from backend.magic_plan.models import parse_displayable_fields
SECTION_TITLE_FIELD = {
"id": "measures.section.title",
"type_as_string": "sectionTitle",
"value": {"has_value": False, "value": ""},
}
CEILING_HEIGHT_FIELD = {
"id": "ceilingHeight",
"type_as_string": "distance",
"value": {"has_value": True, "value": "2.45"},
}
NO_VALUE_FIELD = {
"id": "label",
"type_as_string": "text",
"value": {"has_value": False, "value": ""},
}
class TestParseDisplayableFields:
def test_excludes_section_titles(self) -> None:
result = parse_displayable_fields([SECTION_TITLE_FIELD])
assert result == {}
def test_excludes_fields_without_value(self) -> None:
result = parse_displayable_fields([NO_VALUE_FIELD])
assert result == {}
def test_includes_field_with_value(self) -> None:
result = parse_displayable_fields([CEILING_HEIGHT_FIELD])
assert "ceiling_height" in result
assert result["ceiling_height"] == "2.45"
def test_snake_cases_camel_key(self) -> None:
result = parse_displayable_fields([CEILING_HEIGHT_FIELD])
assert "ceiling_height" in result
assert "ceilingHeight" not in result
def test_mixed_fields(self) -> None:
result = parse_displayable_fields([SECTION_TITLE_FIELD, CEILING_HEIGHT_FIELD, NO_VALUE_FIELD])
assert result == {"ceiling_height": "2.45"}
def test_empty_list(self) -> None:
assert parse_displayable_fields([]) == {}

View file

@ -1,461 +0,0 @@
import json
import math
import xml.etree.ElementTree as ET
from pathlib import Path
import pytest
from backend.magic_plan.models import MagicPlanXMLPlan
from backend.magic_plan.xml_parser import parse_magicplan_xml
FIXTURES = Path(__file__).parent.parent
def _load(filename: str) -> str:
content = (FIXTURES / filename).read_text().strip()
try:
ET.fromstring(content)
return content
except ET.ParseError:
return json.loads(content) # type: ignore[return-value]
@pytest.fixture(scope="module")
def plan1() -> MagicPlanXMLPlan:
return parse_magicplan_xml(_load("xml_example.xml"))
@pytest.fixture(scope="module")
def plan2() -> MagicPlanXMLPlan:
return parse_magicplan_xml(_load("xml_example_2.xml"))
@pytest.fixture(scope="module")
def plan3() -> MagicPlanXMLPlan:
return parse_magicplan_xml(_load("xml_example_3.xml"))
# ---------------------------------------------------------------------------
# Plan-level attributes
# ---------------------------------------------------------------------------
class TestPlanAttributes:
def test_id(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.id == "b66bb427-33fe-4865-8d57-bad7d9d3f2e5"
def test_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.uid == "69e5fafc.0890b3ff"
def test_name(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.name == "275 Carr Hill Rd NE9 5ND"
def test_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.type == "0"
def test_interior_wall_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.interior_wall_width, 0.12)
def test_exterior_wall_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.exterior_wall_width, 0.25)
def test_schematic_false(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.schematic is False
def test_has_land_survey_address_false(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.has_land_survey_address is False
def test_last_patch_identifier(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.last_patch_identifier == "0"
def test_last_roll_identifier(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.last_roll_identifier == "0"
class TestPlanValues:
def test_date(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.values["date"] == "2026-04-20"
def test_statistics_area_of_height(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.values["statistics.areaOfHeight"] == "2.134"
def test_statistics_basement_account(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.values["statistics.basement.account"] == "100"
def test_statistics_exterior_walls(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.values["statistics.exteriorWalls"] == "0"
def test_statistics_interior_walls(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.values["statistics.interiorWalls"] == "0"
def test_plan2_date(self, plan2: MagicPlanXMLPlan) -> None:
assert plan2.values["date"] == "2026-04-16"
# ---------------------------------------------------------------------------
# Floors
# ---------------------------------------------------------------------------
class TestFloors:
def test_floor_count_plan1(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors) == 2
def test_floor_count_plan2(self, plan2: MagicPlanXMLPlan) -> None:
assert len(plan2.floors) == 1
def test_floor_count_plan3(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors) == 1
def test_ground_floor_name(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].name == "Ground Floor"
def test_first_floor_name(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[1].name == "1st Floor"
def test_ground_floor_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].floor_type == "0"
def test_upper_floor_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[1].floor_type == "1"
def test_floor_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].uid == "69e5fb20.4feef7ff"
def test_ground_floor_area_without_walls(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].area_without_walls, 40.20736)
def test_ground_floor_area_with_walls(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].area_with_walls, 48.40593)
def test_ground_floor_area_with_interior_walls_only(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].area_with_interior_walls_only, 40.67878)
def test_floor_rotation(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rotation, 0.0, abs_tol=1e-9)
def test_floor_compass_angle(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].compass_angle, -1.0)
# ---------------------------------------------------------------------------
# Symbol instance
# ---------------------------------------------------------------------------
class TestSymbolInstance:
def test_symbol_instance_id(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].symbol_instance.id == "floor"
def test_symbol_instance_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].symbol_instance.uid == "69e5fb20.4feef7ff"
def test_symbol_instance_symbol(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].symbol_instance.symbol == "floor"
def test_symbol_instance_parent_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].symbol_instance.parent_uid == ""
def test_symbol_instance_ceiling_height_value(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].symbol_instance.values["ceilingHeight"] == "2.323164"
# ---------------------------------------------------------------------------
# Rooms
# ---------------------------------------------------------------------------
class TestRooms:
def test_ground_floor_room_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms) == 2
def test_first_floor_room_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[1].rooms) == 4
def test_plan3_room_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].rooms) == 9
def test_room_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].type == "Kitchen"
def test_room_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].uid == "69e5fbc8.71027bff"
def test_room_area(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].area, 10.78332)
def test_room_perimeter(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].perimeter, 13.32812)
def test_room_x(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].x, 3.80616)
def test_room_y(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].y, 0.23162)
def test_room_rotation(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].rotation, 0.0, abs_tol=1e-9)
def test_room_was_modified_false(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].was_modified is False
def test_room_was_modified_true(self, plan1: MagicPlanXMLPlan) -> None:
closet = plan1.floors[1].rooms[1]
assert closet.type == "Closet"
assert closet.was_modified is True
def test_room_linked_room_0(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].linked_room_0 == "-1"
def test_room_linked_room_1(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].linked_room_1 == "-1"
def test_room_ceiling_height_value(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].values["ceilingHeight"] == "2.323164"
def test_room_label_value(self, plan2: MagicPlanXMLPlan) -> None:
dining = plan2.floors[0].rooms[1]
assert dining.type == "Dining Room"
assert dining.values["label"] == "Room"
def test_room_no_label_when_absent(self, plan1: MagicPlanXMLPlan) -> None:
assert "label" not in plan1.floors[0].rooms[0].values
# ---------------------------------------------------------------------------
# Room points
# ---------------------------------------------------------------------------
class TestRoomPoints:
def test_kitchen_point_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[0].points) == 4
def test_living_room_point_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[1].points) == 8
def test_point_snapped_x(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].points[0].snapped_x, -1.44357)
def test_point_snapped_y(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].points[0].snapped_y, -2.00846)
def test_point_height(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].points[0].height, 2.323164)
def test_point_uid(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].points[0].uid == "69e5fbc8.710363ff"
def test_point_values_empty_when_absent(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].points[0].values == {}
# ---------------------------------------------------------------------------
# Doors (floorRoom context)
# ---------------------------------------------------------------------------
class TestDoors:
def test_kitchen_door_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[0].doors) == 5
def test_corridor_door_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].rooms[0].doors) == 9
def test_door_wall_point_index(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].doors[0].wall_point_index == 3
def test_door_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].doors[0].type == "4"
def test_door_u(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].doors[0].u, 0.47585)
def test_door_snapped_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].doors[0].snapped_width, 1.82394)
def test_door_snapped_height(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].doors[0].snapped_height, 2.08411)
def test_door_snapped_orientation(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].doors[0].snapped_orientation == 3
def test_door_twin_wall_item_uid_present(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].doors[0].twin_wall_item_uid == "69e5fbc8.74614fff"
def test_door_twin_wall_item_uid_absent(self, plan2: MagicPlanXMLPlan) -> None:
assert plan2.floors[0].rooms[0].doors[0].twin_wall_item_uid is None
def test_door_symbol_instance(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].doors[0].symbol_instance == "W-0-0"
def test_door_inset_x(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].doors[0].inset_x, 0.0, abs_tol=1e-9)
# ---------------------------------------------------------------------------
# Windows (floorRoom context)
# ---------------------------------------------------------------------------
class TestWindows:
def test_kitchen_window_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[0].windows) == 1
def test_corridor_window_count_zero(self, plan3: MagicPlanXMLPlan) -> None:
corridor = plan3.floors[0].rooms[0]
assert corridor.type == "Corridor"
assert len(corridor.windows) == 0
def test_window_wall_point_index(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].windows[0].wall_point_index == 1
def test_window_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].windows[0].type == "1"
def test_window_u(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].windows[0].u, 0.68463)
def test_window_snapped_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].windows[0].snapped_width, 1.71972)
def test_window_snapped_height(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].rooms[0].windows[0].snapped_height, 0.94940)
def test_window_symbol_instance(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].rooms[0].windows[0].symbol_instance == "W-0-2"
# ---------------------------------------------------------------------------
# Furniture (room-level)
# ---------------------------------------------------------------------------
class TestRoomFurniture:
def test_kitchen_furniture_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[0].furniture) == 5
def test_bathroom_furniture_count_zero(self, plan1: MagicPlanXMLPlan) -> None:
bathroom = plan1.floors[1].rooms[0]
assert bathroom.type == "Bathroom"
assert len(bathroom.furniture) == 0
def test_furniture_type(self, plan1: MagicPlanXMLPlan) -> None:
assert isinstance(plan1.floors[0].rooms[0].furniture[0].type, str)
def test_furniture_symbol_instance(self, plan1: MagicPlanXMLPlan) -> None:
assert isinstance(plan1.floors[0].rooms[0].furniture[0].symbol_instance, str)
# ---------------------------------------------------------------------------
# Floor-level furniture (example 3)
# ---------------------------------------------------------------------------
class TestFloorLevelFurniture:
def test_floor_furniture_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].furniture) == 1
def test_floor_furniture_x(self, plan3: MagicPlanXMLPlan) -> None:
assert math.isclose(plan3.floors[0].furniture[0].x, -2.09376)
def test_floor_furniture_y(self, plan3: MagicPlanXMLPlan) -> None:
assert math.isclose(plan3.floors[0].furniture[0].y, 3.13664)
def test_floor_furniture_absent_plan1(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].furniture) == 0
# ---------------------------------------------------------------------------
# Main dimensions
# ---------------------------------------------------------------------------
class TestMainDimensions:
def test_main_dimension_count(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].rooms[0].main_dimensions) == 2
def test_main_dimension_from_point(self, plan1: MagicPlanXMLPlan) -> None:
assert isinstance(plan1.floors[0].rooms[0].main_dimensions[0].from_point, int)
def test_main_dimension_is_set(self, plan1: MagicPlanXMLPlan) -> None:
assert isinstance(plan1.floors[0].rooms[0].main_dimensions[0].is_set, bool)
# ---------------------------------------------------------------------------
# Exploded section
# ---------------------------------------------------------------------------
class TestExploded:
def test_exploded_wall_count_ground_floor(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].exploded.walls) == 11
def test_exploded_door_count_ground_floor(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].exploded.doors) == 6
def test_exploded_window_count_ground_floor(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.floors[0].exploded.windows) == 2
def test_exploded_wall_type(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].exploded.walls[0].wall_type == "exterior"
def test_exploded_wall_points(self, plan1: MagicPlanXMLPlan) -> None:
pts = plan1.floors[0].exploded.walls[0].points
assert len(pts) == 2
assert math.isclose(pts[0].x, 2.363)
assert math.isclose(pts[0].y, -1.778)
assert math.isclose(pts[0].height, 2.323164)
def test_exploded_door_x1(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.doors[0].x1, 5.24973)
def test_exploded_door_y1(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.doors[0].y1, -1.333153)
def test_exploded_door_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.doors[0].width, 0.773)
def test_exploded_door_height(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.doors[0].height, 2.02225)
def test_exploded_door_symbol_instance(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].exploded.doors[0].symbol_instance == "W-0-1"
def test_exploded_window_x1(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.windows[0].x1, 5.24973)
def test_exploded_window_width(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.windows[0].width, 1.71972)
def test_exploded_window_height(self, plan1: MagicPlanXMLPlan) -> None:
assert math.isclose(plan1.floors[0].exploded.windows[0].height, 0.949396)
def test_exploded_window_symbol_instance(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.floors[0].exploded.windows[0].symbol_instance == "W-0-2"
def test_plan3_exploded_wall_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].exploded.walls) == 33
def test_plan3_exploded_door_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].exploded.doors) == 12
def test_plan3_exploded_window_count(self, plan3: MagicPlanXMLPlan) -> None:
assert len(plan3.floors[0].exploded.windows) == 5
# ---------------------------------------------------------------------------
# Interior room points
# ---------------------------------------------------------------------------
class TestInteriorRoomPoints:
def test_interior_room_floor_count_plan1(self, plan1: MagicPlanXMLPlan) -> None:
assert len(plan1.interior_room_floors) == 2
def test_interior_room_floor_count_plan2(self, plan2: MagicPlanXMLPlan) -> None:
assert len(plan2.interior_room_floors) == 1
def test_interior_room_floor_uid_matches(self, plan1: MagicPlanXMLPlan) -> None:
assert plan1.interior_room_floors[0].uid == plan1.floors[0].uid

View file

@ -1,985 +0,0 @@
<plan name="275 Carr Hill Rd NE9 5ND" id="b66bb427-33fe-4865-8d57-bad7d9d3f2e5" uid="69e5fafc.0890b3ff" type="0" interiorWallWidth="0.12000" exteriorWallWidth="0.25000" schematic="0" hasLandSurveyAddress="0" lastPatchIdentifier="0" lastRollIdentifier="0">
<values>
<value key="date">2026-04-20</value>
<value key="statistics.areaOfHeight">2.134</value>
<value key="statistics.basement.account">100</value>
<value key="statistics.exteriorWalls">0</value>
<value key="statistics.interiorWalls">0</value>
</values>
<floor uid="69e5fb20.4feef7ff" floorType="0" rotation="0.00000" compassAngle="-1.000000" areaWithoutWalls="40.20736" areaWithInteriorWallsOnly="40.67878" areaWithWalls="48.40593">
<name>Ground Floor</name>
<symbolInstance id="floor" uid="69e5fb20.4feef7ff" parentUid="" symbol="floor">
<values>
<value key="ceilingHeight">2.323164</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-0" uid="69e5fbc8.711517ff" parentUid="" symbol="doordoublehinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.084107</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-1" uid="69e5fbc8.71336fff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.02225</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-2" uid="69e5fbc8.713b47ff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.124639</value>
<value key="wallItemHeight">0.949396</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-3" uid="69e5fbc8.73e407ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.397258</value>
<value key="height">0.746826</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">1.279293</value>
<value key="wallItemHeight">0.746826</value>
<value key="width">0.677733</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-4" uid="69e5fbc8.7408c7ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.368615</value>
<value key="height">0.723145</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">1.311519</value>
<value key="wallItemHeight">0.723145</value>
<value key="width">0.398439</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-5" uid="69e5fbc8.742773ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.604444</value>
<value key="height">0.1</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">0.851311</value>
<value key="wallItemHeight">0.1</value>
<value key="width">0.601075</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-0" uid="69e5fbc8.73d847ff" parentUid="" symbol="furniture-8285a785-4b2a-4a2a-904b-5fd5d91551d4">
<values>
<value key="symbolfilePrefix">furniture</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-1" uid="69e5fbc8.73dfd3ff" parentUid="" symbol="appliances-378151a6-3e37-477c-a52d-7786fcff365a">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-2" uid="69e5fbc8.7400c7ff" parentUid="" symbol="appliances-f4803db0-8455-424c-a414-05a5498b9288">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-3" uid="69e5fbc8.7404e7ff" parentUid="" symbol="appliances-af014f7b-2135-4206-995c-7747bb425ed5">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-4" uid="69e5fdc5.226b2fff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-0" uid="69e5fbc8.74614fff" parentUid="" symbol="doordoublehinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.084107</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-1" uid="69e5fbc8.746863ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.006357</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-2" uid="69e5fbc8.746f47ff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.00597</value>
<value key="wallItemHeight">1.026259</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-0" uid="69e5fbc8.7496abff" parentUid="" symbol="appliances-fee6a83d-7365-4cb3-89cb-26ffea1099e3">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-1" uid="69e5fbc8.74a363ff" parentUid="" symbol="furniture-f4c1d117-d87f-4ca4-b70f-7c1216e07f6d">
<values>
<value key="symbolfilePrefix">furniture</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-2" uid="69e5fbc8.74a783ff" parentUid="" symbol="hvac-1489fe06-b5c5-40ce-b7fa-c0555750d8c9">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.0000</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-3" uid="69e5fd95.4fd913ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-4" uid="69e5fda8.2e9b47ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<floorRoom type="Kitchen" uid="69e5fbc8.71027bff" x="3.80616" y="0.23162" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="10.78332" perimeter="13.32812">
<values>
<value key="ceilingHeight">2.323164</value>
</values>
<point snappedX="-1.44357" snappedY="-2.00846" height="2.323164" uid="69e5fbc8.710363ff" />
<point snappedX="1.44357" snappedY="-2.00846" height="2.323164" uid="69e5fbc8.710a67ff" />
<point snappedX="1.44357" snappedY="2.00846" height="2.323164" uid="69e5fbc8.710e47ff" />
<point snappedX="-1.44357" snappedY="2.00846" height="2.323164" uid="69e5fbc8.7111afff" />
<door point="3" type="4" u="0.47585" width="1.82394" depth="0.91197" height="2.08411" orientation="3" snappedType="4" snappedPosition="0.47585" snappedWidth="1.82394" snappedDepth="0.91197" snappedHeight="2.08411" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fbc8.74614fff" symbolInstance="W-0-0" />
<door point="1" type="2" u="0.19764" width="0.77300" depth="0.77300" height="2.02225" orientation="0" snappedType="2" snappedPosition="0.19764" snappedWidth="0.77300" snappedDepth="0.77300" snappedHeight="2.02225" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" symbolInstance="W-0-1" />
<window point="1" type="1" u="0.68463" width="1.71972" depth="0.12000" height="0.94940" orientation="0" snappedType="1" snappedPosition="0.68463" snappedWidth="1.71972" snappedDepth="0.12000" snappedHeight="0.94940" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-0-2" />
<door point="2" type="0" u="0.14195" width="0.67773" depth="0.39726" height="0.74683" orientation="2" snappedType="0" snappedPosition="0.14195" snappedWidth="0.67773" snappedDepth="0.39726" snappedHeight="0.74683" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-3" />
<door point="2" type="0" u="0.63071" width="0.39844" depth="0.36861" height="0.72315" orientation="2" snappedType="0" snappedPosition="0.63071" snappedWidth="0.39844" snappedDepth="0.36861" snappedHeight="0.72315" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-4" />
<door point="2" type="0" u="0.40931" width="0.60107" depth="0.60444" height="0.10000" orientation="2" snappedType="0" snappedPosition="0.40931" snappedWidth="0.60107" snappedDepth="0.60444" snappedHeight="0.10000" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-5" />
<furniture type="0" x="-0.37437" y="1.64301" snappedX="-0.37437" snappedY="1.64301" angle="3.14159" width="0.73174" depth="0.61090" height="0.83418" snappedWidth="0.73174" snappedDepth="0.61090" snappedHeight="0.83418" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-0" />
<furniture type="0" x="-1.07415" y="1.66141" snappedX="-1.07415" snappedY="1.66141" angle="3.14159" width="0.53467" depth="0.58310" height="1.30356" snappedWidth="0.53467" snappedDepth="0.58310" snappedHeight="1.30356" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-1" />
<furniture type="0" x="0.29204" y="1.64624" snappedX="0.29204" snappedY="1.64624" angle="3.14159" width="0.60107" depth="0.60444" height="0.85131" snappedWidth="0.60107" snappedDepth="0.60444" snappedHeight="0.85131" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-2" />
<furniture type="0" x="-1.02621" y="-1.62776" snappedX="-1.02621" snappedY="-1.62776" angle="0.00000" width="0.59317" depth="0.64140" height="0.80396" snappedWidth="0.59317" snappedDepth="0.64140" snappedHeight="0.80396" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-3" />
<furniture type="0" x="0.10449" y="-1.89546" snappedX="0.10449" snappedY="-1.89546" angle="0.00000" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-4" />
<mainDimension from="0" to="1" dir.x="-1.0000000000" dir.y="-0.0000000000" value="2.7671400000" actualValue="2.7671400000" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0000000000" dir.y="-1.0000000000" value="3.8969200000" actualValue="3.8969200000" isSet="0" />
</floorRoom>
<floorRoom type="Living Room" uid="69e5fbc8.74487bff" x="-1.61210" y="0.23162" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="29.44518" perimeter="24.13895">
<values>
<value key="ceilingHeight">3.285283</value>
</values>
<point snappedX="-3.97469" snappedY="-2.00846" height="3.285283" uid="69e5fbc8.7448bbff" />
<point snappedX="3.97469" snappedY="-2.00846" height="3.285283" uid="69e5fbc8.744c47ff" />
<point snappedX="3.97469" snappedY="2.00846" height="3.285283" uid="69e5fbc8.744f5bff" />
<point snappedX="0.19116" snappedY="2.00846" height="3.285283" uid="69e5fbc8.745263ff" />
<point snappedX="0.19116" snappedY="1.53785" height="3.285283" uid="69e5fbc8.74554fff" />
<point snappedX="-1.57493" snappedY="1.53785" height="3.285283" uid="69e5fbc8.745867ff" />
<point snappedX="-1.71730" snappedY="1.93998" height="3.285283" uid="69e5fbc8.745b7fff" />
<point snappedX="-3.97469" snappedY="1.93998" height="3.285283" uid="69e5fbc8.745e5fff" />
<door point="1" type="4" u="0.52415" width="1.82394" depth="0.91197" height="2.08411" orientation="0" snappedType="4" snappedPosition="0.52415" snappedWidth="1.82394" snappedDepth="0.91197" snappedHeight="2.08411" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fbc8.711517ff" symbolInstance="W-1-0" />
<door point="7" type="2" u="0.81578" width="0.83113" depth="0.83113" height="2.00636" orientation="0" snappedType="2" snappedPosition="0.81578" snappedWidth="0.83113" snappedDepth="0.83113" snappedHeight="2.00636" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" symbolInstance="W-1-1" />
<window point="7" type="1" u="0.46552" width="1.85077" depth="0.12000" height="1.02626" orientation="0" snappedType="1" snappedPosition="0.46552" snappedWidth="1.85077" snappedDepth="0.12000" snappedHeight="1.02626" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-1-2" />
<furniture type="0" x="-3.26415" y="1.35928" snappedX="-3.26415" snappedY="1.35928" angle="3.72376" width="1.10000" depth="0.26400" height="0.71600" snappedWidth="1.10000" snappedDepth="0.26400" snappedHeight="0.71600" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-0" />
<furniture type="0" x="-3.33464" y="1.37128" snappedX="-3.33464" snappedY="1.37128" angle="3.80141" width="1.01832" depth="0.49767" height="0.57273" snappedWidth="1.01832" snappedDepth="0.49767" snappedHeight="0.57273" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-1" />
<furniture type="0" x="-0.60840" y="1.42589" snappedX="-0.60840" snappedY="1.42589" angle="3.14159" width="1.11379" depth="0.42391" height="1.10296" snappedWidth="1.11379" snappedDepth="0.42391" snappedHeight="1.10296" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-2" />
<furniture type="0" x="2.08331" y="1.89546" snappedX="2.08331" snappedY="1.89546" angle="3.14159" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-3" />
<furniture type="0" x="-3.86169" y="0.04424" snappedX="-3.86169" snappedY="0.04424" angle="4.71239" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-4" />
<mainDimension from="0" to="1" dir.x="-1.0000000000" dir.y="-0.0000000000" value="7.8293800000" actualValue="7.8293800000" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0000000000" dir.y="-1.0000000000" value="3.8969200000" actualValue="3.8969200000" isSet="0" />
</floorRoom>
<exploded>
<wall>
<point x="2.363000" y="-1.778000" height="2.323164" />
<point x="-5.586000" y="-1.777000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="5.249000" y="-1.777000" height="2.323164" />
<point x="2.363000" y="-1.778000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="2.363000" y="2.240000" height="2.323164" />
<point x="5.249000" y="2.239000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="2.239000" height="2.323164" />
<point x="2.363000" y="2.240000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="5.249000" y="2.239000" height="2.323164" />
<point x="5.249000" y="-1.777000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-5.586000" y="-1.777000" height="2.323164" />
<point x="-5.586000" y="2.170000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="2.363000" y="-1.778000" height="2.323164" />
<point x="2.363000" y="2.240000" height="2.323164" />
<type>interior</type>
</wall>
<wall>
<point x="-5.586000" y="2.170000" height="2.323164" />
<point x="-3.328500" y="2.170000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="1.768000" height="2.323164" />
<point x="-3.186500" y="1.768000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="1.768000" height="2.323164" />
<point x="-1.421000" y="2.239000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-3.328500" y="2.170000" height="2.323164" />
<point x="-3.186500" y="1.768000" height="2.323164" />
<type>exterior</type>
</wall>
<door type="2" x1="5.249730" y1="-1.333153" x2="5.249730" y2="-0.560153" width="0.773000" depth="0.773000" height="2.022250" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-0-1" />
<window type="1" x1="5.249730" y1="0.091248" x2="5.249730" y2="1.810968" width="1.719720" depth="0.120000" height="0.949396" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-0-2" />
<door type="0" x1="5.135799" y1="2.240080" x2="4.458069" y2="2.240080" width="0.677730" depth="0.397260" height="0.746826" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-3" />
<door type="0" x1="3.643687" y1="2.240080" x2="3.245247" y2="2.240080" width="0.398440" depth="0.368610" height="0.723145" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-4" />
<door type="0" x1="4.357647" y1="2.240080" x2="3.756577" y2="2.240080" width="0.601070" depth="0.604440" height="0.100000" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-5" />
<furniture type="0" x="3.431790" y="1.874630" angle="3.141590" width="0.731740" depth="0.610900" height="0.834180" symbolInstance="F-0-0" />
<furniture type="0" x="2.732010" y="1.893030" angle="3.141590" width="0.534670" depth="0.583097" height="1.303560" symbolInstance="F-0-1" />
<furniture type="0" x="4.098200" y="1.877860" angle="3.141590" width="0.601070" depth="0.604440" height="0.851310" symbolInstance="F-0-2" />
<furniture type="0" x="2.779950" y="-1.396140" angle="0.000000" width="0.593170" depth="0.641400" height="0.803960" symbolInstance="F-0-3" />
<furniture type="0" x="3.910650" y="-1.663840" angle="0.000000" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-0-4" />
<door type="2" x1="-5.586790" y1="-0.596000" x2="-5.586790" y2="-1.427130" width="0.831130" depth="0.831130" height="2.006357" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-1" />
<window type="1" x1="-5.586790" y1="1.254770" x2="-5.586790" y2="-0.596000" width="1.850770" depth="0.120000" height="1.026259" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-1-2" />
<door type="4" x1="2.362590" y1="-0.586239" x2="2.362590" y2="1.237701" width="1.823940" depth="0.911970" height="2.084107" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-0" />
<furniture type="0" x="-4.876250" y="1.590900" angle="3.723760" width="1.100000" depth="0.264000" height="0.716000" symbolInstance="F-1-0" />
<furniture type="0" x="-4.946740" y="1.602900" angle="3.801410" width="1.018320" depth="0.497670" height="0.572730" symbolInstance="F-1-1" />
<furniture type="0" x="-2.220500" y="1.657510" angle="3.141590" width="1.113790" depth="0.423910" height="1.102960" symbolInstance="F-1-2" />
<furniture type="0" x="0.471210" y="2.127080" angle="3.141590" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-3" />
<furniture type="0" x="-5.473790" y="0.275860" angle="4.712390" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-4" />
</exploded>
</floor>
<floor uid="69e5fbdd.882287ff" floorType="1" rotation="0.00000" compassAngle="-1.000000" areaWithoutWalls="29.34605" areaWithInteriorWallsOnly="30.52809" areaWithWalls="36.77256">
<name>1st Floor</name>
<symbolInstance id="floor" uid="69e5fbdd.882287ff" parentUid="" symbol="floor">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-0" uid="69e5fcf6.09fe63ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.074757</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-1" uid="69e5fd68.8e2f33ff" parentUid="" symbol="plumbing-08aa18c5-ec1c-48f3-be68-431c07d4576c">
<values>
<value key="symbolfilePrefix">plumbing</value>
<value key="wallItemDistanceToFloor">1.5000</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-0" uid="69e5fcf6.09e257ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.081704</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-1" uid="69e5fcf6.0a0f3bff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.227592</value>
<value key="wallItemHeight">0.88319</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-0" uid="69e5fd3d.4b9d17ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-1" uid="69e5fe3e.2db4abff" parentUid="" symbol="co-ed10aa18-b3ce-4f51-a5e8-9f0051663885">
<values>
<value key="symbolfilePrefix">677d01685458a</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-0" uid="69e5fcf6.09e257ff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.081704</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-1" uid="69e5fcf6.09fe63ff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.074757</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-2" uid="69e5fcf6.0a077fff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.195494</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-0" uid="69e5fcf6.0a077fff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.195494</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-1" uid="69e5fcf6.0b305fff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">0.915306</value>
<value key="wallItemHeight">1.180143</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-2" uid="69e5fcf6.0bf033ff" parentUid="" symbol="appliances-e648fc54-abba-402a-8313-f5523ec6e5cc">
<values>
<value key="depth">0.1</value>
<value key="height">0.676758</value>
<value key="symbolfilePrefix">appliances</value>
<value key="wallItemDistanceToFloor">1.399472</value>
<value key="wallItemHeight">0.676758</value>
<value key="width">1.253952</value>
</values>
</symbolInstance>
<symbolInstance id="F-3-0" uid="69e5fd4d.64215bff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<floorRoom type="Bathroom" uid="69e5fcf6.08bec3ff" x="0.43937" y="2.21959" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="4.22940" perimeter="8.30295">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="0.95733" snappedY="-1.23850" height="2.382467" uid="69e5fcf6.08c07bff" />
<point snappedX="0.95665" snappedY="1.23881" height="2.382467" uid="69e5fcf6.08d4cbff" />
<point snappedX="-0.95733" snappedY="1.23850" height="2.382467" uid="69e5fcf6.08ce4bff" />
<point snappedX="-0.95702" snappedY="-1.23881" height="2.382467" uid="69e5fcf6.08ca9fff" />
<door point="2" type="2" u="0.20319" width="0.74796" depth="0.74796" height="2.07476" orientation="0" snappedType="2" snappedPosition="0.20319" snappedWidth="0.74796" snappedDepth="0.74796" snappedHeight="2.07476" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09fe63ff.auto" symbolInstance="W-0-0" />
<door point="1" type="0" u="0.48552" width="0.67310" depth="0.13140" height="0.06000" orientation="2" snappedType="0" snappedPosition="0.48552" snappedWidth="0.67310" snappedDepth="0.13140" snappedHeight="0.06000" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-1" />
<mainDimension from="1" to="2" dir.x="-0.9999999620" dir.y="-0.0002757380" value="1.7943400118" actualValue="1.7943400118" isSet="0" />
<mainDimension from="0" to="1" dir.x="0.0002757380" dir.y="-0.9999999620" value="2.3575147609" actualValue="2.3575147609" isSet="0" />
</floorRoom>
<floorRoom type="Closet" uid="69e5fcf6.08d80fff" x="-0.53205" y="-0.23901" rotation="0.00000" wasModified="1" linkedRoom0="-1" linkedRoom1="-1" area="8.65802" perimeter="12.11130">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="1.92843" snappedY="1.21239" height="2.382467" uid="69e5fcf6.08d833ff" />
<point snappedX="-1.92405" snappedY="1.22579" height="2.382467" uid="69e5fcf6.08e7bbff" />
<point snappedX="-1.93535" snappedY="-1.22579" height="2.382467" uid="69e5fcf6.08f1d3ff" />
<point snappedX="1.93535" snappedY="-1.20402" height="2.382467" uid="69e5fcf6.08fa8bff" />
<door point="0" type="2" u="0.64117" width="0.72408" depth="0.72408" height="2.08170" orientation="0" snappedType="2" snappedPosition="0.64117" snappedWidth="0.72408" snappedDepth="0.72408" snappedHeight="2.08170" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09e257ff.auto" symbolInstance="W-1-0" />
<window point="2" type="1" u="0.57311" width="1.92450" depth="0.12000" height="0.88319" orientation="0" snappedType="1" snappedPosition="0.57311" snappedWidth="1.92450" snappedDepth="0.12000" snappedHeight="0.88319" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-1-1" />
<furniture type="0" x="0.58270" y="-1.09832" snappedX="0.58275" snappedY="-1.09825" angle="0.00000" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-0" />
<furniture type="0" x="-1.51619" y="-0.80518" snappedX="-1.51614" snappedY="-0.80511" angle="0.00000" width="0.71386" depth="0.58230" height="1.00000" snappedWidth="0.71386" snappedDepth="0.58230" snappedHeight="1.00000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-1" />
<mainDimension from="2" to="3" dir.x="-0.9999939454" dir.y="0.0034798192" value="3.7501638695" actualValue="3.7501638695" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0034798192" dir.y="-0.9999939454" value="2.3310632946" actualValue="2.3310632946" isSet="0" />
</floorRoom>
<floorRoom type="Other" uid="69e5fcf6.0906ebff" x="-1.48849" y="2.21987" rotation="0.00000" wasModified="1" linkedRoom0="-1" linkedRoom1="-1" area="4.27518" perimeter="8.34147">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="0.97346" snappedY="-1.23218" height="2.382467" uid="69e5fcf6.09070fff" />
<point snappedX="0.96799" snappedY="1.24087" height="2.382467" uid="69e5fcf6.09143bff" />
<point snappedX="-0.95378" snappedY="1.23878" height="2.382467" uid="69e5fcf6.09106fff" />
<point snappedX="-0.97346" snappedY="-1.24087" height="2.382467" uid="69e5fcf6.090d5bff" />
<door point="3" type="2" u="0.73610" width="0.72408" depth="0.72408" height="2.08170" orientation="3" snappedType="2" snappedPosition="0.73610" snappedWidth="0.72408" snappedDepth="0.72408" snappedHeight="2.08170" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09e257ff" symbolInstance="W-2-0" />
<door point="0" type="2" u="0.79528" width="0.74796" depth="0.74796" height="2.07476" orientation="3" snappedType="2" snappedPosition="0.79528" snappedWidth="0.74796" snappedDepth="0.74796" snappedHeight="2.07476" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09fe63ff" symbolInstance="W-2-1" />
<door point="1" type="2" u="0.25222" width="0.76920" depth="0.76920" height="2.19549" orientation="0" snappedType="2" snappedPosition="0.25222" snappedWidth="0.76920" snappedDepth="0.76920" snappedHeight="2.19549" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.0a077fff.auto" symbolInstance="W-2-2" />
<mainDimension from="3" to="0" dir.x="-0.9999975492" dir.y="-0.0022139540" value="1.8263235678" actualValue="1.8263235678" isSet="0" />
<mainDimension from="2" to="3" dir.x="0.0022139540" dir.y="-0.9999975492" value="2.3593927501" actualValue="2.3593927501" isSet="0" />
</floorRoom>
<floorRoom type="Bedroom" uid="69e5fcf6.091a43ff" x="-0.45645" y="5.11834" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="12.19886" perimeter="14.09693">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="1.98414" snappedY="-0.83873" height="2.382467" uid="69e5fcf6.091adbff" />
<point snappedX="1.98413" snappedY="1.66009" height="2.382467" uid="69e5fcf6.091efbff" />
<point snappedX="-1.98413" snappedY="1.66010" height="2.382467" uid="69e5fcf6.092f4bff" />
<point snappedX="-1.98414" snappedY="-1.66010" height="2.382467" uid="69e5fcf6.0975d3ff" />
<point snappedX="1.84248" snappedY="-1.66010" height="2.382467" uid="69e5fcf6.098c6bff" />
<point snappedX="1.84248" snappedY="-0.83873" height="2.382467" uid="69e5fcf6.099a0fff" />
<door point="3" type="2" u="0.36303" width="0.76920" depth="0.76920" height="2.19549" orientation="3" snappedType="2" snappedPosition="0.36303" snappedWidth="0.76920" snappedDepth="0.76920" snappedHeight="2.19549" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.0a077fff" symbolInstance="W-3-0" />
<window point="1" type="1" u="0.49053" width="2.41757" depth="0.12000" height="1.18014" orientation="0" snappedType="1" snappedPosition="0.49053" snappedWidth="2.41757" snappedDepth="0.12000" snappedHeight="1.18014" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-3-1" />
<door point="0" type="0" u="0.73832" width="1.25395" depth="0.10000" height="0.67676" orientation="2" snappedType="0" snappedPosition="0.73832" snappedWidth="1.25395" snappedDepth="0.10000" snappedHeight="0.67676" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-3-2" />
<furniture type="0" x="-0.12434" y="1.54710" snappedX="-0.12434" snappedY="1.54710" angle="3.14159" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-3-0" />
<mainDimension from="1" to="2" dir.x="-1.0000000000" dir.y="-0.0000042038" value="3.8482834528" actualValue="3.8482834528" isSet="0" />
<mainDimension from="2" to="3" dir.x="0.0000042038" dir.y="-1.0000000000" value="3.2002155817" actualValue="3.2002155817" isSet="0" />
</floorRoom>
<exploded>
<wall>
<point x="-2.461000" y="0.983500" height="2.382467" />
<point x="-2.500460" y="3.458000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-2.474000" y="-1.463000" height="2.382467" />
<point x="-2.461000" y="0.983500" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-2.440000" y="6.778000" height="2.382467" />
<point x="1.528000" y="6.778000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.402997" y="-1.441500" height="2.382467" />
<point x="-2.474000" y="-1.463000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-0.505800" y="0.968600" height="2.382467" />
<point x="-2.461000" y="0.983500" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="1.396000" y="0.978000" height="2.382467" />
<point x="-0.505800" y="0.968600" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-0.520000" y="3.458500" height="2.382467" />
<point x="1.394500" y="3.458000" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-2.500460" y="3.458000" height="2.382467" />
<point x="-0.520000" y="3.458500" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-2.500460" y="3.458000" height="2.382467" />
<point x="-2.440000" y="6.778000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.394500" y="3.458000" height="2.382467" />
<point x="1.396000" y="0.978000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.390000" y="4.280000" height="2.382467" />
<point x="1.394500" y="3.458000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.528000" y="6.778000" height="2.382467" />
<point x="1.528000" y="4.280000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.396000" y="0.978000" height="2.382467" />
<point x="1.402997" y="-1.441500" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-0.520000" y="3.458500" height="2.382467" />
<point x="-0.505800" y="0.968600" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="1.390000" y="4.280000" height="2.382467" />
<point x="1.528000" y="4.280000" height="2.382467" />
<type>exterior</type>
</wall>
<door type="0" x1="0.801562" y1="3.458304" x2="0.128462" y2="3.458195" width="0.673100" depth="0.131400" height="0.060000" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-1" />
<door type="2" x1="-0.519034" y1="3.292995" x2="-0.518158" y2="2.545036" width="0.747960" depth="0.747960" height="2.074757" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-0-0" />
<door type="2" x1="-0.694971" y1="0.983772" x2="-1.419046" y2="0.983416" width="0.724080" depth="0.724080" height="2.081704" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-0" />
<window type="1" x1="-1.219716" y1="-1.457780" x2="0.704754" y2="-1.446953" width="1.924500" depth="0.120000" height="0.883190" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-1-1" />
<furniture type="0" x="0.050700" y="-1.337260" angle="0.000000" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-0" />
<furniture type="0" x="-2.048190" y="-1.044120" angle="0.000000" width="0.713860" depth="0.582300" height="1.000000" symbolInstance="F-1-1" />
<door type="2" x1="-0.650374" y1="3.459417" x2="-1.419574" y2="3.458999" width="0.769200" depth="0.769200" height="2.195494" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-2-2" />
<door type="0" x1="1.527685" y1="5.468966" x2="1.527680" y2="6.722916" width="1.253950" depth="0.100000" height="0.676758" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-3-2" />
<window type="1" x1="0.788778" y1="6.778432" x2="-1.628792" y2="6.778438" width="2.417570" depth="0.120000" height="1.180143" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-3-1" />
<furniture type="0" x="-0.580790" y="6.665440" angle="3.141590" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-3-0" />
</exploded>
</floor>
<interiorRoomPoints>
<floor uid="69e5fb20.4feef7ff" floorType="0" rotation="0.00000" compassAngle="-1.000000" areaWithoutWalls="40.20736" areaWithInteriorWallsOnly="40.67878" areaWithWalls="48.40593">
<name>Ground Floor</name>
<symbolInstance id="floor" uid="69e5fb20.4feef7ff" parentUid="" symbol="floor">
<values>
<value key="ceilingHeight">2.323164</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-0" uid="69e5fbc8.711517ff" parentUid="" symbol="doordoublehinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.084107</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-1" uid="69e5fbc8.71336fff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.02225</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-2" uid="69e5fbc8.713b47ff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.124639</value>
<value key="wallItemHeight">0.949396</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-3" uid="69e5fbc8.73e407ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.397258</value>
<value key="height">0.746826</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">1.279293</value>
<value key="wallItemHeight">0.746826</value>
<value key="width">0.677733</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-4" uid="69e5fbc8.7408c7ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.368615</value>
<value key="height">0.723145</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">1.311519</value>
<value key="wallItemHeight">0.723145</value>
<value key="width">0.398439</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-5" uid="69e5fbc8.742773ff" parentUid="" symbol="furniture-3740ec67-24f6-42e6-b7f9-40a88d3f84ee">
<values>
<value key="depth">0.604444</value>
<value key="height">0.1</value>
<value key="symbolfilePrefix">furniture</value>
<value key="wallItemDistanceToFloor">0.851311</value>
<value key="wallItemHeight">0.1</value>
<value key="width">0.601075</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-0" uid="69e5fbc8.73d847ff" parentUid="" symbol="furniture-8285a785-4b2a-4a2a-904b-5fd5d91551d4">
<values>
<value key="symbolfilePrefix">furniture</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-1" uid="69e5fbc8.73dfd3ff" parentUid="" symbol="appliances-378151a6-3e37-477c-a52d-7786fcff365a">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-2" uid="69e5fbc8.7400c7ff" parentUid="" symbol="appliances-f4803db0-8455-424c-a414-05a5498b9288">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-3" uid="69e5fbc8.7404e7ff" parentUid="" symbol="appliances-af014f7b-2135-4206-995c-7747bb425ed5">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-0-4" uid="69e5fdc5.226b2fff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-0" uid="69e5fbc8.74614fff" parentUid="" symbol="doordoublehinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.084107</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-1" uid="69e5fbc8.746863ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.006357</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-2" uid="69e5fbc8.746f47ff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.00597</value>
<value key="wallItemHeight">1.026259</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-0" uid="69e5fbc8.7496abff" parentUid="" symbol="appliances-fee6a83d-7365-4cb3-89cb-26ffea1099e3">
<values>
<value key="symbolfilePrefix">appliances</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-1" uid="69e5fbc8.74a363ff" parentUid="" symbol="furniture-f4c1d117-d87f-4ca4-b70f-7c1216e07f6d">
<values>
<value key="symbolfilePrefix">furniture</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-2" uid="69e5fbc8.74a783ff" parentUid="" symbol="hvac-1489fe06-b5c5-40ce-b7fa-c0555750d8c9">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.0000</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-3" uid="69e5fd95.4fd913ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-4" uid="69e5fda8.2e9b47ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<floorRoom type="Kitchen" uid="69e5fbc8.71027bff" x="3.80616" y="0.23162" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="10.78332" perimeter="13.32812">
<values>
<value key="ceilingHeight">2.323164</value>
</values>
<point snappedX="-1.38357" snappedY="-1.94846" height="2.323164" uid="69e5fbc8.710363ff" />
<point snappedX="1.38357" snappedY="-1.94846" height="2.323164" uid="69e5fbc8.710a67ff" />
<point snappedX="1.38357" snappedY="1.94846" height="2.323164" uid="69e5fbc8.710e47ff" />
<point snappedX="-1.38357" snappedY="1.94846" height="2.323164" uid="69e5fbc8.7111afff" />
<door point="3" type="4" u="0.47585" width="1.82394" depth="0.91197" height="2.08411" orientation="3" snappedType="4" snappedPosition="0.47585" snappedWidth="1.82394" snappedDepth="0.91197" snappedHeight="2.08411" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fbc8.74614fff" symbolInstance="W-0-0" />
<door point="1" type="2" u="0.19764" width="0.77300" depth="0.77300" height="2.02225" orientation="0" snappedType="2" snappedPosition="0.19764" snappedWidth="0.77300" snappedDepth="0.77300" snappedHeight="2.02225" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" symbolInstance="W-0-1" />
<window point="1" type="1" u="0.68463" width="1.71972" depth="0.12000" height="0.94940" orientation="0" snappedType="1" snappedPosition="0.68463" snappedWidth="1.71972" snappedDepth="0.12000" snappedHeight="0.94940" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-0-2" />
<door point="2" type="0" u="0.14195" width="0.67773" depth="0.39726" height="0.74683" orientation="2" snappedType="0" snappedPosition="0.14195" snappedWidth="0.67773" snappedDepth="0.39726" snappedHeight="0.74683" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-3" />
<door point="2" type="0" u="0.63071" width="0.39844" depth="0.36861" height="0.72315" orientation="2" snappedType="0" snappedPosition="0.63071" snappedWidth="0.39844" snappedDepth="0.36861" snappedHeight="0.72315" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-4" />
<door point="2" type="0" u="0.40931" width="0.60107" depth="0.60444" height="0.10000" orientation="2" snappedType="0" snappedPosition="0.40931" snappedWidth="0.60107" snappedDepth="0.60444" snappedHeight="0.10000" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-5" />
<furniture type="0" x="-0.37437" y="1.64301" snappedX="-0.37437" snappedY="1.64301" angle="3.14159" width="0.73174" depth="0.61090" height="0.83418" snappedWidth="0.73174" snappedDepth="0.61090" snappedHeight="0.83418" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-0" />
<furniture type="0" x="-1.07415" y="1.66141" snappedX="-1.07415" snappedY="1.66141" angle="3.14159" width="0.53467" depth="0.58310" height="1.30356" snappedWidth="0.53467" snappedDepth="0.58310" snappedHeight="1.30356" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-1" />
<furniture type="0" x="0.29204" y="1.64624" snappedX="0.29204" snappedY="1.64624" angle="3.14159" width="0.60107" depth="0.60444" height="0.85131" snappedWidth="0.60107" snappedDepth="0.60444" snappedHeight="0.85131" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-2" />
<furniture type="0" x="-1.02621" y="-1.62776" snappedX="-1.02621" snappedY="-1.62776" angle="0.00000" width="0.59317" depth="0.64140" height="0.80396" snappedWidth="0.59317" snappedDepth="0.64140" snappedHeight="0.80396" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-3" />
<furniture type="0" x="0.10449" y="-1.89546" snappedX="0.10449" snappedY="-1.89546" angle="0.00000" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-0-4" />
<mainDimension from="0" to="1" dir.x="-1.0000000000" dir.y="-0.0000000000" value="2.7671400000" actualValue="2.7671400000" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0000000000" dir.y="-1.0000000000" value="3.8969200000" actualValue="3.8969200000" isSet="0" />
</floorRoom>
<floorRoom type="Living Room" uid="69e5fbc8.74487bff" x="-1.61210" y="0.23162" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="29.44518" perimeter="24.13895">
<values>
<value key="ceilingHeight">3.285283</value>
</values>
<point snappedX="-3.91469" snappedY="-1.94846" height="3.285283" uid="69e5fbc8.7448bbff" />
<point snappedX="3.91469" snappedY="-1.94846" height="3.285283" uid="69e5fbc8.744c47ff" />
<point snappedX="3.91469" snappedY="1.94846" height="3.285283" uid="69e5fbc8.744f5bff" />
<point snappedX="0.25116" snappedY="1.94846" height="3.285283" uid="69e5fbc8.745263ff" />
<point snappedX="0.25116" snappedY="1.47785" height="3.285283" uid="69e5fbc8.74554fff" />
<point snappedX="-1.61734" snappedY="1.47785" height="3.285283" uid="69e5fbc8.745867ff" />
<point snappedX="-1.75971" snappedY="1.87998" height="3.285283" uid="69e5fbc8.745b7fff" />
<point snappedX="-3.91469" snappedY="1.87998" height="3.285283" uid="69e5fbc8.745e5fff" />
<door point="1" type="4" u="0.52415" width="1.82394" depth="0.91197" height="2.08411" orientation="0" snappedType="4" snappedPosition="0.52415" snappedWidth="1.82394" snappedDepth="0.91197" snappedHeight="2.08411" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fbc8.711517ff" symbolInstance="W-1-0" />
<door point="7" type="2" u="0.81578" width="0.83113" depth="0.83113" height="2.00636" orientation="0" snappedType="2" snappedPosition="0.81578" snappedWidth="0.83113" snappedDepth="0.83113" snappedHeight="2.00636" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" symbolInstance="W-1-1" />
<window point="7" type="1" u="0.46552" width="1.85077" depth="0.12000" height="1.02626" orientation="0" snappedType="1" snappedPosition="0.46552" snappedWidth="1.85077" snappedDepth="0.12000" snappedHeight="1.02626" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-1-2" />
<furniture type="0" x="-3.26415" y="1.35928" snappedX="-3.26415" snappedY="1.35928" angle="3.72376" width="1.10000" depth="0.26400" height="0.71600" snappedWidth="1.10000" snappedDepth="0.26400" snappedHeight="0.71600" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-0" />
<furniture type="0" x="-3.33464" y="1.37128" snappedX="-3.33464" snappedY="1.37128" angle="3.80141" width="1.01832" depth="0.49767" height="0.57273" snappedWidth="1.01832" snappedDepth="0.49767" snappedHeight="0.57273" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-1" />
<furniture type="0" x="-0.60840" y="1.42589" snappedX="-0.60840" snappedY="1.42589" angle="3.14159" width="1.11379" depth="0.42391" height="1.10296" snappedWidth="1.11379" snappedDepth="0.42391" snappedHeight="1.10296" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-2" />
<furniture type="0" x="2.08331" y="1.89546" snappedX="2.08331" snappedY="1.89546" angle="3.14159" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-3" />
<furniture type="0" x="-3.86169" y="0.04424" snappedX="-3.86169" snappedY="0.04424" angle="4.71239" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-4" />
<mainDimension from="0" to="1" dir.x="-1.0000000000" dir.y="-0.0000000000" value="7.8293800000" actualValue="7.8293800000" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0000000000" dir.y="-1.0000000000" value="3.8969200000" actualValue="3.8969200000" isSet="0" />
</floorRoom>
<exploded>
<wall>
<point x="2.363000" y="-1.778000" height="2.323164" />
<point x="-5.586000" y="-1.777000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="5.249000" y="-1.777000" height="2.323164" />
<point x="2.363000" y="-1.778000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="2.363000" y="2.240000" height="2.323164" />
<point x="5.249000" y="2.239000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="2.239000" height="2.323164" />
<point x="2.363000" y="2.240000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="5.249000" y="2.239000" height="2.323164" />
<point x="5.249000" y="-1.777000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-5.586000" y="-1.777000" height="2.323164" />
<point x="-5.586000" y="2.170000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="2.363000" y="-1.778000" height="2.323164" />
<point x="2.363000" y="2.240000" height="2.323164" />
<type>interior</type>
</wall>
<wall>
<point x="-5.586000" y="2.170000" height="2.323164" />
<point x="-3.328500" y="2.170000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="1.768000" height="2.323164" />
<point x="-3.186500" y="1.768000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-1.421000" y="1.768000" height="2.323164" />
<point x="-1.421000" y="2.239000" height="2.323164" />
<type>exterior</type>
</wall>
<wall>
<point x="-3.328500" y="2.170000" height="2.323164" />
<point x="-3.186500" y="1.768000" height="2.323164" />
<type>exterior</type>
</wall>
<door type="2" x1="5.249730" y1="-1.333153" x2="5.249730" y2="-0.560153" width="0.773000" depth="0.773000" height="2.022250" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-0-1" />
<window type="1" x1="5.249730" y1="0.091248" x2="5.249730" y2="1.810968" width="1.719720" depth="0.120000" height="0.949396" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-0-2" />
<door type="0" x1="5.135799" y1="2.240080" x2="4.458069" y2="2.240080" width="0.677730" depth="0.397260" height="0.746826" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-3" />
<door type="0" x1="3.643687" y1="2.240080" x2="3.245247" y2="2.240080" width="0.398440" depth="0.368610" height="0.723145" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-4" />
<door type="0" x1="4.357647" y1="2.240080" x2="3.756577" y2="2.240080" width="0.601070" depth="0.604440" height="0.100000" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-5" />
<furniture type="0" x="3.431790" y="1.874630" angle="3.141590" width="0.731740" depth="0.610900" height="0.834180" symbolInstance="F-0-0" />
<furniture type="0" x="2.732010" y="1.893030" angle="3.141590" width="0.534670" depth="0.583097" height="1.303560" symbolInstance="F-0-1" />
<furniture type="0" x="4.098200" y="1.877860" angle="3.141590" width="0.601070" depth="0.604440" height="0.851310" symbolInstance="F-0-2" />
<furniture type="0" x="2.779950" y="-1.396140" angle="0.000000" width="0.593170" depth="0.641400" height="0.803960" symbolInstance="F-0-3" />
<furniture type="0" x="3.910650" y="-1.663840" angle="0.000000" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-0-4" />
<door type="2" x1="-5.586790" y1="-0.596000" x2="-5.586790" y2="-1.427130" width="0.831130" depth="0.831130" height="2.006357" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-1" />
<window type="1" x1="-5.586790" y1="1.254770" x2="-5.586790" y2="-0.596000" width="1.850770" depth="0.120000" height="1.026259" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-1-2" />
<door type="4" x1="2.362590" y1="-0.586239" x2="2.362590" y2="1.237701" width="1.823940" depth="0.911970" height="2.084107" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-0" />
<furniture type="0" x="-4.876250" y="1.590900" angle="3.723760" width="1.100000" depth="0.264000" height="0.716000" symbolInstance="F-1-0" />
<furniture type="0" x="-4.946740" y="1.602900" angle="3.801410" width="1.018320" depth="0.497670" height="0.572730" symbolInstance="F-1-1" />
<furniture type="0" x="-2.220500" y="1.657510" angle="3.141590" width="1.113790" depth="0.423910" height="1.102960" symbolInstance="F-1-2" />
<furniture type="0" x="0.471210" y="2.127080" angle="3.141590" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-3" />
<furniture type="0" x="-5.473790" y="0.275860" angle="4.712390" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-4" />
</exploded>
</floor>
<floor uid="69e5fbdd.882287ff" floorType="1" rotation="0.00000" compassAngle="-1.000000" areaWithoutWalls="29.34605" areaWithInteriorWallsOnly="30.52809" areaWithWalls="36.77256">
<name>1st Floor</name>
<symbolInstance id="floor" uid="69e5fbdd.882287ff" parentUid="" symbol="floor">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-0" uid="69e5fcf6.09fe63ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.074757</value>
</values>
</symbolInstance>
<symbolInstance id="W-0-1" uid="69e5fd68.8e2f33ff" parentUid="" symbol="plumbing-08aa18c5-ec1c-48f3-be68-431c07d4576c">
<values>
<value key="symbolfilePrefix">plumbing</value>
<value key="wallItemDistanceToFloor">1.5000</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-0" uid="69e5fcf6.09e257ff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.081704</value>
</values>
</symbolInstance>
<symbolInstance id="W-1-1" uid="69e5fcf6.0a0f3bff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">1.227592</value>
<value key="wallItemHeight">0.88319</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-0" uid="69e5fd3d.4b9d17ff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<symbolInstance id="F-1-1" uid="69e5fe3e.2db4abff" parentUid="" symbol="co-ed10aa18-b3ce-4f51-a5e8-9f0051663885">
<values>
<value key="symbolfilePrefix">677d01685458a</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-0" uid="69e5fcf6.09e257ff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.081704</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-1" uid="69e5fcf6.09fe63ff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.074757</value>
</values>
</symbolInstance>
<symbolInstance id="W-2-2" uid="69e5fcf6.0a077fff" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.195494</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-0" uid="69e5fcf6.0a077fff.auto" parentUid="" symbol="doorhinged">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemHeight">2.195494</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-1" uid="69e5fcf6.0b305fff" parentUid="" symbol="windowfixed">
<values>
<value key="symbolfilePrefix">doors</value>
<value key="wallItemDistanceToFloor">0.915306</value>
<value key="wallItemHeight">1.180143</value>
</values>
</symbolInstance>
<symbolInstance id="W-3-2" uid="69e5fcf6.0bf033ff" parentUid="" symbol="appliances-e648fc54-abba-402a-8313-f5523ec6e5cc">
<values>
<value key="depth">0.1</value>
<value key="height">0.676758</value>
<value key="symbolfilePrefix">appliances</value>
<value key="wallItemDistanceToFloor">1.399472</value>
<value key="wallItemHeight">0.676758</value>
<value key="width">1.253952</value>
</values>
</symbolInstance>
<symbolInstance id="F-3-0" uid="69e5fd4d.64215bff" parentUid="" symbol="hvac-650c5bce-e5fd-48e9-b3f9-1180a0f66cbc">
<values>
<value key="symbolfilePrefix">hvac</value>
<value key="wallItemDistanceToFloor">0.1500</value>
</values>
</symbolInstance>
<floorRoom type="Bathroom" uid="69e5fcf6.08bec3ff" x="0.43937" y="2.21959" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="4.22940" perimeter="8.30295">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="0.89732" snappedY="-1.17851" height="2.382467" uid="69e5fcf6.08c07bff" />
<point snappedX="0.89667" snappedY="1.17880" height="2.382467" uid="69e5fcf6.08d4cbff" />
<point snappedX="-0.89732" snappedY="1.17851" height="2.382467" uid="69e5fcf6.08ce4bff" />
<point snappedX="-0.89702" snappedY="-1.17880" height="2.382467" uid="69e5fcf6.08ca9fff" />
<door point="2" type="2" u="0.20319" width="0.74796" depth="0.74796" height="2.07476" orientation="0" snappedType="2" snappedPosition="0.20319" snappedWidth="0.74796" snappedDepth="0.74796" snappedHeight="2.07476" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09fe63ff.auto" symbolInstance="W-0-0" />
<door point="1" type="0" u="0.48552" width="0.67310" depth="0.13140" height="0.06000" orientation="2" snappedType="0" snappedPosition="0.48552" snappedWidth="0.67310" snappedDepth="0.13140" snappedHeight="0.06000" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-0-1" />
<mainDimension from="1" to="2" dir.x="-0.9999999620" dir.y="-0.0002757380" value="1.7943400118" actualValue="1.7943400118" isSet="0" />
<mainDimension from="0" to="1" dir.x="0.0002757380" dir.y="-0.9999999620" value="2.3575147609" actualValue="2.3575147609" isSet="0" />
</floorRoom>
<floorRoom type="Closet" uid="69e5fcf6.08d80fff" x="-0.53200" y="-0.23894" rotation="0.00000" wasModified="1" linkedRoom0="-1" linkedRoom1="-1" area="8.65802" perimeter="12.11130">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="1.86855" snappedY="1.15253" height="2.382467" uid="69e5fcf6.08d833ff" />
<point snappedX="-1.86438" snappedY="1.16552" height="2.382467" uid="69e5fcf6.08e7bbff" />
<point snappedX="-1.87513" snappedY="-1.16552" height="2.382467" uid="69e5fcf6.08f1d3ff" />
<point snappedX="1.87513" snappedY="-1.14442" height="2.382467" uid="69e5fcf6.08fa8bff" />
<door point="0" type="2" u="0.64117" width="0.72408" depth="0.72408" height="2.08170" orientation="0" snappedType="2" snappedPosition="0.64117" snappedWidth="0.72408" snappedDepth="0.72408" snappedHeight="2.08170" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09e257ff.auto" symbolInstance="W-1-0" />
<window point="2" type="1" u="0.57311" width="1.92450" depth="0.12000" height="0.88319" orientation="0" snappedType="1" snappedPosition="0.57311" snappedWidth="1.92450" snappedDepth="0.12000" snappedHeight="0.88319" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-1-1" />
<furniture type="0" x="0.58270" y="-1.09832" snappedX="0.58270" snappedY="-1.09832" angle="0.00000" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-0" />
<furniture type="0" x="-1.51619" y="-0.80518" snappedX="-1.51619" snappedY="-0.80518" angle="0.00000" width="0.71386" depth="0.58230" height="1.00000" snappedWidth="0.71386" snappedDepth="0.58230" snappedHeight="1.00000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-1-1" />
<mainDimension from="2" to="3" dir.x="-0.9999939454" dir.y="0.0034798192" value="3.7501638695" actualValue="3.7501638695" isSet="0" />
<mainDimension from="1" to="2" dir.x="-0.0034798192" dir.y="-0.9999939454" value="2.3310632946" actualValue="2.3310632946" isSet="0" />
</floorRoom>
<floorRoom type="Other" uid="69e5fcf6.0906ebff" x="-1.48831" y="2.21997" rotation="0.00000" wasModified="1" linkedRoom0="-1" linkedRoom1="-1" area="4.27518" perimeter="8.34147">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="0.91315" snappedY="-1.17255" height="2.382467" uid="69e5fcf6.09070fff" />
<point snappedX="0.90794" snappedY="1.18070" height="2.382467" uid="69e5fcf6.09143bff" />
<point snappedX="-0.89443" snappedY="1.17874" height="2.382467" uid="69e5fcf6.09106fff" />
<point snappedX="-0.91316" snappedY="-1.18070" height="2.382467" uid="69e5fcf6.090d5bff" />
<door point="3" type="2" u="0.73610" width="0.72408" depth="0.72408" height="2.08170" orientation="3" snappedType="2" snappedPosition="0.73610" snappedWidth="0.72408" snappedDepth="0.72408" snappedHeight="2.08170" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09e257ff" symbolInstance="W-2-0" />
<door point="0" type="2" u="0.79528" width="0.74796" depth="0.74796" height="2.07476" orientation="3" snappedType="2" snappedPosition="0.79528" snappedWidth="0.74796" snappedDepth="0.74796" snappedHeight="2.07476" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.09fe63ff" symbolInstance="W-2-1" />
<door point="1" type="2" u="0.25222" width="0.76920" depth="0.76920" height="2.19549" orientation="0" snappedType="2" snappedPosition="0.25222" snappedWidth="0.76920" snappedDepth="0.76920" snappedHeight="2.19549" snappedOrientation="0" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.0a077fff.auto" symbolInstance="W-2-2" />
<mainDimension from="3" to="0" dir.x="-0.9999975492" dir.y="-0.0022139540" value="1.8263235678" actualValue="1.8263235678" isSet="0" />
<mainDimension from="2" to="3" dir.x="0.0022139540" dir.y="-0.9999975492" value="2.3593927501" actualValue="2.3593927501" isSet="0" />
</floorRoom>
<floorRoom type="Bedroom" uid="69e5fcf6.091a43ff" x="-0.45645" y="5.11834" rotation="0.00000" wasModified="0" linkedRoom0="-1" linkedRoom1="-1" area="12.19886" perimeter="14.09693">
<values>
<value key="ceilingHeight">2.382467</value>
</values>
<point snappedX="1.92414" snappedY="-0.77873" height="2.382467" uid="69e5fcf6.091adbff" />
<point snappedX="1.92413" snappedY="1.60009" height="2.382467" uid="69e5fcf6.091efbff" />
<point snappedX="-1.92413" snappedY="1.60010" height="2.382467" uid="69e5fcf6.092f4bff" />
<point snappedX="-1.92414" snappedY="-1.60010" height="2.382467" uid="69e5fcf6.0975d3ff" />
<point snappedX="1.78248" snappedY="-1.60010" height="2.382467" uid="69e5fcf6.098c6bff" />
<point snappedX="1.78248" snappedY="-0.77873" height="2.382467" uid="69e5fcf6.099a0fff" />
<door point="3" type="2" u="0.36303" width="0.76920" depth="0.76920" height="2.19549" orientation="3" snappedType="2" snappedPosition="0.36303" snappedWidth="0.76920" snappedDepth="0.76920" snappedHeight="2.19549" snappedOrientation="3" insetX="0.00000" insetY="0.00000" insetZ="0.00000" twinWallItemUid="69e5fcf6.0a077fff" symbolInstance="W-3-0" />
<window point="1" type="1" u="0.49053" width="2.41757" depth="0.12000" height="1.18014" orientation="0" snappedType="1" snappedPosition="0.49053" snappedWidth="2.41757" snappedDepth="0.12000" snappedHeight="1.18014" snappedOrientation="0" insetX="0.00000" insetY="-0.06000" insetZ="-0.06000" symbolInstance="W-3-1" />
<door point="0" type="0" u="0.73832" width="1.25395" depth="0.10000" height="0.67676" orientation="2" snappedType="0" snappedPosition="0.73832" snappedWidth="1.25395" snappedDepth="0.10000" snappedHeight="0.67676" snappedOrientation="2" insetX="0.00000" insetY="0.03000" insetZ="0.03000" symbolInstance="W-3-2" />
<furniture type="0" x="-0.12434" y="1.54710" snappedX="-0.12434" snappedY="1.54710" angle="3.14159" width="1.00000" depth="0.10600" height="0.60000" snappedWidth="1.00000" snappedDepth="0.10600" snappedHeight="0.60000" sizeLock0="0" sizeLock1="0" sizeLock2="0" symbolInstance="F-3-0" />
<mainDimension from="1" to="2" dir.x="-1.0000000000" dir.y="-0.0000042038" value="3.8482834528" actualValue="3.8482834528" isSet="0" />
<mainDimension from="2" to="3" dir.x="0.0000042038" dir.y="-1.0000000000" value="3.2002155817" actualValue="3.2002155817" isSet="0" />
</floorRoom>
<exploded>
<wall>
<point x="-2.461000" y="0.983500" height="2.382467" />
<point x="-2.500460" y="3.458000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-2.474000" y="-1.463000" height="2.382467" />
<point x="-2.461000" y="0.983500" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-2.440000" y="6.778000" height="2.382467" />
<point x="1.528000" y="6.778000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.402997" y="-1.441500" height="2.382467" />
<point x="-2.474000" y="-1.463000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-0.505800" y="0.968600" height="2.382467" />
<point x="-2.461000" y="0.983500" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="1.396000" y="0.978000" height="2.382467" />
<point x="-0.505800" y="0.968600" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-0.520000" y="3.458500" height="2.382467" />
<point x="1.394500" y="3.458000" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-2.500460" y="3.458000" height="2.382467" />
<point x="-0.520000" y="3.458500" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="-2.500460" y="3.458000" height="2.382467" />
<point x="-2.440000" y="6.778000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.394500" y="3.458000" height="2.382467" />
<point x="1.396000" y="0.978000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.390000" y="4.280000" height="2.382467" />
<point x="1.394500" y="3.458000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.528000" y="6.778000" height="2.382467" />
<point x="1.528000" y="4.280000" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="1.396000" y="0.978000" height="2.382467" />
<point x="1.402997" y="-1.441500" height="2.382467" />
<type>exterior</type>
</wall>
<wall>
<point x="-0.520000" y="3.458500" height="2.382467" />
<point x="-0.505800" y="0.968600" height="2.382467" />
<type>interior</type>
</wall>
<wall>
<point x="1.390000" y="4.280000" height="2.382467" />
<point x="1.528000" y="4.280000" height="2.382467" />
<type>exterior</type>
</wall>
<door type="0" x1="0.801562" y1="3.458304" x2="0.128462" y2="3.458195" width="0.673100" depth="0.131400" height="0.060000" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-0-1" />
<door type="2" x1="-0.519034" y1="3.292995" x2="-0.518158" y2="2.545036" width="0.747960" depth="0.747960" height="2.074757" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-0-0" />
<door type="2" x1="-0.694971" y1="0.983772" x2="-1.419046" y2="0.983416" width="0.724080" depth="0.724080" height="2.081704" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-1-0" />
<window type="1" x1="-1.219716" y1="-1.457780" x2="0.704754" y2="-1.446953" width="1.924500" depth="0.120000" height="0.883190" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-1-1" />
<furniture type="0" x="0.050700" y="-1.337260" angle="0.000000" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-1-0" />
<furniture type="0" x="-2.048190" y="-1.044120" angle="0.000000" width="0.713860" depth="0.582300" height="1.000000" symbolInstance="F-1-1" />
<door type="2" x1="-0.650374" y1="3.459417" x2="-1.419574" y2="3.458999" width="0.769200" depth="0.769200" height="2.195494" insetX="0.000000" insetY="0.000000" orientation="0" symbolInstance="W-2-2" />
<door type="0" x1="1.527685" y1="5.468966" x2="1.527680" y2="6.722916" width="1.253950" depth="0.100000" height="0.676758" insetX="0.000000" insetY="0.060000" orientation="2" symbolInstance="W-3-2" />
<window type="1" x1="0.788778" y1="6.778432" x2="-1.628792" y2="6.778438" width="2.417570" depth="0.120000" height="1.180143" insetX="0.000000" insetY="-0.060000" orientation="0" symbolInstance="W-3-1" />
<furniture type="0" x="-0.580790" y="6.665440" angle="3.141590" width="1.000000" depth="0.106000" height="0.600000" symbolInstance="F-3-0" />
</exploded>
</floor>
</interiorRoomPoints>
</plan>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,224 +0,0 @@
import xml.etree.ElementTree as ET
from backend.magic_plan.models import (
MagicPlanXMLDoor,
MagicPlanXMLExploded,
MagicPlanXMLExplodedOpening,
MagicPlanXMLExplodedWall,
MagicPlanXMLFloor,
MagicPlanXMLFurniture,
MagicPlanXMLMainDimension,
MagicPlanXMLPlan,
MagicPlanXMLRoom,
MagicPlanXMLRoomPoint,
MagicPlanXMLSymbolInstance,
MagicPlanXMLWallPoint,
MagicPlanXMLWindow,
)
def _values(el: ET.Element) -> dict[str, str]:
return {v.get("key", ""): (v.text or "") for v in el.findall("values/value")}
def _parse_room_point(el: ET.Element) -> MagicPlanXMLRoomPoint:
return MagicPlanXMLRoomPoint(
snapped_x=float(el.get("snappedX", "0")),
snapped_y=float(el.get("snappedY", "0")),
height=float(el.get("height", "0")),
uid=el.get("uid", ""),
values=_values(el),
)
def _parse_wall_point(el: ET.Element) -> MagicPlanXMLWallPoint:
return MagicPlanXMLWallPoint(
x=float(el.get("x", "0")),
y=float(el.get("y", "0")),
height=float(el.get("height", "0")),
)
def _parse_door(el: ET.Element) -> MagicPlanXMLDoor:
return MagicPlanXMLDoor(
wall_point_index=int(el.get("point", "0")),
type=el.get("type", ""),
u=float(el.get("u", "0")),
width=float(el.get("width", "0")),
depth=float(el.get("depth", "0")),
height=float(el.get("height", "0")),
orientation=int(el.get("orientation", "0")),
snapped_type=el.get("snappedType", ""),
snapped_position=float(el.get("snappedPosition", "0")),
snapped_width=float(el.get("snappedWidth", "0")),
snapped_depth=float(el.get("snappedDepth", "0")),
snapped_height=float(el.get("snappedHeight", "0")),
snapped_orientation=int(el.get("snappedOrientation", "0")),
inset_x=float(el.get("insetX", "0")),
inset_y=float(el.get("insetY", "0")),
inset_z=float(el.get("insetZ", "0")),
symbol_instance=el.get("symbolInstance", ""),
twin_wall_item_uid=el.get("twinWallItemUid"),
)
def _parse_window(el: ET.Element) -> MagicPlanXMLWindow:
return MagicPlanXMLWindow(
wall_point_index=int(el.get("point", "0")),
type=el.get("type", ""),
u=float(el.get("u", "0")),
width=float(el.get("width", "0")),
depth=float(el.get("depth", "0")),
height=float(el.get("height", "0")),
orientation=int(el.get("orientation", "0")),
snapped_type=el.get("snappedType", ""),
snapped_position=float(el.get("snappedPosition", "0")),
snapped_width=float(el.get("snappedWidth", "0")),
snapped_depth=float(el.get("snappedDepth", "0")),
snapped_height=float(el.get("snappedHeight", "0")),
snapped_orientation=int(el.get("snappedOrientation", "0")),
inset_x=float(el.get("insetX", "0")),
inset_y=float(el.get("insetY", "0")),
inset_z=float(el.get("insetZ", "0")),
symbol_instance=el.get("symbolInstance", ""),
)
def _parse_exploded_opening(el: ET.Element) -> MagicPlanXMLExplodedOpening:
return MagicPlanXMLExplodedOpening(
type=el.get("type", ""),
x1=float(el.get("x1", "0")),
y1=float(el.get("y1", "0")),
x2=float(el.get("x2", "0")),
y2=float(el.get("y2", "0")),
width=float(el.get("width", "0")),
depth=float(el.get("depth", "0")),
height=float(el.get("height", "0")),
inset_x=float(el.get("insetX", "0")),
inset_y=float(el.get("insetY", "0")),
orientation=int(el.get("orientation", "0")),
symbol_instance=el.get("symbolInstance", ""),
)
def _parse_furniture(el: ET.Element) -> MagicPlanXMLFurniture:
return MagicPlanXMLFurniture(
type=el.get("type", ""),
x=float(el.get("x", "0")),
y=float(el.get("y", "0")),
snapped_x=float(el.get("snappedX", "0")),
snapped_y=float(el.get("snappedY", "0")),
angle=float(el.get("angle", "0")),
width=float(el.get("width", "0")),
depth=float(el.get("depth", "0")),
height=float(el.get("height", "0")),
snapped_width=float(el.get("snappedWidth", "0")),
snapped_depth=float(el.get("snappedDepth", "0")),
snapped_height=float(el.get("snappedHeight", "0")),
size_lock_0=el.get("sizeLock0", ""),
size_lock_1=el.get("sizeLock1", ""),
size_lock_2=el.get("sizeLock2", ""),
symbol_instance=el.get("symbolInstance", ""),
)
def _parse_main_dimension(el: ET.Element) -> MagicPlanXMLMainDimension:
return MagicPlanXMLMainDimension(
from_point=int(el.get("from", "0")),
to_point=int(el.get("to", "0")),
dir_x=float(el.get("dir.x", "0")),
dir_y=float(el.get("dir.y", "0")),
value=float(el.get("value", "0")),
actual_value=float(el.get("actualValue", "0")),
is_set=el.get("isSet", "0") == "1",
)
def _parse_exploded_wall(el: ET.Element) -> MagicPlanXMLExplodedWall:
type_el = el.find("type")
return MagicPlanXMLExplodedWall(
wall_type=(type_el.text or "") if type_el is not None else "",
points=[_parse_wall_point(p) for p in el.findall("point")],
)
def _parse_exploded(el: ET.Element) -> MagicPlanXMLExploded:
return MagicPlanXMLExploded(
walls=[_parse_exploded_wall(w) for w in el.findall("wall")],
doors=[_parse_exploded_opening(d) for d in el.findall("door")],
windows=[_parse_exploded_opening(w) for w in el.findall("window")],
furniture=[_parse_furniture(f) for f in el.findall("furniture")],
)
def _parse_symbol_instance(el: ET.Element) -> MagicPlanXMLSymbolInstance:
return MagicPlanXMLSymbolInstance(
id=el.get("id", ""),
uid=el.get("uid", ""),
parent_uid=el.get("parentUid", ""),
symbol=el.get("symbol", ""),
values=_values(el),
)
def _parse_floor(el: ET.Element) -> MagicPlanXMLFloor:
si_el = el.find("symbolInstance")
exploded_el = el.find("exploded")
return MagicPlanXMLFloor(
uid=el.get("uid", ""),
name=el.findtext("name") or "",
floor_type=el.get("floorType", "0"),
rotation=float(el.get("rotation", "0")),
compass_angle=float(el.get("compassAngle", "0")),
area_without_walls=float(el.get("areaWithoutWalls", "0")),
area_with_interior_walls_only=float(el.get("areaWithInteriorWallsOnly", "0")),
area_with_walls=float(el.get("areaWithWalls", "0")),
symbol_instance=_parse_symbol_instance(si_el) if si_el is not None
else MagicPlanXMLSymbolInstance(id="", uid="", parent_uid="", symbol="", values={}),
rooms=[_parse_room(r) for r in el.findall("floorRoom")],
furniture=[_parse_furniture(f) for f in el.findall("furniture")],
exploded=_parse_exploded(exploded_el) if exploded_el is not None
else MagicPlanXMLExploded(walls=[], doors=[], windows=[], furniture=[]),
)
def _parse_room(el: ET.Element) -> MagicPlanXMLRoom:
return MagicPlanXMLRoom(
uid=el.get("uid", ""),
type=el.get("type", ""),
x=float(el.get("x", "0")),
y=float(el.get("y", "0")),
rotation=float(el.get("rotation", "0")),
was_modified=el.get("wasModified", "0") == "1",
linked_room_0=el.get("linkedRoom0", "-1"),
linked_room_1=el.get("linkedRoom1", "-1"),
area=float(el.get("area", "0")),
perimeter=float(el.get("perimeter", "0")),
values=_values(el),
points=[_parse_room_point(p) for p in el.findall("point")],
doors=[_parse_door(d) for d in el.findall("door")],
windows=[_parse_window(w) for w in el.findall("window")],
furniture=[_parse_furniture(f) for f in el.findall("furniture")],
main_dimensions=[_parse_main_dimension(d) for d in el.findall("mainDimension")],
)
def parse_magicplan_xml(xml_str: str) -> MagicPlanXMLPlan:
root = ET.fromstring(xml_str)
irp_el = root.find("interiorRoomPoints")
return MagicPlanXMLPlan(
id=root.get("id", ""),
uid=root.get("uid", ""),
name=root.get("name", ""),
type=root.get("type", ""),
interior_wall_width=float(root.get("interiorWallWidth", "0")),
exterior_wall_width=float(root.get("exteriorWallWidth", "0")),
schematic=root.get("schematic", "0") == "1",
has_land_survey_address=root.get("hasLandSurveyAddress", "0") == "1",
last_patch_identifier=root.get("lastPatchIdentifier", ""),
last_roll_identifier=root.get("lastRollIdentifier", ""),
values=_values(root),
floors=[_parse_floor(f) for f in root.findall("floor")],
interior_room_floors=[_parse_floor(f) for f in irp_el.findall("floor")]
if irp_el is not None else [],
)

View file

@ -1,48 +0,0 @@
# MagicPlan Exchange XML Schema Reference
# Derived from xml_example.xml and https://apidocs.magicplan.app/guide/basic-concepts/plan-exchange-xml-format
#
# <plan>
# attrs: name, id, uid, type, interiorWallWidth (m), exteriorWallWidth (m),
# schematic, hasLandSurveyAddress, lastPatchIdentifier, lastRollIdentifier
# children: <values>, <floor>+, <interiorRoomPoints>
#
# <values> (plan-level metadata)
# children: <value key="...">text</value>
# known keys: date, statistics.areaOfHeight, statistics.basement.account,
# statistics.exteriorWalls, statistics.interiorWalls
#
# <floor>
# attrs: uid, floorType (0=ground 1=upper), rotation, compassAngle,
# areaWithoutWalls (m²), areaWithInteriorWallsOnly (m²), areaWithWalls (m²)
# children: <name>, <symbolInstance>, <floorRoom>+, <exploded>
#
# <floorRoom>
# attrs: type (room label e.g. "Kitchen"), uid, x, y, rotation,
# wasModified, linkedRoom0, linkedRoom1, area (m²), perimeter (m)
# children: <values> (key: ceilingHeight m), <point>+, <door>*, <window>*, <furniture>*, <mainDimension>*
#
# <point> (room corner polygon)
# attrs: snappedX (m), snappedY (m), height (m), uid
#
# <door>
# attrs: point, type, u, width (m), depth (m), height (m), orientation,
# snappedType, snappedPosition, snappedWidth, snappedDepth, snappedHeight, snappedOrientation,
# insetX, insetY, insetZ, twinWallItemUid, symbolInstance
#
# <window>
# attrs: point, type, u, width (m), depth (m), height (m), orientation,
# snappedType, snappedPosition, snappedWidth, snappedDepth, snappedHeight, snappedOrientation,
# insetX, insetY, insetZ, symbolInstance
#
# <exploded> (wall geometry per floor)
# children: <wall>, <door>, <window>, <furniture>
# <wall> children: <point x y height>, <type> (text: "exterior" | "interior")
#
# <interiorRoomPoints>
# children: <floor> (same structure as top-level floor, interior wall room shapes)
#
# All distances in metres. All areas in m².
FLOOR_TYPE_GROUND = "0"
FLOOR_TYPE_UPPER = "1"
FLOOR_TYPE_BASEMENT = "2"