@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,377 @@
|
|
|
1
|
+
import { inherits as _inherits, createClass as _createClass, toConsumableArray as _toConsumableArray, objectSpread2 as _objectSpread2, construct as _construct, superPropGet as _superPropGet, classCallCheck as _classCallCheck, callSuper as _callSuper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { BaseDisposable } from '../../core/baseDisposable.js';
|
|
4
|
+
|
|
5
|
+
var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
6
|
+
function PathRenderingManager(sceneViewer) {
|
|
7
|
+
var _this;
|
|
8
|
+
_classCallCheck(this, PathRenderingManager);
|
|
9
|
+
_this = _callSuper(this, PathRenderingManager);
|
|
10
|
+
_this.sceneViewer = sceneViewer;
|
|
11
|
+
|
|
12
|
+
// Shared gateway resources to prevent memory leaks
|
|
13
|
+
_this._gatewayGeometry = new THREE.SphereGeometry(0.15, 16, 16);
|
|
14
|
+
_this._gatewayMaterial = new THREE.MeshStandardMaterial({
|
|
15
|
+
color: 0xFFFFFF,
|
|
16
|
+
roughness: 0.7,
|
|
17
|
+
metalness: 0.3,
|
|
18
|
+
emissive: 0
|
|
19
|
+
});
|
|
20
|
+
_this.registerDisposable(_this._gatewayGeometry, _this._gatewayMaterial);
|
|
21
|
+
return _this;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get path colors for visual distinction
|
|
26
|
+
* @param {number} index - Path index
|
|
27
|
+
* @returns {string} Hex color string
|
|
28
|
+
*/
|
|
29
|
+
_inherits(PathRenderingManager, _BaseDisposable);
|
|
30
|
+
return _createClass(PathRenderingManager, [{
|
|
31
|
+
key: "getPathColor",
|
|
32
|
+
value: function getPathColor(index) {
|
|
33
|
+
var colors = [
|
|
34
|
+
// '#468e49',
|
|
35
|
+
'#245e29'
|
|
36
|
+
// '#2e80d2',
|
|
37
|
+
// '#1d51a1'
|
|
38
|
+
];
|
|
39
|
+
return colors[index % colors.length];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create gateways in the scene from pathfinding results
|
|
44
|
+
* @param {Object} pathfindingResult - Result object from pathfinder containing gateways
|
|
45
|
+
*/
|
|
46
|
+
}, {
|
|
47
|
+
key: "createGateways",
|
|
48
|
+
value: function createGateways(pathfindingResult) {
|
|
49
|
+
var _this2 = this;
|
|
50
|
+
pathfindingResult.gateways.forEach(function (gateway) {
|
|
51
|
+
if (!gateway.position) {
|
|
52
|
+
console.warn("\u26A0\uFE0F Gateway ".concat(gateway.id, " missing position, skipping creation"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check if gateway already exists in scene (prevent duplicates)
|
|
57
|
+
var existingGateway = _this2.sceneViewer.scene.getObjectByProperty('uuid', gateway.id);
|
|
58
|
+
if (existingGateway) {
|
|
59
|
+
console.log("\u2139\uFE0F Gateway ".concat(gateway.id, " already exists, skipping creation"));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Create gateway mesh using shared geometry and material
|
|
64
|
+
var gatewayMesh = new THREE.Mesh(_this2._gatewayGeometry, _this2._gatewayMaterial);
|
|
65
|
+
|
|
66
|
+
// Handle position format: pathfinder returns {x,y,z} object or [x,y,z] array
|
|
67
|
+
if (Array.isArray(gateway.position)) {
|
|
68
|
+
gatewayMesh.position.fromArray(gateway.position);
|
|
69
|
+
} else if (gateway.position.x !== undefined) {
|
|
70
|
+
gatewayMesh.position.set(gateway.position.x, gateway.position.y, gateway.position.z);
|
|
71
|
+
} else {
|
|
72
|
+
console.error("\u274C Invalid gateway position format for ".concat(gateway.id, ":"), gateway.position);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
gatewayMesh.uuid = gateway.id;
|
|
76
|
+
|
|
77
|
+
// Set userData to make gateways selectable
|
|
78
|
+
gatewayMesh.userData = {
|
|
79
|
+
objectType: 'gateway',
|
|
80
|
+
isDeclared: false,
|
|
81
|
+
gatewayId: gateway.id,
|
|
82
|
+
originalUuid: gateway.id,
|
|
83
|
+
// Deep copy connections to prevent mutations affecting pathfinder's internal state
|
|
84
|
+
connections: gateway.connections ? {
|
|
85
|
+
removed: gateway.connections.removed ? _toConsumableArray(gateway.connections.removed) : [],
|
|
86
|
+
added: gateway.connections.added ? _toConsumableArray(gateway.connections.added) : []
|
|
87
|
+
} : {
|
|
88
|
+
removed: [],
|
|
89
|
+
added: []
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Add to scene
|
|
94
|
+
_this2.sceneViewer.scene.add(gatewayMesh);
|
|
95
|
+
console.log("\uD83D\uDD27 Created gateway: ".concat(gateway.id, " at [").concat(gatewayMesh.position.x.toFixed(2), ", ").concat(gatewayMesh.position.y.toFixed(2), ", ").concat(gatewayMesh.position.z.toFixed(2), "]"));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Material factory function for pipe materials
|
|
101
|
+
* @param {Object} crosscubeTextureSet - Texture set for pipe materials
|
|
102
|
+
* @returns {THREE.Material} Pipe material
|
|
103
|
+
*/
|
|
104
|
+
}, {
|
|
105
|
+
key: "createPipeMaterial",
|
|
106
|
+
value: function createPipeMaterial(crosscubeTextureSet) {
|
|
107
|
+
if (crosscubeTextureSet) {
|
|
108
|
+
var materialProps = _objectSpread2(_objectSpread2({}, crosscubeTextureSet.config.materialProps), {}, {
|
|
109
|
+
color: this.getPathColor(0),
|
|
110
|
+
map: crosscubeTextureSet.textures.diffuse,
|
|
111
|
+
normalMap: crosscubeTextureSet.textures.normal,
|
|
112
|
+
roughnessMap: crosscubeTextureSet.textures.roughness,
|
|
113
|
+
metalness: 0.2,
|
|
114
|
+
roughness: 0.9,
|
|
115
|
+
clearcoat: 0.2,
|
|
116
|
+
clearcoatRoughness: 0.2,
|
|
117
|
+
envMapIntensity: 0.6,
|
|
118
|
+
reflectivity: 0.4
|
|
119
|
+
// transparent: true,
|
|
120
|
+
// opacity: 0.75
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Handle normalScale conversion to Vector2
|
|
124
|
+
if (materialProps.normalScale && Array.isArray(materialProps.normalScale)) {
|
|
125
|
+
materialProps.normalScale = _construct(THREE.Vector2, _toConsumableArray(materialProps.normalScale));
|
|
126
|
+
}
|
|
127
|
+
var material = new THREE.MeshPhysicalMaterial(materialProps);
|
|
128
|
+
|
|
129
|
+
// Configure texture wrapping and repeat
|
|
130
|
+
var pipeTextures = [material.map, material.normalMap, material.roughnessMap].filter(Boolean);
|
|
131
|
+
pipeTextures.forEach(function (texture) {
|
|
132
|
+
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
|
|
133
|
+
texture.repeat.set(crosscubeTextureSet.config.repeat.x * 2, crosscubeTextureSet.config.repeat.y * 2);
|
|
134
|
+
});
|
|
135
|
+
return material;
|
|
136
|
+
} else {
|
|
137
|
+
return new THREE.MeshPhysicalMaterial({
|
|
138
|
+
color: this.getPathColor(0),
|
|
139
|
+
metalness: 0.9,
|
|
140
|
+
roughness: 0.7,
|
|
141
|
+
clearcoat: 0.1,
|
|
142
|
+
clearcoatRoughness: 0.3,
|
|
143
|
+
envMapIntensity: 1.5,
|
|
144
|
+
reflectivity: 0.3
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Create pipe paths from pathfinding results
|
|
151
|
+
* @param {Array} paths - Array of path objects from pathfinder
|
|
152
|
+
* @param {Object} crosscubeTextureSet - Texture set for pipe materials
|
|
153
|
+
*/
|
|
154
|
+
}, {
|
|
155
|
+
key: "createPipePaths",
|
|
156
|
+
value: function createPipePaths(paths, crosscubeTextureSet) {
|
|
157
|
+
var _this3 = this;
|
|
158
|
+
var sceneViewer = this.sceneViewer;
|
|
159
|
+
var globalSegmentIndex = 0; // Counter for globally unique segment indices
|
|
160
|
+
|
|
161
|
+
paths.forEach(function (pathData, index) {
|
|
162
|
+
if (pathData.path && pathData.path.length >= 2) {
|
|
163
|
+
var pipeRadius = 0.1;
|
|
164
|
+
var pipeMaterial = _this3.createPipeMaterial(crosscubeTextureSet);
|
|
165
|
+
|
|
166
|
+
// Convert path points to Vector3 objects for consistent handling
|
|
167
|
+
var pathPoints = pathData.path.map(function (point) {
|
|
168
|
+
if (point instanceof THREE.Vector3) {
|
|
169
|
+
return point.clone();
|
|
170
|
+
} else if (Array.isArray(point)) {
|
|
171
|
+
return new THREE.Vector3().fromArray(point);
|
|
172
|
+
} else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
|
|
173
|
+
return new THREE.Vector3(point.x, point.y, point.z);
|
|
174
|
+
} else {
|
|
175
|
+
console.warn('Unknown point format in createPipePaths:', point);
|
|
176
|
+
return new THREE.Vector3(0, 0, 0);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Create one cylinder per segment (after colinear optimization, this should be minimal segments)
|
|
181
|
+
for (var j = 0; j < pathPoints.length - 1; j++) {
|
|
182
|
+
var start = pathPoints[j];
|
|
183
|
+
var end = pathPoints[j + 1];
|
|
184
|
+
var direction = new THREE.Vector3().subVectors(end, start);
|
|
185
|
+
var length = direction.length();
|
|
186
|
+
|
|
187
|
+
// Skip zero-length segments
|
|
188
|
+
if (length < 1e-6) {
|
|
189
|
+
console.warn("Skipping zero-length segment in path ".concat(pathData.from, "-").concat(pathData.to));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
var cylinderGeometry = new THREE.CylinderGeometry(pipeRadius, pipeRadius, length, 16, 1, false);
|
|
193
|
+
var cylinder = new THREE.Mesh(cylinderGeometry, pipeMaterial);
|
|
194
|
+
cylinder.position.copy(start).add(end).multiplyScalar(0.5);
|
|
195
|
+
var quaternion = new THREE.Quaternion();
|
|
196
|
+
var up = new THREE.Vector3(0, 1, 0);
|
|
197
|
+
quaternion.setFromUnitVectors(up, direction.clone().normalize());
|
|
198
|
+
cylinder.quaternion.copy(quaternion);
|
|
199
|
+
cylinder.castShadow = true;
|
|
200
|
+
cylinder.receiveShadow = true;
|
|
201
|
+
|
|
202
|
+
// Set UUID to SEGMENT-{globalSegmentIndex} format
|
|
203
|
+
cylinder.uuid = "SEGMENT-".concat(globalSegmentIndex);
|
|
204
|
+
|
|
205
|
+
// Make pipe segments selectable and add identifying data
|
|
206
|
+
var segmentId = cylinder.uuid;
|
|
207
|
+
|
|
208
|
+
// Add userData to make pipe segments selectable and for tooltip display
|
|
209
|
+
cylinder.userData = {
|
|
210
|
+
objectType: 'segment',
|
|
211
|
+
segmentId: segmentId,
|
|
212
|
+
segmentIndex: globalSegmentIndex,
|
|
213
|
+
pathFrom: pathData.from,
|
|
214
|
+
pathTo: pathData.to
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Increment global segment counter
|
|
218
|
+
globalSegmentIndex++;
|
|
219
|
+
|
|
220
|
+
// Add segment directly to scene instead of to polyline
|
|
221
|
+
sceneViewer.scene.add(cylinder);
|
|
222
|
+
|
|
223
|
+
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
224
|
+
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Create and add elbow joint if there's a direction change at the current segment
|
|
234
|
+
* @param {Array<THREE.Vector3>} pathPoints - Array of path points
|
|
235
|
+
* @param {number} j - Current segment index
|
|
236
|
+
* @param {number} pipeRadius - Radius of the pipe
|
|
237
|
+
* @param {THREE.Material} pipeMaterial - Material for the elbow
|
|
238
|
+
* @param {Object} pathData - Path data object with from/to information
|
|
239
|
+
* @param {number} index - Path index for naming
|
|
240
|
+
* @param {THREE.Scene} scene - Scene object to add elbow to directly
|
|
241
|
+
*/
|
|
242
|
+
}, {
|
|
243
|
+
key: "createAndAddElbowIfNeeded",
|
|
244
|
+
value: function createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, scene) {
|
|
245
|
+
// Only check if there are at least 2 more points ahead
|
|
246
|
+
if (j >= pathPoints.length - 2) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
var currentSegment = pathPoints[j + 1].clone().sub(pathPoints[j]).normalize();
|
|
250
|
+
var nextSegment = pathPoints[j + 2].clone().sub(pathPoints[j + 1]).normalize();
|
|
251
|
+
|
|
252
|
+
// Check if there's actually a direction change (not just continuing straight)
|
|
253
|
+
var angle = currentSegment.angleTo(nextSegment);
|
|
254
|
+
var minAngle = Math.PI / 36; // 5 degrees minimum for creating an elbow
|
|
255
|
+
|
|
256
|
+
if (angle <= minAngle) {
|
|
257
|
+
return; // No significant direction change
|
|
258
|
+
}
|
|
259
|
+
var elbowGeometry = this.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
|
|
260
|
+
if (!elbowGeometry) {
|
|
261
|
+
return; // Failed to create geometry
|
|
262
|
+
}
|
|
263
|
+
var elbow = new THREE.Mesh(elbowGeometry, pipeMaterial);
|
|
264
|
+
elbow.castShadow = true;
|
|
265
|
+
elbow.receiveShadow = true;
|
|
266
|
+
|
|
267
|
+
// Make elbows selectable as well
|
|
268
|
+
var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
|
|
269
|
+
elbow.uuid = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
|
|
270
|
+
|
|
271
|
+
// Add userData for elbows too
|
|
272
|
+
elbow.userData = {
|
|
273
|
+
isPipeElbow: true,
|
|
274
|
+
elbowId: elbowId,
|
|
275
|
+
elbowIndex: j,
|
|
276
|
+
pathFrom: pathData.from,
|
|
277
|
+
pathTo: pathData.to,
|
|
278
|
+
angle: (angle * 180 / Math.PI).toFixed(1),
|
|
279
|
+
// Add component data for tooltips
|
|
280
|
+
component: {
|
|
281
|
+
type: 'PipeElbow',
|
|
282
|
+
attributes: {
|
|
283
|
+
angle: {
|
|
284
|
+
key: 'Bend Angle',
|
|
285
|
+
value: (angle * 180 / Math.PI).toFixed(1),
|
|
286
|
+
unit: '°'
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
scene.add(elbow);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Create smooth elbow geometry to connect two pipe segments (optimized for 90-degree angles)
|
|
296
|
+
* @param {THREE.Vector3} point1 - First point (before the joint)
|
|
297
|
+
* @param {THREE.Vector3} point2 - Joint point (center of the elbow)
|
|
298
|
+
* @param {THREE.Vector3} point3 - Third point (after the joint)
|
|
299
|
+
* @param {number} radius - Pipe radius
|
|
300
|
+
* @returns {THREE.BufferGeometry} Elbow geometry
|
|
301
|
+
*/
|
|
302
|
+
}, {
|
|
303
|
+
key: "createElbowGeometry",
|
|
304
|
+
value: function createElbowGeometry(point1, point2, point3, radius) {
|
|
305
|
+
try {
|
|
306
|
+
// Fixed elbow radius for 90-degree bends (simplified)
|
|
307
|
+
var elbowRadius = radius * 3;
|
|
308
|
+
|
|
309
|
+
// Create a curve for the 90-degree elbow
|
|
310
|
+
var curve = this.createElbowCurve(point1, point2, point3, elbowRadius);
|
|
311
|
+
|
|
312
|
+
// Fixed tubular segments for 90-degree bends (quarter circle)
|
|
313
|
+
var tubularSegments = 12; // Good balance for smooth 90° curves
|
|
314
|
+
var radialSegments = 16;
|
|
315
|
+
var closed = false;
|
|
316
|
+
var elbowGeometry = new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
|
|
317
|
+
return elbowGeometry;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.warn('Failed to create elbow geometry:', error);
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Create a smooth curve for the 90-degree elbow joint (simplified)
|
|
326
|
+
* @param {THREE.Vector3} point1 - First point
|
|
327
|
+
* @param {THREE.Vector3} point2 - Joint point
|
|
328
|
+
* @param {THREE.Vector3} point3 - Third point
|
|
329
|
+
* @param {number} elbowRadius - Radius of the elbow curve
|
|
330
|
+
* @returns {THREE.Curve} Curve for the elbow
|
|
331
|
+
*/
|
|
332
|
+
}, {
|
|
333
|
+
key: "createElbowCurve",
|
|
334
|
+
value: function createElbowCurve(point1, point2, point3, elbowRadius) {
|
|
335
|
+
// Calculate direction vectors
|
|
336
|
+
var dir1 = point2.clone().sub(point1).normalize();
|
|
337
|
+
var dir2 = point3.clone().sub(point2).normalize();
|
|
338
|
+
|
|
339
|
+
// For 90-degree bends, we can use a simpler approach with a quarter circle
|
|
340
|
+
// The curve radius is proportional to the elbow radius
|
|
341
|
+
var curveRadius = elbowRadius * 0.001;
|
|
342
|
+
|
|
343
|
+
// Calculate the offset distance from the joint point
|
|
344
|
+
var offset = curveRadius;
|
|
345
|
+
|
|
346
|
+
// Calculate start and end points of the curve (offset from the joint)
|
|
347
|
+
var curveStart = point2.clone().sub(dir1.clone().multiplyScalar(offset));
|
|
348
|
+
var curveEnd = point2.clone().add(dir2.clone().multiplyScalar(offset));
|
|
349
|
+
|
|
350
|
+
// For a 90-degree bend, the control point is at the corner
|
|
351
|
+
// We can use a quadratic bezier curve for simplicity
|
|
352
|
+
var controlPoint = point2.clone();
|
|
353
|
+
|
|
354
|
+
// Create a quadratic bezier curve (simpler than cubic for 90° bends)
|
|
355
|
+
var curve = new THREE.QuadraticBezierCurve3(curveStart, controlPoint, curveEnd);
|
|
356
|
+
return curve;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Dispose of rendering resources
|
|
361
|
+
*/
|
|
362
|
+
}, {
|
|
363
|
+
key: "dispose",
|
|
364
|
+
value: function dispose() {
|
|
365
|
+
console.log('🗑️ Disposing PathRenderingManager...');
|
|
366
|
+
|
|
367
|
+
// Call parent dispose to clean up registered resources (shared gateway geometry/material)
|
|
368
|
+
_superPropGet(PathRenderingManager, "dispose", this, 3)([]);
|
|
369
|
+
|
|
370
|
+
// Nullify properties
|
|
371
|
+
this.sceneViewer = null;
|
|
372
|
+
console.log('✅ PathRenderingManager disposed');
|
|
373
|
+
}
|
|
374
|
+
}]);
|
|
375
|
+
}(BaseDisposable);
|
|
376
|
+
|
|
377
|
+
export { PathRenderingManager };
|