PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Branches/0.9.5-DeltaShell/src/Common/SharpMap/Data/Providers/FeatureCollection.cs

#
C# | 405 lines | 331 code | 59 blank | 15 comment | 62 complexity | 5b307ad32b373eec677cce23c88083d8 MD5 | raw file
Possible License(s): LGPL-2.1
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using DelftTools.Utils;
  6. using DelftTools.Utils.Data;
  7. using DelftTools.Utils.Reflection;
  8. using GeoAPI.Extensions.Feature;
  9. using GeoAPI.Geometries;
  10. using GisSharpBlog.NetTopologySuite.Geometries;
  11. using System.Collections.ObjectModel;
  12. namespace SharpMap.Data.Providers
  13. {
  14. //TODO: get this class generic FeatureCollection<F>:where F: is IFeature. This will speed up and prettify the code :)
  15. //Note: See the WFDExplorer plugin for an implementation of FeatureCollection<T>!! It is not fully covered with tests
  16. //yet because not all requirements are clear
  17. public class FeatureCollection : Unique<long>, IFeatureProvider, ITimeNavigatable /* TODO: remove ITimeNavigatable, should be used only on UI facade classes */
  18. {
  19. private int srid;
  20. private Type featureType;
  21. private IList features;
  22. private IEnumerable<DateTime> times;
  23. public FeatureCollection()
  24. {
  25. features = new List<IFeature>();
  26. FilterFeaturesByTime();
  27. }
  28. public FeatureCollection(IList features, Type featureType)
  29. {
  30. if (!featureType.IsClass)
  31. {
  32. // We only accept a class because we want to use Activator to create object
  33. throw new ArgumentException("Can only instantiate FeatureCollection with class");
  34. }
  35. if (!typeof(IFeature).IsAssignableFrom((featureType)))
  36. {
  37. throw new ArgumentException("Feature type should be IFeature");
  38. }
  39. Features = features;
  40. FeatureType = featureType;
  41. }
  42. public virtual int GetFeatureCount()
  43. {
  44. return Features.Count;
  45. }
  46. public virtual IFeature GetFeature(int index)
  47. {
  48. return (IFeature) Features[index];
  49. }
  50. /// <summary>
  51. /// Get the feature by its geometry
  52. /// </summary>
  53. /// <param name="geom"></param>
  54. /// <returns></returns>
  55. public virtual IFeature GetFeature(IGeometry geom)
  56. {
  57. foreach (IFeature feature in Features)
  58. {
  59. if (feature.Geometry == geom)
  60. return feature;
  61. }
  62. return null;
  63. }
  64. public virtual bool Contains(IFeature feature)
  65. {
  66. if (Features.Count == 0)
  67. {
  68. return false;
  69. }
  70. // Since Features can be strongly collection typed we must prevent searching objects of an invalid type
  71. if (FeatureType != null)
  72. {
  73. // test if feature we are looking for is derived from FeatureType
  74. if (!FeatureType.IsAssignableFrom(feature.GetType()))
  75. {
  76. return false;
  77. }
  78. }
  79. else
  80. {
  81. // if FeatureType is not set use type of first object in collection.
  82. if (Features[0].GetType() != feature.GetType())
  83. {
  84. return false;
  85. }
  86. }
  87. return Features.Contains(feature);
  88. }
  89. public virtual int IndexOf(IFeature feature)
  90. {
  91. if (Features.Count == 0 || Features[0].GetType() != feature.GetType())
  92. {
  93. return -1;
  94. }
  95. return Features.IndexOf(feature);
  96. }
  97. public virtual int SRID
  98. {
  99. get { return srid; }
  100. set { srid = value; }
  101. }
  102. public virtual IEnvelope GetExtents()
  103. {
  104. IEnvelope envelope = new Envelope();
  105. if (Features == null)
  106. return envelope;
  107. foreach (IFeature feature in Features)
  108. {
  109. if(feature.Geometry == null)
  110. {
  111. continue;
  112. }
  113. // HACK: probably we should not use EnvelopeInternal here but Envelope
  114. if (envelope.IsNull)
  115. {
  116. envelope = (IEnvelope)feature.Geometry.EnvelopeInternal.Clone();
  117. }
  118. envelope.ExpandToInclude(feature.Geometry.EnvelopeInternal);
  119. }
  120. return envelope;
  121. }
  122. public virtual Collection<IGeometry> GetGeometriesInView(IEnvelope bbox)
  123. {
  124. Collection<IGeometry> result = new Collection<IGeometry>();
  125. int i = 0;
  126. foreach (IFeature feature in Features)
  127. {
  128. if (feature.Geometry.EnvelopeInternal.Intersects(bbox))
  129. {
  130. result.Add(feature.Geometry);
  131. }
  132. i++;
  133. }
  134. return result;
  135. }
  136. public virtual ICollection<IGeometry> GetGeometriesInView(IEnvelope bbox, double minGeometrySize)
  137. {
  138. Collection<IGeometry> result = new Collection<IGeometry>();
  139. int i = 0;
  140. foreach (IFeature feature in Features)
  141. {
  142. if (feature.Geometry.EnvelopeInternal.Intersects(bbox))
  143. {
  144. result.Add(feature.Geometry);
  145. }
  146. i++;
  147. }
  148. return result;
  149. }
  150. public virtual ICollection<int> GetObjectIDsInView(IEnvelope envelope)
  151. {
  152. Collection<int> ids = new Collection<int>();
  153. int i = 0;
  154. foreach (IFeature feature in Features)
  155. {
  156. if (feature.Geometry.EnvelopeInternal.Intersects(envelope))
  157. {
  158. ids.Add(i);
  159. }
  160. i++;
  161. }
  162. return ids;
  163. }
  164. public virtual IGeometry GetGeometryByID(int oid)
  165. {
  166. return ((IFeature) Features[oid]).Geometry;
  167. }
  168. public virtual IList GetFeatures(IGeometry boundingGeometry)
  169. {
  170. IList intersectedFeatures = new ArrayList();
  171. IEnvelope box = boundingGeometry.EnvelopeInternal;
  172. foreach (IFeature feature in Features)
  173. {
  174. if (feature.Geometry == null)
  175. {
  176. continue;
  177. }
  178. if (feature.Geometry.EnvelopeInternal.Intersects(box))
  179. {
  180. if (feature.Geometry.Intersects(boundingGeometry))
  181. {
  182. intersectedFeatures.Add(feature);
  183. }
  184. }
  185. }
  186. return intersectedFeatures;
  187. }
  188. public virtual IList GetFeatures(IEnvelope box)
  189. {
  190. IList intersectedFeatures = new ArrayList();
  191. if (Features != null)
  192. {
  193. foreach (IFeature feature in Features)
  194. {
  195. if (feature.Geometry == null)
  196. {
  197. continue;
  198. }
  199. if (feature.Geometry.EnvelopeInternal.Intersects(box))
  200. {
  201. intersectedFeatures.Add(feature);
  202. }
  203. }
  204. }
  205. return intersectedFeatures;
  206. }
  207. public virtual IList Features
  208. {
  209. get
  210. {
  211. if (times != null)
  212. {
  213. return timeFilteredFeatures;
  214. }
  215. return features;
  216. }
  217. set
  218. {
  219. if (value == null)
  220. {
  221. throw new InvalidOperationException("Features cannot be null in a feature collection.");
  222. }
  223. features = value;
  224. GuessFeatureType();
  225. if (features.Count > 0 && features[0] is ITimeDependent)
  226. {
  227. times = features.Cast<ITimeDependent>().Select(f => f.Time).Distinct().OrderBy(t => t);
  228. }
  229. FilterFeaturesByTime();
  230. }
  231. }
  232. private void GuessFeatureType()
  233. {
  234. if(featureType != null)
  235. {
  236. return;
  237. }
  238. // try to obtain feature type from given collection of features
  239. Type featuresCollectionType = Features.GetType();
  240. if (featuresCollectionType.IsGenericType && !featuresCollectionType.IsInterface)
  241. {
  242. featureType = featuresCollectionType.GetGenericArguments()[0];
  243. }
  244. // guess feature type from the first feature
  245. if (featureType == null && Features.Count > 0)
  246. {
  247. featureType = Features[0].GetType();
  248. }
  249. }
  250. public virtual void Dispose()
  251. {
  252. }
  253. public virtual Type FeatureType
  254. {
  255. get { return featureType; }
  256. set
  257. {
  258. featureType = value;
  259. if (!value.Implements(typeof(IFeature)))
  260. {
  261. throw new ArgumentException(string.Format("Type '{0}' is not a IFeature.", value));
  262. }
  263. }
  264. }
  265. public virtual Func<IFeatureProvider,IGeometry,IFeature> AddNewFeatureFromGeometryDelegate { get; set; }
  266. public virtual IFeature Add(IGeometry geometry)
  267. {
  268. if (featureType == null)
  269. {
  270. GuessFeatureType();
  271. if (featureType == null)
  272. {
  273. throw new NotSupportedException("FeatureType must be set in order to add a new feature geometry");
  274. }
  275. }
  276. IFeature newFeature;
  277. if (AddNewFeatureFromGeometryDelegate != null)
  278. {
  279. newFeature = AddNewFeatureFromGeometryDelegate(this, geometry);
  280. }
  281. else
  282. {
  283. newFeature = (IFeature) Activator.CreateInstance(featureType);
  284. newFeature.Geometry = geometry;
  285. Features.Add(newFeature);
  286. }
  287. return newFeature;
  288. }
  289. public virtual DateTime? TimeSelectionStart
  290. {
  291. get { return timeSelectionStart; }
  292. }
  293. public virtual DateTime? TimeSelectionEnd
  294. {
  295. get { return timeSelectionEnd; }
  296. }
  297. public virtual TimeNavigatableLabelFormatProvider CustomDateTimeFormatProvider
  298. {
  299. get { return null; }
  300. }
  301. private void FilterFeaturesByTime()
  302. {
  303. if(TimeSelectionStart == null || features.Count == 0 || !(features[0] is ITimeDependent))
  304. {
  305. timeFilteredFeatures = features;
  306. return;
  307. }
  308. timeFilteredFeatures = features.Cast<IFeature>()
  309. .Where(f =>
  310. {
  311. var timeDependent = f as ITimeDependent;
  312. return timeDependent.Time >= TimeSelectionStart
  313. && (TimeSelectionEnd == null || timeDependent.Time <= TimeSelectionEnd);
  314. })
  315. .Select(f => f)
  316. .ToList();
  317. }
  318. public virtual void SetCurrentTimeSelection(DateTime? start, DateTime? end)
  319. {
  320. timeSelectionStart = start;
  321. timeSelectionEnd = end;
  322. FilterFeaturesByTime();
  323. if (CurrentTimeSelectionChanged != null)
  324. {
  325. CurrentTimeSelectionChanged();
  326. }
  327. }
  328. public virtual event Action CurrentTimeSelectionChanged;
  329. public virtual IEnumerable<DateTime> Times
  330. {
  331. get { return times; }
  332. }
  333. public virtual event Action TimesChanged;
  334. public virtual TimeSelectionMode SelectionMode
  335. {
  336. get { return TimeSelectionMode.Range; }
  337. }
  338. public virtual SnappingMode SnappingMode
  339. {
  340. get { return SnappingMode.None; }
  341. }
  342. private IList timeFilteredFeatures;
  343. private DateTime? timeSelectionStart;
  344. private DateTime? timeSelectionEnd;
  345. }
  346. }