/* fork me on github: http://github.com/calvinmetcalf/esri2geo */ function toGeoJSON(data,cb){ var outPut = { "type": "FeatureCollection", "features": []}; var fl = data.features.length; var i = 0; while(fl>i){ var ft = data.features[i]; /* as only ESRI based products care if all the features are the same type of geometry, check for geometry type at a feature level*/ var outFT = { "type": "Feature", "properties":ft.attributes }; if(ft.geometry.x){ //check if it's a point outFT.geometry=point(ft.geometry); }else if(ft.geometry.points){ //check if it is a multipoint outFT.geometry=points(ft.geometry); }else if(ft.geometry.paths){ //check if a line (or "ARC" in ESRI terms) outFT.geometry=line(ft.geometry); }else if(ft.geometry.rings){ //check if a poly. outFT.geometry=poly(ft.geometry); } outPut.features.push(outFT); i++; } function point(geometry){ //this one is easy return {"type": "Point","coordinates": [geometry.x,geometry.y]}; } function points(geometry){ //checks if the multipoint only has one point, if so exports as point instead if(geometry.points.length===1){ return {"type": "Point","coordinates": geometry.points[0]}; }else{ return { "type": "MultiPoint","coordinates":geometry.points}; } } function line(geometry){ //checks if their are multiple paths or just one if(geometry.paths.length===1){ return {"type": "LineString","coordinates": geometry.paths[0]}; }else{ return { "type": "MultiLineString","coordinates":geometry.paths}; } } function poly(geometry){ //first we check for some easy cases, like if their is only one ring if(geometry.rings.length===1){ return {"type": "Polygon","coordinates": geometry.rings}; }else{ /*if it isn't that easy then we have to start checking ring direction, basically the ring goes clockwise its part of the polygon, if it goes counterclockwise it is a hole in the polygon, but geojson does it by haveing an array with the first element be the polygons and the next elements being holes in it*/ var ccc= dP(geometry.rings); var d = ccc[0]; var dd = ccc[1]; var r=[]; if(dd.length===0){ /*if their are no holes we don't need to worry about this, but do need to stuck each ring inside its own array*/ var l2 = d.length; var i3 = 0; while(l2>i3){ r.push([d[i3]]); } return { "type": "MultiPolygon","coordinates":r}; }else if(d.length===1){ /*if their is only one clockwise ring then we know all holes are in that poly*/ dd.unshift(d[0]); return {"type": "Polygon","coordinates": dd}; }else{ /*if their are multiple rings and holes we have no way of knowing which belong to which without looking at it specially, so just dump the coordinates and add a hole field, this may cause errors*/ return { "type": "MultiPolygon","coordinates":d, "holes":dd}; } } } function dP(a){ //returns an array of 2 arrays, the first being all the clockwise ones, the second counter clockwise var d = []; var dd =[]; var l = a.length; var ii = 0; while(l>ii){ if(c(a[ii])){ d.push(a[ii]); }else{ dd.push(a[ii]); } ii++; } return [d,dd]; } function c(a){ //return true if clockwise var l = a.length-1; var i = 0; var o=0; while(l>i){ o+=(a[i][0]*a[i+1][1]-a[i+1][0]*a[i][1]); i++; } return o<=0; } if(cb){ cb(outPut) }else{ return outPut; } }