@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.
- package/dist/bundle/index.js +33146 -1
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +432 -1
- package/dist/cjs/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1448 -1
- package/dist/cjs/node_modules/three/examples/jsm/controls/OrbitControls.js +1853 -1
- package/dist/cjs/node_modules/three/examples/jsm/exporters/GLTFExporter.js +3537 -1
- package/dist/cjs/node_modules/three/examples/jsm/exporters/OBJExporter.js +305 -1
- package/dist/cjs/node_modules/three/examples/jsm/exporters/PLYExporter.js +542 -1
- package/dist/cjs/node_modules/three/examples/jsm/exporters/STLExporter.js +218 -1
- package/dist/cjs/node_modules/three/examples/jsm/loaders/DRACOLoader.js +683 -1
- package/dist/cjs/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4811 -1
- package/dist/cjs/node_modules/three/examples/jsm/loaders/RGBELoader.js +480 -1
- package/dist/cjs/node_modules/three/examples/jsm/renderers/CSS2DRenderer.js +309 -1
- package/dist/cjs/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +120 -1
- package/dist/cjs/src/analysis/analysis.js +560 -1
- package/dist/cjs/src/analysis/testing.js +958 -1
- package/dist/cjs/src/core/centralPlant.js +1149 -1
- package/dist/cjs/src/core/debugLogger.js +175 -1
- package/dist/cjs/src/core/mathUtils.js +574 -1
- package/dist/cjs/src/core/nameUtils.js +93 -1
- package/dist/cjs/src/data/export.js +716 -1
- package/dist/cjs/src/data/import.js +380 -1
- package/dist/cjs/src/data/numerics.js +522 -1
- package/dist/cjs/src/helpers/sceneHelper.js +572 -1
- package/dist/cjs/src/index.js +69 -1
- package/dist/cjs/src/managers/components/animationManager.js +123 -1
- package/dist/cjs/src/managers/components/componentManager.js +332 -1
- package/dist/cjs/src/managers/components/pathfindingManager.js +1441 -1
- package/dist/cjs/src/managers/controls/TransformControls.js +1063 -1
- package/dist/cjs/src/managers/controls/cameraControlsManager.js +79 -1
- package/dist/cjs/src/managers/controls/dragDropManager.js +1026 -1
- package/dist/cjs/src/managers/controls/keyboardControlsManager.js +395 -1
- package/dist/cjs/src/managers/controls/transformControlsManager.js +1807 -1
- package/dist/cjs/src/managers/environment/environmentManager.js +714 -1
- package/dist/cjs/src/managers/environment/textureConfig.js +229 -1
- package/dist/cjs/src/managers/scene/sceneExportManager.js +264 -1
- package/dist/cjs/src/managers/scene/sceneInitializationManager.js +346 -1
- package/dist/cjs/src/managers/scene/sceneOperationsManager.js +1509 -1
- package/dist/cjs/src/managers/scene/sceneTooltipsManager.js +661 -1
- package/dist/cjs/src/managers/system/disposalManager.js +444 -1
- package/dist/cjs/src/managers/system/hotReloadManager.js +291 -1
- package/dist/cjs/src/managers/system/performanceMonitor.js +863 -1
- package/dist/cjs/src/rendering/modelPreloader.js +369 -1
- package/dist/cjs/src/rendering/rendering2D.js +631 -1
- package/dist/cjs/src/rendering/rendering3D.js +685 -1
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +396 -1
- package/dist/esm/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1444 -1
- package/dist/esm/node_modules/three/examples/jsm/controls/OrbitControls.js +1849 -1
- package/dist/esm/node_modules/three/examples/jsm/exporters/GLTFExporter.js +3533 -1
- package/dist/esm/node_modules/three/examples/jsm/exporters/OBJExporter.js +301 -1
- package/dist/esm/node_modules/three/examples/jsm/exporters/PLYExporter.js +538 -1
- package/dist/esm/node_modules/three/examples/jsm/exporters/STLExporter.js +214 -1
- package/dist/esm/node_modules/three/examples/jsm/loaders/DRACOLoader.js +679 -1
- package/dist/esm/node_modules/three/examples/jsm/loaders/GLTFLoader.js +4807 -1
- package/dist/esm/node_modules/three/examples/jsm/loaders/RGBELoader.js +476 -1
- package/dist/esm/node_modules/three/examples/jsm/renderers/CSS2DRenderer.js +304 -1
- package/dist/esm/node_modules/three/examples/jsm/utils/BufferGeometryUtils.js +116 -1
- package/dist/esm/src/analysis/analysis.js +536 -1
- package/dist/esm/src/analysis/testing.js +954 -1
- package/dist/esm/src/core/centralPlant.js +1144 -1
- package/dist/esm/src/core/debugLogger.js +167 -1
- package/dist/esm/src/core/mathUtils.js +570 -1
- package/dist/esm/src/core/nameUtils.js +87 -1
- package/dist/esm/src/data/export.js +712 -1
- package/dist/esm/src/data/import.js +356 -1
- package/dist/esm/src/data/numerics.js +518 -1
- package/dist/esm/src/helpers/sceneHelper.js +547 -1
- package/dist/esm/src/index.js +35 -1
- package/dist/esm/src/managers/components/animationManager.js +119 -1
- package/dist/esm/src/managers/components/componentManager.js +328 -1
- package/dist/esm/src/managers/components/pathfindingManager.js +1417 -1
- package/dist/esm/src/managers/controls/TransformControls.js +1057 -1
- package/dist/esm/src/managers/controls/cameraControlsManager.js +75 -1
- package/dist/esm/src/managers/controls/dragDropManager.js +1002 -1
- package/dist/esm/src/managers/controls/keyboardControlsManager.js +371 -1
- package/dist/esm/src/managers/controls/transformControlsManager.js +1782 -1
- package/dist/esm/src/managers/environment/environmentManager.js +690 -1
- package/dist/esm/src/managers/environment/textureConfig.js +202 -1
- package/dist/esm/src/managers/scene/sceneExportManager.js +260 -1
- package/dist/esm/src/managers/scene/sceneInitializationManager.js +322 -1
- package/dist/esm/src/managers/scene/sceneOperationsManager.js +1485 -1
- package/dist/esm/src/managers/scene/sceneTooltipsManager.js +637 -1
- package/dist/esm/src/managers/system/disposalManager.js +440 -1
- package/dist/esm/src/managers/system/hotReloadManager.js +287 -1
- package/dist/esm/src/managers/system/performanceMonitor.js +858 -1
- package/dist/esm/src/rendering/modelPreloader.js +364 -1
- package/dist/esm/src/rendering/rendering2D.js +627 -1
- package/dist/esm/src/rendering/rendering3D.js +661 -1
- 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 };
|