I Am using API to access spatial data collected using kobotoolbox. the api returns spatial data either as geoshape/geotrace/geopoint, but I need to covert that data to Geojson so that I can display them on my map using leaflet.
here is sample string of geoshape '-6.725577650887138 39.10606026649475 0.0 0.0;-6.72631550943841 39.10506717860699 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.727484560110362 39.10561669617891 0.0 0.0;-6.725577650887138 39.10606026649475 0.0 0.0;'
thanks a lot in advance!
That "geoshape" doesn't look like any well-known vector data format but rather looks like a string of
;-separated 4-element vectors, which in turn are space-separated numbers.Some naïve parsing is in order.
Start by splitting the string into an array of strings with
String.prototype.split():Now
pointsis anArrayofStrings. We can turn each of those strings into anArrayofNumbers by providing a function that splits it by spaces:...and another function that coerces a
Stringcontaining the textual representation of a number into aNumber, like......and now let's put in some
Array.prototype.map()magic and some method chaining magic, to make a function in which the input is a space-separated string and the output is anArrayofNumbers:Sometimes it's nicer to define those auxiliary functions passed to
map()(orreduce()orfilter()or etc) as anonymous lambda-functions, like:You can use arrow function syntax instead if you want:
And since we're using
Numberas a function, we can directly use that as the parameter ofmap():Now that we have that function, let's go back to the beginning, and apply that function to each of the
;-separated substrings:Let's change that to add even more lambda and method chaining and arrow syntax:
Also, since the GeoJSON format expects each coordinate as a 2-component vector instead of a 4-component vector, let's
mapeach vector again to keep only the first two components. This uses array destructuring:See? I defined a lambda-function that takes a single argument, assumes it's an array (of numbers) with length 4, destructures the array, then returns a new array containing the first two elements. It can also work like:
Your sample data ends with a
;, and that causes an empty string, so I'll filter that out as well:I'm gonna assume that you're working in Dar es-Salaam and not in Badajoz, so let's flip latitude and longitude (see https://macwright.com/lonlat/ as well) by swapping
xandyin([x,y])=>[y,x]:Now head over to geojson.org and read RFC 7946 to see how GeoJSON data structures are specified. We already have the coordinates of a LineString geometry, so all it needs is some wrapping:
If your sample dataset is meant to be a polygon with an outer hull and no inner hulls (read OGC SFA to know what "hull" means in this context), then you can wrap the coordinates in an extra inline array and specify
Polygonas the geometry type:Now you can feed it to
L.geoJson, e.g.And finally, I'm gonna compact everything together just for the sake of it:
See a working example here. And please, please, don't copy-paste code blindly. Do read the linked documentation and resources, and understand what's going on.