Skip to content

Commit

Permalink
Fix an oversight related to HandleOrdinates.
Browse files Browse the repository at this point in the history
Prior to 2.0.0, all that HandleOrdinates could do was *limit* what got written out.
As of 2.0.0, the value was actually effectively ignored.
Test cases didn't catch this, so they have been updated with checks that actually do fail without the change.
This partially necessitated tweaking the fixture to *actually* run some SpatiaLite integration checks.
It also required tweaking some RandomGeometryHelper methods to *actually* give Z/M/ZM geometries for every type of geometry that we ask for, instead of just some of them.

Resolves #7
  • Loading branch information
airbreather committed Jan 26, 2021
1 parent 640dd43 commit 2370d8f
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 86 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ jobs:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}

env:
DOTNET_CLI_TELEMETRY_OPTOUT: true

strategy:
fail-fast: false
matrix:
Expand All @@ -24,8 +27,6 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.x
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true

- name: Install mod_spatialite (Linux)
if: ${{ matrix.os == 'ubuntu-latest' }}
Expand Down
96 changes: 92 additions & 4 deletions src/NetTopologySuite.IO.SpatiaLite/GaiaGeoWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.IO;
using NetTopologySuite.Geometries;
using NetTopologySuite.Utilities;

namespace NetTopologySuite.IO
{
Expand Down Expand Up @@ -62,8 +63,9 @@ public byte[] Write(Geometry geom)
//if (geom.IsEmpty)
// return GaiaGeoEmptyHelper.EmptyGeometryCollectionWithSrid(geom.SRID);

var hasZ = (HandleOrdinates & Ordinates.Z) == Ordinates.Z;
var hasM = (HandleOrdinates & Ordinates.M) == Ordinates.M;
var ordinates = CheckOrdinates(geom);
var hasZ = (ordinates & Ordinates.Z) == Ordinates.Z;
var hasM = (ordinates & Ordinates.M) == Ordinates.M;

var gaiaExport = SetGaiaGeoExportFunctions(GaiaGeoEndianMarker.GAIA_LITTLE_ENDIAN, hasZ, hasM, UseCompressed);

Expand Down Expand Up @@ -128,6 +130,8 @@ private static void WriteGeometry(Geometry geom, GaiaExport gaiaExport, BinaryWr

//Geometry type
int coordinateFlag = gaiaExport.CoordinateFlag;

// N.B.: only LINESTRING and POLYGON (and their Z / M / ZM variants) support compression
int coordinateFlagNotValidForCompression = coordinateFlag > 1000000
? coordinateFlag - 1000000
: coordinateFlag;
Expand All @@ -150,11 +154,11 @@ private static void WriteGeometry(Geometry geom, GaiaExport gaiaExport, BinaryWr
WriteMultiPoint((MultiPoint)geom, writeCoordinates, gaiaExport, bw);
break;
case OgcGeometryType.MultiLineString:
gaiaExport.WriteInt32(bw, (int)GaiaGeoGeometry.GAIA_MULTILINESTRING | coordinateFlag);
gaiaExport.WriteInt32(bw, (int)GaiaGeoGeometry.GAIA_MULTILINESTRING | coordinateFlagNotValidForCompression);
WriteMultiLineString((MultiLineString)geom, writeCoordinates, gaiaExport, bw);
break;
case OgcGeometryType.MultiPolygon:
gaiaExport.WriteInt32(bw, (int)GaiaGeoGeometry.GAIA_MULTIPOLYGON | coordinateFlag);
gaiaExport.WriteInt32(bw, (int)GaiaGeoGeometry.GAIA_MULTIPOLYGON | coordinateFlagNotValidForCompression);
WriteMultiPolygon((MultiPolygon)geom, writeCoordinates, gaiaExport, bw);
break;
case OgcGeometryType.GeometryCollection:
Expand Down Expand Up @@ -412,5 +416,89 @@ private static void WriteCompressedXYZM(CoordinateSequence coordinateSequence, G
mprev = coordinateSequence.GetOrdinate(maxIndex, Ordinate.M);
wd(bw, cprev.X, cprev.Y, cprev.Z, mprev);
}

private Ordinates CheckOrdinates(Geometry geometry)
{
if (HandleOrdinates == Ordinates.XY)
{
return Ordinates.XY;
}

var filter = new CheckOrdinatesFilter(HandleOrdinates);
geometry.Apply(filter);

var result = Ordinates.XY;
if (filter.FoundZ)
{
result |= Ordinates.Z;
}

if (filter.FoundM)
{
result |= Ordinates.M;
}

return result;
}

private sealed class CheckOrdinatesFilter : IEntireCoordinateSequenceFilter
{
private readonly bool _checkZ;

private readonly bool _checkM;

public CheckOrdinatesFilter(Ordinates ordinatesToCheck)
{
_checkZ = (ordinatesToCheck & Ordinates.Z) == Ordinates.Z;
_checkM = (ordinatesToCheck & Ordinates.M) == Ordinates.M;
}

public bool FoundZ { get; private set; }

public bool FoundM { get; private set; }

public bool Done
{
get
{
if (_checkZ && !FoundZ)
{
return false;
}

if (_checkM && !FoundM)
{
return false;
}

return true;
}
}

bool IEntireCoordinateSequenceFilter.GeometryChanged => false;

public void Filter(CoordinateSequence seq)
{
bool checkZ = _checkZ && !FoundZ && seq.HasZ;
bool checkM = _checkM && !FoundM && seq.HasM;

int zIndex = seq.ZOrdinateIndex;
int mIndex = seq.MOrdinateIndex;
for (int i = 0; (checkZ || checkM) && i < seq.Count; i++)
{
if (checkZ && zIndex >= 0 && !double.IsNaN(seq.GetOrdinate(i, zIndex)))
{
FoundZ = true;
checkZ = false;
}

if (checkM && mIndex >= 0 && !double.IsNaN(seq.GetOrdinate(i, mIndex)))
{
FoundM = true;
checkM = false;
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NetTopologySuite" Version="[2.0.0, 3.0.0-A)" />
<PackageReference Include="NetTopologySuite" Version="[2.1.0, 3.0.0-A)" />
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
Expand Down
18 changes: 13 additions & 5 deletions test/NetTopologySuite.IO.SpatiaLite.Test/AbstractIOFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;

using NetTopologySuite.Geometries;
using NetTopologySuite.Geometries.Implementation;
using NUnit.Framework;
Expand All @@ -23,10 +24,6 @@ protected AbstractIOFixture(GeometryFactory factory)
RandomGeometryHelper = new RandomGeometryHelper(factory);
}

private int _counter;

public int Counter { get { return ++_counter; } }

[SetUp]
public virtual void OnFixtureSetUp()
{
Expand Down Expand Up @@ -173,7 +170,7 @@ public double MaxY
protected set { RandomGeometryHelper.MaxY = value; }
}

public Ordinates Ordinates
public Ordinates InputOrdinates
{
get { return RandomGeometryHelper.Ordinates; }
set
Expand All @@ -183,6 +180,17 @@ public Ordinates Ordinates
}
}

private Ordinates _clipOrdinates = Ordinates.AllOrdinates;
public Ordinates ClipOrdinates
{
get => _clipOrdinates;
set
{
Debug.Assert((value & Ordinates.XY) == Ordinates.XY);
_clipOrdinates = value;
}
}

/// <summary>
/// Function to create the test table and add some data
/// </summary>
Expand Down
28 changes: 21 additions & 7 deletions test/NetTopologySuite.IO.SpatiaLite.Test/GeoPackageFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ public class GeoPackageFixture : AbstractIOFixture
public override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
Ordinates = Ordinates.XY;
InputOrdinates = Ordinates.XY;
Compressed = false;
}

public bool HasZ => (Ordinates & Ordinates.Z) == Ordinates.Z;
public bool InputHasZ => (InputOrdinates & Ordinates.Z) == Ordinates.Z;

public bool HasM => (Ordinates & Ordinates.M) == Ordinates.M;
public bool InputHasM => (InputOrdinates & Ordinates.M) == Ordinates.M;

public bool Compressed { get; set; }

Expand Down Expand Up @@ -86,7 +86,7 @@ protected override byte[] Write(Geometry geom)
{
var writer = new GeoPackageGeoWriter
{
HandleOrdinates = Ordinates
HandleOrdinates = ClipOrdinates
};
return writer.Write(geom);
}
Expand All @@ -101,7 +101,7 @@ public class GeoPackageFixture3D : GeoPackageFixture
public override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
Ordinates = Ordinates.XYZ;
InputOrdinates = Ordinates.XYZ;
}
}

Expand All @@ -114,7 +114,7 @@ public class GeoPackageFixtureM : GeoPackageFixture
public override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
Ordinates = Ordinates.XYM;
InputOrdinates = Ordinates.XYM;
}
}

Expand All @@ -127,7 +127,21 @@ public class GeoPackageFixture3DM : GeoPackageFixture
public override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
Ordinates = Ordinates.XYZM;
InputOrdinates = Ordinates.XYZM;
}
}

[TestFixture]
[Category("Database.IO")]
public class GeoPackageFixture3DMClippedTo2D : GeoPackageFixture
{
protected override string Name => "GeoPackageFixture3DMClippedTo2D.sqlite";

public override void OnFixtureSetUp()
{
base.OnFixtureSetUp();
InputOrdinates = Ordinates.XYZM;
ClipOrdinates = Ordinates.XY;
}
}
}
Loading

0 comments on commit 2370d8f

Please sign in to comment.