@2112-lab/central-plant 0.1.44 → 0.1.45
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 +95 -137
- package/dist/cjs/src/core/centralPlant.js +1 -1
- package/dist/cjs/src/managers/components/transformOperationsManager.js +47 -11
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +47 -125
- package/dist/esm/src/core/centralPlant.js +1 -1
- package/dist/esm/src/managers/components/transformOperationsManager.js +47 -11
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +47 -125
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -18765,7 +18765,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
18765
18765
|
}, {
|
|
18766
18766
|
key: "translateSegment",
|
|
18767
18767
|
value: function translateSegment(segmentId, axis, value) {
|
|
18768
|
-
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$
|
|
18768
|
+
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$man3, _this$sceneViewer$man4, _this$sceneViewer$man5;
|
|
18769
18769
|
// Validate parameters
|
|
18770
18770
|
if (!segmentId || !axis || value === undefined || value === null) {
|
|
18771
18771
|
console.error('❌ translateSegment(): Invalid parameters');
|
|
@@ -18842,7 +18842,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
18842
18842
|
});
|
|
18843
18843
|
console.log("\uD83D\uDD0D After filtering, ".concat(componentConnectorsAtEndpoints.length, " component connectors at endpoints"));
|
|
18844
18844
|
if (componentConnectorsAtEndpoints.length > 0) {
|
|
18845
|
-
var _this$sceneViewer2;
|
|
18845
|
+
var _this$sceneViewer2, _this$sceneViewer$man2;
|
|
18846
18846
|
console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' has component connectors at endpoints."));
|
|
18847
18847
|
console.log(" Found ".concat(componentConnectorsAtEndpoints.length, " component connector(s):"), componentConnectorsAtEndpoints.map(function (c) {
|
|
18848
18848
|
var _c$parent3;
|
|
@@ -18858,9 +18858,45 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
18858
18858
|
console.warn('⚠️ Segment splitting is disabled. Cannot translate segments with component connectors at endpoints.');
|
|
18859
18859
|
return false;
|
|
18860
18860
|
}
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18861
|
+
|
|
18862
|
+
// Split the segment and translate the free half
|
|
18863
|
+
console.log('✂️ Splitting segment to enable translation of the free half...');
|
|
18864
|
+
|
|
18865
|
+
// Get sceneOperationsManager
|
|
18866
|
+
var _sceneOperationsManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.sceneOperationsManager;
|
|
18867
|
+
if (!_sceneOperationsManager) {
|
|
18868
|
+
console.error('❌ translateSegment(): SceneOperationsManager not available for splitting');
|
|
18869
|
+
return false;
|
|
18870
|
+
}
|
|
18871
|
+
try {
|
|
18872
|
+
var splitResult = _sceneOperationsManager.splitSegment(segment);
|
|
18873
|
+
if (splitResult && splitResult.segment1 && splitResult.segment2) {
|
|
18874
|
+
console.log("\u2705 Segment split: ".concat(splitResult.segment1.uuid, " (").concat(splitResult.segment1.geometry.parameters.height, "), ").concat(splitResult.segment2.uuid, " (").concat(splitResult.segment2.geometry.parameters.height, ")"));
|
|
18875
|
+
|
|
18876
|
+
// Determine which segment is the longer one (free side) to translate
|
|
18877
|
+
var segment1Length = splitResult.segment1.geometry.parameters.height;
|
|
18878
|
+
var segment2Length = splitResult.segment2.geometry.parameters.height;
|
|
18879
|
+
|
|
18880
|
+
// The longer segment is the one WITHOUT the component connector
|
|
18881
|
+
var segmentToTranslate = segment1Length > segment2Length ? splitResult.segment1 : splitResult.segment2;
|
|
18882
|
+
console.log("\uD83C\uDFAF Translating ".concat(segmentToTranslate.uuid, " (length: ").concat(segmentToTranslate.geometry.parameters.height, ") - the free segment"));
|
|
18883
|
+
|
|
18884
|
+
// Now translate the chosen segment (recursive call with the new segment)
|
|
18885
|
+
var translateSuccess = this.translateSegment(segmentToTranslate.uuid, axis, value);
|
|
18886
|
+
if (!translateSuccess) {
|
|
18887
|
+
console.error('❌ translateSegment(): Failed to translate split segment half');
|
|
18888
|
+
return false;
|
|
18889
|
+
}
|
|
18890
|
+
console.log('✅ Split and translate operation completed successfully');
|
|
18891
|
+
return true;
|
|
18892
|
+
} else {
|
|
18893
|
+
console.error('❌ translateSegment(): Split operation failed');
|
|
18894
|
+
return false;
|
|
18895
|
+
}
|
|
18896
|
+
} catch (error) {
|
|
18897
|
+
console.error('❌ translateSegment(): Error splitting segment:', error);
|
|
18898
|
+
return false;
|
|
18899
|
+
}
|
|
18864
18900
|
}
|
|
18865
18901
|
console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
|
|
18866
18902
|
|
|
@@ -18925,8 +18961,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
18925
18961
|
}
|
|
18926
18962
|
|
|
18927
18963
|
// Validate PathfindingManager and SceneOperationsManager availability
|
|
18928
|
-
var pathfindingManager = (_this$sceneViewer$
|
|
18929
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
18964
|
+
var pathfindingManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.pathfindingManager;
|
|
18965
|
+
var sceneOperationsManager = (_this$sceneViewer$man4 = this.sceneViewer.managers) === null || _this$sceneViewer$man4 === void 0 ? void 0 : _this$sceneViewer$man4.sceneOperationsManager;
|
|
18930
18966
|
if (!pathfindingManager || !sceneOperationsManager) {
|
|
18931
18967
|
console.error('❌ translateSegment(): PathfindingManager or SceneOperationsManager not available');
|
|
18932
18968
|
return false;
|
|
@@ -18961,7 +18997,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
18961
18997
|
|
|
18962
18998
|
// Store transform parameters using the OperationHistoryManager BEFORE updatePaths
|
|
18963
18999
|
// This is critical so that intersection detection can undo the operation
|
|
18964
|
-
if ((_this$sceneViewer$
|
|
19000
|
+
if ((_this$sceneViewer$man5 = this.sceneViewer.managers) !== null && _this$sceneViewer$man5 !== void 0 && _this$sceneViewer$man5.operationHistory) {
|
|
18965
19001
|
this.sceneViewer.managers.operationHistory.addToOperationHistory('translateSegment', {
|
|
18966
19002
|
segmentId: segmentId,
|
|
18967
19003
|
axis: axis,
|
|
@@ -19009,11 +19045,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19009
19045
|
}, {
|
|
19010
19046
|
key: "translateGateway",
|
|
19011
19047
|
value: function translateGateway(gatewayId, axis, value) {
|
|
19012
|
-
var _this$sceneViewer$
|
|
19048
|
+
var _this$sceneViewer$man6, _this$sceneViewer$man7;
|
|
19013
19049
|
console.log("[Pathfinder] translateGateway started");
|
|
19014
19050
|
|
|
19015
19051
|
// Store transform parameters using the OperationHistoryManager
|
|
19016
|
-
if ((_this$sceneViewer$
|
|
19052
|
+
if ((_this$sceneViewer$man6 = this.sceneViewer.managers) !== null && _this$sceneViewer$man6 !== void 0 && _this$sceneViewer$man6.operationHistoryManager) {
|
|
19017
19053
|
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateGateway', {
|
|
19018
19054
|
gatewayId: gatewayId,
|
|
19019
19055
|
axis: axis,
|
|
@@ -19064,7 +19100,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
19064
19100
|
|
|
19065
19101
|
// Handle manual gateway transformation (convert to declared and process connections)
|
|
19066
19102
|
console.log('🔧 Handling manual gateway transformation via SceneOperationsManager');
|
|
19067
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
19103
|
+
var sceneOperationsManager = (_this$sceneViewer$man7 = this.sceneViewer.managers) === null || _this$sceneViewer$man7 === void 0 ? void 0 : _this$sceneViewer$man7.sceneOperationsManager;
|
|
19068
19104
|
if (!sceneOperationsManager) {
|
|
19069
19105
|
console.error('❌ translateGateway(): SceneOperationsManager not available');
|
|
19070
19106
|
return false;
|
|
@@ -24629,6 +24665,10 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
24629
24665
|
|
|
24630
24666
|
var pipeRadius = 0.1;
|
|
24631
24667
|
var pipeMaterial = this.createPipeMaterial(crosscubeTextureSet);
|
|
24668
|
+
|
|
24669
|
+
// Shared geometry for all connector caps to improve performance
|
|
24670
|
+
var capGeometry = new THREE__namespace.SphereGeometry(pipeRadius, 16, 16);
|
|
24671
|
+
this.registerDisposable(capGeometry);
|
|
24632
24672
|
paths.forEach(function (pathData, index) {
|
|
24633
24673
|
if (pathData.path && pathData.path.length >= 2) {
|
|
24634
24674
|
// Convert path points to Vector3 objects for consistent handling
|
|
@@ -24682,15 +24722,14 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
24682
24722
|
pathTo: pathData.to
|
|
24683
24723
|
};
|
|
24684
24724
|
|
|
24725
|
+
// Create caps at both ends of every segment
|
|
24726
|
+
_this3.createSegmentCaps(cylinder, capGeometry, pipeMaterial, globalSegmentIndex);
|
|
24727
|
+
|
|
24685
24728
|
// Increment global segment counter
|
|
24686
24729
|
globalSegmentIndex++;
|
|
24687
24730
|
|
|
24688
24731
|
// Add segment directly to scene instead of to polyline
|
|
24689
24732
|
sceneViewer.scene.add(cylinder);
|
|
24690
|
-
|
|
24691
|
-
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
24692
|
-
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
|
|
24693
|
-
);
|
|
24694
24733
|
}
|
|
24695
24734
|
console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
|
|
24696
24735
|
}
|
|
@@ -24698,130 +24737,49 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
24698
24737
|
}
|
|
24699
24738
|
|
|
24700
24739
|
/**
|
|
24701
|
-
* Create
|
|
24702
|
-
*
|
|
24703
|
-
* @param {
|
|
24704
|
-
* @param {
|
|
24705
|
-
* @param {THREE.Material}
|
|
24706
|
-
* @param {
|
|
24707
|
-
* @param {number} index - Path index for naming
|
|
24708
|
-
* @param {THREE.Scene} scene - Scene object to add elbow to directly
|
|
24740
|
+
* Create connector caps at both segment endpoints as children of the segment
|
|
24741
|
+
* Caps are positioned in local coordinates to match manual segment connector positioning
|
|
24742
|
+
* @param {THREE.Mesh} segment - The parent segment mesh
|
|
24743
|
+
* @param {THREE.BufferGeometry} capGeometry - Shared geometry for caps
|
|
24744
|
+
* @param {THREE.Material} material - Material for the caps
|
|
24745
|
+
* @param {number} segmentIndex - Global segment index
|
|
24709
24746
|
*/
|
|
24710
24747
|
}, {
|
|
24711
|
-
key: "
|
|
24712
|
-
value: function
|
|
24713
|
-
|
|
24714
|
-
if (j >= pathPoints.length - 2) {
|
|
24715
|
-
return;
|
|
24716
|
-
}
|
|
24717
|
-
var currentSegment = pathPoints[j + 1].clone().sub(pathPoints[j]).normalize();
|
|
24718
|
-
var nextSegment = pathPoints[j + 2].clone().sub(pathPoints[j + 1]).normalize();
|
|
24719
|
-
|
|
24720
|
-
// Check if there's actually a direction change (not just continuing straight)
|
|
24721
|
-
var angle = currentSegment.angleTo(nextSegment);
|
|
24722
|
-
var minAngle = Math.PI / 36; // 5 degrees minimum for creating an elbow
|
|
24723
|
-
|
|
24724
|
-
if (angle <= minAngle) {
|
|
24725
|
-
return; // No significant direction change
|
|
24726
|
-
}
|
|
24727
|
-
var elbowGeometry = this.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
|
|
24728
|
-
if (!elbowGeometry) {
|
|
24729
|
-
return; // Failed to create geometry
|
|
24730
|
-
}
|
|
24731
|
-
var elbow = new THREE__namespace.Mesh(elbowGeometry, pipeMaterial);
|
|
24732
|
-
elbow.castShadow = true;
|
|
24733
|
-
elbow.receiveShadow = true;
|
|
24734
|
-
|
|
24735
|
-
// Make elbows selectable as well
|
|
24736
|
-
var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
|
|
24737
|
-
elbow.uuid = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
|
|
24738
|
-
|
|
24739
|
-
// Add userData for elbows too
|
|
24740
|
-
elbow.userData = {
|
|
24741
|
-
isPipeElbow: true,
|
|
24742
|
-
elbowId: elbowId,
|
|
24743
|
-
elbowIndex: j,
|
|
24744
|
-
pathFrom: pathData.from,
|
|
24745
|
-
pathTo: pathData.to,
|
|
24746
|
-
angle: (angle * 180 / Math.PI).toFixed(1),
|
|
24747
|
-
// Add component data for tooltips
|
|
24748
|
-
component: {
|
|
24749
|
-
type: 'PipeElbow',
|
|
24750
|
-
attributes: {
|
|
24751
|
-
angle: {
|
|
24752
|
-
key: 'Bend Angle',
|
|
24753
|
-
value: (angle * 180 / Math.PI).toFixed(1),
|
|
24754
|
-
unit: '°'
|
|
24755
|
-
}
|
|
24756
|
-
}
|
|
24757
|
-
}
|
|
24758
|
-
};
|
|
24759
|
-
scene.add(elbow);
|
|
24760
|
-
}
|
|
24761
|
-
|
|
24762
|
-
/**
|
|
24763
|
-
* Create smooth elbow geometry to connect two pipe segments (optimized for 90-degree angles)
|
|
24764
|
-
* @param {THREE.Vector3} point1 - First point (before the joint)
|
|
24765
|
-
* @param {THREE.Vector3} point2 - Joint point (center of the elbow)
|
|
24766
|
-
* @param {THREE.Vector3} point3 - Third point (after the joint)
|
|
24767
|
-
* @param {number} radius - Pipe radius
|
|
24768
|
-
* @returns {THREE.BufferGeometry} Elbow geometry
|
|
24769
|
-
*/
|
|
24770
|
-
}, {
|
|
24771
|
-
key: "createElbowGeometry",
|
|
24772
|
-
value: function createElbowGeometry(point1, point2, point3, radius) {
|
|
24773
|
-
try {
|
|
24774
|
-
// Fixed elbow radius for 90-degree bends (simplified)
|
|
24775
|
-
var elbowRadius = radius * 3;
|
|
24776
|
-
|
|
24777
|
-
// Create a curve for the 90-degree elbow
|
|
24778
|
-
var curve = this.createElbowCurve(point1, point2, point3, elbowRadius);
|
|
24779
|
-
|
|
24780
|
-
// Fixed tubular segments for 90-degree bends (quarter circle)
|
|
24781
|
-
var tubularSegments = 12; // Good balance for smooth 90° curves
|
|
24782
|
-
var radialSegments = 16;
|
|
24783
|
-
var closed = false;
|
|
24784
|
-
var elbowGeometry = new THREE__namespace.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
|
|
24785
|
-
return elbowGeometry;
|
|
24786
|
-
} catch (error) {
|
|
24787
|
-
console.warn('Failed to create elbow geometry:', error);
|
|
24788
|
-
return null;
|
|
24789
|
-
}
|
|
24790
|
-
}
|
|
24791
|
-
|
|
24792
|
-
/**
|
|
24793
|
-
* Create a smooth curve for the 90-degree elbow joint (simplified)
|
|
24794
|
-
* @param {THREE.Vector3} point1 - First point
|
|
24795
|
-
* @param {THREE.Vector3} point2 - Joint point
|
|
24796
|
-
* @param {THREE.Vector3} point3 - Third point
|
|
24797
|
-
* @param {number} elbowRadius - Radius of the elbow curve
|
|
24798
|
-
* @returns {THREE.Curve} Curve for the elbow
|
|
24799
|
-
*/
|
|
24800
|
-
}, {
|
|
24801
|
-
key: "createElbowCurve",
|
|
24802
|
-
value: function createElbowCurve(point1, point2, point3, elbowRadius) {
|
|
24803
|
-
// Calculate direction vectors
|
|
24804
|
-
var dir1 = point2.clone().sub(point1).normalize();
|
|
24805
|
-
var dir2 = point3.clone().sub(point2).normalize();
|
|
24806
|
-
|
|
24807
|
-
// For 90-degree bends, we can use a simpler approach with a quarter circle
|
|
24808
|
-
// The curve radius is proportional to the elbow radius
|
|
24809
|
-
var curveRadius = elbowRadius * 0.001;
|
|
24748
|
+
key: "createSegmentCaps",
|
|
24749
|
+
value: function createSegmentCaps(segment, capGeometry, material, segmentIndex) {
|
|
24750
|
+
var length = segment.geometry.parameters.height;
|
|
24810
24751
|
|
|
24811
|
-
//
|
|
24812
|
-
var
|
|
24813
|
-
|
|
24814
|
-
|
|
24815
|
-
|
|
24816
|
-
|
|
24817
|
-
|
|
24818
|
-
|
|
24819
|
-
|
|
24820
|
-
|
|
24821
|
-
|
|
24822
|
-
|
|
24823
|
-
|
|
24824
|
-
|
|
24752
|
+
// Create start cap
|
|
24753
|
+
var startCap = new THREE__namespace.Mesh(capGeometry, material);
|
|
24754
|
+
// Position at segment start in local space (matches manual segment connector positioning)
|
|
24755
|
+
startCap.position.set(0, -length / 2, 0);
|
|
24756
|
+
startCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-START");
|
|
24757
|
+
startCap.userData = {
|
|
24758
|
+
objectType: 'segment-cap',
|
|
24759
|
+
capType: 'start',
|
|
24760
|
+
segmentId: segment.uuid,
|
|
24761
|
+
segmentIndex: segmentIndex
|
|
24762
|
+
};
|
|
24763
|
+
startCap.castShadow = true;
|
|
24764
|
+
startCap.receiveShadow = true;
|
|
24765
|
+
segment.add(startCap);
|
|
24766
|
+
console.log("\uD83D\uDD35 Created START cap for segment ".concat(segmentIndex, " at local position (0, ").concat(-length / 2, ", 0)"));
|
|
24767
|
+
|
|
24768
|
+
// Create end cap
|
|
24769
|
+
var endCap = new THREE__namespace.Mesh(capGeometry, material);
|
|
24770
|
+
// Position at segment end in local space (matches manual segment connector positioning)
|
|
24771
|
+
endCap.position.set(0, length / 2, 0);
|
|
24772
|
+
endCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-END");
|
|
24773
|
+
endCap.userData = {
|
|
24774
|
+
objectType: 'segment-cap',
|
|
24775
|
+
capType: 'end',
|
|
24776
|
+
segmentId: segment.uuid,
|
|
24777
|
+
segmentIndex: segmentIndex
|
|
24778
|
+
};
|
|
24779
|
+
endCap.castShadow = true;
|
|
24780
|
+
endCap.receiveShadow = true;
|
|
24781
|
+
segment.add(endCap);
|
|
24782
|
+
console.log("\uD83D\uDD35 Created END cap for segment ".concat(segmentIndex, " at local position (0, ").concat(length / 2, ", 0)"));
|
|
24825
24783
|
}
|
|
24826
24784
|
|
|
24827
24785
|
/**
|
|
@@ -32488,7 +32446,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
32488
32446
|
* Initialize the CentralPlant manager
|
|
32489
32447
|
*
|
|
32490
32448
|
* @constructor
|
|
32491
|
-
* @version 0.1.
|
|
32449
|
+
* @version 0.1.45
|
|
32492
32450
|
* @updated 2025-10-22
|
|
32493
32451
|
*
|
|
32494
32452
|
* @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.45
|
|
23
23
|
* @updated 2025-10-22
|
|
24
24
|
*
|
|
25
25
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -126,7 +126,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
126
126
|
}, {
|
|
127
127
|
key: "translateSegment",
|
|
128
128
|
value: function translateSegment(segmentId, axis, value) {
|
|
129
|
-
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$
|
|
129
|
+
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$man3, _this$sceneViewer$man4, _this$sceneViewer$man5;
|
|
130
130
|
// Validate parameters
|
|
131
131
|
if (!segmentId || !axis || value === undefined || value === null) {
|
|
132
132
|
console.error('❌ translateSegment(): Invalid parameters');
|
|
@@ -203,7 +203,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
203
203
|
});
|
|
204
204
|
console.log("\uD83D\uDD0D After filtering, ".concat(componentConnectorsAtEndpoints.length, " component connectors at endpoints"));
|
|
205
205
|
if (componentConnectorsAtEndpoints.length > 0) {
|
|
206
|
-
var _this$sceneViewer2;
|
|
206
|
+
var _this$sceneViewer2, _this$sceneViewer$man2;
|
|
207
207
|
console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' has component connectors at endpoints."));
|
|
208
208
|
console.log(" Found ".concat(componentConnectorsAtEndpoints.length, " component connector(s):"), componentConnectorsAtEndpoints.map(function (c) {
|
|
209
209
|
var _c$parent3;
|
|
@@ -219,9 +219,45 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
219
219
|
console.warn('⚠️ Segment splitting is disabled. Cannot translate segments with component connectors at endpoints.');
|
|
220
220
|
return false;
|
|
221
221
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
|
|
223
|
+
// Split the segment and translate the free half
|
|
224
|
+
console.log('✂️ Splitting segment to enable translation of the free half...');
|
|
225
|
+
|
|
226
|
+
// Get sceneOperationsManager
|
|
227
|
+
var _sceneOperationsManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.sceneOperationsManager;
|
|
228
|
+
if (!_sceneOperationsManager) {
|
|
229
|
+
console.error('❌ translateSegment(): SceneOperationsManager not available for splitting');
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
var splitResult = _sceneOperationsManager.splitSegment(segment);
|
|
234
|
+
if (splitResult && splitResult.segment1 && splitResult.segment2) {
|
|
235
|
+
console.log("\u2705 Segment split: ".concat(splitResult.segment1.uuid, " (").concat(splitResult.segment1.geometry.parameters.height, "), ").concat(splitResult.segment2.uuid, " (").concat(splitResult.segment2.geometry.parameters.height, ")"));
|
|
236
|
+
|
|
237
|
+
// Determine which segment is the longer one (free side) to translate
|
|
238
|
+
var segment1Length = splitResult.segment1.geometry.parameters.height;
|
|
239
|
+
var segment2Length = splitResult.segment2.geometry.parameters.height;
|
|
240
|
+
|
|
241
|
+
// The longer segment is the one WITHOUT the component connector
|
|
242
|
+
var segmentToTranslate = segment1Length > segment2Length ? splitResult.segment1 : splitResult.segment2;
|
|
243
|
+
console.log("\uD83C\uDFAF Translating ".concat(segmentToTranslate.uuid, " (length: ").concat(segmentToTranslate.geometry.parameters.height, ") - the free segment"));
|
|
244
|
+
|
|
245
|
+
// Now translate the chosen segment (recursive call with the new segment)
|
|
246
|
+
var translateSuccess = this.translateSegment(segmentToTranslate.uuid, axis, value);
|
|
247
|
+
if (!translateSuccess) {
|
|
248
|
+
console.error('❌ translateSegment(): Failed to translate split segment half');
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
console.log('✅ Split and translate operation completed successfully');
|
|
252
|
+
return true;
|
|
253
|
+
} else {
|
|
254
|
+
console.error('❌ translateSegment(): Split operation failed');
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
} catch (error) {
|
|
258
|
+
console.error('❌ translateSegment(): Error splitting segment:', error);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
225
261
|
}
|
|
226
262
|
console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
|
|
227
263
|
|
|
@@ -286,8 +322,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
286
322
|
}
|
|
287
323
|
|
|
288
324
|
// Validate PathfindingManager and SceneOperationsManager availability
|
|
289
|
-
var pathfindingManager = (_this$sceneViewer$
|
|
290
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
325
|
+
var pathfindingManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.pathfindingManager;
|
|
326
|
+
var sceneOperationsManager = (_this$sceneViewer$man4 = this.sceneViewer.managers) === null || _this$sceneViewer$man4 === void 0 ? void 0 : _this$sceneViewer$man4.sceneOperationsManager;
|
|
291
327
|
if (!pathfindingManager || !sceneOperationsManager) {
|
|
292
328
|
console.error('❌ translateSegment(): PathfindingManager or SceneOperationsManager not available');
|
|
293
329
|
return false;
|
|
@@ -322,7 +358,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
322
358
|
|
|
323
359
|
// Store transform parameters using the OperationHistoryManager BEFORE updatePaths
|
|
324
360
|
// This is critical so that intersection detection can undo the operation
|
|
325
|
-
if ((_this$sceneViewer$
|
|
361
|
+
if ((_this$sceneViewer$man5 = this.sceneViewer.managers) !== null && _this$sceneViewer$man5 !== void 0 && _this$sceneViewer$man5.operationHistory) {
|
|
326
362
|
this.sceneViewer.managers.operationHistory.addToOperationHistory('translateSegment', {
|
|
327
363
|
segmentId: segmentId,
|
|
328
364
|
axis: axis,
|
|
@@ -370,11 +406,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
370
406
|
}, {
|
|
371
407
|
key: "translateGateway",
|
|
372
408
|
value: function translateGateway(gatewayId, axis, value) {
|
|
373
|
-
var _this$sceneViewer$
|
|
409
|
+
var _this$sceneViewer$man6, _this$sceneViewer$man7;
|
|
374
410
|
console.log("[Pathfinder] translateGateway started");
|
|
375
411
|
|
|
376
412
|
// Store transform parameters using the OperationHistoryManager
|
|
377
|
-
if ((_this$sceneViewer$
|
|
413
|
+
if ((_this$sceneViewer$man6 = this.sceneViewer.managers) !== null && _this$sceneViewer$man6 !== void 0 && _this$sceneViewer$man6.operationHistoryManager) {
|
|
378
414
|
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateGateway', {
|
|
379
415
|
gatewayId: gatewayId,
|
|
380
416
|
axis: axis,
|
|
@@ -425,7 +461,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
425
461
|
|
|
426
462
|
// Handle manual gateway transformation (convert to declared and process connections)
|
|
427
463
|
console.log('🔧 Handling manual gateway transformation via SceneOperationsManager');
|
|
428
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
464
|
+
var sceneOperationsManager = (_this$sceneViewer$man7 = this.sceneViewer.managers) === null || _this$sceneViewer$man7 === void 0 ? void 0 : _this$sceneViewer$man7.sceneOperationsManager;
|
|
429
465
|
if (!sceneOperationsManager) {
|
|
430
466
|
console.error('❌ translateGateway(): SceneOperationsManager not available');
|
|
431
467
|
return false;
|
|
@@ -184,6 +184,10 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
184
184
|
|
|
185
185
|
var pipeRadius = 0.1;
|
|
186
186
|
var pipeMaterial = this.createPipeMaterial(crosscubeTextureSet);
|
|
187
|
+
|
|
188
|
+
// Shared geometry for all connector caps to improve performance
|
|
189
|
+
var capGeometry = new THREE__namespace.SphereGeometry(pipeRadius, 16, 16);
|
|
190
|
+
this.registerDisposable(capGeometry);
|
|
187
191
|
paths.forEach(function (pathData, index) {
|
|
188
192
|
if (pathData.path && pathData.path.length >= 2) {
|
|
189
193
|
// Convert path points to Vector3 objects for consistent handling
|
|
@@ -237,15 +241,14 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
237
241
|
pathTo: pathData.to
|
|
238
242
|
};
|
|
239
243
|
|
|
244
|
+
// Create caps at both ends of every segment
|
|
245
|
+
_this3.createSegmentCaps(cylinder, capGeometry, pipeMaterial, globalSegmentIndex);
|
|
246
|
+
|
|
240
247
|
// Increment global segment counter
|
|
241
248
|
globalSegmentIndex++;
|
|
242
249
|
|
|
243
250
|
// Add segment directly to scene instead of to polyline
|
|
244
251
|
sceneViewer.scene.add(cylinder);
|
|
245
|
-
|
|
246
|
-
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
247
|
-
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
|
|
248
|
-
);
|
|
249
252
|
}
|
|
250
253
|
console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
|
|
251
254
|
}
|
|
@@ -253,130 +256,49 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
253
256
|
}
|
|
254
257
|
|
|
255
258
|
/**
|
|
256
|
-
* Create
|
|
257
|
-
*
|
|
258
|
-
* @param {
|
|
259
|
-
* @param {
|
|
260
|
-
* @param {THREE.Material}
|
|
261
|
-
* @param {
|
|
262
|
-
* @param {number} index - Path index for naming
|
|
263
|
-
* @param {THREE.Scene} scene - Scene object to add elbow to directly
|
|
259
|
+
* Create connector caps at both segment endpoints as children of the segment
|
|
260
|
+
* Caps are positioned in local coordinates to match manual segment connector positioning
|
|
261
|
+
* @param {THREE.Mesh} segment - The parent segment mesh
|
|
262
|
+
* @param {THREE.BufferGeometry} capGeometry - Shared geometry for caps
|
|
263
|
+
* @param {THREE.Material} material - Material for the caps
|
|
264
|
+
* @param {number} segmentIndex - Global segment index
|
|
264
265
|
*/
|
|
265
266
|
}, {
|
|
266
|
-
key: "
|
|
267
|
-
value: function
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return; // No significant direction change
|
|
281
|
-
}
|
|
282
|
-
var elbowGeometry = this.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
|
|
283
|
-
if (!elbowGeometry) {
|
|
284
|
-
return; // Failed to create geometry
|
|
285
|
-
}
|
|
286
|
-
var elbow = new THREE__namespace.Mesh(elbowGeometry, pipeMaterial);
|
|
287
|
-
elbow.castShadow = true;
|
|
288
|
-
elbow.receiveShadow = true;
|
|
289
|
-
|
|
290
|
-
// Make elbows selectable as well
|
|
291
|
-
var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
|
|
292
|
-
elbow.uuid = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
|
|
293
|
-
|
|
294
|
-
// Add userData for elbows too
|
|
295
|
-
elbow.userData = {
|
|
296
|
-
isPipeElbow: true,
|
|
297
|
-
elbowId: elbowId,
|
|
298
|
-
elbowIndex: j,
|
|
299
|
-
pathFrom: pathData.from,
|
|
300
|
-
pathTo: pathData.to,
|
|
301
|
-
angle: (angle * 180 / Math.PI).toFixed(1),
|
|
302
|
-
// Add component data for tooltips
|
|
303
|
-
component: {
|
|
304
|
-
type: 'PipeElbow',
|
|
305
|
-
attributes: {
|
|
306
|
-
angle: {
|
|
307
|
-
key: 'Bend Angle',
|
|
308
|
-
value: (angle * 180 / Math.PI).toFixed(1),
|
|
309
|
-
unit: '°'
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
267
|
+
key: "createSegmentCaps",
|
|
268
|
+
value: function createSegmentCaps(segment, capGeometry, material, segmentIndex) {
|
|
269
|
+
var length = segment.geometry.parameters.height;
|
|
270
|
+
|
|
271
|
+
// Create start cap
|
|
272
|
+
var startCap = new THREE__namespace.Mesh(capGeometry, material);
|
|
273
|
+
// Position at segment start in local space (matches manual segment connector positioning)
|
|
274
|
+
startCap.position.set(0, -length / 2, 0);
|
|
275
|
+
startCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-START");
|
|
276
|
+
startCap.userData = {
|
|
277
|
+
objectType: 'segment-cap',
|
|
278
|
+
capType: 'start',
|
|
279
|
+
segmentId: segment.uuid,
|
|
280
|
+
segmentIndex: segmentIndex
|
|
313
281
|
};
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
// Fixed tubular segments for 90-degree bends (quarter circle)
|
|
336
|
-
var tubularSegments = 12; // Good balance for smooth 90° curves
|
|
337
|
-
var radialSegments = 16;
|
|
338
|
-
var closed = false;
|
|
339
|
-
var elbowGeometry = new THREE__namespace.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
|
|
340
|
-
return elbowGeometry;
|
|
341
|
-
} catch (error) {
|
|
342
|
-
console.warn('Failed to create elbow geometry:', error);
|
|
343
|
-
return null;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Create a smooth curve for the 90-degree elbow joint (simplified)
|
|
349
|
-
* @param {THREE.Vector3} point1 - First point
|
|
350
|
-
* @param {THREE.Vector3} point2 - Joint point
|
|
351
|
-
* @param {THREE.Vector3} point3 - Third point
|
|
352
|
-
* @param {number} elbowRadius - Radius of the elbow curve
|
|
353
|
-
* @returns {THREE.Curve} Curve for the elbow
|
|
354
|
-
*/
|
|
355
|
-
}, {
|
|
356
|
-
key: "createElbowCurve",
|
|
357
|
-
value: function createElbowCurve(point1, point2, point3, elbowRadius) {
|
|
358
|
-
// Calculate direction vectors
|
|
359
|
-
var dir1 = point2.clone().sub(point1).normalize();
|
|
360
|
-
var dir2 = point3.clone().sub(point2).normalize();
|
|
361
|
-
|
|
362
|
-
// For 90-degree bends, we can use a simpler approach with a quarter circle
|
|
363
|
-
// The curve radius is proportional to the elbow radius
|
|
364
|
-
var curveRadius = elbowRadius * 0.001;
|
|
365
|
-
|
|
366
|
-
// Calculate the offset distance from the joint point
|
|
367
|
-
var offset = curveRadius;
|
|
368
|
-
|
|
369
|
-
// Calculate start and end points of the curve (offset from the joint)
|
|
370
|
-
var curveStart = point2.clone().sub(dir1.clone().multiplyScalar(offset));
|
|
371
|
-
var curveEnd = point2.clone().add(dir2.clone().multiplyScalar(offset));
|
|
372
|
-
|
|
373
|
-
// For a 90-degree bend, the control point is at the corner
|
|
374
|
-
// We can use a quadratic bezier curve for simplicity
|
|
375
|
-
var controlPoint = point2.clone();
|
|
376
|
-
|
|
377
|
-
// Create a quadratic bezier curve (simpler than cubic for 90° bends)
|
|
378
|
-
var curve = new THREE__namespace.QuadraticBezierCurve3(curveStart, controlPoint, curveEnd);
|
|
379
|
-
return curve;
|
|
282
|
+
startCap.castShadow = true;
|
|
283
|
+
startCap.receiveShadow = true;
|
|
284
|
+
segment.add(startCap);
|
|
285
|
+
console.log("\uD83D\uDD35 Created START cap for segment ".concat(segmentIndex, " at local position (0, ").concat(-length / 2, ", 0)"));
|
|
286
|
+
|
|
287
|
+
// Create end cap
|
|
288
|
+
var endCap = new THREE__namespace.Mesh(capGeometry, material);
|
|
289
|
+
// Position at segment end in local space (matches manual segment connector positioning)
|
|
290
|
+
endCap.position.set(0, length / 2, 0);
|
|
291
|
+
endCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-END");
|
|
292
|
+
endCap.userData = {
|
|
293
|
+
objectType: 'segment-cap',
|
|
294
|
+
capType: 'end',
|
|
295
|
+
segmentId: segment.uuid,
|
|
296
|
+
segmentIndex: segmentIndex
|
|
297
|
+
};
|
|
298
|
+
endCap.castShadow = true;
|
|
299
|
+
endCap.receiveShadow = true;
|
|
300
|
+
segment.add(endCap);
|
|
301
|
+
console.log("\uD83D\uDD35 Created END cap for segment ".concat(segmentIndex, " at local position (0, ").concat(length / 2, ", 0)"));
|
|
380
302
|
}
|
|
381
303
|
|
|
382
304
|
/**
|
|
@@ -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.45
|
|
19
19
|
* @updated 2025-10-22
|
|
20
20
|
*
|
|
21
21
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -102,7 +102,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
102
102
|
}, {
|
|
103
103
|
key: "translateSegment",
|
|
104
104
|
value: function translateSegment(segmentId, axis, value) {
|
|
105
|
-
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$
|
|
105
|
+
var _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$man3, _this$sceneViewer$man4, _this$sceneViewer$man5;
|
|
106
106
|
// Validate parameters
|
|
107
107
|
if (!segmentId || !axis || value === undefined || value === null) {
|
|
108
108
|
console.error('❌ translateSegment(): Invalid parameters');
|
|
@@ -179,7 +179,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
179
179
|
});
|
|
180
180
|
console.log("\uD83D\uDD0D After filtering, ".concat(componentConnectorsAtEndpoints.length, " component connectors at endpoints"));
|
|
181
181
|
if (componentConnectorsAtEndpoints.length > 0) {
|
|
182
|
-
var _this$sceneViewer2;
|
|
182
|
+
var _this$sceneViewer2, _this$sceneViewer$man2;
|
|
183
183
|
console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' has component connectors at endpoints."));
|
|
184
184
|
console.log(" Found ".concat(componentConnectorsAtEndpoints.length, " component connector(s):"), componentConnectorsAtEndpoints.map(function (c) {
|
|
185
185
|
var _c$parent3;
|
|
@@ -195,9 +195,45 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
195
195
|
console.warn('⚠️ Segment splitting is disabled. Cannot translate segments with component connectors at endpoints.');
|
|
196
196
|
return false;
|
|
197
197
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
|
|
199
|
+
// Split the segment and translate the free half
|
|
200
|
+
console.log('✂️ Splitting segment to enable translation of the free half...');
|
|
201
|
+
|
|
202
|
+
// Get sceneOperationsManager
|
|
203
|
+
var _sceneOperationsManager = (_this$sceneViewer$man2 = this.sceneViewer.managers) === null || _this$sceneViewer$man2 === void 0 ? void 0 : _this$sceneViewer$man2.sceneOperationsManager;
|
|
204
|
+
if (!_sceneOperationsManager) {
|
|
205
|
+
console.error('❌ translateSegment(): SceneOperationsManager not available for splitting');
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
var splitResult = _sceneOperationsManager.splitSegment(segment);
|
|
210
|
+
if (splitResult && splitResult.segment1 && splitResult.segment2) {
|
|
211
|
+
console.log("\u2705 Segment split: ".concat(splitResult.segment1.uuid, " (").concat(splitResult.segment1.geometry.parameters.height, "), ").concat(splitResult.segment2.uuid, " (").concat(splitResult.segment2.geometry.parameters.height, ")"));
|
|
212
|
+
|
|
213
|
+
// Determine which segment is the longer one (free side) to translate
|
|
214
|
+
var segment1Length = splitResult.segment1.geometry.parameters.height;
|
|
215
|
+
var segment2Length = splitResult.segment2.geometry.parameters.height;
|
|
216
|
+
|
|
217
|
+
// The longer segment is the one WITHOUT the component connector
|
|
218
|
+
var segmentToTranslate = segment1Length > segment2Length ? splitResult.segment1 : splitResult.segment2;
|
|
219
|
+
console.log("\uD83C\uDFAF Translating ".concat(segmentToTranslate.uuid, " (length: ").concat(segmentToTranslate.geometry.parameters.height, ") - the free segment"));
|
|
220
|
+
|
|
221
|
+
// Now translate the chosen segment (recursive call with the new segment)
|
|
222
|
+
var translateSuccess = this.translateSegment(segmentToTranslate.uuid, axis, value);
|
|
223
|
+
if (!translateSuccess) {
|
|
224
|
+
console.error('❌ translateSegment(): Failed to translate split segment half');
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
console.log('✅ Split and translate operation completed successfully');
|
|
228
|
+
return true;
|
|
229
|
+
} else {
|
|
230
|
+
console.error('❌ translateSegment(): Split operation failed');
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error('❌ translateSegment(): Error splitting segment:', error);
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
201
237
|
}
|
|
202
238
|
console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
|
|
203
239
|
|
|
@@ -262,8 +298,8 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
262
298
|
}
|
|
263
299
|
|
|
264
300
|
// Validate PathfindingManager and SceneOperationsManager availability
|
|
265
|
-
var pathfindingManager = (_this$sceneViewer$
|
|
266
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
301
|
+
var pathfindingManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.pathfindingManager;
|
|
302
|
+
var sceneOperationsManager = (_this$sceneViewer$man4 = this.sceneViewer.managers) === null || _this$sceneViewer$man4 === void 0 ? void 0 : _this$sceneViewer$man4.sceneOperationsManager;
|
|
267
303
|
if (!pathfindingManager || !sceneOperationsManager) {
|
|
268
304
|
console.error('❌ translateSegment(): PathfindingManager or SceneOperationsManager not available');
|
|
269
305
|
return false;
|
|
@@ -298,7 +334,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
298
334
|
|
|
299
335
|
// Store transform parameters using the OperationHistoryManager BEFORE updatePaths
|
|
300
336
|
// This is critical so that intersection detection can undo the operation
|
|
301
|
-
if ((_this$sceneViewer$
|
|
337
|
+
if ((_this$sceneViewer$man5 = this.sceneViewer.managers) !== null && _this$sceneViewer$man5 !== void 0 && _this$sceneViewer$man5.operationHistory) {
|
|
302
338
|
this.sceneViewer.managers.operationHistory.addToOperationHistory('translateSegment', {
|
|
303
339
|
segmentId: segmentId,
|
|
304
340
|
axis: axis,
|
|
@@ -346,11 +382,11 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
346
382
|
}, {
|
|
347
383
|
key: "translateGateway",
|
|
348
384
|
value: function translateGateway(gatewayId, axis, value) {
|
|
349
|
-
var _this$sceneViewer$
|
|
385
|
+
var _this$sceneViewer$man6, _this$sceneViewer$man7;
|
|
350
386
|
console.log("[Pathfinder] translateGateway started");
|
|
351
387
|
|
|
352
388
|
// Store transform parameters using the OperationHistoryManager
|
|
353
|
-
if ((_this$sceneViewer$
|
|
389
|
+
if ((_this$sceneViewer$man6 = this.sceneViewer.managers) !== null && _this$sceneViewer$man6 !== void 0 && _this$sceneViewer$man6.operationHistoryManager) {
|
|
354
390
|
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateGateway', {
|
|
355
391
|
gatewayId: gatewayId,
|
|
356
392
|
axis: axis,
|
|
@@ -401,7 +437,7 @@ var TransformOperationsManager = /*#__PURE__*/function () {
|
|
|
401
437
|
|
|
402
438
|
// Handle manual gateway transformation (convert to declared and process connections)
|
|
403
439
|
console.log('🔧 Handling manual gateway transformation via SceneOperationsManager');
|
|
404
|
-
var sceneOperationsManager = (_this$sceneViewer$
|
|
440
|
+
var sceneOperationsManager = (_this$sceneViewer$man7 = this.sceneViewer.managers) === null || _this$sceneViewer$man7 === void 0 ? void 0 : _this$sceneViewer$man7.sceneOperationsManager;
|
|
405
441
|
if (!sceneOperationsManager) {
|
|
406
442
|
console.error('❌ translateGateway(): SceneOperationsManager not available');
|
|
407
443
|
return false;
|
|
@@ -160,6 +160,10 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
160
160
|
|
|
161
161
|
var pipeRadius = 0.1;
|
|
162
162
|
var pipeMaterial = this.createPipeMaterial(crosscubeTextureSet);
|
|
163
|
+
|
|
164
|
+
// Shared geometry for all connector caps to improve performance
|
|
165
|
+
var capGeometry = new THREE.SphereGeometry(pipeRadius, 16, 16);
|
|
166
|
+
this.registerDisposable(capGeometry);
|
|
163
167
|
paths.forEach(function (pathData, index) {
|
|
164
168
|
if (pathData.path && pathData.path.length >= 2) {
|
|
165
169
|
// Convert path points to Vector3 objects for consistent handling
|
|
@@ -213,15 +217,14 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
213
217
|
pathTo: pathData.to
|
|
214
218
|
};
|
|
215
219
|
|
|
220
|
+
// Create caps at both ends of every segment
|
|
221
|
+
_this3.createSegmentCaps(cylinder, capGeometry, pipeMaterial, globalSegmentIndex);
|
|
222
|
+
|
|
216
223
|
// Increment global segment counter
|
|
217
224
|
globalSegmentIndex++;
|
|
218
225
|
|
|
219
226
|
// Add segment directly to scene instead of to polyline
|
|
220
227
|
sceneViewer.scene.add(cylinder);
|
|
221
|
-
|
|
222
|
-
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
223
|
-
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
|
|
224
|
-
);
|
|
225
228
|
}
|
|
226
229
|
console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
|
|
227
230
|
}
|
|
@@ -229,130 +232,49 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
229
232
|
}
|
|
230
233
|
|
|
231
234
|
/**
|
|
232
|
-
* Create
|
|
233
|
-
*
|
|
234
|
-
* @param {
|
|
235
|
-
* @param {
|
|
236
|
-
* @param {THREE.Material}
|
|
237
|
-
* @param {
|
|
238
|
-
* @param {number} index - Path index for naming
|
|
239
|
-
* @param {THREE.Scene} scene - Scene object to add elbow to directly
|
|
235
|
+
* Create connector caps at both segment endpoints as children of the segment
|
|
236
|
+
* Caps are positioned in local coordinates to match manual segment connector positioning
|
|
237
|
+
* @param {THREE.Mesh} segment - The parent segment mesh
|
|
238
|
+
* @param {THREE.BufferGeometry} capGeometry - Shared geometry for caps
|
|
239
|
+
* @param {THREE.Material} material - Material for the caps
|
|
240
|
+
* @param {number} segmentIndex - Global segment index
|
|
240
241
|
*/
|
|
241
242
|
}, {
|
|
242
|
-
key: "
|
|
243
|
-
value: function
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return; // No significant direction change
|
|
257
|
-
}
|
|
258
|
-
var elbowGeometry = this.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
|
|
259
|
-
if (!elbowGeometry) {
|
|
260
|
-
return; // Failed to create geometry
|
|
261
|
-
}
|
|
262
|
-
var elbow = new THREE.Mesh(elbowGeometry, pipeMaterial);
|
|
263
|
-
elbow.castShadow = true;
|
|
264
|
-
elbow.receiveShadow = true;
|
|
265
|
-
|
|
266
|
-
// Make elbows selectable as well
|
|
267
|
-
var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
|
|
268
|
-
elbow.uuid = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
|
|
269
|
-
|
|
270
|
-
// Add userData for elbows too
|
|
271
|
-
elbow.userData = {
|
|
272
|
-
isPipeElbow: true,
|
|
273
|
-
elbowId: elbowId,
|
|
274
|
-
elbowIndex: j,
|
|
275
|
-
pathFrom: pathData.from,
|
|
276
|
-
pathTo: pathData.to,
|
|
277
|
-
angle: (angle * 180 / Math.PI).toFixed(1),
|
|
278
|
-
// Add component data for tooltips
|
|
279
|
-
component: {
|
|
280
|
-
type: 'PipeElbow',
|
|
281
|
-
attributes: {
|
|
282
|
-
angle: {
|
|
283
|
-
key: 'Bend Angle',
|
|
284
|
-
value: (angle * 180 / Math.PI).toFixed(1),
|
|
285
|
-
unit: '°'
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
243
|
+
key: "createSegmentCaps",
|
|
244
|
+
value: function createSegmentCaps(segment, capGeometry, material, segmentIndex) {
|
|
245
|
+
var length = segment.geometry.parameters.height;
|
|
246
|
+
|
|
247
|
+
// Create start cap
|
|
248
|
+
var startCap = new THREE.Mesh(capGeometry, material);
|
|
249
|
+
// Position at segment start in local space (matches manual segment connector positioning)
|
|
250
|
+
startCap.position.set(0, -length / 2, 0);
|
|
251
|
+
startCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-START");
|
|
252
|
+
startCap.userData = {
|
|
253
|
+
objectType: 'segment-cap',
|
|
254
|
+
capType: 'start',
|
|
255
|
+
segmentId: segment.uuid,
|
|
256
|
+
segmentIndex: segmentIndex
|
|
289
257
|
};
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// Fixed tubular segments for 90-degree bends (quarter circle)
|
|
312
|
-
var tubularSegments = 12; // Good balance for smooth 90° curves
|
|
313
|
-
var radialSegments = 16;
|
|
314
|
-
var closed = false;
|
|
315
|
-
var elbowGeometry = new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
|
|
316
|
-
return elbowGeometry;
|
|
317
|
-
} catch (error) {
|
|
318
|
-
console.warn('Failed to create elbow geometry:', error);
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Create a smooth curve for the 90-degree elbow joint (simplified)
|
|
325
|
-
* @param {THREE.Vector3} point1 - First point
|
|
326
|
-
* @param {THREE.Vector3} point2 - Joint point
|
|
327
|
-
* @param {THREE.Vector3} point3 - Third point
|
|
328
|
-
* @param {number} elbowRadius - Radius of the elbow curve
|
|
329
|
-
* @returns {THREE.Curve} Curve for the elbow
|
|
330
|
-
*/
|
|
331
|
-
}, {
|
|
332
|
-
key: "createElbowCurve",
|
|
333
|
-
value: function createElbowCurve(point1, point2, point3, elbowRadius) {
|
|
334
|
-
// Calculate direction vectors
|
|
335
|
-
var dir1 = point2.clone().sub(point1).normalize();
|
|
336
|
-
var dir2 = point3.clone().sub(point2).normalize();
|
|
337
|
-
|
|
338
|
-
// For 90-degree bends, we can use a simpler approach with a quarter circle
|
|
339
|
-
// The curve radius is proportional to the elbow radius
|
|
340
|
-
var curveRadius = elbowRadius * 0.001;
|
|
341
|
-
|
|
342
|
-
// Calculate the offset distance from the joint point
|
|
343
|
-
var offset = curveRadius;
|
|
344
|
-
|
|
345
|
-
// Calculate start and end points of the curve (offset from the joint)
|
|
346
|
-
var curveStart = point2.clone().sub(dir1.clone().multiplyScalar(offset));
|
|
347
|
-
var curveEnd = point2.clone().add(dir2.clone().multiplyScalar(offset));
|
|
348
|
-
|
|
349
|
-
// For a 90-degree bend, the control point is at the corner
|
|
350
|
-
// We can use a quadratic bezier curve for simplicity
|
|
351
|
-
var controlPoint = point2.clone();
|
|
352
|
-
|
|
353
|
-
// Create a quadratic bezier curve (simpler than cubic for 90° bends)
|
|
354
|
-
var curve = new THREE.QuadraticBezierCurve3(curveStart, controlPoint, curveEnd);
|
|
355
|
-
return curve;
|
|
258
|
+
startCap.castShadow = true;
|
|
259
|
+
startCap.receiveShadow = true;
|
|
260
|
+
segment.add(startCap);
|
|
261
|
+
console.log("\uD83D\uDD35 Created START cap for segment ".concat(segmentIndex, " at local position (0, ").concat(-length / 2, ", 0)"));
|
|
262
|
+
|
|
263
|
+
// Create end cap
|
|
264
|
+
var endCap = new THREE.Mesh(capGeometry, material);
|
|
265
|
+
// Position at segment end in local space (matches manual segment connector positioning)
|
|
266
|
+
endCap.position.set(0, length / 2, 0);
|
|
267
|
+
endCap.uuid = "SEGMENT-".concat(segmentIndex, "-CAP-END");
|
|
268
|
+
endCap.userData = {
|
|
269
|
+
objectType: 'segment-cap',
|
|
270
|
+
capType: 'end',
|
|
271
|
+
segmentId: segment.uuid,
|
|
272
|
+
segmentIndex: segmentIndex
|
|
273
|
+
};
|
|
274
|
+
endCap.castShadow = true;
|
|
275
|
+
endCap.receiveShadow = true;
|
|
276
|
+
segment.add(endCap);
|
|
277
|
+
console.log("\uD83D\uDD35 Created END cap for segment ".concat(segmentIndex, " at local position (0, ").concat(length / 2, ", 0)"));
|
|
356
278
|
}
|
|
357
279
|
|
|
358
280
|
/**
|