Skip to content

线段等分 bisectionLine

把一条三维空间线段按指定段数等分,返回 segments + 1 个均匀插值点。对齐源案例 Analysis/BisectionLine:源实现用 EntityDraw 拾取两点 + 图钉图片标注,本 SDK 以纯函数 bisectionLineCartesian3.lerp 均匀插值)为核心,用点 / 线实体等价再现等分语义。


能力定位

bisectionLine 适合:

  • 空间线段等分:把两点间的直线段等分 N 段,得到 N+1 个均匀分布的点(GIS 常见几何能力);
  • 均匀布点:沿线均匀布置管线桩号、路径节点、轨迹采样点等,只需给起点 / 终点 / 段数;
  • 纯计算复用:无 Viewer 依赖,可在 Node 环境直接验证,结果数组可直接喂给 Entity / Primitive 消费方。

与其他工具的区分:

工具作用面行为
bisectionLine(本工具)纯几何计算线段等分返回等距插值点,不接触 Viewer
BufferAnalysisturf 计算 + 实体点 / 线 / 面缓冲范围分析,生成缓冲面
Measure测距 / 测面测量量算,不生成等分点

纯函数

ts
bisectionLine(
  start: Cartesian3,   // 线段起点(世界坐标)
  end: Cartesian3,     // 线段终点(世界坐标)
  segments: number     // 等分段数,正整数(>= 1)
): Cartesian3[]        // segments + 1 个等分点
参数类型描述
startCartesian3线段起点,Cartesian3.fromDegrees 构造
endCartesian3线段终点,世界坐标
segmentsnumber等分段数;1 段返回 [start, end] 两点,10 段返回 11 点
  • 返回:segments + 1 个等分点,首点为 start、末点为 end,相邻点间欧氏距离相等
  • 入参不被修改,返回数组元素为新对象,可安全用于 Entity 等消费方;
  • segments0 / 负数 / 非整数 / NaN 时抛错。

基础示例

ts
import { bisectionLine } from '@nexa/gis-cesium'
import { Cartesian3 } from 'cesium'

// 把 贵阳→成都 线段等分 10 段 → 11 个等分点
const start = Cartesian3.fromDegrees(106.63, 26.65, 0)
const end = Cartesian3.fromDegrees(104.06, 30.66, 0)
const points = bisectionLine(start, end, 10)
// points.length === 11
// Cartesian3.equalsEpsilon(points[0], start, 1e-9) === true
// Cartesian3.equalsEpsilon(points[10], end, 1e-9) === true

进阶示例

配合 Cesium 实体展示等分结果:橙色源线段 + 绿起点 / 红终点 + 蓝色等分点(关闭深度测试避免被地表遮挡):

ts
const points = bisectionLine(start, end, 20)

// 源线段(橙)
viewer.entities.add({
  polyline: { positions: [start, end], width: 3, material: Cesium.Color.ORANGE },
})
// 起点 / 终点
viewer.entities.add({ position: start, point: { pixelSize: 12, color: Cesium.Color.LIME, disableDepthTestDistance: Number.POSITIVE_INFINITY } })
viewer.entities.add({ position: end, point: { pixelSize: 12, color: Cesium.Color.RED, disableDepthTestDistance: Number.POSITIVE_INFINITY } })
// 等分点
points.forEach((p) => {
  viewer.entities.add({
    position: p,
    point: { pixelSize: 7, color: Cesium.Color.SKYBLUE, disableDepthTestDistance: Number.POSITIVE_INFINITY },
  })
})

交互拾取起 / 终点后自动重新等分:

ts
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
handler.setInputAction((e) => {
  const picked = viewer.scene.pickPosition(e.position) ||
    viewer.scene.camera.pickEllipsoid(e.position, viewer.scene.globe.ellipsoid)
  if (!picked) return
  // 用 picked 替换 start / end 后重新调用 bisectionLine 即可
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)

实现说明

  • 算法count = segments + 1,第 i 点插值系数 offset = i / (count - 1)result[i] = Cartesian3.lerp(start, end, offset)——相邻点欧氏距离必然相等;
  • 纯函数无副作用:入参 start / end 不被修改(lerp 写入独立 new Cartesian3()),结果数组为全新对象,可直接消费;
  • 输入校验segments 必须为正整数,非法值抛错,避免 0 段导致除零 / 数组异常;
  • 高度语义:对同经纬度垂直段,高度随插值系数线性变化;对不同经纬度的斜线,ECEF 笛卡尔插值的高度并非线性(由地球曲率决定),如需精确的高度等分应分别对经纬度与高度插值。

验证

  • 单元测试 LineUtils.spec.ts(7 例):1 段返回 2 点、N 段返回 N+1 点、相邻距离相等、共线(尺度无关 sinθ 判定)、入参不可变、同经纬度垂直段高度线性、非法参数抛错;
  • 浏览器验证:示例外壳 ?id=bisectionLine 顶视俯瞰渲染线段 + 21 个等分点,拾取起 / 终点自动重算。

Cesium 版本限制

  • 仅依赖 Cesium 公开 API:Cartesian3.lerpCartesian3.fromDegrees
  • 无私有字段 / GLSL 依赖;已验证目标版本:Cesium 1.133.1。