gojs
Version:
Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams
498 lines (444 loc) • 52.2 kB
HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Floorplanner (Typescript)</title>
<meta name="description" content="" />
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<!-- Local JS -->
<!-- GoJS -->
<script src="../../release/go.js"></script>
<!-- GoEditor framework basic setup -->
<script src="./goeditor-setup.js"></script>
<!-- Base Data Inspector class -->
<script src="./DataInspector.js"></script>
<!-- Floorplanner specific tweaks to Data Inspector class -->
<script src="./floorplanner-datainspector-overrides.js"></script>
<!-- Go Cloud Storage Classes -->
<script src="../../projects/storage/lib/gcs.js"></script>
<!-- CDN's for GoCloud Storage subclasses -->
<script src="https://apis.google.com/js/api.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropbox.js/2.5.7/Dropbox-sdk.min.js"></script>
<script src="https://js.live.net/v7.2/OneDrive.js"></script>
<script type="text/javascript" src="https://www.dropbox.com/static/api/2/dropins.js" id="dropboxjs" data-app-key="3sm2ko6q7u1gbix"></script>
<!-- GoFloorPlanner bundle -->
<script src="./lib/gfp.js"></script>
<!-- jQuery / UI JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<!-- CSS for GoCloudStorage/Manager -->
<link rel="stylesheet" type="text/css" href="../../projects/storage/samples/GoCloudStorageUI.css" />
<!-- jQuery UI CSS -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<!-- CSS for this app -->
<link rel="stylesheet" type="text/css" href="./goeditor.css" />
<link rel="stylesheet" type="text/css" href="./floorplanner.css" />
<script>
JQUERY = $;
function init() {
Floorplan = gfp.Floorplan;
FloorplanPalette = gfp.FloorplanPalette;
WallBuildingTool = gfp.WallBuildingTool;
WallReshapingTool = gfp.WallReshapingTool;
// Do not remove this function call! This sets up your editor
setupEditorApplication(1, 2, "../../projects/storage", Floorplan);
// replace generic palettes with FloorplanPalettes
myFloorplan = diagrams[0];
palettes[0].div = null;
palettes[1].div = null;
furniturePalette = new FloorplanPalette("ge-palette-0", myFloorplan);
furniturePalette.model = new go.GraphLinksModel(myFloorplan.makeDefaultFurniturePaletteNodeData());
palettes[0] = furniturePalette;
wallPartsPalette = new FloorplanPalette("ge-palette-1", myFloorplan);
wallPartsPalette.model = new go.GraphLinksModel(myFloorplan.makeDefaultWallpartsPaletteNodeData());
palettes[1] = wallPartsPalette;
// set default model for all Cloud Storage subclasses
for (i in storages) {
var storage = storages[i];
var dm = JSON.stringify({
"class": "GraphLinksModel",
"copiesKey": false,
"modelData": { "units": "meters", "unitsAbbreviation": "m", "unitsConversionFactor": 0.02, "gridSize": 10, "wallThickness": 10, "preferences": { "showWallGuidelines": true, "showWallLengths": true, "showWallAngles": true, "showOnlySmallWallAngles": true, "showGrid": true, "gridSnap": true } },
"nodeDataArray": [],
"linkDataArray": []
});
storage.defaultModel = dm;
}
// listen if the model of the Floorplan changes completely -- if so, there has been a load event, and we must update walls / rooms
myFloorplan.addDiagramListener("InitialLayoutCompleted", function (e) {
// update units, grid size, units / px, showGrid, and preferences from the loading model's modelData
var unitsForm = document.getElementById('unitsForm');
var gridSizeInput = document.getElementById('gridSizeInput');
var showGridCheckbox = document.getElementById('showGridCheckbox');
var gridSnapCheckbox = document.getElementById('gridSnapCheckbox');
var showWallGuidelinesCheckbox = document.getElementById('wallGuidelinesCheckbox');
var showWallLengthsCheckbox = document.getElementById('wallLengthsCheckbox');
var showWallAnglesCheckbox = document.getElementById('wallAnglesCheckbox');
var showOnlySmallWallAnglesCheckbox = document.getElementById('onlySmallWallAnglesCheckbox');
var unitsConversionFactorInput = document.getElementById('unitsConversionFactorInput');
var fp = e.diagram;
var md = fp.model.modelData;
var units = md.units;
// if (units === undefined) return;
var unitsRadioChecked = document.getElementById(units);
unitsRadioChecked.checked = true;
var gridSize = md.gridSize;
gridSize = fp.convertPixelsToUnits(gridSize);
gridSizeInput.value = gridSize;
fp.changeGridSize(gridSizeInput);
var unitsConversionFactor = md.unitsConversionFactor;
unitsConversionFactorInput.value = unitsConversionFactor;
fp.changeUnitsConversionFactor(unitsConversionFactorInput, gridSizeInput);
fp.changeUnits(unitsForm);
var showGrid = md.preferences.showGrid;
var gridSnap = md.preferences.gridSnap;
var showWallGuidelines = md.preferences.showWallGuidelines;
var showWallLengths = md.preferences.showWallLengths;
var showWallAngles = md.preferences.showWallAngles;
var showOnlySmallWallAngles = md.preferences.showOnlySmallWallAngles;
showGridCheckbox.checked = showGrid;
gridSnapCheckbox.checked = gridSnap;
showWallGuidelinesCheckbox.checked = showWallGuidelines;
showWallLengthsCheckbox.checked = showWallLengths;
showWallAnglesCheckbox.checked = showWallAngles;
showOnlySmallWallAnglesCheckbox = showOnlySmallWallAngles;
fp.checkboxChanged('showGridCheckbox');
fp.checkboxChanged('gridSnapCheckbox');
fp.checkboxChanged('wallGuidelinesCheckbox');
fp.checkboxChanged('wallLengthsCheckbox');
fp.checkboxChanged('wallAnglesCheckbox');
fp.checkboxChanged('onlySmallWallAnglesCheckbox');
// update walls and rooms geometries
fp.nodes.iterator.each(function (n) {
if (n.category === "WallGroup") {
fp.updateWall(n);
}
if (n.category === "RoomNode") {
fp.updateRoom(n);
}
});
});
// Update the tools buttons so the tool in use is highlighted
updateButtons = function (func, el) {
func.call(myFloorplan);
var toolButtons = document.getElementsByClassName('toolButtons');
for (var i = 0; i < toolButtons.length; i++) {
var tb = toolButtons[i];
if (tb === el) {
tb.style.background = "#4b545f";
tb.style.color = "white";
}
else {
tb.style.background = "rgb(221, 221, 221)";
tb.style.color = "black";
}
}
}
JQUERY(function () {
JQUERY("#ge-palettes-container").accordion({
heightStyle: "content",
activate: function (event, ui) {
for (var i = 0; i < palettes.length; i++) {
var palette = palettes[i];
palette.requestUpdate();
}
}
});
//JQUERY("#ge-overviews-container").accordion();
var draggables = document.getElementsByClassName("ge-draggable");
for (var i = 0; i < draggables.length; i++) {
var draggable = draggables[i];
var id = "#" + draggable.id; var hid = id + "-handle";
// When a window is dragged, its height is set. this is bad. unset height / maybe width after dragging
JQUERY(id).draggable({
handle: hid, stack: ".ge-draggable", containment: "parent", scroll: false, stop: function (event) {
this.style.height = "unset";
var did = event.target.id;
// only unset width for inspector and options menu, whose widths are dependent on contents
if (did === 'ge-inspector-window' || did === 'optionsWindow') {
this.style.width = "unset";
}
}
});
}
}); // end jQuery
// add options window hotkey (other hotkeys are defined in goeditor-setup.js)
document.body.addEventListener("keydown", function (e) {
var keynum = e.which;
if (e.ctrlKey) {
e.preventDefault();
switch (keynum) {
case 66: geHideShowWindow('optionsWindow'); break; // ctrl + b
}
}
});
// function to tweal inspector for app-specific stuff is in floorplanner-datainspector-overrides.js
tweakInspectorForFloorplanner(inspector);
var defaultModelTextarea = document.getElementById('defaultModelTextarea');
var defaultModelString = defaultModelTextarea.value;
var defaultModelJson = JSON.parse(defaultModelString);
myFloorplan.model = go.Model.fromJson(defaultModelJson);
} // end init
</script>
</head>
<body onload="init();">
<div>
<nav>
<span id="currentStorageSpan"></span>
<ul id="ge-filemenus">
<li>
<a href="#">File</a>
<ul>
<li><a href="#" onclick="handlePromise('New')">New <p class="ge-shortcut">(Ctrl + D)</p></a></li>
<li><a href="#" onclick="handlePromise('Load')">Open... <p class="ge-shortcut">(Ctrl + O)</p></a></li>
<li><a href="#" onclick="handlePromise('Save')">Save <p class="ge-shortcut">(Ctrl + S)</p></a></li>
<li><a href="#" onclick="handlePromise('SaveAs')">Save As...</a></li>
<li><a href="#" onclick="handlePromise('Delete')">Remove... <p class="ge-shortcut">(Ctrl + R)</p></a></li>
<li><a href="#" onclick="makeDiagramImage()">Export PNG</a></li>
<li><a href="#" onclick="makeDiagramSvg()">Export SVG</a></li>
<li><a href="#" onclick="updateCurrentStorageSpan()">Change Storage Service</a></li>
</ul>
</li>
<li>
<a href="#">View</a>
<ul>
<li id="ge-viewoption-palettes"><a href="#" onclick="geHideShowWindow('ge-palettes-window', true)" id="ge-palettes-windows-button">Palettes
<p class="ge-shortcut"> (Ctrl + P)</p></a></li>
<li id="ge-viewoption-overviews"><a href="#" onclick="geHideShowWindow('ge-overviews-window', true)" id="ge-overview-windows-button">Overview
<p class="ge-shortcut"> (Ctrl + E)</p></a></li>
<li id="ge-viewoption-inspector"><a href="#" onclick="geHideShowWindow('ge-inspector-window', true)" id="ge-inspector-windows-button">Inspector
<p class="ge-shortcut"> (Ctrl + I)</p></a></li>
<li id="ge-viewoption-options"><a href="#" onclick="geHideShowWindow('optionsWindow', true)" id="optionsWindow-button">Options<p
class="ge-shortcut">(Ctrl + B)</p></a></li>
</ul>
</li>
</ul>
<div id="toolButtonsDiv" style="float: left;">
<button class="toolButtons" onclick="updateButtons(myFloorplan.enableWallBuilding, this)">Build Walls</button>
<button class="toolButtons" onclick="updateButtons(myFloorplan.enableDividerBuilding, this)">Build Room
Dividers</button>
<button class="toolButtons" onclick="updateButtons(myFloorplan.disableWallBuilding, this)">Select</button>
</div>
<p id="isAutoSavingP"><input type="checkbox" id="isAutoSavingCheckbox" unchecked /> <label for="isAutoSavingCheckbox">Autosave
Enabled</label></p>
<p id="ge-header">GoFloorPlanner</p>
<div id="ge-filename">(Unsaved file)</div>
</nav>
<input type="file" id="file-input" style="display: none;" />
<div id="ge-diagrams-container" style="display: flex;">
<div id="ge-diagram-0" style="height: 800px; width: 100%; background: #DAE4E4; border: 1px solid black; "></div>
</div>
<div id="ge-palettes-window" style="visibility: visible" class="ge-draggable ui-draggable">
<div id="ge-palettes-window-handle" class="ge-handle ui-draggable-handle">Palettes<button id="ge-palettes-window-close"
class="ge-window-button ge-clickable" onclick="geHideShowWindow('ge-palettes-window')">X</button></div>
<div id="ge-palettes-container">
<h3>Furniture</h3>
<div>
<div id="ge-palette-0" style="height: 500px; background: lightgray; border: 1px solid black; "></div>
</div>
<h3>Wall Parts</h3>
<div>
<div id="ge-palette-1" style="height: 500px; background: lightgray; border: 1px solid black; "></div>
</div>
</div>
</div>
<div id="ge-overviews-window" style="visibility: visible" class="ge-draggable ui-draggable">
<div id="ge-overviews-window-handle" class="ge-handle ui-draggable-handle">Overview<button id="ge-overviews-window-close"
class="ge-window-button ge-clickable" onclick="geHideShowWindow('ge-overviews-window')">X</button></div>
<!--<div id="ge-overviews-container">
<h3> Overview</h3><div> -->
<div id="ge-overview-0" style="height: 200px; background: white; border: 1px solid black; "></div>
</div>
<!--</div> -->
</div>
<div id="ge-inspector-window" style="visibility: visible" class="ge-draggable ui-draggable">
<div id="ge-inspector-window-handle" class="ge-handle ui-draggable-handle">Properties<button id="ge-inspector-window-close"
class="ge-window-button ge-clickable" onclick="geHideShowWindow('ge-inspector-window')">X</button></div>
<div id="ge-inspector" class="inspector"></div>
</div>
<div id="optionsWindow" style="visibility: hidden;" class="ge-draggable ui-draggable">
<div id="optionsWindow-handle" class="ge-handle ui-draggable-handle">Options <button id="optionsWindowClose" class="windowButtons ge-window-button ge-clickable"
onclick="geHideShowWindow('optionsWindow')">X</button></div>
Units
<div id="unitsRow" class="row data">
<form id="unitsForm" onchange="myFloorplan.changeUnits(this)">
<div class="col-4">
<input type="radio" name="units" id="centimeters" />cm
</div>
<div class="col-4">
<input type="radio" name="units" id="meters" checked /> m
</div>
<div class="col-4">
<input type="radio" name="units" id="inches" />in
</div>
<div class="col-4">
<input type="radio" name="units" id="feet" />ft
</div>
</form>
</div>
Grid
<div id="gridRow" class="row">
<div class="col-2">
<label for="gridSizeInput" style="float: left;">Grid size</label>
<input id="gridSizeInput" placeholder="" class="unitsInput" onchange="myFloorplan.changeGridSize(this)" value="20" />
<input id="gridSizeUnitsInput" class="unitsBox" value="cm" disabled />
</div>
<div class="col-2">
<input type="checkbox" id="showGridCheckbox" onchange="myFloorplan.checkboxChanged('showGridCheckbox')" checked />Show
Grid
</div>
</div>
<div id="gridRow" class="row">
<div class="col-1">
<label for="unitsConversionFactorInput" style="float: left;">Units/1px (at scale 100%)</label>
<input id="unitsConversionFactorInput" placeholder="" onchange="myFloorplan.changeUnitsConversionFactor(this, document.getElementById('gridSizeInput'))"
class="unitsInput" value=".02" />
<input id="" class="unitsBox" value="cm" disabled />
</div>
</div>
Preferences
<div id="miscRow" class="row data">
<div class="col-1">
<input type="checkbox" id="gridSnapCheckbox" onchange="myFloorplan.checkboxChanged('gridSnapCheckbox')" checked />Grid
Snap
</div>
<div class="col-1">
<input type="checkbox" id="wallGuidelinesCheckbox" onchange="myFloorplan.checkboxChanged('wallGuidelinesCheckbox')"
checked /> Show Wall Guidelines
</div>
<div class="col-1">
<input type="checkbox" id="wallLengthsCheckbox" onchange="myFloorplan.checkboxChanged('wallLengthsCheckbox')"
checked /> Show Wall Lengths
</div>
<div class="col-1">
<input type="checkbox" id="wallAnglesCheckbox" onchange="myFloorplan.checkboxChanged('wallAnglesCheckbox')"
checked /> Show Wall Angles
</div>
<div class="col-1">
<input type="checkbox" id="onlySmallWallAnglesCheckbox" onchange="myFloorplan.checkboxChanged('onlySmallWallAnglesCheckbox')"
checked /> Show Only Non-Reflex Wall Angles
</div>
</div>
</div>
</div>
<div id="ge-footer">
<span>Built with the <a href="https://gojs.net">GoJS Diagramming Library</a>, by <a href="https://nwoods.com">
Northwoods Software</a>.</span>
</div>
<p>
This Floorplanner extension of GoJS makes use of multiple classes to allow for users to build, edit, save, and load
feature-rich Floorplans.
To start, build walls (press the 'Build Walls') button to activate the WallBuildingTool, or drag furniture from
Palettes onto the Floorplan area.
When you have an area enclosed by walls, you can create a room there by dragging the floor area node from the Wall
Parts palette, or by right-clicking
within your enclosed area and clicking 'Make Room'.
</p>
<p>
You may also define areas with dividers, which allow one to specify different floor types without the need for wall
boundaries. This is useful if you want to have multiple
types of flooring within a single room, or want to define an area of floor that has no walls.
</p>
<p>
This extension uses the following Floorplanner-specific files:
<ul>
<li><a href="./src/Floorplan.ts">Floorplan.ts</a> - A special kind of <a href="../../api/symbols/Diagram.html">Diagram</a>
with listeners, properties, and methods that help with floorplanning </li>
<li><a href="./src/FloorplanPalette.ts">FloorplanPalette.ts</a> - A special kind of <a href="../../api/symbols/Palette.html">Palette</a>
linked with a specific instance of Floorplan </li>
<li><a href="./src/WallBuildingTool.ts">WallBuildingTool.ts</a> - For constructing new walls / dividers. This
works in conjunction with WallReshapingTool </li>
<li><a href="./src/WallReshapingTool.ts">WallReshapingTool.ts</a> - For reshaping walls / dividers from their
endpoints </li>
</ul>
</p>
<p>
Additionally, this sample makes use of the <a href="../../intro/storage.html">GoCloudStorage</a> library, which
allows users to save / load diagram files to / from LocalStorage, Google Drive, Microsoft OneDrive, and Dropbox.
</p>
<p>
To modify this extension, one must modify the .ts source files (in this project's 'src' directory'), then run <code>npm run build</code>
from the project's main directory. This will output a new
<code>gfp.js</code> bundle that can be used.
</p>
<textarea style='visibility: hidden;' id='defaultModelTextarea'>
{ "class": "GraphLinksModel",
"copiesKey": false,
"modelData": {"units":"meters", "unitsAbbreviation":"m", "unitsConversionFactor":0.02, "gridSize":10, "wallThickness":10, "preferences":{"showWallGuidelines":true, "showWallLengths":true, "showWallAngles":true, "showOnlySmallWallAngles":true, "showGrid":true, "gridSnap":true}},
"nodeDataArray": [
{"key":"wall6", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-910, "y":-320}, "endpoint":{"class":"go.Point", "x":-773, "y":-320}, "smpt1":{"class":"go.Point", "x":-905, "y":-315}, "smpt2":{"class":"go.Point", "x":-915, "y":-325}, "empt1":{"class":"go.Point", "x":-778, "y":-315}, "empt2":{"class":"go.Point", "x":-773, "y":-325}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall5", "category":"WallGroup", "caption":"Wall", "type":"Wall", "startpoint":{"class":"go.Point", "x":-490, "y":-97.6667}, "endpoint":{"class":"go.Point", "x":-490, "y":-320}, "smpt1":{"class":"go.Point", "x":-485, "y":-97.6667}, "smpt2":{"class":"go.Point", "x":-495, "y":-102.6667}, "empt1":{"class":"go.Point", "x":-485, "y":-315}, "empt2":{"class":"go.Point", "x":-495, "y":-315}, "thickness":10, "color":"lightgray", "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall11", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-490, "y":-320}, "endpoint":{"class":"go.Point", "x":-120, "y":-320}, "smpt1":{"class":"go.Point", "x":-485, "y":-315}, "smpt2":{"class":"go.Point", "x":-490, "y":-325}, "empt1":{"class":"go.Point", "x":-125, "y":-315}, "empt2":{"class":"go.Point", "x":-124.99646446609407, "y":-325}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall12", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-773, "y":-178.66666793823242}, "endpoint":{"class":"go.Point", "x":-631, "y":-178.66666793823242}, "smpt1":{"class":"go.Point", "x":-768, "y":-173.66666793823242}, "smpt2":{"class":"go.Point", "x":-768, "y":-183.66666793823242}, "empt1":{"class":"go.Point", "x":-636, "y":-173.66666793823242}, "empt2":{"class":"go.Point", "x":-636, "y":-183.66666793823242}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall13", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-631, "y":-97.6667}, "endpoint":{"class":"go.Point", "x":-490, "y":-97.6667}, "smpt1":{"class":"go.Point", "x":-636, "y":-92.6667}, "smpt2":{"class":"go.Point", "x":-626, "y":-102.6667}, "empt1":{"class":"go.Point", "x":-490.0025, "y":-92.6667}, "empt2":{"class":"go.Point", "x":-495, "y":-102.6667}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall2", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-773, "y":-320}, "endpoint":{"class":"go.Point", "x":-631, "y":-320}, "smpt1":{"class":"go.Point", "x":-768, "y":-315}, "smpt2":{"class":"go.Point", "x":-773, "y":-325}, "empt1":{"class":"go.Point", "x":-636, "y":-315}, "empt2":{"class":"go.Point", "x":-631, "y":-325}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall14", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-631, "y":-320}, "endpoint":{"class":"go.Point", "x":-490, "y":-320}, "smpt1":{"class":"go.Point", "x":-626, "y":-315}, "smpt2":{"class":"go.Point", "x":-631, "y":-325}, "empt1":{"class":"go.Point", "x":-495, "y":-315}, "empt2":{"class":"go.Point", "x":-490, "y":-325}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall10", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-631, "y":-320}, "endpoint":{"class":"go.Point", "x":-631, "y":-178.66666793823242}, "smpt1":{"class":"go.Point", "x":-636, "y":-315}, "smpt2":{"class":"go.Point", "x":-626, "y":-315}, "empt1":{"class":"go.Point", "x":-636, "y":-183.66666793823242}, "empt2":{"class":"go.Point", "x":-626, "y":-178.66666793823242}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall15", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-631, "y":-178.66666793823242}, "endpoint":{"class":"go.Point", "x":-631, "y":-97.6667}, "smpt1":{"class":"go.Point", "x":-636, "y":-173.66666793823242}, "smpt2":{"class":"go.Point", "x":-626, "y":-178.66666793823242}, "empt1":{"class":"go.Point", "x":-636, "y":-92.6667}, "empt2":{"class":"go.Point", "x":-626, "y":-102.6667}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall8", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-773, "y":-10}, "endpoint":{"class":"go.Point", "x":-773, "y":-178.66666793823242}, "smpt1":{"class":"go.Point", "x":-768, "y":-10}, "smpt2":{"class":"go.Point", "x":-778, "y":-10}, "empt1":{"class":"go.Point", "x":-768, "y":-173.66666793823242}, "empt2":{"class":"go.Point", "x":-778, "y":-178.66666793823242}, "thickness":10, "isGroup":true, "notes":""},
{"key":"wall9", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-773, "y":-178.66666793823242}, "endpoint":{"class":"go.Point", "x":-773, "y":-320}, "smpt1":{"class":"go.Point", "x":-768, "y":-183.66666793823242}, "smpt2":{"class":"go.Point", "x":-778, "y":-178.66666793823242}, "empt1":{"class":"go.Point", "x":-768, "y":-315}, "empt2":{"class":"go.Point", "x":-778, "y":-315}, "thickness":10, "isGroup":true, "notes":""},
{"key":"wall16", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-120, "y":200}, "endpoint":{"class":"go.Point", "x":-670.32, "y":200}, "smpt1":{"class":"go.Point", "x":-125, "y":195}, "smpt2":{"class":"go.Point", "x":-124.99646446609407, "y":205}, "empt1":{"class":"go.Point", "x":-665.32, "y":195}, "empt2":{"class":"go.Point", "x":-670.32, "y":205}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall18", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-120, "y":-320}, "endpoint":{"class":"go.Point", "x":-120, "y":10}, "smpt1":{"class":"go.Point", "x":-125, "y":-315}, "smpt2":{"class":"go.Point", "x":-115, "y":-314.99646446609404}, "empt1":{"class":"go.Point", "x":-125, "y":0}, "empt2":{"class":"go.Point", "x":-115, "y":10}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall19", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-120, "y":10}, "endpoint":{"class":"go.Point", "x":-120, "y":200}, "smpt1":{"class":"go.Point", "x":-125, "y":20}, "smpt2":{"class":"go.Point", "x":-115, "y":10}, "empt1":{"class":"go.Point", "x":-125, "y":195}, "empt2":{"class":"go.Point", "x":-115, "y":194.99646446609407}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall4", "category":"WallGroup", "caption":"Divider", "type":"Divider", "startpoint":{"class":"go.Point", "x":-120, "y":-320}, "endpoint":{"class":"go.Point", "x":100, "y":-100}, "smpt1":{"class":"go.Point", "x":-115, "y":-314.99646446609404}, "smpt2":{"class":"go.Point", "x":-124.99646446609407, "y":-325}, "empt1":{"class":"go.Point", "x":99.9975, "y":-99.99896446609407}, "empt2":{"class":"go.Point", "x":100.0025, "y":-100.00103553390593}, "thickness":0.005, "color":"lightgray", "isGroup":true, "notes":"", "isDivider":true},
{"key":"wall25", "category":"WallGroup", "caption":"Divider", "type":"Divider", "startpoint":{"class":"go.Point", "x":-120, "y":200}, "endpoint":{"class":"go.Point", "x":100, "y":-20}, "smpt1":{"class":"go.Point", "x":-124.99646446609407, "y":205}, "smpt2":{"class":"go.Point", "x":-115, "y":194.99646446609407}, "empt1":{"class":"go.Point", "x":100.0025, "y":-19.99896446609407}, "empt2":{"class":"go.Point", "x":99.9975, "y":-20.00103553390593}, "thickness":0.005, "color":"lightgray", "isGroup":true, "notes":"", "isDivider":true},
{"key":"wall22", "category":"WallGroup", "caption":"Divider", "type":"Divider", "startpoint":{"class":"go.Point", "x":-490, "y":-97.6667}, "endpoint":{"class":"go.Point", "x":-490, "y":10}, "smpt1":{"class":"go.Point", "x":-490.0025, "y":-92.6667}, "smpt2":{"class":"go.Point", "x":-489.9975, "y":-97.6667}, "empt1":{"class":"go.Point", "x":-490.0025, "y":0}, "empt2":{"class":"go.Point", "x":-489.9975, "y":0}, "thickness":0.005, "color":"lightgray", "isGroup":true, "notes":"", "isDivider":true},
{"key":"wall23", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"#d3d3d3", "startpoint":{"class":"go.Point", "x":-670.32, "y":10}, "endpoint":{"class":"go.Point", "x":-490, "y":10}, "smpt1":{"class":"go.Point", "x":-665.32, "y":20}, "smpt2":{"class":"go.Point", "x":-675.32, "y":0}, "empt1":{"class":"go.Point", "x":-490, "y":20}, "empt2":{"class":"go.Point", "x":-490.0025, "y":0}, "thickness":20, "isGroup":true, "notes":""},
{"key":"wall26", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"#d3d3d3", "startpoint":{"class":"go.Point", "x":-490, "y":10}, "endpoint":{"class":"go.Point", "x":-120, "y":10}, "smpt1":{"class":"go.Point", "x":-490, "y":20}, "smpt2":{"class":"go.Point", "x":-489.9975, "y":0}, "empt1":{"class":"go.Point", "x":-125, "y":20}, "empt2":{"class":"go.Point", "x":-125, "y":0}, "thickness":20, "isGroup":true, "notes":""},
{"key":"Room", "category":"RoomNode", "name":"Patio", "boundaryWalls":[ [ "wall4",1 ],[ "wall18",2 ],[ "wall19",2 ],[ "wall25",2 ],[ "wall29",1 ] ], "holes":[], "floorImage":"./images/textures/floor6.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-115, "y":-314.99646446609404}, "area":63423.27973184812, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":-5.103470996432179, "offsetY":-64.0326718168821}},
{"key":"Room2", "category":"RoomNode", "name":"Living Room", "boundaryWalls":[ [ "wall23",1 ],[ "wall21",1 ],[ "wall20",1 ],[ "wall16",1 ],[ "wall19",1 ],[ "wall26",1 ] ], "holes":[], "floorImage":"./images/textures/floor7.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-665.32, "y":20}, "area":94556, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":-181.9269405923115, "offsetY":49.07812025216799}},
{"key":"Room3", "category":"RoomNode", "name":"Hallway", "boundaryWalls":[ [ "wall12",1 ],[ "wall8",1 ],[ "wall8",2 ],[ "wall9",2 ],[ "wall6",1 ],[ "wall7",2 ],[ "wall17",2 ],[ "wall21",2 ],[ "wall23",2 ],[ "wall22",1 ],[ "wall13",1 ],[ "wall15",1 ] ], "holes":[], "floorImage":"images/textures/floor1.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-905, "y":-315}, "area":91348.35030109668, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":52.650999571264606, "offsetY":67.99831835696534}},
{"key":"Room4", "category":"RoomNode", "name":"Kitchen / Dining Room", "boundaryWalls":[ [ "wall11",1 ],[ "wall5",1 ],[ "wall22",2 ],[ "wall26",2 ],[ "wall18",1 ] ], "holes":[], "floorImage":"./images/textures/floor4.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-489.9975, "y":-315}, "area":113888.08933324998, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":-80.49751952755344, "offsetY":29.97379349825087}},
{"key":"Room5", "category":"RoomNode", "name":"Bathroom", "boundaryWalls":[ [ "wall14",1 ],[ "wall10",2 ],[ "wall15",2 ],[ "wall13",2 ],[ "wall5",2 ] ], "holes":[], "floorImage":"./images/textures/floor5.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-626, "y":-315}, "area":27815.6623},
{"key":"Room6", "category":"RoomNode", "name":"Laundry Room", "boundaryWalls":[ [ "wall2",1 ],[ "wall9",1 ],[ "wall12",2 ],[ "wall10",1 ] ], "holes":[], "floorImage":"./images/textures/floor5.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-768, "y":-315}, "area":17335.99983215332, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":19.00442716769237, "offsetY":27.642803153007236}},
{"key":"door", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-876.8531037797546 -320", "group":"wall6", "angle":180},
{"key":"door2", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-697.8658953341261 -178.66666793823242", "group":"wall12"},
{"key":"door3", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"right", "notes":"", "loc":"-631 -248.59768600237845", "group":"wall10", "angle":270},
{"key":"door4", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-557.5153168347209 -97.6667", "group":"wall13"},
{"key":"door5", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-120 -50.50422651153826", "group":"wall18", "angle":90},
{"key":"door6", "category":"DoorNode", "caption":"Door", "type":"Door", "length":50, "doorOpeningHeight":20, "swing":"right", "notes":"", "loc":"-236.61674968371233 10", "group":"wall26", "angle":180, "color":"#000000"},
{"category":"WindowNode", "key":"window", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-705 -320", "group":"wall2"},
{"category":"WindowNode", "key":"window2", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-559 -320", "group":"wall14"},
{"key":"door7", "category":"DoorNode", "caption":"Door", "type":"Door", "length":50, "doorOpeningHeight":20, "swing":"left", "notes":"", "loc":"-596 10", "group":"wall23", "angle":180, "color":"#000000"},
{"key":"wall3", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-670.32, "y":200}, "endpoint":{"class":"go.Point", "x":-910, "y":200}, "smpt1":{"class":"go.Point", "x":-675.32, "y":195}, "smpt2":{"class":"go.Point", "x":-670.32, "y":205}, "empt1":{"class":"go.Point", "x":-905, "y":195}, "empt2":{"class":"go.Point", "x":-915, "y":205}, "thickness":10, "isGroup":true, "notes":""},
{"key":"wall17", "category":"WallGroup", "caption":"Wall", "type":"Wall", "startpoint":{"class":"go.Point", "x":-910, "y":69.39500000000001}, "endpoint":{"class":"go.Point", "x":-670.32, "y":69.39500000000001}, "smpt1":{"class":"go.Point", "x":-905, "y":74.39500000000001}, "smpt2":{"class":"go.Point", "x":-905, "y":64.39500000000001}, "empt1":{"class":"go.Point", "x":-675.32, "y":74.39500000000001}, "empt2":{"class":"go.Point", "x":-675.32, "y":64.39500000000001}, "thickness":10, "color":"lightgray", "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall20", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-670.32, "y":200}, "endpoint":{"class":"go.Point", "x":-670.32, "y":69.39500000000001}, "smpt1":{"class":"go.Point", "x":-665.32, "y":195}, "smpt2":{"class":"go.Point", "x":-675.32, "y":195}, "empt1":{"class":"go.Point", "x":-665.32, "y":69.39500000000001}, "empt2":{"class":"go.Point", "x":-675.32, "y":74.39500000000001}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall21", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-670.32, "y":69.39500000000001}, "endpoint":{"class":"go.Point", "x":-670.32, "y":10}, "smpt1":{"class":"go.Point", "x":-665.32, "y":69.39500000000001}, "smpt2":{"class":"go.Point", "x":-675.32, "y":64.39500000000001}, "empt1":{"class":"go.Point", "x":-665.32, "y":20}, "empt2":{"class":"go.Point", "x":-675.32, "y":0}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall7", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-910, "y":-320}, "endpoint":{"class":"go.Point", "x":-910, "y":69.39500000000001}, "smpt1":{"class":"go.Point", "x":-915, "y":-325}, "smpt2":{"class":"go.Point", "x":-905, "y":-315}, "empt1":{"class":"go.Point", "x":-915, "y":69.39500000000001}, "empt2":{"class":"go.Point", "x":-905, "y":64.39500000000001}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"wall27", "category":"WallGroup", "caption":"Wall", "type":"Wall", "color":"lightgray", "startpoint":{"class":"go.Point", "x":-910, "y":69.39500000000001}, "endpoint":{"class":"go.Point", "x":-910, "y":200}, "smpt1":{"class":"go.Point", "x":-915, "y":69.39500000000001}, "smpt2":{"class":"go.Point", "x":-905, "y":74.39500000000001}, "empt1":{"class":"go.Point", "x":-915, "y":205}, "empt2":{"class":"go.Point", "x":-905, "y":195}, "thickness":10, "isGroup":true, "notes":"", "isDivider":false},
{"key":"Room7", "category":"RoomNode", "name":"Spare Bedroom", "boundaryWalls":[ [ "wall17",1 ],[ "wall27",2 ],[ "wall3",1 ],[ "wall20",2 ] ], "holes":[], "floorImage":"./images/textures/floor2.jpg", "showLabel":true, "showFlooringOptions":true, "loc":{"class":"go.Point", "x":-905, "y":74.39500000000001}, "area":27700.556399999972, "labelAlignment":{"class":"go.Spot", "x":0.5, "y":0.5, "offsetX":-31.098153547132597, "offsetY":29.370478350070243}},
{"key":"sofaMedium", "color":"#ffffff", "stroke":"#000000", "caption":"Sofa", "type":"Sofa", "geo":"F1 M0 0 L80 0 80 40 0 40 0 0 M10 35 L10 10 M0 0 Q8 0 10 10 M0 40 Q40 15 80 40 M70 10 Q72 0 80 0 M70 10 L70 35", "height":45, "width":90, "notes":"", "texture":"./images/textures/fabric3.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "fabric1.jpg","fabric2.jpg","fabric3.jpg" ], "loc":"-470 58", "angle":180, "group":-47},
{"key":"sofaMedium2", "color":"#ffffff", "stroke":"#000000", "caption":"Sofa", "type":"Sofa", "geo":"F1 M0 0 L80 0 80 40 0 40 0 0 M10 35 L10 10 M0 0 Q8 0 10 10 M0 40 Q40 15 80 40 M70 10 Q72 0 80 0 M70 10 L70 35", "height":45, "width":90, "notes":"", "texture":"./images/textures/fabric3.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "fabric1.jpg","fabric2.jpg","fabric3.jpg" ], "loc":"-360 60", "angle":180, "group":-47},
{"key":"armChair", "color":"purple", "stroke":"#000000", "caption":"Arm Chair", "type":"Arm Chair", "geo":"F1 M0 0 L40 0 40 40 0 40 0 0 M10 30 L10 10 M0 0 Q8 0 10 10 M0 40 Q20 15 40 40 M30 10 Q32 0 40 0 M30 10 L30 30", "width":45, "height":45, "notes":"", "texture":"fabric1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "fabric1.jpg","fabric2.jpg","fabric3.jpg" ], "loc":"-600 110", "angle":90},
{"key":"armChair2", "color":"purple", "stroke":"#000000", "caption":"Arm Chair", "type":"Arm Chair", "geo":"F1 M0 0 L40 0 40 40 0 40 0 0 M10 30 L10 10 M0 0 Q8 0 10 10 M0 40 Q20 15 40 40 M30 10 Q32 0 40 0 M30 10 L30 30", "width":45, "height":45, "notes":"", "texture":"fabric1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "fabric1.jpg","fabric2.jpg","fabric3.jpg" ], "loc":"-220 110", "angle":270},
{"isGroup":true, "key":-47, "caption":"Group", "notes":""},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode", "caption":"Multi Purpose Node", "color":"#000000", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"TV", "width":175, "height":30, "notes":"", "texture":"granite1.jpg", "usesTexture":false, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-400 171.5"},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode2", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Coffee Table", "width":194, "height":36, "notes":"", "texture":"./images/textures/wood2.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-410 110"},
{"key":"diningTable", "color":"#ffffff", "stroke":"#000000", "caption":"Dining Table", "type":"Dining Table", "geo":"F1 M 0 0 L 0 100 200 100 200 0 0 0 M 25 0 L 25 -10 75 -10 75 0 M 125 0 L 125 -10 175 -10 175 0 M 200 25 L 210 25 210 75 200 75 M 125 100 L 125 110 L 175 110 L 175 100 M 25 100 L 25 110 75 110 75 100 M 0 75 -10 75 -10 25 0 25", "width":150, "height":75, "notes":"", "texture":"./images/textures/floor3.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","floor3.jpg","granite1.jpg","porcelain1.jpg","steel2.jpg" ], "loc":"-270 -70"},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode3", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Island", "width":150, "height":50, "notes":"", "texture":"granite1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-310 -180"},
{"key":"stove", "color":"#ffffff", "stroke":"#000000", "caption":"Stove", "type":"Stove", "geo":"F1 M 0 0 L 0 100 100 100 100 0 0 0M 30 15 A 15 15 180 1 0 30.01 15M 30 20 A 10 10 180 1 0 30.01 20M 30 25 A 5 5 180 1 0 30.01 25M 70 15 A 15 15 180 1 0 70.01 15M 70 20 A 10 10 180 1 0 70.01 20M 70 25 A 5 5 180 1 0 70.01 25M 30 55 A 15 15 180 1 0 30.01 55M 30 60 A 10 10 180 1 0 30.01 60M 30 65 A 5 5 180 1 0 30.01 65M 70 55 A 15 15 180 1 0 70.01 55M 70 60 A 10 10 180 1 0 70.01 60M 70 65 A 5 5 180 1 0 70.01 65", "width":50, "height":50, "notes":"", "texture":"plaster1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "steel1.jpg","porcelain1.jpg","copper1.jpg","plaster1.jpg" ], "loc":"-390 -280"},
{"key":"toilet", "color":"#ffffff", "stroke":"#000000", "caption":"Toilet", "type":"Toilet", "geo":"F1 M0 0 L25 0 25 10 0 10 0 0 M20 10 L20 15 5 15 5 10 20 10 M5 15 Q0 15 0 25 Q0 40 12.5 40 Q25 40 25 25 Q25 15 20 15", "width":25, "height":35, "notes":"", "texture":"porcelain1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "copper1.jpg","steel1.jpg","porcelain1.jpg" ], "loc":"-590 -270"},
{"key":"shower", "color":"#ffffff", "stroke":"#000000", "caption":"Shower/Tub", "type":"Shower/Tub", "geo":"F1 M0 0 L40 0 40 60 0 60 0 0 M35 15 L35 55 5 55 5 15 Q5 5 20 5 Q35 5 35 15 M22.5 20 A2.5 2.5 180 1 1 22.5 19.99", "width":45, "height":75, "notes":"", "texture":"copper1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "copper1.jpg","steel1.jpg","porcelain1.jpg" ], "loc":"-520 -260"},
{"key":"doubleSink", "color":"#ffffff", "stroke":"#000000", "caption":"Double Sink", "type":"Double Sink", "geo":"F1 M0 0 L75 0 75 40 0 40 0 0 M5 7.5 L35 7.5 35 35 5 35 5 7.5 M44 7.5 L70 7.5 70 35 40 35 40 9M15 21.25 A5 5 180 1 0 15 21.24 M50 21.25 A 5 5 180 1 0 50 21.24 M40.5 3.75 A3 3 180 1 1 40.5 3.74M40.5 3.75 L50.5 13.75 47.5 16.5 37.5 6.75 M32.5 3.75 A 1 1 180 1 1 32.5 3.74 M 27.5 4.25 L 27.5 3.25 30.5 3.25M 30.5 4.25 L 27.5 4.25 M44.5 3.75 A 1 1 180 1 1 44.5 3.74 M 44.35 3.25 L 47.5 3.25 47.5 4.25 M 44.35 4.25 L 47.5 4.25", "height":27, "width":52, "notes":"", "texture":"steel2.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "copper1.jpg","steel1.jpg","steel2.jpg","porcelain1.jpg" ], "loc":"-520 -180", "angle":90},
{"key":"sink", "color":"#ffffff", "stroke":"#000000", "caption":"Sink", "type":"Sink", "geo":"F1 M0 0 L40 0 40 40 0 40 0 0z M5 7.5 L18.5 7.5 M 21.5 7.5 L35 7.5 35 35 5 35 5 7.5 M 15 21.25 A 5 5 180 1 0 15 21.24M23 3.75 A 3 3 180 1 1 23 3.74 M21.5 6.25 L 21.5 12.5 18.5 12.5 18.5 6.25 M15 3.75 A 1 1 180 1 1 15 3.74M 10 4.25 L 10 3.25 13 3.25 M 13 4.25 L 10 4.25 M27 3.75 A 1 1 180 1 1 27 3.74 M 26.85 3.25 L 30 3.25 30 4.25 M 26.85 4.25 L 30 4.25", "width":27, "height":27, "notes":"", "texture":"steel1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "copper1.jpg","steel1.jpg","steel2.jpg","porcelain1.jpg" ], "loc":"-750 -240", "angle":270},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode4", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Washer", "width":50, "height":50, "notes":"", "texture":"./images/textures/porcelain1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-740 -290"},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode42", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Dryer", "width":50, "height":50, "notes":"", "texture":"./images/textures/porcelain1.jpg", "usesTexture":true, "showTextureOptions":false, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-680 -290"},
{"key":"staircase", "color":"#ffffff", "stroke":"#000000", "caption":"Staircase", "type":"Staircase", "geo":"F1 M0 0 L 0 100 250 100 250 0 0 0 M25 100 L 25 0 M 50 100 L 50 0 M 75 100 L 75 0M 100 100 L 100 0 M 125 100 L 125 0 M 150 100 L 150 0 M 175 100 L 175 0 M 200 100 L 200 0 M 225 100 L 225 0", "width":125, "height":50, "notes":"", "texture":"./images/textures/wood1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","floor1.jpg","wood2.jpg","steel2.jpg","floor2.jpg" ], "loc":"-810 -240", "angle":270},
{"key":"roundTable", "color":"#ffffff", "stroke":"#000000", "caption":"Round Table", "type":"Round Table", "shape":"Ellipse", "width":50, "height":50, "notes":"", "texture":"wood1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","floor3.jpg","granite1.jpg","porcelain1.jpg" ], "loc":"-710 30"},
{"key":"door8", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-818.1830255911889 69.39500000000001", "group":"wall17", "angle":180},
{"key":"door9", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"left", "notes":"", "loc":"-120 146.01328150307734", "group":"wall19", "angle":90},
{"category":"WindowNode", "key":"window3", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-120 79.59151279559444", "group":"wall19", "angle":90},
{"category":"WindowNode", "key":"window4", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-178 -320", "group":"wall11"},
{"category":"WindowNode", "key":"window5", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-358 -320", "group":"wall11"},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode5", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Fridge", "width":50, "height":50, "notes":"", "texture":"./images/textures/steel1.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-450 -280"},
{"category":"MultiPurposeNode", "showLabel": true, "key":"MultiPurposeNode52", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Counter", "width":219, "height":50, "notes":"", "texture":"./images/textures/wood2.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-245.5 -280"},
{"key":"bed", "color":"#ffffff", "stroke":"#000000", "caption":"Bed", "type":"Bed", "geo":"F1 M0 0 L40 0 40 60 0 60 0 0 M 7.5 2.5 L32.5 2.5 32.5 17.5 7.5 17.5 7.5 2.5 M0 20 L40 20 M0 25 L40 25", "width":76.2, "height":101.6, "notes":"", "texture":"./images/textures/fabric2.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "fabric1.jpg","fabric2.jpg","fabric3.jpg" ], "loc":"-720 130"},
{"category":"MultiPurposeNode", "key":"MultiPurposeNode6", "caption":"Multi Purpose Node", "color":"#ffffff", "stroke":"#000000", "name":"Writable Node", "type":"Writable Node", "shape":"Rectangle", "text":"Dresser", "width":60, "height":60, "notes":"", "texture":"./images/textures/wood2.jpg", "usesTexture":true, "showTextureOptions":true, "textures":[ "wood1.jpg","wood2.jpg","granite1.jpg","porcelain1.jpg","steel1.jpg" ], "loc":"-870 110"},
{"category":"WindowNode", "key":"window6", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-910 141.13616240146848", "group":"wall27", "angle":90},
{"category":"WindowNode", "key":"window7", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-815.2749163157326 -320", "group":"wall6"},
{"category":"WindowNode", "key":"window8", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-910 -226", "group":"wall7", "angle":90},
{"category":"WindowNode", "key":"window9", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-910 -72", "group":"wall7", "angle":90},
{"key":"door10", "category":"DoorNode", "caption":"Door", "type":"Door", "length":40, "doorOpeningHeight":10, "swing":"right", "notes":"", "loc":"-120 -90.50422651153826", "group":"wall18", "angle":90},
{"category":"WindowNode", "key":"window10", "color":"white", "caption":"Window", "type":"Window", "shape":"Rectangle", "height":10, "length":60, "notes":"", "loc":"-120 -239", "group":"wall18", "angle":90},
{"category":"M