@ray-js/robot-map-sdk 0.0.3-beta-9 → 0.0.3-beta-10

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 (31) hide show
  1. package/dist/application/MapApplication.js +1 -1
  2. package/dist/constant/methods.js +1 -1
  3. package/dist/index.d.ts +43 -1
  4. package/dist/index.rjs.js +1 -1
  5. package/dist/managers/MapManager.js +1 -1
  6. package/dist/utils/algorithm.js +1 -1
  7. package/dist-app/assets/{index-C3rjigWj.js → index-zPCor596.js} +1 -1
  8. package/dist-app/index.html +1 -1
  9. package/dist-docs/404.html +2 -2
  10. package/dist-docs/assets/{app.BGQfBD4o.js → app.CWzbsird.js} +1 -1
  11. package/dist-docs/assets/chunks/@localSearchIndexroot.DRAHC9Wk.js +1 -0
  12. package/dist-docs/assets/chunks/{VPLocalSearchBox.YvMlJA6m.js → VPLocalSearchBox.C1dzEhbA.js} +1 -1
  13. package/dist-docs/assets/chunks/{theme.1StzhkaW.js → theme.Dh1LIHtb.js} +2 -2
  14. package/dist-docs/assets/{guide_getting-started.md.D0sqgiqb.js → guide_getting-started.md.9TA9iDUN.js} +1 -1
  15. package/dist-docs/assets/{reference_methods.md.BkU-PXMt.js → reference_methods.md.B71e_LYO.js} +6 -3
  16. package/dist-docs/assets/{reference_methods.md.BkU-PXMt.lean.js → reference_methods.md.B71e_LYO.lean.js} +1 -1
  17. package/dist-docs/guide/advanced-usage.html +3 -3
  18. package/dist-docs/guide/concepts.html +3 -3
  19. package/dist-docs/guide/getting-started.html +5 -5
  20. package/dist-docs/hashmap.json +1 -1
  21. package/dist-docs/index.html +3 -3
  22. package/dist-docs/reference/callbacks.html +3 -3
  23. package/dist-docs/reference/config.html +3 -3
  24. package/dist-docs/reference/data.html +3 -3
  25. package/dist-docs/reference/methods.html +9 -6
  26. package/dist-docs/reference/runtime.html +3 -3
  27. package/dist-docs/reference/types.html +3 -3
  28. package/dist-docs/reference/utils.html +3 -3
  29. package/package.json +1 -1
  30. package/dist-docs/assets/chunks/@localSearchIndexroot.CSdgg9Q0.js +0 -1
  31. /package/dist-docs/assets/{guide_getting-started.md.D0sqgiqb.lean.js → guide_getting-started.md.9TA9iDUN.lean.js} +0 -0
@@ -1 +1 @@
1
- import{Application as e,isMobile as t,Assets as a}from"pixi.js";import{Interaction as n}from"./Interaction.js";import{merge as r}from"lodash-es";import{proxy as i}from"valtio/vanilla";import{MAIN_INSTANCE_KEY as s}from"../constant/index.js";import o from"mitt";import{Logger as c}from"../utils/logger.js";import{AppContext as h}from"./AppService.js";import{nanoid as d}from"nanoid/non-secure";import{calculateLineEndpoints as p}from"../utils/algorithm.js";import{ViewportContainer as m}from"./ViewportContainer.js";import{AppContainer as l}from"./AppContainer.js";import{MapManager as g}from"../managers/MapManager.js";import{PathManager as u}from"../managers/PathManager.js";import{HeatmapManager as w}from"../managers/HeatmapManager.js";import{ControlsManager as M}from"../managers/ControlsManager.js";import{DetectedObjectManager as y}from"../managers/DetectedObjectManager.js";import{CustomElementsManager as f}from"../managers/CustomElementsManager.js";import{RoomManager as x}from"../managers/RoomManager.js";import{getOptimalAntialiasingStrategy as S}from"../utils/browser.js";import{DEFAULT_CONFIG as b,DEFAULT_RUNTIME_CONFIG as v}from"../constant/config.js";class C extends e{mapState=null;components={};managers={};config=b;runtime;scaleMin=.5;scaleMax=5;events={};instanceKey;containerElement;emitter=o();tickerState={renderReasons:new Set,renderTimer:null};pendingAsyncRender=!1;isFirstMapDraw=!0;constructor(e=s){super(),this.instanceKey=e,h.registerInstance(e,this),globalThis.__PIXI_APP__=this}async initialize(e){return h.provideAsync(this,async()=>{const{resizeTo:a,events:n,config:o,runtime:c={},...h}=e;this.config=r(this.config,o??{}),this.runtime=i(Object.assign({},v,c));const d=this.instanceKey===s;this.containerElement=a;const p=d?{textureGCMaxIdle:t.any?180:3600,textureGCCheckCountMax:t.any?100:50,autoStart:!1,eventFeatures:{move:!0,globalMove:!1,click:!0,wheel:!0}}:{textureGCMaxIdle:60,textureGCCheckCountMax:10,autoStart:!1,eventFeatures:{move:!1,globalMove:!1,click:!1,wheel:!1}};await this.init({resizeTo:d?a:void 0,preferWebGLVersion:2,resolution:window.devicePixelRatio||1,antialias:S(),autoDensity:!0,backgroundColor:this.config.global.backgroundColor,...p,...h}),this.preloadAssets(),this.scaleMax=this.config.interaction.zoomRange.max,this.scaleMin=this.config.interaction.zoomRange.min,this.events=n,this.initializeViewportContainer(),this.initializeInteraction(),this.initializeAppContainer(),this.managers.mapManager=new g,this.managers.heatmapManager=new w,this.managers.pathManager=new u,this.managers.controlsManager=new M,this.managers.detectedObjectManager=new y,this.managers.customElementsManager=new f,this.managers.roomsManager=new x,document.addEventListener("visibilitychange",this.onVisibilityChange)})}async drawMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawMap",e);const{size:t,resolution:a,origin:n}=e;n[0]===this.mapState?.origin.x&&n[1]===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(...n),this.managers.controlsManager.updatePositionByOrigin(...n),this.managers.detectedObjectManager.updatePositionByOrigin(...n),this.managers.customElementsManager.updatePositionByOrigin(...n)),this.mapState={id:e.id,status:1===e.status,origin:{x:n[0],y:n[1]},charger:{x:e.charger.coordinate[0],y:e.charger.coordinate[1]},chargerDirection:e.charger.angle??0,resolution:a,width:t[0],height:t[1]},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawMap(e),this.renderOnce()})}async drawRasterMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawRasterMap",e);const{mapHeader:t,mapData:a}=e,{originX:n,originY:r}=t;n===this.mapState?.origin.x&&r===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(n,r),this.managers.controlsManager.updatePositionByOrigin(n,r),this.managers.detectedObjectManager.updatePositionByOrigin(n,r),this.managers.customElementsManager.updatePositionByOrigin(n,r)),this.mapState={id:t.id,status:t.mapStable,origin:{x:n,y:r},charger:{x:t.chargeX,y:t.chargeY},chargerDirection:t.chargeDirection??0,resolution:100*t.mapResolution,width:t.mapWidth,height:t.mapHeight,version:t.version},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawRasterMap(a.parsed,this.mapState),this.renderOnce()})}drawPath(e){return h.provide(this,()=>{c.log("[Path] drawPath",e),this.events?.onPathDrawed?.({id:e.pathHeader.pathId,type:e.pathHeader.type,direction:e.pathHeader.direction,count:e.pathHeader.count,initFlag:e.pathHeader.initFlag,robotPosition:e.pathPoints[e.pathPoints.length-1]??null}),this.managers.pathManager.draw(e),this.renderOnce()})}async drawRoomProperty(e){return h.provide(this,()=>{c.log("[Room] drawRoomProperty",e),this.events?.onRoomPropertiesDrawed?.(e),this.managers.roomsManager.drawRoomProperty(e),this.renderOnceNextFrame()})}drawHeatmap({mapData:e,heatmapPoints:t,useGradient:a=!0}){return h.provide(this,()=>{c.log("[Heatmap] drawHeatmap",t),this.managers.heatmapManager.draw({mapData:e,heatmapPoints:t,useGradient:a}),this.renderOnce()})}drawForbiddenSweepZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenSweepZones",e),this.managers.controlsManager.drawForbiddenSweepZones(e),this.renderOnceNextFrame()})}drawForbiddenMopZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenMopZones",e),this.managers.controlsManager.drawForbiddenMopZones(e),this.renderOnceNextFrame()})}drawCleanZones(e){return h.provide(this,()=>{c.log("[Controls] drawCleanZones",e),this.managers.controlsManager.drawCleanZones(e),this.renderOnceNextFrame()})}drawVirtualWalls(e){return h.provide(this,()=>{c.log("[Controls] drawVirtualWalls",e),this.managers.controlsManager.drawVirtualWalls(e),this.renderOnceNextFrame()})}drawSpots(e){return h.provide(this,()=>{c.log("[Controls] drawSpots",e),this.managers.controlsManager.drawSpots(e),this.renderOnceNextFrame()})}async drawDetectedObjects(e){return h.provideAsync(this,async()=>{c.log("[DetectedObject] drawDetectedObjects",e),await this.managers.detectedObjectManager.drawDetectedObjects(e),this.renderOnceNextFrame()})}async drawCustomElements(e){return h.provideAsync(this,async()=>{c.log("[CustomElements] drawCustomElements",e),await this.managers.customElementsManager.drawCustomElements(e),this.renderOnceNextFrame()})}getForbiddenSweepZones(){return this.managers.controlsManager.getForbiddenSweepZones()}getForbiddenMopZones(){return this.managers.controlsManager.getForbiddenMopZones()}getCleanZones(){return this.managers.controlsManager.getCleanZones()}getVirtualWalls(){return this.managers.controlsManager.getVirtualWalls()}getSpots(){return this.managers.controlsManager.getSpots()}getEffectiveDividerPoints(){return this.managers.controlsManager.getEffectiveDividerPoints()}getDividerEndPoints(){return this.managers.controlsManager.getDividerEndPoints()}resetPanZoom(){this.components.interaction.setPanZoom()}fitMapToView(e,t=!1){return h.provide(this,()=>{if(!e||e.minX===e.maxX||e.minY===e.maxY)return void c.warn("地图边界无效,无法自动适配视图");const a=this.config.map.autoPaddingPercent||.1,n=this.getViewportBounds(),r=e.maxX-e.minX,i=e.maxY-e.minY,s=n.width,o=n.height,h=s*(1-2*a)/r,d=o*(1-2*a)/i,p=Math.min(h,d),m=Math.max(this.config.interaction.fitMinScale,this.scaleMin),l=Math.min(this.config.interaction.fitMaxScale,this.scaleMax),g=Math.max(m,Math.min(l,p)),u=s/2-(e.minX+r/2)*g,w=o/2-(e.minY+i/2)*g;this.components.interaction.setPanZoom({targetPosition:{x:u,y:w},targetScale:{x:g,y:g},setCenter:!0,setScale:!0},t)})}getViewportBounds(){return this.components.viewportContainer?.getViewportBounds()||{x:0,y:0,width:this.renderer.width,height:this.renderer.height}}updateRuntime(e){Object.assign(this.runtime,e),this.renderOnceNextFrame()}metersToPixels(e){return this.mapState?.resolution?e*(1/(this.mapState.resolution/100)):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),20*e)}pixelsToMeters(e){return this.mapState?.resolution?e*(this.mapState.resolution/100):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),.05*e)}toFixedSize(e,t){return e/(t??this.components.appContainer.scale.x)}fromFixedSize(e,t){return e*(t??this.components.appContainer.scale.x)}getViewportCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate center point"),null;const e=this.getViewportBounds(),t=e.x+e.width/2,a=e.y+e.height/2,n=this.components.appContainer,r=n.scale.x,i=(t-n.x)/r,s=(a-n.y)/r;return{x:i-this.mapState.origin.x,y:s-this.mapState.origin.y}}getMapCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate map center point"),null;const e=this.managers.mapManager.mapBounds;if(e.minX===1/0||e.minY===1/0||e.maxX===-1/0||e.maxY===-1/0)return c.warn("Invalid map bounds, cannot calculate map center point"),null;const t=(e.minX+e.maxX)/2,a=(e.minY+e.maxY)/2;return{x:t-this.mapState.origin.x,y:a-this.mapState.origin.y}}getWallPointsByViewportCenter(e){const{width:t=this.config.controls.virtualWall.minWidth,direction:a="horizontal",offsetX:n=0,offsetY:r=0}=e||{},i=this.getViewportCenterPoint()||{x:0,y:0},s=this.metersToPixels(t);return p(i.x,i.y,s,a).map(e=>({x:e.x+n,y:e.y+r}))}getForbiddenSweepZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenSweepZone,{size:a=t.minSize,offsetX:n=0,offsetY:r=0}=e||{};return this.generateZonePoints(a,n,r)}getForbiddenMopZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenMopZone,{size:a=t.minSize,offsetX:n=0,offsetY:r=0}=e||{};return this.generateZonePoints(a,n,r)}getCleanZonePointsByViewportCenter(e){const t=this.config.controls.cleanZone,{size:a=t.minSize,offsetX:n=0,offsetY:r=0}=e||{};return this.generateZonePoints(a,n,r)}getSpotPointByViewportCenter(e){const{offsetX:t=0,offsetY:a=0}=e||{},n=this.getViewportCenterPoint()||{x:0,y:0};return{x:n.x+t,y:n.y+a}}async snapshot(){this.render(),await new Promise(e=>setTimeout(e,0));const{snapshot:e}=this.config;return await this.renderer.extract.base64({target:this.components.appContainer,format:e.format,quality:e.quality,resolution:e.resolution,antialias:e.antialias})}async snapshotByData({map:e,path:t,roomProperties:a,customElements:n,forbiddenSweepZones:r,forbiddenMopZones:i,virtualWalls:s,detectedObjects:o},h={}){const p=`SNAPSHOT_${d()}`;c.log(`[MapApplication] ${p} snapshot start`);const m=new C(p);try{if(await m.initialize({config:this.config,runtime:h}),!e)throw new Error("Map data is required");if(e.startsWith("7b22")){const{decodeMapStructured:t}=await import("@ray-js/robot-protocol"),a=t(e);await m.drawMap(a)}else{const{decodeMap:t}=await import("@ray-js/robot-protocol"),a=t(e);if(!a)throw new Error("Failed to decode raster map data");await m.drawRasterMap(a)}if(t){const{decodePath:e}=await import("@ray-js/robot-protocol"),a=e(t);m.drawPath(a)}a&&a.length>0&&m.drawRoomProperty(a),r&&r.length>0&&m.drawForbiddenSweepZones(r),i&&i.length>0&&m.drawForbiddenMopZones(i),s&&s.length>0&&m.drawVirtualWalls(s),o&&o.length>0&&await m.drawDetectedObjects(o),n&&n.length>0&&await m.drawCustomElements(n);const d=await m.snapshot();return c.log(`[MapApplication] ${p} snapshot completed successfully`),d}catch(e){throw c.error(`[MapApplication] ${p} snapshot other map failed:`,e),e}finally{c.log(`[MapApplication] ${p} destroy`),m.destroy()}}renderOnce(){c.log("[Pixi] renderOnce"),this.render()}renderOnceNextFrame(){this.pendingAsyncRender||(this.pendingAsyncRender=!0,requestAnimationFrame(()=>{c.log("[Pixi] renderOnceNextFrame"),this.render(),this.pendingAsyncRender=!1}))}requestRender(e,t=!1){t?(this.tickerState.renderReasons.add(e),this.ticker.started||(c.debug(`🎬 [Ticker] START: ${e}`),this.ticker.start())):this.renderOnceNextFrame()}stopRender(e){this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&this.scheduleStopRender("final",100)}destroy(){h.unregisterInstance(this.instanceKey),this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderReasons.clear(),this.emitter.all.clear(),document.removeEventListener("visibilitychange",this.onVisibilityChange),this.managers.pathManager.destroy(),this.managers.mapManager.destroy(),this.managers.controlsManager.destroy(),this.managers.detectedObjectManager.destroy(),this.managers.customElementsManager.destroy(),this.managers.roomsManager.destroy(),this.components.interaction.destroy(),this.components.viewportContainer.destroy(),this.components.appContainer.destroy(),super.destroy()}initializeViewportContainer(){this.components.viewportContainer=new m(this.config,this.containerElement),this.stage.addChild(this.components.viewportContainer)}initializeAppContainer(){this.components.appContainer=new l,this.components.interaction.addChild(this.components.appContainer)}initializeInteraction(){this.components.interaction=new n,this.components.viewportContainer.addChild(this.components.interaction)}scheduleStopRender(e,t){this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderTimer=setTimeout(()=>{this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&(c.debug("⏸️ [Ticker] STOP"),this.ticker.stop())},t)}generateZonePoints(e,t,a){const n=this.getViewportCenterPoint()||{x:0,y:0},r=this.metersToPixels(e)/2,i=n.x+t,s=n.y+a;return[{x:i-r,y:s-r},{x:i+r,y:s-r},{x:i+r,y:s+r},{x:i-r,y:s+r}]}preloadAssets(){const e=this.config.robot.icon.src,t=this.config.chargingStation.icon.src,n=[];a.add({alias:"robot",src:e}),n.push("robot"),a.add({alias:"chargingStation",src:t}),n.push("chargingStation"),a.add({alias:"deleteIcon",src:this.config.controls.deleteIconSrc}),n.push("deleteIcon"),a.add({alias:"rotateIcon",src:this.config.controls.rotateIconSrc}),n.push("rotateIcon"),a.add({alias:"scaleIcon",src:this.config.controls.scaleIconSrc}),n.push("scaleIcon"),a.add({alias:"moveIcon",src:this.config.controls.moveIconSrc}),n.push("moveIcon"),a.add({alias:"checkmark",src:this.config.room.selectionIndicator.iconSrc}),n.push("checkmark"),a.add({alias:"spotIcon",src:this.config.controls.spot.iconSrc}),n.push("spotIcon"),this.config.room.property.cleanMode.assets.forEach((e,t)=>{const r=`cleanMode_${t}`;a.add({alias:r,src:e}),n.push(r)}),this.config.room.property.suction.assets.forEach((e,t)=>{const r=`fan_${t}`;a.add({alias:r,src:e}),n.push(r)}),this.config.room.property.cistern.assets.forEach((e,t)=>{const r=`water_${t}`;a.add({alias:r,src:e}),n.push(r)}),this.config.room.property.cleanTimes.assets.forEach((e,t)=>{const r=`cleanTimes${t+1}`;a.add({alias:r,src:e}),n.push(r)}),a.backgroundLoad(n)}onVisibilityChange=()=>{"visible"===document.visibilityState||this.components.interaction?.clearTouches()}}export{C as MapApplication};
1
+ import{Application as e,isMobile as t,Assets as n}from"pixi.js";import{Interaction as a}from"./Interaction.js";import{merge as r}from"lodash-es";import{proxy as i}from"valtio/vanilla";import{MAIN_INSTANCE_KEY as o}from"../constant/index.js";import s from"mitt";import{Logger as c}from"../utils/logger.js";import{AppContext as h}from"./AppService.js";import{nanoid as d}from"nanoid/non-secure";import{calculateLineEndpoints as p,areStructuredRoomsAdjacent as m,areMultipleRoomsConnected as l,areRasterRoomsAdjacent as g}from"../utils/algorithm.js";import{ViewportContainer as u}from"./ViewportContainer.js";import{AppContainer as w}from"./AppContainer.js";import{MapManager as f}from"../managers/MapManager.js";import{PathManager as M}from"../managers/PathManager.js";import{HeatmapManager as y}from"../managers/HeatmapManager.js";import{ControlsManager as x}from"../managers/ControlsManager.js";import{DetectedObjectManager as S}from"../managers/DetectedObjectManager.js";import{CustomElementsManager as v}from"../managers/CustomElementsManager.js";import{RoomManager as b}from"../managers/RoomManager.js";import{getOptimalAntialiasingStrategy as P}from"../utils/browser.js";import{DEFAULT_CONFIG as C,DEFAULT_RUNTIME_CONFIG as R}from"../constant/config.js";class O extends e{mapState=null;components={};managers={};config=C;runtime;scaleMin=.5;scaleMax=5;events={};instanceKey;containerElement;emitter=s();tickerState={renderReasons:new Set,renderTimer:null};pendingAsyncRender=!1;isFirstMapDraw=!0;constructor(e=o){super(),this.instanceKey=e,h.registerInstance(e,this),globalThis.__PIXI_APP__=this}async initialize(e){return h.provideAsync(this,async()=>{const{resizeTo:n,events:a,config:s,runtime:c={},...h}=e;this.config=r(this.config,s??{}),this.runtime=i(Object.assign({},R,c));const d=this.instanceKey===o;this.containerElement=n;const p=d?{textureGCMaxIdle:t.any?180:3600,textureGCCheckCountMax:t.any?100:50,autoStart:!1,eventFeatures:{move:!0,globalMove:!1,click:!0,wheel:!0}}:{textureGCMaxIdle:60,textureGCCheckCountMax:10,autoStart:!1,eventFeatures:{move:!1,globalMove:!1,click:!1,wheel:!1}};await this.init({resizeTo:d?n:void 0,preferWebGLVersion:2,resolution:window.devicePixelRatio||1,antialias:P(),autoDensity:!0,backgroundColor:this.config.global.backgroundColor,...p,...h}),this.preloadAssets(),this.scaleMax=this.config.interaction.zoomRange.max,this.scaleMin=this.config.interaction.zoomRange.min,this.events=a,this.initializeViewportContainer(),this.initializeInteraction(),this.initializeAppContainer(),this.managers.mapManager=new f,this.managers.heatmapManager=new y,this.managers.pathManager=new M,this.managers.controlsManager=new x,this.managers.detectedObjectManager=new S,this.managers.customElementsManager=new v,this.managers.roomsManager=new b,document.addEventListener("visibilitychange",this.onVisibilityChange)})}async drawMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawMap",e);const{size:t,resolution:n,origin:a}=e;a[0]===this.mapState?.origin.x&&a[1]===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(...a),this.managers.controlsManager.updatePositionByOrigin(...a),this.managers.detectedObjectManager.updatePositionByOrigin(...a),this.managers.customElementsManager.updatePositionByOrigin(...a)),this.mapState={id:e.id,status:1===e.status,origin:{x:a[0],y:a[1]},charger:{x:e.charger.coordinate[0],y:e.charger.coordinate[1]},chargerDirection:e.charger.angle??0,resolution:n,width:t[0],height:t[1]},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawMap(e),this.renderOnce()})}async drawRasterMap(e){return h.provideAsync(this,async()=>{c.log("[Map] drawRasterMap",e);const{mapHeader:t,mapData:n}=e,{originX:a,originY:r}=t;a===this.mapState?.origin.x&&r===this.mapState?.origin.y||(this.managers.pathManager.updatePositionByOrigin(a,r),this.managers.controlsManager.updatePositionByOrigin(a,r),this.managers.detectedObjectManager.updatePositionByOrigin(a,r),this.managers.customElementsManager.updatePositionByOrigin(a,r)),this.mapState={id:t.id,status:t.mapStable,origin:{x:a,y:r},charger:{x:t.chargeX,y:t.chargeY},chargerDirection:t.chargeDirection??0,resolution:100*t.mapResolution,width:t.mapWidth,height:t.mapHeight,version:t.version},this.isFirstMapDraw&&(this.isFirstMapDraw=!1,this.events?.onMapFirstDrawed?.(this.mapState)),this.events?.onMapDrawed?.(this.mapState),await this.managers.mapManager.drawRasterMap(n.parsed,this.mapState),this.renderOnce()})}drawPath(e){return h.provide(this,()=>{c.log("[Path] drawPath",e),this.events?.onPathDrawed?.({id:e.pathHeader.pathId,type:e.pathHeader.type,direction:e.pathHeader.direction,count:e.pathHeader.count,initFlag:e.pathHeader.initFlag,robotPosition:e.pathPoints[e.pathPoints.length-1]??null}),this.managers.pathManager.draw(e),this.renderOnce()})}async drawRoomProperty(e){return h.provide(this,()=>{c.log("[Room] drawRoomProperty",e),this.events?.onRoomPropertiesDrawed?.(e),this.managers.roomsManager.drawRoomProperty(e),this.renderOnceNextFrame()})}drawHeatmap({mapData:e,heatmapPoints:t,useGradient:n=!0}){return h.provide(this,()=>{c.log("[Heatmap] drawHeatmap",t),this.managers.heatmapManager.draw({mapData:e,heatmapPoints:t,useGradient:n}),this.renderOnce()})}drawForbiddenSweepZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenSweepZones",e),this.managers.controlsManager.drawForbiddenSweepZones(e),this.renderOnceNextFrame()})}drawForbiddenMopZones(e){return h.provide(this,()=>{c.log("[Controls] drawForbiddenMopZones",e),this.managers.controlsManager.drawForbiddenMopZones(e),this.renderOnceNextFrame()})}drawCleanZones(e){return h.provide(this,()=>{c.log("[Controls] drawCleanZones",e),this.managers.controlsManager.drawCleanZones(e),this.renderOnceNextFrame()})}drawVirtualWalls(e){return h.provide(this,()=>{c.log("[Controls] drawVirtualWalls",e),this.managers.controlsManager.drawVirtualWalls(e),this.renderOnceNextFrame()})}drawSpots(e){return h.provide(this,()=>{c.log("[Controls] drawSpots",e),this.managers.controlsManager.drawSpots(e),this.renderOnceNextFrame()})}async drawDetectedObjects(e){return h.provideAsync(this,async()=>{c.log("[DetectedObject] drawDetectedObjects",e),await this.managers.detectedObjectManager.drawDetectedObjects(e),this.renderOnceNextFrame()})}async drawCustomElements(e){return h.provideAsync(this,async()=>{c.log("[CustomElements] drawCustomElements",e),await this.managers.customElementsManager.drawCustomElements(e),this.renderOnceNextFrame()})}getForbiddenSweepZones(){return this.managers.controlsManager.getForbiddenSweepZones()}getForbiddenMopZones(){return this.managers.controlsManager.getForbiddenMopZones()}getCleanZones(){return this.managers.controlsManager.getCleanZones()}getVirtualWalls(){return this.managers.controlsManager.getVirtualWalls()}getSpots(){return this.managers.controlsManager.getSpots()}getEffectiveDividerPoints(){return this.managers.controlsManager.getEffectiveDividerPoints()}getDividerEndPoints(){return this.managers.controlsManager.getDividerEndPoints()}resetPanZoom(){this.components.interaction.setPanZoom()}fitMapToView(e,t=!1){return h.provide(this,()=>{if(!e||e.minX===e.maxX||e.minY===e.maxY)return void c.warn("地图边界无效,无法自动适配视图");const n=this.config.map.autoPaddingPercent||.1,a=this.getViewportBounds(),r=e.maxX-e.minX,i=e.maxY-e.minY,o=a.width,s=a.height,h=o*(1-2*n)/r,d=s*(1-2*n)/i,p=Math.min(h,d),m=Math.max(this.config.interaction.fitMinScale,this.scaleMin),l=Math.min(this.config.interaction.fitMaxScale,this.scaleMax),g=Math.max(m,Math.min(l,p)),u=o/2-(e.minX+r/2)*g,w=s/2-(e.minY+i/2)*g;this.components.interaction.setPanZoom({targetPosition:{x:u,y:w},targetScale:{x:g,y:g},setCenter:!0,setScale:!0},t)})}getViewportBounds(){return this.components.viewportContainer?.getViewportBounds()||{x:0,y:0,width:this.renderer.width,height:this.renderer.height}}updateRuntime(e){Object.assign(this.runtime,e),this.renderOnceNextFrame()}metersToPixels(e){return this.mapState?.resolution?e*(1/(this.mapState.resolution/100)):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),20*e)}pixelsToMeters(e){return this.mapState?.resolution?e*(this.mapState.resolution/100):(c.warn("Map resolution not available, using default resolution (5cm/pixel)"),.05*e)}toFixedSize(e,t){return e/(t??this.components.appContainer.scale.x)}fromFixedSize(e,t){return e*(t??this.components.appContainer.scale.x)}getViewportCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate center point"),null;const e=this.getViewportBounds(),t=e.x+e.width/2,n=e.y+e.height/2,a=this.components.appContainer,r=a.scale.x,i=(t-a.x)/r,o=(n-a.y)/r;return{x:i-this.mapState.origin.x,y:o-this.mapState.origin.y}}getMapCenterPoint(){if(!this.mapState)return c.warn("Map state not available, cannot calculate map center point"),null;const e=this.managers.mapManager.mapBounds;if(e.minX===1/0||e.minY===1/0||e.maxX===-1/0||e.maxY===-1/0)return c.warn("Invalid map bounds, cannot calculate map center point"),null;const t=(e.minX+e.maxX)/2,n=(e.minY+e.maxY)/2;return{x:t-this.mapState.origin.x,y:n-this.mapState.origin.y}}getWallPointsByViewportCenter(e){const{width:t=this.config.controls.virtualWall.minWidth,direction:n="horizontal",offsetX:a=0,offsetY:r=0}=e||{},i=this.getViewportCenterPoint()||{x:0,y:0},o=this.metersToPixels(t);return p(i.x,i.y,o,n).map(e=>({x:e.x+a,y:e.y+r}))}getForbiddenSweepZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenSweepZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getForbiddenMopZonePointsByViewportCenter(e){const t=this.config.controls.forbiddenMopZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getCleanZonePointsByViewportCenter(e){const t=this.config.controls.cleanZone,{size:n=t.minSize,offsetX:a=0,offsetY:r=0}=e||{};return this.generateZonePoints(n,a,r)}getSpotPointByViewportCenter(e){const{offsetX:t=0,offsetY:n=0}=e||{},a=this.getViewportCenterPoint()||{x:0,y:0};return{x:a.x+t,y:a.y+n}}areRoomsAdjacent(e,t=3){return h.provide(this,()=>{if(!e||0===e.length)return c.warn("[Room] No room IDs provided"),!1;if(1===e.length)return!0;const n=Array.from(new Set(e));return 1===n.length||(void 0!==this.mapState?.version?this.areRasterRoomsAdjacentInternal(n,t):this.areStructuredRoomsAdjacentInternal(n,t))})}areStructuredRoomsAdjacentInternal(e,t){const n=[];for(const t of e){const e=this.managers.mapManager.getRoomById(t);if(!e)return c.warn(`[Room] Room ${t} not found in map`),!1;if(!e.outlinePoints||0===e.outlinePoints.length)return c.warn(`[Room] Room ${t} has no outline points`),!1;n.push({id:t,points:e.outlinePoints})}const a=[];for(let e=0;e<n.length;e++)for(let r=e+1;r<n.length;r++){const i=n[e],o=n[r];m(i.points,o.points,t)&&a.push([e,r])}return l(n.length,a)}areRasterRoomsAdjacentInternal(e,t){if(!this.mapState)return c.warn("[Room] Map state not available"),!1;const n=this.mapState.width,a=[];for(const t of e){const e=this.managers.mapManager.getRasterRoomPixels(t);if(!e)return c.warn(`[Room] Room ${t} pixel data not found in raster map`),!1;a.push({id:t,pixels:e})}const r=[];for(let e=0;e<a.length;e++)for(let i=e+1;i<a.length;i++){const o=a[e],s=a[i];g(o.pixels,s.pixels,n,t)&&r.push([e,i])}return l(a.length,r)}async snapshot(){this.render(),await new Promise(e=>setTimeout(e,0));const{snapshot:e}=this.config;return await this.renderer.extract.base64({target:this.components.appContainer,format:e.format,quality:e.quality,resolution:e.resolution,antialias:e.antialias})}async snapshotByData({map:e,path:t,roomProperties:n,customElements:a,forbiddenSweepZones:r,forbiddenMopZones:i,virtualWalls:o,detectedObjects:s},h={}){const p=`SNAPSHOT_${d()}`;c.log(`[MapApplication] ${p} snapshot start`);const m=new O(p);try{if(await m.initialize({config:this.config,runtime:h}),!e)throw new Error("Map data is required");if(e.startsWith("7b22")){const{decodeMapStructured:t}=await import("@ray-js/robot-protocol"),n=t(e);await m.drawMap(n)}else{const{decodeMap:t}=await import("@ray-js/robot-protocol"),n=t(e);if(!n)throw new Error("Failed to decode raster map data");await m.drawRasterMap(n)}if(t){const{decodePath:e}=await import("@ray-js/robot-protocol"),n=e(t);m.drawPath(n)}n&&n.length>0&&m.drawRoomProperty(n),r&&r.length>0&&m.drawForbiddenSweepZones(r),i&&i.length>0&&m.drawForbiddenMopZones(i),o&&o.length>0&&m.drawVirtualWalls(o),s&&s.length>0&&await m.drawDetectedObjects(s),a&&a.length>0&&await m.drawCustomElements(a);const d=await m.snapshot();return c.log(`[MapApplication] ${p} snapshot completed successfully`),d}catch(e){throw c.error(`[MapApplication] ${p} snapshot other map failed:`,e),e}finally{c.log(`[MapApplication] ${p} destroy`),m.destroy()}}renderOnce(){c.log("[Pixi] renderOnce"),this.render()}renderOnceNextFrame(){this.pendingAsyncRender||(this.pendingAsyncRender=!0,requestAnimationFrame(()=>{c.log("[Pixi] renderOnceNextFrame"),this.render(),this.pendingAsyncRender=!1}))}requestRender(e,t=!1){t?(this.tickerState.renderReasons.add(e),this.ticker.started||(c.debug(`🎬 [Ticker] START: ${e}`),this.ticker.start())):this.renderOnceNextFrame()}stopRender(e){this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&this.scheduleStopRender("final",100)}destroy(){h.unregisterInstance(this.instanceKey),this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderReasons.clear(),this.emitter.all.clear(),document.removeEventListener("visibilitychange",this.onVisibilityChange),this.managers.pathManager.destroy(),this.managers.mapManager.destroy(),this.managers.controlsManager.destroy(),this.managers.detectedObjectManager.destroy(),this.managers.customElementsManager.destroy(),this.managers.roomsManager.destroy(),this.components.interaction.destroy(),this.components.viewportContainer.destroy(),this.components.appContainer.destroy(),super.destroy()}initializeViewportContainer(){this.components.viewportContainer=new u(this.config,this.containerElement),this.stage.addChild(this.components.viewportContainer)}initializeAppContainer(){this.components.appContainer=new w,this.components.interaction.addChild(this.components.appContainer)}initializeInteraction(){this.components.interaction=new a,this.components.viewportContainer.addChild(this.components.interaction)}scheduleStopRender(e,t){this.tickerState.renderTimer&&clearTimeout(this.tickerState.renderTimer),this.tickerState.renderTimer=setTimeout(()=>{this.tickerState.renderReasons.delete(e),0===this.tickerState.renderReasons.size&&(c.debug("⏸️ [Ticker] STOP"),this.ticker.stop())},t)}generateZonePoints(e,t,n){const a=this.getViewportCenterPoint()||{x:0,y:0},r=this.metersToPixels(e)/2,i=a.x+t,o=a.y+n;return[{x:i-r,y:o-r},{x:i+r,y:o-r},{x:i+r,y:o+r},{x:i-r,y:o+r}]}preloadAssets(){const e=this.config.robot.icon.src,t=this.config.chargingStation.icon.src,a=[];n.add({alias:"robot",src:e}),a.push("robot"),n.add({alias:"chargingStation",src:t}),a.push("chargingStation"),n.add({alias:"deleteIcon",src:this.config.controls.deleteIconSrc}),a.push("deleteIcon"),n.add({alias:"rotateIcon",src:this.config.controls.rotateIconSrc}),a.push("rotateIcon"),n.add({alias:"scaleIcon",src:this.config.controls.scaleIconSrc}),a.push("scaleIcon"),n.add({alias:"moveIcon",src:this.config.controls.moveIconSrc}),a.push("moveIcon"),n.add({alias:"checkmark",src:this.config.room.selectionIndicator.iconSrc}),a.push("checkmark"),n.add({alias:"spotIcon",src:this.config.controls.spot.iconSrc}),a.push("spotIcon"),this.config.room.property.cleanMode.assets.forEach((e,t)=>{const r=`cleanMode_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.suction.assets.forEach((e,t)=>{const r=`fan_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cistern.assets.forEach((e,t)=>{const r=`water_${t}`;n.add({alias:r,src:e}),a.push(r)}),this.config.room.property.cleanTimes.assets.forEach((e,t)=>{const r=`cleanTimes${t+1}`;n.add({alias:r,src:e}),a.push(r)}),n.backgroundLoad(a)}onVisibilityChange=()=>{"visible"===document.visibilityState||this.components.interaction?.clearTouches()}}export{O as MapApplication};
@@ -1 +1 @@
1
- const e=["resetPanZoom","getForbiddenSweepZones","getForbiddenMopZones","getCleanZones","getVirtualWalls","getSpots","getViewportCenterPoint","getMapCenterPoint","getWallPointsByViewportCenter","getForbiddenSweepZonePointsByViewportCenter","getForbiddenMopZonePointsByViewportCenter","getCleanZonePointsByViewportCenter","getSpotPointByViewportCenter","getEffectiveDividerPoints","getDividerEndPoints","snapshot","snapshotByData"],o=["onMapFirstDrawed","onMapDrawed","onPathDrawed","onRoomPropertiesDrawed","onClickRoom","onClickRoomProperties","onRemoveForbiddenSweepZone","onRemoveForbiddenMopZone","onRemoveCleanZone","onRemoveVirtualWall","onUpdateForbiddenSweepZone","onUpdateForbiddenMopZone","onUpdateCleanZone","onUpdateVirtualWall","onUpdateSpot","onUpdateDivider","onClickForbiddenSweepZone","onClickForbiddenMopZone","onClickCleanZone","onClickVirtualWall","onClickSpot","onClickDetectedObject","onClickCustomElement"];export{e as MAP_API_METHODS,o as MAP_CALLBACK_METHODS};
1
+ const e=["areRoomsAdjacent","resetPanZoom","getForbiddenSweepZones","getForbiddenMopZones","getCleanZones","getVirtualWalls","getSpots","getViewportCenterPoint","getMapCenterPoint","getWallPointsByViewportCenter","getForbiddenSweepZonePointsByViewportCenter","getForbiddenMopZonePointsByViewportCenter","getCleanZonePointsByViewportCenter","getSpotPointByViewportCenter","getEffectiveDividerPoints","getDividerEndPoints","snapshot","snapshotByData"],o=["onMapFirstDrawed","onMapDrawed","onPathDrawed","onRoomPropertiesDrawed","onClickRoom","onClickRoomProperties","onRemoveForbiddenSweepZone","onRemoveForbiddenMopZone","onRemoveCleanZone","onRemoveVirtualWall","onUpdateForbiddenSweepZone","onUpdateForbiddenMopZone","onUpdateCleanZone","onUpdateVirtualWall","onUpdateSpot","onUpdateDivider","onClickForbiddenSweepZone","onClickForbiddenMopZone","onClickCleanZone","onClickVirtualWall","onClickSpot","onClickDetectedObject","onClickCustomElement"];export{e as MAP_API_METHODS,o as MAP_CALLBACK_METHODS};
package/dist/index.d.ts CHANGED
@@ -1727,7 +1727,7 @@ declare type Managers = {
1727
1727
  roomsManager: RoomManager;
1728
1728
  };
1729
1729
 
1730
- export declare const MAP_API_METHODS: readonly ["resetPanZoom", "getForbiddenSweepZones", "getForbiddenMopZones", "getCleanZones", "getVirtualWalls", "getSpots", "getViewportCenterPoint", "getMapCenterPoint", "getWallPointsByViewportCenter", "getForbiddenSweepZonePointsByViewportCenter", "getForbiddenMopZonePointsByViewportCenter", "getCleanZonePointsByViewportCenter", "getSpotPointByViewportCenter", "getEffectiveDividerPoints", "getDividerEndPoints", "snapshot", "snapshotByData"];
1730
+ export declare const MAP_API_METHODS: readonly ["areRoomsAdjacent", "resetPanZoom", "getForbiddenSweepZones", "getForbiddenMopZones", "getCleanZones", "getVirtualWalls", "getSpots", "getViewportCenterPoint", "getMapCenterPoint", "getWallPointsByViewportCenter", "getForbiddenSweepZonePointsByViewportCenter", "getForbiddenMopZonePointsByViewportCenter", "getCleanZonePointsByViewportCenter", "getSpotPointByViewportCenter", "getEffectiveDividerPoints", "getDividerEndPoints", "snapshot", "snapshotByData"];
1731
1731
 
1732
1732
  export declare const MAP_CALLBACK_METHODS: readonly ["onMapFirstDrawed", "onMapDrawed", "onPathDrawed", "onRoomPropertiesDrawed", "onClickRoom", "onClickRoomProperties", "onRemoveForbiddenSweepZone", "onRemoveForbiddenMopZone", "onRemoveCleanZone", "onRemoveVirtualWall", "onUpdateForbiddenSweepZone", "onUpdateForbiddenMopZone", "onUpdateCleanZone", "onUpdateVirtualWall", "onUpdateSpot", "onUpdateDivider", "onClickForbiddenSweepZone", "onClickForbiddenMopZone", "onClickCleanZone", "onClickVirtualWall", "onClickSpot", "onClickDetectedObject", "onClickCustomElement"];
1733
1733
 
@@ -1884,6 +1884,18 @@ export declare interface MapApi {
1884
1884
  offsetX?: number;
1885
1885
  offsetY?: number;
1886
1886
  }): Point;
1887
+ /**
1888
+ * 判断指定的房间是否相邻(连通)
1889
+ *
1890
+ * 支持结构化地图和点阵地图两种协议。对于多个房间,使用连通性算法判断:
1891
+ * 只要房间之间能通过相邻关系连接起来,就认为它们是相邻的。
1892
+ * 例如:房间A和B相邻,房间B和C相邻,则认为A、B、C三个房间都相邻。
1893
+ *
1894
+ * @param roomIds - 要检测的房间ID数组
1895
+ * @param threshold - 距离阈值(像素),默认为5。两个房间的边界点距离小于等于此阈值时认为相邻
1896
+ * @returns 是否所有指定的房间都相邻(连通)
1897
+ */
1898
+ areRoomsAdjacent(roomIds: number[], threshold?: number): boolean;
1887
1899
  /**
1888
1900
  * 地图截图
1889
1901
  *
@@ -2254,6 +2266,29 @@ export declare class MapApplication extends Application implements MapApi {
2254
2266
  offsetX?: number;
2255
2267
  offsetY?: number;
2256
2268
  }): Point;
2269
+ /**
2270
+ * 判断指定的房间是否相邻(连通)
2271
+ *
2272
+ * 支持结构化地图和点阵地图两种协议。对于多个房间,使用连通性算法判断:
2273
+ * 只要房间之间能通过相邻关系连接起来,就认为它们是相邻的。
2274
+ * 例如:房间A和B相邻,房间B和C相邻,则认为A、B、C三个房间都相邻。
2275
+ *
2276
+ * @param roomIds - 要检测的房间ID数组
2277
+ * @param threshold - 距离阈值(像素),默认为3。两个房间的边界点距离小于等于此阈值时认为相邻
2278
+ * @returns 是否所有指定的房间都相邻(连通)
2279
+ *
2280
+ * @example
2281
+ * ```typescript
2282
+ * // 判断两个房间是否相邻
2283
+ * const isAdjacent = mapApi.areRoomsAdjacent([1, 2])
2284
+ *
2285
+ * // 判断三个房间是否相邻(连通),使用自定义阈值
2286
+ * const isAdjacent = mapApi.areRoomsAdjacent([1, 2, 3], 8)
2287
+ * ```
2288
+ */
2289
+ areRoomsAdjacent(roomIds: number[], threshold?: number): boolean;
2290
+ /* Excluded from this release type: areStructuredRoomsAdjacentInternal */
2291
+ /* Excluded from this release type: areRasterRoomsAdjacentInternal */
2257
2292
  /**
2258
2293
  * 地图截图
2259
2294
  *
@@ -2605,6 +2640,7 @@ declare class MapManager {
2605
2640
  mapBounds: Bounds;
2606
2641
  private lastMapId;
2607
2642
  private roomGeometryMap;
2643
+ private rasterRoomPixelsMap;
2608
2644
  private carpetData;
2609
2645
  private unsubscribeFns;
2610
2646
  constructor();
@@ -2657,6 +2693,12 @@ declare class MapManager {
2657
2693
  * @param rasterData 解析后的栅格数据
2658
2694
  */
2659
2695
  private generateRoomGeometryFromRaster;
2696
+ /**
2697
+ * 获取点阵房间的像素数据
2698
+ * @param roomId 房间ID
2699
+ * @returns 像素索引数组,如果不存在则返回 undefined
2700
+ */
2701
+ getRasterRoomPixels(roomId: number): Uint32Array | undefined;
2660
2702
  destroy(): void;
2661
2703
  }
2662
2704