@2112-lab/central-plant 0.1.30 → 0.1.32
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 +368 -6
- package/dist/cjs/pathfinder/src/PathManager.js +59 -2
- package/dist/cjs/src/core/centralPlant.js +182 -4
- package/dist/cjs/src/managers/components/pathfindingManager.js +127 -0
- package/dist/esm/pathfinder/src/PathManager.js +60 -3
- package/dist/esm/src/core/centralPlant.js +183 -5
- package/dist/esm/src/managers/components/pathfindingManager.js +127 -0
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -18183,7 +18183,7 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
18183
18183
|
}
|
|
18184
18184
|
|
|
18185
18185
|
/**
|
|
18186
|
-
* A* pathfinding algorithm
|
|
18186
|
+
* A* pathfinding algorithm with bend minimization
|
|
18187
18187
|
* @private
|
|
18188
18188
|
* @param {string} start - Start voxel key
|
|
18189
18189
|
* @param {string} goal - Goal voxel key
|
|
@@ -18242,7 +18242,11 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
18242
18242
|
var _gScore$neighbor;
|
|
18243
18243
|
var neighbor = _step2.value;
|
|
18244
18244
|
if (occupied.has(neighbor)) continue;
|
|
18245
|
-
|
|
18245
|
+
|
|
18246
|
+
// Calculate cost with bend penalty
|
|
18247
|
+
var tentativeG = this.calculateGScore(current, neighbor, cameFrom[current], gScore[current]);
|
|
18248
|
+
// const tentativeG = gScore[current] + 1;
|
|
18249
|
+
|
|
18246
18250
|
if (tentativeG < ((_gScore$neighbor = gScore[neighbor]) !== null && _gScore$neighbor !== void 0 ? _gScore$neighbor : Infinity)) {
|
|
18247
18251
|
cameFrom[neighbor] = current;
|
|
18248
18252
|
gScore[neighbor] = tentativeG;
|
|
@@ -18259,6 +18263,59 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
18259
18263
|
return null;
|
|
18260
18264
|
}
|
|
18261
18265
|
|
|
18266
|
+
/**
|
|
18267
|
+
* Calculate G score with bend penalty
|
|
18268
|
+
* @private
|
|
18269
|
+
* @param {string} current - Current voxel key
|
|
18270
|
+
* @param {string} neighbor - Neighbor voxel key
|
|
18271
|
+
* @param {string} parent - Parent voxel key (null if current is start)
|
|
18272
|
+
* @param {number} currentG - Current G score
|
|
18273
|
+
* @returns {number} G score with bend penalty
|
|
18274
|
+
*/
|
|
18275
|
+
}, {
|
|
18276
|
+
key: "calculateGScore",
|
|
18277
|
+
value: function calculateGScore(current, neighbor, parent, currentG) {
|
|
18278
|
+
var cost = currentG + 1; // Base movement cost
|
|
18279
|
+
|
|
18280
|
+
if (parent) {
|
|
18281
|
+
// Check if this move creates a bend
|
|
18282
|
+
var _parent$split$map = parent.split(',').map(Number),
|
|
18283
|
+
_parent$split$map2 = _slicedToArray(_parent$split$map, 3),
|
|
18284
|
+
px = _parent$split$map2[0],
|
|
18285
|
+
py = _parent$split$map2[1],
|
|
18286
|
+
pz = _parent$split$map2[2];
|
|
18287
|
+
var _current$split$map = current.split(',').map(Number),
|
|
18288
|
+
_current$split$map2 = _slicedToArray(_current$split$map, 3),
|
|
18289
|
+
cx = _current$split$map2[0],
|
|
18290
|
+
cy = _current$split$map2[1],
|
|
18291
|
+
cz = _current$split$map2[2];
|
|
18292
|
+
var _neighbor$split$map = neighbor.split(',').map(Number),
|
|
18293
|
+
_neighbor$split$map2 = _slicedToArray(_neighbor$split$map, 3),
|
|
18294
|
+
nx = _neighbor$split$map2[0],
|
|
18295
|
+
ny = _neighbor$split$map2[1],
|
|
18296
|
+
nz = _neighbor$split$map2[2];
|
|
18297
|
+
|
|
18298
|
+
// Direction from parent to current
|
|
18299
|
+
var prevDir = {
|
|
18300
|
+
x: cx - px,
|
|
18301
|
+
y: cy - py,
|
|
18302
|
+
z: cz - pz
|
|
18303
|
+
};
|
|
18304
|
+
// Direction from current to neighbor
|
|
18305
|
+
var nextDir = {
|
|
18306
|
+
x: nx - cx,
|
|
18307
|
+
y: ny - cy,
|
|
18308
|
+
z: nz - cz
|
|
18309
|
+
};
|
|
18310
|
+
|
|
18311
|
+
// If directions are different, add bend penalty
|
|
18312
|
+
if (prevDir.x !== nextDir.x || prevDir.y !== nextDir.y || prevDir.z !== nextDir.z) {
|
|
18313
|
+
cost += 0.00001; // Bend penalty - adjust this value to control how much bends are avoided
|
|
18314
|
+
}
|
|
18315
|
+
}
|
|
18316
|
+
return cost;
|
|
18317
|
+
}
|
|
18318
|
+
|
|
18262
18319
|
/**
|
|
18263
18320
|
* Find a path respecting virtual segments
|
|
18264
18321
|
* @private
|
|
@@ -19356,6 +19413,9 @@ var PathfindingManager = /*#__PURE__*/function () {
|
|
|
19356
19413
|
console.log('Generated gateways:', JSON.parse(JSON.stringify(pathfindingResult.gateways)));
|
|
19357
19414
|
console.log('Rewired connections:', JSON.parse(JSON.stringify(pathfindingResult.rewiredConnections)));
|
|
19358
19415
|
|
|
19416
|
+
// Check for duplicate direction vectors going into the same gateways
|
|
19417
|
+
this.checkForDuplicateGatewayDirections(pathfindingResult, sceneData, connections);
|
|
19418
|
+
|
|
19359
19419
|
// Create gateways in the scene if requested
|
|
19360
19420
|
if (createGateways && pathfindingResult.gateways) {
|
|
19361
19421
|
pathfindingResult.gateways.forEach(function (gateway) {
|
|
@@ -20607,6 +20667,130 @@ var PathfindingManager = /*#__PURE__*/function () {
|
|
|
20607
20667
|
});
|
|
20608
20668
|
return optimizedPaths;
|
|
20609
20669
|
}
|
|
20670
|
+
|
|
20671
|
+
/**
|
|
20672
|
+
* Check for duplicate direction vectors going into the same gateways
|
|
20673
|
+
* This helps diagnose path overlapping issues caused by incorrect connector directions after rotation
|
|
20674
|
+
* @param {Object} pathfindingResult - Result from pathfinder.findPaths()
|
|
20675
|
+
* @param {Object} sceneData - Scene data used for pathfinding
|
|
20676
|
+
* @param {Array} connections - Original connections array
|
|
20677
|
+
*/
|
|
20678
|
+
}, {
|
|
20679
|
+
key: "checkForDuplicateGatewayDirections",
|
|
20680
|
+
value: function checkForDuplicateGatewayDirections(pathfindingResult, sceneData, connections) {
|
|
20681
|
+
var _this4 = this;
|
|
20682
|
+
if (!pathfindingResult.gateways || !pathfindingResult.rewiredConnections) {
|
|
20683
|
+
return; // No gateways or rewired connections to check
|
|
20684
|
+
}
|
|
20685
|
+
console.log('🔍 Checking for duplicate direction vectors going into gateways...');
|
|
20686
|
+
|
|
20687
|
+
// Group connections by gateway
|
|
20688
|
+
var gatewayConnections = new Map();
|
|
20689
|
+
pathfindingResult.rewiredConnections.forEach(function (conn) {
|
|
20690
|
+
// Check if this connection goes TO a gateway
|
|
20691
|
+
var toGateway = pathfindingResult.gateways.find(function (gw) {
|
|
20692
|
+
return gw.id === conn.to;
|
|
20693
|
+
});
|
|
20694
|
+
if (toGateway) {
|
|
20695
|
+
if (!gatewayConnections.has(conn.to)) {
|
|
20696
|
+
gatewayConnections.set(conn.to, []);
|
|
20697
|
+
}
|
|
20698
|
+
gatewayConnections.get(conn.to).push({
|
|
20699
|
+
connection: conn,
|
|
20700
|
+
gateway: toGateway
|
|
20701
|
+
});
|
|
20702
|
+
}
|
|
20703
|
+
});
|
|
20704
|
+
|
|
20705
|
+
// Check each gateway for duplicate direction vectors
|
|
20706
|
+
var hasErrors = false;
|
|
20707
|
+
gatewayConnections.forEach(function (connectionsToGateway, gatewayId) {
|
|
20708
|
+
if (connectionsToGateway.length < 2) {
|
|
20709
|
+
return; // Need at least 2 connections to have duplicates
|
|
20710
|
+
}
|
|
20711
|
+
console.log("\uD83D\uDD0D Checking gateway ".concat(gatewayId, " with ").concat(connectionsToGateway.length, " incoming connections"));
|
|
20712
|
+
|
|
20713
|
+
// Get direction vectors for each connection going into this gateway
|
|
20714
|
+
var directionVectors = [];
|
|
20715
|
+
connectionsToGateway.forEach(function (_ref) {
|
|
20716
|
+
var connection = _ref.connection;
|
|
20717
|
+
// Find the connector object in the scene data
|
|
20718
|
+
var connectorObj = _this4.findObjectInSceneData(sceneData, connection.from);
|
|
20719
|
+
if (connectorObj && connectorObj.userData && connectorObj.userData.direction) {
|
|
20720
|
+
var direction = connectorObj.userData.direction;
|
|
20721
|
+
directionVectors.push({
|
|
20722
|
+
connectionFrom: connection.from,
|
|
20723
|
+
direction: direction,
|
|
20724
|
+
directionString: "[".concat(direction[0], ", ").concat(direction[1], ", ").concat(direction[2], "]")
|
|
20725
|
+
});
|
|
20726
|
+
console.log(" \uD83D\uDCCD Connector ".concat(connection.from, " direction: [").concat(direction[0], ", ").concat(direction[1], ", ").concat(direction[2], "]"));
|
|
20727
|
+
} else {
|
|
20728
|
+
console.warn(" \u26A0\uFE0F Could not find direction for connector ".concat(connection.from));
|
|
20729
|
+
}
|
|
20730
|
+
});
|
|
20731
|
+
|
|
20732
|
+
// Check for duplicate directions
|
|
20733
|
+
var directionMap = new Map();
|
|
20734
|
+
directionVectors.forEach(function (_ref2) {
|
|
20735
|
+
var connectionFrom = _ref2.connectionFrom;
|
|
20736
|
+
_ref2.direction;
|
|
20737
|
+
var directionString = _ref2.directionString;
|
|
20738
|
+
if (!directionMap.has(directionString)) {
|
|
20739
|
+
directionMap.set(directionString, []);
|
|
20740
|
+
}
|
|
20741
|
+
directionMap.get(directionString).push(connectionFrom);
|
|
20742
|
+
});
|
|
20743
|
+
|
|
20744
|
+
// Find duplicates
|
|
20745
|
+
directionMap.forEach(function (connectors, directionString) {
|
|
20746
|
+
if (connectors.length > 1) {
|
|
20747
|
+
hasErrors = true;
|
|
20748
|
+
console.error("\u274C DUPLICATE DIRECTION VECTORS DETECTED!\n" + " Gateway: ".concat(gatewayId, "\n") + " Direction: ".concat(directionString, "\n") + " Connectors with same direction: ".concat(connectors.join(', '), "\n") + " This will cause path overlapping! The connectors going into the same gateway should have different direction vectors after component rotation.");
|
|
20749
|
+
}
|
|
20750
|
+
});
|
|
20751
|
+
});
|
|
20752
|
+
if (!hasErrors) {
|
|
20753
|
+
console.log('✅ No duplicate direction vectors detected in gateway connections');
|
|
20754
|
+
} else {
|
|
20755
|
+
console.error("\u274C PATHFINDING DIAGNOSTIC: Found duplicate direction vectors going into gateways.\n" + " This is likely caused by connector direction vectors not being properly updated after component rotation.\n" + " The rotation code should transform the connector userData.direction arrays to reflect the new orientation.");
|
|
20756
|
+
}
|
|
20757
|
+
}
|
|
20758
|
+
|
|
20759
|
+
/**
|
|
20760
|
+
* Helper method to find an object in scene data by UUID
|
|
20761
|
+
* @param {Object} sceneData - Scene data to search
|
|
20762
|
+
* @param {string} uuid - UUID to find
|
|
20763
|
+
* @returns {Object|null} Found object or null
|
|
20764
|
+
*/
|
|
20765
|
+
}, {
|
|
20766
|
+
key: "findObjectInSceneData",
|
|
20767
|
+
value: function findObjectInSceneData(sceneData, uuid) {
|
|
20768
|
+
var _searchChildren = function searchChildren(children) {
|
|
20769
|
+
var _iterator2 = _createForOfIteratorHelper(children),
|
|
20770
|
+
_step2;
|
|
20771
|
+
try {
|
|
20772
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
20773
|
+
var child = _step2.value;
|
|
20774
|
+
if (child.uuid === uuid) {
|
|
20775
|
+
return child;
|
|
20776
|
+
}
|
|
20777
|
+
if (child.children) {
|
|
20778
|
+
var found = _searchChildren(child.children);
|
|
20779
|
+
if (found) return found;
|
|
20780
|
+
}
|
|
20781
|
+
}
|
|
20782
|
+
} catch (err) {
|
|
20783
|
+
_iterator2.e(err);
|
|
20784
|
+
} finally {
|
|
20785
|
+
_iterator2.f();
|
|
20786
|
+
}
|
|
20787
|
+
return null;
|
|
20788
|
+
};
|
|
20789
|
+
if (sceneData.object && sceneData.object.children) {
|
|
20790
|
+
return _searchChildren(sceneData.object.children);
|
|
20791
|
+
}
|
|
20792
|
+
return null;
|
|
20793
|
+
}
|
|
20610
20794
|
}]);
|
|
20611
20795
|
}();
|
|
20612
20796
|
|
|
@@ -26055,6 +26239,9 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26055
26239
|
// Update the Three.js object position
|
|
26056
26240
|
component.position[axis] += value;
|
|
26057
26241
|
|
|
26242
|
+
// Update world bounding boxes for the component and its children
|
|
26243
|
+
this.updateWorldBoundingBoxes(component);
|
|
26244
|
+
|
|
26058
26245
|
// Update the associated JSON object in currentSceneData if it exists
|
|
26059
26246
|
if (this.sceneViewer.currentSceneData && this.sceneViewer.currentSceneData.scene) {
|
|
26060
26247
|
if (component.userData.associatedJsonObject) {
|
|
@@ -26168,6 +26355,14 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26168
26355
|
// Apply the rotation
|
|
26169
26356
|
component.rotation[axis] += radians;
|
|
26170
26357
|
|
|
26358
|
+
// Update direction vectors for connectors if this is a 90-degree rotation
|
|
26359
|
+
if (value % 90 === 0) {
|
|
26360
|
+
this.updateDirectionAfterRotation(component, axis, value);
|
|
26361
|
+
}
|
|
26362
|
+
|
|
26363
|
+
// Update world bounding boxes for the component and its children
|
|
26364
|
+
this.updateWorldBoundingBoxes(component);
|
|
26365
|
+
|
|
26171
26366
|
// Update the associated JSON object in currentSceneData if it exists
|
|
26172
26367
|
if (this.sceneViewer.currentSceneData && this.sceneViewer.currentSceneData.scene) {
|
|
26173
26368
|
if (component.userData.associatedJsonObject) {
|
|
@@ -26215,6 +26410,173 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26215
26410
|
return true;
|
|
26216
26411
|
}
|
|
26217
26412
|
|
|
26413
|
+
/**
|
|
26414
|
+
* Update userData.direction for components after 90-degree rotation
|
|
26415
|
+
* This method handles the direction vector transformation for connectors when their parent component is rotated
|
|
26416
|
+
*
|
|
26417
|
+
* @param {THREE.Object3D} component - The component that was rotated
|
|
26418
|
+
* @param {string} axis - The axis of rotation ('x', 'y', or 'z')
|
|
26419
|
+
* @param {number} degrees - The rotation angle in degrees (should be multiple of 90)
|
|
26420
|
+
* @private
|
|
26421
|
+
*/
|
|
26422
|
+
}, {
|
|
26423
|
+
key: "updateDirectionAfterRotation",
|
|
26424
|
+
value: function updateDirectionAfterRotation(component, axis, degrees) {
|
|
26425
|
+
var _this = this;
|
|
26426
|
+
if (!component) {
|
|
26427
|
+
console.warn('⚠️ updateDirectionAfterRotation: No component provided');
|
|
26428
|
+
return;
|
|
26429
|
+
}
|
|
26430
|
+
|
|
26431
|
+
// Only handle 90-degree increments
|
|
26432
|
+
if (degrees % 90 !== 0) {
|
|
26433
|
+
console.warn('⚠️ updateDirectionAfterRotation: Only 90-degree increments are supported');
|
|
26434
|
+
return;
|
|
26435
|
+
}
|
|
26436
|
+
|
|
26437
|
+
// Normalize degrees to 0-360 range
|
|
26438
|
+
var normalizedDegrees = (degrees % 360 + 360) % 360;
|
|
26439
|
+
console.log("\uD83D\uDD04 Updating direction vectors for ".concat(component.name || component.uuid, " after ").concat(degrees, "\xB0 rotation around ").concat(axis, " axis"));
|
|
26440
|
+
|
|
26441
|
+
// Traverse all children (connectors) and update their direction vectors
|
|
26442
|
+
component.traverse(function (child) {
|
|
26443
|
+
if (child.userData && Array.isArray(child.userData.direction) && child.userData.componentType === 'connector') {
|
|
26444
|
+
var originalDirection = _toConsumableArray(child.userData.direction);
|
|
26445
|
+
var newDirection = _this.rotateDirectionVector(originalDirection, axis, normalizedDegrees);
|
|
26446
|
+
|
|
26447
|
+
// Update the direction
|
|
26448
|
+
child.userData.direction = newDirection;
|
|
26449
|
+
console.log("\uD83D\uDCCD Updated connector ".concat(child.name || child.uuid, " direction:"), {
|
|
26450
|
+
original: originalDirection,
|
|
26451
|
+
new: newDirection,
|
|
26452
|
+
rotationAxis: axis,
|
|
26453
|
+
rotationDegrees: degrees
|
|
26454
|
+
});
|
|
26455
|
+
}
|
|
26456
|
+
});
|
|
26457
|
+
}
|
|
26458
|
+
|
|
26459
|
+
/**
|
|
26460
|
+
* Rotate a direction vector by 90-degree increments around a specific axis
|
|
26461
|
+
*
|
|
26462
|
+
* @param {Array<number>} direction - The original direction vector [x, y, z]
|
|
26463
|
+
* @param {string} axis - The axis of rotation ('x', 'y', or 'z')
|
|
26464
|
+
* @param {number} degrees - The rotation angle in degrees (must be multiple of 90)
|
|
26465
|
+
* @returns {Array<number>} The new direction vector [x, y, z]
|
|
26466
|
+
* @private
|
|
26467
|
+
*/
|
|
26468
|
+
}, {
|
|
26469
|
+
key: "rotateDirectionVector",
|
|
26470
|
+
value: function rotateDirectionVector(direction, axis, degrees) {
|
|
26471
|
+
if (!Array.isArray(direction) || direction.length !== 3) {
|
|
26472
|
+
console.warn('⚠️ rotateDirectionVector: Invalid direction vector');
|
|
26473
|
+
return direction;
|
|
26474
|
+
}
|
|
26475
|
+
var _direction = _slicedToArray(direction, 3),
|
|
26476
|
+
x = _direction[0],
|
|
26477
|
+
y = _direction[1],
|
|
26478
|
+
z = _direction[2];
|
|
26479
|
+
var steps = degrees / 90; // Number of 90-degree steps
|
|
26480
|
+
|
|
26481
|
+
for (var i = 0; i < steps; i++) {
|
|
26482
|
+
var newX = x,
|
|
26483
|
+
newY = y,
|
|
26484
|
+
newZ = z;
|
|
26485
|
+
switch (axis) {
|
|
26486
|
+
case 'x':
|
|
26487
|
+
// Rotation around X-axis: Y becomes -Z, Z becomes Y
|
|
26488
|
+
newY = -z;
|
|
26489
|
+
newZ = y;
|
|
26490
|
+
break;
|
|
26491
|
+
case 'y':
|
|
26492
|
+
// Rotation around Y-axis: X becomes Z, Z becomes -X
|
|
26493
|
+
newX = z;
|
|
26494
|
+
newZ = -x;
|
|
26495
|
+
break;
|
|
26496
|
+
case 'z':
|
|
26497
|
+
// Rotation around Z-axis: X becomes -Y, Y becomes X
|
|
26498
|
+
newX = -y;
|
|
26499
|
+
newY = x;
|
|
26500
|
+
break;
|
|
26501
|
+
default:
|
|
26502
|
+
console.warn("\u26A0\uFE0F rotateDirectionVector: Invalid axis '".concat(axis, "'"));
|
|
26503
|
+
return direction;
|
|
26504
|
+
}
|
|
26505
|
+
x = newX;
|
|
26506
|
+
y = newY;
|
|
26507
|
+
z = newZ;
|
|
26508
|
+
}
|
|
26509
|
+
return [x, y, z];
|
|
26510
|
+
}
|
|
26511
|
+
|
|
26512
|
+
/**
|
|
26513
|
+
* Update world bounding boxes for a component and its children after transformation
|
|
26514
|
+
* This method recalculates bounding boxes based on the new position/rotation
|
|
26515
|
+
*
|
|
26516
|
+
* @param {THREE.Object3D} component - The component that was transformed
|
|
26517
|
+
* @private
|
|
26518
|
+
*/
|
|
26519
|
+
}, {
|
|
26520
|
+
key: "updateWorldBoundingBoxes",
|
|
26521
|
+
value: function updateWorldBoundingBoxes(component) {
|
|
26522
|
+
var _this$sceneViewer, _this$sceneViewer2;
|
|
26523
|
+
if (!component) {
|
|
26524
|
+
console.warn('⚠️ updateWorldBoundingBoxes: No component provided');
|
|
26525
|
+
return;
|
|
26526
|
+
}
|
|
26527
|
+
console.log("\uD83D\uDCE6 Updating world bounding boxes for ".concat(component.name || component.uuid));
|
|
26528
|
+
|
|
26529
|
+
// Update bounding box for the main component and all its children
|
|
26530
|
+
component.traverse(function (child) {
|
|
26531
|
+
if (child.isMesh || child.userData.componentType) {
|
|
26532
|
+
try {
|
|
26533
|
+
// Force matrix updates to ensure accurate bounding box calculation
|
|
26534
|
+
child.updateMatrix();
|
|
26535
|
+
child.updateMatrixWorld(true);
|
|
26536
|
+
|
|
26537
|
+
// Calculate new world bounding box
|
|
26538
|
+
var boundingBox = new THREE__namespace.Box3().setFromObject(child);
|
|
26539
|
+
|
|
26540
|
+
// Update userData.worldBoundingBox if it exists
|
|
26541
|
+
if (child.userData) {
|
|
26542
|
+
child.userData.worldBoundingBox = {
|
|
26543
|
+
min: boundingBox.min.toArray(),
|
|
26544
|
+
max: boundingBox.max.toArray()
|
|
26545
|
+
};
|
|
26546
|
+
console.log("\uD83D\uDCE6 Updated bounding box for ".concat(child.name || child.uuid, ":"), {
|
|
26547
|
+
min: boundingBox.min.toArray(),
|
|
26548
|
+
max: boundingBox.max.toArray()
|
|
26549
|
+
});
|
|
26550
|
+
}
|
|
26551
|
+
|
|
26552
|
+
// Update associated JSON object if it exists
|
|
26553
|
+
if (child.userData.associatedJsonObject) {
|
|
26554
|
+
if (!child.userData.associatedJsonObject.userData) {
|
|
26555
|
+
child.userData.associatedJsonObject.userData = {};
|
|
26556
|
+
}
|
|
26557
|
+
child.userData.associatedJsonObject.userData.worldBoundingBox = {
|
|
26558
|
+
min: boundingBox.min.toArray(),
|
|
26559
|
+
max: boundingBox.max.toArray()
|
|
26560
|
+
};
|
|
26561
|
+
console.log("\uD83D\uDCE6 Updated JSON bounding box for ".concat(child.name || child.uuid));
|
|
26562
|
+
}
|
|
26563
|
+
} catch (error) {
|
|
26564
|
+
console.warn("\u26A0\uFE0F Error updating bounding box for ".concat(child.name || child.uuid, ":"), error);
|
|
26565
|
+
}
|
|
26566
|
+
}
|
|
26567
|
+
});
|
|
26568
|
+
|
|
26569
|
+
// Also trigger the pathfinding manager's recompute method for consistency
|
|
26570
|
+
if ((_this$sceneViewer = this.sceneViewer) !== null && _this$sceneViewer !== void 0 && _this$sceneViewer.pathfindingManager && (_this$sceneViewer2 = this.sceneViewer) !== null && _this$sceneViewer2 !== void 0 && _this$sceneViewer2.currentSceneData && typeof this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes === 'function') {
|
|
26571
|
+
try {
|
|
26572
|
+
this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes(this.sceneViewer.currentSceneData);
|
|
26573
|
+
console.log('📦 Triggered pathfinding manager bounding box recompute');
|
|
26574
|
+
} catch (error) {
|
|
26575
|
+
console.warn('⚠️ Error triggering pathfinding bounding box recompute:', error);
|
|
26576
|
+
}
|
|
26577
|
+
}
|
|
26578
|
+
}
|
|
26579
|
+
|
|
26218
26580
|
/**
|
|
26219
26581
|
* Update paths in the scene
|
|
26220
26582
|
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
@@ -26268,7 +26630,7 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26268
26630
|
}, {
|
|
26269
26631
|
key: "syncSceneData",
|
|
26270
26632
|
value: function syncSceneData() {
|
|
26271
|
-
var
|
|
26633
|
+
var _this2 = this;
|
|
26272
26634
|
// Check if scene viewer and currentSceneData are available
|
|
26273
26635
|
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
26274
26636
|
console.warn('⚠️ syncSceneData(): Scene viewer or current scene data not available');
|
|
@@ -26293,7 +26655,7 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26293
26655
|
currentSceneData.scene.object.children.forEach(function (sceneDataChild, index) {
|
|
26294
26656
|
// Find matching Three.js object
|
|
26295
26657
|
var matchingThreeObject = null;
|
|
26296
|
-
|
|
26658
|
+
_this2.sceneViewer.scene.traverse(function (threeObject) {
|
|
26297
26659
|
var _sceneDataChild$userD, _threeObject$userData, _threeObject$userData2;
|
|
26298
26660
|
// Check various UUID matching strategies
|
|
26299
26661
|
if (threeObject.uuid === sceneDataChild.uuid || threeObject.uuid === ((_sceneDataChild$userD = sceneDataChild.userData) === null || _sceneDataChild$userD === void 0 ? void 0 : _sceneDataChild$userD.originalUuid) || ((_threeObject$userData = threeObject.userData) === null || _threeObject$userData === void 0 ? void 0 : _threeObject$userData.originalUuid) === sceneDataChild.uuid || ((_threeObject$userData2 = threeObject.userData) === null || _threeObject$userData2 === void 0 ? void 0 : _threeObject$userData2.hardcodedUuid) === sceneDataChild.uuid) {
|
|
@@ -26400,7 +26762,7 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26400
26762
|
}, {
|
|
26401
26763
|
key: "forceSyncSceneData",
|
|
26402
26764
|
value: function forceSyncSceneData() {
|
|
26403
|
-
var
|
|
26765
|
+
var _this3 = this;
|
|
26404
26766
|
// Check if scene viewer and sceneOperationsManager are available
|
|
26405
26767
|
if (!this.sceneViewer || !this.sceneViewer.sceneOperationsManager) {
|
|
26406
26768
|
console.warn('⚠️ forceSyncSceneData(): Scene viewer or scene operations manager not available');
|
|
@@ -26426,7 +26788,7 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
26426
26788
|
console.log("\uD83D\uDD04 Syncing object: ".concat(threeObject.uuid, " (").concat(threeObject.userData.componentType || 'unknown', ")"));
|
|
26427
26789
|
|
|
26428
26790
|
// Use the existing updateSceneDataAfterTransform method
|
|
26429
|
-
var success =
|
|
26791
|
+
var success = _this3.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(threeObject, currentSceneData);
|
|
26430
26792
|
if (success) {
|
|
26431
26793
|
syncedCount++;
|
|
26432
26794
|
} else {
|
|
@@ -27,7 +27,7 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* A* pathfinding algorithm
|
|
30
|
+
* A* pathfinding algorithm with bend minimization
|
|
31
31
|
* @private
|
|
32
32
|
* @param {string} start - Start voxel key
|
|
33
33
|
* @param {string} goal - Goal voxel key
|
|
@@ -86,7 +86,11 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
86
86
|
var _gScore$neighbor;
|
|
87
87
|
var neighbor = _step2.value;
|
|
88
88
|
if (occupied.has(neighbor)) continue;
|
|
89
|
-
|
|
89
|
+
|
|
90
|
+
// Calculate cost with bend penalty
|
|
91
|
+
var tentativeG = this.calculateGScore(current, neighbor, cameFrom[current], gScore[current]);
|
|
92
|
+
// const tentativeG = gScore[current] + 1;
|
|
93
|
+
|
|
90
94
|
if (tentativeG < ((_gScore$neighbor = gScore[neighbor]) !== null && _gScore$neighbor !== void 0 ? _gScore$neighbor : Infinity)) {
|
|
91
95
|
cameFrom[neighbor] = current;
|
|
92
96
|
gScore[neighbor] = tentativeG;
|
|
@@ -103,6 +107,59 @@ var PathManager = /*#__PURE__*/function () {
|
|
|
103
107
|
return null;
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Calculate G score with bend penalty
|
|
112
|
+
* @private
|
|
113
|
+
* @param {string} current - Current voxel key
|
|
114
|
+
* @param {string} neighbor - Neighbor voxel key
|
|
115
|
+
* @param {string} parent - Parent voxel key (null if current is start)
|
|
116
|
+
* @param {number} currentG - Current G score
|
|
117
|
+
* @returns {number} G score with bend penalty
|
|
118
|
+
*/
|
|
119
|
+
}, {
|
|
120
|
+
key: "calculateGScore",
|
|
121
|
+
value: function calculateGScore(current, neighbor, parent, currentG) {
|
|
122
|
+
var cost = currentG + 1; // Base movement cost
|
|
123
|
+
|
|
124
|
+
if (parent) {
|
|
125
|
+
// Check if this move creates a bend
|
|
126
|
+
var _parent$split$map = parent.split(',').map(Number),
|
|
127
|
+
_parent$split$map2 = _rollupPluginBabelHelpers.slicedToArray(_parent$split$map, 3),
|
|
128
|
+
px = _parent$split$map2[0],
|
|
129
|
+
py = _parent$split$map2[1],
|
|
130
|
+
pz = _parent$split$map2[2];
|
|
131
|
+
var _current$split$map = current.split(',').map(Number),
|
|
132
|
+
_current$split$map2 = _rollupPluginBabelHelpers.slicedToArray(_current$split$map, 3),
|
|
133
|
+
cx = _current$split$map2[0],
|
|
134
|
+
cy = _current$split$map2[1],
|
|
135
|
+
cz = _current$split$map2[2];
|
|
136
|
+
var _neighbor$split$map = neighbor.split(',').map(Number),
|
|
137
|
+
_neighbor$split$map2 = _rollupPluginBabelHelpers.slicedToArray(_neighbor$split$map, 3),
|
|
138
|
+
nx = _neighbor$split$map2[0],
|
|
139
|
+
ny = _neighbor$split$map2[1],
|
|
140
|
+
nz = _neighbor$split$map2[2];
|
|
141
|
+
|
|
142
|
+
// Direction from parent to current
|
|
143
|
+
var prevDir = {
|
|
144
|
+
x: cx - px,
|
|
145
|
+
y: cy - py,
|
|
146
|
+
z: cz - pz
|
|
147
|
+
};
|
|
148
|
+
// Direction from current to neighbor
|
|
149
|
+
var nextDir = {
|
|
150
|
+
x: nx - cx,
|
|
151
|
+
y: ny - cy,
|
|
152
|
+
z: nz - cz
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// If directions are different, add bend penalty
|
|
156
|
+
if (prevDir.x !== nextDir.x || prevDir.y !== nextDir.y || prevDir.z !== nextDir.z) {
|
|
157
|
+
cost += 0.00001; // Bend penalty - adjust this value to control how much bends are avoided
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return cost;
|
|
161
|
+
}
|
|
162
|
+
|
|
106
163
|
/**
|
|
107
164
|
* Find a path respecting virtual segments
|
|
108
165
|
* @private
|