├── .gitignore ├── .travis.yml ├── .zuul.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bower.json ├── cli.js ├── component.json ├── index.js ├── package.json ├── test ├── data │ ├── geometrycollection.geojson │ └── geometrycollection.wkt ├── fuzz.js ├── stringify.js └── wellknown.test.js └── wellknown.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | - '0.12' 5 | - 'iojs' 6 | sudo: false 7 | env: 8 | global: 9 | - secure: Xy1Jl53Yovuj9tProdpmMmPThyA+iBxQYhceOqb+1O9FX8+6/9ohrgN+yF7VqvwX5cLPiico7/NCbS/BG/yufuxK8nddc4hPOYR1zZlwz0j1QBGDRsRG8PK3DlOtxyNHJTiDkNGjrDeeuM31uxL2qErl9IpEbE+8qi1bswRpKi8= 10 | - secure: A39ISE6SAsqOCGJNV2UdqVlGEpg0VefYOw6qVuihksRIy5UoBtlmq1YzaXq0Q9Vd6TsYbMdEkBz5Zcok4+uZZIUpgvr90iMYpFHLWm2Qdr87X1PwSrTrce6nVfVUU9D/G0vZXd/LUyw0Lo8DngMHrUMaLuM9Vu10h9SXdDFMM+Y= 11 | -------------------------------------------------------------------------------- /.zuul.yml: -------------------------------------------------------------------------------- 1 | ui: tape 2 | transform: 3 | - transform: brfs 4 | browsers: 5 | - name: chrome 6 | version: latest 7 | - name: firefox 8 | version: latest 9 | - name: safari 10 | version: latest 11 | - name: opera 12 | version: latest 13 | - name: ie 14 | version: 10..latest 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 0.5.0 4 | 5 | * Add support for `Z` coordinates. 6 | 7 | ## 0.4.1 8 | 9 | * Support for [alternative MultiPoint syntax](https://github.com/mapbox/wellknown/pull/29) 10 | 11 | ## 0.4.0 12 | 13 | * Support for 4D geometries 14 | 15 | ## 0.3.1 16 | 17 | * Fix for coordinate arrays with incorrect lengths 18 | * Now uses semistandard for code formatting and tap for tests 19 | 20 | ## 0.3.0 21 | 22 | * Now parses WKT with exponent values for coordinates. 23 | 24 | ## 0.2.0 25 | 26 | * Introduces `.stringify(geojson)` 27 | 28 | ## 0.1.1 29 | 30 | * Fix issue with multicoords being overeager - fixes GeometryCollection cases 31 | 32 | ## 0.1.0 33 | 34 | * Added cli `wellknown` utility 35 | * Supports linebreaks in geometrycollections 36 | * Supports case-insensitive tags 37 | * Added rant to README 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Mapbox 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/mapbox/wellknown.svg?branch=master)](https://travis-ci.org/mapbox/wellknown) [![Coverage Status](https://coveralls.io/repos/mapbox/wellknown/badge.svg)](https://coveralls.io/r/mapbox/wellknown) 2 | 3 | # wellknown 4 | 5 | Parse & stringify [Well-Known Text](http://en.wikipedia.org/wiki/Well-known_text) into [GeoJSON](http://www.geojson.org/). 6 | 7 | Support 8 | 9 | * Point + MultiPoint 10 | * LineString + MultiLineString 11 | * Polygon + MultiPolygon 12 | * GeometryCollection 13 | * 2D, 3D, 4D geometries 14 | 15 | ## cli 16 | 17 | install: 18 | 19 | $ npm install -g wellknown 20 | 21 | use: 22 | 23 | $ echo "MultiPoint(0 0, 1 1, 3 3)" | wellknown > multipoint.geojson 24 | 25 | ## usage 26 | 27 | this is a node-style module that works in node.js via npm and in browsers via 28 | [browserify](https://github.com/substack/node-browserify) or a standalone package: 29 | 30 | **npm install**: 31 | 32 | npm install wellknown 33 | 34 | **bower install**: 35 | 36 | bower install wellknown --save 37 | 38 | **standalone**: 39 | 40 | wget https://raw.github.com/mapbox/wellknown/master/wellknown.js 41 | 42 | ## api 43 | 44 | ### `parse(wkt)` 45 | 46 | Given WKT as a string, return a GeoJSON [geometry object](http://geojson.org/geojson-spec.html#geometry-objects) 47 | or `null` if parse fails. 48 | 49 | ### `stringify(geojson)` 50 | 51 | Given a GeoJSON geometry object or Feature object, return a WKT representation 52 | as a string. Throws an error if given a `FeatureCollection` or unknown input. 53 | 54 | ## example 55 | 56 | ```js 57 | var parse = require('wellknown'); 58 | 59 | parse('POINT(1 2)'); 60 | ``` 61 | 62 | #### Integrating with Leaflet 63 | 64 | ```js 65 | // With Leaflet or MapBox.js 66 | var geojsonLayer = L.geoJson(parse('Point(1 2)')); 67 | ``` 68 | 69 | ## See Also 70 | 71 | * [wicket](https://github.com/arthur-e/Wicket) 72 | * [openlayers wkt](https://github.com/openlayers/openlayers/blob/master/lib/OpenLayers/Format/WKT.js) 73 | * [geomet](https://github.com/geomet/geomet) converts between GeoJSON and WKT in Python 74 | 75 | ## Rant 76 | 77 | The 'WKT Standard' is (mis)managed by the [OGC](http://www.opengeospatial.org/), 78 | and thus is available on page 52 of [this PDF](http://www.opengeospatial.org/standards/sfa). 79 | 80 | Given the inaccessibility of the standard, there are no direct reference to it 81 | in this code. 82 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wellknown", 3 | "description": "convert wkt to geojson", 4 | "version": "0.3.0", 5 | "license": "BSD", 6 | "keywords": [ 7 | "wkt", 8 | "geojson", 9 | "maps" 10 | ], 11 | "main": "wellknown.js" 12 | } 13 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var concat = require('concat-stream'), 4 | wellknown = require('./'), 5 | fs = require('fs'), 6 | argv = require('minimist')(process.argv.slice(2)); 7 | 8 | if (argv.help || argv.h || (!argv._.length && process.stdin.isTTY)) return help(); 9 | 10 | ((argv._[0] && fs.createReadStream(argv._[0])) || process.stdin).pipe(concat(openData)); 11 | 12 | function openData(body) { 13 | try { 14 | console.log(JSON.stringify(wellknown(body.toString()), null, 2)); 15 | } catch(e) { 16 | console.error('Valid GeoJSON file required as input.'); 17 | help(); 18 | } 19 | } 20 | 21 | function help() { 22 | process.stdout.write(fs.readFileSync(__dirname + '/README.md')); 23 | } 24 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wellknown", 3 | "description": "convert wkt to geojson", 4 | "version": "0.3.0", 5 | "license": "BSD", 6 | "keywords": [ 7 | "wkt", 8 | "geojson", 9 | "maps" 10 | ], 11 | "scripts": [ 12 | "index.js" 13 | ] 14 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable no-cond-assign */ 2 | module.exports = parse; 3 | module.exports.parse = parse; 4 | module.exports.stringify = stringify; 5 | 6 | var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/; 7 | // Matches sequences like '100 100' or '100 100 100'. 8 | var tuples = new RegExp('^' + numberRegexp.source + '(\\s' + numberRegexp.source + '){1,}'); 9 | 10 | /* 11 | * Parse WKT and return GeoJSON. 12 | * 13 | * @param {string} _ A WKT geometry 14 | * @return {?Object} A GeoJSON geometry object 15 | */ 16 | function parse (input) { 17 | var parts = input.split(';'); 18 | var _ = parts.pop(); 19 | var srid = (parts.shift() || '').split('=').pop(); 20 | 21 | var i = 0; 22 | 23 | function $ (re) { 24 | var match = _.substring(i).match(re); 25 | if (!match) return null; 26 | else { 27 | i += match[0].length; 28 | return match[0]; 29 | } 30 | } 31 | 32 | function crs (obj) { 33 | if (obj && srid.match(/\d+/)) { 34 | obj.crs = { 35 | type: 'name', 36 | properties: { 37 | name: 'urn:ogc:def:crs:EPSG::' + srid 38 | } 39 | }; 40 | } 41 | 42 | return obj; 43 | } 44 | 45 | function white () { $(/^\s*/); } 46 | 47 | function multicoords () { 48 | white(); 49 | var depth = 0; 50 | var rings = []; 51 | var stack = [rings]; 52 | var pointer = rings; 53 | var elem; 54 | 55 | while (elem = 56 | $(/^(\()/) || 57 | $(/^(\))/) || 58 | $(/^(,)/) || 59 | $(tuples)) { 60 | if (elem === '(') { 61 | stack.push(pointer); 62 | pointer = []; 63 | stack[stack.length - 1].push(pointer); 64 | depth++; 65 | } else if (elem === ')') { 66 | // For the case: Polygon(), ... 67 | if (pointer.length === 0) return null; 68 | 69 | pointer = stack.pop(); 70 | // the stack was empty, input was malformed 71 | if (!pointer) return null; 72 | depth--; 73 | if (depth === 0) break; 74 | } else if (elem === ',') { 75 | pointer = []; 76 | stack[stack.length - 1].push(pointer); 77 | } else if (!elem.split(/\s/g).some(isNaN)) { 78 | Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat)); 79 | } else { 80 | return null; 81 | } 82 | white(); 83 | } 84 | 85 | if (depth !== 0) return null; 86 | 87 | return rings; 88 | } 89 | 90 | function coords () { 91 | var list = []; 92 | var item; 93 | var pt; 94 | while (pt = 95 | $(tuples) || 96 | $(/^(,)/)) { 97 | if (pt === ',') { 98 | list.push(item); 99 | item = []; 100 | } else if (!pt.split(/\s/g).some(isNaN)) { 101 | if (!item) item = []; 102 | Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat)); 103 | } 104 | white(); 105 | } 106 | 107 | if (item) list.push(item); 108 | else return null; 109 | 110 | return list.length ? list : null; 111 | } 112 | 113 | function point () { 114 | if (!$(/^(point(\sz)?)/i)) return null; 115 | white(); 116 | if (!$(/^(\()/)) return null; 117 | var c = coords(); 118 | if (!c) return null; 119 | white(); 120 | if (!$(/^(\))/)) return null; 121 | return { 122 | type: 'Point', 123 | coordinates: c[0] 124 | }; 125 | } 126 | 127 | function multipoint () { 128 | if (!$(/^(multipoint)/i)) return null; 129 | white(); 130 | var newCoordsFormat = _ 131 | .substring(_.indexOf('(') + 1, _.length - 1) 132 | .replace(/\(/g, '') 133 | .replace(/\)/g, ''); 134 | _ = 'MULTIPOINT (' + newCoordsFormat + ')'; 135 | var c = multicoords(); 136 | if (!c) return null; 137 | white(); 138 | return { 139 | type: 'MultiPoint', 140 | coordinates: c 141 | }; 142 | } 143 | 144 | function multilinestring () { 145 | if (!$(/^(multilinestring)/i)) return null; 146 | white(); 147 | var c = multicoords(); 148 | if (!c) return null; 149 | white(); 150 | return { 151 | type: 'MultiLineString', 152 | coordinates: c 153 | }; 154 | } 155 | 156 | function linestring () { 157 | if (!$(/^(linestring(\sz)?)/i)) return null; 158 | white(); 159 | if (!$(/^(\()/)) return null; 160 | var c = coords(); 161 | if (!c) return null; 162 | if (!$(/^(\))/)) return null; 163 | return { 164 | type: 'LineString', 165 | coordinates: c 166 | }; 167 | } 168 | 169 | function polygon () { 170 | if (!$(/^(polygon(\sz)?)/i)) return null; 171 | white(); 172 | var c = multicoords(); 173 | if (!c) return null; 174 | return { 175 | type: 'Polygon', 176 | coordinates: c 177 | }; 178 | } 179 | 180 | function multipolygon () { 181 | if (!$(/^(multipolygon)/i)) return null; 182 | white(); 183 | var c = multicoords(); 184 | if (!c) return null; 185 | return { 186 | type: 'MultiPolygon', 187 | coordinates: c 188 | }; 189 | } 190 | 191 | function geometrycollection () { 192 | var geometries = []; 193 | var geometry; 194 | 195 | if (!$(/^(geometrycollection)/i)) return null; 196 | white(); 197 | 198 | if (!$(/^(\()/)) return null; 199 | while (geometry = root()) { 200 | geometries.push(geometry); 201 | white(); 202 | $(/^(,)/); 203 | white(); 204 | } 205 | if (!$(/^(\))/)) return null; 206 | 207 | return { 208 | type: 'GeometryCollection', 209 | geometries: geometries 210 | }; 211 | } 212 | 213 | function root () { 214 | return point() || 215 | linestring() || 216 | polygon() || 217 | multipoint() || 218 | multilinestring() || 219 | multipolygon() || 220 | geometrycollection(); 221 | } 222 | 223 | return crs(root()); 224 | } 225 | 226 | /** 227 | * Stringifies a GeoJSON object into WKT 228 | */ 229 | function stringify (gj) { 230 | if (gj.type === 'Feature') { 231 | gj = gj.geometry; 232 | } 233 | 234 | function pairWKT (c) { 235 | return c.join(' '); 236 | } 237 | 238 | function ringWKT (r) { 239 | return r.map(pairWKT).join(', '); 240 | } 241 | 242 | function ringsWKT (r) { 243 | return r.map(ringWKT).map(wrapParens).join(', '); 244 | } 245 | 246 | function multiRingsWKT (r) { 247 | return r.map(ringsWKT).map(wrapParens).join(', '); 248 | } 249 | 250 | function wrapParens (s) { return '(' + s + ')'; } 251 | 252 | switch (gj.type) { 253 | case 'Point': 254 | return 'POINT (' + pairWKT(gj.coordinates) + ')'; 255 | case 'LineString': 256 | return 'LINESTRING (' + ringWKT(gj.coordinates) + ')'; 257 | case 'Polygon': 258 | return 'POLYGON (' + ringsWKT(gj.coordinates) + ')'; 259 | case 'MultiPoint': 260 | return 'MULTIPOINT (' + ringWKT(gj.coordinates) + ')'; 261 | case 'MultiPolygon': 262 | return 'MULTIPOLYGON (' + multiRingsWKT(gj.coordinates) + ')'; 263 | case 'MultiLineString': 264 | return 'MULTILINESTRING (' + ringsWKT(gj.coordinates) + ')'; 265 | case 'GeometryCollection': 266 | return 'GEOMETRYCOLLECTION (' + gj.geometries.map(stringify).join(', ') + ')'; 267 | default: 268 | throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input'); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wellknown", 3 | "version": "0.5.0", 4 | "description": "convert wkt to geojson", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "semistandard index.js && tap --coverage test/*.js", 8 | "prepublish": "browserify -s wellknown index.js > wellknown.js" 9 | }, 10 | "bin": { 11 | "wellknown": "cli.js" 12 | }, 13 | "keywords": [ 14 | "wkt", 15 | "geojson", 16 | "maps" 17 | ], 18 | "author": "Tom MacWright", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/mapbox/wellknown.git" 22 | }, 23 | "license": "ISC", 24 | "devDependencies": { 25 | "fuzzer": "~0.2.0", 26 | "semistandard": "^8.0.0", 27 | "tap": "^6.2.0" 28 | }, 29 | "dependencies": { 30 | "concat-stream": "~1.5.0", 31 | "minimist": "~1.2.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/data/geometrycollection.geojson: -------------------------------------------------------------------------------- 1 | { 2 | "type": "GeometryCollection", 3 | "geometries": [ 4 | { 5 | "type": "LineString", 6 | "coordinates": [ 7 | [ 8 | 6308869.40378, 9 | 356821.22669 10 | ], 11 | [ 12 | 6308867.893, 13 | 356822.41744 14 | ], 15 | [ 16 | 6308852.75314, 17 | 356830.22159 18 | ], 19 | [ 20 | 6308869.92754, 21 | 356844.26638 22 | ] 23 | ] 24 | }, 25 | { 26 | "type": "LineString", 27 | "coordinates": [ 28 | [ 29 | 6308755.07971, 30 | 356674.51686 31 | ], 32 | [ 33 | 6308784.81355, 34 | 356719.16757 35 | ], 36 | [ 37 | 6308815.20022, 38 | 356765.46178 39 | ], 40 | [ 41 | 6308829.63774, 42 | 356763.22832 43 | ], 44 | [ 45 | 6308852.87023, 46 | 356759.82402 47 | ], 48 | [ 49 | 6308867.19982, 50 | 356771.06823 51 | ], 52 | [ 53 | 6308875.40631, 54 | 356796.20162 55 | ], 56 | [ 57 | 6308872.51907, 58 | 356815.17242 59 | ] 60 | ] 61 | }, 62 | { 63 | "type": "LineString", 64 | "coordinates": [ 65 | [ 66 | 6308874.12086, 67 | 356813.73392 68 | ], 69 | [ 70 | 6308876.83028, 71 | 356795.77697 72 | ], 73 | [ 74 | 6308868.23871, 75 | 356770.06254 76 | ], 77 | [ 78 | 6308853.09618, 79 | 356758.29456 80 | ], 81 | [ 82 | 6308815.86529, 83 | 356763.89689 84 | ], 85 | [ 86 | 6308799.76731, 87 | 356739.37835 88 | ], 89 | [ 90 | 6308747.77971, 91 | 356662.11613 92 | ], 93 | [ 94 | 6308746.55411, 95 | 356661.61702 96 | ], 97 | [ 98 | 6308744.06545, 99 | 356657.72563 100 | ], 101 | [ 102 | 6308731.77184, 103 | 356668.45076 104 | ], 105 | [ 106 | 6308699.45221, 107 | 356683.15463 108 | ], 109 | [ 110 | 6308682.44689, 111 | 356684.63193 112 | ], 113 | [ 114 | 6308654.96629, 115 | 356683.66846 116 | ], 117 | [ 118 | 6308636.13879, 119 | 356680.0482 120 | ], 121 | [ 122 | 6308618.19888, 123 | 356671.76352 124 | ], 125 | [ 126 | 6308608.41685, 127 | 356661.79428 128 | ], 129 | [ 130 | 6308578.7973, 131 | 356592.35062 132 | ], 133 | [ 134 | 6308545.33908, 135 | 356542.14886 136 | ], 137 | [ 138 | 6308517.52088, 139 | 356509.38474 140 | ], 141 | [ 142 | 6308505.40266, 143 | 356506.84141 144 | ], 145 | [ 146 | 6308493.59689, 147 | 356506.98067 148 | ], 149 | [ 150 | 6308375.07918, 151 | 356520.46209 152 | ] 153 | ] 154 | }, 155 | { 156 | "type": "LineString", 157 | "coordinates": [ 158 | [ 159 | 6308877.92941, 160 | 356819.50984 161 | ], 162 | [ 163 | 6309072.26249, 164 | 356514.14689 165 | ], 166 | [ 167 | 6309073.44938, 168 | 356513.3739 169 | ], 170 | [ 171 | 6309076.25423, 172 | 356511.31751 173 | ], 174 | [ 175 | 6309096.05004, 176 | 356528.52014 177 | ], 178 | [ 179 | 6309103.33938, 180 | 356535.32615 181 | ], 182 | [ 183 | 6309107.49584, 184 | 356539.20699 185 | ], 186 | [ 187 | 6309107.78601, 188 | 356539.47793 189 | ], 190 | [ 191 | 6309119.09139, 192 | 356550.03322 193 | ], 194 | [ 195 | 6309137.04465, 196 | 356567.13752 197 | ], 198 | [ 199 | 6309137.6323, 200 | 356567.69515 201 | ], 202 | [ 203 | 6309138.92096, 204 | 356568.91355 205 | ], 206 | [ 207 | 6309138.46355, 208 | 356569.69798 209 | ], 210 | [ 211 | 6309150.68532, 212 | 356566.34027 213 | ], 214 | [ 215 | 6309151.94333, 216 | 356567.03108 217 | ], 218 | [ 219 | 6309157.81557, 220 | 356565.41779 221 | ], 222 | [ 223 | 6309161.54152, 224 | 356564.33408 225 | ], 226 | [ 227 | 6309174.6464, 228 | 356579.77423 229 | ], 230 | [ 231 | 6309175.71622, 232 | 356581.0361 233 | ], 234 | [ 235 | 6309177.25892, 236 | 356582.84545 237 | ], 238 | [ 239 | 6309225.37695, 240 | 356611.76515 241 | ], 242 | [ 243 | 6309226.90588, 244 | 356612.65173 245 | ], 246 | [ 247 | 6309229.72021, 248 | 356614.34101 249 | ], 250 | [ 251 | 6309232.64678, 252 | 356598.75445 253 | ], 254 | [ 255 | 6309244.10246, 256 | 356528.49893 257 | ], 258 | [ 259 | 6309251.20809, 260 | 356487.90256 261 | ], 262 | [ 263 | 6309252.35489, 264 | 356481.34967 265 | ], 266 | [ 267 | 6309258.41778, 268 | 356442.34047 269 | ], 270 | [ 271 | 6309258.56036, 272 | 356441.19511 273 | ], 274 | [ 275 | 6309258.76115, 276 | 356440.13123 277 | ], 278 | [ 279 | 6309260.99127, 280 | 356426.22389 281 | ], 282 | [ 283 | 6309258.49745, 284 | 356425.57244 285 | ], 286 | [ 287 | 6309240.94882, 288 | 356422.48836 289 | ], 290 | [ 291 | 6309240.53276, 292 | 356422.37171 293 | ], 294 | [ 295 | 6309240.10958, 296 | 356422.29068 297 | ] 298 | ] 299 | }, 300 | { 301 | "type": "LineString", 302 | "coordinates": [ 303 | [ 304 | 6308870.96141, 305 | 356823.05522 306 | ], 307 | [ 308 | 6308881.43519, 309 | 356846.04558 310 | ], 311 | [ 312 | 6308859.94336, 313 | 356857.75024 314 | ], 315 | [ 316 | 6308859.6305, 317 | 356857.95378 318 | ], 319 | [ 320 | 6308893.96675, 321 | 356932.14467 322 | ], 323 | [ 324 | 6308921.19517, 325 | 356993.60222 326 | ], 327 | [ 328 | 6308942.68768, 329 | 357040.82051 330 | ], 331 | [ 332 | 6308961.42173, 333 | 357079.52481 334 | ], 335 | [ 336 | 6308976.48471, 337 | 357108.08898 338 | ], 339 | [ 340 | 6308992.14194, 341 | 357136.52543 342 | ], 343 | [ 344 | 6309018.60922, 345 | 357184.68892 346 | ], 347 | [ 348 | 6309024.87557, 349 | 357193.57884 350 | ], 351 | [ 352 | 6309025.31785, 353 | 357194.20629 354 | ], 355 | [ 356 | 6309028.73486, 357 | 357199.05392 358 | ], 359 | [ 360 | 6309045.86114, 361 | 357220.97586 362 | ], 363 | [ 364 | 6309078.85225, 365 | 357261.01696 366 | ], 367 | [ 368 | 6309131.17986, 369 | 357323.22098 370 | ], 371 | [ 372 | 6309184.03434, 373 | 357388.33409 374 | ], 375 | [ 376 | 6309212.61182, 377 | 357423.54026 378 | ], 379 | [ 380 | 6309252.80543, 381 | 357467.20429 382 | ], 383 | [ 384 | 6309288.51836, 385 | 357504.59499 386 | ], 387 | [ 388 | 6309318.98068, 389 | 357536.37443 390 | ], 391 | [ 392 | 6309366.01084, 393 | 357588.07961 394 | ], 395 | [ 396 | 6309383.32941, 397 | 357609.89089 398 | ], 399 | [ 400 | 6309383.33718, 401 | 357609.92579 402 | ], 403 | [ 404 | 6309383.36584, 405 | 357611.49516 406 | ] 407 | ] 408 | }, 409 | { 410 | "type": "Polygon", 411 | "coordinates": [ 412 | [ 413 | [ 414 | 6309096.87876754, 415 | 357058.96992573235 416 | ], 417 | [ 418 | 6309100.924003807, 419 | 357067.89795246266 420 | ], 421 | [ 422 | 6309103.149740386, 423 | 357077.4436161082 424 | ], 425 | [ 426 | 6309103.470443468, 427 | 357087.24008216924 428 | ], 429 | [ 430 | 6309101.873788615, 431 | 357096.9108779499 432 | ], 433 | [ 434 | 6309098.421134375, 435 | 357106.0843601926 436 | ], 437 | [ 438 | 6309093.245164316, 439 | 357114.40799712023 440 | ], 441 | [ 442 | 6309086.544788064, 443 | 357121.5619160343 444 | ], 445 | [ 446 | 6309078.577497319, 447 | 357127.2711958436 448 | ], 449 | [ 450 | 6309013.594489282, 451 | 357164.7891530477 452 | ], 453 | [ 454 | 6309004.666462537, 455 | 357168.8343893392 456 | ], 457 | [ 458 | 6308995.120798872, 459 | 357171.0601259347 460 | ], 461 | [ 462 | 6308985.324332788, 463 | 357171.38082902494 464 | ], 465 | [ 466 | 6308975.653536983, 467 | 357169.78417417 468 | ], 469 | [ 470 | 6308966.480054719, 471 | 357166.33151992067 472 | ], 473 | [ 474 | 6308958.156417775, 475 | 357161.1555498438 476 | ], 477 | [ 478 | 6308951.002498852, 479 | 357154.45517356717 480 | ], 481 | [ 482 | 6308945.293219042, 483 | 357146.48788279406 484 | ], 485 | [ 486 | 6308795.004339662, 487 | 356886.1799069175 488 | ], 489 | [ 490 | 6308790.959103398, 491 | 356877.251880196 492 | ], 493 | [ 494 | 6308788.733366818, 495 | 356867.70621655986 496 | ], 497 | [ 498 | 6308788.412663732, 499 | 356857.90975050797 500 | ], 501 | [ 502 | 6308790.009318577, 503 | 356848.2389547351 504 | ], 505 | [ 506 | 6308793.461972805, 507 | 356839.0654724979 508 | ], 509 | [ 510 | 6308798.637942851, 511 | 356830.7418355726 512 | ], 513 | [ 514 | 6308805.338319088, 515 | 356823.587916657 516 | ], 517 | [ 518 | 6308813.305609818, 519 | 356817.8786368417 520 | ], 521 | [ 522 | 6308878.288617808, 523 | 356780.3606795366 524 | ], 525 | [ 526 | 6308887.216644556, 527 | 356776.315443229 528 | ], 529 | [ 530 | 6308896.762308229, 531 | 356774.0897066199 532 | ], 533 | [ 534 | 6308906.558774322, 535 | 356773.76900351944 536 | ], 537 | [ 538 | 6308916.229570136, 539 | 356775.36565836804 540 | ], 541 | [ 542 | 6308925.403052411, 543 | 356778.8183126149 544 | ], 545 | [ 546 | 6308933.726689366, 547 | 356783.99428269314 548 | ], 549 | [ 550 | 6308940.880608298, 551 | 356790.6946589744 552 | ], 553 | [ 554 | 6308946.589888114, 555 | 356798.6619497548 556 | ], 557 | [ 558 | 6309096.87876754, 559 | 357058.96992573235 560 | ] 561 | ] 562 | ] 563 | } 564 | ] 565 | } 566 | -------------------------------------------------------------------------------- /test/data/geometrycollection.wkt: -------------------------------------------------------------------------------- 1 | GEOMETRYCOLLECTION (LINESTRING (6308869.40378 356821.22669, 6308867.893 356822.41744, 6308852.75314 356830.22159, 6308869.92754 356844.26638), LINESTRING (6308755.07971 356674.51686, 6308784.81355 356719.16757, 6308815.20022 356765.46178, 6308829.63774 356763.22832, 6308852.87023 356759.82402, 6308867.19982 356771.06823, 6308875.40631 356796.20162, 6308872.51907 356815.17242), LINESTRING (6308874.12086 356813.73392, 6308876.83028 356795.77697, 6308868.23871 356770.06254, 6308853.09618 356758.29456, 6308815.86529 356763.89689, 6308799.76731 356739.37835, 6308747.77971 356662.11613, 6308746.55411 356661.61702, 6308744.06545 356657.72563, 6308731.77184 356668.45076, 6308699.45221 356683.15463, 6308682.44689 356684.63193, 6308654.96629 356683.66846, 6308636.13879 356680.0482, 6308618.19888 356671.76352, 6308608.41685 356661.79428, 6308578.7973 356592.35062, 6308545.33908 356542.14886, 6308517.52088 356509.38474, 6308505.40266 356506.84141, 6308493.59689 356506.98067, 6308375.07918 356520.46209), LINESTRING (6308877.92941 356819.50984, 6309072.26249 356514.14689, 6309073.44938 356513.3739, 6309076.25423 356511.31751, 6309096.05004 356528.52014, 6309103.33938 356535.32615, 6309107.49584 356539.20699, 6309107.78601 356539.47793, 6309119.09139 356550.03322, 6309137.04465 356567.13752, 6309137.6323 356567.69515, 6309138.92096 356568.91355, 6309138.46355 356569.69798, 6309150.68532 356566.34027, 6309151.94333 356567.03108, 6309157.81557 356565.41779, 6309161.54152 356564.33408, 6309174.6464 356579.77423, 6309175.71622 356581.0361, 6309177.25892 356582.84545, 6309225.37695 356611.76515, 6309226.90588 356612.65173, 6309229.72021 356614.34101, 6309232.64678 356598.75445, 6309244.10246 356528.49893, 6309251.20809 356487.90256, 6309252.35489 356481.34967, 6309258.41778 356442.34047, 6309258.56036 356441.19511, 6309258.76115 356440.13123, 6309260.99127 356426.22389, 6309258.49745 356425.57244, 6309240.94882 356422.48836, 6309240.53276 356422.37171, 6309240.10958 356422.29068), LINESTRING (6308870.96141 356823.05522, 6308881.43519 356846.04558, 6308859.94336 356857.75024, 6308859.6305 356857.95378, 6308893.96675 356932.14467, 6308921.19517 356993.60222, 6308942.68768 357040.82051, 6308961.42173 357079.52481, 6308976.48471 357108.08898, 6308992.14194 357136.52543, 6309018.60922 357184.68892, 6309024.87557 357193.57884, 6309025.31785 357194.20629, 6309028.73486 357199.05392, 6309045.86114 357220.97586, 6309078.85225 357261.01696, 6309131.17986 357323.22098, 6309184.03434 357388.33409, 6309212.61182 357423.54026, 6309252.80543 357467.20429, 6309288.51836 357504.59499, 6309318.98068 357536.37443, 6309366.01084 357588.07961, 6309383.32941 357609.89089, 6309383.33718 357609.92579, 6309383.36584 357611.49516), POLYGON ((6309096.87876754 357058.96992573235, 6309100.9240038069 357067.89795246266, 6309103.1497403858 357077.44361610821, 6309103.4704434676 357087.24008216924, 6309101.8737886148 357096.91087794991, 6309098.421134375 357106.08436019259, 6309093.2451643161 357114.40799712023, 6309086.5447880644 357121.56191603432, 6309078.5774973193 357127.27119584358, 6309013.594489282 357164.78915304772, 6309004.6664625369 357168.8343893392, 6308995.1207988719 357171.06012593472, 6308985.3243327877 357171.38082902494, 6308975.6535369828 357169.78417417, 6308966.4800547194 357166.33151992067, 6308958.156417775 357161.1555498438, 6308951.0024988521 357154.45517356717, 6308945.293219042 357146.48788279406, 6308795.0043396624 356886.1799069175, 6308790.959103398 356877.251880196, 6308788.7333668182 356867.70621655986, 6308788.4126637317 356857.90975050797, 6308790.0093185771 356848.2389547351, 6308793.4619728047 356839.0654724979, 6308798.6379428506 356830.74183557258, 6308805.3383190883 356823.587916657, 6308813.3056098176 356817.87863684172, 6308878.2886178084 356780.36067953659, 6308887.2166445563 356776.315443229, 6308896.7623082288 356774.08970661991, 6308906.5587743223 356773.76900351944, 6308916.2295701364 356775.36565836804, 6308925.403052411 356778.81831261492, 6308933.7266893657 356783.99428269314, 6308940.8806082979 356790.69465897442, 6308946.5898881136 356798.66194975481, 6309096.87876754 357058.96992573235))) 2 | -------------------------------------------------------------------------------- /test/fuzz.js: -------------------------------------------------------------------------------- 1 | var parse = require('../'), 2 | fuzzer = require('fuzzer'), 3 | test = require('tap').test; 4 | 5 | test('fuzz', function(t) { 6 | fuzzer.seed(0); 7 | var inputs = [ 8 | 'MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))', 9 | 'POINT(1.1 1.1)', 10 | 'LINESTRING (30 10, 10 30, 40 40)', 11 | 'GeometryCollection(POINT(4 6),\nLINESTRING(4 6,7 10))']; 12 | inputs.forEach(function(str) { 13 | for (var i = 0; i < 10000; i++) { 14 | try { 15 | var input = fuzzer.mutate.string(str); 16 | parse(input); 17 | } catch(e) { 18 | t.fail('could not parse ' + input + ', exception ' + e + '\n' + e.stack); 19 | } 20 | } 21 | }); 22 | t.end(); 23 | }); 24 | -------------------------------------------------------------------------------- /test/stringify.js: -------------------------------------------------------------------------------- 1 | var wellknown = require('../'), 2 | test = require('tap').test; 3 | 4 | test('wellknown', function(t) { 5 | t.throws(function() { 6 | wellknown.stringify({ 7 | type: 'FeatureCollection' 8 | }); 9 | }, 'does not accept featurecollections'); 10 | 11 | var fixtures = [ 12 | 'LINESTRING (30 10, 10 30, 40 40)', 13 | 'POINT (1 1)', 14 | 'POINT (1 1 1 1)', 15 | 'LINESTRING (1 2 3, 4 5 6)', 16 | 'LINESTRING (1 2 3 4, 5 6 7 8)', 17 | 'POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))', 18 | 'POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10), (20 30, 35 35, 30 20, 20 30))', 19 | 'MULTIPOINT (1 1, 2 3)', 20 | 'MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5), (10 10, 15 10, 15 15, 10 10)))', 21 | 'MULTILINESTRING ((30 10, 10 30, 40 40), (30 10, 10 30, 40 40))', 22 | 'GEOMETRYCOLLECTION (POINT (4 6), LINESTRING (4 6, 7 10))' 23 | ]; 24 | 25 | fixtures.forEach(function(fix) { 26 | t.equal(fix, loop(fix), fix); 27 | }); 28 | 29 | function loop(s) { 30 | return wellknown.stringify(wellknown(s)); 31 | } 32 | 33 | t.equal(wellknown.stringify({ 34 | type: 'Feature', 35 | properties: {}, 36 | geometry: { 37 | type: 'Point', 38 | coordinates: [42, 20] 39 | } 40 | }), 'POINT (42 20)', 'point equal'); 41 | 42 | t.end(); 43 | }); 44 | -------------------------------------------------------------------------------- /test/wellknown.test.js: -------------------------------------------------------------------------------- 1 | var parse = require('../'), 2 | fs = require('fs'), 3 | fuzzer = require('fuzzer'), 4 | test = require('tap').test; 5 | 6 | test('wellknown', function(t) { 7 | t.deepEqual(parse('POINT (0 1)'), { 8 | type: 'Point', 9 | coordinates: [0, 1] 10 | }); 11 | t.deepEqual(parse('POINT (1 1)'), { 12 | type: 'Point', 13 | coordinates: [1, 1] 14 | }); 15 | t.deepEqual(parse('POINT(1 1)'), { 16 | type: 'Point', 17 | coordinates: [1, 1] 18 | }); 19 | t.deepEqual(parse('POINT\n\r(1 1)'), { 20 | type: 'Point', 21 | coordinates: [1, 1] 22 | }); 23 | t.deepEqual(parse('POINT(1.1 1.1)'), { 24 | type: 'Point', 25 | coordinates: [1.1, 1.1] 26 | }); 27 | t.deepEqual(parse('point(1.1 1.1)'), { 28 | type: 'Point', 29 | coordinates: [1.1, 1.1] 30 | }); 31 | t.deepEqual(parse('point(1 2 3)'), { 32 | type: 'Point', 33 | coordinates: [1, 2, 3] 34 | }); 35 | t.deepEqual(parse('point(1 2 3 4)'), { 36 | type: 'Point', 37 | coordinates: [1, 2, 3, 4] 38 | }); 39 | t.deepEqual(parse('SRID=3857;POINT (1 2 3)'), { 40 | type: 'Point', 41 | coordinates: [1, 2, 3], 42 | crs: { 43 | type: 'name', 44 | 'properties': { 45 | name: 'urn:ogc:def:crs:EPSG::3857' 46 | } 47 | } 48 | }); 49 | t.deepEqual(parse('LINESTRING (30 10, 10 30, 40 40)'), { 50 | type: 'LineString', 51 | coordinates: [[30, 10], [10, 30], [40, 40]] 52 | }); 53 | t.deepEqual(parse('LINESTRING(30 10, 10 30, 40 40)'), { 54 | type: 'LineString', 55 | coordinates: [[30, 10], [10, 30], [40, 40]] 56 | }); 57 | t.deepEqual(parse('LineString(30 10, 10 30, 40 40)'), { 58 | type: 'LineString', 59 | coordinates: [[30, 10], [10, 30], [40, 40]] 60 | }); 61 | t.deepEqual(parse('LINESTRING (1 2 3, 4 5 6)'), { 62 | type: 'LineString', 63 | coordinates: [[1, 2, 3], [4, 5, 6]] 64 | }); 65 | t.deepEqual(parse('LINESTRING (1 2 3 4, 5 6 7 8)'), { 66 | type: 'LineString', 67 | coordinates: [[1, 2, 3, 4], [5, 6, 7, 8]] 68 | }); 69 | t.deepEqual(parse('SRID=3857;LINESTRING (30 10, 10 30, 40 40)'), { 70 | type: 'LineString', 71 | coordinates: [[30, 10], [10, 30], [40, 40]], 72 | crs: { 73 | type: 'name', 74 | 'properties': { 75 | name: 'urn:ogc:def:crs:EPSG::3857' 76 | } 77 | } 78 | }); 79 | t.deepEqual(parse('POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))'), { 80 | type: 'Polygon', 81 | coordinates: [[[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]] 82 | }); 83 | t.deepEqual(parse('POLYGON((30 10, 10 20, 20 40, 40 40, 30 10))'), { 84 | type: 'Polygon', 85 | coordinates: [[[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]] 86 | }); 87 | t.deepEqual(parse('SRID=3857;POLYGON ((30 10, 10 20, 20 40, 40 40, 30 10))'), { 88 | type: 'Polygon', 89 | coordinates: [[[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]], 90 | crs: { 91 | type: 'name', 92 | 'properties': { 93 | name: 'urn:ogc:def:crs:EPSG::3857' 94 | } 95 | } 96 | }); 97 | t.deepEqual(parse('POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))'), { 98 | type: 'Polygon', 99 | coordinates: 100 | [ 101 | [ 102 | [ 35, 10 ], 103 | [ 10, 20 ], 104 | [ 15, 40 ], 105 | [ 45, 45 ], 106 | [ 35, 10 ] 107 | ], [ 108 | [ 20, 30 ], 109 | [ 35, 35 ], 110 | [ 30, 20 ], 111 | [ 20, 30 ] 112 | ] 113 | ] 114 | }); 115 | t.deepEqual(parse('MULTIPOINT (0 0, 2 3)'), { 116 | type: 'MultiPoint', 117 | coordinates: [[0, 0], [2, 3]] 118 | }); 119 | t.deepEqual(parse('MULTIPOINT (1 1, 2 3)'), { 120 | type: 'MultiPoint', 121 | coordinates: [[1, 1], [2, 3]] 122 | }); 123 | t.deepEqual(parse('MultiPoint (1 1, 2 3)'), { 124 | type: 'MultiPoint', 125 | coordinates: [[1, 1], [2, 3]] 126 | }); 127 | t.deepEqual(parse('SRID=3857;MULTIPOINT (1 1, 2 3)'), { 128 | type: 'MultiPoint', 129 | coordinates: [[1, 1], [2, 3]], 130 | crs: { 131 | type: 'name', 132 | 'properties': { 133 | name: 'urn:ogc:def:crs:EPSG::3857' 134 | } 135 | } 136 | }); 137 | t.deepEqual(parse('MULTIPOINT ((0 0), (2 3))'), { 138 | type: 'MultiPoint', 139 | coordinates: [[0, 0], [2, 3]] 140 | }); 141 | t.deepEqual(parse('MULTIPOINT ((1 1), (2 3))'), { 142 | type: 'MultiPoint', 143 | coordinates: [[1, 1], [2, 3]] 144 | }); 145 | t.deepEqual(parse('MultiPoint ((1 1), (2 3))'), { 146 | type: 'MultiPoint', 147 | coordinates: [[1, 1], [2, 3]] 148 | }); 149 | t.deepEqual(parse('SRID=3857;MULTIPOINT ((1 1), (2 3))'), { 150 | type: 'MultiPoint', 151 | coordinates: [[1, 1], [2, 3]], 152 | crs: { 153 | type: 'name', 154 | 'properties': { 155 | name: 'urn:ogc:def:crs:EPSG::3857' 156 | } 157 | } 158 | }); 159 | t.deepEqual(parse('MULTILINESTRING ((30 10, 10 30, 40 40), (30 10, 10 30, 40 40))'), { 160 | type: 'MultiLineString', 161 | coordinates: [ 162 | [[30, 10], [10, 30], [40, 40]], 163 | [[30, 10], [10, 30], [40, 40]]] 164 | }); 165 | t.deepEqual(parse('SRID=3857;MULTILINESTRING ((30 10, 10 30, 40 40), (30 10, 10 30, 40 40))'), { 166 | type: 'MultiLineString', 167 | coordinates: [ 168 | [[30, 10], [10, 30], [40, 40]], 169 | [[30, 10], [10, 30], [40, 40]]], 170 | crs: { 171 | type: 'name', 172 | 'properties': { 173 | name: 'urn:ogc:def:crs:EPSG::3857' 174 | } 175 | } 176 | }); 177 | t.deepEqual(parse('MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))'), { 178 | type: 'MultiPolygon', 179 | coordinates: [ 180 | [[[30, 20], [10, 40], [45, 40], [30, 20]]], 181 | [[[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]]] 182 | }); 183 | t.deepEqual(parse('MULTIPOLYGON (((-74.03349399999999 40.688348)))'), 184 | {"type":"MultiPolygon","coordinates":[[[[-74.03349399999999,40.688348]]]]} 185 | ); 186 | t.deepEqual(parse('MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5), (10 10, 15 10, 15 15, 10 10)))'), { 187 | type: 'MultiPolygon', 188 | coordinates: [ 189 | [[[30, 20], [10, 40], [45, 40], [30, 20]]], 190 | [ 191 | [[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]], 192 | [[10, 10], [15, 10], [15, 15], [10, 10]]]] 193 | }); 194 | t.deepEqual(parse('SRID=3857;MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))'), { 195 | type: 'MultiPolygon', 196 | coordinates: [ 197 | [[[30, 20], [10, 40], [45, 40], [30, 20]]], 198 | [[[15, 5], [40, 10], [10, 20], [5, 10], [15, 5]]]], 199 | crs: { 200 | type: 'name', 201 | 'properties': { 202 | name: 'urn:ogc:def:crs:EPSG::3857' 203 | } 204 | } 205 | }); 206 | t.deepEqual(parse(fs.readFileSync('test/data/geometrycollection.wkt', 'utf8')), 207 | JSON.parse(fs.readFileSync('test/data/geometrycollection.geojson'))); 208 | t.deepEqual(parse('GeometryCollection(POINT(4 6),LINESTRING(4 6,7 10))'), { 209 | type: 'GeometryCollection', 210 | geometries: [ 211 | { 212 | type: 'Point', 213 | coordinates: [4, 6] 214 | }, 215 | { 216 | type: 'LineString', 217 | coordinates: [[4, 6], [7, 10]] 218 | } 219 | ] 220 | }); 221 | t.deepEqual(parse('GeometryCollection(POINT(4 6),\nLINESTRING(4 6,7 10))'), { 222 | type: 'GeometryCollection', 223 | geometries: [ 224 | { 225 | type: 'Point', 226 | coordinates: [4, 6] 227 | }, 228 | { 229 | type: 'LineString', 230 | coordinates: [[4, 6], [7, 10]] 231 | } 232 | ] 233 | }); 234 | t.deepEqual(parse('POINT (1e-6 1E+2)'), { 235 | type: 'Point', 236 | coordinates: [1e-6, 1E+2] 237 | }); 238 | t.equal(parse('POINT(100)'), null); 239 | t.equal(parse('POINT(100, 100)'), null); 240 | t.equal(parse('POINT()'), null); 241 | t.equal(parse('MULTIPOINT()'), null); 242 | t.equal(parse('MULTIPOINT(1)'), null); 243 | t.equal(parse('MULTIPOINT(1 1, 1)'), null); 244 | 245 | 246 | t.deepEqual(parse('POINT Z (1 2 3)'), { 247 | type: 'Point', 248 | coordinates: [1, 2, 3] 249 | }); 250 | 251 | t.deepEqual(parse('LINESTRING Z (30 10 1, 10 30 2, 40 40 3)'), { 252 | type: 'LineString', 253 | coordinates: [[30, 10, 1], [10, 30, 2], [40, 40, 3]] 254 | }); 255 | 256 | t.deepEqual(parse('POLYGON Z ((30 10 1, 10 20 2, 20 40 3, 40 40 4, 30 10 5))'), { 257 | type: 'Polygon', 258 | coordinates: [[[30, 10, 1], [10, 20, 2], [20, 40, 3], [40, 40, 4], [30, 10, 5]]] 259 | }); 260 | 261 | t.end(); 262 | }); 263 | -------------------------------------------------------------------------------- /wellknown.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.wellknown = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o