@2112-lab/central-plant 0.1.54 → 0.1.55

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.
@@ -19070,6 +19070,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19070
19070
  component.updateMatrix();
19071
19071
  component.updateMatrixWorld(true);
19072
19072
 
19073
+ // Update component position in currentSceneData
19074
+ this.updateComponentPositionInSceneData(component);
19075
+
19073
19076
  // Check if component is underground and fix if needed (based on settings)
19074
19077
  var checkUnderground = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.settingsManager) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.getSetting('scene', 'checkUnderground');
19075
19078
  if (checkUnderground) {
@@ -19214,7 +19217,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19214
19217
  }, {
19215
19218
  key: "validateTranslateSegmentCollisions",
19216
19219
  value: function validateTranslateSegmentCollisions(segment, axis, value) {
19217
- var _this$sceneViewer2;
19220
+ var _segment$userData4, _segment$userData5;
19218
19221
  // Store original position for reverting
19219
19222
  var originalPosition = segment.position[axis];
19220
19223
 
@@ -19223,6 +19226,14 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19223
19226
  segment.updateMatrix();
19224
19227
  segment.updateMatrixWorld(true);
19225
19228
 
19229
+ // IMPORTANT: Update stored endpoints if they exist, since position changed
19230
+ // This ensures checkSegmentIntersection uses the correct translated endpoints
19231
+ if ((_segment$userData4 = segment.userData) !== null && _segment$userData4 !== void 0 && (_segment$userData4 = _segment$userData4.endpoints) !== null && _segment$userData4 !== void 0 && _segment$userData4.startOffset && (_segment$userData5 = segment.userData) !== null && _segment$userData5 !== void 0 && (_segment$userData5 = _segment$userData5.endpoints) !== null && _segment$userData5 !== void 0 && _segment$userData5.endOffset) {
19232
+ // Endpoints are stored as offsets from center, so they don't need updating
19233
+ // The getSegmentEndpoints method will automatically use the new position
19234
+ console.log("\uD83D\uDD0D Checking collisions with translated position: ".concat(axis, "=").concat(segment.position[axis].toFixed(3)));
19235
+ }
19236
+
19226
19237
  // Check for collision with component connectors along the segment's path
19227
19238
  var connectorCollision = this.checkSegmentPathConnectorCollision(segment);
19228
19239
  if (connectorCollision) {
@@ -19252,26 +19263,21 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19252
19263
  return false;
19253
19264
  }
19254
19265
 
19255
- // Check if translationalOverrideForAutomaticSegments is enabled
19256
- var translationalOverride = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.settingsManager) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.getSetting('scene', 'translationalOverrideForAutomaticSegments');
19257
-
19258
- // If override is disabled (false), check for intersections with computed segments
19259
- if (translationalOverride === false) {
19260
- console.log('🔍 Checking for intersections with computed segments (translationalOverrideForAutomaticSegments is disabled)');
19266
+ // ALWAYS check for segment-to-segment intersections
19267
+ console.log('🔍 Checking for intersections with other segments...');
19261
19268
 
19262
- // Check if the translated segment intersects with any computed segments
19263
- var hasIntersection = this.checkSegmentIntersection(segment);
19264
- console.log("\uD83D\uDD04 translateSegment() hasIntersection:", hasIntersection);
19265
- if (hasIntersection) {
19266
- // Revert the translation
19267
- segment.position[axis] = originalPosition;
19268
- segment.updateMatrix();
19269
- segment.updateMatrixWorld(true);
19270
- console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would intersect with computed segment(s)");
19271
- return false;
19272
- }
19273
- console.log('✅ No intersections detected, proceeding with translation');
19269
+ // Check if the translated segment intersects with any other segments
19270
+ var hasIntersection = this.checkSegmentIntersection(segment);
19271
+ console.log("\uD83D\uDD04 translateSegment() hasIntersection:", hasIntersection);
19272
+ if (hasIntersection) {
19273
+ // Revert the translation
19274
+ segment.position[axis] = originalPosition;
19275
+ segment.updateMatrix();
19276
+ segment.updateMatrixWorld(true);
19277
+ console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would intersect with other segment(s)");
19278
+ return false;
19274
19279
  }
19280
+ console.log('✅ No intersections detected, proceeding with translation');
19275
19281
 
19276
19282
  // Revert the temporary translation
19277
19283
  segment.position[axis] = originalPosition;
@@ -19733,9 +19739,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19733
19739
  }, {
19734
19740
  key: "findConnectorsAtPositions",
19735
19741
  value: function findConnectorsAtPositions(positions) {
19736
- var _this$sceneViewer3;
19742
+ var _this$sceneViewer2;
19737
19743
  var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
19738
- if (!((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.scene)) {
19744
+ if (!((_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.scene)) {
19739
19745
  return [];
19740
19746
  }
19741
19747
  var foundConnectors = [];
@@ -19779,10 +19785,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19779
19785
  }, {
19780
19786
  key: "updateSegmentConnectorPositions",
19781
19787
  value: function updateSegmentConnectorPositions(segment) {
19782
- var _this$sceneViewer4,
19788
+ var _this$sceneViewer3,
19783
19789
  _this = this;
19784
19790
  console.log("updateSegmentConnectorPositions started:", segment);
19785
- if (!segment || !((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && (_this$sceneViewer4 = _this$sceneViewer4.currentSceneData) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.scene)) {
19791
+ if (!segment || !((_this$sceneViewer3 = this.sceneViewer) !== null && _this$sceneViewer3 !== void 0 && (_this$sceneViewer3 = _this$sceneViewer3.currentSceneData) !== null && _this$sceneViewer3 !== void 0 && _this$sceneViewer3.scene)) {
19786
19792
  console.warn('⚠️ updateSegmentConnectorPositions(): Missing segment or scene data');
19787
19793
  return;
19788
19794
  }
@@ -19833,24 +19839,25 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19833
19839
  }
19834
19840
 
19835
19841
  /**
19836
- * Check if a segment intersects with any computed segments in the scene
19837
- * Uses segment-to-segment distance calculation, excluding endpoint connections
19842
+ * Check if a segment intersects with any segments in the scene
19843
+ * For grid-based segments (0.5 grid), checks if segments cross or overlap
19844
+ * Uses only endpoint comparisons, no radius checks
19845
+ * Allows T-junctions (endpoint touching line) if segments are connected (same pathFrom/pathTo)
19838
19846
  * @param {THREE.Object3D} segment - The segment to check for intersections
19839
- * @returns {boolean} True if segment intersects with any computed segment (not just touching at ends)
19847
+ * @returns {boolean} True if segment intersects with any segment
19840
19848
  * @private
19841
19849
  */
19842
19850
  }, {
19843
19851
  key: "checkSegmentIntersection",
19844
19852
  value: function checkSegmentIntersection(segment) {
19845
- var _this$sceneViewer5,
19853
+ var _this$sceneViewer4,
19846
19854
  _this2 = this;
19847
- if (!((_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.scene)) {
19855
+ if (!((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.scene)) {
19848
19856
  return false;
19849
19857
  }
19850
19858
 
19851
- // Get endpoints of the segment being checked
19852
- var segmentEndpoints = this.calculateSegmentEndpoints(segment);
19853
- var segmentRadius = segment.geometry.parameters.radiusTop || 0.05;
19859
+ // Get endpoints of the segment being checked (use stored endpoints if available)
19860
+ var segmentEndpoints = this.getSegmentEndpoints(segment);
19854
19861
 
19855
19862
  // Track if any intersection was found
19856
19863
  var hasIntersection = false;
@@ -19863,41 +19870,74 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19863
19870
  return;
19864
19871
  }
19865
19872
 
19866
- // Only check computed segments (isDeclared === false or undefined)
19867
- if (((_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.objectType) === 'segment' && ((_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.isDeclared) !== true) {
19868
- // Get endpoints of the computed segment
19869
- var computedEndpoints = _this2.calculateSegmentEndpoints(child);
19870
- var computedRadius = child.geometry.parameters.radiusTop || 0.05;
19873
+ // Only check computed segments in the scene
19874
+ if (((_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.objectType) === 'segment' && (_child$userData0 = child.userData) !== null && _child$userData0 !== void 0 && _child$userData0.isDeclared) {
19875
+ var _segment$userData6, _child$userData1, _segment$userData7, _child$userData10;
19876
+ // Check if segments are part of the same connection path
19877
+ var sameConnection = ((_segment$userData6 = segment.userData) === null || _segment$userData6 === void 0 ? void 0 : _segment$userData6.pathFrom) === ((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.pathFrom) && ((_segment$userData7 = segment.userData) === null || _segment$userData7 === void 0 ? void 0 : _segment$userData7.pathTo) === ((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.pathTo);
19871
19878
 
19872
- // Combined radius threshold - segments intersect if closer than this
19873
- var combinedRadius = segmentRadius + computedRadius;
19879
+ // Get endpoints of the other segment (use stored endpoints if available)
19880
+ var otherEndpoints = _this2.getSegmentEndpoints(child);
19874
19881
 
19875
- // First, check if segments are connected at endpoints
19876
- // This is a cheaper check than full segment-to-segment distance
19877
- var endpointTolerance = 0.55; // Generous tolerance for endpoint connections
19882
+ // Grid tolerance for endpoint comparisons (0.5 grid system)
19883
+ var endpointTolerance = 0.01; // Very tight tolerance for grid-aligned segments
19878
19884
 
19879
- var d1 = segmentEndpoints.start.distanceTo(computedEndpoints.start);
19880
- var d2 = segmentEndpoints.start.distanceTo(computedEndpoints.end);
19881
- var d3 = segmentEndpoints.end.distanceTo(computedEndpoints.start);
19882
- var d4 = segmentEndpoints.end.distanceTo(computedEndpoints.end);
19885
+ var d1 = segmentEndpoints.start.distanceTo(otherEndpoints.start);
19886
+ var d2 = segmentEndpoints.start.distanceTo(otherEndpoints.end);
19887
+ var d3 = segmentEndpoints.end.distanceTo(otherEndpoints.start);
19888
+ var d4 = segmentEndpoints.end.distanceTo(otherEndpoints.end);
19883
19889
 
19884
- // Check if any endpoint of segment A is near any endpoint of segment B (they're connected)
19885
- var isConnectedAtEnds = d1 < endpointTolerance || d2 < endpointTolerance || d3 < endpointTolerance || d4 < endpointTolerance;
19890
+ // Count how many endpoints are shared/touching
19891
+ var sharedEndpointCount = 0;
19892
+ if (d1 < endpointTolerance) sharedEndpointCount++;
19893
+ if (d2 < endpointTolerance) sharedEndpointCount++;
19894
+ if (d3 < endpointTolerance) sharedEndpointCount++;
19895
+ if (d4 < endpointTolerance) sharedEndpointCount++;
19886
19896
 
19887
- // If connected at ends, skip this segment (no collision)
19888
- if (isConnectedAtEnds) {
19889
- console.log("\u2705 Segments connected at endpoints - skipping intersection check (min endpoint distance: ".concat(Math.min(d1, d2, d3, d4).toFixed(3), ")"));
19897
+ // If segments share 2 or more endpoints, they're overlapping on the same line
19898
+ if (sharedEndpointCount >= 2) {
19899
+ console.log("\uD83D\uDD34 Overlapping segments detected - segments share ".concat(sharedEndpointCount, " endpoints"));
19900
+ console.log(" Segment 1: [".concat(segmentEndpoints.start.x.toFixed(2), ", ").concat(segmentEndpoints.start.y.toFixed(2), ", ").concat(segmentEndpoints.start.z.toFixed(2), "] to [").concat(segmentEndpoints.end.x.toFixed(2), ", ").concat(segmentEndpoints.end.y.toFixed(2), ", ").concat(segmentEndpoints.end.z.toFixed(2), "]"));
19901
+ console.log(" Segment 2: [".concat(otherEndpoints.start.x.toFixed(2), ", ").concat(otherEndpoints.start.y.toFixed(2), ", ").concat(otherEndpoints.start.z.toFixed(2), "] to [").concat(otherEndpoints.end.x.toFixed(2), ", ").concat(otherEndpoints.end.y.toFixed(2), ", ").concat(otherEndpoints.end.z.toFixed(2), "]"));
19902
+ hasIntersection = true;
19890
19903
  return;
19891
19904
  }
19892
19905
 
19893
- // Calculate the minimum distance between the two line segments
19894
- var distance = _this2.calculateSegmentToSegmentDistance(segmentEndpoints.start, segmentEndpoints.end, computedEndpoints.start, computedEndpoints.end);
19906
+ // If exactly 1 endpoint is shared, check if they overlap along the same line
19907
+ if (sharedEndpointCount === 1) {
19908
+ // Check if segments are collinear (on the same line)
19909
+ var _distance = _this2.calculateSegmentToSegmentDistance(segmentEndpoints.start, segmentEndpoints.end, otherEndpoints.start, otherEndpoints.end);
19910
+ if (_distance < endpointTolerance) {
19911
+ // Segments are on the same line and share one endpoint
19912
+ // This means they overlap along part of their length
19913
+ console.log("\uD83D\uDD34 Overlapping collinear segments detected - share 1 endpoint and are on same line");
19914
+ console.log(" Segment 1: [".concat(segmentEndpoints.start.x.toFixed(2), ", ").concat(segmentEndpoints.start.y.toFixed(2), ", ").concat(segmentEndpoints.start.z.toFixed(2), "] to [").concat(segmentEndpoints.end.x.toFixed(2), ", ").concat(segmentEndpoints.end.y.toFixed(2), ", ").concat(segmentEndpoints.end.z.toFixed(2), "]"));
19915
+ console.log(" Segment 2: [".concat(otherEndpoints.start.x.toFixed(2), ", ").concat(otherEndpoints.start.y.toFixed(2), ", ").concat(otherEndpoints.start.z.toFixed(2), "] to [").concat(otherEndpoints.end.x.toFixed(2), ", ").concat(otherEndpoints.end.y.toFixed(2), ", ").concat(otherEndpoints.end.z.toFixed(2), "]"));
19916
+ console.log(" Distance: ".concat(_distance.toFixed(6)));
19917
+ hasIntersection = true;
19918
+ } else {
19919
+ // Valid end-to-end connection at different angles
19920
+ console.log("\u2705 Segments connected at one endpoint with different directions - valid connection");
19921
+ }
19922
+ return;
19923
+ }
19924
+
19925
+ // No shared endpoints - check if segments cross or overlap
19926
+ var distance = _this2.calculateSegmentToSegmentDistance(segmentEndpoints.start, segmentEndpoints.end, otherEndpoints.start, otherEndpoints.end);
19895
19927
 
19896
- // Only flag as intersection if segments are closer than combined radius
19897
- if (distance < combinedRadius) {
19898
- console.log("\uD83D\uDD34 Intersection detected with computed segment: ".concat(child.uuid || child.name));
19899
- console.log(" Distance: ".concat(distance.toFixed(3), ", Combined radius: ").concat(combinedRadius.toFixed(3)));
19900
- console.log(" Endpoint distances: [".concat(d1.toFixed(3), ", ").concat(d2.toFixed(3), ", ").concat(d3.toFixed(3), ", ").concat(d4.toFixed(3), "]"));
19928
+ // If distance is near zero, segments cross or overlap
19929
+ if (distance < endpointTolerance) {
19930
+ // Special case: T-junction (one segment's endpoint touches the other's line)
19931
+ // This is allowed if the segments are part of the same connection path
19932
+ if (sameConnection) {
19933
+ var _segment$userData8, _segment$userData9;
19934
+ console.log("\u2705 T-junction detected but allowed - segments are part of the same connection (".concat((_segment$userData8 = segment.userData) === null || _segment$userData8 === void 0 ? void 0 : _segment$userData8.pathFrom, " \u2192 ").concat((_segment$userData9 = segment.userData) === null || _segment$userData9 === void 0 ? void 0 : _segment$userData9.pathTo, ")"));
19935
+ return;
19936
+ }
19937
+ console.log("\uD83D\uDD34 Intersection detected - segments cross or overlap");
19938
+ console.log(" Segment 1: [".concat(segmentEndpoints.start.x.toFixed(2), ", ").concat(segmentEndpoints.start.y.toFixed(2), ", ").concat(segmentEndpoints.start.z.toFixed(2), "] to [").concat(segmentEndpoints.end.x.toFixed(2), ", ").concat(segmentEndpoints.end.y.toFixed(2), ", ").concat(segmentEndpoints.end.z.toFixed(2), "]"));
19939
+ console.log(" Segment 2: [".concat(otherEndpoints.start.x.toFixed(2), ", ").concat(otherEndpoints.start.y.toFixed(2), ", ").concat(otherEndpoints.start.z.toFixed(2), "] to [").concat(otherEndpoints.end.x.toFixed(2), ", ").concat(otherEndpoints.end.y.toFixed(2), ", ").concat(otherEndpoints.end.z.toFixed(2), "]"));
19940
+ console.log(" Distance: ".concat(distance.toFixed(6)));
19901
19941
  hasIntersection = true;
19902
19942
  }
19903
19943
  }
@@ -19905,6 +19945,32 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19905
19945
  return hasIntersection;
19906
19946
  }
19907
19947
 
19948
+ /**
19949
+ * Get segment endpoints, using stored userData.endpoints if available, otherwise calculate
19950
+ * @param {THREE.Object3D} segment - The segment object
19951
+ * @returns {Object} Object with start and end Vector3 points
19952
+ * @private
19953
+ */
19954
+ }, {
19955
+ key: "getSegmentEndpoints",
19956
+ value: function getSegmentEndpoints(segment) {
19957
+ var _segment$userData0, _segment$userData1;
19958
+ // Check if segment has stored endpoints in userData
19959
+ if ((_segment$userData0 = segment.userData) !== null && _segment$userData0 !== void 0 && (_segment$userData0 = _segment$userData0.endpoints) !== null && _segment$userData0 !== void 0 && _segment$userData0.startOffset && (_segment$userData1 = segment.userData) !== null && _segment$userData1 !== void 0 && (_segment$userData1 = _segment$userData1.endpoints) !== null && _segment$userData1 !== void 0 && _segment$userData1.endOffset) {
19960
+ // Reconstruct world positions from stored offsets
19961
+ var centerPoint = segment.position;
19962
+ var startOffset = segment.userData.endpoints.startOffset;
19963
+ var endOffset = segment.userData.endpoints.endOffset;
19964
+ return {
19965
+ start: new THREE__namespace.Vector3(centerPoint.x + startOffset.x, centerPoint.y + startOffset.y, centerPoint.z + startOffset.z),
19966
+ end: new THREE__namespace.Vector3(centerPoint.x + endOffset.x, centerPoint.y + endOffset.y, centerPoint.z + endOffset.z)
19967
+ };
19968
+ }
19969
+
19970
+ // Fallback to calculating endpoints from geometry
19971
+ return this.calculateSegmentEndpoints(segment);
19972
+ }
19973
+
19908
19974
  /**
19909
19975
  * Check if any point along a segment's path would collide with component connector within 0.5 radius
19910
19976
  * @param {THREE.Object3D} segment - The segment to check
@@ -19914,8 +19980,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19914
19980
  }, {
19915
19981
  key: "checkSegmentPathConnectorCollision",
19916
19982
  value: function checkSegmentPathConnectorCollision(segment) {
19917
- var _this$sceneViewer6;
19918
- if (!((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.scene) || !segment) {
19983
+ var _this$sceneViewer5;
19984
+ if (!((_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.scene) || !segment) {
19919
19985
  return null;
19920
19986
  }
19921
19987
  var collisionRadius = 0.5; // Radius around connector that triggers collision
@@ -19929,11 +19995,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19929
19995
 
19930
19996
  // Traverse scene to find all component connectors
19931
19997
  this.sceneViewer.scene.traverse(function (child) {
19932
- var _child$userData1;
19998
+ var _child$userData11;
19933
19999
  if (collision) return; // Stop if collision already found
19934
20000
 
19935
20001
  // Check if this is a component connector (not a segment-connector)
19936
- if (((_child$userData1 = child.userData) === null || _child$userData1 === void 0 ? void 0 : _child$userData1.objectType) === 'connector') {
20002
+ if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'connector') {
19937
20003
  // Get world position of connector
19938
20004
  var connectorWorldPos = new THREE__namespace.Vector3();
19939
20005
  child.getWorldPosition(connectorWorldPos);
@@ -19954,8 +20020,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19954
20020
 
19955
20021
  // Handle degenerate case (zero-length segment)
19956
20022
  if (segmentLengthSquared < 1e-10) {
19957
- var _distance = startPoint.distanceTo(connectorWorldPos);
19958
- if (_distance <= collisionRadius) {
20023
+ var _distance2 = startPoint.distanceTo(connectorWorldPos);
20024
+ if (_distance2 <= collisionRadius) {
19959
20025
  // Find the parent component
19960
20026
  var component = child.parent;
19961
20027
  while (component && !((_component$userData2 = component.userData) !== null && _component$userData2 !== void 0 && _component$userData2.libraryId)) {
@@ -19975,7 +20041,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
19975
20041
  y: startPoint.y,
19976
20042
  z: startPoint.z
19977
20043
  },
19978
- distance: _distance
20044
+ distance: _distance2
19979
20045
  };
19980
20046
  }
19981
20047
  return;
@@ -20029,8 +20095,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20029
20095
  }, {
20030
20096
  key: "checkComponentConnectorCollision",
20031
20097
  value: function checkComponentConnectorCollision(newPosition) {
20032
- var _this$sceneViewer7;
20033
- if (!((_this$sceneViewer7 = this.sceneViewer) !== null && _this$sceneViewer7 !== void 0 && _this$sceneViewer7.scene)) {
20098
+ var _this$sceneViewer6;
20099
+ if (!((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.scene)) {
20034
20100
  return null;
20035
20101
  }
20036
20102
  var tolerance = 0.01; // Small tolerance for floating-point comparison
@@ -20038,9 +20104,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20038
20104
 
20039
20105
  // Traverse scene to find all component connectors
20040
20106
  this.sceneViewer.scene.traverse(function (child) {
20041
- var _child$userData10;
20107
+ var _child$userData12;
20042
20108
  // Check if this is a component connector (not a segment-connector)
20043
- if (((_child$userData10 = child.userData) === null || _child$userData10 === void 0 ? void 0 : _child$userData10.objectType) === 'connector') {
20109
+ if (((_child$userData12 = child.userData) === null || _child$userData12 === void 0 ? void 0 : _child$userData12.objectType) === 'connector') {
20044
20110
  // Get world position of connector
20045
20111
  var connectorWorldPos = new THREE__namespace.Vector3();
20046
20112
  child.getWorldPosition(connectorWorldPos);
@@ -20086,8 +20152,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20086
20152
  }, {
20087
20153
  key: "checkSegmentComponentBoundingBoxCollision",
20088
20154
  value: function checkSegmentComponentBoundingBoxCollision(segment) {
20089
- var _this$sceneViewer8;
20090
- if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !segment) {
20155
+ var _this$sceneViewer7;
20156
+ if (!((_this$sceneViewer7 = this.sceneViewer) !== null && _this$sceneViewer7 !== void 0 && _this$sceneViewer7.scene) || !segment) {
20091
20157
  return null;
20092
20158
  }
20093
20159
 
@@ -20097,11 +20163,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20097
20163
 
20098
20164
  // Traverse scene to find all components
20099
20165
  this.sceneViewer.scene.traverse(function (child) {
20100
- var _child$userData11, _child$userData12;
20166
+ var _child$userData13, _child$userData14;
20101
20167
  if (collision) return; // Stop if collision already found
20102
20168
 
20103
20169
  // Check if this is a component (equipment)
20104
- if (((_child$userData11 = child.userData) === null || _child$userData11 === void 0 ? void 0 : _child$userData11.objectType) === 'component' && (_child$userData12 = child.userData) !== null && _child$userData12 !== void 0 && _child$userData12.libraryId) {
20170
+ if (((_child$userData13 = child.userData) === null || _child$userData13 === void 0 ? void 0 : _child$userData13.objectType) === 'component' && (_child$userData14 = child.userData) !== null && _child$userData14 !== void 0 && _child$userData14.libraryId) {
20105
20171
  // Create bounding box for the component
20106
20172
  var componentBBox = new THREE__namespace.Box3().setFromObject(child);
20107
20173
 
@@ -20228,10 +20294,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20228
20294
  }, {
20229
20295
  key: "snapSegmentConnectorsToNearbyEndpoints",
20230
20296
  value: function snapSegmentConnectorsToNearbyEndpoints(movedSegment) {
20231
- var _this$sceneViewer9,
20232
- _this$sceneViewer0,
20297
+ var _this$sceneViewer8,
20298
+ _this$sceneViewer9,
20233
20299
  _this3 = this;
20234
- if (!movedSegment || !((_this$sceneViewer9 = this.sceneViewer) !== null && _this$sceneViewer9 !== void 0 && _this$sceneViewer9.scene)) {
20300
+ if (!movedSegment || !((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene)) {
20235
20301
  return [];
20236
20302
  }
20237
20303
  console.log('🔗 Finding adjacent segments connected to moved segment...');
@@ -20239,8 +20305,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20239
20305
  // Get the moved segment's connectors
20240
20306
  var movedConnectors = [];
20241
20307
  movedSegment.traverse(function (child) {
20242
- var _child$userData13;
20243
- if (((_child$userData13 = child.userData) === null || _child$userData13 === void 0 ? void 0 : _child$userData13.objectType) === 'segment-connector') {
20308
+ var _child$userData15;
20309
+ if (((_child$userData15 = child.userData) === null || _child$userData15 === void 0 ? void 0 : _child$userData15.objectType) === 'segment-connector') {
20244
20310
  movedConnectors.push(child);
20245
20311
  }
20246
20312
  });
@@ -20253,7 +20319,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20253
20319
  var newEndpoints = this.calculateSegmentEndpoints(movedSegment);
20254
20320
 
20255
20321
  // Check scene data for connections involving the moved segment's connectors
20256
- var connections = ((_this$sceneViewer0 = this.sceneViewer) === null || _this$sceneViewer0 === void 0 || (_this$sceneViewer0 = _this$sceneViewer0.currentSceneData) === null || _this$sceneViewer0 === void 0 ? void 0 : _this$sceneViewer0.connections) || [];
20322
+ var connections = ((_this$sceneViewer9 = this.sceneViewer) === null || _this$sceneViewer9 === void 0 || (_this$sceneViewer9 = _this$sceneViewer9.currentSceneData) === null || _this$sceneViewer9 === void 0 ? void 0 : _this$sceneViewer9.connections) || [];
20257
20323
  var movedConnectorIds = movedConnectors.map(function (c) {
20258
20324
  return c.uuid;
20259
20325
  });
@@ -20310,8 +20376,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20310
20376
  // Get all connectors of the adjacent segment
20311
20377
  var adjacentConnectors = [];
20312
20378
  adjacentSegment.traverse(function (child) {
20313
- var _child$userData14;
20314
- if (((_child$userData14 = child.userData) === null || _child$userData14 === void 0 ? void 0 : _child$userData14.objectType) === 'segment-connector') {
20379
+ var _child$userData16;
20380
+ if (((_child$userData16 = child.userData) === null || _child$userData16 === void 0 ? void 0 : _child$userData16.objectType) === 'segment-connector') {
20315
20381
  adjacentConnectors.push(child);
20316
20382
  }
20317
20383
  });
@@ -20399,6 +20465,68 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20399
20465
  this.updateConnectorPositionInSceneData(connector, worldPosition, parentSegment);
20400
20466
  }
20401
20467
 
20468
+ /**
20469
+ * Update component position in currentSceneData after translation
20470
+ * @param {THREE.Object3D} component - The component that was translated
20471
+ * @private
20472
+ */
20473
+ }, {
20474
+ key: "updateComponentPositionInSceneData",
20475
+ value: function updateComponentPositionInSceneData(component) {
20476
+ var _this$sceneViewer0;
20477
+ if (!((_this$sceneViewer0 = this.sceneViewer) !== null && _this$sceneViewer0 !== void 0 && (_this$sceneViewer0 = _this$sceneViewer0.currentSceneData) !== null && _this$sceneViewer0 !== void 0 && _this$sceneViewer0.scene)) {
20478
+ console.warn('⚠️ Cannot update component position: currentSceneData not available');
20479
+ return;
20480
+ }
20481
+ var cleanPosition = function cleanPosition(value) {
20482
+ return Math.abs(value) < 1e-10 ? 0 : value;
20483
+ };
20484
+
20485
+ // Find the component in scene data
20486
+ var sceneDataComponent = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
20487
+ var _component$userData5;
20488
+ return child.uuid === component.uuid || child.uuid === ((_component$userData5 = component.userData) === null || _component$userData5 === void 0 ? void 0 : _component$userData5.originalUuid);
20489
+ });
20490
+ if (sceneDataComponent) {
20491
+ // Update position object for components (different from connectors which use array)
20492
+ if (!sceneDataComponent.position) {
20493
+ sceneDataComponent.position = {};
20494
+ }
20495
+ sceneDataComponent.position.x = cleanPosition(component.position.x);
20496
+ sceneDataComponent.position.y = cleanPosition(component.position.y);
20497
+ sceneDataComponent.position.z = cleanPosition(component.position.z);
20498
+ console.log("\u2705 Updated component ".concat(component.uuid, " position in scene data to [").concat(component.position.x, ", ").concat(component.position.y, ", ").concat(component.position.z, "]"));
20499
+
20500
+ // Also update child connectors' positions if they exist
20501
+ if (sceneDataComponent.children) {
20502
+ sceneDataComponent.children.forEach(function (child) {
20503
+ var _child$userData17;
20504
+ if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.objectType) === 'connector') {
20505
+ // Find the actual connector object in the scene
20506
+ var connectorObj = component.children.find(function (c) {
20507
+ var _c$userData;
20508
+ return c.uuid === child.uuid || ((_c$userData = c.userData) === null || _c$userData === void 0 ? void 0 : _c$userData.originalUuid) === child.uuid;
20509
+ });
20510
+ if (connectorObj) {
20511
+ // Get world position of connector
20512
+ var worldPos = new THREE__namespace.Vector3();
20513
+ connectorObj.getWorldPosition(worldPos);
20514
+
20515
+ // Update connector's position in userData as array
20516
+ if (!child.userData) {
20517
+ child.userData = {};
20518
+ }
20519
+ child.userData.position = [cleanPosition(worldPos.x), cleanPosition(worldPos.y), cleanPosition(worldPos.z)];
20520
+ console.log(" \u21B3 Updated child connector ".concat(child.uuid, " position to [").concat(child.userData.position.join(', '), "]"));
20521
+ }
20522
+ }
20523
+ });
20524
+ }
20525
+ } else {
20526
+ console.warn("\u26A0\uFE0F Component ".concat(component.uuid, " not found in scene data"));
20527
+ }
20528
+ }
20529
+
20402
20530
  /**
20403
20531
  * Update a connector's position in scene data
20404
20532
  * @param {THREE.Object3D} connector - The connector to update
@@ -20681,8 +20809,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20681
20809
  // Remove segment from scene data
20682
20810
  if (currentSceneData.scene && currentSceneData.scene.children) {
20683
20811
  var segmentIndex = currentSceneData.scene.children.findIndex(function (child) {
20684
- var _segment$userData4;
20685
- return child.uuid === segment.uuid || child.uuid === ((_segment$userData4 = segment.userData) === null || _segment$userData4 === void 0 ? void 0 : _segment$userData4.originalUuid);
20812
+ var _segment$userData10;
20813
+ return child.uuid === segment.uuid || child.uuid === ((_segment$userData10 = segment.userData) === null || _segment$userData10 === void 0 ? void 0 : _segment$userData10.originalUuid);
20686
20814
  });
20687
20815
  if (segmentIndex !== -1) {
20688
20816
  currentSceneData.scene.children.splice(segmentIndex, 1);
@@ -20702,8 +20830,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20702
20830
  // Check if either external connector belongs to the active segment
20703
20831
  var activeSegmentConnectors = [];
20704
20832
  activeSegment.traverse(function (child) {
20705
- var _child$userData15;
20706
- if (((_child$userData15 = child.userData) === null || _child$userData15 === void 0 ? void 0 : _child$userData15.objectType) === 'segment-connector') {
20833
+ var _child$userData18;
20834
+ if (((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.objectType) === 'segment-connector') {
20707
20835
  activeSegmentConnectors.push(child.uuid);
20708
20836
  }
20709
20837
  });
@@ -20751,8 +20879,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
20751
20879
  // Get all connectors of the active segment
20752
20880
  var activeConnectors = [];
20753
20881
  activeSegment.traverse(function (child) {
20754
- var _child$userData16;
20755
- if (((_child$userData16 = child.userData) === null || _child$userData16 === void 0 ? void 0 : _child$userData16.objectType) === 'segment-connector') {
20882
+ var _child$userData19;
20883
+ if (((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.objectType) === 'segment-connector') {
20756
20884
  activeConnectors.push(child);
20757
20885
  }
20758
20886
  });
@@ -24564,365 +24692,6 @@ var PathData = /*#__PURE__*/function () {
24564
24692
  }]);
24565
24693
  }();
24566
24694
 
24567
- /**
24568
- * PathIntersectionDetector - Detects intersections between pipe paths
24569
- *
24570
- * This class handles all intersection detection logic for both computed paths
24571
- * (from pathfinding) and manual segments (user-positioned pipes).
24572
- *
24573
- * @class PathIntersectionDetector
24574
- */
24575
- var PathIntersectionDetector = /*#__PURE__*/function () {
24576
- /**
24577
- * Create a new PathIntersectionDetector
24578
- * @param {Object} sceneViewer - Reference to the scene viewer
24579
- */
24580
- function PathIntersectionDetector(sceneViewer) {
24581
- _classCallCheck(this, PathIntersectionDetector);
24582
- this.sceneViewer = sceneViewer;
24583
- }
24584
-
24585
- /**
24586
- * Check for intersections between paths
24587
- * @param {Array} paths - Array of path objects from pathfinder
24588
- * @param {number} tolerance - Distance tolerance for considering pipes as intersecting (default: 0.2)
24589
- * @param {boolean} includeManualSegments - Whether to include manual segments in the check (default: true)
24590
- * @returns {Object} Intersection results
24591
- * @property {boolean} hasIntersections - Whether any intersections were found
24592
- * @property {Array<Object>} intersections - Array of intersection details
24593
- * @property {number} count - Total number of intersections found
24594
- */
24595
- return _createClass(PathIntersectionDetector, [{
24596
- key: "checkPathIntersections",
24597
- value: function checkPathIntersections(paths) {
24598
- var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.2;
24599
- var includeManualSegments = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
24600
- var intersections = [];
24601
-
24602
- // Convert all paths to line segments for comparison
24603
- var pathSegments = paths.map(function (pathData, pathIndex) {
24604
- if (!pathData.path || pathData.path.length < 2) {
24605
- return null;
24606
- }
24607
- var segments = [];
24608
- var pathPoints = pathData.path.map(function (point) {
24609
- if (point instanceof THREE__namespace.Vector3) {
24610
- return point.clone();
24611
- } else if (Array.isArray(point)) {
24612
- return new THREE__namespace.Vector3().fromArray(point);
24613
- } else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
24614
- return new THREE__namespace.Vector3(point.x, point.y, point.z);
24615
- }
24616
- return null;
24617
- }).filter(function (p) {
24618
- return p !== null;
24619
- });
24620
- for (var i = 0; i < pathPoints.length - 1; i++) {
24621
- segments.push({
24622
- start: pathPoints[i],
24623
- end: pathPoints[i + 1],
24624
- pathIndex: pathIndex,
24625
- segmentIndex: i,
24626
- pathFrom: pathData.from,
24627
- pathTo: pathData.to,
24628
- isFirstSegment: i === 0,
24629
- isLastSegment: i === pathPoints.length - 2,
24630
- isManual: false // Computed path segment
24631
- });
24632
- }
24633
- return segments;
24634
- }).filter(function (s) {
24635
- return s !== null;
24636
- }).flat();
24637
-
24638
- // Add manual segments if requested
24639
- if (includeManualSegments) {
24640
- var manualSegments = this._collectManualSegments(pathSegments.length);
24641
- pathSegments.push.apply(pathSegments, _toConsumableArray(manualSegments));
24642
- console.log("\uD83D\uDCE6 Added ".concat(manualSegments.length, " manual segment(s) to intersection check"));
24643
- }
24644
- console.log("\uD83D\uDD0D Checking ".concat(pathSegments.length, " segments for intersections..."));
24645
-
24646
- // Check each pair of segments
24647
- for (var i = 0; i < pathSegments.length; i++) {
24648
- for (var j = i + 1; j < pathSegments.length; j++) {
24649
- var seg1 = pathSegments[i];
24650
- var seg2 = pathSegments[j];
24651
-
24652
- // Skip if segments are from the same path
24653
- if (seg1.pathIndex === seg2.pathIndex) {
24654
- continue;
24655
- }
24656
-
24657
- // Check if segments intersect
24658
- var intersection = this._checkLineSegmentIntersection(seg1.start, seg1.end, seg2.start, seg2.end, tolerance);
24659
- if (intersection) {
24660
- // Check if this is a shared endpoint (connector/gateway)
24661
- // Paths naturally touch at shared connectors - this is not an intersection
24662
- var endpointTolerance = 0.01; // Very small tolerance for endpoint matching
24663
- var touchingAtEndpoint = this._areSegmentsTouchingAtSharedEndpoint(seg1, seg2, endpointTolerance);
24664
- if (touchingAtEndpoint) {
24665
- console.log("\u2139\uFE0F Segments share endpoint (not an intersection): ".concat(seg1.pathFrom, " \u2194 ").concat(seg2.pathFrom));
24666
- continue; // Skip this - it's a valid shared connection point
24667
- }
24668
- intersections.push({
24669
- path1: {
24670
- from: seg1.pathFrom,
24671
- to: seg1.pathTo,
24672
- segmentIndex: seg1.segmentIndex,
24673
- isManual: seg1.isManual
24674
- },
24675
- path2: {
24676
- from: seg2.pathFrom,
24677
- to: seg2.pathTo,
24678
- segmentIndex: seg2.segmentIndex,
24679
- isManual: seg2.isManual
24680
- },
24681
- point: intersection.point,
24682
- distance: intersection.distance,
24683
- type: intersection.type
24684
- });
24685
- var seg1Type = seg1.isManual ? 'manual' : 'computed';
24686
- var seg2Type = seg2.isManual ? 'manual' : 'computed';
24687
- console.log("\u26A0\uFE0F Intersection found between paths:\n Path 1 (".concat(seg1Type, "): ").concat(seg1.pathFrom, " \u2192 ").concat(seg1.pathTo, " (segment ").concat(seg1.segmentIndex, ")\n Path 2 (").concat(seg2Type, "): ").concat(seg2.pathFrom, " \u2192 ").concat(seg2.pathTo, " (segment ").concat(seg2.segmentIndex, ")\n Distance: ").concat(intersection.distance.toFixed(4), "\n Type: ").concat(intersection.type));
24688
- }
24689
- }
24690
- }
24691
- var result = {
24692
- hasIntersections: intersections.length > 0,
24693
- intersections: intersections,
24694
- count: intersections.length
24695
- };
24696
- if (result.hasIntersections) {
24697
- console.log("\uD83D\uDEA8 Found ".concat(result.count, " intersection(s) between paths"));
24698
- } else {
24699
- console.log("\u2705 No path intersections detected");
24700
- }
24701
- return result;
24702
- }
24703
-
24704
- /**
24705
- * Collect manual segments from the scene and convert them to path segments format
24706
- * @private
24707
- * @param {number} startingPathIndex - The starting index for manual segment paths
24708
- * @returns {Array} Array of segment objects in the same format as computed paths
24709
- */
24710
- }, {
24711
- key: "_collectManualSegments",
24712
- value: function _collectManualSegments(startingPathIndex) {
24713
- var _this = this;
24714
- var manualSegments = [];
24715
- var sceneViewer = this.sceneViewer;
24716
- var pathIndex = startingPathIndex;
24717
-
24718
- // Traverse the scene to find manual segments (lowercase "Segment-")
24719
- sceneViewer.scene.traverse(function (obj) {
24720
- var _obj$userData, _obj$userData2;
24721
- if (obj.uuid && obj.uuid.startsWith('Segment-') && ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType) === 'segment' && ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.isDeclared) === true) {
24722
- // Calculate segment endpoints from the cylinder geometry
24723
- var endpoints = _this._calculateSegmentEndpoints(obj);
24724
-
24725
- // Create segment object in the same format as computed paths
24726
- manualSegments.push({
24727
- start: endpoints.start,
24728
- end: endpoints.end,
24729
- pathIndex: pathIndex,
24730
- segmentIndex: 0,
24731
- // Manual segments are single-segment paths
24732
- pathFrom: obj.userData.pathFrom || obj.uuid,
24733
- pathTo: obj.userData.pathTo || obj.uuid,
24734
- isFirstSegment: true,
24735
- isLastSegment: true,
24736
- isManual: true,
24737
- // Flag to identify manual segments
24738
- segmentUuid: obj.uuid
24739
- });
24740
- pathIndex++;
24741
- console.log("\uD83D\uDCE6 Collected manual segment: ".concat(obj.uuid));
24742
- }
24743
- });
24744
- return manualSegments;
24745
- }
24746
-
24747
- /**
24748
- * Calculate the start and end points of a pipe segment in world coordinates
24749
- * @private
24750
- * @param {THREE.Object3D} segment - The pipe segment
24751
- * @returns {Object} Object with start and end points
24752
- */
24753
- }, {
24754
- key: "_calculateSegmentEndpoints",
24755
- value: function _calculateSegmentEndpoints(segment) {
24756
- // Get the segment's geometry to determine its length and orientation
24757
- var geometry = segment.geometry;
24758
- var length = geometry.parameters.height || 1;
24759
-
24760
- // Calculate start and end points based on segment position and orientation
24761
- var startPoint = new THREE__namespace.Vector3();
24762
- var endPoint = new THREE__namespace.Vector3();
24763
-
24764
- // Get the segment's direction vector
24765
- var direction = new THREE__namespace.Vector3(0, 1, 0);
24766
- direction.applyQuaternion(segment.quaternion);
24767
-
24768
- // Calculate start point (half length back from center)
24769
- startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(length / 2));
24770
-
24771
- // Calculate end point (half length forward from center)
24772
- endPoint.copy(segment.position).add(direction.clone().multiplyScalar(length / 2));
24773
- return {
24774
- start: startPoint,
24775
- end: endPoint
24776
- };
24777
- }
24778
-
24779
- /**
24780
- * Check if two segments are touching at a shared endpoint (connector/gateway)
24781
- * @private
24782
- * @param {Object} seg1 - First segment
24783
- * @param {Object} seg2 - Second segment
24784
- * @param {number} tolerance - Distance tolerance for considering points as the same
24785
- * @returns {boolean} True if segments share an endpoint
24786
- */
24787
- }, {
24788
- key: "_areSegmentsTouchingAtSharedEndpoint",
24789
- value: function _areSegmentsTouchingAtSharedEndpoint(seg1, seg2, tolerance) {
24790
- // Check all possible endpoint combinations
24791
- var endpoints = [
24792
- // seg1.start with seg2 endpoints
24793
- {
24794
- p1: seg1.start,
24795
- p2: seg2.start,
24796
- isSeg1Start: true,
24797
- isSeg2Start: true
24798
- }, {
24799
- p1: seg1.start,
24800
- p2: seg2.end,
24801
- isSeg1Start: true,
24802
- isSeg2Start: false
24803
- },
24804
- // seg1.end with seg2 endpoints
24805
- {
24806
- p1: seg1.end,
24807
- p2: seg2.start,
24808
- isSeg1Start: false,
24809
- isSeg2Start: true
24810
- }, {
24811
- p1: seg1.end,
24812
- p2: seg2.end,
24813
- isSeg1Start: false,
24814
- isSeg2Start: false
24815
- }];
24816
- for (var _i = 0, _endpoints = endpoints; _i < _endpoints.length; _i++) {
24817
- var _endpoints$_i = _endpoints[_i],
24818
- p1 = _endpoints$_i.p1,
24819
- p2 = _endpoints$_i.p2,
24820
- isSeg1Start = _endpoints$_i.isSeg1Start,
24821
- isSeg2Start = _endpoints$_i.isSeg2Start;
24822
- var distance = p1.distanceTo(p2);
24823
- if (distance <= tolerance) {
24824
- // Verify this is actually an endpoint of the path (not just any segment point)
24825
- var isSeg1Endpoint = isSeg1Start && seg1.isFirstSegment || !isSeg1Start && seg1.isLastSegment;
24826
- var isSeg2Endpoint = isSeg2Start && seg2.isFirstSegment || !isSeg2Start && seg2.isLastSegment;
24827
-
24828
- // Only count as shared endpoint if at least one is a path endpoint
24829
- // (This handles both connector-to-connector and connector-to-gateway cases)
24830
- if (isSeg1Endpoint || isSeg2Endpoint) {
24831
- return true;
24832
- }
24833
- }
24834
- }
24835
- return false;
24836
- }
24837
-
24838
- /**
24839
- * Check if two line segments intersect or come within tolerance distance
24840
- * @private
24841
- * @param {THREE.Vector3} p1 - Start of first segment
24842
- * @param {THREE.Vector3} p2 - End of first segment
24843
- * @param {THREE.Vector3} p3 - Start of second segment
24844
- * @param {THREE.Vector3} p4 - End of second segment
24845
- * @param {number} tolerance - Distance tolerance
24846
- * @returns {Object|null} Intersection details or null
24847
- */
24848
- }, {
24849
- key: "_checkLineSegmentIntersection",
24850
- value: function _checkLineSegmentIntersection(p1, p2, p3, p4, tolerance) {
24851
- // Calculate closest points on two line segments
24852
- var d1 = new THREE__namespace.Vector3().subVectors(p2, p1); // Direction of segment 1
24853
- var d2 = new THREE__namespace.Vector3().subVectors(p4, p3); // Direction of segment 2
24854
- var r = new THREE__namespace.Vector3().subVectors(p1, p3);
24855
- var a = d1.dot(d1);
24856
- var b = d1.dot(d2);
24857
- var c = d2.dot(d2);
24858
- var d = d1.dot(r);
24859
- var e = d2.dot(r);
24860
- var denom = a * c - b * b;
24861
-
24862
- // Check if lines are parallel
24863
- if (Math.abs(denom) < 1e-10) {
24864
- // Lines are parallel, check if they're close enough
24865
- var distToLine = this._distancePointToLineSegment(p3, p1, p2);
24866
- if (distToLine <= tolerance) {
24867
- return {
24868
- point: p3.clone(),
24869
- distance: distToLine,
24870
- type: 'parallel'
24871
- };
24872
- }
24873
- return null;
24874
- }
24875
-
24876
- // Calculate parameters for closest points
24877
- var s = (b * e - c * d) / denom;
24878
- var t = (a * e - b * d) / denom;
24879
-
24880
- // Clamp to segment bounds
24881
- s = Math.max(0, Math.min(1, s));
24882
- t = Math.max(0, Math.min(1, t));
24883
-
24884
- // Calculate closest points
24885
- var closestPoint1 = new THREE__namespace.Vector3().addVectors(p1, d1.clone().multiplyScalar(s));
24886
- var closestPoint2 = new THREE__namespace.Vector3().addVectors(p3, d2.clone().multiplyScalar(t));
24887
-
24888
- // Calculate distance between closest points
24889
- var distance = closestPoint1.distanceTo(closestPoint2);
24890
-
24891
- // Check if within tolerance
24892
- if (distance <= tolerance) {
24893
- var midPoint = new THREE__namespace.Vector3().addVectors(closestPoint1, closestPoint2).multiplyScalar(0.5);
24894
- return {
24895
- point: midPoint,
24896
- distance: distance,
24897
- type: distance < 0.01 ? 'crossing' : 'near'
24898
- };
24899
- }
24900
- return null;
24901
- }
24902
-
24903
- /**
24904
- * Calculate distance from a point to a line segment
24905
- * @private
24906
- * @param {THREE.Vector3} point - The point
24907
- * @param {THREE.Vector3} lineStart - Start of line segment
24908
- * @param {THREE.Vector3} lineEnd - End of line segment
24909
- * @returns {number} Distance to line segment
24910
- */
24911
- }, {
24912
- key: "_distancePointToLineSegment",
24913
- value: function _distancePointToLineSegment(point, lineStart, lineEnd) {
24914
- var line = new THREE__namespace.Vector3().subVectors(lineEnd, lineStart);
24915
- var lineLength = line.length();
24916
- if (lineLength < 1e-10) {
24917
- return point.distanceTo(lineStart);
24918
- }
24919
- var t = Math.max(0, Math.min(1, new THREE__namespace.Vector3().subVectors(point, lineStart).dot(line) / (lineLength * lineLength)));
24920
- var projection = new THREE__namespace.Vector3().addVectors(lineStart, line.multiplyScalar(t));
24921
- return point.distanceTo(projection);
24922
- }
24923
- }]);
24924
- }();
24925
-
24926
24695
  /**
24927
24696
  * SceneDataManager
24928
24697
  * Utility class for managing scene data transformations and queries
@@ -24935,118 +24704,12 @@ var SceneDataManager = /*#__PURE__*/function () {
24935
24704
  }
24936
24705
 
24937
24706
  /**
24938
- * Get simplified scene data for pathfinding
24939
- * Collects all objects with objectType, filters out computed objects,
24940
- * and calculates world bounding boxes
24941
- * @returns {Object} Simplified scene data with children array
24707
+ * Helper method to find an object in scene data by UUID
24708
+ * @param {Object} sceneData - Scene data to search
24709
+ * @param {string} uuid - UUID to find
24710
+ * @returns {Object|null} Found object or null
24942
24711
  */
24943
24712
  return _createClass(SceneDataManager, [{
24944
- key: "getSimplifiedSceneData",
24945
- value: function getSimplifiedSceneData() {
24946
- // Collect all objects with objectType (flattened list from scene traversal)
24947
- // Filter out ALL computed objects - only include declared/source objects
24948
- var sceneDataNew = [];
24949
- this.sceneViewer.scene.traverse(function (obj) {
24950
- if (obj.userData && obj.userData.objectType) {
24951
- // Skip computed gateways (only include declared/manual gateways)
24952
- if (obj.userData.objectType === 'gateway' && !obj.userData.isDeclared) {
24953
- return;
24954
- }
24955
- sceneDataNew.push(obj);
24956
- }
24957
- });
24958
- console.log('🔗 [SceneDataManager] sceneDataNew (flattened):', sceneDataNew);
24959
-
24960
- // Calculate world bounding boxes for each object individually (after flattening)
24961
- // This way we don't need to worry about children - each object is standalone
24962
- var simplifiedSceneData = {};
24963
- simplifiedSceneData.children = sceneDataNew.map(function (obj) {
24964
- var _obj$children;
24965
- var uuid = obj.uuid;
24966
-
24967
- // Calculate world bounding box for this individual object
24968
- var worldBoundingBox = null;
24969
-
24970
- // For meshes, calculate bbox from geometry only (ignoring children)
24971
- if (obj.isMesh && obj.geometry) {
24972
- try {
24973
- // Compute bounding box from geometry in world space
24974
- var bbox = new THREE__namespace.Box3();
24975
- obj.geometry.computeBoundingBox();
24976
- if (obj.geometry.boundingBox) {
24977
- // Transform local bbox to world space
24978
- bbox.copy(obj.geometry.boundingBox);
24979
- bbox.applyMatrix4(obj.matrixWorld);
24980
-
24981
- // Only include valid bounding boxes
24982
- // Check if all components of min and max are finite numbers
24983
- var isValidBBox = !bbox.isEmpty() && isFinite(bbox.min.x) && isFinite(bbox.min.y) && isFinite(bbox.min.z) && isFinite(bbox.max.x) && isFinite(bbox.max.y) && isFinite(bbox.max.z);
24984
- if (isValidBBox) {
24985
- worldBoundingBox = {
24986
- min: bbox.min.toArray(),
24987
- max: bbox.max.toArray()
24988
- };
24989
- } else {
24990
- console.warn("\u26A0\uFE0F Invalid bounding box for ".concat(uuid, ", skipping"));
24991
- }
24992
- }
24993
- } catch (error) {
24994
- console.warn("\u26A0\uFE0F Failed to calculate bounding box for ".concat(uuid, ":"), error);
24995
- }
24996
- }
24997
- // For groups or objects with children, use setFromObject but only on this object
24998
- else if (obj.isGroup || ((_obj$children = obj.children) === null || _obj$children === void 0 ? void 0 : _obj$children.length) > 0) {
24999
- try {
25000
- var _bbox = new THREE__namespace.Box3().setFromObject(obj);
25001
-
25002
- // Check if all components of min and max are finite numbers
25003
- var _isValidBBox = !_bbox.isEmpty() && isFinite(_bbox.min.x) && isFinite(_bbox.min.y) && isFinite(_bbox.min.z) && isFinite(_bbox.max.x) && isFinite(_bbox.max.y) && isFinite(_bbox.max.z);
25004
- if (_isValidBBox) {
25005
- worldBoundingBox = {
25006
- min: _bbox.min.toArray(),
25007
- max: _bbox.max.toArray()
25008
- };
25009
- }
25010
- } catch (error) {
25011
- console.warn("\u26A0\uFE0F Failed to calculate bounding box for ".concat(uuid, ":"), error);
25012
- }
25013
- }
25014
- var results = {
25015
- uuid: uuid,
25016
- userData: _objectSpread2(_objectSpread2({}, obj.userData), worldBoundingBox && {
25017
- worldBoundingBox: worldBoundingBox
25018
- })
25019
- };
25020
-
25021
- // For connectors and gateways, add world position
25022
- if (obj.userData.objectType.includes('connector') || obj.userData.objectType === 'gateway') {
25023
- var worldPosition = new THREE__namespace.Vector3();
25024
- obj.getWorldPosition(worldPosition);
25025
- results.userData.position = [worldPosition.x, worldPosition.y, worldPosition.z];
25026
-
25027
- // Differentiate component connectors from segment connectors for pathfinder
25028
- // Component connectors are children of components
25029
- if (obj.userData.objectType === 'connector') {
25030
- var _parent$userData;
25031
- // Check if parent is a component (not a segment)
25032
- var parent = obj.parent;
25033
- if (parent && ((_parent$userData = parent.userData) === null || _parent$userData === void 0 ? void 0 : _parent$userData.objectType) === 'component') {
25034
- results.userData.objectType = 'component-connector';
25035
- }
25036
- }
25037
- }
25038
- return results;
25039
- });
25040
- return simplifiedSceneData;
25041
- }
25042
-
25043
- /**
25044
- * Helper method to find an object in scene data by UUID
25045
- * @param {Object} sceneData - Scene data to search
25046
- * @param {string} uuid - UUID to find
25047
- * @returns {Object|null} Found object or null
25048
- */
25049
- }, {
25050
24713
  key: "findObjectInSceneData",
25051
24714
  value: function findObjectInSceneData(sceneData, uuid) {
25052
24715
  var _searchChildren = function searchChildren(children) {
@@ -25384,7 +25047,8 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25384
25047
  }
25385
25048
  var cylinderGeometry = new THREE__namespace.CylinderGeometry(pipeRadius, pipeRadius, length, 16, 1, false);
25386
25049
  var cylinder = new THREE__namespace.Mesh(cylinderGeometry, pipeMaterial);
25387
- cylinder.position.copy(start).add(end).multiplyScalar(0.5);
25050
+ var centerPoint = new THREE__namespace.Vector3().copy(start).add(end).multiplyScalar(0.5);
25051
+ cylinder.position.copy(centerPoint);
25388
25052
  var quaternion = new THREE__namespace.Quaternion();
25389
25053
  var up = new THREE__namespace.Vector3(0, 1, 0);
25390
25054
  quaternion.setFromUnitVectors(up, direction.clone().normalize());
@@ -25405,6 +25069,10 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25405
25069
  var isLastSegment = j === pathPoints.length - 2;
25406
25070
  var isImmutable = fromHasDirection && isFirstSegment || toHasDirection && isLastSegment;
25407
25071
 
25072
+ // Calculate relative endpoint offsets from center point
25073
+ var startOffset = new THREE__namespace.Vector3().subVectors(start, centerPoint);
25074
+ var endOffset = new THREE__namespace.Vector3().subVectors(end, centerPoint);
25075
+
25408
25076
  // Add userData to make pipe segments selectable and for tooltip display
25409
25077
  cylinder.userData = {
25410
25078
  objectType: 'segment',
@@ -25412,7 +25080,21 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
25412
25080
  segmentIndex: globalSegmentIndex,
25413
25081
  pathFrom: pathData.from,
25414
25082
  pathTo: pathData.to,
25415
- immutable: isImmutable // Mark segments connected to component connectors as immutable
25083
+ immutable: isImmutable,
25084
+ // Mark segments connected to component connectors as immutable
25085
+ // Store endpoint offsets relative to center point for reconstruction
25086
+ endpoints: {
25087
+ startOffset: {
25088
+ x: startOffset.x,
25089
+ y: startOffset.y,
25090
+ z: startOffset.z
25091
+ },
25092
+ endOffset: {
25093
+ x: endOffset.x,
25094
+ y: endOffset.y,
25095
+ z: endOffset.z
25096
+ }
25097
+ }
25416
25098
  };
25417
25099
 
25418
25100
  // Increment global segment counter
@@ -26651,9 +26333,6 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26651
26333
  }
26652
26334
  }
26653
26335
 
26654
- // Initialize intersection detector
26655
- _this.intersectionDetector = new PathIntersectionDetector(sceneViewer);
26656
-
26657
26336
  // Initialize rendering manager
26658
26337
  _this.renderingManager = new PathRenderingManager(sceneViewer);
26659
26338
  _this.registerDisposable(_this.renderingManager);
@@ -26725,17 +26404,67 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26725
26404
  // END NEW ADAPTER METHODS
26726
26405
  // ============================================================================
26727
26406
 
26407
+ /**
26408
+ * Enrich sceneData with worldBoundingBox for segments
26409
+ * Connectors remain with just position information
26410
+ * @param {Object} sceneData - Original scene data
26411
+ * @returns {Object} Enriched scene data (shallow copy with modifications)
26412
+ * @private
26413
+ */
26414
+ }, {
26415
+ key: "_enrichSceneDataWithBoundingBoxes",
26416
+ value: function _enrichSceneDataWithBoundingBoxes(sceneData) {
26417
+ var _this3 = this;
26418
+ // Create a shallow copy of sceneData structure
26419
+ var enriched = _objectSpread2({}, sceneData);
26420
+ if (!sceneData.children || !Array.isArray(sceneData.children)) {
26421
+ console.warn('⚠️ sceneData has no children array');
26422
+ return enriched;
26423
+ }
26424
+
26425
+ // Process children to add worldBoundingBox to segments
26426
+ enriched.children = sceneData.children.map(function (child) {
26427
+ // Only enrich segments (check if objectType is 'segment' in userData)
26428
+ if (child.userData && child.userData.objectType === 'segment') {
26429
+ // Find the actual segment object in the scene
26430
+ var segmentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
26431
+ if (segmentObject) {
26432
+ // Compute world bounding box
26433
+ var worldBBox = new THREE__namespace.Box3().setFromObject(segmentObject);
26434
+
26435
+ // Return enriched segment data with worldBoundingBox in userData
26436
+ // Note: pathfinder expects arrays [x, y, z] format for min/max
26437
+ return _objectSpread2(_objectSpread2({}, child), {}, {
26438
+ userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
26439
+ worldBoundingBox: {
26440
+ min: [worldBBox.min.x, worldBBox.min.y, worldBBox.min.z],
26441
+ max: [worldBBox.max.x, worldBBox.max.y, worldBBox.max.z]
26442
+ }
26443
+ })
26444
+ });
26445
+ } else {
26446
+ console.warn("\u26A0\uFE0F Could not find segment object in scene: ".concat(child.uuid));
26447
+ }
26448
+ }
26449
+
26450
+ // For non-segments (including connectors), return as-is
26451
+ return child;
26452
+ });
26453
+ return enriched;
26454
+ }
26455
+
26728
26456
  /**
26729
26457
  * Core pathfinding logic shared across initialization and updates
26730
26458
  */
26731
26459
  }, {
26732
26460
  key: "_executePathfinding",
26733
- value: function () {
26461
+ value: (function () {
26734
26462
  var _executePathfinding2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(sceneData, connections) {
26735
26463
  var options,
26736
26464
  _options$context,
26737
26465
  context,
26738
26466
  connectionsCopy,
26467
+ enrichedSceneData,
26739
26468
  sceneDataCopy,
26740
26469
  pathfindingResult,
26741
26470
  _args = arguments;
@@ -26752,26 +26481,11 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26752
26481
  console.log("\uD83D\uDD04 Updated matrix world for ".concat(context, " pathfinding execution"));
26753
26482
 
26754
26483
  // Deep copy connections to prevent pathfinder from mutating the original
26755
- connectionsCopy = JSON.parse(JSON.stringify(connections));
26756
- sceneDataCopy = JSON.parse(JSON.stringify(sceneData));
26484
+ connectionsCopy = JSON.parse(JSON.stringify(connections)); // Enrich sceneData with worldBoundingBox for segments before deep copy
26485
+ enrichedSceneData = this._enrichSceneDataWithBoundingBoxes(sceneData);
26486
+ sceneDataCopy = JSON.parse(JSON.stringify(enrichedSceneData));
26757
26487
  console.log("[Pathfinder] sceneDataCopy:", sceneDataCopy);
26758
26488
 
26759
- // const simplifiedSceneData = JSON.parse(JSON.stringify( this.getSimplifiedSceneData() ));
26760
-
26761
- // // Take snapshot before pathfinding execution (capture Three.js scene)
26762
- // this.snapshotManager.takeSnapshot(
26763
- // this.sceneViewer.scene, // Pass the actual Three.js scene
26764
- // connectionsCopy,
26765
- // context
26766
- // );
26767
-
26768
- // console.log('[Pathfinder] simplifiedSceneData length at creation:', simplifiedSceneData.children?.length);
26769
- // console.log('[Pathfinder] simplifiedSceneData (deep clone for inspection):', JSON.parse(JSON.stringify(simplifiedSceneData)));
26770
-
26771
- // // Add debugging for pathfinder input
26772
- // console.log('🔍 PATHFINDER DEBUGGING:');
26773
- // console.log('🔗 [Pathfinder] Connections:', JSON.parse(JSON.stringify(connectionsCopy)));
26774
-
26775
26489
  // Find paths using v1.0.17 API (sceneData and connections separately)
26776
26490
  // Pass deep copy to ensure pathfinder cannot mutate original connections
26777
26491
  pathfindingResult = this.pathfinder.findPaths(sceneDataCopy, connectionsCopy);
@@ -26780,79 +26494,6 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26780
26494
  console.log('Rewired connections:', JSON.parse(JSON.stringify(pathfindingResult.rewiredConnections)));
26781
26495
  console.log("intersectionCheck input:", pathfindingResult.paths);
26782
26496
 
26783
- // // Check for path intersections (including manual segments)
26784
- // const intersectionCheck = this.checkPathIntersections(pathfindingResult.paths, 0.2, true);
26785
- // pathfindingResult.intersections = intersectionCheck;
26786
-
26787
- // console.log("intersectionCheck:", intersectionCheck);
26788
- // console.log("intersectionCheck.hasIntersections:", intersectionCheck.hasIntersections);
26789
-
26790
- // // Handle intersection detection - undo last operation if intersections found
26791
- // // Skip this if we're already in the middle of an undo operation
26792
- // if (intersectionCheck.hasIntersections && !this.isUndoInProgress) {
26793
- // console.warn('⚠️ Path intersections detected! Attempting to undo last operation...');
26794
-
26795
- // // Set flag to prevent recursive undo attempts
26796
- // this.isUndoInProgress = true;
26797
-
26798
- // // Access operationHistoryManager through sceneViewer.managers.operationHistory
26799
- // const operationHistoryManager = this.sceneViewer?.managers?.operationHistory;
26800
-
26801
- // if (operationHistoryManager) {
26802
- // const lastOp = operationHistoryManager.getLastOperation();
26803
-
26804
- // if (lastOp) {
26805
- // console.warn(`⚠️ Intersection caused by operation: ${lastOp.operationName}`, lastOp.params);
26806
-
26807
- // // Attempt to undo the operation FIRST (before removing computed objects)
26808
- // // This is important because undo needs to find the segment that was moved
26809
- // const undoSuccess = operationHistoryManager.undoLastOperation();
26810
-
26811
- // if (undoSuccess) {
26812
- // console.log('✅ Successfully undid operation that caused intersection');
26813
-
26814
- // // Now remove the buggy computed objects that were created with the invalid state
26815
- // console.log('🗑️ Removing buggy computed objects after undo...');
26816
- // this.removeComputedObjects();
26817
-
26818
- // // Re-run pathfinding after undo to restore valid state
26819
- // console.log('🔄 Re-running pathfinding after undo to restore clean state...');
26820
-
26821
- // // Recursively call _executePathfinding with the corrected scene state
26822
- // // This is safe because we've undone the operation, so we won't get into an infinite loop
26823
- // const correctedResult = await this._executePathfinding(
26824
- // sceneData,
26825
- // connections,
26826
- // { ...options, context: `${context} (After Undo)` }
26827
- // );
26828
-
26829
- // // Mark that we performed an undo and return the corrected result
26830
- // correctedResult.undoPerformed = true;
26831
- // correctedResult.undoneOperation = lastOp;
26832
-
26833
- // // Clear the undo flag before returning
26834
- // this.isUndoInProgress = false;
26835
-
26836
- // return correctedResult;
26837
- // } else {
26838
- // console.error('❌ Failed to undo operation that caused intersection');
26839
- // pathfindingResult.undoFailed = true;
26840
- // // Clear the undo flag even on failure
26841
- // this.isUndoInProgress = false;
26842
- // }
26843
- // } else {
26844
- // console.warn('⚠️ No operation in history to undo');
26845
- // this.isUndoInProgress = false;
26846
- // }
26847
- // } else {
26848
- // console.error('❌ OperationHistoryManager not available for undo');
26849
- // console.error(' Available managers:', Object.keys(this.sceneViewer?.managers || {}));
26850
- // this.isUndoInProgress = false;
26851
- // }
26852
- // } else if (intersectionCheck.hasIntersections && this.isUndoInProgress) {
26853
- // console.log('⏭️ Skipping intersection handling - undo already in progress');
26854
- // }
26855
-
26856
26497
  // Create gateways in the scene if requested
26857
26498
  if (options.createGateways && pathfindingResult.gateways) {
26858
26499
  this.renderingManager.createGateways(pathfindingResult);
@@ -26869,7 +26510,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26869
26510
  return _executePathfinding2.apply(this, arguments);
26870
26511
  }
26871
26512
  return _executePathfinding;
26872
- }()
26513
+ }())
26873
26514
  }, {
26874
26515
  key: "getSimplifiedSceneData",
26875
26516
  value: function getSimplifiedSceneData() {
@@ -26960,25 +26601,6 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
26960
26601
  console.log("\u2705 Removed ".concat(objectsToRemove.length, " computed objects from scene (segments, elbows, and gateways)"));
26961
26602
  }
26962
26603
 
26963
- /**
26964
- * Check for intersections between paths
26965
- * Delegates to PathIntersectionDetector for the actual detection logic
26966
- * @param {Array} paths - Array of path objects from pathfinder
26967
- * @param {number} tolerance - Distance tolerance for considering pipes as intersecting (default: 0.2)
26968
- * @param {boolean} includeManualSegments - Whether to include manual segments in the check (default: true)
26969
- * @returns {Object} Intersection results
26970
- * @property {boolean} hasIntersections - Whether any intersections were found
26971
- * @property {Array<Object>} intersections - Array of intersection details
26972
- * @property {number} count - Total number of intersections found
26973
- */
26974
- }, {
26975
- key: "checkPathIntersections",
26976
- value: function checkPathIntersections(paths) {
26977
- var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.2;
26978
- var includeManualSegments = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
26979
- return this.intersectionDetector.checkPathIntersections(paths, tolerance, includeManualSegments);
26980
- }
26981
-
26982
26604
  /**
26983
26605
  * Update pathfinding after object transforms
26984
26606
  */
@@ -33805,7 +33427,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
33805
33427
  * Initialize the CentralPlant manager
33806
33428
  *
33807
33429
  * @constructor
33808
- * @version 0.1.54
33430
+ * @version 0.1.55
33809
33431
  * @updated 2025-10-22
33810
33432
  *
33811
33433
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -38011,7 +37633,6 @@ exports.KeyboardControlsManager = KeyboardControlsManager;
38011
37633
  exports.ModelManager = ModelManager;
38012
37634
  exports.OperationHistoryManager = OperationHistoryManager;
38013
37635
  exports.PathData = PathData;
38014
- exports.PathIntersectionDetector = PathIntersectionDetector;
38015
37636
  exports.PathfindingManager = PathfindingManager;
38016
37637
  exports.PerformanceMonitorManager = PerformanceMonitorManager;
38017
37638
  exports.Rendering2D = rendering2D;