Skip to content

Commit e1ed2f3

Browse files
authored
Merge pull request #19 from justinhachemeister/master
Make MsSqlSpatial BoundingBox optional
2 parents 9d3365d + 60c775e commit e1ed2f3

File tree

4 files changed

+155
-43
lines changed

4 files changed

+155
-43
lines changed

src/GeoJSON.Net.Contrib.MsSqlSpatial/MsSqlSpatialConvertToGeoJson.cs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ public static partial class MsSqlSpatialConvert
2323
{
2424
#region SqlGeometry to GeoJSON
2525

26-
/// <summary>
27-
/// Converts a native Sql Server geometry (lat/lon) to GeoJSON geometry
28-
/// </summary>
29-
/// <param name="sqlGeometry">SQL Server geometry to convert</param>
30-
/// <returns>GeoJSON geometry</returns>
31-
public static IGeometryObject ToGeoJSONGeometry(this SqlGeometry sqlGeometry)
26+
/// <summary>
27+
/// Converts a native Sql Server geometry (lat/lon) to GeoJSON geometry
28+
/// </summary>
29+
/// <param name="sqlGeometry">SQL Server geometry to convert</param>
30+
/// <param name="withBoundingBox">Value indicating whether the feature's BoundingBox should be set.</param>
31+
/// <returns>GeoJSON geometry</returns>
32+
public static IGeometryObject ToGeoJSONGeometry(this SqlGeometry sqlGeometry, bool withBoundingBox = true)
3233
{
3334
if (sqlGeometry == null || sqlGeometry.IsNull)
3435
{
@@ -43,17 +44,18 @@ public static IGeometryObject ToGeoJSONGeometry(this SqlGeometry sqlGeometry)
4344
}
4445

4546
// Conversion using geometry sink
46-
SqlGeometryGeoJsonSink sink = new SqlGeometryGeoJsonSink();
47+
SqlGeometryGeoJsonSink sink = new SqlGeometryGeoJsonSink(withBoundingBox);
4748
sqlGeometry.Populate(sink);
4849
return sink.ConstructedGeometry;
4950
}
5051

51-
/// <summary>
52-
/// Converts a native Sql Server geometry (lat/lon) to GeoJSON geometry
53-
/// </summary>
54-
/// <param name="sqlGeometry">SQL Server geometry to convert</param>
55-
/// <returns>GeoJSON geometry</returns>
56-
public static T ToGeoJSONObject<T>(this SqlGeometry sqlGeometry) where T : GeoJSONObject
52+
/// <summary>
53+
/// Converts a native Sql Server geometry (lat/lon) to GeoJSON geometry
54+
/// </summary>
55+
/// <param name="sqlGeometry">SQL Server geometry to convert</param>
56+
/// <param name="withBoundingBox">Value indicating whether the feature's BoundingBox should be set.</param>
57+
/// <returns>GeoJSON geometry</returns>
58+
public static T ToGeoJSONObject<T>(this SqlGeometry sqlGeometry, bool withBoundingBox = true) where T : GeoJSONObject
5759
{
5860
if (sqlGeometry == null || sqlGeometry.IsNull)
5961
{
@@ -72,7 +74,8 @@ public static T ToGeoJSONObject<T>(this SqlGeometry sqlGeometry) where T : GeoJ
7274
SqlGeometryGeoJsonSink sink = new SqlGeometryGeoJsonSink();
7375
sqlGeometry.Populate(sink);
7476
geoJSONobj = sink.ConstructedGeometry as T;
75-
geoJSONobj.BoundingBoxes = sink.BoundingBox;
77+
78+
geoJSONobj.BoundingBoxes = withBoundingBox ? sink.BoundingBox : null;
7679

7780
return geoJSONobj;
7881
}
@@ -106,12 +109,13 @@ public static IGeometryObject ToGeoJSONGeometry(this SqlGeography sqlGeography)
106109
return sink.ConstructedGeography;
107110
}
108111

109-
/// <summary>
110-
/// Converts a native Sql Server geography to GeoJSON geometry
111-
/// </summary>
112-
/// <param name="sqlGeography">SQL Server geography to convert</param>
113-
/// <returns>GeoJSON geometry</returns>
114-
public static T ToGeoJSONObject<T>(this SqlGeography sqlGeography) where T : GeoJSONObject
112+
/// <summary>
113+
/// Converts a native Sql Server geography to GeoJSON geometry
114+
/// </summary>
115+
/// <param name="sqlGeography">SQL Server geography to convert</param>
116+
/// <param name="withBoundingBox">Value indicating whether the feature's BoundingBox should be set.</param>
117+
/// <returns>GeoJSON geometry</returns>
118+
public static T ToGeoJSONObject<T>(this SqlGeography sqlGeography, bool withBoundingBox = true) where T : GeoJSONObject
115119
{
116120
if (sqlGeography == null || sqlGeography.IsNull)
117121
{
@@ -130,7 +134,7 @@ public static T ToGeoJSONObject<T>(this SqlGeography sqlGeography) where T : Geo
130134
SqlGeographyGeoJsonSink sink = new SqlGeographyGeoJsonSink();
131135
sqlGeography.Populate(sink);
132136
geoJSONobj = sink.ConstructedGeography as T;
133-
geoJSONobj.BoundingBoxes = sink.BoundingBox;
137+
geoJSONobj.BoundingBoxes = withBoundingBox ? sink.BoundingBox : null;
134138

135139
return geoJSONobj;
136140
}

src/GeoJSON.Net.Contrib.MsSqlSpatial/Sinks/SqlGeographyGeoJSONSink.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ internal class SqlGeographyGeoJsonSink : IGeographySink110
2727
double _lonMax = -180;
2828
double _latMax = -90;
2929

30+
private readonly bool _withBoundingBox;
31+
32+
public SqlGeographyGeoJsonSink(bool withBoundingBox = true)
33+
{
34+
this._withBoundingBox = withBoundingBox;
35+
}
36+
3037
#region Sink implementation
3138

3239
public void BeginGeography(OpenGisGeographyType type)
@@ -136,7 +143,7 @@ public IGeometryObject ConstructedGeography
136143
List<IGeometryObject> subGeometries = _geomCollection.SubItems.Select(subItem => GeometryFromSinkGeometryCollection(subItem)).ToList();
137144
_geometry = new GeometryCollection(subGeometries);
138145

139-
((GeometryCollection)_geometry).BoundingBoxes = this.BoundingBox;
146+
((GeometryCollection)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
140147
break;
141148
default:
142149
throw new NotSupportedException("Geometry type " + _geomCollection.GeometryType.ToString() + " is not supported yet.");
@@ -155,33 +162,33 @@ private IGeometryObject GeometryFromSinkGeometryCollection(SinkGeometryCollectio
155162
{
156163
case OpenGisGeographyType.Point:
157164
_geometry = ConstructGeometryPart(sinkCollection[0]);
158-
((Point)_geometry).BoundingBoxes = this.BoundingBox;
165+
((Point)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
159166
break;
160167
case OpenGisGeographyType.MultiPoint:
161168
_geometry = new MultiPoint(sinkCollection.Skip(1)
162169
.Select(g => (Point)ConstructGeometryPart(g))
163170
.ToList());
164-
((MultiPoint)_geometry).BoundingBoxes = this.BoundingBox;
171+
((MultiPoint)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
165172
break;
166173
case OpenGisGeographyType.LineString:
167174
_geometry = ConstructGeometryPart(sinkCollection[0]);
168-
((LineString)_geometry).BoundingBoxes = this.BoundingBox;
175+
((LineString)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
169176
break;
170177
case OpenGisGeographyType.MultiLineString:
171178
_geometry = new MultiLineString(sinkCollection.Skip(1)
172179
.Select(g => (LineString)ConstructGeometryPart(g))
173180
.ToList());
174-
((MultiLineString)_geometry).BoundingBoxes = this.BoundingBox;
181+
((MultiLineString)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
175182
break;
176183
case OpenGisGeographyType.Polygon:
177184
_geometry = ConstructGeometryPart(sinkCollection.First());
178-
((Polygon)_geometry).BoundingBoxes = this.BoundingBox;
185+
((Polygon)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
179186
break;
180187
case OpenGisGeographyType.MultiPolygon:
181188
_geometry = new MultiPolygon(sinkCollection.Skip(1)
182189
.Select(g => (Polygon)ConstructGeometryPart(g))
183190
.ToList());
184-
((MultiPolygon)_geometry).BoundingBoxes = this.BoundingBox;
191+
((MultiPolygon)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
185192
break;
186193
default:
187194
throw new NotSupportedException("Geometry type " + sinkCollection.GeometryType.ToString() + " is not possible in GetConstructedGeometry.");
@@ -194,10 +201,7 @@ private IGeometryObject GeometryFromSinkGeometryCollection(SinkGeometryCollectio
194201

195202
public double[] BoundingBox
196203
{
197-
get
198-
{
199-
return new double[] { _lonMin, _latMin, _lonMax, _latMax };
200-
}
204+
get { return this._withBoundingBox ? new double[] {_lonMin, _latMin, _lonMax, _latMax} : null; }
201205
}
202206

203207
private IGeometryObject ConstructGeometryPart(SinkGeometry<OpenGisGeographyType> geomPart)

src/GeoJSON.Net.Contrib.MsSqlSpatial/Sinks/SqlGeometryGeoJSONSink.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ internal class SqlGeometryGeoJsonSink : IGeometrySink110
2828
double _xmax = double.MinValue;
2929
double _ymax = double.MinValue;
3030

31+
private readonly bool _withBoundingBox;
32+
33+
public SqlGeometryGeoJsonSink(bool withBoundingBox = true)
34+
{
35+
this._withBoundingBox = withBoundingBox;
36+
}
37+
3138
#region Sink implementation
3239

3340
public void BeginGeometry(OpenGisGeometryType type)
@@ -134,7 +141,7 @@ public IGeometryObject ConstructedGeometry
134141
List<IGeometryObject> subGeometries = _geomCollection.SubItems.Select(subItem => GeometryFromSinkGeometryCollection(subItem)).ToList();
135142
_geometry = new GeometryCollection(subGeometries);
136143

137-
((GeometryCollection)_geometry).BoundingBoxes = this.BoundingBox;
144+
((GeometryCollection)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
138145
break;
139146
default:
140147
throw new NotSupportedException("Geometry type " + _geomCollection.GeometryType.ToString() + " is not supported yet.");
@@ -153,33 +160,33 @@ private IGeometryObject GeometryFromSinkGeometryCollection(SinkGeometryCollectio
153160
{
154161
case OpenGisGeometryType.Point:
155162
_geometry = ConstructGeometryPart(sinkCollection[0]);
156-
((Point)_geometry).BoundingBoxes = this.BoundingBox;
163+
((Point)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
157164
break;
158165
case OpenGisGeometryType.MultiPoint:
159166
_geometry = new MultiPoint(sinkCollection.Skip(1)
160167
.Select(g => (Point)ConstructGeometryPart(g))
161168
.ToList());
162-
((MultiPoint)_geometry).BoundingBoxes = this.BoundingBox;
169+
((MultiPoint)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
163170
break;
164171
case OpenGisGeometryType.LineString:
165172
_geometry = ConstructGeometryPart(sinkCollection[0]);
166-
((LineString)_geometry).BoundingBoxes = this.BoundingBox;
173+
((LineString)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
167174
break;
168175
case OpenGisGeometryType.MultiLineString:
169176
_geometry = new MultiLineString(sinkCollection.Skip(1)
170177
.Select(g => (LineString)ConstructGeometryPart(g))
171178
.ToList());
172-
((MultiLineString)_geometry).BoundingBoxes = this.BoundingBox;
179+
((MultiLineString)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
173180
break;
174181
case OpenGisGeometryType.Polygon:
175182
_geometry = ConstructGeometryPart(sinkCollection.First());
176-
((Polygon)_geometry).BoundingBoxes = this.BoundingBox;
183+
((Polygon)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
177184
break;
178185
case OpenGisGeometryType.MultiPolygon:
179186
_geometry = new MultiPolygon(sinkCollection.Skip(1)
180187
.Select(g => (Polygon)ConstructGeometryPart(g))
181188
.ToList());
182-
((MultiPolygon)_geometry).BoundingBoxes = this.BoundingBox;
189+
((MultiPolygon)_geometry).BoundingBoxes = this._withBoundingBox ? this.BoundingBox : null;
183190
break;
184191
default:
185192
throw new NotSupportedException("Geometry type " + sinkCollection.GeometryType.ToString() + " is not possible in GetConstructedGeometry.");
@@ -191,10 +198,7 @@ private IGeometryObject GeometryFromSinkGeometryCollection(SinkGeometryCollectio
191198

192199
public double[] BoundingBox
193200
{
194-
get
195-
{
196-
return new double[] { _xmin, _ymin, _xmax, _ymax };
197-
}
201+
get { return this._withBoundingBox ? new double[] {_xmin, _ymin, _xmax, _ymax} : null; }
198202
}
199203

200204
private IGeometryObject ConstructGeometryPart(SinkGeometry<OpenGisGeometryType> geomPart)

test/GeoJSON.Net.Contrib.MsSqlSpatial.Test/ToGeoJSONGeographyTests.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,106 @@ public void TestEmptGeometryCollection_Geography()
228228

229229
}
230230

231+
[TestMethod]
232+
[TestCategory("ToGeoJSONGeography")]
233+
public void TestGeometryCollectionWithoutBoundingBox()
234+
{
235+
var geoJSONobj = this.geomCol.ToGeoJSONObject<GeometryCollection>(false);
236+
237+
Assert.IsNotNull(geoJSONobj);
238+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.GeometryCollection);
239+
Assert.IsNull(geoJSONobj.BoundingBoxes);
240+
Assert.AreEqual(geoJSONobj.Geometries.Count, 3);
241+
Assert.AreEqual(geoJSONobj.Geometries[0].Type, GeoJSONObjectType.Polygon);
242+
Assert.AreEqual(geoJSONobj.Geometries[1].Type, GeoJSONObjectType.Point);
243+
Assert.AreEqual(geoJSONobj.Geometries[2].Type, GeoJSONObjectType.MultiLineString);
244+
}
245+
246+
[TestMethod]
247+
[TestCategory("ToGeoJSONGeography")]
248+
public void TestLineStringWithoutBoundingBox()
249+
{
250+
var geoJSONobj = this.lineString.ToGeoJSONObject<LineString>(false);
251+
252+
Assert.IsNotNull(geoJSONobj);
253+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.LineString);
254+
Assert.IsNull(geoJSONobj.BoundingBoxes);
255+
}
256+
257+
[TestMethod]
258+
[TestCategory("ToGeoJSONGeography")]
259+
public void TestMultiLineStringWithoutBoundingBox()
260+
{
261+
var geoJSONobj = this.multiLineString.ToGeoJSONObject<MultiLineString>(false);
262+
263+
Assert.IsNotNull(geoJSONobj);
264+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.MultiLineString);
265+
Assert.IsNull(geoJSONobj.BoundingBoxes);
266+
}
267+
268+
[TestMethod]
269+
[TestCategory("ToGeoJSONGeography")]
270+
public void TestSimplePointWithoutBoundingBox()
271+
{
272+
Point geoJSONobj = this.simplePoint.ToGeoJSONObject<Point>(false);
273+
274+
Assert.IsNotNull(geoJSONobj);
275+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.Point);
276+
Assert.IsNull(geoJSONobj.BoundingBoxes);
277+
}
278+
279+
[TestMethod]
280+
[TestCategory("ToGeoJSONGeography")]
281+
public void TestMultiPointWithoutBoundingBox()
282+
{
283+
MultiPoint geoJSONobj = this.multiPoint.ToGeoJSONObject<MultiPoint>(false);
284+
285+
Assert.IsNotNull(geoJSONobj);
286+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.MultiPoint);
287+
Assert.IsNull(geoJSONobj.BoundingBoxes);
288+
}
289+
290+
[TestMethod]
291+
[TestCategory("ToGeoJSONGeography")]
292+
public void TestSimplePolygonWithoutBoundingBox()
293+
{
294+
var geoJSONobj = this.simplePoly.ToGeoJSONObject<Polygon>(false);
295+
296+
Assert.IsNotNull(geoJSONobj);
297+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.Polygon);
298+
Assert.IsNull(geoJSONobj.BoundingBoxes);
299+
Assert.AreEqual(geoJSONobj.Coordinates.Count, 1);
300+
}
301+
302+
[TestMethod]
303+
[TestCategory("ToGeoJSONGeography")]
304+
public void TestPolygonWitHoleWithoutBoundingBox()
305+
{
306+
var geoJSONobj = this.polyWithHole.ToGeoJSONObject<Polygon>(false);
307+
308+
Assert.IsNotNull(geoJSONobj);
309+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.Polygon);
310+
Assert.IsNull(geoJSONobj.BoundingBoxes);
311+
Assert.AreEqual(geoJSONobj.Coordinates.Count, 2);
312+
}
313+
314+
[TestMethod]
315+
[TestCategory("ToGeoJSONGeography")]
316+
public void TestMultiPolygonWithoutBoundingBox()
317+
{
318+
var geoJSONobj = this.multiPolygon.ToGeoJSONObject<MultiPolygon>(false);
319+
320+
Assert.IsNotNull(geoJSONobj);
321+
Assert.AreEqual(geoJSONobj.Type, GeoJSONObjectType.MultiPolygon);
322+
Assert.IsNull(geoJSONobj.BoundingBoxes);
323+
Assert.AreEqual(geoJSONobj.Coordinates.Count, 3);
324+
Assert.AreEqual(geoJSONobj.Coordinates[1].Coordinates.Count, 2);
325+
Assert.AreEqual(geoJSONobj.Coordinates[1].Coordinates[0].Coordinates.Count, 6);
326+
Assert.AreEqual(geoJSONobj.Coordinates[1].Coordinates[1].Coordinates.Count, 4);
327+
Assert.AreEqual(geoJSONobj.Coordinates[2].Coordinates[0].Coordinates.Count, 5);
328+
Assert.AreEqual(geoJSONobj.Coordinates[2].Coordinates[1].Coordinates.Count, 5);
329+
}
330+
231331
#region Test geographies
232332

233333
SqlGeography simplePoint = SqlGeography.Parse(new SqlString(WktSamples.POINT)).MakeValidIfInvalid();

0 commit comments

Comments
 (0)