@archilogic/floor-plan-sdk 5.0.0-rc.1 → 5.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fpe.d.ts CHANGED
@@ -379,7 +379,7 @@ export declare class FloorPlanEngine extends FloorPlanCore {
379
379
  */
380
380
  off<EventType extends FpeEvent, Context>(event: EventType, handler?: FpeEventHandler<EventType>, ctx?: Context): this;
381
381
  emit<EventType extends FpeEvent>(event: EventType, ...args: FpeEventMap[EventType]): this;
382
- handleDrop(evt: any): void;
382
+ handleDrop(evt: DragEvent): void;
383
383
  /**
384
384
  * Change options after the floor plan engine instance has been created
385
385
  * @param args - Startup options
@@ -575,6 +575,13 @@ declare type FpeCoreEventMap = {
575
575
  export declare type FpeDragEvent = {
576
576
  position: Vector2_2;
577
577
  screenPos: Vector2_2;
578
+ sourceEvent: FpeInteractionEvent;
579
+ };
580
+
581
+ export declare type FpeDropEvent = {
582
+ position: Vector2_2;
583
+ screenPos: Vector2_2;
584
+ verticalPos: number;
578
585
  sourceEvent: DragEvent;
579
586
  };
580
587
 
@@ -587,9 +594,7 @@ export declare type FpeEventMap = FpeCoreEventMap & {
587
594
  dblclick: [event: FpePointerEvent];
588
595
  'context-menu': [event: FpePointerEvent];
589
596
  mousemove: [event: FpePointerEvent];
590
- drop: [event: FpeDragEvent & {
591
- verticalPos: number;
592
- }];
597
+ drop: [event: FpeDropEvent];
593
598
  'drag-move': [event: FpeDragEvent];
594
599
  'drag-start': [event: FpeDragEvent];
595
600
  'drag-end': [event: FpeDragEvent];
@@ -629,6 +634,8 @@ declare interface FpeInteraction {
629
634
  preventFocusoutOnAltKeyup: boolean;
630
635
  }
631
636
 
637
+ export declare type FpeInteractionEvent = InteractionEventType[keyof InteractionEventType];
638
+
632
639
  export declare type FpeKeyEvent = {
633
640
  key: string;
634
641
  lowerCaseKey: string;
@@ -669,10 +676,10 @@ declare class FpeLoader extends TinyEmitter {
669
676
  declare type FpeLoader_2 = FloorPlanCore['loader'];
670
677
 
671
678
  export declare type FpePointerEvent = {
672
- sourceEvent: PointerEvent;
673
679
  nodeId?: string;
674
680
  position: Vector2_2;
675
681
  isDoubleClick?: boolean;
682
+ sourceEvent: FpeInteractionEvent;
676
683
  };
677
684
 
678
685
  declare class GeometryBase extends SpaceGraphNodeBase {
@@ -977,6 +984,10 @@ declare interface InfoWindowState extends InfoWindowArgs {
977
984
  floorPlan?: FloorPlanEngine;
978
985
  }
979
986
 
987
+ declare type InteractionEventType = {
988
+ dom: MouseEvent;
989
+ };
990
+
980
991
  declare class Layout2dView extends LayoutViewBase {
981
992
  type: Layout2dViewType;
982
993
  parameters: Layout2dViewParameters;
@@ -2230,6 +2241,7 @@ declare type PolygonCurveType = typeof PolygonCurveTypeValue;
2230
2241
 
2231
2242
  declare const PolygonCurveTypeValue = "curve:polygon";
2232
2243
 
2244
+ /** outer ring counter clockwise, inner rings ( holes ) clockwise */
2233
2245
  declare type PolygonWithHoles = Polygon[];
2234
2246
 
2235
2247
  declare interface PolygonWithHolesCurve extends BaseShape {
package/dist/fpe.js CHANGED
@@ -5,7 +5,7 @@ var __publicField = (obj, key, value) => {
5
5
  return value;
6
6
  };
7
7
  /*!
8
- Archilogic Floor Plan Engine SDK v5.0.0-rc.1 webgl build 240712-133126-1d4aa7
8
+ Archilogic Floor Plan Engine SDK v5.0.0-rc.2 webgl build 240717-162515-eac508
9
9
 
10
10
  Copyright (c) 2024 Archilogic AG. All rights reserved.
11
11
 
@@ -4501,6 +4501,80 @@ function polygonUnion(polygons) {
4501
4501
  );
4502
4502
  return getPolygonsFromClipper(solution_paths);
4503
4503
  }
4504
+ function getPolyTreeAndPolygons(polyNode, index = 0, polyTree = [], polygons = [], currentPolygon = []) {
4505
+ for (let child of polyNode.m_Children) {
4506
+ if (!child.m_polygon.length) {
4507
+ continue;
4508
+ }
4509
+ let isHole = index % 2 !== 0;
4510
+ let polygon = getPolygonsFromClipper([child.m_polygon])[0];
4511
+ let node = { polygon, children: [] };
4512
+ polyTree.push(node);
4513
+ if (!isHole) {
4514
+ currentPolygon = [polygon];
4515
+ polygons.push(currentPolygon);
4516
+ } else {
4517
+ currentPolygon.push(polygon);
4518
+ }
4519
+ getPolyTreeAndPolygons(child, index + 1, node.children, polygons, currentPolygon);
4520
+ }
4521
+ polygons.sort((a2, b2) => {
4522
+ let areaA = polygonArea(a2[0]);
4523
+ let areaB = polygonArea(b2[0]);
4524
+ if (areaA > areaB) {
4525
+ return -1;
4526
+ } else {
4527
+ return 1;
4528
+ }
4529
+ });
4530
+ return { polyTree, polygons };
4531
+ }
4532
+ function polygonWithHolesUnion(polygonLists) {
4533
+ if (!polygonLists.length || !polygonLists[0]) {
4534
+ return { polygons: [], polyTree: [] };
4535
+ }
4536
+ let subj_paths = getClipperPolygons(polygonLists[0]);
4537
+ let clip_paths = polygonLists.slice(1).flatMap(getClipperPolygons);
4538
+ let cpr = new ClipperLib$1.Clipper();
4539
+ cpr.AddPaths(subj_paths, ClipperLib$1.PolyType.ptSubject, true);
4540
+ cpr.AddPaths(clip_paths, ClipperLib$1.PolyType.ptClip, true);
4541
+ let clipperPolyTree = new ClipperLib$1.PolyTree();
4542
+ cpr.Execute(
4543
+ ClipperLib$1.ClipType.ctUnion,
4544
+ clipperPolyTree,
4545
+ ClipperLib$1.PolyFillType.pftNonZero,
4546
+ ClipperLib$1.PolyFillType.pftNonZero
4547
+ );
4548
+ return getPolyTreeAndPolygons(clipperPolyTree);
4549
+ }
4550
+ function polygonOffset(polygons, delta = 0.1, endType, skipCleaning) {
4551
+ const DEFAULT_DELTA = 0.1;
4552
+ if (!polygons.length || !polygons[0]) {
4553
+ return [];
4554
+ }
4555
+ if (endType === void 0) {
4556
+ endType = ClipperLib$1.EndType.etClosedPolygon;
4557
+ }
4558
+ polygons = cleanPolygons(polygons);
4559
+ delta = delta && typeof delta === "number" ? delta : DEFAULT_DELTA;
4560
+ let _polygons = getClipperPolygons(polygons);
4561
+ let co = new ClipperLib$1.ClipperOffset(2);
4562
+ let solution = [];
4563
+ co.AddPaths(_polygons, ClipperLib$1.JoinType.jtMiter, endType);
4564
+ co.Execute(solution, delta);
4565
+ return getPolygonsFromClipper(solution);
4566
+ }
4567
+ function polygonWithHolesOffset(polygonLists, delta = 0.1, endType = ClipperLib$1.EndType.etClosedPolygon) {
4568
+ if (!polygonLists.length || !polygonLists[0]) {
4569
+ return { polygons: [], polyTree: [] };
4570
+ }
4571
+ let paths = polygonLists.flatMap(getClipperPolygons);
4572
+ let co = new ClipperLib$1.ClipperOffset(2);
4573
+ co.AddPaths(paths, ClipperLib$1.JoinType.jtMiter, endType);
4574
+ let clipperPolyTree = new ClipperLib$1.PolyTree();
4575
+ co.Execute(clipperPolyTree, delta);
4576
+ return getPolyTreeAndPolygons(clipperPolyTree);
4577
+ }
4504
4578
  function polygonDifference(subjectPolygons, clipPolygons, subjectPathOpen) {
4505
4579
  if (!subjectPolygons.length || !subjectPolygons[0]) {
4506
4580
  return [];
@@ -4521,6 +4595,24 @@ function polygonDifference(subjectPolygons, clipPolygons, subjectPathOpen) {
4521
4595
  let result = solution_paths;
4522
4596
  return getPolygonsFromClipper(result);
4523
4597
  }
4598
+ function polygonWithHolesDifference(subjectPolygonLists, clipPolygonLists) {
4599
+ if (!subjectPolygonLists.length || !subjectPolygonLists[0]) {
4600
+ return { polygons: [], polyTree: [] };
4601
+ }
4602
+ let subj_paths = subjectPolygonLists.flatMap(getClipperPolygons);
4603
+ let clip_paths = clipPolygonLists.flatMap(getClipperPolygons);
4604
+ let cpr = new ClipperLib$1.Clipper();
4605
+ cpr.AddPaths(subj_paths, ClipperLib$1.PolyType.ptSubject, true);
4606
+ cpr.AddPaths(clip_paths, ClipperLib$1.PolyType.ptClip, true);
4607
+ let clipperPolyTree = new ClipperLib$1.PolyTree();
4608
+ cpr.Execute(
4609
+ ClipperLib$1.ClipType.ctDifference,
4610
+ clipperPolyTree,
4611
+ ClipperLib$1.PolyFillType.pftNonZero,
4612
+ ClipperLib$1.PolyFillType.pftNonZero
4613
+ );
4614
+ return getPolyTreeAndPolygons(clipperPolyTree);
4615
+ }
4524
4616
  function pointInPolygon$1(point, polygon, holes = []) {
4525
4617
  let pt2 = new ClipperLib$1.FPoint(point[0], -point[1]);
4526
4618
  let _polygon = getClipperPolygons([polygon])[0];
@@ -6324,6 +6416,9 @@ function vec2Cross(v1, v2) {
6324
6416
  function vec2Dot(v1, v2) {
6325
6417
  return v1[0] * v2[0] + v1[1] * v2[1];
6326
6418
  }
6419
+ function vec2Equal(v1, v2, epsilon) {
6420
+ return Math.abs(v1[0] - v2[0]) < epsilon && Math.abs(v1[1] - v2[1]) < epsilon;
6421
+ }
6327
6422
  function vec2Length(v2) {
6328
6423
  return Math.sqrt(vec2SqrLength(v2));
6329
6424
  }
@@ -6547,6 +6642,107 @@ function applyPolygonTransform2d(polygon, transform2d) {
6547
6642
  return position;
6548
6643
  });
6549
6644
  }
6645
+ const SEGMENT_TARGET$1 = 48;
6646
+ const MIN_SEGMENTS$1 = 12;
6647
+ function getArcSegmentCount(angleDelta, radius) {
6648
+ let count = Math.ceil(SEGMENT_TARGET$1 / (Math.PI * 2) * angleDelta * radius);
6649
+ const minCount = Math.ceil(MIN_SEGMENTS$1 / (Math.PI * 2) * angleDelta);
6650
+ return Math.max(minCount, count);
6651
+ }
6652
+ function getArcPoint(angle, radius) {
6653
+ let x2 = radius * Math.cos(angle);
6654
+ let y2 = -radius * Math.sin(angle);
6655
+ return [x2, y2];
6656
+ }
6657
+ function getArcPoints(angleStart, angleEnd, radius, open = true) {
6658
+ let points = [];
6659
+ let angleDelta = angleEnd - angleStart;
6660
+ let segmentCount = getArcSegmentCount(Math.abs(angleDelta), radius);
6661
+ let angleStep = angleDelta / segmentCount;
6662
+ for (let i2 = 0; i2 < segmentCount; i2++) {
6663
+ let angle = angleStart + i2 * angleStep;
6664
+ let point = getArcPoint(angle, radius);
6665
+ points.push(point);
6666
+ }
6667
+ if (open) {
6668
+ let point = getArcPoint(angleEnd, radius);
6669
+ points.push(point);
6670
+ }
6671
+ return points;
6672
+ }
6673
+ function getOpenCurvePoints(curve) {
6674
+ let points = [];
6675
+ switch (curve.type) {
6676
+ case "curve:line":
6677
+ points.push(curve.start, curve.end);
6678
+ break;
6679
+ case "curve:arc":
6680
+ let angleStart = Math.PI * curve.startAngle / 180;
6681
+ let angleEnd = Math.PI * curve.endAngle / 180;
6682
+ points = getArcPoints(angleStart, angleEnd, curve.radius);
6683
+ break;
6684
+ case "curve:polyline":
6685
+ points = curve.points;
6686
+ break;
6687
+ }
6688
+ return points;
6689
+ }
6690
+ function resolveProfile(profile) {
6691
+ let points = [];
6692
+ let segmentRanges = [];
6693
+ switch (profile.type) {
6694
+ case "curve:circle":
6695
+ points = getArcPoints(0, 2 * Math.PI, profile.radius, false);
6696
+ segmentRanges.push({ index: 0, count: points.length });
6697
+ break;
6698
+ case "curve:polygon":
6699
+ points = profile.points;
6700
+ for (let i2 = 0; i2 < points.length; i2++) {
6701
+ segmentRanges.push({ index: i2, count: 1 });
6702
+ }
6703
+ break;
6704
+ case "curve:rectangle":
6705
+ let { dimensions } = profile;
6706
+ let sX = dimensions[0];
6707
+ let sY = dimensions[1];
6708
+ points = [
6709
+ [0, 0],
6710
+ [0, sY],
6711
+ [sX, sY],
6712
+ [sX, 0]
6713
+ ];
6714
+ for (let i2 = 0; i2 < points.length; i2++) {
6715
+ segmentRanges.push({ index: i2, count: 1 });
6716
+ }
6717
+ break;
6718
+ case "curve:composite":
6719
+ const epsilon = 1e-7;
6720
+ let firstPoint;
6721
+ let lastPoint;
6722
+ let segments = profile.segments;
6723
+ for (let i2 = 0; i2 < segments.length; i2++) {
6724
+ let segment = segments[i2];
6725
+ let segmentPoints = getOpenCurvePoints(segment);
6726
+ let p1 = segmentPoints[0];
6727
+ let p2 = segmentPoints[segmentPoints.length - 1];
6728
+ let curveContinuous = i2 === 0 ? true : vec2Equal(p1, lastPoint, epsilon);
6729
+ if (!curveContinuous) {
6730
+ logger$1.warn(`Composite curve segments ${i2} and ${i2 + 1} are not continuous.`);
6731
+ }
6732
+ if (i2 === 0) {
6733
+ firstPoint = p1;
6734
+ }
6735
+ lastPoint = p2;
6736
+ segmentRanges.push({ index: points.length, count: segmentPoints.length - 1 });
6737
+ points.push(...segmentPoints.slice(0, segmentPoints.length - 1));
6738
+ }
6739
+ if (segments.length > 0 && !vec2Equal(lastPoint, firstPoint, epsilon)) {
6740
+ logger$1.warn(`Composite curve not closed.`);
6741
+ }
6742
+ break;
6743
+ }
6744
+ return { points, segmentRanges };
6745
+ }
6550
6746
  class LayoutBoundary {
6551
6747
  constructor() {
6552
6748
  this.vertices = [];
@@ -17742,6 +17938,80 @@ function getSpaceObjectAlignedBoundingBox(space) {
17742
17938
  elementIsAxisAligned: false
17743
17939
  };
17744
17940
  }
17941
+ function getOpeningShapes(opening, offset = [0, 0]) {
17942
+ let { dimensions } = opening.parameters;
17943
+ let parent = opening.parent;
17944
+ if (!parent)
17945
+ return [];
17946
+ let width = parent.parameters.width;
17947
+ let polygon = [
17948
+ [-offset[0], -offset[1]],
17949
+ [dimensions[0] + offset[0], -offset[1]],
17950
+ [dimensions[0] + offset[0], width + offset[1]],
17951
+ [-offset[0], width + offset[1]]
17952
+ ];
17953
+ let mTransform = getPositionRotationMatrix(
17954
+ opening.position,
17955
+ opening.rotation,
17956
+ [0, 1, 0]
17957
+ );
17958
+ applyTransformMatrix2d(polygon, mTransform);
17959
+ return [
17960
+ {
17961
+ type: "curve:polygon",
17962
+ points: polygon
17963
+ }
17964
+ ];
17965
+ }
17966
+ function getWallContours(layout) {
17967
+ const offset = 0.01;
17968
+ const walls = layout.elementsByType["element:wall"];
17969
+ const boundaryWalls = layout.elementsByType["element:boundaryWall"];
17970
+ const columns = layout.elementsByType["element:column"];
17971
+ const openings = layout.elementsByType["element:opening"];
17972
+ const openingContours = [];
17973
+ for (const opening of openings) {
17974
+ const shape = getOpeningShapes(opening, [0, offset]);
17975
+ let points = shape[0].points;
17976
+ openingContours.push([points]);
17977
+ }
17978
+ const wallShapes = [];
17979
+ for (const wall of walls) {
17980
+ let { points } = wall.geometryProfile;
17981
+ points = polygonOffset([points], offset)[0];
17982
+ wallShapes.push([points]);
17983
+ }
17984
+ for (const column of columns) {
17985
+ const { profile } = column.parameters;
17986
+ let { points } = resolveProfile(profile);
17987
+ if (profile.type === "curve:rectangle") {
17988
+ const [x2, y2] = profile.dimensions;
17989
+ points = [
17990
+ [-x2 / 2, -y2 / 2],
17991
+ [x2 / 2, -y2 / 2],
17992
+ [x2 / 2, y2 / 2],
17993
+ [-x2 / 2, y2 / 2]
17994
+ ];
17995
+ }
17996
+ points = applyPolygonTransform2d(points, {
17997
+ position: [column.position[0], column.position[2]],
17998
+ rotation: column.rotation
17999
+ });
18000
+ points = polygonOffset([points], offset)[0];
18001
+ wallShapes.push([points]);
18002
+ }
18003
+ for (const boundaryWall of boundaryWalls) {
18004
+ let points = boundaryWall.boundaries[0].geometryProfile;
18005
+ points = polygonOffset([points], offset)[0];
18006
+ wallShapes.push([points]);
18007
+ }
18008
+ let { polygons } = polygonWithHolesUnion(wallShapes);
18009
+ polygons = polygonWithHolesOffset(polygons, -offset).polygons;
18010
+ if (openingContours.length) {
18011
+ polygons = polygonWithHolesDifference(polygons, openingContours).polygons;
18012
+ }
18013
+ return polygons;
18014
+ }
17745
18015
  const _FloorPlanCore = class _FloorPlanCore2 {
17746
18016
  constructor({ options = {} } = {}) {
17747
18017
  this.settings = Ve(defaultConfig);
@@ -17797,6 +18067,9 @@ const _FloorPlanCore = class _FloorPlanCore2 {
17797
18067
  computeLayoutGeometry(this.layout);
17798
18068
  createElementGeometries(this.layout);
17799
18069
  }
18070
+ if (this.settings.theme.wallContours) {
18071
+ this.computed.wallContours = getWallContours(this.layout);
18072
+ }
17800
18073
  setTimeout(() => {
17801
18074
  this.loader.emit("spaces-loaded");
17802
18075
  }, 0);
@@ -17860,7 +18133,7 @@ const _FloorPlanCore = class _FloorPlanCore2 {
17860
18133
  * Change options after the floor plan engine instance has been created
17861
18134
  */
17862
18135
  set(args = {}) {
17863
- var _a, _b, _c, _d, _e2;
18136
+ var _a, _b, _c, _d, _e2, _f, _g, _h, _i;
17864
18137
  const assetsAreHidden = (_a = this.settings.hideElements) == null ? void 0 : _a.includes("element:asset");
17865
18138
  let newSettings = Ve(args);
17866
18139
  if (newSettings.theme)
@@ -17892,6 +18165,11 @@ const _FloorPlanCore = class _FloorPlanCore2 {
17892
18165
  if (this.layout) {
17893
18166
  if (assetsAreHidden && showAssets)
17894
18167
  loadAllAssetResources(this);
18168
+ if (((_f = newSettings.theme) == null ? void 0 : _f.wallContours) && !((_g = this.computed.wallContours) == null ? void 0 : _g.length)) {
18169
+ this.computed.wallContours = getWallContours(this.layout);
18170
+ } else if (!((_h = newSettings.theme) == null ? void 0 : _h.wallContours) && ((_i = this.computed.wallContours) == null ? void 0 : _i.length)) {
18171
+ this.computed.wallContours = [];
18172
+ }
17895
18173
  }
17896
18174
  this.emit("update-settings", this.settings);
17897
18175
  }
@@ -17931,7 +18209,7 @@ const _FloorPlanCore = class _FloorPlanCore2 {
17931
18209
  delete this.utils;
17932
18210
  }
17933
18211
  };
17934
- _FloorPlanCore.version = "5.0.0-rc.1";
18212
+ _FloorPlanCore.version = "5.0.0-rc.2";
17935
18213
  let FloorPlanCore = _FloorPlanCore;
17936
18214
  function getDoorAnnotations(node) {
17937
18215
  let {
@@ -18120,31 +18398,6 @@ function getEdgeShapes(edge, style = {}) {
18120
18398
  }
18121
18399
  return shapes;
18122
18400
  }
18123
- function getOpeningShapes(opening) {
18124
- let { dimensions } = opening.parameters;
18125
- let parent = opening.parent;
18126
- if (!parent)
18127
- return [];
18128
- let width = parent.parameters.width;
18129
- let polygon = [
18130
- [0, 0],
18131
- [dimensions[0], 0],
18132
- [dimensions[0], width],
18133
- [0, width]
18134
- ];
18135
- let mTransform = getPositionRotationMatrix(
18136
- opening.position,
18137
- opening.rotation,
18138
- [0, 1, 0]
18139
- );
18140
- applyTransformMatrix2d(polygon, mTransform);
18141
- return [
18142
- {
18143
- type: "curve:polygon",
18144
- points: polygon
18145
- }
18146
- ];
18147
- }
18148
18401
  var r$2 = { grad: 0.9, turn: 360, rad: 360 / (2 * Math.PI) }, t$2 = function(r2) {
18149
18402
  return "string" == typeof r2 ? r2.length > 0 : "number" == typeof r2;
18150
18403
  }, n$2 = function(r2, t2, n2) {
@@ -41203,10 +41456,12 @@ function drawNode(node, floorPlan, { ctx, style, container, preview }) {
41203
41456
  } else {
41204
41457
  nodeContainer = new Container();
41205
41458
  }
41459
+ const wallContourTypes = ["element:wall", "element:boundaryWall", "element:column", "spatialGraph:edge"];
41206
41460
  const skipGraphic = settings2.hideElements.includes(node.type) || // conditionally draw edges and floor plan images
41207
41461
  node.type === "spatialGraph:edge" && !settings2.showSpaceDividers || node.type === "spatialGraph:edge" && ((_a = node.element) == null ? void 0 : _a.type) === "element:spaceDivider" || node.type === "element:spaceDivider" && !settings2.showSpaceDividers || node.type === "annotation:floorPlanImage" && !settings2.showFloorPlan || // don't draw 'element:floor' and 'element:ceiling' because we already draw the space
41208
41462
  "space" in node || // skip detached opening elements
41209
- (node.type === "element:window" || node.type === "element:door") && !node.parent;
41463
+ (node.type === "element:window" || node.type === "element:door") && !node.parent || // skip structural elements if merged wall contours are drawn
41464
+ floorPlan.computed.wallContours.length && wallContourTypes.includes(node.type);
41210
41465
  const zValue = getIndex(node.type);
41211
41466
  nodeContainer.zIndex = zValue || 0;
41212
41467
  if (!skipGraphic) {
@@ -41630,6 +41885,35 @@ const focusHandler = (floorPlan) => {
41630
41885
  false
41631
41886
  );
41632
41887
  };
41888
+ function drawWallContours(floorPlan, options) {
41889
+ const { ctx, style } = options;
41890
+ const { wallContours } = floorPlan.computed;
41891
+ const id = "wallContours";
41892
+ const shapes = wallContours.map((polygons) => ({
41893
+ type: "curve:polygonWithHoles",
41894
+ polygons
41895
+ }));
41896
+ let container = ctx.getChildByName(id);
41897
+ if (container) {
41898
+ clearContainer(container);
41899
+ } else {
41900
+ container = new Container();
41901
+ container.name = id;
41902
+ }
41903
+ const zValue = getIndex("element:wall");
41904
+ container.zIndex = zValue || 0;
41905
+ const nodeStyle = getNodeStyle({
41906
+ style,
41907
+ settings: floorPlan.settings,
41908
+ elementType: "element:wall"
41909
+ });
41910
+ const gfx = new Graphics();
41911
+ for (const shape of shapes) {
41912
+ drawShape({ shape, gfx, style: nodeStyle });
41913
+ }
41914
+ container.addChild(gfx);
41915
+ ctx.addChild(container);
41916
+ }
41633
41917
  function drawLayout({ floorPlan, update = false }) {
41634
41918
  const { layout, view, settings: settings2 } = floorPlan;
41635
41919
  const { _renderer: renderer, _viewport: viewport } = view;
@@ -41655,6 +41939,9 @@ function drawLayout({ floorPlan, update = false }) {
41655
41939
  for (let edge of layout.spatialGraph.edges) {
41656
41940
  drawNode(edge, floorPlan, drawNodeOptions);
41657
41941
  }
41942
+ if (floorPlan.computed.wallContours.length) {
41943
+ drawWallContours(floorPlan, drawNodeOptions);
41944
+ }
41658
41945
  drawRoomStamps(floorPlan, true);
41659
41946
  view.emit("scene-rendered", { update });
41660
41947
  view.viewportNeedsUpdate = true;