1/** @license 2 * 3 * Copyright (C) 2012 K. Arthur Endsley ([email protected]) 4 * Michigan Tech Research Institute (MTRI) 5 * 3600 Green Court, Suite 100, Ann Arbor, MI, 48105 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22/** 23 * @augments Wkt.Wkt 24 * A framework-dependent flag, set for each Wkt.Wkt() instance, that indicates 25 * whether or not a closed polygon geometry should be interpreted as a rectangle. 26 */ 27(function (root, factory) { 28 if (typeof exports === 'object') { 29 // CommonJS 30 module.exports = factory(require('./wicket')); 31 } else if (typeof define === 'function' && define.amd) { 32 // AMD. Register as an anonymous module. 33 define(['wicket'], factory); 34 } else { 35 // Browser globals 36 factory(root.Wkt); 37 } 38} 39 (this, function (Wkt) { 40 Wkt.Wkt.prototype.isRectangle = false; 41 42 /** 43 * @augments Wkt.Wkt 44 * Truncates an Array of coordinates by the closing coordinate when it is 45 * equal to the first coordinate given--this is only to be used for closed 46 * geometries in order to provide merely an "implied" closure to Leaflet. 47 * @param coords {Array} An Array of x,y coordinates (objects) 48 * @return {Array} 49 */ 50 Wkt.Wkt.prototype.trunc = function (coords) { 51 var i, verts = []; 52 53 for (i = 0; i < coords.length; i += 1) { 54 if (Wkt.isArray(coords[i])) { 55 verts.push(this.trunc(coords[i])); 56 57 } else { 58 59 // Add the first coord, but skip the last if it is identical 60 if (i === 0 || !this.sameCoords(coords[0], coords[i])) { 61 verts.push(coords[i]); 62 } 63 } 64 } 65 66 return verts; 67 }; 68 69 /** 70 * @augments Wkt.Wkt 71 * An object of framework-dependent construction methods used to generate 72 * objects belonging to the various geometry classes of the framework. 73 */ 74 Wkt.Wkt.prototype.construct = { 75 /** 76 * Creates the framework's equivalent point geometry object. 77 * @param config {Object} An optional properties hash the object should use 78 * @param component {Object} An optional component to build from 79 * @return {L.marker} 80 */ 81 point: function (config, component) { 82 var coord = component || this.components; 83 if (coord instanceof Array) { 84 coord = coord[0]; 85 } 86 87 return L.marker(this.coordsToLatLng(coord), config); 88 }, 89 90 /** 91 * Creates the framework's equivalent multipoint geometry object. 92 * @param config {Object} An optional properties hash the object should use 93 * @return {L.featureGroup} 94 */ 95 multipoint: function (config) { 96 var i, 97 layers = [], 98 coords = this.components; 99 100 for (i = 0; i < coords.length; i += 1) { 101 layers.push(this.construct.point.call(this, config, coords[i])); 102 } 103 104 return L.featureGroup(layers, config); 105 }, 106 107 /** 108 * Creates the framework's equivalent linestring geometry object. 109 * @param config {Object} An optional properties hash the object should use 110 * @param component {Object} An optional component to build from 111 * @return {L.polyline} 112 */ 113 linestring: function (config, component) { 114 var coords = component || this.components, 115 latlngs = this.coordsToLatLngs(coords, 0, this.coordsToLatLng); 116 117 return L.polyline(latlngs, config); 118 }, 119 120 /** 121 * Creates the framework's equivalent multilinestring geometry object. 122 * @param config {Object} An optional properties hash the object should use 123 * @return {L.multiPolyline} 124 */ 125 multilinestring: function (config) { 126 var coords = this.components, 127 latlngs = this.coordsToLatLngs(coords, 1, this.coordsToLatLng); 128 129 if (L.multiPolyline) { 130 return L.multiPolyline(latlngs, config); 131 } 132 else { 133 return L.polyline(latlngs, config); 134 } 135 }, 136 137 /** 138 * Creates the framework's equivalent polygon geometry object. 139 * @param config {Object} An optional properties hash the object should use 140 * @return {L.multiPolygon} 141 */ 142 polygon: function (config) { 143 // Truncate the coordinates to remove the closing coordinate 144 var coords = this.trunc(this.components), 145 latlngs = this.coordsToLatLngs(coords, 1, this.coordsToLatLng); 146 return L.polygon(latlngs, config); 147 }, 148 149 /** 150 * Creates the framework's equivalent multipolygon geometry object. 151 * @param config {Object} An optional properties hash the object should use 152 * @return {L.multiPolygon} 153 */ 154 multipolygon: function (config) { 155 // Truncate the coordinates to remove the closing coordinate 156 var coords = this.trunc(this.components), 157 latlngs = this.coordsToLatLngs(coords, 2, this.coordsToLatLng); 158 159 if (L.multiPolygon) { 160 return L.multiPolygon(latlngs, config); 161 } 162 else { 163 return L.polygon(latlngs, config); 164 } 165 }, 166 167 /** 168 * Creates the framework's equivalent collection of geometry objects. 169 * @param config {Object} An optional properties hash the object should use 170 * @return {L.featureGroup} 171 */ 172 geometrycollection: function (config) { 173 var comps, i, layers; 174 175 comps = this.trunc(this.components); 176 layers = []; 177 for (i = 0; i < this.components.length; i += 1) { 178 layers.push(this.construct[comps[i].type].call(this, comps[i])); 179 } 180 181 return L.featureGroup(layers, config); 182 } 183 }; 184 185 L.Util.extend(Wkt.Wkt.prototype, { 186 coordsToLatLngs: L.GeoJSON.coordsToLatLngs, 187 // TODO Why doesn't the coordsToLatLng function in L.GeoJSON already suffice? 188 coordsToLatLng: function (coords, reverse) { 189 var lat = reverse ? coords.x : coords.y,
190 lng = reverse ? coords.y : coords.x; 191 192 return L.latLng(lat, lng, true); 193 } 194 }); 195 196 /** 197 * @augments Wkt.Wkt 198 * A framework-dependent deconstruction method used to generate internal 199 * geometric representations from instances of framework geometry. This method 200 * uses object detection to attempt to classify members of framework geometry 201 * classes into the standard WKT types. 202 * @param obj {Object} An instance of one of the framework's geometry classes 203 * @return {Object} A hash of the 'type' and 'components' thus derived 204 */ 205 Wkt.Wkt.prototype.deconstruct = function (obj) { 206 var attr, coordsFromLatLngs, features, i, verts, rings, tmp; 207 208 /** 209 * Accepts an Array (arr) of LatLngs from which it extracts each one as a 210 * vertex; calls itself recursively to deal with nested Arrays. 211 */ 212 coordsFromLatLngs = function (arr) { 213 var i, coords; 214 215 coords = []; 216 for (i = 0; i < arr.length; i += 1) { 217 if (Wkt.isArray(arr[i])) { 218 coords.push(coordsFromLatLngs(arr[i])); 219 220 } else { 221 coords.push({ 222 x: arr[i].lng, 223 y: arr[i].lat 224 }); 225 } 226 } 227 228 return coords; 229 }; 230 231 // L.Marker //////////////////////////////////////////////////////////////// 232 if (obj.constructor === L.Marker || obj.constructor === L.marker) { 233 return { 234 type: 'point', 235 components: [{ 236 x: obj.getLatLng().lng, 237 y: obj.getLatLng().lat 238 }] 239 }; 240 } 241 242 // L.Rectangle ///////////////////////////////////////////////////////////// 243 if (obj.constructor === L.Rectangle || obj.constructor === L.rectangle) { 244 tmp = obj.getBounds(); // L.LatLngBounds instance 245 return { 246 type: 'polygon', 247 isRectangle: true, 248 components: [ 249 [ 250 { // NW corner
251 x: tmp.getSouthWest().lng, 252 y: tmp.getNorthEast().lat 253 }, 254 { // NE corner 255 x: tmp.getNorthEast().lng, 256 y: tmp.getNorthEast().lat 257 }, 258 { // SE corner 259 x: tmp.getNorthEast().lng, 260 y: tmp.getSouthWest().lat 261 }, 262 { // SW corner 263 x: tmp.getSouthWest().lng, 264 y: tmp.getSouthWest().lat 265 }, 266 { // NW corner (again, for closure) 267 x: tmp.getSouthWest().lng, 268 y: tmp.getNorthEast().lat 269 } 270 ] 271 ] 272 }; 273 274 } 275 276 // L.Polyline ////////////////////////////////////////////////////////////// 277 if (obj.constructor === L.Polyline || obj.constructor === L.polyline) { 278 verts = []; 279 tmp = obj.getLatLngs(); 280 281 if (!tmp[0].equals(tmp[tmp.length - 1])) { 282 283 for (i = 0; i < tmp.length; i += 1) { 284 verts.push({ 285 x: tmp[i].lng, 286 y: tmp[i].lat 287 }); 288 } 289 290 return { 291 type: 'linestring', 292 components: verts 293 }; 294 295 } 296 } 297 298 // L.Polygon /////////////////////////////////////////////////////////////// 299 300 if (obj.constructor === L.Polygon || obj.constructor === L.polygon) { 301 rings = []; 302 verts = []; 303 boundary = obj.getLatLngs()[0]; 304 305 // First, we deal with the boundary points 306 for (i = 0; i < boundary.length; i += 1) { 307 verts.push({ // Add the first coordinate again for closure 308 x: boundary[i].lng, 309 y: boundary[i].lat 310 }); 311 } 312 313 verts.push({ // Add the first coordinate again for closure 314 x: boundary[0].lng, 315 y: boundary[0].lat 316 }); 317 318 rings.push(verts); 319 320 // Now, any holes 321 if (obj._holes && obj._holes.length > 0) { 322 // Reworked to support holes properly 323 verts = coordsFromLatLngs(obj._holes); 324 for (i = 0; i < verts.length; i++) { 325 verts[i].push(verts[i][0]); // Copy the beginning coords again for closure 326 rings.push(verts[i]); 327 } 328 } 329 330 return { 331 type: 'polygon', 332 components: rings 333 }; 334 335 } 336 337 // L.MultiPolyline ///////////////////////////////////////////////////////// 338 // L.MultiPolygon ////////////////////////////////////////////////////////// 339 // L.LayerGroup //////////////////////////////////////////////////////////// 340 // L.FeatureGroup ////////////////////////////////////////////////////////// 341 if (obj.constructor === L.MultiPolyline || obj.constructor === L.MultiPolygon 342 || obj.constructor === L.LayerGroup || obj.constructor === L.FeatureGroup) { 343 344 features = []; 345 tmp = obj._layers; 346 347 for (attr in tmp) { 348 if (tmp.hasOwnProperty(attr)) { 349 if (tmp[attr].getLatLngs || tmp[attr].getLatLng) { 350 // Recursively deconstruct each layer 351 features.push(this.deconstruct(tmp[attr])); 352 } 353 } 354 } 355 356 return { 357 358 type: (function () { 359 switch (obj.constructor) { 360 case L.MultiPolyline: 361 return 'multilinestring'; 362 case L.MultiPolygon: 363 return 'multipolygon'; 364 case L.FeatureGroup: 365 return (function () { 366 var i, mpgon, mpline, mpoint; 367 368 // Assume that all layers are of one type (any one type) 369 mpgon = true; 370 mpline = true; 371 mpoint = true; 372 373 for (i in obj._layers) { 374 if (obj._layers.hasOwnProperty(i)) { 375 if (obj._layers[i].constructor !== L.Marker) { 376 mpoint = false; 377 } 378 if (obj._layers[i].constructor !== L.Polyline) { 379 mpline = false; 380 } 381 if (obj._layers[i].constructor !== L.Polygon) { 382 mpgon = false; 383 } 384 } 385 } 386 387 if (mpoint) { 388 return 'multipoint'; 389 } 390 if (mpline) { 391 return 'multilinestring'; 392 } 393 if (mpgon) { 394 return 'multipolygon'; 395 } 396 return 'geometrycollection'; 397 398 }()); 399 default: 400 return 'geometrycollection'; 401 } 402 }()), 403 404 components: (function () { 405 // Pluck the components from each Wkt 406 var i, comps; 407 408 comps = []; 409 for (i = 0; i < features.length; i += 1) { 410 if (features[i].components) { 411 comps.push(features[i].components); 412 } 413 } 414 415 return comps; 416 }()) 417 418 }; 419 420 } 421
422 // L.Circle //////////////////////////////////////////////////////////////// 423 if (obj.constructor === L.Circle || obj.constructor === L.circle) { 424 console.log('Deconstruction of L.Circle objects is not yet supported'); 425 426 } else { 427 console.log('The passed object does not have any recognizable properties.'); 428 } 429 430 }; 431 432 return Wkt; 433 }));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.