目錄
標繪作為GIS最基本需求之一,想必大家在工作中肯定遇到了,標題中的這些標繪大家肯定都實現過,但是也許總是不太全面,在此,我把標繪的邏輯做了統一的封裝處理,沒準等你看完了點線面的處理邏輯後,你會說,只要你給我一個演演算法,我給你畫出個牡丹花(本質上就是給你一堆點,看你能畫出什麼奇奇怪怪的東西了)
繪製邏輯說明:
constructor:這裡採用ES6的新語法,用來構造每種標繪型別的建構函式(js沒有類的概念,就是一個語法糖,誰不知道呢?)
getData:返回該標繪物件座標資料,該資料可以儲存到資料庫,用於二次從資料庫中直接讀取載入該標繪(誰規定非要用滑鼠互動繪製呢?)
loadXXX(data):將getData返回的資料傳入該函數中,即可重新構造出該標繪(資料匯入構建)
startCreate:註冊滑鼠互動事件,用於繪製該標繪(滑鼠互動構建)
destroy:銷燬滑鼠互動
clear:清空臨時實體物件
說了這麼多,相比你心裡還有一些疑惑,下面就從程式碼由淺入深逐漸理解吧,如果你對
CallbackProperty機制不熟悉,最好還是先熟悉一下,這樣你會更加容易理解後面發生的一切。
// DrawPoint
/*
繪製點
*/
class DrawPoint {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.callback=arg.callback;
this._point = null; //最後一個點
this._pointData = null;//點資料用於構造點
this._entities = []; //髒資料
}
//返回最後活動點
get point() {
return this._point;
}
//載入點
loadPoint(data) {
return this.createPoint(data);
}
//返回點資料用於載入點
getData() {
return this._pointData;
}
//開始繪製
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
var cartesian = $this.getCatesian3FromPX(evt.position);
if (!cartesian) return;
var point = $this.createPoint(cartesian);
$this._pointData = cartesian;
$this._point = point;
if(typeof $this.callback=="function"){
$this.callback(point);
}
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities.push(point); //載入髒資料
return point;
}
//銷燬滑鼠事件
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities.length; i++) {
this.viewer.entities.remove(this._entities[i]);
}
this._entities = [];
this._point = null;
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
}
export default DrawPoint;
// DrawPolyline
/*
繪製線
*/
class DrawPolyline {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.callback=arg.callback;
this._polyline = null; //活動線
this._polylineLast = null; //最後一條線
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_line = []; //髒資料
this._polylineData = null; //用於構造線資料
}
//返回最後活動線
get line() {
return this._polylineLast;
}
//返回線資料用於載入線
getData() {
return this._polylineData;
}
//載入線
loadPolyline(data) {
var $this = this;
var polyline = this.viewer.entities.add({
polyline: {
positions: data,
show: true,
material: $this.Cesium.Color.RED,
width: 3,
clampToGround: true
}
});
return polyline;
}
//開始建立
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
//螢幕座標轉地形上座標
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
}
$this._positions.push(cartesian);
$this.createPoint(cartesian);// 繪製點
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製線
if ($this._positions.length < 1) return;
var cartesian = $this.getCatesian3FromPX(evt.endPosition);
if (!$this.Cesium.defined($this._polyline)) {
$this._polyline = $this.createPolyline();
}
if ($this._polyline) {
$this._positions.pop();
$this._positions.push(cartesian);
}
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._polyline) return;
var cartesian = $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this.createPoint(cartesian);// 繪製點
$this._polylineData = $this._positions.concat();
$this.viewer.entities.remove($this._polyline); //移除
$this._polyline = null;
$this._positions = [];
var line = $this.loadPolyline($this._polylineData); //載入線
$this._entities_line.push(line);
$this._polylineLast=line;
if(typeof $this.callback=="function"){
$this.callback(line);
}
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities_point.push(point);
return point;
}
//建立線
createPolyline() {
var $this = this;
var polyline = this.viewer.entities.add({
polyline: {
//使用cesium的peoperty
positions: new $this.Cesium.CallbackProperty(function () {
return $this._positions
}, false),
show: true,
material: $this.Cesium.Color.RED,
width: 3,
clampToGround: true
}
});
$this._entities_line.push(polyline);
return polyline;
}
//銷燬
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_line.length; i++) {
this.viewer.entities.remove(this._entities_line[i]);
}
this._polyline = null;
this._positions = [];
this._entities_point = []; //髒資料
this._entities_line = []; //髒資料
this._polylineData = null; //用於構造線資料
this._polylineLast=null;
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
}
export default DrawPolyline
// DrawCurve
/*
繪製曲線
*/
class DrawCurve {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.floatingPoint = null;//標識點
this._curveline = null; //活動曲線
this._curvelineLast = null; //最後一條曲線
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_line = []; //髒資料
this._curvelineData = null; //用於構造麴線資料
}
//返回最後活動曲線
get curveline() {
return this._curvelineLast;
}
//返回線資料用於載入線
getData() {
return this._curvelineData;
}
//載入曲線
loadCurveline(data) {
var $this = this;
var points = $this.fineBezier(data);
var polyline = this.viewer.entities.add({
polyline: {
positions: points,
show: true,
material: $this.Cesium.Color.RED,
width: 3,
clampToGround: true
}
});
return polyline;
}
//開始建立
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
//螢幕座標轉地形上座標
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
$this.floatingPoint = $this.createPoint(cartesian);
$this.createPoint(cartesian);// 繪製點
}
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製線
if ($this._positions.length < 4) return;
var cartesian = $this.getCatesian3FromPX(evt.endPosition);
if (!$this.Cesium.defined($this._curveline)) {
$this._curveline = $this.createCurveline();
}
$this.floatingPoint.position.setValue(cartesian);
if ($this._curveline) {
$this._positions.pop();
$this._positions.push(cartesian);
}
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._curveline) return;
var cartesian = $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this.createPoint(cartesian);// 繪製點
$this._curvelineData = $this._positions.concat();
$this.viewer.entities.remove($this._curveline); //移除
$this._curveline = null;
$this._positions = [];
$this.floatingPoint.position.setValue(cartesian);
var line = $this.loadCurveline($this._curvelineData); //載入曲線
$this._entities_line.push(line);
$this._curvelineLast = line;
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities_point.push(point);
return point;
}
//建立曲線
createCurveline() {
var $this = this;
var polyline = this.viewer.entities.add({
polyline: {
//使用cesium的peoperty
positions: new $this.Cesium.CallbackProperty(function () {
return $this.fineBezier($this._positions);
}, false),
show: true,
material: $this.Cesium.Color.RED,
width: 3,
clampToGround: true
}
});
$this._entities_line.push(polyline);
return polyline;
}
//銷燬
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_line.length; i++) {
this.viewer.entities.remove(this._entities_line[i]);
}
this.floatingPoint = null;//標識點
this._curveline = null; //活動曲線
this._curvelineLast = null; //最後一條曲線
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_line = []; //髒資料
this._curvelineData = null; //用於構造麴線資料
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
cartesianToLatlng(cartesian) {
var latlng = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
var lat = this.Cesium.Math.toDegrees(latlng.latitude);
var lng = this.Cesium.Math.toDegrees(latlng.longitude);
return [lng, lat];
}
/貝塞爾曲線實現//
fineBezier(points) {
var $this = this;
var pointNUM = 40; //個點
var poins2D = [];
var d = [];
for (var i = 0; i < points.length; i++) {
var res = $this.cartesianToLatlng(points[i]);
var point = new Object();
point.x = res[0];
point.y = res[1];
poins2D.push(point);
}
var cbs = $this.ComputeBezier(poins2D, pointNUM);
for (var j = 0; j < cbs.length; j++) {
d.push(cbs[j].x);
d.push(cbs[j].y);
}
return $this.Cesium.Cartesian3.fromDegreesArray(d);
}
/*
cp在此是四個元素的陣列:
cp[0]為起始點,或上圖中的P0
cp[1]為第一個控制點,或上圖中的P1
cp[2]為第二個控制點,或上圖中的P2
cp[3]為結束點,或上圖中的P3
t為參數值,0 <= t <= 1
*/
PointOnCubicBezier(cp, t) {
var ax, bx, cx;
var ay, by, cy;
var tSquared, tCubed;
var result = new Object();
var length = cp.length;
var inteval = Math.floor(length / 4);// 向下取整
/*計算多項式係數*/
cx = 3.0 * (cp[inteval].x - cp[0].x);
bx = 3.0 * (cp[2 * inteval].x - cp[inteval].x) - cx;
ax = cp[length - 1].x - cp[0].x - cx - bx;
cy = 3.0 * (cp[inteval].y - cp[0].y);
by = 3.0 * (cp[2 * inteval].y - cp[inteval].y) - cy;
ay = cp[length - 1].y - cp[0].y - cy - by;
/*計算位於參數值t的曲線點*/
tSquared = t * t;
tCubed = tSquared * t;
result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x;
result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].y;
return result;
}
/*
ComputeBezier以控制點cp所產生的曲線點,填入Point2D結構的陣列。
呼叫者必須分配足夠的記憶體以供輸出結果,其為<sizeof(Point2D) numberOfPoints>
*/
ComputeBezier(cp, numberOfPoints) {
var $this = this;
var dt;
var i;
var curve = [];
dt = 1.0 / (numberOfPoints - 1);
for (i = 0; i < numberOfPoints; i++) {
curve[i] = $this.PointOnCubicBezier(cp, i * dt);
}
return curve
}
}
export default DrawCurve
/*
繪製圓
*/
class DrawCircle {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.callback=arg.callback;
this._cicle = null; //活動圓
this.floatingPoint = null;
this._cicleLast = null; //最後一個圓
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_cicle = []; //髒資料
this._cicleData = null; //用於構造圓形資料
}
get cicle() {
return this._cicleLast;
}
//載入圓
loadCicle(data) {
var that = this;
var position = data[0];
var value = data;
var r = Math.sqrt(
Math.pow(value[0].x - value[value.length - 1].x, 2) +
Math.pow(value[0].y - value[value.length - 1].y, 2)
);
var shape = this.viewer.entities.add({
position: position,
name: "circle",
type: "circle",
ellipse: {
semiMinorAxis: r,
semiMajorAxis: r,
material: that.Cesium.Color.RED.withAlpha(0.5),
outline: true
}
});
return shape;
}
//返回資料
getData() {
return this._cicleData;
}
startCreate() {
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.viewer.scene.globe.depthTestAgainstTerrain = true;
var $this = this;
this.handler.setInputAction(function (evt) { //單機開始繪製
$this.viewer.scene.globe.depthTestAgainstTerrain = true;
//螢幕座標轉地形上座標
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
$this.floatingPoint = $this.createPoint(cartesian);
}
if (!$this._cicle) {
$this.createPoint(cartesian);// 繪製點
}
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製圓
if ($this._positions.length < 1) return;
var cartesian = $this.viewer.scene.pickPosition(evt.endPosition);// $this.getCatesian3FromPX(evt.endPosition);
if (!$this.Cesium.defined($this._cicle)) {
$this._cicle = $this.createCicle();
}
$this.floatingPoint.position.setValue(cartesian);
if ($this._cicle) {
$this._positions.pop();
$this._positions.push(cartesian);
}
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._cicle) return;
$this.viewer.scene.globe.depthTestAgainstTerrain = false;
var cartesian = $this.viewer.scene.pickPosition(evt.position); // $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this._cicleData = $this._positions.concat();
$this.viewer.entities.remove($this._cicle); //移除
$this._cicle = null;
$this._positions = [];
$this.floatingPoint.position.setValue(cartesian);
var cicle = $this.loadCicle($this._cicleData); //載入
$this._entities_cicle.push(cicle);
$this._cicleLast = cicle;
$this.clearPoint();
if(typeof $this.callback=="function"){
$this.callback(cicle);
}
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立圓
createCicle() {
var that = this;
var shape = this.viewer.entities.add({
position: that._positions[0],
name: "circle",
type: "circle",
ellipse: {
semiMinorAxis: new that.Cesium.CallbackProperty(function () {
//半徑 兩點間距離
var r = Math.sqrt(
Math.pow(that._positions[0].x - that._positions[that._positions.length - 1].x, 2) +
Math.pow(that._positions[0].y - that._positions[that._positions.length - 1].y, 2)
);
return r ? r : r + 1;
}, false),
semiMajorAxis: new that.Cesium.CallbackProperty(function () {
var r = Math.sqrt(
Math.pow(that._positions[0].x - that._positions[that._positions.length - 1].x, 2) +
Math.pow(that._positions[0].y - that._positions[that._positions.length - 1].y, 2)
);
return r ? r : r + 1;
}, false),
material: that.Cesium.Color.RED.withAlpha(0.5),
outline: true
}
});
that._entities_cicle.push(shape);
return shape;
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});;
$this._entities_point.push(point);
return point;
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
clearPoint(){
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
this._entities_point = []; //髒資料
}
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_cicle.length; i++) {
this.viewer.entities.remove(this._entities_cicle[i]);
}
this._cicle = null; //活動圓
this.floatingPoint = null;
this._cicleLast = null; //最後一個圓
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_cicle = []; //髒資料
this._cicleData = null; //用於構造圓形資料
}
}
export default DrawCircle
// DrawCurve
/*
繪製矩形
*/
class DrawRectangle {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.callback=arg.callback;
this.floatingPoint = null;//標識點
this._rectangle = null; //活動矩形
this._rectangleLast = null; //最後一個矩形
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_rectangle = []; //髒資料
this._rectangleData = null; //用於構造矩形資料
}
//返回最後圖形
get line() {
return this._rectangleLast;
}
//返回矩形資料
getData() {
return this._rectangleData;
}
//載入
loadRectangle(data) {
var $this = this;
var shape = this.viewer.entities.add({
name: "rectangle",
rectangle: {
coordinates: $this.Cesium.Rectangle.fromCartesianArray(data),
material: $this.Cesium.Color.RED.withAlpha(0.5)
}
});
$this._entities_rectangle.push(shape);
return shape;
}
//開始建立
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
//螢幕座標轉地形上座標
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
$this.floatingPoint = $this.createPoint(cartesian);
$this.createPoint(cartesian);// 繪製點
}
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製線
if ($this._positions.length < 3) return;
var cartesian = $this.getCatesian3FromPX(evt.endPosition);
if (!$this.Cesium.defined($this._rectangle)) {
$this._rectangle = $this.createRectangle();
}
$this.floatingPoint.position.setValue(cartesian);
if ($this._rectangle) {
$this._positions.pop();
$this._positions.push(cartesian);
}
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._rectangle) return;
var cartesian = $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this.createPoint(cartesian);// 繪製點
$this._rectangleData = $this._positions.concat();
$this.viewer.entities.remove($this._rectangle); //移除
$this._rectangle = null;
$this._positions = [];
$this.floatingPoint.position.setValue(cartesian);
var rectangle = $this.loadRectangle($this._rectangleData); //載入
$this._entities_rectangle.push(rectangle);
$this._rectangleLast = rectangle;
if(typeof $this.callback=="function"){
$this.callback(rectangle);
}
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities_point.push(point);
return point;
}
//建立矩形
createRectangle() {
var $this = this;
var shape = this.viewer.entities.add({
name: "rectangle",
rectangle: {
coordinates: new $this.Cesium.CallbackProperty(function() {
var obj = $this.Cesium.Rectangle.fromCartesianArray($this._positions);
return obj;
}, false),
material: $this.Cesium.Color.RED.withAlpha(0.5)
}
});
$this._entities_rectangle.push(shape);
return shape;
}
//銷燬
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_rectangle.length; i++) {
this.viewer.entities.remove(this._entities_rectangle[i]);
}
this.floatingPoint = null;//標識點
this._rectangle = null; //活動矩形
this._rectangleLast = null; //最後一個矩形
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_rectangle = []; //髒資料
this._rectangleData = null; //用於構造矩形資料
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
}
export default DrawRectangle
// DrawPolygon
/*
繪製面
*/
class DrawPolygon {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.callback=arg.callback;
this._polygon = null; //活動面
this._polygonLast = null; //最後一個面
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_polygon = []; //髒資料
this._polygonData = null; //使用者構造面
}
//返回最後活動面
get polygon() {
return this._polygonLast;
}
//返回面資料用於載入面
getData() {
return this._polygonData;
}
//載入面
loadPolygon(data) {
var $this = this;
return this.viewer.entities.add({
polygon: {
hierarchy: new $this.Cesium.PolygonHierarchy(data),
clampToGround: true,
show: true,
fill: true,
material: $this.Cesium.Color.RED.withAlpha(0.5),
width: 3,
outlineColor: $this.Cesium.Color.BLACK,
outlineWidth: 1,
outline: false
}
});
}
//開始繪製
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
}
$this.createPoint(cartesian);
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製面
if ($this._positions.length < 1) return;
var cartesian = $this.getCatesian3FromPX(evt.endPosition);
if ($this._positions.length == 3) {
if (!$this.Cesium.defined($this._polygon)) {
$this._polygon = $this.createPolygon();
}
}
$this._positions.pop();
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._polygon) return;
var cartesian = $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this.createPoint(cartesian);
$this._polygonData = $this._positions.concat();
$this.viewer.entities.remove($this._positions); //移除
$this._positions=null;
$this._positions = [];
var Polygon = $this.loadPolygon($this._polygonData);
$this._entities_polygon.push(Polygon);
$this._polygonLast = Polygon;
if(typeof $this.callback=="function"){
$this.callback(Polygon);
}
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立面
createPolygon() {
var $this = this;
var polygon = this.viewer.entities.add({
polygon: {
hierarchy: new $this.Cesium.CallbackProperty(function () {
return new $this.Cesium.PolygonHierarchy($this._positions);
}, false),
clampToGround: true,
show: true,
fill: true,
material: $this.Cesium.Color.RED.withAlpha(0.5),
width: 3,
outlineColor: $this.Cesium.Color.BLACK,
outlineWidth: 1,
outline: false
}
});
$this._entities_polygon.push(polygon);
return polygon;
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities_point.push(point);
return point;
}
//銷燬事件
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_polygon.length; i++) {
this.viewer.entities.remove(this._entities_polygon[i]);
}
this._polygon = null; //活動面
this._polygonLast = null; //最後一個面
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_polygon = []; //髒資料
this._polygonData = null; //使用者構造面
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
}
export default DrawPolygon
// DrawstraightArrow
/*
繪製直線箭頭
*/
class DrawstraightArrow {
constructor(arg) {
this.viewer = arg.viewer;
this.Cesium = arg.Cesium;
this.floatingPoint = null;//標識點
this._straightArrow = null; //活動箭頭
this._straightArrowLast = null; //最後一個箭頭
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_straightArrow = []; //髒資料
this._straightArrowData = null; //用於構造箭頭資料
}
//返回箭頭
get straightArrow() {
return this._straightArrowLast;
}
//返回箭頭資料用於載入箭頭
getData() {
return this._straightArrowData;
}
//載入箭頭
loadStraightArrow(data) {
var $this = this;
if (data.length < 2) {
return null;
}
var length = data.length;
var p1 = data[0];
var p2 = data[length - 1];
var firstPoint = $this.cartesianToLatlng(p1);
var endPoints = $this.cartesianToLatlng(p2);
var arrow = [];
var res = $this.fineArrow([firstPoint[0], firstPoint[1]], [endPoints[0], endPoints[1]]);
for (var i = 0; i < res.length; i++) {
var cart3 = new $this.Cesium.Cartesian3(res[i].x, res[i].y, res[i].z);
arrow.push(cart3);
}
var arrowEntity = $this.viewer.entities.add({
polygon: {
hierarchy: new $this.Cesium.PolygonHierarchy(arrow),
show: true,
fill: true,
clampToGround: true,
material: $this.Cesium.Color.AQUA.withAlpha(0.5)
}
});
return arrowEntity;
}
//開始建立
startCreate() {
var $this = this;
this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction(function (evt) { //單機開始繪製
//螢幕座標轉地形上座標
var cartesian = $this.getCatesian3FromPX(evt.position);
if ($this._positions.length == 0) {
$this._positions.push(cartesian.clone());
$this.floatingPoint = $this.createPoint(cartesian);
}
if (!$this._straightArrow) {
$this.createPoint(cartesian);// 繪製點
}
$this._positions.push(cartesian);
}, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction(function (evt) { //移動時繪製面
if ($this._positions.length < 2) return;
var cartesian = $this.getCatesian3FromPX(evt.endPosition);
if (!$this.Cesium.defined($this._straightArrow)) {
$this._straightArrow = $this.createStraightArrow();
}
$this.floatingPoint.position.setValue(cartesian);
if ($this._straightArrow) {
$this._positions.pop();
$this._positions.push(cartesian);
}
}, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.setInputAction(function (evt) {
if (!$this._straightArrow) return;
var cartesian = $this.getCatesian3FromPX(evt.position);
$this._positions.pop();
$this._positions.push(cartesian);
$this._straightArrowData = $this._positions.concat();
$this.viewer.entities.remove($this._straightArrow); //移除
$this._straightArrow = null;
$this._positions = [];
$this.floatingPoint.position.setValue(cartesian);
var straightArrow = $this.loadStraightArrow($this._straightArrowData); //載入
$this._entities_straightArrow.push(straightArrow);
$this._straightArrowLast = straightArrow;
$this.clearPoint();
}, $this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
//建立直線箭頭
createStraightArrow() {
var $this = this;
var arrowEntity = $this.viewer.entities.add({
polygon: {
hierarchy: new $this.Cesium.CallbackProperty(
function () {
// return new $this.Cesium.PolygonHierarchy($this._positions);
var length = $this._positions.length;
var p1 = $this._positions[0];
var p2 = $this._positions[length - 1];
var firstPoint = $this.cartesianToLatlng(p1);
var endPoints = $this.cartesianToLatlng(p2);
var arrow = [];
var res = $this.fineArrow([firstPoint[0], firstPoint[1]], [endPoints[0], endPoints[1]]);
for (var i = 0; i < res.length; i++) {
var cart3 = new $this.Cesium.Cartesian3(res[i].x, res[i].y, res[i].z);
arrow.push(cart3);
}
return new $this.Cesium.PolygonHierarchy(arrow);
}, false),
show: true,
fill: true,
clampToGround: true,
material: $this.Cesium.Color.AQUA.withAlpha(0.5)
}
}
)
$this._entities_straightArrow.push(arrowEntity);
return arrowEntity
}
//建立點
createPoint(cartesian) {
var $this = this;
var point = this.viewer.entities.add({
position: cartesian,
point: {
pixelSize: 10,
color: $this.Cesium.Color.YELLOW,
}
});
$this._entities_point.push(point);
return point;
}
cartesianToLatlng(cartesian) {
var latlng = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
var lat = this.Cesium.Math.toDegrees(latlng.latitude);
var lng = this.Cesium.Math.toDegrees(latlng.longitude);
return [lng, lat];
}
//銷燬
destroy() {
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
}
clearPoint() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
this._entities_point = []; //髒資料
}
//清空實體物件
clear() {
for (var i = 0; i < this._entities_point.length; i++) {
this.viewer.entities.remove(this._entities_point[i]);
}
for (var i = 0; i < this._entities_straightArrow.length; i++) {
this.viewer.entities.remove(this._entities_straightArrow[i]);
}
this.floatingPoint = null;//標識點
this._straightArrow = null; //活動箭頭
this._straightArrowLast = null; //最後一個箭頭
this._positions = []; //活動點
this._entities_point = []; //髒資料
this._entities_straightArrow = []; //髒資料
this._straightArrowData = null; //用於構造箭頭資料
}
getCatesian3FromPX(px) {
var cartesian;
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
return cartesian;
}
求取箭頭座標函數/
//箭頭設定函數
fineArrowDefualParam() {
return {
tailWidthFactor: 0.15,
neckWidthFactor: 0.20,
headWidthFactor: 0.25,
headAngle: Math.PI / 8.5,
neckAngle: Math.PI / 13
}
}
fineArrow(tailPoint, headerPoint) {
var $this = this;
if ((tailPoint.length < 2) || (headerPoint.length < 2)) return;
//畫箭頭的函數
let tailWidthFactor = $this.fineArrowDefualParam().tailWidthFactor;
let neckWidthFactor = $this.fineArrowDefualParam().neckWidthFactor;
let headWidthFactor = $this.fineArrowDefualParam().headWidthFactor;
let headAngle = $this.fineArrowDefualParam().headAngle;
let neckAngle = $this.fineArrowDefualParam().neckAngle;
var o = [];
o[0] = tailPoint;
o[1] = headerPoint;
var e = o[0],
r = o[1],
n = $this.getBaseLength(o),
g = n * tailWidthFactor,
//尾部寬度因子
i = n * neckWidthFactor,
//脖子寬度銀子
s = n * headWidthFactor,
//頭部寬度因子
a = $this.getThirdPoint(r, e, Math.PI / 2, g, !0),
l = $this.getThirdPoint(r, e, Math.PI / 2, g, !1),
u = $this.getThirdPoint(e, r, headAngle, s, !1),
c = $this.getThirdPoint(e, r, headAngle, s, !0),
p = $this.getThirdPoint(e, r, neckAngle, i, !1),
h = $this.getThirdPoint(e, r, neckAngle, i, !0),
d = [];
d.push(a[0], a[1], p[0], p[1], u[0], u[1], r[0], r[1], c[0], c[1], h[0], h[1], l[0], l[1], e[0], e[1]);
return $this.Cesium.Cartesian3.fromDegreesArray(d);
}
getBaseLength(t) {
return Math.pow(this.wholeDistance(t), .99)
}
wholeDistance(t) {
for (var o = 0, e = 0; e < t.length - 1; e++) o += this.distance(t[e], t[e + 1]);
return o
}
distance(t, o) {
return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2))
}
getThirdPoint(t, o, e, r, n) {
var g = this.getAzimuth(t, o),
i = n ? g + e : g - e,
s = r * Math.cos(i),
a = r * Math.sin(i);
return [o[0] + s, o[1] + a]
}
getAzimuth(t, o) {
var e, r = Math.asin(Math.abs(o[1] - t[1]) / this.distance(t, o));
return o[1] >= t[1] && o[0] >= t[0] ? e = r + Math.PI : o[1] >= t[1] && o[0] < t[0] ? e = 2 * Math.PI - r : o[1] < t[1] && o[0] < t[0] ? e = r : o[1] < t[1] && o[0] >= t[0] && (e = Math.PI - r), e
}
}
export default DrawstraightArrow
現在你仔細把程式碼過一下,發現規律了嗎?現在你會畫出牡丹花了吧,哈哈
這裡有個地方需要說明,由於篇幅有限,攻擊箭頭和鉗擊箭頭的程式碼沒有貼出來,
如果你還有不瞭解的地方,
如果你還需要進行cesium交流,
那一起學習探討吧。
你可以加入我們的基地,我們基地的地址是:450342630(QQ群號)