@2112-lab/central-plant 0.1.55 → 0.1.60
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/bundle/index.js +1019 -558
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/components/transformOperationsManager.js +441 -51
- package/dist/cjs/src/managers/controls/transformControlsManager.js +520 -434
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +33 -72
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +28 -4
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/components/transformOperationsManager.js +442 -52
- package/dist/esm/src/managers/controls/transformControlsManager.js +521 -435
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +33 -72
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +28 -4
- package/package.json +4 -3
package/dist/bundle/index.js
CHANGED
|
@@ -3993,6 +3993,80 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
3993
3993
|
var hasConnectorName = object.name && object.name.toLowerCase().includes('connector');
|
|
3994
3994
|
return (hasConnectorGeometry || isSphereConnector) && hasConnectorName;
|
|
3995
3995
|
}
|
|
3996
|
+
|
|
3997
|
+
/**
|
|
3998
|
+
* Check if a segment can be added to the current selection
|
|
3999
|
+
* Prevents mixing horizontal and vertical segments
|
|
4000
|
+
* @param {THREE.Object3D} segment - The segment to check
|
|
4001
|
+
* @returns {boolean} True if segment can be added, false otherwise
|
|
4002
|
+
* @private
|
|
4003
|
+
*/
|
|
4004
|
+
}, {
|
|
4005
|
+
key: "_canAddSegmentToSelection",
|
|
4006
|
+
value: function _canAddSegmentToSelection(segment) {
|
|
4007
|
+
if (!isSegment(segment)) {
|
|
4008
|
+
return true; // Non-segments can always be added
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
// Find any segments already in selection
|
|
4012
|
+
var existingSegments = this.selectedObjects.filter(function (obj) {
|
|
4013
|
+
return isSegment(obj);
|
|
4014
|
+
});
|
|
4015
|
+
|
|
4016
|
+
// If no segments selected yet, this is the first one - allow it
|
|
4017
|
+
if (existingSegments.length === 0) {
|
|
4018
|
+
return true;
|
|
4019
|
+
}
|
|
4020
|
+
|
|
4021
|
+
// Check orientation compatibility
|
|
4022
|
+
var isNewSegmentHorizontal = this._isSegmentHorizontal(segment);
|
|
4023
|
+
|
|
4024
|
+
// Check if all existing segments have the same orientation
|
|
4025
|
+
var _iterator = _createForOfIteratorHelper(existingSegments),
|
|
4026
|
+
_step;
|
|
4027
|
+
try {
|
|
4028
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
4029
|
+
var existingSegment = _step.value;
|
|
4030
|
+
var isExistingHorizontal = this._isSegmentHorizontal(existingSegment);
|
|
4031
|
+
|
|
4032
|
+
// Disallow mixing horizontal and vertical
|
|
4033
|
+
if (isNewSegmentHorizontal !== isExistingHorizontal) {
|
|
4034
|
+
return false;
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
} catch (err) {
|
|
4038
|
+
_iterator.e(err);
|
|
4039
|
+
} finally {
|
|
4040
|
+
_iterator.f();
|
|
4041
|
+
}
|
|
4042
|
+
return true;
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
/**
|
|
4046
|
+
* Check if a segment is horizontal (Z-up coordinate system)
|
|
4047
|
+
* @param {THREE.Object3D} segment - The segment to check
|
|
4048
|
+
* @returns {boolean} True if horizontal, false if vertical
|
|
4049
|
+
* @private
|
|
4050
|
+
*/
|
|
4051
|
+
}, {
|
|
4052
|
+
key: "_isSegmentHorizontal",
|
|
4053
|
+
value: function _isSegmentHorizontal(segment) {
|
|
4054
|
+
if (!segment || !segment.geometry || !segment.quaternion) {
|
|
4055
|
+
return false;
|
|
4056
|
+
}
|
|
4057
|
+
|
|
4058
|
+
// Get the segment's direction vector (cylinder aligned with Y-axis by default)
|
|
4059
|
+
var direction = new THREE__namespace.Vector3(0, 1, 0);
|
|
4060
|
+
direction.applyQuaternion(segment.quaternion);
|
|
4061
|
+
direction.normalize();
|
|
4062
|
+
|
|
4063
|
+
// In Z-up coordinate system, horizontal segments have Z component near 0
|
|
4064
|
+
var zComponent = Math.abs(direction.z);
|
|
4065
|
+
var tolerance = 0.1; // ~5.7 degrees
|
|
4066
|
+
|
|
4067
|
+
return zComponent < tolerance;
|
|
4068
|
+
}
|
|
4069
|
+
|
|
3996
4070
|
/**
|
|
3997
4071
|
* Default object selection filter
|
|
3998
4072
|
* @param {THREE.Object3D} object - The object to check
|
|
@@ -4112,6 +4186,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4112
4186
|
this.selectedObjects.splice(index, 1);
|
|
4113
4187
|
console.log("\u2796 Removed from selection: ".concat(object.name || object.uuid));
|
|
4114
4188
|
} else {
|
|
4189
|
+
// Validate segment orientation compatibility before adding
|
|
4190
|
+
if (isSegment(object) && !this._canAddSegmentToSelection(object)) {
|
|
4191
|
+
console.warn('⚠️ Cannot mix horizontal and vertical segments in multi-selection');
|
|
4192
|
+
return;
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4115
4195
|
// Object is not selected, add it
|
|
4116
4196
|
this.selectedObjects.push(object);
|
|
4117
4197
|
console.log("\u2795 Added to selection: ".concat(object.name || object.uuid));
|
|
@@ -4768,11 +4848,11 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4768
4848
|
var objectFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
4769
4849
|
var objectsWithBounds = this.getSelectableObjectsWithBounds(objectFilter);
|
|
4770
4850
|
var intersections = [];
|
|
4771
|
-
var
|
|
4772
|
-
|
|
4851
|
+
var _iterator2 = _createForOfIteratorHelper(objectsWithBounds),
|
|
4852
|
+
_step2;
|
|
4773
4853
|
try {
|
|
4774
|
-
for (
|
|
4775
|
-
var item =
|
|
4854
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
4855
|
+
var item = _step2.value;
|
|
4776
4856
|
var object = item.object,
|
|
4777
4857
|
boundingBox = item.boundingBox;
|
|
4778
4858
|
|
|
@@ -4792,9 +4872,9 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4792
4872
|
|
|
4793
4873
|
// Sort by distance (closest first)
|
|
4794
4874
|
} catch (err) {
|
|
4795
|
-
|
|
4875
|
+
_iterator2.e(err);
|
|
4796
4876
|
} finally {
|
|
4797
|
-
|
|
4877
|
+
_iterator2.f();
|
|
4798
4878
|
}
|
|
4799
4879
|
intersections.sort(function (a, b) {
|
|
4800
4880
|
return a.distance - b.distance;
|
|
@@ -4896,35 +4976,20 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4896
4976
|
key: "applyMultiSelectionTransform",
|
|
4897
4977
|
value: (function () {
|
|
4898
4978
|
var _applyMultiSelectionTransform = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
4899
|
-
var
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
while (1) switch (_context4.n) {
|
|
4979
|
+
var _this$_calculateTrans, deltaX, deltaY, deltaZ, threshold, segments, gateways, components;
|
|
4980
|
+
return _regenerator().w(function (_context2) {
|
|
4981
|
+
while (1) switch (_context2.n) {
|
|
4903
4982
|
case 0:
|
|
4904
4983
|
if (!(!this.multiSelectionGroup || this.selectedObjects.length === 0)) {
|
|
4905
|
-
|
|
4984
|
+
_context2.n = 1;
|
|
4906
4985
|
break;
|
|
4907
4986
|
}
|
|
4908
|
-
return
|
|
4987
|
+
return _context2.a(2);
|
|
4909
4988
|
case 1:
|
|
4910
4989
|
console.log("\uD83D\uDD27 Applying multi-selection transform to ".concat(this.selectedObjects.length, " objects"));
|
|
4911
4990
|
|
|
4912
|
-
// Calculate
|
|
4913
|
-
|
|
4914
|
-
originalCentroid = new THREE__namespace.Vector3();
|
|
4915
|
-
this.selectedObjects.forEach(function (obj) {
|
|
4916
|
-
var originalWorldPos = obj.userData._multiSelectOriginalWorldPosition;
|
|
4917
|
-
if (originalWorldPos) {
|
|
4918
|
-
originalCentroid.add(originalWorldPos);
|
|
4919
|
-
}
|
|
4920
|
-
});
|
|
4921
|
-
originalCentroid.divideScalar(this.selectedObjects.length);
|
|
4922
|
-
|
|
4923
|
-
// Calculate position delta - this is the same for ALL objects
|
|
4924
|
-
positionDelta = groupPosition.clone().sub(originalCentroid); // Round deltas to avoid floating point precision issues
|
|
4925
|
-
deltaX = Math.round(positionDelta.x * 2) / 2;
|
|
4926
|
-
deltaY = Math.round(positionDelta.y * 2) / 2;
|
|
4927
|
-
deltaZ = Math.round(positionDelta.z * 2) / 2;
|
|
4991
|
+
// Calculate transformation deltas
|
|
4992
|
+
_this$_calculateTrans = this._calculateTransformDeltas(), deltaX = _this$_calculateTrans.deltaX, deltaY = _this$_calculateTrans.deltaY, deltaZ = _this$_calculateTrans.deltaZ, threshold = _this$_calculateTrans.threshold;
|
|
4928
4993
|
console.log('🔧 Transform delta:', {
|
|
4929
4994
|
deltaX: deltaX,
|
|
4930
4995
|
deltaY: deltaY,
|
|
@@ -4932,23 +4997,16 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4932
4997
|
});
|
|
4933
4998
|
|
|
4934
4999
|
// Only process if there's a meaningful translation
|
|
4935
|
-
threshold
|
|
4936
|
-
|
|
4937
|
-
_context4.n = 21;
|
|
5000
|
+
if (!(this.currentMode !== 'translate' || Math.abs(deltaX) < threshold && Math.abs(deltaY) < threshold && Math.abs(deltaZ) < threshold)) {
|
|
5001
|
+
_context2.n = 2;
|
|
4938
5002
|
break;
|
|
4939
5003
|
}
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
if (originalPos) {
|
|
4945
|
-
obj.position.copy(originalPos);
|
|
4946
|
-
obj.updateMatrixWorld(true);
|
|
4947
|
-
}
|
|
4948
|
-
});
|
|
4949
|
-
console.log('🔄 Reset objects to original positions before API calls');
|
|
5004
|
+
return _context2.a(2);
|
|
5005
|
+
case 2:
|
|
5006
|
+
// Reset all objects to original positions
|
|
5007
|
+
this._resetObjectsToOriginalPositions();
|
|
4950
5008
|
|
|
4951
|
-
// Separate
|
|
5009
|
+
// Separate objects by type
|
|
4952
5010
|
segments = this.selectedObjects.filter(function (obj) {
|
|
4953
5011
|
return isSegment(obj);
|
|
4954
5012
|
});
|
|
@@ -4957,433 +5015,462 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4957
5015
|
});
|
|
4958
5016
|
components = this.selectedObjects.filter(function (obj) {
|
|
4959
5017
|
return !isSegment(obj) && !isGateway(obj);
|
|
4960
|
-
}); //
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
5018
|
+
}); // Translate each object type
|
|
5019
|
+
_context2.n = 3;
|
|
5020
|
+
return this._translateSegments(segments, deltaX, deltaY, deltaZ, threshold);
|
|
5021
|
+
case 3:
|
|
5022
|
+
_context2.n = 4;
|
|
5023
|
+
return this._translateGateways(gateways, deltaX, deltaY, deltaZ, threshold);
|
|
5024
|
+
case 4:
|
|
5025
|
+
_context2.n = 5;
|
|
5026
|
+
return this._translateComponents(components, deltaX, deltaY, deltaZ, threshold);
|
|
5027
|
+
case 5:
|
|
5028
|
+
console.log("\u2705 All ".concat(this.selectedObjects.length, " objects translated"));
|
|
5029
|
+
|
|
5030
|
+
// Cleanup and refresh
|
|
5031
|
+
this._finalizeMultiSelectionTransform();
|
|
5032
|
+
case 6:
|
|
5033
|
+
return _context2.a(2);
|
|
5034
|
+
}
|
|
5035
|
+
}, _callee2, this);
|
|
5036
|
+
}));
|
|
5037
|
+
function applyMultiSelectionTransform() {
|
|
5038
|
+
return _applyMultiSelectionTransform.apply(this, arguments);
|
|
5039
|
+
}
|
|
5040
|
+
return applyMultiSelectionTransform;
|
|
5041
|
+
}()
|
|
5042
|
+
/**
|
|
5043
|
+
* Calculate transformation deltas from multi-selection group
|
|
5044
|
+
* @returns {Object} Delta values and threshold
|
|
5045
|
+
* @private
|
|
5046
|
+
*/
|
|
5047
|
+
)
|
|
5048
|
+
}, {
|
|
5049
|
+
key: "_calculateTransformDeltas",
|
|
5050
|
+
value: function _calculateTransformDeltas() {
|
|
5051
|
+
var groupPosition = this.multiSelectionGroup.position.clone();
|
|
5052
|
+
|
|
5053
|
+
// Get original centroid position
|
|
5054
|
+
var originalCentroid = new THREE__namespace.Vector3();
|
|
5055
|
+
this.selectedObjects.forEach(function (obj) {
|
|
5056
|
+
var originalWorldPos = obj.userData._multiSelectOriginalWorldPosition;
|
|
5057
|
+
if (originalWorldPos) {
|
|
5058
|
+
originalCentroid.add(originalWorldPos);
|
|
5059
|
+
}
|
|
5060
|
+
});
|
|
5061
|
+
originalCentroid.divideScalar(this.selectedObjects.length);
|
|
5062
|
+
|
|
5063
|
+
// Calculate and round deltas
|
|
5064
|
+
var positionDelta = groupPosition.clone().sub(originalCentroid);
|
|
5065
|
+
return {
|
|
5066
|
+
deltaX: Math.round(positionDelta.x * 2) / 2,
|
|
5067
|
+
deltaY: Math.round(positionDelta.y * 2) / 2,
|
|
5068
|
+
deltaZ: Math.round(positionDelta.z * 2) / 2,
|
|
5069
|
+
threshold: 0.001
|
|
5070
|
+
};
|
|
5071
|
+
}
|
|
5072
|
+
|
|
5073
|
+
/**
|
|
5074
|
+
* Reset all selected objects to their original positions
|
|
5075
|
+
* @private
|
|
5076
|
+
*/
|
|
5077
|
+
}, {
|
|
5078
|
+
key: "_resetObjectsToOriginalPositions",
|
|
5079
|
+
value: function _resetObjectsToOriginalPositions() {
|
|
5080
|
+
this.selectedObjects.forEach(function (obj) {
|
|
5081
|
+
var originalPos = obj.userData._multiSelectOriginalPosition;
|
|
5082
|
+
if (originalPos) {
|
|
5083
|
+
obj.position.copy(originalPos);
|
|
5084
|
+
obj.updateMatrixWorld(true);
|
|
5085
|
+
}
|
|
5086
|
+
});
|
|
5087
|
+
console.log('🔄 Reset objects to original positions before API calls');
|
|
5088
|
+
}
|
|
5089
|
+
|
|
5090
|
+
/**
|
|
5091
|
+
* Translate segments with batched path updates
|
|
5092
|
+
* @private
|
|
5093
|
+
*/
|
|
5094
|
+
}, {
|
|
5095
|
+
key: "_translateSegments",
|
|
5096
|
+
value: (function () {
|
|
5097
|
+
var _translateSegments2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(segments, deltaX, deltaY, deltaZ, threshold) {
|
|
5098
|
+
var _this$sceneViewer, _this$sceneViewer2;
|
|
5099
|
+
var transformOpsManager, useOptimizedPath, throttleDelay, AXIS_THROTTLE, OBJECT_DELAY, i, segment, axes, _i, _axes, _axes$_i, axis, delta;
|
|
5100
|
+
return _regenerator().w(function (_context3) {
|
|
5101
|
+
while (1) switch (_context3.n) {
|
|
5102
|
+
case 0:
|
|
5103
|
+
if (!(segments.length === 0)) {
|
|
5104
|
+
_context3.n = 1;
|
|
4973
5105
|
break;
|
|
4974
5106
|
}
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
5107
|
+
return _context3.a(2);
|
|
5108
|
+
case 1:
|
|
5109
|
+
transformOpsManager = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.transformOperationsManager;
|
|
5110
|
+
useOptimizedPath = transformOpsManager != null;
|
|
5111
|
+
if (useOptimizedPath) {
|
|
5112
|
+
console.log("\uD83D\uDD27 Batch translating ".concat(segments.length, " segments..."));
|
|
5113
|
+
} else {
|
|
5114
|
+
console.warn('⚠️ TransformOperationsManager not available, using fallback');
|
|
5115
|
+
}
|
|
5116
|
+
throttleDelay = function throttleDelay(ms) {
|
|
4981
5117
|
return new Promise(function (resolve) {
|
|
4982
5118
|
return setTimeout(resolve, ms);
|
|
4983
5119
|
});
|
|
4984
|
-
};
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
return _regenerator().w(function (_context2) {
|
|
4988
|
-
while (1) switch (_context2.n) {
|
|
4989
|
-
case 0:
|
|
4990
|
-
segment = segments[i]; // Call translateSegment API with skipPathUpdate=true to defer path updates
|
|
4991
|
-
// IMPORTANT: Refresh segment reference after each axis to handle UUID changes from manualization
|
|
4992
|
-
if (!(Math.abs(deltaX) > threshold)) {
|
|
4993
|
-
_context2.n = 1;
|
|
4994
|
-
break;
|
|
4995
|
-
}
|
|
4996
|
-
segmentId = segment.uuid || ((_segment$userData = segment.userData) === null || _segment$userData === void 0 ? void 0 : _segment$userData.originalUuid);
|
|
4997
|
-
success = transformOpsManager.translateSegment(segmentId, 'x', deltaX, true);
|
|
4998
|
-
if (!success) {
|
|
4999
|
-
console.warn("\u26A0\uFE0F Failed to translate segment ".concat(segmentId, " on X axis"));
|
|
5000
|
-
}
|
|
5001
|
-
// Refresh segment reference by searching for the new UUID or by segmentIndex
|
|
5002
|
-
// After manualization, UUID changes from SEGMENT-X to Segment-X
|
|
5003
|
-
newSegmentId = (_segment$userData2 = segment.userData) !== null && _segment$userData2 !== void 0 && _segment$userData2.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : segmentId;
|
|
5004
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', newSegmentId) || segment;
|
|
5005
|
-
|
|
5006
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5007
|
-
if (segment) {
|
|
5008
|
-
segment.updateMatrix();
|
|
5009
|
-
segment.updateMatrixWorld(true);
|
|
5010
|
-
}
|
|
5011
|
-
_context2.n = 1;
|
|
5012
|
-
return _throttleDelay(THROTTLE_DELAY);
|
|
5013
|
-
case 1:
|
|
5014
|
-
if (!(Math.abs(deltaY) > threshold)) {
|
|
5015
|
-
_context2.n = 2;
|
|
5016
|
-
break;
|
|
5017
|
-
}
|
|
5018
|
-
_segmentId = segment.uuid || ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.originalUuid);
|
|
5019
|
-
_success = transformOpsManager.translateSegment(_segmentId, 'y', deltaY, true);
|
|
5020
|
-
if (!_success) {
|
|
5021
|
-
console.warn("\u26A0\uFE0F Failed to translate segment ".concat(_segmentId, " on Y axis"));
|
|
5022
|
-
}
|
|
5023
|
-
// Refresh segment reference by searching for the new UUID
|
|
5024
|
-
_newSegmentId = (_segment$userData4 = segment.userData) !== null && _segment$userData4 !== void 0 && _segment$userData4.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId;
|
|
5025
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId) || segment;
|
|
5026
|
-
|
|
5027
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5028
|
-
if (segment) {
|
|
5029
|
-
segment.updateMatrix();
|
|
5030
|
-
segment.updateMatrixWorld(true);
|
|
5031
|
-
}
|
|
5032
|
-
_context2.n = 2;
|
|
5033
|
-
return _throttleDelay(THROTTLE_DELAY);
|
|
5034
|
-
case 2:
|
|
5035
|
-
if (!(Math.abs(deltaZ) > threshold)) {
|
|
5036
|
-
_context2.n = 3;
|
|
5037
|
-
break;
|
|
5038
|
-
}
|
|
5039
|
-
_segmentId2 = segment.uuid || ((_segment$userData5 = segment.userData) === null || _segment$userData5 === void 0 ? void 0 : _segment$userData5.originalUuid);
|
|
5040
|
-
_success2 = transformOpsManager.translateSegment(_segmentId2, 'z', deltaZ, true);
|
|
5041
|
-
if (!_success2) {
|
|
5042
|
-
console.warn("\u26A0\uFE0F Failed to translate segment ".concat(_segmentId2, " on Z axis"));
|
|
5043
|
-
}
|
|
5044
|
-
// Refresh segment reference by searching for the new UUID
|
|
5045
|
-
_newSegmentId2 = (_segment$userData6 = segment.userData) !== null && _segment$userData6 !== void 0 && _segment$userData6.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId2;
|
|
5046
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId2) || segment;
|
|
5047
|
-
|
|
5048
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5049
|
-
if (segment) {
|
|
5050
|
-
segment.updateMatrix();
|
|
5051
|
-
segment.updateMatrixWorld(true);
|
|
5052
|
-
}
|
|
5053
|
-
_context2.n = 3;
|
|
5054
|
-
return _throttleDelay(THROTTLE_DELAY);
|
|
5055
|
-
case 3:
|
|
5056
|
-
// Update the segment in the selectedObjects array with the refreshed reference
|
|
5057
|
-
// This ensures transform controls and multi-selection display use the current object
|
|
5058
|
-
selectedIndex = _this9.selectedObjects.findIndex(function (obj) {
|
|
5059
|
-
var _obj$userData;
|
|
5060
|
-
return obj.uuid === segments[i].uuid || ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.originalUuid) === segments[i].uuid;
|
|
5061
|
-
});
|
|
5062
|
-
if (selectedIndex !== -1 && segment) {
|
|
5063
|
-
// Clear bounding box cache for both old and new segment references
|
|
5064
|
-
if (_this9.boundingBoxCache.has(segments[i])) {
|
|
5065
|
-
_this9.boundingBoxCache.delete(segments[i]);
|
|
5066
|
-
}
|
|
5067
|
-
if (_this9.boundingBoxCache.has(segment)) {
|
|
5068
|
-
_this9.boundingBoxCache.delete(segment);
|
|
5069
|
-
}
|
|
5070
|
-
_this9.selectedObjects[selectedIndex] = segment;
|
|
5071
|
-
console.log("\u2705 Updated selectedObjects[".concat(selectedIndex, "] with refreshed segment reference"));
|
|
5072
|
-
}
|
|
5073
|
-
if (segment) {
|
|
5074
|
-
console.log("\uD83D\uDCE6 Segment ".concat(segment.name, " translated (").concat(i + 1, "/").concat(segments.length, "):"), {
|
|
5075
|
-
deltaX: deltaX,
|
|
5076
|
-
deltaY: deltaY,
|
|
5077
|
-
deltaZ: deltaZ
|
|
5078
|
-
});
|
|
5079
|
-
} else {
|
|
5080
|
-
console.warn("\u26A0\uFE0F Segment reference became null after translation (".concat(i + 1, "/").concat(segments.length, ")"));
|
|
5081
|
-
}
|
|
5082
|
-
|
|
5083
|
-
// Delay between segments to ensure all updates propagate
|
|
5084
|
-
if (!(i < segments.length - 1)) {
|
|
5085
|
-
_context2.n = 4;
|
|
5086
|
-
break;
|
|
5087
|
-
}
|
|
5088
|
-
_context2.n = 4;
|
|
5089
|
-
return _throttleDelay(SEGMENT_DELAY);
|
|
5090
|
-
case 4:
|
|
5091
|
-
return _context2.a(2);
|
|
5092
|
-
}
|
|
5093
|
-
}, _loop);
|
|
5094
|
-
});
|
|
5120
|
+
};
|
|
5121
|
+
AXIS_THROTTLE = 10;
|
|
5122
|
+
OBJECT_DELAY = 20;
|
|
5095
5123
|
i = 0;
|
|
5096
5124
|
case 2:
|
|
5097
5125
|
if (!(i < segments.length)) {
|
|
5098
|
-
|
|
5126
|
+
_context3.n = 8;
|
|
5099
5127
|
break;
|
|
5100
5128
|
}
|
|
5101
|
-
|
|
5129
|
+
segment = segments[i];
|
|
5130
|
+
axes = [{
|
|
5131
|
+
axis: 'x',
|
|
5132
|
+
delta: deltaX
|
|
5133
|
+
}, {
|
|
5134
|
+
axis: 'y',
|
|
5135
|
+
delta: deltaY
|
|
5136
|
+
}, {
|
|
5137
|
+
axis: 'z',
|
|
5138
|
+
delta: deltaZ
|
|
5139
|
+
}]; // Translate on each axis
|
|
5140
|
+
_i = 0, _axes = axes;
|
|
5102
5141
|
case 3:
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
case 4:
|
|
5107
|
-
// Only call updatePaths ONCE after all segments are translated
|
|
5108
|
-
console.log('🔄 Calling updatePaths once for all segments...');
|
|
5109
|
-
if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
|
|
5110
|
-
this.sceneViewer.updatePaths();
|
|
5111
|
-
console.log('✅ Paths regenerated successfully for all segments');
|
|
5142
|
+
if (!(_i < _axes.length)) {
|
|
5143
|
+
_context3.n = 6;
|
|
5144
|
+
break;
|
|
5112
5145
|
}
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
if (!(segments.length > 0)) {
|
|
5117
|
-
_context4.n = 8;
|
|
5146
|
+
_axes$_i = _axes[_i], axis = _axes$_i.axis, delta = _axes$_i.delta;
|
|
5147
|
+
if (!(Math.abs(delta) > threshold)) {
|
|
5148
|
+
_context3.n = 5;
|
|
5118
5149
|
break;
|
|
5119
5150
|
}
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
});
|
|
5131
|
-
};
|
|
5132
|
-
_loop2 = /*#__PURE__*/_regenerator().m(function _loop2(_i) {
|
|
5133
|
-
var segment, _segment$userData7, _segment$userData8, segmentId, newSegmentId, _segment$userData9, _segment$userData0, _segmentId3, _newSegmentId3, _segment$userData1, _segment$userData10, _segmentId4, _newSegmentId4, selectedIndex;
|
|
5134
|
-
return _regenerator().w(function (_context3) {
|
|
5135
|
-
while (1) switch (_context3.n) {
|
|
5136
|
-
case 0:
|
|
5137
|
-
segment = segments[_i];
|
|
5138
|
-
if (!(Math.abs(deltaX) > threshold)) {
|
|
5139
|
-
_context3.n = 1;
|
|
5140
|
-
break;
|
|
5141
|
-
}
|
|
5142
|
-
segmentId = segment.uuid || ((_segment$userData7 = segment.userData) === null || _segment$userData7 === void 0 ? void 0 : _segment$userData7.originalUuid);
|
|
5143
|
-
_this9.centralPlant.translateSegment(segmentId, 'x', deltaX);
|
|
5144
|
-
// Refresh segment reference by searching for the new UUID after manualization
|
|
5145
|
-
newSegmentId = (_segment$userData8 = segment.userData) !== null && _segment$userData8 !== void 0 && _segment$userData8.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : segmentId;
|
|
5146
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', newSegmentId) || segment;
|
|
5147
|
-
|
|
5148
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5149
|
-
if (segment) {
|
|
5150
|
-
segment.updateMatrix();
|
|
5151
|
-
segment.updateMatrixWorld(true);
|
|
5152
|
-
}
|
|
5153
|
-
_context3.n = 1;
|
|
5154
|
-
return _throttleDelay2(_THROTTLE_DELAY);
|
|
5155
|
-
case 1:
|
|
5156
|
-
if (!(Math.abs(deltaY) > threshold)) {
|
|
5157
|
-
_context3.n = 2;
|
|
5158
|
-
break;
|
|
5159
|
-
}
|
|
5160
|
-
_segmentId3 = segment.uuid || ((_segment$userData9 = segment.userData) === null || _segment$userData9 === void 0 ? void 0 : _segment$userData9.originalUuid);
|
|
5161
|
-
_this9.centralPlant.translateSegment(_segmentId3, 'y', deltaY);
|
|
5162
|
-
// Refresh segment reference by searching for the new UUID after manualization
|
|
5163
|
-
_newSegmentId3 = (_segment$userData0 = segment.userData) !== null && _segment$userData0 !== void 0 && _segment$userData0.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId3;
|
|
5164
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId3) || segment;
|
|
5165
|
-
|
|
5166
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5167
|
-
if (segment) {
|
|
5168
|
-
segment.updateMatrix();
|
|
5169
|
-
segment.updateMatrixWorld(true);
|
|
5170
|
-
}
|
|
5171
|
-
_context3.n = 2;
|
|
5172
|
-
return _throttleDelay2(_THROTTLE_DELAY);
|
|
5173
|
-
case 2:
|
|
5174
|
-
if (!(Math.abs(deltaZ) > threshold)) {
|
|
5175
|
-
_context3.n = 3;
|
|
5176
|
-
break;
|
|
5177
|
-
}
|
|
5178
|
-
_segmentId4 = segment.uuid || ((_segment$userData1 = segment.userData) === null || _segment$userData1 === void 0 ? void 0 : _segment$userData1.originalUuid);
|
|
5179
|
-
_this9.centralPlant.translateSegment(_segmentId4, 'z', deltaZ);
|
|
5180
|
-
// Refresh segment reference by searching for the new UUID after manualization
|
|
5181
|
-
_newSegmentId4 = (_segment$userData10 = segment.userData) !== null && _segment$userData10 !== void 0 && _segment$userData10.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : _segmentId4;
|
|
5182
|
-
segment = _this9.sceneViewer.scene.getObjectByProperty('uuid', _newSegmentId4) || segment;
|
|
5183
|
-
|
|
5184
|
-
// Update matrix to ensure geometry is current for next operation
|
|
5185
|
-
if (segment) {
|
|
5186
|
-
segment.updateMatrix();
|
|
5187
|
-
segment.updateMatrixWorld(true);
|
|
5188
|
-
}
|
|
5189
|
-
_context3.n = 3;
|
|
5190
|
-
return _throttleDelay2(_THROTTLE_DELAY);
|
|
5191
|
-
case 3:
|
|
5192
|
-
// Update the segment in the selectedObjects array with the refreshed reference
|
|
5193
|
-
selectedIndex = _this9.selectedObjects.findIndex(function (obj) {
|
|
5194
|
-
var _obj$userData2;
|
|
5195
|
-
return obj.uuid === segments[_i].uuid || ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.originalUuid) === segments[_i].uuid;
|
|
5196
|
-
});
|
|
5197
|
-
if (selectedIndex !== -1 && segment) {
|
|
5198
|
-
// Clear bounding box cache for both old and new segment references
|
|
5199
|
-
if (_this9.boundingBoxCache.has(segments[_i])) {
|
|
5200
|
-
_this9.boundingBoxCache.delete(segments[_i]);
|
|
5201
|
-
}
|
|
5202
|
-
if (_this9.boundingBoxCache.has(segment)) {
|
|
5203
|
-
_this9.boundingBoxCache.delete(segment);
|
|
5204
|
-
}
|
|
5205
|
-
_this9.selectedObjects[selectedIndex] = segment;
|
|
5206
|
-
console.log("\u2705 Updated selectedObjects[".concat(selectedIndex, "] with refreshed segment reference"));
|
|
5207
|
-
}
|
|
5208
|
-
if (segment) {
|
|
5209
|
-
console.log("\uD83D\uDCE6 Segment ".concat(segment.name, " translated (").concat(_i + 1, "/").concat(segments.length, "):"), {
|
|
5210
|
-
deltaX: deltaX,
|
|
5211
|
-
deltaY: deltaY,
|
|
5212
|
-
deltaZ: deltaZ
|
|
5213
|
-
});
|
|
5214
|
-
} else {
|
|
5215
|
-
console.warn("\u26A0\uFE0F Segment reference became null after translation (".concat(_i + 1, "/").concat(segments.length, ")"));
|
|
5216
|
-
}
|
|
5217
|
-
|
|
5218
|
-
// Delay between segments
|
|
5219
|
-
if (!(_i < segments.length - 1)) {
|
|
5220
|
-
_context3.n = 4;
|
|
5221
|
-
break;
|
|
5222
|
-
}
|
|
5223
|
-
_context3.n = 4;
|
|
5224
|
-
return _throttleDelay2(_SEGMENT_DELAY);
|
|
5225
|
-
case 4:
|
|
5226
|
-
return _context3.a(2);
|
|
5227
|
-
}
|
|
5228
|
-
}, _loop2);
|
|
5229
|
-
});
|
|
5230
|
-
_i = 0;
|
|
5151
|
+
_context3.n = 4;
|
|
5152
|
+
return this._translateSegmentOnAxis(segment, axis, delta, useOptimizedPath, i);
|
|
5153
|
+
case 4:
|
|
5154
|
+
segment = _context3.v;
|
|
5155
|
+
_context3.n = 5;
|
|
5156
|
+
return throttleDelay(AXIS_THROTTLE);
|
|
5157
|
+
case 5:
|
|
5158
|
+
_i++;
|
|
5159
|
+
_context3.n = 3;
|
|
5160
|
+
break;
|
|
5231
5161
|
case 6:
|
|
5232
|
-
|
|
5233
|
-
|
|
5162
|
+
// Update selected objects array with refreshed reference
|
|
5163
|
+
this._updateSegmentReference(segments[i], segment, i);
|
|
5164
|
+
if (segment) {
|
|
5165
|
+
console.log("\uD83D\uDCE6 Segment ".concat(segment.name, " translated (").concat(i + 1, "/").concat(segments.length, ")"));
|
|
5166
|
+
} else {
|
|
5167
|
+
console.warn("\u26A0\uFE0F Segment reference became null (".concat(i + 1, "/").concat(segments.length, ")"));
|
|
5168
|
+
}
|
|
5169
|
+
if (!(i < segments.length - 1)) {
|
|
5170
|
+
_context3.n = 7;
|
|
5234
5171
|
break;
|
|
5235
5172
|
}
|
|
5236
|
-
|
|
5173
|
+
_context3.n = 7;
|
|
5174
|
+
return throttleDelay(OBJECT_DELAY);
|
|
5237
5175
|
case 7:
|
|
5238
|
-
|
|
5239
|
-
|
|
5176
|
+
i++;
|
|
5177
|
+
_context3.n = 2;
|
|
5240
5178
|
break;
|
|
5241
5179
|
case 8:
|
|
5242
|
-
//
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5180
|
+
// Batch update paths for optimized path only
|
|
5181
|
+
if (useOptimizedPath && (_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.updatePaths) {
|
|
5182
|
+
console.log('🔄 Calling updatePaths once for all segments...');
|
|
5183
|
+
this.sceneViewer.updatePaths();
|
|
5184
|
+
console.log('✅ Paths regenerated successfully');
|
|
5185
|
+
}
|
|
5186
|
+
case 9:
|
|
5187
|
+
return _context3.a(2);
|
|
5188
|
+
}
|
|
5189
|
+
}, _callee3, this);
|
|
5190
|
+
}));
|
|
5191
|
+
function _translateSegments(_x, _x2, _x3, _x4, _x5) {
|
|
5192
|
+
return _translateSegments2.apply(this, arguments);
|
|
5193
|
+
}
|
|
5194
|
+
return _translateSegments;
|
|
5195
|
+
}()
|
|
5196
|
+
/**
|
|
5197
|
+
* Refresh segment reference after manualization
|
|
5198
|
+
* Handles the UUID change from original format to SEGMENT-{index} format
|
|
5199
|
+
* @param {THREE.Object3D} segment - Original segment object
|
|
5200
|
+
* @returns {THREE.Object3D|null} Refreshed segment reference or null if not found
|
|
5201
|
+
* @private
|
|
5202
|
+
*/
|
|
5203
|
+
)
|
|
5204
|
+
}, {
|
|
5205
|
+
key: "_refreshSegmentReference",
|
|
5206
|
+
value: function _refreshSegmentReference(segment) {
|
|
5207
|
+
var _segment$userData, _segment$userData2;
|
|
5208
|
+
if (!segment) return null;
|
|
5209
|
+
var segmentId = segment.uuid || ((_segment$userData = segment.userData) === null || _segment$userData === void 0 ? void 0 : _segment$userData.originalUuid);
|
|
5210
|
+
|
|
5211
|
+
// Try to find by new UUID format (SEGMENT-{index})
|
|
5212
|
+
var newSegmentId = (_segment$userData2 = segment.userData) !== null && _segment$userData2 !== void 0 && _segment$userData2.segmentIndex ? "SEGMENT-".concat(segment.userData.segmentIndex) : segmentId;
|
|
5213
|
+
var refreshedSegment = this.sceneViewer.scene.getObjectByProperty('uuid', newSegmentId) || segment;
|
|
5214
|
+
if (refreshedSegment) {
|
|
5215
|
+
refreshedSegment.updateMatrix();
|
|
5216
|
+
refreshedSegment.updateMatrixWorld(true);
|
|
5217
|
+
}
|
|
5218
|
+
return refreshedSegment;
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
/**
|
|
5222
|
+
* Translate a segment on a single axis and refresh its reference
|
|
5223
|
+
* @private
|
|
5224
|
+
*/
|
|
5225
|
+
}, {
|
|
5226
|
+
key: "_translateSegmentOnAxis",
|
|
5227
|
+
value: (function () {
|
|
5228
|
+
var _translateSegmentOnAxis2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(segment, axis, delta, useOptimizedPath, index) {
|
|
5229
|
+
var _segment$userData3;
|
|
5230
|
+
var segmentId, success;
|
|
5231
|
+
return _regenerator().w(function (_context4) {
|
|
5232
|
+
while (1) switch (_context4.n) {
|
|
5233
|
+
case 0:
|
|
5234
|
+
segmentId = segment.uuid || ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.originalUuid);
|
|
5235
|
+
if (useOptimizedPath) {
|
|
5236
|
+
success = this.sceneViewer.transformOperationsManager.translateSegment(segmentId, axis, delta, true);
|
|
5237
|
+
if (!success) {
|
|
5238
|
+
console.warn("\u26A0\uFE0F Failed to translate segment ".concat(segmentId, " on ").concat(axis, " axis"));
|
|
5239
|
+
}
|
|
5240
|
+
} else {
|
|
5241
|
+
this.centralPlant.translateSegment(segmentId, axis, delta);
|
|
5242
|
+
}
|
|
5243
|
+
|
|
5244
|
+
// Refresh segment reference after manualization
|
|
5245
|
+
return _context4.a(2, this._refreshSegmentReference(segment));
|
|
5246
|
+
}
|
|
5247
|
+
}, _callee4, this);
|
|
5248
|
+
}));
|
|
5249
|
+
function _translateSegmentOnAxis(_x6, _x7, _x8, _x9, _x0) {
|
|
5250
|
+
return _translateSegmentOnAxis2.apply(this, arguments);
|
|
5251
|
+
}
|
|
5252
|
+
return _translateSegmentOnAxis;
|
|
5253
|
+
}()
|
|
5254
|
+
/**
|
|
5255
|
+
* Update segment reference in selectedObjects array and clear cache
|
|
5256
|
+
* @private
|
|
5257
|
+
*/
|
|
5258
|
+
)
|
|
5259
|
+
}, {
|
|
5260
|
+
key: "_updateSegmentReference",
|
|
5261
|
+
value: function _updateSegmentReference(oldSegment, newSegment, index) {
|
|
5262
|
+
var selectedIndex = this.selectedObjects.findIndex(function (obj) {
|
|
5263
|
+
var _obj$userData;
|
|
5264
|
+
return obj.uuid === oldSegment.uuid || ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.originalUuid) === oldSegment.uuid;
|
|
5265
|
+
});
|
|
5266
|
+
if (selectedIndex !== -1 && newSegment) {
|
|
5267
|
+
// Clear bounding box cache
|
|
5268
|
+
this.boundingBoxCache.delete(oldSegment);
|
|
5269
|
+
this.boundingBoxCache.delete(newSegment);
|
|
5270
|
+
this.selectedObjects[selectedIndex] = newSegment;
|
|
5271
|
+
console.log("\u2705 Updated selectedObjects[".concat(selectedIndex, "] with refreshed reference"));
|
|
5272
|
+
}
|
|
5273
|
+
}
|
|
5274
|
+
|
|
5275
|
+
/**
|
|
5276
|
+
* Translate gateways on all axes
|
|
5277
|
+
* @private
|
|
5278
|
+
*/
|
|
5279
|
+
}, {
|
|
5280
|
+
key: "_translateGateways",
|
|
5281
|
+
value: (function () {
|
|
5282
|
+
var _translateGateways2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(gateways, deltaX, deltaY, deltaZ, threshold) {
|
|
5283
|
+
var _this9 = this;
|
|
5284
|
+
var throttleDelay, AXIS_THROTTLE, OBJECT_DELAY, i, _gateway$userData, gateway, gatewayId;
|
|
5285
|
+
return _regenerator().w(function (_context5) {
|
|
5286
|
+
while (1) switch (_context5.n) {
|
|
5287
|
+
case 0:
|
|
5288
|
+
if (!(gateways.length === 0)) {
|
|
5289
|
+
_context5.n = 1;
|
|
5290
|
+
break;
|
|
5291
|
+
}
|
|
5292
|
+
return _context5.a(2);
|
|
5293
|
+
case 1:
|
|
5247
5294
|
throttleDelay = function throttleDelay(ms) {
|
|
5248
5295
|
return new Promise(function (resolve) {
|
|
5249
5296
|
return setTimeout(resolve, ms);
|
|
5250
5297
|
});
|
|
5251
|
-
};
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5298
|
+
};
|
|
5299
|
+
AXIS_THROTTLE = 10;
|
|
5300
|
+
OBJECT_DELAY = 15;
|
|
5301
|
+
i = 0;
|
|
5302
|
+
case 2:
|
|
5303
|
+
if (!(i < gateways.length)) {
|
|
5304
|
+
_context5.n = 5;
|
|
5256
5305
|
break;
|
|
5257
5306
|
}
|
|
5258
|
-
gateway = gateways[
|
|
5307
|
+
gateway = gateways[i];
|
|
5259
5308
|
gatewayId = gateway.uuid || ((_gateway$userData = gateway.userData) === null || _gateway$userData === void 0 ? void 0 : _gateway$userData.originalUuid);
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
}
|
|
5264
|
-
this.centralPlant.translateGateway(gatewayId, 'x', deltaX);
|
|
5265
|
-
_context4.n = 10;
|
|
5266
|
-
return throttleDelay(GATEWAY_THROTTLE);
|
|
5267
|
-
case 10:
|
|
5268
|
-
if (!(Math.abs(deltaY) > threshold)) {
|
|
5269
|
-
_context4.n = 11;
|
|
5270
|
-
break;
|
|
5271
|
-
}
|
|
5272
|
-
this.centralPlant.translateGateway(gatewayId, 'y', deltaY);
|
|
5273
|
-
_context4.n = 11;
|
|
5274
|
-
return throttleDelay(GATEWAY_THROTTLE);
|
|
5275
|
-
case 11:
|
|
5276
|
-
if (!(Math.abs(deltaZ) > threshold)) {
|
|
5277
|
-
_context4.n = 12;
|
|
5278
|
-
break;
|
|
5279
|
-
}
|
|
5280
|
-
this.centralPlant.translateGateway(gatewayId, 'z', deltaZ);
|
|
5281
|
-
_context4.n = 12;
|
|
5282
|
-
return throttleDelay(GATEWAY_THROTTLE);
|
|
5283
|
-
case 12:
|
|
5284
|
-
console.log("\uD83D\uDEAA Gateway ".concat(gateway.name, " translated (").concat(_i2 + 1, "/").concat(gateways.length, "):"), {
|
|
5285
|
-
deltaX: deltaX,
|
|
5286
|
-
deltaY: deltaY,
|
|
5287
|
-
deltaZ: deltaZ
|
|
5309
|
+
_context5.n = 3;
|
|
5310
|
+
return this._translateObjectOnAxes(gatewayId, deltaX, deltaY, deltaZ, threshold, throttleDelay, AXIS_THROTTLE, function (id, axis, delta) {
|
|
5311
|
+
return _this9.centralPlant.translateGateway(id, axis, delta);
|
|
5288
5312
|
});
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
if (!(
|
|
5292
|
-
|
|
5313
|
+
case 3:
|
|
5314
|
+
console.log("\uD83D\uDEAA Gateway ".concat(gateway.name, " translated (").concat(i + 1, "/").concat(gateways.length, ")"));
|
|
5315
|
+
if (!(i < gateways.length - 1)) {
|
|
5316
|
+
_context5.n = 4;
|
|
5293
5317
|
break;
|
|
5294
5318
|
}
|
|
5295
|
-
|
|
5296
|
-
return throttleDelay(
|
|
5297
|
-
case
|
|
5298
|
-
|
|
5299
|
-
|
|
5319
|
+
_context5.n = 4;
|
|
5320
|
+
return throttleDelay(OBJECT_DELAY);
|
|
5321
|
+
case 4:
|
|
5322
|
+
i++;
|
|
5323
|
+
_context5.n = 2;
|
|
5300
5324
|
break;
|
|
5301
|
-
case
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5325
|
+
case 5:
|
|
5326
|
+
return _context5.a(2);
|
|
5327
|
+
}
|
|
5328
|
+
}, _callee5, this);
|
|
5329
|
+
}));
|
|
5330
|
+
function _translateGateways(_x1, _x10, _x11, _x12, _x13) {
|
|
5331
|
+
return _translateGateways2.apply(this, arguments);
|
|
5332
|
+
}
|
|
5333
|
+
return _translateGateways;
|
|
5334
|
+
}()
|
|
5335
|
+
/**
|
|
5336
|
+
* Translate components on all axes
|
|
5337
|
+
* @private
|
|
5338
|
+
*/
|
|
5339
|
+
)
|
|
5340
|
+
}, {
|
|
5341
|
+
key: "_translateComponents",
|
|
5342
|
+
value: (function () {
|
|
5343
|
+
var _translateComponents2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(components, deltaX, deltaY, deltaZ, threshold) {
|
|
5344
|
+
var _this0 = this;
|
|
5345
|
+
var throttleDelay, AXIS_THROTTLE, OBJECT_DELAY, i, _component$userData, component, componentId;
|
|
5346
|
+
return _regenerator().w(function (_context6) {
|
|
5347
|
+
while (1) switch (_context6.n) {
|
|
5348
|
+
case 0:
|
|
5349
|
+
if (!(components.length === 0)) {
|
|
5350
|
+
_context6.n = 1;
|
|
5320
5351
|
break;
|
|
5321
5352
|
}
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5353
|
+
return _context6.a(2);
|
|
5354
|
+
case 1:
|
|
5355
|
+
throttleDelay = function throttleDelay(ms) {
|
|
5356
|
+
return new Promise(function (resolve) {
|
|
5357
|
+
return setTimeout(resolve, ms);
|
|
5358
|
+
});
|
|
5359
|
+
};
|
|
5360
|
+
AXIS_THROTTLE = 10;
|
|
5361
|
+
OBJECT_DELAY = 15;
|
|
5362
|
+
i = 0;
|
|
5363
|
+
case 2:
|
|
5364
|
+
if (!(i < components.length)) {
|
|
5365
|
+
_context6.n = 5;
|
|
5328
5366
|
break;
|
|
5329
5367
|
}
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
deltaX: deltaX,
|
|
5336
|
-
deltaY: deltaY,
|
|
5337
|
-
deltaZ: deltaZ
|
|
5368
|
+
component = components[i];
|
|
5369
|
+
componentId = component.uuid || ((_component$userData = component.userData) === null || _component$userData === void 0 ? void 0 : _component$userData.originalUuid);
|
|
5370
|
+
_context6.n = 3;
|
|
5371
|
+
return this._translateObjectOnAxes(componentId, deltaX, deltaY, deltaZ, threshold, throttleDelay, AXIS_THROTTLE, function (id, axis, delta) {
|
|
5372
|
+
return _this0.centralPlant.translate(id, axis, delta);
|
|
5338
5373
|
});
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
if (!(
|
|
5342
|
-
|
|
5374
|
+
case 3:
|
|
5375
|
+
console.log("\uD83D\uDD27 Component ".concat(component.name, " translated (").concat(i + 1, "/").concat(components.length, ")"));
|
|
5376
|
+
if (!(i < components.length - 1)) {
|
|
5377
|
+
_context6.n = 4;
|
|
5343
5378
|
break;
|
|
5344
5379
|
}
|
|
5345
|
-
|
|
5346
|
-
return throttleDelay(
|
|
5347
|
-
case
|
|
5348
|
-
|
|
5349
|
-
|
|
5380
|
+
_context6.n = 4;
|
|
5381
|
+
return throttleDelay(OBJECT_DELAY);
|
|
5382
|
+
case 4:
|
|
5383
|
+
i++;
|
|
5384
|
+
_context6.n = 2;
|
|
5350
5385
|
break;
|
|
5351
|
-
case
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5386
|
+
case 5:
|
|
5387
|
+
return _context6.a(2);
|
|
5388
|
+
}
|
|
5389
|
+
}, _callee6, this);
|
|
5390
|
+
}));
|
|
5391
|
+
function _translateComponents(_x14, _x15, _x16, _x17, _x18) {
|
|
5392
|
+
return _translateComponents2.apply(this, arguments);
|
|
5393
|
+
}
|
|
5394
|
+
return _translateComponents;
|
|
5395
|
+
}()
|
|
5396
|
+
/**
|
|
5397
|
+
* Generic method to translate object on all axes with throttling
|
|
5398
|
+
* @private
|
|
5399
|
+
*/
|
|
5400
|
+
)
|
|
5401
|
+
}, {
|
|
5402
|
+
key: "_translateObjectOnAxes",
|
|
5403
|
+
value: (function () {
|
|
5404
|
+
var _translateObjectOnAxes2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(objectId, deltaX, deltaY, deltaZ, threshold, throttleDelay, axisThrottle, translateFn) {
|
|
5405
|
+
var axes, _i2, _axes2, _axes2$_i, axis, delta;
|
|
5406
|
+
return _regenerator().w(function (_context7) {
|
|
5407
|
+
while (1) switch (_context7.n) {
|
|
5408
|
+
case 0:
|
|
5409
|
+
axes = [{
|
|
5410
|
+
axis: 'x',
|
|
5411
|
+
delta: deltaX
|
|
5412
|
+
}, {
|
|
5413
|
+
axis: 'y',
|
|
5414
|
+
delta: deltaY
|
|
5415
|
+
}, {
|
|
5416
|
+
axis: 'z',
|
|
5417
|
+
delta: deltaZ
|
|
5418
|
+
}];
|
|
5419
|
+
_i2 = 0, _axes2 = axes;
|
|
5420
|
+
case 1:
|
|
5421
|
+
if (!(_i2 < _axes2.length)) {
|
|
5422
|
+
_context7.n = 3;
|
|
5423
|
+
break;
|
|
5366
5424
|
}
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
// Update the multi-selection display with new positions (only if we still have selected objects)
|
|
5373
|
-
if (this.selectedObjects.length > 0) {
|
|
5374
|
-
this.updateMultiSelection();
|
|
5425
|
+
_axes2$_i = _axes2[_i2], axis = _axes2$_i.axis, delta = _axes2$_i.delta;
|
|
5426
|
+
if (!(Math.abs(delta) > threshold)) {
|
|
5427
|
+
_context7.n = 2;
|
|
5428
|
+
break;
|
|
5375
5429
|
}
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
return
|
|
5430
|
+
translateFn(objectId, axis, delta);
|
|
5431
|
+
_context7.n = 2;
|
|
5432
|
+
return throttleDelay(axisThrottle);
|
|
5433
|
+
case 2:
|
|
5434
|
+
_i2++;
|
|
5435
|
+
_context7.n = 1;
|
|
5436
|
+
break;
|
|
5437
|
+
case 3:
|
|
5438
|
+
return _context7.a(2);
|
|
5379
5439
|
}
|
|
5380
|
-
},
|
|
5440
|
+
}, _callee7);
|
|
5381
5441
|
}));
|
|
5382
|
-
function
|
|
5383
|
-
return
|
|
5442
|
+
function _translateObjectOnAxes(_x19, _x20, _x21, _x22, _x23, _x24, _x25, _x26) {
|
|
5443
|
+
return _translateObjectOnAxes2.apply(this, arguments);
|
|
5384
5444
|
}
|
|
5385
|
-
return
|
|
5445
|
+
return _translateObjectOnAxes;
|
|
5386
5446
|
}()
|
|
5447
|
+
/**
|
|
5448
|
+
* Finalize multi-selection transform by resetting group and updating display
|
|
5449
|
+
* @private
|
|
5450
|
+
*/
|
|
5451
|
+
)
|
|
5452
|
+
}, {
|
|
5453
|
+
key: "_finalizeMultiSelectionTransform",
|
|
5454
|
+
value: function _finalizeMultiSelectionTransform() {
|
|
5455
|
+
// Reset multi-selection group transform
|
|
5456
|
+
if (this.multiSelectionGroup) {
|
|
5457
|
+
this.multiSelectionGroup.position.set(0, 0, 0);
|
|
5458
|
+
this.multiSelectionGroup.rotation.set(0, 0, 0);
|
|
5459
|
+
this.multiSelectionGroup.scale.set(1, 1, 1);
|
|
5460
|
+
} else {
|
|
5461
|
+
console.warn('⚠️ Multi-selection group was cleared during transformation');
|
|
5462
|
+
}
|
|
5463
|
+
|
|
5464
|
+
// Clear bounding box cache after manualization
|
|
5465
|
+
this.clearBoundingBoxCache();
|
|
5466
|
+
|
|
5467
|
+
// Update multi-selection display
|
|
5468
|
+
if (this.selectedObjects.length > 0) {
|
|
5469
|
+
this.updateMultiSelection();
|
|
5470
|
+
}
|
|
5471
|
+
console.log("\u2705 Multi-selection transform applied");
|
|
5472
|
+
}
|
|
5473
|
+
|
|
5387
5474
|
/**
|
|
5388
5475
|
* Handle transformation of a pipe segment using the centralPlant translateSegment API
|
|
5389
5476
|
*
|
|
@@ -5393,11 +5480,10 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5393
5480
|
*
|
|
5394
5481
|
* @param {THREE.Object3D} segment - The transformed pipe segment
|
|
5395
5482
|
*/
|
|
5396
|
-
)
|
|
5397
5483
|
}, {
|
|
5398
5484
|
key: "handlePipeSegmentTransform",
|
|
5399
5485
|
value: function handlePipeSegmentTransform(segment) {
|
|
5400
|
-
var _this$transformState, _this$transformState2, _segment$
|
|
5486
|
+
var _this$transformState, _this$transformState2, _segment$userData4;
|
|
5401
5487
|
console.log('🔧 Pipe segment transformed:', segment.name);
|
|
5402
5488
|
|
|
5403
5489
|
// Safety checks
|
|
@@ -5434,7 +5520,7 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5434
5520
|
});
|
|
5435
5521
|
|
|
5436
5522
|
// Get the segment ID (try both uuid and originalUuid)
|
|
5437
|
-
var segmentId = segment.uuid || ((_segment$
|
|
5523
|
+
var segmentId = segment.uuid || ((_segment$userData4 = segment.userData) === null || _segment$userData4 === void 0 ? void 0 : _segment$userData4.originalUuid);
|
|
5438
5524
|
if (!segmentId) {
|
|
5439
5525
|
console.error('❌ Cannot find segment ID for translateSegment API call');
|
|
5440
5526
|
return;
|
|
@@ -5453,14 +5539,14 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5453
5539
|
if (Math.abs(deltaY) > threshold) {
|
|
5454
5540
|
// Round to nearest 0.5 to match grid snapping
|
|
5455
5541
|
var roundedDeltaY = Math.round(deltaY * 2) / 2;
|
|
5456
|
-
var
|
|
5457
|
-
if (
|
|
5542
|
+
var _success = this.centralPlant.translateSegment(segmentId, 'y', roundedDeltaY);
|
|
5543
|
+
if (_success) translationApplied = true;
|
|
5458
5544
|
}
|
|
5459
5545
|
if (Math.abs(deltaZ) > threshold) {
|
|
5460
5546
|
// Round to nearest 0.5 to match grid snapping
|
|
5461
5547
|
var roundedDeltaZ = Math.round(deltaZ * 2) / 2;
|
|
5462
|
-
var
|
|
5463
|
-
if (
|
|
5548
|
+
var _success2 = this.centralPlant.translateSegment(segmentId, 'z', roundedDeltaZ);
|
|
5549
|
+
if (_success2) translationApplied = true;
|
|
5464
5550
|
}
|
|
5465
5551
|
if (translationApplied) {
|
|
5466
5552
|
console.log("\u2705 Applied segment translation through centralPlant translateSegment API");
|
|
@@ -5536,14 +5622,14 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5536
5622
|
if (Math.abs(deltaY) > threshold) {
|
|
5537
5623
|
// Round to nearest 0.5 to match grid snapping
|
|
5538
5624
|
var roundedDeltaY = Math.round(deltaY * 2) / 2;
|
|
5539
|
-
var
|
|
5540
|
-
if (
|
|
5625
|
+
var _success3 = this.centralPlant.translateGateway(gatewayId, 'y', roundedDeltaY);
|
|
5626
|
+
if (_success3) translationApplied = true;
|
|
5541
5627
|
}
|
|
5542
5628
|
if (Math.abs(deltaZ) > threshold) {
|
|
5543
5629
|
// Round to nearest 0.5 to match grid snapping
|
|
5544
5630
|
var roundedDeltaZ = Math.round(deltaZ * 2) / 2;
|
|
5545
|
-
var
|
|
5546
|
-
if (
|
|
5631
|
+
var _success4 = this.centralPlant.translateGateway(gatewayId, 'z', roundedDeltaZ);
|
|
5632
|
+
if (_success4) translationApplied = true;
|
|
5547
5633
|
}
|
|
5548
5634
|
if (translationApplied) {
|
|
5549
5635
|
console.log("\u2705 Applied gateway translation through centralPlant translateGateway API");
|
|
@@ -19059,10 +19145,15 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19059
19145
|
console.error("\u274C translateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
19060
19146
|
return false;
|
|
19061
19147
|
}
|
|
19062
|
-
|
|
19063
|
-
// Apply the translation
|
|
19064
19148
|
console.log("\uD83D\uDD04 translateComponent(): Translating component ".concat(componentId, " on ").concat(axis, " axis by ").concat(value));
|
|
19065
19149
|
|
|
19150
|
+
// Run collision validation checks before applying the translation
|
|
19151
|
+
var collisionValidation = this.validateTranslateComponentCollisions(component, axis, value);
|
|
19152
|
+
if (!collisionValidation) {
|
|
19153
|
+
return false;
|
|
19154
|
+
}
|
|
19155
|
+
|
|
19156
|
+
// All validations passed - apply the translation
|
|
19066
19157
|
// Update the Three.js object position
|
|
19067
19158
|
component.position[axis] += value;
|
|
19068
19159
|
|
|
@@ -19106,6 +19197,100 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19106
19197
|
return true;
|
|
19107
19198
|
}
|
|
19108
19199
|
|
|
19200
|
+
/**
|
|
19201
|
+
* Validate collision checks for translateComponent operation
|
|
19202
|
+
* @param {THREE.Object3D} component - The component to translate
|
|
19203
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
19204
|
+
* @param {number} value - The value to translate by
|
|
19205
|
+
* @returns {boolean} True if no collisions detected, false if translation would cause collision
|
|
19206
|
+
* @private
|
|
19207
|
+
*/
|
|
19208
|
+
}, {
|
|
19209
|
+
key: "validateTranslateComponentCollisions",
|
|
19210
|
+
value: function validateTranslateComponentCollisions(component, axis, value) {
|
|
19211
|
+
// Store original position for reverting
|
|
19212
|
+
var originalPosition = component.position[axis];
|
|
19213
|
+
|
|
19214
|
+
// Temporarily apply the translation to check for collisions
|
|
19215
|
+
component.position[axis] += value;
|
|
19216
|
+
component.updateMatrix();
|
|
19217
|
+
component.updateMatrixWorld(true);
|
|
19218
|
+
console.log("\uD83D\uDD0D Checking collisions with translated position: ".concat(axis, "=").concat(component.position[axis].toFixed(3)));
|
|
19219
|
+
|
|
19220
|
+
// Check for collision with manual segments
|
|
19221
|
+
var manualSegmentCollision = this.checkComponentManualSegmentCollision(component);
|
|
19222
|
+
if (manualSegmentCollision) {
|
|
19223
|
+
console.warn("\u26A0\uFE0F translateComponent(): Component would collide with manual segment (allowed)");
|
|
19224
|
+
console.warn(" Segment ID: ".concat(manualSegmentCollision.segmentId));
|
|
19225
|
+
console.warn(" Distance to segment: ".concat(manualSegmentCollision.distance.toFixed(3)));
|
|
19226
|
+
console.warn(" Segment endpoints: [".concat(manualSegmentCollision.segmentStart.x.toFixed(3), ", ").concat(manualSegmentCollision.segmentStart.y.toFixed(3), ", ").concat(manualSegmentCollision.segmentStart.z.toFixed(3), "] to [").concat(manualSegmentCollision.segmentEnd.x.toFixed(3), ", ").concat(manualSegmentCollision.segmentEnd.y.toFixed(3), ", ").concat(manualSegmentCollision.segmentEnd.z.toFixed(3), "]"));
|
|
19227
|
+
// Note: We do NOT return false - collision is allowed
|
|
19228
|
+
} else {
|
|
19229
|
+
console.log('✅ No collisions detected');
|
|
19230
|
+
}
|
|
19231
|
+
|
|
19232
|
+
// Revert the temporary translation
|
|
19233
|
+
component.position[axis] = originalPosition;
|
|
19234
|
+
component.updateMatrix();
|
|
19235
|
+
component.updateMatrixWorld(true);
|
|
19236
|
+
return true; // Always allow translation
|
|
19237
|
+
}
|
|
19238
|
+
|
|
19239
|
+
/**
|
|
19240
|
+
* Validate collision checks for translateGateway operation
|
|
19241
|
+
* @param {THREE.Object3D} gateway - The gateway to translate
|
|
19242
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
19243
|
+
* @param {number} value - The value to translate by
|
|
19244
|
+
* @returns {boolean} True if no collisions detected, false if translation would cause collision
|
|
19245
|
+
* @private
|
|
19246
|
+
*/
|
|
19247
|
+
}, {
|
|
19248
|
+
key: "validateTranslateGatewayCollisions",
|
|
19249
|
+
value: function validateTranslateGatewayCollisions(gateway, axis, value) {
|
|
19250
|
+
// Store original position for reverting
|
|
19251
|
+
var originalPosition = gateway.position[axis];
|
|
19252
|
+
|
|
19253
|
+
// Temporarily apply the translation to check for collisions
|
|
19254
|
+
gateway.position[axis] += value;
|
|
19255
|
+
gateway.updateMatrix();
|
|
19256
|
+
gateway.updateMatrixWorld(true);
|
|
19257
|
+
console.log("\uD83D\uDD0D Checking collisions with translated gateway position: ".concat(axis, "=").concat(gateway.position[axis].toFixed(3)));
|
|
19258
|
+
|
|
19259
|
+
// Check for collision with components (this should block translation)
|
|
19260
|
+
var componentCollision = this.checkGatewayComponentCollision(gateway);
|
|
19261
|
+
if (componentCollision) {
|
|
19262
|
+
// Revert the translation
|
|
19263
|
+
gateway.position[axis] = originalPosition;
|
|
19264
|
+
gateway.updateMatrix();
|
|
19265
|
+
gateway.updateMatrixWorld(true);
|
|
19266
|
+
console.warn("\u26A0\uFE0F translateGateway(): Translation canceled - gateway would collide with component");
|
|
19267
|
+
console.warn(" Component ID: ".concat(componentCollision.componentId));
|
|
19268
|
+
console.warn(" Component Name: ".concat(componentCollision.componentName));
|
|
19269
|
+
return false;
|
|
19270
|
+
}
|
|
19271
|
+
|
|
19272
|
+
// Check for collision with manual segments (this should also block translation)
|
|
19273
|
+
var manualSegmentCollision = this.checkGatewayManualSegmentCollision(gateway);
|
|
19274
|
+
if (manualSegmentCollision) {
|
|
19275
|
+
// Revert the translation
|
|
19276
|
+
gateway.position[axis] = originalPosition;
|
|
19277
|
+
gateway.updateMatrix();
|
|
19278
|
+
gateway.updateMatrixWorld(true);
|
|
19279
|
+
console.warn("\u26A0\uFE0F translateGateway(): Translation canceled - gateway would collide with manual segment");
|
|
19280
|
+
console.warn(" Segment ID: ".concat(manualSegmentCollision.segmentId));
|
|
19281
|
+
console.warn(" Distance to segment: ".concat(manualSegmentCollision.distance.toFixed(3), " (threshold: 0.25)"));
|
|
19282
|
+
console.warn(" Segment endpoints: [".concat(manualSegmentCollision.segmentStart.x.toFixed(3), ", ").concat(manualSegmentCollision.segmentStart.y.toFixed(3), ", ").concat(manualSegmentCollision.segmentStart.z.toFixed(3), "] to [").concat(manualSegmentCollision.segmentEnd.x.toFixed(3), ", ").concat(manualSegmentCollision.segmentEnd.y.toFixed(3), ", ").concat(manualSegmentCollision.segmentEnd.z.toFixed(3), "]"));
|
|
19283
|
+
return false;
|
|
19284
|
+
}
|
|
19285
|
+
console.log('✅ No collisions detected');
|
|
19286
|
+
|
|
19287
|
+
// Revert the temporary translation
|
|
19288
|
+
gateway.position[axis] = originalPosition;
|
|
19289
|
+
gateway.updateMatrix();
|
|
19290
|
+
gateway.updateMatrixWorld(true);
|
|
19291
|
+
return true; // Allow translation only if no collisions
|
|
19292
|
+
}
|
|
19293
|
+
|
|
19109
19294
|
/**
|
|
19110
19295
|
* Translate a pipe segment by segmentId
|
|
19111
19296
|
* @param {string} segmentId - The UUID of the pipe segment to translate
|
|
@@ -19277,12 +19462,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19277
19462
|
console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would intersect with other segment(s)");
|
|
19278
19463
|
return false;
|
|
19279
19464
|
}
|
|
19280
|
-
console.log('✅ No intersections detected,
|
|
19465
|
+
console.log('✅ No intersections detected, translation pre-applied');
|
|
19281
19466
|
|
|
19282
|
-
//
|
|
19283
|
-
|
|
19284
|
-
segment.updateMatrix();
|
|
19285
|
-
segment.updateMatrixWorld(true);
|
|
19467
|
+
// Leave the translation applied - caller expects it to be ready
|
|
19468
|
+
// This eliminates redundant matrix updates
|
|
19286
19469
|
return true;
|
|
19287
19470
|
}
|
|
19288
19471
|
}, {
|
|
@@ -19298,16 +19481,14 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19298
19481
|
var segment = validationResult.segment;
|
|
19299
19482
|
console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
|
|
19300
19483
|
|
|
19301
|
-
// Run collision validation checks
|
|
19484
|
+
// Run collision validation checks (applies translation if successful)
|
|
19302
19485
|
var collisionValidation = this.validateTranslateSegmentCollisions(segment, axis, value);
|
|
19303
19486
|
if (!collisionValidation) {
|
|
19304
19487
|
return false;
|
|
19305
19488
|
}
|
|
19306
19489
|
|
|
19307
|
-
// All validations passed -
|
|
19308
|
-
|
|
19309
|
-
segment.updateMatrix();
|
|
19310
|
-
segment.updateMatrixWorld(true);
|
|
19490
|
+
// All validations passed - translation already applied by validateTranslateSegmentCollisions
|
|
19491
|
+
// No need to redundantly update matrices again
|
|
19311
19492
|
|
|
19312
19493
|
// Validate PathfindingManager and SceneOperationsManager availability
|
|
19313
19494
|
var pathfindingManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.pathfindingManager;
|
|
@@ -19432,7 +19613,13 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19432
19613
|
}
|
|
19433
19614
|
console.log("\uD83D\uDD04 translateGateway(): Translating gateway ".concat(gatewayId, " on ").concat(axis, " axis by ").concat(value));
|
|
19434
19615
|
|
|
19435
|
-
//
|
|
19616
|
+
// Run collision validation checks before applying the translation
|
|
19617
|
+
var collisionValidation = this.validateTranslateGatewayCollisions(gateway, axis, value);
|
|
19618
|
+
if (!collisionValidation) {
|
|
19619
|
+
return false;
|
|
19620
|
+
}
|
|
19621
|
+
|
|
19622
|
+
// All validations passed - apply the translation to the Three.js object
|
|
19436
19623
|
gateway.position[axis] += value;
|
|
19437
19624
|
|
|
19438
19625
|
// Update matrices
|
|
@@ -19842,7 +20029,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19842
20029
|
* Check if a segment intersects with any segments in the scene
|
|
19843
20030
|
* For grid-based segments (0.5 grid), checks if segments cross or overlap
|
|
19844
20031
|
* Uses only endpoint comparisons, no radius checks
|
|
19845
|
-
* Allows T-junctions
|
|
20032
|
+
* Allows T-junctions in two cases:
|
|
20033
|
+
* 1. Segments are part of the same connection path (same pathFrom/pathTo)
|
|
20034
|
+
* 2. One segment's endpoint touches another segment's line (not at endpoints)
|
|
19846
20035
|
* @param {THREE.Object3D} segment - The segment to check for intersections
|
|
19847
20036
|
* @returns {boolean} True if segment intersects with any segment
|
|
19848
20037
|
* @private
|
|
@@ -19905,19 +20094,26 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19905
20094
|
|
|
19906
20095
|
// If exactly 1 endpoint is shared, check if they overlap along the same line
|
|
19907
20096
|
if (sharedEndpointCount === 1) {
|
|
19908
|
-
// Check if segments are collinear (on the same line)
|
|
19909
|
-
|
|
19910
|
-
|
|
19911
|
-
|
|
19912
|
-
|
|
19913
|
-
|
|
20097
|
+
// Check if segments are collinear (on the same line) by comparing direction vectors
|
|
20098
|
+
// Get direction vectors for both segments
|
|
20099
|
+
var dir1 = new THREE__namespace.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize();
|
|
20100
|
+
var dir2 = new THREE__namespace.Vector3().subVectors(otherEndpoints.end, otherEndpoints.start).normalize();
|
|
20101
|
+
|
|
20102
|
+
// Calculate the absolute dot product (to handle opposite directions)
|
|
20103
|
+
var dotProduct = Math.abs(dir1.dot(dir2));
|
|
20104
|
+
|
|
20105
|
+
// If dot product is close to 1.0, the segments are parallel/collinear
|
|
20106
|
+
// Threshold of 0.9999 allows for ~0.8 degree deviation
|
|
20107
|
+
var collinearThreshold = 0.9999;
|
|
20108
|
+
if (dotProduct > collinearThreshold) {
|
|
20109
|
+
// Segments are collinear and share one endpoint - they overlap
|
|
20110
|
+
console.log("\uD83D\uDD34 Overlapping collinear segments detected - share 1 endpoint and are parallel (dot product: ".concat(dotProduct.toFixed(6), ")"));
|
|
19914
20111
|
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
20112
|
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
20113
|
hasIntersection = true;
|
|
19918
20114
|
} else {
|
|
19919
|
-
// Valid end-to-end connection at different angles
|
|
19920
|
-
console.log("\u2705 Segments connected at one endpoint with different directions - valid
|
|
20115
|
+
// Valid end-to-end connection at different angles (L-junction, etc.)
|
|
20116
|
+
console.log("\u2705 Segments connected at one endpoint with different directions - valid L-junction (dot product: ".concat(dotProduct.toFixed(6), ")"));
|
|
19921
20117
|
}
|
|
19922
20118
|
return;
|
|
19923
20119
|
}
|
|
@@ -19928,12 +20124,23 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19928
20124
|
// If distance is near zero, segments cross or overlap
|
|
19929
20125
|
if (distance < endpointTolerance) {
|
|
19930
20126
|
// Special case: T-junction (one segment's endpoint touches the other's line)
|
|
19931
|
-
// This is allowed if
|
|
20127
|
+
// This is allowed if:
|
|
20128
|
+
// 1. Segments are part of the same connection path, OR
|
|
20129
|
+
// 2. The moving segment's endpoint touches the manual segment (T-junction)
|
|
19932
20130
|
if (sameConnection) {
|
|
19933
20131
|
var _segment$userData8, _segment$userData9;
|
|
19934
20132
|
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
20133
|
return;
|
|
19936
20134
|
}
|
|
20135
|
+
|
|
20136
|
+
// Check if this is a valid T-junction (moving segment endpoint touching manual segment)
|
|
20137
|
+
var isTJunction = _this2.isTJunction(segmentEndpoints.start, segmentEndpoints.end, otherEndpoints.start, otherEndpoints.end, endpointTolerance);
|
|
20138
|
+
if (isTJunction) {
|
|
20139
|
+
console.log("\u2705 T-junction detected but allowed - moving segment endpoint touches manual segment");
|
|
20140
|
+
console.log(" Moving segment: [".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), "]"));
|
|
20141
|
+
console.log(" Manual segment: [".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), "]"));
|
|
20142
|
+
return;
|
|
20143
|
+
}
|
|
19937
20144
|
console.log("\uD83D\uDD34 Intersection detected - segments cross or overlap");
|
|
19938
20145
|
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
20146
|
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), "]"));
|
|
@@ -19971,6 +20178,71 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19971
20178
|
return this.calculateSegmentEndpoints(segment);
|
|
19972
20179
|
}
|
|
19973
20180
|
|
|
20181
|
+
/**
|
|
20182
|
+
* Check if two segments form a valid T-junction
|
|
20183
|
+
* A T-junction occurs when one segment's endpoint touches the other segment's line (not at an endpoint)
|
|
20184
|
+
* @param {THREE.Vector3} seg1Start - Start point of segment 1
|
|
20185
|
+
* @param {THREE.Vector3} seg1End - End point of segment 1
|
|
20186
|
+
* @param {THREE.Vector3} seg2Start - Start point of segment 2
|
|
20187
|
+
* @param {THREE.Vector3} seg2End - End point of segment 2
|
|
20188
|
+
* @param {number} tolerance - Distance tolerance for "touching"
|
|
20189
|
+
* @returns {boolean} True if segments form a T-junction
|
|
20190
|
+
* @private
|
|
20191
|
+
*/
|
|
20192
|
+
}, {
|
|
20193
|
+
key: "isTJunction",
|
|
20194
|
+
value: function isTJunction(seg1Start, seg1End, seg2Start, seg2End, tolerance) {
|
|
20195
|
+
// Helper function to check if a point lies on a line segment (not at endpoints)
|
|
20196
|
+
var isPointOnLineSegment = function isPointOnLineSegment(point, lineStart, lineEnd, tol) {
|
|
20197
|
+
// Direction vector of the line
|
|
20198
|
+
var lineDir = new THREE__namespace.Vector3().subVectors(lineEnd, lineStart);
|
|
20199
|
+
var lineLength = lineDir.length();
|
|
20200
|
+
if (lineLength < 1e-10) {
|
|
20201
|
+
return false; // Degenerate line segment
|
|
20202
|
+
}
|
|
20203
|
+
lineDir.normalize();
|
|
20204
|
+
|
|
20205
|
+
// Vector from line start to point
|
|
20206
|
+
var toPoint = new THREE__namespace.Vector3().subVectors(point, lineStart);
|
|
20207
|
+
|
|
20208
|
+
// Project point onto line to find closest point on line
|
|
20209
|
+
var projectionLength = toPoint.dot(lineDir);
|
|
20210
|
+
|
|
20211
|
+
// Check if projection is within the line segment (not at endpoints)
|
|
20212
|
+
if (projectionLength <= tol || projectionLength >= lineLength - tol) {
|
|
20213
|
+
return false; // Point is at or near an endpoint, not a T-junction
|
|
20214
|
+
}
|
|
20215
|
+
|
|
20216
|
+
// Calculate closest point on line
|
|
20217
|
+
var closestPoint = new THREE__namespace.Vector3().copy(lineStart).add(lineDir.clone().multiplyScalar(projectionLength));
|
|
20218
|
+
|
|
20219
|
+
// Check if point is close enough to the line
|
|
20220
|
+
var distance = point.distanceTo(closestPoint);
|
|
20221
|
+
return distance < tol;
|
|
20222
|
+
};
|
|
20223
|
+
|
|
20224
|
+
// Check if seg1's start point touches seg2's line (not at endpoints)
|
|
20225
|
+
if (isPointOnLineSegment(seg1Start, seg2Start, seg2End, tolerance)) {
|
|
20226
|
+
return true;
|
|
20227
|
+
}
|
|
20228
|
+
|
|
20229
|
+
// Check if seg1's end point touches seg2's line (not at endpoints)
|
|
20230
|
+
if (isPointOnLineSegment(seg1End, seg2Start, seg2End, tolerance)) {
|
|
20231
|
+
return true;
|
|
20232
|
+
}
|
|
20233
|
+
|
|
20234
|
+
// Check if seg2's start point touches seg1's line (not at endpoints)
|
|
20235
|
+
if (isPointOnLineSegment(seg2Start, seg1Start, seg1End, tolerance)) {
|
|
20236
|
+
return true;
|
|
20237
|
+
}
|
|
20238
|
+
|
|
20239
|
+
// Check if seg2's end point touches seg1's line (not at endpoints)
|
|
20240
|
+
if (isPointOnLineSegment(seg2End, seg1Start, seg1End, tolerance)) {
|
|
20241
|
+
return true;
|
|
20242
|
+
}
|
|
20243
|
+
return false;
|
|
20244
|
+
}
|
|
20245
|
+
|
|
19974
20246
|
/**
|
|
19975
20247
|
* Check if any point along a segment's path would collide with component connector within 0.5 radius
|
|
19976
20248
|
* @param {THREE.Object3D} segment - The segment to check
|
|
@@ -20020,8 +20292,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20020
20292
|
|
|
20021
20293
|
// Handle degenerate case (zero-length segment)
|
|
20022
20294
|
if (segmentLengthSquared < 1e-10) {
|
|
20023
|
-
var
|
|
20024
|
-
if (
|
|
20295
|
+
var _distance = startPoint.distanceTo(connectorWorldPos);
|
|
20296
|
+
if (_distance <= collisionRadius) {
|
|
20025
20297
|
// Find the parent component
|
|
20026
20298
|
var component = child.parent;
|
|
20027
20299
|
while (component && !((_component$userData2 = component.userData) !== null && _component$userData2 !== void 0 && _component$userData2.libraryId)) {
|
|
@@ -20041,7 +20313,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20041
20313
|
y: startPoint.y,
|
|
20042
20314
|
z: startPoint.z
|
|
20043
20315
|
},
|
|
20044
|
-
distance:
|
|
20316
|
+
distance: _distance
|
|
20045
20317
|
};
|
|
20046
20318
|
}
|
|
20047
20319
|
return;
|
|
@@ -20185,6 +20457,210 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20185
20457
|
return collision;
|
|
20186
20458
|
}
|
|
20187
20459
|
|
|
20460
|
+
/**
|
|
20461
|
+
* Check if a component would collide with any manual (declared) segment
|
|
20462
|
+
* @param {THREE.Object3D} component - The component to check for collisions
|
|
20463
|
+
* @returns {Object|null} Collision info {segmentId, distance, segmentStart, segmentEnd} if collision detected, null otherwise
|
|
20464
|
+
* @private
|
|
20465
|
+
*/
|
|
20466
|
+
}, {
|
|
20467
|
+
key: "checkComponentManualSegmentCollision",
|
|
20468
|
+
value: function checkComponentManualSegmentCollision(component) {
|
|
20469
|
+
var _this$sceneViewer8,
|
|
20470
|
+
_this3 = this;
|
|
20471
|
+
if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !component) {
|
|
20472
|
+
return null;
|
|
20473
|
+
}
|
|
20474
|
+
|
|
20475
|
+
// Create a bounding box for the component
|
|
20476
|
+
var componentBBox = new THREE__namespace.Box3().setFromObject(component);
|
|
20477
|
+
var collision = null;
|
|
20478
|
+
|
|
20479
|
+
// Traverse scene to find all manual segments (isDeclared === true)
|
|
20480
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
20481
|
+
var _child$userData15, _child$userData16;
|
|
20482
|
+
if (collision) return; // Stop if collision already found
|
|
20483
|
+
|
|
20484
|
+
// Only check manual segments (isDeclared === true)
|
|
20485
|
+
if (((_child$userData15 = child.userData) === null || _child$userData15 === void 0 ? void 0 : _child$userData15.objectType) === 'segment' && ((_child$userData16 = child.userData) === null || _child$userData16 === void 0 ? void 0 : _child$userData16.isDeclared) === true) {
|
|
20486
|
+
// Get segment endpoints
|
|
20487
|
+
var segmentEndpoints = _this3.getSegmentEndpoints(child);
|
|
20488
|
+
|
|
20489
|
+
// Check if segment intersects with component's bounding box
|
|
20490
|
+
// We'll use a line-box intersection test
|
|
20491
|
+
var line = new THREE__namespace.Line3(segmentEndpoints.start, segmentEndpoints.end);
|
|
20492
|
+
var closestPoint = new THREE__namespace.Vector3();
|
|
20493
|
+
line.closestPointToPoint(componentBBox.getCenter(new THREE__namespace.Vector3()), true, closestPoint);
|
|
20494
|
+
|
|
20495
|
+
// Check if the closest point on the line is within the bounding box
|
|
20496
|
+
if (componentBBox.containsPoint(closestPoint)) {
|
|
20497
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box collision with manual segment:', child.uuid);
|
|
20498
|
+
collision = {
|
|
20499
|
+
segmentId: child.uuid,
|
|
20500
|
+
distance: 0,
|
|
20501
|
+
// Inside the bounding box
|
|
20502
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20503
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20504
|
+
};
|
|
20505
|
+
return;
|
|
20506
|
+
}
|
|
20507
|
+
|
|
20508
|
+
// Also check if either endpoint of the segment is inside the component bounding box
|
|
20509
|
+
if (componentBBox.containsPoint(segmentEndpoints.start) || componentBBox.containsPoint(segmentEndpoints.end)) {
|
|
20510
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box contains manual segment endpoint:', child.uuid);
|
|
20511
|
+
collision = {
|
|
20512
|
+
segmentId: child.uuid,
|
|
20513
|
+
distance: 0,
|
|
20514
|
+
// Inside the bounding box
|
|
20515
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20516
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20517
|
+
};
|
|
20518
|
+
return;
|
|
20519
|
+
}
|
|
20520
|
+
|
|
20521
|
+
// Additionally, check if the segment line intersects any of the bounding box faces
|
|
20522
|
+
// This catches cases where the segment passes through the box without endpoints inside
|
|
20523
|
+
var ray = new THREE__namespace.Ray(segmentEndpoints.start, new THREE__namespace.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize());
|
|
20524
|
+
var segmentLength = segmentEndpoints.start.distanceTo(segmentEndpoints.end);
|
|
20525
|
+
var intersection = ray.intersectBox(componentBBox, new THREE__namespace.Vector3());
|
|
20526
|
+
if (intersection) {
|
|
20527
|
+
var distanceToIntersection = segmentEndpoints.start.distanceTo(intersection);
|
|
20528
|
+
if (distanceToIntersection <= segmentLength) {
|
|
20529
|
+
console.log('⚠️ TransformOperationsManager: Manual segment intersects component bounding box:', child.uuid);
|
|
20530
|
+
collision = {
|
|
20531
|
+
segmentId: child.uuid,
|
|
20532
|
+
distance: 0,
|
|
20533
|
+
// Intersects the bounding box
|
|
20534
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20535
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20536
|
+
};
|
|
20537
|
+
}
|
|
20538
|
+
}
|
|
20539
|
+
}
|
|
20540
|
+
});
|
|
20541
|
+
return collision;
|
|
20542
|
+
}
|
|
20543
|
+
|
|
20544
|
+
/**
|
|
20545
|
+
* Check if a gateway would collide with any manual (declared) segment
|
|
20546
|
+
* Gateways are treated as point objects, so we check if the gateway point
|
|
20547
|
+
* is too close to any manual segment line. Gateways ARE allowed to be at
|
|
20548
|
+
* segment endpoints, but NOT along the segment between endpoints.
|
|
20549
|
+
* @param {THREE.Object3D} gateway - The gateway to check for collisions
|
|
20550
|
+
* @returns {Object|null} Collision info {segmentId, distance, segmentStart, segmentEnd} if collision detected, null otherwise
|
|
20551
|
+
* @private
|
|
20552
|
+
*/
|
|
20553
|
+
}, {
|
|
20554
|
+
key: "checkGatewayManualSegmentCollision",
|
|
20555
|
+
value: function checkGatewayManualSegmentCollision(gateway) {
|
|
20556
|
+
var _this$sceneViewer9,
|
|
20557
|
+
_this4 = this;
|
|
20558
|
+
if (!((_this$sceneViewer9 = this.sceneViewer) !== null && _this$sceneViewer9 !== void 0 && _this$sceneViewer9.scene) || !gateway) {
|
|
20559
|
+
return null;
|
|
20560
|
+
}
|
|
20561
|
+
|
|
20562
|
+
// Get gateway world position
|
|
20563
|
+
var gatewayPos = new THREE__namespace.Vector3();
|
|
20564
|
+
gateway.getWorldPosition(gatewayPos);
|
|
20565
|
+
|
|
20566
|
+
// Define collision threshold - gateways are small point objects
|
|
20567
|
+
var collisionThreshold = 0.25; // Gateway is too close to segment if within this distance
|
|
20568
|
+
var endpointTolerance = 0.01; // Tolerance for considering gateway at an endpoint
|
|
20569
|
+
|
|
20570
|
+
var collision = null;
|
|
20571
|
+
|
|
20572
|
+
// Traverse scene to find all manual segments (isDeclared === true)
|
|
20573
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
20574
|
+
var _child$userData17, _child$userData18;
|
|
20575
|
+
if (collision) return; // Stop if collision already found
|
|
20576
|
+
|
|
20577
|
+
// Only check manual segments (isDeclared === true)
|
|
20578
|
+
if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.objectType) === 'segment' && ((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.isDeclared) === true) {
|
|
20579
|
+
// Get segment endpoints
|
|
20580
|
+
var segmentEndpoints = _this4.getSegmentEndpoints(child);
|
|
20581
|
+
|
|
20582
|
+
// Check if gateway is at either endpoint - this is ALLOWED
|
|
20583
|
+
var distToStart = gatewayPos.distanceTo(segmentEndpoints.start);
|
|
20584
|
+
var distToEnd = gatewayPos.distanceTo(segmentEndpoints.end);
|
|
20585
|
+
if (distToStart < endpointTolerance || distToEnd < endpointTolerance) {
|
|
20586
|
+
console.log('✅ TransformOperationsManager: Gateway at segment endpoint (allowed):', child.uuid);
|
|
20587
|
+
return; // Skip collision check - this is allowed
|
|
20588
|
+
}
|
|
20589
|
+
|
|
20590
|
+
// Calculate distance from gateway point to segment line
|
|
20591
|
+
var line = new THREE__namespace.Line3(segmentEndpoints.start, segmentEndpoints.end);
|
|
20592
|
+
var closestPoint = new THREE__namespace.Vector3();
|
|
20593
|
+
line.closestPointToPoint(gatewayPos, true, closestPoint);
|
|
20594
|
+
var distance = gatewayPos.distanceTo(closestPoint);
|
|
20595
|
+
|
|
20596
|
+
// Check if gateway is too close to the segment (but not at endpoints)
|
|
20597
|
+
if (distance < collisionThreshold) {
|
|
20598
|
+
console.log('⚠️ TransformOperationsManager: Gateway too close to manual segment:', child.uuid);
|
|
20599
|
+
console.log(" Distance: ".concat(distance.toFixed(3), " (threshold: ").concat(collisionThreshold, ")"));
|
|
20600
|
+
collision = {
|
|
20601
|
+
segmentId: child.uuid,
|
|
20602
|
+
distance: distance,
|
|
20603
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20604
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20605
|
+
};
|
|
20606
|
+
return;
|
|
20607
|
+
}
|
|
20608
|
+
}
|
|
20609
|
+
});
|
|
20610
|
+
return collision;
|
|
20611
|
+
}
|
|
20612
|
+
|
|
20613
|
+
/**
|
|
20614
|
+
* Check if a gateway would collide with any component's bounding box
|
|
20615
|
+
* Uses worldBoundingBox from currentSceneData for optimal performance
|
|
20616
|
+
* @param {THREE.Object3D} gateway - The gateway to check for collisions
|
|
20617
|
+
* @returns {Object|null} Collision info {componentId, componentName} if collision detected, null otherwise
|
|
20618
|
+
* @private
|
|
20619
|
+
*/
|
|
20620
|
+
}, {
|
|
20621
|
+
key: "checkGatewayComponentCollision",
|
|
20622
|
+
value: function checkGatewayComponentCollision(gateway) {
|
|
20623
|
+
var _this$sceneViewer0;
|
|
20624
|
+
if (!((_this$sceneViewer0 = this.sceneViewer) !== null && _this$sceneViewer0 !== void 0 && _this$sceneViewer0.scene) || !gateway) {
|
|
20625
|
+
return null;
|
|
20626
|
+
}
|
|
20627
|
+
|
|
20628
|
+
// Get gateway world position
|
|
20629
|
+
var gatewayPos = new THREE__namespace.Vector3();
|
|
20630
|
+
gateway.getWorldPosition(gatewayPos);
|
|
20631
|
+
var collision = null;
|
|
20632
|
+
|
|
20633
|
+
// Traverse scene to find all components
|
|
20634
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
20635
|
+
var _child$userData19, _child$userData20;
|
|
20636
|
+
if (collision) return; // Stop if collision already found
|
|
20637
|
+
|
|
20638
|
+
// Check if this is a component (equipment)
|
|
20639
|
+
if (((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.objectType) === 'component' && (_child$userData20 = child.userData) !== null && _child$userData20 !== void 0 && _child$userData20.libraryId) {
|
|
20640
|
+
// Try to get worldBoundingBox from userData first (most up-to-date)
|
|
20641
|
+
var bbox = null;
|
|
20642
|
+
if (child.userData.worldBoundingBox) {
|
|
20643
|
+
// Use stored worldBoundingBox (array format: {min: [x,y,z], max: [x,y,z]})
|
|
20644
|
+
bbox = new THREE__namespace.Box3(_construct(THREE__namespace.Vector3, _toConsumableArray(child.userData.worldBoundingBox.min)), _construct(THREE__namespace.Vector3, _toConsumableArray(child.userData.worldBoundingBox.max)));
|
|
20645
|
+
} else {
|
|
20646
|
+
// Fallback: compute from object
|
|
20647
|
+
bbox = new THREE__namespace.Box3().setFromObject(child);
|
|
20648
|
+
}
|
|
20649
|
+
|
|
20650
|
+
// Check if gateway position is inside the component's bounding box
|
|
20651
|
+
if (bbox.containsPoint(gatewayPos)) {
|
|
20652
|
+
console.log('⚠️ TransformOperationsManager: Gateway position inside component bounding box:', child.userData.libraryId || child.name || child.uuid);
|
|
20653
|
+
collision = {
|
|
20654
|
+
componentId: child.uuid,
|
|
20655
|
+
componentName: child.name || child.userData.libraryId || 'Unknown'
|
|
20656
|
+
};
|
|
20657
|
+
return;
|
|
20658
|
+
}
|
|
20659
|
+
}
|
|
20660
|
+
});
|
|
20661
|
+
return collision;
|
|
20662
|
+
}
|
|
20663
|
+
|
|
20188
20664
|
/**
|
|
20189
20665
|
* Calculate the minimum distance between two line segments in 3D space
|
|
20190
20666
|
* @param {THREE.Vector3} p1 - Start point of first segment
|
|
@@ -20294,10 +20770,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20294
20770
|
}, {
|
|
20295
20771
|
key: "snapSegmentConnectorsToNearbyEndpoints",
|
|
20296
20772
|
value: function snapSegmentConnectorsToNearbyEndpoints(movedSegment) {
|
|
20297
|
-
var _this$
|
|
20298
|
-
_this$
|
|
20299
|
-
|
|
20300
|
-
if (!movedSegment || !((_this$
|
|
20773
|
+
var _this$sceneViewer1,
|
|
20774
|
+
_this$sceneViewer10,
|
|
20775
|
+
_this5 = this;
|
|
20776
|
+
if (!movedSegment || !((_this$sceneViewer1 = this.sceneViewer) !== null && _this$sceneViewer1 !== void 0 && _this$sceneViewer1.scene)) {
|
|
20301
20777
|
return [];
|
|
20302
20778
|
}
|
|
20303
20779
|
console.log('🔗 Finding adjacent segments connected to moved segment...');
|
|
@@ -20305,8 +20781,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20305
20781
|
// Get the moved segment's connectors
|
|
20306
20782
|
var movedConnectors = [];
|
|
20307
20783
|
movedSegment.traverse(function (child) {
|
|
20308
|
-
var _child$
|
|
20309
|
-
if (((_child$
|
|
20784
|
+
var _child$userData21;
|
|
20785
|
+
if (((_child$userData21 = child.userData) === null || _child$userData21 === void 0 ? void 0 : _child$userData21.objectType) === 'segment-connector') {
|
|
20310
20786
|
movedConnectors.push(child);
|
|
20311
20787
|
}
|
|
20312
20788
|
});
|
|
@@ -20319,7 +20795,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20319
20795
|
var newEndpoints = this.calculateSegmentEndpoints(movedSegment);
|
|
20320
20796
|
|
|
20321
20797
|
// Check scene data for connections involving the moved segment's connectors
|
|
20322
|
-
var connections = ((_this$
|
|
20798
|
+
var connections = ((_this$sceneViewer10 = this.sceneViewer) === null || _this$sceneViewer10 === void 0 || (_this$sceneViewer10 = _this$sceneViewer10.currentSceneData) === null || _this$sceneViewer10 === void 0 ? void 0 : _this$sceneViewer10.connections) || [];
|
|
20323
20799
|
var movedConnectorIds = movedConnectors.map(function (c) {
|
|
20324
20800
|
return c.uuid;
|
|
20325
20801
|
});
|
|
@@ -20354,7 +20830,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20354
20830
|
// Find the adjacent connector in the scene
|
|
20355
20831
|
var adjacentConnector = null;
|
|
20356
20832
|
var adjacentSegment = null;
|
|
20357
|
-
|
|
20833
|
+
_this5.sceneViewer.scene.traverse(function (object) {
|
|
20358
20834
|
var _object$userData;
|
|
20359
20835
|
if (object.uuid === pair.adjacentConnectorId && ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === 'segment-connector') {
|
|
20360
20836
|
adjacentConnector = object;
|
|
@@ -20376,8 +20852,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20376
20852
|
// Get all connectors of the adjacent segment
|
|
20377
20853
|
var adjacentConnectors = [];
|
|
20378
20854
|
adjacentSegment.traverse(function (child) {
|
|
20379
|
-
var _child$
|
|
20380
|
-
if (((_child$
|
|
20855
|
+
var _child$userData22;
|
|
20856
|
+
if (((_child$userData22 = child.userData) === null || _child$userData22 === void 0 ? void 0 : _child$userData22.objectType) === 'segment-connector') {
|
|
20381
20857
|
adjacentConnectors.push(child);
|
|
20382
20858
|
}
|
|
20383
20859
|
});
|
|
@@ -20403,12 +20879,12 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20403
20879
|
// Constrain movement to maintain orthogonal alignment
|
|
20404
20880
|
// Horizontal segments: only adjust X and Y, keep Z constant
|
|
20405
20881
|
// Vertical segments: only adjust Z, keep X and Y constant
|
|
20406
|
-
var constrainedPosition =
|
|
20882
|
+
var constrainedPosition = _this5.constrainPositionToOrthogonal(pair.newPosition, stationaryWorldPos, adjacentSegment);
|
|
20407
20883
|
|
|
20408
20884
|
// Recreate the segment mesh with new length using explicit endpoint positions
|
|
20409
20885
|
// Pass the intended positions, not the connector objects (which may have temporary positions)
|
|
20410
20886
|
// Pass movedSegment as activeSegment context so zero-length removal knows which segment to extend
|
|
20411
|
-
|
|
20887
|
+
_this5.recreateSegmentMeshWithNewLength(adjacentSegment, adjacentConnectors, constrainedPosition, stationaryWorldPos, movedSegment);
|
|
20412
20888
|
|
|
20413
20889
|
// CRITICAL: After recreating the mesh, BOTH connectors need to be repositioned
|
|
20414
20890
|
// because the segment's center and rotation have changed
|
|
@@ -20417,13 +20893,13 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20417
20893
|
var movingLocalPos = adjacentSegment.worldToLocal(constrainedPosition.clone());
|
|
20418
20894
|
movingConnector.position.copy(movingLocalPos);
|
|
20419
20895
|
movingConnector.updateMatrixWorld(true);
|
|
20420
|
-
|
|
20896
|
+
_this5.updateConnectorPositionInSceneData(movingConnector, constrainedPosition, adjacentSegment);
|
|
20421
20897
|
|
|
20422
20898
|
// Position stationary connector at its original world position
|
|
20423
20899
|
var stationaryLocalPos = adjacentSegment.worldToLocal(stationaryWorldPos.clone());
|
|
20424
20900
|
stationaryConnector.position.copy(stationaryLocalPos);
|
|
20425
20901
|
stationaryConnector.updateMatrixWorld(true);
|
|
20426
|
-
|
|
20902
|
+
_this5.updateConnectorPositionInSceneData(stationaryConnector, stationaryWorldPos, adjacentSegment);
|
|
20427
20903
|
|
|
20428
20904
|
// Record this connection as satisfied
|
|
20429
20905
|
satisfiedConnections.push({
|
|
@@ -20473,8 +20949,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20473
20949
|
}, {
|
|
20474
20950
|
key: "updateComponentPositionInSceneData",
|
|
20475
20951
|
value: function updateComponentPositionInSceneData(component) {
|
|
20476
|
-
var _this$
|
|
20477
|
-
if (!((_this$
|
|
20952
|
+
var _this$sceneViewer11;
|
|
20953
|
+
if (!((_this$sceneViewer11 = this.sceneViewer) !== null && _this$sceneViewer11 !== void 0 && (_this$sceneViewer11 = _this$sceneViewer11.currentSceneData) !== null && _this$sceneViewer11 !== void 0 && _this$sceneViewer11.scene)) {
|
|
20478
20954
|
console.warn('⚠️ Cannot update component position: currentSceneData not available');
|
|
20479
20955
|
return;
|
|
20480
20956
|
}
|
|
@@ -20500,8 +20976,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20500
20976
|
// Also update child connectors' positions if they exist
|
|
20501
20977
|
if (sceneDataComponent.children) {
|
|
20502
20978
|
sceneDataComponent.children.forEach(function (child) {
|
|
20503
|
-
var _child$
|
|
20504
|
-
if (((_child$
|
|
20979
|
+
var _child$userData23;
|
|
20980
|
+
if (((_child$userData23 = child.userData) === null || _child$userData23 === void 0 ? void 0 : _child$userData23.objectType) === 'connector') {
|
|
20505
20981
|
// Find the actual connector object in the scene
|
|
20506
20982
|
var connectorObj = component.children.find(function (c) {
|
|
20507
20983
|
var _c$userData;
|
|
@@ -20537,9 +21013,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20537
21013
|
}, {
|
|
20538
21014
|
key: "updateConnectorPositionInSceneData",
|
|
20539
21015
|
value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
|
|
20540
|
-
var _this$
|
|
21016
|
+
var _this$sceneViewer12;
|
|
20541
21017
|
// Update scene data if available
|
|
20542
|
-
if (!((_this$
|
|
21018
|
+
if (!((_this$sceneViewer12 = this.sceneViewer) !== null && _this$sceneViewer12 !== void 0 && (_this$sceneViewer12 = _this$sceneViewer12.currentSceneData) !== null && _this$sceneViewer12 !== void 0 && _this$sceneViewer12.scene)) {
|
|
20543
21019
|
return;
|
|
20544
21020
|
}
|
|
20545
21021
|
var cleanPosition = function cleanPosition(value) {
|
|
@@ -20830,8 +21306,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20830
21306
|
// Check if either external connector belongs to the active segment
|
|
20831
21307
|
var activeSegmentConnectors = [];
|
|
20832
21308
|
activeSegment.traverse(function (child) {
|
|
20833
|
-
var _child$
|
|
20834
|
-
if (((_child$
|
|
21309
|
+
var _child$userData24;
|
|
21310
|
+
if (((_child$userData24 = child.userData) === null || _child$userData24 === void 0 ? void 0 : _child$userData24.objectType) === 'segment-connector') {
|
|
20835
21311
|
activeSegmentConnectors.push(child.uuid);
|
|
20836
21312
|
}
|
|
20837
21313
|
});
|
|
@@ -20879,8 +21355,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20879
21355
|
// Get all connectors of the active segment
|
|
20880
21356
|
var activeConnectors = [];
|
|
20881
21357
|
activeSegment.traverse(function (child) {
|
|
20882
|
-
var _child$
|
|
20883
|
-
if (((_child$
|
|
21358
|
+
var _child$userData25;
|
|
21359
|
+
if (((_child$userData25 = child.userData) === null || _child$userData25 === void 0 ? void 0 : _child$userData25.objectType) === 'segment-connector') {
|
|
20884
21360
|
activeConnectors.push(child);
|
|
20885
21361
|
}
|
|
20886
21362
|
});
|
|
@@ -25104,7 +25580,7 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
25104
25580
|
sceneViewer.scene.add(cylinder);
|
|
25105
25581
|
|
|
25106
25582
|
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
25107
|
-
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index,
|
|
25583
|
+
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, cylinder // Pass the segment so elbow can be added as a child
|
|
25108
25584
|
);
|
|
25109
25585
|
}
|
|
25110
25586
|
}
|
|
@@ -25119,11 +25595,11 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
25119
25595
|
* @param {THREE.Material} pipeMaterial - Material for the elbow
|
|
25120
25596
|
* @param {Object} pathData - Path data object with from/to information
|
|
25121
25597
|
* @param {number} index - Path index for naming
|
|
25122
|
-
* @param {THREE.
|
|
25598
|
+
* @param {THREE.Object3D} segment - The parent segment to add the elbow to as a child
|
|
25123
25599
|
*/
|
|
25124
25600
|
}, {
|
|
25125
25601
|
key: "createAndAddElbowIfNeeded",
|
|
25126
|
-
value: function createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index,
|
|
25602
|
+
value: function createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, segment) {
|
|
25127
25603
|
// Only check if there are at least 2 more points ahead
|
|
25128
25604
|
if (j >= pathPoints.length - 2) {
|
|
25129
25605
|
return;
|
|
@@ -25138,11 +25614,12 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
25138
25614
|
if (angle <= minAngle) {
|
|
25139
25615
|
return; // No significant direction change
|
|
25140
25616
|
}
|
|
25141
|
-
|
|
25142
|
-
|
|
25143
|
-
|
|
25144
|
-
|
|
25145
|
-
var
|
|
25617
|
+
|
|
25618
|
+
// Create simple sphere elbow (efficient geometry)
|
|
25619
|
+
var sphereRadius = 0.1;
|
|
25620
|
+
var sphereSegments = 16;
|
|
25621
|
+
var sphereGeometry = new THREE__namespace.SphereGeometry(sphereRadius, sphereSegments, sphereSegments);
|
|
25622
|
+
var elbow = new THREE__namespace.Mesh(sphereGeometry, pipeMaterial);
|
|
25146
25623
|
elbow.castShadow = true;
|
|
25147
25624
|
elbow.receiveShadow = true;
|
|
25148
25625
|
|
|
@@ -25172,72 +25649,32 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
25172
25649
|
}
|
|
25173
25650
|
}
|
|
25174
25651
|
};
|
|
25175
|
-
scene.add(elbow);
|
|
25176
|
-
}
|
|
25177
25652
|
|
|
25178
|
-
|
|
25179
|
-
|
|
25180
|
-
|
|
25181
|
-
* @param {THREE.Vector3} point2 - Joint point (center of the elbow)
|
|
25182
|
-
* @param {THREE.Vector3} point3 - Third point (after the joint)
|
|
25183
|
-
* @param {number} radius - Pipe radius
|
|
25184
|
-
* @returns {THREE.BufferGeometry} Elbow geometry
|
|
25185
|
-
*/
|
|
25186
|
-
}, {
|
|
25187
|
-
key: "createElbowGeometry",
|
|
25188
|
-
value: function createElbowGeometry(point1, point2, point3, radius) {
|
|
25189
|
-
try {
|
|
25190
|
-
// Fixed elbow radius for 90-degree bends (simplified)
|
|
25191
|
-
var elbowRadius = radius * 3;
|
|
25192
|
-
|
|
25193
|
-
// Create a curve for the 90-degree elbow
|
|
25194
|
-
var curve = this.createElbowCurve(point1, point2, point3, elbowRadius);
|
|
25195
|
-
|
|
25196
|
-
// Fixed tubular segments for 90-degree bends (quarter circle)
|
|
25197
|
-
var tubularSegments = 12; // Good balance for smooth 90° curves
|
|
25198
|
-
var radialSegments = 16;
|
|
25199
|
-
var closed = false;
|
|
25200
|
-
var elbowGeometry = new THREE__namespace.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
|
|
25201
|
-
return elbowGeometry;
|
|
25202
|
-
} catch (error) {
|
|
25203
|
-
console.warn('Failed to create elbow geometry:', error);
|
|
25204
|
-
return null;
|
|
25205
|
-
}
|
|
25206
|
-
}
|
|
25653
|
+
// Calculate elbow position in segment's local space
|
|
25654
|
+
// The elbow is at the end point of the segment (pathPoints[j + 1])
|
|
25655
|
+
// We need to convert this world position to segment's local space
|
|
25207
25656
|
|
|
25208
|
-
|
|
25209
|
-
|
|
25210
|
-
* @param {THREE.Vector3} point1 - First point
|
|
25211
|
-
* @param {THREE.Vector3} point2 - Joint point
|
|
25212
|
-
* @param {THREE.Vector3} point3 - Third point
|
|
25213
|
-
* @param {number} elbowRadius - Radius of the elbow curve
|
|
25214
|
-
* @returns {THREE.Curve} Curve for the elbow
|
|
25215
|
-
*/
|
|
25216
|
-
}, {
|
|
25217
|
-
key: "createElbowCurve",
|
|
25218
|
-
value: function createElbowCurve(point1, point2, point3, elbowRadius) {
|
|
25219
|
-
// Calculate direction vectors
|
|
25220
|
-
var dir1 = point2.clone().sub(point1).normalize();
|
|
25221
|
-
var dir2 = point3.clone().sub(point2).normalize();
|
|
25657
|
+
// Get the elbow position in world space
|
|
25658
|
+
var elbowWorldPos = pathPoints[j + 1].clone();
|
|
25222
25659
|
|
|
25223
|
-
//
|
|
25224
|
-
//
|
|
25225
|
-
var
|
|
25660
|
+
// Convert world position to segment's local space
|
|
25661
|
+
// First, get the segment's world position
|
|
25662
|
+
var segmentWorldPos = segment.position.clone();
|
|
25226
25663
|
|
|
25227
|
-
// Calculate the offset
|
|
25228
|
-
var
|
|
25664
|
+
// Calculate the offset from segment center to elbow in world space
|
|
25665
|
+
var localOffset = elbowWorldPos.clone().sub(segmentWorldPos);
|
|
25229
25666
|
|
|
25230
|
-
//
|
|
25231
|
-
|
|
25232
|
-
var
|
|
25667
|
+
// Convert the offset to segment's local coordinate system
|
|
25668
|
+
// We need to apply the inverse of the segment's rotation
|
|
25669
|
+
var inverseQuaternion = segment.quaternion.clone().invert();
|
|
25670
|
+
localOffset.applyQuaternion(inverseQuaternion);
|
|
25233
25671
|
|
|
25234
|
-
//
|
|
25235
|
-
|
|
25236
|
-
var controlPoint = point2.clone();
|
|
25672
|
+
// Set elbow position in local space
|
|
25673
|
+
elbow.position.copy(localOffset);
|
|
25237
25674
|
|
|
25238
|
-
//
|
|
25239
|
-
|
|
25240
|
-
|
|
25675
|
+
// Add elbow as a child of the segment
|
|
25676
|
+
segment.add(elbow);
|
|
25677
|
+
console.log("\u2705 Elbow sphere added as child of segment at local position (".concat(localOffset.x.toFixed(2), ", ").concat(localOffset.y.toFixed(2), ", ").concat(localOffset.z.toFixed(2), ")"));
|
|
25241
25678
|
}
|
|
25242
25679
|
|
|
25243
25680
|
/**
|
|
@@ -26405,7 +26842,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26405
26842
|
// ============================================================================
|
|
26406
26843
|
|
|
26407
26844
|
/**
|
|
26408
|
-
* Enrich sceneData with worldBoundingBox for segments
|
|
26845
|
+
* Enrich sceneData with worldBoundingBox for segments and components
|
|
26409
26846
|
* Connectors remain with just position information
|
|
26410
26847
|
* @param {Object} sceneData - Original scene data
|
|
26411
26848
|
* @returns {Object} Enriched scene data (shallow copy with modifications)
|
|
@@ -26422,9 +26859,9 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26422
26859
|
return enriched;
|
|
26423
26860
|
}
|
|
26424
26861
|
|
|
26425
|
-
// Process children to add worldBoundingBox to segments
|
|
26862
|
+
// Process children to add worldBoundingBox to segments and components
|
|
26426
26863
|
enriched.children = sceneData.children.map(function (child) {
|
|
26427
|
-
//
|
|
26864
|
+
// Enrich segments (check if objectType is 'segment' in userData)
|
|
26428
26865
|
if (child.userData && child.userData.objectType === 'segment') {
|
|
26429
26866
|
// Find the actual segment object in the scene
|
|
26430
26867
|
var segmentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
@@ -26447,7 +26884,31 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26447
26884
|
}
|
|
26448
26885
|
}
|
|
26449
26886
|
|
|
26450
|
-
//
|
|
26887
|
+
// Enrich components (check if objectType is 'component' in userData)
|
|
26888
|
+
if (child.userData && child.userData.objectType === 'component') {
|
|
26889
|
+
// Find the actual component object in the scene
|
|
26890
|
+
var componentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
26891
|
+
if (componentObject) {
|
|
26892
|
+
// Compute world bounding box
|
|
26893
|
+
var _worldBBox = new THREE__namespace.Box3().setFromObject(componentObject);
|
|
26894
|
+
console.log("\uD83D\uDD04 Updated worldBoundingBox for component ".concat(child.uuid, ": min=[").concat(_worldBBox.min.x.toFixed(2), ", ").concat(_worldBBox.min.y.toFixed(2), ", ").concat(_worldBBox.min.z.toFixed(2), "], max=[").concat(_worldBBox.max.x.toFixed(2), ", ").concat(_worldBBox.max.y.toFixed(2), ", ").concat(_worldBBox.max.z.toFixed(2), "]"));
|
|
26895
|
+
|
|
26896
|
+
// Return enriched component data with worldBoundingBox in userData
|
|
26897
|
+
// Note: pathfinder expects arrays [x, y, z] format for min/max
|
|
26898
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
26899
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
26900
|
+
worldBoundingBox: {
|
|
26901
|
+
min: [_worldBBox.min.x, _worldBBox.min.y, _worldBBox.min.z],
|
|
26902
|
+
max: [_worldBBox.max.x, _worldBBox.max.y, _worldBBox.max.z]
|
|
26903
|
+
}
|
|
26904
|
+
})
|
|
26905
|
+
});
|
|
26906
|
+
} else {
|
|
26907
|
+
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
26908
|
+
}
|
|
26909
|
+
}
|
|
26910
|
+
|
|
26911
|
+
// For non-segments and non-components (including connectors), return as-is
|
|
26451
26912
|
return child;
|
|
26452
26913
|
});
|
|
26453
26914
|
return enriched;
|
|
@@ -33427,7 +33888,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
33427
33888
|
* Initialize the CentralPlant manager
|
|
33428
33889
|
*
|
|
33429
33890
|
* @constructor
|
|
33430
|
-
* @version 0.1.
|
|
33891
|
+
* @version 0.1.60
|
|
33431
33892
|
* @updated 2025-10-22
|
|
33432
33893
|
*
|
|
33433
33894
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|