我明明拾取的是中间的房子, 得到的四个点就是房子的四个角, 但是最终渲染出来, 将两侧的房子、 后面的树木以及前面的马路都选染上了。 使用代码如下:
// 鼠标事件
drawLine() {
var _this = this;
_this.drawLineString(function(positions) {
var wgs84_positions = [];
for (var i = 0; i < positions.length; i++) {
var wgs84_point = _this.Cartesian3_to_WGS84({
x: positions[i].x,
y: positions[i].y,
z: positions[i].z,
});
wgs84_positions.push(wgs84_point);
}
// wgs84_positions为最终得到的结果
_this.coordinates = arr.join(",");
});
},
// drawLineString方法,此方法直接使用pickEllipsoid在三维模型上获取点,结果不准确
drawLineString: function(callback) {
var _this = this;
var PolyLinePrimitive = (function() {
function _(positions) {
this.options = {
polyline: {
show: true,
positions: [],
material: Cesium.Color.RED,
width: 3,
},
};
this.positions = positions;
this._init();
}
_.prototype._init = function() {
var _self = this;
var _update = function() {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(
_update,
false
);
_this.viewer.entities.add(this.options);
};
return _;
})();
var handler = new Cesium.ScreenSpaceEventHandler(
_this.viewer.scene.canvas
);
var positions = [];
var poly = undefined;
//鼠标左键单击画点
handler.setInputAction(function(movement) {
var cartesian = _this.viewer.scene.camera.pickEllipsoid(
movement.position,
_this.viewer.scene.globe.ellipsoid
);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动
handler.setInputAction(function(movement) {
var cartesian = _this.viewer.scene.camera.pickEllipsoid(
movement.endPosition,
_this.viewer.scene.globe.ellipsoid
);
if (positions.length >= 2) {
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
if (cartesian != undefined) {
positions.pop();
cartesian.y += 1 + Math.random();
positions.push(cartesian);
}
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//单击鼠标右键结束画线
handler.setInputAction(function(movement) {
handler.destroy();
callback(positions);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
},
后来在百度上找到了一个非常全面的方法,它将鼠标在地球上、地形上还是3DTILES上点击,进行了判断,不同实体进行使用不同的方法进行坐标拾取,如pick、pickEllipsoid等(参考:屏幕坐标转世界坐标的方法对比 http://www.5imoban.net/jiaocheng/mapgis/2021/0622/4869.html),并且对坐标进行了转换,非常不错:
/**
* 拾取位置点,能够根据鼠标位置判断出是画在3dtils上,还是画在地球上,还是画在地形上
*
* @param {Object} px 屏幕坐标
*
* @return {Object} Cartesian3 三维坐标
*/
getCatesian3FromPX: function(px) {
if (this.viewer && px) {
var picks = this.viewer.scene.drillPick(px);
var cartesian = null;
var isOn3dtiles = false,
isOnTerrain = false;
// drillPick
for (let i in picks) {
let pick = picks[i];
if (
(pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
(pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
(pick && pick.primitive instanceof Cesium.Model)
) {
//模型上拾取
isOn3dtiles = true;
}
// 3dtilset
if (isOn3dtiles) {
this.viewer.scene.pick(px); // pick
cartesian = this.viewer.scene.pickPosition(px);
if (cartesian) {
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
if (cartographic.height < 0) cartographic.height = 0;
let lon = Cesium.Math.toDegrees(cartographic.longitude),
lat = Cesium.Math.toDegrees(cartographic.latitude),
height = cartographic.height;
cartesian = this.transformWGS84ToCartesian({
lng: lon,
lat: lat,
alt: height,
});
}
}
}
// 地形
let boolTerrain =
this.viewer.terrainProvider instanceof
Cesium.EllipsoidTerrainProvider;
// Terrain
if (!isOn3dtiles && !boolTerrain) {
var ray = this.viewer.scene.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
isOnTerrain = true;
}
// 地球
if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
cartesian = this.viewer.scene.camera.pickEllipsoid(
px,
this.viewer.scene.globe.ellipsoid
);
}
if (cartesian) {
let position = this.transformCartesianToWGS84(cartesian);
if (position.alt < 0) {
cartesian = this.transformWGS84ToCartesian(position, 0.1);
}
return cartesian;
}
return false;
}
},
/***
* 坐标转换 笛卡尔转84
*
* @param {Object} Cartesian3 三维位置坐标
*
* @return {Object} {lng,lat,alt} 地理坐标
*/
transformCartesianToWGS84: function(cartesian) {
if (this.viewer && cartesian) {
var ellipsoid = Cesium.Ellipsoid.WGS84;
var cartographic = ellipsoid.cartesianToCartographic(cartesian);
return {
lng: Cesium.Math.toDegrees(cartographic.longitude),
lat: Cesium.Math.toDegrees(cartographic.latitude),
alt: cartographic.height,
};
}
},
/***
* 坐标转换 84转笛卡尔
*
* @param {Object} {lng,lat,alt} 地理坐标
*
* @return {Object} Cartesian3 三维位置坐标
*/
transformWGS84ToCartesian: function(position, alt) {
if (this.viewer) {
return position ?
Cesium.Cartesian3.fromDegrees(
position.lng || position.lon,
position.lat,
position.alt = alt || position.alt,
Cesium.Ellipsoid.WGS84
) :
Cesium.Cartesian3.ZERO
}
},
将上面的代码,放到项目中(注意修改里面的this、viewer等问题),然后,修改之前的drawLineString方法:
drawLineString: function(callback) {
var _this = this;
var PolyLinePrimitive = (function() {
function _(positions) {
this.options = {
polyline: {
show: true,
positions: [],
material: Cesium.Color.RED,
width: 3,
},
};
this.positions = positions;
this._init();
}
_.prototype._init = function() {
var _self = this;
var _update = function() {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(
_update,
false
);
_this.viewer.entities.add(this.options);
};
return _;
})();
var handler = new Cesium.ScreenSpaceEventHandler(
_this.viewer.scene.canvas
);
var positions = [];
var poly = undefined;
//鼠标左键单击画点
handler.setInputAction(function(movement) {
// 使用getCatesian3FromPX方法来获取坐标
var cartesian = _this.getCatesian3FromPX(movement.position);
//之前的单纯的pickEllipsoid拾取坐标不可取,这里注释了
// var cartesian = _this.viewer.scene.camera.pickEllipsoid(
// movement.position,
// _this.viewer.scene.globe.ellipsoid
// );
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动
handler.setInputAction(function(movement) {
// 使用getCatesian3FromPX方法来获取坐标
var cartesian = _this.getCatesian3FromPX(movement.position);
//之前的单纯的pickEllipsoid拾取坐标不可取,这里注释了
// var cartesian = _this.viewer.scene.camera.pickEllipsoid(
// movement.position,
// _this.viewer.scene.globe.ellipsoid
// );
if (positions.length >= 2) {
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
if (cartesian != undefined) {
positions.pop();
cartesian.y += 1 + Math.random();
positions.push(cartesian);
}
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//单击鼠标右键结束画线
handler.setInputAction(function(movement) {
handler.destroy();
callback(positions);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
},
修改后,拾取的坐标,再次渲染结果(换了一栋建筑物):