Cesium绘制平滑曲线(样条线和贝塞尔曲线)

先看最终效果:

QQ截图20230404143450

沙盒演示 (链接打不开建议科学-学习-上网)

最近搞路径漫游,需要绘制平滑曲线,刚开始想到的是绘制贝塞尔曲线,但是贝塞尔曲线不确保经过控制点,最后才知道需要的是样条线这个东西。

通过样条线获取平滑曲线的插值点,用点绘制线就可以了,如下:

const viewer = new Cesium.Viewer("cesiumContainer");

// 定义控制点
var controlPoints = [
  new Cesium.Cartesian3(-1000000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(-500000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(0.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, -500000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, -1500000.0),
  new Cesium.Cartesian3(2000000.0, 0.0, -1500000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, -2000000.0)
];

let count = controlPoints.length;
let times = [];
let step = 1/(count-1);
for(let i =0;i<count;i++){
  let time = step*i;
  times.push(time);
}

// 样条线
var spline = new Cesium.CatmullRomSpline({
  times,
  points: controlPoints
});

// 获取平滑曲线(样条线)的插值点
var numSamples = 100;
var samples = [];
for (var i = 0; i <= numSamples; i++) {
  var time = i / numSamples;
  var sample = spline.evaluate(time);
  samples.push(sample);
}

viewer.scene.primitives.add(new Cesium.PolylineCollection());
var polyline = new Cesium.PolylineGeometry({
  positions: samples,
  width: 5.0
});
var polylineInstance = new Cesium.GeometryInstance({
  geometry: polyline,
  attributes: {
    color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW)
  }
});

// 绘制曲线
viewer.scene.primitives.add(new Cesium.Primitive({
  geometryInstances: [polylineInstance],
  appearance: new Cesium.PolylineMaterialAppearance({
    material: Cesium.Material.fromType('Color', {
      color: Cesium.Color.YELLOW
    })
  })
}));

// 绘制控制点
controlPoints.forEach(p => {
  viewer.entities.add({
    position:p,
    point:{
      pixelSize:15,
      color:Cesium.Color.RED
    }
    
  })
})


viewer.scene.globe.show = false;

贝塞尔曲线也顺便贴上来吧。。。

var viewer = new Cesium.Viewer('cesiumContainer');

// 控制点
var controlPoints = [
  new Cesium.Cartesian3(-1000000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(-500000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(0.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(500000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, 1000000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, 500000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, 0.0),
  new Cesium.Cartesian3(1000000.0, 0.0, -500000.0),
  new Cesium.Cartesian3(1000000.0, 0.0, -1000000.0),
  new Cesium.Cartesian3(500000.0, 0.0, -1000000.0)
];

// 插值
var numSamples = 100;
var samples = [];
for (var i = 0; i <= numSamples; i++) {
  var t = i / numSamples;
  var point = controlPoints[0];
  for (var j = 1; j < controlPoints.length; j++) {
    var prevPoint = point;
    point = Cesium.Cartesian3.lerp(prevPoint, controlPoints[j], t, new Cesium.Cartesian3());
  }
  samples.push(point);
}

// 绘制曲线
viewer.entities.add({
  polyline: {
    positions: samples,
    width: 5.0,
    material: Cesium.Color.YELLOW
  }
});

viewer.scene.globe.show = false;

 

posted @ 2025-06-11 09:50  我的五年  阅读(229)  评论(0)    收藏  举报