c6890ef64bdac46759ebba6c37f94dd0f8d4ed90..25ce610f6ecca7325e7a743dc032c4a76559c63d
2021-07-02 liuyg
Merge branch 'master' of http://192.168.0.105:10010/r/pyhmap
25ce61 diff | tree
2021-07-02 liuyg
飞行测试
6d4779 diff | tree
2 files modified
15 files added
4201 ■■■■■ changed files
config.json 7 ●●●● patch | view | raw | blame | history
widgets/filyL/FileSaver.js 244 ●●●●● patch | view | raw | blame | history
widgets/filyL/Widget.html 35 ●●●●● patch | view | raw | blame | history
widgets/filyL/Widget.js 354 ●●●●● patch | view | raw | blame | history
widgets/filyL/css/a.css 160 ●●●●● patch | view | raw | blame | history
widgets/filyL/css/style.css 188 ●●●●● patch | view | raw | blame | history
widgets/filyL/fly.js 529 ●●●●● patch | view | raw | blame | history
widgets/filyL/flyroute.json 55 ●●●●● patch | view | raw | blame | history
widgets/filyL/js/DrawHelper.js 1874 ●●●●● patch | view | raw | blame | history
widgets/filyL/js/move.js 103 ●●●●● patch | view | raw | blame | history
widgets/filyL/manifest.json 17 ●●●●● patch | view | raw | blame | history
widgets/filyL/nls/es/strings.js 5 ●●●●● patch | view | raw | blame | history
widgets/filyL/nls/strings.js 7 ●●●●● patch | view | raw | blame | history
widgets/filyL/nls/zh-cn/strings.js 5 ●●●●● patch | view | raw | blame | history
widgets/filyL/实例临时 copy 2.html 30 ●●●●● patch | view | raw | blame | history
widgets/filyL/实例临时 copy.html 587 ●●●●● patch | view | raw | blame | history
widgets/visibleArea/Widget.js 1 ●●●● patch | view | raw | blame | history
config.json
@@ -284,8 +284,7 @@
      {
        "name": "开敞度分析",
        "uri": "widgets/openAnalysis/Widget"
      }
      ,
      },
      {
        "name": "BOX交互裁剪",
        "uri": "widgets/BOXInteractive/Widget"
@@ -293,6 +292,10 @@
      {
        "name": "Cross裁剪",
        "uri": "widgets/crossTailoring/Widget"
      },
      {
        "name": "飞行",
        "uri": "widgets/filyL/Widget"
      }
    ],
    "groups": [],
widgets/filyL/FileSaver.js
New file
@@ -0,0 +1,244 @@
/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 2014-11-29
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
 */
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs
  // IE 10+ (native saveAs)
  || (typeof navigator !== "undefined" &&
      navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  // Everyone else
  || (function(view) {
    "use strict";
    // IE <10 is explicitly unsupported
    if (typeof navigator !== "undefined" &&
        /MSIE [1-9]\./.test(navigator.userAgent)) {
        return;
    }
    var
          doc = view.document
          // only get URL when necessary in case Blob.js hasn't overridden it yet
        , get_URL = function() {
            return view.URL || view.webkitURL || view;
        }
        , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
        , can_use_save_link = "download" in save_link
        , click = function(node) {
            var event = doc.createEvent("MouseEvents");
            event.initMouseEvent(
                "click", true, false, view, 0, 0, 0, 0, 0
                , false, false, false, false, 0, null
            );
            node.dispatchEvent(event);
        }
        , webkit_req_fs = view.webkitRequestFileSystem
        , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
        , throw_outside = function(ex) {
            (view.setImmediate || view.setTimeout)(function() {
                throw ex;
            }, 0);
        }
        , force_saveable_type = "application/octet-stream"
        , fs_min_size = 0
        // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
        // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
        // for the reasoning behind the timeout and revocation flow
        , arbitrary_revoke_timeout = 500 // in ms
        , revoke = function(file) {
            var revoker = function() {
                if (typeof file === "string") { // file is an object URL
                    get_URL().revokeObjectURL(file);
                } else { // file is a File
                    file.remove();
                }
            };
            if (view.chrome) {
                revoker();
            } else {
                setTimeout(revoker, arbitrary_revoke_timeout);
            }
        }
        , dispatch = function(filesaver, event_types, event) {
            event_types = [].concat(event_types);
            var i = event_types.length;
            while (i--) {
                var listener = filesaver["on" + event_types[i]];
                if (typeof listener === "function") {
                    try {
                        listener.call(filesaver, event || filesaver);
                    } catch (ex) {
                        throw_outside(ex);
                    }
                }
            }
        }
        , FileSaver = function(blob, name) {
            // First try a.download, then web filesystem, then object URLs
            var
                  filesaver = this
                , type = blob.type
                , blob_changed = false
                , object_url
                , target_view
                , dispatch_all = function() {
                    dispatch(filesaver, "writestart progress write writeend".split(" "));
                }
                // on any filesys errors revert to saving with object URLs
                , fs_error = function() {
                    // don't create more object URLs than needed
                    if (blob_changed || !object_url) {
                        object_url = get_URL().createObjectURL(blob);
                    }
                    if (target_view) {
                        target_view.location.href = object_url;
                    } else {
                        var new_tab = view.open(object_url, "_blank");
                        if (new_tab == undefined && typeof safari !== "undefined") {
                            //Apple do not allow window.open, see http://bit.ly/1kZffRI
                            view.location.href = object_url
                        }
                    }
                    filesaver.readyState = filesaver.DONE;
                    dispatch_all();
                    revoke(object_url);
                }
                , abortable = function(func) {
                    return function() {
                        if (filesaver.readyState !== filesaver.DONE) {
                            return func.apply(this, arguments);
                        }
                    };
                }
                , create_if_not_found = {create: true, exclusive: false}
                , slice
            ;
            filesaver.readyState = filesaver.INIT;
            if (!name) {
                name = "download";
            }
            if (can_use_save_link) {
                object_url = get_URL().createObjectURL(blob);
                save_link.href = object_url;
                save_link.download = name;
                click(save_link);
                filesaver.readyState = filesaver.DONE;
                dispatch_all();
                revoke(object_url);
                return;
            }
            // Object and web filesystem URLs have a problem saving in Google Chrome when
            // viewed in a tab, so I force save with application/octet-stream
            // http://code.google.com/p/chromium/issues/detail?id=91158
            // Update: Google errantly closed 91158, I submitted it again:
            // https://code.google.com/p/chromium/issues/detail?id=389642
            if (view.chrome && type && type !== force_saveable_type) {
                slice = blob.slice || blob.webkitSlice;
                blob = slice.call(blob, 0, blob.size, force_saveable_type);
                blob_changed = true;
            }
            // Since I can't be sure that the guessed media type will trigger a download
            // in WebKit, I append .download to the filename.
            // https://bugs.webkit.org/show_bug.cgi?id=65440
            if (webkit_req_fs && name !== "download") {
                name += ".download";
            }
            if (type === force_saveable_type || webkit_req_fs) {
                target_view = view;
            }
            if (!req_fs) {
                fs_error();
                return;
            }
            fs_min_size += blob.size;
            req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
                fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
                    var save = function() {
                        dir.getFile(name, create_if_not_found, abortable(function(file) {
                            file.createWriter(abortable(function(writer) {
                                writer.onwriteend = function(event) {
                                    target_view.location.href = file.toURL();
                                    filesaver.readyState = filesaver.DONE;
                                    dispatch(filesaver, "writeend", event);
                                    revoke(file);
                                };
                                writer.onerror = function() {
                                    var error = writer.error;
                                    if (error.code !== error.ABORT_ERR) {
                                        fs_error();
                                    }
                                };
                                "writestart progress write abort".split(" ").forEach(function(event) {
                                    writer["on" + event] = filesaver["on" + event];
                                });
                                writer.write(blob);
                                filesaver.abort = function() {
                                    writer.abort();
                                    filesaver.readyState = filesaver.DONE;
                                };
                                filesaver.readyState = filesaver.WRITING;
                            }), fs_error);
                        }), fs_error);
                    };
                    dir.getFile(name, {create: false}, abortable(function(file) {
                        // delete file if it already exists
                        file.remove();
                        save();
                    }), abortable(function(ex) {
                        if (ex.code === ex.NOT_FOUND_ERR) {
                            save();
                        } else {
                            fs_error();
                        }
                    }));
                }), fs_error);
            }), fs_error);
        }
        , FS_proto = FileSaver.prototype
        , saveAs = function(blob, name) {
            return new FileSaver(blob, name);
        }
    ;
    FS_proto.abort = function() {
        var filesaver = this;
        filesaver.readyState = filesaver.DONE;
        dispatch(filesaver, "abort");
    };
    FS_proto.readyState = FS_proto.INIT = 0;
    FS_proto.WRITING = 1;
    FS_proto.DONE = 2;
    FS_proto.error =
    FS_proto.onwritestart =
    FS_proto.onprogress =
    FS_proto.onwrite =
    FS_proto.onabort =
    FS_proto.onerror =
    FS_proto.onwriteend =
        null;
    return saveAs;
}(
       typeof self !== "undefined" && self
    || typeof window !== "undefined" && window
    || this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module !== null) {
  module.exports = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
  define([], function() {
    return saveAs;
  });
}
widgets/filyL/Widget.html
New file
@@ -0,0 +1,35 @@
<div>
    <div class="fly-route-header">
        <i></i> 飞行漫游
        <!-- <div class="close-flyrouter"><i class="layui-icon" style="font-size: 20px">&#x1006;</i></div> -->
    </div>
    <div class="fly-route-continer">
        <div class="fly-route-control">
            <select id="flightRoutefilyL"></select>
            <div class="fly-route-control-btn">
                <input type="button" id="ksfilyL" value="开始" />
                <input type="button" id="ztfilyL" value="暂停" />
                <input type="button" id="tzfilyL" value="停止" />
            </div>
        </div>
        <div class="fly-route-new">
            <div class="fly-route-new-top">
                <span class="fly-text-route">定制路线:</span>
                <input id="routeNamefilyL" type="text" placeholder="请输入路线名称" />
            </div>
            <!--<input id="speed" type="text" placeholder="请输入飞行速度"/>m-->
            <div class="fly-route-new-btn">
                <input type="button" id="addfilyL" value="新增途经点" />
                <input type="button" id="exportfilyL" value="保存路线" />
                <input type="button" id="detelefilyL" value="清除路线" />
                <input type="button" id="openViewL" value="开放/固定视角" />
            </div>
            <div>
                <ul id="passPointfilyL"></ul>
            </div>
        </div>
    </div>
    <i class="layui-icon closeOUR">
        &#x1006;
    </i></span>
</div>
widgets/filyL/Widget.js
New file
@@ -0,0 +1,354 @@
define([
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/array',
    'dojo/_base/html',
    'dojo/topic',
    'jimu/BaseWidget',
    './fly',
    './FileSaver'
],
    function (declare,
        lang,
        array,
        html,
        topic,
        BaseWidget
    ) {
        return declare([BaseWidget], {
            baseClass: 'jimu-widget-filyL',
            name: 'filyL',
            flightTool: null,
            allRoutes: null,
            flag: false,
            startup: function () {
                var that = this;
                topic.subscribe("beginfilyL", lang.hitch(this, this.beginfilyL));
                topic.subscribe("closesfilyL", lang.hitch(this, this.closesfilyL));
                // topic.publish('getbeginSlope', that.beginSlope);
                $(`.${that.baseClass}`).find('.closeOUR').click(() => {
                    $(`.${that.baseClass}`).hide();
                    that.closesfilyL();
                })
                // that.beginfilyL();
            },
            beginfilyL: function () {
                console.log(`${this.name}--kaishi`);
                var that = this;
                var viewer = that.map;
                //飞机飞行
                this.flag = true;
                this.init();
            },
            init: function init(evt) {
                var self = this;
                var that = this;
                var viewer = that.map
                    , scene = viewer.scene;
                //实例化飞行工具
                self.flightTool = new Fly_NZC(self.map);
                //获取全部路线数据
                $.ajax({
                    url: "./widgets/filyL/flyroute.json",
                    // http://sw797.com:82/blade-ycreal/flyroute/detail?id=1
                    // type: "POST",
                    dataType: "json",
                    success: function success(data) {
                        if (data.length == undefined) return;
                        // let datas = data.data;
                        self.allRoutes = data;
                        $("#flightRoutefilyL").empty();
                        $('#passPointfilyL').empty();
                        // if (data.code == 200) {
                        for (var i = 0; i < data.length; i++) {
                            $("#flightRoutefilyL").append('<option value = ' + data[i].name + ' > ' + data[i].name + ' </option>');
                        }
                        // }
                        self._loadRoute(self.allRoutes[0].sites);
                        $("#flightRoutefilyL").on("change", function (e) {
                            var selectRoute = self.allRoutes.find(function (x) {
                                return x.name == $("#flightRoutefilyL").val();
                            });
                            self._loadRoute(selectRoute.sites);
                        });
                        //初始加载默认路线
                        //self._loadRoute(self.allRoutes[0].sites);
                    }
                });
                //开始漫游
                $("#ksfilyL").click(function () {
                    self.flightTool.flyManager.play();
                });
                //暂停漫游
                $("#ztfilyL").click(function () {
                    self.flightTool.flyManager.pause();
                });
                //停止漫游
                $("#tzfilyL").click(function () {
                    self.flightTool.flyManager.stop();
                });
                //删除路线
                $("#detelefilyL").click(function () {
                    self.flightTool.RouteCollection.removeAllSites();
                    $("#passPointfilyL").empty();
                });
                //绘制路线
                // var pointHandler = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Point);//添加鼠标点事件
                var dataArr = [],
                    id = 3;
                // pointHandler.drawEvt.addEventListener(function (result) {
                // });
                var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                $("#addfilyL").click(function () {
                    var liStr = "<li class='item'>途径点" + ($("#passPointfilyL").children().length + 1) + "</li>";
                    var liDom = $(liStr);
                    var lat = 0;
                    var lng = 0;
                    var height = 0;
                    // 鼠标移动时间回调
                    handler.setInputAction(function (e) {
                        // 若此标记为false,则激活对可视域分析对象的操作
                        // console.log(e,1213486)
                        //     //获取鼠标屏幕坐标,并将其转化成笛卡尔坐标
                        var position = e.endPosition;
                        var last = scene.pickPosition(position);
                        console.log(position, 'position')
                        // 将鼠标当前点坐标转化成经纬度
                        // var cartographic = Cesium.Cartographic.fromCartesian(last);
                        // lat = Cesium.Math.toDegrees(cartographic.longitude);
                        // lng = Cesium.Math.toDegrees(cartographic.latitude);
                        // height = cartographic.height;
                        var ray = viewer.camera.getPickRay(position);
                        var cartesian = viewer.scene.globe.pick(ray, viewer.scene);
                        // console.log(cartesian, 'cartesian')
                        lat = cartesian.y;
                        lng = cartesian.x;
                        height = cartesian.z;
                    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                    // 鼠标左键时间回调
                    handler.setInputAction(function (e) {
                        var data = {};
                        data.ids = id;
                        data.position_x = lng;
                        data.position_y = lat;
                        data.position_z = height + 10;
                        data.heading = 0;
                        data.pitch = -1;
                        data.roll = 0;
                        // data.heading = 6.108652381980;
                        // data.pitch = -0.653625804871;
                        // data.roll = 0;
                        data.time = 10;
                        dataArr.push(data);
                        // console.log(dataArr, 'dataArr');
                        // console.log(id, 'id')
                        self.flightTool.RouteCollection.AddSite(data);
                        // console.log(id, 'id2')
                        liDom.on('click', data, function (event) {
                            // console.log(event)
                            var site = self.flightTool.RouteCollection.getSiteByIndex(event.data.id);
                            self.flightTool.flyManager.viewToSite(data);
                        });
                        $('#passPointfilyL').append(liDom);
                        self.flightTool.RouteCollection.AddSiteByView(id);
                        id++;
                        handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                    // var liStr = "<li class='item'>途径点" + ($("#passPointfilyL").children().length + 1) + "</li>";
                    // var liDom = $(liStr);
                    // var camera = self.map.scene.camera;
                    // var cartographic = Cesium.Cartographic.fromCartesian(camera.position);
                    // var lat = Cesium.Math.toDegrees(cartographic.latitude);
                    // var lng = Cesium.Math.toDegrees(cartographic.longitude);
                    // var height = cartographic.height;
                    // var data = {};
                    // // data.id = id;
                    // // data.lgtd = lng;
                    // // data.lttd = lat;
                    // // data.height = height;
                    // // data.heading = Cesium.Math.toDegrees(camera.heading);
                    // // data.pitch = Cesium.Math.toDegrees(camera.pitch);
                    // // data.roll = Cesium.Math.toDegrees(camera.roll);
                    // data.id = id;
                    // data.lgtd = lng;
                    // data.lttd = lat;
                    // data.height = height;
                    // data.heading = Cesium.Math.toDegrees(camera.heading);
                    // data.pitch = Cesium.Math.toDegrees(camera.pitch);
                    // data.roll = Cesium.Math.toDegrees(camera.roll);
                    // data.time = null;
                    // dataArr.push(data);
                    // liDom.on('click', data, function (event) {
                    // });
                    // $('#passPointfilyL').append(liDom);
                    // self.flightTool.RouteCollection.AddSiteByView(id);
                    // id++;
                });
                //视角固定
                $("#openViewL").click(function () {
                    self.flightTool.flyManager.openView();
                })
                //导出路线
                $("#exportfilyL").click(function () {
                    for (var i = 0; i < dataArr.length - 1; i++) {
                        var a = Cesium.Cartesian3.fromDegrees(dataArr[i].lgtd, dataArr[i].lttd, dataArr[i].height);
                        var b = Cesium.Cartesian3.fromDegrees(dataArr[i + 1].lgtd, dataArr[i + 1].lttd, dataArr[i + 1].height);
                        var c = self.getSpaceDistance([a, b]);
                        dataArr[i].time = c;
                    }
                    var data = {
                        name: $('#routeNamefilyL').val(),
                        sites: dataArr
                    };
                    var content = JSON.stringify(data);
                    var blob = new Blob([content], {
                        type: "text/plain;charset=utf-8"
                    });
                    saveAs(blob, "save.json");
                    dataArr = [];
                });
                topic.subscribe("autoRoam", lang.hitch(this, this._executeRoam));
                topic.subscribe("stopflay", lang.hitch(this, this._stopFlay));
            },
            closesfilyL: function (froms) {
                console.log(`${this.name}--guanbi`);
                // var that = this;
                var self = this;
                if (item == this.name && this.flag == true) {
                    this.flag = false;
                    // $('.jimu-widget-filyL').hide();
                    // $('.jimu-widget-visualAngle .v-a-One').addClass('on').siblings().removeClass('on');
                    self.flightTool.flyManager.stop();
                    self.flightTool.RouteCollection.removeAllSites();
                }
            },
            //空间两点距离计算函数
            getSpaceDistance: function getSpaceDistance(positions) {
                var distance = 0;
                for (var i = 0; i < positions.length - 1; i++) {
                    var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
                    var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
                    /**根据经纬度计算出距离**/
                    var geodesic = new Cesium.EllipsoidGeodesic();
                    geodesic.setEndPoints(point1cartographic, point2cartographic);
                    var s = geodesic.surfaceDistance;
                    //返回两点之间的距离
                    s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
                    distance = distance + s;
                }
                return (distance / 70);
            },
            _executeRoam: function _executeRoam(data) {
                this.flightTool.flyManager.stop();
                this.flightTool.RouteCollection.removeAllSites();
                var selectRoute = this.allRoutes.find(function (x) {
                    return x.name == data;
                });
                for (var i = 0; i < selectRoute.sites.length; i++) {
                    var cartesian3 = Cesium.Cartesian3.fromDegrees(selectRoute.sites[i].lgtd, selectRoute.sites[i].lttd, selectRoute.sites[i].height);
                    var site = {
                        "ids": selectRoute.sites[i].id,
                        "position_x": cartesian3.x,
                        "position_y": cartesian3.y,
                        "position_z": cartesian3.z,
                        "pitch": Cesium.Math.toRadians(selectRoute.sites[i].pitch),
                        "heading": Cesium.Math.toRadians(selectRoute.sites[i].heading),
                        "roll": Cesium.Math.toRadians(selectRoute.sites[i].roll),
                        "time": selectRoute.sites[i].time
                    };
                    this.flightTool.allSites[i] = site;
                }
                this.flightTool.flyManager.play();
            },
            _stopFlay: function _stopFlay(data) {
                if (data) {
                    this.flightTool.flyManager.stop();
                    this.flightTool.RouteCollection.removeAllSites();
                }
            },
            _loadRoute: function _loadRoute(route) {
                console.log(route)
                var self = this;
                $("#passPointfilyL").empty();
                self.flightTool.RouteCollection.AddRoute(route);
                for (var j = 0; j < route.length; j++) {
                    var liStr = "<li class='item'>q途径点" + (j + 1) + "</li>";
                    var liDom = $(liStr);
                    liDom.on('click', route[j], function (event) {
                        var site = self.flightTool.RouteCollection.getSiteByIndex(event.data.id);
                        self.flightTool.flyManager.viewToSite(site);
                    });
                    $('#passPointfilyL').append(liDom);
                }
            },
            onOpen: function () {
            },
            onClose: function () {
                //面板关闭的时候触发 (when this panel is closed trigger)
                console.log('jies')
            },
            onMinimize: function () {
                this.resize();
            },
            onMaximize: function () {
                this.resize();
            },
            resize: function () {
            },
            destroy: function () {
                //销毁的时候触发
                //todo
                //do something before this func
                this.inherited(arguments);
            }
        });
    });
widgets/filyL/css/a.css
New file
@@ -0,0 +1,160 @@
.jimu-widget-FlyRoute {
    width: 100%;
    height: 100%;
    overflow-x: hidden;
    background-color: rgba(255, 255, 255, 0.8);
    display: none;
    font-size: 14px;
    border: 1px solid rgb(212, 212, 212);
    border-radius: 5px;
    color: rgb(0, 0, 0);
    z-index: 9 !important;
}
/* 头部 */
.jimu-widget-FlyRoute .fly-route-header {
    position: relative;
    width: 100%;
    height: 40px;
    line-height: 40px;
    font-size: 20px;
    border-bottom: 1px solid rgb(184, 184, 184);
}
.jimu-widget-FlyRoute .fly-route-header i {
    display: inline-block;
    margin-left: 6px;
    vertical-align: middle;
    width: 20px;
    height: 20px;
    background: url(../../../images/toolbox.png ) no-repeat 0 -176px;
    background-size: 20px;
}
.jimu-widget-FlyRoute .fly-route-header .close-flyrouter {
    position: absolute;
    top: 50%;
    right: 8px;
    font-size: 38px;
    font-weight: 400;
    height: 28px;
    line-height: 18px;
    /* display: flex;
    align-items: center;
    justify-content: center; */
    cursor: pointer;
    transform: translateY(-50%);
}
.jimu-widget-FlyRoute input,
.jimu-widget-FlyRoute select {
    border: 0;
}
.jimu-widget-FlyRoute .fly-route-continer {
    /* margin: 10px 8px; */
    position: absolute;
    top: 51px;
    left: 10px;
    right: 10px;
    bottom: 10px;
}
/* 选择框,或者说选择飞行路线 */
.jimu-widget-FlyRoute .fly-route-control #flightRoute {
    width: 100%;
    height: 30px;
}
/* 控制按钮 */
.jimu-widget-FlyRoute .fly-route-continer .fly-route-control-btn,
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new-btn {
    margin-top: 10px;
    width: 100%;
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-control-btn input,
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new-btn input {
    margin: 0 1%;
    width: 30%;
    height: 30px;
    color: #fff;
    background: rgb(62, 159, 252);
    border: 1px solid rgb(69, 154, 251);
    border-radius: 4px;
    cursor: pointer;
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new {
    position: absolute;
    top: 80px;
    bottom: 0px;
    width: 100%;
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new-top {
    height: 24px;
    line-height: 24px;
    font-size: 16px;
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new-top span {
    margin: 0;
    display: inline-block;
    width: 80px;
    /* height: 16px !important; */
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new-top input {
    margin: 0;
    width: 150px;
    height: 24px;
    vertical-align: top;
    border: none;
}
.jimu-widget-FlyRoute .fly-route-continer .fly-route-new>div:nth-child(3) {
    position: absolute;
    top: 64px;
    left: 0;
    bottom: 0;
    width: 100%;
    height: auto;
}
.jimu-widget-FlyRoute #passPoint,
.jimu-widget-FlyRoute #passPoint li {
    margin: 0;
    padding: 0;
}
.jimu-widget-FlyRoute #passPoint {
    height: 100%;
    list-style: none;
    overflow: auto;
}
.jimu-widget-FlyRoute #passPoint li {
    margin: 10px 40px;
}
.jimu-widget-FlyRoute .item {
    background: #3E9FFC;
    border-radius: 5px;
    height: 20px;
    padding-left: 5px;
    color: white;
    font-family: "微软雅黑";
    text-align: center;
    margin-bottom: 5px;
    cursor: pointer;
}
.jimu-widget-FlyRoute .item:nth-child(1) {
    margin-top: 20px !important;
}
widgets/filyL/css/style.css
New file
@@ -0,0 +1,188 @@
@import url(./a.css);
.jimu-widget-filyL {
  position: fixed !important;
  top: 72px !important;
  right: 388px !important;
  width: 300px !important;
  height: 600px !important;
  background-color: rgb(255, 255, 255);
  font-size: 14px;
  color: rgb(0, 0, 0);
  z-index: 12 !important;
  border-radius: 10px;
  display: none;
  box-shadow: 0 0 8px #fff;
  padding: 0px 5px !important;
}
.jimu-widget-filyL .closeOUR {
  position: absolute;
  right: 5px;
  top: 5px;
  font-size: 18px;
  cursor: pointer;
}
.jimu-widget-filyL .closeOUR:hover {
  color: red;
}
/* .jimu-widget-filyL .but {
  line-height: 30px;
  width: 80px;
  height: 30px;
  font-size: 14px;
  border-radius: 5px;
  box-shadow: 2px 2px 15px -5px #378ef1;
   border: 1px solid transparent;
  background-color: #fff;
}
.jimu-widget-filyL .but:hover {
  box-shadow: 2px 2px 25px -5px #1679eb;
} */
/* 头部 */
.jimu-widget-filyL .fly-route-header {
  position: relative;
  width: 100%;
  height: 40px;
  line-height: 40px;
  font-size: 20px;
  border-bottom: 1px solid rgb(184, 184, 184);
}
.jimu-widget-filyL .fly-route-header i {
  display: inline-block;
  margin-left: 6px;
  vertical-align: middle;
  width: 20px;
  height: 20px;
  background: url(../../../images/toolbox.png ) no-repeat 0 -176px;
  background-size: 20px;
}
.jimu-widget-filyL .fly-route-header .close-flyrouter {
  position: absolute;
  top: 50%;
  right: 8px;
  font-size: 38px;
  font-weight: 400;
  height: 28px;
  line-height: 18px;
  /* display: flex;
align-items: center;
justify-content: center; */
  cursor: pointer;
  transform: translateY(-50%);
}
.jimu-widget-filyL input, .jimu-widget-filyL select {
  border: 0;
}
.jimu-widget-filyL .fly-route-continer {
  /* margin: 10px 8px; */
  position: absolute;
  top: 51px;
  left: 10px;
  right: 10px;
  bottom: 10px;
}
/* 选择框,或者说选择飞行路线 */
.jimu-widget-filyL .fly-route-control #flightRoute {
  width: 100%;
  height: 30px;
}
/* 控制按钮 */
.jimu-widget-filyL .fly-route-continer .fly-route-control-btn, .jimu-widget-filyL .fly-route-continer .fly-route-new-btn {
  margin-top: 10px;
  width: 100%;
}
.jimu-widget-filyL .fly-route-continer .fly-route-control-btn input, .jimu-widget-filyL .fly-route-continer .fly-route-new-btn input {
  margin: 0 1%;
  /* width: 20%; */
  height: 30px;
  color: #fff;
  background: rgb(62, 159, 252);
  border: 1px solid rgb(69, 154, 251);
  border-radius: 4px;
  cursor: pointer;
  padding: 0 5px;
}
.jimu-widget-filyL .fly-route-continer .fly-route-new {
  position: absolute;
  top: 80px;
  bottom: 0px;
  width: 100%;
}
.jimu-widget-filyL #openViewL{
  position:relative;
  top: 5px;
}
.jimu-widget-filyL .fly-route-continer .fly-route-new-top {
  height: 24px;
  line-height: 24px;
  font-size: 16px;
}
.jimu-widget-filyL .fly-route-continer .fly-route-new-top span {
  margin: 0;
  display: inline-block;
  width: 80px;
  /* height: 16px !important; */
}
.jimu-widget-filyL .fly-route-continer .fly-route-new-top input {
  margin: 0;
  width: 150px;
  height: 24px;
  vertical-align: top;
  border: none;
}
.jimu-widget-filyL .fly-route-continer .fly-route-new>div:nth-child(3) {
  position: absolute;
  top: 90px;
  left: 0;
  bottom: 0;
  width: 100%;
  height: auto;
}
.jimu-widget-filyL #passPoint, .jimu-widget-filyL #passPoint li {
  margin: 0;
  padding: 0;
}
.jimu-widget-filyL #passPoint {
  height: 100%;
  list-style: none;
  overflow: auto;
}
.jimu-widget-filyL #passPoint li {
  margin: 10px 40px;
}
.jimu-widget-filyL .item {
  background: #3E9FFC;
  border-radius: 5px;
  height: 20px;
  padding-left: 5px;
  color: white;
  font-family: "微软雅黑";
  text-align: center;
  margin-bottom: 5px;
  cursor: pointer;
}
.jimu-widget-filyL .item:nth-child(1) {
  margin-top: 20px !important;
}
widgets/filyL/fly.js
New file
@@ -0,0 +1,529 @@
function newSite(x, y, z, h, p, time, ids) {
    if (x != null && y != null && z != null && h != null && p != null && time != null && ids != null) {
        this.position_x = x;
        this.position_y = y;
        this.position_z = z;
        this.pitch = p;
        this.heading = h;
        this.time = time;
        this.ids = ids;
    } else {
        return false;
    }
}
function Fly_NZC(viewer) {
    this.viewer = viewer;
    this.scene = viewer.scene;
    this.entities = viewer.entities;
    //全部飞行站点数组
    this.allSites = [];
    var that = this;
    this.checkIds = function (ids) {
        console.log(ids, 'cids')
        console.log(that.allSites, 'that.allSites')
        for (var i = 0; i < that.allSites.length + 1; i++) {
            if (i == that.allSites.length) {
                console.log(i, 'endcids')
                return false;
                break;
            }
            if (that.allSites[i].ids == ids) {
                console.log(i, 'havecids')
                return i;
                break;
            }
        }
        // img_path
    };
    this.RouteCollection = {
        //线颜色
        //LineColor:Cesium.Color.WHITE,
        //站点和路线显隐是否开启
        point_show: true,
        line_show: true,
        //站点图片路径
        img_path: "widgets/FlyRoute/images/location4.png",
        //飞行路线颜色
        /* setLineColor:function(){
              Cesium.Color.WHITE,
         },*/
        AddRoute: function (Route) {
            this.deleteEntities();
            that.allSites = [];
            for (var i = 0; i < Route.length; i++) {
                let cartesian3 = Cesium.Cartesian3.fromDegrees(Route[i].lgtd, Route[i].lttd, Route[i].height);
                let site = {
                    "ids": Route[i].id,
                    "position_x": cartesian3.x,
                    "position_y": cartesian3.y,
                    "position_z": cartesian3.z,
                    "pitch": Cesium.Math.toRadians(Route[i].pitch),
                    "heading": Cesium.Math.toRadians(Route[i].heading),
                    "roll": Cesium.Math.toRadians(Route[i].roll),
                    "time": Route[i].time
                };
                that.allSites[i] = site;
            }
            this.controlEntities();
        },
        //设置点图片
        setPointImg: function (path) {
            this.img_path = path;
            this.controlEntities();
        },
        //mod=0为设置点的可见,1为设置线的可见,2为控制点和线的可见
        setVisible: function (mod, bool) {
            if (mod === 0) {
                this.point_show = bool;
            }
            if (mod === 1) {
                this.line_show = bool;
            }
            if (mod === 2) {
                this.point_show = bool;
                this.line_show = bool;
            }
            this.controlEntities();
        },
        //通过传入站点类添加站点
        AddSite: function (newSite) {
            //判断id是否重复
            console.log(newSite.ids)
            var bool = that.checkIds(newSite.ids);
            if (bool) {
                return false;
            } else {
                var Site = {};
                Site.position_x = newSite.position_x;
                Site.position_y = newSite.position_y;
                Site.position_z = newSite.position_z;
                Site.heading = newSite.heading;
                Site.pitch = newSite.pitch;
                //Site.roll=camera.roll;
                Site.time = newSite.time;
                Site.ids = newSite.ids;
                that.allSites.push(Site);
                this.controlEntities();
                console.log(that.allSites, '444f')
                return true;
            }
        },
        //添加当前视角为站点需要传入id
        AddSiteByView: function (ids) {
            //判断id是否重复
            console.log(ids, 'ids')
            var bool = that.checkIds(ids);
            if (bool) {
                return false;
            } else {
                try {
                    var position = that.scene.camera.position;
                    //获取当前相机位置参数(飞行用)
                    var Site = {};
                    Site.position_x = position.x;
                    Site.position_y = position.y;
                    Site.position_z = position.z;
                    Site.heading = that.scene.camera.heading;
                    Site.pitch = that.scene.camera.pitch;
                    Site.roll = that.scene.camera.roll;
                    Site.time = 3;
                    Site.ids = ids;
                    //添加到站点数组
                    // that.allSites.push(Site);
                    this.controlEntities();
                    return true;
                } catch (e) {
                    return false;
                }
            }
        },
        //根据索引获取站点信息
        getSiteByIndex: function (index) {
            console.log(that.allSites[index], 'site.index');
            return that.allSites[index];
        },
        deleteEntities: function () {
            //50000+为线id
            for (var i = 0; i < that.allSites.length; i++) {
                that.entities.removeById(that.allSites[i].ids);
            }
            for (var i = 1; i < 500000; i++) {
                var ids = parseInt(50000 + i);
                var entities_del = that.entities.getById(ids);
                if (entities_del) {
                    that.entities.remove(entities_del);
                } else {
                    break;
                }
            }
        },
        controlEntities: function () {
            var position_1, position_2, x1, x2, y1, y2, z1, z2, point_1_cartographic, point_2_cartographic;
            //添加和删除站点,更改颜色或图片后,先清空entities,然后重新添加。
            this.deleteEntities();
            //添加显示的站点
            var length = that.allSites.length;
            if (this.point_show == true) {
                for (var j = 0; j < length; j++) {
                    that.entities.add({
                        position: new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z),
                        billboard: {
                            image: this.img_path,
                            width: 30,
                            height: 40,
                        },
                        //name : 10000+j,
                        id: that.allSites[j].ids
                    });
                }
            }
            //添加显示的线
            if (this.line_show == true) {
                for (var j = 1; j < length; j++) {
                    //将笛卡尔坐标转为经纬度坐标,用于绘制线
                    position_1 = new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z)
                    point_1_cartographic = Cesium.Cartographic.fromCartesian(position_1);
                    console.log(position_1, '555f')
                    x1 = Cesium.Math.toDegrees(point_1_cartographic.longitude);
                    y1 = Cesium.Math.toDegrees(point_1_cartographic.latitude);
                    z1 = point_1_cartographic.height;
                    position_2 = new Cesium.Cartesian3(that.allSites[j - 1].position_x, that.allSites[j - 1].position_y, that.allSites[j - 1].position_z)
                    point_2_cartographic = Cesium.Cartographic.fromCartesian(position_2);
                    x2 = Cesium.Math.toDegrees(point_2_cartographic.longitude);
                    y2 = Cesium.Math.toDegrees(point_2_cartographic.latitude);
                    z2 = point_2_cartographic.height;
                    that.entities.add({
                        id: 50000 + j,
                        // name : drowallStops.length,
                        polyline: {
                            positions: Cesium.Cartesian3.fromDegreesArrayHeights([x1, y1, z1, x2, y2, z2]),
                            width: 5,
                            material: Cesium.Color.WHITE
                        }
                    });
                }
            }
            //如果关闭显示了站点和飞行路线,添加的新站点和飞行路线将先不显示
            if (this.line_show == false) {
                for (var j = 1; j < length; j++) {
                    //将笛卡尔坐标转为经纬度坐标,用于绘制线
                    position_1 = new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z)
                    point_1_cartographic = Cesium.Cartographic.fromCartesian(position_1);
                    x1 = Cesium.Math.toDegrees(point_1_cartographic.longitude);
                    y1 = Cesium.Math.toDegrees(point_1_cartographic.latitude);
                    z1 = point_1_cartographic.height;
                    position_2 = new Cesium.Cartesian3(that.allSites[j - 1].position_x, that.allSites[j - 1].position_y, that.allSites[j - 1].position_z)
                    point_2_cartographic = Cesium.Cartographic.fromCartesian(position_2);
                    x2 = Cesium.Math.toDegrees(point_2_cartographic.longitude);
                    y2 = Cesium.Math.toDegrees(point_2_cartographic.latitude);
                    z2 = point_2_cartographic.height;
                    that.entities.add({
                        id: 50000 + j,
                        show: false,
                        // name : drowallStops.length,
                        polyline: {
                            positions: Cesium.Cartesian3.fromDegreesArrayHeights([x1, y1, z1, x2, y2, z2]),
                            width: 5,
                            material: Cesium.Color.WHITE
                        }
                    });
                }
            }
            if (this.point_show == false) {
                for (var j = 0; j < length; j++) {
                    that.entities.add({
                        position: new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z),
                        billboard: {
                            image: this.img_path,
                            width: 30,
                            height: 40,
                        },
                        show: false,
                        //name : 10000+j,
                        id: that.allSites[j].ids
                    });
                }
            }
        },
        removeAllSites: function () {
            this.deleteEntities();
            that.allSites = [];
        },
        removeSiteById: function (ids) {
            var id = that.checkIds(ids)
            if (id) {
                this.deleteEntities();
                that.allSites.splice(id, 1);
                this.controlEntities();
            } else {
                return false
            }
        }
    };
    this.l = 0;
    this.b = 0;
    //用于判断执行的时暂停还是停止
    this.play_bool = true;
    var x, y, z, p, h;
    this.setInterval_fly = null;
    this.setcamera = function () {
        //设置俯仰角
        var set = that.allSites[that.l].time * 50
        that.viewer.camera.setView({
            orientation: {
                heading: viewer.scene.camera.heading + h / set,
                pitch: viewer.scene.camera.pitch + p / set,
                roll: 0.0
            }
        });
        //move移动相机
        that.viewer.camera.move(new Cesium.Cartesian3(x, y, z), 1 / set);
        that.b--;
        if (that.b <= 0) {
            that.l++;
            clearInterval(that.setInterval_fly);
            that.setInterval_fly = null;
            that.Interval();
            // that.b=0;
        }
    };
    this.Interval = function () {
        var l = that.l;
        if (that.play_bool) {
            that.b = that.allSites[l].time * 50
        } else {
            that.play_bool = true;
        }
        if (that.allSites[l + 1]) {
            x = that.allSites[l + 1].position_x - that.allSites[l].position_x;
            y = that.allSites[l + 1].position_y - that.allSites[l].position_y;
            z = that.allSites[l + 1].position_z - that.allSites[l].position_z;
            p = that.allSites[l + 1].pitch - that.allSites[l].pitch;
            h = that.allSites[l + 1].heading - that.allSites[l].heading;
            var tem = Cesium.Math.toDegrees(that.allSites[l + 1].heading) - Cesium.Math.toDegrees(that.allSites[l].heading);
            if (Math.abs(tem) > 180) {
                if (tem >= 0) {
                    tem = 360 - tem;
                } else {
                    tem = 360 + tem;
                }
                h = Cesium.Math.toRadians(tem);
            }
            //that.b=that.allSites[l].time*20
            that.setInterval_fly = setInterval(that.setcamera, 12);
        } else {
            that.play_bool = true;
            that.l = 0;
            that.scene.screenSpaceCameraController.enableRotate = true;
            that.scene.screenSpaceCameraController.enableTranslate = true;
            that.scene.screenSpaceCameraController.enableZoom = true;
            that.scene.screenSpaceCameraController.enableTilt = true;
            that.scene.screenSpaceCameraController.enableLook = true;
        }
    };
    this.flyManager = {
        img_path: "widgets/FlyRoute/images/location4.png",
        //用于储存暂停时的位置
        Site_pause: {},
        actives: false,
        isguding: false,
        openView: function () {
            if (this.actives == true) {
                console.log('视角改变');
                that.scene.screenSpaceCameraController.enableRotate = false;
                that.scene.screenSpaceCameraController.enableTranslate = false;
                that.scene.screenSpaceCameraController.enableZoom = false;
                that.scene.screenSpaceCameraController.enableTilt = false;
                that.scene.screenSpaceCameraController.enableLook = false;
                // that.scene.screenSpaceCameraController.enableRotate = true;
                // that.scene.screenSpaceCameraController.enableTranslate = true;
                // that.scene.screenSpaceCameraController.enableZoom = true;
                that.scene.screenSpaceCameraController.enableTilt = true;
                // that.scene.screenSpaceCameraController.enableLook = true;
                if (this.isguding == true) {
                    that.scene.screenSpaceCameraController.enableRotate = false;
                    that.scene.screenSpaceCameraController.enableTranslate = false;
                    that.scene.screenSpaceCameraController.enableZoom = false;
                    that.scene.screenSpaceCameraController.enableTilt = false;
                    that.scene.screenSpaceCameraController.enableLook = false;
                }
                this.isguding = !this.isguding;
            } else {
                console.log('未开始飞行');
            }
        },
        play: function () {
            this.actives = true;
            for (var i = 0; i < that.allSites.length; i++) {
                that.entities.removeById(that.allSites[i].ids);
            }
            //如果之前点的时停止重新开始飞行
            if (that.allSites.length > 1) {
                that.scene.screenSpaceCameraController.enableRotate = false;
                that.scene.screenSpaceCameraController.enableTranslate = false;
                that.scene.screenSpaceCameraController.enableZoom = false;
                that.scene.screenSpaceCameraController.enableTilt = false;
                that.scene.screenSpaceCameraController.enableLook = false;
                if (that.play_bool) {
                    //设置初始点
                    that.scene.camera.setView({
                        destination: new Cesium.Cartesian3(that.allSites[that.l].position_x, that.allSites[that.l].position_y, that.allSites[that.l].position_z),
                        orientation: {
                            heading: that.allSites[that.l].heading,
                            pitch: that.allSites[that.l].pitch,
                            roll: that.allSites[that.l].roll
                        }
                    });
                    if (that.setInterval_fly) {
                        clearInterval(that.setInterval_fly);
                    }
                    that.Interval();
                } else {
                    //如果之前是暂停,继续飞行
                    that.scene.camera.setView({
                        //将经度、纬度、高度的坐标转换为笛卡尔坐标
                        destination: new Cesium.Cartesian3(this.Site_pause.position_x, this.Site_pause.position_y, this.Site_pause.position_z),
                        orientation: {
                            heading: this.Site_pause.heading,
                            pitch: this.Site_pause.pitch,
                            roll: this.Site_pause.roll
                        }
                    });
                    that.Interval();
                }
            }
        },
        stop: function () {
            //添加显示的站点
            this.actives = false;
            var length = that.allSites.length;
            for (var j = 0; j < length; j++) {
                var flag = false;
                for (var i = 0; i < that.entities.values.length; i++) {
                    if (that.allSites[j].ids == that.entities.values[i].id) {
                        flag = true
                    }
                }
                if (flag == false) {
                    that.entities.add({
                        position: new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z),
                        billboard: {
                            image: this.img_path,
                            width: 30,
                            height: 40,
                        },
                        //name : 10000+j,
                        id: that.allSites[j].ids
                    });
                }
            }
            if (that.setInterval_fly != null) {
                clearInterval(that.setInterval_fly);
                that.setInterval_fly = null;
            }
            that.l = 0;
            that.play_bool = true;
            that.scene.screenSpaceCameraController.enableRotate = true;
            that.scene.screenSpaceCameraController.enableTranslate = true;
            that.scene.screenSpaceCameraController.enableZoom = true;
            that.scene.screenSpaceCameraController.enableTilt = true;
            that.scene.screenSpaceCameraController.enableLook = true;
        },
        pause: function () {
            actives = false;
            //添加显示的站点
            var length = that.allSites.length;
            for (var j = 0; j < length; j++) {
                var flag = false;
                for (var i = 0; i < that.entities.values.length; i++) {
                    if (that.allSites[j].ids == that.entities.values[i].id) {
                        flag = true
                    }
                }
                if (flag == false) {
                    that.entities.add({
                        position: new Cesium.Cartesian3(that.allSites[j].position_x, that.allSites[j].position_y, that.allSites[j].position_z),
                        billboard: {
                            image: this.img_path,
                            width: 30,
                            height: 40,
                        },
                        //name : 10000+j,
                        id: that.allSites[j].ids
                    });
                }
            }
            if (that.setInterval_fly != null) {
                clearInterval(that.setInterval_fly);
                that.setInterval_fly = null;
                that.play_bool = false;
            }
            //获取暂停时的camera数据
            var position = that.scene.camera.position;
            this.Site_pause.position_x = position.x;
            this.Site_pause.position_y = position.y;
            this.Site_pause.position_z = position.z;
            this.Site_pause.heading = that.scene.camera.heading;
            this.Site_pause.pitch = that.scene.camera.pitch;
            this.Site_pause.roll = that.scene.camera.roll;
            that.scene.screenSpaceCameraController.enableRotate = true;
            that.scene.screenSpaceCameraController.enableTranslate = true;
            that.scene.screenSpaceCameraController.enableZoom = true;
            that.scene.screenSpaceCameraController.enableTilt = true;
            that.scene.screenSpaceCameraController.enableLook = true;
        },
        SetStartSite: function (ids) {
            var bool = that.checkIds(ids);
            if (bool) {
                that.l = bool;
                return true;
            } else {
                return false;
            }
        },
        viewToSite: function (site) {
            console.log(site, 'viewto')
            that.scene.camera.setView({
                destination: new Cesium.Cartesian3(site.position_x - 1000, site.position_y + 2000, site.position_z),
                orientation: {
                    heading: site.heading,
                    pitch: site.pitch,
                    roll: site.roll
                }
            });
        }
    };
}
widgets/filyL/flyroute.json
New file
@@ -0,0 +1,55 @@
[
    {
        "name": "鄱阳湖国家级保护区倾斜飞行路线1",
        "sites": [{
            "id": 0,
            "lgtd": 115.749088,
            "lttd": 28.674319,
            "height": 12179.32,
            "heading": 338.02,
            "pitch": -70.89,
            "roll": 0,
            "time": 10
        }, {
            "id": 1,
            "lgtd": 115.741067,
            "lttd": 28.695646,
            "height": 3236.37,
            "heading": 338.02,
            "pitch": -70.86,
            "roll": 0,
            "time": 10
        }, {
            "id": 2,
            "lgtd": 115.738726,
            "lttd": 28.702285,
            "height": 330.00,
            "heading": 350.00,
            "pitch": -37.45,
            "roll": 0,
            "time": 0
        }]
    },
    {
        "name": "鄱阳湖国家级保护区倾斜飞行路线2",
        "sites": [{
            "id": 0,
            "lgtd": 115.960852,
            "lttd": 29.164005,
            "height": 1497.76,
            "heading": 87.75,
            "pitch": -41.49,
            "roll": 0,
            "time": 16
        }, {
            "id": 1,
            "lgtd": 116.010312,
            "lttd": 29.187787,
            "height": 140.39,
            "heading": 88.07,
            "pitch": -24.73,
            "roll": 0,
            "time": 0
        }]
    }
]
widgets/filyL/js/DrawHelper.js
New file
@@ -0,0 +1,1874 @@
/**
 * Created by thomas on 9/01/14.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * (c) www.geocento.com
 * www.metaaps.com
 *
 */
var DrawHelper = (function () {
    // static variables
    var ellipsoid = Cesium.Ellipsoid.WGS84;
    // constructor
    function _(cesiumWidget) {
        this._scene = cesiumWidget.scene;
        this._tooltip = createTooltip(cesiumWidget.container);
        this._surfaces = [];
        this.initialiseHandlers();
        this.enhancePrimitives();
    }
    _.prototype.initialiseHandlers = function () {
        var scene = this._scene;
        var _self = this;
        // scene events
        var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        function callPrimitiveCallback(name, position) {
            if (_self._handlersMuted == true) return;
            var pickedObject = scene.pick(position);
            if (pickedObject && pickedObject.primitive && pickedObject.primitive[name]) {
                pickedObject.primitive[name](position);
            }
        }
        handler.setInputAction(
            function (movement) {
                callPrimitiveCallback('leftClick', movement.position);
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.setInputAction(
            function (movement) {
                callPrimitiveCallback('leftDoubleClick', movement.position);
            }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        var mouseOutObject;
        handler.setInputAction(
            function (movement) {
                if (_self._handlersMuted == true) return;
                var pickedObject = scene.pick(movement.endPosition);
                if (mouseOutObject && (!pickedObject || mouseOutObject != pickedObject.primitive)) {
                    !(mouseOutObject.isDestroyed && mouseOutObject.isDestroyed()) && mouseOutObject.mouseOut(movement.endPosition);
                    mouseOutObject = null;
                }
                if (pickedObject && pickedObject.primitive) {
                    pickedObject = pickedObject.primitive;
                    if (pickedObject.mouseOut) {
                        mouseOutObject = pickedObject;
                    }
                    if (pickedObject.mouseMove) {
                        pickedObject.mouseMove(movement.endPosition);
                    }
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        handler.setInputAction(
            function (movement) {
                callPrimitiveCallback('leftUp', movement.position);
            }, Cesium.ScreenSpaceEventType.LEFT_UP);
        handler.setInputAction(
            function (movement) {
                callPrimitiveCallback('leftDown', movement.position);
            }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
    }
    _.prototype.setListener = function (primitive, type, callback) {
        primitive[type] = callback;
    }
    _.prototype.muteHandlers = function (muted) {
        this._handlersMuted = muted;
    }
    // register event handling for an editable shape
    // shape should implement setEditMode and setHighlighted
    _.prototype.registerEditableShape = function (surface) {
        var _self = this;
        // handlers for interactions
        // highlight polygon when mouse is entering
        setListener(surface, 'mouseMove', function (position) {
            surface.setHighlighted(true);
            if (!surface._editMode) {
                _self._tooltip.showAt(position, "Click to edit this shape");
            }
        });
        // hide the highlighting when mouse is leaving the polygon
        setListener(surface, 'mouseOut', function (position) {
            surface.setHighlighted(false);
            _self._tooltip.setVisible(false);
        });
        setListener(surface, 'leftClick', function (position) {
            surface.setEditMode(true);
        });
    }
    _.prototype.startDrawing = function (cleanUp) {
        // undo any current edit of shapes
        this.disableAllEditMode();
        // check for cleanUp first
        if (this.editCleanUp) {
            this.editCleanUp();
        }
        this.editCleanUp = cleanUp;
        this.muteHandlers(true);
    }
    _.prototype.stopDrawing = function () {
        // check for cleanUp first
        if (this.editCleanUp) {
            this.editCleanUp();
            this.editCleanUp = null;
        }
        this.muteHandlers(false);
    }
    // make sure only one shape is highlighted at a time
    _.prototype.disableAllHighlights = function () {
        this.setHighlighted(undefined);
    }
    _.prototype.setHighlighted = function (surface) {
        if (this._highlightedSurface && !this._highlightedSurface.isDestroyed() && this._highlightedSurface != surface) {
            this._highlightedSurface.setHighlighted(false);
        }
        this._highlightedSurface = surface;
    }
    _.prototype.disableAllEditMode = function () {
        this.setEdited(undefined);
    }
    _.prototype.setEdited = function (surface) {
        if (this._editedSurface && !this._editedSurface.isDestroyed()) {
            this._editedSurface.setEditMode(false);
        }
        this._editedSurface = surface;
    }
    var material = Cesium.Material.fromType(Cesium.Material.ColorType);
    material.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 0.5);
    var defaultShapeOptions = {
        ellipsoid: Cesium.Ellipsoid.WGS84,
        textureRotationAngle: 0.0,
        height: 0.0,
        asynchronous: true,
        show: true,
        debugShowBoundingVolume: false
    }
    var defaultSurfaceOptions = copyOptions(defaultShapeOptions, {
        appearance: new Cesium.EllipsoidSurfaceAppearance({
            aboveGround: false
        }),
        material: material,
        granularity: Math.PI / 180.0
    });
    var defaultPolygonOptions = copyOptions(defaultShapeOptions, {});
    var defaultExtentOptions = copyOptions(defaultShapeOptions, {});
    var defaultCircleOptions = copyOptions(defaultShapeOptions, {});
    var defaultEllipseOptions = copyOptions(defaultSurfaceOptions, { rotation: 0 });
    var defaultPolylineOptions = copyOptions(defaultShapeOptions, {
        width: 5,
        geodesic: true,
        granularity: 10000,
        appearance: new Cesium.PolylineMaterialAppearance({
            aboveGround: false
        }),
        material: material
    });
    //    Cesium.Polygon.prototype.setStrokeStyle = setStrokeStyle;
    //
    //    Cesium.Polygon.prototype.drawOutline = drawOutline;
    //
    var ChangeablePrimitive = (function () {
        function _() {
        }
        _.prototype.initialiseOptions = function (options) {
            fillOptions(this, options);
            this._ellipsoid = undefined;
            this._granularity = undefined;
            this._height = undefined;
            this._textureRotationAngle = undefined;
            this._id = undefined;
            // set the flags to initiate a first drawing
            this._createPrimitive = true;
            this._primitive = undefined;
            this._outlinePolygon = undefined;
        }
        _.prototype.setAttribute = function (name, value) {
            this[name] = value;
            this._createPrimitive = true;
        };
        _.prototype.getAttribute = function (name) {
            return this[name];
        };
        /**
         * @private
         */
        _.prototype.update = function (context, frameState, commandList) {
            if (!Cesium.defined(this.ellipsoid)) {
                throw new Cesium.DeveloperError('this.ellipsoid must be defined.');
            }
            if (!Cesium.defined(this.appearance)) {
                throw new Cesium.DeveloperError('this.material must be defined.');
            }
            if (this.granularity < 0.0) {
                throw new Cesium.DeveloperError('this.granularity and scene2D/scene3D overrides must be greater than zero.');
            }
            if (!this.show) {
                return;
            }
            if (!this._createPrimitive && (!Cesium.defined(this._primitive))) {
                // No positions/hierarchy to draw
                return;
            }
            if (this._createPrimitive ||
                (this._ellipsoid !== this.ellipsoid) ||
                (this._granularity !== this.granularity) ||
                (this._height !== this.height) ||
                (this._textureRotationAngle !== this.textureRotationAngle) ||
                (this._id !== this.id)) {
                var geometry = this.getGeometry();
                if (!geometry) {
                    return;
                }
                this._createPrimitive = false;
                this._ellipsoid = this.ellipsoid;
                this._granularity = this.granularity;
                this._height = this.height;
                this._textureRotationAngle = this.textureRotationAngle;
                this._id = this.id;
                this._primitive = this._primitive && this._primitive.destroy();
                this._primitive = new Cesium.Primitive({
                    geometryInstances: new Cesium.GeometryInstance({
                        geometry: geometry,
                        id: this.id,
                        pickPrimitive: this
                    }),
                    appearance: this.appearance,
                    asynchronous: this.asynchronous
                });
                this._outlinePolygon = this._outlinePolygon && this._outlinePolygon.destroy();
                if (this.strokeColor && this.getOutlineGeometry) {
                    // create the highlighting frame
                    this._outlinePolygon = new Cesium.Primitive({
                        geometryInstances: new Cesium.GeometryInstance({
                            geometry: this.getOutlineGeometry(),
                            attributes: {
                                color: Cesium.ColorGeometryInstanceAttribute.fromColor(this.strokeColor)
                            }
                        }),
                        appearance: new Cesium.PerInstanceColorAppearance({
                            flat: true,
                            renderState: {
                                depthTest: {
                                    enabled: true
                                },
                                lineWidth: Math.min(this.strokeWidth || 4.0, context._aliasedLineWidthRange[1])
                            }
                        })
                    });
                }
            }
            var primitive = this._primitive;
            primitive.appearance.material = this.material;
            primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;
            primitive.update(context, frameState, commandList);
            this._outlinePolygon && this._outlinePolygon.update(context, frameState, commandList);
        };
        _.prototype.isDestroyed = function () {
            return false;
        };
        _.prototype.destroy = function () {
            this._primitive = this._primitive && this._primitive.destroy();
            return Cesium.destroyObject(this);
        };
        _.prototype.setStrokeStyle = function (strokeColor, strokeWidth) {
            if (!this.strokeColor || !this.strokeColor.equals(strokeColor) || this.strokeWidth != strokeWidth) {
                this._createPrimitive = true;
                this.strokeColor = strokeColor;
                this.strokeWidth = strokeWidth;
            }
        }
        return _;
    })();
    _.ExtentPrimitive = (function () {
        function _(options) {
            if (!Cesium.defined(options.extent)) {
                throw new Cesium.DeveloperError('Extent is required');
            }
            options = copyOptions(options, defaultSurfaceOptions);
            this.initialiseOptions(options);
            this.setExtent(options.extent);
        }
        _.prototype = new ChangeablePrimitive();
        _.prototype.setExtent = function (extent) {
            this.setAttribute('extent', extent);
        };
        _.prototype.getExtent = function () {
            return this.getAttribute('extent');
        };
        _.prototype.getGeometry = function () {
            if (!Cesium.defined(this.extent)) {
                return;
            }
            return new Cesium.RectangleGeometry({
                rectangle: this.extent,
                height: this.height,
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                stRotation: this.textureRotationAngle,
                ellipsoid: this.ellipsoid,
                granularity: this.granularity
            });
        };
        _.prototype.getOutlineGeometry = function () {
            return new Cesium.RectangleOutlineGeometry({
                rectangle: this.extent
            });
        }
        return _;
    })();
    _.PolygonPrimitive = (function () {
        function _(options) {
            options = copyOptions(options, defaultSurfaceOptions);
            this.initialiseOptions(options);
            this.isPolygon = true;
        }
        _.prototype = new ChangeablePrimitive();
        _.prototype.setPositions = function (positions) {
            this.setAttribute('positions', positions);
        };
        _.prototype.getPositions = function () {
            return this.getAttribute('positions');
        };
        _.prototype.getGeometry = function () {
            if (!Cesium.defined(this.positions) || this.positions.length < 3) {
                return;
            }
            return Cesium.PolygonGeometry.fromPositions({
                positions: this.positions,
                height: this.height,
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                stRotation: this.textureRotationAngle,
                ellipsoid: this.ellipsoid,
                granularity: this.granularity
            });
        };
        _.prototype.getOutlineGeometry = function () {
            return Cesium.PolygonOutlineGeometry.fromPositions({
                positions: this.getPositions()
            });
        }
        return _;
    })();
    _.CirclePrimitive = (function () {
        function _(options) {
            if (!(Cesium.defined(options.center) && Cesium.defined(options.radius))) {
                throw new Cesium.DeveloperError('Center and radius are required');
            }
            options = copyOptions(options, defaultSurfaceOptions);
            this.initialiseOptions(options);
            this.setRadius(options.radius);
        }
        _.prototype = new ChangeablePrimitive();
        _.prototype.setCenter = function (center) {
            this.setAttribute('center', center);
        };
        _.prototype.setRadius = function (radius) {
            this.setAttribute('radius', Math.max(0.1, radius));
        };
        _.prototype.getCenter = function () {
            return this.getAttribute('center');
        };
        _.prototype.getRadius = function () {
            return this.getAttribute('radius');
        };
        _.prototype.getGeometry = function () {
            if (!(Cesium.defined(this.center) && Cesium.defined(this.radius))) {
                return;
            }
            return new Cesium.CircleGeometry({
                center: this.center,
                radius: this.radius,
                height: this.height,
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                stRotation: this.textureRotationAngle,
                ellipsoid: this.ellipsoid,
                granularity: this.granularity
            });
        };
        _.prototype.getOutlineGeometry = function () {
            return new Cesium.CircleOutlineGeometry({
                center: this.getCenter(),
                radius: this.getRadius()
            });
        }
        return _;
    })();
    _.EllipsePrimitive = (function () {
        function _(options) {
            if (!(Cesium.defined(options.center) && Cesium.defined(options.semiMajorAxis) && Cesium.defined(options.semiMinorAxis))) {
                throw new Cesium.DeveloperError('Center and semi major and semi minor axis are required');
            }
            options = copyOptions(options, defaultEllipseOptions);
            this.initialiseOptions(options);
        }
        _.prototype = new ChangeablePrimitive();
        _.prototype.setCenter = function (center) {
            this.setAttribute('center', center);
        };
        _.prototype.setSemiMajorAxis = function (semiMajorAxis) {
            if (semiMajorAxis < this.getSemiMinorAxis()) return;
            this.setAttribute('semiMajorAxis', semiMajorAxis);
        };
        _.prototype.setSemiMinorAxis = function (semiMinorAxis) {
            if (semiMinorAxis > this.getSemiMajorAxis()) return;
            this.setAttribute('semiMinorAxis', semiMinorAxis);
        };
        _.prototype.setRotation = function (rotation) {
            return this.setAttribute('rotation', rotation);
        };
        _.prototype.getCenter = function () {
            return this.getAttribute('center');
        };
        _.prototype.getSemiMajorAxis = function () {
            return this.getAttribute('semiMajorAxis');
        };
        _.prototype.getSemiMinorAxis = function () {
            return this.getAttribute('semiMinorAxis');
        };
        _.prototype.getRotation = function () {
            return this.getAttribute('rotation');
        };
        _.prototype.getGeometry = function () {
            if (!(Cesium.defined(this.center) && Cesium.defined(this.semiMajorAxis) && Cesium.defined(this.semiMinorAxis))) {
                return;
            }
            return new Cesium.EllipseGeometry({
                ellipsoid: this.ellipsoid,
                center: this.center,
                semiMajorAxis: this.semiMajorAxis,
                semiMinorAxis: this.semiMinorAxis,
                rotation: this.rotation,
                height: this.height,
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                stRotation: this.textureRotationAngle,
                ellipsoid: this.ellipsoid,
                granularity: this.granularity
            });
        };
        _.prototype.getOutlineGeometry = function () {
            return new Cesium.EllipseOutlineGeometry({
                center: this.getCenter(),
                semiMajorAxis: this.getSemiMajorAxis(),
                semiMinorAxis: this.getSemiMinorAxis(),
                rotation: this.getRotation()
            });
        }
        return _;
    })();
    _.PolylinePrimitive = (function () {
        function _(options) {
            options = copyOptions(options, defaultPolylineOptions);
            this.initialiseOptions(options);
        }
        _.prototype = new ChangeablePrimitive();
        _.prototype.setPositions = function (positions) {
            this.setAttribute('positions', positions);
        };
        _.prototype.setWidth = function (width) {
            this.setAttribute('width', width);
        };
        _.prototype.setGeodesic = function (geodesic) {
            this.setAttribute('geodesic', geodesic);
        };
        _.prototype.getPositions = function () {
            return this.getAttribute('positions');
        };
        _.prototype.getWidth = function () {
            return this.getAttribute('width');
        };
        _.prototype.getGeodesic = function (geodesic) {
            return this.getAttribute('geodesic');
        };
        _.prototype.getGeometry = function () {
            if (!Cesium.defined(this.positions) || this.positions.length < 2) {
                return;
            }
            return new Cesium.PolylineGeometry({
                positions: this.positions,
                height: this.height,
                width: this.width < 1 ? 1 : this.width,
                vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                ellipsoid: this.ellipsoid
            });
        }
        return _;
    })();
    var defaultBillboard = {
        iconUrl: "./img/dragIcon.png",
        shiftX: 0,
        shiftY: 0
    }
    var dragBillboard = {
        iconUrl: "./img/dragIcon.png",
        shiftX: 0,
        shiftY: 0
    }
    var dragHalfBillboard = {
        iconUrl: "./img/dragIconLight.png",
        shiftX: 0,
        shiftY: 0
    }
    _.prototype.createBillboardGroup = function (points, options, callbacks) {
        var markers = new _.BillboardGroup(this, options);
        markers.addBillboards(points, callbacks);
        return markers;
    }
    _.BillboardGroup = function (drawHelper, options) {
        this._drawHelper = drawHelper;
        this._scene = drawHelper._scene;
        this._options = copyOptions(options, defaultBillboard);
        // create one common billboard collection for all billboards
        var b = new Cesium.BillboardCollection();
        this._scene.primitives.add(b);
        this._billboards = b;
        // keep an ordered list of billboards
        this._orderedBillboards = [];
    }
    _.BillboardGroup.prototype.createBillboard = function (position, callbacks) {
        var billboard = this._billboards.add({
            show: true,
            position: position,
            pixelOffset: new Cesium.Cartesian2(this._options.shiftX, this._options.shiftY),
            eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0),
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            scale: 1.0,
            image: this._options.iconUrl,
            color: new Cesium.Color(1.0, 1.0, 1.0, 1.0)
        });
        // if editable
        if (callbacks) {
            var _self = this;
            var screenSpaceCameraController = this._scene.screenSpaceCameraController;
            function enableRotation(enable) {
                screenSpaceCameraController.enableRotate = enable;
            }
            function getIndex() {
                // find index
                for (var i = 0, I = _self._orderedBillboards.length; i < I && _self._orderedBillboards[i] != billboard; ++i);
                return i;
            }
            if (callbacks.dragHandlers) {
                var _self = this;
                setListener(billboard, 'leftDown', function (position) {
                    // TODO - start the drag handlers here
                    // create handlers for mouseOut and leftUp for the billboard and a mouseMove
                    function onDrag(position) {
                        billboard.position = position;
                        // find index
                        for (var i = 0, I = _self._orderedBillboards.length; i < I && _self._orderedBillboards[i] != billboard; ++i);
                        callbacks.dragHandlers.onDrag && callbacks.dragHandlers.onDrag(getIndex(), position);
                    }
                    function onDragEnd(position) {
                        handler.destroy();
                        enableRotation(true);
                        callbacks.dragHandlers.onDragEnd && callbacks.dragHandlers.onDragEnd(getIndex(), position);
                    }
                    var handler = new Cesium.ScreenSpaceEventHandler(_self._scene.canvas);
                    handler.setInputAction(function (movement) {
                        var cartesian = _self._scene.camera.pickEllipsoid(movement.endPosition, ellipsoid);
                        if (cartesian) {
                            onDrag(cartesian);
                        } else {
                            onDragEnd(cartesian);
                        }
                    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                    handler.setInputAction(function (movement) {
                        onDragEnd(_self._scene.camera.pickEllipsoid(movement.position, ellipsoid));
                    }, Cesium.ScreenSpaceEventType.LEFT_UP);
                    enableRotation(false);
                    callbacks.dragHandlers.onDragStart && callbacks.dragHandlers.onDragStart(getIndex(), _self._scene.camera.pickEllipsoid(position, ellipsoid));
                });
            }
            if (callbacks.onDoubleClick) {
                setListener(billboard, 'leftDoubleClick', function (position) {
                    callbacks.onDoubleClick(getIndex());
                });
            }
            if (callbacks.onClick) {
                setListener(billboard, 'leftClick', function (position) {
                    callbacks.onClick(getIndex());
                });
            }
            if (callbacks.tooltip) {
                setListener(billboard, 'mouseMove', function (position) {
                    _self._drawHelper._tooltip.showAt(position, callbacks.tooltip());
                });
                setListener(billboard, 'mouseOut', function (position) {
                    _self._drawHelper._tooltip.setVisible(false);
                });
            }
        }
        return billboard;
    }
    _.BillboardGroup.prototype.insertBillboard = function (index, position, callbacks) {
        this._orderedBillboards.splice(index, 0, this.createBillboard(position, callbacks));
    }
    _.BillboardGroup.prototype.addBillboard = function (position, callbacks) {
        this._orderedBillboards.push(this.createBillboard(position, callbacks));
    }
    _.BillboardGroup.prototype.addBillboards = function (positions, callbacks) {
        var index = 0;
        for (; index < positions.length; index++) {
            this.addBillboard(positions[index], callbacks);
        }
    }
    _.BillboardGroup.prototype.updateBillboardsPositions = function (positions) {
        var index = 0;
        for (; index < positions.length; index++) {
            this.getBillboard(index).position = positions[index];
        }
    }
    _.BillboardGroup.prototype.countBillboards = function () {
        return this._orderedBillboards.length;
    }
    _.BillboardGroup.prototype.getBillboard = function (index) {
        return this._orderedBillboards[index];
    }
    _.BillboardGroup.prototype.removeBillboard = function (index) {
        this._billboards.remove(this.getBillboard(index));
        this._orderedBillboards.splice(index, 1);
    }
    _.BillboardGroup.prototype.remove = function () {
        this._billboards = this._billboards && this._billboards.removeAll() && this._billboards.destroy();
    }
    _.BillboardGroup.prototype.setOnTop = function () {
        this._scene.primitives.raiseToTop(this._billboards);
    }
    _.prototype.startDrawingMarker = function (options) {
        var options = copyOptions(options, defaultBillboard);
        this.startDrawing(
            function () {
                markers.remove();
                mouseHandler.destroy();
                tooltip.setVisible(false);
            }
        );
        var _self = this;
        var scene = this._scene;
        var primitives = scene.primitives;
        var tooltip = this._tooltip;
        var markers = new _.BillboardGroup(this, options);
        var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        // Now wait for start
        mouseHandler.setInputAction(function (movement) {
            if (movement.position != null) {
                var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
                if (cartesian) {
                    markers.addBillboard(cartesian);
                    _self.stopDrawing();
                    options.callback(cartesian);
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        mouseHandler.setInputAction(function (movement) {
            var position = movement.endPosition;
            if (position != null) {
                var cartesian = scene.camera.pickEllipsoid(position, ellipsoid);
                if (cartesian) {
                    tooltip.showAt(position, "<p>Click to add your marker. Position is: </p>" + getDisplayLatLngString(ellipsoid.cartesianToCartographic(cartesian)));
                } else {
                    tooltip.showAt(position, "<p>Click on the globe to add your marker.</p>");
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }
    _.prototype.startDrawingPolygon = function (options) {
        var options = copyOptions(options, defaultSurfaceOptions);
        this.startDrawingPolyshape(true, options);
    }
    _.prototype.startDrawingPolyline = function (options) {
        var options = copyOptions(options, defaultPolylineOptions);
        this.startDrawingPolyshape(false, options);
    }
    _.prototype.startDrawingPolyshape = function (isPolygon, options) {
        this.startDrawing(
            function () {
                primitives.remove(poly);
                markers.remove();
                mouseHandler.destroy();
                tooltip.setVisible(false);
            }
        );
        var _self = this;
        var scene = this._scene;
        var primitives = scene.primitives;
        var tooltip = this._tooltip;
        var minPoints = isPolygon ? 3 : 2;
        var poly;
        if (isPolygon) {
            poly = new DrawHelper.PolygonPrimitive(options);
        } else {
            poly = new DrawHelper.PolylinePrimitive(options);
        }
        poly.asynchronous = false;
        primitives.add(poly);
        var positions = [];
        var markers = new _.BillboardGroup(this, defaultBillboard);
        var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        // Now wait for start
        mouseHandler.setInputAction(function (movement) {
            if (movement.position != null) {
                var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
                if (cartesian) {
                    // first click
                    if (positions.length == 0) {
                        positions.push(cartesian.clone());
                        markers.addBillboard(positions[0]);
                    }
                    if (positions.length >= minPoints) {
                        poly.positions = positions;
                        poly._createPrimitive = true;
                    }
                    // add new point to polygon
                    // this one will move with the mouse
                    positions.push(cartesian);
                    // add marker at the new position
                    markers.addBillboard(cartesian);
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
        mouseHandler.setInputAction(function (movement) {
            var position = movement.endPosition;
            if (position != null) {
                if (positions.length == 0) {
                    tooltip.showAt(position, "<p>Click to add first point</p>");
                } else {
                    var cartesian = scene.camera.pickEllipsoid(position, ellipsoid);
                    if (cartesian) {
                        positions.pop();
                        // make sure it is slightly different
                        cartesian.y += (1 + Math.random());
                        positions.push(cartesian);
                        if (positions.length >= minPoints) {
                            poly.positions = positions;
                            poly._createPrimitive = true;
                        }
                        // update marker
                        markers.getBillboard(positions.length - 1).position = cartesian;
                        // show tooltip
                        tooltip.showAt(position, "<p>Click to add new point (" + positions.length + ")</p>" + (positions.length > minPoints ? "<p>Double click to finish drawing</p>" : ""));
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        mouseHandler.setInputAction(function (movement) {
            var position = movement.position;
            if (position != null) {
                if (positions.length < minPoints + 2) {
                    return;
                } else {
                    var cartesian = scene.camera.pickEllipsoid(position, ellipsoid);
                    if (cartesian) {
                        _self.stopDrawing();
                        if (typeof options.callback == 'function') {
                            // remove overlapping ones
                            var index = positions.length - 1;
                            options.callback(positions);
                        }
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    }
    function getExtentCorners(value) {
        return ellipsoid.cartographicArrayToCartesianArray([Cesium.Rectangle.northwest(value), Cesium.Rectangle.northeast(value), Cesium.Rectangle.southeast(value), Cesium.Rectangle.southwest(value)]);
    }
    _.prototype.startDrawingExtent = function (options) {
        var options = copyOptions(options, defaultSurfaceOptions);
        this.startDrawing(
            function () {
                if (extent != null) {
                    primitives.remove(extent);
                }
                markers.remove();
                mouseHandler.destroy();
                tooltip.setVisible(false);
            }
        );
        var _self = this;
        var scene = this._scene;
        var primitives = this._scene.primitives;
        var tooltip = this._tooltip;
        var firstPoint = null;
        var extent = null;
        var markers = null;
        var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        function updateExtent(value) {
            if (extent == null) {
                extent = new Cesium.RectanglePrimitive();
                extent.asynchronous = false;
                primitives.add(extent);
            }
            extent.rectangle = value;
            // update the markers
            var corners = getExtentCorners(value);
            // create if they do not yet exist
            if (markers == null) {
                markers = new _.BillboardGroup(_self, defaultBillboard);
                markers.addBillboards(corners);
            } else {
                markers.updateBillboardsPositions(corners);
            }
        }
        // Now wait for start
        mouseHandler.setInputAction(function (movement) {
            if (movement.position != null) {
                var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
                if (cartesian) {
                    if (extent == null) {
                        // create the rectangle
                        firstPoint = ellipsoid.cartesianToCartographic(cartesian);
                        var value = getExtent(firstPoint, firstPoint);
                        updateExtent(value);
                    } else {
                        _self.stopDrawing();
                        if (typeof options.callback == 'function') {
                            options.callback(getExtent(firstPoint, ellipsoid.cartesianToCartographic(cartesian)));
                        }
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
        mouseHandler.setInputAction(function (movement) {
            var position = movement.endPosition;
            if (position != null) {
                if (extent == null) {
                    tooltip.showAt(position, "<p>Click to start drawing rectangle</p>");
                } else {
                    var cartesian = scene.camera.pickEllipsoid(position, ellipsoid);
                    if (cartesian) {
                        var value = getExtent(firstPoint, ellipsoid.cartesianToCartographic(cartesian));
                        updateExtent(value);
                        tooltip.showAt(position, "<p>Drag to change rectangle extent</p><p>Click again to finish drawing</p>");
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }
    _.prototype.startDrawingCircle = function (options) {
        var options = copyOptions(options, defaultSurfaceOptions);
        this.startDrawing(
            function cleanUp() {
                if (circle != null) {
                    primitives.remove(circle);
                }
                markers.remove();
                mouseHandler.destroy();
                tooltip.setVisible(false);
            }
        );
        var _self = this;
        var scene = this._scene;
        var primitives = this._scene.primitives;
        var tooltip = this._tooltip;
        var circle = null;
        var markers = null;
        var mouseHandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        // Now wait for start
        mouseHandler.setInputAction(function (movement) {
            if (movement.position != null) {
                var cartesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
                if (cartesian) {
                    if (circle == null) {
                        // create the circle
                        circle = new _.CirclePrimitive({
                            center: cartesian,
                            radius: 0,
                            asynchronous: false,
                            material: options.material
                        });
                        primitives.add(circle);
                        markers = new _.BillboardGroup(_self, defaultBillboard);
                        markers.addBillboards([cartesian]);
                    } else {
                        if (typeof options.callback == 'function') {
                            options.callback(circle.getCenter(), circle.getRadius());
                        }
                        _self.stopDrawing();
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
        mouseHandler.setInputAction(function (movement) {
            var position = movement.endPosition;
            if (position != null) {
                if (circle == null) {
                    tooltip.showAt(position, "<p>Click to start drawing the circle</p>");
                } else {
                    var cartesian = scene.camera.pickEllipsoid(position, ellipsoid);
                    if (cartesian) {
                        circle.setRadius(Cesium.Cartesian3.distance(circle.getCenter(), cartesian));
                        markers.updateBillboardsPositions(cartesian);
                        tooltip.showAt(position, "<p>Move mouse to change circle radius</p><p>Click again to finish drawing</p>");
                    }
                }
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }
    _.prototype.enhancePrimitives = function () {
        var drawHelper = this;
        Cesium.Billboard.prototype.setEditable = function () {
            if (this._editable) {
                return;
            }
            this._editable = true;
            var billboard = this;
            var _self = this;
            function enableRotation(enable) {
                drawHelper._scene.screenSpaceCameraController.enableRotate = enable;
            }
            setListener(billboard, 'leftDown', function (position) {
                // TODO - start the drag handlers here
                // create handlers for mouseOut and leftUp for the billboard and a mouseMove
                function onDrag(position) {
                    billboard.position = position;
                    _self.executeListeners({ name: 'drag', positions: position });
                }
                function onDragEnd(position) {
                    handler.destroy();
                    enableRotation(true);
                    _self.executeListeners({ name: 'dragEnd', positions: position });
                }
                var handler = new Cesium.ScreenSpaceEventHandler(drawHelper._scene.canvas);
                handler.setInputAction(function (movement) {
                    var cartesian = drawHelper._scene.camera.pickEllipsoid(movement.endPosition, ellipsoid);
                    if (cartesian) {
                        onDrag(cartesian);
                    } else {
                        onDragEnd(cartesian);
                    }
                }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                handler.setInputAction(function (movement) {
                    onDragEnd(drawHelper._scene.camera.pickEllipsoid(movement.position, ellipsoid));
                }, Cesium.ScreenSpaceEventType.LEFT_UP);
                enableRotation(false);
            });
            enhanceWithListeners(billboard);
        }
        function setHighlighted(highlighted) {
            var scene = drawHelper._scene;
            // if no change
            // if already highlighted, the outline polygon will be available
            if (this._highlighted && this._highlighted == highlighted) {
                return;
            }
            // disable if already in edit mode
            if (this._editMode === true) {
                return;
            }
            this._highlighted = highlighted;
            // highlight by creating an outline polygon matching the polygon points
            if (highlighted) {
                // make sure all other shapes are not highlighted
                drawHelper.setHighlighted(this);
                this._strokeColor = this.strokeColor;
                this.setStrokeStyle(Cesium.Color.fromCssColorString('white'), this.strokeWidth);
            } else {
                if (this._strokeColor) {
                    this.setStrokeStyle(this._strokeColor, this.strokeWidth);
                } else {
                    this.setStrokeStyle(undefined, undefined);
                }
            }
        }
        function setEditMode(editMode) {
            // if no change
            if (this._editMode == editMode) {
                return;
            }
            // make sure all other shapes are not in edit mode before starting the editing of this shape
            drawHelper.disableAllHighlights();
            // display markers
            if (editMode) {
                drawHelper.setEdited(this);
                var scene = drawHelper._scene;
                var _self = this;
                // create the markers and handlers for the editing
                if (this._markers == null) {
                    var markers = new _.BillboardGroup(drawHelper, dragBillboard);
                    var editMarkers = new _.BillboardGroup(drawHelper, dragHalfBillboard);
                    // function for updating the edit markers around a certain point
                    function updateHalfMarkers(index, positions) {
                        // update the half markers before and after the index
                        var editIndex = index - 1 < 0 ? positions.length - 1 : index - 1;
                        if (editIndex < editMarkers.countBillboards()) {
                            editMarkers.getBillboard(editIndex).position = calculateHalfMarkerPosition(editIndex);
                        }
                        editIndex = index;
                        if (editIndex < editMarkers.countBillboards()) {
                            editMarkers.getBillboard(editIndex).position = calculateHalfMarkerPosition(editIndex);
                        }
                    }
                    function onEdited() {
                        _self.executeListeners({ name: 'onEdited', positions: _self.positions });
                    }
                    var handleMarkerChanges = {
                        dragHandlers: {
                            onDrag: function (index, position) {
                                _self.positions[index] = position;
                                updateHalfMarkers(index, _self.positions);
                                _self._createPrimitive = true;
                            },
                            onDragEnd: function (index, position) {
                                _self._createPrimitive = true;
                                onEdited();
                            }
                        },
                        onDoubleClick: function (index) {
                            if (_self.positions.length < 4) {
                                return;
                            }
                            // remove the point and the corresponding markers
                            _self.positions.splice(index, 1);
                            _self._createPrimitive = true;
                            markers.removeBillboard(index);
                            editMarkers.removeBillboard(index);
                            updateHalfMarkers(index, _self.positions);
                            onEdited();
                        },
                        tooltip: function () {
                            if (_self.positions.length > 3) {
                                return "Double click to remove this point";
                            }
                        }
                    };
                    // add billboards and keep an ordered list of them for the polygon edges
                    markers.addBillboards(_self.positions, handleMarkerChanges);
                    this._markers = markers;
                    function calculateHalfMarkerPosition(index) {
                        var positions = _self.positions;
                        return ellipsoid.cartographicToCartesian(
                            new Cesium.EllipsoidGeodesic(ellipsoid.cartesianToCartographic(positions[index]),
                                ellipsoid.cartesianToCartographic(positions[index < positions.length - 1 ? index + 1 : 0])).
                                interpolateUsingFraction(0.5)
                        );
                    }
                    var halfPositions = [];
                    var index = 0;
                    var length = _self.positions.length + (this.isPolygon ? 0 : -1);
                    for (; index < length; index++) {
                        halfPositions.push(calculateHalfMarkerPosition(index));
                    }
                    var handleEditMarkerChanges = {
                        dragHandlers: {
                            onDragStart: function (index, position) {
                                // add a new position to the polygon but not a new marker yet
                                this.index = index + 1;
                                _self.positions.splice(this.index, 0, position);
                                _self._createPrimitive = true;
                            },
                            onDrag: function (index, position) {
                                _self.positions[this.index] = position;
                                _self._createPrimitive = true;
                            },
                            onDragEnd: function (index, position) {
                                // create new sets of makers for editing
                                markers.insertBillboard(this.index, position, handleMarkerChanges);
                                editMarkers.getBillboard(this.index - 1).position = calculateHalfMarkerPosition(this.index - 1);
                                editMarkers.insertBillboard(this.index, calculateHalfMarkerPosition(this.index), handleEditMarkerChanges);
                                _self._createPrimitive = true;
                                onEdited();
                            }
                        },
                        tooltip: function () {
                            return "Drag to create a new point";
                        }
                    };
                    editMarkers.addBillboards(halfPositions, handleEditMarkerChanges);
                    this._editMarkers = editMarkers;
                    // add a handler for clicking in the globe
                    this._globeClickhandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                    this._globeClickhandler.setInputAction(
                        function (movement) {
                            var pickedObject = scene.pick(movement.position);
                            if (!(pickedObject && pickedObject.primitive)) {
                                _self.setEditMode(false);
                            }
                        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                    // set on top of the polygon
                    markers.setOnTop();
                    editMarkers.setOnTop();
                }
                this._editMode = true;
            } else {
                if (this._markers != null) {
                    this._markers.remove();
                    this._editMarkers.remove();
                    this._markers = null;
                    this._editMarkers = null;
                    this._globeClickhandler.destroy();
                }
                this._editMode = false;
            }
        }
        DrawHelper.PolylinePrimitive.prototype.setEditable = function () {
            if (this.setEditMode) {
                return;
            }
            var polyline = this;
            polyline.isPolygon = false;
            polyline.asynchronous = false;
            drawHelper.registerEditableShape(polyline);
            polyline.setEditMode = setEditMode;
            var originalWidth = this.width;
            polyline.setHighlighted = function (highlighted) {
                // disable if already in edit mode
                if (this._editMode === true) {
                    return;
                }
                if (highlighted) {
                    drawHelper.setHighlighted(this);
                    this.setWidth(originalWidth * 2);
                } else {
                    this.setWidth(originalWidth);
                }
            }
            polyline.getExtent = function () {
                return Cesium.Extent.fromCartographicArray(ellipsoid.cartesianArrayToCartographicArray(this.positions));
            }
            enhanceWithListeners(polyline);
            polyline.setEditMode(false);
        }
        DrawHelper.PolygonPrimitive.prototype.setEditable = function () {
            var polygon = this;
            polygon.asynchronous = false;
            var scene = drawHelper._scene;
            drawHelper.registerEditableShape(polygon);
            polygon.setEditMode = setEditMode;
            polygon.setHighlighted = setHighlighted;
            enhanceWithListeners(polygon);
            polygon.setEditMode(false);
        }
        DrawHelper.ExtentPrimitive.prototype.setEditable = function () {
            if (this.setEditMode) {
                return;
            }
            var extent = this;
            var scene = drawHelper._scene;
            drawHelper.registerEditableShape(extent);
            extent.asynchronous = false;
            extent.setEditMode = function (editMode) {
                // if no change
                if (this._editMode == editMode) {
                    return;
                }
                drawHelper.disableAllHighlights();
                // display markers
                if (editMode) {
                    // make sure all other shapes are not in edit mode before starting the editing of this shape
                    drawHelper.setEdited(this);
                    // create the markers and handlers for the editing
                    if (this._markers == null) {
                        var markers = new _.BillboardGroup(drawHelper, dragBillboard);
                        function onEdited() {
                            extent.executeListeners({ name: 'onEdited', extent: extent.extent });
                        }
                        var handleMarkerChanges = {
                            dragHandlers: {
                                onDrag: function (index, position) {
                                    var corner = markers.getBillboard((index + 2) % 4).position;
                                    extent.setExtent(getExtent(ellipsoid.cartesianToCartographic(corner), ellipsoid.cartesianToCartographic(position)));
                                    markers.updateBillboardsPositions(getExtentCorners(extent.extent));
                                },
                                onDragEnd: function (index, position) {
                                    onEdited();
                                }
                            },
                            tooltip: function () {
                                return "Drag to change the corners of this extent";
                            }
                        };
                        markers.addBillboards(getExtentCorners(extent.extent), handleMarkerChanges);
                        this._markers = markers;
                        // add a handler for clicking in the globe
                        this._globeClickhandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                        this._globeClickhandler.setInputAction(
                            function (movement) {
                                var pickedObject = scene.pick(movement.position);
                                // disable edit if pickedobject is different or not an object
                                if (!(pickedObject && !pickedObject.isDestroyed() && pickedObject.primitive)) {
                                    extent.setEditMode(false);
                                }
                            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                        // set on top of the polygon
                        markers.setOnTop();
                    }
                    this._editMode = true;
                } else {
                    if (this._markers != null) {
                        this._markers.remove();
                        this._markers = null;
                        this._globeClickhandler.destroy();
                    }
                    this._editMode = false;
                }
            }
            extent.setHighlighted = setHighlighted;
            enhanceWithListeners(extent);
            extent.setEditMode(false);
        }
        _.EllipsePrimitive.prototype.setEditable = function () {
            if (this.setEditMode) {
                return;
            }
            var ellipse = this;
            var scene = drawHelper._scene;
            ellipse.asynchronous = false;
            drawHelper.registerEditableShape(ellipse);
            ellipse.setEditMode = function (editMode) {
                // if no change
                if (this._editMode == editMode) {
                    return;
                }
                drawHelper.disableAllHighlights();
                // display markers
                if (editMode) {
                    // make sure all other shapes are not in edit mode before starting the editing of this shape
                    drawHelper.setEdited(this);
                    var _self = this;
                    // create the markers and handlers for the editing
                    if (this._markers == null) {
                        var markers = new _.BillboardGroup(drawHelper, dragBillboard);
                        function getMarkerPositions() {
                            return Cesium.Shapes.computeEllipseBoundary(ellipsoid, ellipse.getCenter(), ellipse.getSemiMajorAxis(), ellipse.getSemiMinorAxis(), ellipse.getRotation() + Math.PI / 2, Math.PI / 2.0).splice(0, 4);
                        }
                        function onEdited() {
                            ellipse.executeListeners({ name: 'onEdited', center: ellipse.getCenter(), semiMajorAxis: ellipse.getSemiMajorAxis(), semiMinorAxis: ellipse.getSemiMinorAxis(), rotation: 0 });
                        }
                        var handleMarkerChanges = {
                            dragHandlers: {
                                onDrag: function (index, position) {
                                    var distance = Cesium.Cartesian3.distance(ellipse.getCenter(), position);
                                    if (index % 2 == 0) {
                                        ellipse.setSemiMajorAxis(distance);
                                    } else {
                                        ellipse.setSemiMinorAxis(distance);
                                    }
                                    markers.updateBillboardsPositions(getMarkerPositions());
                                },
                                onDragEnd: function (index, position) {
                                    onEdited();
                                }
                            },
                            tooltip: function () {
                                return "Drag to change the excentricity and radius";
                            }
                        };
                        markers.addBillboards(getMarkerPositions(), handleMarkerChanges);
                        this._markers = markers;
                        // add a handler for clicking in the globe
                        this._globeClickhandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                        this._globeClickhandler.setInputAction(
                            function (movement) {
                                var pickedObject = scene.pick(movement.position);
                                if (!(pickedObject && pickedObject.primitive)) {
                                    _self.setEditMode(false);
                                }
                            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                        // set on top of the polygon
                        markers.setOnTop();
                    }
                    this._editMode = true;
                } else {
                    if (this._markers != null) {
                        this._markers.remove();
                        this._markers = null;
                        this._globeClickhandler.destroy();
                    }
                    this._editMode = false;
                }
            }
            ellipse.setHighlighted = setHighlighted;
            enhanceWithListeners(ellipse);
            ellipse.setEditMode(false);
        }
        _.CirclePrimitive.prototype.getCircleCartesianCoordinates = function (granularity) {
            var geometry = Cesium.CircleOutlineGeometry.createGeometry(new Cesium.CircleOutlineGeometry({ ellipsoid: ellipsoid, center: this.getCenter(), radius: this.getRadius(), granularity: granularity }));
            var count = 0, value, values = [];
            for (; count < geometry.attributes.position.values.length; count += 3) {
                value = geometry.attributes.position.values;
                values.push(new Cesium.Cartesian3(value[count], value[count + 1], value[count + 2]));
            }
            return values;
        };
        _.CirclePrimitive.prototype.setEditable = function () {
            if (this.setEditMode) {
                return;
            }
            var circle = this;
            var scene = drawHelper._scene;
            circle.asynchronous = false;
            drawHelper.registerEditableShape(circle);
            circle.setEditMode = function (editMode) {
                // if no change
                if (this._editMode == editMode) {
                    return;
                }
                drawHelper.disableAllHighlights();
                // display markers
                if (editMode) {
                    // make sure all other shapes are not in edit mode before starting the editing of this shape
                    drawHelper.setEdited(this);
                    var _self = this;
                    // create the markers and handlers for the editing
                    if (this._markers == null) {
                        var markers = new _.BillboardGroup(drawHelper, dragBillboard);
                        function getMarkerPositions() {
                            return _self.getCircleCartesianCoordinates(Cesium.Math.PI_OVER_TWO);
                        }
                        function onEdited() {
                            circle.executeListeners({ name: 'onEdited', center: circle.getCenter(), radius: circle.getRadius() });
                        }
                        var handleMarkerChanges = {
                            dragHandlers: {
                                onDrag: function (index, position) {
                                    circle.setRadius(Cesium.Cartesian3.distance(circle.getCenter(), position));
                                    markers.updateBillboardsPositions(getMarkerPositions());
                                },
                                onDragEnd: function (index, position) {
                                    onEdited();
                                }
                            },
                            tooltip: function () {
                                return "Drag to change the radius";
                            }
                        };
                        markers.addBillboards(getMarkerPositions(), handleMarkerChanges);
                        this._markers = markers;
                        // add a handler for clicking in the globe
                        this._globeClickhandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
                        this._globeClickhandler.setInputAction(
                            function (movement) {
                                var pickedObject = scene.pick(movement.position);
                                if (!(pickedObject && pickedObject.primitive)) {
                                    _self.setEditMode(false);
                                }
                            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                        // set on top of the polygon
                        markers.setOnTop();
                    }
                    this._editMode = true;
                } else {
                    if (this._markers != null) {
                        this._markers.remove();
                        this._markers = null;
                        this._globeClickhandler.destroy();
                    }
                    this._editMode = false;
                }
            }
            circle.setHighlighted = setHighlighted;
            enhanceWithListeners(circle);
            circle.setEditMode(false);
        }
    }
    _.DrawHelperWidget = (function () {
        // constructor
        function _(drawHelper, options) {
            // container must be specified
            if (!(Cesium.defined(options.container))) {
                throw new Cesium.DeveloperError('Container is required');
            }
            var drawOptions = {
                markerIcon: "./img/glyphicons_242_google_maps.png",
                polylineIcon: "./img/glyphicons_097_vector_path_line.png",
                polygonIcon: "./img/glyphicons_096_vector_path_polygon.png",
                circleIcon: "./img/glyphicons_095_vector_path_circle.png",
                extentIcon: "./img/glyphicons_094_vector_path_square.png",
                clearIcon: "./img/glyphicons_067_cleaning.png",
                polylineDrawingOptions: defaultPolylineOptions,
                polygonDrawingOptions: defaultPolygonOptions,
                extentDrawingOptions: defaultExtentOptions,
                circleDrawingOptions: defaultCircleOptions
            };
            fillOptions(options, drawOptions);
            var _self = this;
            var toolbar = document.createElement('DIV');
            toolbar.className = "toolbar";
            options.container.appendChild(toolbar);
            function addIcon(id, url, title, callback) {
                var div = document.createElement('DIV');
                div.className = 'button';
                div.title = title;
                toolbar.appendChild(div);
                div.onclick = callback;
                var span = document.createElement('SPAN');
                div.appendChild(span);
                var image = document.createElement('IMG');
                image.src = url;
                span.appendChild(image);
                return div;
            }
            var scene = drawHelper._scene;
            addIcon('marker', options.markerIcon, 'Click to start drawing a 2D marker', function () {
                drawHelper.startDrawingMarker({
                    callback: function (position) {
                        _self.executeListeners({ name: 'markerCreated', position: position });
                    }
                });
            })
            addIcon('polyline', options.polylineIcon, 'Click to start drawing a 2D polyline', function () {
                drawHelper.startDrawingPolyline({
                    callback: function (positions) {
                        _self.executeListeners({ name: 'polylineCreated', positions: positions });
                    }
                });
            })
            addIcon('polygon', options.polygonIcon, 'Click to start drawing a 2D polygon', function () {
                drawHelper.startDrawingPolygon({
                    callback: function (positions) {
                        _self.executeListeners({ name: 'polygonCreated', positions: positions });
                    }
                });
            })
            addIcon('extent', options.extentIcon, 'Click to start drawing an Extent', function () {
                drawHelper.startDrawingExtent({
                    callback: function (extent) {
                        _self.executeListeners({ name: 'extentCreated', extent: extent });
                    }
                });
            })
            addIcon('circle', options.circleIcon, 'Click to start drawing a Circle', function () {
                drawHelper.startDrawingCircle({
                    callback: function (center, radius) {
                        _self.executeListeners({ name: 'circleCreated', center: center, radius: radius });
                    }
                });
            })
            // add a clear button at the end
            // add a divider first
            var div = document.createElement('DIV');
            div.className = 'divider';
            toolbar.appendChild(div);
            addIcon('clear', options.clearIcon, 'Remove all primitives', function () {
                scene.primitives.removeAll();
            });
            enhanceWithListeners(this);
        }
        return _;
    })();
    _.prototype.addToolbar = function (container, options) {
        options = copyOptions(options, { container: container });
        return new _.DrawHelperWidget(this, options);
    }
    function getExtent(mn, mx) {
        var e = new Cesium.Rectangle();
        // Re-order so west < east and south < north
        e.west = Math.min(mn.longitude, mx.longitude);
        e.east = Math.max(mn.longitude, mx.longitude);
        e.south = Math.min(mn.latitude, mx.latitude);
        e.north = Math.max(mn.latitude, mx.latitude);
        // Check for approx equal (shouldn't require abs due to re-order)
        var epsilon = Cesium.Math.EPSILON7;
        if ((e.east - e.west) < epsilon) {
            e.east += epsilon * 2.0;
        }
        if ((e.north - e.south) < epsilon) {
            e.north += epsilon * 2.0;
        }
        return e;
    };
    function createTooltip(frameDiv) {
        var tooltip = function (frameDiv) {
            var div = document.createElement('DIV');
            div.className = "twipsy right";
            var arrow = document.createElement('DIV');
            arrow.className = "twipsy-arrow";
            div.appendChild(arrow);
            var title = document.createElement('DIV');
            title.className = "twipsy-inner";
            div.appendChild(title);
            this._div = div;
            this._title = title;
            // add to frame div and display coordinates
            frameDiv.appendChild(div);
        }
        tooltip.prototype.setVisible = function (visible) {
            this._div.style.display = visible ? 'block' : 'none';
        }
        tooltip.prototype.showAt = function (position, message) {
            if (position && message) {
                this.setVisible(true);
                this._title.innerHTML = message;
                this._div.style.left = position.x + 10 + "px";
                this._div.style.top = (position.y - this._div.clientHeight / 2) + "px";
            }
        }
        return new tooltip(frameDiv);
    }
    function getDisplayLatLngString(cartographic, precision) {
        return cartographic.longitude.toFixed(precision || 3) + ", " + cartographic.latitude.toFixed(precision || 3);
    }
    function clone(from, to) {
        if (from == null || typeof from != "object") return from;
        if (from.constructor != Object && from.constructor != Array) return from;
        if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function ||
            from.constructor == String || from.constructor == Number || from.constructor == Boolean)
            return new from.constructor(from);
        to = to || new from.constructor();
        for (var name in from) {
            to[name] = typeof to[name] == "undefined" ? clone(from[name], null) : to[name];
        }
        return to;
    }
    function fillOptions(options, defaultOptions) {
        options = options || {};
        var option;
        for (option in defaultOptions) {
            if (options[option] === undefined) {
                options[option] = clone(defaultOptions[option]);
            }
        }
    }
    // shallow copy
    function copyOptions(options, defaultOptions) {
        var newOptions = clone(options), option;
        for (option in defaultOptions) {
            if (newOptions[option] === undefined) {
                newOptions[option] = clone(defaultOptions[option]);
            }
        }
        return newOptions;
    }
    function setListener(primitive, type, callback) {
        primitive[type] = callback;
    }
    function enhanceWithListeners(element) {
        element._listeners = {};
        element.addListener = function (name, callback) {
            this._listeners[name] = (this._listeners[name] || []);
            this._listeners[name].push(callback);
            return this._listeners[name].length;
        }
        element.executeListeners = function (event, defaultCallback) {
            if (this._listeners[event.name] && this._listeners[event.name].length > 0) {
                var index = 0;
                for (; index < this._listeners[event.name].length; index++) {
                    this._listeners[event.name][index](event);
                }
            } else {
                if (defaultCallback) {
                    defaultCallback(event);
                }
            }
        }
    }
    return _;
})();
widgets/filyL/js/move.js
New file
@@ -0,0 +1,103 @@
function move(dom, Wx, Wy) {
    this.dom = $(dom);
    this.left = 0;
    this.top = 0;
    this.moveWhat = () => {
        this.moveWhats();
        console.log(this, 'inmoveWhat');
    };
    this.moveWhats = () => {
        console.log(this.dom, 'inmoveWhatS');
    };
    var beginrelative = () => {//relative
        var that = this;
        this.dom.mousedown((e) => {
            var a = 'null';
            var x = e.clientX
                , y = e.clientY
                , xx, yy
                , L = that.left
                , T = that.top;
            this.dom.css({
                'left': that.left,
                "top": that.top
            })
            console.log("dianxia");
            this.dom.mousemove((e) => {
                console.log("yidong")
                a = e;
                xx = e.clientX;
                yy = e.clientY;
                that.left = xx - x + L;
                that.top = yy - y + T;
                console.log((x + L + that.left) < e.offsetX)
                this.dom.css({
                    'left': that.left,
                    "top": that.top
                })
            })
            this.dom.mouseup(() => {
                if (a != 'null') {
                    this.dom.unbind(a);
                    a = 'null';
                    console.log("songkai")
                }
            })
            this.dom.mouseout((e) => {
                if (a != 'null') {
                    this.dom.unbind(a);
                    a = 'null';
                    console.log("songkai")
                }
                this.dom.unbind(e);
            })
        })
    }
    // beginrelative();
    var beginabsolute = () => {
        var that = this;
        this.dom.mousedown((e) => {
            var a = 'null';
            var x = e.clientX
                , y = e.clientY
                , xx, yy;
            this.dom.css({
                'left': that.left,
                "top": that.top
            })
            console.log("dianxia");
            this.dom.mousemove((e) => {
                console.log("yidong")
                a = e;
                xx = e.clientX;
                yy = e.clientY;
                that.left = xx - x;
                that.top = yy - y;
                console.log((x + L + that.left) < e.offsetX)
                this.dom.css({
                    'left': that.left,
                    "top": that.top
                })
            })
            this.dom.mouseup(() => {
                if (a != 'null') {
                    this.dom.unbind(a);
                    a = 'null';
                    console.log("songkai")
                }
            })
            this.dom.mouseout((e) => {
                if (a != 'null') {
                    this.dom.unbind(a);
                    a = 'null';
                    console.log("songkai")
                }
                this.dom.unbind(e);
            })
        })
    }
    beginabsolute();
}
widgets/filyL/manifest.json
New file
@@ -0,0 +1,17 @@
{
  "name": "filyL",
  "2D": true,
  "3D": true,
  "platform": "HTML",
  "version": "2.10",
  "wabVersion": "2.10",
  "author": "liuyg",
  "description": "",
  "copyright": "",
  "license": "",
  "properties": {
    "hasConfig": false,
    "inPanel": false,
    "hasVersionManager": false
  }
}
widgets/filyL/nls/es/strings.js
New file
@@ -0,0 +1,5 @@
define(
   ({
    _widgetLabel: "filyL"
  })
);
widgets/filyL/nls/strings.js
New file
@@ -0,0 +1,7 @@
define({
  root: ({
    _widgetLabel: "filyL"
  }),
  "es": 1,
  "zh-cn": 1
});
widgets/filyL/nls/zh-cn/strings.js
New file
@@ -0,0 +1,5 @@
define(
   ({
    _widgetLabel: "飞行"
  })
);
widgets/filyL/实例临时 copy 2.html
New file
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #box {
            width: 100px;
            height: 100px;
            border: 3px solid springgreen;
            /* background-color: teal; */
            border-radius: 50px;
            position: absolute;
        }
    </style>
</head>
<body>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="./js/move.js"></script>
    <!-- <script src="js/flycesium.js"></script> -->
    <div id="box"></div>
    <script>
        var m = new move('#box');
        m.moveWhat();
    </script>
</body>
</html>
widgets/filyL/实例临时 copy.html
New file
@@ -0,0 +1,587 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="js/Cesium1.63/Widgets/widgets.css">
    <link rel="stylesheet" href="css/bootstrap.css">
    <link rel="stylesheet" href="css/cesiumviewer.css">
    <link rel="stylesheet" href="css/DrawHelper.css">
    <link rel="stylesheet" href="js/jqueryDialog/jDialog/jDialog.css">
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
    <script src="js/jquery-3.4.1.js"></script>
    <script src="js/Cesium1.63/Cesium.js"></script>
    <script src="js/jqueryDialog/jDialog.js"></script>
    <script src="js/DrawHelper.js"></script>
    <script src="js/viewerCesiumNavigationMixin.js"></script>
    <!-- <script src="js/flycesium.js"></script> -->
    <script>
        viewer = new Cesium.Viewer('box', {
            animation: false,
            baseLayerPicker: false,
            geocoder: true,
            timeline: false,
            sceneModePicker: true,
            navigationHelpButton: false,
            useDefaultRenderLoop: true,
            showRenderLoopErrors: true,
            fullscreenButton: true,
            fullscreenElement: 'map3d',
            infoBox: true,
            mapProjection: new Cesium.WebMercatorProjection(),
            imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
                url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=ebf64362215c081f8317203220f133eb",
                layer: "tdtBasicLayer",
                style: "default",
                format: "image/jpeg",
                tileMatrixSetID: "GoogleMapsCompatible",
                show: false,
                maximumLevel: 18
            })
        });
        var drawHelper = new DrawHelper(viewer);
        //三维飞行初始化
        bxmap.FlyCesium.Init(viewer, drawHelper, 'box');//初始化漫游飞行路径功能
        var bxmap = bxmap || {};
        bxmap.FlyCesium = {
            cesiumViewer: null,
            draw3DObj: null,
            drawHelper: null,
            isDrawFly: false,//设定路线模式
            drawPolyline: null,//飞行绘制路线
            parentID: null,
            node: null,
            data: [
                /*{
                    id:'1',name:'阳江闸坡',geojson:'{"orientation":{"heading":0.07372076173362352,"pitch":-1.5574628887292024,"roll":0},"position":{"x":-2205629.231433604,"y":5509184.64306962,"z":2331219.615547844},"geometry":{"type":"LineString","coordinates":[[111.8181532375421,21.57868178213224],[111.81835028960268,21.578460581633188],[111.81832383076255,21.57812489081727],[111.81847943987464,21.577930686377922],[111.81878489838651,21.57765953027421],[111.81916083936886,21.577412646930927],[111.81958489944898,21.57729241143278],[111.82004766614196,21.57718315464893],[111.8206409631356,21.577000552080584],[111.82134398589339,21.576873639989994],[111.8219423400026,21.576726154070943],[111.822467537162,21.576376210912294],[111.82307030263561,21.576058642812292],[111.8237103973151,21.5756704298083],[111.8240924390803,21.575296152837485],[111.82504071801145,21.575766169089448],[111.82603850185104,21.576124273877287],[111.82694738799758,21.576428149353344],[111.82754018969692,21.576728981595224],[111.828099605676,21.57697046673728],[111.82845968318266,21.577307788777407],[111.8287111214647,21.577998110617774],[111.82881328135024,21.578557636789135],[111.82905095574245,21.57877846306897],[111.82918966895863,21.579074053131905],[111.82928422024466,21.579329257594996],[111.82930019172734,21.579630618390876],[111.82966603969574,21.580020790142015],[111.82960868244719,21.580744679418963],[111.82989219533579,21.581251462292837],[111.83013608532544,21.582236343172],[111.83037855800974,21.58254231013029],[111.83032824715998,21.58299431932842],[111.83001717858694,21.583468817164515],[111.8299185766154,21.584290601587544],[111.82948276544901,21.58496623602712],[111.8289749235787,21.58556878427974],[111.82886305199469,21.585776309810406],[111.8287779821505,21.585946333271792],[111.82865496967007,21.586265136888645],[111.82847674720864,21.586438092096014],[111.82845974740698,21.586567373767977],[111.828355170664,21.586736247366822],[111.82830843296874,21.586863152790087],[111.82825365102633,21.58710380271154],[111.82821734971404,21.587138762444976],[111.82817916952548,21.587294814193356],[111.82787759367034,21.587314539280754],[111.82719468513524,21.587237821164194],[111.82672929414602,21.58716013804561],[111.82658494057793,21.587131014021804],[111.82652478882481,21.587094797111455],[111.82647814913857,21.58694770659332],[111.82649812273736,21.58651375697629],[111.82650209141173,21.586517166652694],[111.82650209141173,21.586517166652694]]}}'
                }*/
            ],//漫游路径信息模拟数据
            Init: function (cesiumViewer, drawHelper, parentID) {
                this.cesiumViewer = cesiumViewer; //cesium对象
                this.drawHelper = drawHelper;//drawHelper对象
                this.parentID = parentID;//父容器
                this.InitHtml();
                this.InitEvent();
                this.loadData();
            },
            InitHtml: function () {
                var parent = document.getElementById(bxmap.FlyCesium.parentID);
                bxmap.FlyCesium.node = `<div id= "fly3DPaths" class="fly3DPaths">
        <div class="fly3DPaths_title">操作菜单 <span id="fly3DClose" class="fly3DClose"></span></div>
        <!--新增-->
        <!-- tab导航部分 -->
        <div class='fly3DPaths_tab'>
            <ul style='margin-left:0;' class="fly3DPaths_tab_ul">
                <li id="overFlyClick"><span><span class='flss'></span><a href='javascript:void(0)'>预设路线</a></span></li>
                <li id="drawFlyCilck" class="select"><span><span class='flss'></span><a href='javascript:void(0);'>手动绘制</a></span></li>
            </ul>
        </div>
        <!-- tab内容部分 -->
        <!-- 预设路线 -->
        <div id='overFlyPage' style='height: 100%;; display:none'>
            <div style="padding: 5px;margin-top: 5px;">
                <div class='ydph-table-wrap'>
                    <div class='ydph-talbe-head'>
                        <table id='overFly_table' class='table table-bordered'>
                            <thead>
                            <tr>
                                <!--<th class='colspan1'><input type='checkbox' οnchange=''/></th>-->
                                <th class='colspan4'>名称</th>
                                <th class='colspan2'>操作</th>
                                <th class='colspan2'>修改</th>
                                <th class='colspan2'>删除</th>
                            </tr>
                            </thead>
                            <tbody></tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
        <!-- 手动绘制 -->
        <div id='drawFlyPage' style='height: 100%'>
            <div class="fly3DPaths_content">
                <input id="start_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="开始飞行">
                <input id="pause_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="暂停飞行">
                <input id="playForward_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="向前飞行">
                <input id="playReverse_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="向后飞行">
                <input id="draw_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="设定路线">
                <input id="save_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="保存路线">
                <input id="clear_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="清空路线">
                <input id="stop_Fly3DPaths" class="fly3DPaths_model_id" type="button" value="退出飞行">
            </div>
        </div>
    </div>`;
                $(parent).append(bxmap.FlyCesium.node);
            },
            InitEvent: function () {
                //飞行路径顶端部分的切换事件
                $(".fly3DPaths_tab li").bind("click", function () {
                    $('.fly3DPaths_tab_ul>li').each(function (index) {
                        $('.fly3DPaths_tab_ul>li').eq(index).removeClass('select');
                    });
                    var $overFlyPage = $("#overFlyPage");
                    var $drawFlyPage = $("#drawFlyPage");
                    //三角形标识切换
                    switch ($(this).index()) {
                        case 0://预设路线
                            $('#overFlyClick').addClass('select');
                            $overFlyPage.css({ display: "block" });
                            $drawFlyPage.css({ display: "none" });
                            bxmap.FlyCesium.loadData();
                            break;
                        case 1://手动绘制
                            $('#drawFlyCilck').addClass('select');
                            $overFlyPage.css({ display: "none" });
                            $drawFlyPage.css({ display: "block" });
                            break;
                    }
                });
                //开始飞行
                $("#start_Fly3DPaths").click(function () {
                    //debugger;
                    if (bxmap.FlyCesium.draw3DObj) {
                        bxmap.FlyCesium.showFly3DPaths(bxmap.FlyCesium.draw3DObj);
                    } else {
                        jDialog.dialog({
                            title: "提示信息",
                            modal: true,// 非模态,即不显示遮罩层
                            autoClose: 1500,
                            content: "漫游路线不存在"
                        });
                    }
                });
                //暂停飞行
                $("#pause_Fly3DPaths").click(function () {
                    bxmap.FlyCesium.pauseFly3DPaths();
                });
                //向前飞行
                $("#playForward_Fly3DPaths").click(function () {
                    bxmap.FlyCesium.playForwardFly3DPaths();
                });
                //向后飞行
                $("#playReverse_Fly3DPaths").click(function () {
                    bxmap.FlyCesium.playReverseFly3DPaths();
                });
                //退出飞行
                $("#stop_Fly3DPaths").click(function () {
                    $("#cesiumFly3DPaths").click();
                    bxmap.FlyCesium.stopFly3DPaths();
                });
                //清空路线
                $("#clear_Fly3DPaths").click(function () {
                    bxmap.FlyCesium.clearFly3DPaths();
                });
                //设定路线
                $("#draw_Fly3DPaths").click(function () {
                    if (!bxmap.FlyCesium.drawHelper) {
                        bxmap.FlyCesium.drawHelper = new DrawHelper(bxmap.FlyCesium.cesiumViewer);
                    }
                    bxmap.FlyCesium.draw3DObj = bxmap.FlyCesium.DrawFly3DPaths(bxmap.FlyCesium.drawHelper);
                });
                //保存路线
                $("#save_Fly3DPaths").click(function () {
                    if (bxmap.FlyCesium.draw3DObj && bxmap.FlyCesium.isDrawFly) {
                        jDialog.dialog({
                            title: '保存路线',
                            content: '<div><span>名称:</span><input type="text" id="FlyAdd_name" value="' + name + '"></div>',
                            width: 300,
                            height: 120,
                            modal: true,// 非模态,即不显示遮罩层
                            buttons: [
                                {
                                    text: '确定',
                                    handler: function (button, dialog) {
                                        var draw3DObj = JSON.stringify(bxmap.FlyCesium.draw3DObj); //将JSON对象转化为JSON字符
                                        var TbFly = { id: Math.random().toString(36).substr(2), name: $("#FlyAdd_name").val(), geojson: draw3DObj };
                                        bxmap.FlyCesium.data.push(TbFly);
                                        $("#overFlyClick").click();
                                        dialog.close();
                                        bxmap.FlyCesium.clearFly3DPaths();
                                    }
                                }, {
                                    text: '取消',
                                    handler: function (button, dialog) {
                                        dialog.close();
                                    }
                                }
                            ]
                        });
                    } else {
                        jDialog.dialog({
                            title: "提示信息",
                            modal: true,// 非模态,即不显示遮罩层
                            autoClose: 1500,
                            content: "设定的漫游路线不存在,请绘制再保存"
                        });
                    }
                });
                //关闭界面
                $("#fly3DClose").click(function () {
                    var $fly3DPaths = $("#fly3DPaths");
                    bxmap.FlyCesium.clearFly3DPaths();
                    $fly3DPaths.hide(1000, function () {
                        $fly3DPaths.remove();
                    });
                });
            },
            //飞行路径列表表格监听事件
            flyTableOnclick: function () {
                $("#overFly_table td").click(function () {
                    var trSeq = $(this).parent().parent().find("tr").index($(this).parent());//选中的哪行
                    var geojson = $("#overFly_table tr:gt(0):eq(" + trSeq + ") td:eq(5)").text();//获取选中行的geojson列值
                    var name = $("#overFly_table tr:gt(0):eq(" + trSeq + ") td:eq(0)").text();//获取选中行的name列值
                    var id = $("#overFly_table tr:gt(0):eq(" + trSeq + ") td:eq(4)").text();//获取选中行的id列值
                    geojson = eval("(" + geojson + ")");
                    var tdSeq = $(this).parent().find("td").index($(this));//选中哪一列
                    switch (tdSeq) {
                        case 0://名称
                            break;
                        case 1://飞行
                            bxmap.FlyCesium.draw3DObj = geojson;
                            //bxmap.FlyCesium.cesium.showFly3DPaths(geojson);
                            bxmap.FlyCesium.showFly3DPaths(geojson);
                            $("#drawFlyCilck").click();
                            break;
                        case 2://修改
                            jDialog.dialog({
                                title: '修改路线',
                                content: '<div><span>名称:</span><input type="text" id="Fly_name" value="' + name + '"></div>',
                                width: 300,
                                height: 120,
                                modal: true,// 非模态,即不显示遮罩层
                                buttons: [
                                    {
                                        text: '确定',
                                        handler: function (button, dialog) {
                                            bxmap.FlyCesium.data = bxmap.FlyCesium.modifyElement(bxmap.FlyCesium.data, id, $("#Fly_name").val());
                                            $("#overFlyClick").click();
                                            dialog.close();
                                        }
                                    }, {
                                        text: '取消',
                                        handler: function (button, dialog) {
                                            dialog.close();
                                        }
                                    }
                                ]
                            });
                            break;
                        case 3://删除
                            //删除
                            jDialog.dialog({
                                title: '删除路线',
                                modal: true,// 非模态,即不显示遮罩层
                                content: "确定要删除该漫游路线?",
                                buttons: [
                                    {
                                        text: '确定',
                                        handler: function (button, dialog) {
                                            bxmap.FlyCesium.data = bxmap.FlyCesium.delElement(bxmap.FlyCesium.data, id);
                                            $("#overFlyClick").click();
                                            dialog.close();
                                        }
                                    }, {
                                        text: '取消',
                                        handler: function (button, dialog) {
                                            dialog.close();
                                        }
                                    }
                                ]
                            });
                            break;
                    }
                })
            },
            /**
             * 从数组中移除指定的元素,要是存在的话
             @ serviceArray筛选数组
             @ id移除元素id
             */
            delElement: function (serviceArray, id) {
                var array = [];
                for (var i = 0; i < serviceArray.length; i++) {
                    if (serviceArray[i].id !== id) {
                        array.push(serviceArray[i]);
                    }
                }
                return array;
            },
            /**
             * 从数组中修改指定的元素,要是存在的话
             @ serviceArray筛选数组
             @ id修改元素id
             @ name修改元素名称
             */
            modifyElement: function (serviceArray, id, name) {
                var array = [];
                for (var i = 0; i < serviceArray.length; i++) {
                    if (serviceArray[i].id === id) {
                        serviceArray[i].name = name;
                    }
                    array.push(serviceArray[i]);
                }
                return array;
            },
            loadData: function () {
                var data = bxmap.FlyCesium.data;
                var html = '';
                var $overFly_table = $('#overFly_table');
                if (data.length >= 0) {
                    for (var i = 0; i < data.length; i++) {
                        var flydata = data[i];
                        html += '<tr>' +
                            '<td><a style="color:#fff;text-decoration:none;font-size:12px;">' + flydata.name + '</a></td>' +
                            '<td><button class="btn btn-default btn-xs" style="color:#fff;">飞行</button></td>' +
                            '<td><button class="btn btn-default btn-xs" style="color:#fff;">修改</button></td>' +
                            '<td><button class="btn btn-default btn-xs" style="color:#fff;">删除</button></td>' +
                            "<td><a style='color:black;text-decoration:none;font-size:13px;'>" + flydata.id + "</a></td>" +
                            "<td><a style='color:black;text-decoration:none;font-size:13px;'>" + flydata.geojson + "</a></td>" +
                            "<td><a style='color:black;text-decoration:none;font-size:13px;'>" + flydata.position + "</a></td>" +
                            "<td><a style='color:black;text-decoration:none;font-size:13px;'>" + flydata.orientation + "</a></td>" +
                            '</tr>';
                    }
                    $("#overFly_table tbody").html(html);
                    $overFly_table.find('td:eq(4)').hide();//隐藏id字段列
                    $overFly_table.find('td:eq(5)').hide();//隐藏geojson字段列
                    $overFly_table.find('td:eq(6)').hide();//隐藏position字段列
                    $overFly_table.find('td:eq(7)').hide();//隐藏orientation字段列
                    //表格---行点击事件
                    bxmap.FlyCesium.flyTableOnclick();
                }
            },
            /**
         * 清空漫游路径
         * @method stopFly3DPaths
         * @return
         */
            clearFly3DPaths: function () {
                this.cesiumViewer.trackedEntity = undefined;
                bxmap.FlyCesium.isDrawFly = false;
                bxmap.FlyCesium.draw3DObj = null;
                this.cesiumViewer.entities.removeAll();//清空所有模型
                //清空绘制飞行路线
                if (this.drawPolyline) {
                    this.cesiumViewer.scene.primitives.remove(this.drawPolyline);
                    this.drawPolyline = null;
                }
            },
            /**
             * 飞行漫游路径
             * @param pathsData
             */
            showFly3DPaths: function (pathsData) {
                var T = this;
                this.clearFly3DPaths();
                T.cesiumViewer.camera.setView({
                    destination: pathsData.position,
                    orientation: pathsData.orientation,
                });
                setTimeout(function () {
                    executeFly3D();
                }, 200);
                function executeFly3D() {
                    if (pathsData && pathsData.geometry) {
                        var positionA = pathsData.geometry.coordinates;
                        var position = [];
                        if (positionA.length > 0) {
                            for (var i = 0; i < positionA.length; i++) {
                                var x = positionA[i][0];
                                var y = positionA[i][1];
                                position.push({ x: x, y: y });
                            }
                        } else {
                            return;
                        }
                        function computeCirclularFlight() {
                            var property = new Cesium.SampledPositionProperty();
                            for (var i = 0; i < position.length; i++) {
                                if (i === 0) {
                                    var time = Cesium.JulianDate.addSeconds(start, i, new Cesium.JulianDate());
                                    //var _position = Cesium.Cartesian3.fromDegrees(position[i].x, position[i].y, 1170);
                                    var _position = Cesium.Cartesian3.fromDegrees(position[i].x, position[i].y, 0);
                                    property.addSample(time, _position);
                                }
                                if (i < 10000 && i > 0) {
                                    var position_a = new Cesium.Cartesian3(property._property._values[i * 3 - 3], property._property._values[i * 3 - 2], property._property._values[i * 3 - 1]);
                                    if (i < 976) {
                                        var _position = Cesium.Cartesian3.fromDegrees(position[i].x, position[i].y, 0);
                                    }
                                    else if (i > 975 && i < 986) {
                                        var _position = Cesium.Cartesian3.fromDegrees(position[i].x, position[i].y, 0);
                                    }
                                    else if (i > 985) {
                                        var _position = Cesium.Cartesian3.fromDegrees(position[i].x, position[i].y, 0);
                                    }
                                    var positions = [Cesium.Ellipsoid.WGS84.cartesianToCartographic(position_a), Cesium.Ellipsoid.WGS84.cartesianToCartographic(_position)];
                                    var a = new Cesium.EllipsoidGeodesic(positions[0], positions[1]);
                                    var long = a.surfaceDistance;
                                    var _time = long / 50;
                                    var time = Cesium.JulianDate.addSeconds(property._property._times[i - 1], _time, new Cesium.JulianDate());
                                    property.addSample(time, _position);
                                }
                            }
                            return property;
                        }
                        var start = Cesium.JulianDate.fromDate(new Date());
                        var stop = Cesium.JulianDate.addSeconds(start, 30000, new Cesium.JulianDate());
                        T.cesiumViewer.clock.startTime = start.clone();
                        T.cesiumViewer.clock.stopTime = stop.clone();
                        T.cesiumViewer.clock.currentTime = start.clone();
                        T.cesiumViewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
                        T.cesiumViewer.clock.multiplier = 5;//值越大,飞行越快
                        T.cesiumViewer.clock.canAnimate = false;
                        T.cesiumViewer.clock.shouldAnimate = true;//设置时间轴动态效果
                        var _position = computeCirclularFlight();
                        T.entityFly = T.cesiumViewer.entities.add({
                            availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
                                start: start,
                                stop: stop
                            })]),
                            position: _position,
                            orientation: new Cesium.VelocityOrientationProperty(_position),
                            point: {
                                color: Cesium.Color.RED,
                                outlineColor: Cesium.Color.WHITE,
                                outlineWidth: 2,
                                pixelSize: 15,
                            },
                            //Show the path as a pink line sampled in 1 second increments.
                            path: {
                                resolution: 1,
                                material: new Cesium.PolylineGlowMaterialProperty({
                                    glowPower: 0.1,
                                    color: Cesium.Color.YELLOW
                                }),
                                //width: 30
                                width: 10
                            }
                        });
                        T.cesiumViewer.trackedEntity = T.entityFly;
                        setTimeout(function () {
                            T.cesiumViewer.camera.zoomOut(500.0);//缩小地图,避免底图没有数据
                        }, 100);
                    } else {
                        return;
                    }
                }
            },
            /**
         * 暂停飞行漫游路径
         * @method pauseFly3DPaths
         * @return
         */
            pauseFly3DPaths: function () {
                var clockViewModel = this.cesiumViewer.clockViewModel;
                if (clockViewModel.shouldAnimate) {
                    clockViewModel.shouldAnimate = false;
                } else if (this.cesiumViewer.clockViewModel.canAnimate) {
                    clockViewModel.shouldAnimate = true;
                }
            },
            /**
           * 向前飞行漫游路径
           * @method playForwardFly3DPaths
           * @return
           */
            playForwardFly3DPaths: function () {
                var clockViewModel = this.cesiumViewer.clockViewModel;
                var multiplier = clockViewModel.multiplier;
                if (multiplier < 0) {
                    clockViewModel.multiplier = -multiplier;
                }
                clockViewModel.shouldAnimate = true;
            },
            /**
             * 向后飞行漫游路径
             * @method playForwardFly3DPaths
             * @return
             */
            playReverseFly3DPaths: function () {
                var clockViewModel = this.cesiumViewer.clockViewModel;
                var multiplier = clockViewModel.multiplier;
                if (multiplier > 0) {
                    clockViewModel.multiplier = -multiplier;
                }
                clockViewModel.shouldAnimate = true;
            },
            /**
          * 设定飞行漫游路径
          * @method DrawFly3DPaths
          * @return
          */
            DrawFly3DPaths: function (drawHelper) {
                var T = this;
                this.clearFly3DPaths();
                drawHelper.startDrawingPolyline({
                    callback: function (positions) {
                        T.drawPolyline = new DrawHelper.PolylinePrimitive({
                            positions: positions,
                            width: 5,
                            type: "plot",
                            geodesic: true
                        });
                        T.cesiumViewer.scene.primitives.add(T.drawPolyline);
                        T.drawPolyline.setEditable();
                        //构造设定路线的返回信息
                        var coordinates = [];
                        var position = null;
                        var heading = null;
                        var pitch = null;
                        var roll = null;
                        for (var i = 0; i < positions.length; i++) {
                            var cartographic = Cesium.Cartographic.fromCartesian(positions[i]);//世界坐标转地理坐标(弧度)
                            var point = [cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180];//地理坐标(弧度)转经纬度坐标
                            //console.log(point);
                            coordinates.push(point);
                        }
                        //orientation":{"heading":2.411783930363565,"pitch":-0.21097267398444197,"roll":0.0015622392231300353},"position": {"x":-2206260.239730831,"y":5510911.392077349,"z":2331987.10863007},
                        position = drawHelper._cameraPosition;
                        heading = drawHelper._cameraHeading;
                        pitch = drawHelper._cameraPitch;
                        roll = drawHelper._cameraRoll;
                        var pathsData = { "orientation": { "heading": heading, "pitch": pitch, "roll": roll }, "position": position, "geometry": { "type": "LineString", "coordinates": coordinates } };
                        if (bxmap.FlyCesium) {
                            bxmap.FlyCesium.draw3DObj = T.draw3DObj = pathsData;
                            bxmap.FlyCesium.isDrawFly = true;
                        }
                        //return T.draw3DObj;
                    }
                });
            },
            /**
         * 退出飞行漫游路径
         * @method stopFly3DPaths
         * @return
         */
            stopFly3DPaths: function () {
                var start = Cesium.JulianDate.fromDate(new Date());
                this.cesiumViewer.clock.startTime = start.clone();
                var stop = Cesium.JulianDate.addSeconds(start, 300000000, new Cesium.JulianDate());
                this.cesiumViewer.clock.stopTime = stop.clone();
                //this.cesiumViewer.entities.remove(this.entityFly);
                this.clearFly3DPaths();
            },
        };
    </script>
</body>
</html>
widgets/visibleArea/Widget.js
@@ -261,6 +261,7 @@
                            viewshed3D.setDistDirByPoint([longitude, latitude, height]);
                        }
                    }
                    // handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
                }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                handler.setInputAction(function (e) {