cesium-to-three 0.1.0
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/README.md +226 -0
- package/dist/arrow.js +523 -0
- package/dist/arrow.js.map +1 -0
- package/dist/ground.js +34 -0
- package/dist/ground.js.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/text-primitive-Ci0sbuh1.js +60066 -0
- package/dist/text-primitive-Ci0sbuh1.js.map +1 -0
- package/dist/types/cesium-three-ground.d.ts +2 -0
- package/dist/types/cesium-three-ground.d.ts.map +1 -0
- package/dist/types/lib/arrow/arrow-curves.d.ts +73 -0
- package/dist/types/lib/arrow/arrow-curves.d.ts.map +1 -0
- package/dist/types/lib/arrow/arrow-geometry.d.ts +140 -0
- package/dist/types/lib/arrow/arrow-geometry.d.ts.map +1 -0
- package/dist/types/lib/arrow/arrow-polygon.d.ts +87 -0
- package/dist/types/lib/arrow/arrow-polygon.d.ts.map +1 -0
- package/dist/types/lib/arrow/arrow-types.d.ts +152 -0
- package/dist/types/lib/arrow/arrow-types.d.ts.map +1 -0
- package/dist/types/lib/arrow/index.d.ts +8 -0
- package/dist/types/lib/arrow/index.d.ts.map +1 -0
- package/dist/types/lib/arrow/shapes/assault-direction-arrow.d.ts +20 -0
- package/dist/types/lib/arrow/shapes/assault-direction-arrow.d.ts.map +1 -0
- package/dist/types/lib/arrow/shapes/attack-arrow.d.ts +56 -0
- package/dist/types/lib/arrow/shapes/attack-arrow.d.ts.map +1 -0
- package/dist/types/lib/arrow/shapes/curved-arrow.d.ts +10 -0
- package/dist/types/lib/arrow/shapes/curved-arrow.d.ts.map +1 -0
- package/dist/types/lib/arrow/shapes/fine-arrow.d.ts +23 -0
- package/dist/types/lib/arrow/shapes/fine-arrow.d.ts.map +1 -0
- package/dist/types/lib/arrow/shapes/swallowtail-attack-arrow.d.ts +12 -0
- package/dist/types/lib/arrow/shapes/swallowtail-attack-arrow.d.ts.map +1 -0
- package/dist/types/lib/ground/cesium-ground-adapter.d.ts +9 -0
- package/dist/types/lib/ground/cesium-ground-adapter.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-construct-extruded.d.ts +62 -0
- package/dist/types/lib/ground/circle/circle-construct-extruded.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-extents.d.ts +23 -0
- package/dist/types/lib/ground/circle/circle-extents.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-options.d.ts +59 -0
- package/dist/types/lib/ground/circle/circle-options.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-positions.d.ts +56 -0
- package/dist/types/lib/ground/circle/circle-positions.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-shadow-volume.d.ts +24 -0
- package/dist/types/lib/ground/circle/circle-shadow-volume.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-top-bottom.d.ts +70 -0
- package/dist/types/lib/ground/circle/circle-top-bottom.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-top-indices.d.ts +28 -0
- package/dist/types/lib/ground/circle/circle-top-indices.d.ts.map +1 -0
- package/dist/types/lib/ground/circle/circle-wall-construction.d.ts +75 -0
- package/dist/types/lib/ground/circle/circle-wall-construction.d.ts.map +1 -0
- package/dist/types/lib/ground/classification.d.ts +124 -0
- package/dist/types/lib/ground/classification.d.ts.map +1 -0
- package/dist/types/lib/ground/constants.d.ts +26 -0
- package/dist/types/lib/ground/constants.d.ts.map +1 -0
- package/dist/types/lib/ground/depth.d.ts +63 -0
- package/dist/types/lib/ground/depth.d.ts.map +1 -0
- package/dist/types/lib/ground/geometry.d.ts +12 -0
- package/dist/types/lib/ground/geometry.d.ts.map +1 -0
- package/dist/types/lib/ground/index.d.ts +6 -0
- package/dist/types/lib/ground/index.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-arrowhead.d.ts +67 -0
- package/dist/types/lib/ground/line/line-arrowhead.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-densify.d.ts +35 -0
- package/dist/types/lib/ground/line/line-densify.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-geometry-normals.d.ts +49 -0
- package/dist/types/lib/ground/line/line-geometry-normals.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-options.d.ts +54 -0
- package/dist/types/lib/ground/line/line-options.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-preprocess.d.ts +12 -0
- package/dist/types/lib/ground/line/line-preprocess.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-segment-attributes.d.ts +24 -0
- package/dist/types/lib/ground/line/line-segment-attributes.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-shadow-volume.d.ts +25 -0
- package/dist/types/lib/ground/line/line-shadow-volume.d.ts.map +1 -0
- package/dist/types/lib/ground/line/line-types.d.ts +74 -0
- package/dist/types/lib/ground/line/line-types.d.ts.map +1 -0
- package/dist/types/lib/ground/materials.d.ts +69 -0
- package/dist/types/lib/ground/materials.d.ts.map +1 -0
- package/dist/types/lib/ground/math/cartographic.d.ts +27 -0
- package/dist/types/lib/ground/math/cartographic.d.ts.map +1 -0
- package/dist/types/lib/ground/math/constants.d.ts +20 -0
- package/dist/types/lib/ground/math/constants.d.ts.map +1 -0
- package/dist/types/lib/ground/math/ellipsoid-geodesic.d.ts +93 -0
- package/dist/types/lib/ground/math/ellipsoid-geodesic.d.ts.map +1 -0
- package/dist/types/lib/ground/math/ellipsoid-rhumb-line.d.ts +45 -0
- package/dist/types/lib/ground/math/ellipsoid-rhumb-line.d.ts.map +1 -0
- package/dist/types/lib/ground/math/ellipsoid.d.ts +94 -0
- package/dist/types/lib/ground/math/ellipsoid.d.ts.map +1 -0
- package/dist/types/lib/ground/math/enu-frame.d.ts +27 -0
- package/dist/types/lib/ground/math/enu-frame.d.ts.map +1 -0
- package/dist/types/lib/ground/math/matrix4-helpers.d.ts +20 -0
- package/dist/types/lib/ground/math/matrix4-helpers.d.ts.map +1 -0
- package/dist/types/lib/ground/math/rte-encoding.d.ts +51 -0
- package/dist/types/lib/ground/math/rte-encoding.d.ts.map +1 -0
- package/dist/types/lib/ground/math/vec3-helpers.d.ts +50 -0
- package/dist/types/lib/ground/math/vec3-helpers.d.ts.map +1 -0
- package/dist/types/lib/ground/math/wgs84-helpers.d.ts +22 -0
- package/dist/types/lib/ground/math/wgs84-helpers.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/ellipsoid-tangent-plane.d.ts +71 -0
- package/dist/types/lib/ground/polygon/ellipsoid-tangent-plane.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-cap-construction.d.ts +59 -0
- package/dist/types/lib/ground/polygon/polygon-cap-construction.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-construct-extruded.d.ts +44 -0
- package/dist/types/lib/ground/polygon/polygon-construct-extruded.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-extents.d.ts +24 -0
- package/dist/types/lib/ground/polygon/polygon-extents.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-helpers.d.ts +76 -0
- package/dist/types/lib/ground/polygon/polygon-helpers.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-hierarchy.d.ts +60 -0
- package/dist/types/lib/ground/polygon/polygon-hierarchy.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-offset.d.ts +15 -0
- package/dist/types/lib/ground/polygon/polygon-offset.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-options.d.ts +41 -0
- package/dist/types/lib/ground/polygon/polygon-options.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-rectangle.d.ts +30 -0
- package/dist/types/lib/ground/polygon/polygon-rectangle.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-rings.d.ts +64 -0
- package/dist/types/lib/ground/polygon/polygon-rings.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-shadow-volume.d.ts +39 -0
- package/dist/types/lib/ground/polygon/polygon-shadow-volume.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-style-points.d.ts +29 -0
- package/dist/types/lib/ground/polygon/polygon-style-points.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-subdivide-line.d.ts +93 -0
- package/dist/types/lib/ground/polygon/polygon-subdivide-line.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-subdivide-triangle.d.ts +53 -0
- package/dist/types/lib/ground/polygon/polygon-subdivide-triangle.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/polygon-wall-construction.d.ts +77 -0
- package/dist/types/lib/ground/polygon/polygon-wall-construction.d.ts.map +1 -0
- package/dist/types/lib/ground/polygon/triangulation.d.ts +40 -0
- package/dist/types/lib/ground/polygon/triangulation.d.ts.map +1 -0
- package/dist/types/lib/ground/primitives.d.ts +262 -0
- package/dist/types/lib/ground/primitives.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-attributes.d.ts +29 -0
- package/dist/types/lib/ground/rectangle/rectangle-attributes.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-construct-cap.d.ts +53 -0
- package/dist/types/lib/ground/rectangle/rectangle-construct-cap.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-construct-extruded.d.ts +35 -0
- package/dist/types/lib/ground/rectangle/rectangle-construct-extruded.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-debug.d.ts +22 -0
- package/dist/types/lib/ground/rectangle/rectangle-debug.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-extents.d.ts +33 -0
- package/dist/types/lib/ground/rectangle/rectangle-extents.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-grid.d.ts +76 -0
- package/dist/types/lib/ground/rectangle/rectangle-grid.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-helpers.d.ts +103 -0
- package/dist/types/lib/ground/rectangle/rectangle-helpers.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-options.d.ts +21 -0
- package/dist/types/lib/ground/rectangle/rectangle-options.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-radians.d.ts +51 -0
- package/dist/types/lib/ground/rectangle/rectangle-radians.d.ts.map +1 -0
- package/dist/types/lib/ground/rectangle/rectangle-shadow-volume.d.ts +28 -0
- package/dist/types/lib/ground/rectangle/rectangle-shadow-volume.d.ts.map +1 -0
- package/dist/types/lib/ground/terrain-heights.d.ts +65 -0
- package/dist/types/lib/ground/terrain-heights.d.ts.map +1 -0
- package/dist/types/lib/ground/terrain-log-depth.d.ts +32 -0
- package/dist/types/lib/ground/terrain-log-depth.d.ts.map +1 -0
- package/dist/types/lib/ground/text/index.d.ts +7 -0
- package/dist/types/lib/ground/text/index.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-canvas.d.ts +22 -0
- package/dist/types/lib/ground/text/text-canvas.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-color.d.ts +28 -0
- package/dist/types/lib/ground/text/text-color.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-construct-extruded.d.ts +27 -0
- package/dist/types/lib/ground/text/text-construct-extruded.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-defaults.d.ts +12 -0
- package/dist/types/lib/ground/text/text-defaults.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-extents.d.ts +19 -0
- package/dist/types/lib/ground/text/text-extents.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-layout.d.ts +18 -0
- package/dist/types/lib/ground/text/text-layout.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-options.d.ts +26 -0
- package/dist/types/lib/ground/text/text-options.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-placement.d.ts +34 -0
- package/dist/types/lib/ground/text/text-placement.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-primitive.d.ts +74 -0
- package/dist/types/lib/ground/text/text-primitive.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-shadow-volume.d.ts +21 -0
- package/dist/types/lib/ground/text/text-shadow-volume.d.ts.map +1 -0
- package/dist/types/lib/ground/text/text-types.d.ts +156 -0
- package/dist/types/lib/ground/text/text-types.d.ts.map +1 -0
- package/dist/types/lib/ground/types.d.ts +484 -0
- package/dist/types/lib/ground/types.d.ts.map +1 -0
- package/dist/types/lib/ground/validation.d.ts +8 -0
- package/dist/types/lib/ground/validation.d.ts.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrow.js","sources":["../src/lib/arrow/arrow-geometry.ts","../src/lib/arrow/arrow-polygon.ts","../src/lib/arrow/shapes/fine-arrow.ts","../src/lib/arrow/shapes/assault-direction-arrow.ts","../src/lib/arrow/arrow-curves.ts","../src/lib/arrow/shapes/attack-arrow.ts","../src/lib/arrow/shapes/swallowtail-attack-arrow.ts","../src/lib/arrow/shapes/curved-arrow.ts"],"sourcesContent":["// ============================================================\r\n// arrow/arrow-geometry.ts — 箭头标绘的 2D 几何基础工具\r\n// 层级:L0(零依赖纯函数,经纬度看作平面坐标)\r\n// 职责:提供距离/中点/方位角/旋转步进等纯函数。所有函数都是无副作用的,\r\n// 接收 [lon, lat] 数组,输出新数组或标量。\r\n//\r\n// 与 cesium-plot-js v0.x 的 utils.ts 接口基本一致,但做了三处\r\n// 重要修正:\r\n// 1. azimuthBackward 用 Math.atan2 取代原 asin + 四象限分支,\r\n// 消除轴对齐输入(dx=0 或 dy=0)与零距离时的不确定性。\r\n// 2. mathDistance 与 wholeDistance 加入零长度检测,返回数值零而非\r\n// NaN(原项目在两端重合时 distance=0 → 后续除法产生 NaN)。\r\n// 3. getThirdPoint 接受 finite 检查,保证返回值始终为有限数。\r\n//\r\n// 依赖:无(纯 JS Math)。\r\n// 被消费:arrow/shapes/*.ts、arrow/arrow-curves.ts、arrow/arrow-polygon.ts。\r\n// 算法对应:cesium-plot-js utils.ts(MathDistance / Mid / getAzimuth /\r\n// getThirdPoint / isClockWise / getAngleOfThreePoints / getNormal)。\r\n// ============================================================\r\n\r\nimport type { LonLatPoint } from './arrow-types';\r\n\r\nconst WGS84_SEMI_MAJOR_AXIS_METERS = 6378137.0;\r\nconst WGS84_INVERSE_FLATTENING = 298.257223563;\r\nconst WGS84_FLATTENING = 1.0 / WGS84_INVERSE_FLATTENING;\r\nconst WGS84_FIRST_ECCENTRICITY_SQUARED =\r\n\t2.0 * WGS84_FLATTENING - WGS84_FLATTENING * WGS84_FLATTENING;\r\nconst DEGREES_TO_RADIANS = Math.PI / 180.0;\r\nconst RADIANS_TO_DEGREES = 180.0 / Math.PI;\r\n\r\n/**\r\n * 两个浮点数被视为相等的容差(度坐标空间)。\r\n *\r\n * 1e-9 度 ≈ 0.11 mm @ 赤道,远低于任何实际绘图精度,所以视作\"同点\"。\r\n * 主要用于零距离检测与角度退化判断,避免后续除以 0。\r\n */\r\nconst COINCIDENT_TOLERANCE = 1e-9;\r\n\r\n/**\r\n * 在局部 WGS84 east/north 米制平面中运行箭头生成器。\n *\n * 箭头公式是欧氏几何:宽度、长度、角度必须共享同一单位。公开调用方传入\n * WGS84 度制坐标,所以本辅助函数会先把控制点投影到局部米制坐标框架中\n * 构造形状,再把输出环转换回 lon/lat 度。\n *\n * @param controlPoints 公开 WGS84 [lon, lat] 控制点,单位度。\n * @param createLocalRing 消费局部 [east, north] 米制坐标的工厂函数。\n * @returns 转换回 WGS84 度制后的工厂输出。\n */\nexport function createArrowInLocalMeterPlane(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\tcreateLocalRing: ( localPoints: readonly LonLatPoint[] ) => readonly LonLatPoint[],\r\n): LonLatPoint[] {\r\n\tif ( controlPoints.length === 0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tlet longitudeSum = 0.0;\r\n\tlet latitudeSum = 0.0;\r\n\tfor ( const point of controlPoints ) {\r\n\t\tif (\r\n\t\t\t! Number.isFinite( point[ 0 ] ) ||\r\n\t\t\t! Number.isFinite( point[ 1 ] )\r\n\t\t) {\r\n\t\t\treturn [];\r\n\t\t}\r\n\t\tlongitudeSum += point[ 0 ];\r\n\t\tlatitudeSum += point[ 1 ];\r\n\t}\r\n\r\n\tconst inverseCount = 1.0 / controlPoints.length;\r\n\tconst originLongitudeDegrees = longitudeSum * inverseCount;\r\n\tconst originLatitudeDegrees = latitudeSum * inverseCount;\r\n\tconst latitudeRadians = originLatitudeDegrees * DEGREES_TO_RADIANS;\r\n\tconst sinLatitude = Math.sin( latitudeRadians );\r\n\tconst cosLatitude = Math.cos( latitudeRadians );\r\n\tconst oneMinusESin2 =\r\n\t\t1.0 - WGS84_FIRST_ECCENTRICITY_SQUARED * sinLatitude * sinLatitude;\r\n\tconst primeVerticalRadius =\r\n\t\tWGS84_SEMI_MAJOR_AXIS_METERS / Math.sqrt( oneMinusESin2 );\r\n\tconst meridianRadius =\r\n\t\tWGS84_SEMI_MAJOR_AXIS_METERS *\r\n\t\t( 1.0 - WGS84_FIRST_ECCENTRICITY_SQUARED ) /\r\n\t\t( oneMinusESin2 * Math.sqrt( oneMinusESin2 ) );\r\n\tconst longitudeMetersPerRadian = primeVerticalRadius * cosLatitude;\r\n\tconst latitudeMetersPerRadian = meridianRadius;\r\n\r\n\tif (\r\n\t\tMath.abs( longitudeMetersPerRadian ) < 1e-6 ||\r\n\t\t! Number.isFinite( longitudeMetersPerRadian ) ||\r\n\t\t! Number.isFinite( latitudeMetersPerRadian )\r\n\t) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst localPoints: LonLatPoint[] = controlPoints.map( ( point ) => [\r\n\t\t( point[ 0 ] - originLongitudeDegrees ) *\r\n\t\t\tDEGREES_TO_RADIANS *\r\n\t\t\tlongitudeMetersPerRadian,\r\n\t\t( point[ 1 ] - originLatitudeDegrees ) *\r\n\t\t\tDEGREES_TO_RADIANS *\r\n\t\t\tlatitudeMetersPerRadian,\r\n\t] as LonLatPoint );\r\n\r\n\tconst localRing = createLocalRing( localPoints );\r\n\treturn localRing.map( ( point ) => [\r\n\t\toriginLongitudeDegrees +\r\n\t\t\t( point[ 0 ] / longitudeMetersPerRadian ) * RADIANS_TO_DEGREES,\r\n\t\toriginLatitudeDegrees +\r\n\t\t\t( point[ 1 ] / latitudeMetersPerRadian ) * RADIANS_TO_DEGREES,\r\n\t] as LonLatPoint );\r\n}\r\n\r\n/**\r\n * 两点的欧氏距离(度坐标空间)。\r\n *\r\n * 注:经纬度被当成平面坐标,**不是**地球表面真实距离。本模块的箭头默认\r\n * 跨度较小(< 数十公里),平面近似带来的形变可以忽略。如需长距离贴地\r\n * 绘图,应改用大地线插值后再调用本函数。\r\n *\r\n * @param p1 第一个点 [lon°, lat°]。\r\n * @param p2 第二个点 [lon°, lat°]。\r\n * @returns 距离,度;两点重合时返回 0,不返回 NaN。\r\n */\r\nexport function mathDistance( p1: LonLatPoint, p2: LonLatPoint ): number {\r\n\tconst dx = p1[ 0 ] - p2[ 0 ];\r\n\tconst dy = p1[ 1 ] - p2[ 1 ];\r\n\tconst d2 = dx * dx + dy * dy;\r\n\treturn d2 > 0.0 ? Math.sqrt( d2 ) : 0.0;\r\n}\r\n\r\n/**\r\n * 点序列的总折线长度(相邻点距离之和)。\r\n *\r\n * @param points 至少 1 个点。\r\n * @returns 累积距离,度;单点序列返回 0。\r\n */\r\nexport function wholeDistance( points: readonly LonLatPoint[] ): number {\r\n\tlet total = 0.0;\r\n\tfor ( let i = 1; i < points.length; i++ ) {\r\n\t\ttotal += mathDistance( points[ i - 1 ], points[ i ] );\r\n\t}\r\n\treturn total;\r\n}\r\n\r\n/**\r\n * 基准长度 = 总折线长 ** 0.99。\r\n *\r\n * 与 cesium-plot-js 完全一致——指数 0.99 让长箭头的宽度增长稍慢于线性,\r\n * 即\"大的箭头不至于按比例同样粗\"。指数 1.0 也能用,但视觉上长箭头会\r\n * 显得\"过粗\"。\r\n *\r\n * @param points 控制点序列。\r\n * @returns 基准长度(度的 0.99 次幂);空/单点返回 0。\r\n */\r\nexport function getBaseLength( points: readonly LonLatPoint[] ): number {\r\n\tconst total = wholeDistance( points );\r\n\treturn total > 0.0 ? Math.pow( total, 0.99 ) : 0.0;\r\n}\r\n\r\n/**\r\n * 两点的中点。\r\n *\r\n * @param p1 第一个点。\r\n * @param p2 第二个点。\r\n * @returns 新数组,两点坐标的算术平均。\r\n */\r\nexport function mid( p1: LonLatPoint, p2: LonLatPoint ): LonLatPoint {\r\n\treturn [ ( p1[ 0 ] + p2[ 0 ] ) / 2.0, ( p1[ 1 ] + p2[ 1 ] ) / 2.0 ];\r\n}\r\n\r\n/**\r\n * 沿 startPnt → endPnt 反方向(即从 endPnt 看向 startPnt)的极角,弧度。\r\n *\r\n * 这是 cesium-plot-js 原 getAzimuth 的语义:`(cos α, sin α)` 是从 endPnt\r\n * **指向** startPnt 的单位向量,而不是 start 到 end 的方向。\r\n *\r\n * 内部实现用 `Math.atan2(start.y - end.y, start.x - end.x)`,自然处理所有\r\n * 四个象限以及轴对齐输入,返回范围 [-π, π]。\r\n *\r\n * 这与原项目用 asin + 四个 if 分支的实现等价但更稳健 —— 原实现在\r\n * dx = 0 且 dy = 0 时 distance = 0 → asin(0/0) = NaN,\r\n * 或 dx = 0 时四个分支没有覆盖到边界值,\r\n * 都会让下游 getThirdPoint 返回 NaN,导致整个箭头消失或自交。\r\n *\r\n * @param startPnt 起点(在公式语义中代表\"目标方向\")。\r\n * @param endPnt 终点(下游 getThirdPoint 会以此为锚点)。\r\n * @returns 极角,弧度,范围 [-π, π];两点重合时返回 0(任意方向)。\r\n */\r\nexport function azimuthBackward(\r\n\tstartPnt: LonLatPoint,\r\n\tendPnt: LonLatPoint,\r\n): number {\r\n\tconst dx = startPnt[ 0 ] - endPnt[ 0 ];\r\n\tconst dy = startPnt[ 1 ] - endPnt[ 1 ];\r\n\t// 两点重合时,任意角度都\"合法\",约定返回 0 以让下游 getThirdPoint\r\n\t// 返回 endPnt 沿 +x 方向偏 distance 的点(而非 NaN)。\r\n\tif ( Math.abs( dx ) < COINCIDENT_TOLERANCE && Math.abs( dy ) < COINCIDENT_TOLERANCE ) {\r\n\t\treturn 0.0;\r\n\t}\r\n\treturn Math.atan2( dy, dx );\r\n}\r\n\r\n/**\r\n * 三点共线判定:p1 → p2 → p3 是否顺时针。\r\n *\r\n * 用叉积符号判定:`(p2 - p1) × (p3 - p1) < 0` 时为顺时针(右手系)。\r\n * 共线(叉积 = 0)时返回 false,与原 cesium-plot-js 行为一致。\r\n *\r\n * @param p1 第一个点。\r\n * @param p2 第二个点。\r\n * @param p3 第三个点。\r\n * @returns true 表示顺时针,false 表示逆时针或共线。\r\n */\r\nexport function isClockWise(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\tp3: LonLatPoint,\r\n): boolean {\r\n\tconst ax = p2[ 0 ] - p1[ 0 ];\r\n\tconst ay = p2[ 1 ] - p1[ 1 ];\r\n\tconst bx = p3[ 0 ] - p1[ 0 ];\r\n\tconst by = p3[ 1 ] - p1[ 1 ];\r\n\t// 与 cesium-plot-js 原始公式严格等价:\r\n\t// (p3.y - p1.y) * (p2.x - p1.x) > (p2.y - p1.y) * (p3.x - p1.x)\r\n\t// = by * ax > ay * bx\r\n\t// = ax * by - ay * bx > 0\r\n\t//\r\n\t// 注:cesium-plot-js 的 `isClockWise` 函数名其实是 misnomer——其判别式\r\n\t// `cross > 0` 在标准右手系下是 CCW。但本算法下游(attack-arrow 的\r\n\t// \"if isClockWise then swap tailLeft/tailRight\")依赖的恰是这个语义,\r\n\t// 因此本实现严格保持与原项目一致,不修正函数名。\r\n\t//\r\n\t// 修复历史:早期版本曾写作 `ay*bx - ax*by > 0`(符号反转),导致\r\n\t// 3 点直线情况下 tailLeft 被错误地放到 spine 的\"另一侧\",体部边线\r\n\t// 跨越脊线产生自交。\r\n\treturn ax * by - ay * bx > 0.0;\r\n}\r\n\r\n/**\r\n * 在 endPnt 处,沿 endPnt → startPnt 方向旋转 ±angle 弧度,前进 distance 距离。\r\n *\r\n * 这是箭头几何中最核心的工具——尾翼、颈部、翼尖等所有特殊位置都靠它从\r\n * 一对参考点出发计算出来。\r\n *\r\n * 几何含义:\r\n * 1. 取从 endPnt 看向 startPnt 的方向作为基准方向(azimuthBackward)。\r\n * 2. clockwise = true 时顺时针(+angle)旋转,false 时逆时针(-angle)旋转。\r\n * 3. 沿旋转后的方向从 endPnt 走 distance 度,返回到达的点。\r\n *\r\n * @param startPnt 起点(决定基准方向)。\r\n * @param endPnt 终点(也是输出点的几何锚点)。\r\n * @param angle 从基准方向偏转的角度,弧度,非负。\r\n * @param distance 从 endPnt 出发的距离,度。\r\n * @param clockwise 旋转方向:true = 顺时针,false = 逆时针。\r\n * @returns 新数组,目标点 [lon°, lat°];输入含 NaN/无穷时返回 endPnt 副本。\r\n */\r\nexport function getThirdPoint(\r\n\tstartPnt: LonLatPoint,\r\n\tendPnt: LonLatPoint,\r\n\tangle: number,\r\n\tdistance: number,\r\n\tclockwise: boolean,\r\n): LonLatPoint {\r\n\t// 极端输入保护:任何参数为 NaN/Infinity 时退化为 endPnt 副本,而不是污染输出。\r\n\tif (\r\n\t\t! Number.isFinite( startPnt[ 0 ] ) || ! Number.isFinite( startPnt[ 1 ] ) ||\r\n\t\t! Number.isFinite( endPnt[ 0 ] ) || ! Number.isFinite( endPnt[ 1 ] ) ||\r\n\t\t! Number.isFinite( angle ) || ! Number.isFinite( distance )\r\n\t) {\r\n\t\treturn [ endPnt[ 0 ], endPnt[ 1 ] ];\r\n\t}\r\n\r\n\tconst baseAngle = azimuthBackward( startPnt, endPnt );\r\n\t// 顺/逆时针约定与原项目一致:clockwise = true 时角度 + ,false 时 - 。\r\n\tconst alpha = clockwise ? baseAngle + angle : baseAngle - angle;\r\n\treturn [\r\n\t\tendPnt[ 0 ] + distance * Math.cos( alpha ),\r\n\t\tendPnt[ 1 ] + distance * Math.sin( alpha ),\r\n\t];\r\n}\r\n\r\n/**\r\n * 三点形成的内角(B 顶点处)。\r\n *\r\n * 用 azimuthBackward 而不是 atan2 的差,确保和原 cesium-plot-js 的\r\n * `getAngleOfThreePoints` 在所有合法输入上数值一致。\r\n *\r\n * 返回的角度归一化到 [0, 2π) ——这一点对体部宽度计算的 sin(angle/2)\r\n * 至关重要,如果返回负值会导致 sin 为负 → 宽度方向反转。\r\n *\r\n * @param a 第一个端点。\r\n * @param b 中间顶点。\r\n * @param c 第二个端点。\r\n * @returns 角 ABC 的大小,弧度,范围 [0, 2π);任意点退化时返回 π(直线)。\r\n */\r\nexport function getAngleOfThreePoints(\r\n\ta: LonLatPoint,\r\n\tb: LonLatPoint,\r\n\tc: LonLatPoint,\r\n): number {\r\n\t// b → a 与 b → c 的\"反向方位角\"(即 azimuthBackward 语义)。\r\n\t// 差值即为从 (b→c) 方向旋转到 (b→a) 方向需要的角度。\r\n\tconst angle = azimuthBackward( a, b ) - azimuthBackward( c, b );\r\n\tif ( ! Number.isFinite( angle ) ) {\r\n\t\treturn Math.PI;\r\n\t}\r\n\t// 归一化到 [0, 2π)。\r\n\tlet normalized = angle;\r\n\twhile ( normalized < 0.0 ) {\r\n\t\tnormalized += Math.PI * 2.0;\r\n\t}\r\n\twhile ( normalized >= Math.PI * 2.0 ) {\r\n\t\tnormalized -= Math.PI * 2.0;\r\n\t}\r\n\treturn normalized;\r\n}\r\n\r\n/**\r\n * p2 处的\"内向角平分线\"方向向量(未归一化)。\r\n *\r\n * 几何含义:p1→p2 和 p3→p2 各自单位向量之和,指向 p2 内角的平分线方向。\r\n * 共线时长度趋近于 0,调用方需检查长度判断退化。\r\n *\r\n * 主要用于曲线插值中确定 Bézier 控制点的偏移方向。\r\n *\r\n * @param p1 前一个点。\r\n * @param p2 中间点(法向量从此处发出)。\r\n * @param p3 后一个点。\r\n * @returns [dx, dy] 法向量分量;p1 或 p3 与 p2 重合时返回 [0, 0]。\r\n */\r\nexport function getNormalVector(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\tp3: LonLatPoint,\r\n): [ number, number ] {\r\n\tconst d1 = mathDistance( p1, p2 );\r\n\tconst d2 = mathDistance( p3, p2 );\r\n\tif ( d1 < COINCIDENT_TOLERANCE || d2 < COINCIDENT_TOLERANCE ) {\r\n\t\t// 任一段退化:返回零向量,调用方走\"共线兜底\"分支。\r\n\t\treturn [ 0.0, 0.0 ];\r\n\t}\r\n\tconst ux1 = ( p1[ 0 ] - p2[ 0 ] ) / d1;\r\n\tconst uy1 = ( p1[ 1 ] - p2[ 1 ] ) / d1;\r\n\tconst ux2 = ( p3[ 0 ] - p2[ 0 ] ) / d2;\r\n\tconst uy2 = ( p3[ 1 ] - p2[ 1 ] ) / d2;\r\n\treturn [ ux1 + ux2, uy1 + uy2 ];\r\n}\r\n\r\n/**\r\n * 把一个角度归一化到 [0, 2π)。\r\n *\r\n * 用于角度差运算后保证范围一致,避免后续 sin/cos 因周期性导致符号错误。\r\n *\r\n * @param angle 任意实数角度,弧度。\r\n * @returns 归一化后角度,[0, 2π);输入 NaN 时返回 0。\r\n */\r\nexport function normalizeAngle( angle: number ): number {\r\n\tif ( ! Number.isFinite( angle ) ) {\r\n\t\treturn 0.0;\r\n\t}\r\n\tlet normalized = angle % ( Math.PI * 2.0 );\r\n\tif ( normalized < 0.0 ) {\r\n\t\tnormalized += Math.PI * 2.0;\r\n\t}\r\n\treturn normalized;\r\n}\r\n","// ============================================================\r\n// arrow/arrow-polygon.ts — 箭头输出多边形的清理与正规化\r\n// 层级:L0(基于 arrow-geometry.ts)\r\n// 职责:把箭头生成器拼接出来的\"原始环\"清理为可以安全交给\r\n// CesiumGroundPolygonPrimitive 的\"干净环\",包括三步:\r\n//\r\n// 1. dedupeConsecutivePoints —— 去除连续重复顶点。\r\n// 箭头流程中 leftPnts 的最后一个点是 neckLeft,headPnts 的第一个\r\n// 点也是 neckLeft,直接拼接会产生连续重复;某些三角剖分器对\r\n// 零面积边敏感,需要先 collapse。\r\n//\r\n// 2. ensureCounterClockwise —— 强制 CCW 绕向。\r\n// CesiumGroundPolygonPrimitive 的 shadow volume / SDF 着色器\r\n// 隐含约定外环 CCW,反向会让填充与描边方向错乱。本函数通过\r\n// Shoelace 公式计算有向面积,< 0 则反转。\r\n//\r\n// 3. clampVertexCount —— 必要时降采样到上限以内。\r\n// CesiumGroundPolygonPrimitive 的 MAX_POLYGON_STYLE_VERTICES\r\n// = 128,本模块默认上限 = 120,留 8 个余量。降采样均匀步进保留\r\n// 首尾点,确保闭合形状不变。\r\n//\r\n// 依赖:arrow-geometry.ts 的 mathDistance / COINCIDENT_TOLERANCE 同等阈值。\r\n// 被消费:arrow/shapes/*.ts(所有箭头生成器在 return 前调用 finalizePolygon)。\r\n// ============================================================\r\n\r\nimport { mathDistance } from './arrow-geometry';\r\nimport type { LonLatPoint } from './arrow-types';\r\n\r\n/**\r\n * 顶点上限——给 MAX_POLYGON_STYLE_VERTICES(128) 留出 8 个 buffer。\r\n *\r\n * 留 buffer 的原因:渲染管线可能在内部 stroke / 闭合时追加 1-2 个顶点,\r\n * 严格压到 128 容易在边界 case 触发\"polygon supports at most 128 points\"\r\n * 异常。\r\n */\r\nexport const ARROW_OUTPUT_MAX_VERTICES = 120;\r\n\r\n/**\r\n * 两顶点被视为\"连续重复\"的距离阈值(度)。\r\n *\r\n * 取 1e-10 度 ≈ 0.011 mm @ 赤道,远小于实际绘图可分辨距离。任何小于此阈值\r\n * 的连续顶点都会被 collapse 为一个。\r\n */\r\nconst DEDUPE_TOLERANCE = 1e-10;\r\n\r\n/**\r\n * 去除连续重复顶点(同时检查首尾闭合重复)。\r\n *\r\n * 注:不去重\"非连续\"的重复——多边形中段如果出现两个同坐标顶点,通常意味着\r\n * 形状自交,简单去重会改变拓扑;此情况留给 ensurePolygonValid(可选)处理。\r\n *\r\n * @param ring 原始环。\r\n * @returns 新数组,连续重复点已合并。\r\n */\r\nexport function dedupeConsecutivePoints( ring: readonly LonLatPoint[] ): LonLatPoint[] {\r\n\tif ( ring.length === 0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst out: LonLatPoint[] = [ [ ring[ 0 ][ 0 ], ring[ 0 ][ 1 ] ] ];\r\n\r\n\tfor ( let i = 1; i < ring.length; i++ ) {\r\n\t\tconst current = ring[ i ];\r\n\t\tconst previous = out[ out.length - 1 ];\r\n\t\tif ( mathDistance( current, previous ) > DEDUPE_TOLERANCE ) {\r\n\t\t\tout.push( [ current[ 0 ], current[ 1 ] ] );\r\n\t\t}\r\n\t}\r\n\r\n\t// 检查首尾闭合重复:箭头多边形是闭合环,首尾点不应重复,否则\r\n\t// CesiumGroundPolygonPrimitive 的 normalizePolygonPoints 会按\"独立顶点\"\r\n\t// 处理而产生零长度边。\r\n\tif ( out.length >= 2 ) {\r\n\t\tconst first = out[ 0 ];\r\n\t\tconst last = out[ out.length - 1 ];\r\n\t\tif ( mathDistance( first, last ) <= DEDUPE_TOLERANCE ) {\r\n\t\t\tout.pop();\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\n/**\r\n * 用 Shoelace 公式计算多边形的有向面积(度的平方)。\r\n *\r\n * 公式:`A = 0.5 * Σ (x_i * y_{i+1} - x_{i+1} * y_i)`,索引模 n。\r\n * `A > 0` 时顶点 CCW(逆时针),`A < 0` 时 CW(顺时针)。\r\n *\r\n * @param ring 至少 3 个点,首尾不重复。\r\n * @returns 有向面积;ring.length < 3 时返回 0。\r\n */\r\nexport function signedAreaShoelace( ring: readonly LonLatPoint[] ): number {\r\n\tconst n = ring.length;\r\n\tif ( n < 3 ) {\r\n\t\treturn 0.0;\r\n\t}\r\n\tlet sum = 0.0;\r\n\tfor ( let i = 0; i < n; i++ ) {\r\n\t\tconst a = ring[ i ];\r\n\t\tconst b = ring[ ( i + 1 ) % n ];\r\n\t\tsum += a[ 0 ] * b[ 1 ] - b[ 0 ] * a[ 1 ];\r\n\t}\r\n\treturn sum * 0.5;\r\n}\r\n\r\n/**\r\n * 强制把环调整为 CCW(逆时针)绕向。\r\n *\r\n * CesiumGroundPolygonPrimitive 的着色器与 polygon-rings.ts 的 winding 处理\r\n * 默认外环 CCW,若输入是 CW 会导致填充方向错(以洞当外、或翻面)。\r\n *\r\n * @param ring 已经去重的环。\r\n * @returns 新数组,保证 CCW;若输入已经 CCW 则只是浅拷贝。\r\n */\r\nexport function ensureCounterClockwise( ring: readonly LonLatPoint[] ): LonLatPoint[] {\r\n\tconst area = signedAreaShoelace( ring );\r\n\tif ( area < 0.0 ) {\r\n\t\t// CW → 反转。新数组每点都新建,避免 caller 持有的内部数组被改。\r\n\t\tconst reversed: LonLatPoint[] = new Array( ring.length );\r\n\t\tfor ( let i = 0; i < ring.length; i++ ) {\r\n\t\t\tconst src = ring[ ring.length - 1 - i ];\r\n\t\t\treversed[ i ] = [ src[ 0 ], src[ 1 ] ];\r\n\t\t}\r\n\t\treturn reversed;\r\n\t}\r\n\t// 已经 CCW 或共线(area = 0),浅拷贝即可。\r\n\treturn ring.map( ( p ) => [ p[ 0 ], p[ 1 ] ] as LonLatPoint );\r\n}\r\n\r\n/**\r\n * 均匀降采样到指定上限,严格保留首尾点。\r\n *\r\n * 算法:从 [0, n-1] 区间按 (maxCount-1) 段均匀步进取整数索引。这样\r\n * 首点 (i=0) 与末点 (i=maxCount-1 对应 ring.length-1) 永远入选,中间\r\n * 视形状均匀分布。\r\n *\r\n * 注:严格的\"保形降采样\"应该用 Visvalingam–Whyatt 之类的算法,根据三角形\r\n * 面积优先级删除冗余点。但本模块的箭头由 Catmull-Rom 平滑生成,任意位置\r\n * 的曲率分布都比较均匀,简单步进足够保形 + 实现简单。\r\n *\r\n * @param ring 输入环。\r\n * @param maxCount 目标点数上限,≥ 4。\r\n * @returns 长度 ≤ maxCount 的新数组;输入已满足上限时浅拷贝返回。\r\n */\r\nexport function clampVertexCount(\r\n\tring: readonly LonLatPoint[],\r\n\tmaxCount: number,\r\n): LonLatPoint[] {\r\n\tconst cap = Math.max( Math.floor( maxCount ), 4 );\r\n\tif ( ring.length <= cap ) {\r\n\t\treturn ring.map( ( p ) => [ p[ 0 ], p[ 1 ] ] as LonLatPoint );\r\n\t}\r\n\r\n\tconst sampled: LonLatPoint[] = new Array( cap );\r\n\tconst step = ( ring.length - 1 ) / ( cap - 1 );\r\n\tfor ( let i = 0; i < cap; i++ ) {\r\n\t\tconst srcIdx = Math.round( i * step );\r\n\t\tconst safeIdx = Math.min( srcIdx, ring.length - 1 );\r\n\t\tconst src = ring[ safeIdx ];\r\n\t\tsampled[ i ] = [ src[ 0 ], src[ 1 ] ];\r\n\t}\r\n\treturn sampled;\r\n}\r\n\r\n/**\r\n * 移除 hairpin 顶点(转角 > 阈值的近 180° U-turn)。\r\n *\r\n * 箭头脊线在急转弯处经 Catmull-Rom 平滑后会出现 sample 聚集 + perp 方向\r\n * 急速旋转,Frenet 偏移产生的 leftSide / rightSide 在 cluster 内部出现\r\n * 「短退一步 → 反向冲出」的 cusp(转角接近 180°)。多边形拓扑上虽然不\r\n * 自交,但视觉上是一根「针尖」 — fragment shader 的 point-in-polygon 测试\r\n * 在 cusp 附近边密集 + 浮点边界判断,容易把 cusp 周围一小片像素误判成外部\r\n * (用户截图的三角凹口正是这种 cusp 产生的视觉物)。\r\n *\r\n * 算法:每轮扫描,凡 |turn| > π − threshold(默认 30°,即 turn > 150°)\r\n * 的顶点直接删除。继续迭代直到没有更多 hairpin 或剩余顶点 < 4。\r\n *\r\n * @param ring 已去重的多边形环。\r\n * @param thresholdRad hairpin 阈值(弧度),默认 30° = π/6。turn 接近 π\r\n * (180°)说明前后两条边几乎反向。\r\n * @returns 移除 hairpin 后的环。\r\n */\r\nexport function removeHairpinVertices(\r\n\tring: readonly LonLatPoint[],\r\n\tthresholdRad: number = Math.PI / 6,\r\n): LonLatPoint[] {\r\n\tlet cleaned: LonLatPoint[] = ring.map( ( p ) => [ p[ 0 ], p[ 1 ] ] as LonLatPoint );\r\n\tconst halfTurnMinusThreshold = Math.PI - thresholdRad;\r\n\r\n\tlet changed = true;\r\n\tlet safety = 0;\r\n\twhile ( changed && cleaned.length >= 4 && safety < 1000 ) {\r\n\t\tsafety++;\r\n\t\tchanged = false;\r\n\t\tconst next: LonLatPoint[] = [];\r\n\t\tconst n = cleaned.length;\r\n\t\tfor ( let i = 0; i < n; i++ ) {\r\n\t\t\tconst prev = cleaned[ ( i - 1 + n ) % n ];\r\n\t\t\tconst curr = cleaned[ i ];\r\n\t\t\tconst nxt = cleaned[ ( i + 1 ) % n ];\r\n\t\t\tconst v1x = curr[ 0 ] - prev[ 0 ];\r\n\t\t\tconst v1y = curr[ 1 ] - prev[ 1 ];\r\n\t\t\tconst v2x = nxt[ 0 ] - curr[ 0 ];\r\n\t\t\tconst v2y = nxt[ 1 ] - curr[ 1 ];\r\n\t\t\tconst cross = v1x * v2y - v1y * v2x;\r\n\t\t\tconst dot = v1x * v2x + v1y * v2y;\r\n\t\t\tconst turn = Math.abs( Math.atan2( cross, dot ) );\r\n\t\t\tif ( turn > halfTurnMinusThreshold ) {\r\n\t\t\t\t// hairpin → 跳过这个顶点\r\n\t\t\t\tchanged = true;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tnext.push( [ curr[ 0 ], curr[ 1 ] ] );\r\n\t\t}\r\n\t\tcleaned = next;\r\n\t}\r\n\treturn cleaned;\r\n}\r\n\r\n/**\r\n * 一站式正规化:**去重 → 移除 hairpin → 强制 CCW → 降采样 ≤ maxCount**。\r\n *\r\n * 所有箭头生成器最后一步都应调用此函数,确保输出符合\r\n * CesiumGroundPolygonPrimitive 的契约(3-128 顶点、闭合、CCW、无重复)。\r\n *\r\n * @param rawRing 拼接出来的原始环(可能含重复、CW、超长)。\r\n * @param maxCount 顶点上限,默认 ARROW_OUTPUT_MAX_VERTICES = 120。\r\n * @returns 干净的多边形环;若输入太退化(去重后 < 3 点)返回空数组。\r\n * @throws 从不抛错;非法输入返回空数组,由调用方决定如何反馈。\r\n */\r\nexport function finalizePolygon(\r\n\trawRing: readonly LonLatPoint[],\r\n\tmaxCount: number = ARROW_OUTPUT_MAX_VERTICES,\r\n): LonLatPoint[] {\r\n\t// 1. 去除连续重复 + 首尾闭合重复\r\n\tconst dedup = dedupeConsecutivePoints( rawRing );\r\n\tif ( dedup.length < 3 ) {\r\n\t\t// 退化形状(整条线/单点),无法构成多边形,返回空数组。\r\n\t\t// 调用方需要检查长度 < 3 然后决定是否回退到更简单的箭头。\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// 2. 移除 hairpin(近 180° U-turn 的顶点)。\r\n\tconst noHairpin = removeHairpinVertices( dedup );\r\n\tif ( noHairpin.length < 3 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// 3. 强制 CCW(外环约定)\r\n\tconst ccw = ensureCounterClockwise( noHairpin );\r\n\r\n\t// 4. 降采样到上限\r\n\treturn clampVertexCount( ccw, maxCount );\r\n}\r\n","// ============================================================\r\n// arrow/shapes/fine-arrow.ts — 细箭头(2 点),单笔周界遍历\r\n// 层级:L1(基于 arrow-geometry + arrow-polygon)\r\n// 职责:由两个端点 p1(尾) 和 p2(头) 构造一个 8 顶点的填充箭头多边形:\r\n//\r\n// tailLeft ─── neckLeft ── headLeft\r\n// │ ╲\r\n// p1 p2(尖端)\r\n// │ ╱\r\n// tailRight ── neckRight ── headRight\r\n//\r\n// 尺寸由\"基准长度\"= |p1 p2|^0.99 派生,所有比例(尾宽、颈宽、翼展)\r\n// 通过 FineArrowOptions 暴露给上层覆盖。\r\n//\r\n// 与早期\"成对调用 getThirdPoint(clockwise=true/false) 计算镜像点\"的\r\n// 写法相比,本文件采用**单笔周界遍历**:先在 p1/p2 处确定脊线基(\r\n// spineDir + perp),然后**按 CCW 顺序逐顶点**计算位置,每个顶点都\r\n// 是\"以 p1 或 p2 为锚点 ± 沿脊线/法线的明确偏移\"。\r\n//\r\n// 这样写的两个好处:\r\n// 1. 不再有\"左右两次调用同一个函数\",代码读起来就是 CCW 走一圈,\r\n// 视觉与执行顺序一致;\r\n// 2. 每个 body 顶点之间的边天然位于\"沿脊线 / 沿法线\"两个轴向上,\r\n// 下游 polygon-helpers.ts 的 centroid-径向外扩与\"边垂直方向\"\r\n// 近似一致 → 描边带均匀,而不会沿体部抖动。\r\n//\r\n// 与原 cesium-plot-js 数学上等价(纯重组,顶点坐标完全相同),但更\r\n// 贴合本项目的描边管线。\r\n//\r\n// 依赖:arrow-geometry.ts(mathDistance + getBaseLength),\r\n// arrow-polygon.ts(finalizePolygon),\r\n// arrow-types.ts(FineArrowOptions)。\r\n// 被消费:arrow/index.ts、\r\n// arrow/shapes/attack-arrow.ts(2 控制点退化)、\r\n// arrow/shapes/swallowtail-attack-arrow.ts(2 控制点退化)。\r\n// ============================================================\r\n\r\nimport {\r\n\tcreateArrowInLocalMeterPlane,\r\n\tgetBaseLength,\r\n\tmathDistance,\r\n} from '../arrow-geometry';\r\nimport { finalizePolygon } from '../arrow-polygon';\r\nimport type { ArrowPolygon, FineArrowOptions, LonLatPoint } from '../arrow-types';\r\n\r\n// ── 默认值常量 ──\r\n// 与 cesium-plot-js 完全一致,任何修改请同步更新 arrow-types.ts JSDoc。\r\nconst DEFAULT_TAIL_WIDTH_FACTOR = 0.10;\r\nconst DEFAULT_NECK_WIDTH_FACTOR = 0.20;\r\nconst DEFAULT_HEAD_WIDTH_FACTOR = 0.25;\r\n// 翼展夹角 ≈ 21.18°,颈部夹角 ≈ 13.85°,视觉上呈\"尖锐三角箭头\"。\r\nconst DEFAULT_HEAD_ANGLE_RADIANS = Math.PI / 8.5;\r\nconst DEFAULT_NECK_ANGLE_RADIANS = Math.PI / 13.0;\r\n\r\n/**\r\n * 生成细箭头多边形(单笔 CCW 周界遍历)。\r\n *\r\n * 几何步骤:\r\n * 1. 计算 spineDir = (p2 - p1) / |p2 - p1|;\r\n * perp_CCW = ( -spineDir.y, spineDir.x )(在 +y 朝北的右手系下指向\"逻辑左\")。\r\n * 2. 基准长度 L = |p1 p2|^0.99,派生 tailHalfWidth / neckHalfWidth / headHalfWidth。\r\n * 每个 *HalfWidth 就是该处脊线到对应顶点的**垂直距离**(原版用 tailWidth/\r\n * neckWidth/headWidth 命名,实际上都是 half-width)。\r\n * 3. 颈/翼的纵向位置(从 p2 向 p1 方向回退多少)= cos(angle) × halfWidth;\r\n * 横向位置(垂直脊线偏离多少)= sin(angle) × halfWidth。\r\n * 4. 按 CCW 顺序逐顶点排列 8 个点:\r\n * p1 → tailRight → neckRight → headRight → p2 → headLeft → neckLeft → tailLeft\r\n * 5. 交给 finalizePolygon 去重 + CCW 校正 + 顶点上限 clamp。\r\n *\r\n * @param p1 尾部端点 [lon°, lat°]。\r\n * @param p2 头部端点(尖端)[lon°, lat°]。\r\n * @param options 可选比例覆盖。\r\n * @returns 8(去重后可能更少)顶点的闭合多边形;p1 与 p2 重合时返回空数组。\r\n */\r\nexport function createFineArrow(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\toptions: FineArrowOptions = {},\r\n): ArrowPolygon {\r\n\treturn createArrowInLocalMeterPlane(\r\n\t\t[ p1, p2 ],\r\n\t\t( localPoints ) => createFineArrowLocal(\r\n\t\t\tlocalPoints[ 0 ],\r\n\t\t\tlocalPoints[ 1 ],\r\n\t\t\toptions,\r\n\t\t),\r\n\t);\r\n}\r\n\r\nfunction createFineArrowLocal(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\toptions: FineArrowOptions = {},\r\n): ArrowPolygon {\r\n\tconst tailWidthFactor = options.tailWidthFactor ?? DEFAULT_TAIL_WIDTH_FACTOR;\r\n\tconst neckWidthFactor = options.neckWidthFactor ?? DEFAULT_NECK_WIDTH_FACTOR;\r\n\tconst headWidthFactor = options.headWidthFactor ?? DEFAULT_HEAD_WIDTH_FACTOR;\r\n\tconst headAngleRadians = options.headAngleRadians ?? DEFAULT_HEAD_ANGLE_RADIANS;\r\n\tconst neckAngleRadians = options.neckAngleRadians ?? DEFAULT_NECK_ANGLE_RADIANS;\r\n\r\n\tconst spineLen = mathDistance( p1, p2 );\r\n\tif ( spineLen <= 0.0 ) {\r\n\t\t// 两点重合:无方向可言,返回空让上层决定回退策略。\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst baseLen = getBaseLength( [ p1, p2 ] );\r\n\tif ( baseLen <= 0.0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst tailHalfWidth = baseLen * tailWidthFactor;\r\n\tconst neckHalfWidth = baseLen * neckWidthFactor;\r\n\tconst headHalfWidth = baseLen * headWidthFactor;\r\n\r\n\t// ── 脊线基:spineDir + perp_CCW ──\r\n\tconst spineDirX = ( p2[ 0 ] - p1[ 0 ] ) / spineLen;\r\n\tconst spineDirY = ( p2[ 1 ] - p1[ 1 ] ) / spineLen;\r\n\t// perp_CCW = ( -spineDir.y, spineDir.x ) 是切线左手 90° 旋转,\r\n\t// 在经纬度 +y 朝北的右手系下指向\"沿脊线行进方向的左侧\"。\r\n\tconst perpX = - spineDirY;\r\n\tconst perpY = spineDirX;\r\n\r\n\t// ── 颈 / 翼的\"轴 + 法向\"偏移 ──\r\n\t// 颈点 = p2 + (-spineDir × cos × halfWidth) + (±perp × sin × halfWidth)\r\n\t// 即:从尖端 p2 沿脊线向尾部回退 cos(neckAngle)*neckHalfWidth,\r\n\t// 然后沿 perp 偏离 sin(neckAngle)*neckHalfWidth(左右取符号)。\r\n\tconst neckBack = Math.cos( neckAngleRadians ) * neckHalfWidth;\r\n\tconst neckSide = Math.sin( neckAngleRadians ) * neckHalfWidth;\r\n\tconst headBack = Math.cos( headAngleRadians ) * headHalfWidth;\r\n\tconst headSide = Math.sin( headAngleRadians ) * headHalfWidth;\r\n\r\n\t// ── 8 个 CCW 顶点:沿周界一笔走完,不再分左右两次镜像 ──\r\n\tconst tailRight: LonLatPoint = [\r\n\t\tp1[ 0 ] - perpX * tailHalfWidth,\r\n\t\tp1[ 1 ] - perpY * tailHalfWidth,\r\n\t];\r\n\tconst neckRight: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * neckBack - perpX * neckSide,\r\n\t\tp2[ 1 ] - spineDirY * neckBack - perpY * neckSide,\r\n\t];\r\n\tconst headRight: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * headBack - perpX * headSide,\r\n\t\tp2[ 1 ] - spineDirY * headBack - perpY * headSide,\r\n\t];\r\n\tconst headLeft: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * headBack + perpX * headSide,\r\n\t\tp2[ 1 ] - spineDirY * headBack + perpY * headSide,\r\n\t];\r\n\tconst neckLeft: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * neckBack + perpX * neckSide,\r\n\t\tp2[ 1 ] - spineDirY * neckBack + perpY * neckSide,\r\n\t];\r\n\tconst tailLeft: LonLatPoint = [\r\n\t\tp1[ 0 ] + perpX * tailHalfWidth,\r\n\t\tp1[ 1 ] + perpY * tailHalfWidth,\r\n\t];\r\n\r\n\tconst rawRing: LonLatPoint[] = [\r\n\t\t[ p1[ 0 ], p1[ 1 ] ], // 尾中(下方衔接 tailRight,上方衔接 tailLeft)\r\n\t\ttailRight,\r\n\t\tneckRight,\r\n\t\theadRight,\r\n\t\t[ p2[ 0 ], p2[ 1 ] ], // 箭尖\r\n\t\theadLeft,\r\n\t\tneckLeft,\r\n\t\ttailLeft,\r\n\t];\r\n\r\n\treturn finalizePolygon( rawRing );\r\n}\r\n","// ============================================================\r\n// arrow/shapes/assault-direction-arrow.ts — 突击方向箭头(2 点),\r\n// 单笔周界遍历\r\n// 层级:L1\r\n// 职责:与 FineArrow 同形(8 顶点闭合多边形,p1 尾 + p2 头)但更\"窄长\":\r\n// - 默认尾宽 8% / 颈宽 10% / 翼展 13%(FineArrow 是 10/20/25)\r\n// - 翼展夹角 45°(FineArrow 是 ~21°),颈部夹角 ~32°(FineArrow 是 ~14°)\r\n// - 内部把基准长度放大 1.5 倍(配置项 lengthScale),让箭头看起来更修长。\r\n// 视觉效果:相比 FineArrow,AssaultDirectionArrow 更像\"匕首\"——尾部\r\n// 非常细,头部翼展角度大但翼展短,适合表示局部突击/侦察方向。\r\n//\r\n// 构造方式与 fine-arrow.ts 完全相同:**先取脊线基(spineDir+perp),\r\n// 再单笔走完 8 个 CCW 顶点**。没有\"成对调用 getThirdPoint 计算镜像点\"\r\n// 这种左右拆分,体部边天然沿脊线 / 法线方向排列,描边友好。\r\n//\r\n// 与原 cesium-plot-js 数学等价(纯重组),但更适合本项目的描边管线。\r\n//\r\n// 依赖:arrow-geometry.ts(mathDistance + getBaseLength),\r\n// arrow-polygon.ts(finalizePolygon),\r\n// arrow-types.ts(AssaultDirectionArrowOptions)。\r\n// 被消费:arrow/index.ts。\r\n// ============================================================\r\n\r\nimport {\r\n\tcreateArrowInLocalMeterPlane,\r\n\tgetBaseLength,\r\n\tmathDistance,\r\n} from '../arrow-geometry';\r\nimport { finalizePolygon } from '../arrow-polygon';\r\nimport type {\r\n\tArrowPolygon,\r\n\tAssaultDirectionArrowOptions,\r\n\tLonLatPoint,\r\n} from '../arrow-types';\r\n\r\n// ── 默认值(与 cesium-plot-js AssaultDirection 完全一致)──\r\nconst DEFAULT_LENGTH_SCALE = 1.5;\r\nconst DEFAULT_TAIL_WIDTH_FACTOR = 0.08;\r\nconst DEFAULT_NECK_WIDTH_FACTOR = 0.10;\r\nconst DEFAULT_HEAD_WIDTH_FACTOR = 0.13;\r\nconst DEFAULT_HEAD_ANGLE_RADIANS = Math.PI / 4.0;\r\n// 0.17741π ≈ 0.5575 rad ≈ 31.94°\r\nconst DEFAULT_NECK_ANGLE_RADIANS = Math.PI * 0.17741;\r\n\r\n/**\r\n * 生成突击方向箭头多边形(单笔 CCW 周界遍历)。\r\n *\r\n * 与 createFineArrow 的差异仅在默认比例与 lengthScale,几何步骤完全相同:\r\n * 1. spineDir = (p2 - p1) / |p2 - p1|;perp_CCW = ( -spineDir.y, spineDir.x )\r\n * 2. baseLen = |p1 p2|^0.99 × lengthScale,派生 tail/neck/head 三个 halfWidth\r\n * 3. 颈 / 翼的\"轴 + 法向\"偏移由 cos(angle) × halfWidth 和 sin(angle) × halfWidth\r\n * 给出\r\n * 4. 按 CCW 顺序逐顶点排列 8 个点:\r\n * p1 → tailRight → neckRight → headRight → p2 → headLeft → neckLeft → tailLeft\r\n * 5. 交给 finalizePolygon 去重 + CCW 校正 + 顶点上限 clamp。\r\n *\r\n * @param p1 尾部端点。\r\n * @param p2 头部端点。\r\n * @param options 可选比例覆盖。\r\n * @returns 8 顶点闭合多边形;p1 与 p2 重合时返回空数组。\r\n */\r\nexport function createAssaultDirectionArrow(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\toptions: AssaultDirectionArrowOptions = {},\r\n): ArrowPolygon {\r\n\treturn createArrowInLocalMeterPlane(\r\n\t\t[ p1, p2 ],\r\n\t\t( localPoints ) => createAssaultDirectionArrowLocal(\r\n\t\t\tlocalPoints[ 0 ],\r\n\t\t\tlocalPoints[ 1 ],\r\n\t\t\toptions,\r\n\t\t),\r\n\t);\r\n}\r\n\r\nfunction createAssaultDirectionArrowLocal(\r\n\tp1: LonLatPoint,\r\n\tp2: LonLatPoint,\r\n\toptions: AssaultDirectionArrowOptions = {},\r\n): ArrowPolygon {\r\n\tconst lengthScale = options.lengthScale ?? DEFAULT_LENGTH_SCALE;\r\n\tconst tailWidthFactor = options.tailWidthFactor ?? DEFAULT_TAIL_WIDTH_FACTOR;\r\n\tconst neckWidthFactor = options.neckWidthFactor ?? DEFAULT_NECK_WIDTH_FACTOR;\r\n\tconst headWidthFactor = options.headWidthFactor ?? DEFAULT_HEAD_WIDTH_FACTOR;\r\n\tconst headAngleRadians = options.headAngleRadians ?? DEFAULT_HEAD_ANGLE_RADIANS;\r\n\tconst neckAngleRadians = options.neckAngleRadians ?? DEFAULT_NECK_ANGLE_RADIANS;\r\n\r\n\tconst spineLen = mathDistance( p1, p2 );\r\n\tif ( spineLen <= 0.0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// 基准长度放大 lengthScale 倍——只缩放所有宽度,不改变 p1 / p2 之间的距离。\r\n\t// 视觉上等效于\"箭头看起来更修长\",因为 head/neck/tail 同步变粗,而长度不变,\r\n\t// \"宽 vs 长\"比例下降。\r\n\tconst baseLen = getBaseLength( [ p1, p2 ] ) * lengthScale;\r\n\tif ( baseLen <= 0.0 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst tailHalfWidth = baseLen * tailWidthFactor;\r\n\tconst neckHalfWidth = baseLen * neckWidthFactor;\r\n\tconst headHalfWidth = baseLen * headWidthFactor;\r\n\r\n\t// ── 脊线基:spineDir + perp_CCW ──\r\n\tconst spineDirX = ( p2[ 0 ] - p1[ 0 ] ) / spineLen;\r\n\tconst spineDirY = ( p2[ 1 ] - p1[ 1 ] ) / spineLen;\r\n\tconst perpX = - spineDirY;\r\n\tconst perpY = spineDirX;\r\n\r\n\t// ── 颈 / 翼的\"轴 + 法向\"偏移 ──\r\n\tconst neckBack = Math.cos( neckAngleRadians ) * neckHalfWidth;\r\n\tconst neckSide = Math.sin( neckAngleRadians ) * neckHalfWidth;\r\n\tconst headBack = Math.cos( headAngleRadians ) * headHalfWidth;\r\n\tconst headSide = Math.sin( headAngleRadians ) * headHalfWidth;\r\n\r\n\t// ── 8 个 CCW 顶点:沿周界一笔走完 ──\r\n\tconst tailRight: LonLatPoint = [\r\n\t\tp1[ 0 ] - perpX * tailHalfWidth,\r\n\t\tp1[ 1 ] - perpY * tailHalfWidth,\r\n\t];\r\n\tconst neckRight: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * neckBack - perpX * neckSide,\r\n\t\tp2[ 1 ] - spineDirY * neckBack - perpY * neckSide,\r\n\t];\r\n\tconst headRight: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * headBack - perpX * headSide,\r\n\t\tp2[ 1 ] - spineDirY * headBack - perpY * headSide,\r\n\t];\r\n\tconst headLeft: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * headBack + perpX * headSide,\r\n\t\tp2[ 1 ] - spineDirY * headBack + perpY * headSide,\r\n\t];\r\n\tconst neckLeft: LonLatPoint = [\r\n\t\tp2[ 0 ] - spineDirX * neckBack + perpX * neckSide,\r\n\t\tp2[ 1 ] - spineDirY * neckBack + perpY * neckSide,\r\n\t];\r\n\tconst tailLeft: LonLatPoint = [\r\n\t\tp1[ 0 ] + perpX * tailHalfWidth,\r\n\t\tp1[ 1 ] + perpY * tailHalfWidth,\r\n\t];\r\n\r\n\tconst rawRing: LonLatPoint[] = [\r\n\t\t[ p1[ 0 ], p1[ 1 ] ],\r\n\t\ttailRight,\r\n\t\tneckRight,\r\n\t\theadRight,\r\n\t\t[ p2[ 0 ], p2[ 1 ] ],\r\n\t\theadLeft,\r\n\t\tneckLeft,\r\n\t\ttailLeft,\r\n\t];\r\n\r\n\treturn finalizePolygon( rawRing );\r\n}\r\n","// ============================================================\r\n// arrow/arrow-curves.ts — 通过控制点的平滑曲线插值\r\n// 层级:L0(基于 arrow-geometry.ts)\r\n// 职责:把一组离散控制点插值为一条平滑曲线。本模块用 Centripetal Catmull-Rom\r\n// 样条(α = 0.5),它的两个关键性质恰好解决了 cesium-plot-js 用的\r\n// Quadric B-Spline 的两个老问题:\r\n//\r\n// 1. 通过所有控制点(interpolating)。\r\n// QBSpline 是 approximating 样条,曲线只\"靠近\"控制点而不经过。\r\n// 在箭头体部上,起点 tailLeft 之后立刻跳到 (tailLeft+body1)/2,\r\n// 造成可见的折角;Centripetal CR 严格通过 tailLeft、body1、neckLeft,\r\n// 体部边缘从尾部到颈部连续平滑。\r\n//\r\n// 2. 避免自交与超调。\r\n// Uniform CR 和 Chordal CR 在控制点间距悬殊或近共线时容易出现\r\n// cusps 与环路;Centripetal CR(α = 0.5)在数学上证明\r\n// (Yuksel et al. 2011)无自交、无尖点,正好适合\"沿脊线偏移\r\n// 出的体部边缘\"——这种边缘点距常常因为脊线段长度不均而悬殊。\r\n//\r\n// Bonus:此模块也提供 cubic Bézier(对接 cesium-plot-js 原 getCurvePoints\r\n// 的语义,用于 CurvedArrow 的弯曲脊线)与 chaikin 角点圆滑(用于\r\n// 多边形边角光顺)。\r\n//\r\n// 依赖:arrow-geometry.ts 的 mathDistance / azimuthBackward。\r\n// 被消费:arrow/shapes/attack-arrow.ts、arrow/shapes/curved-arrow.ts、\r\n// arrow/shapes/swallowtail-attack-arrow.ts。\r\n// 算法对应:Catmull-Rom Splines, with Local Control — Yuksel, Schaefer,\r\n// Keyser, 2011 (https://www.cemyuksel.com/research/catmullrom_param/)。\r\n// ============================================================\r\n\r\nimport { mathDistance } from './arrow-geometry';\r\nimport type { LonLatPoint } from './arrow-types';\r\n\r\n/**\r\n * Centripetal Catmull-Rom 样条采样。\r\n *\r\n * 算法步骤:\r\n * 1. 对原始控制点序列两端各 mirror 一个虚拟点,使两端段也能用 CR 公式。\r\n * 镜像点 = `2 * P_endpoint - P_neighbor`,效果等价于\"端点处切线与\r\n * 首/末段平行\",视觉上箭头不会在端点处突然偏离方向。\r\n * 2. 对每相邻 4 个点 P0 P1 P2 P3 计算从 P1 到 P2 的 CR 段,共 N 段。\r\n * 3. 每段内按\"中心向参数化\"(centripetal,α = 0.5)的 t 间隔均匀采样\r\n * `segmentSamples + 1` 个点(含端点,排除下段重复)。\r\n * 4. 在段间共享端点(不重复),最后追加最后一个原始控制点。\r\n *\r\n * 输出长度公式:\r\n * `1 + (controlPoints.length - 1) * segmentSamples`\r\n * 例:5 个控制点 × 12 段采样 = 1 + 4*12 = 49 个输出点。\r\n *\r\n * @param controlPoints 控制点序列,至少 2 个;少于 2 时原样返回。\r\n * @param segmentSamples 每相邻控制点之间额外采样的点数(不含端点),≥ 1。\r\n * @returns 平滑曲线点序列,严格通过所有原始控制点。\r\n */\r\nexport function centripetalCatmullRomSamples(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\tsegmentSamples: number,\r\n): LonLatPoint[] {\r\n\tif ( controlPoints.length < 2 ) {\r\n\t\t// 单点或空:无曲线可言,原样返回浅拷贝。\r\n\t\treturn controlPoints.map( ( p ) => [ p[ 0 ], p[ 1 ] ] as LonLatPoint );\r\n\t}\r\n\tif ( controlPoints.length === 2 ) {\r\n\t\t// 两个点退化为直线段,按 segmentSamples 均匀采样。\r\n\t\treturn linearSegmentSamples( controlPoints[ 0 ], controlPoints[ 1 ], segmentSamples );\r\n\t}\r\n\r\n\t// ── 步骤 1:两端 mirror 虚拟点 ──\n\t// 端点处的 CR 段需要\"前一段\"和\"后一段\"的存在;mirror 提供这两段的\r\n\t// 虚拟控制点,使端点切线沿首/末段方向延伸而不是任意翻转。\r\n\tconst p0First = controlPoints[ 0 ];\r\n\tconst p1First = controlPoints[ 1 ];\r\n\tconst mirrorStart: LonLatPoint = [\r\n\t\t2.0 * p0First[ 0 ] - p1First[ 0 ],\r\n\t\t2.0 * p0First[ 1 ] - p1First[ 1 ],\r\n\t];\r\n\tconst pLast = controlPoints[ controlPoints.length - 1 ];\r\n\tconst pPrev = controlPoints[ controlPoints.length - 2 ];\r\n\tconst mirrorEnd: LonLatPoint = [\r\n\t\t2.0 * pLast[ 0 ] - pPrev[ 0 ],\r\n\t\t2.0 * pLast[ 1 ] - pPrev[ 1 ],\r\n\t];\r\n\r\n\tconst extended: LonLatPoint[] = [ mirrorStart, ...controlPoints, mirrorEnd ];\r\n\r\n\t// ── 步骤 2/3:遍历每相邻 4 个点 (P0,P1,P2,P3) 采样段 P1→P2 ──\n\tconst output: LonLatPoint[] = [];\r\n\tconst safeSegmentSamples = Math.max( Math.floor( segmentSamples ), 1 );\r\n\tconst totalSegments = controlPoints.length - 1;\r\n\r\n\tfor ( let segIdx = 0; segIdx < totalSegments; segIdx++ ) {\r\n\t\tconst p0 = extended[ segIdx ];\r\n\t\tconst p1 = extended[ segIdx + 1 ];\r\n\t\tconst p2 = extended[ segIdx + 2 ];\r\n\t\tconst p3 = extended[ segIdx + 3 ];\r\n\r\n\t\t// 中心向参数化:t_i = t_{i-1} + |P_i - P_{i-1}|^α,α = 0.5。\r\n\t\t// 一些边长可能为 0(连续重合点),取一个最小 chord 避免除零。\r\n\t\tconst MIN_CHORD = 1e-12;\r\n\t\tconst t0 = 0.0;\r\n\t\tconst t1 = t0 + Math.max( Math.pow( mathDistance( p0, p1 ), 0.5 ), MIN_CHORD );\r\n\t\tconst t2 = t1 + Math.max( Math.pow( mathDistance( p1, p2 ), 0.5 ), MIN_CHORD );\r\n\t\tconst t3 = t2 + Math.max( Math.pow( mathDistance( p2, p3 ), 0.5 ), MIN_CHORD );\r\n\r\n\t\t// 在 [t1, t2] 区间均匀采样。第一段输出包含起点 P1,后续段跳过起点\r\n\t\t// (避免重复)。\r\n\t\tconst includeStart = segIdx === 0;\r\n\t\tconst startSampleIndex = includeStart ? 0 : 1;\r\n\t\t// 每段输出 segmentSamples + 1 个点(含起点和终点);最终所有段\r\n\t\t// 共有 1 + N * segmentSamples 个采样点,与文档保持一致。\r\n\t\t// 注意:终点 P2 是下段的起点 P1,所以这里只到 segmentSamples(不含),\r\n\t\t// 而最后一段把 P2(原始最后一个控制点)单独 push 进去。\r\n\t\tconst isLastSegment = segIdx === totalSegments - 1;\r\n\t\tconst endSampleIndex = isLastSegment ? safeSegmentSamples + 1 : safeSegmentSamples;\r\n\r\n\t\tfor ( let i = startSampleIndex; i < endSampleIndex; i++ ) {\r\n\t\t\tconst t = t1 + ( t2 - t1 ) * ( i / safeSegmentSamples );\r\n\t\t\toutput.push( catmullRomBlend( p0, p1, p2, p3, t0, t1, t2, t3, t ) );\r\n\t\t}\r\n\t}\r\n\r\n\treturn output;\r\n}\r\n\r\n/**\r\n * Centripetal Catmull-Rom 的 4 点混合公式(Yuksel et al. 2011)。\r\n *\r\n * 给定 4 个控制点 P0..P3 与对应参数 t0..t3,以及当前参数 t (t1 ≤ t ≤ t2),\r\n * 返回曲线在 t 处的位置。混合用嵌套线性插值:\r\n *\r\n * A1 = lerp(P0, P1, (t-t0)/(t1-t0))\r\n * A2 = lerp(P1, P2, (t-t1)/(t2-t1))\r\n * A3 = lerp(P2, P3, (t-t2)/(t3-t2))\r\n * B1 = lerp(A1, A2, (t-t0)/(t2-t0))\r\n * B2 = lerp(A2, A3, (t-t1)/(t3-t1))\r\n * C = lerp(B1, B2, (t-t1)/(t2-t1))\r\n *\r\n * 共 6 次 lerp,可证明 C(t1) = P1,C(t2) = P2(经过控制点性质)。\r\n */\r\nfunction catmullRomBlend(\r\n\tp0: LonLatPoint, p1: LonLatPoint, p2: LonLatPoint, p3: LonLatPoint,\r\n\tt0: number, t1: number, t2: number, t3: number,\r\n\tt: number,\r\n): LonLatPoint {\r\n\tconst a1 = lerpPoint( p0, p1, ( t - t0 ) / ( t1 - t0 ) );\r\n\tconst a2 = lerpPoint( p1, p2, ( t - t1 ) / ( t2 - t1 ) );\r\n\tconst a3 = lerpPoint( p2, p3, ( t - t2 ) / ( t3 - t2 ) );\r\n\tconst b1 = lerpPoint( a1, a2, ( t - t0 ) / ( t2 - t0 ) );\r\n\tconst b2 = lerpPoint( a2, a3, ( t - t1 ) / ( t3 - t1 ) );\r\n\treturn lerpPoint( b1, b2, ( t - t1 ) / ( t2 - t1 ) );\r\n}\r\n\r\n/**\r\n * 两点的线性插值。`f = 0` 返回 a,`f = 1` 返回 b。\r\n *\r\n * 不做 clamp:Catmull-Rom 内部混合需要 f 略大于 1 或略小于 0 也能正确外推\r\n * (但实际数值上都在 [0, 1] 附近)。\r\n */\r\nfunction lerpPoint(\r\n\ta: LonLatPoint,\r\n\tb: LonLatPoint,\r\n\tf: number,\r\n): LonLatPoint {\r\n\treturn [\r\n\t\ta[ 0 ] + ( b[ 0 ] - a[ 0 ] ) * f,\r\n\t\ta[ 1 ] + ( b[ 1 ] - a[ 1 ] ) * f,\r\n\t];\r\n}\r\n\r\n/**\r\n * 两点之间的均匀线性采样,含两端点。\r\n *\r\n * 退化分支:当 Centripetal CR 输入只有 2 个控制点时,曲线退化为直线段,\r\n * 这里直接均匀采样 segmentSamples + 1 个点。\r\n *\r\n * @param a 起点。\r\n * @param b 终点。\r\n * @param segmentSamples 段内额外采样数,≥ 1。\r\n * @returns 长度 segmentSamples + 1 的点序列,首尾分别为 a / b。\r\n */\r\nfunction linearSegmentSamples(\r\n\ta: LonLatPoint,\r\n\tb: LonLatPoint,\r\n\tsegmentSamples: number,\r\n): LonLatPoint[] {\r\n\tconst n = Math.max( Math.floor( segmentSamples ), 1 );\r\n\tconst points: LonLatPoint[] = new Array( n + 1 );\r\n\tfor ( let i = 0; i <= n; i++ ) {\r\n\t\tconst t = i / n;\r\n\t\tpoints[ i ] = [\r\n\t\t\ta[ 0 ] + ( b[ 0 ] - a[ 0 ] ) * t,\r\n\t\t\ta[ 1 ] + ( b[ 1 ] - a[ 1 ] ) * t,\r\n\t\t];\r\n\t}\r\n\treturn points;\r\n}\r\n\r\n/**\r\n * 三次 Bézier 曲线段采样(用于 CurvedArrow 的脊线)。\r\n *\r\n * 公式 B(t) = (1-t)³·P0 + 3(1-t)²t·C1 + 3(1-t)t²·C2 + t³·P3\r\n *\r\n * 与 cesium-plot-js 的 getCubicValue 一致,这里只是单段采样;\r\n * 整条 Bézier 链需要调用方在每段间用同样的控制点连接(C1 连续由\r\n * 调用方保证控制点对称即可)。\r\n *\r\n * @param p0 起点。\r\n * @param c1 第一个控制点。\r\n * @param c2 第二个控制点。\r\n * @param p3 终点。\r\n * @param samples 段内采样数(不含两端),≥ 1。\r\n * @returns 包含两端点的采样点序列,长度 samples + 1。\r\n */\r\nexport function cubicBezierSegmentSamples(\r\n\tp0: LonLatPoint,\r\n\tc1: LonLatPoint,\r\n\tc2: LonLatPoint,\r\n\tp3: LonLatPoint,\r\n\tsamples: number,\r\n): LonLatPoint[] {\r\n\tconst n = Math.max( Math.floor( samples ), 1 );\r\n\tconst out: LonLatPoint[] = new Array( n + 1 );\r\n\tfor ( let i = 0; i <= n; i++ ) {\r\n\t\tconst t = i / n;\r\n\t\tconst tp = 1.0 - t;\r\n\t\tconst t2 = t * t;\r\n\t\tconst t3 = t2 * t;\r\n\t\tconst tp2 = tp * tp;\r\n\t\tconst tp3 = tp2 * tp;\r\n\t\tout[ i ] = [\r\n\t\t\ttp3 * p0[ 0 ] + 3.0 * tp2 * t * c1[ 0 ] + 3.0 * tp * t2 * c2[ 0 ] + t3 * p3[ 0 ],\r\n\t\t\ttp3 * p0[ 1 ] + 3.0 * tp2 * t * c1[ 1 ] + 3.0 * tp * t2 * c2[ 1 ] + t3 * p3[ 1 ],\r\n\t\t];\r\n\t}\r\n\treturn out;\r\n}\r\n\r\n/**\r\n * 沿一条折线/曲线计算每点处的切线方向(单位向量)。\r\n *\r\n * 用于按 perpendicular offset 生成\"等宽线条\"的左右两条平行线。\r\n * 中间点用中央差分(前后邻居距离归一),端点用前向/后向差分。\r\n *\r\n * @param points 至少 2 个点。\r\n * @returns 与输入等长的单位切向量数组,每个元素 [tx, ty]。\r\n */\r\nexport function computeTangents(\r\n\tpoints: readonly LonLatPoint[],\r\n): [ number, number ][] {\r\n\tconst n = points.length;\r\n\tconst tangents: [ number, number ][] = new Array( n );\r\n\r\n\tif ( n === 0 ) {\r\n\t\treturn tangents;\r\n\t}\r\n\tif ( n === 1 ) {\r\n\t\t// 单点:无意义,返回 +x 方向占位。\r\n\t\ttangents[ 0 ] = [ 1.0, 0.0 ];\r\n\t\treturn tangents;\r\n\t}\r\n\r\n\tfor ( let i = 0; i < n; i++ ) {\r\n\t\t// 中央差分(端点退化为前向/后向差分):\r\n\t\t// prevIdx = i > 0 ? i - 1 : i\r\n\t\t// nextIdx = i < n-1 ? i + 1 : i\r\n\t\tconst prevIdx = i > 0 ? i - 1 : i;\r\n\t\tconst nextIdx = i < n - 1 ? i + 1 : i;\r\n\t\tconst dx = points[ nextIdx ][ 0 ] - points[ prevIdx ][ 0 ];\r\n\t\tconst dy = points[ nextIdx ][ 1 ] - points[ prevIdx ][ 1 ];\r\n\t\tconst len = Math.sqrt( dx * dx + dy * dy );\r\n\t\tif ( len > 0.0 ) {\r\n\t\t\ttangents[ i ] = [ dx / len, dy / len ];\r\n\t\t} else {\r\n\t\t\t// 退化:前后邻居完全重合(在去重之后理论上不会发生)。\r\n\t\t\t// 用 +x 占位,避免下游 perpendicular 算出 NaN。\r\n\t\t\ttangents[ i ] = [ 1.0, 0.0 ];\r\n\t\t}\r\n\t}\r\n\r\n\treturn tangents;\r\n}\r\n\r\n/**\r\n * 沿折线/曲线从末尾回退给定弧长,定位精确截断点。\r\n *\r\n * 用于 attack/swallowtail/curved 三类箭头里\"把 spine 在 neck 处剪开\"的需求:\r\n * - body 部分用 spine[0..k] + 截断点\r\n * - head 部分由调用方独立构造\r\n *\r\n * 算法:从最末样本开始往回累加段长,直到累加值刚好覆盖 distanceFromEnd。\r\n * 截断点落在最后那个跨越阈值的线段内,用线性插值得到精确坐标。\r\n *\r\n * @param samples 至少 2 个点的密采折线/曲线。\r\n * @param distanceFromEnd 截断点距 samples 末点的弧长。\r\n * ≤ 0 时截断点即末点(localT = 1.0);\r\n * ≥ totalLen 时返回 null(头部比脊线还长)。\r\n * @returns 截断点 segmentIdx (起点索引)、 localT (∈[0,1])、 point (坐标)\r\n * 的对象;距离不可达时返回 null。\r\n */\r\nexport interface PolylineCutPoint {\r\n\tsegmentIdx: number;\r\n\tlocalT: number;\r\n\tpoint: LonLatPoint;\r\n}\r\n\r\nexport function findPointAlongPolylineFromEnd(\r\n\tsamples: readonly LonLatPoint[],\r\n\tdistanceFromEnd: number,\r\n): PolylineCutPoint | null {\r\n\tconst n = samples.length;\r\n\tif ( n < 2 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// distanceFromEnd ≤ 0:截断点就是末点本身;落在最后一段的末端 (localT = 1)。\r\n\tif ( distanceFromEnd <= 0.0 ) {\r\n\t\treturn {\r\n\t\t\tsegmentIdx: n - 2,\r\n\t\t\tlocalT: 1.0,\r\n\t\t\tpoint: [ samples[ n - 1 ][ 0 ], samples[ n - 1 ][ 1 ] ],\r\n\t\t};\r\n\t}\r\n\r\n\tlet accum = 0.0;\r\n\tfor ( let i = n - 1; i > 0; i-- ) {\r\n\t\tconst segLen = mathDistance( samples[ i ], samples[ i - 1 ] );\r\n\t\tif ( accum + segLen >= distanceFromEnd ) {\r\n\t\t\t// 截断点落在线段 [i-1, i] 内。\r\n\t\t\t// remainFromEndPoint = 截断点距 samples[i] 的距离。\r\n\t\t\tconst remainFromEndPoint = distanceFromEnd - accum;\r\n\t\t\t// 由于我们从 samples[i] 出发往 samples[i-1] 走 remainFromEndPoint,\r\n\t\t\t// 等价 localT = 1 - remainFromEndPoint / segLen 在 [0,1] 内。\r\n\t\t\tconst localT = segLen > 0.0 ? 1.0 - remainFromEndPoint / segLen : 1.0;\r\n\t\t\tconst ax = samples[ i - 1 ][ 0 ];\r\n\t\t\tconst ay = samples[ i - 1 ][ 1 ];\r\n\t\t\tconst bx = samples[ i ][ 0 ];\r\n\t\t\tconst by = samples[ i ][ 1 ];\r\n\t\t\treturn {\r\n\t\t\t\tsegmentIdx: i - 1,\r\n\t\t\t\tlocalT,\r\n\t\t\t\tpoint: [\r\n\t\t\t\t\tax + ( bx - ax ) * localT,\r\n\t\t\t\t\tay + ( by - ay ) * localT,\r\n\t\t\t\t],\r\n\t\t\t};\r\n\t\t}\r\n\t\taccum += segLen;\r\n\t}\r\n\r\n\t// 走完整条折线都没覆盖 distanceFromEnd → 头部比脊线还长。\r\n\treturn null;\r\n}\r\n","// ============================================================\r\n// arrow/shapes/attack-arrow.ts — 攻击箭头(3+ 点),Frenet 带状构造\r\n// 层级:L1\r\n// 职责:由 3 个以上控制点定义\"宽体渐变\"攻击箭头。本文件用 **Frenet 法线\r\n// 偏移**构造箭头体,而不是先在脊线两侧各算一组离散偏移点然后分别\r\n// Catmull-Rom 平滑(见\"为什么放弃左右各自平滑\"一节)。\r\n//\r\n// 输出多边形仍然是一个 CCW 闭合环,几何形态与原 cesium-plot-js\r\n// AttackArrow 相同:尾部直边 + 渐变体部 + 5 点三角头。\r\n//\r\n// 控制点契约:\r\n// points[0], points[1] —— 两点决定尾部位置与宽度(连线为尾边)\r\n// points[2..n] —— 从第 3 点开始定义脊线(箭头体走向),\r\n// 最末点 points[n-1] 即箭头尖端\r\n//\r\n// 几何步骤(单笔周界遍历):\r\n// 1. tailLeft / tailRight (用 isClockWise 判定方向),midTail = mid(L,R)\r\n// 2. spineControlPoints = [ midTail, points[2..n-1] ]\r\n// 3. spineSamples = Centripetal Catmull-Rom(spineControlPoints) —— 这是\r\n// 整条脊线唯一的一次平滑,左右两侧共享同一组样本。\r\n// 4. headHeight clamp(同原版):受 tailWidth*headTailFactor 与最末段长约束\r\n// 5. neckPoint = findPointAlongPolylineFromEnd(spineSamples, neckHeight)\r\n// 把 spineSamples 在 neck 处剪开:bodySpine = samples[0..k] ⊕ neckPoint\r\n// 6. tangents = computeTangents(bodySpine) —— 每个 body 样本的单位切向\r\n// 7. 沿 bodySpine 一笔走完左侧 (tailLeft → neckLeft),再走头部 3 点\r\n// (headLeft → tip → headRight),再反向走完右侧 (neckRight → tailRight)。\r\n// 每个 body 顶点 = sample + ±perp × halfWidth(i),其中 halfWidth(i)\r\n// 在 [tailHalfWidth, neckHalfWidth] 之间线性插值(taper 由控制点契约\r\n// 隐含,无需额外参数)。\r\n// 8. 收尾:把 leftSide[0] / rightSide[0] 强制对齐 tailLeft / tailRight,\r\n// 保证用户指定的尾角严格出现在多边形上(避免 Catmull-Rom 微小漂移)。\r\n//\r\n// 为什么放弃\"左右各自平滑\":\r\n// 原 cesium-plot-js AttackArrow 在脊线每个内部顶点处计算 leftBody[i] /\r\n// rightBody[i] 两个互为镜像的离散偏移点,然后**各自**做一次 Catmull-Rom\r\n// 平滑。问题:\r\n// a. 左右各做一次 CR,导致同一脊线段两侧的密采点 **轴向上**不一致\r\n// (左侧的第 k 个样本与右侧的第 k 个样本不在同一脊线弧长位置上),\r\n// 多边形相邻 body 顶点之间的边并不严格沿脊线切线方向。\r\n// b. 这些 body 顶点交给 polygon-helpers.ts 的\r\n// `expandPolygonPointsThroughMeters` 做描边外扩时,后者沿\r\n// **多边形 centroid → 顶点** 径向方向推每个顶点 N 米。body 侧顶点的\r\n// 径向方向 ≈ 脊线垂直方向(理想),但只有\"边沿脊线切向排列\"时,\r\n// 逐顶点的径向 ≈ 边垂直,描边才会均匀。\r\n// 左右各自 CR 给出的边方向偏离脊线切向,导致描边宽度沿体部抖动。\r\n//\r\n// 本实现改为**对脊线只做一次 CR**,然后逐样本沿切向 perp 偏移生成\r\n// left/right 两条平行带 —— 同一 i 的 leftSide[i] 与 rightSide[i] 严格位于\r\n// 同一脊线弧长位置的两侧,相邻 body 顶点之间的边天然沿脊线切线方向,描边\r\n// 外扩与\"边垂直方向\"近似一致 → 描边带均匀。\r\n//\r\n// 注:本实现的输出多边形仍然关于脊线对称。差别在内部构造路径——\"两次\r\n// 各自 CR 漂移\"vs\"一次 CR 共享样本\"。对下游描边管线的友好度天差地别。\r\n//\r\n// 依赖:arrow-geometry.ts、arrow-curves.ts、arrow-polygon.ts、arrow-types.ts、\r\n// shapes/fine-arrow.ts(2 控制点退化)。\r\n// 被消费:arrow/index.ts、arrow/shapes/swallowtail-attack-arrow.ts(复用本文件\r\n// 的 `buildAttackArrowSkeleton` 内部 helper)。\r\n// ============================================================\r\n\r\nimport {\r\n\tcreateArrowInLocalMeterPlane,\r\n\tgetBaseLength,\r\n\tmathDistance,\r\n\tmid,\r\n} from '../arrow-geometry';\r\nimport {\r\n\tcentripetalCatmullRomSamples,\r\n\tcomputeTangents,\r\n\tfindPointAlongPolylineFromEnd,\r\n} from '../arrow-curves';\r\nimport { finalizePolygon } from '../arrow-polygon';\r\nimport type {\r\n\tArrowPolygon,\r\n\tAttackArrowOptions,\r\n\tLonLatPoint,\r\n} from '../arrow-types';\r\nimport { createFineArrow } from './fine-arrow';\r\n\r\n// ── 默认值(与 cesium-plot-js AttackArrow 同名字段保持一致)──\r\nconst DEFAULT_HEAD_HEIGHT_FACTOR = 0.28;\r\nconst DEFAULT_HEAD_WIDTH_FACTOR = 0.55;\r\nconst DEFAULT_NECK_HEIGHT_FACTOR = 0.85;\r\nconst DEFAULT_NECK_WIDTH_FACTOR = 0.22;\r\nconst DEFAULT_HEAD_TAIL_FACTOR = 1.25;\r\n// 12:Catmull-Rom 每段采样 12 点。多控制点脊线下采样总数 = (n-1)*12 + 1,\r\n// 远低于 ARROW_OUTPUT_MAX_VERTICES = 120 的上限。\r\nconst DEFAULT_BODY_SMOOTHING_SEGMENTS = 12;\r\n// 注:`minBodyHalfAngleRadians` / `bodyWidthMargin` 在原实现里用来反算\r\n// w = (tailWidth/2 - dropoff) / sin(halfAngle) 时做 clamp。Frenet 构造下,\r\n// 体宽由 tailHalfWidth 与 neckHalfWidth 之间的线性插值决定,完全不进入\r\n// sin(α) 这条分母路径,因此两个鲁棒性字段保留在 API 表面只是为了让 GUI\r\n// 上层不必为\"老选项是否仍存在\"做条件渲染。Frenet 构造内部已无相关计算。\r\n\r\n/**\r\n * 攻击箭头骨架。\r\n *\r\n * 暴露给 swallowtail-attack-arrow.ts 复用,后者只需要在尾部多加一个燕尾\r\n * 凸点,体部 / 头部几何与本文件 100% 一致。\r\n */\r\nexport interface AttackArrowSkeleton {\r\n\t/** 脊线左侧带,leftSide[0] = tailLeft、leftSide[last] = neckLeft。 */\r\n\tleftSide: LonLatPoint[];\r\n\t/** 脊线右侧带,rightSide[0] = tailRight、rightSide[last] = neckRight。 */\r\n\trightSide: LonLatPoint[];\r\n\t/** 左翼尖(在 neck 处沿法线外扩 headHalfWidth)。 */\r\n\theadLeft: LonLatPoint;\r\n\t/** 右翼尖。 */\r\n\theadRight: LonLatPoint;\r\n\t/** 箭尖(与用户控制点 controlPoints[n-1] 严格一致)。 */\r\n\ttip: LonLatPoint;\r\n\t/** 尾左角(与 leftSide[0] 严格一致)。 */\r\n\ttailLeft: LonLatPoint;\r\n\t/** 尾右角(与 rightSide[0] 严格一致)。 */\r\n\ttailRight: LonLatPoint;\r\n\t/** 尾中点(燕尾箭头里用作\"燕尾凸出方向\"的参考)。 */\r\n\tmidTail: LonLatPoint;\r\n\t/** 脊线第二个控制点(燕尾箭头里用作\"燕尾凸出方向\"的参考)。 */\r\n\tspineSecond: LonLatPoint;\r\n\t/**\r\n\t * 整条脊线(含 midTail + 全部 controlPoints[2..n-1])的基准长度\r\n\t * = wholeDistance(spineControlPoints) ** 0.99。\r\n\t * 燕尾箭头里\"燕尾凸出深度\"的尺度来自这个值,与原版一致。\r\n\t */\r\n\tspineBaseLen: number;\r\n}\r\n\r\n/**\r\n * 构造攻击箭头(Frenet 带状)。\r\n *\r\n * @param controlPoints 控制点序列,至少 3 个。少于 3 时:\r\n * - controlPoints.length === 2 → 退化为 createFineArrow(与原版兼容)\r\n * - controlPoints.length < 2 → 返回空数组\r\n * @param options 可选比例与平滑参数。\r\n * @returns 闭合多边形;输入退化时可能返回空数组。\r\n */\r\nexport function createAttackArrow(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: AttackArrowOptions = {},\r\n): ArrowPolygon {\r\n\treturn createArrowInLocalMeterPlane(\r\n\t\tcontrolPoints,\r\n\t\t( localPoints ) => createAttackArrowLocal( localPoints, options ),\r\n\t);\r\n}\r\n\r\nfunction createAttackArrowLocal(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: AttackArrowOptions = {},\r\n): ArrowPolygon {\r\n\t// ── 输入校验 + 兼容退化 ──\r\n\tif ( controlPoints.length < 2 ) {\r\n\t\treturn [];\r\n\t}\r\n\tif ( controlPoints.length === 2 ) {\r\n\t\treturn createFineArrow( controlPoints[ 0 ], controlPoints[ 1 ] );\r\n\t}\r\n\r\n\tconst skeleton = buildAttackArrowSkeleton( controlPoints, options );\r\n\tif ( ! skeleton ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// ── 单笔周界遍历(CCW)──\r\n\t// 顺序:\r\n\t// leftSide[0..lastBodyIdx] (tailLeft → neckLeft,沿脊线左侧前进)\r\n\t// headLeft (左翼尖,在 neck 处法线外扩 headWidth)\r\n\t// tip (脊线最末点,严格采用用户控制点)\r\n\t// headRight (右翼尖)\r\n\t// reverse rightSide[..0] (neckRight → tailRight,沿脊线右侧回退)\r\n\t//\r\n\t// leftSide[last] = neckLeft、rightSide[last] = neckRight 已经是颈侧顶点。\r\n\t// headLeft / headRight 与 neckLeft / neckRight 在同一垂直于切线的射线上,\r\n\t// 只是 headLeft / Right 半宽更大 → 形成自然翼展张开,不产生重复顶点。\r\n\tconst rawRing: LonLatPoint[] = [\r\n\t\t...skeleton.leftSide, // tailLeft → ... → neckLeft\r\n\t\tskeleton.headLeft, // 左翼尖\r\n\t\tskeleton.tip, // 箭尖\r\n\t\tskeleton.headRight, // 右翼尖\r\n\t\t...skeleton.rightSide.slice().reverse(), // neckRight → ... → tailRight\r\n\t];\r\n\r\n\treturn finalizePolygon( rawRing );\r\n}\r\n\r\n/**\r\n * 构造攻击箭头骨架(脊线 + 左右带 + 头部 3 点)。\r\n *\r\n * 把 spine、左右带、头部 3 点暴露给 swallowtail-attack-arrow.ts 复用,\r\n * 详细几何步骤见文件顶部的\"几何步骤\"注释。\r\n * 任何输入退化(脊线少于 2 点、长度为 0 等)时返回 null。\r\n *\r\n * @param controlPoints 控制点序列,至少 3 个(由调用方校验)。\r\n * @param options AttackArrow 选项;未传字段使用本文件默认值。\r\n * @returns 骨架对象;输入退化时返回 null。\r\n */\r\nexport function buildAttackArrowSkeleton(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: AttackArrowOptions,\r\n): AttackArrowSkeleton | null {\r\n\t// ── 解析选项 ──\r\n\tconst headHeightFactor = options.headHeightFactor ?? DEFAULT_HEAD_HEIGHT_FACTOR;\r\n\tconst headWidthFactor = options.headWidthFactor ?? DEFAULT_HEAD_WIDTH_FACTOR;\r\n\tconst neckHeightFactor = options.neckHeightFactor ?? DEFAULT_NECK_HEIGHT_FACTOR;\r\n\tconst neckWidthFactor = options.neckWidthFactor ?? DEFAULT_NECK_WIDTH_FACTOR;\r\n\tconst headTailFactor = options.headTailFactor ?? DEFAULT_HEAD_TAIL_FACTOR;\r\n\tconst bodySmoothingSegments =\r\n\t\toptions.bodySmoothingSegments ?? DEFAULT_BODY_SMOOTHING_SEGMENTS;\r\n\r\n\t// ── 步骤 1:tailLeft / tailRight + midTail ──\r\n\t// 体部走 Frenet 法线偏移:perp_CCW = ( -spineDirY, spineDirX ) 指向脊线的\r\n\t// 左侧(在 +y 朝北的右手系下)。要求 leftSide[0] = tailLeft 也位于这一侧,\r\n\t// 否则 leftSide[0] → leftSide[1] 这条边会穿过脊线,整个多边形自交,\r\n\t// 下游 polygon-helpers.ts 描边路径(centroid-径向外扩 + 偶奇规则\r\n\t// point-in-polygon)在自交多边形上结果不定 → 描边只画一半、燕尾退化成\r\n\t// 三角形等明显异常。\r\n\t//\r\n\t// 判定:用 spineDir × (controlPoints[0] - midTail) 的 2D 叉积符号判定\r\n\t// controlPoints[0] 落在脊线的 CCW(左)还是 CW(右)侧。叉积 > 0 → 左侧,\r\n\t// 维持 tailLeft = controlPoints[0];叉积 < 0 → 右侧,交换。\r\n\t//\r\n\t// 注:原 cesium-plot-js 的 `isClockWise(p0, p1, p2)` 判定**也**做了一次交换,\r\n\t// 但那是为它自己的\"两次镜像偏移点 + 各自 Catmull-Rom\"构造路径量身定做的;\r\n\t// Frenet 构造下需要的\"侧\"语义不同,必须独立判定,**不能**沿用\r\n\t// `isClockWise` 那一行。\r\n\tconst tentativeMidTail = mid( controlPoints[ 0 ], controlPoints[ 1 ] );\r\n\tconst tentativeSpineDirX = controlPoints[ 2 ][ 0 ] - tentativeMidTail[ 0 ];\r\n\tconst tentativeSpineDirY = controlPoints[ 2 ][ 1 ] - tentativeMidTail[ 1 ];\r\n\tconst tailVecX = controlPoints[ 0 ][ 0 ] - tentativeMidTail[ 0 ];\r\n\tconst tailVecY = controlPoints[ 0 ][ 1 ] - tentativeMidTail[ 1 ];\r\n\tconst sideTest =\r\n\t\ttentativeSpineDirX * tailVecY - tentativeSpineDirY * tailVecX;\r\n\r\n\tlet tailLeft = controlPoints[ 0 ];\r\n\tlet tailRight = controlPoints[ 1 ];\r\n\tif ( sideTest < 0.0 ) {\r\n\t\ttailLeft = controlPoints[ 1 ];\r\n\t\ttailRight = controlPoints[ 0 ];\r\n\t}\r\n\tconst midTail = mid( tailLeft, tailRight );\r\n\r\n\t// ── 步骤 2:脊线控制点 ──\r\n\tconst spineControlPoints: LonLatPoint[] = [ midTail ];\r\n\tfor ( let i = 2; i < controlPoints.length; i++ ) {\r\n\t\tspineControlPoints.push( controlPoints[ i ] );\r\n\t}\r\n\tif ( spineControlPoints.length < 2 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// ── 步骤 3:**唯一一次** Catmull-Rom 平滑脊线 ──\r\n\tconst spineSamples = centripetalCatmullRomSamples(\r\n\t\tspineControlPoints,\r\n\t\tbodySmoothingSegments,\r\n\t);\r\n\tif ( spineSamples.length < 2 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// ── 步骤 4:头部尺寸 clamp ──\r\n\tconst tailWidth = mathDistance( tailLeft, tailRight );\r\n\tconst baseLen = getBaseLength( spineControlPoints );\r\n\tconst tip: LonLatPoint = [\r\n\t\tspineControlPoints[ spineControlPoints.length - 1 ][ 0 ],\r\n\t\tspineControlPoints[ spineControlPoints.length - 1 ][ 1 ],\r\n\t];\r\n\tconst beforeTip = spineControlPoints[ spineControlPoints.length - 2 ];\r\n\tconst lastSegLen = mathDistance( tip, beforeTip );\r\n\r\n\tlet headHeight = baseLen * headHeightFactor;\r\n\t// 防止箭头头大于身(原版 headTailFactor)。\r\n\tif ( headHeight > tailWidth * headTailFactor ) {\r\n\t\theadHeight = tailWidth * headTailFactor;\r\n\t}\r\n\t// 防止头部伸出脊线之外。\r\n\tif ( headHeight > lastSegLen ) {\r\n\t\theadHeight = lastSegLen;\r\n\t}\r\n\tif ( headHeight <= 0.0 ) {\r\n\t\t// 整条脊线退化为单点 → 无法构造头部。\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// neckHeight = 颈与尖之间沿脊线的弧长(< headHeight)。\r\n\t// 体部止于 neckHeight 位置,头部在 neckHeight..0 之间张开成 5 点三角。\r\n\tconst neckHeight = headHeight * neckHeightFactor;\r\n\r\n\t// 修复 4(沿用原版):headHalfWidth / neckHalfWidth 在 headHeight 最终\r\n\t// clamp 之后计算,避免头被压缩时翼宽相对过宽。\r\n\tconst headHalfWidth = headHeight * headWidthFactor;\r\n\tconst neckHalfWidth = headHeight * neckWidthFactor;\r\n\r\n\t// ── 步骤 5:把 spineSamples 在 neck 处剪开 ──\r\n\tconst neckCut = findPointAlongPolylineFromEnd( spineSamples, neckHeight );\r\n\tif ( neckCut === null ) {\r\n\t\t// 头部比整条脊线还长 — 上面 clamp 之后不应进入此分支。\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// bodySpine = [ spineSamples[0..neckCut.segmentIdx], neckCut.point ]\r\n\t// 让 neckCut.point 作为 bodySpine 最后一个元素,使 computeTangents 在末点\r\n\t// 用\"前向差分\"得到与脊线 neck 处切线一致的方向。\r\n\tconst bodySpine: LonLatPoint[] = [];\r\n\tfor ( let i = 0; i <= neckCut.segmentIdx; i++ ) {\r\n\t\tbodySpine.push( [ spineSamples[ i ][ 0 ], spineSamples[ i ][ 1 ] ] );\r\n\t}\r\n\t// 当 neckCut.localT 几乎为 0 时,neckCut.point 与 spineSamples[segmentIdx]\r\n\t// 几乎重合 → 不再 push,以免后续 computeTangents 出现零长边。\r\n\tconst lastSpineX = spineSamples[ neckCut.segmentIdx ][ 0 ];\r\n\tconst lastSpineY = spineSamples[ neckCut.segmentIdx ][ 1 ];\r\n\tconst dx = neckCut.point[ 0 ] - lastSpineX;\r\n\tconst dy = neckCut.point[ 1 ] - lastSpineY;\r\n\tif ( ( dx * dx + dy * dy ) > 1e-24 ) {\r\n\t\tbodySpine.push( [ neckCut.point[ 0 ], neckCut.point[ 1 ] ] );\r\n\t}\r\n\tif ( bodySpine.length < 2 ) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// ── 步骤 6:逐 body 样本切向 + 法线 ──\r\n\tconst tangents = computeTangents( bodySpine );\r\n\r\n\t// ── 步骤 7:沿脊线一笔走完左侧,再走右侧(同一组样本,严格对齐)──\r\n\tconst tailHalfWidth = tailWidth / 2.0;\r\n\tconst lastBodyIdx = bodySpine.length - 1;\r\n\r\n\tconst leftSide: LonLatPoint[] = new Array( bodySpine.length );\r\n\tconst rightSide: LonLatPoint[] = new Array( bodySpine.length );\r\n\r\n\tfor ( let i = 0; i <= lastBodyIdx; i++ ) {\r\n\t\tconst t = lastBodyIdx > 0 ? i / lastBodyIdx : 0.0;\r\n\t\t// halfWidth(i) 线性插值:tail → neck。\r\n\t\tlet halfW: number;\r\n\t\tif ( i === lastBodyIdx ) {\r\n\t\t\t// 末点强制对齐 neck,与头部 5 点共点,无台阶。\r\n\t\t\thalfW = neckHalfWidth;\r\n\t\t} else {\r\n\t\t\thalfW = tailHalfWidth * ( 1.0 - t ) + neckHalfWidth * t;\r\n\t\t}\r\n\r\n\t\t// perp = ( -ty, tx ) 是切线的左手 90°(+y 朝北的右手系下指向\"逻辑左\")。\r\n\t\tconst tx = tangents[ i ][ 0 ];\r\n\t\tconst ty = tangents[ i ][ 1 ];\r\n\t\tconst px = -ty;\r\n\t\tconst py = tx;\r\n\r\n\t\tconst sx = bodySpine[ i ][ 0 ];\r\n\t\tconst sy = bodySpine[ i ][ 1 ];\r\n\r\n\t\tleftSide[ i ] = [ sx + px * halfW, sy + py * halfW ];\r\n\t\trightSide[ i ] = [ sx - px * halfW, sy - py * halfW ];\r\n\t}\r\n\r\n\t// ── 步骤 8:把用户指定的 tail 严格钉在多边形上 ──\r\n\t// midTail = mid(tailLeft, tailRight) 经过 Centripetal CR 后端点严格通过,\r\n\t// 但是 CR 的 mirror 端点策略可能让 spineSamples[0] 与 midTail 有微小漂移。\r\n\t// 这里把 leftSide[0] / rightSide[0] 强制覆盖为用户指定的 tailLeft / tailRight,\r\n\t// 保证视觉上\"用户点击的尾角\"严格出现在最终多边形上。\r\n\tleftSide[ 0 ] = [ tailLeft[ 0 ], tailLeft[ 1 ] ];\r\n\trightSide[ 0 ] = [ tailRight[ 0 ], tailRight[ 1 ] ];\r\n\r\n\t// ── 步骤 9:头部 3 个新点(headLeft / tip / headRight)──\r\n\t// 翼尖在 neck 处沿法线外扩 headHalfWidth(比 neckHalfWidth 大 → 翼展张开)。\r\n\tconst neckTx = tangents[ lastBodyIdx ][ 0 ];\r\n\tconst neckTy = tangents[ lastBodyIdx ][ 1 ];\r\n\tconst neckPx = -neckTy;\r\n\tconst neckPy = neckTx;\r\n\tconst neckX = bodySpine[ lastBodyIdx ][ 0 ];\r\n\tconst neckY = bodySpine[ lastBodyIdx ][ 1 ];\r\n\r\n\tconst headLeft: LonLatPoint = [\r\n\t\tneckX + neckPx * headHalfWidth,\r\n\t\tneckY + neckPy * headHalfWidth,\r\n\t];\r\n\tconst headRight: LonLatPoint = [\r\n\t\tneckX - neckPx * headHalfWidth,\r\n\t\tneckY - neckPy * headHalfWidth,\r\n\t];\r\n\r\n\treturn {\r\n\t\tleftSide,\r\n\t\trightSide,\r\n\t\theadLeft,\r\n\t\theadRight,\r\n\t\ttip,\r\n\t\ttailLeft: [ tailLeft[ 0 ], tailLeft[ 1 ] ],\r\n\t\ttailRight: [ tailRight[ 0 ], tailRight[ 1 ] ],\r\n\t\tmidTail: [ midTail[ 0 ], midTail[ 1 ] ],\r\n\t\tspineSecond: [ spineControlPoints[ 1 ][ 0 ], spineControlPoints[ 1 ][ 1 ] ],\r\n\t\tspineBaseLen: baseLen,\r\n\t};\r\n}\r\n","// ============================================================\r\n// arrow/shapes/swallowtail-attack-arrow.ts — 燕尾攻击箭头(3+ 点),\r\n// Frenet 带状构造 + 燕尾凸点\r\n// 层级:L1\r\n// 职责:在 AttackArrow 的 Frenet 带状骨架(`buildAttackArrowSkeleton`)基础上,\r\n// 在尾部中线方向多挤出一个\"燕尾凸点\",让原本平直的尾部边缘从一条\r\n// 直线变成 V 形凹口。\r\n//\r\n// 体部 / 头部 / 脊线平滑 / 描边友好性 全部继承自 attack-arrow.ts —\r\n// 本文件不再做任何独立的左右带平滑,**绝不**重新计算 leftBody /\r\n// rightBody 这种镜像离散偏移点。\r\n//\r\n// 控制点契约:与 createAttackArrow 完全相同。\r\n//\r\n// 几何步骤:\r\n// 1. 调用 buildAttackArrowSkeleton(controlPoints, options) 拿到:\r\n// leftSide / rightSide / headLeft / headRight / tip / tailLeft /\r\n// tailRight / midTail / spineSecond\r\n// 2. 计算 swallowtailPnt:从 spineSecond 沿\"指向 midTail\"的方向多走\r\n// `len = baseLength × tailWidthFactor × swallowtailFactor` 距离。\r\n// 即燕尾凸点位于 midTail 之后(脊线反方向)的延长线上。\r\n// 3. 单笔周界遍历(CCW):\r\n// leftSide (tailLeft → ... → neckLeft)\r\n// headLeft (左翼尖)\r\n// tip (箭尖)\r\n// headRight (右翼尖)\r\n// reverse rightSide (neckRight → ... → tailRight)\r\n// swallowtailPnt (V 形凹口顶点,在 tailLeft 与 tailRight 之间)\r\n// 最后 finalizePolygon 把闭合环交给下游。\r\n//\r\n// 与 AttackArrow 的差异总结:\r\n// - **唯一**新增几何:swallowtailPnt 一个顶点。\r\n// - **唯一**新增选项:swallowtailFactor、tailWidthFactor(仅影响燕尾深度)。\r\n// - 体部、头部、脊线平滑、描边友好的 Frenet 法线偏移路径 完全复用。\r\n//\r\n// 依赖:arrow-geometry.ts(getBaseLength + getThirdPoint),\r\n// arrow-polygon.ts(finalizePolygon),\r\n// arrow-types.ts(SwallowtailAttackArrowOptions),\r\n// shapes/attack-arrow.ts(buildAttackArrowSkeleton),\r\n// shapes/fine-arrow.ts(2 控制点退化)。\r\n// 被消费:arrow/index.ts。\r\n// ============================================================\r\n\r\nimport {\r\n\tcreateArrowInLocalMeterPlane,\r\n\tgetThirdPoint,\r\n} from '../arrow-geometry';\r\nimport { finalizePolygon } from '../arrow-polygon';\r\nimport type {\r\n\tArrowPolygon,\r\n\tLonLatPoint,\r\n\tSwallowtailAttackArrowOptions,\r\n} from '../arrow-types';\r\nimport { buildAttackArrowSkeleton } from './attack-arrow';\r\nimport { createFineArrow } from './fine-arrow';\r\n\r\n// ── 燕尾特有默认值 ──\r\n// tailWidthFactor 0.10:燕尾长度的基准比例(基准长度 × 此值 × swallowtailFactor)。\r\n// swallowtailFactor 1.0:燕尾凸出深度倍率,1.0 即标准深度,>1 凸出更深,\r\n// 0 时凸点与 midTail 重合 → 视觉上等价 AttackArrow。\r\nconst DEFAULT_TAIL_WIDTH_FACTOR = 0.08;\r\nconst DEFAULT_SWALLOWTAIL_FACTOR = 0.70;\r\n\r\n/**\r\n * 构造燕尾攻击箭头(Frenet 带状 + 尾部 V 形凹口)。\r\n *\r\n * @param controlPoints 控制点序列,至少 3 个。少于 3 时:\r\n * - 2 个点 → 退化为 createFineArrow(与 attack-arrow 保持一致)\r\n * - < 2 → 返回空数组\r\n * @param options 比例与平滑参数(继承 AttackArrowOptions + 燕尾两项)。\r\n * @returns 闭合多边形;输入退化时可能返回空数组。\r\n */\r\nexport function createSwallowtailAttackArrow(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: SwallowtailAttackArrowOptions = {},\r\n): ArrowPolygon {\r\n\treturn createArrowInLocalMeterPlane(\r\n\t\tcontrolPoints,\r\n\t\t( localPoints ) => createSwallowtailAttackArrowLocal( localPoints, options ),\r\n\t);\r\n}\r\n\r\nfunction createSwallowtailAttackArrowLocal(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: SwallowtailAttackArrowOptions = {},\r\n): ArrowPolygon {\r\n\t// ── 输入校验 + 兼容退化 ──\r\n\tif ( controlPoints.length < 2 ) {\r\n\t\treturn [];\r\n\t}\r\n\tif ( controlPoints.length === 2 ) {\r\n\t\treturn createFineArrow( controlPoints[ 0 ], controlPoints[ 1 ] );\r\n\t}\r\n\r\n\t// ── 复用 AttackArrow 骨架(Frenet 带状,描边友好)──\r\n\tconst skeleton = buildAttackArrowSkeleton( controlPoints, options );\r\n\tif ( ! skeleton ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// ── 燕尾特有参数 ──\r\n\tconst tailWidthFactor = options.tailWidthFactor ?? DEFAULT_TAIL_WIDTH_FACTOR;\r\n\tconst swallowtailFactor = options.swallowtailFactor ?? DEFAULT_SWALLOWTAIL_FACTOR;\r\n\r\n\t// 燕尾深度的尺度来自整条脊线的基准长度(skeleton.spineBaseLen,\r\n\t// 与原版 attack-arrow 内部的 baseLen 一致)。这样无论脊线有几个控制点,\r\n\t// 燕尾凸出量都按\"整体箭头大小\"等比例缩放,而不是只跟尾段长度挂钩。\r\n\tconst swallowtailLen = skeleton.spineBaseLen * tailWidthFactor * swallowtailFactor;\r\n\r\n\t// 从 spineSecond 沿\"反向 spineSecond → midTail\"的延长线多走 swallowtailLen,\r\n\t// 得到燕尾凸点(位于 midTail 之后的脊线反方向)。\r\n\t//\r\n\t// getThirdPoint( startPnt = spineSecond, endPnt = midTail, angle = 0,\r\n\t// distance = swallowtailLen, clockwise = true )\r\n\t// 含义:从 midTail 看向 spineSecond 反向(= midTail → 远离 spineSecond\r\n\t// 方向 = midTail → 燕尾外侧方向)起步,旋转 0,前进 swallowtailLen。\r\n\t// 退化:swallowtailFactor = 0 时 swallowtailLen = 0,getThirdPoint 返回\r\n\t// midTail 本身 → 燕尾凸点与尾中点重合,视觉等价 AttackArrow。\r\n\tconst swallowtailPnt: LonLatPoint = getThirdPoint(\r\n\t\tskeleton.spineSecond,\r\n\t\tskeleton.midTail,\r\n\t\t0.0,\r\n\t\tswallowtailLen,\r\n\t\ttrue,\r\n\t);\r\n\r\n\t// ── 单笔周界遍历(CCW)──\r\n\t// 顺序与 AttackArrow 相同,只是在最后多加一个 swallowtailPnt 顶点,\r\n\t// 把\"tailRight → tailLeft\"的直边切成\"tailRight → swallowtailPnt → tailLeft\"\r\n\t// 两条边,中间形成 V 形凹口(对外为\"^\"形)。\r\n\tconst rawRing: LonLatPoint[] = [\r\n\t\t...skeleton.leftSide, // tailLeft → ... → neckLeft\r\n\t\tskeleton.headLeft, // 左翼尖\r\n\t\tskeleton.tip, // 箭尖\r\n\t\tskeleton.headRight, // 右翼尖\r\n\t\t...skeleton.rightSide.slice().reverse(), // neckRight → ... → tailRight\r\n\t\tswallowtailPnt, // 燕尾凹口顶点\r\n\t];\r\n\r\n\treturn finalizePolygon( rawRing );\r\n}\r\n","// ============================================================\r\n// arrow/shapes/curved-arrow.ts — 曲线箭头(2+ 点)\r\n// 层级:L1\r\n// 职责:由 2+ 个控制点定义平滑曲线脊线,沿脊线两侧偏移给定半宽,末端附加\r\n// 三角箭头,闭合成填充多边形。\r\n//\r\n// 与 cesium-plot-js 的 CurvedArrow 不同(后者输出 `line` 类型的折线\r\n// polyline),本实现输出**闭合多边形**。原因:本项目仅有\r\n// CesiumGroundPolygonPrimitive,没有 line primitive。把曲线沿法线\r\n// \"增厚\"为带状多边形是兼容 polygon-only 管线的标准做法。\r\n//\r\n// 控制点契约:\r\n// - 2 个点:直线变体,等价于宽度可调、自带三角箭头的窄长 FineArrow。\r\n// - 3+ 个点:用 Centripetal Catmull-Rom 平滑,严格通过所有控制点;\r\n// 末点为箭头尖端。\r\n//\r\n// 几何步骤(3+ 点):\r\n// 1. spineSamples = 通过控制点的密采曲线\r\n// 2. totalLen = 累积弧长,bodyWidth/headWidth/headLength/neckWidth 全部\r\n// 相对 totalLen 计算\r\n// 3. 沿 spineSamples 从末尾回退 headLength 距离,定位\"颈点\" exactNeck\r\n// (精确插值,不是最近样本)。bodySpine = spineSamples[0..k] ⊕ exactNeck。\r\n// 4. 对 bodySpine 计算逐点切线 → 顺时针 90° 法线 perp = (-ty, tx)\r\n// 5. 半宽 w(i):tail 处 = bodyWidth/2,沿曲线按 bodyTaperRatio 线性收窄;\r\n// 末点(neck 处)强制等于 neckWidth/2,保证与头部 neck 共点(无台阶)\r\n// 6. leftSide[i] = spine[i] + perp[i] × w(i),rightSide[i] 同理但 - perp\r\n// 7. 头部 3 点:tip = controlPoints[末]、headLeft/headRight 用 exactNeck\r\n// 处的法线 × headWidth/2(比 neck 更宽 → 翼展)\r\n// 8. 闭合环:leftSide ⊕ [headLeft, tip, headRight] ⊕ reverse(rightSide)\r\n//\r\n// 边界处理:\r\n// - headLength clamp 到 ≤ totalLen × 0.6,防止 headLength 把 bodyLength\r\n// 压缩到负值。\r\n// - 任何两个相邻控制点重合时,centripetalCatmullRomSamples 内部已防御除零。\r\n// - bodySpine 出现退化(< 2 点)时返回空多边形。\r\n//\r\n// 依赖:arrow-geometry.ts、arrow-curves.ts、arrow-polygon.ts、arrow-types.ts。\r\n// 被消费:arrow/index.ts。\r\n// 算法对应:cesium-plot-js src/arrow/curved-arrow.ts(其输出为 polyline,\r\n// 本实现把\"折线 + 末端三角\"改写为\"带状多边形 + 末端三角\")。\r\n// ============================================================\r\n\r\nimport {\r\n\tcreateArrowInLocalMeterPlane,\r\n\twholeDistance,\r\n} from '../arrow-geometry';\r\nimport {\r\n\tcentripetalCatmullRomSamples,\r\n\tcomputeTangents,\r\n\tfindPointAlongPolylineFromEnd,\r\n} from '../arrow-curves';\r\nimport { finalizePolygon } from '../arrow-polygon';\r\nimport type {\r\n\tArrowPolygon,\r\n\tCurvedArrowOptions,\r\n\tLonLatPoint,\r\n} from '../arrow-types';\r\n\r\n// ── 默认值 ──\r\n// 这些默认值经过手工调校,使在 3 控制点、曲线长度 ~0.01 弧度尺度(WGS84\r\n// 约 1 km)时的箭头视觉与 cesium-plot-js 同名箭头风格一致(略修长,\r\n// 头部不喧宾夺主)。\r\nconst DEFAULT_BODY_WIDTH_FACTOR = 0.05;\r\nconst DEFAULT_HEAD_WIDTH_FACTOR = 0.16;\r\nconst DEFAULT_HEAD_LENGTH_FACTOR = 0.18;\r\nconst DEFAULT_NECK_WIDTH_RELATIVE_TO_HEAD = 0.40;\r\nconst DEFAULT_CURVE_SMOOTHING_SEGMENTS = 16;\r\nconst DEFAULT_BODY_TAPER_RATIO = 0.0;\r\n\r\n// 头部长度上限:不超过曲线总长的 60%,防止 body 被吃光。\r\nconst HEAD_LENGTH_MAX_FRACTION = 0.6;\r\n\r\n/**\r\n * 生成曲线箭头(沿曲线的填充多边形)。\r\n *\r\n * @param controlPoints 控制点序列,至少 2 个;最末点为箭头尖端。\r\n * @param options 体型与平滑参数。\r\n * @returns 闭合多边形;输入退化(< 2 点或所有点重合)时返回空数组。\r\n */\r\nexport function createCurvedArrow(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: CurvedArrowOptions = {},\r\n): ArrowPolygon {\r\n\treturn createArrowInLocalMeterPlane(\r\n\t\tcontrolPoints,\r\n\t\t( localPoints ) => createCurvedArrowLocal( localPoints, options ),\r\n\t);\r\n}\r\n\r\nfunction createCurvedArrowLocal(\r\n\tcontrolPoints: readonly LonLatPoint[],\r\n\toptions: CurvedArrowOptions = {},\r\n): ArrowPolygon {\r\n\t// ── 输入校验 ──\r\n\tif ( controlPoints.length < 2 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// ── 解析选项 ──\r\n\tconst bodyWidthFactor = options.bodyWidthFactor ?? DEFAULT_BODY_WIDTH_FACTOR;\r\n\tconst headWidthFactor = options.headWidthFactor ?? DEFAULT_HEAD_WIDTH_FACTOR;\r\n\tconst headLengthFactor = options.headLengthFactor ?? DEFAULT_HEAD_LENGTH_FACTOR;\r\n\tconst neckWidthRelativeToHead =\r\n\t\toptions.neckWidthRelativeToHead ?? DEFAULT_NECK_WIDTH_RELATIVE_TO_HEAD;\r\n\tconst curveSmoothingSegments =\r\n\t\toptions.curveSmoothingSegments ?? DEFAULT_CURVE_SMOOTHING_SEGMENTS;\r\n\tconst bodyTaperRatio = options.bodyTaperRatio ?? DEFAULT_BODY_TAPER_RATIO;\r\n\r\n\t// ── 步骤 1:生成平滑脊线 ──\r\n\t// 2 点 → 直线段密采(centripetalCatmullRomSamples 内部已处理 2 点退化);\r\n\t// 3+ 点 → 严格通过控制点的 Centripetal Catmull-Rom。\r\n\tconst spineSamples = centripetalCatmullRomSamples(\r\n\t\tcontrolPoints, curveSmoothingSegments,\r\n\t);\r\n\tif ( spineSamples.length < 2 ) {\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// ── 步骤 2:总弧长与各种宽度 ──\r\n\tconst totalLen = wholeDistance( spineSamples );\r\n\tif ( totalLen <= 0.0 ) {\r\n\t\t// 所有控制点重合 → 无法构造箭头。\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst bodyHalfWidth = ( totalLen * bodyWidthFactor ) / 2.0;\r\n\tconst headHalfWidth = ( totalLen * headWidthFactor ) / 2.0;\r\n\tconst neckHalfWidth = headHalfWidth * neckWidthRelativeToHead;\r\n\t// 头长 clamp 到 ≤ totalLen × HEAD_LENGTH_MAX_FRACTION,防止 body 长度负值。\r\n\tconst headLength = Math.min(\r\n\t\ttotalLen * headLengthFactor,\r\n\t\ttotalLen * HEAD_LENGTH_MAX_FRACTION,\r\n\t);\r\n\r\n\t// ── 步骤 3:定位精确颈点(沿脊线从末尾回退 headLength) ──\r\n\tconst neck = findPointAlongPolylineFromEnd( spineSamples, headLength );\r\n\tif ( neck === null ) {\r\n\t\t// headLength 大于整条脊线 → 不可能(已 clamp),理论不可达;返回空保安。\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// bodySpine:从脊线起点到 exactNeck 的所有点(含 exactNeck)。\r\n\t// 之所以重新构造数组而不是直接 slice(...,neckSegIdx+1).push(exactNeck),\r\n\t// 是为了显式让 exactNeck 成为最后一个元素,使 computeTangents 在末点\r\n\t// 处用\"前向差分\"得到与 exactNeck 之前样本的切线方向(自然与脊线末段\r\n\t// 切线方向一致)。\r\n\tconst bodySpine: LonLatPoint[] = spineSamples\r\n\t\t.slice( 0, neck.segmentIdx + 1 )\r\n\t\t.map( ( p ) => [ p[ 0 ], p[ 1 ] ] as LonLatPoint );\r\n\tbodySpine.push( neck.point );\r\n\r\n\tif ( bodySpine.length < 2 ) {\r\n\t\t// 退化:headLength 接近 totalLen,body 几乎被吃光。\r\n\t\t// 仍可绘制(给最小 2 点 body),否则返回空多边形。\r\n\t\treturn [];\r\n\t}\r\n\r\n\t// ── 步骤 4:逐点切线 + 90° 法线 ──\r\n\t// perpendicular = ( -ty, tx ) 是切线左手 90°(在 +y 朝上坐标系下指向\"逻辑左\")。\r\n\t// 经纬度坐标系也是 +y 朝北的右手系,perp 朝\"曲线行进方向的左侧\"。\r\n\tconst tangents = computeTangents( bodySpine );\r\n\r\n\t// ── 步骤 5:全局曲率体宽兜底 + 逐点半宽(尾→颈线性插值)──\r\n\t//\r\n\t// 关键问题:Frenet 法线偏移在 halfW > 局部曲率半径 R=1/κ 时,弯曲内侧\r\n\t// 会自交,polygon 渲染成镂空三角(用户在 plot demo 大比例尺 curved\r\n\t// 拐角处看到的)。\r\n\t//\r\n\t// 早期实现做过「逐 sample 按本地 κ clamp halfW」,但这让 body 在急弯\r\n\t// 处突然变窄、其他位置正常 → 整体宽度不均、视觉变形。\r\n\t//\r\n\t// **新策略**:扫一遍全脊线,找出最紧曲率半径 minR,把 bodyHalfWidth /\r\n\t// neckHalfWidth 全局 cap 到 (minR × CURVATURE_SAFETY) 之内。整条 body\r\n\t// 保持均匀宽度——只是急弯输入下会整体偏窄一些,但形态平滑无变形。\r\n\tconst lastBodyIdx = bodySpine.length - 1;\r\n\tconst CURVATURE_SAFETY = 0.5;\r\n\r\n\tlet tightestRadius = Infinity;\r\n\tfor ( let i = 1; i < lastBodyIdx; i++ ) {\r\n\t\tconst prev = bodySpine[ i - 1 ];\r\n\t\tconst curr = bodySpine[ i ];\r\n\t\tconst next = bodySpine[ i + 1 ];\r\n\t\tconst v1x = curr[ 0 ] - prev[ 0 ];\r\n\t\tconst v1y = curr[ 1 ] - prev[ 1 ];\r\n\t\tconst v2x = next[ 0 ] - curr[ 0 ];\r\n\t\tconst v2y = next[ 1 ] - curr[ 1 ];\r\n\t\tconst len1 = Math.hypot( v1x, v1y );\r\n\t\tconst len2 = Math.hypot( v2x, v2y );\r\n\t\tif ( len1 < 1e-9 || len2 < 1e-9 ) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst cross = v1x * v2y - v1y * v2x;\r\n\t\tconst dot = v1x * v2x + v1y * v2y;\r\n\t\tconst dtheta = Math.abs( Math.atan2( cross, dot ) );\r\n\t\tconst ds = ( len1 + len2 ) * 0.5;\r\n\t\tif ( dtheta < 1e-9 ) {\r\n\t\t\tcontinue; // 直线段,半径无穷\r\n\t\t}\r\n\t\tconst r = ds / dtheta; // 局部曲率半径\r\n\t\tif ( r < tightestRadius ) {\r\n\t\t\ttightestRadius = r;\r\n\t\t}\r\n\t}\r\n\r\n\tlet safeMax = Infinity;\r\n\tif ( Number.isFinite( tightestRadius ) ) {\r\n\t\tsafeMax = tightestRadius * CURVATURE_SAFETY;\r\n\t}\r\n\t// **关键**:所有宽度按相同 scale 同步缩放,保持原比例关系。只 cap body\r\n\t// 而 head 用原始 headHalfWidth 时,head 翼会比窄缩的 body 宽很多倍,polygon\r\n\t// 在 neck 处形成「窄腰宽翼」的视觉变形(用户截图的三角凹口就是这种比例\r\n\t// 突变)。这里以 bodyHalfWidth 是否超 safeMax 触发缩放,所有 width 同步乘\r\n\t// scale,head / body / neck 三者保持原 width factor 决定的比例。\r\n\tlet widthScale = 1.0;\r\n\tif ( bodyHalfWidth > safeMax && bodyHalfWidth > 0.0 ) {\r\n\t\twidthScale = safeMax / bodyHalfWidth;\r\n\t}\r\n\tconst cappedBodyHalfWidth = bodyHalfWidth * widthScale;\r\n\tconst cappedNeckHalfWidth = neckHalfWidth * widthScale;\r\n\tconst cappedHeadHalfWidth = headHalfWidth * widthScale;\r\n\r\n\tconst leftSide: LonLatPoint[] = new Array( bodySpine.length );\r\n\tconst rightSide: LonLatPoint[] = new Array( bodySpine.length );\r\n\r\n\tfor ( let i = 0; i < bodySpine.length; i++ ) {\r\n\t\tconst t = lastBodyIdx > 0 ? i / lastBodyIdx : 0.0;\r\n\t\tlet widthHalf: number;\r\n\t\tif ( i === lastBodyIdx ) {\r\n\t\t\twidthHalf = cappedNeckHalfWidth;\r\n\t\t} else {\r\n\t\t\tconst interpolant = t * bodyTaperRatio;\r\n\t\t\twidthHalf = cappedBodyHalfWidth * ( 1.0 - interpolant )\r\n\t\t\t\t+ cappedNeckHalfWidth * interpolant;\r\n\t\t}\r\n\r\n\t\tconst tx = tangents[ i ][ 0 ];\r\n\t\tconst ty = tangents[ i ][ 1 ];\r\n\t\tconst px = -ty;\r\n\t\tconst py = tx;\r\n\t\tconst sx = bodySpine[ i ][ 0 ];\r\n\t\tconst sy = bodySpine[ i ][ 1 ];\r\n\r\n\t\tleftSide[ i ] = [ sx + px * widthHalf, sy + py * widthHalf ];\r\n\t\trightSide[ i ] = [ sx - px * widthHalf, sy - py * widthHalf ];\r\n\t}\r\n\r\n\t// ── 步骤 6:头部 3 个新点(neckLeft/Right 已由 leftSide/rightSide 末点表示)──\r\n\t// 头部翼展用 exactNeck 处的法线 × cappedHeadHalfWidth(经曲率 scale 后,\r\n\t// 与 body / neck 保持相同比例,避免「窄腰宽翼」变形)。\r\n\tconst neckTx = tangents[ lastBodyIdx ][ 0 ];\r\n\tconst neckTy = tangents[ lastBodyIdx ][ 1 ];\r\n\tconst neckPx = -neckTy;\r\n\tconst neckPy = neckTx;\r\n\tconst neckX = neck.point[ 0 ];\r\n\tconst neckY = neck.point[ 1 ];\r\n\r\n\tconst headLeft: LonLatPoint = [\r\n\t\tneckX + neckPx * cappedHeadHalfWidth,\r\n\t\tneckY + neckPy * cappedHeadHalfWidth,\r\n\t];\r\n\tconst headRight: LonLatPoint = [\r\n\t\tneckX - neckPx * cappedHeadHalfWidth,\r\n\t\tneckY - neckPy * cappedHeadHalfWidth,\r\n\t];\r\n\t// 尖端 = 用户控制点的最末点(确保箭尖严格在用户指定位置)。\r\n\tconst tip: LonLatPoint = [\r\n\t\tcontrolPoints[ controlPoints.length - 1 ][ 0 ],\r\n\t\tcontrolPoints[ controlPoints.length - 1 ][ 1 ],\r\n\t];\r\n\r\n\t// ── 步骤 7:拼接最终多边形 ──\r\n\t// 顺序(CCW):\r\n\t// leftSide(尾→颈) → headLeft → tip → headRight → rightSide 反向(颈→尾)\r\n\t// leftSide[last] = neckLeft,rightSide[last] = neckRight,它们与 headLeft/\r\n\t// headRight 在同一垂直于切线的射线上,只是 headLeft/Right 更外侧,\r\n\t// 形成自然的翼展张开。\r\n\t//\r\n\t// 注意:leftSide / rightSide 的末点本身就是 neckLeft/neckRight,不能\r\n\t// 在这里 slice(0, -1),因为它们与 headLeft/headRight 是不同的点\r\n\t// (一个 neckHalfWidth、一个 headHalfWidth),不会产生重复顶点。\r\n\tconst rawRing: LonLatPoint[] = [\r\n\t\t...leftSide, // tailLeft → neckLeft\r\n\t\theadLeft, // 翼尖\r\n\t\ttip, // 箭尖\r\n\t\theadRight, // 翼尖\r\n\t\t...rightSide.slice().reverse(), // neckRight → tailRight\r\n\t];\r\n\r\n\treturn finalizePolygon( rawRing );\r\n}\r\n\r\n// 内部颈点搜索由 arrow-curves.ts 的 `findPointAlongPolylineFromEnd` 统一提供\r\n// (attack-arrow / swallowtail-attack-arrow / curved-arrow 三个箭头共享)。\r\n"],"names":["WGS84_INVERSE_FLATTENING","WGS84_FLATTENING","WGS84_FIRST_ECCENTRICITY_SQUARED","DEGREES_TO_RADIANS","RADIANS_TO_DEGREES","COINCIDENT_TOLERANCE","createArrowInLocalMeterPlane","controlPoints","createLocalRing","longitudeSum","latitudeSum","point","inverseCount","originLongitudeDegrees","originLatitudeDegrees","latitudeRadians","sinLatitude","cosLatitude","oneMinusESin2","primeVerticalRadius","meridianRadius","longitudeMetersPerRadian","latitudeMetersPerRadian","localPoints","mathDistance","p1","p2","dx","dy","d2","wholeDistance","points","total","i","getBaseLength","mid","azimuthBackward","startPnt","endPnt","getThirdPoint","angle","distance","clockwise","alpha","ARROW_OUTPUT_MAX_VERTICES","DEDUPE_TOLERANCE","dedupeConsecutivePoints","ring","out","current","previous","first","last","signedAreaShoelace","sum","a","b","ensureCounterClockwise","reversed","src","p","clampVertexCount","maxCount","cap","sampled","step","srcIdx","safeIdx","removeHairpinVertices","thresholdRad","cleaned","halfTurnMinusThreshold","changed","safety","next","n","prev","curr","nxt","v1x","v1y","v2x","v2y","cross","dot","finalizePolygon","rawRing","dedup","noHairpin","ccw","DEFAULT_TAIL_WIDTH_FACTOR","DEFAULT_NECK_WIDTH_FACTOR","DEFAULT_HEAD_WIDTH_FACTOR","DEFAULT_HEAD_ANGLE_RADIANS","DEFAULT_NECK_ANGLE_RADIANS","createFineArrow","options","createFineArrowLocal","tailWidthFactor","neckWidthFactor","headWidthFactor","headAngleRadians","neckAngleRadians","spineLen","baseLen","tailHalfWidth","neckHalfWidth","headHalfWidth","spineDirX","spineDirY","perpX","perpY","neckBack","neckSide","headBack","headSide","tailRight","neckRight","headRight","headLeft","neckLeft","tailLeft","DEFAULT_LENGTH_SCALE","createAssaultDirectionArrow","createAssaultDirectionArrowLocal","lengthScale","centripetalCatmullRomSamples","segmentSamples","linearSegmentSamples","p0First","p1First","mirrorStart","pLast","pPrev","mirrorEnd","extended","output","safeSegmentSamples","totalSegments","segIdx","p0","p3","MIN_CHORD","t0","t1","t2","t3","startSampleIndex","endSampleIndex","t","catmullRomBlend","a1","lerpPoint","a2","a3","b1","b2","f","computeTangents","tangents","prevIdx","nextIdx","len","findPointAlongPolylineFromEnd","samples","distanceFromEnd","accum","segLen","remainFromEndPoint","localT","ax","ay","bx","by","DEFAULT_HEAD_HEIGHT_FACTOR","DEFAULT_NECK_HEIGHT_FACTOR","DEFAULT_HEAD_TAIL_FACTOR","DEFAULT_BODY_SMOOTHING_SEGMENTS","createAttackArrow","createAttackArrowLocal","skeleton","buildAttackArrowSkeleton","headHeightFactor","neckHeightFactor","headTailFactor","bodySmoothingSegments","tentativeMidTail","tentativeSpineDirX","tentativeSpineDirY","tailVecX","tailVecY","sideTest","midTail","spineControlPoints","spineSamples","tailWidth","tip","beforeTip","lastSegLen","headHeight","neckHeight","neckCut","bodySpine","lastSpineX","lastSpineY","lastBodyIdx","leftSide","rightSide","halfW","tx","px","py","sx","sy","neckTx","neckPx","neckPy","neckX","neckY","DEFAULT_SWALLOWTAIL_FACTOR","createSwallowtailAttackArrow","createSwallowtailAttackArrowLocal","swallowtailFactor","swallowtailLen","swallowtailPnt","DEFAULT_BODY_WIDTH_FACTOR","DEFAULT_HEAD_LENGTH_FACTOR","DEFAULT_NECK_WIDTH_RELATIVE_TO_HEAD","DEFAULT_CURVE_SMOOTHING_SEGMENTS","DEFAULT_BODY_TAPER_RATIO","HEAD_LENGTH_MAX_FRACTION","createCurvedArrow","createCurvedArrowLocal","bodyWidthFactor","headLengthFactor","neckWidthRelativeToHead","curveSmoothingSegments","bodyTaperRatio","totalLen","bodyHalfWidth","headLength","neck","CURVATURE_SAFETY","tightestRadius","len1","len2","dtheta","ds","r","safeMax","widthScale","cappedBodyHalfWidth","cappedNeckHalfWidth","cappedHeadHalfWidth","widthHalf","interpolant"],"mappings":"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"}
|
package/dist/ground.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { C as r, a, b as t, c as o, d as n, e as m, f as C, g as L, h as g, i as u, L as _, j as l, k as D, M as R, l as A, m as E, n as I, o as p, p as d, q as M, r as N, s as T, t as P, u as G, v as U, w as h, x as F, y as c, z as v } from "./text-primitive-Ci0sbuh1.js";
|
|
2
|
+
import "three";
|
|
3
|
+
export {
|
|
4
|
+
r as CESIUM_GLOBE_MINIMUM_ALTITUDE,
|
|
5
|
+
a as CESIUM_GROUND_NON_PICKABLE_LAYER,
|
|
6
|
+
t as CesiumClassificationPrimitive,
|
|
7
|
+
o as CesiumGlobeDepth,
|
|
8
|
+
n as CesiumGroundCirclePrimitive,
|
|
9
|
+
m as CesiumGroundPointPrimitive,
|
|
10
|
+
C as CesiumGroundPolygonPrimitive,
|
|
11
|
+
L as CesiumGroundPolylinePrimitive,
|
|
12
|
+
g as CesiumGroundRectanglePrimitive,
|
|
13
|
+
u as CesiumGroundTextPrimitive,
|
|
14
|
+
_ as LINE_DEFAULT_GRANULARITY,
|
|
15
|
+
l as LINE_DEFAULT_RENDER_ORDER,
|
|
16
|
+
D as LINE_DEFAULT_WIDTH_PIXELS,
|
|
17
|
+
R as MAX_CIRCLE_GRANULARITY_RADIANS,
|
|
18
|
+
A as MIN_CIRCLE_GRANULARITY_RADIANS,
|
|
19
|
+
E as applyCesiumLogDepthToMaterial,
|
|
20
|
+
I as createCesiumEllipsoidDepthMeshes,
|
|
21
|
+
p as getTerrainMinMaxHeightsForRectangle,
|
|
22
|
+
d as initializeApproximateTerrainHeights,
|
|
23
|
+
M as isApproximateTerrainHeightsReady,
|
|
24
|
+
N as longitudeLatitudeFromCenterOffsetsMeters,
|
|
25
|
+
T as rectangleDegreesFromCenterSizeMeters,
|
|
26
|
+
P as rectangleDegreesFromLonLatPoints,
|
|
27
|
+
G as rectangleMeterSizeFromDegrees,
|
|
28
|
+
U as terrainLogDepthUniforms,
|
|
29
|
+
h as updateTerrainLogDepthUniforms,
|
|
30
|
+
F as validateCesiumGroundRenderer,
|
|
31
|
+
c as wgs84NormalFromDegrees,
|
|
32
|
+
v as wgs84PositionFromDegrees
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=ground.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ground.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { C as r, a, b as t, c as o, d as n, e as m, f as C, g as L, h as g, i as u, L as _, j as l, k as D, M as R, l as A, m as E, n as I, o as p, p as d, q as M, r as N, s as T, t as P, u as G, v as U, w as h, x as F, y as c, z as v } from "./text-primitive-Ci0sbuh1.js";
|
|
2
|
+
import "three";
|
|
3
|
+
export {
|
|
4
|
+
r as CESIUM_GLOBE_MINIMUM_ALTITUDE,
|
|
5
|
+
a as CESIUM_GROUND_NON_PICKABLE_LAYER,
|
|
6
|
+
t as CesiumClassificationPrimitive,
|
|
7
|
+
o as CesiumGlobeDepth,
|
|
8
|
+
n as CesiumGroundCirclePrimitive,
|
|
9
|
+
m as CesiumGroundPointPrimitive,
|
|
10
|
+
C as CesiumGroundPolygonPrimitive,
|
|
11
|
+
L as CesiumGroundPolylinePrimitive,
|
|
12
|
+
g as CesiumGroundRectanglePrimitive,
|
|
13
|
+
u as CesiumGroundTextPrimitive,
|
|
14
|
+
_ as LINE_DEFAULT_GRANULARITY,
|
|
15
|
+
l as LINE_DEFAULT_RENDER_ORDER,
|
|
16
|
+
D as LINE_DEFAULT_WIDTH_PIXELS,
|
|
17
|
+
R as MAX_CIRCLE_GRANULARITY_RADIANS,
|
|
18
|
+
A as MIN_CIRCLE_GRANULARITY_RADIANS,
|
|
19
|
+
E as applyCesiumLogDepthToMaterial,
|
|
20
|
+
I as createCesiumEllipsoidDepthMeshes,
|
|
21
|
+
p as getTerrainMinMaxHeightsForRectangle,
|
|
22
|
+
d as initializeApproximateTerrainHeights,
|
|
23
|
+
M as isApproximateTerrainHeightsReady,
|
|
24
|
+
N as longitudeLatitudeFromCenterOffsetsMeters,
|
|
25
|
+
T as rectangleDegreesFromCenterSizeMeters,
|
|
26
|
+
P as rectangleDegreesFromLonLatPoints,
|
|
27
|
+
G as rectangleMeterSizeFromDegrees,
|
|
28
|
+
U as terrainLogDepthUniforms,
|
|
29
|
+
h as updateTerrainLogDepthUniforms,
|
|
30
|
+
F as validateCesiumGroundRenderer,
|
|
31
|
+
c as wgs84NormalFromDegrees,
|
|
32
|
+
v as wgs84PositionFromDegrees
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|