ayende/ravendb — pull request #284 by sibartlett (2013-03-18 12:47:04+00:00)
Title: Spatial Enhancements

## Strongly-typed spatial indexes

I've updated AbstractIndexCreationTask so that spatial indexes are defined like so:

```csharp
public class MySpatialIndex : AbstractIndexCreationTask
{
public MySpatialIndex()
{
Map = docs =>	from doc in docs
select new {
doc.Name,
doc.WKT
};

Spatial(x => x.WKT, x => x.Geography(maxTreeLevel:12,
strategy: SpatialSearchStrategy.GeohashPrefixTree));
}
}
```

## 2D Cartesian planes

I've added support for indexing and querying shapes on a 2D Cartesian plane.

```csharp
public class MySpatialIndex : AbstractIndexCreationTask
{
public MySpatialIndex()
{
...

Spatial(x => x.WKT, x => x.Cartesian(minX:0, maxX:2000, minY:0, maxY:2000, maxTreeLevel:12));
}
}
```

## GeoJSON

I've added full support for indexing [GeoJSON](http://www.geojson.org/geojson-spec.html) objects.

```csharp
using (var session = store.OpenSession())
{
var point = new {
type = "Point",
coordinates = new[] { -10d, 45d }
};

session.Store(new SpatialDoc { Shape = point });
session.SaveChanges();
}
```

## Different storage formats for Points

In addition to WKT and GeoJSON, I've added support for indexing points in different formats (arrays, key-value objects, Geo URI).

```csharp
using (var session = store.OpenSession())
{
session.Store(new SpatialDoc { Point = new [] { -10d, 45d } });
session.Store(new SpatialDoc { Point = new { X = -10d, Y = 45d } });
session.Store(new SpatialDoc { Point = new { Latitude = 45d, Longitude = -10d } });
session.Store(new SpatialDoc { Point = new { lat = 45d, lon = -10d } });
session.Store(new SpatialDoc { Point = new { lat = 45d, lng = -10d } });
session.Store(new SpatialDoc { Point = new { Lat = 45d, Long = -10d } });
session.Store(new SpatialDoc { Point = "geo:45.0,-10.0;u=2.0" }); // Geo URI
session.SaveChanges();
}
```

## Raven Studio - Index editor

Spatial fields can be defined in Raven Studio, similar to how regular fields are defined. The precision of the spatial index is dynamically calculated and displayed as the user changes the field's settings.

![raven_studio_spatial](https://f.cloud.github.com/assets/216687/208455/f7f43ab4-822c-11e2-83cd-ddfee9083caa.png)

## Raven Studio - Spatial queries

I improved spatial query support in Raven Studio, so that spatial queries can be run against both old and new style spatial indexes. There's now a "Field" combobox, which allows the user to select which spatial field to query against.

![spatial-query](https://f.cloud.github.com/assets/216687/270495/617cd28a-8fc9-11e2-9df0-212d612b5a2b.jpg)

I also added support for cartesian queries.

![cartesian-query](https://f.cloud.github.com/assets/216687/270496/665fac14-8fc9-11e2-8a60-52eb7f52ad3a.jpg)

## New query methods

I've added new .Spatial(...) query methods,
* there are strongly-typed versions
* the coordinate ordering of the new ```WithinRadiusOf``` methods is X then Y, now that we support 2D cartesian planes.
* these methods support third-party spatial libraries (see next feature)

The aim is to replace the old methods in the long-term.

```csharp
var results1 = session.Query()
.Spatial(x => x.Shape, x => x.WithinRadiusOf(700, 40, 40))
.ToList();

var results2 = session.Query()
.Spatial(x => x.Shape, x => x.Intersects(shapeWkt))
.ToList();
```

## Third-party spatial library integration

Third party spatial libraries can be integrated, so that geometry classes can be stored in documents and used in queries. An example using NetTopologySuite:

```csharp
using (var session = store.OpenSession())
{
session.Store(new SpatialDoc {
Geometry = new Polygon(new LinearRing(new[]
{
new Coordinate(1850, 1850),
new Coordinate(1950, 1850),
new Coordinate(1950, 1950),
new Coordinate(1850, 1950),
new Coordinate(1850, 1850),
}))
});
session.SaveChanges();
}

using (var session = store.OpenSession())
{
var results = session.Query()
.Spatial(x => x.Geometry, x => x.Intersects(new Point(1900, 1900)))
.ToList();
}
```

The document store justs needs to be configured to use a custom JsonConverter which reads/writes WKT or GeoJSON. I have created [JsonConverters for DotSpatial, Geo, and NetTopologySuite](https://github.com/sibartlett/RavenDB.Client.Spatial).