Skip to content

Commit 83b2b25

Browse files
author
Travis Yeik
committed
Implemented a more dynamic CoordinateSystemService
Implemented a database service to obtain fast indexing of coordinates systems by codes from an sqlite database. Also added a file service to obtain indexing coordinates systems from a csv file. Fixed parsing errors of wkts and added and EXTENSION parse.
1 parent 9265e2a commit 83b2b25

15 files changed

+878
-289
lines changed

src/ProjNet/CoordinateSystemServices.cs

Lines changed: 65 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -14,94 +14,26 @@
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with SharpMap; if not, write to the Free Software
1616
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17-
17+
1818
using System;
19-
using System.Collections;
2019
using System.Collections.Generic;
21-
using System.Threading;
20+
using System.Net.Http;
21+
using System.Threading.Tasks;
2222
using ProjNet.CoordinateSystems;
2323
using ProjNet.CoordinateSystems.Transformations;
24+
using ProjNet.Services;
2425

2526
namespace ProjNet
2627
{
2728
/// <summary>
2829
/// A coordinate system services class
2930
/// </summary>
30-
public class CoordinateSystemServices // : ICoordinateSystemServices
31+
public class CoordinateSystemServices
3132
{
32-
//private static ICoordinateSequenceFactory _coordinateSequenceFactory;
33-
34-
///// <summary>
35-
///// Gets or sets a default coordinate sequence factory
36-
///// </summary>
37-
//public static ICoordinateSequenceFactory CoordinateSequenceFactory
38-
//{
39-
// get { return _coordinateSequenceFactory ?? new CoordinateArraySequenceFactory(); }
40-
// set { _coordinateSequenceFactory = value; }
41-
//}
42-
43-
private readonly Dictionary<int, CoordinateSystem> _csBySrid;
44-
private readonly Dictionary<IInfo, int> _sridByCs;
4533

34+
private readonly ICoordinateSystemService _service;
4635
private readonly CoordinateSystemFactory _coordinateSystemFactory;
4736
private readonly CoordinateTransformationFactory _ctFactory;
48-
49-
private readonly ManualResetEvent _initialization = new ManualResetEvent(false);
50-
51-
#region CsEqualityComparer class
52-
private class CsEqualityComparer : EqualityComparer<IInfo>
53-
{
54-
public override bool Equals(IInfo x, IInfo y)
55-
{
56-
return x.AuthorityCode == y.AuthorityCode &&
57-
string.Compare(x.Authority, y.Authority, StringComparison.OrdinalIgnoreCase) == 0;
58-
}
59-
60-
public override int GetHashCode(IInfo obj)
61-
{
62-
if (obj == null) return 0;
63-
return Convert.ToInt32(obj.AuthorityCode) + (obj.Authority != null ? obj.Authority.GetHashCode() : 0);
64-
}
65-
}
66-
#endregion
67-
68-
#region CoordinateSystemKey class
69-
70-
private class CoordinateSystemKey : IInfo
71-
{
72-
public CoordinateSystemKey(string authority, long authorityCode)
73-
{
74-
Authority = authority;
75-
AuthorityCode = authorityCode;
76-
}
77-
78-
public bool EqualParams(object obj)
79-
{
80-
throw new NotSupportedException();
81-
}
82-
83-
public string Name { get { return null; } }
84-
public string Authority { get; private set; }
85-
public long AuthorityCode { get; private set; }
86-
public string Alias { get { return null; } }
87-
public string Abbreviation { get { return null; } }
88-
public string Remarks { get { return null; } }
89-
public string WKT { get { return null; } }
90-
public string XML { get { return null; } }
91-
}
92-
93-
#endregion
94-
95-
/// <summary>
96-
/// Creates an instance of this class
97-
/// </summary>
98-
/// <param name="coordinateSystemFactory">The coordinate sequence factory to use.</param>
99-
/// <param name="coordinateTransformationFactory">The coordinate transformation factory to use</param>
100-
public CoordinateSystemServices(CoordinateSystemFactory coordinateSystemFactory,
101-
CoordinateTransformationFactory coordinateTransformationFactory)
102-
: this(coordinateSystemFactory, coordinateTransformationFactory, null)
103-
{
104-
}
10537

10638
/// <summary>
10739
/// Creates an instance of this class.
@@ -116,32 +48,9 @@ public CoordinateSystemServices(IEnumerable<KeyValuePair<int, string>> definitio
11648
/// Creates an instance of this class
11749
/// </summary>
11850
public CoordinateSystemServices()
119-
: this(new CoordinateSystemFactory(), new CoordinateTransformationFactory(), null)
51+
: this(new CoordinateSystemFactory(), new CoordinateTransformationFactory())
12052
{
12153
}
122-
//public Func<string, long, string> GetDefinition { get; set; }
123-
124-
/*
125-
public static string GetFromSpatialReferenceOrg(string authority, long code)
126-
{
127-
var url = string.Format("http://spatialreference.org/ref/{0}/{1}/ogcwkt/",
128-
authority.ToLowerInvariant(),
129-
code);
130-
var req = (HttpWebRequest) WebRequest.Create(url);
131-
using (var resp = req.GetResponse())
132-
{
133-
using (var resps = resp.GetResponseStream())
134-
{
135-
if (resps != null)
136-
{
137-
using (var sr = new StreamReader(resps))
138-
return sr.ReadToEnd();
139-
}
140-
}
141-
}
142-
return null;
143-
}
144-
*/
14554

14655
/// <summary>
14756
/// Creates an instance of this class
@@ -161,93 +70,64 @@ public CoordinateSystemServices(CoordinateSystemFactory coordinateSystemFactory,
16170
throw new ArgumentNullException(nameof(coordinateTransformationFactory));
16271
_ctFactory = coordinateTransformationFactory;
16372

164-
_csBySrid = new Dictionary<int, CoordinateSystem>();
165-
_sridByCs = new Dictionary<IInfo, int>(new CsEqualityComparer());
166-
167-
object enumObj = (object)enumeration ?? DefaultInitialization();
168-
_initialization = new ManualResetEvent(false);
169-
System.Threading.Tasks.Task.Run(() => FromEnumeration((new[] { this, enumObj })));
73+
_service = new DefaultCoordinateService(this, enumeration);
17074
}
17175

172-
//private CoordinateSystemServices(ICoordinateSystemFactory coordinateSystemFactory,
173-
// ICoordinateTransformationFactory coordinateTransformationFactory,
174-
// IEnumerable<KeyValuePair<int, ICoordinateSystem>> enumeration)
175-
// : this(coordinateSystemFactory, coordinateTransformationFactory)
176-
//{
177-
// var enumObj = (object)enumeration ?? DefaultInitialization();
178-
// _initialization = new ManualResetEvent(false);
179-
// ThreadPool.QueueUserWorkItem(FromEnumeration, new[] { this, enumObj });
180-
//}
181-
182-
private static CoordinateSystem CreateCoordinateSystem(CoordinateSystemFactory coordinateSystemFactory, string wkt)
76+
/// <summary>
77+
/// Creates an instance of this class
78+
/// </summary>
79+
/// <param name="coordinateSystemFactory">The coordinate sequence factory to use.</param>
80+
/// <param name="coordinateTransformationFactory">The coordinate transformation factory to use</param>
81+
public CoordinateSystemServices(CoordinateSystemFactory coordinateSystemFactory,
82+
CoordinateTransformationFactory coordinateTransformationFactory)
18383
{
184-
try
185-
{
186-
return coordinateSystemFactory.CreateFromWkt(wkt.Replace("ELLIPSOID", "SPHEROID"));
187-
}
188-
catch (Exception)
189-
{
190-
// as a fallback we ignore projections not supported
191-
return null;
192-
}
193-
}
84+
if (coordinateSystemFactory == null)
85+
throw new ArgumentNullException(nameof(coordinateSystemFactory));
86+
_coordinateSystemFactory = coordinateSystemFactory;
19487

195-
private static IEnumerable<KeyValuePair<int, CoordinateSystem>> DefaultInitialization()
196-
{
197-
yield return new KeyValuePair<int, CoordinateSystem>(4326, GeographicCoordinateSystem.WGS84);
198-
yield return new KeyValuePair<int, CoordinateSystem>(3857, ProjectedCoordinateSystem.WebMercator);
88+
if (coordinateTransformationFactory == null)
89+
throw new ArgumentNullException(nameof(coordinateTransformationFactory));
90+
_ctFactory = coordinateTransformationFactory;
91+
92+
_service = new DatabaseCoordinateService(this);
19993
}
20094

201-
private static void FromEnumeration(CoordinateSystemServices css,
202-
IEnumerable<KeyValuePair<int, CoordinateSystem>> enumeration)
95+
/// <summary>
96+
/// Returns a CoordinateSystem from a url containing the wkt
97+
/// </summary>
98+
/// <param name="url"></param>
99+
/// <returns>Returns null if not found</returns>
100+
public async Task<CoordinateSystem> GetCoordinateSystemFromWeb(string url)
203101
{
204-
foreach (var sridCs in enumeration)
102+
try
205103
{
206-
css.AddCoordinateSystem(sridCs.Key, sridCs.Value);
104+
using (var client = new HttpClient())
105+
{
106+
string wkt = await client.GetStringAsync(url);
107+
return _coordinateSystemFactory.CreateFromWkt(wkt);
108+
}
207109
}
208-
}
209-
210-
private static IEnumerable<KeyValuePair<int, CoordinateSystem>> CreateCoordinateSystems(
211-
CoordinateSystemFactory factory,
212-
IEnumerable<KeyValuePair<int, string>> enumeration)
213-
{
214-
foreach (var sridWkt in enumeration)
110+
catch (HttpRequestException ex)
215111
{
216-
var cs = CreateCoordinateSystem(factory, sridWkt.Value);
217-
if (cs != null)
218-
yield return new KeyValuePair<int, CoordinateSystem>(sridWkt.Key, cs);
112+
System.Diagnostics.Debug.WriteLine(ex.Message);
219113
}
220-
}
221114

222-
private static void FromEnumeration(CoordinateSystemServices css,
223-
IEnumerable<KeyValuePair<int, string>> enumeration)
224-
{
225-
FromEnumeration(css, CreateCoordinateSystems(css._coordinateSystemFactory, enumeration));
115+
return null;
226116
}
227117

228-
private static void FromEnumeration(object parameter)
118+
public CoordinateSystem CreateFromWkt(string wkt)
229119
{
230-
object[] paras = (object[]) parameter;
231-
var css = (CoordinateSystemServices) paras[0];
232-
233-
if (paras[1] is IEnumerable<KeyValuePair<int, string>>)
234-
FromEnumeration(css, (IEnumerable<KeyValuePair<int, string>>) paras[1]);
235-
else
236-
FromEnumeration(css, (IEnumerable<KeyValuePair<int, CoordinateSystem>>)paras[1]);
237-
238-
css._initialization.Set();
120+
return _coordinateSystemFactory.CreateFromWkt(wkt);
239121
}
240122

241-
242123
/// <summary>
243124
/// Returns the coordinate system by <paramref name="srid" /> identifier
244125
/// </summary>
245126
/// <param name="srid">The initialization for the coordinate system</param>
246127
/// <returns>The coordinate system.</returns>
247128
public CoordinateSystem GetCoordinateSystem(int srid)
248129
{
249-
_initialization.WaitOne();
250-
return _csBySrid.TryGetValue(srid, out var cs) ? cs : null;
130+
return _service.GetCoordinateSystem(srid);
251131
}
252132

253133
/// <summary>
@@ -258,10 +138,7 @@ public CoordinateSystem GetCoordinateSystem(int srid)
258138
/// <returns>The coordinate system.</returns>
259139
public CoordinateSystem GetCoordinateSystem(string authority, long code)
260140
{
261-
int? srid = GetSRID(authority, code);
262-
if (srid.HasValue)
263-
return GetCoordinateSystem(srid.Value);
264-
return null;
141+
return _service.GetCoordinateSystem(authority, code);
265142
}
266143

267144
/// <summary>
@@ -272,13 +149,7 @@ public CoordinateSystem GetCoordinateSystem(string authority, long code)
272149
/// <returns>The identifier or <value>null</value></returns>
273150
public int? GetSRID(string authority, long authorityCode)
274151
{
275-
var key = new CoordinateSystemKey(authority, authorityCode);
276-
int srid;
277-
_initialization.WaitOne();
278-
if (_sridByCs.TryGetValue(key, out srid))
279-
return srid;
280-
281-
return null;
152+
return _service.GetSRID(authority, authorityCode);
282153
}
283154

284155
/// <summary>
@@ -305,64 +176,46 @@ public ICoordinateTransformation CreateTransformation(CoordinateSystem source, C
305176
return _ctFactory.CreateFromCoordinateSystems(source, target);
306177
}
307178

308-
protected void AddCoordinateSystem(int srid, CoordinateSystem coordinateSystem)
179+
/// <summary>
180+
/// Adds a coordinate system to the service
181+
/// </summary>
182+
public void AddCoordinateSystem(int srid, CoordinateSystem coordinateSystem)
309183
{
310-
lock (((IDictionary) _csBySrid).SyncRoot)
311-
{
312-
lock (((IDictionary) _sridByCs).SyncRoot)
313-
{
314-
if (_sridByCs.ContainsKey(coordinateSystem))
315-
return;
316-
317-
if (_csBySrid.ContainsKey(srid))
318-
{
319-
if (ReferenceEquals(coordinateSystem, _csBySrid[srid]))
320-
return;
321-
322-
_sridByCs.Remove(_csBySrid[srid]);
323-
_csBySrid[srid] = coordinateSystem;
324-
_sridByCs.Add(coordinateSystem, srid);
325-
}
326-
else
327-
{
328-
_csBySrid.Add(srid, coordinateSystem);
329-
_sridByCs.Add(coordinateSystem, srid);
330-
}
331-
}
332-
}
184+
_service.AddCoordinateSystem(srid, coordinateSystem);
333185
}
334186

335-
protected virtual int AddCoordinateSystem(CoordinateSystem coordinateSystem)
187+
/// <summary>
188+
/// Adds a coordinate system to the service
189+
/// </summary>
190+
public virtual int AddCoordinateSystem(CoordinateSystem coordinateSystem)
336191
{
337-
int srid = (int) coordinateSystem.AuthorityCode;
338-
AddCoordinateSystem(srid, coordinateSystem);
339-
340-
return srid;
192+
return _service.AddCoordinateSystem(coordinateSystem);
341193
}
342194

343-
protected void Clear()
195+
/// <summary>
196+
/// Returns the number of coordinate systems in the service
197+
/// </summary>
198+
public int Count
344199
{
345-
_csBySrid.Clear();
200+
get { return _service.Count; }
346201
}
347202

348-
protected int Count
203+
[Obsolete]
204+
public bool RemoveCoordinateSystem(int srid)
349205
{
350-
get
351-
{
352-
_initialization.WaitOne();
353-
return _sridByCs.Count;
354-
}
206+
throw new NotSupportedException();
355207
}
356208

357-
public bool RemoveCoordinateSystem(int srid)
209+
[Obsolete]
210+
protected void Clear()
358211
{
359212
throw new NotSupportedException();
360213
}
361214

215+
[Obsolete]
362216
public IEnumerator<KeyValuePair<int, CoordinateSystem>> GetEnumerator()
363217
{
364-
_initialization.WaitOne();
365-
return _csBySrid.GetEnumerator();
218+
throw new NotSupportedException();
366219
}
367220
}
368221
}

src/ProjNet/CoordinateSystems/Projection.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ public ProjectionParameter GetParameter(int index)
7676
return _parameters[index];
7777
}
7878

79+
/// <summary>
80+
/// Adds a parameter to the parameter list
81+
/// </summary>
82+
/// <param name="param">The projection parameter to add</param>
83+
public void AddParameter(string name, double value)
84+
{
85+
ProjectionParameter param = new ProjectionParameter(name, value);
86+
_parameters.Add(param);
87+
}
88+
7989
/// <summary>
8090
/// Gets an named parameter of the projection.
8191
/// </summary>

0 commit comments

Comments
 (0)