├── .eslintrc.js ├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── dist ├── shp.esm.js ├── shp.esm.min.js ├── shp.js └── shp.min.js ├── files ├── Readme.txt ├── TM_WORLD_BORDERS_SIMPL-0.3.dbf ├── TM_WORLD_BORDERS_SIMPL-0.3.shp ├── TM_WORLD_BORDERS_SIMPL-0.3.shx ├── TM_WORLD_BORDERS_SIMPL-0.3.zip ├── counties5.zip ├── empty-shp.zip ├── maSP.zip ├── nj_counties.zip ├── nj_muni.zip ├── pandr.dbf ├── pandr.prj ├── pandr.qpj ├── pandr.sbn ├── pandr.sbx ├── pandr.shp ├── pandr.shp.xml ├── pandr.shx └── pandr.zip ├── index.html ├── lib ├── binaryajax.js ├── browser.js ├── combine.js ├── index.js ├── parseShp.js └── unzip.js ├── package.json ├── rollup.config.js ├── site ├── catiline.js ├── curl.js ├── gh-fork-ribbon.css ├── images │ ├── layers-2x.png │ ├── layers.png │ ├── marker-icon-2x.png │ ├── marker-icon.png │ └── marker-shadow.png ├── leaflet.css ├── leaflet.ie.css ├── leaflet.js ├── leaflet.zip ├── map.html ├── proj-small.html ├── proj.html └── require.js └── test ├── bundle.js ├── data ├── LGA_2013_AUST.cpg ├── LGA_2013_AUST.dbf ├── LGA_2013_AUST.prj ├── LGA_2013_AUST.shp ├── LGA_2013_AUST.shx ├── SHP_Exclude.zip ├── T8Th4_6n.zip ├── bad.dbf ├── bad.shp ├── badlen.zip ├── badzip.zip ├── codepage.cpg ├── codepage.dbf ├── codepage.prj ├── codepage.qpj ├── codepage.shp ├── codepage.shx ├── codepage.zip ├── counties.dbf ├── counties.sbn ├── counties.sbx ├── counties.shp ├── counties.shp.xml ├── counties.shx ├── counties.zip ├── export_multipointz.dbf ├── export_multipointz.prj ├── export_multipointz.shp ├── export_multipointz.shx ├── export_polylinez.dbf ├── export_polylinez.prj ├── export_polylinez.shp ├── export_polylinez.shx ├── htmlcpg.cpg ├── htmlcpg.dbf ├── htmlcpg.prj ├── htmlcpg.shp ├── htmlprj.cpg ├── htmlprj.dbf ├── htmlprj.prj ├── htmlprj.shp ├── ipra_dresden_polygon.dbf ├── ipra_dresden_polygon.prj ├── ipra_dresden_polygon.shp ├── ipra_dresden_polygon.shx ├── mixedcase.zip ├── no-dbf.sbx ├── no-dbf.shp ├── no-dbf.zip ├── noshp.zip ├── qgis.zip ├── senate.dbf ├── senate.prj ├── senate.sbn ├── senate.sbx ├── senate.shp ├── senate.shp.xml ├── senate.shx ├── senate.zip ├── train_stations.zip ├── utf.cpg ├── utf.dbf ├── utf.prj ├── utf.qpj ├── utf.shp ├── utf.shx ├── utf.zip └── zero-len-line.zip ├── fixtures.js ├── index.html ├── server.js └── test.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | node: true, 5 | es6: true, 6 | mocha: true 7 | }, 8 | extends: 'semistandard' 9 | }; 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | node_modules 3 | .c9revisions 4 | jam 5 | components 6 | .DS_Store 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | site 3 | files 4 | jam 5 | *.zip 6 | *.geojson 7 | *.topojson -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © 2024 - Calvin Metcalf and other `shapefile-js` contributors. 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shapefile.js 2 | 3 | Pure JavaScript library for parsing Shapefiles, returns Geojson projected into WGS84 lat lons. 4 | 5 | ## Usage 6 | 7 | For use in node, rollup, webpack and where ever ESM modules are used we have a lovely package you can install via npm or yarn or whatever. 8 | 9 | npm install shpjs --save 10 | 11 | If you need a stand alone file to include in your webpage the old fashioned way then you can grab the built version that's either included in the repo or you can use unpkg. 12 | 13 | https://unpkg.com/shpjs@latest/dist/shp.js 14 | 15 | or 16 | 17 | https://unpkg.com/shpjs@latest/dist/shp.min.js 18 | 19 | 20 | When using this library in some sort of bundler for the browser, no polyfills for node apis are required, the only thing needed is some sort of dependency resolver plugin like [rollup node-resolve](https://www.npmjs.com/package/@rollup/plugin-node-resolve) if your bundler doesn't have it, you are almost certainly already using one to get this library anyway. 21 | 22 | Addtionally you can import it directly into an esm based web script with 23 | 24 | ```js 25 | import shp from 'https://unpkg.com/shpjs@latest/dist/shp.esm.js' 26 | ``` 27 | 28 | ## API 29 | 30 | There are 3 ways to use it: 31 | 32 | 1\. you can pass it a url to a shapefile, either to the shapefile itself (with or without the .shp suffix) 33 | 34 | ```javascript 35 | import shp from 'shpjs'; 36 | //for the shapefiles in the folder called 'files' with the name pandr.shp 37 | const geojson = await shp("files/pandr.shp"); 38 | ``` 39 | 40 | or you can pass it a url to a a .zip file which contains the shapefile 41 | 42 | ```javascript 43 | //for the shapefiles in the files folder called pandr.shp 44 | const geojson = await shp("files/pandr.zip"); 45 | ``` 46 | 47 | 2\. you can pass in in a binary buffer (ArrayBuffer, TypedArray, DataView, Node Buffer) containing a zip file containing at least one shapefile like from a file in node: 48 | 49 | ```javascript 50 | // in node 51 | const data = await fs.readFile('./path/to/shp.zip'); 52 | const geojson = await shp(data); 53 | ``` 54 | or the [File API](https://developer.mozilla.org/en-US/docs/Web/API/File) in the browser 55 | 56 | ```javascript 57 | // in browser from some sort of file upload 58 | const data = await file.arrayBuffer() 59 | const geojson = await shp(data); 60 | ``` 61 | 62 | 3\. You can pass in an object with `shp`, `dbf`, `prj`, and `cpg` properties. 63 | 64 | ```javascript 65 | const object = {} 66 | object.shp = await fs.readFile('./path/to/file.shp'); 67 | // dbf is optional, but needed if you want attributes 68 | object.dbf = await fs.readFile('./path/to/file.dbf'); 69 | // prj is optional, but needed if your file is in some projection you don't want it in 70 | object.prj = await fs.readFile('./path/to/file.prj'); 71 | // cpg is optional but needed if your dbf is in some weird (non utf8) encoding. 72 | object.cpg = await fs.readFile('./path/to/file.cpg'); 73 | 74 | const geojson = await shp(object) 75 | ``` 76 | 77 | ## on zipfiles 78 | 79 | If there is only one shp in the zipefile it returns geojson, if there are multiple then it will be an array. All of the geojson objects have an extra key `fileName` the value of which is the 80 | name of the shapefile minus the extension (I.E. the part of the name that's the same for all of them). 81 | 82 | 83 | # links 84 | 85 | - [wikipedia article](https://en.wikipedia.org/wiki/Shapefile) 86 | - [ESRI white paper](http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf) 87 | - [This page on Xbase](http://www.clicketyclick.dk/databases/xbase/format/dbf.html) 88 | 89 | ## Demos 90 | 91 | - [Countries/zipfile](http://calvinmetcalf.github.io/shapefile-js) 92 | - [Google maps](http://calvinmetcalf.github.io/shapefile-js/site/map.html) 93 | - [Local Zipfile](http://leaflet.calvinmetcalf.com) 94 | - [Projected big with web workers](http://calvinmetcalf.github.io/shapefile-js/site/proj.html) 95 | 96 | ## About 97 | 98 | Descended in a ship of theseus way from [RandomEtc's shapefile library](https://github.com/RandomEtc/shapefile-js) no code is shared. 99 | 100 | - [World Borders shapefile](http://thematicmapping.org/downloads/world_borders.php) is CC-BY-SA 3.0. 101 | - Park and Ride shapefile is from [MassDOT](http://mass.gov/massdot) and is public domain. 102 | - MA town boundaries from [MassGIS](http://www.mass.gov/anf/research-and-tech/it-serv-and-support/application-serv/office-of-geographic-information-massgis/) and is public domain 103 | - NJ County Boundaries from [NJgin](https://njgin.state.nj.us/NJ_NJGINExplorer/index.jsp) and should be public domain. 104 | - [Proj4js](https://github.com/proj4js/proj4js) by me et al MIT 105 | - Other test datasets copyright their respective owners. -------------------------------------------------------------------------------- /files/Readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/Readme.txt -------------------------------------------------------------------------------- /files/TM_WORLD_BORDERS_SIMPL-0.3.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/TM_WORLD_BORDERS_SIMPL-0.3.dbf -------------------------------------------------------------------------------- /files/TM_WORLD_BORDERS_SIMPL-0.3.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/TM_WORLD_BORDERS_SIMPL-0.3.shp -------------------------------------------------------------------------------- /files/TM_WORLD_BORDERS_SIMPL-0.3.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/TM_WORLD_BORDERS_SIMPL-0.3.shx -------------------------------------------------------------------------------- /files/TM_WORLD_BORDERS_SIMPL-0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/TM_WORLD_BORDERS_SIMPL-0.3.zip -------------------------------------------------------------------------------- /files/counties5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/counties5.zip -------------------------------------------------------------------------------- /files/empty-shp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/empty-shp.zip -------------------------------------------------------------------------------- /files/maSP.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/maSP.zip -------------------------------------------------------------------------------- /files/nj_counties.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/nj_counties.zip -------------------------------------------------------------------------------- /files/nj_muni.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/nj_muni.zip -------------------------------------------------------------------------------- /files/pandr.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.dbf -------------------------------------------------------------------------------- /files/pandr.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] -------------------------------------------------------------------------------- /files/pandr.qpj: -------------------------------------------------------------------------------- 1 | GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] 2 | -------------------------------------------------------------------------------- /files/pandr.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.sbn -------------------------------------------------------------------------------- /files/pandr.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.sbx -------------------------------------------------------------------------------- /files/pandr.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.shp -------------------------------------------------------------------------------- /files/pandr.shp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2012053008362400FALSECreateFeatureclass "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities" ParkAndRide # Export_Output_2_Layer SAME_AS_TEMPLATE SAME_AS_TEMPLATE "PROJCS['NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Lambert_Conformal_Conic'],PARAMETER['False_Easting',200000.0],PARAMETER['False_Northing',750000.0],PARAMETER['Central_Meridian',-71.5],PARAMETER['Standard_Parallel_1',41.71666666666667],PARAMETER['Standard_Parallel_2',42.68333333333333],PARAMETER['Latitude_Of_Origin',41.0],UNIT['Meter',1.0]];-361489.141077092 327975.618391579 1953.12499818101;0 1;0 1" # 0 0 0 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities\gisvector.GISADMIN.ParkAndRide"Append Export_Output_2_Layer "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities\gisvector.GISADMIN.ParkAndRide" TEST "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities\gisvector.GISADMIN.ParkAndRide"FeatureClassToFeatureClass S:\HQ\Planning\DataResources\Workspace\PaulN\ParknRide\ParkandRide-PN.mdb\Export_Output_2 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities" ParkAndRide # "TOWN TOWN VISIBLE;LOCATION LOCATION VISIBLE;STATUS STATUS VISIBLE;DISTRICT DISTRICT VISIBLE;OPERATOR OPERATOR VISIBLE;BIKE_RACKS BIKE_RACKS VISIBLE;SHELTERS SHELTERS VISIBLE;PHONES PHONES VISIBLE;LIGHTS LIGHTS VISIBLE;FENCES FENCES VISIBLE;SIGNS SIGNS VISIBLE;OWNER OWNER VISIBLE;CAPACITY CAPACITY VISIBLE;BUS_SERVICE BUS_SERVICE VISIBLE;RAIL_SERVICE RAIL_SERVICE VISIBLE;BOAT_SERVICE BOAT_SERVICE VISIBLE;MAP_ID MAP_ID VISIBLE;MPO MPO VISIBLE" SAME_AS_TEMPLATE SAME_AS_TEMPLATE # 0 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.PublicFacilities\gisvector.GISADMIN.ParkAndRide"FeatureClassToFeatureClass "Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots" S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb Update2009 # "TOWN 'TOWN' true true false 25 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,TOWN,-1,-1;LOCATION 'LOCATION' true true false 45 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,LOCATION,-1,-1;STATUS 'STATUS' true true false 15 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,STATUS,-1,-1;DISTRICT 'DISTRICT' true true false 4 Long 0 10 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,DISTRICT,-1,-1;OPERATOR 'OPERATOR' true true false 25 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,OPERATOR,-1,-1;BIKE_RACKS 'BIKE_RACKS' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,BIKE_RACKS,-1,-1;SHELTERS 'SHELTERS' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,SHELTERS,-1,-1;PHONES 'PHONES' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,PHONES,-1,-1;LIGHTS 'LIGHTS' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,LIGHTS,-1,-1;FENCES 'FENCES' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,FENCES,-1,-1;SIGNS 'SIGNS' true true false 3 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,SIGNS,-1,-1;OWNER 'OWNER' true true false 15 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,OWNER,-1,-1;CAPACITY 'CAPACITY' true true false 4 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,CAPACITY,-1,-1;BUS_SERVICE 'BUS_SERVICE' true true false 25 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,BUS_SERVICE,-1,-1;RAIL_SERVICE 'RAIL_SERVICE' true true false 10 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,RAIL_SERVICE,-1,-1;BOAT_SERVICE 'BOAT_SERVICE' true true false 10 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,BOAT_SERVICE,-1,-1;MAP_ID 'MAP_ID' true true false 4 Long 0 10 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,MAP_ID,-1,-1;MPO 'MPO' true true false 50 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,MPO,-1,-1;SYMBOL 'SYMBOL' true true false 1 Text 0 0 ,First,#,Database Connections\MassDOT GIS.sde\gisVector.GISADMIN.Transportation\gisvector.GISADMIN.ParkAndRideLots,SYMBOL,-1,-1" # S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009FeatureClassToFeatureClass S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Transportation" ParkAndRide # "TOWN 'TOWN' true true false 25 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,TOWN,-1,-1;LOCATION 'LOCATION' true true false 45 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,LOCATION,-1,-1;STATUS 'STATUS' true true false 15 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,STATUS,-1,-1;DISTRICT 'DISTRICT' true true false 4 Long 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,DISTRICT,-1,-1;OPERATOR 'OPERATOR' true true false 25 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,OPERATOR,-1,-1;BIKE_RACKS 'BIKE_RACKS' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,BIKE_RACKS,-1,-1;SHELTERS 'SHELTERS' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,SHELTERS,-1,-1;PHONES 'PHONES' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,PHONES,-1,-1;LIGHTS 'LIGHTS' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,LIGHTS,-1,-1;FENCES 'FENCES' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,FENCES,-1,-1;SIGNS 'SIGNS' true true false 3 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,SIGNS,-1,-1;OWNER 'OWNER' true true false 15 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,OWNER,-1,-1;CAPACITY 'CAPACITY' true true false 4 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,CAPACITY,-1,-1;BUS_SERVICE 'BUS_SERVICE' true true false 25 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,BUS_SERVICE,-1,-1;RAIL_SERVICE 'RAIL_SERVICE' true true false 10 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,RAIL_SERVICE,-1,-1;BOAT_SERVICE 'BOAT_SERVICE' true true false 10 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,BOAT_SERVICE,-1,-1;MAP_ID 'MAP_ID' true true false 4 Long 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,MAP_ID,-1,-1;MPO 'MPO' true true false 50 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,MPO,-1,-1;SYMBOL 'SYMBOL' true true false 1 Text 0 0 ,First,#,S:\HQ\Planning\DataResources\Workspace\Paul\ParkAndRideUpdate.mdb\Update2009,SYMBOL,-1,-1" # "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Transportation\GISVECTOR.GISADMIN.ParkAndRide"Project "Database Connections\wh.sde\gisvector.GISADMIN.Facilities\gisVector.GISADMIN.ParkandRideLot" "C:\Documents and Settings\MetcalfC\Desktop\pandr.shp" GEOGCS['GCS_WGS_1984',DATUM['D_WGS_1984',SPHEROID['WGS_1984',6378137.0,298.257223563]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]] NAD_1983_To_WGS_1984_1 PROJCS['NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Lambert_Conformal_Conic'],PARAMETER['False_Easting',200000.0],PARAMETER['False_Northing',750000.0],PARAMETER['Central_Meridian',-71.5],PARAMETER['Standard_Parallel_1',41.71666666666667],PARAMETER['Standard_Parallel_2',42.68333333333333],PARAMETER['Latitude_Of_Origin',41.0],UNIT['Meter',1.0]]200912180626530020091218062653001.0Microsoft Windows XP Version 5.1 (Build 2600) Service Pack 3; ESRI ArcCatalog 9.3.1.3000enREQUIRED: A brief narrative summary of the data set.REQUIRED: A summary of the intentions with which the data set was developed.REQUIRED: The name of an organization or individual that developed the data set.REQUIRED: The date when the data set is published or otherwise made available for release.GISVECTOR.GISADMIN.ParkAndRideGISVECTOR.GISADMIN.ParkAndRidevector digital dataServer=mhd-gis-wh; Service=sde:sqlserver:mhd-gis-wh; Database=gisVector; User=gisadmin; Version=sde.DEFAULTREQUIRED: The basis on which the time period of content information is determined.REQUIRED: The year (and optionally month, or month and day) for which the data set corresponds to the ground.REQUIRED: The state of the data set.REQUIRED: The frequency with which changes and additions are made to the data set after the initial data set is completed.REQUIRED: Western-most coordinate of the limit of coverage expressed in longitude.REQUIRED: Eastern-most coordinate of the limit of coverage expressed in longitude.REQUIRED: Northern-most coordinate of the limit of coverage expressed in latitude.REQUIRED: Southern-most coordinate of the limit of coverage expressed in latitude.REQUIRED: Reference to a formally registered thesaurus or a similar authoritative source of theme keywords.REQUIRED: Common-use word or phrase used to describe the subject of the data set.REQUIRED: Restrictions and legal prerequisites for accessing the data set.REQUIRED: Restrictions and legal prerequisites for using the data set after access is granted.SDE Feature ClassMicrosoft Windows XP Version 5.1 (Build 2600) Service Pack 3; ESRI ArcCatalog 9.3.1.3000GISVECTOR.GISADMIN.ParkAndRideenFGDC Content Standards for Digital Geospatial MetadataFGDC-STD-001-1998local timeREQUIRED: The person responsible for the metadata information.REQUIRED: The organization responsible for the metadata information.REQUIRED: The mailing and/or physical address for the organization or individual.REQUIRED: The city of the address.REQUIRED: The state or province of the address.REQUIRED: The ZIP or other postal code of the address.REQUIRED: The telephone number by which individuals can speak to the organization or individual.20091218http://www.esri.com/metadata/esriprof80.htmlESRI Metadata ProfileISO 19115 Geographic Information - MetadataDIS_ESRI1.0datasetDownloadable Data002Server=mhd-gis-wh; Service=sde:sqlserver:mhd-gis-wh; Database=gisVector; User=gisadmin; Version=sde.DEFAULTArcSDE ConnectionSDE Feature ClassVectorSimplePointFALSE0TRUEFALSEEntity point0GCS_North_American_1983NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001coordinate pairmeters0.0005120.000512State Plane Coordinate System 1983200141.71666742.683333-71.50000041.000000200000.000000750000.000000North American Datum of 1983Geodetic Reference System 806378137.000000298.257222Explicit elevation coordinate included with horizontal coordinates1.000000NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_20010GISVECTOR.GISADMIN.ParkAndRideFeature Class0OBJECTIDOBJECTIDOID4100Internal feature number.ESRISequential unique whole numbers that are automatically generated.ShapeShapeGeometry400Feature geometry.ESRICoordinates defining the features.TOWNTOWNString2500LOCATIONLOCATIONString4500STATUSSTATUSString1500DISTRICTDISTRICTInteger4100OPERATOROPERATORString2500BIKE_RACKSBIKE_RACKSString300SHELTERSSHELTERSString300PHONESPHONESString300LIGHTSLIGHTSString300FENCESFENCESString300SIGNSSIGNSString300OWNEROWNERString1500CAPACITYCAPACITYString400BUS_SERVICEBUS_SERVICEString2500RAIL_SERVICERAIL_SERVICEString1000BOAT_SERVICEBOAT_SERVICEString1000MAP_IDMAP_IDInteger4100MPOMPOString5000SYMBOLSYMBOLString10020091218Dataset copied.Server=mhd-gis-wh; Service=esri_sde; Database=gisvector; User=gisviewer; Version=sde.DEFAULT2010081307273100 4 | -------------------------------------------------------------------------------- /files/pandr.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.shx -------------------------------------------------------------------------------- /files/pandr.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/files/pandr.zip -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Shapefile in Leaflet! 8 | 23 | 24 | 27 | 28 | 29 | 40 | 41 | 42 | 43 |
44 |
45 | Fork me on GitHub 46 |
47 |
48 |
49 | 50 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /lib/binaryajax.js: -------------------------------------------------------------------------------- 1 | import combine from './combine.js'; 2 | 3 | export default async function binaryAjax(_url, type) { 4 | 5 | const url = combine(_url, type); 6 | const isOptionalTxt = type === 'prj' || type === 'cpg'; 7 | try { 8 | const resp = await fetch(url); 9 | if (resp.status > 399) { 10 | throw new Error(resp.statusText); 11 | } 12 | if (isOptionalTxt) { 13 | return resp.text(); 14 | } 15 | const parsed = await resp.arrayBuffer(); 16 | return new DataView(parsed) 17 | } catch (e) { 18 | if (isOptionalTxt || type === 'dbf') { 19 | return false; 20 | } 21 | throw e; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /lib/browser.js: -------------------------------------------------------------------------------- 1 | import shp, { combine, getShapefile, parseDbf, parseZip, parseShp, } from './index.js'; 2 | 3 | shp.combine = combine; 4 | shp.parseDbf = parseDbf; 5 | shp.parseZip = parseZip; 6 | shp.parseShp = parseShp; 7 | export default shp; -------------------------------------------------------------------------------- /lib/combine.js: -------------------------------------------------------------------------------- 1 | const URL = globalThis.URL; 2 | 3 | export default (base, type) => { 4 | if (!type) { 5 | return base; 6 | } 7 | const url = new URL(base); 8 | url.pathname = `${url.pathname}.${type}`; 9 | return url.href; 10 | }; 11 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import proj4 from 'proj4' 2 | import unzip from './unzip.js'; 3 | import binaryAjax from './binaryajax.js'; 4 | import parseShp from './parseShp.js'; 5 | import parseDbf from 'parsedbf'; 6 | const URL = globalThis.URL; 7 | const toUitn8Arr = b => { 8 | if (!b) { 9 | throw new Error('forgot to pass buffer'); 10 | } 11 | if (isArrayBuffer(b)) { 12 | return new Uint8Array(b); 13 | } 14 | if (isArrayBuffer(b.buffer)) { 15 | if (b.BYTES_PER_ELEMENT === 1) { 16 | return b; 17 | } 18 | return new Uint8Array(b.buffer, b.byteOffset, b.byteLength); 19 | } 20 | throw new Error('invalid buffer like object') 21 | }; 22 | const txtDecoder = new TextDecoder(); 23 | const toString = (possibleString) => { 24 | if (!possibleString) { 25 | return; 26 | } 27 | if (typeof possibleString === 'string') { 28 | return possibleString; 29 | } 30 | if (isArrayBuffer(possibleString) || ArrayBuffer.isView(possibleString) || isDataView(possibleString)) { 31 | return txtDecoder.decode(possibleString); 32 | } 33 | } 34 | const toDataView = b => { 35 | if (!b) { 36 | throw new Error('forgot to pass buffer'); 37 | } 38 | if (isDataView(b)) { 39 | return b; 40 | } 41 | if (isArrayBuffer(b)) { 42 | return new DataView(b); 43 | } 44 | if (isArrayBuffer(b.buffer)) { 45 | return new DataView(b.buffer, b.byteOffset, b.byteLength); 46 | } 47 | throw new Error('invalid buffer like object') 48 | }; 49 | 50 | function isArrayBuffer(subject) { 51 | return subject instanceof globalThis.ArrayBuffer || Object.prototype.toString.call(subject) === '[object ArrayBuffer]'; 52 | } 53 | function isDataView(subject) { 54 | return subject instanceof globalThis.DataView || Object.prototype.toString.call(subject) === '[object DataView]' 55 | } 56 | 57 | export const combine = function ([shp, dbf]) { 58 | const out = {}; 59 | out.type = 'FeatureCollection'; 60 | out.features = []; 61 | let i = 0; 62 | const len = shp.length; 63 | if (!dbf) { 64 | dbf = []; 65 | } 66 | while (i < len) { 67 | out.features.push({ 68 | type: 'Feature', 69 | geometry: shp[i], 70 | properties: dbf[i] || {} 71 | }); 72 | i++; 73 | } 74 | return out; 75 | }; 76 | export const parseZip = async function (buffer, whiteList) { 77 | let key; 78 | buffer = toUitn8Arr(buffer); 79 | const zip = await unzip(buffer); 80 | const names = []; 81 | whiteList = whiteList || []; 82 | for (key in zip) { 83 | if (key.indexOf('__MACOSX') !== -1) { 84 | continue; 85 | } 86 | if (key.slice(-4).toLowerCase() === '.shp') { 87 | names.push(key.slice(0, -4)); 88 | zip[key.slice(0, -3) + key.slice(-3).toLowerCase()] = zip[key]; 89 | } else if (key.slice(-4).toLowerCase() === '.prj') { 90 | zip[key.slice(0, -3) + key.slice(-3).toLowerCase()] = proj4(zip[key]); 91 | } else if (key.slice(-5).toLowerCase() === '.json' || whiteList.indexOf(key.split('.').pop()) > -1) { 92 | names.push(key.slice(0, -3) + key.slice(-3).toLowerCase()); 93 | } else if (key.slice(-4).toLowerCase() === '.dbf' || key.slice(-4).toLowerCase() === '.cpg') { 94 | zip[key.slice(0, -3) + key.slice(-3).toLowerCase()] = zip[key]; 95 | } 96 | } 97 | if (!names.length) { 98 | throw new Error('no layers founds'); 99 | } 100 | const geojson = names.map(function (name) { 101 | let parsed, dbf; 102 | const lastDotIdx = name.lastIndexOf('.'); 103 | if (lastDotIdx > -1 && name.slice(lastDotIdx).indexOf('json') > -1) { 104 | parsed = JSON.parse(zip[name]); 105 | parsed.fileName = name.slice(0, lastDotIdx); 106 | } else if (whiteList.indexOf(name.slice(lastDotIdx + 1)) > -1) { 107 | parsed = zip[name]; 108 | parsed.fileName = name; 109 | } else { 110 | if (zip[name + '.dbf']) { 111 | dbf = parseDbf(zip[name + '.dbf'], zip[name + '.cpg']); 112 | } 113 | parsed = combine([parseShp(zip[name + '.shp'], zip[name + '.prj']), dbf]); 114 | parsed.fileName = name; 115 | } 116 | return parsed; 117 | }); 118 | if (geojson.length === 1) { 119 | return geojson[0]; 120 | } else { 121 | return geojson; 122 | } 123 | }; 124 | async function getZip(base, whiteList) { 125 | const a = await binaryAjax(base); 126 | return parseZip(a, whiteList); 127 | } 128 | const handleShp = async (base) => { 129 | const args = await Promise.all([ 130 | binaryAjax(base, 'shp'), 131 | binaryAjax(base, 'prj') 132 | ]); 133 | let prj = false; 134 | try { 135 | if (args[1]) { 136 | prj = proj4(args[1]); 137 | } 138 | } catch (e) { 139 | prj = false; 140 | } 141 | return parseShp(args[0], prj); 142 | }; 143 | const handleDbf = async (base) => { 144 | const [dbf, cpg] = await Promise.all([ 145 | binaryAjax(base, 'dbf'), 146 | binaryAjax(base, 'cpg') 147 | ]); 148 | if (!dbf) { 149 | return; 150 | } 151 | return parseDbf(dbf, cpg); 152 | }; 153 | const checkSuffix = (base, suffix) => { 154 | const url = new URL(base, globalThis?.document?.location); 155 | return url.pathname.slice(-4).toLowerCase() === suffix; 156 | }; 157 | const fromObject = ({ shp, dbf, cpg, prj }) => { 158 | const things = [ 159 | _parseShp(shp, prj) 160 | ] 161 | if (dbf) { 162 | things.push(_parseDbf(dbf, cpg)); 163 | } 164 | return combine(things); 165 | } 166 | export const getShapefile = async function (base, whiteList) { 167 | if (typeof base !== 'string') { 168 | if (isArrayBuffer(base) || ArrayBuffer.isView(base) || isDataView(base)) { 169 | return parseZip(base); 170 | } 171 | if (base.shp) { 172 | return fromObject(base); 173 | } 174 | throw new TypeError('must be a string, some sort of Buffer, or an object with at least a .shp property') 175 | } 176 | if (checkSuffix(base, '.zip')) { 177 | return getZip(base, whiteList); 178 | } 179 | if (checkSuffix(base, '.shp')) { 180 | base = base.slice(0, -4); 181 | } 182 | const results = await Promise.all([ 183 | handleShp(base), 184 | handleDbf(base) 185 | ]); 186 | return combine(results); 187 | }; 188 | const _parseShp = function (shp, prj) { 189 | shp = toDataView(shp); 190 | prj = toString(prj); 191 | if (typeof prj === 'string') { 192 | try { 193 | prj = proj4(prj); 194 | } catch (e) { 195 | prj = false; 196 | } 197 | } 198 | return parseShp(shp, prj); 199 | }; 200 | const _parseDbf = function (dbf, cpg) { 201 | dbf = toDataView(dbf); 202 | cpg = toString(cpg); 203 | return parseDbf(dbf, cpg); 204 | }; 205 | export default getShapefile; 206 | export { 207 | _parseDbf as parseDbf, 208 | _parseShp as parseShp, 209 | } -------------------------------------------------------------------------------- /lib/parseShp.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function isClockWise(array) { 4 | let sum = 0; 5 | let i = 1; 6 | const len = array.length; 7 | let prev, cur; 8 | const bbox = [array[0][0], array[0][1], array[0][0], array[0][1]]; 9 | while (i < len) { 10 | prev = cur || array[0]; 11 | cur = array[i]; 12 | sum += ((cur[0] - prev[0]) * (cur[1] + prev[1])); 13 | i++; 14 | if (cur[0] < bbox[0]) { 15 | bbox[0] = cur[0]; 16 | } 17 | if (cur[1] < bbox[1]) { 18 | bbox[1] = cur[1]; 19 | } 20 | if (cur[0] > bbox[2]) { 21 | bbox[2] = cur[0]; 22 | } 23 | if (cur[1] > bbox[3]) { 24 | bbox[3] = cur[1]; 25 | } 26 | } 27 | return { 28 | ring: array, 29 | clockWise: sum > 0, 30 | bbox, 31 | children: [] 32 | } 33 | 34 | } 35 | 36 | function contains(outer, inner) { 37 | if (outer.bbox[0] > inner.bbox[0]) { 38 | return false; 39 | } 40 | if (outer.bbox[1] > inner.bbox[1]) { 41 | return false; 42 | } 43 | if (outer.bbox[2] < inner.bbox[2]) { 44 | return false; 45 | } 46 | if (outer.bbox[3] < inner.bbox[3]) { 47 | return false; 48 | } 49 | return true; 50 | } 51 | 52 | function handleRings(rings) { 53 | const outers = []; 54 | const inners = []; 55 | for (const ring of rings) { 56 | const proccessed = isClockWise(ring); 57 | if (proccessed.clockWise) { 58 | outers.push(proccessed) 59 | } else { 60 | inners.push(proccessed) 61 | } 62 | } 63 | // this is an optimization, 64 | // but it would also put in weird bad rings that would otherwise get left out 65 | // if (outers.length === 1) { 66 | // const out = [outers[0].ring] 67 | // for (const inner of inners) { 68 | // out.push(inner.ring); 69 | 70 | // } 71 | // return [out]; 72 | // } 73 | for (const inner of inners) { 74 | for (const outer of outers) { 75 | if (contains(outer, inner)) { 76 | outer.children.push(inner.ring); 77 | break; 78 | } 79 | } 80 | } 81 | const out = []; 82 | for (const outer of outers) { 83 | out.push([outer.ring].concat(outer.children)); 84 | } 85 | return out; 86 | } 87 | function polyReduce(a, b) { 88 | if (isClockWise(b) || !a.length) { 89 | a.push([b]); 90 | } else { 91 | a[a.length - 1].push(b); 92 | } 93 | return a; 94 | } 95 | ParseShp.prototype.parsePoint = function (data) { 96 | return { 97 | type: 'Point', 98 | coordinates: this.parseCoord(data, 0) 99 | }; 100 | }; 101 | ParseShp.prototype.parseZPoint = function (data) { 102 | const pointXY = this.parsePoint(data); 103 | pointXY.coordinates.push(data.getFloat64(16, true)); 104 | return pointXY; 105 | }; 106 | ParseShp.prototype.parsePointArray = function (data, offset, num) { 107 | const out = []; 108 | let done = 0; 109 | while (done < num) { 110 | out.push(this.parseCoord(data, offset)); 111 | offset += 16; 112 | done++; 113 | } 114 | return out; 115 | }; 116 | ParseShp.prototype.parseZPointArray = function (data, zOffset, num, coordinates) { 117 | let i = 0; 118 | while (i < num) { 119 | coordinates[i].push(data.getFloat64(zOffset, true)); 120 | i++; 121 | zOffset += 8; 122 | } 123 | return coordinates; 124 | }; 125 | ParseShp.prototype.parseArrayGroup = function (data, offset, partOffset, num, tot) { 126 | const out = []; 127 | let done = 0; 128 | let curNum; let nextNum = 0; 129 | let pointNumber; 130 | while (done < num) { 131 | done++; 132 | partOffset += 4; 133 | curNum = nextNum; 134 | if (done === num) { 135 | nextNum = tot; 136 | } else { 137 | nextNum = data.getInt32(partOffset, true); 138 | } 139 | pointNumber = nextNum - curNum; 140 | if (!pointNumber) { 141 | continue; 142 | } 143 | out.push(this.parsePointArray(data, offset, pointNumber)); 144 | offset += (pointNumber << 4); 145 | } 146 | return out; 147 | }; 148 | ParseShp.prototype.parseZArrayGroup = function (data, zOffset, num, coordinates) { 149 | let i = 0; 150 | while (i < num) { 151 | coordinates[i] = this.parseZPointArray(data, zOffset, coordinates[i].length, coordinates[i]); 152 | zOffset += (coordinates[i].length << 3); 153 | i++; 154 | } 155 | return coordinates; 156 | }; 157 | ParseShp.prototype.parseMultiPoint = function (data) { 158 | const out = {}; 159 | const num = data.getInt32(32, true); 160 | if (!num) { 161 | return null; 162 | } 163 | const mins = this.parseCoord(data, 0); 164 | const maxs = this.parseCoord(data, 16); 165 | out.bbox = [ 166 | mins[0], 167 | mins[1], 168 | maxs[0], 169 | maxs[1] 170 | ]; 171 | const offset = 36; 172 | if (num === 1) { 173 | out.type = 'Point'; 174 | out.coordinates = this.parseCoord(data, offset); 175 | } else { 176 | out.type = 'MultiPoint'; 177 | out.coordinates = this.parsePointArray(data, offset, num); 178 | } 179 | return out; 180 | }; 181 | ParseShp.prototype.parseZMultiPoint = function (data) { 182 | const geoJson = this.parseMultiPoint(data); 183 | if (!geoJson) { 184 | return null; 185 | } 186 | let num; 187 | if (geoJson.type === 'Point') { 188 | geoJson.coordinates.push(data.getFloat64(72, true)); 189 | return geoJson; 190 | } else { 191 | num = geoJson.coordinates.length; 192 | } 193 | const zOffset = 52 + (num << 4); 194 | geoJson.coordinates = this.parseZPointArray(data, zOffset, num, geoJson.coordinates); 195 | return geoJson; 196 | }; 197 | ParseShp.prototype.parsePolyline = function (data) { 198 | const out = {}; 199 | const numParts = data.getInt32(32, true); 200 | if (!numParts) { 201 | return null; 202 | } 203 | const mins = this.parseCoord(data, 0); 204 | const maxs = this.parseCoord(data, 16); 205 | out.bbox = [ 206 | mins[0], 207 | mins[1], 208 | maxs[0], 209 | maxs[1] 210 | ]; 211 | const num = data.getInt32(36, true); 212 | let offset, partOffset; 213 | if (numParts === 1) { 214 | out.type = 'LineString'; 215 | offset = 44; 216 | out.coordinates = this.parsePointArray(data, offset, num); 217 | } else { 218 | out.type = 'MultiLineString'; 219 | offset = 40 + (numParts << 2); 220 | partOffset = 40; 221 | out.coordinates = this.parseArrayGroup(data, offset, partOffset, numParts, num); 222 | } 223 | return out; 224 | }; 225 | ParseShp.prototype.parseZPolyline = function (data) { 226 | const geoJson = this.parsePolyline(data); 227 | if (!geoJson) { 228 | return null; 229 | } 230 | const num = geoJson.coordinates.length; 231 | let zOffset; 232 | if (geoJson.type === 'LineString') { 233 | zOffset = 60 + (num << 4); 234 | geoJson.coordinates = this.parseZPointArray(data, zOffset, num, geoJson.coordinates); 235 | return geoJson; 236 | } else { 237 | const totalPoints = geoJson.coordinates.reduce(function (a, v) { 238 | return a + v.length; 239 | }, 0); 240 | zOffset = 56 + (totalPoints << 4) + (num << 2); 241 | geoJson.coordinates = this.parseZArrayGroup(data, zOffset, num, geoJson.coordinates); 242 | return geoJson; 243 | } 244 | }; 245 | ParseShp.prototype.polyFuncs = function (out) { 246 | if (!out) { 247 | return out; 248 | } 249 | if (out.type === 'LineString') { 250 | out.type = 'Polygon'; 251 | out.coordinates = [out.coordinates]; 252 | return out; 253 | } else { 254 | out.coordinates = handleRings(out.coordinates) 255 | if (out.coordinates.length === 1) { 256 | out.type = 'Polygon'; 257 | out.coordinates = out.coordinates[0]; 258 | return out; 259 | } else { 260 | out.type = 'MultiPolygon'; 261 | return out; 262 | } 263 | } 264 | }; 265 | ParseShp.prototype.parsePolygon = function (data) { 266 | return this.polyFuncs(this.parsePolyline(data)); 267 | }; 268 | ParseShp.prototype.parseZPolygon = function (data) { 269 | return this.polyFuncs(this.parseZPolyline(data)); 270 | }; 271 | const shpFuncObj = { 272 | 1: 'parsePoint', 273 | 3: 'parsePolyline', 274 | 5: 'parsePolygon', 275 | 8: 'parseMultiPoint', 276 | 11: 'parseZPoint', 277 | 13: 'parseZPolyline', 278 | 15: 'parseZPolygon', 279 | 18: 'parseZMultiPoint' 280 | }; 281 | 282 | function makeParseCoord(trans) { 283 | if (trans) { 284 | return function (data, offset) { 285 | const args = [data.getFloat64(offset, true), data.getFloat64(offset + 8, true)]; 286 | return trans.inverse(args); 287 | }; 288 | } else { 289 | return function (data, offset) { 290 | return [data.getFloat64(offset, true), data.getFloat64(offset + 8, true)]; 291 | }; 292 | } 293 | } 294 | 295 | function ParseShp(buffer, trans) { 296 | if (!(this instanceof ParseShp)) { 297 | return new ParseShp(buffer, trans); 298 | } 299 | this.buffer = buffer; 300 | this.headers = this.parseHeader(); 301 | this.shpFuncs(trans); 302 | this.rows = this.getRows(); 303 | } 304 | ParseShp.prototype.shpFuncs = function (tran) { 305 | let num = this.headers.shpCode; 306 | if (num > 20) { 307 | num -= 20; 308 | } 309 | if (!(num in shpFuncObj)) { 310 | throw new Error(`I don't know shp type "${num}"`); 311 | } 312 | this.parseFunc = this[shpFuncObj[num]]; 313 | this.parseCoord = makeParseCoord(tran); 314 | }; 315 | ParseShp.prototype.getShpCode = function () { 316 | return this.parseHeader().shpCode; 317 | }; 318 | ParseShp.prototype.parseHeader = function () { 319 | const view = this.buffer; 320 | return { 321 | length: view.getInt32(6 << 2) << 1, 322 | version: view.getInt32(7 << 2, true), 323 | shpCode: view.getInt32(8 << 2, true), 324 | bbox: [ 325 | view.getFloat64(9 << 2, true), 326 | view.getFloat64(11 << 2, true), 327 | view.getFloat64(13 << 2, true), 328 | view.getFloat64(15 << 2, true) 329 | ] 330 | }; 331 | }; 332 | ParseShp.prototype.getRows = function () { 333 | let offset = 100; 334 | const len = this.buffer.byteLength - 8; 335 | const out = []; 336 | let current; 337 | while (offset <= len) { 338 | current = this.getRow(offset); 339 | if (!current) { 340 | break; 341 | } 342 | offset += 8; 343 | offset += current.len; 344 | if (current.type) { 345 | out.push(this.parseFunc(current.data)); 346 | } else { 347 | out.push(null); 348 | } 349 | } 350 | return out; 351 | }; 352 | ParseShp.prototype.getRow = function (offset) { 353 | const id = this.buffer.getInt32(offset); 354 | const len = this.buffer.getInt32(offset + 4) << 1; 355 | if (len === 0) { 356 | return { 357 | id: id, 358 | len: len, 359 | type: 0 360 | }; 361 | } 362 | 363 | if (offset + len + 8 > this.buffer.byteLength) { 364 | return; 365 | } 366 | return { 367 | id: id, 368 | len: len, 369 | data: new DataView(this.buffer.buffer, this.buffer.byteOffset + offset + 12, len - 4), 370 | type: this.buffer.getInt32(offset + 8, true) 371 | }; 372 | }; 373 | export default function (buffer, trans) { 374 | return new ParseShp(buffer, trans).rows; 375 | }; 376 | -------------------------------------------------------------------------------- /lib/unzip.js: -------------------------------------------------------------------------------- 1 | import { iter } from 'but-unzip'; 2 | 3 | const regex = /.+\.(shp|dbf|json|prj|cpg)$/i; 4 | export default async (buffer) => { 5 | const files = {}; 6 | const proms = []; 7 | for (const entry of iter(buffer)) { 8 | if (!regex.test(entry.filename)) { 9 | continue; 10 | } 11 | proms.push(Promise.resolve(entry.read()).then(bytes => files[entry.filename] = bytes)); 12 | } 13 | await Promise.all(proms); 14 | const out = {}; 15 | const decoder = new TextDecoder(); 16 | for (const [key, value] of Object.entries(files)) { 17 | if (key.slice(-3).toLowerCase() === 'shp' || key.slice(-3).toLowerCase() === 'dbf') { 18 | out[key] = new DataView(value.buffer, value.byteOffset, value.byteLength) 19 | } else { 20 | out[key] = decoder.decode(value); 21 | } 22 | } 23 | return out; 24 | }; 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shpjs", 3 | "version": "6.1.0", 4 | "description": "Load shapefiles in pure JavaScript", 5 | "main": "lib/index.js", 6 | "exports": { 7 | "import": "./lib/index.js", 8 | "require": "./dist/shp.js" 9 | }, 10 | "type": "module", 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/calvinmetcalf/shapefile-js.git" 14 | }, 15 | "scripts": { 16 | "test": "mocha --require test/fixtures.js ./test/test.js", 17 | "build": "rollup -c", 18 | "test-browser": "SERVING=true node test/server.js" 19 | }, 20 | "author": "Calvin Metcalf", 21 | "license": "MIT", 22 | "readmeFilename": "README.md", 23 | "devDependencies": { 24 | "@rollup/plugin-node-resolve": "^15.2.3", 25 | "@rollup/plugin-terser": "^0.4.4", 26 | "chai": "^5.1.0", 27 | "chai-promised": "^1.0.2", 28 | "eslint": "^8.24.0", 29 | "express": "^4.17.2", 30 | "mocha": "^8.2.0", 31 | "morgan": "^1.10.0", 32 | "rollup": "^4.13.0", 33 | "semistandard": "^16.0.1" 34 | }, 35 | "dependencies": { 36 | "but-unzip": "^0.1.4", 37 | "parsedbf": "^2.0.0", 38 | "proj4": "^2.1.4" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 2 | import terser from '@rollup/plugin-terser'; 3 | 4 | export default [{ 5 | input: './lib/browser.js', 6 | plugins: [ 7 | nodeResolve({ browser: true }) 8 | ], 9 | output: [{ 10 | file: './dist/shp.js', 11 | format: 'umd', 12 | name: 'shp' 13 | }, { 14 | file: './dist/shp.min.js', 15 | format: 'umd', 16 | name: 'shp', 17 | plugins: [terser()] 18 | }] 19 | }, { 20 | input: './lib/index.js', 21 | plugins: [ 22 | nodeResolve({ browser: true }) 23 | ], 24 | output: [{ 25 | file: './dist/shp.esm.js', 26 | format: 'esm' 27 | }, { 28 | file: './dist/shp.esm.min.js', 29 | format: 'esm', 30 | plugins: [terser()] 31 | }] 32 | }] -------------------------------------------------------------------------------- /site/catiline.js: -------------------------------------------------------------------------------- 1 | /*! catiline 2.4.2 2013-08-08*/ 2 | /*!©2013 Calvin Metcalf @license MIT https://github.com/calvinmetcalf/catiline */ 3 | if (typeof document === 'undefined') { 4 | self._noTransferable=true; 5 | self.onmessage=function(e){ 6 | /*jslint evil: true */ 7 | eval(e.data); 8 | }; 9 | } else { 10 | (function(global){ 11 | 'use strict'; 12 | /*!From setImmediate Copyright (c) 2012 Barnesandnoble.com,llc, Donavon West, and Domenic Denicola @license MIT https://github.com/NobleJS/setImmediate */ 13 | (function(attachTo,global) { 14 | var tasks = (function () { 15 | function Task(handler, args) { 16 | this.handler = handler; 17 | this.args = args; 18 | } 19 | Task.prototype.run = function () { 20 | // See steps in section 5 of the spec. 21 | if (typeof this.handler === 'function') { 22 | // Choice of `thisArg` is not in the setImmediate spec; `undefined` is in the setTimeout spec though: 23 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html 24 | this.handler.apply(undefined, this.args); 25 | } else { 26 | var scriptSource = '' + this.handler; 27 | /*jshint evil: true */ 28 | eval(scriptSource); 29 | } 30 | }; 31 | 32 | var nextHandle = 1; // Spec says greater than zero 33 | var tasksByHandle = {}; 34 | var currentlyRunningATask = false; 35 | 36 | return { 37 | addFromSetImmediateArguments: function (args) { 38 | var handler = args[0]; 39 | var argsToHandle = Array.prototype.slice.call(args, 1); 40 | var task = new Task(handler, argsToHandle); 41 | 42 | var thisHandle = nextHandle++; 43 | tasksByHandle[thisHandle] = task; 44 | return thisHandle; 45 | }, 46 | runIfPresent: function (handle) { 47 | // From the spec: 'Wait until any invocations of this algorithm started before this one have completed.' 48 | // So if we're currently running a task, we'll need to delay this invocation. 49 | if (!currentlyRunningATask) { 50 | var task = tasksByHandle[handle]; 51 | if (task) { 52 | currentlyRunningATask = true; 53 | try { 54 | task.run(); 55 | } finally { 56 | delete tasksByHandle[handle]; 57 | currentlyRunningATask = false; 58 | } 59 | } 60 | } else { 61 | // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a 62 | // 'too much recursion' error. 63 | global.setTimeout(function () { 64 | tasks.runIfPresent(handle); 65 | }, 0); 66 | } 67 | }, 68 | remove: function (handle) { 69 | delete tasksByHandle[handle]; 70 | } 71 | }; 72 | }()); 73 | // Installs an event handler on `global` for the `message` event: see 74 | // * https://developer.mozilla.org/en/DOM/window.postMessage 75 | // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages 76 | 77 | var MESSAGE_PREFIX = 'com.catilinejs.setImmediate' + Math.random(); 78 | 79 | function isStringAndStartsWith(string, putativeStart) { 80 | return typeof string === 'string' && string.substring(0, putativeStart.length) === putativeStart; 81 | } 82 | 83 | function onGlobalMessage(event) { 84 | // This will catch all incoming messages (even from other windows!), so we need to try reasonably hard to 85 | // avoid letting anyone else trick us into firing off. We test the origin is still this window, and that a 86 | // (randomly generated) unpredictable identifying prefix is present. 87 | if (event.source === global && isStringAndStartsWith(event.data, MESSAGE_PREFIX)) { 88 | var handle = event.data.substring(MESSAGE_PREFIX.length); 89 | tasks.runIfPresent(handle); 90 | } 91 | } 92 | if (global.addEventListener) { 93 | global.addEventListener('message', onGlobalMessage, false); 94 | } else { 95 | global.attachEvent('onmessage', onGlobalMessage); 96 | } 97 | 98 | attachTo.setImmediate = function () { 99 | var handle = tasks.addFromSetImmediateArguments(arguments); 100 | 101 | // Make `global` post a message to itself with the handle and identifying prefix, thus asynchronously 102 | // invoking our onGlobalMessage listener above. 103 | global.postMessage(MESSAGE_PREFIX + handle, '*'); 104 | 105 | return handle; 106 | }; 107 | })(catiline,global); 108 | 109 | /*! Promiscuous ©2013 Ruben Verborgh @license MIT https://github.com/RubenVerborgh/promiscuous*/ 110 | (function (exports,tick) { 111 | var func = 'function'; 112 | // Creates a deferred: an object with a promise and corresponding resolve/reject methods 113 | function Deferred() { 114 | // The `handler` variable points to the function that will 115 | // 1) handle a .then(onFulfilled, onRejected) call 116 | // 2) handle a .resolve or .reject call (if not fulfilled) 117 | // Before 2), `handler` holds a queue of callbacks. 118 | // After 2), `handler` is a simple .then handler. 119 | // We use only one function to save memory and complexity. 120 | var handler = function (onFulfilled, onRejected, value) { 121 | // Case 1) handle a .then(onFulfilled, onRejected) call 122 | var createdDeffered; 123 | if (onFulfilled !== handler) { 124 | createdDeffered = createDeferred(); 125 | handler.queue.push({ deferred: createdDeffered, resolve: onFulfilled, reject: onRejected }); 126 | return createdDeffered.promise; 127 | } 128 | 129 | // Case 2) handle a .resolve or .reject call 130 | // (`onFulfilled` acts as a sentinel) 131 | // The actual function signature is 132 | // .re[ject|solve](sentinel, success, value) 133 | var action = onRejected ? 'resolve' : 'reject',queue,deferred,callback; 134 | for (var i = 0, l = handler.queue.length; i < l; i++) { 135 | queue = handler.queue[i]; 136 | deferred = queue.deferred; 137 | callback = queue[action]; 138 | if (typeof callback !== func) { 139 | deferred[action](value); 140 | } else { 141 | execute(callback, value, deferred); 142 | } 143 | } 144 | // Replace this handler with a simple resolved or rejected handler 145 | handler = createHandler(promise, value, onRejected); 146 | }; 147 | function Promise(){ 148 | this.then=function (onFulfilled, onRejected) { 149 | return handler(onFulfilled, onRejected); 150 | }; 151 | } 152 | var promise = new Promise(); 153 | this.promise = promise; 154 | // The queue of deferreds 155 | handler.queue = []; 156 | 157 | this.resolve = function (value) { 158 | handler.queue && handler(handler, true, value); 159 | }; 160 | 161 | this.reject = function (reason) { 162 | handler.queue && handler(handler, false, reason); 163 | }; 164 | } 165 | 166 | function createDeferred(){ 167 | return new Deferred(); 168 | } 169 | 170 | // Creates a fulfilled or rejected .then function 171 | function createHandler(promise, value, success) { 172 | return function (onFulfilled, onRejected) { 173 | var callback = success ? onFulfilled : onRejected, result; 174 | if (typeof callback !== func) { 175 | return promise; 176 | } 177 | execute(callback, value, result = createDeferred()); 178 | return result.promise; 179 | }; 180 | } 181 | 182 | // Executes the callback with the specified value, 183 | // resolving or rejecting the deferred 184 | function execute(callback, value, deferred) { 185 | tick(function () { 186 | var result; 187 | try { 188 | result = callback(value); 189 | if (result && typeof result.then === func) { 190 | result.then(deferred.resolve, deferred.reject); 191 | } else { 192 | deferred.resolve(result); 193 | } 194 | } 195 | catch (error) { 196 | deferred.reject(error); 197 | } 198 | }); 199 | } 200 | 201 | // Returns a resolved promise 202 | exports.resolve= function (value) { 203 | var promise = {}; 204 | promise.then = createHandler(promise, value, true); 205 | return promise; 206 | }; 207 | // Returns a rejected promise 208 | exports.reject= function (reason) { 209 | var promise = {}; 210 | promise.then = createHandler(promise, reason, false); 211 | return promise; 212 | }; 213 | // Returns a deferred 214 | exports.deferred= createDeferred; 215 | exports.all=function(array){ 216 | var promise = exports.deferred(); 217 | var len = array.length; 218 | var resolved=0; 219 | var out = []; 220 | var onSuccess=function(n){ 221 | return function(v){ 222 | out[n]=v; 223 | resolved++; 224 | if(resolved===len){ 225 | promise.resolve(out); 226 | } 227 | }; 228 | }; 229 | array.forEach(function(v,i){ 230 | v.then(onSuccess(i),function(a){ 231 | promise.reject(a); 232 | }); 233 | }); 234 | return promise.promise; 235 | }; 236 | })(catiline,catiline.setImmediate); 237 | 238 | catiline._hasWorker = typeof Worker !== 'undefined'&&typeof fakeLegacy === 'undefined'; 239 | catiline.URL = window.URL || window.webkitURL; 240 | catiline._noTransferable=!catiline.URL; 241 | //regex out the importScript call and move it up to the top out of the function. 242 | function regexImports(string){ 243 | var rest=string, 244 | match = true, 245 | matches = {}, 246 | loopFunc = function(a,b){ 247 | if(b){ 248 | 'importScripts('+b.split(',').forEach(function(cc){ 249 | matches[catiline.makeUrl(cc.match(/\s*[\'\"](\S*)[\'\"]\s*/)[1])]=true; // trim whitespace, add to matches 250 | })+');\n'; 251 | } 252 | }; 253 | while(match){ 254 | match = rest.match(/(importScripts\(.*?\);?)/); 255 | rest = rest.replace(/(importScripts\(\s*(?:[\'\"].*?[\'\"])?\s*\);?)/,'\n'); 256 | if(match){ 257 | match[0].replace(/importScripts\(\s*([\'\"].*?[\'\"])?\s*\);?/g,loopFunc); 258 | } 259 | } 260 | matches = Object.keys(matches); 261 | return [matches,rest]; 262 | } 263 | 264 | function moveImports(string){ 265 | var str = regexImports(string); 266 | var matches = str[0]; 267 | var rest = str[1]; 268 | if(matches.length>0){ 269 | return 'importScripts(\''+matches.join('\',\'')+'\');\n'+rest; 270 | }else{ 271 | return rest; 272 | } 273 | } 274 | function moveIimports(string){ 275 | var str = regexImports(string); 276 | var matches = str[0]; 277 | var rest = str[1]; 278 | if(matches.length>0){ 279 | return 'importScripts(\''+matches.join('\',\'')+'\');eval(__scripts__);\n'+rest; 280 | }else{ 281 | return rest; 282 | } 283 | } 284 | function getPath(){ 285 | if(typeof SHIM_WORKER_PATH !== 'undefined'){ 286 | return SHIM_WORKER_PATH; 287 | }else if('SHIM_WORKER_PATH' in catiline){ 288 | return catiline.SHIM_WORKER_PATH; 289 | } 290 | var scripts = document.getElementsByTagName('script'); 291 | var len = scripts.length; 292 | var i = 0; 293 | while(i0){', 328 | ' scripts.forEach(function(url){', 329 | ' var ajax = new XMLHttpRequest();', 330 | ' ajax.open(\'GET\',url,false);', 331 | ' ajax.send();__scripts__+=ajax.responseText;', 332 | ' __scripts__+=\'\\n;\';', 333 | ' });', 334 | ' }', 335 | '};', 336 | script, 337 | '}catch(e){', 338 | ' window.parent.postMessage([\''+codeword+'\',\'error\'],\'*\')', 339 | '}'].join('\n'); 340 | appendScript(iDoc,text); 341 | 342 | return iFrame; 343 | } 344 | function makeIframe(script,codeword){ 345 | var promise = catiline.deferred(); 346 | if(document.readyState==='complete'){ 347 | promise.resolve(actualMakeI(script,codeword)); 348 | }else{ 349 | window.addEventListener('load',function(){ 350 | promise.resolve(actualMakeI(script,codeword)); 351 | },false); 352 | } 353 | return promise.promise; 354 | } 355 | catiline.makeIWorker = function (strings,codeword){ 356 | var script =moveIimports(strings.join('')); 357 | var worker = {onmessage:function(){}}; 358 | var ipromise = makeIframe(script,codeword); 359 | window.addEventListener('message',function(e){ 360 | if(typeof e.data ==='string'&&e.data.length>codeword.length&&e.data.slice(0,codeword.length)===codeword){ 361 | worker.onmessage({data:JSON.parse(e.data.slice(codeword.length))}); 362 | } 363 | }); 364 | worker.postMessage=function(data){ 365 | ipromise.then(function(iFrame){ 366 | iFrame.contentWindow.postMessage(JSON.stringify(data),'*'); 367 | }); 368 | }; 369 | worker.terminate=function(){ 370 | ipromise.then(function(iFrame){ 371 | document.body.removeChild(iFrame); 372 | }); 373 | }; 374 | return worker; 375 | 376 | }; 377 | //accepts an array of strings, joins them, and turns them into a worker. 378 | function makeFallbackWorker(script){ 379 | catiline._noTransferable=true; 380 | var worker = new Worker(getPath()); 381 | worker.postMessage(script); 382 | return worker; 383 | } 384 | catiline.makeWorker = function (strings, codeword){ 385 | if(!catiline._hasWorker){ 386 | return catiline.makeIWorker(strings,codeword); 387 | } 388 | var worker; 389 | var script =moveImports(strings.join('')); 390 | if(catiline._noTransferable){ 391 | return makeFallbackWorker(script); 392 | } 393 | try{ 394 | worker= new Worker(catiline.URL.createObjectURL(new Blob([script],{type: 'text/javascript'}))); 395 | }catch(e){ 396 | try{ 397 | worker=makeFallbackWorker(script); 398 | }catch(ee){ 399 | worker = catiline.makeIWorker(strings,codeword); 400 | } 401 | }finally{ 402 | return worker; 403 | } 404 | }; 405 | 406 | catiline.makeUrl = function (fileName) { 407 | var link = document.createElement('link'); 408 | link.href = fileName; 409 | return link.href; 410 | }; 411 | 412 | catiline.Worker = function Catiline(obj) { 413 | if(typeof obj === 'function'){ 414 | obj = { 415 | data:obj 416 | }; 417 | } 418 | var __codeWord__='com.catilinejs.'+(catiline._hasWorker?'iframe':'worker')+Math.random(); 419 | var listeners = {}; 420 | var self = this; 421 | self.on = function (eventName, func, scope) { 422 | scope = scope || self; 423 | if (eventName.indexOf(' ') > 0) { 424 | eventName.split(' ').map(function (v) { 425 | return self.on(v, func, scope); 426 | }, this); 427 | return self; 428 | } 429 | if (!(eventName in listeners)) { 430 | listeners[eventName] = []; 431 | } 432 | listeners[eventName].push(function (a) { 433 | func.call(scope, a); 434 | }); 435 | return self; 436 | }; 437 | 438 | function _fire(eventName, data) { 439 | if (eventName.indexOf(' ') > 0) { 440 | eventName.split(' ').forEach(function (v) { 441 | _fire(v, data); 442 | }); 443 | return self; 444 | } 445 | if (!(eventName in listeners)) { 446 | return self; 447 | } 448 | listeners[eventName].forEach(function (v) { 449 | v(data); 450 | }); 451 | return self; 452 | } 453 | self.fire = function (eventName, data, transfer) { 454 | if(catiline._noTransferable){ 455 | worker.postMessage([[eventName], data]); 456 | }else{ 457 | worker.postMessage([[eventName], data], transfer); 458 | } 459 | 460 | return self; 461 | }; 462 | self.off = function (eventName, func) { 463 | if (eventName.indexOf(' ') > 0) { 464 | eventName.split(' ').map(function (v) { 465 | return self.off(v, func); 466 | }); 467 | return self; 468 | } 469 | if (!(eventName in listeners)) { 470 | return self; 471 | } 472 | else if (!func) { 473 | delete listeners[eventName]; 474 | } 475 | else { 476 | if (listeners[eventName].indexOf(func) > -1) { 477 | if (listeners[eventName].length > 1) { 478 | delete listeners[eventName]; 479 | } 480 | else { 481 | listeners[eventName].splice(listeners[eventName].indexOf(func), 1); 482 | } 483 | } 484 | } 485 | return self; 486 | }; 487 | var i = 0; 488 | var promises = []; 489 | var rejectPromises = function (msg) { 490 | if (typeof msg !== 'string' && 'preventDefault' in msg) { 491 | msg.preventDefault(); 492 | msg = msg.message; 493 | } 494 | promises.forEach(function (p) { 495 | if (p) { 496 | p.reject(msg); 497 | } 498 | }); 499 | }; 500 | obj.__codeWord__='"'+__codeWord__+'"'; 501 | if (!('initialize' in obj)) { 502 | if ('init' in obj) { 503 | obj.initialize = obj.init; 504 | } 505 | else { 506 | obj.initialize = function () {}; 507 | } 508 | } 509 | var fObj = '{\n\t'; 510 | var keyFunc = function (key) { 511 | var out = function (data, transfer) { 512 | var i = promises.length; 513 | promises[i] = catiline.deferred(); 514 | if(catiline._noTransferable){ 515 | worker.postMessage([[__codeWord__, i], key, data]); 516 | }else{ 517 | worker.postMessage([[__codeWord__, i], key, data], transfer); 518 | } 519 | return promises[i].promise; 520 | }; 521 | return out; 522 | }; 523 | for (var key in obj) { 524 | if (i !== 0) { 525 | fObj = fObj + ',\n\t'; 526 | } 527 | else { 528 | i++; 529 | } 530 | fObj = fObj + key + ':' + obj[key].toString(); 531 | self[key] = keyFunc(key); 532 | } 533 | fObj = fObj + '}'; 534 | var worker = catiline.makeWorker(['\'use strict\';\n\nvar _db = ',fObj,';\nvar listeners = {};\nvar __iFrame__ = typeof document!=="undefined";\nvar __self__={onmessage:function(e){\n _fire("messege",e.data[1]);\n if(e.data[0][0]===_db.__codeWord__){\n return regMsg(e);\n }else{\n _fire(e.data[0][0],e.data[1]);\n }\n}};\nif(__iFrame__){\n window.onmessage=function(e){\n if(typeof e.data === "string"){\n e ={data: JSON.parse(e.data)};\n }\n __self__.onmessage(e);\n };\n}else{\n self.onmessage=__self__.onmessage;\n}\n__self__.postMessage=function(rawData, transfer){\n var data;\n if(!self._noTransferable&&!__iFrame__){\n self.postMessage(rawData, transfer);\n }else if(__iFrame__){\n data = _db.__codeWord__+JSON.stringify(rawData);\n window.parent.postMessage(data,"*");\n }else if(self._noTransferable){\n self.postMessage(rawData);\n }\n};\n_db.on = function (eventName, func, scope) {\n if(eventName.indexOf(" ")>0){\n return eventName.split(" ").map(function(v){\n return _db.on(v,func,scope);\n },_db);\n }\n scope = scope || _db;\n if (!(eventName in listeners)) {\n listeners[eventName] = [];\n }\n listeners[eventName].push(function (a) {\n func.call(scope, a, _db);\n });\n};\nfunction _fire(eventName,data){\n if(eventName.indexOf(" ")>0){\n eventName.split(" ").forEach(function(v){\n _fire(v,data);\n });\n return;\n }\n if (!(eventName in listeners)) {\n return;\n }\n listeners[eventName].forEach(function (v) {\n v(data);\n });\n}\n\n_db.fire = function (eventName, data, transfer) {\n __self__.postMessage([[eventName], data], transfer);\n};\n_db.off=function(eventName,func){\n if(eventName.indexOf(" ")>0){\n return eventName.split(" ").map(function(v){\n return _db.off(v,func);\n });\n }\n if(!(eventName in listeners)){\n return;\n }else if(!func){\n delete listeners[eventName];\n }else{\n if(listeners[eventName].indexOf(func)>-1){\n if(listeners[eventName].length>1){\n delete listeners[eventName];\n }else{\n listeners[eventName].splice(listeners[eventName].indexOf(func),1);\n }\n }\n }\n};\nvar console={};\nfunction makeConsole(method){\n return function(){\n var len = arguments.length;\n var out =[];\n var i = 0;\n while (if)return a;e.splice(f,d);return e.concat(c||[]).join("/")}return c}function H(a){var b=a.indexOf("!");return{g:a.substr(b+1),d:0<=b&&a.substr(0,b)}}function M(){}function u(a,b){M.prototype= 4 | a||N;var d=new M;M.prototype=N;for(var c in b)d[c]=b[c];return d}function A(){function a(a,b,d){c.push([a,b,d])}function b(a,b){for(var d,e=0;d=c[e++];)(d=d[a])&&d(b)}var d,c,e;d=this;c=[];e=function(d,g){a=d?function(a){a&&a(g)}:function(a,b){b&&b(g)};e=R;b(d?0:1,g);b=R;c=k};this.A=function(b,c,e){a(b,c,e);return d};this.h=function(a){d.oa=a;e(!0,a)};this.e=function(a){d.na=a;e(!1,a)};this.u=function(a){b(2,a)}}function I(a){return a instanceof A||a instanceof y}function v(a,b,d,c){I(a)?a.A(b,d, 5 | c):b(a)}function B(a,b,d){var c;return function(){0<=--a&&b&&(c=b.apply(k,arguments));0==a&&d&&d(c);return c}}function z(){var a,b;a=[].slice.call(arguments);m(a[0],"Object")&&(b=a.shift(),b=J(b));return new y(a[0],a[1],a[2],b)}function J(a,b,d){var c,e,f;if(a&&(h.O(a),n=h.a(a),"preloads"in a&&(c=new y(a.preloads,k,d,C,!0),h.K(function(){C=c})),f=(f=a.main)&&String(f).split(Z)))return e=new A,e.A(b,d),a=f[1]?function(){new y([f[1]],e.h,e.e)}:e.e,new y([f[0]],e.h,a),e}function y(a,b,d,c,e){var f;f= 6 | h.j(n,k,[].concat(a),e);this.then=this.A=a=function(a,b){v(f,function(b){a&&a.apply(k,b)},function(a){if(b)b(a);else throw a;});return this};this.next=function(a,b,c){return new y(a,b,c,f)};this.config=J;(b||d)&&a(b,d);h.K(function(){v(e||C,function(){v(c,function(){h.q(f)},d)})})}function T(a){var b,d;b=a.id;b==k&&(D!==k?D={G:"Multiple anonymous defines encountered"}:(b=h.$())||(D=a));if(b!=k){d=l[b];b in l||(d=h.i(b,n),d=h.C(d.a,b),l[b]=d);if(!I(d))throw Error("duplicate define: "+b);d.ca=!1;h.D(d, 7 | a)}}function O(){var a=h.X(arguments);T(a)}var n,w,E,x=p.document,P=x&&(x.head||x.getElementsByTagName("head")[0]),$=P&&P.getElementsByTagName("base")[0]||null,U={},V={},K={},aa="addEventListener"in p?{}:{loaded:1,complete:1},N={},X=N.toString,k,l={},L={},C=!1,D,W=/^\/|^[^:]+:\/\//,Y=/(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,ba=/\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g,ca=/require\s*\(\s*(["'])(.*?[^\\])\1\s*\)|[^\\]?(["'])/g,Z=/\s*,\s*/,Q,h;h={m:function(a,b,d){var c;a=S(a,b);if("."==a.charAt(0))return a;c=H(a); 8 | a=(b=c.d)||c.g;a in d.c&&(a=d.c[a].l||a);b&&(0>b.indexOf("/")&&!(b in d.c)&&(a=G(d.M)+"/"+b),a=a+"!"+c.g);return a},j:function(a,b,d,c){function e(b,c){var d,f;d=h.m(b,g.id,a);if(!c)return d;f=H(d);if(!f.d)return d;d=l[f.d];f.g="normalize"in d?d.normalize(f.g,e,g.a)||"":e(f.g);return f.d+"!"+f.g}function f(b,d,f){var r;r=d&&function(a){d.apply(k,a)};if(m(b,"String")){if(r)throw Error("require(id, callback) not allowed");f=e(b,!0);b=l[f];if(!(f in l))throw Error("Module not resolved: "+f);return(f= 9 | I(b)&&b.b)||b}v(h.q(h.j(a,g.id,b,c)),r,f)}var g;g=new A;g.id=b||"";g.aa=c;g.F=d;g.a=a;g.v=f;f.toUrl=function(b){return h.i(e(b,!0),a).url};g.m=e;return g},C:function(a,b,d){var c,e,f;c=h.j(a,b,k,d);e=c.h;f=B(1,function(a){c.p=a;try{return h.R(c)}catch(b){c.e(b)}});c.h=function(a){v(d||C,function(){e(l[c.id]=L[c.url]=f(a))})};c.H=function(a){v(d||C,function(){c.b&&(f(a),c.u(V))})};return c},Q:function(a,b,d,c){return h.j(a,d,k,c)},Z:function(a){return a.v},I:function(a){return a.b||(a.b={})},Y:function(a){var b= 10 | a.r;b||(b=a.r={id:a.id,uri:h.J(a),exports:h.I(a),config:function(){return a.a}},b.b=b.exports);return b},J:function(a){return a.url||(a.url=h.B(a.v.toUrl(a.id),a.a))},O:function(a){var b,d,c,e,f;b="curl";d="define";c=e=p;if(a&&(f=a.overwriteApi||a.la,b=a.apiName||a.ea||b,c=a.apiContext||a.da||c,d=a.defineName||a.ga||d,e=a.defineContext||a.fa||e,w&&m(w,"Function")&&(p.curl=w),w=null,E&&m(E,"Function")&&(p.define=E),E=null,!f)){if(c[b]&&c[b]!=z)throw Error(b+" already exists");if(e[d]&&e[d]!=O)throw Error(d+ 11 | " already exists");}c[b]=z;e[d]=O},a:function(a){function b(a,b){var d,c,g,q,s;for(s in a){g=a[s];m(g,"String")&&(g={path:a[s]});g.name=g.name||s;q=e;c=H(G(g.name));d=c.g;if(c=c.d)q=f[c],q||(q=f[c]=u(e),q.c=u(e.c),q.f=[]),delete a[s];c=g;var l=b,F=void 0;c.path=G(c.path||c.location||"");l&&(F=c.main||"./main","."==F.charAt(0)||(F="./"+F),c.l=S(F,c.name+"/"));c.a=c.config;c.a&&(c.a=u(e,c.a));c.P=d.split("/").length;d?(q.c[d]=c,q.f.push(d)):q.n=h.N(g.path,e)}}function d(a){var b=a.c;a.L=RegExp("^("+ 12 | a.f.sort(function(a,c){return b[c].P-b[a].P}).join("|").replace(/\/|\./g,"\\$&")+")(?=\\/|$)");delete a.f}var c,e,f,g;"baseUrl"in a&&(a.n=a.baseUrl);"main"in a&&(a.l=a.main);"preloads"in a&&(a.ma=a.preloads);"pluginPath"in a&&(a.M=a.pluginPath);if("dontAddFileExt"in a||a.k)a.k=RegExp(a.dontAddFileExt||a.k);c=n;e=u(c,a);e.c=u(c.c);f=a.plugins||{};e.plugins=u(c.plugins);e.t=u(c.t,a.t);e.s=u(c.s,a.s);e.f=[];b(a.packages,!0);b(a.paths,!1);for(g in f)a=h.m(g+"!","",e),e.plugins[a.substr(0,a.length-1)]= 13 | f[g];f=e.plugins;for(g in f)if(f[g]=u(e,f[g]),a=f[g].f)f[g].f=a.concat(e.f),d(f[g]);for(g in c.c)e.c.hasOwnProperty(g)||e.f.push(g);d(e);return e},i:function(a,b){var d,c,e,f;d=b.c;e=W.test(a)?a:a.replace(b.L,function(a){c=d[a]||{};f=c.a;return c.path||""});return{a:f||n,url:h.N(e,b)}},N:function(a,b){var d=b.n;return d&&!W.test(a)?G(d)+"/"+a:a},B:function(a,b){return a+((b||n).k.test(a)?"":".js")},ba:function(a,b,d){var c=x.createElement("script");c.onload=c.onreadystatechange=function(d){d=d||p.event; 14 | if("load"==d.type||aa[c.readyState])delete K[a.id],c.onload=c.onreadystatechange=c.onerror="",b()};c.onerror=function(){d(Error("Syntax or http error: "+a.url))};c.type=a.ia||"text/javascript";c.charset="utf-8";c.async=!a.ka;c.src=a.url;K[a.id]=c;P.insertBefore(c,$);return c},S:function(a){var b=[],d;("string"==typeof a?a:a.toSource?a.toSource():a.toString()).replace(ba,"").replace(ca,function(a,e,f,g){g?d=d==g?k:d:d||b.push(f);return""});return b},X:function(a){var b,d,c,e,f,g;f=a.length;c=a[f-1]; 15 | e=m(c,"Function")?c.length:-1;2==f?m(a[0],"Array")?d=a[0]:b=a[0]:3==f&&(b=a[0],d=a[1]);!d&&0 2 | 3 | 8 | Example 9 | 10 | 11 | 51 | 52 | 53 |
54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /site/proj-small.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Projected Shapefiles in Leaflet! 9 | 10 | 13 | 14 | 15 |
16 |
17 | Fork me on GitHub 18 |
19 |
20 | 21 | 51 | 52 | -------------------------------------------------------------------------------- /site/proj.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Projected Shapefiles in Leaflet! 9 | 10 | 13 | 14 | 15 |
16 |
17 | Fork me on GitHub 18 |
19 |
20 | 21 | 55 | 56 | -------------------------------------------------------------------------------- /site/require.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | var requirejs,require,define; 7 | (function(Z){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function y(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(H(m)){if(this.events.error&&this.map.isDefine||j.onError!==aa)try{e=i.execCb(c,m,b,e)}catch(d){a=d}else e=i.execCb(c,m,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!== 19 | this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",v(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(r[c]=e,j.onResourceLoad))j.onResourceLoad(i,this.map,this.depMaps);x(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete= 20 | !0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=n(a.prefix);this.depMaps.push(d);t(d,"defined",u(this,function(e){var m,d;d=this.map.name;var g=this.map.parentMap?this.map.parentMap.name:null,h=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,g,!0)})||""),e=n(a.prefix+"!"+d,this.map.parentMap),t(e,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})), 21 | d=l(p,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else m=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];F(p,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&x(a.map.id)});v(a)}),m.fromText=u(this,function(e,c){var d=a.name,g=n(d),B=O;c&&(e=c);B&&(O=!1);q(g);s(k.config,b)&&(k.config[d]=k.config[b]);try{j.exec(e)}catch(ca){return v(A("fromtexteval", 22 | "fromText eval for "+b+" failed: "+ca,ca,[b]))}B&&(O=!0);this.depMaps.push(g);i.completeLoad(d);h([d],m)}),e.load(a.name,h,m,k)}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){T[this.map.id]=this;this.enabling=this.enabled=!0;y(this.depMaps,u(this,function(a,b){var c,e;if("string"===typeof a){a=n(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=l(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;t(a,"defined",u(this,function(a){this.defineDep(b, 23 | a);this.check()}));this.errback&&t(a,"error",u(this,this.errback))}c=a.id;e=p[c];!s(N,c)&&(e&&!e.enabled)&&i.enable(a,this)}));F(this.pluginMaps,u(this,function(a){var b=l(p,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:k,contextName:b,registry:p,defined:r,urlFetched:S,defQueue:G,Module:X,makeModuleMap:n, 24 | nextTick:j.nextTick,onError:v,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};F(a,function(a,b){e[b]?"map"===b?(k.map||(k.map={}),Q(k[b],a,!0,!0)):Q(k[b],a,!0):k[b]=a});a.shim&&(F(a.shim,function(a,b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);c[b]=a}),k.shim=c);a.packages&&(y(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name, 25 | location:a.location||a.name,main:(a.main||"main").replace(ja,"").replace(ea,"")}}),k.pkgs=b);F(p,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=n(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Z,arguments));return b||a.exports&&ba(a.exports)}},makeRequire:function(a,f){function d(e,c,h){var g,k;f.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return v(A("requireargs", 26 | "Invalid require call"),h);if(a&&s(N,e))return N[e](p[a.id]);if(j.get)return j.get(i,e,a,d);g=n(e,a,!1,!0);g=g.id;return!s(r,g)?v(A("notloaded",'Module name "'+g+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[g]}K();i.nextTick(function(){K();k=q(n(null,a));k.skipMap=f.skipMap;k.init(e,c,h,{enabled:!0});C()});return d}f=f||{};Q(d,{isBrowser:z,toUrl:function(b){var d,f=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==f&&(!("."===g||".."===g)||1h.attachEvent.toString().indexOf("[native code"))&&!W?(O=!0,h.attachEvent("onreadystatechange",b.onScriptLoad)):(h.addEventListener("load",b.onScriptLoad,!1),h.addEventListener("error", 34 | b.onScriptError,!1)),h.src=d,K=h,C?x.insertBefore(h,C):x.appendChild(h),K=null,h;if(da)try{importScripts(d),b.completeLoad(c)}catch(l){b.onError(A("importscripts","importScripts failed for "+c+" at "+d,l,[c]))}};z&&M(document.getElementsByTagName("script"),function(b){x||(x=b.parentNode);if(J=b.getAttribute("data-main"))return q=J,t.baseUrl||(D=q.split("/"),q=D.pop(),fa=D.length?D.join("/")+"/":"./",t.baseUrl=fa),q=q.replace(ea,""),j.jsExtRegExp.test(q)&&(q=J),t.deps=t.deps?t.deps.concat(q):[q],!0}); 35 | define=function(b,c,d){var h,j;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=null);!c&&H(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(h=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),h=P;h&&(b||(b=h.getAttribute("data-requiremodule")),j=E[h.getAttribute("data-requirecontext")])}(j?j.defQueue: 36 | R).push([b,c,d])};define.amd={jQuery:!0};j.exec=function(b){return eval(b)};j(t)}})(this); 37 | -------------------------------------------------------------------------------- /test/data/LGA_2013_AUST.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /test/data/LGA_2013_AUST.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/LGA_2013_AUST.dbf -------------------------------------------------------------------------------- /test/data/LGA_2013_AUST.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433],AUTHORITY["EPSG",4283]] -------------------------------------------------------------------------------- /test/data/LGA_2013_AUST.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/LGA_2013_AUST.shp -------------------------------------------------------------------------------- /test/data/LGA_2013_AUST.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/LGA_2013_AUST.shx -------------------------------------------------------------------------------- /test/data/SHP_Exclude.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/SHP_Exclude.zip -------------------------------------------------------------------------------- /test/data/T8Th4_6n.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/T8Th4_6n.zip -------------------------------------------------------------------------------- /test/data/bad.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/bad.dbf -------------------------------------------------------------------------------- /test/data/bad.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/bad.shp -------------------------------------------------------------------------------- /test/data/badlen.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/badlen.zip -------------------------------------------------------------------------------- /test/data/badzip.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/badzip.zip -------------------------------------------------------------------------------- /test/data/codepage.cpg: -------------------------------------------------------------------------------- 1 | ANSI 1250 2 | -------------------------------------------------------------------------------- /test/data/codepage.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/codepage.dbf -------------------------------------------------------------------------------- /test/data/codepage.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /test/data/codepage.qpj: -------------------------------------------------------------------------------- 1 | GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] 2 | -------------------------------------------------------------------------------- /test/data/codepage.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/codepage.shp -------------------------------------------------------------------------------- /test/data/codepage.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/codepage.shx -------------------------------------------------------------------------------- /test/data/codepage.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/codepage.zip -------------------------------------------------------------------------------- /test/data/counties.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.dbf -------------------------------------------------------------------------------- /test/data/counties.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.sbn -------------------------------------------------------------------------------- /test/data/counties.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.sbx -------------------------------------------------------------------------------- /test/data/counties.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.shp -------------------------------------------------------------------------------- /test/data/counties.shp.xml: -------------------------------------------------------------------------------- 1 | 2013091008255500FALSECreateFeatureclass "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries" Towns # GISPLANNER_Layer SAME_AS_TEMPLATE SAME_AS_TEMPLATE "PROJCS['NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Lambert_Conformal_Conic'],PARAMETER['False_Easting',200000.0],PARAMETER['False_Northing',750000.0],PARAMETER['Central_Meridian',-71.5],PARAMETER['Standard_Parallel_1',41.71666666666667],PARAMETER['Standard_Parallel_2',42.68333333333333],PARAMETER['Latitude_Of_Origin',41.0],UNIT['Meter',1.0]];-361489.141077092 327975.618391579 1953.12499818101;0 1;0 1" # 0 0 0 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisVector.GISADMIN.Towns"Append GISPLANNER_Layer "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisVector.GISADMIN.Towns" TEST "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisVector.GISADMIN.Towns"FeatureClassToFeatureClass "Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Mark\gisdevelopment.GISPLANNER.boundary" "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries" Towns # "TOWN TOWN VISIBLE;TOWN_ID TOWN_ID VISIBLE;TOWNS_ID TOWNS_ID VISIBLE;COASTAL_POLY COASTAL_POLY VISIBLE;SQUARE_MILES SQUARE_MILES VISIBLE;SHAPE.area SHAPE.area VISIBLE;SHAPE.len SHAPE.len VISIBLE" SAME_AS_TEMPLATE SAME_AS_TEMPLATE # 0 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisVector.GISADMIN.Towns"CopyFeatures Counties_poly_from_361_new S:\HQ\Planning\DataResources\Workspace\Mark\Assets.mdb\County_poly # 1000 0 0AddField S:\HQ\Planning\DataResources\Workspace\Mark\Assets.mdb\County_poly F_AREA DOUBLE # # # # NULLABLE NON_REQUIRED # S:\HQ\Planning\DataResources\Workspace\Mark\Assets.mdb\County_polyCalculateAreas Counties_poly_from_361_new S:\HQ\Planning\DataResources\Workspace\Mark\Assets.mdb\County_polyFeatureClassToFeatureClass "Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Mark\gisdevelopment.GISPLANNER.Counties_poly" "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries" Counties2 # "COUNTY COUNTY true true false 20 Text 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Mark\gisdevelopment.GISPLANNER.Counties_poly,COUNTY,-1,-1;area area false false true 0 Double 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Mark\gisdevelopment.GISPLANNER.Counties_poly,Shape.area,-1,-1;len len false false true 0 Double 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Mark\gisdevelopment.GISPLANNER.Counties_poly,Shape.len,-1,-1" # "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties2"AddSpatialIndex "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties" 0 0 0 "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties"FeatureClassToFeatureClass "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties" "Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin" Counties2 # "COUNTY COUNTY true true false 20 Text 0 0 ,First,#,Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties,COUNTY,-1,-1;area area false true true 8 Double 8 38 ,First,#,Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties,gisvector.GISADMIN.Counties.area,-1,-1;len len false true true 8 Double 8 38 ,First,#,Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties,gisvector.GISADMIN.Counties.len,-1,-1;area_1 area_1 false false true 0 Double 0 0 ,First,#,Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties,Shape.area,-1,-1;len_1 len_1 false false true 0 Double 0 0 ,First,#,Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties,Shape.len,-1,-1" # "Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2"FeatureClassToFeatureClass "Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2" "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries" Counties # "COUNTY COUNTY true true false 20 Text 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,COUNTY,-1,-1;area area false true true 8 Double 8 38 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,gisdevelopment.GISPLANNER.Counties2.area,-1,-1;len len false true true 8 Double 8 38 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,gisdevelopment.GISPLANNER.Counties2.len,-1,-1;area_1 area_1 false true true 8 Double 8 38 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,area_1,-1,-1;len_1 len_1 false true true 8 Double 8 38 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,len_1,-1,-1;area_12 area_12 false false true 0 Double 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,Shape.area,-1,-1;len_12 len_12 false false true 0 Double 0 0 ,First,#,Database Connections\Planning Development.sde\gisDevelopment.GISPLANNER.Kevin\gisdevelopment.GISPLANNER.Counties2,Shape.len,-1,-1" # "Database Connections\Admin gisVector.sde\gisVector.GISADMIN.Boundaries\gisvector.GISADMIN.Counties"Project gisvector.GISADMIN.Counties "\\mhd-fsp-bos-v01\urd$\metcalfc\My Documents\ArcGIS\Default.gdb\Counties_Project1" GEOGCS['GCS_WGS_1984',DATUM['D_WGS_1984',SPHEROID['WGS_1984',6378137.0,298.257223563]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]] NAD_1983_To_WGS_1984_1 PROJCS['NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Lambert_Conformal_Conic'],PARAMETER['False_Easting',200000.0],PARAMETER['False_Northing',750000.0],PARAMETER['Central_Meridian',-71.5],PARAMETER['Standard_Parallel_1',41.71666666666667],PARAMETER['Standard_Parallel_2',42.68333333333333],PARAMETER['Latitude_Of_Origin',41.0],UNIT['Meter',1.0]]SimplifyPolygon Counties_Project1 \\mhd-fsp-bos-v01\urd$\metcalfc\Desktop\shapefilejs\counties.shp POINT_REMOVE "20 Meters" "0 SquareMeters" NO_CHECK NO_KEEPfile://\\mhd-fsp-bos-v01\urd$\metcalfc\Desktop\shapefilejs\counties.shpLocal Area Networkcounties0020.000GeographicGCS_WGS_1984Angular Unit: Degree (0.017453)<GeographicCoordinateSystem xsi:type='typens:GeographicCoordinateSystem' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.0'><WKT>GEOGCS[&quot;GCS_WGS_1984&quot;,DATUM[&quot;D_WGS_1984&quot;,SPHEROID[&quot;WGS_1984&quot;,6378137.0,298.257223563]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433],AUTHORITY[&quot;EPSG&quot;,4326]]</WKT><XOrigin>-399.99999999999989</XOrigin><YOrigin>-399.99999999999989</YOrigin><XYScale>11258999068426.24</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>8.9831528411952133e-009</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision><LeftLongitude>-180</LeftLongitude><WKID>4326</WKID></GeographicCoordinateSystem>201309100849230020130910084923001.0Server=mhd-gis-wh; Service=5151; Database=gisvector; User=gisadmin; Version=sde.DEFAULTREQUIRED: The name of an organization or individual that developed the data set.REQUIRED: The date when the data set is published or otherwise made available for release.gisvector.GISADMIN.Countiesgisvector.GISADMIN.Countiesvector digital dataMicrosoft Windows XP Version 5.1 (Build 2600) Service Pack 2; ESRI ArcCatalog 9.2.2.1350enREQUIRED: A brief narrative summary of the data set.REQUIRED: A summary of the intentions with which the data set was developed.REQUIRED: The basis on which the time period of content information is determined.REQUIRED: The year (and optionally month, or month and day) for which the data set corresponds to the ground.REQUIRED: The state of the data set.REQUIRED: The frequency with which changes and additions are made to the data set after the initial data set is completed.REQUIRED: Western-most coordinate of the limit of coverage expressed in longitude.REQUIRED: Eastern-most coordinate of the limit of coverage expressed in longitude.REQUIRED: Northern-most coordinate of the limit of coverage expressed in latitude.REQUIRED: Southern-most coordinate of the limit of coverage expressed in latitude.REQUIRED: Reference to a formally registered thesaurus or a similar authoritative source of theme keywords.REQUIRED: Common-use word or phrase used to describe the subject of the data set.REQUIRED: Restrictions and legal prerequisites for accessing the data set.REQUIRED: Restrictions and legal prerequisites for using the data set after access is granted.SDE Feature ClassServer=mhd-gis-wh; Service=5151; Database=gisvector; User=gisadmin; Version=sde.DEFAULTArcSDE Connection002SDE Feature ClassShapefile0.000Dataset copied.Server=mhd-gis-wh; Service=esri_sde; Database=gisvector; User=gisviewer; Version=sde.DEFAULT20061207Dataset copied.20061208Dataset copied.\\MHD-Shared\SharedData$\HQ\Planning\DataResources\Workspace\Mark\Assets.mdb20061211Microsoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; ESRI ArcGIS 10.0.5.4400countiesenFGDC Content Standards for Digital Geospatial MetadataFGDC-STD-001-1998local timeREQUIRED: The person responsible for the metadata information.REQUIRED: The organization responsible for the metadata information.REQUIRED: The mailing and/or physical address for the organization or individual.REQUIRED: The city of the address.REQUIRED: The state or province of the address.REQUIRED: The ZIP or other postal code of the address.REQUIRED: The telephone number by which individuals can speak to the organization or individual.20070518ISO 19115 Geographic Information - MetadataDIS_ESRI1.0datasetDownloadable DataVectorSimpleFALSE0FALSEFALSEGCS_North_American_1983NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001North American Datum of 1983Geodetic Reference System 806378137.000000298.257222Explicit elevation coordinate included with horizontal coordinates1.000000NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001EPSG7.4.10countiesFeature Class0len_12FIDOID400Internal feature number.ESRISequential unique whole numbers that are automatically generated.Shapearea_1Double1900Feature geometry.ESRICoordinates defining the features.area_1len_1Double1900areaareaDouble1900lenlenDouble1900len_1COUNTYString2000COUNTYShapeGeometry000Feature geometry.ESRICoordinates defining the features.SHAPEarea_12Double1900Feature geometry.ESRICoordinates defining the features.area_12len_12Double1900Shape_LengShape_LengDouble1900Shape_AreaShape_AreaDouble1900Area of feature in internal units squared.ESRIPositive real numbers that are automatically generated.20130910 2 | -------------------------------------------------------------------------------- /test/data/counties.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.shx -------------------------------------------------------------------------------- /test/data/counties.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/counties.zip -------------------------------------------------------------------------------- /test/data/export_multipointz.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_multipointz.dbf -------------------------------------------------------------------------------- /test/data/export_multipointz.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] -------------------------------------------------------------------------------- /test/data/export_multipointz.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_multipointz.shp -------------------------------------------------------------------------------- /test/data/export_multipointz.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_multipointz.shx -------------------------------------------------------------------------------- /test/data/export_polylinez.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_polylinez.dbf -------------------------------------------------------------------------------- /test/data/export_polylinez.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] -------------------------------------------------------------------------------- /test/data/export_polylinez.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_polylinez.shp -------------------------------------------------------------------------------- /test/data/export_polylinez.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/export_polylinez.shx -------------------------------------------------------------------------------- /test/data/htmlcpg.cpg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Projected Shapefiles in Leaflet! 9 | 10 | 13 | 14 | 15 |
16 |
17 | Fork me on GitHub 18 |
19 |
20 | 21 | 55 | 56 | -------------------------------------------------------------------------------- /test/data/htmlcpg.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/htmlcpg.dbf -------------------------------------------------------------------------------- /test/data/htmlcpg.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /test/data/htmlcpg.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/htmlcpg.shp -------------------------------------------------------------------------------- /test/data/htmlprj.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /test/data/htmlprj.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/htmlprj.dbf -------------------------------------------------------------------------------- /test/data/htmlprj.prj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Projected Shapefiles in Leaflet! 9 | 10 | 13 | 14 | 15 |
16 |
17 | Fork me on GitHub 18 |
19 |
20 | 21 | 55 | 56 | -------------------------------------------------------------------------------- /test/data/htmlprj.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/htmlprj.shp -------------------------------------------------------------------------------- /test/data/ipra_dresden_polygon.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/ipra_dresden_polygon.dbf -------------------------------------------------------------------------------- /test/data/ipra_dresden_polygon.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] -------------------------------------------------------------------------------- /test/data/ipra_dresden_polygon.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/ipra_dresden_polygon.shp -------------------------------------------------------------------------------- /test/data/ipra_dresden_polygon.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/ipra_dresden_polygon.shx -------------------------------------------------------------------------------- /test/data/mixedcase.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/mixedcase.zip -------------------------------------------------------------------------------- /test/data/no-dbf.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/no-dbf.sbx -------------------------------------------------------------------------------- /test/data/no-dbf.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/no-dbf.shp -------------------------------------------------------------------------------- /test/data/no-dbf.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/no-dbf.zip -------------------------------------------------------------------------------- /test/data/noshp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/noshp.zip -------------------------------------------------------------------------------- /test/data/qgis.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/qgis.zip -------------------------------------------------------------------------------- /test/data/senate.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.dbf -------------------------------------------------------------------------------- /test/data/senate.prj: -------------------------------------------------------------------------------- 1 | PROJCS["NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",200000.0],PARAMETER["False_Northing",750000.0],PARAMETER["Central_Meridian",-71.5],PARAMETER["Standard_Parallel_1",41.71666666666667],PARAMETER["Standard_Parallel_2",42.68333333333333],PARAMETER["Latitude_Of_Origin",41.0],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /test/data/senate.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.sbn -------------------------------------------------------------------------------- /test/data/senate.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.sbx -------------------------------------------------------------------------------- /test/data/senate.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.shp -------------------------------------------------------------------------------- /test/data/senate.shp.xml: -------------------------------------------------------------------------------- 1 | 20120312140039001.0FGDC CSDGM MetadataFALSE2013091008390500senate00233861.260000330846.090100777514.310000959747.4400001file://\\mhd-fsp-bos-v01\urd$\metcalfc\Desktop\shapefilejs\senate.shpLocal Area Network0.000ProjectedGCS_North_American_1983NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001<ProjectedCoordinateSystem xsi:type='typens:ProjectedCoordinateSystem' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.0'><WKT>PROJCS[&quot;NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001&quot;,GEOGCS[&quot;GCS_North_American_1983&quot;,DATUM[&quot;D_North_American_1983&quot;,SPHEROID[&quot;GRS_1980&quot;,6378137.0,298.257222101]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433]],PROJECTION[&quot;Lambert_Conformal_Conic&quot;],PARAMETER[&quot;False_Easting&quot;,200000.0],PARAMETER[&quot;False_Northing&quot;,750000.0],PARAMETER[&quot;Central_Meridian&quot;,-71.5],PARAMETER[&quot;Standard_Parallel_1&quot;,41.71666666666667],PARAMETER[&quot;Standard_Parallel_2&quot;,42.68333333333333],PARAMETER[&quot;Latitude_Of_Origin&quot;,41.0],UNIT[&quot;Meter&quot;,1.0],AUTHORITY[&quot;EPSG&quot;,26986]]</WKT><XOrigin>-36530900</XOrigin><YOrigin>-28803200</YOrigin><XYScale>122610652.81195112</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>0.001</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision><WKID>26986</WKID></ProjectedCoordinateSystem>Linear Unit: Meter (1.000000)CopyFeatures "Database Connections\GISDATA_VT_DC.sde\GISDATA.SENATE2012_POLY" E:\MassGIS\mtrust\MassGIS_DataViewer_SHP\gisdata\men1\Political_Boundaries\SENATE2012_POLY.shp # 0 0 0SimplifyPolygon SENATE2012_POLY \\mhd-fsp-bos-v01\urd$\metcalfc\Desktop\shapefilejs\senate.shp POINT_REMOVE "20 Meters" "0 SquareMeters" NO_CHECK NO_KEEP2013091008390500FGDC/9j/4AAQSkZJRgABAQEAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a 2 | HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy 3 | MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCACFAMgDASIA 4 | AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA 5 | AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3 6 | ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm 7 | p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA 8 | AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx 9 | BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK 10 | U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3 11 | uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iii 12 | gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKge6jCZjZJDnGA3A+p7VXF7uUyieDavBUOCo 13 | +rf5/Gsp14QdpMaTZfoqG1nFzbrMpBDZwVORwcVNWogooooAKKKKACiiigAooooAinkaNBsxvZgB 14 | kce/6A1F5lx/fi/74P8AjSyndcgdkX9T/wDq/WivMxOJnGpywexcYq2oefP/AM8Y/wDv4f8A4mmv 15 | dTIuTCnUDiQ9zj0p1MlQyRMoOCRwfQ9jWKxlXuPlRJ9pccNbuT/skEfqR/Kj7Uf+feX81/xqszTR 16 | ywh5IiHYrgIQehPHPtViq+u1V2DlQ77V6wygdzwf5Gj7XF/00/79N/hTarJLcTKJYlj8onKhzgsu 17 | OuRnHPbHSqWOqdkHKi2t5CyhlMhBGQfLb/Cl+1w92Kj1ZSo/MiqgdolSBE3yIgJ5wMdOv4UqyyTA 18 | GNCi4zukXH4bev54/Gq+vT7C5Sz9stcZ+0w4/wB8Uv2u2/5+Iv8AvsVTmRo7J04dmJGOgO4/j61L 19 | DPHcRh42BHcZ5B9D6Gn9fdr8ochY+1W//PeL/vsVUu72MhohtKZUFs/eyegAHzdDUVx5zXI2MdsY 20 | DhVA3MfmBwTx6daZaSowaaUvvUNtLgbvLOPTgjI460p42Uo6IFEc8yXcvkojDcvLsMZTPIHfqMfj 21 | n0qW5tklifEaM+3ADLkH0BGRmmWiIssrLHIu75suDkZ6rz788cc1DBMwkEsjuqNuPOSDliFA98Dt 22 | +Gc5ri9CiHwheC40qSHYEa3mddqrhQCdwA9hnH4V0GQc4PTrXMXliY5P7T0y9S3xGcRrgRyNzyf6 23 | 9+PXmrmhpLIkdyoaNCmyZHHLyDgt+YPOfXivYo11USSX/AM2rG3RRRXQIKKKKACiiigAooqK4cpb 24 | uVOGPyqfQngfqaTdldgQRnful/56NuH06D9AKfSKoVQqjAAwBS189OTlJyfU2CiiipArvsa/hGfn 25 | VGbGeg4HT8ev1qxVe3LPJJIoxE+GBIwScAevoO471M7qi5Y8dOmap9gB2VY2ZvugEn6UkKlIUVuo 26 | GKr3EyTRrHG+Q8gRwOoHcH06EVboasgI5IVd0kGBImQremev8qi+0uUVxF8u8Ix3epxxxyM/SrBA 27 | ZSpGQRgiqyoZYXiUjajAKSMkbSOD+X+epF5gTyoZEwGAIIPIz0OahjEV7bRvNHGzFfmBGdpxyPam 28 | Tm7DJINqqjrlEy24E4OeM8CnQOszvc/KI+QjD+JeOSfqOP8A69O2gCeWTeCNn3oImGCOQCR1PfOD 29 | +VRlGkmSB5I3eACQHZjB6DOSc5GenTFQx30m9lVFExUzSZwV2gYwCCec4/MmpNTZPl5Jb7rjy2dQ 30 | hPJOOnTOfb8qs72ERtCsyLudJXMrLkjcpJO4EZPYfyIqDUvP821FpLJHMjBfIjYFJEwcgDt9eMY9 31 | MmsibVhFttkixG4KSjAUK6nPLZxznGcgg46V0GgwwC0hu0eeFmXZLA56vknLAjduO7PpgjjpXZQw 32 | 7lK72JbLdjptvGxunt1FxLtYl/mZcAcZOTWjRRXppW2ICiiigAooooAKKKKACq9wd0scfYZc/wAh 33 | /PP4VYqoDvnlftnaD7D/AOvmubFz5aT89CorUdRRTJpBDBJKRkIpbH0FeKaD6iM2X2RoznnJ6KPx 34 | /wAM0nmyL9+BvcoQw/of0p0AIgXcMMRuYe55P60WAr4ube1QeZCWUKuNh5PA65/X9KkRWmyzyHaH 35 | OEAGODx79s0y4E1yk0MMscZHyksm7qM56j1/So7G5LFYEtfKSNcP84baw7ZGQfzzzyBV2urgStAn 36 | 9pRS7RxG2PY5HP1+Y1aqvDGDcSytzKPkz2C9QB+fP/1hVipYCMSFJUbiBwM4zVITSwsZ/KMkE21v 37 | 3S5ZSeMnuRjb29au7l37Nw3YzjPOKpxi5h3pERMqMEVXO0qOO4HPB/SnEBksbrE9w/mK6scFmztU 38 | 8dAcDAOfwGaeGElsbaBC8e0R+Yu3aOOT17Zomnksz51xLmNuCixnC4B6HqSeB79gKVPMmlZ4mkiQ 39 | AEoygbmzznI9AOnrT6CGagok+UKwKAM8isBtQn5h78A/kKr2trfk7zII0Y/Oso3swPvxzjHX0PA7 40 | vneG9IUY8ySJk8tuMOOQCCOcEHr/AFqV/MitnntQkZwQ6SHaoI4z3Axj8apXSsBhz21zcxTQmKGG 41 | IT+UrttwwHcg5BAxgDjA4pYr+4e7Mlha3E7RSKCrsh3Y4J3HPUOcbcY/HFbU8dutlHKVZDsCKWJD 42 | DdgcjuRnNFvJIkUa28EYjMrqMtgFcseMZx0H8sd63p4mUIvlQnG5ftr5Lid4DHJHNGAWVhxg9wRw 43 | atViXM7XMStaeU08EiySQscOApyQOeCemTwQT2Na8M0dxAk0TbkdQyn2rvw9Z1Y67ohqxJRRRXQI 44 | KKKKACiiigAqv9kwW2zyqCScDb3OfSrFFTOEZq0lcLlbyJh0mTHvHz/OmvazSIyGaPDAg/uz/wDF 45 | VborL6tS/lHzMqLDcIoUmOQgctkrn8OajmknhIBty5YHb5ZJ544PHHX9Kv0VDwdF9B8zM25sXnBZ 46 | 7a3dyu3cTkgd8ZX3NPgtJLaLy4oowu4t80zE5JyeSDV+in9UpbBzMpJDcq0h2Q/M2f8AWH0A/u+1 47 | O/fDgwEn1VgR+uKt0UngqXYOZmZ9md3MklvIZd2QysuVHTAOemP5mpEVoUbbay+pO4MT+uT0q/RS 48 | eCpvuHMyl5o/uS/9+m/wpfNH9yX/AL9N/hVyio+oU+7DnZk2kQjuJXcESSFsfuivyhieT3Pzf55q 49 | QRmS2kRSFcSMRkcA7sjI/KrF2/lOkpViqo2doz6f4VWj3W1sWcL5jvk5P8TNgDPfGQPwrjxFL2c7 50 | IqLuQI8r3Ek6y2wj2gqrkllOBwefl5+tPtpIZLog2/lyDLK5Bw+c5wcc+v41ZjiUAByryA7ySO/q 51 | PSomMd021XeKVCwVgACMcEjOQR+dY3uUVkkS1jR5oTHFFGUkIAwjHBOQOueDkfjU2iyyjzoZ0fzW 52 | YzZ8oooB6LzwCABke/1pxV4ZPOmdGUjY+1MDHYnr/wDWyacIpbZXNtIcfeETAFemMD0GB/npXVhq 53 | 0Kcm5dSZJs0qjuImmgeNJWiZhw69RT1YOispyrDINLXrGZlBLu3t2uJJmjKsd6M29duevPQY5P07 54 | VoQS+chJGHU7WHof88/jTb3d9guNgJbymwAM5ODVKznuBqMsNxGBj5N652ucbhgduM559Kx1hJJb 55 | DNSiiithBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBFdAtayhQSdh4HU8dKz5blZ4SLcOzq6 56 | jBjYYIIODkcVq1n6pYPdxpJDLLHNGQyiNgA2DkbgeoHpXNiKHtbNbopOxTtp7m4v7xUTy4VYASnD 57 | HIUZUc9ufxz71adY4XgCbBJ8wUM2CwPX684JpkX7iCGGI/eJUyMpzu5JJHqTu/GlcRRyCAsRLKjO 58 | JG55Uj+pzjp1ryHvYsS4uSiTJM0EOEHzvJxzn1HsajN7HGZLV5EjdI12FWMjHORnGMnke+aoXdm2 59 | q3kduBHNH5pacupC7V2qQO+eW9Rzz2w7TLBLPX9SxEAihCshYtydxPJ6HBGfXOe9b+wtS9oxX1sb 60 | dldwSxrCn7uRBjyXyGAH15I96t1kSTC4Q+bGI7bIPmORhx2x6Zz/AJNUXt9NtJmmfVJlWZymzz/l 61 | HqvHQcde3qK66eNTVpLXyJcTea8t1Yr5ysw6qh3N+Q5rC1S6ni1fTZN/kxSXKrs5y/8ADzjjnd/4 62 | 6PWtCC6MjMkVtKY1wI2C4DDHUE4GPxrN1WO5fVtMaO3nVmfG4SKQo7kqM9MnkH+lONSrUmrxsgsk 63 | dNRRRXaSFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQBzl9fRw30Np5jBxdfOm3Gd2XX6 64 | jAI4zzipI7eHXnlacExIhQRvFgxuwIYHPUjtj17itO60qxvH3z20TyblO8qC3BBxn046fWmz3iWM 65 | iW8Fq8nyFtsKHCjt2x6988dDXNHDxjPnKvpYksrVdPsVhLqQgJZ9ipn3IGBWaLqR5bmXT4Dd+ZOP 66 | 4tqgBVB5PHbpU1xbS3itJqSItoqk+Qjbt3Hfgc9entUVzcXtiiywQxx2cY5hjjyVUA9h1/h6dOeu 67 | BTrum0ozEr9CG10We/8ALfWFIjRNotllJXOTgnHcDj/9QrbNpAVjUxLiPbt46ben5UiXlvJMsMcq 68 | u7IXAU5BUHBOenWp62hCMVaIgqt5cjal5pUiNItqnPUk5PH4CrNFUAUUUUAFFFFABRRRQAUUUUAF 69 | FFFABRRRQAUUUUAFFFFABRRRQAUUUUAZci6hLqCxusRgUM4bBADZAX68E8ev0Bq35E//AD2j/wC/ 70 | Z/8AiqmjiEW/DO25i3zNnGew9B7U+sZUISd5K47szrTSha373XmKWcMCqx7c7iDknJJ6fqas3Nw9 71 | syuYy0PRigJYHtx6VYorVJJWQio2pWixPL5pMaZ3MqMw4+gqnpl073tyDC8VvLJmIMm35tuSR9eS 72 | ffPfmr5s4gSY90RJydh465PHTn1xSraqJFdpJHK8qGxgHpngD1rN+15tLWHoT0UUVqIKKKKACiii 73 | gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP//Z20130910Microsoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; ESRI ArcGIS 10.0.5.4400State Senate Districts (2012)MassGISOne Ashburton Place, Room 1601BostonMA02108USA617-619-5611Map of the Commonwealth of Massachusetts, Senate Districts, Chapter 152 of the Acts of 2011 74 | Bill: http://www.malegislature.gov/Bills/Detail?billNumber=s02045002-73.533350-69.89847742.88835141.2303411Massachusetts General Court Special Joint Committee on Redistricting and MassGISNoneMassGISOne Ashburton Place, Room 1601BostonMA02108USA617-619-5611Senate 2012 DistrictsSenate 2012 Districts<DIV STYLE="text-align:Left;"><DIV><DIV><P><SPAN>Massachusetts Senate Districts (polygons) as signed into law on November 3, 2011. These districts were based on demographic data from the 2010 U.S. Census and are used for elections in 2012 and beyond until the districts are redrawn.</SPAN></P></DIV></DIV></DIV>Map of the Commonwealth of Massachusetts, Senate Districts, Chapter 152 of the Acts of 2011 75 | Bill: http://www.malegislature.gov/Bills/Detail?billNumber=s02045ShapefileMassGISOne Ashburton Place, Room 1601BostonMA02108USA617-619-5611Download from http://www.mass.gov/itd/senate20120.000datasetEPSG7.4.1VectorSimpleFALSE0FALSEFALSE0senateFeature Class0FIDFIDOID400Internal feature number.ESRISequential unique whole numbers that are automatically generated.SENDISTNUMSENDISTNUMInteger550Numeric Senate district identifierSEN_DISTSEN_DISTString4300Name of Senate DistrictSEN_FIRSTSEN_FIRSTString1300Senator's first nameSEN_LASTSEN_LASTString1500Senator's last nameSEN_PARTYSEN_PARTYString300Senator's political partySENATORSENATORString4000Senator's full name and partyURLURLString15000Senator's Web siteSHAPEShapeGeometry000Feature geometry.ESRICoordinates defining the features.SHAPE_AREASHAPE_AREADouble1900Area of feature in internal units squared.ESRIPositive real numbers that are automatically generated.SHAPE_LENSHAPE_LENDouble1900State Senate Districts (2012)Massachusetts General Court Special Joint Committee on Redistricting and MassGIS20130529Massachusetts Senate Districts (polygons) as signed into law on November 3, 2011. These districts were based on demographic data from the 2010 U.S. Census and are used for elections in 2012 and beyond until the districts are redrawn.Senate 2012 DistrictsEnglishMap of the Commonwealth of Massachusetts, Senate Districts, Chapter 152 of the Acts of 2011 76 | Bill: http://www.malegislature.gov/Bills/Detail?billNumber=s02045NoneNoneMassachusetts General Court Special Joint Committee on Redistricting and MassGISMassGISmailing and physical address
One Ashburton Place, Room 1601
BostonMA02108USA
617-619-5611
20130529publication dateCompleteAs neededNoneState Senate Districts (2012)NoneCommonwealth of MassachusettsSDE Feature Class
20130529http://www.mass.gov/itd/senate2012MassGIS Web DocumentationMassGISmailing and physical address
One Ashburton Place, Room 1601
BostonMA02108USA
617-619-5611
MassGISmailing and physical address
One Ashburton Place, Room 1601
BostonMA02108USA
617-619-5611
Download from http://www.mass.gov/itd/senate2012
GCS_North_American_1983NAD_1983_StatePlane_Massachusetts_Mainland_FIPS_2001North American Datum of 1983Geodetic Reference System 806378137.000000298.257222coordinate pair0.0100000.010000metersData obtained in early 2012 by MassGIS from the Massachusetts General Court Special Joint Committee on Redistricting. MassGIS added its 1:100,000 coastline and standardized attributes, followed by QA/QC procedures. Attribute updates on May 29 2013ArcGIS 10.0NoneNone
77 | -------------------------------------------------------------------------------- /test/data/senate.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.shx -------------------------------------------------------------------------------- /test/data/senate.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/senate.zip -------------------------------------------------------------------------------- /test/data/train_stations.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/train_stations.zip -------------------------------------------------------------------------------- /test/data/utf.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /test/data/utf.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/utf.dbf -------------------------------------------------------------------------------- /test/data/utf.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /test/data/utf.qpj: -------------------------------------------------------------------------------- 1 | GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] 2 | -------------------------------------------------------------------------------- /test/data/utf.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/utf.shp -------------------------------------------------------------------------------- /test/data/utf.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/utf.shx -------------------------------------------------------------------------------- /test/data/utf.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/utf.zip -------------------------------------------------------------------------------- /test/data/zero-len-line.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calvinmetcalf/shapefile-js/fc8cf45df99c6fc8d9454e83ab882f8e42ede115/test/data/zero-len-line.zip -------------------------------------------------------------------------------- /test/fixtures.js: -------------------------------------------------------------------------------- 1 | import server from './server.js' 2 | export async function mochaGlobalSetup() { 3 | return new Promise((yes, no) => { 4 | this.server = server.listen(3000, (err) => { 5 | if (err) { 6 | return no(err); 7 | } 8 | yes() 9 | }); 10 | }); 11 | } 12 | export async function mochaGlobalTeardown() { 13 | return new Promise((yes, no) => { 14 | this.server.close((err) => { 15 | if (err) { 16 | return no(err); 17 | } 18 | yes(); 19 | }); 20 | }); 21 | }; -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Tests 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 |
21 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/server.js: -------------------------------------------------------------------------------- 1 | 2 | import express from 'express'; 3 | import morgan from 'morgan'; 4 | import path from 'path'; 5 | import { rollup } from 'rollup'; 6 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 7 | 8 | const app = express(); 9 | if (process.env.SERVING) { 10 | app.use(morgan('dev')); 11 | } 12 | app.get('/test/bundle-browser.js', (req, res) => { 13 | rollup({ 14 | input: path.join(import.meta.dirname, 'test.js'), 15 | plugins: [ 16 | nodeResolve({ browser: true }) 17 | ], 18 | }) 19 | .then(result => { 20 | return result.generate({ 21 | format: 'iife' 22 | }) 23 | }) 24 | .then(({ output: [{ code }] }) => { 25 | res.type('.js'); 26 | res.send(code); 27 | }).catch(e => { 28 | console.log(e); 29 | res.sendStatus(500) 30 | }) 31 | }) 32 | 33 | app.use('/', express.static(path.join(import.meta.dirname, '..'))); 34 | export default app; 35 | if (process.env.SERVING) { 36 | app.listen(3000, () => { 37 | console.log('go to http://localhost:3000/test/ to test in the browser'); 38 | }); 39 | } -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 2 | import shp from '../lib/index.js'; 3 | import { should as shouldRaw, use } from 'chai'; 4 | 5 | import { chaiAsPromised } from 'chai-promised'; 6 | const should = shouldRaw(); 7 | use(chaiAsPromised); 8 | const get = url => fetch(url).then(resp => resp.arrayBuffer()) 9 | describe('Shp', function () { 10 | describe('park and rides not zipped', function () { 11 | const pandr = shp('http://localhost:3000/files/pandr'); 12 | it('should have the right keys', function () { 13 | return pandr.should.eventually.contain.keys('type', 'features'); 14 | }); 15 | it('should be the right type', function () { 16 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 17 | }); 18 | it('should have the right number of features', function () { 19 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(80); 20 | }); 21 | }); 22 | describe('park and rides not zipped but with suffix', function () { 23 | const pandr = shp('http://localhost:3000/files/pandr.shp'); 24 | it('should have the right keys', function () { 25 | return pandr.should.eventually.contain.keys('type', 'features'); 26 | }); 27 | it('should be the right type', function () { 28 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 29 | }); 30 | it('should have the right number of features', function () { 31 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(80); 32 | }); 33 | }); 34 | describe('park and rides not zipped but loaded individually', async function () { 35 | const pandr = Promise.all([ 36 | get('http://localhost:3000/files/pandr.shp'), 37 | get('http://localhost:3000/files/pandr.dbf'), 38 | get('http://localhost:3000/files/pandr.prj') 39 | ]).then(([shapefile, dbf, prj]) => shp({ 40 | shp: shapefile, dbf, prj 41 | })) 42 | it('should have the right keys', function () { 43 | return pandr.should.eventually.contain.keys('type', 'features'); 44 | }); 45 | it('should be the right type', function () { 46 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 47 | }); 48 | it('should have the right number of features', function () { 49 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(80); 50 | }); 51 | }); 52 | describe('park and rides zipped', function () { 53 | const pandr = shp('http://localhost:3000/files/pandr.zip').catch(e => console.log('ERR', e)); 54 | it('should have the right keys', function () { 55 | return pandr.should.eventually.contain.keys('type', 'features'); 56 | }); 57 | it('should be the right type', function () { 58 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 59 | }); 60 | it('should have the right number of features', function () { 61 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(80); 62 | }); 63 | }); 64 | describe('senate unzipped', function () { 65 | const pandr = shp('http://localhost:3000/test/data/senate'); 66 | it('should have the right keys', function () { 67 | return pandr.should.eventually.contain.keys('type', 'features'); 68 | }); 69 | it('should be the right type', function () { 70 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 71 | }); 72 | it('should have the right number of features', function () { 73 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(40); 74 | }); 75 | }); 76 | describe('mixed case zipped', function () { 77 | const pandr = shp('http://localhost:3000/test/data/mixedcase.zip'); 78 | it('should have the right keys', function () { 79 | return pandr.should.eventually.contain.keys('type', 'features'); 80 | }); 81 | it('should be the right type', function () { 82 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 83 | }); 84 | it('should have the right number of features', function () { 85 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(40); 86 | }); 87 | }); 88 | describe('senate zipped', function () { 89 | const pandr = shp('http://localhost:3000/test/data/senate.zip'); 90 | it('should have the right keys', function () { 91 | return pandr.should.eventually.contain.keys('type', 'features'); 92 | }); 93 | it('should be the right type', function () { 94 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 95 | }); 96 | it('should have the right number of features', function () { 97 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(40); 98 | }); 99 | }); 100 | describe('county unzipped', function () { 101 | const pandr = shp('http://localhost:3000/test/data/counties'); 102 | it('should have the right keys', function () { 103 | return pandr.should.eventually.contain.keys('type', 'features'); 104 | }); 105 | it('should be the right type', function () { 106 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 107 | }); 108 | it('should have the right number of features', function () { 109 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(14); 110 | }); 111 | }); 112 | describe('county zipped', function () { 113 | return shp('http://localhost:3000/test/data/counties.zip').then(thing => { 114 | thing.should.contain.keys('type', 'features'); 115 | thing.should.have.property('type', 'FeatureCollection'); 116 | return thing.features; 117 | }).should.eventually.have.length(14); 118 | }); 119 | describe('trains zipped', function () { 120 | const pandr = shp('http://localhost:3000/test/data/train_stations.zip'); 121 | it('should have the right keys', function () { 122 | return pandr.should.eventually.contain.keys('type', 'features'); 123 | }); 124 | it('should be the right type', function () { 125 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 126 | }); 127 | it('should have the right number of features', function () { 128 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(361); 129 | }); 130 | }); 131 | describe('trains zipped with query params', function () { 132 | const pandr = shp('http://localhost:3000/test/data/train_stations.zip?foo=bar'); 133 | it('should have the right keys', function () { 134 | return pandr.should.eventually.contain.keys('type', 'features'); 135 | }); 136 | it('should be the right type', function () { 137 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 138 | }); 139 | it('should have the right number of features', function () { 140 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(361); 141 | }); 142 | }); 143 | describe('z', function () { 144 | it('should work with multipoint z', function () { 145 | return shp('http://localhost:3000/test/data/export_multipointz').then(function (resp) { 146 | return resp.features[0].geometry.coordinates; 147 | }).should.eventually.deep.equal([ 148 | [ 149 | -123.00000000000001, 150 | 48.00000000000001, 151 | 1200 152 | ], 153 | [ 154 | -122, 155 | 47, 156 | 2500 157 | ], 158 | [ 159 | -121, 160 | 46, 161 | 3600 162 | ] 163 | ]); 164 | }); 165 | it('should work with polyline z', function () { 166 | return shp('http://localhost:3000/test/data/export_polylinez').then(function (resp) { 167 | return resp.features[0].geometry.coordinates; 168 | }).should.eventually.deep.equal([ 169 | [ 170 | [ 171 | -119.99999999999999, 172 | 45, 173 | 800 174 | ], 175 | [ 176 | -119, 177 | 44, 178 | 1100 179 | ], 180 | [ 181 | -118.00000000000001, 182 | 43, 183 | 2300 184 | ] 185 | ], 186 | [ 187 | [ 188 | -115, 189 | 40, 190 | 0 191 | ], 192 | [ 193 | -114.00000000000001, 194 | 39, 195 | 0 196 | ], 197 | [ 198 | -113, 199 | 38, 200 | 0 201 | ] 202 | ] 203 | ]); 204 | }); 205 | }); 206 | describe('empty attributes table', function () { 207 | const pandr = shp('http://localhost:3000/files/empty-shp.zip'); 208 | it('should have the right keys', function () { 209 | return pandr.should.eventually.contain.keys('type', 'features'); 210 | }); 211 | it('should be the right type', function () { 212 | return pandr.should.eventually.have.property('type', 'FeatureCollection'); 213 | }); 214 | it('should have the right number of features', function () { 215 | return pandr.then(function (a) { return a.features; }).should.eventually.have.length(2); 216 | }); 217 | }); 218 | describe('errors', function () { 219 | it('bad file should be rejected', function () { 220 | return shp('http://localhost:3000/test/data/bad').should.be.rejected; 221 | }); 222 | it('imaginary file file should be rejected', function (done) { 223 | shp('http://localhost:3000/test/data/notthere').then(function () { 224 | done(true); 225 | }, function () { 226 | done(); 227 | }); 228 | }); 229 | it('bad zip be rejected', function () { 230 | return shp('http://localhost:3000/test/data/badzip.zip').should.be.rejected; 231 | }); 232 | it('no shp in zip', function () { 233 | return shp('http://localhost:3000/test/data/noshp.zip').should.be.rejected; 234 | }); 235 | }); 236 | describe('encoding', function () { 237 | it('should work for utf.zip', function () { 238 | return shp('http://localhost:3000/test/data/utf.zip').then(function (item) { 239 | item.should.contain.keys('type', 'features'); 240 | return item.features.map(function (feature) { 241 | return feature.properties.field; 242 | }); 243 | }).should.eventually.deep.equal([ 244 | '💩', 245 | 'Hněvošický háj' 246 | ]); 247 | }); 248 | it('should work for utf', function () { 249 | return shp('http://localhost:3000/test/data/utf').then(function (item) { 250 | item.should.contain.keys('type', 'features'); 251 | return item.features.map(function (feature) { 252 | return feature.properties.field; 253 | }); 254 | }).should.eventually.deep.equal([ 255 | '💩', 256 | 'Hněvošický háj' 257 | ]); 258 | }); 259 | it('should work for codepage.zip', function () { 260 | return shp('http://localhost:3000/test/data/codepage.zip').then(function (item) { 261 | item.should.contain.keys('type', 'features'); 262 | return item.features.map(function (feature) { 263 | return feature.properties.field; 264 | }); 265 | }).should.eventually.deep.equal([ 266 | '??', 267 | 'Hněvošický háj' 268 | ]); 269 | }); 270 | it('should work for codepage', function () { 271 | return shp('http://localhost:3000/test/data/codepage').then(function (item) { 272 | item.should.contain.keys('type', 'features'); 273 | return item.features.map(function (feature) { 274 | return feature.properties.field; 275 | }); 276 | }).should.eventually.deep.equal([ 277 | '??', 278 | 'Hněvošický háj' 279 | ]); 280 | }); 281 | it('should work for codepage individually', function () { 282 | return Promise.all([ 283 | get('http://localhost:3000/test/data/codepage.shp'), 284 | get('http://localhost:3000/test/data/codepage.dbf'), 285 | get('http://localhost:3000/test/data/codepage.prj'), 286 | get('http://localhost:3000/test/data/codepage.cpg') 287 | ]).then(([shapefile, dbf, prj, cpg]) => shp({ 288 | shp: shapefile, dbf, prj, cpg 289 | })).then(function (item) { 290 | item.should.contain.keys('type', 'features'); 291 | return item.features.map(function (feature) { 292 | return feature.properties.field; 293 | }); 294 | }).should.eventually.deep.equal([ 295 | '??', 296 | 'Hněvošický háj' 297 | ]); 298 | }); 299 | it('should work for a stupid code page', function () { 300 | return shp('http://localhost:3000/test/data/htmlcpg').then(function (item) { 301 | item.should.contain.keys('type', 'features'); 302 | return item.features.map(function (feature) { 303 | return feature.properties.field; 304 | }); 305 | }).should.eventually.deep.equal([ 306 | '💩', 307 | 'Hněvošický háj' 308 | ]); 309 | }); 310 | it('should work for a stupid prj', function () { 311 | return shp('http://localhost:3000/test/data/htmlprj').then(function (item) { 312 | item.should.contain.keys('type', 'features'); 313 | return item.features.map(function (feature) { 314 | return feature.properties.field; 315 | }); 316 | }).should.eventually.deep.equal([ 317 | '💩', 318 | 'Hněvošický háj' 319 | ]); 320 | }); 321 | it('should work for a stupid prj and query params', function () { 322 | return shp('http://localhost:3000/test/data/htmlprj?blah=baz').then(function (item) { 323 | item.should.contain.keys('type', 'features'); 324 | return item.features.map(function (feature) { 325 | return feature.properties.field; 326 | }); 327 | }).should.eventually.deep.equal([ 328 | '💩', 329 | 'Hněvošický háj' 330 | ]); 331 | }); 332 | }); 333 | describe('misc stuff', function () { 334 | it('should work for a null geom', function () { 335 | return shp('http://localhost:3000/test/data/LGA_2013_AUST').then(function (item) { 336 | item.should.contain.keys('type', 'features'); 337 | item.features[4].geometry.coordinates.length.should.equal(21); 338 | item.features[4].properties.LGA_NAME13.should.equal('Kangaroo Island (DC)'); 339 | return item.features.length; 340 | }).should.eventually.equal(13); 341 | }); 342 | it('should work for with this shapfile', function () { 343 | return shp('http://localhost:3000/test/data/T8Th4_6n.zip').then(function (item) { 344 | item.should.contain.keys('type', 'features'); 345 | return item.features.length; 346 | }).should.eventually.equal(3); 347 | }); 348 | it('should work for with this shapfile with a query param', function () { 349 | return shp('http://localhost:3000/test/data/T8Th4_6n.zip?foo=bar').then(function (item) { 350 | item.should.contain.keys('type', 'features'); 351 | return item.features.length; 352 | }).should.eventually.equal(3); 353 | }); 354 | it('file too long', function () { 355 | return shp('http://localhost:3000/test/data/ipra_dresden_polygon'); 356 | }); 357 | it('should handle missing dbf', function () { 358 | return shp('http://localhost:3000/test/data/no-dbf').then(thing => { 359 | thing.should.contain.keys('type', 'features'); 360 | thing.should.have.property('type', 'FeatureCollection'); 361 | return thing.features; 362 | }).should.eventually.have.length(14); 363 | }); 364 | it('should handle missing dbf in a zip', function () { 365 | return shp('http://localhost:3000/test/data/no-dbf.zip').then(thing => { 366 | thing.should.contain.keys('type', 'features'); 367 | thing.should.have.property('type', 'FeatureCollection'); 368 | return thing.features; 369 | }).should.eventually.have.length(14); 370 | }); 371 | it('should work with a line that has zero points', function () { 372 | return shp('http://localhost:3000/test/data/zero-len-line.zip').then(thing => { 373 | thing.should.contain.keys('type', 'features'); 374 | thing.should.have.property('type', 'FeatureCollection'); 375 | should.equal(thing.features[1].geometry, null); 376 | return thing.features; 377 | }).should.eventually.have.length(3); 378 | }); 379 | it('should handle .mshp files', function () { 380 | return shp('http://localhost:3000/test/data/qgis.zip').then(thing => { 381 | thing.should.contain.keys('type', 'features'); 382 | thing.should.have.property('type', 'FeatureCollection'); 383 | return thing.features; 384 | }).should.eventually.have.length(2); 385 | }); 386 | it('should handle weirdly ordered rings', function () { 387 | return shp('http://localhost:3000/test/data/SHP_Exclude.zip').then(thing => { 388 | thing.should.contain.keys('type', 'features'); 389 | thing.should.have.property('type', 'FeatureCollection'); 390 | return thing.features[0].geometry.coordinates; 391 | }).should.eventually.have.length(2); 392 | }); 393 | it('should handle files that lie about their length', function () { 394 | return shp('http://localhost:3000/test/data/badlen.zip').then(thing => { 395 | thing.should.contain.keys('type', 'features'); 396 | thing.should.have.property('type', 'FeatureCollection'); 397 | return thing.features; 398 | }).should.eventually.have.length(203); 399 | }); 400 | }); 401 | }); 402 | --------------------------------------------------------------------------------