@2112-lab/central-plant 0.1.55 → 0.1.59
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 +186 -31
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/components/transformOperationsManager.js +157 -26
- 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 +157 -26
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +28 -4
- package/package.json +4 -3
package/dist/bundle/index.js
CHANGED
|
@@ -19059,10 +19059,15 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19059
19059
|
console.error("\u274C translateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
19060
19060
|
return false;
|
|
19061
19061
|
}
|
|
19062
|
-
|
|
19063
|
-
// Apply the translation
|
|
19064
19062
|
console.log("\uD83D\uDD04 translateComponent(): Translating component ".concat(componentId, " on ").concat(axis, " axis by ").concat(value));
|
|
19065
19063
|
|
|
19064
|
+
// Run collision validation checks before applying the translation
|
|
19065
|
+
var collisionValidation = this.validateTranslateComponentCollisions(component, axis, value);
|
|
19066
|
+
if (!collisionValidation) {
|
|
19067
|
+
return false;
|
|
19068
|
+
}
|
|
19069
|
+
|
|
19070
|
+
// All validations passed - apply the translation
|
|
19066
19071
|
// Update the Three.js object position
|
|
19067
19072
|
component.position[axis] += value;
|
|
19068
19073
|
|
|
@@ -19106,6 +19111,48 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19106
19111
|
return true;
|
|
19107
19112
|
}
|
|
19108
19113
|
|
|
19114
|
+
/**
|
|
19115
|
+
* Validate collision checks for translateComponent operation
|
|
19116
|
+
* @param {THREE.Object3D} component - The component to translate
|
|
19117
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
19118
|
+
* @param {number} value - The value to translate by
|
|
19119
|
+
* @returns {boolean} True if no collisions detected, false if translation would cause collision
|
|
19120
|
+
* @private
|
|
19121
|
+
*/
|
|
19122
|
+
}, {
|
|
19123
|
+
key: "validateTranslateComponentCollisions",
|
|
19124
|
+
value: function validateTranslateComponentCollisions(component, axis, value) {
|
|
19125
|
+
// Store original position for reverting
|
|
19126
|
+
var originalPosition = component.position[axis];
|
|
19127
|
+
|
|
19128
|
+
// Temporarily apply the translation to check for collisions
|
|
19129
|
+
component.position[axis] += value;
|
|
19130
|
+
component.updateMatrix();
|
|
19131
|
+
component.updateMatrixWorld(true);
|
|
19132
|
+
console.log("\uD83D\uDD0D Checking collisions with translated position: ".concat(axis, "=").concat(component.position[axis].toFixed(3)));
|
|
19133
|
+
|
|
19134
|
+
// Check for collision with manual segments
|
|
19135
|
+
var manualSegmentCollision = this.checkComponentManualSegmentCollision(component);
|
|
19136
|
+
if (manualSegmentCollision) {
|
|
19137
|
+
// Revert the translation
|
|
19138
|
+
component.position[axis] = originalPosition;
|
|
19139
|
+
component.updateMatrix();
|
|
19140
|
+
component.updateMatrixWorld(true);
|
|
19141
|
+
console.warn("\u26A0\uFE0F translateComponent(): Translation canceled - component would collide with manual segment");
|
|
19142
|
+
console.warn(" Segment ID: ".concat(manualSegmentCollision.segmentId));
|
|
19143
|
+
console.warn(" Distance to segment: ".concat(manualSegmentCollision.distance.toFixed(3), " (max allowed: 0)"));
|
|
19144
|
+
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), "]"));
|
|
19145
|
+
return false;
|
|
19146
|
+
}
|
|
19147
|
+
console.log('✅ No collisions detected, proceeding with translation');
|
|
19148
|
+
|
|
19149
|
+
// Revert the temporary translation
|
|
19150
|
+
component.position[axis] = originalPosition;
|
|
19151
|
+
component.updateMatrix();
|
|
19152
|
+
component.updateMatrixWorld(true);
|
|
19153
|
+
return true;
|
|
19154
|
+
}
|
|
19155
|
+
|
|
19109
19156
|
/**
|
|
19110
19157
|
* Translate a pipe segment by segmentId
|
|
19111
19158
|
* @param {string} segmentId - The UUID of the pipe segment to translate
|
|
@@ -20185,6 +20232,90 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20185
20232
|
return collision;
|
|
20186
20233
|
}
|
|
20187
20234
|
|
|
20235
|
+
/**
|
|
20236
|
+
* Check if a component would collide with any manual (declared) segment
|
|
20237
|
+
* @param {THREE.Object3D} component - The component to check for collisions
|
|
20238
|
+
* @returns {Object|null} Collision info {segmentId, distance, segmentStart, segmentEnd} if collision detected, null otherwise
|
|
20239
|
+
* @private
|
|
20240
|
+
*/
|
|
20241
|
+
}, {
|
|
20242
|
+
key: "checkComponentManualSegmentCollision",
|
|
20243
|
+
value: function checkComponentManualSegmentCollision(component) {
|
|
20244
|
+
var _this$sceneViewer8,
|
|
20245
|
+
_this3 = this;
|
|
20246
|
+
if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !component) {
|
|
20247
|
+
return null;
|
|
20248
|
+
}
|
|
20249
|
+
|
|
20250
|
+
// Create a bounding box for the component
|
|
20251
|
+
var componentBBox = new THREE__namespace.Box3().setFromObject(component);
|
|
20252
|
+
var collision = null;
|
|
20253
|
+
|
|
20254
|
+
// Traverse scene to find all manual segments (isDeclared === true)
|
|
20255
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
20256
|
+
var _child$userData15, _child$userData16;
|
|
20257
|
+
if (collision) return; // Stop if collision already found
|
|
20258
|
+
|
|
20259
|
+
// Only check manual segments (isDeclared === true)
|
|
20260
|
+
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) {
|
|
20261
|
+
// Get segment endpoints
|
|
20262
|
+
var segmentEndpoints = _this3.getSegmentEndpoints(child);
|
|
20263
|
+
|
|
20264
|
+
// Check if segment intersects with component's bounding box
|
|
20265
|
+
// We'll use a line-box intersection test
|
|
20266
|
+
var line = new THREE__namespace.Line3(segmentEndpoints.start, segmentEndpoints.end);
|
|
20267
|
+
var closestPoint = new THREE__namespace.Vector3();
|
|
20268
|
+
line.closestPointToPoint(componentBBox.getCenter(new THREE__namespace.Vector3()), true, closestPoint);
|
|
20269
|
+
|
|
20270
|
+
// Check if the closest point on the line is within the bounding box
|
|
20271
|
+
if (componentBBox.containsPoint(closestPoint)) {
|
|
20272
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box collision with manual segment:', child.uuid);
|
|
20273
|
+
collision = {
|
|
20274
|
+
segmentId: child.uuid,
|
|
20275
|
+
distance: 0,
|
|
20276
|
+
// Inside the bounding box
|
|
20277
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20278
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20279
|
+
};
|
|
20280
|
+
return;
|
|
20281
|
+
}
|
|
20282
|
+
|
|
20283
|
+
// Also check if either endpoint of the segment is inside the component bounding box
|
|
20284
|
+
if (componentBBox.containsPoint(segmentEndpoints.start) || componentBBox.containsPoint(segmentEndpoints.end)) {
|
|
20285
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box contains manual segment endpoint:', child.uuid);
|
|
20286
|
+
collision = {
|
|
20287
|
+
segmentId: child.uuid,
|
|
20288
|
+
distance: 0,
|
|
20289
|
+
// Inside the bounding box
|
|
20290
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20291
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20292
|
+
};
|
|
20293
|
+
return;
|
|
20294
|
+
}
|
|
20295
|
+
|
|
20296
|
+
// Additionally, check if the segment line intersects any of the bounding box faces
|
|
20297
|
+
// This catches cases where the segment passes through the box without endpoints inside
|
|
20298
|
+
var ray = new THREE__namespace.Ray(segmentEndpoints.start, new THREE__namespace.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize());
|
|
20299
|
+
var segmentLength = segmentEndpoints.start.distanceTo(segmentEndpoints.end);
|
|
20300
|
+
var intersection = ray.intersectBox(componentBBox, new THREE__namespace.Vector3());
|
|
20301
|
+
if (intersection) {
|
|
20302
|
+
var distanceToIntersection = segmentEndpoints.start.distanceTo(intersection);
|
|
20303
|
+
if (distanceToIntersection <= segmentLength) {
|
|
20304
|
+
console.log('⚠️ TransformOperationsManager: Manual segment intersects component bounding box:', child.uuid);
|
|
20305
|
+
collision = {
|
|
20306
|
+
segmentId: child.uuid,
|
|
20307
|
+
distance: 0,
|
|
20308
|
+
// Intersects the bounding box
|
|
20309
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
20310
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
20311
|
+
};
|
|
20312
|
+
}
|
|
20313
|
+
}
|
|
20314
|
+
}
|
|
20315
|
+
});
|
|
20316
|
+
return collision;
|
|
20317
|
+
}
|
|
20318
|
+
|
|
20188
20319
|
/**
|
|
20189
20320
|
* Calculate the minimum distance between two line segments in 3D space
|
|
20190
20321
|
* @param {THREE.Vector3} p1 - Start point of first segment
|
|
@@ -20294,10 +20425,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20294
20425
|
}, {
|
|
20295
20426
|
key: "snapSegmentConnectorsToNearbyEndpoints",
|
|
20296
20427
|
value: function snapSegmentConnectorsToNearbyEndpoints(movedSegment) {
|
|
20297
|
-
var _this$
|
|
20298
|
-
_this$
|
|
20299
|
-
|
|
20300
|
-
if (!movedSegment || !((_this$
|
|
20428
|
+
var _this$sceneViewer9,
|
|
20429
|
+
_this$sceneViewer0,
|
|
20430
|
+
_this4 = this;
|
|
20431
|
+
if (!movedSegment || !((_this$sceneViewer9 = this.sceneViewer) !== null && _this$sceneViewer9 !== void 0 && _this$sceneViewer9.scene)) {
|
|
20301
20432
|
return [];
|
|
20302
20433
|
}
|
|
20303
20434
|
console.log('🔗 Finding adjacent segments connected to moved segment...');
|
|
@@ -20305,8 +20436,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20305
20436
|
// Get the moved segment's connectors
|
|
20306
20437
|
var movedConnectors = [];
|
|
20307
20438
|
movedSegment.traverse(function (child) {
|
|
20308
|
-
var _child$
|
|
20309
|
-
if (((_child$
|
|
20439
|
+
var _child$userData17;
|
|
20440
|
+
if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.objectType) === 'segment-connector') {
|
|
20310
20441
|
movedConnectors.push(child);
|
|
20311
20442
|
}
|
|
20312
20443
|
});
|
|
@@ -20319,7 +20450,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20319
20450
|
var newEndpoints = this.calculateSegmentEndpoints(movedSegment);
|
|
20320
20451
|
|
|
20321
20452
|
// Check scene data for connections involving the moved segment's connectors
|
|
20322
|
-
var connections = ((_this$
|
|
20453
|
+
var connections = ((_this$sceneViewer0 = this.sceneViewer) === null || _this$sceneViewer0 === void 0 || (_this$sceneViewer0 = _this$sceneViewer0.currentSceneData) === null || _this$sceneViewer0 === void 0 ? void 0 : _this$sceneViewer0.connections) || [];
|
|
20323
20454
|
var movedConnectorIds = movedConnectors.map(function (c) {
|
|
20324
20455
|
return c.uuid;
|
|
20325
20456
|
});
|
|
@@ -20354,7 +20485,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20354
20485
|
// Find the adjacent connector in the scene
|
|
20355
20486
|
var adjacentConnector = null;
|
|
20356
20487
|
var adjacentSegment = null;
|
|
20357
|
-
|
|
20488
|
+
_this4.sceneViewer.scene.traverse(function (object) {
|
|
20358
20489
|
var _object$userData;
|
|
20359
20490
|
if (object.uuid === pair.adjacentConnectorId && ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === 'segment-connector') {
|
|
20360
20491
|
adjacentConnector = object;
|
|
@@ -20376,8 +20507,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20376
20507
|
// Get all connectors of the adjacent segment
|
|
20377
20508
|
var adjacentConnectors = [];
|
|
20378
20509
|
adjacentSegment.traverse(function (child) {
|
|
20379
|
-
var _child$
|
|
20380
|
-
if (((_child$
|
|
20510
|
+
var _child$userData18;
|
|
20511
|
+
if (((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.objectType) === 'segment-connector') {
|
|
20381
20512
|
adjacentConnectors.push(child);
|
|
20382
20513
|
}
|
|
20383
20514
|
});
|
|
@@ -20403,12 +20534,12 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20403
20534
|
// Constrain movement to maintain orthogonal alignment
|
|
20404
20535
|
// Horizontal segments: only adjust X and Y, keep Z constant
|
|
20405
20536
|
// Vertical segments: only adjust Z, keep X and Y constant
|
|
20406
|
-
var constrainedPosition =
|
|
20537
|
+
var constrainedPosition = _this4.constrainPositionToOrthogonal(pair.newPosition, stationaryWorldPos, adjacentSegment);
|
|
20407
20538
|
|
|
20408
20539
|
// Recreate the segment mesh with new length using explicit endpoint positions
|
|
20409
20540
|
// Pass the intended positions, not the connector objects (which may have temporary positions)
|
|
20410
20541
|
// Pass movedSegment as activeSegment context so zero-length removal knows which segment to extend
|
|
20411
|
-
|
|
20542
|
+
_this4.recreateSegmentMeshWithNewLength(adjacentSegment, adjacentConnectors, constrainedPosition, stationaryWorldPos, movedSegment);
|
|
20412
20543
|
|
|
20413
20544
|
// CRITICAL: After recreating the mesh, BOTH connectors need to be repositioned
|
|
20414
20545
|
// because the segment's center and rotation have changed
|
|
@@ -20417,13 +20548,13 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20417
20548
|
var movingLocalPos = adjacentSegment.worldToLocal(constrainedPosition.clone());
|
|
20418
20549
|
movingConnector.position.copy(movingLocalPos);
|
|
20419
20550
|
movingConnector.updateMatrixWorld(true);
|
|
20420
|
-
|
|
20551
|
+
_this4.updateConnectorPositionInSceneData(movingConnector, constrainedPosition, adjacentSegment);
|
|
20421
20552
|
|
|
20422
20553
|
// Position stationary connector at its original world position
|
|
20423
20554
|
var stationaryLocalPos = adjacentSegment.worldToLocal(stationaryWorldPos.clone());
|
|
20424
20555
|
stationaryConnector.position.copy(stationaryLocalPos);
|
|
20425
20556
|
stationaryConnector.updateMatrixWorld(true);
|
|
20426
|
-
|
|
20557
|
+
_this4.updateConnectorPositionInSceneData(stationaryConnector, stationaryWorldPos, adjacentSegment);
|
|
20427
20558
|
|
|
20428
20559
|
// Record this connection as satisfied
|
|
20429
20560
|
satisfiedConnections.push({
|
|
@@ -20473,8 +20604,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20473
20604
|
}, {
|
|
20474
20605
|
key: "updateComponentPositionInSceneData",
|
|
20475
20606
|
value: function updateComponentPositionInSceneData(component) {
|
|
20476
|
-
var _this$
|
|
20477
|
-
if (!((_this$
|
|
20607
|
+
var _this$sceneViewer1;
|
|
20608
|
+
if (!((_this$sceneViewer1 = this.sceneViewer) !== null && _this$sceneViewer1 !== void 0 && (_this$sceneViewer1 = _this$sceneViewer1.currentSceneData) !== null && _this$sceneViewer1 !== void 0 && _this$sceneViewer1.scene)) {
|
|
20478
20609
|
console.warn('⚠️ Cannot update component position: currentSceneData not available');
|
|
20479
20610
|
return;
|
|
20480
20611
|
}
|
|
@@ -20500,8 +20631,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20500
20631
|
// Also update child connectors' positions if they exist
|
|
20501
20632
|
if (sceneDataComponent.children) {
|
|
20502
20633
|
sceneDataComponent.children.forEach(function (child) {
|
|
20503
|
-
var _child$
|
|
20504
|
-
if (((_child$
|
|
20634
|
+
var _child$userData19;
|
|
20635
|
+
if (((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.objectType) === 'connector') {
|
|
20505
20636
|
// Find the actual connector object in the scene
|
|
20506
20637
|
var connectorObj = component.children.find(function (c) {
|
|
20507
20638
|
var _c$userData;
|
|
@@ -20537,9 +20668,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20537
20668
|
}, {
|
|
20538
20669
|
key: "updateConnectorPositionInSceneData",
|
|
20539
20670
|
value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
|
|
20540
|
-
var _this$
|
|
20671
|
+
var _this$sceneViewer10;
|
|
20541
20672
|
// Update scene data if available
|
|
20542
|
-
if (!((_this$
|
|
20673
|
+
if (!((_this$sceneViewer10 = this.sceneViewer) !== null && _this$sceneViewer10 !== void 0 && (_this$sceneViewer10 = _this$sceneViewer10.currentSceneData) !== null && _this$sceneViewer10 !== void 0 && _this$sceneViewer10.scene)) {
|
|
20543
20674
|
return;
|
|
20544
20675
|
}
|
|
20545
20676
|
var cleanPosition = function cleanPosition(value) {
|
|
@@ -20830,8 +20961,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20830
20961
|
// Check if either external connector belongs to the active segment
|
|
20831
20962
|
var activeSegmentConnectors = [];
|
|
20832
20963
|
activeSegment.traverse(function (child) {
|
|
20833
|
-
var _child$
|
|
20834
|
-
if (((_child$
|
|
20964
|
+
var _child$userData20;
|
|
20965
|
+
if (((_child$userData20 = child.userData) === null || _child$userData20 === void 0 ? void 0 : _child$userData20.objectType) === 'segment-connector') {
|
|
20835
20966
|
activeSegmentConnectors.push(child.uuid);
|
|
20836
20967
|
}
|
|
20837
20968
|
});
|
|
@@ -20879,8 +21010,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
20879
21010
|
// Get all connectors of the active segment
|
|
20880
21011
|
var activeConnectors = [];
|
|
20881
21012
|
activeSegment.traverse(function (child) {
|
|
20882
|
-
var _child$
|
|
20883
|
-
if (((_child$
|
|
21013
|
+
var _child$userData21;
|
|
21014
|
+
if (((_child$userData21 = child.userData) === null || _child$userData21 === void 0 ? void 0 : _child$userData21.objectType) === 'segment-connector') {
|
|
20884
21015
|
activeConnectors.push(child);
|
|
20885
21016
|
}
|
|
20886
21017
|
});
|
|
@@ -26405,7 +26536,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26405
26536
|
// ============================================================================
|
|
26406
26537
|
|
|
26407
26538
|
/**
|
|
26408
|
-
* Enrich sceneData with worldBoundingBox for segments
|
|
26539
|
+
* Enrich sceneData with worldBoundingBox for segments and components
|
|
26409
26540
|
* Connectors remain with just position information
|
|
26410
26541
|
* @param {Object} sceneData - Original scene data
|
|
26411
26542
|
* @returns {Object} Enriched scene data (shallow copy with modifications)
|
|
@@ -26422,9 +26553,9 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26422
26553
|
return enriched;
|
|
26423
26554
|
}
|
|
26424
26555
|
|
|
26425
|
-
// Process children to add worldBoundingBox to segments
|
|
26556
|
+
// Process children to add worldBoundingBox to segments and components
|
|
26426
26557
|
enriched.children = sceneData.children.map(function (child) {
|
|
26427
|
-
//
|
|
26558
|
+
// Enrich segments (check if objectType is 'segment' in userData)
|
|
26428
26559
|
if (child.userData && child.userData.objectType === 'segment') {
|
|
26429
26560
|
// Find the actual segment object in the scene
|
|
26430
26561
|
var segmentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
@@ -26447,7 +26578,31 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26447
26578
|
}
|
|
26448
26579
|
}
|
|
26449
26580
|
|
|
26450
|
-
//
|
|
26581
|
+
// Enrich components (check if objectType is 'component' in userData)
|
|
26582
|
+
if (child.userData && child.userData.objectType === 'component') {
|
|
26583
|
+
// Find the actual component object in the scene
|
|
26584
|
+
var componentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
26585
|
+
if (componentObject) {
|
|
26586
|
+
// Compute world bounding box
|
|
26587
|
+
var _worldBBox = new THREE__namespace.Box3().setFromObject(componentObject);
|
|
26588
|
+
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), "]"));
|
|
26589
|
+
|
|
26590
|
+
// Return enriched component data with worldBoundingBox in userData
|
|
26591
|
+
// Note: pathfinder expects arrays [x, y, z] format for min/max
|
|
26592
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
26593
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
26594
|
+
worldBoundingBox: {
|
|
26595
|
+
min: [_worldBBox.min.x, _worldBBox.min.y, _worldBBox.min.z],
|
|
26596
|
+
max: [_worldBBox.max.x, _worldBBox.max.y, _worldBBox.max.z]
|
|
26597
|
+
}
|
|
26598
|
+
})
|
|
26599
|
+
});
|
|
26600
|
+
} else {
|
|
26601
|
+
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
26602
|
+
}
|
|
26603
|
+
}
|
|
26604
|
+
|
|
26605
|
+
// For non-segments and non-components (including connectors), return as-is
|
|
26451
26606
|
return child;
|
|
26452
26607
|
});
|
|
26453
26608
|
return enriched;
|
|
@@ -33427,7 +33582,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
33427
33582
|
* Initialize the CentralPlant manager
|
|
33428
33583
|
*
|
|
33429
33584
|
* @constructor
|
|
33430
|
-
* @version 0.1.
|
|
33585
|
+
* @version 0.1.59
|
|
33431
33586
|
* @updated 2025-10-22
|
|
33432
33587
|
*
|
|
33433
33588
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
19
19
|
* Initialize the CentralPlant manager
|
|
20
20
|
*
|
|
21
21
|
* @constructor
|
|
22
|
-
* @version 0.1.
|
|
22
|
+
* @version 0.1.59
|
|
23
23
|
* @updated 2025-10-22
|
|
24
24
|
*
|
|
25
25
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -86,10 +86,15 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
86
86
|
console.error("\u274C translateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
87
87
|
return false;
|
|
88
88
|
}
|
|
89
|
-
|
|
90
|
-
// Apply the translation
|
|
91
89
|
console.log("\uD83D\uDD04 translateComponent(): Translating component ".concat(componentId, " on ").concat(axis, " axis by ").concat(value));
|
|
92
90
|
|
|
91
|
+
// Run collision validation checks before applying the translation
|
|
92
|
+
var collisionValidation = this.validateTranslateComponentCollisions(component, axis, value);
|
|
93
|
+
if (!collisionValidation) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// All validations passed - apply the translation
|
|
93
98
|
// Update the Three.js object position
|
|
94
99
|
component.position[axis] += value;
|
|
95
100
|
|
|
@@ -133,6 +138,48 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
133
138
|
return true;
|
|
134
139
|
}
|
|
135
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Validate collision checks for translateComponent operation
|
|
143
|
+
* @param {THREE.Object3D} component - The component to translate
|
|
144
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
145
|
+
* @param {number} value - The value to translate by
|
|
146
|
+
* @returns {boolean} True if no collisions detected, false if translation would cause collision
|
|
147
|
+
* @private
|
|
148
|
+
*/
|
|
149
|
+
}, {
|
|
150
|
+
key: "validateTranslateComponentCollisions",
|
|
151
|
+
value: function validateTranslateComponentCollisions(component, axis, value) {
|
|
152
|
+
// Store original position for reverting
|
|
153
|
+
var originalPosition = component.position[axis];
|
|
154
|
+
|
|
155
|
+
// Temporarily apply the translation to check for collisions
|
|
156
|
+
component.position[axis] += value;
|
|
157
|
+
component.updateMatrix();
|
|
158
|
+
component.updateMatrixWorld(true);
|
|
159
|
+
console.log("\uD83D\uDD0D Checking collisions with translated position: ".concat(axis, "=").concat(component.position[axis].toFixed(3)));
|
|
160
|
+
|
|
161
|
+
// Check for collision with manual segments
|
|
162
|
+
var manualSegmentCollision = this.checkComponentManualSegmentCollision(component);
|
|
163
|
+
if (manualSegmentCollision) {
|
|
164
|
+
// Revert the translation
|
|
165
|
+
component.position[axis] = originalPosition;
|
|
166
|
+
component.updateMatrix();
|
|
167
|
+
component.updateMatrixWorld(true);
|
|
168
|
+
console.warn("\u26A0\uFE0F translateComponent(): Translation canceled - component would collide with manual segment");
|
|
169
|
+
console.warn(" Segment ID: ".concat(manualSegmentCollision.segmentId));
|
|
170
|
+
console.warn(" Distance to segment: ".concat(manualSegmentCollision.distance.toFixed(3), " (max allowed: 0)"));
|
|
171
|
+
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), "]"));
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
console.log('✅ No collisions detected, proceeding with translation');
|
|
175
|
+
|
|
176
|
+
// Revert the temporary translation
|
|
177
|
+
component.position[axis] = originalPosition;
|
|
178
|
+
component.updateMatrix();
|
|
179
|
+
component.updateMatrixWorld(true);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
136
183
|
/**
|
|
137
184
|
* Translate a pipe segment by segmentId
|
|
138
185
|
* @param {string} segmentId - The UUID of the pipe segment to translate
|
|
@@ -1212,6 +1259,90 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1212
1259
|
return collision;
|
|
1213
1260
|
}
|
|
1214
1261
|
|
|
1262
|
+
/**
|
|
1263
|
+
* Check if a component would collide with any manual (declared) segment
|
|
1264
|
+
* @param {THREE.Object3D} component - The component to check for collisions
|
|
1265
|
+
* @returns {Object|null} Collision info {segmentId, distance, segmentStart, segmentEnd} if collision detected, null otherwise
|
|
1266
|
+
* @private
|
|
1267
|
+
*/
|
|
1268
|
+
}, {
|
|
1269
|
+
key: "checkComponentManualSegmentCollision",
|
|
1270
|
+
value: function checkComponentManualSegmentCollision(component) {
|
|
1271
|
+
var _this$sceneViewer8,
|
|
1272
|
+
_this3 = this;
|
|
1273
|
+
if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !component) {
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// Create a bounding box for the component
|
|
1278
|
+
var componentBBox = new THREE__namespace.Box3().setFromObject(component);
|
|
1279
|
+
var collision = null;
|
|
1280
|
+
|
|
1281
|
+
// Traverse scene to find all manual segments (isDeclared === true)
|
|
1282
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
1283
|
+
var _child$userData15, _child$userData16;
|
|
1284
|
+
if (collision) return; // Stop if collision already found
|
|
1285
|
+
|
|
1286
|
+
// Only check manual segments (isDeclared === true)
|
|
1287
|
+
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) {
|
|
1288
|
+
// Get segment endpoints
|
|
1289
|
+
var segmentEndpoints = _this3.getSegmentEndpoints(child);
|
|
1290
|
+
|
|
1291
|
+
// Check if segment intersects with component's bounding box
|
|
1292
|
+
// We'll use a line-box intersection test
|
|
1293
|
+
var line = new THREE__namespace.Line3(segmentEndpoints.start, segmentEndpoints.end);
|
|
1294
|
+
var closestPoint = new THREE__namespace.Vector3();
|
|
1295
|
+
line.closestPointToPoint(componentBBox.getCenter(new THREE__namespace.Vector3()), true, closestPoint);
|
|
1296
|
+
|
|
1297
|
+
// Check if the closest point on the line is within the bounding box
|
|
1298
|
+
if (componentBBox.containsPoint(closestPoint)) {
|
|
1299
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box collision with manual segment:', child.uuid);
|
|
1300
|
+
collision = {
|
|
1301
|
+
segmentId: child.uuid,
|
|
1302
|
+
distance: 0,
|
|
1303
|
+
// Inside the bounding box
|
|
1304
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1305
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1306
|
+
};
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
// Also check if either endpoint of the segment is inside the component bounding box
|
|
1311
|
+
if (componentBBox.containsPoint(segmentEndpoints.start) || componentBBox.containsPoint(segmentEndpoints.end)) {
|
|
1312
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box contains manual segment endpoint:', child.uuid);
|
|
1313
|
+
collision = {
|
|
1314
|
+
segmentId: child.uuid,
|
|
1315
|
+
distance: 0,
|
|
1316
|
+
// Inside the bounding box
|
|
1317
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1318
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1319
|
+
};
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// Additionally, check if the segment line intersects any of the bounding box faces
|
|
1324
|
+
// This catches cases where the segment passes through the box without endpoints inside
|
|
1325
|
+
var ray = new THREE__namespace.Ray(segmentEndpoints.start, new THREE__namespace.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize());
|
|
1326
|
+
var segmentLength = segmentEndpoints.start.distanceTo(segmentEndpoints.end);
|
|
1327
|
+
var intersection = ray.intersectBox(componentBBox, new THREE__namespace.Vector3());
|
|
1328
|
+
if (intersection) {
|
|
1329
|
+
var distanceToIntersection = segmentEndpoints.start.distanceTo(intersection);
|
|
1330
|
+
if (distanceToIntersection <= segmentLength) {
|
|
1331
|
+
console.log('⚠️ TransformOperationsManager: Manual segment intersects component bounding box:', child.uuid);
|
|
1332
|
+
collision = {
|
|
1333
|
+
segmentId: child.uuid,
|
|
1334
|
+
distance: 0,
|
|
1335
|
+
// Intersects the bounding box
|
|
1336
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1337
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
return collision;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1215
1346
|
/**
|
|
1216
1347
|
* Calculate the minimum distance between two line segments in 3D space
|
|
1217
1348
|
* @param {THREE.Vector3} p1 - Start point of first segment
|
|
@@ -1321,10 +1452,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1321
1452
|
}, {
|
|
1322
1453
|
key: "snapSegmentConnectorsToNearbyEndpoints",
|
|
1323
1454
|
value: function snapSegmentConnectorsToNearbyEndpoints(movedSegment) {
|
|
1324
|
-
var _this$
|
|
1325
|
-
_this$
|
|
1326
|
-
|
|
1327
|
-
if (!movedSegment || !((_this$
|
|
1455
|
+
var _this$sceneViewer9,
|
|
1456
|
+
_this$sceneViewer0,
|
|
1457
|
+
_this4 = this;
|
|
1458
|
+
if (!movedSegment || !((_this$sceneViewer9 = this.sceneViewer) !== null && _this$sceneViewer9 !== void 0 && _this$sceneViewer9.scene)) {
|
|
1328
1459
|
return [];
|
|
1329
1460
|
}
|
|
1330
1461
|
console.log('🔗 Finding adjacent segments connected to moved segment...');
|
|
@@ -1332,8 +1463,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1332
1463
|
// Get the moved segment's connectors
|
|
1333
1464
|
var movedConnectors = [];
|
|
1334
1465
|
movedSegment.traverse(function (child) {
|
|
1335
|
-
var _child$
|
|
1336
|
-
if (((_child$
|
|
1466
|
+
var _child$userData17;
|
|
1467
|
+
if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.objectType) === 'segment-connector') {
|
|
1337
1468
|
movedConnectors.push(child);
|
|
1338
1469
|
}
|
|
1339
1470
|
});
|
|
@@ -1346,7 +1477,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1346
1477
|
var newEndpoints = this.calculateSegmentEndpoints(movedSegment);
|
|
1347
1478
|
|
|
1348
1479
|
// Check scene data for connections involving the moved segment's connectors
|
|
1349
|
-
var connections = ((_this$
|
|
1480
|
+
var connections = ((_this$sceneViewer0 = this.sceneViewer) === null || _this$sceneViewer0 === void 0 || (_this$sceneViewer0 = _this$sceneViewer0.currentSceneData) === null || _this$sceneViewer0 === void 0 ? void 0 : _this$sceneViewer0.connections) || [];
|
|
1350
1481
|
var movedConnectorIds = movedConnectors.map(function (c) {
|
|
1351
1482
|
return c.uuid;
|
|
1352
1483
|
});
|
|
@@ -1381,7 +1512,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1381
1512
|
// Find the adjacent connector in the scene
|
|
1382
1513
|
var adjacentConnector = null;
|
|
1383
1514
|
var adjacentSegment = null;
|
|
1384
|
-
|
|
1515
|
+
_this4.sceneViewer.scene.traverse(function (object) {
|
|
1385
1516
|
var _object$userData;
|
|
1386
1517
|
if (object.uuid === pair.adjacentConnectorId && ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === 'segment-connector') {
|
|
1387
1518
|
adjacentConnector = object;
|
|
@@ -1403,8 +1534,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1403
1534
|
// Get all connectors of the adjacent segment
|
|
1404
1535
|
var adjacentConnectors = [];
|
|
1405
1536
|
adjacentSegment.traverse(function (child) {
|
|
1406
|
-
var _child$
|
|
1407
|
-
if (((_child$
|
|
1537
|
+
var _child$userData18;
|
|
1538
|
+
if (((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.objectType) === 'segment-connector') {
|
|
1408
1539
|
adjacentConnectors.push(child);
|
|
1409
1540
|
}
|
|
1410
1541
|
});
|
|
@@ -1430,12 +1561,12 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1430
1561
|
// Constrain movement to maintain orthogonal alignment
|
|
1431
1562
|
// Horizontal segments: only adjust X and Y, keep Z constant
|
|
1432
1563
|
// Vertical segments: only adjust Z, keep X and Y constant
|
|
1433
|
-
var constrainedPosition =
|
|
1564
|
+
var constrainedPosition = _this4.constrainPositionToOrthogonal(pair.newPosition, stationaryWorldPos, adjacentSegment);
|
|
1434
1565
|
|
|
1435
1566
|
// Recreate the segment mesh with new length using explicit endpoint positions
|
|
1436
1567
|
// Pass the intended positions, not the connector objects (which may have temporary positions)
|
|
1437
1568
|
// Pass movedSegment as activeSegment context so zero-length removal knows which segment to extend
|
|
1438
|
-
|
|
1569
|
+
_this4.recreateSegmentMeshWithNewLength(adjacentSegment, adjacentConnectors, constrainedPosition, stationaryWorldPos, movedSegment);
|
|
1439
1570
|
|
|
1440
1571
|
// CRITICAL: After recreating the mesh, BOTH connectors need to be repositioned
|
|
1441
1572
|
// because the segment's center and rotation have changed
|
|
@@ -1444,13 +1575,13 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1444
1575
|
var movingLocalPos = adjacentSegment.worldToLocal(constrainedPosition.clone());
|
|
1445
1576
|
movingConnector.position.copy(movingLocalPos);
|
|
1446
1577
|
movingConnector.updateMatrixWorld(true);
|
|
1447
|
-
|
|
1578
|
+
_this4.updateConnectorPositionInSceneData(movingConnector, constrainedPosition, adjacentSegment);
|
|
1448
1579
|
|
|
1449
1580
|
// Position stationary connector at its original world position
|
|
1450
1581
|
var stationaryLocalPos = adjacentSegment.worldToLocal(stationaryWorldPos.clone());
|
|
1451
1582
|
stationaryConnector.position.copy(stationaryLocalPos);
|
|
1452
1583
|
stationaryConnector.updateMatrixWorld(true);
|
|
1453
|
-
|
|
1584
|
+
_this4.updateConnectorPositionInSceneData(stationaryConnector, stationaryWorldPos, adjacentSegment);
|
|
1454
1585
|
|
|
1455
1586
|
// Record this connection as satisfied
|
|
1456
1587
|
satisfiedConnections.push({
|
|
@@ -1500,8 +1631,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1500
1631
|
}, {
|
|
1501
1632
|
key: "updateComponentPositionInSceneData",
|
|
1502
1633
|
value: function updateComponentPositionInSceneData(component) {
|
|
1503
|
-
var _this$
|
|
1504
|
-
if (!((_this$
|
|
1634
|
+
var _this$sceneViewer1;
|
|
1635
|
+
if (!((_this$sceneViewer1 = this.sceneViewer) !== null && _this$sceneViewer1 !== void 0 && (_this$sceneViewer1 = _this$sceneViewer1.currentSceneData) !== null && _this$sceneViewer1 !== void 0 && _this$sceneViewer1.scene)) {
|
|
1505
1636
|
console.warn('⚠️ Cannot update component position: currentSceneData not available');
|
|
1506
1637
|
return;
|
|
1507
1638
|
}
|
|
@@ -1527,8 +1658,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1527
1658
|
// Also update child connectors' positions if they exist
|
|
1528
1659
|
if (sceneDataComponent.children) {
|
|
1529
1660
|
sceneDataComponent.children.forEach(function (child) {
|
|
1530
|
-
var _child$
|
|
1531
|
-
if (((_child$
|
|
1661
|
+
var _child$userData19;
|
|
1662
|
+
if (((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.objectType) === 'connector') {
|
|
1532
1663
|
// Find the actual connector object in the scene
|
|
1533
1664
|
var connectorObj = component.children.find(function (c) {
|
|
1534
1665
|
var _c$userData;
|
|
@@ -1564,9 +1695,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1564
1695
|
}, {
|
|
1565
1696
|
key: "updateConnectorPositionInSceneData",
|
|
1566
1697
|
value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
|
|
1567
|
-
var _this$
|
|
1698
|
+
var _this$sceneViewer10;
|
|
1568
1699
|
// Update scene data if available
|
|
1569
|
-
if (!((_this$
|
|
1700
|
+
if (!((_this$sceneViewer10 = this.sceneViewer) !== null && _this$sceneViewer10 !== void 0 && (_this$sceneViewer10 = _this$sceneViewer10.currentSceneData) !== null && _this$sceneViewer10 !== void 0 && _this$sceneViewer10.scene)) {
|
|
1570
1701
|
return;
|
|
1571
1702
|
}
|
|
1572
1703
|
var cleanPosition = function cleanPosition(value) {
|
|
@@ -1857,8 +1988,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1857
1988
|
// Check if either external connector belongs to the active segment
|
|
1858
1989
|
var activeSegmentConnectors = [];
|
|
1859
1990
|
activeSegment.traverse(function (child) {
|
|
1860
|
-
var _child$
|
|
1861
|
-
if (((_child$
|
|
1991
|
+
var _child$userData20;
|
|
1992
|
+
if (((_child$userData20 = child.userData) === null || _child$userData20 === void 0 ? void 0 : _child$userData20.objectType) === 'segment-connector') {
|
|
1862
1993
|
activeSegmentConnectors.push(child.uuid);
|
|
1863
1994
|
}
|
|
1864
1995
|
});
|
|
@@ -1906,8 +2037,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1906
2037
|
// Get all connectors of the active segment
|
|
1907
2038
|
var activeConnectors = [];
|
|
1908
2039
|
activeSegment.traverse(function (child) {
|
|
1909
|
-
var _child$
|
|
1910
|
-
if (((_child$
|
|
2040
|
+
var _child$userData21;
|
|
2041
|
+
if (((_child$userData21 = child.userData) === null || _child$userData21 === void 0 ? void 0 : _child$userData21.objectType) === 'segment-connector') {
|
|
1911
2042
|
activeConnectors.push(child);
|
|
1912
2043
|
}
|
|
1913
2044
|
});
|
|
@@ -130,7 +130,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
130
130
|
// ============================================================================
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
|
-
* Enrich sceneData with worldBoundingBox for segments
|
|
133
|
+
* Enrich sceneData with worldBoundingBox for segments and components
|
|
134
134
|
* Connectors remain with just position information
|
|
135
135
|
* @param {Object} sceneData - Original scene data
|
|
136
136
|
* @returns {Object} Enriched scene data (shallow copy with modifications)
|
|
@@ -147,9 +147,9 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
147
147
|
return enriched;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
// Process children to add worldBoundingBox to segments
|
|
150
|
+
// Process children to add worldBoundingBox to segments and components
|
|
151
151
|
enriched.children = sceneData.children.map(function (child) {
|
|
152
|
-
//
|
|
152
|
+
// Enrich segments (check if objectType is 'segment' in userData)
|
|
153
153
|
if (child.userData && child.userData.objectType === 'segment') {
|
|
154
154
|
// Find the actual segment object in the scene
|
|
155
155
|
var segmentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
@@ -172,7 +172,31 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
//
|
|
175
|
+
// Enrich components (check if objectType is 'component' in userData)
|
|
176
|
+
if (child.userData && child.userData.objectType === 'component') {
|
|
177
|
+
// Find the actual component object in the scene
|
|
178
|
+
var componentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
179
|
+
if (componentObject) {
|
|
180
|
+
// Compute world bounding box
|
|
181
|
+
var _worldBBox = new THREE__namespace.Box3().setFromObject(componentObject);
|
|
182
|
+
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), "]"));
|
|
183
|
+
|
|
184
|
+
// Return enriched component data with worldBoundingBox in userData
|
|
185
|
+
// Note: pathfinder expects arrays [x, y, z] format for min/max
|
|
186
|
+
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child), {}, {
|
|
187
|
+
userData: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, child.userData), {}, {
|
|
188
|
+
worldBoundingBox: {
|
|
189
|
+
min: [_worldBBox.min.x, _worldBBox.min.y, _worldBBox.min.z],
|
|
190
|
+
max: [_worldBBox.max.x, _worldBBox.max.y, _worldBBox.max.z]
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// For non-segments and non-components (including connectors), return as-is
|
|
176
200
|
return child;
|
|
177
201
|
});
|
|
178
202
|
return enriched;
|
|
@@ -15,7 +15,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
15
15
|
* Initialize the CentralPlant manager
|
|
16
16
|
*
|
|
17
17
|
* @constructor
|
|
18
|
-
* @version 0.1.
|
|
18
|
+
* @version 0.1.59
|
|
19
19
|
* @updated 2025-10-22
|
|
20
20
|
*
|
|
21
21
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -62,10 +62,15 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
62
62
|
console.error("\u274C translateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
63
63
|
return false;
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
// Apply the translation
|
|
67
65
|
console.log("\uD83D\uDD04 translateComponent(): Translating component ".concat(componentId, " on ").concat(axis, " axis by ").concat(value));
|
|
68
66
|
|
|
67
|
+
// Run collision validation checks before applying the translation
|
|
68
|
+
var collisionValidation = this.validateTranslateComponentCollisions(component, axis, value);
|
|
69
|
+
if (!collisionValidation) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// All validations passed - apply the translation
|
|
69
74
|
// Update the Three.js object position
|
|
70
75
|
component.position[axis] += value;
|
|
71
76
|
|
|
@@ -109,6 +114,48 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
109
114
|
return true;
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Validate collision checks for translateComponent operation
|
|
119
|
+
* @param {THREE.Object3D} component - The component to translate
|
|
120
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
121
|
+
* @param {number} value - The value to translate by
|
|
122
|
+
* @returns {boolean} True if no collisions detected, false if translation would cause collision
|
|
123
|
+
* @private
|
|
124
|
+
*/
|
|
125
|
+
}, {
|
|
126
|
+
key: "validateTranslateComponentCollisions",
|
|
127
|
+
value: function validateTranslateComponentCollisions(component, axis, value) {
|
|
128
|
+
// Store original position for reverting
|
|
129
|
+
var originalPosition = component.position[axis];
|
|
130
|
+
|
|
131
|
+
// Temporarily apply the translation to check for collisions
|
|
132
|
+
component.position[axis] += value;
|
|
133
|
+
component.updateMatrix();
|
|
134
|
+
component.updateMatrixWorld(true);
|
|
135
|
+
console.log("\uD83D\uDD0D Checking collisions with translated position: ".concat(axis, "=").concat(component.position[axis].toFixed(3)));
|
|
136
|
+
|
|
137
|
+
// Check for collision with manual segments
|
|
138
|
+
var manualSegmentCollision = this.checkComponentManualSegmentCollision(component);
|
|
139
|
+
if (manualSegmentCollision) {
|
|
140
|
+
// Revert the translation
|
|
141
|
+
component.position[axis] = originalPosition;
|
|
142
|
+
component.updateMatrix();
|
|
143
|
+
component.updateMatrixWorld(true);
|
|
144
|
+
console.warn("\u26A0\uFE0F translateComponent(): Translation canceled - component would collide with manual segment");
|
|
145
|
+
console.warn(" Segment ID: ".concat(manualSegmentCollision.segmentId));
|
|
146
|
+
console.warn(" Distance to segment: ".concat(manualSegmentCollision.distance.toFixed(3), " (max allowed: 0)"));
|
|
147
|
+
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), "]"));
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
console.log('✅ No collisions detected, proceeding with translation');
|
|
151
|
+
|
|
152
|
+
// Revert the temporary translation
|
|
153
|
+
component.position[axis] = originalPosition;
|
|
154
|
+
component.updateMatrix();
|
|
155
|
+
component.updateMatrixWorld(true);
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
112
159
|
/**
|
|
113
160
|
* Translate a pipe segment by segmentId
|
|
114
161
|
* @param {string} segmentId - The UUID of the pipe segment to translate
|
|
@@ -1188,6 +1235,90 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1188
1235
|
return collision;
|
|
1189
1236
|
}
|
|
1190
1237
|
|
|
1238
|
+
/**
|
|
1239
|
+
* Check if a component would collide with any manual (declared) segment
|
|
1240
|
+
* @param {THREE.Object3D} component - The component to check for collisions
|
|
1241
|
+
* @returns {Object|null} Collision info {segmentId, distance, segmentStart, segmentEnd} if collision detected, null otherwise
|
|
1242
|
+
* @private
|
|
1243
|
+
*/
|
|
1244
|
+
}, {
|
|
1245
|
+
key: "checkComponentManualSegmentCollision",
|
|
1246
|
+
value: function checkComponentManualSegmentCollision(component) {
|
|
1247
|
+
var _this$sceneViewer8,
|
|
1248
|
+
_this3 = this;
|
|
1249
|
+
if (!((_this$sceneViewer8 = this.sceneViewer) !== null && _this$sceneViewer8 !== void 0 && _this$sceneViewer8.scene) || !component) {
|
|
1250
|
+
return null;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
// Create a bounding box for the component
|
|
1254
|
+
var componentBBox = new THREE.Box3().setFromObject(component);
|
|
1255
|
+
var collision = null;
|
|
1256
|
+
|
|
1257
|
+
// Traverse scene to find all manual segments (isDeclared === true)
|
|
1258
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
1259
|
+
var _child$userData15, _child$userData16;
|
|
1260
|
+
if (collision) return; // Stop if collision already found
|
|
1261
|
+
|
|
1262
|
+
// Only check manual segments (isDeclared === true)
|
|
1263
|
+
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) {
|
|
1264
|
+
// Get segment endpoints
|
|
1265
|
+
var segmentEndpoints = _this3.getSegmentEndpoints(child);
|
|
1266
|
+
|
|
1267
|
+
// Check if segment intersects with component's bounding box
|
|
1268
|
+
// We'll use a line-box intersection test
|
|
1269
|
+
var line = new THREE.Line3(segmentEndpoints.start, segmentEndpoints.end);
|
|
1270
|
+
var closestPoint = new THREE.Vector3();
|
|
1271
|
+
line.closestPointToPoint(componentBBox.getCenter(new THREE.Vector3()), true, closestPoint);
|
|
1272
|
+
|
|
1273
|
+
// Check if the closest point on the line is within the bounding box
|
|
1274
|
+
if (componentBBox.containsPoint(closestPoint)) {
|
|
1275
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box collision with manual segment:', child.uuid);
|
|
1276
|
+
collision = {
|
|
1277
|
+
segmentId: child.uuid,
|
|
1278
|
+
distance: 0,
|
|
1279
|
+
// Inside the bounding box
|
|
1280
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1281
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1282
|
+
};
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// Also check if either endpoint of the segment is inside the component bounding box
|
|
1287
|
+
if (componentBBox.containsPoint(segmentEndpoints.start) || componentBBox.containsPoint(segmentEndpoints.end)) {
|
|
1288
|
+
console.log('⚠️ TransformOperationsManager: Component bounding box contains manual segment endpoint:', child.uuid);
|
|
1289
|
+
collision = {
|
|
1290
|
+
segmentId: child.uuid,
|
|
1291
|
+
distance: 0,
|
|
1292
|
+
// Inside the bounding box
|
|
1293
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1294
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1295
|
+
};
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// Additionally, check if the segment line intersects any of the bounding box faces
|
|
1300
|
+
// This catches cases where the segment passes through the box without endpoints inside
|
|
1301
|
+
var ray = new THREE.Ray(segmentEndpoints.start, new THREE.Vector3().subVectors(segmentEndpoints.end, segmentEndpoints.start).normalize());
|
|
1302
|
+
var segmentLength = segmentEndpoints.start.distanceTo(segmentEndpoints.end);
|
|
1303
|
+
var intersection = ray.intersectBox(componentBBox, new THREE.Vector3());
|
|
1304
|
+
if (intersection) {
|
|
1305
|
+
var distanceToIntersection = segmentEndpoints.start.distanceTo(intersection);
|
|
1306
|
+
if (distanceToIntersection <= segmentLength) {
|
|
1307
|
+
console.log('⚠️ TransformOperationsManager: Manual segment intersects component bounding box:', child.uuid);
|
|
1308
|
+
collision = {
|
|
1309
|
+
segmentId: child.uuid,
|
|
1310
|
+
distance: 0,
|
|
1311
|
+
// Intersects the bounding box
|
|
1312
|
+
segmentStart: segmentEndpoints.start.clone(),
|
|
1313
|
+
segmentEnd: segmentEndpoints.end.clone()
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
return collision;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1191
1322
|
/**
|
|
1192
1323
|
* Calculate the minimum distance between two line segments in 3D space
|
|
1193
1324
|
* @param {THREE.Vector3} p1 - Start point of first segment
|
|
@@ -1297,10 +1428,10 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1297
1428
|
}, {
|
|
1298
1429
|
key: "snapSegmentConnectorsToNearbyEndpoints",
|
|
1299
1430
|
value: function snapSegmentConnectorsToNearbyEndpoints(movedSegment) {
|
|
1300
|
-
var _this$
|
|
1301
|
-
_this$
|
|
1302
|
-
|
|
1303
|
-
if (!movedSegment || !((_this$
|
|
1431
|
+
var _this$sceneViewer9,
|
|
1432
|
+
_this$sceneViewer0,
|
|
1433
|
+
_this4 = this;
|
|
1434
|
+
if (!movedSegment || !((_this$sceneViewer9 = this.sceneViewer) !== null && _this$sceneViewer9 !== void 0 && _this$sceneViewer9.scene)) {
|
|
1304
1435
|
return [];
|
|
1305
1436
|
}
|
|
1306
1437
|
console.log('🔗 Finding adjacent segments connected to moved segment...');
|
|
@@ -1308,8 +1439,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1308
1439
|
// Get the moved segment's connectors
|
|
1309
1440
|
var movedConnectors = [];
|
|
1310
1441
|
movedSegment.traverse(function (child) {
|
|
1311
|
-
var _child$
|
|
1312
|
-
if (((_child$
|
|
1442
|
+
var _child$userData17;
|
|
1443
|
+
if (((_child$userData17 = child.userData) === null || _child$userData17 === void 0 ? void 0 : _child$userData17.objectType) === 'segment-connector') {
|
|
1313
1444
|
movedConnectors.push(child);
|
|
1314
1445
|
}
|
|
1315
1446
|
});
|
|
@@ -1322,7 +1453,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1322
1453
|
var newEndpoints = this.calculateSegmentEndpoints(movedSegment);
|
|
1323
1454
|
|
|
1324
1455
|
// Check scene data for connections involving the moved segment's connectors
|
|
1325
|
-
var connections = ((_this$
|
|
1456
|
+
var connections = ((_this$sceneViewer0 = this.sceneViewer) === null || _this$sceneViewer0 === void 0 || (_this$sceneViewer0 = _this$sceneViewer0.currentSceneData) === null || _this$sceneViewer0 === void 0 ? void 0 : _this$sceneViewer0.connections) || [];
|
|
1326
1457
|
var movedConnectorIds = movedConnectors.map(function (c) {
|
|
1327
1458
|
return c.uuid;
|
|
1328
1459
|
});
|
|
@@ -1357,7 +1488,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1357
1488
|
// Find the adjacent connector in the scene
|
|
1358
1489
|
var adjacentConnector = null;
|
|
1359
1490
|
var adjacentSegment = null;
|
|
1360
|
-
|
|
1491
|
+
_this4.sceneViewer.scene.traverse(function (object) {
|
|
1361
1492
|
var _object$userData;
|
|
1362
1493
|
if (object.uuid === pair.adjacentConnectorId && ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.objectType) === 'segment-connector') {
|
|
1363
1494
|
adjacentConnector = object;
|
|
@@ -1379,8 +1510,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1379
1510
|
// Get all connectors of the adjacent segment
|
|
1380
1511
|
var adjacentConnectors = [];
|
|
1381
1512
|
adjacentSegment.traverse(function (child) {
|
|
1382
|
-
var _child$
|
|
1383
|
-
if (((_child$
|
|
1513
|
+
var _child$userData18;
|
|
1514
|
+
if (((_child$userData18 = child.userData) === null || _child$userData18 === void 0 ? void 0 : _child$userData18.objectType) === 'segment-connector') {
|
|
1384
1515
|
adjacentConnectors.push(child);
|
|
1385
1516
|
}
|
|
1386
1517
|
});
|
|
@@ -1406,12 +1537,12 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1406
1537
|
// Constrain movement to maintain orthogonal alignment
|
|
1407
1538
|
// Horizontal segments: only adjust X and Y, keep Z constant
|
|
1408
1539
|
// Vertical segments: only adjust Z, keep X and Y constant
|
|
1409
|
-
var constrainedPosition =
|
|
1540
|
+
var constrainedPosition = _this4.constrainPositionToOrthogonal(pair.newPosition, stationaryWorldPos, adjacentSegment);
|
|
1410
1541
|
|
|
1411
1542
|
// Recreate the segment mesh with new length using explicit endpoint positions
|
|
1412
1543
|
// Pass the intended positions, not the connector objects (which may have temporary positions)
|
|
1413
1544
|
// Pass movedSegment as activeSegment context so zero-length removal knows which segment to extend
|
|
1414
|
-
|
|
1545
|
+
_this4.recreateSegmentMeshWithNewLength(adjacentSegment, adjacentConnectors, constrainedPosition, stationaryWorldPos, movedSegment);
|
|
1415
1546
|
|
|
1416
1547
|
// CRITICAL: After recreating the mesh, BOTH connectors need to be repositioned
|
|
1417
1548
|
// because the segment's center and rotation have changed
|
|
@@ -1420,13 +1551,13 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1420
1551
|
var movingLocalPos = adjacentSegment.worldToLocal(constrainedPosition.clone());
|
|
1421
1552
|
movingConnector.position.copy(movingLocalPos);
|
|
1422
1553
|
movingConnector.updateMatrixWorld(true);
|
|
1423
|
-
|
|
1554
|
+
_this4.updateConnectorPositionInSceneData(movingConnector, constrainedPosition, adjacentSegment);
|
|
1424
1555
|
|
|
1425
1556
|
// Position stationary connector at its original world position
|
|
1426
1557
|
var stationaryLocalPos = adjacentSegment.worldToLocal(stationaryWorldPos.clone());
|
|
1427
1558
|
stationaryConnector.position.copy(stationaryLocalPos);
|
|
1428
1559
|
stationaryConnector.updateMatrixWorld(true);
|
|
1429
|
-
|
|
1560
|
+
_this4.updateConnectorPositionInSceneData(stationaryConnector, stationaryWorldPos, adjacentSegment);
|
|
1430
1561
|
|
|
1431
1562
|
// Record this connection as satisfied
|
|
1432
1563
|
satisfiedConnections.push({
|
|
@@ -1476,8 +1607,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1476
1607
|
}, {
|
|
1477
1608
|
key: "updateComponentPositionInSceneData",
|
|
1478
1609
|
value: function updateComponentPositionInSceneData(component) {
|
|
1479
|
-
var _this$
|
|
1480
|
-
if (!((_this$
|
|
1610
|
+
var _this$sceneViewer1;
|
|
1611
|
+
if (!((_this$sceneViewer1 = this.sceneViewer) !== null && _this$sceneViewer1 !== void 0 && (_this$sceneViewer1 = _this$sceneViewer1.currentSceneData) !== null && _this$sceneViewer1 !== void 0 && _this$sceneViewer1.scene)) {
|
|
1481
1612
|
console.warn('⚠️ Cannot update component position: currentSceneData not available');
|
|
1482
1613
|
return;
|
|
1483
1614
|
}
|
|
@@ -1503,8 +1634,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1503
1634
|
// Also update child connectors' positions if they exist
|
|
1504
1635
|
if (sceneDataComponent.children) {
|
|
1505
1636
|
sceneDataComponent.children.forEach(function (child) {
|
|
1506
|
-
var _child$
|
|
1507
|
-
if (((_child$
|
|
1637
|
+
var _child$userData19;
|
|
1638
|
+
if (((_child$userData19 = child.userData) === null || _child$userData19 === void 0 ? void 0 : _child$userData19.objectType) === 'connector') {
|
|
1508
1639
|
// Find the actual connector object in the scene
|
|
1509
1640
|
var connectorObj = component.children.find(function (c) {
|
|
1510
1641
|
var _c$userData;
|
|
@@ -1540,9 +1671,9 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1540
1671
|
}, {
|
|
1541
1672
|
key: "updateConnectorPositionInSceneData",
|
|
1542
1673
|
value: function updateConnectorPositionInSceneData(connector, worldPosition, parentSegment) {
|
|
1543
|
-
var _this$
|
|
1674
|
+
var _this$sceneViewer10;
|
|
1544
1675
|
// Update scene data if available
|
|
1545
|
-
if (!((_this$
|
|
1676
|
+
if (!((_this$sceneViewer10 = this.sceneViewer) !== null && _this$sceneViewer10 !== void 0 && (_this$sceneViewer10 = _this$sceneViewer10.currentSceneData) !== null && _this$sceneViewer10 !== void 0 && _this$sceneViewer10.scene)) {
|
|
1546
1677
|
return;
|
|
1547
1678
|
}
|
|
1548
1679
|
var cleanPosition = function cleanPosition(value) {
|
|
@@ -1833,8 +1964,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1833
1964
|
// Check if either external connector belongs to the active segment
|
|
1834
1965
|
var activeSegmentConnectors = [];
|
|
1835
1966
|
activeSegment.traverse(function (child) {
|
|
1836
|
-
var _child$
|
|
1837
|
-
if (((_child$
|
|
1967
|
+
var _child$userData20;
|
|
1968
|
+
if (((_child$userData20 = child.userData) === null || _child$userData20 === void 0 ? void 0 : _child$userData20.objectType) === 'segment-connector') {
|
|
1838
1969
|
activeSegmentConnectors.push(child.uuid);
|
|
1839
1970
|
}
|
|
1840
1971
|
});
|
|
@@ -1882,8 +2013,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
1882
2013
|
// Get all connectors of the active segment
|
|
1883
2014
|
var activeConnectors = [];
|
|
1884
2015
|
activeSegment.traverse(function (child) {
|
|
1885
|
-
var _child$
|
|
1886
|
-
if (((_child$
|
|
2016
|
+
var _child$userData21;
|
|
2017
|
+
if (((_child$userData21 = child.userData) === null || _child$userData21 === void 0 ? void 0 : _child$userData21.objectType) === 'segment-connector') {
|
|
1887
2018
|
activeConnectors.push(child);
|
|
1888
2019
|
}
|
|
1889
2020
|
});
|
|
@@ -106,7 +106,7 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
106
106
|
// ============================================================================
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* Enrich sceneData with worldBoundingBox for segments
|
|
109
|
+
* Enrich sceneData with worldBoundingBox for segments and components
|
|
110
110
|
* Connectors remain with just position information
|
|
111
111
|
* @param {Object} sceneData - Original scene data
|
|
112
112
|
* @returns {Object} Enriched scene data (shallow copy with modifications)
|
|
@@ -123,9 +123,9 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
123
123
|
return enriched;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
// Process children to add worldBoundingBox to segments
|
|
126
|
+
// Process children to add worldBoundingBox to segments and components
|
|
127
127
|
enriched.children = sceneData.children.map(function (child) {
|
|
128
|
-
//
|
|
128
|
+
// Enrich segments (check if objectType is 'segment' in userData)
|
|
129
129
|
if (child.userData && child.userData.objectType === 'segment') {
|
|
130
130
|
// Find the actual segment object in the scene
|
|
131
131
|
var segmentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
@@ -148,7 +148,31 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
//
|
|
151
|
+
// Enrich components (check if objectType is 'component' in userData)
|
|
152
|
+
if (child.userData && child.userData.objectType === 'component') {
|
|
153
|
+
// Find the actual component object in the scene
|
|
154
|
+
var componentObject = _this3.sceneViewer.scene.getObjectByProperty('uuid', child.uuid);
|
|
155
|
+
if (componentObject) {
|
|
156
|
+
// Compute world bounding box
|
|
157
|
+
var _worldBBox = new THREE.Box3().setFromObject(componentObject);
|
|
158
|
+
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), "]"));
|
|
159
|
+
|
|
160
|
+
// Return enriched component data with worldBoundingBox in userData
|
|
161
|
+
// Note: pathfinder expects arrays [x, y, z] format for min/max
|
|
162
|
+
return _objectSpread2(_objectSpread2({}, child), {}, {
|
|
163
|
+
userData: _objectSpread2(_objectSpread2({}, child.userData), {}, {
|
|
164
|
+
worldBoundingBox: {
|
|
165
|
+
min: [_worldBBox.min.x, _worldBBox.min.y, _worldBBox.min.z],
|
|
166
|
+
max: [_worldBBox.max.x, _worldBBox.max.y, _worldBBox.max.z]
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
});
|
|
170
|
+
} else {
|
|
171
|
+
console.warn("\u26A0\uFE0F Could not find component object in scene: ".concat(child.uuid));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// For non-segments and non-components (including connectors), return as-is
|
|
152
176
|
return child;
|
|
153
177
|
});
|
|
154
178
|
return enriched;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2112-lab/central-plant",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.59",
|
|
4
4
|
"description": "Utility modules for the Central Plant Application",
|
|
5
5
|
"main": "dist/bundle/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"build:types": "node -e \"require('fs').copyFileSync('src/index.d.ts', 'dist/index.d.ts')\"",
|
|
20
20
|
"dev": "rollup -c -w",
|
|
21
21
|
"prepublishOnly": "npm run build",
|
|
22
|
-
"docs": "jsdoc -c jsdoc.json"
|
|
22
|
+
"docs": "jsdoc -c jsdoc.json",
|
|
23
|
+
"release": "npm install @2112-lab/pathfinder@latest && npm version patch && npm publish"
|
|
23
24
|
},
|
|
24
25
|
"keywords": [
|
|
25
26
|
"central-plant",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"author": "CentralPlant Team",
|
|
31
32
|
"license": "MIT",
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@2112-lab/pathfinder": "1.0.34",
|
|
34
|
+
"@2112-lab/pathfinder": "^1.0.34",
|
|
34
35
|
"stats.js": "^0.17.0",
|
|
35
36
|
"three": "^0.177.0"
|
|
36
37
|
},
|