@2112-lab/central-plant 0.1.7 → 0.1.9
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.
|
@@ -601,12 +601,19 @@ class ConnectorManager {
|
|
|
601
601
|
* @returns {Array<Object>} Array of clusters
|
|
602
602
|
*/
|
|
603
603
|
clusterConnections(connections) {
|
|
604
|
+
// Filter out connections where either from or to UUID starts with "gateway" (case insensitive)
|
|
605
|
+
const filteredConnections = connections.filter(conn => {
|
|
606
|
+
const fromStartsWithGateway = conn.from.toLowerCase().startsWith('gateway');
|
|
607
|
+
const toStartsWithGateway = conn.to.toLowerCase().startsWith('gateway');
|
|
608
|
+
return !fromStartsWithGateway && !toStartsWithGateway;
|
|
609
|
+
});
|
|
610
|
+
|
|
604
611
|
const clusters = new Map(); // Map of object UUID to its cluster
|
|
605
612
|
const clusterMap = new Map(); // Map of cluster ID to set of object UUIDs
|
|
606
613
|
let nextClusterId = 0;
|
|
607
614
|
|
|
608
615
|
// First pass: create initial clusters for each object
|
|
609
|
-
|
|
616
|
+
filteredConnections.forEach(conn => {
|
|
610
617
|
const { from, to } = conn;
|
|
611
618
|
|
|
612
619
|
// If neither object is in a cluster, create new cluster
|
|
@@ -651,13 +658,8 @@ class ConnectorManager {
|
|
|
651
658
|
objects: Array.from(objects)
|
|
652
659
|
}));
|
|
653
660
|
|
|
654
|
-
// Filter out clusters containing objects with "GATEWAY" in their UUID
|
|
655
|
-
const filteredClusters = clustersArray.filter(cluster =>
|
|
656
|
-
!cluster.objects.some(uuid => uuid.includes('GATEWAY'))
|
|
657
|
-
);
|
|
658
|
-
|
|
659
661
|
// Enrich clusters with point and direction information
|
|
660
|
-
|
|
662
|
+
clustersArray.forEach(cluster => {
|
|
661
663
|
cluster.objectPoints = cluster.objects.map(uuid => {
|
|
662
664
|
const object = this.sceneManager.findObjectByUUID(uuid);
|
|
663
665
|
if (object && object.userData.worldBoundingBox) {
|
|
@@ -689,7 +691,7 @@ class ConnectorManager {
|
|
|
689
691
|
});
|
|
690
692
|
|
|
691
693
|
|
|
692
|
-
return
|
|
694
|
+
return clustersArray;
|
|
693
695
|
}
|
|
694
696
|
}
|
|
695
697
|
|
|
@@ -1090,11 +1092,14 @@ class PathManager {
|
|
|
1090
1092
|
}
|
|
1091
1093
|
|
|
1092
1094
|
/**
|
|
1093
|
-
* Manages
|
|
1094
|
-
* @class
|
|
1095
|
+
* Manages tree path calculations and Minimum Spanning Tree (MST) operations
|
|
1096
|
+
* @class TreePathManager
|
|
1095
1097
|
*/
|
|
1096
|
-
class
|
|
1097
|
-
constructor() {
|
|
1098
|
+
class TreePathManager {
|
|
1099
|
+
constructor(gridSystem = null, sceneManager = null) {
|
|
1100
|
+
this.gridSystem = gridSystem;
|
|
1101
|
+
this.sceneManager = sceneManager;
|
|
1102
|
+
}
|
|
1098
1103
|
|
|
1099
1104
|
/**
|
|
1100
1105
|
* Calculate distance between two points
|
|
@@ -1149,13 +1154,62 @@ class SteinerTreeManager {
|
|
|
1149
1154
|
|
|
1150
1155
|
return mst;
|
|
1151
1156
|
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Find the nearest free voxel to a given position
|
|
1160
|
+
* @param {Vector3} position - Position to find free voxel near
|
|
1161
|
+
* @param {number} maxSearchRadius - Maximum search radius in voxel units
|
|
1162
|
+
* @returns {Vector3|null} Nearest free position or null if none found
|
|
1163
|
+
*/
|
|
1164
|
+
findNearestFreeVoxel(position, maxSearchRadius = 5) {
|
|
1165
|
+
if (!this.gridSystem || !this.sceneManager) {
|
|
1166
|
+
return position; // Return original position if systems not available
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
const originalVoxelKey = this.gridSystem.voxelKey(position);
|
|
1170
|
+
|
|
1171
|
+
// Check if original position is free
|
|
1172
|
+
if (!this.sceneManager.isVoxelOccupiedByMesh(originalVoxelKey, this.gridSystem.gridSize)) {
|
|
1173
|
+
return position;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// Search in expanding rings around the position
|
|
1177
|
+
for (let radius = 1; radius <= maxSearchRadius; radius++) {
|
|
1178
|
+
const [x, y, z] = originalVoxelKey.split(',').map(Number);
|
|
1179
|
+
|
|
1180
|
+
// Generate all voxels at this radius
|
|
1181
|
+
const candidates = [];
|
|
1182
|
+
|
|
1183
|
+
// Generate all combinations of offsets at this radius
|
|
1184
|
+
for (let dx = -radius; dx <= radius; dx++) {
|
|
1185
|
+
for (let dy = -radius; dy <= radius; dy++) {
|
|
1186
|
+
for (let dz = -radius; dz <= radius; dz++) {
|
|
1187
|
+
// Only consider voxels exactly at this radius
|
|
1188
|
+
if (Math.abs(dx) + Math.abs(dy) + Math.abs(dz) === radius) {
|
|
1189
|
+
candidates.push([x + dx, y + dy, z + dz]);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// Check each candidate
|
|
1196
|
+
for (const [cx, cy, cz] of candidates) {
|
|
1197
|
+
const candidateKey = `${cx},${cy},${cz}`;
|
|
1198
|
+
if (!this.sceneManager.isVoxelOccupiedByMesh(candidateKey, this.gridSystem.gridSize)) {
|
|
1199
|
+
return this.gridSystem.voxelToVec3(candidateKey);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
return null;
|
|
1205
|
+
}
|
|
1152
1206
|
|
|
1153
1207
|
/**
|
|
1154
|
-
* Find
|
|
1208
|
+
* Find joint point
|
|
1155
1209
|
* @param {Array<Vector3>} points - Array of points to connect
|
|
1156
|
-
* @returns {Vector3|null}
|
|
1210
|
+
* @returns {Vector3|null} Joint point or null if not possible
|
|
1157
1211
|
*/
|
|
1158
|
-
|
|
1212
|
+
findJointPoint(points) {
|
|
1159
1213
|
if (points.length <= 2) {
|
|
1160
1214
|
return null;
|
|
1161
1215
|
}
|
|
@@ -1167,36 +1221,61 @@ class SteinerTreeManager {
|
|
|
1167
1221
|
return null;
|
|
1168
1222
|
}
|
|
1169
1223
|
|
|
1170
|
-
// Find the
|
|
1171
|
-
let
|
|
1172
|
-
let
|
|
1224
|
+
// Find the best edge in MST
|
|
1225
|
+
let bestEdge = null;
|
|
1226
|
+
let maxScore = -1;
|
|
1173
1227
|
|
|
1174
|
-
mst.forEach(([i, j]) => {
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1228
|
+
mst.forEach(([i, j], edgeIndex) => {
|
|
1229
|
+
const pointA = points[i];
|
|
1230
|
+
const pointB = points[j];
|
|
1231
|
+
|
|
1232
|
+
// Calculate edge components
|
|
1233
|
+
const dx = Math.abs(pointB.x - pointA.x);
|
|
1234
|
+
const dy = Math.abs(pointB.y - pointA.y);
|
|
1235
|
+
const dz = Math.abs(pointB.z - pointA.z);
|
|
1236
|
+
|
|
1237
|
+
// Calculate total length
|
|
1238
|
+
const totalLength = dx + dy + dz;
|
|
1239
|
+
|
|
1240
|
+
if (totalLength > 0) {
|
|
1241
|
+
// Calculate score
|
|
1242
|
+
// Higher score = more orthogonal (closer to being axis-aligned) relative to the total length of the edge
|
|
1243
|
+
const maxComponent = Math.max(dx, dy, dz);
|
|
1244
|
+
const score = (maxComponent / totalLength) / totalLength;
|
|
1245
|
+
|
|
1246
|
+
// Check if this edge has a better orthogonality score
|
|
1247
|
+
if (score > maxScore) {
|
|
1248
|
+
maxScore = score;
|
|
1249
|
+
bestEdge = [pointA, pointB];
|
|
1250
|
+
}
|
|
1179
1251
|
}
|
|
1180
1252
|
});
|
|
1181
1253
|
|
|
1182
|
-
if (!
|
|
1254
|
+
if (!bestEdge) {
|
|
1183
1255
|
return null;
|
|
1184
1256
|
}
|
|
1185
1257
|
|
|
1186
|
-
// Place
|
|
1187
|
-
const
|
|
1188
|
-
(
|
|
1189
|
-
(
|
|
1190
|
-
(
|
|
1258
|
+
// Place joint point at the midpoint of the most orthogonal edge
|
|
1259
|
+
const jointPoint = new Vector3(
|
|
1260
|
+
(bestEdge[0].x + bestEdge[1].x) * 0.5,
|
|
1261
|
+
(bestEdge[0].y + bestEdge[1].y) * 0.5,
|
|
1262
|
+
(bestEdge[0].z + bestEdge[1].z) * 0.5
|
|
1191
1263
|
);
|
|
1192
1264
|
|
|
1193
1265
|
// Snap to 0.5 grid
|
|
1194
1266
|
const snapToGrid = (value) => Math.round(value * 2) / 2;
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1267
|
+
jointPoint.x = snapToGrid(jointPoint.x);
|
|
1268
|
+
jointPoint.y = snapToGrid(jointPoint.y);
|
|
1269
|
+
jointPoint.z = snapToGrid(jointPoint.z);
|
|
1198
1270
|
|
|
1199
|
-
|
|
1271
|
+
// Check if the joint point is in an occupied voxel and move it if necessary
|
|
1272
|
+
const freeJointPoint = this.findNearestFreeVoxel(jointPoint);
|
|
1273
|
+
|
|
1274
|
+
if (freeJointPoint) {
|
|
1275
|
+
return freeJointPoint;
|
|
1276
|
+
} else {
|
|
1277
|
+
return jointPoint; // Return original if no free position found
|
|
1278
|
+
}
|
|
1200
1279
|
}
|
|
1201
1280
|
}
|
|
1202
1281
|
|
|
@@ -1243,8 +1322,8 @@ class Pathfinder {
|
|
|
1243
1322
|
this.ASTAR_TIMEOUT
|
|
1244
1323
|
);
|
|
1245
1324
|
|
|
1246
|
-
// Initialize
|
|
1247
|
-
this.
|
|
1325
|
+
// Initialize tree path manager
|
|
1326
|
+
this.treePathManager = new TreePathManager(this.gridSystem, null);
|
|
1248
1327
|
}
|
|
1249
1328
|
|
|
1250
1329
|
/**
|
|
@@ -1279,6 +1358,13 @@ class Pathfinder {
|
|
|
1279
1358
|
* @property {string} gateways[].clusterId - ID of the cluster this gateway belongs to
|
|
1280
1359
|
* @property {number} gateways[].id - Unique identifier for the gateway
|
|
1281
1360
|
* @property {Vector3} gateways[].position - Position of the gateway in 3D space
|
|
1361
|
+
* @property {Object} gateways[].connections - Connection mapping information
|
|
1362
|
+
* @property {Array<Object>} gateways[].connections.removed - Array of original connections that were removed
|
|
1363
|
+
* @property {string} gateways[].connections.removed[].from - Source object UUID
|
|
1364
|
+
* @property {string} gateways[].connections.removed[].to - Target object UUID
|
|
1365
|
+
* @property {Array<Object>} gateways[].connections.added - Array of new connections that were added
|
|
1366
|
+
* @property {string} gateways[].connections.added[].from - Source object UUID
|
|
1367
|
+
* @property {string} gateways[].connections.added[].to - Target object UUID
|
|
1282
1368
|
*/
|
|
1283
1369
|
findPaths(scene, connections) {
|
|
1284
1370
|
// Create scene manager with the provided scene
|
|
@@ -1287,6 +1373,7 @@ class Pathfinder {
|
|
|
1287
1373
|
// Update scene manager references
|
|
1288
1374
|
this.connectorManager.sceneManager = sceneManager;
|
|
1289
1375
|
this.pathManager.sceneManager = sceneManager;
|
|
1376
|
+
this.treePathManager.sceneManager = sceneManager;
|
|
1290
1377
|
|
|
1291
1378
|
// Cluster the connections
|
|
1292
1379
|
const clusters = this.connectorManager.clusterConnections(connections);
|
|
@@ -1294,41 +1381,41 @@ class Pathfinder {
|
|
|
1294
1381
|
// Filter clusters to only include those with more than 2 objects
|
|
1295
1382
|
const filteredClusters = clusters.filter(cluster => cluster.objects.length > 2);
|
|
1296
1383
|
|
|
1297
|
-
// Calculate
|
|
1384
|
+
// Calculate joint points for each cluster
|
|
1298
1385
|
filteredClusters.forEach((cluster, index) => {
|
|
1299
1386
|
const points = cluster.displacedPoints.map(p => p.displacedPoint);
|
|
1300
|
-
cluster.
|
|
1301
|
-
cluster.steinerPoint = this.steinerTreeManager.findSteinerPoint(points);
|
|
1387
|
+
cluster.jointPoint = this.treePathManager.findJointPoint(points);
|
|
1302
1388
|
});
|
|
1303
1389
|
|
|
1304
|
-
let gatewayCounter = 1;
|
|
1305
1390
|
const gatewayMap = new Map();
|
|
1306
1391
|
|
|
1307
1392
|
filteredClusters.forEach(cluster => {
|
|
1308
|
-
if (cluster.
|
|
1309
|
-
|
|
1393
|
+
if (cluster.jointPoint) {
|
|
1394
|
+
// Generate a shorter unique ID (8 characters)
|
|
1395
|
+
const uuid = crypto.randomUUID().replace(/-/g, '').substring(0, 8);
|
|
1396
|
+
const gatewayId = `Gateway-${uuid}`;
|
|
1310
1397
|
gatewayMap.set(cluster.clusterId, gatewayId);
|
|
1311
1398
|
}
|
|
1312
1399
|
});
|
|
1313
1400
|
|
|
1314
1401
|
// Create virtual gateway objects in the scene
|
|
1315
1402
|
filteredClusters.forEach(cluster => {
|
|
1316
|
-
if (cluster.
|
|
1403
|
+
if (cluster.jointPoint) {
|
|
1317
1404
|
const gatewayId = gatewayMap.get(cluster.clusterId);
|
|
1318
1405
|
const gatewayObject = {
|
|
1319
|
-
uuid:
|
|
1406
|
+
uuid: gatewayId,
|
|
1320
1407
|
type: 'Mesh',
|
|
1321
1408
|
userData: {
|
|
1322
1409
|
worldBoundingBox: {
|
|
1323
1410
|
min: [
|
|
1324
|
-
cluster.
|
|
1325
|
-
cluster.
|
|
1326
|
-
cluster.
|
|
1411
|
+
cluster.jointPoint.x - 0.25,
|
|
1412
|
+
cluster.jointPoint.y - 0.25,
|
|
1413
|
+
cluster.jointPoint.z - 0.25
|
|
1327
1414
|
],
|
|
1328
1415
|
max: [
|
|
1329
|
-
cluster.
|
|
1330
|
-
cluster.
|
|
1331
|
-
cluster.
|
|
1416
|
+
cluster.jointPoint.x + 0.25,
|
|
1417
|
+
cluster.jointPoint.y + 0.25,
|
|
1418
|
+
cluster.jointPoint.z + 0.25
|
|
1332
1419
|
]
|
|
1333
1420
|
}
|
|
1334
1421
|
}
|
|
@@ -1340,6 +1427,7 @@ class Pathfinder {
|
|
|
1340
1427
|
// Rewire connections through gateways
|
|
1341
1428
|
const rewiredConnections = [];
|
|
1342
1429
|
const connectionSet = new Set(); // Track unique connections
|
|
1430
|
+
const gatewayConnectionMappings = new Map(); // Track which original connections are replaced by which gateway connections
|
|
1343
1431
|
|
|
1344
1432
|
// Find direct connections (not part of clusters with >2 objects)
|
|
1345
1433
|
const directConnections = connections.filter(conn => {
|
|
@@ -1367,44 +1455,63 @@ class Pathfinder {
|
|
|
1367
1455
|
)?.clusterId;
|
|
1368
1456
|
|
|
1369
1457
|
if (fromCluster !== undefined && toCluster !== undefined) {
|
|
1370
|
-
const fromGateway =
|
|
1371
|
-
const toGateway =
|
|
1372
|
-
|
|
1373
|
-
|
|
1458
|
+
const fromGateway = gatewayMap.get(fromCluster);
|
|
1459
|
+
const toGateway = gatewayMap.get(toCluster);
|
|
1460
|
+
if (fromGateway !== undefined && toGateway !== undefined) {
|
|
1461
|
+
const fromGatewayId = fromGateway;
|
|
1462
|
+
const toGatewayId = toGateway;
|
|
1463
|
+
|
|
1464
|
+
// Track the original connection that will be replaced
|
|
1465
|
+
const originalConnection = { from: conn.from, to: conn.to };
|
|
1466
|
+
const addedConnections = [];
|
|
1467
|
+
|
|
1374
1468
|
// If both objects are in the same cluster, connect through their gateway
|
|
1375
1469
|
if (fromCluster === toCluster) {
|
|
1376
|
-
const conn1 = { from: conn.from, to:
|
|
1377
|
-
const conn2 = { from:
|
|
1470
|
+
const conn1 = { from: conn.from, to: fromGatewayId };
|
|
1471
|
+
const conn2 = { from: fromGatewayId, to: conn.to };
|
|
1378
1472
|
|
|
1379
1473
|
// Only add if not already present
|
|
1380
1474
|
if (!connectionSet.has(JSON.stringify(conn1))) {
|
|
1381
1475
|
gatewayConnections.push(conn1);
|
|
1382
1476
|
connectionSet.add(JSON.stringify(conn1));
|
|
1477
|
+
addedConnections.push(conn1);
|
|
1383
1478
|
}
|
|
1384
1479
|
if (!connectionSet.has(JSON.stringify(conn2))) {
|
|
1385
1480
|
gatewayConnections.push(conn2);
|
|
1386
1481
|
connectionSet.add(JSON.stringify(conn2));
|
|
1482
|
+
addedConnections.push(conn2);
|
|
1387
1483
|
}
|
|
1388
1484
|
} else {
|
|
1389
1485
|
// If objects are in different clusters, connect through both gateways
|
|
1390
|
-
const conn1 = { from: conn.from, to:
|
|
1391
|
-
const conn2 = { from:
|
|
1392
|
-
const conn3 = { from:
|
|
1486
|
+
const conn1 = { from: conn.from, to: fromGatewayId };
|
|
1487
|
+
const conn2 = { from: fromGatewayId, to: toGatewayId };
|
|
1488
|
+
const conn3 = { from: toGatewayId, to: conn.to };
|
|
1393
1489
|
|
|
1394
1490
|
// Only add if not already present
|
|
1395
1491
|
if (!connectionSet.has(JSON.stringify(conn1))) {
|
|
1396
1492
|
gatewayConnections.push(conn1);
|
|
1397
1493
|
connectionSet.add(JSON.stringify(conn1));
|
|
1494
|
+
addedConnections.push(conn1);
|
|
1398
1495
|
}
|
|
1399
1496
|
if (!connectionSet.has(JSON.stringify(conn2))) {
|
|
1400
1497
|
gatewayConnections.push(conn2);
|
|
1401
1498
|
connectionSet.add(JSON.stringify(conn2));
|
|
1499
|
+
addedConnections.push(conn2);
|
|
1402
1500
|
}
|
|
1403
1501
|
if (!connectionSet.has(JSON.stringify(conn3))) {
|
|
1404
1502
|
gatewayConnections.push(conn3);
|
|
1405
1503
|
connectionSet.add(JSON.stringify(conn3));
|
|
1504
|
+
addedConnections.push(conn3);
|
|
1406
1505
|
}
|
|
1407
1506
|
}
|
|
1507
|
+
|
|
1508
|
+
// Store the mapping for this connection
|
|
1509
|
+
if (addedConnections.length > 0) {
|
|
1510
|
+
gatewayConnectionMappings.set(JSON.stringify(originalConnection), {
|
|
1511
|
+
removed: [originalConnection],
|
|
1512
|
+
added: addedConnections
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1408
1515
|
}
|
|
1409
1516
|
}
|
|
1410
1517
|
});
|
|
@@ -1418,8 +1525,8 @@ class Pathfinder {
|
|
|
1418
1525
|
|
|
1419
1526
|
if (!objA1 || !objA2 || !objB1 || !objB2) return 0;
|
|
1420
1527
|
|
|
1421
|
-
const distA = this.
|
|
1422
|
-
const distB = this.
|
|
1528
|
+
const distA = this.treePathManager.distance(sceneManager.getWorldPosition(objA1), sceneManager.getWorldPosition(objA2));
|
|
1529
|
+
const distB = this.treePathManager.distance(sceneManager.getWorldPosition(objB1), sceneManager.getWorldPosition(objB2));
|
|
1423
1530
|
|
|
1424
1531
|
return distA - distB;
|
|
1425
1532
|
});
|
|
@@ -1429,13 +1536,69 @@ class Pathfinder {
|
|
|
1429
1536
|
|
|
1430
1537
|
const paths = this.pathManager.findPaths(rewiredConnections || []);
|
|
1431
1538
|
|
|
1539
|
+
// Aggregate connection mappings by gateway
|
|
1540
|
+
const gatewayConnectionsMap = new Map();
|
|
1541
|
+
|
|
1542
|
+
// Initialize connection mappings for each gateway
|
|
1543
|
+
Array.from(gatewayMap.entries()).forEach(([clusterId, gatewayId]) => {
|
|
1544
|
+
gatewayConnectionsMap.set(gatewayId, {
|
|
1545
|
+
removed: [],
|
|
1546
|
+
added: []
|
|
1547
|
+
});
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1550
|
+
// Populate connection mappings
|
|
1551
|
+
gatewayConnectionMappings.forEach((mapping, connectionKey) => {
|
|
1552
|
+
const originalConnection = JSON.parse(connectionKey);
|
|
1553
|
+
const fromCluster = clusters.find(cluster =>
|
|
1554
|
+
cluster.objects.includes(originalConnection.from)
|
|
1555
|
+
)?.clusterId;
|
|
1556
|
+
const toCluster = clusters.find(cluster =>
|
|
1557
|
+
cluster.objects.includes(originalConnection.to)
|
|
1558
|
+
)?.clusterId;
|
|
1559
|
+
|
|
1560
|
+
if (fromCluster !== undefined && toCluster !== undefined) {
|
|
1561
|
+
const fromGateway = gatewayMap.get(fromCluster);
|
|
1562
|
+
const toGateway = gatewayMap.get(toCluster);
|
|
1563
|
+
|
|
1564
|
+
if (fromGateway !== undefined && toGateway !== undefined) {
|
|
1565
|
+
// Add to both gateways if they're different
|
|
1566
|
+
if (fromGateway === toGateway) {
|
|
1567
|
+
// Same gateway
|
|
1568
|
+
const gatewayConnections = gatewayConnectionsMap.get(fromGateway);
|
|
1569
|
+
gatewayConnections.removed.push(originalConnection);
|
|
1570
|
+
gatewayConnections.added.push(...mapping.added);
|
|
1571
|
+
} else {
|
|
1572
|
+
// Different gateways - split the connections
|
|
1573
|
+
const fromGatewayConnections = gatewayConnectionsMap.get(fromGateway);
|
|
1574
|
+
const toGatewayConnections = gatewayConnectionsMap.get(toGateway);
|
|
1575
|
+
|
|
1576
|
+
// Add the original connection to both gateways' removed list
|
|
1577
|
+
fromGatewayConnections.removed.push(originalConnection);
|
|
1578
|
+
toGatewayConnections.removed.push(originalConnection);
|
|
1579
|
+
|
|
1580
|
+
// Split added connections by gateway
|
|
1581
|
+
mapping.added.forEach(conn => {
|
|
1582
|
+
if (conn.from === originalConnection.from || conn.to === fromGateway) {
|
|
1583
|
+
fromGatewayConnections.added.push(conn);
|
|
1584
|
+
}
|
|
1585
|
+
if (conn.from === toGateway || conn.to === originalConnection.to) {
|
|
1586
|
+
toGatewayConnections.added.push(conn);
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
});
|
|
1593
|
+
|
|
1432
1594
|
return {
|
|
1433
1595
|
paths,
|
|
1434
1596
|
rewiredConnections,
|
|
1435
1597
|
gateways: Array.from(gatewayMap.entries()).map(([clusterId, gatewayId]) => ({
|
|
1436
1598
|
clusterId,
|
|
1437
1599
|
id: gatewayId,
|
|
1438
|
-
position: clusters.find(c => c.clusterId === clusterId)?.
|
|
1600
|
+
position: clusters.find(c => c.clusterId === clusterId)?.jointPoint,
|
|
1601
|
+
connections: gatewayConnectionsMap.get(gatewayId) || { removed: [], added: [] }
|
|
1439
1602
|
}))
|
|
1440
1603
|
};
|
|
1441
1604
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2112-lab/central-plant",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Utility modules for the Central Plant Application",
|
|
5
5
|
"main": "dist/bundle/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"author": "CentralPlant Team",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@2112-lab/pathfinder": "^1.0.
|
|
32
|
+
"@2112-lab/pathfinder": "^1.0.27",
|
|
33
33
|
"three": "^0.177.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|