@realsee/dnalogel 4.0.0-webgpu.3 → 4.0.0-webgpu.5
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/CHANGELOG.md +12 -0
- package/dist/floorplan.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +270 -35
- package/dist/index.js.map +1 -0
- package/dist/internal/{BasePlugin-CT5K8m36.js → BasePlugin-CF9WwPH0.js} +3 -3
- package/dist/internal/{BasePlugin-CT5K8m36.js.map → BasePlugin-CF9WwPH0.js.map} +1 -1
- package/dist/internal/BasePluginWithData-D_Nd-o8X.js +7 -0
- package/dist/internal/{BasePluginWithData-9z4tpAT4.js.map → BasePluginWithData-D_Nd-o8X.js.map} +1 -1
- package/dist/internal/{BetterTween-BX0aTvP1.js → BetterTween-DmptqE8m.js} +2 -2
- package/dist/internal/{BetterTween-BX0aTvP1.js.map → BetterTween-DmptqE8m.js.map} +1 -1
- package/dist/internal/{CSS3DRenderPlugin-ccSpcvwd.js → CSS3DRenderPlugin-CEatgl0m.js} +3 -3
- package/dist/internal/CSS3DRenderPlugin-CEatgl0m.js.map +1 -0
- package/dist/internal/{Controller-Csut_kcH.js → Controller-Dryon8vR.js} +8 -8
- package/dist/internal/{Controller-Csut_kcH.js.map → Controller-Dryon8vR.js.map} +1 -1
- package/dist/internal/{FiveDomEvents-3H9NvDOz.js → FiveDomEvents-BUBLFzti.js} +2 -2
- package/dist/internal/{FiveDomEvents-3H9NvDOz.js.map → FiveDomEvents-BUBLFzti.js.map} +1 -1
- package/dist/internal/FivePuppet-C6QmVY70.js +67 -0
- package/dist/internal/FivePuppet-C6QmVY70.js.map +1 -0
- package/dist/internal/{PointHelper-D565h9b_.js → PointHelper-DIhgdjY2.js} +48 -48
- package/dist/internal/{PointHelper-D565h9b_.js.map → PointHelper-DIhgdjY2.js.map} +1 -1
- package/dist/internal/{Polygon-CBGvYUfJ.js → Polygon-D3xIL1Pl.js} +30 -30
- package/dist/internal/{Polygon-CBGvYUfJ.js.map → Polygon-D3xIL1Pl.js.map} +1 -1
- package/dist/internal/{Prism-Dm5ESkgg.js → Prism-CJlyAEAU.js} +13 -13
- package/dist/internal/{Prism-Dm5ESkgg.js.map → Prism-CJlyAEAU.js.map} +1 -1
- package/dist/internal/{Rectangle-D-zkDycu.js → Rectangle-BoIJCQwi.js} +118 -129
- package/dist/internal/Rectangle-BoIJCQwi.js.map +1 -0
- package/dist/internal/{Work-DF8j5GnL.js → Work-Be2SHN6W.js} +9 -9
- package/dist/internal/{Work-DF8j5GnL.js.map → Work-Be2SHN6W.js.map} +1 -1
- package/dist/internal/{animationFrame-XGKHIeQK.js → animationFrame-CacKXN8l.js} +14 -3
- package/dist/internal/animationFrame-CacKXN8l.js.map +1 -0
- package/dist/internal/{area-maker-Bd9l2pIp.js → area-maker-7PeyKcgL.js} +4 -4
- package/dist/internal/{area-maker-Bd9l2pIp.js.map → area-maker-7PeyKcgL.js.map} +1 -1
- package/dist/internal/{boundingBox-DvCor5Hd.js → boundingBox-CIqXgNXW.js} +2 -2
- package/dist/internal/{boundingBox-DvCor5Hd.js.map → boundingBox-CIqXgNXW.js.map} +1 -1
- package/dist/internal/{camera-movement-CwI7UqUk.js → camera-movement-C1pwfMk_.js} +2 -2
- package/dist/internal/camera-movement-C1pwfMk_.js.map +1 -0
- package/dist/internal/{changeMode-BVGYCoqu.js → changeMode-D_I2AOjH.js} +2 -2
- package/dist/internal/{changeMode-BVGYCoqu.js.map → changeMode-D_I2AOjH.js.map} +1 -1
- package/dist/internal/{controller-BWkZT0l1.js → controller-B_X85eJa.js} +1991 -2050
- package/dist/internal/controller-B_X85eJa.js.map +1 -0
- package/dist/internal/{cruise-C3F0eNQ-.js → cruise-Cd0Lx_8t.js} +2 -2
- package/dist/internal/{cruise-C3F0eNQ-.js.map → cruise-Cd0Lx_8t.js.map} +1 -1
- package/dist/internal/{current-pano-image-DKUWluR-.js → current-pano-image-k6epv1ic.js} +4 -4
- package/dist/internal/{current-pano-image-DKUWluR-.js.map → current-pano-image-k6epv1ic.js.map} +1 -1
- package/dist/internal/{defaultUrls-CjKkS9k9.js → defaultUrls-CfMtGzqM.js} +14 -3
- package/dist/internal/defaultUrls-CfMtGzqM.js.map +1 -0
- package/dist/internal/{fire-scene-CczaBz2_.js → fire-scene-BzZGvyh_.js} +9 -4
- package/dist/internal/fire-scene-BzZGvyh_.js.map +1 -0
- package/dist/internal/{fiveModelLoad-mg-TnpnM.js → fiveModelLoad-BUIBYxzp.js} +2 -2
- package/dist/internal/{fiveModelLoad-mg-TnpnM.js.map → fiveModelLoad-BUIBYxzp.js.map} +1 -1
- package/dist/internal/{floorplan-KWlIsTvO.js → floorplan-b_k7HM-B.js} +5 -5
- package/dist/internal/{floorplan-KWlIsTvO.js.map → floorplan-b_k7HM-B.js.map} +1 -1
- package/dist/internal/{generatePolygonGeometry-B_5JFq8y.js → generatePolygonGeometry-BOnzdCaG.js} +181 -178
- package/dist/internal/generatePolygonGeometry-BOnzdCaG.js.map +1 -0
- package/dist/internal/{lookObject-wesf8xt6.js → lookObject-DuRab5wf.js} +2 -2
- package/dist/internal/{lookObject-wesf8xt6.js.map → lookObject-DuRab5wf.js.map} +1 -1
- package/dist/internal/{measure-BX6boAC7.js → measure-B4jFwdQ6.js} +5 -5
- package/dist/internal/{measure-BX6boAC7.js.map → measure-B4jFwdQ6.js.map} +1 -1
- package/dist/internal/{model-chassis-compass-InVNmOAQ.js → model-chassis-compass-C6NTVMLo.js} +2 -2
- package/dist/internal/{model-chassis-compass-InVNmOAQ.js.map → model-chassis-compass-C6NTVMLo.js.map} +1 -1
- package/dist/internal/{model-entry-door-guide-wZbyY77a.js → model-entry-door-guide-DnGTLY2s.js} +2 -2
- package/dist/internal/{model-entry-door-guide-wZbyY77a.js.map → model-entry-door-guide-DnGTLY2s.js.map} +1 -1
- package/dist/internal/{model-maker-uO8xlTuO.js → model-maker-C2xJUK4Q.js} +15 -15
- package/dist/internal/{model-maker-uO8xlTuO.js.map → model-maker-C2xJUK4Q.js.map} +1 -1
- package/dist/internal/{model-tv-video-DzXb2JRf.js → model-tv-video-BP-7HoDC.js} +2 -2
- package/dist/internal/{model-tv-video-DzXb2JRf.js.map → model-tv-video-BP-7HoDC.js.map} +1 -1
- package/dist/internal/{model-view-CBeeMM98.js → model-view-BWUU0-uq.js} +2 -2
- package/dist/internal/{model-view-CBeeMM98.js.map → model-view-BWUU0-uq.js.map} +1 -1
- package/dist/internal/object3d-helper-Dh6U9yE_.js +7 -0
- package/dist/internal/{object3d-helper-DDYsVPN6.js.map → object3d-helper-Dh6U9yE_.js.map} +1 -1
- package/dist/internal/{pano-compass-jSr629BP.js → pano-compass-CE49XtPR.js} +7 -7
- package/dist/internal/{pano-compass-jSr629BP.js.map → pano-compass-CE49XtPR.js.map} +1 -1
- package/dist/internal/{pano-door-label-DKoYIKLa.js → pano-door-label-B3o8HEuf.js} +3 -3
- package/dist/internal/{pano-door-label-DKoYIKLa.js.map → pano-door-label-B3o8HEuf.js.map} +1 -1
- package/dist/internal/{pano-measure-DW9mdx1O.js → pano-measure-Debf40XO.js} +14 -14
- package/dist/internal/{pano-measure-DW9mdx1O.js.map → pano-measure-Debf40XO.js.map} +1 -1
- package/dist/internal/{pano-ruler-pro-D7q0Ob21.js → pano-ruler-pro-D9yTbHJz.js} +2 -2
- package/dist/internal/{pano-ruler-pro-D7q0Ob21.js.map → pano-ruler-pro-D9yTbHJz.js.map} +1 -1
- package/dist/internal/{pano-spatial-tag-D0qn-__S.js → pano-spatial-tag-B7Gxn3BS.js} +3 -3
- package/dist/internal/{pano-spatial-tag-D0qn-__S.js.map → pano-spatial-tag-B7Gxn3BS.js.map} +1 -1
- package/dist/internal/{pano-tag-BW5MXXws.js → pano-tag-CsqfnBhp.js} +2 -2
- package/dist/internal/{pano-tag-BW5MXXws.js.map → pano-tag-CsqfnBhp.js.map} +1 -1
- package/dist/internal/{pano-video-Bmud_CAn.js → pano-video-fYkV7T4S.js} +42 -29
- package/dist/internal/pano-video-fYkV7T4S.js.map +1 -0
- package/dist/internal/{pipeline-DDqgb1gw.js → pipeline-hoComnfA.js} +4 -4
- package/dist/internal/{pipeline-DDqgb1gw.js.map → pipeline-hoComnfA.js.map} +1 -1
- package/dist/internal/{sculpt-BNkLJR6p.js → sculpt-j9CUwpnR.js} +64 -63
- package/dist/internal/{sculpt-BNkLJR6p.js.map → sculpt-j9CUwpnR.js.map} +1 -1
- package/dist/internal/tagPosition-DA9YguT8.js +176 -0
- package/dist/internal/tagPosition-DA9YguT8.js.map +1 -0
- package/dist/internal/withResolvers-DVr4bnnk.js +15 -0
- package/dist/internal/withResolvers-DVr4bnnk.js.map +1 -0
- package/dist/plugins/area-maker.js +1 -1
- package/dist/plugins/camera-movement.js +1 -1
- package/dist/plugins/cruise.js +2 -2
- package/dist/plugins/css3d-render.js +1 -1
- package/dist/plugins/current-pano-image.js +1 -1
- package/dist/plugins/digital-performance.d.ts +1 -1
- package/dist/plugins/digital-performance.js +1 -1
- package/dist/plugins/fire-scene.d.ts +1 -1
- package/dist/plugins/fire-scene.js +1 -1
- package/dist/plugins/guide-line.js +1 -1
- package/dist/plugins/measure.js +1 -1
- package/dist/plugins/model-chassis-compass.js +1 -1
- package/dist/plugins/model-entry-door-guide.js +1 -1
- package/dist/plugins/model-maker.d.ts +1 -1
- package/dist/plugins/model-maker.js +1 -1
- package/dist/plugins/model-tv-video.js +1 -1
- package/dist/plugins/model-view.js +1 -1
- package/dist/plugins/object3d-helper.d.ts +1 -1
- package/dist/plugins/object3d-helper.js +3 -1
- package/dist/plugins/pano-compass.js +1 -1
- package/dist/plugins/pano-door-label.js +1 -1
- package/dist/plugins/pano-measure.js +1 -1
- package/dist/plugins/pano-ruler-pro.js +1 -1
- package/dist/plugins/pano-spatial-tag.js +1 -1
- package/dist/plugins/pano-tag.d.ts +1 -1
- package/dist/plugins/pano-tag.js +4 -1
- package/dist/plugins/pano-video.js +1 -1
- package/dist/plugins/pipeline.js +1 -1
- package/dist/plugins/sculpt.d.ts +1 -1
- package/dist/plugins/sculpt.js +7 -1
- package/dist/types/PanoVideoPlugin/VideoMeshController.d.ts +3 -0
- package/dist/types/public/index.d.ts +2 -0
- package/dist/types/public/plugins/digital-performance.d.ts +1 -0
- package/dist/types/public/plugins/fire-scene.d.ts +1 -0
- package/dist/types/public/plugins/model-maker.d.ts +1 -0
- package/dist/types/public/plugins/object3d-helper.d.ts +1 -0
- package/dist/types/public/plugins/pano-tag.d.ts +2 -0
- package/dist/types/public/plugins/sculpt.d.ts +8 -0
- package/dist/types/public/utils.d.ts +5 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +16 -50
- package/package.json +1 -1
- package/dist/internal/BasePluginWithData-9z4tpAT4.js +0 -7
- package/dist/internal/CSS3DRenderPlugin-ccSpcvwd.js.map +0 -1
- package/dist/internal/Rectangle-D-zkDycu.js.map +0 -1
- package/dist/internal/animationFrame-XGKHIeQK.js.map +0 -1
- package/dist/internal/blink-DD_0mH-m.js +0 -113
- package/dist/internal/blink-DD_0mH-m.js.map +0 -1
- package/dist/internal/camera-movement-CwI7UqUk.js.map +0 -1
- package/dist/internal/controller-BWkZT0l1.js.map +0 -1
- package/dist/internal/defaultUrls-CjKkS9k9.js.map +0 -1
- package/dist/internal/fire-scene-CczaBz2_.js.map +0 -1
- package/dist/internal/generatePolygonGeometry-B_5JFq8y.js.map +0 -1
- package/dist/internal/object3d-helper-DDYsVPN6.js +0 -7
- package/dist/internal/pano-video-Bmud_CAn.js.map +0 -1
- package/dist/utils.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generatePolygonGeometry-B_5JFq8y.js","names":["equals","getFiveModel","anyPositionToVector3","centerPoint","getObjectVisible","toArray","IObject3D","getNormal","FiveUtil","_raycaster","resizeObserver","throttle","notNil","LineMaterial","LineGeometry","THREE_Line2","THREE","owners","bindFiveOwner","object","five","getFiveFromParentChain","current","DEFAULT_COLOR","DEFAULT_OPACITY","DEFAULT_HIGHLIGHT_OPACITY","vector3ToScreen","vector3","camera","x","rendererSize","y","fiveEveryReadyListener","registered","registerFiveRenderFireFunction","callback","filterVisibleIntersections","intersections","intersection","_vector2","Vector2","LightTag","position","config","p","div","params","waitFiveModelLoaded","domId","tagWrapper","dom","fiveEveryReadyListenerDisposer","d","positionsForRotate","matrix","renderSize","screenPosition","scale","sseDenominator","distance","cssRotate","p0","p1","screenP0","screenP1","leftPoint","rightPoint","v","canShowTag","distanceError","direction","intersectsForFiveModel","intersectsForExtraObjects","intersect","a","b","fiveElement","observe","unobserve","tag","calculateThreeMouse","element","mouseXY","left","width","top","height","getLengthHTML","style","offsetTransform","text","localToWorld","worldPoints","point","worldToLocal","localPoints","LineMaterial2","formatFractionalInch","whole","inchValue","frac","numerator","denominator","fraction","transformUnit","stringValue","unit","value","precision","totalInches","roundedTotalInches","foot","inch","transformUnitSquare","RenderDom","obj","visible","setObjectOriginSortBounds","geometry","objects","bounds","LineMesh","line","raycast","sortBounds","preciseBounds","raycaster","intersects","size","lineMaterialParams","lineMaterial1","lineMaterial2","force","lastRenderDomItem","points","vectors","lineGeometry","positions","resolution","resolution2","color","occlusionVisibility","occlusionMode","highlightOpacity","clear","lines","i","tagPosition","render","str","screenLineLength","screenWidth","screenHeight","halfScreenWidth","halfScreenHeight","ndcP0","ndcP1","distanceToCamera","fov","distanceStyle","getTextWidth","tempElement","offsetY","textWidth","getGeometryInfo","triangles","getGeometryTriangles","area","center","Vector3","p2","p3","triArea","triangleArea","triCenter","triangleCenter","indices","vertexIndices","index","i0","i1","i2","steiners","filteredOut","earcut","hasHoles","holeIndices","outerLen","dim","data","outerNode","linkedList","minX","minY","invSize","eliminateHoles","maxX","maxY","earcutLinked","last","clockwise","signedArea","start","end","insertNode","equals$1","removeNode","filterPoints","full","again","indexCurve","ear","stop","cured","prev","next","isEarHashed","isEar","cureLocalIntersections","c","ax","bx","cx","ay","by","cy","x0","y0","x1","y1","pointInTriangle","minZ","zOrder","maxZ","n","locallyInside","splitEarcut","isValidDiagonal","splitPolygon","indexActive","queue","len","list","getLeftmost","compareXYSlope","buildBlockIndex","indexSegment","eliminateHole","bridge","findHoleBridge","hole","bridgeReverse","bridge2","K","blockBBox","numBlocks","blockHead","blockStop","maxBlocks","maxNodes","numHoles","head","k","g","growBlock","tail","liveBlockStop","liveBlockHead","hx","hy","qx","m","mx","my","tminY","tmaxY","tanMin","tan","sectorContainsSector","sortArr","sortBuf","zArr","zBuf","counts","node","sortNodes","z","j","radixPass","srcZ","shift","sum","pos","src","leftmost","px","py","zeroLength","intersectsPolygon","middleInside","q","r","o1","q1","o2","q2","o3","o4","includeBoundary","onSegment","inside","a2","createNode","b2","an","bp","earcut3D","normal","quaternion","isIntersecting","line2","line1","equals","areLinesIntersecting3D","dirVec1","line1End","line1Start","dirVec2","line2End","line2Start","rows","A","detA","determinant","t","matrixVectorMultiply","inverseMatrix","isInSegmentRange","det","vector","generatePolygonGeometry","_points","arrayPosition","positionAttribute","indexAttribute"],"sources":["../../src/shared-utils/five/getFiveFromParentChain.ts","../../src/Sculpt/typings/style.ts","../../src/shared-utils/five/vector3ToScreen.ts","../../src/shared-utils/five/fiveEveryReadyListener.ts","../../src/shared-utils/three/filterVisibleIntersections.ts","../../src/shared-utils/tag.ts","../../src/shared-utils/five/calculateThreeMouse.ts","../../src/Sculpt/utils/Meshes/getLengthHTML.ts","../../src/shared-utils/three/applyObjectMatrixWorld.ts","../../src/shared-utils/three/core/LineMaterial2.ts","../../src/Sculpt/utils/unit.ts","../../src/Sculpt/utils/renderDom.ts","../../src/shared-utils/three/setObjectOriginSortBounds.ts","../../src/Sculpt/Meshes/Line.ts","../../src/shared-utils/three/geometryUtil.ts","../../../node_modules/earcut/src/earcut.js","../../src/shared-utils/three/earcut3D.ts","../../src/PanoMeasurePlugin/utils/isIntersecting.ts","../../src/shared-utils/three/generatePolygonGeometry.ts"],"sourcesContent":["import type { Five } from '@realsee/five-webgpu'\nimport type { Object3D } from 'three/webgpu'\n\nconst owners = new WeakMap<Object3D, Five>()\nexport function bindFiveOwner(object: Object3D, five: Five) { owners.set(object, five) }\nexport function getFiveFromParentChain(object: Object3D): Five | undefined {\n let current: Object3D | null = object\n while (current) {\n const five = owners.get(current)\n if (five) return five\n current = current.parent\n }\n return undefined\n}\n","import type * as THREE from 'three/webgpu'\n\nexport type Color = THREE.Color | string | number\n\nexport const DEFAULT_COLOR = 0xffffff\n\nexport const DEFAULT_LINE_COLOR = 0xffffff\n\nexport const DEFAULT_LINE_WIDTH = 1\n\nexport const DEFAULT_LINE_OPACITY = 1\n\nexport const DEFAULT_OPACITY = 0.4\n\nexport const DEFAULT_HIGHLIGHT_OPACITY = 0.6\n\nexport type OpacityStyle = {\n /**\n * @description: 透明度\n * @default 0.5\n */\n opacity?: number\n}\n\nexport type ColorStyle = {\n /**\n * @description: 颜色\n * @default 0xffffff\n */\n color?: Color\n}\n\nexport type LineOpacityStyle = {\n /**\n * @description: 透明度\n * @default 1\n */\n lineOpacity?: number\n}\n\nexport type LineColorStyle = {\n /**\n * @description: 边框线颜色\n * @default 0xffffff\n */\n lineColor?: Color\n}\n\nexport type LineWidthStyle = {\n /**\n * @description: 线宽\n * @default 1\n */\n lineWidth?: number\n}\n\nexport type CreateLimitConfig = {\n /**\n * @description 限制折线绘制的平面; `xoz` 限制在水平面; `y` 限制垂直面; `none` 不限制\n * @default `none`\n */\n limit: 'xoz' | 'y' | 'none'\n}\n\nexport type DrawMethodConfig = {\n /**\n * @description 矩形绘制方式; `vertex` 按顺序绘制三个点; `diagonal` 先绘制对角线;\n * @default `diagonal`\n */\n drawMethod: 'vertex' | 'diagonal'\n}\n\nexport type OcclusionStyle = {\n /**\n * @description 是否以一种半透明的方式显示遮挡的部分\n */\n occlusionVisibility: boolean\n /**\n * @description 当 occlusionVisibility 为true时,以哪种方式显示被遮挡的部分\n * @params 'depthTest': 关闭深度测试, 'translucence': 半透明\n * @default 'translucence'\n */\n occlusionMode: 'translucence' | 'depthTest'\n}\n\nexport type LengthConfig = {\n /**\n * @description 开启 距离 展示\n * @default false\n */\n lengthEnable: boolean\n /**\n * @description 距离/面积 单位\n * @default 'm'\n */\n lengthUnit: 'm' | 'mm' | 'ft'\n /**\n * @description Number of decimal places for length measurements in metric units (meters). Area measurements remain at fixed 2 decimal places.\n * @default 2\n */\n precision?: number\n}\n\nexport type DisplayInfoConfig = {\n /**\n * @description 提示信息\n */\n tip: string | HTMLElement\n /**\n * @description 提示信息样式\n */\n cssStyle?: string\n}\n\nexport type LineStyle = LineColorStyle & LineOpacityStyle & LineWidthStyle\n\nexport type PolygonDrawConfig = {\n /**\n * @description 简单模式:不吸附、不与模型发生关系,所有点高度取模型最高点\n * @default false\n */\n simpleMode?: boolean\n /**\n * @description 闭合吸附的屏幕像素距离,单位px,默认10\n */\n autoClosePixelDistance?: number\n}\n","import type * as THREE from 'three/webgpu'\n\nexport default function vector3ToScreen(camera: THREE.Camera, vector3: THREE.Vector3, rendererSize: THREE.Vector2) {\n const { x, y, z } = vector3.clone().project(camera)\n\n // 在背后\n if (z > 1) return\n\n const screenPosition = {\n leftPx: ((x + 1) / 2) * rendererSize.x,\n topPx: ((-y + 1) / 2) * rendererSize.y,\n }\n\n return screenPosition\n}\n","import type { Five } from '@realsee/five-webgpu'\nimport throttle from '../throttle'\n\nexport function fiveEveryReadyListener(five: Five, callback: () => void) {\n let registered = false\n const registerFiveRenderFireFunction = throttle(() => {\n if (registered) return\n registered = true\n five.ready().then(() => {\n callback()\n registered = false\n })\n }, 150)\n\n five.on('camera.update', registerFiveRenderFireFunction)\n\n return () => {\n five.off('camera.update', registerFiveRenderFireFunction)\n }\n}\n","import type * as THREE from 'three/webgpu'\nimport { getObjectVisible } from './getObjectVisible'\n\n/** Three.js Raycaster 会命中不可见父节点下的子对象,此处补齐渲染可见性语义。 */\nexport function filterVisibleIntersections(intersections: THREE.Intersection[]): THREE.Intersection[] {\n return intersections.filter((intersection) => getObjectVisible(intersection.object))\n}\n","import type * as THREE from 'three/webgpu'\nimport type { Five } from '@realsee/five-webgpu'\nimport { anyPositionToVector3, type AnyPosition } from './positionToVector3'\nimport vector3ToScreen from './five/vector3ToScreen'\nimport { getFiveModel } from './five/getFiveModel'\nimport { FiveUtil } from './Utils/FiveUtil'\nimport { _raycaster } from './three/temp'\nimport { resizeObserver } from './dom/resizeObserver'\nimport { fiveEveryReadyListener } from './five/fiveEveryReadyListener'\nimport { waitFiveModelLoaded } from '.'\nimport { Vector2 } from 'three/webgpu'\nimport { filterVisibleIntersections } from './three/filterVisibleIntersections'\n\nconst _vector2 = new Vector2()\n\nexport class LightTag {\n /**\n * @description 单个标签 dom\n */\n public container: HTMLDivElement\n public visible = false\n public enabled = false\n\n /**\n * @description 标签的可见性数组\n * ```\n * [0] this.visible\n * [1] 碰撞检测\n * [2] 元素遮挡\n * [3] 强制显示\n * ```\n */\n public visibles: boolean[] = []\n\n public get position() {\n return this.transformedPosition\n }\n\n /**\n * @description 标签容器的父容器\n * @default this.five.getElement()?.parentElement\n */\n public wrapper: HTMLElement\n public positionsForRotate?: THREE.Vector3[]\n\n /**\n * @description 碰撞检测\n * @default true\n */\n public intersectCheck = true\n\n /**\n * @description 用于碰撞检测的额外 Object3D\n */\n public extraObjectsForIntersectCheck: THREE.Object3D[] = []\n\n /**\n * @description 模拟3D\n * @default false\n */\n public simulate3D = false\n\n\n public set needsRender(val: true) {\n this.applyVisible()\n }\n\n /**\n * @description 标签的容器,根据 namespace 区分\n */\n private tagWrapper?: HTMLElement\n private five: Five\n private originPosition?: THREE.Vector3\n private transformedPosition?: THREE.Vector3\n private disposer: () => void\n private config: { wrapper?: HTMLElement; positionsForRotate?: AnyPosition[]; namespace?: string }\n private fiveUtil: FiveUtil\n private disposers: (() => void)[] = []\n\n public constructor(\n five: Five,\n position?: AnyPosition,\n config?: { wrapper?: HTMLElement; positionsForRotate?: AnyPosition[]; namespace?: string; disableOpacityTransition?: boolean },\n ) {\n this.five = five\n this.fiveUtil = (five as any).__fiveUtil__ ?? ((five as any).__fiveUtil__ = new FiveUtil(five))\n this.originPosition = position ? anyPositionToVector3(position).clone() : undefined\n this.transformedPosition = this.originPosition?.clone()\n this.positionsForRotate = config?.positionsForRotate?.map((p) => anyPositionToVector3(p).clone())\n this.config = config ?? {}\n\n this.container = (() => {\n const div = document.createElement('div')\n div.classList.add('light-tag')\n div.style.width = '0'\n div.style.height = '0'\n div.style.position = 'absolute'\n if (!config?.disableOpacityTransition) {\n div.style.transition = 'opacity 0.2s linear'\n }\n return div\n })()\n this.addResizeListener()\n\n this.show()\n this.enable()\n\n setTimeout(() => {\n // 有些属性会在实例化完事后设置,需要等待下一帧才能生效\n this.updateVisible()\n this.needsRender = true\n }, 0)\n }\n\n /**\n * @description 显示标签\n */\n public show(params?: { force?: boolean }) {\n this.visible = true\n this.visibles[0] = true\n if (params?.force) this.visibles[3] = true\n this.container.style.opacity = '1'\n this.container.style.pointerEvents = 'auto'\n this.updateVisible()\n this.onCameraUpdate()\n }\n\n /**\n * @description 隐藏标签\n */\n public hide() {\n this.visible = false\n this.visibles[0] = false\n this.container.style.opacity = '0'\n this.container.style.pointerEvents = 'none'\n }\n\n /**\n * @description 启用标签\n */\n public async enable() {\n if (this.enabled) return\n this.enabled = true\n\n await waitFiveModelLoaded(this.five)\n\n if (!this.enabled) return\n\n this.wrapper = this.config.wrapper ?? this.five.getElement()?.parentElement\n if (!this.wrapper) {\n console.error('lighttag: wrapper is required')\n return\n }\n const domId = `light-tag-wrapper-${this.config?.namespace ?? 'default'}`\n\n if (!this.tagWrapper) {\n let tagWrapper = Array.from(this.wrapper.children).find((dom) => dom.id === domId) as HTMLElement\n\n if (!tagWrapper) {\n const dom = document.createElement('div')\n tagWrapper = dom\n\n dom.id = domId\n dom.style.position = 'absolute'\n dom.style.overflow = 'hidden'\n dom.style.top = '0'\n dom.style.left = '0'\n dom.style.width = '100%'\n dom.style.height = '100%'\n dom.style.pointerEvents = 'none'\n dom.style.zIndex = '1'\n\n this.wrapper.appendChild(tagWrapper)\n }\n\n this.tagWrapper = tagWrapper\n }\n\n this.tagWrapper.appendChild(this.container)\n\n this.updateVisible()\n\n const fiveEveryReadyListenerDisposer = fiveEveryReadyListener(this.five, this.onFiveEveryReady)\n this.five.on('cameraUpdate', this.onCameraUpdate)\n this.five.on('cameraFovUpdate', this.onCameraFovUpdate)\n this.five.on('panoArrived', this.onPanoArrived)\n this.five.on('modeChange', this.onModeChange)\n\n this.disposer = () => {\n fiveEveryReadyListenerDisposer()\n this.five.off('cameraUpdate', this.onCameraUpdate)\n this.five.off('cameraFovUpdate', this.onCameraFovUpdate)\n this.five.off('panoArrived', this.onPanoArrived)\n this.five.off('modeChange', this.onModeChange)\n }\n }\n\n /**\n * @description 禁用标签\n */\n public disable() {\n if (!this.enabled) return\n this.enabled = false\n\n // 添加安全检查\n if (this.tagWrapper && this.container && this.tagWrapper.contains(this.container)) {\n this.tagWrapper.removeChild(this.container)\n }\n\n this.disposer?.()\n }\n\n /**\n * @description 销毁标签,并释放相关资源\n */\n public destroy() {\n this.disable()\n this.container.remove()\n this.disposers.forEach((d) => d())\n }\n\n /**\n * @description 设置标签位置\n * @param position 位置\n * @param positionsForRotate 用于 css 旋转的斜线的两个端点\n */\n public setPosition(position: AnyPosition, positionsForRotate?: AnyPosition[]) {\n this.transformedPosition = anyPositionToVector3(position).clone()\n this.positionsForRotate = positionsForRotate?.map((p) => anyPositionToVector3(p).clone())\n this.onCameraUpdate()\n setTimeout(() => this.onCameraUpdate(), 0) // 不知道哪里的 bug,偶现 project 出来的位置不对,需要稍后再更新一次\n }\n\n public setTransformMatrix(matrix: THREE.Matrix4) {\n this.transformedPosition = this.originPosition?.clone().applyMatrix4(matrix)\n this.onCameraUpdate()\n }\n\n public updateScreenPosition() {\n if (!this.transformedPosition) {\n this.container.style.left = '-100%'\n this.container.style.top = '-100%'\n return\n }\n\n const renderSize = this.five.renderer?.getSize(_vector2)\n\n if (!renderSize) {\n this.container.style.left = '-100%'\n this.container.style.top = '-100%'\n return\n }\n\n const screenPosition = vector3ToScreen(this.five.camera, this.transformedPosition, renderSize)\n\n if (!screenPosition) {\n this.container.style.left = '-100%'\n this.container.style.top = '-100%'\n return\n }\n\n const scale = (() => {\n if (!this.simulate3D) return 1\n const scale = 3.0 // 系数,数值越大,文字大小变化越明显\n const sseDenominator = scale * Math.tan(((0.5 * this.five.camera.fov) / 180) * Math.PI)\n const distance = this.transformedPosition!.distanceTo(this.five.camera.position)\n return Math.max(Math.min(1 - (sseDenominator * distance) / 40, 1), 0.75)\n })()\n\n const cssRotate = (() => {\n if (this.positionsForRotate === undefined) return 0\n if (this.positionsForRotate.length !== 2) return 0\n const [p0, p1] = this.positionsForRotate\n const screenP0 = vector3ToScreen(this.five.camera, p0, renderSize)\n const screenP1 = vector3ToScreen(this.five.camera, p1, renderSize)\n if (!screenP0 || !screenP1) return 0\n const leftPoint = screenP0.leftPx > screenP1.leftPx ? screenP1 : screenP0\n const rightPoint = screenP0.leftPx > screenP1.leftPx ? screenP0 : screenP1\n const x = rightPoint.leftPx - leftPoint.leftPx\n const y = rightPoint.topPx - leftPoint.topPx\n return Math.atan2(y, x) * (180 / Math.PI)\n })()\n\n this.container.style.left = screenPosition.leftPx + 'px'\n this.container.style.top = screenPosition.topPx + 'px'\n this.container.style.transformOrigin = 'center'\n this.container.style.transform = `scale(${scale})`\n if (cssRotate) this.container.style.transform += ` rotate(${cssRotate}deg)`\n }\n\n private onModeChange = () => {\n this.visibles[3] = undefined\n this.updateVisible()\n }\n\n private onPanoArrived = () => {\n this.visibles[3] = undefined\n this.updateVisible()\n }\n\n private onCameraUpdate = () => {\n if (this.visible === false) return\n this.updateScreenPosition()\n }\n\n private onCameraFovUpdate = () => {\n this.onCameraUpdate()\n this.five.off('render.prepare', this.onCameraUpdate)\n this.five.on('render.prepare', this.onCameraUpdate)\n setTimeout(() => {\n this.five.off('render.prepare', this.onCameraUpdate)\n }, 1000)\n }\n\n private onFiveEveryReady = () => {\n if (this.five.state.mode !== 'Panorama') {\n this.updateVisible()\n }\n }\n\n private updateVisible = () => {\n if (!this.visible) return\n this.updateIntersectCheckVisible()\n this.needsRender = true\n }\n\n private applyVisible = () => {\n const canShow = this.visibles[3] === true || this.visibles.every((v) => v !== false)\n if (canShow) {\n this.container.style.opacity = '1'\n this.container.style.pointerEvents = 'auto'\n } else {\n this.container.style.opacity = '0'\n this.container.style.pointerEvents = 'none'\n }\n }\n\n private updateIntersectCheckVisible = () => {\n if (!this.position) return\n if (!this.intersectCheck) {\n this.visibles[1] = true\n return\n }\n\n let canShowTag = false\n\n // 碰撞检测\n let distanceError = 0.01\n if (this.fiveUtil.workUtil.fromType === 'poincare') distanceError = 0.05\n const direction = this.transformedPosition.clone().sub(this.five.camera.position).normalize()\n\n _raycaster.set(this.five.camera.position, direction)\n const intersectsForFiveModel = getFiveModel(this.five).intersectRaycaster(_raycaster) ?? []\n const intersectsForExtraObjects = filterVisibleIntersections(\n _raycaster.intersectObjects(this.extraObjectsForIntersectCheck, true) ?? [],\n )\n\n const intersects: THREE.Intersection[] = [...intersectsForFiveModel, ...intersectsForExtraObjects]\n\n const intersect = intersects.sort((a, b) => a.distance - b.distance)[0]\n\n if (!intersect) {\n canShowTag = true\n } else {\n canShowTag = intersect?.distance + distanceError > this.transformedPosition.distanceTo(this.five.camera.position)\n }\n\n this.visibles[1] = canShowTag\n }\n\n private addResizeListener() {\n const fiveElement = this.five.getElement()\n if (fiveElement) {\n const { observe, unobserve } = resizeObserver(this.onCameraUpdate, fiveElement)\n observe()\n this.disposers.push(unobserve)\n }\n }\n}\n\nexport function tag(...params: ConstructorParameters<typeof LightTag>) {\n return new LightTag(...params)\n}\n","import * as THREE from 'three/webgpu'\n\n/**\n * 计算 three 中的 mouse 的值\n * @param mouseXY - 鼠标相对屏幕位置\n * @param element - canvas元素(three的展示元素)\n */\nfunction calculateThreeMouse(mouseXY: { x: number; y: number }, element: HTMLElement) {\n const { top, left, width, height } = element.getBoundingClientRect()\n return new THREE.Vector2(((mouseXY.x - left) / width) * 2 - 1, (-(mouseXY.y - top) / height) * 2 + 1)\n}\n\nexport { calculateThreeMouse }\n","export function getLengthHTML(text: string, params?: { style?: string; offsetY?: number }) {\n if (!document.getElementById('LineLengthTagStyle')) {\n const style = document.createElement('style')\n style.id = 'LineLengthTagStyle'\n document.head.appendChild(style)\n style.innerHTML = `\n .LineLengthTag {\n cursor: default;\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: Arial-BoldMT;\n font-weight: BoldMT;\n color: #041066;\n letter-spacing: 0;\n line-height: 20px;\n background-color: #FFFFFF;\n border-radius: 12px;\n padding: 2px 8px;\n left: 50%;\n transform: translate(-50%, -50%);\n white-space: nowrap;\n word-break: keep-all;\n --distance-scale: 1; /* Default scale if not provided */\n transition: font-size 0.5s ease; /* Smooth transition for font size */\n }\n \n /* sm screen */\n @media screen and (max-width: 499px) {\n .LineLengthTag {\n font-size: calc(12px + (14px - 12px) * var(--distance-scale));\n }\n }\n \n /* md screen */\n @media screen and (min-width: 500px) and (max-width: 929px) {\n .LineLengthTag {\n font-size: calc(12px + (14px - 12px) * var(--distance-scale));\n }\n }\n \n /* lg screen */\n @media screen and (min-width: 930px) and (max-width: 1365px) {\n .LineLengthTag {\n font-size: calc(14px + (16px - 14px) * var(--distance-scale));\n }\n }\n \n /* xl screen */\n @media screen and (min-width: 1366px) and (max-width: 2549px) {\n .LineLengthTag {\n font-size: calc(14px + (16px - 14px) * var(--distance-scale));\n }\n }\n \n /* xxl screen */\n @media screen and (min-width: 2550px) {\n .LineLengthTag {\n font-size: calc(0.875rem + (1rem - 0.875rem) * var(--distance-scale));\n }\n }\n `\n }\n\n // Apply vertical offset if specified\n const offsetTransform = params?.offsetY ? `translateY(${params.offsetY}px)` : ''\n const transformStyle = offsetTransform ? `transform: translate(-50%, -50%) ${offsetTransform};` : ''\n\n const html = `\n <div class=\"LineLengthTag\" style=\"${transformStyle}${params?.style ? ' ' + params.style : ''}\">\n ${text}\n </div>\n `\n\n return html\n}\n","import type * as THREE from 'three/webgpu'\nimport type { Object3D } from 'three/webgpu'\nimport { toArray } from '../util'\n\nexport function localToWorld<P extends THREE.Vector3 | THREE.Vector3[]>(object: Object3D, point: P): P {\n const points = toArray(point)\n\n const worldPoints = points.map((p) => object.localToWorld(p.clone()))\n\n if (Array.isArray(point)) {\n return worldPoints as P\n } else {\n return worldPoints[0] as P\n }\n}\n\nexport function worldToLocal<P extends THREE.Vector3 | THREE.Vector3[]>(object: Object3D, point: P): P {\n const points = toArray(point)\n\n const localPoints = points.map((p) => object.worldToLocal(p.clone()))\n\n if (Array.isArray(point)) {\n return localPoints as P\n } else {\n return localPoints[0] as P\n }\n}\n","import type { MeshBasicMaterialParameters } from 'three/webgpu'\nimport { LineMaterial, type LineMaterialParameters } from './LineMaterial'\n\nexport class LineMaterial2 extends LineMaterial {\n public constructor(params: LineMaterialParameters & MeshBasicMaterialParameters = {}) {\n super(params)\n }\n}\n","/**\n * Format inches with optional fractional precision.\n * Keep the selected denominator as-is (e.g. 8/16 stays 8/16 under 1/16\" precision).\n * @param inchValue - inches in [0, 12)\n * @param denominator - 1 | 4 | 8 | 16\n */\nfunction formatFractionalInch(inchValue: number, denominator: number): string {\n const whole = Math.floor(inchValue + 1e-9)\n const frac = inchValue - whole\n if (Math.abs(frac) < 1e-9) {\n return String(whole)\n }\n\n const numerator = Math.round(frac * denominator)\n if (numerator === 0) {\n return String(whole)\n }\n if (numerator === denominator) {\n return String(whole + 1)\n }\n\n const fraction = `${numerator}/${denominator}`\n // 整英寸与分数英寸用连字符连接,避免标签内折行,如 7-5/16\n return whole === 0 ? fraction : `${whole}-${fraction}`\n}\n\n/**\n * @param value - length in meters\n * @param unit - display unit\n * @param precision - for `m`: decimal places; for `ft`: inch fraction denominator (1 | 4 | 8 | 16)\n */\nexport function transformUnit(value: number, unit: 'm' | 'mm' | 'ft' = 'm', precision: number = 2) {\n let stringValue: string\n if (unit === 'm') {\n stringValue = value.toFixed(precision)\n if (parseFloat(stringValue) === 0) return\n return stringValue + 'm'\n } else if (unit === 'mm') {\n stringValue = (value * 1000).toFixed(0)\n if (stringValue === '0') return\n return stringValue + 'mm'\n } else if (unit === 'ft') {\n // precision as inch fraction denominator: 1\" / 1/4\" / 1/8\" / 1/16\"\n const denominator = precision === 4 || precision === 8 || precision === 16 ? precision : 1\n const totalInches = value / 0.0254\n const roundedTotalInches = Math.round(totalInches * denominator) / denominator\n if (roundedTotalInches === 0) return\n\n let foot = Math.floor(roundedTotalInches / 12)\n let inch = roundedTotalInches - foot * 12\n // 严格判断 inch 的值是否等于 12,达到了 12,那么英尺数(foot)就增加 1, 将英寸数(inch)清零,这样就不会出现 12-0″ 的情况\n if (Math.abs(inch - 12) < 1e-9) {\n foot += 1\n inch = 0\n }\n\n return `${foot}′${formatFractionalInch(inch, denominator)}″`\n }\n}\n\n// 转换平方\nexport function transformUnitSquare(value: number, unit: 'm' | 'mm' | 'ft' = 'm') {\n let stringValue: string\n if (unit === 'm') {\n stringValue = value.toFixed(2)\n if (stringValue === '0.00') return\n return stringValue + 'm²'\n } else if (unit === 'mm') {\n stringValue = (value * 1000 * 1000).toFixed(0)\n if (stringValue === '0') return\n return stringValue + 'mm²'\n } else if (unit === 'ft') {\n const stringValue = (value * 10.76).toFixed(1)\n if (stringValue === '0.0') return\n return stringValue + 'ft²'\n }\n}\n","import type * as THREE from 'three/webgpu'\n\nexport type RenderDomObjectType = THREE.Object3D & {\n _onAdded: () => void\n _onRemoved: () => void\n _onShowed: () => void\n _onHidden: () => void\n}\n\nexport class RenderDom {\n public static cacheObject = new Set<THREE.Object3D & RenderDomObjectType>()\n\n public static checkDomEveryFrameIsRunning = false\n\n public static checkDom(obj: RenderDomObjectType) {\n let object: THREE.Object3D = obj\n let visible = true\n while (object.parent) {\n if (visible === true && object.visible === false) {\n visible = false\n }\n object = object.parent\n }\n\n if (object.type === 'Scene') {\n obj._onAdded()\n if (visible) {\n obj._onShowed()\n } else {\n obj._onHidden()\n }\n } else {\n obj._onRemoved()\n }\n }\n\n public static checkDomEveryFrame() {\n if (RenderDom.checkDomEveryFrameIsRunning) return\n RenderDom.checkDomEveryFrameIsRunning = true\n RenderDom._checkDomEveryFrame()\n }\n\n public static _checkDomEveryFrame() {\n RenderDom.cacheObject.forEach((obj) => RenderDom.checkDom(obj))\n requestAnimationFrame(RenderDom._checkDomEveryFrame)\n }\n}\n","import type { BufferGeometry, Object3D } from 'three/webgpu'\n\n/** Keep object-origin sort keys without replacing precise per-object culling bounds. */\nexport function setObjectOriginSortBounds(geometry: BufferGeometry, objects: Object3D[]): void {\n if (!geometry.getAttribute('position')) {\n for (const object of objects) delete (object as Object3D & { boundingSphere?: unknown }).boundingSphere\n return\n }\n\n // Use the geometry's virtual methods: instanced LineGeometry bounds come from\n // segment endpoints, not its position attribute's screen-space quad.\n geometry.computeBoundingSphere()\n const bounds = geometry.boundingSphere.clone()\n geometry.computeBoundingBox()\n for (const object of objects) Object.assign(object, { boundingSphere: bounds.clone() })\n\n // Pinned r183 sorts on the geometry sphere but culls on an object's own sphere.\n geometry.boundingSphere.center.set(0, 0, 0)\n geometry.boundingSphere.radius = bounds.radius + bounds.center.length()\n}\n","\n\nimport * as THREE from 'three/webgpu'\nimport {\n DEFAULT_LINE_COLOR,\n DEFAULT_LINE_WIDTH,\n DEFAULT_HIGHLIGHT_OPACITY,\n type OcclusionStyle,\n type LineStyle,\n type LengthConfig,\n type DisplayInfoConfig,\n type Color,\n} from '../typings/style'\nimport { anyPositionToVector3, type AnyPositions } from '../../shared-utils/positionToVector3'\nimport { IObject3D } from '../../shared-utils/three/IObject3D'\nimport { notNil } from '../../shared-utils'\nimport type { PointsData } from '../utils/data'\nimport { LightTag } from '../../shared-utils/tag'\nimport { centerPoint } from '../../shared-utils/three/centerPoint'\nimport { getLengthHTML } from '../utils/Meshes/getLengthHTML'\nimport { localToWorld } from '../../shared-utils/three/applyObjectMatrixWorld'\nimport { getFiveFromParentChain } from '../../shared-utils/five/getFiveFromParentChain'\nimport type { Five } from '@realsee/five-webgpu'\nimport { LineGeometry } from '../../shared-utils/three/core/LineGeometry'\nimport { LineMaterial } from '../../shared-utils/three/core/LineMaterial'\nimport { THREE_Line2 } from '../../shared-utils/three/core/Line2'\nimport { LineMaterial2 } from '../../shared-utils/three/core/LineMaterial2'\nimport { transformUnit } from '../utils/unit'\nimport { RenderDom, type RenderDomObjectType } from '../utils/renderDom'\nimport { setObjectOriginSortBounds } from '../../shared-utils/three/setObjectOriginSortBounds'\n\nexport type LineMeshStyle = LineStyle & { dashed?: boolean } & OcclusionStyle & Partial<LengthConfig> & Partial<DisplayInfoConfig>\n\nexport type LineData = PointsData\n\nexport class LineMesh extends IObject3D implements RenderDomObjectType {\n public name = 'LineMesh'\n public type = 'Line2'\n public object?: THREE.Object3D\n public points: THREE.Vector3[] = []\n public doms: LightTag[] = []\n\n public get style(): LineMeshStyle {\n return {\n lineColor: this.color,\n lineWidth: this.lineWidth,\n lineOpacity: this.lineOpacity,\n dashed: this.dashed,\n occlusionVisibility: this.occlusionVisibility,\n occlusionMode: this.occlusionMode,\n lengthEnable: this.paramsStyle.lengthEnable,\n tip: this.paramsStyle.tip,\n }\n }\n\n public get lineOpacity() {\n return this.line1.material.opacity ?? this.paramsStyle.lineOpacity\n }\n\n public get lineWidth() {\n return this.line1.material.linewidth ?? this.paramsStyle.lineWidth\n }\n\n public get color() {\n return this.line1.material.three_color.clone()\n }\n\n public get dashed() {\n return this.paramsStyle.dashed\n }\n\n public get occlusionVisibility() {\n return this.paramsStyle.occlusionVisibility\n }\n\n public get occlusionMode() {\n return this.paramsStyle.occlusionMode\n }\n\n protected highlighted = false\n\n private get five(): Five | undefined {\n return getFiveFromParentChain(this)\n }\n\n public set geometry(geometry: LineGeometry) {\n this._geometry = geometry\n\n if (this.line1) this.line1.geometry = geometry\n if (this.line2) this.line2.geometry = geometry\n this.line1?.computeLineDistances()\n this.syncOriginSortBounds()\n }\n\n public get geometry() {\n return this._geometry\n }\n private _geometry: LineGeometry\n\n private originSort = false\n\n /** Opt in only saved ModelMaker edges; ordinary Sculpt lines keep their bounds. */\n public enableOriginSort(): void {\n if (this.originSort) return\n this.originSort = true\n this.syncOriginSortBounds()\n for (const line of [this.line1, this.line2]) {\n const raycast = line.raycast\n line.raycast = function (raycaster: THREE.Raycaster, intersects: THREE.Intersection[]): void {\n const geometry = this.geometry\n const sortBounds = geometry.boundingSphere\n const preciseBounds = (this as THREE_Line2 & { boundingSphere?: THREE.Sphere }).boundingSphere\n // Native Line2 expands its sphere by the screen-space line width using\n // distance from the camera. That calculation needs the precise sphere.\n if (preciseBounds) geometry.boundingSphere = preciseBounds\n try {\n raycast.call(this, raycaster, intersects)\n } finally {\n geometry.boundingSphere = sortBounds\n }\n }\n }\n }\n\n private syncOriginSortBounds(): void {\n if (!this.originSort || !this.line1 || !this.line2) return\n setObjectOriginSortBounds(this.line1.geometry, [this.line1, this.line2])\n }\n\n protected line1: THREE_Line2\n protected line2: THREE_Line2\n\n private opacityBeforeHighlight: number\n private colorBeforeHighlight: Color\n private paramsStyle: Partial<LineMeshStyle> = {}\n\n private lastRenderDomItem: string\n private lastFOV: number | undefined\n private fiveListenersInited = false\n private fiveRef?: Five\n\n private initFiveListeners() {\n const five = this.five\n if (!five || this.fiveListenersInited) return\n this.fiveListenersInited = true\n this.fiveRef = five\n const size = five.renderer?.getSize(new THREE.Vector2())\n if (size) this.setResolution(size.width, size.height)\n five.on('cameraUpdate', this.onCameraUpdate)\n five.on('cameraFovUpdate', this.onCameraUpdate)\n five.on('panoArrived', this.onPanoArrived)\n }\n\n private removeFiveListeners() {\n if (this.fiveRef) {\n this.fiveRef.off('cameraUpdate', this.onCameraUpdate)\n this.fiveRef.off('cameraFovUpdate', this.onCameraUpdate)\n this.fiveRef.off('panoArrived', this.onPanoArrived)\n this.fiveRef = undefined\n }\n this.fiveListenersInited = false\n }\n\n public constructor(params?: Partial<LineMeshStyle & LineData>) {\n super()\n\n this.paramsStyle = { dashed: false, lineOpacity: 1, ...params }\n\n this.geometry = new LineGeometry()\n\n const lineMaterialParams: ConstructorParameters<typeof LineMaterial>[0] = {\n color: new THREE.Color(params?.lineColor ?? DEFAULT_LINE_COLOR),\n linewidth: params?.lineWidth ?? DEFAULT_LINE_WIDTH,\n dashScale: 1,\n dashSize: 0.02,\n gapSize: 0.02,\n opacity: params?.lineOpacity ?? 1,\n depthWrite: false,\n transparent: true,\n }\n\n const lineMaterial1 = new LineMaterial({ ...lineMaterialParams, dashed: false, depthTest: true })\n const lineMaterial2 = new LineMaterial2({ ...lineMaterialParams, dashed: true, depthTest: false })\n\n this.line1 = new THREE_Line2(this.geometry, lineMaterial1)\n this.line2 = new THREE_Line2(this.geometry, lineMaterial2 as any)\n\n this.line1.renderOrder = 2\n this.line2.renderOrder = 2\n\n this.line1.name = 'line1'\n this.line2.name = 'line2'\n\n this.add(this.line1)\n\n this.initFiveListeners()\n\n if (params) this.setStyle(params)\n\n if (params?.points) {\n this.setPoints(params.points)\n }\n\n this.addEventListener('removed', () => {\n this.removeFiveListeners()\n RenderDom.cacheObject.delete(this)\n RenderDom.checkDom(this)\n })\n this.addEventListener('added', () => {\n this.initFiveListeners()\n RenderDom.cacheObject.add(this)\n })\n\n RenderDom.checkDomEveryFrame()\n }\n\n public updateMatrixWorld(force?: boolean) {\n super.updateMatrixWorld(force)\n if (this.points) {\n const lastRenderDomItem = localToWorld(this, this.points)\n ?.map((p) => p.toArray().join(','))\n .join(',')\n if (lastRenderDomItem !== this.lastRenderDomItem) {\n this.updateDomItems()\n this.lastRenderDomItem = lastRenderDomItem\n }\n }\n }\n\n public setPoints(points: AnyPositions) {\n if (this.points.length === 0 && points.length === 0) {\n this.syncOriginSortBounds()\n return\n }\n\n const vectors = points.map(anyPositionToVector3).filter(notNil)\n this.points = vectors\n\n if (vectors.length < 2) {\n const lineGeometry = new LineGeometry()\n this.line1.geometry = lineGeometry\n this.line2.geometry = lineGeometry\n this.syncOriginSortBounds()\n this.updateDomItems()\n return\n }\n\n const positions = vectors.flatMap((v) => [v.x, v.y, v.z])\n\n // Five bug, 当前要设置的 positions 的数量大于上次设置的数量时,只能销毁重建,否则多出来的点不会展示\n // 基于以上原因,普通的线段(非折线)不会触发此 bug,所以做一下过滤\n if (positions.length > 2) {\n this.line1.geometry.dispose()\n const lineGeometry = new LineGeometry()\n this.line1.geometry = lineGeometry\n this.line2.geometry = lineGeometry\n }\n this.line1.geometry.setPositions(positions)\n\n // 不能删,删了虚线不生效\n this.line1.computeLineDistances()\n this.syncOriginSortBounds()\n\n this.updateDomItems()\n\n this.needsRender = true\n }\n\n public setResolution(width: number, height: number) {\n const resolution = this.line1.material.resolution\n if (resolution.x !== width || resolution.y !== height) {\n resolution.set(width, height)\n this.needsRender = true\n }\n const resolution2 = this.line2.material.resolution\n if (resolution2.x !== width || resolution2.y !== height) {\n resolution2.set(width, height)\n this.needsRender = true\n }\n }\n\n public setStyle(params: Partial<LineMeshStyle>) {\n this.paramsStyle = { ...this.paramsStyle, ...params }\n if (notNil(params.lineColor)) {\n const color = new THREE.Color(params.lineColor)\n this.line1.material.three_color = color\n this.line2.material.three_color = color\n }\n if (notNil(params.lineWidth)) {\n this.line1.material.linewidth = params.lineWidth\n this.line2.material.linewidth = params.lineWidth\n }\n if (notNil(params.dashed)) {\n this.line1.material.dashed = params.dashed\n }\n if (notNil(params.lineOpacity)) {\n this.line1.material.opacity = params.lineOpacity\n this.line2.material.opacity = params.lineOpacity\n }\n\n this.updateDomItems({ force: true })\n\n const occlusionVisibility = params.occlusionVisibility ?? this.paramsStyle.occlusionVisibility ?? true\n const occlusionMode = params.occlusionMode ?? this.paramsStyle.occlusionMode ?? 'translucence'\n\n if (occlusionVisibility) {\n if (this.dashed) {\n this.remove(this.line2)\n this.line1.material.dashed = true\n this.line1.material.depthTest = false\n } else if (occlusionMode === 'depthTest') {\n this.remove(this.line2)\n this.line1.material.dashed = false\n this.line1.material.depthTest = false\n } else if (occlusionMode === 'translucence') {\n this.line1.material.depthTest = true\n this.line2.material.depthTest = false\n this.line1.material.dashed = true\n this.line2.material.dashed = true\n this.addIfNotExists(this.line2)\n }\n } else {\n this.remove(this.line2)\n this.line1.material.depthTest = true\n this.line1.material.dashed = this.paramsStyle.dashed\n }\n this.doms.forEach((dom) => (dom.intersectCheck = !occlusionVisibility))\n\n this.needsRender = true\n }\n\n public highlight(params?: { color?: Color }) {\n this.highlighted = true\n\n if (params?.color) {\n const color = new THREE.Color(params.color)\n this.colorBeforeHighlight = this.colorBeforeHighlight ?? this.line1.material.three_color.clone()\n this.line1.material.three_color = color\n this.line2.material.three_color = color\n } else {\n this.opacityBeforeHighlight = this.opacityBeforeHighlight ?? this.line1.material.opacity\n const highlightOpacity = this.opacityBeforeHighlight * DEFAULT_HIGHLIGHT_OPACITY\n this.line1.material.opacity = highlightOpacity\n this.line2.material.opacity = highlightOpacity\n }\n\n this.needsRender = true\n }\n\n public unhighlight() {\n if (!this.highlighted) return\n this.highlighted = false\n\n if (notNil(this.opacityBeforeHighlight)) {\n this.line1.material.opacity = this.opacityBeforeHighlight\n this.line2.material.opacity = this.line1.material.opacity\n this.opacityBeforeHighlight = undefined\n }\n\n if (notNil(this.colorBeforeHighlight)) {\n this.line1.material.three_color = this.colorBeforeHighlight\n this.line2.material.three_color = this.colorBeforeHighlight\n this.colorBeforeHighlight = undefined\n }\n\n this.needsRender = true\n }\n\n public _onAdded = () => {\n if (this.doms.length === 0 && this.paramsStyle.lengthEnable) this.updateDomItems()\n }\n\n public _onRemoved = () => {\n this.doms.forEach((dom) => dom.destroy())\n this.doms = []\n }\n\n public _onShowed = () => {\n this.doms.forEach((dom) => (dom.container.style.display = 'block'))\n }\n\n public _onHidden = () => {\n this.doms.forEach((dom) => (dom.container.style.display = 'none'))\n }\n\n private updateDomItems(params?: { force?: boolean }) {\n const clear = () => {\n this.doms.forEach((dom) => dom.destroy())\n this.doms = []\n }\n\n if (!this.points || this.points.length < 2) return clear()\n if (!this.paramsStyle.lengthEnable && !this.paramsStyle.tip) return clear()\n\n if (!this.five) return console.error('Five not found')\n\n const lines = this.points\n .map((p, i) => {\n if (i !== 0) return [this.points[i - 1], p]\n return null\n })\n .filter(notNil)\n .map((p) => localToWorld(this, p))\n\n lines.forEach(([p0, p1], i) => {\n const tagPosition = centerPoint(p0, p1)\n this.doms[i] =\n this.doms[i] ??\n (() => {\n const tag = new LightTag(this.five)\n const occlusionVisibility = this.paramsStyle.occlusionVisibility ?? true\n tag.intersectCheck = !occlusionVisibility\n tag.simulate3D = true\n return tag\n })()\n this.doms[i].setPosition(tagPosition, [p0, p1])\n\n const render = (str: string | HTMLElement | null, params?: { force?: boolean }) => {\n const force = params?.force ?? false\n if ((this.doms[i] as any).__text === str && !force) return\n ;(this.doms[i] as any).__text = str\n\n if (str instanceof HTMLElement) {\n this.doms[i].container.innerHTML = ''\n this.doms[i].container.appendChild(str)\n } else if (str) {\n // Calculate the line length on screen\n const screenLineLength = (() => {\n if (!this.five || !this.five.camera) return 0\n\n // Get the screen coordinates of both points\n const fiveElement = this.five.getElement()\n if (!fiveElement) return 0\n\n const screenWidth = fiveElement.clientWidth\n const screenHeight = fiveElement.clientHeight\n const halfScreenWidth = screenWidth / 2\n const halfScreenHeight = screenHeight / 2\n\n // Project the line endpoints to screen coordinates\n const ndcP0 = p0.clone().project(this.five.camera)\n const ndcP1 = p1.clone().project(this.five.camera)\n\n // Convert to screen coordinates\n const screenP0 = {\n x: ndcP0.x * halfScreenWidth,\n y: ndcP0.y * halfScreenHeight,\n }\n const screenP1 = {\n x: ndcP1.x * halfScreenWidth,\n y: ndcP1.y * halfScreenHeight,\n }\n\n // Calculate the distance between points on screen\n return Math.sqrt(Math.pow(screenP1.x - screenP0.x, 2) + Math.pow(screenP1.y - screenP0.y, 2))\n })()\n\n // Calculate distance-based scale factor\n const distanceToCamera = (() => {\n if (!this.five || !this.five.camera) return 20 // Default distance\n const center = centerPoint(p0, p1)\n return center.distanceTo(this.five.camera.position)\n })()\n\n // Include FOV in scale calculation\n const fov = this.five?.camera?.fov || 60\n const sseDenominator = 2.0 * Math.tan(((0.5 * fov) / 180) * Math.PI)\n const scaleFactor = Math.max(Math.min(1 - (sseDenominator * distanceToCamera) / 40, 1), 0)\n const distanceStyle = `--distance-scale: ${scaleFactor};`\n\n // Get approximate text width (creating temporary element to measure)\n const getTextWidth = (text: string) => {\n const tempElement = document.createElement('div')\n tempElement.classList.add('LineLengthTag')\n tempElement.style.visibility = 'hidden'\n tempElement.style.position = 'absolute'\n tempElement.style.padding = '2px 8px'\n tempElement.style.fontFamily = 'Arial-BoldMT'\n tempElement.style.fontSize = '14px'\n tempElement.innerText = text\n document.body.appendChild(tempElement)\n const width = tempElement.offsetWidth\n document.body.removeChild(tempElement)\n return width\n }\n\n // Calculate if we need to offset the text vertically\n let offsetY = 0\n const textWidth = getTextWidth(str)\n if (screenLineLength > 0 && textWidth > screenLineLength) {\n offsetY = -20 // Move label above the line if it's too short\n }\n\n // Render with potential offset\n this.doms[i].container.innerHTML = getLengthHTML(str, {\n style: `${distanceStyle} ${this.paramsStyle.cssStyle || ''}`,\n offsetY: offsetY,\n })\n } else {\n this.doms[i].container.innerHTML = ''\n }\n }\n\n if (this.paramsStyle.tip) {\n render(this.paramsStyle.tip, params)\n } else {\n const length = transformUnit(p0.distanceTo(p1), this.paramsStyle.lengthUnit, this.paramsStyle.precision)\n if (!length) {\n render(null, params)\n } else {\n render(length, params)\n }\n }\n })\n\n if (this.doms.length > lines.length) {\n this.doms.slice(lines.length).forEach((dom) => dom.destroy())\n this.doms.length = lines.length\n }\n }\n\n // Handle camera updates (zoom changes)\n private onCameraUpdate = () => {\n if (this.five?.camera && this.lastFOV !== this.five.camera.fov) {\n this.lastFOV = this.five.camera.fov\n this.updateDomItems({ force: true })\n }\n }\n\n // Handle panorama point changes\n private onPanoArrived = () => {\n // Force update on panorama change to recalculate distances\n setTimeout(() => this.updateDomItems({ force: true }), 100)\n }\n}\n","import type * as THREE from 'three/webgpu'\nimport { Vector3 } from 'three/webgpu'\nimport { centerPoint } from './centerPoint'\n\nexport function getGeometryArea(geometry: THREE.BufferGeometry) {\n const area = getGeometryTriangles(geometry).reduce((acc, [p1, p2, p3]) => acc + triangleArea(p1, p2, p3), 0)\n return area\n}\n\nexport function getGeometryInfo(geometry: THREE.BufferGeometry): { center: Vector3; area: number } | undefined {\n const triangles = getGeometryTriangles(geometry)\n\n if (triangles.length === 0) {\n return\n }\n\n let area = 0\n let center = new Vector3()\n\n for (const [p1, p2, p3] of triangles) {\n const triArea = triangleArea(p1, p2, p3)\n const triCenter = triangleCenter(p1, p2, p3, triArea)\n\n area += triArea\n center.add(triCenter)\n }\n\n if (area <= 0 || !Number.isFinite(area)) return\n center = center.divideScalar(area)\n\n return { center, area }\n}\n\n/**\n * @description: 计算三角形的面积\n */\nexport function triangleArea(p1: Vector3, p2: Vector3, p3: Vector3): number {\n return p2.clone().sub(p1).cross(p3.clone().sub(p1)).length() / 2\n}\n\n/**\n * @description: 计算三角形的质心\n */\n\nexport function triangleCenter(p1: Vector3, p2: Vector3, p3: Vector3, area?: number): Vector3 {\n const triArea = area ?? triangleArea(p1, p2, p3)\n return centerPoint(p1, p2, p3).multiplyScalar(triArea)\n}\n\n/**\n * @description: 获取几何体的三角形\n */\nfunction getGeometryTriangles(geometry: THREE.BufferGeometry): [Vector3, Vector3, Vector3][] {\n const positions = geometry.getAttribute('position')\n const indices = geometry.getIndex()?.array\n\n if (!positions) return []\n const vertexIndices = indices ?? Array.from({ length: positions.count }, (_, index) => index)\n\n let triangles = []\n\n for (let i = 0; i + 2 < vertexIndices.length; i += 3) {\n // 顶点三角形的顶点的索引\n const i0 = vertexIndices[i]\n const i1 = vertexIndices[i + 1]\n const i2 = vertexIndices[i + 2]\n\n // 根据顶点的索引获取三角形的三个顶点\n const p1 = new Vector3().fromArray([positions.getX(i0), positions.getY(i0), positions.getZ(i0)])\n const p2 = new Vector3().fromArray([positions.getX(i1), positions.getY(i1), positions.getZ(i1)])\n const p3 = new Vector3().fromArray([positions.getX(i2), positions.getY(i2), positions.getZ(i2)])\n\n triangles.push([p1, p2, p3])\n }\n\n return triangles\n}\n","/**\n * A vertex in a circular doubly linked list representing a polygon ring.\n * `prev`/`next` are always linked (set immediately after {@link createNode}), so they're typed\n * non-null; `prevZ`/`nextZ` are the z-order list links and are null at the ends.\n *\n * @typedef {object} Node\n * @property {number} i vertex index in the coordinates array\n * @property {number} x vertex x coordinate\n * @property {number} y vertex y coordinate\n * @property {Node} prev previous vertex node in the polygon ring\n * @property {Node} next next vertex node in the polygon ring\n * @property {number} z z-order curve value; doubles as the owning block index during eliminateHoles\n * @property {Node | null} prevZ previous node in z-order\n * @property {Node | null} nextZ next node in z-order\n */\n\n// single-vertex holes to preserve through filterPoints (steiner points); kept off the Node\n// shape since they're rare — the empty-set fast path means non-steiner inputs pay nothing\n/** @type {Set<Node>} */\nconst steiners = new Set();\n\n// set by filterPoints whenever it removes at least one node; read by earcutLinked's stall\n// handler to decide whether another clip pass is worth attempting before the costlier stages\nlet filteredOut = false;\n\n/**\n * Triangulate a polygon given as a flat array of vertex coordinates.\n *\n * @param {ArrayLike<number>} data flat array of vertex coordinates\n * @param {ArrayLike<number> | null} [holeIndices] indices (in vertices, not coordinates) where each hole ring starts\n * @param {number} [dim=2] number of coordinates per vertex in `data`\n * @returns {number[]} triangles as triplets of vertex indices into `data`\n * @example earcut([10,0, 0,50, 60,60, 70,10]); // [1,0,3, 3,2,1]\n */\nexport default function earcut(data, holeIndices, dim = 2) {\n\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n if (steiners.size) steiners.clear();\n\n let outerNode = linkedList(data, 0, outerLen, dim, true);\n /** @type {number[]} */\n const triangles = [];\n\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n let minX = 0, minY = 0, invSize = 0;\n\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n if (data.length > 80 * dim) {\n minX = data[0];\n minY = data[1];\n let maxX = minX;\n let maxY = minY;\n\n for (let i = dim; i < outerLen; i += dim) {\n const x = data[i];\n const y = data[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n invSize = Math.max(maxX - minX, maxY - minY);\n invSize = invSize !== 0 ? 32767 / invSize : 0;\n }\n\n earcutLinked(outerNode, triangles, minX, minY, invSize);\n\n return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\n/** @param {ArrayLike<number>} data @param {number} start @param {number} end @param {number} dim @param {boolean} clockwise @returns {Node | null} */\nfunction linkedList(data, start, end, dim, clockwise) {\n /** @type {Node | null} */\n let last = null;\n\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n } else {\n for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n }\n\n if (last && equals(last, last.next)) {\n removeNode(last);\n last = last.next;\n }\n\n return last;\n}\n\n// Remove collinear or coincident points; removability depends only on a node's immediate\n// neighbors, so we sweep forward and re-check the predecessor after each removal. With no `end`\n// we sweep the whole ring, lapping until nothing is removable (the fixpoint the clipper needs).\n// With an explicit `end` we heal only the dirty window around a bridge/diagonal cut, stopping at\n// `end` rather than lapping — O(window) instead of O(ring).\n/** @param {Node} start @param {Node} [end] @returns {Node} */\nfunction filterPoints(start, end = start) {\n const full = end === start;\n\n let p = start, again;\n do {\n again = false;\n if (p !== p.next && (steiners.size === 0 || !steiners.has(p)) &&\n (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n if (full || p === end) end = p.prev; // pull the stop bound back past the removal\n filteredOut = true;\n removeNode(p);\n p = p.prev; // re-check the predecessor\n again = true;\n } else if (full || p !== end) {\n p = p.next;\n again = !full; // local heal: keep looping until the sweep reaches end\n }\n } while (again || p !== end);\n\n return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\n/** @param {Node} ear @param {number[]} triangles @param {number} minX @param {number} minY @param {number} invSize */\nfunction earcutLinked(ear, triangles, minX, minY, invSize) {\n // interlink polygon nodes in z-order\n if (invSize) indexCurve(ear, minX, minY, invSize);\n\n let stop = ear, cured = false;\n\n // iterate through ears, slicing them one by one\n while (ear.prev !== ear.next) {\n const prev = ear.prev;\n /** @type {Node} */\n const next = ear.next;\n\n if (area(prev, ear, next) < 0 && (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear))) {\n triangles.push(prev.i, ear.i, next.i); // cut off the triangle\n\n removeNode(ear);\n ear = next;\n stop = next;\n continue;\n }\n\n ear = next;\n\n // if we looped through the whole remaining polygon and can't find any more ears\n if (ear === stop) {\n // try filtering collinear/coincident points and slicing again — repeat as long as\n // filtering actually removes nodes, since each removal can expose new ears\n filteredOut = false;\n ear = filterPoints(ear);\n if (filteredOut) { stop = ear; continue; }\n\n // filtering is exhausted: cure small local self-intersections once, then retry\n if (!cured) {\n ear = cureLocalIntersections(ear, triangles);\n stop = ear;\n cured = true;\n continue;\n }\n\n // as a last resort, try splitting the remaining polygon into two\n splitEarcut(ear, triangles, minX, minY, invSize);\n break;\n }\n }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\n/** @param {Node} ear @returns {boolean} */\nfunction isEar(ear) {\n // reflex check (area(a, b, c) >= 0) is hoisted into the earcutLinked caller to avoid non-inlined call here\n const a = ear.prev, b = ear, c = ear.next,\n ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y,\n x0 = Math.min(ax, bx, cx), // triangle bbox\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy);\n\n // make sure we don't have other points inside the potential ear\n let p = c.next;\n while (p !== a) {\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && !(ax === p.x && ay === p.y) &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.next;\n }\n return true;\n}\n\n/** @param {Node} ear @param {number} minX @param {number} minY @param {number} invSize @returns {boolean} */\nfunction isEarHashed(ear, minX, minY, invSize) {\n // reflex check is hoisted into the earcutLinked caller (see isEar)\n const a = ear.prev, b = ear, c = ear.next,\n ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y,\n x0 = Math.min(ax, bx, cx), // triangle bbox\n y0 = Math.min(ay, by, cy),\n x1 = Math.max(ax, bx, cx),\n y1 = Math.max(ay, by, cy),\n minZ = zOrder(x0, y0, minX, minY, invSize), // z-order range for the current triangle bbox;\n maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n let p = ear.prevZ;\n while (p && p.z >= minZ) { // look for points inside the triangle in decreasing z-order\n if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== c && !(ax === p.x && ay === p.y) &&\n pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n p = p.prevZ;\n }\n let n = ear.nextZ;\n while (n && n.z <= maxZ) { // look for points in increasing z-order\n if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== c && !(ax === n.x && ay === n.y) &&\n pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n n = n.nextZ;\n }\n return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\n/** @param {Node} start @param {number[]} triangles @returns {Node} */\nfunction cureLocalIntersections(start, triangles) {\n let p = start;\n let cured = false;\n do {\n const a = p.prev,\n b = p.next.next;\n\n if (intersects(a, p, p.next, b, false) && locallyInside(a, b) && locallyInside(b, a)) {\n\n triangles.push(a.i, p.i, b.i);\n\n // remove two nodes involved\n removeNode(p);\n removeNode(p.next);\n\n p = start = b;\n cured = true;\n }\n p = p.next;\n } while (p !== start);\n\n return cured ? filterPoints(p) : p;\n}\n\n// try splitting polygon into two and triangulate them independently\n/** @param {Node} start @param {number[]} triangles @param {number} minX @param {number} minY @param {number} invSize */\nfunction splitEarcut(start, triangles, minX, minY, invSize) {\n // look for a valid diagonal that divides the polygon into two\n let a = start;\n do {\n let b = a.next.next;\n while (b !== a.prev) {\n if (a.i !== b.i && isValidDiagonal(a, b)) {\n // split the polygon in two by the diagonal\n let c = splitPolygon(a, b);\n\n // filter colinear points around the cuts\n a = filterPoints(a, a.next);\n c = filterPoints(c, c.next);\n\n // run earcut on each half\n earcutLinked(a, triangles, minX, minY, invSize);\n earcutLinked(c, triangles, minX, minY, invSize);\n return;\n }\n b = b.next;\n }\n a = a.next;\n } while (a !== start);\n}\n\n// true only while eliminateHoles merges holes, so removeNode keeps the block index live (growBlock)\nlet indexActive = false;\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\n/** @param {ArrayLike<number>} data @param {ArrayLike<number>} holeIndices @param {Node} outerNode @param {number} dim @returns {Node} */\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n const queue = [];\n\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n const list = /** @type {Node} */ (linkedList(data, start, end, dim, false));\n if (list === list.next) steiners.add(list);\n queue.push(getLeftmost(list));\n }\n\n queue.sort(compareXYSlope);\n\n // block-bbox index for findHoleBridge, grown append-only as holes merge (see notes\n // above buildBlockIndex). Seed it with the outer ring, then append each merged hole.\n buildBlockIndex(data.length / dim, holeIndices.length);\n indexSegment(outerNode, outerNode);\n\n // process holes from left to right; indexActive lets removeNode keep block bboxes live as\n // filterPoints heals edges during merges (see growBlock)\n indexActive = true;\n for (let i = 0; i < queue.length; i++) {\n outerNode = eliminateHole(queue[i], outerNode);\n }\n indexActive = false;\n\n // collapse collinear/coincident points across the whole merged ring once before clipping\n return filterPoints(outerNode);\n}\n\n/** @param {Node} a @param {Node} b @returns {number} */\nfunction compareXYSlope(a, b) {\n // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find\n // the bridge to the outer shell is always the point that they meet at.\n return a.x - b.x || a.y - b.y ||\n (a.next.y - a.y) / (a.next.x - a.x) -\n (b.next.y - b.y) / (b.next.x - b.x);\n}\n\n// find a bridge between vertices that connects hole with an outer ring and link it\n/** @param {Node} hole @param {Node} outerNode @returns {Node} */\nfunction eliminateHole(hole, outerNode) {\n const bridge = findHoleBridge(hole, outerNode);\n if (!bridge) {\n return outerNode;\n }\n\n const bridgeReverse = splitPolygon(bridge, hole);\n\n // index the merged-in segment before filtering: in ring order the splice runs\n // bridge -> hole -> bridgeReverse -> bridge2 -> (bridge's old next), covering the\n // hole's edges and both new slit edges. filterPoints below only drops collinear /\n // coincident points, so these bboxes stay valid (conservative) supersets.\n const bridge2 = bridgeReverse.next;\n indexSegment(bridge, bridge2.next);\n\n // heal collinear/coincident points around the two new slit edges\n filterPoints(bridgeReverse, bridgeReverse.next);\n return filterPoints(bridge, bridge.next);\n}\n\n// Block-bbox index for findHoleBridge (issue #183): one [minX,minY,maxX,maxY] bbox per K\n// consecutive ring edges, in a flat Float64Array, so the leftward-ray scan can skip whole\n// blocks in O(1) instead of walking the entire merged ring. Grown append-only — the outer\n// ring seeds it, then each merged hole appends a segment (head node, stop node, K-blocks\n// over head..stop); independent segments, not a ring tiling, since splices land mid-ring.\n// Buffers are sized once from the input upper bound and reused across calls.\n//\n// filterPoints only drops collinear/coincident points, so a stale bbox stays a conservative\n// superset of its live edges (never a false skip); the scan skips dead nodes (p.prev.next !==\n// p) and lazily advances a dead stop. Blocks are scanned in append (not ring) order, so the\n// chosen bridge can differ from the un-indexed code — a different but equally valid result.\nconst K = 16; // edges per block\n\nlet blockBBox = new Float64Array(0); // [minX,minY,maxX,maxY] per block\nlet numBlocks = 0;\n/** @type {Node[]} */\nconst blockHead = []; // first node of each block's segment\n/** @type {Node[]} */\nconst blockStop = []; // node just past each block's segment (exclusive walk bound)\n\n/** @param {number} maxNodes @param {number} numHoles */\nfunction buildBlockIndex(maxNodes, numHoles) {\n // upper bound: every input node indexed once, +2 bridge nodes per hole, plus a partial\n // trailing block per appended segment (outer ring + one per hole)\n const maxBlocks = Math.ceil((maxNodes + 2 * numHoles) / K) + numHoles + 2;\n if (blockBBox.length < maxBlocks * 4) blockBBox = new Float64Array(maxBlocks * 4);\n numBlocks = 0;\n}\n\n// index the ring run head..stop (exclusive) as ceil(len / K) blocks; head === stop means\n// the whole ring. each block's bbox covers both endpoints of every edge it owns.\n/** @param {Node} head @param {Node} stop */\nfunction indexSegment(head, stop) {\n let p = head;\n do {\n const b = numBlocks++;\n blockHead[b] = p;\n let minX = p.x, minY = p.y, maxX = p.x, maxY = p.y;\n let k = 0;\n do {\n const c = p.next; // edge p->c; bbox must bound both endpoints\n p.z = b; // reuse z as the owning block during eliminateHoles (see growBlock)\n if (c.x < minX) minX = c.x; if (c.x > maxX) maxX = c.x;\n if (c.y < minY) minY = c.y; if (c.y > maxY) maxY = c.y;\n p = c;\n } while (++k < K && p !== stop);\n blockStop[b] = p;\n const g = b * 4;\n blockBBox[g] = minX; blockBBox[g + 1] = minY; blockBBox[g + 2] = maxX; blockBBox[g + 3] = maxY;\n } while (p !== stop);\n}\n\n// when filterPoints heals an edge head->tail (removing the collinear node between them), the\n// healed edge can extend past head's frozen block bbox if its old far endpoint lived in another\n// block; grow head's block bbox to cover tail so the leftward-ray prune can't false-skip it.\n/** @param {Node} head @param {Node} tail */\nfunction growBlock(head, tail) {\n const g = head.z * 4;\n if (tail.x < blockBBox[g]) blockBBox[g] = tail.x;\n if (tail.y < blockBBox[g + 1]) blockBBox[g + 1] = tail.y;\n if (tail.x > blockBBox[g + 2]) blockBBox[g + 2] = tail.x;\n if (tail.y > blockBBox[g + 3]) blockBBox[g + 3] = tail.y;\n}\n\n/** @param {number} b @returns {Node} */\nfunction liveBlockStop(b) {\n let stop = blockStop[b];\n while (stop.prev.next !== stop) stop = stop.next;\n blockStop[b] = stop;\n return stop;\n}\n\n// the block's head node can be removed by filterPoints during merges; advance it to the next\n// live node so the walk doesn't start on (and immediately terminate at) a dead node. For the\n// single full-ring seed block (head === stop) the same forward advance keeps them equal, so the\n// do-while still laps the whole ring instead of collapsing to an empty walk.\n/** @param {number} b @returns {Node} */\nfunction liveBlockHead(b) {\n let head = blockHead[b];\n while (head.prev.next !== head) head = head.next;\n blockHead[b] = head;\n return head;\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\n/** @param {Node} hole @param {Node} outerNode @returns {Node | null} */\nfunction findHoleBridge(hole, outerNode) {\n let p = outerNode;\n const hx = hole.x;\n const hy = hole.y;\n let qx = -Infinity;\n /** @type {Node | undefined} */\n let m;\n\n // find a segment intersected by a ray from the hole's leftmost point to the left;\n // segment's endpoint with lesser x will be potential connection point\n // unless they intersect at a vertex, then choose the vertex\n if (equals(hole, p)) return p;\n\n // scan blocks; skip any whose bbox can't hold a crossing that beats qx and lies left\n // of hx (the prune Morton order can't express — explicit per-axis [minY,maxY]/[minX,maxX])\n for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {\n if (hy < blockBBox[g + 1] || hy > blockBBox[g + 3] || blockBBox[g] > hx || blockBBox[g + 2] <= qx) continue;\n\n // ensure the walk's exclusive bound is live so we don't overrun into other blocks\n const stop = liveBlockStop(b);\n\n p = liveBlockHead(b);\n do {\n if (p.prev.next === p) { // skip nodes removed by filterPoints (stale in the index)\n if (equals(hole, p.next)) return p.next;\n else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n if (x <= hx && x > qx) {\n qx = x;\n m = p.x < p.next.x ? p : p.next;\n if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n }\n }\n }\n p = p.next;\n } while (p !== stop);\n }\n\n if (!m) return null;\n\n // look for points inside the triangle of hole point, segment intersection and endpoint;\n // if there are no points found, we have a valid connection;\n // otherwise choose the point of the minimum angle with the ray as connection point\n\n const mx = m.x;\n const my = m.y;\n const tminY = Math.min(hy, my); // the triangle's y span; x span is [mx, hx]\n const tmaxY = Math.max(hy, my);\n let tanMin = Infinity;\n\n // scan the same blocks; skip any whose bbox can't overlap the triangle's [mx,hx]×[tminY,tmaxY] box\n for (let b = 0, g = 0; b < numBlocks; b++, g += 4) {\n if (blockBBox[g + 2] < mx || blockBBox[g] > hx || blockBBox[g + 3] < tminY || blockBBox[g + 1] > tmaxY) continue;\n\n const stop = liveBlockStop(b);\n\n p = liveBlockHead(b);\n do {\n if (p.prev.next === p && hx >= p.x && p.x >= mx && hx !== p.x && // skip dead nodes\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n // if hole point sits on p's horizontal edge (T-junction touch): the bridge runs\n // along that edge — locallyInside rejects it as collinear, but it's valid\n if ((locallyInside(p, hole) || (p.y === hy && p.next.y === hy && p.next.x > hx)) &&\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n m = p;\n tanMin = tan;\n }\n }\n\n p = p.next;\n } while (p !== stop);\n }\n\n return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\n/** @param {Node} m @param {Node} p @returns {boolean} */\nfunction sectorContainsSector(m, p) {\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// scratch buffers reused across calls and grown on demand: two node-ref arrays that\n// ping-pong during the radix passes, plus parallel z-value arrays so the passes read\n// z from contiguous memory instead of dereferencing each node. 256-entry histogram for\n// 8-bit digits; the small histogram keeps per-call setup cheap (most rings are short)\n/** @type {Node[]} */\nconst sortArr = [];\n/** @type {Node[]} */\nlet sortBuf = [];\nlet zArr = new Uint32Array(0);\nlet zBuf = new Uint32Array(0);\nconst counts = new Uint32Array(256);\n\n// interlink polygon nodes in z-order: collect into an array, sort by z, relink\n/** @param {Node} start @param {number} minX @param {number} minY @param {number} invSize */\nfunction indexCurve(start, minX, minY, invSize) {\n let p = start;\n let n = 0;\n do {\n // always (re)compute: z may still hold a block index left over from eliminateHoles\n p.z = zOrder(p.x, p.y, minX, minY, invSize);\n sortArr[n++] = p;\n p = p.next;\n } while (p !== start);\n\n sortNodes(n);\n\n /** @type {Node | null} */\n let prev = null;\n for (let i = 0; i < n; i++) {\n const node = sortArr[i];\n node.prevZ = prev;\n if (prev) prev.nextZ = node;\n prev = node;\n }\n /** @type {Node} */ (prev).nextZ = null;\n\n // drop the node refs but keep the capacity: setting length to 0 leaves sortBuf unresized\n // (its growth is gated on zArr), so the radix scatter regrows it out of order every call\n sortArr.fill(/** @type {Node} */ (/** @type {unknown} */ (null)), 0, n);\n sortBuf.fill(/** @type {Node} */ (/** @type {unknown} */ (null)), 0, n);\n}\n\n// sort the first n nodes of sortArr by z, in place: insertion sort for small n (cheaper\n// than histogram setup), else LSD radix in four 8-bit passes (covering z's 30 bits)\n/** @param {number} n */\nfunction sortNodes(n) {\n if (n <= 32) {\n for (let i = 1; i < n; i++) {\n const node = sortArr[i], z = node.z;\n let j = i - 1;\n while (j >= 0 && sortArr[j].z > z) { sortArr[j + 1] = sortArr[j]; j--; }\n sortArr[j + 1] = node;\n }\n return;\n }\n\n if (zArr.length < n) {\n zArr = new Uint32Array(n);\n zBuf = new Uint32Array(n);\n sortBuf = new Array(n);\n }\n for (let i = 0; i < n; i++) zArr[i] = sortArr[i].z;\n\n // even pass count lands the sorted result back in sortArr\n radixPass(n, sortArr, zArr, sortBuf, zBuf, 0);\n radixPass(n, sortBuf, zBuf, sortArr, zArr, 8);\n radixPass(n, sortArr, zArr, sortBuf, zBuf, 16);\n radixPass(n, sortBuf, zBuf, sortArr, zArr, 24);\n}\n\n// one LSD radix pass: stably scatter the first n nodes (and their z) from src to dst,\n// bucketed by the 8-bit digit of z at the given bit shift\n/** @param {number} n @param {Node[]} src @param {Uint32Array} srcZ @param {Node[]} dst @param {Uint32Array} dstZ @param {number} shift */\nfunction radixPass(n, src, srcZ, dst, dstZ, shift) {\n counts.fill(0);\n for (let i = 0; i < n; i++) counts[(srcZ[i] >>> shift) & 0xff]++;\n // turn per-bucket counts into start offsets (prefix sum)\n let sum = 0;\n for (let b = 0; b < 256; b++) { const c = counts[b]; counts[b] = sum; sum += c; }\n for (let i = 0; i < n; i++) {\n const z = srcZ[i];\n const pos = counts[(z >>> shift) & 0xff]++;\n dst[pos] = src[i];\n dstZ[pos] = z;\n }\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\n/** @param {number} x @param {number} y @param {number} minX @param {number} minY @param {number} invSize @returns {number} */\nfunction zOrder(x, y, minX, minY, invSize) {\n // coords are transformed into non-negative 15-bit integer range\n x = (x - minX) * invSize | 0;\n y = (y - minY) * invSize | 0;\n\n x = (x | (x << 8)) & 0x00FF00FF;\n x = (x | (x << 4)) & 0x0F0F0F0F;\n x = (x | (x << 2)) & 0x33333333;\n x = (x | (x << 1)) & 0x55555555;\n\n y = (y | (y << 8)) & 0x00FF00FF;\n y = (y | (y << 4)) & 0x0F0F0F0F;\n y = (y | (y << 2)) & 0x33333333;\n y = (y | (y << 1)) & 0x55555555;\n\n return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\n/** @param {Node} start @returns {Node} */\nfunction getLeftmost(start) {\n let p = start,\n leftmost = start;\n do {\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n p = p.next;\n } while (p !== start);\n\n return leftmost;\n}\n\n// check if a point lies within a convex triangle\n/** @param {number} ax @param {number} ay @param {number} bx @param {number} by @param {number} cx @param {number} cy @param {number} px @param {number} py @returns {boolean} */\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\n/** @param {Node} a @param {Node} b @returns {boolean} true when the diagonal is valid */\nfunction isValidDiagonal(a, b) {\n const zeroLength = equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0; // degenerate case\n return a.next.i !== b.i && (zeroLength || locallyInside(a, b) && locallyInside(b, a) && // // locally visible\n (area(a.prev, a, b.prev) !== 0 || area(a, b.prev, b) !== 0)) && // no opposite-facing sectors\n !intersectsPolygon(a, b) && (zeroLength || middleInside(a, b)); // doesn't intersect other edges, diagonal inside polygon\n}\n\n// signed area of a triangle\n/** @param {Node} p @param {Node} q @param {Node} r @returns {number} */\nfunction area(p, q, r) {\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\n/** @param {Node} p1 @param {Node} p2 @returns {boolean} */\nfunction equals(p1, p2) {\n return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect; by default includes collinear boundary touches\n/** @param {Node} p1 @param {Node} q1 @param {Node} p2 @param {Node} q2 @param {boolean} [includeBoundary] @returns {boolean} */\nfunction intersects(p1, q1, p2, q2, includeBoundary = true) {\n const o1 = area(p1, q1, p2);\n const o2 = area(p1, q1, q2);\n const o3 = area(p2, q2, p1);\n const o4 = area(p2, q2, q1);\n\n if (((o1 > 0 && o2 < 0) || (o1 < 0 && o2 > 0)) && ((o3 > 0 && o4 < 0) || (o3 < 0 && o4 > 0))) return true;\n\n if (!includeBoundary) return false;\n\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\n/** @param {Node} p @param {Node} q @param {Node} r @returns {boolean} */\nfunction onSegment(p, q, r) {\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\n// check if a polygon diagonal intersects any polygon segments\n/** @param {Node} a @param {Node} b @returns {boolean} */\nfunction intersectsPolygon(a, b) {\n // diagonal bbox; an edge whose bbox can't overlap it can't intersect it, so\n // skip the orientation test for those (the common case — the diagonal is short)\n const minX = Math.min(a.x, b.x);\n const maxX = Math.max(a.x, b.x);\n const minY = Math.min(a.y, b.y);\n const maxY = Math.max(a.y, b.y);\n\n let p = a;\n do {\n const n = p.next;\n if ((p.x > maxX && n.x > maxX) || (p.x < minX && n.x < minX) ||\n (p.y > maxY && n.y > maxY) || (p.y < minY && n.y < minY)) {\n p = n;\n continue;\n }\n if (p.i !== a.i && n.i !== a.i && p.i !== b.i && n.i !== b.i &&\n intersects(p, n, a, b)) return true;\n p = n;\n } while (p !== a);\n\n return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\n/** @param {Node} a @param {Node} b @returns {boolean} */\nfunction locallyInside(a, b) {\n return area(a.prev, a, a.next) < 0 ?\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\n/** @param {Node} a @param {Node} b @returns {boolean} */\nfunction middleInside(a, b) {\n let p = a;\n let inside = false;\n const px = (a.x + b.x) / 2;\n const py = (a.y + b.y) / 2;\n do {\n const n = p.next;\n if (((p.y > py) !== (n.y > py)) && (px < (n.x - p.x) * (py - p.y) / (n.y - p.y) + p.x))\n inside = !inside;\n p = n;\n } while (p !== a);\n\n return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\n/** @param {Node} a @param {Node} b @returns {Node} */\nfunction splitPolygon(a, b) {\n const a2 = createNode(a.i, a.x, a.y),\n b2 = createNode(b.i, b.x, b.y),\n an = a.next,\n bp = b.prev;\n\n a.next = b;\n b.prev = a;\n\n a2.next = an;\n an.prev = a2;\n\n b2.next = a2;\n a2.prev = b2;\n\n bp.next = b2;\n b2.prev = bp;\n\n return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\n/** @param {number} i @param {number} x @param {number} y @param {Node | null} last @returns {Node} */\nfunction insertNode(i, x, y, last) {\n const p = createNode(i, x, y);\n\n if (!last) {\n p.prev = p;\n p.next = p;\n\n } else {\n p.next = last.next;\n p.prev = last;\n last.next.prev = p;\n last.next = p;\n }\n return p;\n}\n\n/** @param {Node} p */\nfunction removeNode(p) {\n p.next.prev = p.prev;\n p.prev.next = p.next;\n\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n\n // keep the hole-bridge index's block bboxes covering the healed prev->next edge\n if (indexActive) growBlock(p.prev, p.next);\n}\n\n/** @param {number} i @param {number} x @param {number} y @returns {Node} */\nfunction createNode(i, x, y) {\n // prev/next are assigned by the caller before any read, so the null init is cast away here\n return /** @type {Node} */ (/** @type {unknown} */ ({\n i, // vertex index in coordinates array\n x, y, // vertex coordinates\n prev: null, // previous and next vertex nodes in a polygon ring\n next: null,\n z: 0, // z-order curve value; doubles as owning block in the hole-bridge index during eliminateHoles\n prevZ: null, // previous and next nodes in z-order\n nextZ: null\n }));\n}\n\n/**\n * Return the relative difference between the polygon area and the area of its triangulation —\n * a value near 0 means a correct triangulation. Useful for verifying output in tests.\n *\n * @param {ArrayLike<number>} data\n * @param {ArrayLike<number> | null} holeIndices\n * @param {number} dim number of coordinates per vertex in `data`\n * @param {ArrayLike<number>} triangles output of {@link earcut}\n * @returns {number}\n * @example deviation(data, holes, dim, earcut(data, holes, dim)); // ~0 if correct\n */\nexport function deviation(data, holeIndices, dim, triangles) {\n const hasHoles = holeIndices && holeIndices.length;\n const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n let polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n if (hasHoles) {\n for (let i = 0, len = holeIndices.length; i < len; i++) {\n const start = holeIndices[i] * dim;\n const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\n }\n }\n\n let trianglesArea = 0;\n for (let i = 0; i < triangles.length; i += 3) {\n const a = triangles[i] * dim;\n const b = triangles[i + 1] * dim;\n const c = triangles[i + 2] * dim;\n trianglesArea += Math.abs(\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n }\n\n // with no triangles, a polygon area within shoelace roundoff of zero (which scales with the\n // squared coordinate magnitude) means the input was degenerate rather than mistriangulated\n if (trianglesArea === 0) {\n let max = 0;\n for (let i = 0; i < data.length; i += dim) max = Math.max(max, Math.abs(data[i]), Math.abs(data[i + 1]));\n return Math.abs(polygonArea) <= data.length * max * max * Number.EPSILON ? 0 : 1;\n }\n return Math.abs((trianglesArea - polygonArea) / polygonArea);\n}\n\n/** @param {ArrayLike<number>} data @param {number} start @param {number} end @param {number} dim @returns {number} */\nfunction signedArea(data, start, end, dim) {\n let sum = 0;\n for (let i = start, j = end - dim; i < end; i += dim) {\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n j = i;\n }\n return sum;\n}\n\n/**\n * Turn a polygon in multi-dimensional array form (e.g. as in GeoJSON) into the flat form Earcut accepts.\n *\n * @param {ReadonlyArray<ReadonlyArray<ArrayLike<number>>>} data array of rings; the first ring is the outer contour, the rest are holes\n * @returns {{vertices: number[], holes: number[], dimensions: number}}\n * @example const {vertices, holes, dimensions} = flatten(geojson.coordinates);\n */\nexport function flatten(data) {\n const vertices = [];\n const holes = [];\n const dimensions = data[0][0].length;\n let holeIndex = 0;\n let prevLen = 0;\n\n for (const ring of data) {\n for (const p of ring) {\n for (let d = 0; d < dimensions; d++) vertices.push(p[d]);\n }\n if (prevLen) {\n holeIndex += prevLen;\n holes.push(holeIndex);\n }\n prevLen = ring.length;\n }\n return {vertices, holes, dimensions};\n}\n\n// Reusable module-level scratch for refine():\n// he = twin half-edge of each edge, or -1 on the polygon boundary\n// hTable = open-addressing hash, slot -> half-edge index, valid iff hStamp[slot] === gen\n// edgeStamp = pending-in-stack flag, cleared when the edge is popped\n/** @type {Int32Array} */ let edgeStack;\n/** @type {Int32Array} */ let he;\n/** @type {Int32Array} */ let hTable;\n/** @type {Uint32Array} */ let hStamp;\n/** @type {Uint8Array} */ let edgeStamp;\nlet hMask = 0, gen = 0;\n\n/**\n * Refine a triangulation toward the constrained Delaunay triangulation by legalizing every\n * interior edge in place with Lawson flips — maximizing the minimum angle and removing most\n * slivers. An optional post-pass for {@link earcut} output, or any manifold triangle-index array\n * indexing into `coords`. Adapted from delaunator's edge legalization.\n *\n * Uses non-robust predicates: float input is fine, and the worst case is a not-quite-Delaunay\n * edge, never an invalid mesh.\n *\n * @param {number[]} triangles triangle indices, as returned by {@link earcut}; mutated in place\n * @param {ArrayLike<number>} coords the flat vertex coordinates passed to {@link earcut}\n * @param {number} [dim=2] number of coordinates per vertex in `coords`\n * @example refine(earcut(data), data);\n */\nexport function refine(triangles, coords, dim = 2) {\n const t = triangles;\n const n = t.length;\n if (n < 6) return;\n ensureScratch(n);\n gen++; // bumping the generation logically empties the hash (no clearing)\n he.fill(-1, 0, n);\n\n // Build half-edge twins with an undirected-edge hash; consumed slots mark linked pairs. As each\n // pair is linked we seed the stack with one representative (s, the earlier-inserted edge) — this\n // fuses the initial \"push every interior edge\" pass into the build, saving a full O(n) scan.\n // edgeStamp is all-zero here (balanced push/pop leaves it clean) and each pair links once, so\n // the seed write needs no dedup guard.\n let i = 0;\n for (let e = 0; e < n; e++) {\n const a = t[e], b = t[nextHE(e)];\n const lo = a < b ? a : b, hi = a < b ? b : a;\n let h = (Math.imul(lo, 0x9e3779b1) ^ Math.imul(hi, 0x85ebca6b)) & hMask;\n while (hStamp[h] === gen) {\n const s = hTable[h];\n // s === -1 marks a consumed slot (a pair already linked) — skip past it\n if (s !== -1) {\n const sa = t[s], sb = t[nextHE(s)];\n if ((sa === lo && sb === hi) || (sa === hi && sb === lo)) {\n he[e] = s; he[s] = e; hTable[h] = -1; // link, then consume the slot\n edgeStamp[s] = 1; edgeStack[i++] = s; // seed the interior edge for the cascade\n break;\n }\n }\n h = (h + 1) & hMask;\n }\n if (hStamp[h] !== gen) { hTable[h] = e; hStamp[h] = gen; } // first occurrence: insert\n }\n\n while (i > 0) {\n const a = edgeStack[--i];\n edgeStamp[a] = 0;\n const b = he[a];\n if (b === -1) continue;\n\n const a0 = a - a % 3;\n const b0 = b - b % 3;\n const ar = a0 + (a + 2) % 3;\n const al = a0 + (a + 1) % 3;\n const bl = b0 + (b + 2) % 3;\n const br = b0 + (b + 1) % 3;\n const p0 = t[ar], pr = t[a], pl = t[al], p1 = t[bl];\n\n const x0 = coords[p0 * dim], y0 = coords[p0 * dim + 1];\n const xr = coords[pr * dim], yr = coords[pr * dim + 1];\n const xl = coords[pl * dim], yl = coords[pl * dim + 1];\n const x1 = coords[p1 * dim], y1 = coords[p1 * dim + 1];\n\n // Test inCircle first: most interior edges are already Delaunay (inCircle true → no flip),\n // so this short-circuits before the two convexity orients on the common path. The quad must\n // also be convex (both new triangles CCW) — flipping a reflex quad would push a triangle\n // outside the polygon. Boundary/hole edges need no guard — they self-protect via he === -1.\n if (!inCircle(x0, y0, xr, yr, xl, yl, x1, y1) &&\n orient(x0, y0, xr, yr, x1, y1) > 0 && orient(x0, y0, x1, y1, xl, yl) > 0) {\n t[a] = p1; t[b] = p0;\n const hbl = he[bl], har = he[ar];\n he[a] = hbl; if (hbl !== -1) he[hbl] = a;\n he[b] = har; if (har !== -1) he[har] = b;\n he[ar] = bl; he[bl] = ar;\n\n // re-check the quad's four outer edges; skip boundary edges (he === -1) and any\n // already queued (edgeStamp), which also keeps the stack bounded by n.\n if (hbl !== -1 && edgeStamp[a] === 0) { edgeStamp[a] = 1; edgeStack[i++] = a; }\n if (har !== -1 && edgeStamp[b] === 0) { edgeStamp[b] = 1; edgeStack[i++] = b; }\n if (he[al] !== -1 && edgeStamp[al] === 0) { edgeStamp[al] = 1; edgeStack[i++] = al; }\n if (he[br] !== -1 && edgeStamp[br] === 0) { edgeStamp[br] = 1; edgeStack[i++] = br; }\n }\n }\n}\n\n/** @param {number} ax @param {number} ay @param {number} bx @param {number} by @param {number} cx @param {number} cy */\nfunction orient(ax, ay, bx, by, cx, cy) {\n return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);\n}\n\n// Whether p is inside or exactly on the circumcircle of triangle (a, b, c). Sign is negated vs the\n// usual predicate to match earcut's CCW winding — the standard sign would build the anti-Delaunay\n// mesh. Cocircular quads are legal ties, so refine only flips when this returns false.\n/** @param {number} ax @param {number} ay @param {number} bx @param {number} by @param {number} cx @param {number} cy @param {number} px @param {number} py */\nfunction inCircle(ax, ay, bx, by, cx, cy, px, py) {\n const dx = ax - px, dy = ay - py, ex = bx - px, ey = by - py, fx = cx - px, fy = cy - py;\n const ap = dx * dx + dy * dy, bp = ex * ex + ey * ey, cp = fx * fx + fy * fy;\n // A near-cocircular quad is a legal Delaunay tie, but roundoff can flag both an edge and its\n // flip as illegal, cascading into an endless flip loop (#205) — so treat a determinant within\n // a small margin of zero as a tie. The determinant's worst-case roundoff error is provably\n // below 9e-16·(ap + bp + cp)² (Shewchuk-style bound), so the margin guarantees every executed\n // flip is illegal in exact arithmetic, and Lawson flipping always terminates.\n const s = ap + bp + cp;\n return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) <= 1e-13 * s * s;\n}\n\n/** @param {number} e */\nfunction nextHE(e) { // next half-edge within the same triangle\n return e - e % 3 + (e + 1) % 3;\n}\n\n// Grow the scratch arrays on demand (like earcut's z-order arrays). Allocating lazily here rather\n// than at module load lets the whole refine() block tree-shake away for callers who don't use it.\n/** @param {number} n */\nfunction ensureScratch(n) {\n // edgeStack holds at most one entry per half-edge (edgeStamp dedups), so n is a safe cap —\n // sizing it up front lets the cascade push without a bounds/grow check.\n if (!edgeStack || edgeStack.length < n) edgeStack = new Int32Array(n);\n if (!he || he.length < n) he = new Int32Array(n);\n if (!edgeStamp || edgeStamp.length < n) edgeStamp = new Uint8Array(n);\n let size = 1;\n while (size < n * 4) size <<= 1; // power-of-two table, load factor <= 0.25\n if (!hTable || hTable.length < size) { hTable = new Int32Array(size); hStamp = new Uint32Array(size); }\n hMask = size - 1;\n}\n","import earcut from 'earcut'\nimport getNormal from './getNormal'\nimport * as THREE from 'three/webgpu'\n\nexport default function earcut3D(points: THREE.Vector3[]) {\n if (points.length < 3) return []\n\n const normal = getNormal(points)\n\n const quaternion = new THREE.Quaternion().setFromUnitVectors(normal, new THREE.Vector3(0, 1, 0))\n const rotatedPoint = points.map((point) => point.clone().applyQuaternion(quaternion))\n\n const point2D = rotatedPoint.flatMap((p) => [p.x, p.z])\n\n const result = earcut(point2D)\n\n return result\n}\n","interface Point3D {\n x: number\n y: number\n z: number\n}\n\ninterface Line3D {\n start: Point3D\n end: Point3D\n}\n\n/**\n * @description 判断线段是否相交\n * @todo ai写的一些变量名起的比较怪,懒得改了\n */\nexport function isIntersecting(line1: Line3D, line2: Line3D | Line3D[]): boolean {\n const lines = Array.isArray(line2) ? line2 : [line2]\n\n for (let i = 0; i < lines.length; i++) {\n const p1 = line1.start\n const q1 = line1.end\n const p2 = lines[i].start\n const q2 = lines[i].end\n\n // 重合不算相交\n if (equals(p1, p2) || equals(p1, q2) || equals(q1, p2) || equals(q1, q2) || equals(p1, q1)) {\n continue\n }\n\n if (areLinesIntersecting3D([p1.x, p1.y, p1.z], [q1.x, q1.y, q1.z], [p2.x, p2.y, p2.z], [q2.x, q2.y, q2.z])) return true\n }\n\n return false\n}\n\nfunction areLinesIntersecting3D(line1Start, line1End, line2Start, line2End) {\n // 计算方向向量\n const dirVec1 = [line1End[0] - line1Start[0], line1End[1] - line1Start[1], line1End[2] - line1Start[2]]\n const dirVec2 = [line2End[0] - line2Start[0], line2End[1] - line2Start[1], line2End[2] - line2Start[2]]\n\n // 设定两个参数方程相等,解三个标量方程\n // 三行对应 X, Y, Z 三个方向\n const rows = [\n { a: [dirVec1[0], -dirVec2[0]], b: line2Start[0] - line1Start[0] },\n { a: [dirVec1[1], -dirVec2[1]], b: line2Start[1] - line1Start[1] },\n { a: [dirVec1[2], -dirVec2[2]], b: line2Start[2] - line1Start[2] },\n ]\n\n // 尝试所有两行组合 (XY, XZ, YZ),找到行列式非零的组合\n const combinations = [\n [0, 1], // X 和 Y\n [0, 2], // X 和 Z\n [1, 2], // Y 和 Z\n ]\n\n for (const [i, j] of combinations) {\n const A = [rows[i].a, rows[j].a]\n const b = [rows[i].b, rows[j].b]\n\n const detA = determinant(A)\n if (Math.abs(detA) < 1e-10) {\n continue // 这个组合行列式为零,换下一个\n }\n\n const A_inv = inverseMatrix(A, detA)\n const [t, s] = matrixVectorMultiply(A_inv, b)\n\n // 检查解是否在线段范围内\n if (isInSegmentRange(t) && isInSegmentRange(s)) {\n return true\n }\n\n // 找到有效解后就返回,不需要继续\n return false\n }\n\n // 所有组合行列式都为零,说明线段平行或共线\n return false\n}\n\nfunction determinant(A) {\n // 计算2x2矩阵的行列式\n return A[0][0] * A[1][1] - A[0][1] * A[1][0]\n}\n\nfunction inverseMatrix(A, det) {\n // 计算2x2矩阵的逆矩阵,传入已计算的行列式值\n return [\n [A[1][1] / det, -A[0][1] / det],\n [-A[1][0] / det, A[0][0] / det],\n ]\n}\n\nfunction matrixVectorMultiply(matrix, vector) {\n return [matrix[0][0] * vector[0] + matrix[0][1] * vector[1], matrix[1][0] * vector[0] + matrix[1][1] * vector[1]]\n}\n\nfunction isInSegmentRange(value) {\n return value >= 0 && value <= 1\n}\n\nfunction equals(p1: Point3D, p2: Point3D): boolean {\n return p1.x === p2.x && p1.y === p2.y && p1.z === p2.z\n}\n","import type { Vector3 } from 'three/webgpu'\nimport * as THREE from 'three/webgpu'\nimport earcut3D from './earcut3D'\nimport { isIntersecting } from '../../PanoMeasurePlugin/utils/isIntersecting'\n\n/**\n * @description 根据多边形的顶点数组生成多边形的 BufferGeometry\n * @param checkLinesIntersect 检查多边形边线是否相交,需要保证传入的顶点是有序的\n */\nexport default function generatePolygonGeometry(_points: Vector3[], config?: { checkLinesIntersect?: boolean }): THREE.BufferGeometry {\n // 去重\n const points = [...new Set(_points)]\n if (points.length < 3) return\n\n // 闭合 position\n if (!points.at(-1).equals(points[0])) points.push(points[0])\n\n // 检查是否有交点,多边形不能有交点\n if (config?.checkLinesIntersect && points.length >= 5) {\n const lines = points\n .map((_, i) => {\n if (i === 0) return null\n return { start: points[i - 1], end: points[i] }\n })\n .filter(Boolean)\n\n for (let i = 0; i < lines.length; i++) {\n const hasIntersect = isIntersecting(lines[i], lines.slice(i))\n if (hasIntersect) return // 有交点,返回空\n }\n }\n\n // 打平 position\n const arrayPosition = points.flatMap((p) => [p.x, p.y, p.z])\n\n const positionAttribute = new THREE.Float32BufferAttribute(arrayPosition, 3)\n\n const indexAttribute = earcut3D(points)\n if (indexAttribute.length < 3) return\n\n // geometry\n const geometry = new THREE.BufferGeometry()\n geometry.setAttribute('position', positionAttribute)\n geometry.setIndex(indexAttribute)\n geometry.name = 'PolygonGeometry'\n\n return geometry\n}\n"],"ignoreList":[15],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pano-video-Bmud_CAn.js","names":["BasePlugin.Controller","__exportAll","requestAnimationFrameInterval","animate","Controller","createVideoTexture","THREE","directionToLongitudeAndLatitude","PI_2","longitude","direction","latitude","VideoMeshController","five","params","video","videoTexture","size","sourceUv","wrapWidth","wrappedU","videoUv","fadeX","fadeY","insideX","insideY","material","MeshBasicNodeMaterial","geometry","SphereGeometry","videoMesh","Mesh","userAction","session","operations","muted","generation","error","uvCenter","position","Vector3","PI","_2PI","u","_u","v","_v","originPosition","observer","transition","quaternion","finalPosition","currentFiveState","Quaternion","x","y","z","w","panoIndex","mode","intersection","raycaster","event","opacity","meg","target","minU","_minV","width","height","bounding","minV","maxU","maxV","PanoVideoPluginController","options","data","panoVideoItem","renderID","videoItem","controller","id","controllers","errors","typings_exports","PanoVideoPlugin"],"sources":["../../src/PanoVideoPlugin/utils/index.ts","../../src/PanoVideoPlugin/VideoMeshController.ts","../../src/PanoVideoPlugin/Controller.ts","../../src/PanoVideoPlugin/typings.ts","../../src/PanoVideoPlugin/index.ts"],"sourcesContent":["import type { Vector3 } from 'three/webgpu'\n\nexport default function directionToLongitudeAndLatitude(\n direction:\n | Vector3\n | {\n x: number\n y: number\n z: number\n },\n) {\n const PI_2 = Math.PI * 2\n let longitude = -Math.atan2(direction.x, -direction.z)\n longitude = ((longitude % PI_2) + PI_2) % PI_2\n const latitude = -Math.asin(direction.y / 1)\n return { longitude, latitude }\n}\n","import { createVideoTexture } from '../shared-utils/three/loadVideoTexture'\nimport type { PlaybackManager, PlaybackController, PlaybackSession } from '../shared-utils/playback'\nimport type { Five, Mode, WorkObserver, WorkResolvedObserver } from '@realsee/five-webgpu'\nimport type { VideoMeshParams } from './typings'\nimport { requestAnimationFrameInterval } from '../shared-utils'\nimport type { Raycaster } from 'three/webgpu'\nimport * as THREE from 'three/webgpu'\nimport {\n type Intersection,\n LinearFilter,\n Mesh,\n Quaternion,\n MeshBasicNodeMaterial,\n SphereGeometry,\n Vector3,\n type VideoTexture,\n} from 'three/webgpu'\nimport directionToLongitudeAndLatitude from './utils'\nimport { animate } from 'animejs'\nimport type { Subscribe } from '../shared-utils/Subscribe'\nimport type { PluginEventMap } from './typings'\nimport type { Simplify } from 'type-fest'\nimport type { FiveUtil } from '../shared-utils/Utils/FiveUtil'\n\n/** 点位视频控制器\n * @description 控制器存在副作用,包括:\n * - 对 Five 事件的监听。\n * - 对 DOM 原生事件的监听。\n * - 用于播放视频的模型。\n * - 视频实例。\n * @description 清除副作用的力度从弱到强:\n * - 隐藏:hide,用于隐藏 UI 元素;不销毁多媒体资源。用于临时隐藏。\n * - 取消挂载:unmount,销毁视频资源;移除模型。用于不符合自身展示条件时执行。\n * - 禁用:disable,销毁视频资源;移除模型;取消监听。用于外部条件变换导致的功能禁用。\n * - 销毁:dispose,用于彻底销毁实例,dispose 之后将不响应任何事件。\n */\nexport class VideoMeshController {\n /** 传入的 ID,不可更改 */\n public get renderID() {\n return this._id\n }\n /** 是否已经销毁 */\n public get disposed() {\n return this._disposed\n }\n /** 是否已经启用 */\n public get enabled() {\n return this._enabled\n }\n public video: HTMLVideoElement\n\n private fiveUtil?: FiveUtil\n\n private _id: string\n /** 视频资源地址 */\n private readonly url: string\n /** Five Instance */\n private five: Five\n /** 视频对应的点位 */\n private panoIndex: number\n /** 视频对应的 Work Observer */\n private observer?: WorkResolvedObserver\n /** 视频在球面的 uv:[left, top, width, height] */\n private origin: number[]\n /** Video DOM */\n /** Video Mesh */\n private videoMesh: Mesh<SphereGeometry, MeshBasicNodeMaterial>\n private readonly videoTexture: VideoTexture\n private _enabled = true\n private _disposed = false\n /** 视频资源是否满足播放条件 */\n private videoDataLoaded = false\n /** 视频是否曾经播放过 */\n private hasVideoEverPlayed = false\n /** 自动 render five 的销毁函数\n * @remark 由于 render video 依赖 Five render,因此需要自动 render five。\n */\n private renderFiveDisposer?: () => void\n private fadeAnimation?: ReturnType<typeof animate>\n private playbackController?: PlaybackController\n private session?: PlaybackSession\n private playbackGeneration = 0\n private readonly videoOpacity = THREE.TSL.uniform(0)\n private hooks: Subscribe<Simplify<PluginEventMap>>\n\n /** 初始化视频、模型以及相关事件监听。 */\n public constructor(five: Five, params: VideoMeshParams & { mediaManager?: PlaybackManager; fiveUtil?: FiveUtil } & { hooks: Subscribe<Simplify<PluginEventMap>> }) {\n this.five = five\n this.panoIndex = params.panoIndex\n this.fiveUtil = params.fiveUtil\n this._id = params.renderID\n this.url = params.url\n this.origin = params.origin.slice() as number[]\n this.hooks = params.hooks\n this._enabled = params.initialState?.enabled ?? true\n // ========== 初始化 Video Instance ==========\n const video = document.createElement('video')\n video.crossOrigin = 'anonymous'\n video.autoplay = false\n video.muted = true\n video.loop = true\n video.playsInline = true\n this.video = video\n this.playbackController = params.mediaManager?.createController({ label: 'pano-video', onCancel: () => { this.playbackGeneration++; this.session = undefined } })\n // ========== 初始化模型 ==========\n // 视频贴图\n const videoTexture = this.videoTexture = createVideoTexture(this.video)\n // 模型材质:在球面原始 UV 中裁剪视频区域,并在边缘做 10% 羽化。\n const size = THREE.TSL.uniform(new THREE.Vector4(this.origin[0], 1 - this.origin[1] - this.origin[3], this.origin[2], this.origin[3]))\n const sourceUv = THREE.TSL.uv()\n const wrapWidth = THREE.TSL.max(size.x.add(size.z).sub(1), 0)\n const wrappedU = THREE.TSL.select(sourceUv.x.lessThanEqual(wrapWidth), sourceUv.x.add(1), sourceUv.x)\n const videoUv = THREE.TSL.vec2(wrappedU.sub(size.x).div(size.z), sourceUv.y.sub(size.y).div(size.w))\n const fadeX = THREE.TSL.select(\n videoUv.x.lessThan(0.1),\n videoUv.x.div(0.1),\n THREE.TSL.select(videoUv.x.greaterThan(0.9), THREE.TSL.float(1).sub(videoUv.x).div(0.1), 1),\n )\n const fadeY = THREE.TSL.select(\n videoUv.y.lessThan(0.1),\n videoUv.y.div(0.1),\n THREE.TSL.select(videoUv.y.greaterThan(0.9), THREE.TSL.float(1).sub(videoUv.y).div(0.1), 1),\n )\n const insideX = THREE.TSL.float(1).sub(THREE.TSL.step(0.5, THREE.TSL.abs(videoUv.x.sub(0.5))))\n const insideY = THREE.TSL.float(1).sub(THREE.TSL.step(0.5, THREE.TSL.abs(videoUv.y.sub(0.5))))\n const material = new MeshBasicNodeMaterial({ depthTest: true, transparent: true })\n material.colorNode = THREE.TSL.texture(videoTexture, videoUv).rgb\n material.opacityNode = insideX.mul(insideY).mul(THREE.TSL.min(fadeX, fadeY)).mul(this.videoOpacity)\n // 模型几何体\n const geometry = new SphereGeometry(1, 64, 64)\n // 因为是从内向外看,需要翻转 X 轴。\n geometry.scale(-1, 1, 1)\n // 点位视频模型\n const videoMesh = new Mesh(geometry, material)\n videoMesh.name = 'pano-video-plugin'\n this.videoMesh = videoMesh\n // five work 存在,说明已经加载过数据。\n if (this.fiveUtil.workUtil.work) this.onFiveDataLoaded()\n // 插件初始化时如果是开启状态,添加事件监听。\n if (this.enabled) this.addEventListeners()\n // 如果初始化时满足挂载条件,需要挂载副作用。\n this.mountIfNeeded()\n }\n\n /**\n * 取消静音\n *\n * @warning 需要注意:由于大部分浏览器的限制,视频的声音必须在用户有交互事件后才能开启,否则会被浏览器禁用视频播放。\n */\n public unmute = async (userAction = false) => {\n if (this.disposed) return\n if (!this.video.paused) return this.play(userAction, false)\n const session = this.playbackController?.begin({ userAction, audible: true })\n if (this.playbackController && !session) return\n this.session = session\n const operations = session?.bind(this.video) ?? this.video\n operations.muted = false\n }\n\n public async play(userAction = false, muted = false) {\n if (this.disposed) return\n const session = this.playbackController?.begin({ userAction, audible: !muted })\n if (this.playbackController && !session) return\n this.session = session\n const generation = ++this.playbackGeneration\n const operations = session?.bind(this.video) ?? this.video\n operations.muted = muted\n try { await operations.play() } catch (error) {\n if (session?.signal.aborted || generation !== this.playbackGeneration) return\n if ((error as Error).name === 'AbortError') { this.pause(); return }\n this.pause()\n throw error\n }\n }\n\n public pause() {\n // disable removes the native pause listener before unmounting the video.\n this.renderFiveDisposer?.()\n this.renderFiveDisposer = undefined\n this.fadeAnimation?.cancel()\n this.fadeAnimation = undefined\n if (this.videoOpacity.value > 0) this.videoOpacity.value = 1\n this.video.removeEventListener('timeupdate', this.onVideoTimeUpdate)\n this.playbackController?.cancel()\n this.playbackGeneration++\n this.session = undefined\n this.video.muted = true\n this.video.pause()\n }\n\n public mute() {\n const operations = this.session?.bind(this.video) ?? this.video\n operations.muted = true\n }\n\n /** 彻底销毁,不响应之后的任何事件 */\n public dispose() {\n if (this.disposed) return\n this.disable()\n this.playbackController?.dispose()\n this._disposed = true\n this.videoTexture.dispose()\n this.videoMesh.geometry.dispose()\n this.videoMesh.material.dispose()\n }\n\n public enable() {\n if (this.disposed) return\n if (this.enabled) return\n this._enabled = true\n if (!this.observer && this.five.work) this.onFiveDataLoaded()\n this.addEventListeners()\n this.mountIfNeeded()\n }\n\n /** 禁用插件 */\n public disable() {\n if (this.disposed) return\n if (!this.enabled) return\n this._enabled = false\n this.removeEventListeners()\n this.unmount()\n }\n\n /** 切换到全景模式并看向视频\n * @remark 如果遇到不能自动播放的问题,需要放到用户交互事件中调用。\n */\n public lookAtVideo() {\n if (!this.observer) return\n const uvCenter = this.getUVCenter()\n if (!uvCenter) return\n const position = this.uv2Position(uvCenter[0], uvCenter[1])\n if (!position) return\n const direction = new Vector3().subVectors(position, this.observer.position).normalize()\n const { longitude, latitude } = directionToLongitudeAndLatitude(direction)\n this.five.setState({ mode: 'Panorama', panoIndex: this.panoIndex, longitude, latitude })\n // setState 不会触发 wantsMoveToPano 事件,因此需要手动触发。\n this.onFiveWantsMoveToPano(this.panoIndex)\n }\n\n /** 把 uv 值转换成位置 */\n private uv2Position = (_u: number, _v: number) => {\n const r = 1\n // π: 180°\n const PI = Math.PI\n // 2π: 360°\n const _2PI = Math.PI * 2\n const u = _u\n const v = 1 - _v\n // 构造原始球面坐标\n // 球面原始朝向是 Z 轴正方向。\n // v = 0.5,即 X、Z 取到最大值。\n // x、z 的变化相当于 -X 轴绕 +Y 轴逆时针旋转 360° 回到 -X 轴。\n // 此时 x = -r * cos(2π * u)、z = r * sin(2π * u)\n // v 的变换相当于 -Y 轴绕 +Z 轴逆时针旋转 180°。\n // 此时 x = -r * cos(2π * u) * sin(π * v)、y = r * cos(π * v)、z = r * sin(2π * u) * sin(π * v)\n const originPosition = new Vector3(\n -r * Math.cos(_2PI * u) * Math.sin(PI * v),\n r * Math.cos(PI * v),\n r * Math.sin(_2PI * u) * Math.sin(PI * v),\n )\n // 由于从内向外看,需要翻转 X 轴坐标。\n originPosition.setX(-originPosition.x)\n\n const observer = this.fiveUtil.workUtil.getResolvedObserver(this.panoIndex)\n if (!observer) return this.logWarning(`点位 ${this.panoIndex} 不存在,请检查 Five 数据是否正常。`)\n const transition = observer.position.clone()\n const quaternion = observer.quaternion.clone()\n\n const finalPosition = originPosition.clone()\n // 原因同模型旋转。\n finalPosition.applyAxisAngle(new Vector3(0, 1, 0), Math.PI / 2)\n finalPosition.applyQuaternion(quaternion)\n finalPosition.add(transition)\n\n return finalPosition\n }\n\n /** 获取视频中心点的 uv */\n private getUVCenter() {\n if (!this.origin) return\n const u = this.origin[0] + this.origin[2] / 2\n const v = this.origin[1] + this.origin[3] / 2\n return [u, v] as const\n }\n\n /** 添加时间监听 */\n private addEventListeners() {\n this.five.on('loaded', this.onFiveDataLoaded)\n this.five.on('modeChange', this.onFiveModeChange)\n this.five.on('panoArrived', this.onFivePanoArrived)\n this.five.on('panoWillArrive', this.onFivePanoWillArrive)\n this.five.on('wantsMoveToPano', this.onFiveWantsMoveToPano)\n this.five.on('wantsTapGesture', this.onFiveWantsTapGesture)\n this.five.on('initAnimationEnded', this.onFiveInitAnimationEnded)\n this.video.addEventListener('canplaythrough', this.onVideoDataLoaded)\n this.video.addEventListener('playing', this.onVideoPlaying)\n this.video.addEventListener('pause', this.onVideoPaused)\n }\n\n /** 移除事件监听 */\n private removeEventListeners() {\n this.five.off('loaded', this.onFiveDataLoaded)\n this.five.off('modeChange', this.onFiveModeChange)\n this.five.off('panoArrived', this.onFivePanoArrived)\n this.five.off('panoWillArrive', this.onFivePanoWillArrive)\n this.five.off('wantsMoveToPano', this.onFiveWantsMoveToPano)\n this.five.off('wantsTapGesture', this.onFiveWantsTapGesture)\n this.five.off('initAnimationEnded', this.onFiveInitAnimationEnded)\n this.video.removeEventListener('canplaythrough', this.onVideoDataLoaded)\n this.video.removeEventListener('playing', this.onVideoPlaying)\n this.video.removeEventListener('pause', this.onVideoPaused)\n }\n\n /** 如果满足 mount 条件,mount */\n private mountIfNeeded() {\n const currentFiveState = this.five.getCurrentState()\n if (currentFiveState.mode === 'Panorama' && currentFiveState.panoIndex === this.panoIndex && this.enabled) {\n this.mount()\n }\n }\n\n /** 挂载:加载视频资源;添加模型。 */\n private mount() {\n if (this.disposed) return this.logWarning('插件已经销毁,无法挂载。')\n if (this.url === '') return this.logWarning('视频资源不存在。')\n // if (this.panoIndex )\n if (this.video.src !== this.url) {\n this.video.src = this.url\n }\n // 如果视频正在播放,不做任何操作。\n if (!this.video.paused) return\n this.play(false, this.video.muted).catch((error) => {\n this.logWarning(error instanceof Error ? error.message : '视频播放失败。')\n })\n }\n\n /** 卸载:销毁视频资源;移除模型。 */\n private unmount() {\n this.pause()\n this.video.pause()\n // 去除模型后下次播放时,需要渐变显示,这里透明度重置为0。\n this.videoOpacity.value = 0\n this.video.removeAttribute('src')\n this.video.load()\n this.five.scene.remove(this.videoMesh)\n }\n\n /** 暂停视频,去除模型。 */\n private hide() {\n this.pause()\n this.video.pause()\n // 去除模型后下次播放时,需要渐变显示,这里透明度重置为0。\n this.videoOpacity.value = 0\n this.five.scene.remove(this.videoMesh)\n }\n\n /** Five 数据加载后需要根据点位位姿调整点位模型位置 */\n private onFiveDataLoaded = () => {\n const observer = this.fiveUtil.workUtil.getResolvedObserver(this.panoIndex)\n if (!observer) return this.logWarning(`点位 ${this.panoIndex} 不存在,请检查 Five 数据是否正常。`)\n // 初始化依赖 work 的数据\n this.observer = observer\n // 初始化模型位姿\n const { x, y, z, w } = observer.quaternion\n const quaternion = new Quaternion(x, y, z, w)\n const position = observer.position\n this.videoMesh.position.fromArray([position.x, position.y, position.z])\n // 重置模型旋转\n this.videoMesh.quaternion.set(0, 0, 0, 1)\n // 绕 Y 轴逆时针旋转 90 度\n // 这里是因为历史问题,算法模块里面转了 90 度,所以前端也要转 90 度。\n // 后面可以联系 @饶童 一起改掉。\n this.videoMesh.rotateOnAxis(new Vector3(0, 1, 0), Math.PI / 2)\n // 应用点位旋转\n this.videoMesh.applyQuaternion(quaternion)\n }\n\n /** 兼容视频播放 */\n private onFiveWantsMoveToPano = (panoIndex: number) => {\n // 点位不匹配,不做任何操作。\n if (panoIndex !== this.panoIndex) return\n // 如果视频之前播放过,不用再做兼容\n if (this.hasVideoEverPlayed) return\n this.play(false, true).catch(() => {\n // 视频播放失败时,不做任何操作。\n })\n }\n\n /** 走到某个点位上时,挂载/卸载视频 */\n private onFivePanoArrived = (panoIndex: number) => {\n if (this.disposed) return this.logWarning('实例已被销毁')\n if (!this.enabled) return\n // 如果点位条件满足,挂载。\n if (this.panoIndex === panoIndex) this.mount()\n }\n\n private onFivePanoWillArrive = (panoIndex: number) => {\n // wantsMoveToPano 和 panoArrived 可能不是同一个点位,如果不一致,销毁副作用。\n if (panoIndex !== this.panoIndex) return this.unmount()\n if (this.panoIndex !== panoIndex) this.unmount()\n }\n\n /** Five 模型变化 */\n private onFiveModeChange = (mode: Mode) => {\n if (mode !== 'Panorama') this.hide()\n // Panorama 的判断在 onFiveInitAnimationEnded\n }\n\n /** Five mode change 动画结束 */\n private onFiveInitAnimationEnded = () => {\n const currentFiveState = this.five.getCurrentState()\n if (currentFiveState.mode === 'Panorama' && currentFiveState.panoIndex === this.panoIndex) this.mount()\n }\n\n /** Five Canvas 点击 */\n private onFiveWantsTapGesture = (raycaster: Raycaster) => {\n if (!this.five.scene.children.includes(this.videoMesh)) return\n if (this.disposed) return this.logWarning('实例已被销毁')\n if (!this.enabled) return this.logWarning('实例已被禁用')\n const [intersection] = raycaster.intersectObject(this.videoMesh)\n if (!intersection) return\n const isIntersectInVideo = this.checkIntersectionInBounding(this.origin, intersection)\n if (isIntersectInVideo) {\n const event = {\n target: this,\n _preventDefaultReturn: false,\n preventDefault: () => {\n event._preventDefaultReturn = true\n },\n }\n this.hooks.emit('click', event)\n if (event._preventDefaultReturn === false) {\n if (this.video.muted) this.unmute(true)\n else { this.mute() }\n }\n return false as const\n }\n }\n\n /** video canplaythrough 事件触发 */\n private onVideoDataLoaded = () => {\n this.videoDataLoaded = true\n if (this.video.paused === false && this.video.src !== '') this.onVideoPlayingAndLoaded()\n }\n\n /** video playing 事件触发\n * @remarks\n * 事件触发时机:\n * - video is ready to start after having been paused.\n * - video is ready to play after delayed due to lack of data.\n * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video\n */\n private onVideoPlaying = () => {\n this.hasVideoEverPlayed = true\n // 空视频不能挂载。\n if (!this.enabled) return\n if (this.videoDataLoaded) this.onVideoPlayingAndLoaded()\n }\n\n /** 触发 playing 和 canplaythrough */\n private onVideoPlayingAndLoaded = () => {\n if (!this.videoDataLoaded) return this.logWarning('视频数据未加载')\n if (this.video.paused === true) return this.logWarning('视频已暂停')\n\n this.video.removeEventListener('timeupdate', this.onVideoTimeUpdate)\n this.video.addEventListener('timeupdate', this.onVideoTimeUpdate, { once: true })\n }\n\n private onVideoTimeUpdate = () => {\n if (this.disposed || !this.enabled) return\n if (this.panoIndex !== this.five.getCurrentState().panoIndex || this.five.getCurrentState().mode !== 'Panorama') return\n if (!this.renderFiveDisposer) this.renderFiveDisposer = requestAnimationFrameInterval(() => { this.five.needsRender = true }, 30)\n this.five.scene.add(this.videoMesh)\n if (this.videoOpacity.value === 0) {\n this.fadeAnimation?.cancel()\n const opacity = { value: 0 }\n this.fadeAnimation = animate(opacity, {\n value: 1, duration: 300, ease: 'linear',\n onUpdate: () => { this.videoOpacity.value = opacity.value },\n onComplete: () => { this.videoOpacity.value = 1; this.fadeAnimation = undefined },\n })\n }\n }\n\n /** video pause 事件触发 */\n private onVideoPaused = () => {\n this.renderFiveDisposer?.()\n this.renderFiveDisposer = undefined\n }\n\n /** 控制台打印警告 */\n private logWarning(meg: string) {\n console.warn(`⛔ ==> [VideoMeshController]:`, meg)\n }\n\n /** 检测射线与模型的交点是不是在视频的范围内 */\n private checkIntersectionInBounding(bounding: number[], target: Intersection) {\n if (!target.uv) return false\n const [u, v] = target.uv.toArray()\n const [minU, _minV, width, height] = bounding\n const minV = 1 - _minV - height\n const maxU = minU + width\n const maxV = minV + height\n return u >= minU && u <= maxU && v >= minV && v <= maxV\n }\n}\n","import type { PlaybackManager } from '../shared-utils/playback'\nimport type { Five } from '@realsee/five-webgpu'\nimport type { LoadParams, PluginEventMap, PluginState, PluginData, VideoItem } from './typings'\nimport { VideoMeshController } from './VideoMeshController'\nimport * as BasePlugin from '../base/BasePlugin'\n\nexport class PanoVideoPluginController extends BasePlugin.Controller<PluginState, PluginEventMap> {\n /** 插件 State */\n public get state() {\n return {\n enabled: this.enabled,\n }\n }\n\n /** 插件是否已被销毁 */\n public get disposed() {\n return this._disposed\n }\n\n public controllerMap: Map<string, VideoMeshController> = new Map()\n\n public data?: PluginData\n\n private enabled = true\n private _disposed = false\n private readonly removeFiveDisposeListener: () => void\n\n public constructor(five: Five, private options?: { mediaManager?: PlaybackManager }) {\n super(five)\n // Five emits dispose synchronously, before it releases the renderer.\n this.removeFiveDisposeListener = five.on('dispose', () => {\n try { this.dispose() } catch (error) {\n // Five must finish disposing its other resources and the renderer.\n console.error('[PanoVideoPluginController]: dispose failed', error)\n }\n })\n }\n\n /** 加载点位视频数据,加载数据并不代表会加载点位视频。 */\n public load(data: PluginData, params?: LoadParams) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n if (typeof params?.initialState?.enabled !== 'undefined' && params.initialState.enabled !== this.enabled) {\n params.initialState.enabled ? this.enable() : this.disable()\n }\n this.clear()\n // 初始化 controller 实例\n data.list.forEach((panoVideoItem) => {\n const panoIndex = panoVideoItem.pano_index\n const renderID = panoVideoItem.render_id\n panoVideoItem.video_list.forEach((videoItem) => {\n this.controllerMap.set(\n videoItem.render_id,\n new VideoMeshController(this.five, {\n mediaManager: this.options?.mediaManager,\n ...videoItem,\n fiveUtil: this.fiveUtil,\n panoIndex,\n renderID,\n hooks: this.hooks,\n initialState: { enabled: this.enabled },\n }),\n )\n })\n })\n\n this.data = data\n\n this.hooks.emit('dataLoaded', data)\n }\n\n /** 开启插件功能。 */\n public enable(options?: BasePlugin.BaseOptions) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n if (this.enabled) return\n this.enabled = true\n Array.from(this.controllerMap.values()).forEach((controller) => controller.enable())\n const userAction = options?.userAction ?? true\n this.hooks.emit('enable', { userAction })\n }\n\n /** 禁用插件功能。 */\n public disable(options?: BasePlugin.BaseOptions) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n if (!this.enabled) return\n this.enabled = false\n Array.from(this.controllerMap.values()).forEach((controller) => controller.disable())\n const userAction = options?.userAction ?? true\n this.hooks.emit('disable', { userAction })\n }\n\n /** 看向某个视频。\n * - 会自动切换到全景模式。\n * - 如果遇到不能自动播放的问题,需要放到用户交互事件中调用。\n */\n public lookAtVideoItemByRenderID(id: string) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n const controller = this.controllerMap.get(id)\n if (!controller) return this.logWarning(`ID 为 ${id} 的点位视频不存在`)\n controller.lookAtVideo()\n }\n\n /**\n * 取消静音。\n *\n * 大部分浏览器需要用户交互后才能开启视频声音。\n *\n * 如果需要取消静音,建议在用户交互事件中调用本方法。\n *\n * 例如:\n *\n * ```jsx\n * onClick={() => {\n * panoVideoPluginController.lookAtVideoItemByRenderID('xxx')\n * panoVideoPluginController.unmuteByRenderID('xxx')\n * }}\n * ```\n */\n public unmuteByRenderID(id: string, userAction = false) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n const controller = this.controllerMap.get(id)\n if (!controller) return this.logWarning(`ID 为 ${id} 的点位视频不存在`)\n controller.unmute(userAction)\n }\n\n /** 为一个点位添加视频(可以是多条)。 */\n public add(panoIndex: number, videoItems: VideoItem[]) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n videoItems.forEach((videoItem) => {\n if (this.controllerMap.get(videoItem.render_id)) return this.logWarning(`ID 为 ${videoItem.render_id} 的点位视频已存在`)\n const renderID = videoItem.render_id\n this.controllerMap.set(\n videoItem.render_id,\n new VideoMeshController(this.five, {\n mediaManager: this.options?.mediaManager,\n ...videoItem,\n fiveUtil: this.fiveUtil,\n panoIndex,\n renderID,\n hooks: this.hooks,\n initialState: { enabled: this.enabled },\n }),\n )\n })\n }\n\n /** 根据 VideoItem render_id 删除某个视频。 */\n public removeByRenderID(id: string) {\n if (this.disposed) return this.logWarning('插件已被销毁')\n const controller = this.controllerMap.get(id)\n if (!controller) return this.logWarning(`ID 为 ${id} 的点位视频不存在`)\n controller.dispose()\n this.controllerMap.delete(id)\n }\n\n /** 清空现有数据 */\n public clear() {\n if (this.disposed) return this.logWarning('插件已被销毁')\n this.releaseControllers()\n }\n\n /** 销毁插件 */\n public dispose() {\n if (this.disposed) return\n this._disposed = true\n this.removeFiveDisposeListener()\n this.releaseControllers()\n }\n\n private releaseControllers() {\n const controllers = Array.from(this.controllerMap.values())\n this.controllerMap.clear()\n // Retire every video even if a material disposal listener throws.\n const errors: unknown[] = []\n for (const controller of controllers) {\n try { controller.dispose() } catch (error) { errors.push(error) }\n }\n if (errors.length) throw errors[0]\n }\n\n /** 控制台打印警告 */\n // TODO: 全局函数 curry 化\n private logWarning(meg: string) {\n console.warn(`⛔ ==> [PanoVideoPluginController]:`, meg)\n }\n}\n","import type * as BasePlugin from '../base/BasePluginWithData'\nimport type { VideoMeshController } from './VideoMeshController'\n\n/** 单个视频元素 */\nexport interface VideoItem {\n /** client render ID\n * @remarks 为什么不用 id 作为唯一标识?\n * - id 是后端生成的,而 render_id 是前端生成的,在编辑时为了保证在请求后端数据之前也能进行渲染,使用额外的 id 进行渲染。\n * - 为了保证两端的数据一致性,插件里使用 render_id 作为唯一 ID。\n */\n render_id: string\n /** 文件地址 */\n url: string\n /** 算法处理的视频 uv 信息\n * @description [left, top, width, height]\n */\n origin: number[]\n}\n\n/** 点位视频元素 */\nexport interface PanoVideoItem {\n /** client render ID */\n render_id: string\n /** 视频播放点位 */\n pano_index: number\n /** 视频列表 */\n video_list: VideoItem[]\n}\n\n/** 点位视频模型参数 */\nexport interface VideoMeshParams {\n /** client render ID */\n renderID: string\n /** video 文件地址 */\n url: string\n /** 算法处理的视频 uv 信息\n * @description [left, top, width, height]\n */\n origin: number[]\n /** 视频播放点位 */\n panoIndex: number\n /** 初始状态 */\n initialState?: {\n enabled?: boolean\n }\n}\n\n/** 加载数据时的额外参数 */\nexport interface LoadParams {\n initialState?: {\n enabled?: boolean\n }\n}\n\nexport interface PluginState {\n enabled: boolean\n}\n\nexport interface PluginData {\n list: PanoVideoItem[]\n}\n\nexport interface PluginEventMap extends BasePlugin.EventMap<PluginState, PluginData> {\n /** 点位视频模型开启 */\n enable: (params: { userAction: boolean }) => void\n /** 点位视频模型关闭 */\n disable: (params: { userAction: boolean }) => void\n /** 点位视频被点击 */\n click: (event: { target: VideoMeshController; preventDefault: () => void }) => void\n}\n","import type { PlaybackManager } from '../shared-utils/playback'\nimport type { FivePlugin } from '@realsee/five-webgpu'\nimport { PanoVideoPluginController } from './Controller'\nimport * as _PanoVideoPluginType from './typings'\n\n/** 点位视频播放插件\n * - 支持一次性加载多组数据。\n * - 走到点位上时播放视频(可能是多个)。\n * - 走出点位时销毁视频。\n * - 允许动态开启和禁用功能。\n * - 视频只能在全景模式且点位一致时才会播放。不满足条件会自动销毁。\n * - 不做多媒体缓存,缓解内存占用。\n */\nexport const PanoVideoPlugin: FivePlugin<{ mediaManager?: PlaybackManager } | undefined, PanoVideoPluginController> = (five, options) => {\n return new PanoVideoPluginController(five, options)\n}\n\nexport { _PanoVideoPluginType as PanoVideoPluginType }\nexport type PanoVideoPluginParameterType = { mediaManager?: PlaybackManager } | undefined\nexport type PanoVideoPluginReturnType = InstanceType<typeof PanoVideoPluginController>\nexport default PanoVideoPlugin\n"],"mappings":"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"}
|
package/dist/utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":["transformPosition","isTouchDevice","PointSelector","Magnifier","transformUnitSquare","getGeometryInfo","generatePolygonGeometry","transformUnit","waitFiveModelLoaded","arrayPositionToVector3","anyPositionToVector3","centerPoint","toArray","isPanoramaLike","isModelLike","reblink","lookPoint","blink","notNil","isNil","FiveDomEvents","uuid","StandaloneRenderer","boxVertexes","worldBoundingSphere","lookObject","recurveFindObject","omit","THREE","_vector2","FivePuppet","five","params","rendererSize","pixelRatio","_newRendererCache","_newCameraCache","wrapper","Subscribe"],"sources":["../src/shared-utils/five/FivePuppet.ts"],"sourcesContent":["import type { Five } from '@realsee/five-webgpu'\nimport * as THREE from 'three/webgpu'\nimport { StandaloneRenderer } from '../rendering/StandaloneRenderer'\n\nconst _vector2 = new THREE.Vector2()\n\n/**\n * @description 模拟 Five 行为的 canvas,与 Five 唯一区别是 scene 是空的\n * @usecase\n * 当需 five 的 canvas 上层有一些额外的 Dom 元素比如平面图时,希望在这些 Dom 元素上层再绘制一些三维物体,可以\n * 使用 FivePuppet,将要渲染的物体加入到 FivePuppet 的 scene 中即可。甚至可以是原本在 five 中的物体,可以使\n * 用 `.clone()` 将物体克隆一份然后加入到 FivePuppet 的 scene 中。\n * @example react\n ```typescript\n import { FivePuppet } from '@realsee/dnalogel/utils'\n\n function App() {\n const fivePuppet = React.useRef<FivePuppet>()\n const five = unsafe__useFiveInstance()\n\n React.useEffect(() => {\n fivePuppet.current = new FivePuppet(five, { zIndex: 20 })\n\n const object = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial({ color: 0xff0000 }))\n fivePuppet.current.scene.add(object)\n\n return () => {\n fivePuppet.current?.dispose()\n }\n }, [five])\n }\n ```\n * @example javascript\n ```typescript\n import { FivePuppet } from '@realsee/dnalogel/utils'\n\n const five = new Five({\n plugins: [\n [(five) => new FivePuppet(five), 'fivePuppet']\n ],\n })\n\n const object = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial({ color: 0xff0000 }))\n five.plugins.fivePuppet.scene.add(object)\n ```\n */\nexport class FivePuppet {\n public scene = new THREE.Scene()\n\n private five: Five\n private renderer: StandaloneRenderer\n private cancelRequestAnimationFrameId: number\n private camera: Five['camera']\n\n private domInited = false\n private canvasWrapper?: HTMLDivElement\n private params?: { zIndex?: number }\n\n private _rendererCache: string\n private _cameraCache: string\n private disposed = false\n\n public constructor(\n five: Five,\n params?: {\n /**\n * @description canvas 的 zIndex\n * @default 1\n */\n zIndex: number\n },\n ) {\n this.five = five\n this.camera = five.camera.clone() as Five['camera']\n this.params = params\n\n this.renderer = new StandaloneRenderer()\n this.renderer.setClearColor(0, 0)\n this.renderer.domElement.style.pointerEvents = 'none'\n this.renderer.setSize(1, 1)\n\n five.on('dispose', this.dispose)\n\n this.animate()\n }\n\n public animate = () => {\n if (this.disposed) return\n this.cancelRequestAnimationFrameId = requestAnimationFrame(this.animate)\n\n if (!this.five.renderer) return\n\n const rendererSize = this.five.renderer.getSize(_vector2)\n const pixelRatio = this.five.renderer.getPixelRatio()\n const _newRendererCache = rendererSize.toArray().join(',') + ',' + pixelRatio\n if (_newRendererCache !== this._rendererCache) {\n this._rendererCache = _newRendererCache\n this.renderer.setPixelRatio(pixelRatio)\n this.renderer.setSize(rendererSize.x, rendererSize.y)\n }\n\n const _newCameraCache = this.five.camera.projectionMatrix.toArray().join(',') + this.five.camera.matrixWorld.toArray().join(',')\n if (_newCameraCache !== this._cameraCache) {\n this._cameraCache = _newCameraCache\n this.camera.copy(this.five.camera)\n }\n\n this.renderer.render(this.scene, this.camera)\n\n if (!this.domInited) {\n const wrapper = this.five.getElement()?.parentElement\n if (wrapper) {\n this.canvasWrapper = document.createElement('div')\n this.canvasWrapper.classList.add('five-puppet')\n this.canvasWrapper.style.position = 'absolute'\n this.canvasWrapper.style.pointerEvents = 'none'\n this.canvasWrapper.style.left = '0'\n this.canvasWrapper.style.top = '0'\n this.canvasWrapper.style.zIndex = `${this.params?.zIndex ?? 1}`\n\n this.canvasWrapper.appendChild(this.renderer.domElement)\n wrapper.appendChild(this.canvasWrapper)\n\n this.domInited = true\n }\n }\n }\n\n public stopAnimate = () => {\n this.cancelRequestAnimationFrameId && cancelAnimationFrame(this.cancelRequestAnimationFrameId)\n }\n\n public dispose = () => {\n if (this.disposed) return\n this.disposed = true\n this.five.off('dispose', this.dispose)\n this.stopAnimate()\n this.renderer.dispose()\n this.renderer.domElement.remove()\n this.canvasWrapper?.remove()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAIA,IAAM6B,IAAW,IAAID,EAAM,QAAQ,GA0CtBE,IAAb,MAAwB;CACtB,QAAe,IAAIF,EAAM,MAAM;CAE/B;CACA;CACA;CACA;CAEA,YAAoB;CACpB;CACA;CAEA;CACA;CACA,WAAmB;CAEnB,YACE,GACA,GAOA;EAYA,AAXA,KAAK,OAAOG,GACZ,KAAK,SAASA,EAAK,OAAO,MAAM,GAChC,KAAK,SAASC,GAEd,KAAK,WAAW,IAAIV,EAAmB,GACvC,KAAK,SAAS,cAAc,GAAG,CAAC,GAChC,KAAK,SAAS,WAAW,MAAM,gBAAgB,QAC/C,KAAK,SAAS,QAAQ,GAAG,CAAC,GAE1BS,EAAK,GAAG,WAAW,KAAK,OAAO,GAE/B,KAAK,QAAQ;CACf;CAEA,gBAAuB;EAIrB,IAHI,KAAK,aACT,KAAK,gCAAgC,sBAAsB,KAAK,OAAO,GAEnE,CAAC,KAAK,KAAK,WAAU;EAEzB,IAAME,IAAe,KAAK,KAAK,SAAS,QAAQJ,CAAQ,GAClDK,IAAa,KAAK,KAAK,SAAS,cAAc,GAC9CC,IAAoBF,EAAa,QAAQ,CAAC,CAAC,KAAK,GAAG,IAAI,MAAMC;EACnE,AAAIC,MAAsB,KAAK,mBAC7B,KAAK,iBAAiBA,GACtB,KAAK,SAAS,cAAcD,CAAU,GACtC,KAAK,SAAS,QAAQD,EAAa,GAAGA,EAAa,CAAC;EAGtD,IAAMG,IAAkB,KAAK,KAAK,OAAO,iBAAiB,QAAQ,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,KAAK,OAAO,YAAY,QAAQ,CAAC,CAAC,KAAK,GAAG;EAQ/H,IAPIA,MAAoB,KAAK,iBAC3B,KAAK,eAAeA,GACpB,KAAK,OAAO,KAAK,KAAK,KAAK,MAAM,IAGnC,KAAK,SAAS,OAAO,KAAK,OAAO,KAAK,MAAM,GAExC,CAAC,KAAK,WAAW;GACnB,IAAMC,IAAU,KAAK,KAAK,WAAW,CAAC,EAAE;GACxC,AAAIA,MACF,KAAK,gBAAgB,SAAS,cAAc,KAAK,GACjD,KAAK,cAAc,UAAU,IAAI,aAAa,GAC9C,KAAK,cAAc,MAAM,WAAW,YACpC,KAAK,cAAc,MAAM,gBAAgB,QACzC,KAAK,cAAc,MAAM,OAAO,KAChC,KAAK,cAAc,MAAM,MAAM,KAC/B,KAAK,cAAc,MAAM,SAAS,GAAG,KAAK,QAAQ,UAAU,KAE5D,KAAK,cAAc,YAAY,KAAK,SAAS,UAAU,GACvDA,EAAQ,YAAY,KAAK,aAAa,GAEtC,KAAK,YAAY;EAErB;CACF;CAEA,oBAA2B;EACzB,KAAK,iCAAiC,qBAAqB,KAAK,6BAA6B;CAC/F;CAEA,gBAAuB;EACrB,AAAI,KAAK,aACT,KAAK,WAAW,IAChB,KAAK,KAAK,IAAI,WAAW,KAAK,OAAO,GACrC,KAAK,YAAY,GACjB,KAAK,SAAS,QAAQ,GACtB,KAAK,SAAS,WAAW,OAAO,GAChC,KAAK,eAAe,OAAO;CAC7B;AACF"}
|