Skip to content

Commit 8ee8eb7

Browse files
authored
Merge pull request #122 from peetw/feature/issue-120
Ensure that Z/M ordinates of 3D/4D PostGIS geometries are saved to the database
2 parents f2dd344 + 69086a2 commit 8ee8eb7

File tree

10 files changed

+256
-6
lines changed

10 files changed

+256
-6
lines changed

NHibernate.Spatial.PostGis/Dialect/PostGisDialect.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ private string QuoteSchema(string schema)
477477
/// <param name="column">The column.</param>
478478
/// <param name="srid">The srid.</param>
479479
/// <param name="subtype">The subtype.</param>
480-
/// <param name="dimension">[3DIS] The dimension</param>
480+
/// <param name="dimension">The dimension.</param>
481481
/// <param name="isNullable">Whether or not the column is nullable</param>
482482
/// <returns></returns>
483483
public string GetSpatialCreateString(string schema, string table, string column, int srid, string subtype, int dimension, bool isNullable)
@@ -493,8 +493,7 @@ public string GetSpatialCreateString(string schema, string table, string column,
493493
builder.Append(this.MultipleQueriesSeparator);
494494

495495
builder.AppendFormat("SELECT AddGeometryColumn('{0}','{1}','{2}',{3},'{4}',{5})",
496-
//this.QuoteSchema(schema), this.QuoteForTableName(table), this.QuoteForColumnName(column), srid, subtype, dimension == 3 ? 3 : 2);
497-
schema, table, column, srid, subtype, dimension == 3 ? 3 : 2);
496+
schema, table, column, srid, subtype, dimension);
498497

499498
if (!isNullable)
500499
{

NHibernate.Spatial.PostGis/Type/PostGisGeometryType.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ protected override byte[] FromGeometry(object value)
6666

6767
// Determine the ordinality of the geometry to ensure 3D and 4D geometries are
6868
// correctly serialized by PostGisWriter (see issue #66)
69+
// NOTE: Cannot use InteriorPoint here as that always returns a 2D point (see #120)
6970
// TODO: Is there a way of getting the ordinates directly from the geometry?
7071
var ordinates = Ordinates.XY;
71-
var interiorPoint = geometry.InteriorPoint;
72-
if (!interiorPoint.IsEmpty && !double.IsNaN(interiorPoint.Z))
72+
var coordinate = geometry.Coordinate;
73+
if (coordinate != null && !double.IsNaN(coordinate.Z))
7374
{
7475
ordinates |= Ordinates.Z;
7576
}
76-
if (!interiorPoint.IsEmpty && !double.IsNaN(interiorPoint.M))
77+
if (coordinate != null && !double.IsNaN(coordinate.M))
7778
{
7879
ordinates |= Ordinates.M;
7980
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using NetTopologySuite.Geometries;
3+
4+
namespace Tests.NHibernate.Spatial.Models
5+
{
6+
[Serializable]
7+
public class PolygonM
8+
{
9+
public int Id { get; set; }
10+
11+
public Geometry Geom { get; set; }
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
3+
4+
<class table="polygon_m" name="Tests.NHibernate.Spatial.Models.PolygonM, Tests.NHibernate.Spatial.PostGis20">
5+
<id name="Id" type="Int32" column="id">
6+
<generator class="assigned" />
7+
</id>
8+
<property name="Geom" column="geom">
9+
<type name="NHibernate.Spatial.Type.GeometryType,NHibernate.Spatial">
10+
<param name="srid">0</param>
11+
<param name="subtype">POLYGONM</param>
12+
<param name="dimension">3</param>
13+
</type>
14+
</property>
15+
</class>
16+
</hibernate-mapping>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using NetTopologySuite.Geometries;
3+
4+
namespace Tests.NHibernate.Spatial.Models
5+
{
6+
[Serializable]
7+
public class PolygonZ
8+
{
9+
public int Id { get; set; }
10+
11+
public Geometry Geom { get; set; }
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
3+
4+
<class table="polygon_z" name="Tests.NHibernate.Spatial.Models.PolygonZ, Tests.NHibernate.Spatial.PostGis20">
5+
<id name="Id" type="Int32" column="id">
6+
<generator class="assigned" />
7+
</id>
8+
<property name="Geom" column="geom">
9+
<type name="NHibernate.Spatial.Type.GeometryType,NHibernate.Spatial">
10+
<param name="srid">0</param>
11+
<param name="subtype">POLYGONZ</param>
12+
<param name="dimension">3</param>
13+
</type>
14+
</property>
15+
</class>
16+
</hibernate-mapping>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using NetTopologySuite.Geometries;
3+
4+
namespace Tests.NHibernate.Spatial.Models
5+
{
6+
[Serializable]
7+
public class PolygonZM
8+
{
9+
public int Id { get; set; }
10+
11+
public Geometry Geom { get; set; }
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
3+
4+
<class table="polygon_zm" name="Tests.NHibernate.Spatial.Models.PolygonZM, Tests.NHibernate.Spatial.PostGis20">
5+
<id name="Id" type="Int32" column="id">
6+
<generator class="assigned" />
7+
</id>
8+
<property name="Geom" column="geom">
9+
<type name="NHibernate.Spatial.Type.GeometryType,NHibernate.Spatial">
10+
<param name="srid">0</param>
11+
<param name="subtype">POLYGON</param>
12+
<param name="dimension">4</param>
13+
</type>
14+
</property>
15+
</class>
16+
</hibernate-mapping>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
using System;
2+
using NHibernate;
3+
using NHibernate.Cfg;
4+
using NUnit.Framework;
5+
using Tests.NHibernate.Spatial.Models;
6+
7+
namespace Tests.NHibernate.Spatial
8+
{
9+
[TestFixture]
10+
public class PostGis20MiscTestsFixture : AbstractFixture
11+
{
12+
private ISession _session;
13+
14+
protected override Type[] Mappings => new[]
15+
{
16+
typeof(PolygonZ),
17+
typeof(PolygonM),
18+
typeof(PolygonZM),
19+
};
20+
21+
protected override bool CheckDatabaseWasCleanedOnTearDown => false;
22+
23+
protected override void Configure(Configuration config)
24+
{
25+
TestConfiguration.Configure(config);
26+
}
27+
28+
protected override void OnTestFixtureSetUp()
29+
{ }
30+
31+
protected override void OnTestFixtureTearDown()
32+
{
33+
using (var session = sessions.OpenSession())
34+
{
35+
DeleteMappings(session);
36+
}
37+
}
38+
39+
protected override void OnSetUp()
40+
{
41+
_session = sessions.OpenSession();
42+
}
43+
44+
protected override void OnTearDown()
45+
{
46+
_session.Clear();
47+
_session.Close();
48+
_session.Dispose();
49+
}
50+
51+
/// <summary>
52+
/// Test that Z values are properly round-tripped (see #120).
53+
/// </summary>
54+
[Test]
55+
public void PolygonZValuesAreStoredAndRetrievedCorrectly()
56+
{
57+
// Arrange
58+
const string wkt = "POLYGONZ ((0 0 1, 0 100 2, 100 100 3, 100 0 4, 0 0 5))";
59+
using (var session = sessions.OpenSession())
60+
{
61+
var obj = new PolygonZ
62+
{
63+
Id = 1,
64+
Geom = Wkt.Read(wkt)
65+
};
66+
session.Save(obj);
67+
session.Flush();
68+
}
69+
var expected = Wkt.Read(wkt);
70+
var expectedCoord = expected.Coordinate;
71+
72+
// Act
73+
var polygonZ = _session.Load<PolygonZ>(1);
74+
var polygonZCoord = polygonZ.Geom.Coordinate;
75+
76+
// Assert
77+
// NOTE: Cannot use EqualsTopologically or EqualsExact here since
78+
// both ignore Z/M components
79+
Assert.AreEqual(expectedCoord.X, polygonZCoord.X);
80+
Assert.AreEqual(expectedCoord.Y, polygonZCoord.Y);
81+
Assert.AreEqual(expectedCoord.Z, polygonZCoord.Z);
82+
}
83+
84+
/// <summary>
85+
/// Test that M values are properly round-tripped (see #120).
86+
/// </summary>
87+
[Test]
88+
public void PolygonMValuesAreStoredAndRetrievedCorrectly()
89+
{
90+
// Arrange
91+
const string wkt = "POLYGONM ((0 0 1, 0 100 2, 100 100 3, 100 0 4, 0 0 5))";
92+
using (var session = sessions.OpenSession())
93+
{
94+
var obj = new PolygonM
95+
{
96+
Id = 1,
97+
Geom = Wkt.Read(wkt)
98+
};
99+
session.Save(obj);
100+
session.Flush();
101+
}
102+
var expected = Wkt.Read(wkt);
103+
var expectedCoord = expected.Coordinate;
104+
105+
// Act
106+
var polygonM = _session.Load<PolygonM>(1);
107+
var polygonMCoord = polygonM.Geom.Coordinate;
108+
109+
// Assert
110+
// NOTE: Cannot use EqualsTopologically or EqualsExact here since
111+
// both ignore Z/M components
112+
Assert.AreEqual(expectedCoord.X, polygonMCoord.X);
113+
Assert.AreEqual(expectedCoord.Y, polygonMCoord.Y);
114+
Assert.AreEqual(expectedCoord.M, polygonMCoord.M);
115+
}
116+
117+
/// <summary>
118+
/// Test that ZM values are properly round-tripped (see #120).
119+
/// </summary>
120+
[Test]
121+
public void PolygonZMValuesAreStoredAndRetrievedCorrectly()
122+
{
123+
// Arrange
124+
const string wkt = "POLYGONZM ((0 0 1 11, 0 100 2 22, 100 100 3 33, 100 0 4 44, 0 0 5 55))";
125+
using (var session = sessions.OpenSession())
126+
{
127+
var obj = new PolygonZM
128+
{
129+
Id = 1,
130+
Geom = Wkt.Read(wkt)
131+
};
132+
session.Save(obj);
133+
session.Flush();
134+
}
135+
var expected = Wkt.Read(wkt);
136+
var expectedCoord = expected.Coordinate;
137+
138+
// Act
139+
var polygonZM = _session.Load<PolygonZM>(1);
140+
var polygonZMCoord = polygonZM.Geom.Coordinate;
141+
142+
// Assert
143+
// NOTE: Cannot use EqualsTopologically or EqualsExact here since
144+
// both ignore Z/M components
145+
Assert.AreEqual(expectedCoord.X, polygonZMCoord.X);
146+
Assert.AreEqual(expectedCoord.Y, polygonZMCoord.Y);
147+
Assert.AreEqual(expectedCoord.Z, polygonZMCoord.Z);
148+
Assert.AreEqual(expectedCoord.M, polygonZMCoord.M);
149+
}
150+
}
151+
}

Tests.NHibernate.Spatial.PostGis20/Tests.NHibernate.Spatial.PostGis20.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88
<RootNamespace>Tests.NHibernate.Spatial</RootNamespace>
99
</PropertyGroup>
1010

11+
<ItemGroup>
12+
<None Remove="Models\PolygonM.hbm.xml" />
13+
<None Remove="Models\PolygonZ.hbm.xml" />
14+
<None Remove="Models\PolygonZM.hbm.xml" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<EmbeddedResource Include="Models\PolygonM.hbm.xml" />
19+
<EmbeddedResource Include="Models\PolygonZM.hbm.xml" />
20+
<EmbeddedResource Include="Models\PolygonZ.hbm.xml" />
21+
</ItemGroup>
22+
1123
<ItemGroup>
1224
<PackageReference Include="nunit" Version="3.12.0" />
1325
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />

0 commit comments

Comments
 (0)