17

Context: I'm a just-hours-old newbie at OpenLayers, please be gentle.

Fundamentally, I have a map with some drawn objects on it. If I understand things correctly, I have a number of OpenLayer.Feature.Vector (layers?) with a number of OpenLayer.Geometry "things" (like LinearRing) on it.

At the moment, I seem to be able to get a nice representation of the geometry, using .toString(). Yes, I suspect I'm doing it wrong -- feel free to point me in the right direction.

This yields a very human readable, and database storable, strings such as:

  • POINT(-104.74560546875 44.2841796875)

  • POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875))

  • LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125)

Is there an inverse way of getting these back into the object format from whence they came?

I'd love to be using JSON, but can't seem to get GeoJSON to accept my OpenLayer.Feature.Vector object (which is what the CLASS_NAME property says it is when I peer inside).

Many thanks.

Walt Stoneburner
  • 2,562
  • 4
  • 24
  • 37

2 Answers2

29

The Openlayers.Geometry objects’ toString method converts them nicely to WKT (Well-Known Text). If you use a GIS layer on top of your database (like PostGIS for PostGres, SQL Spatial for SQL Server, Spatialite for SQLite, etc.), they should offer functions that enable you to process WKT.

But if you want to convert that WKT to a new Openlayers.Geometry object (in the browser), you can use the fromWKT function:

var point = OpenLayers.Geometry.fromWKT('POINT(-104.74560546875 44.2841796875)');
alert(point.toString()); // POINT(-104.74560546875 44.2841796875)

Here, the variable point will now contain a new Openlayers.Geometry object, which has the same properties as the original one you used toString() on.

If you pass an array to the fromWKT function, it will return a GeometryCollection containing all the generated geometries.

var geometryTexts = [
      'POINT(-104.74560546875 44.2841796875)'
    , 'POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875))'
    , 'LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125)'
    ],
    collection = OpenLayers.Geometry.fromWKT(geometryTexts);

After this, collection.toString() should yield the following:

GEOMETRYCOLLECTION(POINT(-104.74560546875 44.2841796875),POLYGON((-96.52783203125 44.6796875,-96.52783203125 45.734375,-92.22119140625 45.734375,-92.22119140625 44.6796875,-96.52783203125 44.6796875)),LINESTRING(-105.71240234375 44.6796875,-106.06396484375 42.658203125,-103.55908203125 42.7021484375,-103.47119140625 45.55859375,-104.65771484375 45.20703125))

Martijn
  • 13,225
  • 3
  • 48
  • 58
17

In my other answer, I went with WKT because you mentioned it. I now see that you seem to prefer GeoJSON.

To convert a vector layer or an Openlayers.Geometry object to a GeoJSON string, you should use the OpenLayers.Format.GeoJSON.write function:

var geoJSON = new OpenLayers.Format.GeoJSON(),
    geoJSONText = geoJSON.write(geometryObject);

Note that you should be able to pass your object to this function, since (according to documentation) it accepts an OpenLayers.Feature.Vector as well as a OpenLayers.Geometry or an array of features.

Conversely, when you’ve got a GeoJSON string, you can convert that back to an object using the OpenLayers.Format.GeoJSON.read function:

var geometry = geoJSON.read(geoJSONText, 'Geometry');

The second parameter lets you indicate which type of object you’d like returned. Read the docs linked to for more information.

Also, take a look at this demo for a more extensive example. (View the source of the page to see how they’re doing it).

Martijn
  • 13,225
  • 3
  • 48
  • 58
  • Excellent follow up! This is brilliant. – Walt Stoneburner Mar 04 '11 at 15:56
  • 1
    @WaltStoneburner: I agree, OpenLayers _is_ brilliant. Just a tad underdocumented. – Martijn Mar 04 '11 at 16:38
  • Note to those that follow, I actually had to do this: var geoJSON = new OpenLayers.Format.GeoJSON().write(geometryObject); – Walt Stoneburner Mar 04 '11 at 19:13
  • Ah yes, GeoJSON is a constructor. I’ve updated the answer to fix this. – Martijn Mar 04 '11 at 20:36
  • Is there a way to actually get the GeoJSON object, instead of a string, without JSON-parsing it again? – relet Nov 04 '14 at 12:28
  • @relet: what do you mean by **GeoJSON object**? GeoJSON is a text format. The [GeoJSON.read](http://dev.openlayers.org/docs/files/OpenLayers/Format/GeoJSON-js.html#OpenLayers.Format.GeoJSON.read) function parses GeoJSON text into one or more [Openlayers.Geometry](http://dev.openlayers.org/docs/files/OpenLayers/Geometry-js.html)-objects. – Martijn Nov 04 '14 at 12:46
  • JSON is a text format. GeoJSON in my perception is more of a data structure definition. What I was thinking of is a javascript object or associative array that follows the GeoJSON standard, i.e. what you would get when using JSON.parse on your string. What I was trying to do is to wrap that object into a more complex data structure, before serializing it to JSON. – relet Nov 04 '14 at 16:45
  • @relet: GeoJSON is a subset of JSON. If JSON is a text format, then so is GeoJSON. If you want to parse GeoJSON into corresponding javascript objects, you're free to do so. But Openlayers uses its own object structures to represent geometries. Those can be _converted_ to many formats besides GeoJSON. – Martijn Nov 04 '14 at 16:58
  • @relet: anyway, what you seem to ask for is one of the [OpenLayers.Format.GeoJSON.extract](http://dev.openlayers.org/docs/files/OpenLayers/Format/GeoJSON-js.html#OpenLayers.Format.GeoJSON.extract) functions of `Openlayers.Format.GeoJSON`. Depending on the type of object you want to convert into a GeoJSON-compliant javascript object, you need to use `extract.feature`, `extract.geometry`, `extract.point` or one of the other functions. – Martijn Nov 04 '14 at 17:06
  • @relet: in the example above, you'd use `new OpenLayers.Format.GeoJSON().extract.geometry(geometryObject);` to get a GeoJSON-compliant object. – Martijn Nov 04 '14 at 17:09
  • "A complete GeoJSON data structure is always an object (in JSON terms)." --http://geojson.org/geojson-spec.html - Introduction – relet Nov 05 '14 at 08:09
  • But thank you for the pointer. I'm confused by the use of "this" in the method. If I call it on my feature.geometry, it points to the extract array. If I call write first, then extract, it correctly points to the OpenLayers.Format.GeoJSON object. – relet Nov 05 '14 at 08:33
  • `var format = new OpenLayers.Format.GeoJSON(); var geojson = format.write(feature); var test = format.extract.geometry(feature.geometry);` works, but only if the write statement is present. – relet Nov 05 '14 at 08:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/64305/discussion-between-martijn-and-relet). – Martijn Nov 05 '14 at 10:46