diff --git a/src/ProjNet/CoordinateSystems/Projection.cs b/src/ProjNet/CoordinateSystems/Projection.cs
index 1372986..a1be243 100644
--- a/src/ProjNet/CoordinateSystems/Projection.cs
+++ b/src/ProjNet/CoordinateSystems/Projection.cs
@@ -76,6 +76,17 @@ public ProjectionParameter GetParameter(int index)
return _parameters[index];
}
+ ///
+ /// Adds a parameter to the parameter list
+ ///
+ /// The projection parameter name
+ /// The value
+ internal void AddParameter(string name, double value)
+ {
+ var param = new ProjectionParameter(name, value);
+ _parameters.Add(param);
+ }
+
///
/// Gets an named parameter of the projection.
///
diff --git a/src/ProjNet/CoordinateSystems/Projections/MapProjection.cs b/src/ProjNet/CoordinateSystems/Projections/MapProjection.cs
index a369567..0d1ac44 100644
--- a/src/ProjNet/CoordinateSystems/Projections/MapProjection.cs
+++ b/src/ProjNet/CoordinateSystems/Projections/MapProjection.cs
@@ -244,6 +244,14 @@ public ProjectionParameter GetParameter(string name)
return _Parameters.Find(name);
}
+ ///
+ /// Adds a parameter to the parameter list
+ ///
+ internal void AddParameter(string name, double value)
+ {
+ _Parameters.Add(name, value);
+ }
+
///
///
///
diff --git a/src/ProjNet/IO/CoordinateSystems/CoordinateSystemWktReader.cs b/src/ProjNet/IO/CoordinateSystems/CoordinateSystemWktReader.cs
index a5b3dae..002f049 100644
--- a/src/ProjNet/IO/CoordinateSystems/CoordinateSystemWktReader.cs
+++ b/src/ProjNet/IO/CoordinateSystems/CoordinateSystemWktReader.cs
@@ -109,7 +109,7 @@ private static IUnit ReadUnit(WktStreamTokenizer tokenizer)
tokenizer.ReadAuthority(out authority, out authorityCode);
tokenizer.ReadCloser(bracket);
}
- else
+ else
tokenizer.CheckCloser(bracket);
return new Unit(unitsPerUnit, unitName, authority, authorityCode, string.Empty, string.Empty, string.Empty);
@@ -192,6 +192,7 @@ private static AxisInfo ReadAxis(WktStreamTokenizer tokenizer)
case "SOUTH": return new AxisInfo(axisName, AxisOrientationEnum.South);
case "UP": return new AxisInfo(axisName, AxisOrientationEnum.Up);
case "WEST": return new AxisInfo(axisName, AxisOrientationEnum.West);
+ case "UNKNOWN": return new AxisInfo(axisName, AxisOrientationEnum.Other);
default:
throw new ArgumentException("Invalid axis name '" + unitname + "' in WKT");
}
@@ -206,7 +207,7 @@ private static CoordinateSystem ReadCoordinateSystem(string coordinateSystem, Wk
case "PROJCS":
return ReadProjectedCoordinateSystem(tokenizer);
case "FITTED_CS":
- return ReadFittedCoordinateSystem (tokenizer);
+ return ReadFittedCoordinateSystem(tokenizer);
case "GEOCCS":
return ReadGeocentricCoordinateSystem(tokenizer);
case "COMPD_CS":
@@ -285,7 +286,7 @@ private static Ellipsoid ReadEllipsoid(WktStreamTokenizer tokenizer)
return ellipsoid;
}
- private static IProjection ReadProjection(WktStreamTokenizer tokenizer)
+ private static Projection ReadProjection(WktStreamTokenizer tokenizer)
{
if (tokenizer.GetStringValue() != "PROJECTION")
tokenizer.ReadToken("PROJECTION");
@@ -303,34 +304,46 @@ private static IProjection ReadProjection(WktStreamTokenizer tokenizer)
else
tokenizer.CheckCloser(bracket);
- tokenizer.ReadToken(",");//,
- tokenizer.ReadToken("PARAMETER");
var paramList = new List();
- while (tokenizer.GetStringValue() == "PARAMETER")
- {
- bracket = tokenizer.ReadOpener();
- string paramName = tokenizer.ReadDoubleQuotedWord();
- tokenizer.ReadToken(",");
- tokenizer.NextToken();
- double paramValue = tokenizer.GetNumericValue();
- tokenizer.ReadCloser(bracket);
- paramList.Add(new ProjectionParameter(paramName, paramValue));
- //tokenizer.ReadToken(",");
- //tokenizer.NextToken();
- tokenizer.NextToken();
- if (tokenizer.GetStringValue() == ",")
- {
- tokenizer.NextToken();
- }
- else
- {
- break;
- }
- }
+
var projection = new Projection(projectionName, paramList, projectionName, authority, authorityCode, string.Empty, string.Empty, string.Empty);
return projection;
}
+ private static void ReadParamater(WktStreamTokenizer tokenizer, Projection projection)
+ {
+ var bracket = tokenizer.ReadOpener();
+ string paramName = tokenizer.ReadDoubleQuotedWord();
+ tokenizer.ReadToken(",");
+ tokenizer.NextToken();
+ double paramValue = tokenizer.GetNumericValue();
+ tokenizer.ReadCloser(bracket);
+
+ projection.AddParameter(paramName, paramValue);
+ }
+
+ private static void ReadExtension(WktStreamTokenizer tokenizer)
+ {
+ var bracket = tokenizer.ReadOpener();
+ string paramName = tokenizer.ReadDoubleQuotedWord();
+ tokenizer.ReadToken(",");
+ tokenizer.NextToken();
+ if (paramName == "PROJ4")
+ {
+ string paramValue = tokenizer.ReadDoubleQuotedWord();
+ }
+ else
+ {
+ System.Diagnostics.Debug.WriteLine("What are you?");
+ }
+
+ tokenizer.ReadCloser(bracket);
+
+ System.Diagnostics.Debug.WriteLine("Now what do we do with you?");
+ }
+
+
+
private static ProjectedCoordinateSystem ReadProjectedCoordinateSystem(WktStreamTokenizer tokenizer)
{
/*PROJCS[
@@ -356,42 +369,64 @@ private static ProjectedCoordinateSystem ReadProjectedCoordinateSystem(WktStream
*/
var bracket = tokenizer.ReadOpener();
string name = tokenizer.ReadDoubleQuotedWord();
- tokenizer.ReadToken(",");
- tokenizer.ReadToken("GEOGCS");
- var geographicCS = ReadGeographicCoordinateSystem(tokenizer);
- tokenizer.ReadToken(",");
- tokenizer.ReadToken("PROJECTION");
- var projection = ReadProjection(tokenizer);
- var unit = ReadLinearUnit(tokenizer);
+ tokenizer.NextToken();
+
+ GeographicCoordinateSystem geographicCS = null;
+ Projection projection = null;
+ LinearUnit unit = null;
var axisInfo = new List(2);
string authority = string.Empty;
long authorityCode = -1;
- tokenizer.NextToken();
- if (tokenizer.GetStringValue() == ",")
+ while (tokenizer.GetStringValue() == ",")
{
tokenizer.NextToken();
- while (tokenizer.GetStringValue() == "AXIS")
- {
- axisInfo.Add(ReadAxis(tokenizer));
- tokenizer.NextToken();
- if (tokenizer.GetStringValue() == ",") tokenizer.NextToken();
- }
- if (tokenizer.GetStringValue() == ",") tokenizer.NextToken();
- if (tokenizer.GetStringValue() == "AUTHORITY")
+ string nextToken = tokenizer.GetStringValue();
+ switch (nextToken)
{
- tokenizer.ReadAuthority(out authority, out authorityCode);
- tokenizer.ReadCloser(bracket);
+ case "AUTHORITY":
+ tokenizer.ReadAuthority(out authority, out authorityCode);
+ break;
+ case "AXIS":
+ axisInfo.Add(ReadAxis(tokenizer));
+ break;
+ case "GEOGCS":
+ geographicCS = ReadGeographicCoordinateSystem(tokenizer);
+ break;
+ case "PARAMETER":
+ ReadParamater(tokenizer, projection);
+ break;
+ case "PROJECTION":
+ projection = ReadProjection(tokenizer);
+ break;
+ case "UNIT":
+ unit = ReadLinearUnit(tokenizer);
+ break;
+ case "EXTENSION":
+ ReadExtension(tokenizer);
+ break;
+ default:
+ throw new ArgumentException("Token not found for {0]", nextToken);
}
+
+ tokenizer.NextToken();
}
- //This is default axis values if not specified.
+
+ // we should be at the end already!?
+ tokenizer.CheckCloser(bracket);
+
if (axisInfo.Count == 0)
{
axisInfo.Add(new AxisInfo("X", AxisOrientationEnum.East));
axisInfo.Add(new AxisInfo("Y", AxisOrientationEnum.North));
}
- var projectedCS = new ProjectedCoordinateSystem(geographicCS.HorizontalDatum, geographicCS, unit as LinearUnit, projection, axisInfo, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
- return projectedCS;
+
+ if (geographicCS != null)
+ {
+ return new ProjectedCoordinateSystem(geographicCS.HorizontalDatum, geographicCS, unit as LinearUnit, projection, axisInfo, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
+ }
+
+ return null;
}
private static VerticalCoordinateSystem ReadVerticalCoordinateSystem(WktStreamTokenizer tokenizer)
@@ -451,10 +486,10 @@ private static CompoundCoordinateSystem ReadCompoundCoordinateSystem(WktStreamTo
long authorityCode = -1;
tokenizer.NextToken();
- if ( tokenizer.GetStringValue() == ",")
+ if (tokenizer.GetStringValue() == ",")
{
tokenizer.NextToken();
- if(tokenizer.GetStringValue() == "AUTHORITY")
+ if (tokenizer.GetStringValue() == "AUTHORITY")
{
tokenizer.ReadAuthority(out authority, out authorityCode);
}
@@ -541,23 +576,27 @@ private static GeographicCoordinateSystem ReadGeographicCoordinateSystem(WktStre
long authorityCode = -1;
tokenizer.NextToken();
var info = new List(2);
- if (tokenizer.GetStringValue() == ",")
+ while (tokenizer.GetStringValue() == ",")
{
tokenizer.NextToken();
- while (tokenizer.GetStringValue() == "AXIS")
+ string nextToken = tokenizer.GetStringValue();
+ if (nextToken == "AXIS")
{
info.Add(ReadAxis(tokenizer));
- tokenizer.NextToken();
- if (tokenizer.GetStringValue() == ",") tokenizer.NextToken();
}
- if (tokenizer.GetStringValue() == ",") tokenizer.NextToken();
- if (tokenizer.GetStringValue() == "AUTHORITY")
+ else if (nextToken == "AUTHORITY")
{
tokenizer.ReadAuthority(out authority, out authorityCode);
- tokenizer.ReadCloser(bracket);
}
+
+ tokenizer.NextToken();
}
+ //We should be closed already
+ tokenizer.CheckCloser(bracket);
+ //if (tokenizer.GetStringValue() != "]")
+ // tokenizer.ReadCloser(bracket);
+
//This is default axis values if not specified.
if (info.Count == 0)
{
@@ -575,6 +614,8 @@ private static HorizontalDatum ReadHorizontalDatum(WktStreamTokenizer tokenizer)
Wgs84ConversionInfo wgsInfo = null;
string authority = string.Empty;
long authorityCode = -1;
+ string extension = string.Empty;
+ string extensionMethod = string.Empty;
var bracket = tokenizer.ReadOpener();
string name = tokenizer.ReadDoubleQuotedWord();
@@ -595,6 +636,11 @@ private static HorizontalDatum ReadHorizontalDatum(WktStreamTokenizer tokenizer)
tokenizer.ReadAuthority(out authority, out authorityCode);
tokenizer.ReadCloser(bracket);
}
+ else if (tokenizer.GetStringValue() == "EXTENSION")
+ {
+ tokenizer.ReadExtension(out extension, out extensionMethod);
+ tokenizer.ReadCloser(bracket);
+ }
}
// make an assumption about the datum type.
var horizontalDatum = new HorizontalDatum(ellipsoid, wgsInfo, DatumType.HD_Geocentric, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
@@ -612,7 +658,7 @@ private static VerticalDatum ReadVerticalDatum(WktStreamTokenizer tokenizer)
string name = tokenizer.ReadDoubleQuotedWord();
tokenizer.ReadToken(",");
tokenizer.NextToken();
- var datumType = (DatumType) tokenizer.GetNumericValue();
+ var datumType = (DatumType)tokenizer.GetNumericValue();
tokenizer.NextToken();
if (tokenizer.GetStringValue() == ",")
{
@@ -623,7 +669,7 @@ private static VerticalDatum ReadVerticalDatum(WktStreamTokenizer tokenizer)
tokenizer.ReadCloser(bracket);
}
}
- var verticalDatum = new VerticalDatum( datumType, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
+ var verticalDatum = new VerticalDatum(datumType, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
return verticalDatum;
}
@@ -654,7 +700,7 @@ private static PrimeMeridian ReadPrimeMeridian(WktStreamTokenizer tokenizer)
return primeMeridian;
}
- private static FittedCoordinateSystem ReadFittedCoordinateSystem (WktStreamTokenizer tokenizer)
+ private static FittedCoordinateSystem ReadFittedCoordinateSystem(WktStreamTokenizer tokenizer)
{
/*
FITTED_CS[
@@ -676,21 +722,21 @@ private static FittedCoordinateSystem ReadFittedCoordinateSystem (WktStreamToken
]
*/
var bracket = tokenizer.ReadOpener();
- string name = tokenizer.ReadDoubleQuotedWord ();
- tokenizer.ReadToken (",");
- tokenizer.ReadToken ("PARAM_MT");
- var toBaseTransform = MathTransformWktReader.ReadMathTransform (tokenizer);
- tokenizer.ReadToken (",");
- tokenizer.NextToken ();
- var baseCS = ReadCoordinateSystem (null, tokenizer);
+ string name = tokenizer.ReadDoubleQuotedWord();
+ tokenizer.ReadToken(",");
+ tokenizer.ReadToken("PARAM_MT");
+ var toBaseTransform = MathTransformWktReader.ReadMathTransform(tokenizer);
+ tokenizer.ReadToken(",");
+ tokenizer.NextToken();
+ var baseCS = ReadCoordinateSystem(null, tokenizer);
string authority = string.Empty;
long authorityCode = -1;
- var ct = tokenizer.NextToken ();
+ var ct = tokenizer.NextToken();
while (ct != TokenType.Eol && ct != TokenType.Eof)
{
- switch (tokenizer.GetStringValue ())
+ switch (tokenizer.GetStringValue())
{
case ",":
break;
@@ -700,14 +746,14 @@ private static FittedCoordinateSystem ReadFittedCoordinateSystem (WktStreamToken
break;
case "AUTHORITY":
- tokenizer.ReadAuthority (out authority, out authorityCode);
+ tokenizer.ReadAuthority(out authority, out authorityCode);
//tokenizer.ReadCloser(bracket);
break;
}
- ct = tokenizer.NextToken ();
+ ct = tokenizer.NextToken();
}
- var fittedCS = new FittedCoordinateSystem (baseCS, toBaseTransform, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
+ var fittedCS = new FittedCoordinateSystem(baseCS, toBaseTransform, name, authority, authorityCode, string.Empty, string.Empty, string.Empty);
return fittedCS;
}
}
diff --git a/src/ProjNet/IO/CoordinateSystems/WKTStreamTokenizer.cs b/src/ProjNet/IO/CoordinateSystems/WKTStreamTokenizer.cs
index c6fa98b..ceab90e 100644
--- a/src/ProjNet/IO/CoordinateSystems/WKTStreamTokenizer.cs
+++ b/src/ProjNet/IO/CoordinateSystems/WKTStreamTokenizer.cs
@@ -169,5 +169,18 @@ public void ReadAuthority(out string authority, out long authorityCode)
long.TryParse(ReadDoubleQuotedWord(), NumberStyles.Any, _nfi, out authorityCode);
ReadCloser(bracket);
}
+
+ public void ReadExtension(out string extension, out string extensionMethod)
+ {
+ //EXTENSION["PROJ4_GRIDS","CA61_003.gsb"]
+ if (GetStringValue() != "EXTENSION")
+ ReadToken("EXTENSION");
+ var bracket = ReadOpener();
+ extension = ReadDoubleQuotedWord();
+ ReadToken(",");
+ NextToken();
+ extensionMethod = ReadDoubleQuotedWord();
+ ReadCloser(bracket);
+ }
}
}
diff --git a/test/ProjNet.Tests/WKT/WKTParseExtensionTests.cs b/test/ProjNet.Tests/WKT/WKTParseExtensionTests.cs
new file mode 100644
index 0000000..c0d35d9
--- /dev/null
+++ b/test/ProjNet.Tests/WKT/WKTParseExtensionTests.cs
@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities;
+using NUnit.Framework;
+using ProjNet.CoordinateSystems;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjNET.Tests.WKT
+{
+ internal class WKTParseTests_11_17_2022
+ {
+ private readonly CoordinateSystemFactory _coordinateSystemFactory = new CoordinateSystemFactory();
+
+ private const string extensionWkt1 = "PROJCS[\"NAD27/BLM59N(ftUS)\",GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke1866\",6378206.4,294.978698213898],EXTENSION[\"PROJ4_GRIDS\",\"NTv2_0.gsb\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4267\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",171],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",1640416.67],PARAMETER[\"false_northing\",0],UNIT[\"USsurveyfoot\",0.304800609601219],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"4399\"]]";
+ private const string extensionWkt2 = "PROJCS[\"NAD27/BLM60N(ftUS)\",GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke1866\",6378206.4,294.978698213898],EXTENSION[\"PROJ4_GRIDS\",\"NTv2_0.gsb\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4267\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",177],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",1640416.67],PARAMETER[\"false_northing\",0],UNIT[\"USsurveyfoot\",0.304800609601219],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"4400\"]]";
+ private const string extensionWkt3 = "PROJCS[\"WGS84/Pseudo-Mercator\",GEOGCS[\"WGS84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],EXTENSION[\"PROJ4\",\"+proj=merc+a=6378137+b=6378137+lat_ts=0+lon_0=0+x_0=0+y_0=0+k=1+units=m+nadgrids=@null+wktext+no_defs\"],AUTHORITY[\"EPSG\",\"3857\"]]";
+ private const string extensionWkt4 = "COMPD_CS[\"WGS84/Pseudo-Mercator+EGM2008geoidheight\",PROJCS[\"WGS84/Pseudo-Mercator\",GEOGCS[\"WGS84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],EXTENSION[\"PROJ4\",\"+proj=merc+a=6378137+b=6378137+lat_ts=0+lon_0=0+x_0=0+y_0=0+k=1+units=m+nadgrids=@null+wktext+no_defs\"],AUTHORITY[\"EPSG\",\"3857\"]],VERT_CS[\"EGM2008height\",VERT_DATUM[\"EGM2008geoid\",2005,AUTHORITY[\"EPSG\",\"1027\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Gravity-relatedheight\",UP],AUTHORITY[\"EPSG\",\"3855\"]],AUTHORITY[\"EPSG\",\"6871\"]]";
+
+ [Test]
+ public void TestExtensions()
+ {
+ CoordinateSystem cs = null;
+ Assert.That(() => cs = _coordinateSystemFactory.CreateFromWkt(extensionWkt1) as CoordinateSystem, Throws.Nothing);
+
+ cs = null;
+ Assert.That(() => cs = _coordinateSystemFactory.CreateFromWkt(extensionWkt2) as CoordinateSystem, Throws.Nothing);
+
+ cs = null;
+ Assert.That(() => cs = _coordinateSystemFactory.CreateFromWkt(extensionWkt3) as CoordinateSystem, Throws.Nothing);
+
+ cs = null;
+ Assert.That(() => cs = _coordinateSystemFactory.CreateFromWkt(extensionWkt4) as CoordinateSystem, Throws.Nothing);
+ }
+ }
+}