@2112-lab/central-plant 0.1.39 → 0.1.41
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 +7991 -7054
- package/dist/cjs/src/core/centralPlant.js +48 -3
- package/dist/cjs/src/core/centralPlantInternals.js +75 -566
- package/dist/cjs/src/core/sceneViewer.js +38 -13
- package/dist/cjs/src/index.js +6 -4
- package/dist/cjs/src/managers/components/pathfindingManager.js +75 -60
- package/dist/cjs/src/managers/components/transformOperationsManager.js +929 -0
- package/dist/cjs/src/managers/controls/keyboardControlsManager.js +57 -1
- package/dist/cjs/src/managers/controls/transformControls.js +11 -3
- package/dist/cjs/src/managers/controls/transformControlsManager.js +563 -263
- package/dist/cjs/src/managers/pathfinding/ConnectorManager.js +385 -0
- package/dist/cjs/src/managers/pathfinding/PathIntersectionDetector.js +387 -0
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +401 -0
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +378 -0
- package/dist/cjs/src/managers/pathfinding/sceneDataManager.js +256 -0
- package/dist/cjs/src/managers/scene/animationManager.js +145 -0
- package/dist/cjs/src/managers/scene/sceneExportManager.js +14 -13
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +516 -21
- package/dist/cjs/src/managers/scene/sceneTooltipsManager.js +1 -8
- package/dist/cjs/src/managers/system/operationHistoryManager.js +414 -0
- package/dist/cjs/src/managers/system/settingsManager.js +2 -1
- package/dist/cjs/src/utils/objectTypes.js +5 -7
- package/dist/esm/src/core/centralPlant.js +48 -3
- package/dist/esm/src/core/centralPlantInternals.js +76 -567
- package/dist/esm/src/core/sceneViewer.js +38 -13
- package/dist/esm/src/index.js +4 -3
- package/dist/esm/src/managers/components/pathfindingManager.js +75 -60
- package/dist/esm/src/managers/components/transformOperationsManager.js +904 -0
- package/dist/esm/src/managers/controls/keyboardControlsManager.js +57 -1
- package/dist/esm/src/managers/controls/transformControls.js +11 -3
- package/dist/esm/src/managers/controls/transformControlsManager.js +564 -264
- package/dist/esm/src/managers/pathfinding/ConnectorManager.js +361 -0
- package/dist/esm/src/managers/pathfinding/PathIntersectionDetector.js +363 -0
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +377 -0
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +374 -0
- package/dist/esm/src/managers/pathfinding/sceneDataManager.js +232 -0
- package/dist/esm/src/managers/scene/animationManager.js +141 -0
- package/dist/esm/src/managers/scene/sceneExportManager.js +14 -13
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +516 -21
- package/dist/esm/src/managers/scene/sceneTooltipsManager.js +1 -8
- package/dist/esm/src/managers/system/operationHistoryManager.js +409 -0
- package/dist/esm/src/managers/system/settingsManager.js +2 -1
- package/dist/esm/src/utils/objectTypes.js +5 -7
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var THREE = require('three');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n["default"] = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
27
|
+
|
|
28
|
+
var TransformOperationsManager = /*#__PURE__*/function () {
|
|
29
|
+
/**
|
|
30
|
+
* @param {Object} sceneViewer - The scene viewer instance
|
|
31
|
+
*/
|
|
32
|
+
function TransformOperationsManager(sceneViewer) {
|
|
33
|
+
_rollupPluginBabelHelpers.classCallCheck(this, TransformOperationsManager);
|
|
34
|
+
this.sceneViewer = sceneViewer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Translate a component by componentId
|
|
39
|
+
* @param {string} componentId - The UUID of the component to translate
|
|
40
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
41
|
+
* @param {number} value - The value to translate by
|
|
42
|
+
* @returns {boolean} True if translation was successful, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
return _rollupPluginBabelHelpers.createClass(TransformOperationsManager, [{
|
|
45
|
+
key: "translateComponent",
|
|
46
|
+
value: function translateComponent(componentId, axis, value) {
|
|
47
|
+
var _this$sceneViewer$man, _this$sceneViewer;
|
|
48
|
+
// Store transform parameters using the OperationHistoryManager
|
|
49
|
+
if ((_this$sceneViewer$man = this.sceneViewer.managers) !== null && _this$sceneViewer$man !== void 0 && _this$sceneViewer$man.operationHistoryManager) {
|
|
50
|
+
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateComponent', {
|
|
51
|
+
componentId: componentId,
|
|
52
|
+
axis: axis,
|
|
53
|
+
value: value
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Validate parameters
|
|
58
|
+
if (!componentId || !axis || value === undefined || value === null) {
|
|
59
|
+
console.error('❌ translateComponent(): Invalid parameters');
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
63
|
+
console.error("\u274C translateComponent(): Invalid axis '".concat(axis, "'. Must be 'x', 'y', or 'z'"));
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
67
|
+
console.error('❌ translateComponent(): Scene viewer or scene not available');
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Find the component in the scene
|
|
72
|
+
var component = null;
|
|
73
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
74
|
+
var _child$userData;
|
|
75
|
+
if (child.uuid === componentId || ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid) === componentId) {
|
|
76
|
+
component = child;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
if (!component) {
|
|
80
|
+
console.error("\u274C translateComponent(): Component with ID '".concat(componentId, "' not found in scene"));
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Validate that it's actually a component
|
|
85
|
+
if (!component.userData || !component.userData.objectType) {
|
|
86
|
+
console.error("\u274C translateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Apply the translation
|
|
91
|
+
console.log("\uD83D\uDD04 translateComponent(): Translating component ".concat(componentId, " on ").concat(axis, " axis by ").concat(value));
|
|
92
|
+
|
|
93
|
+
// Update the Three.js object position
|
|
94
|
+
component.position[axis] += value;
|
|
95
|
+
|
|
96
|
+
// Update matrices
|
|
97
|
+
component.updateMatrix();
|
|
98
|
+
component.updateMatrixWorld(true);
|
|
99
|
+
|
|
100
|
+
// Check if component is underground and fix if needed (based on settings)
|
|
101
|
+
var checkUnderground = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.settingsManager) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.getSetting('scene', 'checkUnderground');
|
|
102
|
+
if (checkUnderground) {
|
|
103
|
+
this.fixUndergroundComponent(component);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Emit transform event if available
|
|
107
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
108
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
109
|
+
object: component,
|
|
110
|
+
transformType: 'translate',
|
|
111
|
+
axis: axis,
|
|
112
|
+
value: value
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
console.log("\u2705 translateComponent(): Component ".concat(componentId, " translated successfully"));
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Translate a pipe segment by segmentId
|
|
121
|
+
* @param {string} segmentId - The UUID of the pipe segment to translate
|
|
122
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
123
|
+
* @param {number} value - The value to translate by
|
|
124
|
+
* @returns {boolean} True if translation was successful, false otherwise
|
|
125
|
+
*/
|
|
126
|
+
}, {
|
|
127
|
+
key: "translateSegment",
|
|
128
|
+
value: function translateSegment(segmentId, axis, value) {
|
|
129
|
+
var _this$sceneViewer$man2, _segment$userData, _segment$userData2, _this$sceneViewer3, _this$sceneViewer$man4, _this$sceneViewer$man5;
|
|
130
|
+
// Store transform parameters using the OperationHistoryManager
|
|
131
|
+
if ((_this$sceneViewer$man2 = this.sceneViewer.managers) !== null && _this$sceneViewer$man2 !== void 0 && _this$sceneViewer$man2.operationHistoryManager) {
|
|
132
|
+
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateSegment', {
|
|
133
|
+
segmentId: segmentId,
|
|
134
|
+
axis: axis,
|
|
135
|
+
value: value
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Validate parameters
|
|
140
|
+
if (!segmentId || !axis || value === undefined || value === null) {
|
|
141
|
+
console.error('❌ translateSegment(): Invalid parameters');
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
145
|
+
console.error("\u274C translateSegment(): Invalid axis '".concat(axis, "'. Must be 'x', 'y', or 'z'"));
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
149
|
+
console.error('❌ translateSegment(): Scene viewer or scene not available');
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Find the segment in the scene
|
|
154
|
+
var segment = null;
|
|
155
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
156
|
+
var _child$userData2;
|
|
157
|
+
if (child.uuid === segmentId || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === segmentId) {
|
|
158
|
+
segment = child;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
if (!segment) {
|
|
162
|
+
console.error("\u274C translateSegment(): Segment with ID '".concat(segmentId, "' not found in scene"));
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Validate that it's actually a pipe segment
|
|
167
|
+
if (!((_segment$userData = segment.userData) !== null && _segment$userData !== void 0 && _segment$userData.objectType) === 'segment') {
|
|
168
|
+
console.error("\u274C translateSegment(): Object with ID '".concat(segmentId, "' is not a valid pipe segment"));
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Check if segment is transformable
|
|
173
|
+
if (((_segment$userData2 = segment.userData) === null || _segment$userData2 === void 0 ? void 0 : _segment$userData2.transformable) === false) {
|
|
174
|
+
console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' is marked as non-transformable (stub segment)"));
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
console.log('[translateSegment] segment:', segment);
|
|
178
|
+
|
|
179
|
+
// Calculate segment endpoints to check for nearby connectors
|
|
180
|
+
var segmentEndpoints = this.calculateSegmentEndpoints(segment);
|
|
181
|
+
|
|
182
|
+
// Check if there are any connectors (component or manual) at segment endpoints
|
|
183
|
+
var connectorsAtEndpoints = this.findConnectorsAtPositions([segmentEndpoints.start, segmentEndpoints.end], 0.15 // tolerance for position matching
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// Filter out segment connectors - we only care about component connectors
|
|
187
|
+
var componentConnectorsAtEndpoints = connectorsAtEndpoints.filter(function (connector) {
|
|
188
|
+
var _connector$userData;
|
|
189
|
+
return ((_connector$userData = connector.userData) === null || _connector$userData === void 0 ? void 0 : _connector$userData.objectType) !== 'segment-connector';
|
|
190
|
+
});
|
|
191
|
+
if (componentConnectorsAtEndpoints.length > 0) {
|
|
192
|
+
var _this$sceneViewer$man3, _this$sceneViewer2;
|
|
193
|
+
console.warn("\u26A0\uFE0F translateSegment(): Segment '".concat(segmentId, "' has component connectors at endpoints. Splitting segment..."));
|
|
194
|
+
console.log(" Found ".concat(componentConnectorsAtEndpoints.length, " component connector(s):"), componentConnectorsAtEndpoints.map(function (c) {
|
|
195
|
+
var _c$parent;
|
|
196
|
+
return {
|
|
197
|
+
uuid: c.uuid,
|
|
198
|
+
parent: (_c$parent = c.parent) === null || _c$parent === void 0 ? void 0 : _c$parent.uuid
|
|
199
|
+
};
|
|
200
|
+
}));
|
|
201
|
+
|
|
202
|
+
// Split the segment using SceneOperationsManager (will auto-detect component connectors)
|
|
203
|
+
var _sceneOperationsManager = (_this$sceneViewer$man3 = this.sceneViewer.managers) === null || _this$sceneViewer$man3 === void 0 ? void 0 : _this$sceneViewer$man3.sceneOperationsManager;
|
|
204
|
+
if (!_sceneOperationsManager) {
|
|
205
|
+
console.error('❌ translateSegment(): SceneOperationsManager not available for splitting');
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Check if segment splitting is enabled in settings
|
|
210
|
+
var splitSegmentsEnabled = (_this$sceneViewer2 = this.sceneViewer) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.managers) === null || _this$sceneViewer2 === void 0 || (_this$sceneViewer2 = _this$sceneViewer2.settingsManager) === null || _this$sceneViewer2 === void 0 ? void 0 : _this$sceneViewer2.getSetting('scene', 'splitSegmentsWithComponentConnectors');
|
|
211
|
+
if (splitSegmentsEnabled === false) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
var splitResult = _sceneOperationsManager.splitSegment(segment);
|
|
216
|
+
if (splitResult && splitResult.segment1 && splitResult.segment2) {
|
|
217
|
+
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, ")"));
|
|
218
|
+
|
|
219
|
+
// Determine which segment is the longer one (free side) to translate
|
|
220
|
+
var segment1Length = splitResult.segment1.geometry.parameters.height;
|
|
221
|
+
var segment2Length = splitResult.segment2.geometry.parameters.height;
|
|
222
|
+
|
|
223
|
+
// The longer segment is the one WITHOUT the component connector
|
|
224
|
+
var segmentToTranslate = segment1Length > segment2Length ? splitResult.segment1 : splitResult.segment2;
|
|
225
|
+
console.log("\uD83C\uDFAF Translating ".concat(segmentToTranslate.uuid, " (length: ").concat(segmentToTranslate.geometry.parameters.height, ") - the free segment"));
|
|
226
|
+
|
|
227
|
+
// Now translate the chosen segment (recursive call with the new segment)
|
|
228
|
+
var translateSuccess = this.translateSegment(segmentToTranslate.uuid, axis, value);
|
|
229
|
+
if (!translateSuccess) {
|
|
230
|
+
console.error('❌ translateSegment(): Failed to translate split segment half');
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
console.log('✅ Split and translate operation completed successfully');
|
|
234
|
+
return true;
|
|
235
|
+
} else {
|
|
236
|
+
console.error('❌ translateSegment(): Split operation failed');
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error('❌ translateSegment(): Error splitting segment:', error);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
console.log("\uD83D\uDD04 translateSegment(): Translating segment ".concat(segmentId, " on ").concat(axis, " axis by ").concat(value));
|
|
245
|
+
|
|
246
|
+
// Check if translationalOverrideForAutomaticSegments is enabled
|
|
247
|
+
var translationalOverride = (_this$sceneViewer3 = this.sceneViewer) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.managers) === null || _this$sceneViewer3 === void 0 || (_this$sceneViewer3 = _this$sceneViewer3.settingsManager) === null || _this$sceneViewer3 === void 0 ? void 0 : _this$sceneViewer3.getSetting('scene', 'translationalOverrideForAutomaticSegments');
|
|
248
|
+
|
|
249
|
+
// If override is disabled (false), check for intersections with computed segments
|
|
250
|
+
if (translationalOverride === false) {
|
|
251
|
+
console.log('🔍 Checking for intersections with computed segments (translationalOverrideForAutomaticSegments is disabled)');
|
|
252
|
+
|
|
253
|
+
// Temporarily apply the translation to check for intersections
|
|
254
|
+
var originalPosition = segment.position[axis];
|
|
255
|
+
segment.position[axis] += value;
|
|
256
|
+
segment.updateMatrix();
|
|
257
|
+
segment.updateMatrixWorld(true);
|
|
258
|
+
|
|
259
|
+
// Check if the translated segment intersects with any computed segments
|
|
260
|
+
var hasIntersection = this.checkSegmentIntersection(segment);
|
|
261
|
+
console.log("\uD83D\uDD04 translateSegment() hasIntersection:", hasIntersection);
|
|
262
|
+
if (hasIntersection) {
|
|
263
|
+
// Revert the translation
|
|
264
|
+
segment.position[axis] = originalPosition;
|
|
265
|
+
segment.updateMatrix();
|
|
266
|
+
segment.updateMatrixWorld(true);
|
|
267
|
+
console.warn("\u26A0\uFE0F translateSegment(): Translation canceled - segment would intersect with computed segment(s)");
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
console.log('✅ No intersections detected, proceeding with translation');
|
|
271
|
+
} else {
|
|
272
|
+
// Apply the translation to the Three.js object
|
|
273
|
+
segment.position[axis] += value;
|
|
274
|
+
|
|
275
|
+
// Update matrices
|
|
276
|
+
segment.updateMatrix();
|
|
277
|
+
segment.updateMatrixWorld(true);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Validate PathfindingManager and SceneOperationsManager availability
|
|
281
|
+
var pathfindingManager = (_this$sceneViewer$man4 = this.sceneViewer.managers) === null || _this$sceneViewer$man4 === void 0 ? void 0 : _this$sceneViewer$man4.pathfindingManager;
|
|
282
|
+
var sceneOperationsManager = (_this$sceneViewer$man5 = this.sceneViewer.managers) === null || _this$sceneViewer$man5 === void 0 ? void 0 : _this$sceneViewer$man5.sceneOperationsManager;
|
|
283
|
+
if (!pathfindingManager || !sceneOperationsManager) {
|
|
284
|
+
console.error('❌ translateSegment(): PathfindingManager or SceneOperationsManager not available');
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Check if segment is already declared - if not, manualize it first
|
|
289
|
+
if (segment.userData.isDeclared !== true) {
|
|
290
|
+
console.log('🔌 Handling manual segment transformation via SceneOperationsManager (first move)');
|
|
291
|
+
try {
|
|
292
|
+
sceneOperationsManager.manualizeSegment(segment, this.sceneViewer.currentSceneData);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
console.error('❌ translateSegment(): Error in manualizeSegment:', error);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
console.log('🔄 Segment already declared, updating connector positions (subsequent move)');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ALWAYS update connector positions after segment movement (first or subsequent moves)
|
|
302
|
+
this.updateSegmentConnectorPositions(segment);
|
|
303
|
+
|
|
304
|
+
// Regenerate paths to create new pipe segments that connect to the moved segment
|
|
305
|
+
console.log('🔄 Regenerating paths to create connecting pipe segments...');
|
|
306
|
+
try {
|
|
307
|
+
if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
|
|
308
|
+
this.sceneViewer.updatePaths();
|
|
309
|
+
console.log('✅ Paths regenerated successfully - new connecting segments created');
|
|
310
|
+
} else {
|
|
311
|
+
console.warn('⚠️ updatePaths method not available on sceneViewer');
|
|
312
|
+
}
|
|
313
|
+
} catch (error) {
|
|
314
|
+
console.error('❌ Error regenerating paths:', error);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Emit transform event if available
|
|
318
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
319
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
320
|
+
object: segment,
|
|
321
|
+
transformType: 'translateSegment',
|
|
322
|
+
axis: axis,
|
|
323
|
+
value: value
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
console.log("\u2705 translateSegment(): Segment ".concat(segmentId, " translated and connections restructured successfully"));
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Translate a gateway by gatewayId
|
|
332
|
+
* @param {string} gatewayId - The UUID of the gateway to translate
|
|
333
|
+
* @param {string} axis - The axis to translate on ('x', 'y', or 'z')
|
|
334
|
+
* @param {number} value - The value to translate by
|
|
335
|
+
* @returns {boolean} True if translation was successful, false otherwise
|
|
336
|
+
*/
|
|
337
|
+
}, {
|
|
338
|
+
key: "translateGateway",
|
|
339
|
+
value: function translateGateway(gatewayId, axis, value) {
|
|
340
|
+
var _this$sceneViewer$man6, _this$sceneViewer$man7;
|
|
341
|
+
console.log("[Pathfinder] translateGateway started");
|
|
342
|
+
|
|
343
|
+
// Store transform parameters using the OperationHistoryManager
|
|
344
|
+
if ((_this$sceneViewer$man6 = this.sceneViewer.managers) !== null && _this$sceneViewer$man6 !== void 0 && _this$sceneViewer$man6.operationHistoryManager) {
|
|
345
|
+
this.sceneViewer.managers.operationHistoryManager.addToOperationHistory('translateGateway', {
|
|
346
|
+
gatewayId: gatewayId,
|
|
347
|
+
axis: axis,
|
|
348
|
+
value: value
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Validate parameters
|
|
353
|
+
if (!gatewayId || !axis || value === undefined || value === null) {
|
|
354
|
+
console.error('❌ translateGateway(): Invalid parameters');
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
358
|
+
console.error("\u274C translateGateway(): Invalid axis '".concat(axis, "'. Must be 'x', 'y', or 'z'"));
|
|
359
|
+
return false;
|
|
360
|
+
}
|
|
361
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
362
|
+
console.error('❌ translateGateway(): Scene viewer or scene not available');
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Find the gateway in the scene
|
|
367
|
+
var gateway = null;
|
|
368
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
369
|
+
var _child$userData3;
|
|
370
|
+
if (child.uuid === gatewayId || ((_child$userData3 = child.userData) === null || _child$userData3 === void 0 ? void 0 : _child$userData3.originalUuid) === gatewayId) {
|
|
371
|
+
gateway = child;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
if (!gateway) {
|
|
375
|
+
console.error("\u274C translateGateway(): Gateway with ID '".concat(gatewayId, "' not found in scene"));
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Validate that it's actually a gateway
|
|
380
|
+
if (!gateway.userData || gateway.userData.objectType !== 'gateway') {
|
|
381
|
+
console.error("\u274C translateGateway(): Object with ID '".concat(gatewayId, "' is not a valid gateway"));
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
console.log("\uD83D\uDD04 translateGateway(): Translating gateway ".concat(gatewayId, " on ").concat(axis, " axis by ").concat(value));
|
|
385
|
+
|
|
386
|
+
// Apply the translation to the Three.js object
|
|
387
|
+
gateway.position[axis] += value;
|
|
388
|
+
|
|
389
|
+
// Update matrices
|
|
390
|
+
gateway.updateMatrix();
|
|
391
|
+
gateway.updateMatrixWorld(true);
|
|
392
|
+
|
|
393
|
+
// Handle manual gateway transformation (convert to declared and process connections)
|
|
394
|
+
console.log('🔧 Handling manual gateway transformation via SceneOperationsManager');
|
|
395
|
+
var sceneOperationsManager = (_this$sceneViewer$man7 = this.sceneViewer.managers) === null || _this$sceneViewer$man7 === void 0 ? void 0 : _this$sceneViewer$man7.sceneOperationsManager;
|
|
396
|
+
if (!sceneOperationsManager) {
|
|
397
|
+
console.error('❌ translateGateway(): SceneOperationsManager not available');
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
sceneOperationsManager.manualizeGateway(gateway, this.sceneViewer.currentSceneData);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
console.error('❌ translateGateway(): Error in manualizeGateway:', error);
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Regenerate paths to reflect the gateway's new position
|
|
408
|
+
console.log('🔄 Regenerating paths to reflect gateway movement...');
|
|
409
|
+
try {
|
|
410
|
+
if (this.sceneViewer && typeof this.sceneViewer.updatePaths === 'function') {
|
|
411
|
+
this.sceneViewer.updatePaths();
|
|
412
|
+
console.log('✅ Paths regenerated successfully - routing updated for new gateway position');
|
|
413
|
+
} else {
|
|
414
|
+
console.warn('⚠️ updatePaths method not available on sceneViewer');
|
|
415
|
+
}
|
|
416
|
+
} catch (error) {
|
|
417
|
+
console.error('❌ Error regenerating paths:', error);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Emit transform event if available
|
|
421
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
422
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
423
|
+
object: gateway,
|
|
424
|
+
transformType: 'translateGateway',
|
|
425
|
+
axis: axis,
|
|
426
|
+
value: value
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
console.log("\u2705 translateGateway(): Gateway ".concat(gatewayId, " translated and marked as declared successfully"));
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Rotate a component by componentId
|
|
435
|
+
* @param {string} componentId - The UUID of the component to rotate
|
|
436
|
+
* @param {string} axis - The axis to rotate around ('x', 'y', or 'z')
|
|
437
|
+
* @param {number} value - The value to rotate by in degrees
|
|
438
|
+
* @returns {boolean} True if rotation was successful, false otherwise
|
|
439
|
+
*/
|
|
440
|
+
}, {
|
|
441
|
+
key: "rotateComponent",
|
|
442
|
+
value: function rotateComponent(componentId, axis, value) {
|
|
443
|
+
// Validate parameters
|
|
444
|
+
if (!componentId || !axis || value === undefined || value === null) {
|
|
445
|
+
console.error('❌ rotateComponent(): Invalid parameters');
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
449
|
+
console.error("\u274C rotateComponent(): Invalid axis '".concat(axis, "'. Must be 'x', 'y', or 'z'"));
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
453
|
+
console.error('❌ rotateComponent(): Scene viewer or scene not available');
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Find the component in the scene
|
|
458
|
+
var component = null;
|
|
459
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
460
|
+
var _child$userData4;
|
|
461
|
+
if (child.uuid === componentId || ((_child$userData4 = child.userData) === null || _child$userData4 === void 0 ? void 0 : _child$userData4.originalUuid) === componentId) {
|
|
462
|
+
component = child;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
if (!component) {
|
|
466
|
+
console.error("\u274C rotateComponent(): Component with ID '".concat(componentId, "' not found in scene"));
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
if (!component.userData.libraryId) {
|
|
470
|
+
console.error("\u274C rotateComponent(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Store previous rotation for potential undo
|
|
475
|
+
var previousRotation = {
|
|
476
|
+
x: component.rotation.x,
|
|
477
|
+
y: component.rotation.y,
|
|
478
|
+
z: component.rotation.z
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// Convert degrees to radians
|
|
482
|
+
var radians = value * Math.PI / 180;
|
|
483
|
+
console.log("\uD83D\uDD04 rotateComponent(): Rotating component ".concat(componentId, " around ").concat(axis, " axis by ").concat(value, " degrees (").concat(radians, " radians)"));
|
|
484
|
+
|
|
485
|
+
// Apply the rotation
|
|
486
|
+
component.rotation[axis] += radians;
|
|
487
|
+
|
|
488
|
+
// Update direction vectors for connectors if this is a 90-degree rotation
|
|
489
|
+
if (value % 90 === 0) {
|
|
490
|
+
this.updateConnectorDirections(component, axis, value);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Update matrices
|
|
494
|
+
component.updateMatrix();
|
|
495
|
+
component.updateMatrixWorld(true);
|
|
496
|
+
|
|
497
|
+
// Emit transform event if available
|
|
498
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
499
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
500
|
+
object: component,
|
|
501
|
+
transformType: 'rotate',
|
|
502
|
+
axis: axis,
|
|
503
|
+
value: value,
|
|
504
|
+
radians: radians,
|
|
505
|
+
previousRotation: previousRotation
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
console.log("\u2705 rotateComponent(): Component ".concat(componentId, " rotated successfully"));
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Update connector direction vectors after component rotation
|
|
514
|
+
* @param {THREE.Object3D} component - The component that was rotated
|
|
515
|
+
* @param {string} axis - The axis of rotation ('x', 'y', or 'z')
|
|
516
|
+
* @param {number} degrees - The rotation angle in degrees (should be multiple of 90)
|
|
517
|
+
* @private
|
|
518
|
+
*/
|
|
519
|
+
}, {
|
|
520
|
+
key: "updateConnectorDirections",
|
|
521
|
+
value: function updateConnectorDirections(component, axis, degrees) {
|
|
522
|
+
if (!component || degrees % 90 !== 0) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
console.log("\uD83D\uDD04 Updating connector directions after ".concat(degrees, "\xB0 rotation around ").concat(axis, " axis"));
|
|
526
|
+
|
|
527
|
+
// Simple approach: just log that directions may need manual verification
|
|
528
|
+
// In most cases, Three.js world matrices handle the actual positioning correctly
|
|
529
|
+
component.traverse(function (child) {
|
|
530
|
+
var _child$userData5, _child$userData6;
|
|
531
|
+
if (((_child$userData5 = child.userData) === null || _child$userData5 === void 0 ? void 0 : _child$userData5.objectType) === 'connector' && (_child$userData6 = child.userData) !== null && _child$userData6 !== void 0 && _child$userData6.direction) {
|
|
532
|
+
console.log("\uD83D\uDCCD Connector ".concat(child.uuid, " direction may need verification after rotation"));
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Check if a component is positioned underground (below Z=0 in Z-up coordinate system)
|
|
539
|
+
* @param {THREE.Object3D} component - The component to check
|
|
540
|
+
* @returns {Object} Object with { isUnderground: boolean, lowestZ: number, correction: number }
|
|
541
|
+
*/
|
|
542
|
+
}, {
|
|
543
|
+
key: "checkComponentUnderground",
|
|
544
|
+
value: function checkComponentUnderground(component) {
|
|
545
|
+
if (!component) {
|
|
546
|
+
return {
|
|
547
|
+
isUnderground: false,
|
|
548
|
+
lowestZ: 0,
|
|
549
|
+
correction: 0
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
try {
|
|
553
|
+
// Calculate bounding box in world coordinates
|
|
554
|
+
var boundingBox = new THREE__namespace.Box3().setFromObject(component);
|
|
555
|
+
|
|
556
|
+
// In Z-up coordinate system, ground is at z=0
|
|
557
|
+
// Check the lowest Z point of the bounding box
|
|
558
|
+
var lowestZ = boundingBox.min.z;
|
|
559
|
+
var isUnderground = lowestZ < 0;
|
|
560
|
+
|
|
561
|
+
// Calculate how much we need to move up to put the lowest point at ground level
|
|
562
|
+
var correction = isUnderground ? Math.abs(lowestZ) : 0;
|
|
563
|
+
return {
|
|
564
|
+
isUnderground: isUnderground,
|
|
565
|
+
lowestZ: lowestZ,
|
|
566
|
+
correction: correction
|
|
567
|
+
};
|
|
568
|
+
} catch (error) {
|
|
569
|
+
console.warn('⚠️ Error checking component underground status:', error);
|
|
570
|
+
return {
|
|
571
|
+
isUnderground: false,
|
|
572
|
+
lowestZ: 0,
|
|
573
|
+
correction: 0
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Fix component position if it's underground
|
|
580
|
+
* @param {THREE.Object3D} component - The component to fix
|
|
581
|
+
* @returns {boolean} True if component was adjusted, false otherwise
|
|
582
|
+
*/
|
|
583
|
+
}, {
|
|
584
|
+
key: "fixUndergroundComponent",
|
|
585
|
+
value: function fixUndergroundComponent(component) {
|
|
586
|
+
if (!component) {
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
var checkResult = this.checkComponentUnderground(component);
|
|
590
|
+
if (checkResult.isUnderground) {
|
|
591
|
+
var _component$userData;
|
|
592
|
+
var componentId = component.uuid || ((_component$userData = component.userData) === null || _component$userData === void 0 ? void 0 : _component$userData.originalUuid) || 'unknown';
|
|
593
|
+
console.log("\uD83D\uDD27 Component ".concat(componentId, " is underground (lowest Z: ").concat(checkResult.lowestZ.toFixed(3), "), moving up by ").concat(checkResult.correction.toFixed(3)));
|
|
594
|
+
|
|
595
|
+
// Move the component up so its lowest point is at ground level (z=0)
|
|
596
|
+
component.position.z += checkResult.correction;
|
|
597
|
+
|
|
598
|
+
// Update matrices
|
|
599
|
+
component.updateMatrix();
|
|
600
|
+
component.updateMatrixWorld(true);
|
|
601
|
+
console.log("\u2705 Component ".concat(componentId, " moved to surface (new position Z: ").concat(component.position.z.toFixed(3), ")"));
|
|
602
|
+
return true;
|
|
603
|
+
}
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Check if a pipe segment is horizontal (Z-axis aligned in Z-up coordinate system)
|
|
609
|
+
* A segment is considered horizontal if its direction vector has minimal Z component
|
|
610
|
+
* @param {THREE.Object3D} segment - The pipe segment to check
|
|
611
|
+
* @param {number} tolerance - Angular tolerance in radians (default: ~5.7 degrees)
|
|
612
|
+
* @returns {boolean} True if segment is horizontal, false otherwise
|
|
613
|
+
* @private
|
|
614
|
+
*/
|
|
615
|
+
}, {
|
|
616
|
+
key: "isSegmentHorizontal",
|
|
617
|
+
value: function isSegmentHorizontal(segment) {
|
|
618
|
+
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.1;
|
|
619
|
+
if (!segment || !segment.geometry || !segment.quaternion) {
|
|
620
|
+
console.warn('⚠️ Invalid segment provided to isSegmentHorizontal');
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Get the segment's direction vector (cylinder aligned with Y-axis by default)
|
|
625
|
+
var direction = new THREE__namespace.Vector3(0, 1, 0);
|
|
626
|
+
direction.applyQuaternion(segment.quaternion);
|
|
627
|
+
direction.normalize();
|
|
628
|
+
|
|
629
|
+
// In Z-up coordinate system, horizontal segments should have Z component near 0
|
|
630
|
+
// A perfectly horizontal segment would have direction.z = 0
|
|
631
|
+
var zComponent = Math.abs(direction.z);
|
|
632
|
+
|
|
633
|
+
// Allow small tolerance for floating point precision
|
|
634
|
+
return zComponent < tolerance;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Calculate segment endpoints in world coordinates
|
|
639
|
+
* @param {THREE.Object3D} segment - The pipe segment
|
|
640
|
+
* @returns {Object} Object with start and end Vector3 points
|
|
641
|
+
* @private
|
|
642
|
+
*/
|
|
643
|
+
}, {
|
|
644
|
+
key: "calculateSegmentEndpoints",
|
|
645
|
+
value: function calculateSegmentEndpoints(segment) {
|
|
646
|
+
// Get the segment's geometry to determine its length and orientation
|
|
647
|
+
var geometry = segment.geometry;
|
|
648
|
+
var length = geometry.parameters.height || 1;
|
|
649
|
+
|
|
650
|
+
// Calculate start and end points based on segment position and orientation
|
|
651
|
+
var startPoint = new THREE__namespace.Vector3();
|
|
652
|
+
var endPoint = new THREE__namespace.Vector3();
|
|
653
|
+
|
|
654
|
+
// Get the segment's direction vector
|
|
655
|
+
var direction = new THREE__namespace.Vector3(0, 1, 0);
|
|
656
|
+
direction.applyQuaternion(segment.quaternion);
|
|
657
|
+
|
|
658
|
+
// Calculate start point (half length back from center)
|
|
659
|
+
startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(length / 2));
|
|
660
|
+
|
|
661
|
+
// Calculate end point (half length forward from center)
|
|
662
|
+
endPoint.copy(segment.position).add(direction.clone().multiplyScalar(length / 2));
|
|
663
|
+
return {
|
|
664
|
+
start: startPoint,
|
|
665
|
+
end: endPoint
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Find all connectors (component or manual) at given positions
|
|
671
|
+
* @param {Array<THREE.Vector3>} positions - Array of positions to check
|
|
672
|
+
* @param {number} tolerance - Distance tolerance for position matching
|
|
673
|
+
* @returns {Array<THREE.Object3D>} Array of connector objects found at positions
|
|
674
|
+
* @private
|
|
675
|
+
*/
|
|
676
|
+
}, {
|
|
677
|
+
key: "findConnectorsAtPositions",
|
|
678
|
+
value: function findConnectorsAtPositions(positions) {
|
|
679
|
+
var _this$sceneViewer4;
|
|
680
|
+
var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.15;
|
|
681
|
+
if (!((_this$sceneViewer4 = this.sceneViewer) !== null && _this$sceneViewer4 !== void 0 && _this$sceneViewer4.scene)) {
|
|
682
|
+
return [];
|
|
683
|
+
}
|
|
684
|
+
var foundConnectors = [];
|
|
685
|
+
|
|
686
|
+
// Traverse scene to find all connectors
|
|
687
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
688
|
+
var _child$userData7;
|
|
689
|
+
// Check if this is a connector (component connector or manual segment connector)
|
|
690
|
+
if (((_child$userData7 = child.userData) === null || _child$userData7 === void 0 ? void 0 : _child$userData7.objectType) === 'connector') {
|
|
691
|
+
// Get world position of connector
|
|
692
|
+
var connectorWorldPos = new THREE__namespace.Vector3();
|
|
693
|
+
child.getWorldPosition(connectorWorldPos);
|
|
694
|
+
|
|
695
|
+
// Check if connector is near any of the target positions
|
|
696
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(positions),
|
|
697
|
+
_step;
|
|
698
|
+
try {
|
|
699
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
700
|
+
var position = _step.value;
|
|
701
|
+
var distance = connectorWorldPos.distanceTo(position);
|
|
702
|
+
if (distance <= tolerance) {
|
|
703
|
+
foundConnectors.push(child);
|
|
704
|
+
break; // Don't count the same connector twice
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
} catch (err) {
|
|
708
|
+
_iterator.e(err);
|
|
709
|
+
} finally {
|
|
710
|
+
_iterator.f();
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
return foundConnectors;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Update connector positions in scene data after a declared segment is moved
|
|
719
|
+
* @param {THREE.Object3D} segment - The segment whose connectors need updating
|
|
720
|
+
* @private
|
|
721
|
+
*/
|
|
722
|
+
}, {
|
|
723
|
+
key: "updateSegmentConnectorPositions",
|
|
724
|
+
value: function updateSegmentConnectorPositions(segment) {
|
|
725
|
+
var _this$sceneViewer5;
|
|
726
|
+
console.log("updateSegmentConnectorPositions started:", segment);
|
|
727
|
+
if (!segment || !((_this$sceneViewer5 = this.sceneViewer) !== null && _this$sceneViewer5 !== void 0 && (_this$sceneViewer5 = _this$sceneViewer5.currentSceneData) !== null && _this$sceneViewer5 !== void 0 && _this$sceneViewer5.scene)) {
|
|
728
|
+
console.warn('⚠️ updateSegmentConnectorPositions(): Missing segment or scene data');
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Helper function to clean up floating-point precision errors
|
|
733
|
+
var cleanPosition = function cleanPosition(value) {
|
|
734
|
+
return Math.abs(value) < 1e-10 ? 0 : value;
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
// Find all child connectors of the segment
|
|
738
|
+
var connectors = [];
|
|
739
|
+
segment.traverse(function (child) {
|
|
740
|
+
var _child$userData8;
|
|
741
|
+
if (((_child$userData8 = child.userData) === null || _child$userData8 === void 0 ? void 0 : _child$userData8.objectType) === 'segment-connector') {
|
|
742
|
+
connectors.push(child);
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
if (connectors.length === 0) {
|
|
746
|
+
console.warn("\u26A0\uFE0F No connectors found for segment ".concat(segment.uuid));
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
console.log("\uD83D\uDCCD Updating ".concat(connectors.length, " connector positions in scene data for segment ").concat(segment.uuid));
|
|
750
|
+
|
|
751
|
+
// First, find the segment in scene data
|
|
752
|
+
var sceneDataSegment = this.sceneViewer.currentSceneData.scene.children.find(function (child) {
|
|
753
|
+
var _segment$userData3;
|
|
754
|
+
return child.uuid === segment.uuid || child.uuid === ((_segment$userData3 = segment.userData) === null || _segment$userData3 === void 0 ? void 0 : _segment$userData3.originalUuid);
|
|
755
|
+
});
|
|
756
|
+
if (!sceneDataSegment) {
|
|
757
|
+
console.warn("\u26A0\uFE0F Segment ".concat(segment.uuid, " not found in scene data"));
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
if (!sceneDataSegment.children || !Array.isArray(sceneDataSegment.children)) {
|
|
761
|
+
console.warn("\u26A0\uFE0F Segment ".concat(segment.uuid, " has no children array in scene data"));
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
console.log("\u2705 Found segment in scene data with ".concat(sceneDataSegment.children.length, " children"));
|
|
765
|
+
|
|
766
|
+
// Update each connector's position in scene data
|
|
767
|
+
connectors.forEach(function (connector) {
|
|
768
|
+
// Get world position
|
|
769
|
+
var worldPosition = new THREE__namespace.Vector3();
|
|
770
|
+
connector.getWorldPosition(worldPosition);
|
|
771
|
+
|
|
772
|
+
// Find the connector in the segment's children array (not root scene.children)
|
|
773
|
+
var sceneDataConnector = sceneDataSegment.children.find(function (child) {
|
|
774
|
+
var _connector$userData2;
|
|
775
|
+
return child.uuid === connector.uuid || child.uuid === ((_connector$userData2 = connector.userData) === null || _connector$userData2 === void 0 ? void 0 : _connector$userData2.originalUuid);
|
|
776
|
+
});
|
|
777
|
+
if (sceneDataConnector && sceneDataConnector.userData) {
|
|
778
|
+
// Update position as array [x, y, z] for pathfinder compatibility
|
|
779
|
+
sceneDataConnector.userData.position = [cleanPosition(worldPosition.x), cleanPosition(worldPosition.y), cleanPosition(worldPosition.z)];
|
|
780
|
+
console.log("\u2705 Updated connector ".concat(connector.uuid, " position to [").concat(sceneDataConnector.userData.position.join(', '), "]"));
|
|
781
|
+
} else {
|
|
782
|
+
console.warn("\u26A0\uFE0F Connector ".concat(connector.uuid, " not found in segment's children in scene data"));
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Check if a segment intersects with any computed segments in the scene
|
|
789
|
+
* Uses segment-to-segment distance calculation, excluding endpoint connections
|
|
790
|
+
* @param {THREE.Object3D} segment - The segment to check for intersections
|
|
791
|
+
* @returns {boolean} True if segment intersects with any computed segment (not just touching at ends)
|
|
792
|
+
* @private
|
|
793
|
+
*/
|
|
794
|
+
}, {
|
|
795
|
+
key: "checkSegmentIntersection",
|
|
796
|
+
value: function checkSegmentIntersection(segment) {
|
|
797
|
+
var _this$sceneViewer6,
|
|
798
|
+
_this = this;
|
|
799
|
+
if (!((_this$sceneViewer6 = this.sceneViewer) !== null && _this$sceneViewer6 !== void 0 && _this$sceneViewer6.scene)) {
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// Get endpoints of the segment being checked
|
|
804
|
+
var segmentEndpoints = this.calculateSegmentEndpoints(segment);
|
|
805
|
+
var segmentRadius = segment.geometry.parameters.radiusTop || 0.05;
|
|
806
|
+
|
|
807
|
+
// Track if any intersection was found
|
|
808
|
+
var hasIntersection = false;
|
|
809
|
+
|
|
810
|
+
// Check all segments in the scene
|
|
811
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
812
|
+
var _child$userData9, _child$userData0;
|
|
813
|
+
// Skip the segment itself
|
|
814
|
+
if (child.uuid === segment.uuid) {
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// Only check computed segments (isDeclared === false or undefined)
|
|
819
|
+
if (((_child$userData9 = child.userData) === null || _child$userData9 === void 0 ? void 0 : _child$userData9.objectType) === 'segment' && ((_child$userData0 = child.userData) === null || _child$userData0 === void 0 ? void 0 : _child$userData0.isDeclared) !== true) {
|
|
820
|
+
// Get endpoints of the computed segment
|
|
821
|
+
var computedEndpoints = _this.calculateSegmentEndpoints(child);
|
|
822
|
+
var computedRadius = child.geometry.parameters.radiusTop || 0.05;
|
|
823
|
+
|
|
824
|
+
// Combined radius threshold - segments intersect if closer than this
|
|
825
|
+
var combinedRadius = segmentRadius + computedRadius;
|
|
826
|
+
|
|
827
|
+
// First, check if segments are connected at endpoints
|
|
828
|
+
// This is a cheaper check than full segment-to-segment distance
|
|
829
|
+
var endpointTolerance = 0.55; // Generous tolerance for endpoint connections
|
|
830
|
+
|
|
831
|
+
var d1 = segmentEndpoints.start.distanceTo(computedEndpoints.start);
|
|
832
|
+
var d2 = segmentEndpoints.start.distanceTo(computedEndpoints.end);
|
|
833
|
+
var d3 = segmentEndpoints.end.distanceTo(computedEndpoints.start);
|
|
834
|
+
var d4 = segmentEndpoints.end.distanceTo(computedEndpoints.end);
|
|
835
|
+
|
|
836
|
+
// Check if any endpoint of segment A is near any endpoint of segment B (they're connected)
|
|
837
|
+
var isConnectedAtEnds = d1 < endpointTolerance || d2 < endpointTolerance || d3 < endpointTolerance || d4 < endpointTolerance;
|
|
838
|
+
|
|
839
|
+
// If connected at ends, skip this segment (no collision)
|
|
840
|
+
if (isConnectedAtEnds) {
|
|
841
|
+
console.log("\u2705 Segments connected at endpoints - skipping intersection check (min endpoint distance: ".concat(Math.min(d1, d2, d3, d4).toFixed(3), ")"));
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// Calculate the minimum distance between the two line segments
|
|
846
|
+
var distance = _this.calculateSegmentToSegmentDistance(segmentEndpoints.start, segmentEndpoints.end, computedEndpoints.start, computedEndpoints.end);
|
|
847
|
+
|
|
848
|
+
// Only flag as intersection if segments are closer than combined radius
|
|
849
|
+
if (distance < combinedRadius) {
|
|
850
|
+
console.log("\uD83D\uDD34 Intersection detected with computed segment: ".concat(child.uuid || child.name));
|
|
851
|
+
console.log(" Distance: ".concat(distance.toFixed(3), ", Combined radius: ").concat(combinedRadius.toFixed(3)));
|
|
852
|
+
console.log(" Endpoint distances: [".concat(d1.toFixed(3), ", ").concat(d2.toFixed(3), ", ").concat(d3.toFixed(3), ", ").concat(d4.toFixed(3), "]"));
|
|
853
|
+
hasIntersection = true;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
return hasIntersection;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Calculate the minimum distance between two line segments in 3D space
|
|
862
|
+
* @param {THREE.Vector3} p1 - Start point of first segment
|
|
863
|
+
* @param {THREE.Vector3} p2 - End point of first segment
|
|
864
|
+
* @param {THREE.Vector3} p3 - Start point of second segment
|
|
865
|
+
* @param {THREE.Vector3} p4 - End point of second segment
|
|
866
|
+
* @returns {number} Minimum distance between the two segments
|
|
867
|
+
* @private
|
|
868
|
+
*/
|
|
869
|
+
}, {
|
|
870
|
+
key: "calculateSegmentToSegmentDistance",
|
|
871
|
+
value: function calculateSegmentToSegmentDistance(p1, p2, p3, p4) {
|
|
872
|
+
// Direction vectors
|
|
873
|
+
var d1 = new THREE__namespace.Vector3().subVectors(p2, p1); // Segment 1 direction
|
|
874
|
+
var d2 = new THREE__namespace.Vector3().subVectors(p4, p3); // Segment 2 direction
|
|
875
|
+
var r = new THREE__namespace.Vector3().subVectors(p1, p3); // Vector between start points
|
|
876
|
+
|
|
877
|
+
var a = d1.dot(d1); // Squared length of segment 1
|
|
878
|
+
var e = d2.dot(d2); // Squared length of segment 2
|
|
879
|
+
var f = d2.dot(r);
|
|
880
|
+
|
|
881
|
+
// Handle degenerate cases (zero-length segments)
|
|
882
|
+
if (a <= 1e-10 && e <= 1e-10) {
|
|
883
|
+
// Both segments are points
|
|
884
|
+
return p1.distanceTo(p3);
|
|
885
|
+
}
|
|
886
|
+
if (a <= 1e-10) {
|
|
887
|
+
// First segment is a point
|
|
888
|
+
var _t = Math.max(0, Math.min(1, f / e));
|
|
889
|
+
var closestPoint = new THREE__namespace.Vector3().addVectors(p3, d2.clone().multiplyScalar(_t));
|
|
890
|
+
return p1.distanceTo(closestPoint);
|
|
891
|
+
}
|
|
892
|
+
var c = d1.dot(r);
|
|
893
|
+
if (e <= 1e-10) {
|
|
894
|
+
// Second segment is a point
|
|
895
|
+
var _s = Math.max(0, Math.min(1, -c / a));
|
|
896
|
+
var _closestPoint = new THREE__namespace.Vector3().addVectors(p1, d1.clone().multiplyScalar(_s));
|
|
897
|
+
return p3.distanceTo(_closestPoint);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// General case - both segments have length
|
|
901
|
+
var b = d1.dot(d2);
|
|
902
|
+
var denom = a * e - b * b;
|
|
903
|
+
|
|
904
|
+
// Compute parameters for closest points
|
|
905
|
+
var s, t;
|
|
906
|
+
if (denom !== 0) {
|
|
907
|
+
s = Math.max(0, Math.min(1, (b * f - c * e) / denom));
|
|
908
|
+
} else {
|
|
909
|
+
s = 0;
|
|
910
|
+
}
|
|
911
|
+
t = (b * s + f) / e;
|
|
912
|
+
if (t < 0) {
|
|
913
|
+
t = 0;
|
|
914
|
+
s = Math.max(0, Math.min(1, -c / a));
|
|
915
|
+
} else if (t > 1) {
|
|
916
|
+
t = 1;
|
|
917
|
+
s = Math.max(0, Math.min(1, (b - c) / a));
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Calculate closest points
|
|
921
|
+
var c1 = new THREE__namespace.Vector3().addVectors(p1, d1.clone().multiplyScalar(s));
|
|
922
|
+
var c2 = new THREE__namespace.Vector3().addVectors(p3, d2.clone().multiplyScalar(t));
|
|
923
|
+
return c1.distanceTo(c2);
|
|
924
|
+
}
|
|
925
|
+
}]);
|
|
926
|
+
}();
|
|
927
|
+
|
|
928
|
+
exports.TransformOperationsManager = TransformOperationsManager;
|
|
929
|
+
exports["default"] = TransformOperationsManager;
|