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