@2112-lab/central-plant 0.1.4 → 0.1.6

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.
Files changed (88) hide show
  1. package/dist/bundle/index.js +33146 -1
  2. package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +432 -1
  3. package/dist/cjs/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1448 -1
  4. package/dist/cjs/node_modules/three/examples/jsm/controls/OrbitControls.js +1853 -1
  5. package/dist/cjs/node_modules/three/examples/jsm/exporters/GLTFExporter.js +3537 -1
  6. package/dist/cjs/node_modules/three/examples/jsm/exporters/OBJExporter.js +305 -1
  7. package/dist/cjs/node_modules/three/examples/jsm/exporters/PLYExporter.js +542 -1
  8. package/dist/cjs/node_modules/three/examples/jsm/exporters/STLExporter.js +218 -1
  9. package/dist/cjs/node_modules/three/examples/jsm/loaders/DRACOLoader.js +683 -1
  10. package/dist/cjs/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4811 -1
  11. package/dist/cjs/node_modules/three/examples/jsm/loaders/RGBELoader.js +480 -1
  12. package/dist/cjs/node_modules/three/examples/jsm/renderers/CSS2DRenderer.js +309 -1
  13. package/dist/cjs/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +120 -1
  14. package/dist/cjs/src/analysis/analysis.js +560 -1
  15. package/dist/cjs/src/analysis/testing.js +958 -1
  16. package/dist/cjs/src/core/centralPlant.js +1149 -1
  17. package/dist/cjs/src/core/debugLogger.js +175 -1
  18. package/dist/cjs/src/core/mathUtils.js +574 -1
  19. package/dist/cjs/src/core/nameUtils.js +93 -1
  20. package/dist/cjs/src/data/export.js +716 -1
  21. package/dist/cjs/src/data/import.js +380 -1
  22. package/dist/cjs/src/data/numerics.js +522 -1
  23. package/dist/cjs/src/helpers/sceneHelper.js +572 -1
  24. package/dist/cjs/src/index.js +69 -1
  25. package/dist/cjs/src/managers/components/animationManager.js +123 -1
  26. package/dist/cjs/src/managers/components/componentManager.js +332 -1
  27. package/dist/cjs/src/managers/components/pathfindingManager.js +1441 -1
  28. package/dist/cjs/src/managers/controls/TransformControls.js +1063 -1
  29. package/dist/cjs/src/managers/controls/cameraControlsManager.js +79 -1
  30. package/dist/cjs/src/managers/controls/dragDropManager.js +1026 -1
  31. package/dist/cjs/src/managers/controls/keyboardControlsManager.js +395 -1
  32. package/dist/cjs/src/managers/controls/transformControlsManager.js +1807 -1
  33. package/dist/cjs/src/managers/environment/environmentManager.js +714 -1
  34. package/dist/cjs/src/managers/environment/textureConfig.js +229 -1
  35. package/dist/cjs/src/managers/scene/sceneExportManager.js +264 -1
  36. package/dist/cjs/src/managers/scene/sceneInitializationManager.js +346 -1
  37. package/dist/cjs/src/managers/scene/sceneOperationsManager.js +1509 -1
  38. package/dist/cjs/src/managers/scene/sceneTooltipsManager.js +661 -1
  39. package/dist/cjs/src/managers/system/disposalManager.js +444 -1
  40. package/dist/cjs/src/managers/system/hotReloadManager.js +291 -1
  41. package/dist/cjs/src/managers/system/performanceMonitor.js +863 -1
  42. package/dist/cjs/src/rendering/modelPreloader.js +369 -1
  43. package/dist/cjs/src/rendering/rendering2D.js +631 -1
  44. package/dist/cjs/src/rendering/rendering3D.js +685 -1
  45. package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +396 -1
  46. package/dist/esm/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1444 -1
  47. package/dist/esm/node_modules/three/examples/jsm/controls/OrbitControls.js +1849 -1
  48. package/dist/esm/node_modules/three/examples/jsm/exporters/GLTFExporter.js +3533 -1
  49. package/dist/esm/node_modules/three/examples/jsm/exporters/OBJExporter.js +301 -1
  50. package/dist/esm/node_modules/three/examples/jsm/exporters/PLYExporter.js +538 -1
  51. package/dist/esm/node_modules/three/examples/jsm/exporters/STLExporter.js +214 -1
  52. package/dist/esm/node_modules/three/examples/jsm/loaders/DRACOLoader.js +679 -1
  53. package/dist/esm/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4807 -1
  54. package/dist/esm/node_modules/three/examples/jsm/loaders/RGBELoader.js +476 -1
  55. package/dist/esm/node_modules/three/examples/jsm/renderers/CSS2DRenderer.js +304 -1
  56. package/dist/esm/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +116 -1
  57. package/dist/esm/src/analysis/analysis.js +536 -1
  58. package/dist/esm/src/analysis/testing.js +954 -1
  59. package/dist/esm/src/core/centralPlant.js +1144 -1
  60. package/dist/esm/src/core/debugLogger.js +167 -1
  61. package/dist/esm/src/core/mathUtils.js +570 -1
  62. package/dist/esm/src/core/nameUtils.js +87 -1
  63. package/dist/esm/src/data/export.js +712 -1
  64. package/dist/esm/src/data/import.js +356 -1
  65. package/dist/esm/src/data/numerics.js +518 -1
  66. package/dist/esm/src/helpers/sceneHelper.js +547 -1
  67. package/dist/esm/src/index.js +35 -1
  68. package/dist/esm/src/managers/components/animationManager.js +119 -1
  69. package/dist/esm/src/managers/components/componentManager.js +328 -1
  70. package/dist/esm/src/managers/components/pathfindingManager.js +1417 -1
  71. package/dist/esm/src/managers/controls/TransformControls.js +1057 -1
  72. package/dist/esm/src/managers/controls/cameraControlsManager.js +75 -1
  73. package/dist/esm/src/managers/controls/dragDropManager.js +1002 -1
  74. package/dist/esm/src/managers/controls/keyboardControlsManager.js +371 -1
  75. package/dist/esm/src/managers/controls/transformControlsManager.js +1782 -1
  76. package/dist/esm/src/managers/environment/environmentManager.js +690 -1
  77. package/dist/esm/src/managers/environment/textureConfig.js +202 -1
  78. package/dist/esm/src/managers/scene/sceneExportManager.js +260 -1
  79. package/dist/esm/src/managers/scene/sceneInitializationManager.js +322 -1
  80. package/dist/esm/src/managers/scene/sceneOperationsManager.js +1485 -1
  81. package/dist/esm/src/managers/scene/sceneTooltipsManager.js +637 -1
  82. package/dist/esm/src/managers/system/disposalManager.js +440 -1
  83. package/dist/esm/src/managers/system/hotReloadManager.js +287 -1
  84. package/dist/esm/src/managers/system/performanceMonitor.js +858 -1
  85. package/dist/esm/src/rendering/modelPreloader.js +364 -1
  86. package/dist/esm/src/rendering/rendering2D.js +627 -1
  87. package/dist/esm/src/rendering/rendering3D.js +661 -1
  88. package/package.json +1 -1
@@ -1 +1,1417 @@
1
- import{createClass as n,objectSpread2 as e,construct as t,toConsumableArray as r,slicedToArray as i,classCallCheck as o,createForOfIteratorHelper as a,asyncToGenerator as u,regenerator as s}from"../../../_virtual/_rollupPluginBabelHelpers.js";import*as c from"three";import{Pathfinder as l}from"../../../node_modules/@2112-lab/pathfinder/dist/index.esm.js";import{logger as f,pathfinderLogger as v}from"../../core/debugLogger.js";import{generateUuidFromName as d}from"../../core/nameUtils.js";var h=function(){return n(function n(e){o(this,n),this.sceneViewer=e,this.pathfinder=null,this.crosscubeTextureSet=null,this.pathfinderVersionInfo=null,this.pathfinderConfig={grid:{size:.5,safetyMargin:0,minSegmentLength:.5,timeout:1e3}}},[{key:"getPathfinderVersionInfo",value:(w=u(s().m(function n(){var e;return s().w(function(n){for(;;)switch(n.n){case 0:if(!this.pathfinderVersionInfo){n.n=1;break}return n.a(2,this.pathfinderVersionInfo);case 1:return e={version:"1.0.17",detectionMethod:"hardcoded-fallback",timestamp:(new Date).toISOString()},this.pathfinderVersionInfo=e,n.a(2,e)}},n,this)})),function(){return w.apply(this,arguments)})},{key:"logPathfinderVersion",value:(g=u(s().m(function n(){var e,t,r,i=arguments;return s().w(function(n){for(;;)switch(n.n){case 0:return e=i.length>0&&void 0!==i[0]?i[0]:"Unknown Context",n.p=1,n.n=2,this.getPathfinderVersionInfo();case 2:t=n.v,v.info("[".concat(e,"] Pathfinder Module Information:"),{version:t.version,detectionMethod:t.detectionMethod,context:e,timestamp:t.timestamp,pathfinderInstance:!!this.pathfinder}),n.n=4;break;case 3:n.p=3,r=n.v,v.error("[".concat(e,"] Failed to get pathfinder version:"),r);case 4:return n.a(2)}},n,this,[[1,3]])})),function(){return g.apply(this,arguments)})},{key:"getPathColor",value:function(n){var e=["#468e49","#245e29","#2e80d2","#1d51a1"];return e[n%e.length]}},{key:"_executePathfinding",value:(p=u(s().m(function n(e,t){var r,i,o,a,u,f,v,d=this,h=arguments;return s().w(function(n){for(;;)switch(n.n){case 0:return i=(r=h.length>2&&void 0!==h[2]?h[2]:{}).createGateways,o=void 0!==i&&i,a=r.context,u=void 0===a?"Pathfinding":a,n.n=1,this.logPathfinderVersion(u);case 1:return this.pathfinder=new l(this.pathfinderConfig),this.sceneViewer.pathfinder=this.pathfinder,e.object.children=e.object.children.filter(function(n){return"computed"!==n.userData.origin}),f=this.pathfinder.findPaths(e,t),o&&f.gateways&&f.gateways.forEach(function(n){if(n.position){var e=new c.Mesh(new c.SphereGeometry(.15,16,16),new c.MeshStandardMaterial({color:16777215,roughness:.7,metalness:.3,emissive:0}));e.position.copy(n.position),e.name=n.id,e.uuid=n.id,e.userData={componentType:"gateway",forExport:!0,gatewayId:n.id,originalUuid:n.id,origin:"computed",connections:n.connections},d.sceneViewer.scene.add(e)}}),v=this.mergeColinearPaths(f.paths),this.createPipePaths(v,this.crosscubeTextureSet),n.a(2,f)}},n,this)})),function(n,e){return p.apply(this,arguments)})},{key:"initializePathfinder",value:(y=u(s().m(function n(e,t){var r;return s().w(function(n){for(;;)switch(n.n){case 0:return this.crosscubeTextureSet=t,n.n=1,this.t(e.scene,e.connections,{createGateways:!0,context:"Scene Loading"});case 1:return(r=n.v).rewiredConnections,n.a(2,r)}},n,this)})),function(n,e){return y.apply(this,arguments)})},{key:"removeComputedObjects",value:function(){var n=this.sceneViewer,e=[];n.scene.traverse(function(n){if(n.name&&n.name.includes("Polyline")){var t=!1,r=[];if(n.traverse(function(n){n.userData&&n.userData.isPipeSegment&&n.userData.isManuallyPositioned&&(t=!0,r.push(n))}),t){var i=[];n.traverse(function(n){(n.userData&&n.userData.isPipeSegment&&!n.userData.isManuallyPositioned||n.userData&&n.userData.isPipeElbow)&&i.push(n)}),i.forEach(function(e){n.remove(e),e.geometry&&e.geometry.dispose(),e.material&&(Array.isArray(e.material)?e.material.forEach(function(n){return n.dispose()}):e.material.dispose())}),0===n.children.length&&e.push(n)}else e.push(n)}n.userData&&"computed"===n.userData.origin&&e.push(n)});for(var t=0,r=e;t<r.length;t++){var i=r[t];n.scene.remove(i),i.geometry&&i.geometry.dispose(),i.material&&(Array.isArray(i.material)?i.material.forEach(function(n){return n.dispose()}):i.material.dispose())}}},{key:"createPipeMaterial",value:function(n,i){if(n){var o=e(e({},n.config.materialProps),{},{color:this.getPathColor(i),map:n.textures.diffuse,normalMap:n.textures.normal,roughnessMap:n.textures.roughness,metalness:.2,roughness:.9,clearcoat:.2,clearcoatRoughness:.2,envMapIntensity:.6,reflectivity:.4});o.normalScale&&Array.isArray(o.normalScale)&&(o.normalScale=t(c.Vector2,r(o.normalScale)));var a=new c.MeshPhysicalMaterial(o);return[a.map,a.normalMap,a.roughnessMap].filter(Boolean).forEach(function(e){e.wrapS=e.wrapT=c.RepeatWrapping,e.repeat.set(2*n.config.repeat.x,2*n.config.repeat.y)}),a}return new c.MeshPhysicalMaterial({color:this.getPathColor(i),metalness:.9,roughness:.7,clearcoat:.1,clearcoatRoughness:.3,envMapIntensity:1.5,reflectivity:.3})}},{key:"createPipePaths",value:function(n,e){var t=this,r=this.sceneViewer;n.forEach(function(n,i){if(n.path&&n.path.length>=2){var o=new c.Object3D;o.name="Polyline ".concat(n.from,"-").concat(n.to);for(var a=t.createPipeMaterial(e,i),u=n.path.map(function(n){return n instanceof c.Vector3?n.clone():Array.isArray(n)?(new c.Vector3).fromArray(n):void 0!==n.x&&void 0!==n.y&&void 0!==n.z?new c.Vector3(n.x,n.y,n.z):new c.Vector3(0,0,0)}),s=function(e){var s=u[e],l=u[e+1],f=(new c.Vector3).subVectors(l,s),v=f.length();if(v<1e-6)return 0;var d=!1;if(r.scene.traverse(function(t){t.userData&&t.userData.isPipeSegment&&t.userData.isManuallyPositioned&&t.userData.segmentId==="pipe-segment-".concat(n.from,"-").concat(n.to,"-").concat(e)&&(d=!0)}),d)return 0;var h=new c.CylinderGeometry(.1,.1,v,8,1,!1),m=new c.Mesh(h,a);m.position.copy(s).add(l).multiplyScalar(.5);var y=new c.Quaternion,p=new c.Vector3(0,1,0);y.setFromUnitVectors(p,f.clone().normalize()),m.quaternion.copy(y),m.castShadow=!0,m.receiveShadow=!0;var g="pipe-segment-".concat(n.from,"-").concat(n.to,"-").concat(e);if(m.name="Pipe Segment ".concat(e+1,": ").concat(n.from,"-").concat(n.to),m.userData={isPipeSegment:!0,segmentId:g,segmentIndex:e,pathFrom:n.from,pathTo:n.to,pathIndex:i,length:v.toFixed(2),component:{type:"PipeSegment",attributes:{length:{key:"Length",value:v.toFixed(2),unit:"m"}}}},o.add(m),e<u.length-2){var w=u[e+1].clone().sub(u[e]).normalize(),k=u[e+2].clone().sub(u[e+1]).normalize(),x=w.angleTo(k);if(x>Math.PI/36){var P=t.createElbowGeometry(u[e],u[e+1],u[e+2],.1);if(P){var S=new c.Mesh(P,a);S.castShadow=!0,S.receiveShadow=!0;var b="pipe-elbow-".concat(n.from,"-").concat(n.to,"-").concat(e);S.name="Pipe Elbow ".concat(e+1,": ").concat(n.from,"-").concat(n.to),S.userData={isPipeElbow:!0,elbowId:b,elbowIndex:e,pathFrom:n.from,pathTo:n.to,pathIndex:i,angle:(180*x/Math.PI).toFixed(1),component:{type:"PipeElbow",attributes:{angle:{key:"Bend Angle",value:(180*x/Math.PI).toFixed(1),unit:"°"}}}},o.add(S)}}}},l=0;l<u.length-1;l++)s(l);o.name="Polyline",r.scene.add(o)}})}},{key:"handleManualSegmentTransformation",value:function(n,e){if(n&&n.userData&&n.userData.isPipeSegment){var t=this.calculateSegmentEndpoints(n),r=this.createSegmentConnectors(n,t);this.addConnectorsToScene(r),this.convertConnectedGatewaysToManual(r,e);var i=this.findOriginalConnection(n,e.connections);i&&(this.restructureConnections(i,r,e),n.userData.isManuallyPositioned=!0,n.userData.manualConnectors=r.map(function(n){return n.uuid}),this.addManualSegmentToSceneData(n))}}},{key:"convertConnectedGatewaysToManual",value:function(n,e){var t,r,i=this,o=this.sceneViewer,a=[],u=null!==(t=n[0])&&void 0!==t&&null!==(t=t.userData)&&void 0!==t&&t.manualSegmentUuid?o.scene.getObjectByProperty("uuid",n[0].userData.manualSegmentUuid):null;u&&null!==(r=u.userData)&&void 0!==r&&r.isPipeSegment&&([u.userData.pathFrom,u.userData.pathTo].forEach(function(n){var t,r,u=null;(o.scene.traverse(function(e){var t;e.uuid!==n&&(null===(t=e.userData)||void 0===t?void 0:t.originalUuid)!==n||(u=e)}),u)&&("gateway"===(null===(t=u.userData)||void 0===t?void 0:t.componentType)&&"computed"===(null===(r=u.userData)||void 0===r?void 0:r.origin)&&(i.convertGatewayToManual(u,e),a.push(u)))}),a.length)}},{key:"convertGatewayToManual",value:function(n,e){var t;n.userData.origin="declared";for(var r=0;r<e.scene.object.children.length;r++){var i,o,a=e.scene.object.children[r];if(a.uuid===n.uuid||a.uuid===(null===(i=n.userData)||void 0===i?void 0:i.originalUuid)||n.uuid===(null===(o=a.userData)||void 0===o?void 0:o.originalUuid)){a.userData||(a.userData={}),a.userData.origin="declared";break}}if(null!==(t=n.userData)&&void 0!==t&&t.connections&&e.connections){var u=n.userData.connections,s=e.connections;u.removed&&Array.isArray(u.removed)&&(e.connections=s.filter(function(n){var e=u.removed.some(function(e){return e.from===n.from&&e.to===n.to||e.from===n.to&&e.to===n.from});return!e})),u.added&&Array.isArray(u.added)&&u.added.forEach(function(n){e.connections.some(function(e){return e.from===n.from&&e.to===n.to||e.from===n.to&&e.to===n.from})||e.connections.push(n)})}}},{key:"findOriginalConnection",value:function(n,e){var t=n.userData,r=t.pathFrom,i=t.pathTo,o=e.find(function(n){return n.from===r&&n.to===i||n.from===i&&n.to===r});if(o)return o;var a=this.sceneViewer,u=null,s=null;if(a.scene.traverse(function(n){var e,t;n.uuid!==r&&(null===(e=n.userData)||void 0===e?void 0:e.originalUuid)!==r||(u=n),n.uuid!==i&&(null===(t=n.userData)||void 0===t?void 0:t.originalUuid)!==i||(s=n)}),u&&s&&(o=e.find(function(n){return n.from===u.uuid&&n.to===s.uuid||n.from===s.uuid&&n.to===u.uuid})))return o;var c=e.filter(function(n){var e,t,o=n.from===r||n.from===i,u=n.to===r||n.to===i,s="gateway"===(null===(e=a.scene.getObjectByProperty("uuid",n.from))||void 0===e||null===(e=e.userData)||void 0===e?void 0:e.componentType),c="gateway"===(null===(t=a.scene.getObjectByProperty("uuid",n.to))||void 0===t||null===(t=t.userData)||void 0===t?void 0:t.componentType);return o||u||s||c});return c.length>0?c[0]:null}},{key:"calculateSegmentEndpoints",value:function(n){var e=n.geometry.parameters.height||1,t=new c.Vector3,r=new c.Vector3,i=new c.Vector3(0,1,0);return i.applyQuaternion(n.quaternion),t.copy(n.position).sub(i.clone().multiplyScalar(e/2)),r.copy(n.position).add(i.clone().multiplyScalar(e/2)),{start:t,end:r}}},{key:"createSegmentConnectors",value:function(n,e){var t=n.userData.segmentId,r=[],i=new c.Mesh(new c.SphereGeometry(.2,16,16),new c.MeshStandardMaterial({color:65280,roughness:.7,metalness:.3,emissive:13056}));i.position.copy(e.start),i.uuid="".concat(t,"-connector-start"),i.name="Manual Segment Start Connector: ".concat(n.name),i.userData={componentType:"connector",forExport:!0,isManualSegmentConnector:!0,segmentId:t,connectorType:"start",manualSegmentUuid:n.uuid};var o=new c.Mesh(new c.SphereGeometry(.2,16,16),new c.MeshStandardMaterial({color:16711680,roughness:.7,metalness:.3,emissive:3342336}));return o.position.copy(e.end),o.uuid="".concat(t,"-connector-end"),o.name="Manual Segment End Connector: ".concat(n.name),o.userData={componentType:"connector",forExport:!0,isManualSegmentConnector:!0,segmentId:t,connectorType:"end",manualSegmentUuid:n.uuid},r.push(i,o),r}},{key:"addConnectorsToScene",value:function(n){var t=this.sceneViewer;n.forEach(function(n){if(t.scene.add(n),t.currentSceneData&&t.currentSceneData.scene&&t.currentSceneData.scene.object){var r={uuid:n.uuid,name:n.name,type:n.type,userData:e({},n.userData),position:{x:n.position.x,y:n.position.y,z:n.position.z},rotation:{x:n.rotation.x,y:n.rotation.y,z:n.rotation.z},scale:{x:n.scale.x,y:n.scale.y,z:n.scale.z},geometry:"CONNECTOR-GEO"};t.currentSceneData.scene.object.children.push(r)}})}},{key:"addManualSegmentToSceneData",value:function(n){var t=this.sceneViewer;if(t.currentSceneData&&t.currentSceneData.scene&&t.currentSceneData.scene.object){var r={uuid:n.uuid,name:n.name,type:n.type,userData:e({},n.userData),position:{x:n.position.x,y:n.position.y,z:n.position.z},rotation:{x:n.rotation.x,y:n.rotation.y,z:n.rotation.z},scale:{x:n.scale.x,y:n.scale.y,z:n.scale.z}};t.currentSceneData.scene.object.children.push(r)}}},{key:"restructureConnections",value:function(n,e,t){var o=i(e,2),a=o[0],u=o[1],s=t.connections.findIndex(function(e){return e.from===n.from&&e.to===n.to||e.from===n.to&&e.to===n.from});if(-1!==s){t.connections.splice(s,1);var c={from:n.from,to:a.uuid},l={from:u.uuid,to:n.to};t.connections.push(c,l),this.sceneViewer.currentSceneData&&(this.sceneViewer.currentSceneData.connections=r(t.connections))}}},{key:"createElbowGeometry",value:function(n,e,t,r){try{var i=3*r,o=this.createElbowCurve(n,e,t,i);return new c.TubeGeometry(o,12,r,8,!1)}catch(n){return null}}},{key:"createElbowCurve",value:function(n,e,t,r){var i=e.clone().sub(n).normalize(),o=t.clone().sub(e).normalize(),a=.001*r,u=e.clone().sub(i.clone().multiplyScalar(a)),s=e.clone().add(o.clone().multiplyScalar(a)),l=e.clone();return new c.QuadraticBezierCurve3(u,l,s)}},{key:"recomputeWorldBoundingBoxes",value:function(n){this.sceneViewer.scene.traverse(function(e){if(e.isMesh){var t=null,r=function(n){var t,i=a(n);try{for(i.s();!(t=i.n()).done;){var o,u,s=t.value;if(s.uuid===e.uuid||s.uuid===(null===(o=e.userData)||void 0===o?void 0:o.originalUuid)||e.uuid===(null===(u=s.userData)||void 0===u?void 0:u.originalUuid))return s;if(e.name&&s.name){var c=d(e.name),l=d(s.name);if(c===l||c===s.uuid||l===e.uuid)return s}if(e.name&&s.name&&e.name===s.name)return s;if(s.children){var f=r(s.children);if(f)return f}}}catch(n){i.e(n)}finally{i.f()}return null};if(t=r(n.scene.object.children)){var i=(new c.Box3).setFromObject(e);t.userData||(t.userData={}),t.userData.worldBoundingBox={min:i.min.toArray(),max:i.max.toArray()},t.userData.origin||(t.userData.origin=e.userData.origin),t.userData.direction||(t.userData.direction=e.userData.direction),t.userData.group||(t.userData.group=e.userData.group),t.userData.connections||(t.userData.connections=e.userData.connections),e.userData.associatedJsonObject=t}}})}},{key:"updatePathfindingWithConnections",value:(m=u(s().m(function n(e){var t,i;return s().w(function(n){for(;;)switch(n.n){case 0:if((t=this.sceneViewer).currentSceneData){n.n=1;break}return n.a(2,!1);case 1:return this.removeComputedObjects(),(i=JSON.parse(JSON.stringify(t.currentSceneData))).connections=r(e),n.n=2,this.t(i.scene,i.connections,{createGateways:!1,context:"Connections Update"});case 2:return t.currentSceneData=i,n.a(2,!0)}},n,this)})),function(n){return m.apply(this,arguments)})},{key:"updatePathfindingAfterTransform",value:(h=u(s().m(function n(e){return s().w(function(n){for(;;)switch(n.n){case 0:return this.removeComputedObjects(),n.n=1,this.t(e.scene,e.connections,{createGateways:!0,context:"Transform Update"});case 1:return n.a(2)}},n,this)})),function(n){return h.apply(this,arguments)})},{key:"dispose",value:function(){this.removeComputedObjects(),this.pathfinder=null,this.crosscubeTextureSet=null,this.pathfinderVersionInfo=null,f.info("PathfindingManager disposed")}},{key:"mergeColinearPaths",value:function(n){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.001,t=JSON.parse(JSON.stringify(n));return t.forEach(function(n){if(n.path&&!(n.path.length<=2)){var t=n.path.map(function(n){return n instanceof c.Vector3?n.clone():Array.isArray(n)?(new c.Vector3).fromArray(n):void 0!==n.x&&void 0!==n.y&&void 0!==n.z?new c.Vector3(n.x,n.y,n.z):new c.Vector3(0,0,0)});if(!(t.length<=2)){for(var r=[t[0]],i=0,o=function(){var n=t[i],o=t[i+1],a=(new c.Vector3).subVectors(o,n);if(a.length()<1e-6)return i++,1;a.normalize();for(var u=i+2;u<t.length;){var s=t[u],l=(new c.Vector3).subVectors(s,n);if(l.length()<1e-6)u++;else{l.normalize();var f=a.dot(l);if(!(Math.abs(f-1)<e))break;o=s,u++}}o.equals(n)||r.push(o);var v=t.findIndex(function(n,e){return e>i&&n.equals(o)});-1===v?i++:i=v};i<t.length-1;)o();var a=r.map(function(e){return Array.isArray(n.path[0])?[e.x,e.y,e.z]:void 0!==n.path[0].x?{x:e.x,y:e.y,z:e.z}:e});n.path=a;t.length,r.length}}}),t}}]);var h,m,y,p,g,w}();export{h as PathfindingManager};
1
+ import { createClass as _createClass, objectSpread2 as _objectSpread2, construct as _construct, toConsumableArray as _toConsumableArray, slicedToArray as _slicedToArray, classCallCheck as _classCallCheck, createForOfIteratorHelper as _createForOfIteratorHelper, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
+ import * as THREE from 'three';
3
+ import { Pathfinder } from '../../../node_modules/@2112-lab/pathfinder/dist/index.esm.js';
4
+ import { logger, pathfinderLogger } from '../../core/debugLogger.js';
5
+ import { generateUuidFromName } from '../../core/nameUtils.js';
6
+
7
+ var PathfindingManager = /*#__PURE__*/function () {
8
+ function PathfindingManager(sceneViewer) {
9
+ _classCallCheck(this, PathfindingManager);
10
+ this.sceneViewer = sceneViewer;
11
+ this.pathfinder = null;
12
+ this.crosscubeTextureSet = null;
13
+ this.pathfinderVersionInfo = null;
14
+ // Configuration for pathfinder grid
15
+ this.pathfinderConfig = {
16
+ grid: {
17
+ size: 0.5,
18
+ safetyMargin: 0,
19
+ minSegmentLength: 0.5,
20
+ timeout: 1000
21
+ }
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Get pathfinder version information
27
+ */
28
+ return _createClass(PathfindingManager, [{
29
+ key: "getPathfinderVersionInfo",
30
+ value: (function () {
31
+ var _getPathfinderVersionInfo = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
32
+ var versionInfo;
33
+ return _regenerator().w(function (_context) {
34
+ while (1) switch (_context.n) {
35
+ case 0:
36
+ if (!this.pathfinderVersionInfo) {
37
+ _context.n = 1;
38
+ break;
39
+ }
40
+ return _context.a(2, this.pathfinderVersionInfo);
41
+ case 1:
42
+ versionInfo = {
43
+ version: '1.0.17',
44
+ detectionMethod: 'hardcoded-fallback',
45
+ timestamp: new Date().toISOString()
46
+ };
47
+ this.pathfinderVersionInfo = versionInfo;
48
+ return _context.a(2, versionInfo);
49
+ }
50
+ }, _callee, this);
51
+ }));
52
+ function getPathfinderVersionInfo() {
53
+ return _getPathfinderVersionInfo.apply(this, arguments);
54
+ }
55
+ return getPathfinderVersionInfo;
56
+ }()
57
+ /**
58
+ * Log pathfinder version information
59
+ */
60
+ )
61
+ }, {
62
+ key: "logPathfinderVersion",
63
+ value: (function () {
64
+ var _logPathfinderVersion = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
65
+ var context,
66
+ versionInfo,
67
+ _args2 = arguments,
68
+ _t;
69
+ return _regenerator().w(function (_context2) {
70
+ while (1) switch (_context2.n) {
71
+ case 0:
72
+ context = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : 'Unknown Context';
73
+ _context2.p = 1;
74
+ _context2.n = 2;
75
+ return this.getPathfinderVersionInfo();
76
+ case 2:
77
+ versionInfo = _context2.v;
78
+ pathfinderLogger.info("[".concat(context, "] Pathfinder Module Information:"), {
79
+ version: versionInfo.version,
80
+ detectionMethod: versionInfo.detectionMethod,
81
+ context: context,
82
+ timestamp: versionInfo.timestamp,
83
+ pathfinderInstance: !!this.pathfinder
84
+ });
85
+ _context2.n = 4;
86
+ break;
87
+ case 3:
88
+ _context2.p = 3;
89
+ _t = _context2.v;
90
+ pathfinderLogger.error("[".concat(context, "] Failed to get pathfinder version:"), _t);
91
+ case 4:
92
+ return _context2.a(2);
93
+ }
94
+ }, _callee2, this, [[1, 3]]);
95
+ }));
96
+ function logPathfinderVersion() {
97
+ return _logPathfinderVersion.apply(this, arguments);
98
+ }
99
+ return logPathfinderVersion;
100
+ }()
101
+ /**
102
+ * Get path colors for visual distinction
103
+ */
104
+ )
105
+ }, {
106
+ key: "getPathColor",
107
+ value: function getPathColor(index) {
108
+ var colors = ['#468e49', '#245e29', '#2e80d2', '#1d51a1'];
109
+ return colors[index % colors.length];
110
+ }
111
+
112
+ /**
113
+ * Core pathfinding logic shared across initialization and updates
114
+ */
115
+ }, {
116
+ key: "_executePathfinding",
117
+ value: (function () {
118
+ var _executePathfinding2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(sceneData, connections) {
119
+ var _this = this;
120
+ var options,
121
+ _options$createGatewa,
122
+ createGateways,
123
+ _options$context,
124
+ context,
125
+ pathfindingResult,
126
+ optimizedPaths,
127
+ _args3 = arguments;
128
+ return _regenerator().w(function (_context3) {
129
+ while (1) switch (_context3.n) {
130
+ case 0:
131
+ options = _args3.length > 2 && _args3[2] !== undefined ? _args3[2] : {};
132
+ _options$createGatewa = options.createGateways, createGateways = _options$createGatewa === void 0 ? false : _options$createGatewa, _options$context = options.context, context = _options$context === void 0 ? 'Pathfinding' : _options$context; // Log pathfinder version information
133
+ _context3.n = 1;
134
+ return this.logPathfinderVersion(context);
135
+ case 1:
136
+ // Create pathfinder instance with configuration only
137
+ this.pathfinder = new Pathfinder(this.pathfinderConfig);
138
+ this.sceneViewer.pathfinder = this.pathfinder;
139
+
140
+ // Add debugging for pathfinder input
141
+ if (context === 'Scene Loading') {
142
+ console.log('🔍 PATHFINDER DEBUGGING:');
143
+ console.log('🔗 Connections:', connections);
144
+ console.log('🏗️ Scene structure:', JSON.parse(JSON.stringify(sceneData.object)));
145
+ }
146
+
147
+ // Remove from sceneData objects that are origin: computed
148
+ sceneData.object.children = sceneData.object.children.filter(function (child) {
149
+ return child.userData.origin !== 'computed';
150
+ });
151
+
152
+ // Add debugging for pathfinder input
153
+ console.log('🔍 PATHFINDER DEBUGGING:');
154
+ console.log('🔗 Connections:', JSON.parse(JSON.stringify(connections)));
155
+ console.log('🏗️ Scene structure:', JSON.parse(JSON.stringify(sceneData.object)));
156
+
157
+ // Find paths using v1.0.17 API (scene and connections separately)
158
+ pathfindingResult = this.pathfinder.findPaths(sceneData, connections);
159
+ console.log('Found paths:', JSON.parse(JSON.stringify(pathfindingResult.paths)));
160
+ console.log('Generated gateways:', JSON.parse(JSON.stringify(pathfindingResult.gateways)));
161
+ console.log('Rewired connections:', JSON.parse(JSON.stringify(pathfindingResult.rewiredConnections)));
162
+
163
+ // Create gateways in the scene if requested
164
+ if (createGateways && pathfindingResult.gateways) {
165
+ pathfindingResult.gateways.forEach(function (gateway) {
166
+ if (gateway.position) {
167
+ // Create gateway mesh using shared geometry and material
168
+ var gatewayMesh = new THREE.Mesh(new THREE.SphereGeometry(0.15, 16, 16), new THREE.MeshStandardMaterial({
169
+ color: 0xFFFFFF,
170
+ roughness: 0.7,
171
+ metalness: 0.3,
172
+ emissive: 0
173
+ }));
174
+ gatewayMesh.position.copy(gateway.position);
175
+ gatewayMesh.name = gateway.id;
176
+ gatewayMesh.uuid = gateway.id;
177
+
178
+ // Set userData to make gateways selectable
179
+ gatewayMesh.userData = {
180
+ componentType: 'gateway',
181
+ forExport: true,
182
+ gatewayId: gateway.id,
183
+ originalUuid: gateway.id,
184
+ origin: 'computed',
185
+ connections: gateway.connections
186
+ };
187
+
188
+ // Add to scene using editor command
189
+ _this.sceneViewer.scene.add(gatewayMesh);
190
+ console.log("\uD83D\uDD27 Created selectable gateway: ".concat(gateway.id, " with componentType='gateway'"));
191
+ }
192
+ });
193
+ }
194
+ console.log("pathfindingResult.paths:", pathfindingResult.paths);
195
+
196
+ // Preprocess paths to merge colinear segments
197
+ optimizedPaths = this.mergeColinearPaths(pathfindingResult.paths);
198
+ console.log('Path optimization complete. Creating pipe paths...');
199
+
200
+ // Create pipe paths with materials using the optimized paths
201
+ this.createPipePaths(optimizedPaths, this.crosscubeTextureSet);
202
+ return _context3.a(2, pathfindingResult);
203
+ }
204
+ }, _callee3, this);
205
+ }));
206
+ function _executePathfinding(_x, _x2) {
207
+ return _executePathfinding2.apply(this, arguments);
208
+ }
209
+ return _executePathfinding;
210
+ }()
211
+ /**
212
+ * Initialize pathfinder and create paths
213
+ */
214
+ )
215
+ }, {
216
+ key: "initializePathfinder",
217
+ value: (function () {
218
+ var _initializePathfinder = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(data, crosscubeTextureSet) {
219
+ var pathfindingResult;
220
+ return _regenerator().w(function (_context4) {
221
+ while (1) switch (_context4.n) {
222
+ case 0:
223
+ this.crosscubeTextureSet = crosscubeTextureSet;
224
+
225
+ // Use shared pathfinding logic with gateway creation enabled
226
+ _context4.n = 1;
227
+ return this._executePathfinding(data.scene, data.connections, {
228
+ createGateways: true,
229
+ context: 'Scene Loading'
230
+ });
231
+ case 1:
232
+ pathfindingResult = _context4.v;
233
+ // Update connections with rewired connections
234
+ if (pathfindingResult.rewiredConnections) {
235
+ // data.connections = pathfindingResult.rewiredConnections;
236
+ console.log('🔄 Updated connections with rewired connections:', data.connections);
237
+ }
238
+
239
+ // Return full result for potential additional processing
240
+ return _context4.a(2, pathfindingResult);
241
+ }
242
+ }, _callee4, this);
243
+ }));
244
+ function initializePathfinder(_x3, _x4) {
245
+ return _initializePathfinder.apply(this, arguments);
246
+ }
247
+ return initializePathfinder;
248
+ }()
249
+ /**
250
+ * Remove all computed objects from the scene (polyline paths and gateways)
251
+ */
252
+ )
253
+ }, {
254
+ key: "removeComputedObjects",
255
+ value: function removeComputedObjects() {
256
+ var component = this.sceneViewer;
257
+ console.log("removeComputedObjects started");
258
+ var objectsToRemove = [];
259
+ component.scene.traverse(function (obj) {
260
+ // Check the name property instead of uuid, as UUIDs are auto-generated
261
+ if (obj.name && obj.name.includes("Polyline")) {
262
+ console.log("removeComputedObjects ".concat(obj.name, " (uuid: ").concat(obj.uuid, ") found"));
263
+
264
+ // Check if this polyline contains manually transformed segments
265
+ var hasManualSegments = false;
266
+ var manualSegments = [];
267
+ obj.traverse(function (child) {
268
+ if (child.userData && child.userData.isPipeSegment && child.userData.isManuallyPositioned) {
269
+ hasManualSegments = true;
270
+ manualSegments.push(child);
271
+ console.log("\uD83D\uDD12 Found manually positioned pipe segment: ".concat(child.name));
272
+ }
273
+ });
274
+ if (!hasManualSegments) {
275
+ // No manual segments, remove the entire polyline
276
+ objectsToRemove.push(obj);
277
+ } else {
278
+ // Has manual segments, preserve only the manual ones and remove the rest
279
+ console.log("\uD83D\uDD12 Processing polyline with ".concat(manualSegments.length, " manual segments: ").concat(obj.name));
280
+
281
+ // Remove non-manual segments and elbows from the polyline
282
+ var segmentsToRemove = [];
283
+ obj.traverse(function (child) {
284
+ if (child.userData && child.userData.isPipeSegment && !child.userData.isManuallyPositioned) {
285
+ segmentsToRemove.push(child);
286
+ console.log("\uD83D\uDDD1\uFE0F Marking non-manual segment for removal: ".concat(child.name));
287
+ } else if (child.userData && child.userData.isPipeElbow) {
288
+ segmentsToRemove.push(child);
289
+ console.log("\uD83D\uDDD1\uFE0F Marking pipe elbow for removal: ".concat(child.name));
290
+ }
291
+ });
292
+
293
+ // Remove the non-manual segments
294
+ segmentsToRemove.forEach(function (segment) {
295
+ obj.remove(segment);
296
+ if (segment.geometry) segment.geometry.dispose();
297
+ if (segment.material) {
298
+ if (Array.isArray(segment.material)) {
299
+ segment.material.forEach(function (mat) {
300
+ return mat.dispose();
301
+ });
302
+ } else {
303
+ segment.material.dispose();
304
+ }
305
+ }
306
+ console.log("\uD83D\uDDD1\uFE0F Removed non-manual segment: ".concat(segment.name));
307
+ });
308
+
309
+ // If the polyline is now empty, remove it too
310
+ if (obj.children.length === 0) {
311
+ objectsToRemove.push(obj);
312
+ console.log("\uD83D\uDDD1\uFE0F Polyline is now empty, marking for removal: ".concat(obj.name));
313
+ } else {
314
+ console.log("\uD83D\uDD12 Preserved polyline with ".concat(obj.children.length, " manual segments: ").concat(obj.name));
315
+ }
316
+ }
317
+ }
318
+ // Also remove objects with computed origin (like gateways)
319
+ if (obj.userData && obj.userData.origin === 'computed') {
320
+ console.log("removeComputedObjects computed object ".concat(obj.name || obj.type, " (uuid: ").concat(obj.uuid, ") found"));
321
+ objectsToRemove.push(obj);
322
+ }
323
+ });
324
+ for (var _i = 0, _objectsToRemove = objectsToRemove; _i < _objectsToRemove.length; _i++) {
325
+ var obj = _objectsToRemove[_i];
326
+ component.scene.remove(obj);
327
+ if (obj.geometry) obj.geometry.dispose();
328
+ if (obj.material) {
329
+ if (Array.isArray(obj.material)) {
330
+ obj.material.forEach(function (mat) {
331
+ return mat.dispose();
332
+ });
333
+ } else {
334
+ obj.material.dispose();
335
+ }
336
+ }
337
+ }
338
+ console.log("\u2705 Removed ".concat(objectsToRemove.length, " objects from scene (polylines and computed objects)"));
339
+ }
340
+
341
+ /**
342
+ * Material factory function to reduce duplication
343
+ */
344
+ }, {
345
+ key: "createPipeMaterial",
346
+ value: function createPipeMaterial(crosscubeTextureSet, pathIndex) {
347
+ if (crosscubeTextureSet) {
348
+ var materialProps = _objectSpread2(_objectSpread2({}, crosscubeTextureSet.config.materialProps), {}, {
349
+ color: this.getPathColor(pathIndex),
350
+ map: crosscubeTextureSet.textures.diffuse,
351
+ normalMap: crosscubeTextureSet.textures.normal,
352
+ roughnessMap: crosscubeTextureSet.textures.roughness,
353
+ metalness: 0.2,
354
+ roughness: 0.9,
355
+ clearcoat: 0.2,
356
+ clearcoatRoughness: 0.2,
357
+ envMapIntensity: 0.6,
358
+ reflectivity: 0.4
359
+ });
360
+
361
+ // Handle normalScale conversion to Vector2
362
+ if (materialProps.normalScale && Array.isArray(materialProps.normalScale)) {
363
+ materialProps.normalScale = _construct(THREE.Vector2, _toConsumableArray(materialProps.normalScale));
364
+ }
365
+ var material = new THREE.MeshPhysicalMaterial(materialProps);
366
+
367
+ // Configure texture wrapping and repeat
368
+ var pipeTextures = [material.map, material.normalMap, material.roughnessMap].filter(Boolean);
369
+ pipeTextures.forEach(function (texture) {
370
+ texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
371
+ texture.repeat.set(crosscubeTextureSet.config.repeat.x * 2, crosscubeTextureSet.config.repeat.y * 2);
372
+ });
373
+ return material;
374
+ } else {
375
+ return new THREE.MeshPhysicalMaterial({
376
+ color: this.getPathColor(pathIndex),
377
+ metalness: 0.9,
378
+ roughness: 0.7,
379
+ clearcoat: 0.1,
380
+ clearcoatRoughness: 0.3,
381
+ envMapIntensity: 1.5,
382
+ reflectivity: 0.3
383
+ });
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Helper function to create pipe paths
389
+ */
390
+ }, {
391
+ key: "createPipePaths",
392
+ value: function createPipePaths(paths, crosscubeTextureSet) {
393
+ var _this2 = this;
394
+ var component = this.sceneViewer;
395
+ paths.forEach(function (pathData, index) {
396
+ if (pathData.path && pathData.path.length >= 2) {
397
+ var polyline = new THREE.Object3D();
398
+ polyline.name = "Polyline ".concat(pathData.from, "-").concat(pathData.to);
399
+ var pipeRadius = 0.1;
400
+ var pipeMaterial = _this2.createPipeMaterial(crosscubeTextureSet, index);
401
+
402
+ // Convert path points to Vector3 objects for consistent handling
403
+ var pathPoints = pathData.path.map(function (point) {
404
+ if (point instanceof THREE.Vector3) {
405
+ return point.clone();
406
+ } else if (Array.isArray(point)) {
407
+ return new THREE.Vector3().fromArray(point);
408
+ } else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
409
+ return new THREE.Vector3(point.x, point.y, point.z);
410
+ } else {
411
+ console.warn('Unknown point format in createPipePaths:', point);
412
+ return new THREE.Vector3(0, 0, 0);
413
+ }
414
+ });
415
+
416
+ // Create one cylinder per segment (after colinear optimization, this should be minimal segments)
417
+ var _loop = function _loop(j) {
418
+ var start = pathPoints[j];
419
+ var end = pathPoints[j + 1];
420
+ var direction = new THREE.Vector3().subVectors(end, start);
421
+ var length = direction.length();
422
+
423
+ // Skip zero-length segments
424
+ if (length < 1e-6) {
425
+ console.warn("Skipping zero-length segment in path ".concat(pathData.from, "-").concat(pathData.to));
426
+ return 0; // continue
427
+ }
428
+
429
+ // Check if this segment has been manually positioned
430
+ var isManuallyPositioned = false;
431
+ component.scene.traverse(function (sceneObj) {
432
+ if (sceneObj.userData && sceneObj.userData.isPipeSegment && sceneObj.userData.isManuallyPositioned) {
433
+ if (sceneObj.userData.segmentId === "pipe-segment-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j)) {
434
+ isManuallyPositioned = true;
435
+ }
436
+ }
437
+ });
438
+ if (isManuallyPositioned) {
439
+ console.log("\uD83D\uDD12 Skipping segment creation for manually positioned segment: ".concat(pathData.from, "-").concat(pathData.to, " segment ").concat(j));
440
+ return 0; // continue
441
+ }
442
+ var cylinderGeometry = new THREE.CylinderGeometry(pipeRadius, pipeRadius, length, 8, 1, false);
443
+ var cylinder = new THREE.Mesh(cylinderGeometry, pipeMaterial);
444
+ cylinder.position.copy(start).add(end).multiplyScalar(0.5);
445
+ var quaternion = new THREE.Quaternion();
446
+ var up = new THREE.Vector3(0, 1, 0);
447
+ quaternion.setFromUnitVectors(up, direction.clone().normalize());
448
+ cylinder.quaternion.copy(quaternion);
449
+ cylinder.castShadow = true;
450
+ cylinder.receiveShadow = true;
451
+
452
+ // Make pipe segments selectable and add identifying data
453
+ var segmentId = "pipe-segment-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
454
+ cylinder.name = "Pipe Segment ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
455
+
456
+ // Add userData to make pipe segments selectable and for tooltip display
457
+ cylinder.userData = {
458
+ isPipeSegment: true,
459
+ segmentId: segmentId,
460
+ segmentIndex: j,
461
+ pathFrom: pathData.from,
462
+ pathTo: pathData.to,
463
+ pathIndex: index,
464
+ length: length.toFixed(2),
465
+ // Add component data structure for tooltips
466
+ component: {
467
+ type: 'PipeSegment',
468
+ attributes: {
469
+ length: {
470
+ key: 'Length',
471
+ value: length.toFixed(2),
472
+ unit: 'm'
473
+ }
474
+ // connection: {
475
+ // key: 'Connection',
476
+ // value: `${pathData.from} → ${pathData.to}`
477
+ // }
478
+ }
479
+ }
480
+ };
481
+ polyline.add(cylinder);
482
+
483
+ // Add smooth elbow joints only at actual direction changes (not at every point)
484
+ if (j < pathPoints.length - 2) {
485
+ var currentSegment = pathPoints[j + 1].clone().sub(pathPoints[j]).normalize();
486
+ var nextSegment = pathPoints[j + 2].clone().sub(pathPoints[j + 1]).normalize();
487
+
488
+ // Check if there's actually a direction change (not just continuing straight)
489
+ var angle = currentSegment.angleTo(nextSegment);
490
+ var minAngle = Math.PI / 36; // 5 degrees minimum for creating an elbow
491
+
492
+ if (angle > minAngle) {
493
+ var elbowGeometry = _this2.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
494
+ if (elbowGeometry) {
495
+ var elbow = new THREE.Mesh(elbowGeometry, pipeMaterial);
496
+ elbow.castShadow = true;
497
+ elbow.receiveShadow = true;
498
+
499
+ // Make elbows selectable as well
500
+ var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
501
+ elbow.name = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
502
+
503
+ // Add userData for elbows too
504
+ elbow.userData = {
505
+ isPipeElbow: true,
506
+ elbowId: elbowId,
507
+ elbowIndex: j,
508
+ pathFrom: pathData.from,
509
+ pathTo: pathData.to,
510
+ pathIndex: index,
511
+ angle: (angle * 180 / Math.PI).toFixed(1),
512
+ // Add component data for tooltips
513
+ component: {
514
+ type: 'PipeElbow',
515
+ attributes: {
516
+ angle: {
517
+ key: 'Bend Angle',
518
+ value: (angle * 180 / Math.PI).toFixed(1),
519
+ unit: '°'
520
+ }
521
+ }
522
+ }
523
+ };
524
+ polyline.add(elbow);
525
+ }
526
+ }
527
+ }
528
+ },
529
+ _ret;
530
+ for (var j = 0; j < pathPoints.length - 1; j++) {
531
+ _ret = _loop(j);
532
+ if (_ret === 0) continue;
533
+ }
534
+ polyline.name = "Polyline";
535
+ component.scene.add(polyline);
536
+ console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
537
+ }
538
+ });
539
+ }
540
+
541
+ /**
542
+ * Handle manual segment transformation by creating connectors and restructuring connections
543
+ * @param {THREE.Object3D} segment - The transformed pipe segment
544
+ * @param {Object} currentSceneData - Current scene data with connections
545
+ */
546
+ }, {
547
+ key: "handleManualSegmentTransformation",
548
+ value: function handleManualSegmentTransformation(segment, currentSceneData) {
549
+ if (!segment || !segment.userData || !segment.userData.isPipeSegment) {
550
+ console.log('❌ Object is not a pipe segment:', {
551
+ isObject: !!segment,
552
+ hasUserData: !!(segment && segment.userData),
553
+ isPipeSegment: !!(segment && segment.userData && segment.userData.isPipeSegment)
554
+ });
555
+ return;
556
+ }
557
+ console.log('🔧 Handling manual segment transformation:', segment.name);
558
+
559
+ // Calculate segment endpoints in world coordinates
560
+ var segmentEndpoints = this.calculateSegmentEndpoints(segment);
561
+ console.log('📍 Segment endpoints:', segmentEndpoints);
562
+
563
+ // Create connectors at the segment endpoints
564
+ var connectors = this.createSegmentConnectors(segment, segmentEndpoints);
565
+ console.log('🔌 Created connectors:', connectors);
566
+
567
+ // Add connectors to the scene
568
+ this.addConnectorsToScene(connectors);
569
+
570
+ // Check and convert connected gateways to manual (declared) BEFORE finding original connection
571
+ this.convertConnectedGatewaysToManual(connectors, currentSceneData);
572
+
573
+ // Find the original connection that this segment belongs to (after gateways are converted)
574
+ var originalConnection = this.findOriginalConnection(segment, currentSceneData.connections);
575
+ if (!originalConnection) {
576
+ console.warn('⚠️ Could not find original connection for segment:', segment.name);
577
+ return;
578
+ }
579
+ console.log('🔍 Found original connection:', originalConnection);
580
+
581
+ // Restructure connections
582
+ this.restructureConnections(originalConnection, connectors, currentSceneData);
583
+
584
+ // Mark segment as manually positioned
585
+ segment.userData.isManuallyPositioned = true;
586
+ segment.userData.manualConnectors = connectors.map(function (c) {
587
+ return c.uuid;
588
+ });
589
+
590
+ // Add the manually positioned segment to scene data
591
+ this.addManualSegmentToSceneData(segment);
592
+ console.log('✅ Manual segment transformation completed');
593
+ }
594
+
595
+ /**
596
+ * Check and convert gateways at the original path endpoints to manual (declared)
597
+ * @param {Array} connectors - Array of connector objects (used to get segment reference)
598
+ * @param {Object} currentSceneData - Current scene data
599
+ */
600
+ }, {
601
+ key: "convertConnectedGatewaysToManual",
602
+ value: function convertConnectedGatewaysToManual(connectors, currentSceneData) {
603
+ var _connectors$,
604
+ _segment$userData,
605
+ _this3 = this;
606
+ console.log('🔍 Checking for connected gateways to convert to manual...');
607
+ var component = this.sceneViewer;
608
+ var convertedGateways = [];
609
+
610
+ // Get the segment from the first connector's userData
611
+ var segment = (_connectors$ = connectors[0]) !== null && _connectors$ !== void 0 && (_connectors$ = _connectors$.userData) !== null && _connectors$ !== void 0 && _connectors$.manualSegmentUuid ? component.scene.getObjectByProperty('uuid', connectors[0].userData.manualSegmentUuid) : null;
612
+ if (!segment || !((_segment$userData = segment.userData) !== null && _segment$userData !== void 0 && _segment$userData.isPipeSegment)) {
613
+ console.log('❌ Could not find segment for gateway conversion');
614
+ return;
615
+ }
616
+ var pathFrom = segment.userData.pathFrom;
617
+ var pathTo = segment.userData.pathTo;
618
+ console.log("\uD83D\uDD0D Checking original path endpoints for gateways: ".concat(pathFrom, " \u2192 ").concat(pathTo));
619
+
620
+ // Check the original path endpoints for gateways
621
+ [pathFrom, pathTo].forEach(function (endpointUuid) {
622
+ console.log("\uD83D\uDD0D Checking endpoint: ".concat(endpointUuid));
623
+
624
+ // Find the object in the scene that corresponds to this endpoint
625
+ var endpointObject = null;
626
+ component.scene.traverse(function (obj) {
627
+ var _obj$userData;
628
+ if (obj.uuid === endpointUuid || ((_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.originalUuid) === endpointUuid) {
629
+ endpointObject = obj;
630
+ }
631
+ });
632
+ if (endpointObject) {
633
+ var _endpointObject$userD, _endpointObject$userD2, _endpointObject$userD3, _endpointObject$userD4;
634
+ console.log("\uD83D\uDD0D Found endpoint object: ".concat(endpointObject.name, " (").concat(endpointObject.uuid, ") - componentType: ").concat((_endpointObject$userD = endpointObject.userData) === null || _endpointObject$userD === void 0 ? void 0 : _endpointObject$userD.componentType, ", origin: ").concat((_endpointObject$userD2 = endpointObject.userData) === null || _endpointObject$userD2 === void 0 ? void 0 : _endpointObject$userD2.origin));
635
+
636
+ // Check if this endpoint is a gateway that needs to be converted to manual
637
+ if (((_endpointObject$userD3 = endpointObject.userData) === null || _endpointObject$userD3 === void 0 ? void 0 : _endpointObject$userD3.componentType) === 'gateway' && ((_endpointObject$userD4 = endpointObject.userData) === null || _endpointObject$userD4 === void 0 ? void 0 : _endpointObject$userD4.origin) === 'computed') {
638
+ console.log("\uD83D\uDD27 Found computed gateway at endpoint: ".concat(endpointObject.name, " (").concat(endpointObject.uuid, ")"));
639
+
640
+ // Convert gateway to manual (declared)
641
+ _this3.convertGatewayToManual(endpointObject, currentSceneData);
642
+ convertedGateways.push(endpointObject);
643
+ }
644
+ } else {
645
+ console.log("\u26A0\uFE0F Could not find object for endpoint: ".concat(endpointUuid));
646
+ }
647
+ });
648
+ if (convertedGateways.length > 0) {
649
+ console.log("\u2705 Converted ".concat(convertedGateways.length, " gateways to manual:"), convertedGateways.map(function (g) {
650
+ return g.name;
651
+ }));
652
+ } else {
653
+ console.log('ℹ️ No connected gateways found to convert');
654
+ }
655
+ }
656
+
657
+ /**
658
+ * Convert a gateway from computed to manual (declared) - reusing logic from sceneOperationsManager
659
+ * @param {THREE.Object3D} gateway - The gateway object to convert
660
+ * @param {Object} currentSceneData - Current scene data
661
+ */
662
+ }, {
663
+ key: "convertGatewayToManual",
664
+ value: function convertGatewayToManual(gateway, currentSceneData) {
665
+ var _gateway$userData2;
666
+ console.log("\uD83D\uDD27 Converting gateway from computed to declared: ".concat(gateway.name, " (").concat(gateway.uuid, ")"));
667
+
668
+ // Change origin from computed to declared
669
+ gateway.userData.origin = 'declared';
670
+
671
+ // Update the corresponding scene data object
672
+ for (var i = 0; i < currentSceneData.scene.object.children.length; i++) {
673
+ var _gateway$userData, _child$userData;
674
+ var child = currentSceneData.scene.object.children[i];
675
+ if (child.uuid === gateway.uuid || child.uuid === ((_gateway$userData = gateway.userData) === null || _gateway$userData === void 0 ? void 0 : _gateway$userData.originalUuid) || gateway.uuid === ((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.originalUuid)) {
676
+ if (!child.userData) child.userData = {};
677
+ child.userData.origin = 'declared';
678
+ console.log("\u2705 Updated scene data gateway origin to declared: ".concat(child.uuid));
679
+ break;
680
+ }
681
+ }
682
+
683
+ // Process gateway connections (same logic as in sceneOperationsManager)
684
+ if ((_gateway$userData2 = gateway.userData) !== null && _gateway$userData2 !== void 0 && _gateway$userData2.connections && currentSceneData.connections) {
685
+ console.log('🔗 Processing gateway connections for filtering:', gateway.userData.connections);
686
+ var gatewayConnections = gateway.userData.connections;
687
+ var currentConnections = currentSceneData.connections;
688
+
689
+ // Filter out removed connections
690
+ if (gatewayConnections.removed && Array.isArray(gatewayConnections.removed)) {
691
+ console.log('🗑️ Filtering out removed connections:', gatewayConnections.removed);
692
+ currentSceneData.connections = currentConnections.filter(function (connection) {
693
+ var isRemoved = gatewayConnections.removed.some(function (removedConn) {
694
+ return removedConn.from === connection.from && removedConn.to === connection.to || removedConn.from === connection.to && removedConn.to === connection.from;
695
+ });
696
+ if (isRemoved) {
697
+ console.log("\uD83D\uDDD1\uFE0F Removed connection: ".concat(connection.from, " \u2192 ").concat(connection.to));
698
+ }
699
+ return !isRemoved;
700
+ });
701
+ }
702
+
703
+ // Add new connections
704
+ if (gatewayConnections.added && Array.isArray(gatewayConnections.added)) {
705
+ console.log('➕ Adding new connections:', gatewayConnections.added);
706
+ gatewayConnections.added.forEach(function (newConnection) {
707
+ // Check if connection already exists to avoid duplicates
708
+ var alreadyExists = currentSceneData.connections.some(function (conn) {
709
+ return conn.from === newConnection.from && conn.to === newConnection.to || conn.from === newConnection.to && conn.to === newConnection.from;
710
+ });
711
+ if (!alreadyExists) {
712
+ currentSceneData.connections.push(newConnection);
713
+ console.log("\u2795 Added new connection: ".concat(newConnection.from, " \u2192 ").concat(newConnection.to));
714
+ } else {
715
+ console.log("\u26A0\uFE0F Connection already exists, skipping: ".concat(newConnection.from, " \u2192 ").concat(newConnection.to));
716
+ }
717
+ });
718
+ }
719
+ console.log('✅ Gateway connections processing completed. Total connections:', currentSceneData.connections.length);
720
+ }
721
+ console.log("\u2705 Gateway ".concat(gateway.name, " successfully converted to manual (declared)"));
722
+ }
723
+
724
+ /**
725
+ * Find the original connection that a segment belongs to
726
+ * @param {THREE.Object3D} segment - The pipe segment
727
+ * @param {Array} connections - Array of connections
728
+ * @returns {Object|null} The original connection or null
729
+ */
730
+ }, {
731
+ key: "findOriginalConnection",
732
+ value: function findOriginalConnection(segment, connections) {
733
+ var _fromObject$userData, _toObject$userData;
734
+ var segmentData = segment.userData;
735
+ var pathFrom = segmentData.pathFrom;
736
+ var pathTo = segmentData.pathTo;
737
+ console.log('🔍 Looking for connection:', {
738
+ pathFrom: pathFrom,
739
+ pathTo: pathTo
740
+ });
741
+ console.log('🔍 Available connections:', connections);
742
+
743
+ // First try: direct connection match
744
+ var foundConnection = connections.find(function (conn) {
745
+ return conn.from === pathFrom && conn.to === pathTo || conn.from === pathTo && conn.to === pathFrom;
746
+ });
747
+ if (foundConnection) {
748
+ console.log('🔍 Found direct connection match:', foundConnection);
749
+ return foundConnection;
750
+ }
751
+
752
+ // Second try: look for connections that might involve gateways
753
+ // This can happen when the original connection involves a gateway that was computed
754
+ console.log('🔍 No direct match found, checking for gateway-involved connections...');
755
+ var component = this.sceneViewer;
756
+
757
+ // Look for objects in the scene that might be the pathFrom or pathTo
758
+ var fromObject = null;
759
+ var toObject = null;
760
+ component.scene.traverse(function (obj) {
761
+ var _obj$userData2, _obj$userData3;
762
+ if (obj.uuid === pathFrom || ((_obj$userData2 = obj.userData) === null || _obj$userData2 === void 0 ? void 0 : _obj$userData2.originalUuid) === pathFrom) {
763
+ fromObject = obj;
764
+ }
765
+ if (obj.uuid === pathTo || ((_obj$userData3 = obj.userData) === null || _obj$userData3 === void 0 ? void 0 : _obj$userData3.originalUuid) === pathTo) {
766
+ toObject = obj;
767
+ }
768
+ });
769
+ console.log('🔍 Scene objects found:', {
770
+ fromObject: fromObject ? {
771
+ uuid: fromObject.uuid,
772
+ name: fromObject.name,
773
+ componentType: (_fromObject$userData = fromObject.userData) === null || _fromObject$userData === void 0 ? void 0 : _fromObject$userData.componentType
774
+ } : null,
775
+ toObject: toObject ? {
776
+ uuid: toObject.uuid,
777
+ name: toObject.name,
778
+ componentType: (_toObject$userData = toObject.userData) === null || _toObject$userData === void 0 ? void 0 : _toObject$userData.componentType
779
+ } : null
780
+ });
781
+
782
+ // If we found the objects, look for connections involving their UUIDs
783
+ if (fromObject && toObject) {
784
+ foundConnection = connections.find(function (conn) {
785
+ return conn.from === fromObject.uuid && conn.to === toObject.uuid || conn.from === toObject.uuid && conn.to === fromObject.uuid;
786
+ });
787
+ if (foundConnection) {
788
+ console.log('🔍 Found connection via object UUIDs:', foundConnection);
789
+ return foundConnection;
790
+ }
791
+ }
792
+
793
+ // Third try: look for any connection that might be related to this segment
794
+ // This is a fallback for cases where the connection structure is complex
795
+ console.log('🔍 Trying fallback: looking for any connection that might be related...');
796
+
797
+ // Look for connections that might involve the segment's path information
798
+ var possibleConnections = connections.filter(function (conn) {
799
+ var _component$scene$getO, _component$scene$getO2;
800
+ // Check if either end of the connection might be related to our segment
801
+ var fromMatches = conn.from === pathFrom || conn.from === pathTo;
802
+ var toMatches = conn.to === pathFrom || conn.to === pathTo;
803
+
804
+ // Also check if the connection involves any gateway or component that might be related
805
+ var fromIsGateway = ((_component$scene$getO = component.scene.getObjectByProperty('uuid', conn.from)) === null || _component$scene$getO === void 0 || (_component$scene$getO = _component$scene$getO.userData) === null || _component$scene$getO === void 0 ? void 0 : _component$scene$getO.componentType) === 'gateway';
806
+ var toIsGateway = ((_component$scene$getO2 = component.scene.getObjectByProperty('uuid', conn.to)) === null || _component$scene$getO2 === void 0 || (_component$scene$getO2 = _component$scene$getO2.userData) === null || _component$scene$getO2 === void 0 ? void 0 : _component$scene$getO2.componentType) === 'gateway';
807
+ return fromMatches || toMatches || fromIsGateway || toIsGateway;
808
+ });
809
+ if (possibleConnections.length > 0) {
810
+ console.log('🔍 Found possible related connections:', possibleConnections);
811
+ // Return the first one as a best guess
812
+ return possibleConnections[0];
813
+ }
814
+ console.log('❌ No connection found for segment');
815
+ return null;
816
+ }
817
+
818
+ /**
819
+ * Calculate the start and end points of a pipe segment in world coordinates
820
+ * @param {THREE.Object3D} segment - The pipe segment
821
+ * @returns {Object} Object with start and end points
822
+ */
823
+ }, {
824
+ key: "calculateSegmentEndpoints",
825
+ value: function calculateSegmentEndpoints(segment) {
826
+ // Get the segment's geometry to determine its length and orientation
827
+ var geometry = segment.geometry;
828
+ var length = geometry.parameters.height || 1;
829
+
830
+ // Calculate start and end points based on segment position and orientation
831
+ var startPoint = new THREE.Vector3();
832
+ var endPoint = new THREE.Vector3();
833
+
834
+ // Get the segment's direction vector
835
+ var direction = new THREE.Vector3(0, 1, 0);
836
+ direction.applyQuaternion(segment.quaternion);
837
+
838
+ // Calculate start point (half length back from center)
839
+ startPoint.copy(segment.position).sub(direction.clone().multiplyScalar(length / 2));
840
+
841
+ // Calculate end point (half length forward from center)
842
+ endPoint.copy(segment.position).add(direction.clone().multiplyScalar(length / 2));
843
+ return {
844
+ start: startPoint,
845
+ end: endPoint
846
+ };
847
+ }
848
+
849
+ /**
850
+ * Create connector objects at segment endpoints
851
+ * @param {THREE.Object3D} segment - The pipe segment
852
+ * @param {Object} endpoints - Object with start and end points
853
+ * @returns {Array} Array of connector objects
854
+ */
855
+ }, {
856
+ key: "createSegmentConnectors",
857
+ value: function createSegmentConnectors(segment, endpoints) {
858
+ var segmentData = segment.userData;
859
+ var segmentId = segmentData.segmentId;
860
+ var connectors = [];
861
+
862
+ // Create start connector
863
+ var startConnector = new THREE.Mesh(new THREE.SphereGeometry(0.2, 16, 16), new THREE.MeshStandardMaterial({
864
+ color: 0x00FF00,
865
+ roughness: 0.7,
866
+ metalness: 0.3,
867
+ emissive: 0x003300
868
+ }));
869
+ startConnector.position.copy(endpoints.start);
870
+ startConnector.uuid = "".concat(segmentId, "-connector-start");
871
+ startConnector.name = "Manual Segment Start Connector: ".concat(segment.name);
872
+ startConnector.userData = {
873
+ componentType: 'connector',
874
+ forExport: true,
875
+ isManualSegmentConnector: true,
876
+ segmentId: segmentId,
877
+ connectorType: 'start',
878
+ manualSegmentUuid: segment.uuid
879
+ };
880
+
881
+ // Create end connector
882
+ var endConnector = new THREE.Mesh(new THREE.SphereGeometry(0.2, 16, 16), new THREE.MeshStandardMaterial({
883
+ color: 0xFF0000,
884
+ roughness: 0.7,
885
+ metalness: 0.3,
886
+ emissive: 0x330000
887
+ }));
888
+ endConnector.position.copy(endpoints.end);
889
+ endConnector.uuid = "".concat(segmentId, "-connector-end");
890
+ endConnector.name = "Manual Segment End Connector: ".concat(segment.name);
891
+ endConnector.userData = {
892
+ componentType: 'connector',
893
+ forExport: true,
894
+ isManualSegmentConnector: true,
895
+ segmentId: segmentId,
896
+ connectorType: 'end',
897
+ manualSegmentUuid: segment.uuid
898
+ };
899
+ connectors.push(startConnector, endConnector);
900
+ return connectors;
901
+ }
902
+
903
+ /**
904
+ * Add connectors to the scene and scene data
905
+ * @param {Array} connectors - Array of connector objects
906
+ */
907
+ }, {
908
+ key: "addConnectorsToScene",
909
+ value: function addConnectorsToScene(connectors) {
910
+ var component = this.sceneViewer;
911
+ connectors.forEach(function (connector) {
912
+ // Add to Three.js scene
913
+ component.scene.add(connector);
914
+ console.log("\uD83D\uDD0C Added connector to Three.js scene: ".concat(connector.name));
915
+
916
+ // Add to scene data structure
917
+ if (component.currentSceneData && component.currentSceneData.scene && component.currentSceneData.scene.object) {
918
+ var sceneDataConnector = {
919
+ uuid: connector.uuid,
920
+ name: connector.name,
921
+ type: connector.type,
922
+ userData: _objectSpread2({}, connector.userData),
923
+ position: {
924
+ x: connector.position.x,
925
+ y: connector.position.y,
926
+ z: connector.position.z
927
+ },
928
+ rotation: {
929
+ x: connector.rotation.x,
930
+ y: connector.rotation.y,
931
+ z: connector.rotation.z
932
+ },
933
+ scale: {
934
+ x: connector.scale.x,
935
+ y: connector.scale.y,
936
+ z: connector.scale.z
937
+ },
938
+ geometry: 'CONNECTOR-GEO'
939
+ };
940
+ component.currentSceneData.scene.object.children.push(sceneDataConnector);
941
+ console.log("\uD83D\uDD0C Added connector to scene data: ".concat(connector.name));
942
+ } else {
943
+ console.warn('⚠️ Could not add connector to scene data - currentSceneData not available');
944
+ }
945
+ });
946
+ }
947
+
948
+ /**
949
+ * Add manually positioned segment to scene data
950
+ * @param {THREE.Object3D} segment - The manually positioned pipe segment
951
+ */
952
+ }, {
953
+ key: "addManualSegmentToSceneData",
954
+ value: function addManualSegmentToSceneData(segment) {
955
+ var component = this.sceneViewer;
956
+ if (!component.currentSceneData || !component.currentSceneData.scene || !component.currentSceneData.scene.object) {
957
+ console.warn('⚠️ Could not add manual segment to scene data - currentSceneData not available');
958
+ return;
959
+ }
960
+
961
+ // Create scene data representation of the segment
962
+ var sceneDataSegment = {
963
+ uuid: segment.uuid,
964
+ name: segment.name,
965
+ type: segment.type,
966
+ userData: _objectSpread2({}, segment.userData),
967
+ position: {
968
+ x: segment.position.x,
969
+ y: segment.position.y,
970
+ z: segment.position.z
971
+ },
972
+ rotation: {
973
+ x: segment.rotation.x,
974
+ y: segment.rotation.y,
975
+ z: segment.rotation.z
976
+ },
977
+ scale: {
978
+ x: segment.scale.x,
979
+ y: segment.scale.y,
980
+ z: segment.scale.z
981
+ }
982
+ };
983
+
984
+ // Add to scene data children
985
+ component.currentSceneData.scene.object.children.push(sceneDataSegment);
986
+ console.log("\uD83D\uDD27 Added manual segment to scene data: ".concat(segment.name));
987
+ }
988
+
989
+ /**
990
+ * Restructure connections to use the new connectors
991
+ * @param {Object} originalConnection - The original connection
992
+ * @param {Array} connectors - Array of connector objects
993
+ * @param {Object} currentSceneData - Current scene data
994
+ */
995
+ }, {
996
+ key: "restructureConnections",
997
+ value: function restructureConnections(originalConnection, connectors, currentSceneData) {
998
+ var _connectors = _slicedToArray(connectors, 2),
999
+ startConnector = _connectors[0],
1000
+ endConnector = _connectors[1];
1001
+ console.log('🔗 Restructuring connections...');
1002
+ console.log('🔗 Original connection:', originalConnection);
1003
+ console.log('🔗 Start connector:', startConnector.uuid);
1004
+ console.log('🔗 End connector:', endConnector.uuid);
1005
+
1006
+ // Find the original connection in the connections array
1007
+ var connectionIndex = currentSceneData.connections.findIndex(function (conn) {
1008
+ return conn.from === originalConnection.from && conn.to === originalConnection.to || conn.from === originalConnection.to && conn.to === originalConnection.from;
1009
+ });
1010
+ if (connectionIndex === -1) {
1011
+ console.warn('⚠️ Could not find original connection in connections array');
1012
+ return;
1013
+ }
1014
+ console.log("\uD83D\uDD17 Found original connection at index: ".concat(connectionIndex));
1015
+
1016
+ // Remove the original connection
1017
+ currentSceneData.connections.splice(connectionIndex, 1);
1018
+ console.log("\uD83D\uDDD1\uFE0F Removed original connection: ".concat(originalConnection.from, " \u2192 ").concat(originalConnection.to));
1019
+
1020
+ // Add two new connections
1021
+ var newConnection1 = {
1022
+ from: originalConnection.from,
1023
+ to: startConnector.uuid
1024
+ };
1025
+ var newConnection2 = {
1026
+ from: endConnector.uuid,
1027
+ to: originalConnection.to
1028
+ };
1029
+ currentSceneData.connections.push(newConnection1, newConnection2);
1030
+ console.log("\u2795 Added new connections:");
1031
+ console.log(" ".concat(newConnection1.from, " \u2192 ").concat(newConnection1.to));
1032
+ console.log(" ".concat(newConnection2.from, " \u2192 ").concat(newConnection2.to));
1033
+
1034
+ // Update the component's current scene data
1035
+ if (this.sceneViewer.currentSceneData) {
1036
+ this.sceneViewer.currentSceneData.connections = _toConsumableArray(currentSceneData.connections);
1037
+ console.log('✅ Updated component currentSceneData connections');
1038
+ }
1039
+ console.log('🔗 Connection restructuring completed');
1040
+ }
1041
+
1042
+ /**
1043
+ * Create smooth elbow geometry to connect two pipe segments (optimized for 90-degree angles)
1044
+ * @param {THREE.Vector3} point1 - First point (before the joint)
1045
+ * @param {THREE.Vector3} point2 - Joint point (center of the elbow)
1046
+ * @param {THREE.Vector3} point3 - Third point (after the joint)
1047
+ * @param {number} radius - Pipe radius
1048
+ * @returns {THREE.BufferGeometry} Elbow geometry
1049
+ */
1050
+ }, {
1051
+ key: "createElbowGeometry",
1052
+ value: function createElbowGeometry(point1, point2, point3, radius) {
1053
+ try {
1054
+ // Fixed elbow radius for 90-degree bends (simplified)
1055
+ var elbowRadius = radius * 3;
1056
+
1057
+ // Create a curve for the 90-degree elbow
1058
+ var curve = this.createElbowCurve(point1, point2, point3, elbowRadius);
1059
+
1060
+ // Fixed tubular segments for 90-degree bends (quarter circle)
1061
+ var tubularSegments = 12; // Good balance for smooth 90° curves
1062
+ var radialSegments = 8;
1063
+ var closed = false;
1064
+ var elbowGeometry = new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
1065
+ return elbowGeometry;
1066
+ } catch (error) {
1067
+ console.warn('Failed to create elbow geometry:', error);
1068
+ return null;
1069
+ }
1070
+ }
1071
+
1072
+ /**
1073
+ * Create a smooth curve for the 90-degree elbow joint (simplified)
1074
+ * @param {THREE.Vector3} point1 - First point
1075
+ * @param {THREE.Vector3} point2 - Joint point
1076
+ * @param {THREE.Vector3} point3 - Third point
1077
+ * @param {number} elbowRadius - Radius of the elbow curve
1078
+ * @returns {THREE.Curve} Curve for the elbow
1079
+ */
1080
+ }, {
1081
+ key: "createElbowCurve",
1082
+ value: function createElbowCurve(point1, point2, point3, elbowRadius) {
1083
+ // Calculate direction vectors
1084
+ var dir1 = point2.clone().sub(point1).normalize();
1085
+ var dir2 = point3.clone().sub(point2).normalize();
1086
+
1087
+ // For 90-degree bends, we can use a simpler approach with a quarter circle
1088
+ // The curve radius is proportional to the elbow radius
1089
+ var curveRadius = elbowRadius * 0.001;
1090
+
1091
+ // Calculate the offset distance from the joint point
1092
+ var offset = curveRadius;
1093
+
1094
+ // Calculate start and end points of the curve (offset from the joint)
1095
+ var curveStart = point2.clone().sub(dir1.clone().multiplyScalar(offset));
1096
+ var curveEnd = point2.clone().add(dir2.clone().multiplyScalar(offset));
1097
+
1098
+ // For a 90-degree bend, the control point is at the corner
1099
+ // We can use a quadratic bezier curve for simplicity
1100
+ var controlPoint = point2.clone();
1101
+
1102
+ // Create a quadratic bezier curve (simpler than cubic for 90° bends)
1103
+ var curve = new THREE.QuadraticBezierCurve3(curveStart, controlPoint, curveEnd);
1104
+ return curve;
1105
+ }
1106
+
1107
+ /**
1108
+ * Recompute world bounding boxes after transforms
1109
+ */
1110
+ }, {
1111
+ key: "recomputeWorldBoundingBoxes",
1112
+ value: function recomputeWorldBoundingBoxes(currentSceneData) {
1113
+ var component = this.sceneViewer;
1114
+ component.scene.traverse(function (object) {
1115
+ if (object.isMesh) {
1116
+ // Find the corresponding JSON object
1117
+ var jsonObject = null;
1118
+ var _findJsonObject = function findJsonObject(children) {
1119
+ var _iterator = _createForOfIteratorHelper(children),
1120
+ _step;
1121
+ try {
1122
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1123
+ var _object$userData, _child$userData2;
1124
+ var child = _step.value;
1125
+ // Enhanced matching logic with hardcoded UUID priority
1126
+
1127
+ // Strategy 1: Direct hardcoded UUID match (HIGHEST PRIORITY)
1128
+ if (child.uuid === object.uuid || child.uuid === ((_object$userData = object.userData) === null || _object$userData === void 0 ? void 0 : _object$userData.originalUuid) || object.uuid === ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid)) {
1129
+ return child;
1130
+ }
1131
+
1132
+ // Strategy 2: Name-based UUID match (FALLBACK)
1133
+ if (object.name && child.name) {
1134
+ var objectGeneratedUuid = generateUuidFromName(object.name);
1135
+ var childGeneratedUuid = generateUuidFromName(child.name);
1136
+ if (objectGeneratedUuid === childGeneratedUuid || objectGeneratedUuid === child.uuid || childGeneratedUuid === object.uuid) {
1137
+ return child;
1138
+ }
1139
+ }
1140
+
1141
+ // Strategy 3: Name match
1142
+ if (object.name && child.name && object.name === child.name) {
1143
+ return child;
1144
+ }
1145
+
1146
+ // Recursively search children
1147
+ if (child.children) {
1148
+ var found = _findJsonObject(child.children);
1149
+ if (found) return found;
1150
+ }
1151
+ }
1152
+ } catch (err) {
1153
+ _iterator.e(err);
1154
+ } finally {
1155
+ _iterator.f();
1156
+ }
1157
+ return null;
1158
+ };
1159
+ jsonObject = _findJsonObject(currentSceneData.scene.object.children);
1160
+ if (jsonObject) {
1161
+ // Compute world bounding box
1162
+ var boundingBox = new THREE.Box3().setFromObject(object);
1163
+
1164
+ // Store in JSON userData for pathfinder
1165
+ if (!jsonObject.userData) jsonObject.userData = {};
1166
+ jsonObject.userData.worldBoundingBox = {
1167
+ min: boundingBox.min.toArray(),
1168
+ max: boundingBox.max.toArray()
1169
+ };
1170
+ if (!jsonObject.userData.origin) jsonObject.userData.origin = object.userData.origin;
1171
+ if (!jsonObject.userData.direction) jsonObject.userData.direction = object.userData.direction;
1172
+ if (!jsonObject.userData.group) jsonObject.userData.group = object.userData.group;
1173
+ if (!jsonObject.userData.connections) jsonObject.userData.connections = object.userData.connections;
1174
+ object.userData.associatedJsonObject = jsonObject;
1175
+ console.log("Added world bounding box for ".concat(jsonObject.name, ":"), jsonObject.userData.worldBoundingBox);
1176
+ }
1177
+ }
1178
+ });
1179
+ } /**
1180
+ * Update pathfinding with new connections data
1181
+ */
1182
+ }, {
1183
+ key: "updatePathfindingWithConnections",
1184
+ value: (function () {
1185
+ var _updatePathfindingWithConnections = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(newConnections) {
1186
+ var _component$currentSce, _component$currentSce2, _component$currentSce3, _updatedSceneData$sce;
1187
+ var component, updatedSceneData;
1188
+ return _regenerator().w(function (_context5) {
1189
+ while (1) switch (_context5.n) {
1190
+ case 0:
1191
+ console.log('[A] updatePathfindingWithConnections');
1192
+ component = this.sceneViewer; // Check if we have current scene data to work with
1193
+ if (component.currentSceneData) {
1194
+ _context5.n = 1;
1195
+ break;
1196
+ }
1197
+ console.warn('⚠️ No current scene data available for pathfinder update');
1198
+ return _context5.a(2, false);
1199
+ case 1:
1200
+ // Remove all existing paths from the scene
1201
+ this.removeComputedObjects();
1202
+ console.log('🔄 Updating pathfinder with new connections:', newConnections);
1203
+ console.log('🔍 Current scene data structure:', {
1204
+ hasConnections: !!component.currentSceneData.connections,
1205
+ connectionsCount: ((_component$currentSce = component.currentSceneData.connections) === null || _component$currentSce === void 0 ? void 0 : _component$currentSce.length) || 0,
1206
+ hasScene: !!component.currentSceneData.scene,
1207
+ hasSceneObject: !!((_component$currentSce2 = component.currentSceneData.scene) !== null && _component$currentSce2 !== void 0 && _component$currentSce2.object),
1208
+ childrenCount: ((_component$currentSce3 = component.currentSceneData.scene) === null || _component$currentSce3 === void 0 || (_component$currentSce3 = _component$currentSce3.object) === null || _component$currentSce3 === void 0 || (_component$currentSce3 = _component$currentSce3.children) === null || _component$currentSce3 === void 0 ? void 0 : _component$currentSce3.length) || 0
1209
+ });
1210
+
1211
+ // Create a deep copy of the current scene data to avoid mutations
1212
+ updatedSceneData = JSON.parse(JSON.stringify(component.currentSceneData)); // Update the connections in the copied scene data
1213
+ updatedSceneData.connections = _toConsumableArray(newConnections);
1214
+ console.log('🔍 Updated scene data for pathfinder:', {
1215
+ connectionsCount: updatedSceneData.connections.length,
1216
+ connections: updatedSceneData.connections,
1217
+ hasScene: !!updatedSceneData.scene,
1218
+ childrenCount: ((_updatedSceneData$sce = updatedSceneData.scene) === null || _updatedSceneData$sce === void 0 || (_updatedSceneData$sce = _updatedSceneData$sce.object) === null || _updatedSceneData$sce === void 0 || (_updatedSceneData$sce = _updatedSceneData$sce.children) === null || _updatedSceneData$sce === void 0 ? void 0 : _updatedSceneData$sce.length) || 0
1219
+ });
1220
+
1221
+ // Use shared pathfinding logic (no gateways needed for updates)
1222
+ _context5.n = 2;
1223
+ return this._executePathfinding(updatedSceneData.scene, updatedSceneData.connections, {
1224
+ createGateways: false,
1225
+ context: 'Connections Update'
1226
+ });
1227
+ case 2:
1228
+ // Update the component's current scene data to reflect the changes
1229
+ component.currentSceneData = updatedSceneData;
1230
+ console.log('✅ Pathfinding updated successfully with new connections');
1231
+ return _context5.a(2, true);
1232
+ }
1233
+ }, _callee5, this);
1234
+ }));
1235
+ function updatePathfindingWithConnections(_x5) {
1236
+ return _updatePathfindingWithConnections.apply(this, arguments);
1237
+ }
1238
+ return updatePathfindingWithConnections;
1239
+ }()
1240
+ /**
1241
+ * Update pathfinding after object transforms
1242
+ */
1243
+ )
1244
+ }, {
1245
+ key: "updatePathfindingAfterTransform",
1246
+ value: (function () {
1247
+ var _updatePathfindingAfterTransform = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(currentSceneData) {
1248
+ return _regenerator().w(function (_context6) {
1249
+ while (1) switch (_context6.n) {
1250
+ case 0:
1251
+ // Remove all existing paths from the scene
1252
+ this.removeComputedObjects();
1253
+ console.log('🔄 Starting pathfinding with updated scene data...');
1254
+
1255
+ // Use shared pathfinding logic (no gateways needed for transform updates)
1256
+ _context6.n = 1;
1257
+ return this._executePathfinding(currentSceneData.scene, currentSceneData.connections, {
1258
+ createGateways: true,
1259
+ context: 'Transform Update'
1260
+ });
1261
+ case 1:
1262
+ return _context6.a(2);
1263
+ }
1264
+ }, _callee6, this);
1265
+ }));
1266
+ function updatePathfindingAfterTransform(_x6) {
1267
+ return _updatePathfindingAfterTransform.apply(this, arguments);
1268
+ }
1269
+ return updatePathfindingAfterTransform;
1270
+ }()
1271
+ /**
1272
+ * Dispose of pathfinding resources
1273
+ */
1274
+ )
1275
+ }, {
1276
+ key: "dispose",
1277
+ value: function dispose() {
1278
+ this.removeComputedObjects();
1279
+ this.pathfinder = null;
1280
+ this.crosscubeTextureSet = null;
1281
+ this.pathfinderVersionInfo = null;
1282
+ logger.info('PathfindingManager disposed');
1283
+ }
1284
+
1285
+ /**
1286
+ * Merges colinear segments in path data to optimize pipe creation
1287
+ * @param {Array} paths - Array of path objects from pathfinder
1288
+ * @param {Number} tolerance - Angular tolerance for considering segments colinear (default: ~0.57 degrees)
1289
+ * @returns {Array} Optimized paths with merged colinear segments
1290
+ */
1291
+ }, {
1292
+ key: "mergeColinearPaths",
1293
+ value: function mergeColinearPaths(paths) {
1294
+ var tolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.001;
1295
+ // Create a deep copy of paths to avoid modifying the original
1296
+ var optimizedPaths = JSON.parse(JSON.stringify(paths));
1297
+ optimizedPaths.forEach(function (pathData) {
1298
+ if (!pathData.path || pathData.path.length <= 2) {
1299
+ return; // Skip paths with 0-2 points (no optimization needed)
1300
+ }
1301
+
1302
+ // Convert path points to THREE.Vector3 objects for easier processing
1303
+ var originalPath = pathData.path.map(function (point) {
1304
+ if (point instanceof THREE.Vector3) {
1305
+ return point.clone();
1306
+ } else if (Array.isArray(point)) {
1307
+ return new THREE.Vector3().fromArray(point);
1308
+ } else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
1309
+ return new THREE.Vector3(point.x, point.y, point.z);
1310
+ } else {
1311
+ console.warn('Unknown point format:', point);
1312
+ return new THREE.Vector3(0, 0, 0);
1313
+ }
1314
+ });
1315
+ if (originalPath.length <= 2) {
1316
+ return; // Skip after conversion if still too few points
1317
+ }
1318
+ var newPath = [originalPath[0]]; // Start with the first point
1319
+
1320
+ // Iterate through segments starting from the first segment
1321
+ var i = 0;
1322
+ var _loop2 = function _loop2() {
1323
+ var segmentStart = originalPath[i];
1324
+ var segmentEnd = originalPath[i + 1];
1325
+
1326
+ // Calculate initial direction vector
1327
+ var currentDir = new THREE.Vector3().subVectors(segmentEnd, segmentStart);
1328
+ var initialLength = currentDir.length();
1329
+
1330
+ // Skip zero-length segments
1331
+ if (initialLength < 1e-6) {
1332
+ i++;
1333
+ return 1; // continue
1334
+ }
1335
+ currentDir.normalize();
1336
+
1337
+ // Look ahead to find all colinear points
1338
+ var j = i + 2;
1339
+ while (j < originalPath.length) {
1340
+ var nextPoint = originalPath[j];
1341
+
1342
+ // Check if the line from segmentStart to nextPoint is colinear with currentDir
1343
+ var testDir = new THREE.Vector3().subVectors(nextPoint, segmentStart);
1344
+ var testLength = testDir.length();
1345
+ if (testLength < 1e-6) {
1346
+ // Skip zero-length vectors
1347
+ j++;
1348
+ continue;
1349
+ }
1350
+ testDir.normalize();
1351
+
1352
+ // Check colinearity using dot product (should be very close to 1 for same direction)
1353
+ var dot = currentDir.dot(testDir);
1354
+ var isColinear = Math.abs(dot - 1) < tolerance;
1355
+ if (isColinear) {
1356
+ // Extend the segment to this point
1357
+ segmentEnd = nextPoint;
1358
+ j++;
1359
+ } else {
1360
+ // Not colinear, stop extending this segment
1361
+ break;
1362
+ }
1363
+ }
1364
+
1365
+ // Add the final point of this merged segment (unless it's the start point)
1366
+ if (!segmentEnd.equals(segmentStart)) {
1367
+ newPath.push(segmentEnd);
1368
+ }
1369
+
1370
+ // Move to the next unprocessed point
1371
+ // Find the index of segmentEnd in the original path
1372
+ var nextIndex = originalPath.findIndex(function (point, idx) {
1373
+ return idx > i && point.equals(segmentEnd);
1374
+ });
1375
+ if (nextIndex === -1) {
1376
+ // If we can't find it, just increment by 1 (fallback)
1377
+ i++;
1378
+ } else {
1379
+ i = nextIndex;
1380
+ }
1381
+ };
1382
+ while (i < originalPath.length - 1) {
1383
+ if (_loop2()) continue;
1384
+ }
1385
+
1386
+ // Convert back to the original format (arrays if input was arrays)
1387
+ var outputPath = newPath.map(function (point) {
1388
+ if (Array.isArray(pathData.path[0])) {
1389
+ return [point.x, point.y, point.z];
1390
+ } else if (pathData.path[0].x !== undefined) {
1391
+ return {
1392
+ x: point.x,
1393
+ y: point.y,
1394
+ z: point.z
1395
+ };
1396
+ } else {
1397
+ return point;
1398
+ }
1399
+ });
1400
+
1401
+ // Replace the original path with the optimized one
1402
+ pathData.path = outputPath;
1403
+
1404
+ // Log the optimization results
1405
+ var reduction = originalPath.length - newPath.length;
1406
+ if (reduction > 0) {
1407
+ console.log("\u2705 Optimized path ".concat(pathData.from, "-").concat(pathData.to, ": ") + "Reduced ".concat(originalPath.length, " points to ").concat(newPath.length, " ") + "(".concat(Math.round(reduction / originalPath.length * 100), "% reduction)"));
1408
+ } else {
1409
+ console.log("\u27A1\uFE0F Path ".concat(pathData.from, "-").concat(pathData.to, ": No optimization possible ") + "(".concat(originalPath.length, " points)"));
1410
+ }
1411
+ });
1412
+ return optimizedPaths;
1413
+ }
1414
+ }]);
1415
+ }();
1416
+
1417
+ export { PathfindingManager };