为了实现Cesium 对模型的拖拽平移和旋转,需要以模型为中心建立箭头坐标轴(沿坐标轴方向移动)和圆坐标轴(沿圆弧方向旋转)。
利用Cesium的矩阵运算,创建primitive,操作矩阵实现各种坐标轴。箭头坐标轴比圆坐标轴简单很多,Cesium内置了箭头材质,更改材质即可。
Cesium中添加图形的两种方法,一种是entities,一种是primitives。后者更适合开发,主要用到modelmatrix属性。添加箭头可以理解为添加同一个坐标起点的本地沿坐标轴方向的三条箭头线。
宽度和长度可根据需求自己调节。主要更改material即可。
// 创建x方向的箭头
var arrowx = viewer.entities.add({
name:"arrowx",
polyline:{
positions:Cesium.Cartesian3.fromDegreesArrayHeights([
lon,lat,hei,lon+0.00003,lat,hei]),
width:25,
arcType:Cesium.ArcType.NONE,
material:new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),
},
});
依次画出y、z坐标。
绘制圆坐标的话,用primitive来画,要用到modelmatrix。用线画圆可以调节圆的宽度。可以创建圆后,拿到圆的坐标,再用线绘制。
绘制圆,granularity越小,密度越大。
var circle = new Cesium.CircleOutlineGeometry({
center:Cesium.Cartesian3.fromDegrees(lan,lat,height),
radius:3.0,
granularity:0.001
});
取坐标,存入数组
var geometry = new Cesium.CircleOutlineGeometry.createGeometry(circle);
var Positions = geometry.attributes.position.values;
var Pos = [].slice.call(Positions);
把坐标转换为position
var erll = Positions.length/3;
var erl = [];
for (var h=0;h<erll;h++)
{
erl[h] =[];
}
var k =0;
for (var p = 0;p<erll;p++)
{
for (var q = 0;q<3;q++)
{
erl[p][q]= Pos[k];
k++;
if(k>Positions.length-1)
{
break;
}
}
}
var posCirle = [];
for (var t= 0;t<erl.length;t++)
{
var car3 = new Cesium.Cartesian3();
posCirle.push(new Cesium.Cartesian3(erl[t][0],erl[t][1],erl[t][2]));
}
//首尾相连
posCirle.push(new Cesium.Cartesian3(erl[0][0],erl[0][1],erl[0][2]));
创建GeometryInstance
var polyline = new Cesium.PolylineGeometry({
positions: posCirle,
width: 5.0,
vertexFormat:Cesium.PolylineColorAppearance.VERTEX_FORMAT
});
var rectangleInstance = new Cesium.GeometryInstance({
geometry: polyline,
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE),
},
id:"lineZ"
});//HEADING
绘制,依次绘制剩余坐标轴
var lineZ = new Cesium.Primitive({
geometryInstances:rectangleInstance ,
appearance:new Cesium.PolylineColorAppearance({
translucent:false
}),
asynchronous: false,
});
viewer.scene.primitives.add(lineZ);
转换坐标轴,用这种方法绘制的圆实际上是没有经过坐标转换矩阵的,默认单位阵。可以通过Cesium.Matrix3.fromRotationX(或者yz)生成旋转矩阵,再与原矩阵相乘。
这里建议手写转换矩阵,学过坐标矩阵转换后很容易理解。分别将绘制的圆绕x轴和y轴旋转,再平移矩阵至原坐标点。当仅有X坐标时的旋转矩阵,如下(注意Cesium矩阵的写法,按行输入):
lineY.modelMatrix = new Cesium.Matrix4(0,0,1,X,0,1,0,0,1,0,0,-X,0,0,0,1);
lineX.modelMatrix = new Cesium.Matrix4(0,1,0,X,1,0,0,-X,0,0,1,0,0,0,0,1);
坐标的平移量可以通过圆心点的坐标来计算。
var cartest = new Cesium.Cartesian3(x,y,z);
cartest = Cesium.Matrix4.multiplyByPoint(lineX.modelMatrix,cartest,cartest);
console.log(cartest);
通过计算cartest的坐标差值来计算平移量。
绘制箭头相对比较简单,不需要矩阵操作,如果需要的话,建议也用primitive绘制,方法与圆坐标的方法相同。绘制圆坐标的主要是获取坐标点后,对绘制的圆进行坐标矩阵转换。可以通过其他讲解坐标转换矩阵的博客进行学习。一些有关Cesium中的坐标矩阵问题后续会进行说明和补充。
下一篇博客会讲述如何实现模型沿坐标轴平移和旋转。