赣州市洪水风险预警系统二维版本
xiebin
2023-03-02 b39483c96ae572121d3c619c0b9d37634e682cc4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/**
 * @name Extruded Feature Layer 
 * @author: Nianwei Liu 
 * @fileoverview
 * A canvas based ESRI ArcGIS Server JavaScript API ported from Open Streem Map Buildings.(osmbuildings.org).
 */
 
/*(function() {
  if (!window.OSMBuildings) {
    // only include minimal filters: invert and desaturate. If need more, include the pixastic.all.js in header before require this.
    var src = dojo.moduleUrl("agsjs", "osm/OSMBuildings.js");
    var s = dojo.create("script", {
      type: "text/javascript",
      src: src
    });
    dojo.doc.getElementsByTagName("head")[0].appendChild(s);
  }
}());
*/
// ********* end of osm *******************/
dojo.provide("agsjs.layers.ExtrudedFeatureLayer");
 
dojo.addOnLoad(function() {
   dojo.declare("agsjs.layers.ExtrudedFeatureLayer", esri.layers.Layer, {
     _osmb: null,
     _canvas: null,
     _tileInfo: null,
     _mode: 0,// ON_DEMAND|SNAPSHOT
    _heightAttribute: '',
    _oidField: null,// will be overridden from meta query
    _query: null,
    _task: null,
    _oids: null, //track current objectids to mark new/old for animation fade in
    _featureExt: null,//current feature extent, 1.5 map extent
    _suspendOnPan: false,//whether to suspend drawing during map panning. default is false. set to true if performance is not optimal (non-Chrome browsers);
   /**
   * @name ExtrudedFeatureLayerOptions
   * @class This is an object literal that specify the options for each ExtrudedFeatureLayer.
   * @property {string} heightAttribute required. name of the attribute for height;
   * @property {number} defaultHeight optional. default Height to use if the height value is 0. default=0;
   * @property {number} heightScaleRatio optional. number used to multiple the value from service. default=1;
   * @property {number} extentScaleRatio optional. extra buffer on map extent to load features to reduce server traffic. default=1.5;
   * @property {int} [mode] optional. agsjs.layers.ExtrudedFeatureLayer.MODE_ONDEMAND | MODE_SNAPSHOT. default=ON_DEMAND
   * @property {esri.tasks.Query} [query] optional. query set on the feature layer for retrieving data.
   * @property {Object} [style] object with color, roofColor (#ffcc00' 'rgb(255,200,200)' 'rgba(255,200,200,0.9)), strokeRoofs (boolean)
   */
    /** 
   * Create an ExtrudedFeatureLayer
   * @name ExtrudedFeatureLayer
   * @constructor
   * @class This class is a ExtrudedFeatureLayer, such as a polygon feature layer with a height attribute.
   * @param {string||FeatureCollection} url
   * @param {ExtrudedFeatureLayerOptions} opts
   */
    constructor: function(url, opts) {
      // Manually call superclass constructor with required arguments
      if (!(!!document.createElement('canvas').getContext)){
        throw new Error('Canvas unsupported. Try different browser');
      }
      this.inherited(arguments);
      var opts = opts || {};
      this._heightAttribute = opts.heightAttribute;
      this._mode = opts.mode || agsjs.layers.ExtrudedFeatureLayer.MODE_ONDEMAND;
      this._heightScaleRatio = opts.heightScaleRatio || 1;
      this._extentScaleRatio = opts.extentScaleRatio || 1.5;
      this._defaultHeight = opts.defaultHeight || 0;
      this._style = opts.style;
      // Deal with feature collection
      if (dojo.isObject(url) && url.featureSet) {
        this._mode = agsjs.layers.ExtrudedFeatureLayer.MODE_SNAPSHOT;
        this._setFeatures(url.featureSet.features);
        this.loaded = true;
        this.onLoad(this);
      } else {
        this._url = url;
        // get meta data for layer
        new esri.request({
          url: this._url,
          content: {
            f: "json"
          },
          callbackParamName: "callback"
        }).then(dojo.hitch(this, this._initLayer));
        this._query = new esri.tasks.Query();
        dojo.mixin(this._query, opts.query);
        dojo.mixin(this._query, {
          returnGeometry: true,
          outSpatialReference: {
            "wkid": 4326
          }
        });
        this._task = new esri.tasks.QueryTask(url);
        dojo.connect(this._task, 'onComplete', dojo.hitch(this, this._onQueryComplete));
        dojo.connect(this._task, 'onError', esri.config.defaults.io.errorHandler);
      }
    },
    /**********************
   * @see http://help.arcgis.com/en/webapi/javascript/arcgis/samples/exp_rasterlayer/javascript/RasterLayer.js
   * Internal Properties
   *
   * _map
   * _element
   * _context
   * _mapWidth
   * _mapHeight
   * _connects
   *
   **********************/
    //esri.layers.Layer.method
    _setMap: function(map, container, ind, lod) {
      this._map = map;
      
      var element = dojo.create("div", {
        width: map.width + "px",
        height: map.height + "px",
        style: "position: absolute; left: 0px; top: 0px;"
      }, container);
      this._osmb = new OSMBuildings();
      // allow attribution widget to add copyright text
      this.suspended = false;
      this.copyright=OSMBuildings.ATTRIBUTION+","+this.copyrightText;
      
      this._element = element;
      this._canvas = this._osmb.createCanvas(element);
      this._osmb.setSize(map.width, map.height);
      // calc orgins
      //9241483,13264618
      if (map.layerIds.length == 0 || !map.getLayer(map.layerIds[0]).tileInfo) {
        throw new Error('must have at least one tiled layer added before this layer');
      }
      this._tileInfo = map.getLayer(map.layerIds[0]).tileInfo;
      this._osmb.setZoom(map.getLevel()); // ! assume basemap is tiled.
      this._setOrigin();
      
      
      //
      this._loadData();
      // Event connections
      this._connects = [];
      this._connects.push(dojo.connect(map, "onResize", this, this._onResize));
      this._connects.push(dojo.connect(map, "onPan", this, this._onPan));
      this._connects.push(dojo.connect(map, "onExtentChange", this, this._onExtentChange));
      this._connects.push(dojo.connect(map, "onZoomStart", this, this._onZoomStart));
      return element;
    },
    // esri.layers.Layer.method
    _unsetMap: function(map, container) {
      this._osmb && this._osmb.destroyCanvas();
      this._osmb = null;
      dojo.forEach(this._connects, dojo.disconnect, dojo);
      if (this._element) {
        container.removeChild(this._element);
      }
      this._map = null;
      this._element = null;
    },
    _initLayer: function(json) {
      //dojo.mixin(this, json);
      this.setMinScale(json.minScale || 0);
      this.setMaxScale (json.maxScale || 0);
      this.copyrightText = json.copyrightText;
      dojo.some(json.fields, function(field, i) {
        if (field.type == 'esriFieldTypeOID') {
          this._oidField = field.name;
          return true;
        }
        return false;
      }, this);
      this._query.outFields = [this._oidField, this._heightAttribute];
      this.loaded = true;
      this.onLoad(this);
    },
    _setOrigin: function(dx, dy) {
      var resolution = this._tileInfo.lods[this._map.getLevel()].resolution; //map.getScale()/12/96/3.28084; //inch_pre_ft/px_per_in/ft_per_mt; 
      var topLeft = this._map.toMap(new esri.geometry.Point(0, 0));
      var x = Math.round((topLeft.x - this._tileInfo.origin.x) / resolution);
      var y = Math.round((this._tileInfo.origin.y - topLeft.y) / resolution);
      this._osmb.setOrigin(x+(dx||0), y+(dy||0));
      this._osmb.setSize(this._map.width, this._map.height);
      
    },
    _onResize: function(extent, width, height) {
      if (this._osmb) {
        this._osmb.setSize(width,height );
        this._osmb.render();
      };
    },
    _onPan: function(extent, delta) {
      if (this._suspendOnPan){
       dojo.style(this._canvas, {
        left: delta.x + "px",
        top: delta.y + "px"
       });
       //this._osmb.setCamOffset(-delta.x, -delta.y);
      } else {
        this._setOrigin(-delta.x, -delta.y);
        this._osmb.render();
      }
    },
    _onExtentChange: function(extent, delta, levelChange, lod) {
      dojo.style(this._canvas, {
        left: "0px",
        top: "0px"
      });
      this._setOrigin();
      this._osmb.setCamOffset(0, 0);
      if (levelChange) {
        this._osmb.onZoomEnd({
          zoom: this._map.getLevel()
        });
        
        if (this.isVisibleAtScale(this._map.getScale())) {
          this._loadData();
        } else {
          // clear canvas. Current OSMB does not handle null or {} as no feature.
          this._osmb.geoJSON({
            features: []
          });
        }
      } else {
        this._osmb.onMoveEnd();
        if (this._featureExt && !this._featureExt.contains(extent)) {
          this._loadData();
        };
      }
      
    },
    _onZoomStart: function(extent, zoomFactor, anchor, level) {
      // actually clear the 
      this._osmb.onZoomStart();
    },
    _setFeatures: function(features) {
      var oids = {};
      var jfs = [];
      this._oids = this._oids ||{};
      for (var i = 0; i < features.length; i++) {
        var f = features[i];
        
        var oid = f.attributes[this._oidField];
        var gj = {
          "type": "Feature",
          "geometry": {
            "type": "Polygon",
            "coordinates": f.geometry.rings
          },
          "properties": {
            "height": (f.attributes[this._heightAttribute] || this._defaultHeight) * this._heightScaleRatio,
            'isNew': !this._oids[oid]
          }
        }
        // find out the y coords range for sorting
        var minY = maxY = f.geometry.rings[0][0][1];
        for (var j = 0; j < f.geometry.rings.length;  j++){
          for (var k = 0; k < f.geometry.rings[j].length; k++){
            minY = Math.min(minY,f.geometry.rings[j][k][1] );
            maxY = Math.max(maxY,f.geometry.rings[j][k][1] );
          }
        }
        gj.minY = minY;
        gj.maxY = maxY;
        jfs[i] = gj;
        oids[oid] = f;
      }
      // sort features by height and y coord desc for potential drawing improvement
      jfs.sort(function (a, b){
       // if polygon a is completely north of b then put a first.
       // otherwise put the taller one first.
       // this ensures north/taller poly draw first
       if (a.maxY < b.minY){
          return 1;
        } else if (a.minY > b.maxY){
          return -1;
        } else {
          return b.properties.height - a.properties.height
        }
      });
      this._oids = oids;
      this._osmb.geoJSON({
        "type": "FeatureCollection",
        "features": jfs
      });
      if (this._style) {
        this._osmb.setStyle(this._style);
      }
    },
    _loadData: function() {
      if (this._mode == agsjs.layers.ExtrudedFeatureLayer.MODE_SNAPSHOT) {
        if (this._oids) {
          return;
        } else {
          this._query.geometry = null;
          this._query.where = this._query.where || '1=1';
          
        }
      } else {
        this._featureExt = this._map.extent.expand(this._extentScaleRatio);
        this._query.geometry = this._featureExt;
      }
      this._task.execute(this._query);
    },
    _onQueryComplete: function(featureSet) {
      this._setFeatures(featureSet.features);
    }
  });
   dojo.mixin(agsjs.layers.ExtrudedFeatureLayer, {
     MODE_ONDEMAND: 0,
     MODE_SNAPSHOT: 1
   });
});