using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.IO; using Deltares.Dam.Data.DataPlugins.Configuration; using Deltares.Geotechnics; using DotSpatial.Data; using DotSpatial.Topology; using NetTopologySuite.IO; using NUnit.Framework; namespace Deltares.Dam.Tests { [TestFixture] public class IntersectionOnShapesTest { [Test] [Category("Slow")] public void AllIntersectionsWithTrafficLoad() { const string crossSectionFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\Crosssection.shp"; const string trafficFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\TrafficLoad.shp"; FindAllIntersectionsDotSpatial(crossSectionFile, trafficFile); } [Test] [Category("Slow")] [Ignore("Takes 25 minutes on buildserver")] public void AllIntersectionsWithPolderLevel() { const string crossSectionFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\Crosssection.shp"; const string polderLevelFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\PolderLevel.shp"; FindAllIntersectionsDotSpatial(crossSectionFile, polderLevelFile); } [Test] public void OneIntersectionWithTrafficLoad() { const string crossSectionFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\Crosssection.shp"; const string trafficFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\TrafficLoad.shp"; FindFirstIntersectionDotSpatial(crossSectionFile, trafficFile); } [Test] public void OneIntersectionWithPolderLevel() { const string crossSectionFile = @"..\..\..\data\Dam\Waterboards\HHNK\shapefiles\Crosssection.shp"; const string polderLevelFile = @"..\..\..\data\Dam\Waterboards\HHNK\ShapeFiles\PolderLevel.shp"; Debug.WriteLine("--- DotSpatial ---"); FindFirstIntersectionDotSpatial(crossSectionFile, polderLevelFile); Debug.WriteLine("--- NetTopologySuite ---"); FindFirstIntersectionNetTopology(crossSectionFile, polderLevelFile); } private void FindAllIntersectionsDotSpatial(string sourceFile, string targetFile) { IFeatureSet crossSectionFeatureSet = FeatureSet.Open(sourceFile); IFeatureSet trafficLoadFeatureSet = FeatureSet.Open(targetFile); DateTime start = DateTime.Now; int intersections = 0; foreach (Feature crossSectionFeature in crossSectionFeatureSet.Features) { foreach (Feature trafficLoadFeature in trafficLoadFeatureSet.Features) { if (crossSectionFeature.Intersects(trafficLoadFeature)) { intersections++; } } } DateTime finish = DateTime.Now; TimeSpan duration = finish - start; Debug.WriteLine("Number of source sections: " + crossSectionFeatureSet.Features.Count); Debug.WriteLine("Number of targets: " + trafficLoadFeatureSet.Features.Count); Debug.WriteLine("Number of intersections: " + intersections); Debug.WriteLine("Seconds: " + duration.TotalSeconds); Debug.WriteLine("Seconds per intersection: " + duration.TotalSeconds / (trafficLoadFeatureSet.Features.Count * crossSectionFeatureSet.Features.Count)); } private void FindFirstIntersectionDotSpatial(string sourceFile, string targetFile) { IFeatureSet crossSectionFeatureSet = FeatureSet.Open(sourceFile); IFeatureSet trafficLoadFeatureSet = FeatureSet.Open(targetFile); DateTime start = DateTime.Now; int intersections = 0; IFeature crossSectionFeature = crossSectionFeatureSet.Features[0]; foreach (Feature trafficLoadFeature in trafficLoadFeatureSet.Features) { if (crossSectionFeature.Intersects(trafficLoadFeature)) { intersections++; } } DateTime finish = DateTime.Now; TimeSpan duration = finish - start; Debug.WriteLine("Number of source sections: 1"); Debug.WriteLine("Number of targets: " + trafficLoadFeatureSet.Features.Count); Debug.WriteLine("Number of intersections: " + intersections); Debug.WriteLine("Seconds: " + duration.TotalSeconds); Debug.WriteLine("Seconds per intersection: " + duration.TotalSeconds / trafficLoadFeatureSet.Features.Count); } private void FindFirstIntersectionNetTopology(string sourceFile, string targetFile) { var crossSectionFeatures = NtsFeature.Read(sourceFile); var trafficLoadFeatures = NtsFeature.Read(targetFile); DateTime start = DateTime.Now; int intersections = 0; //if (featureToTest.IsWithin(feature) || featureToTest.IsTouching(feature)) line-polygon //if (feature.IsIntersecting(featureToTest)) line-line NtsFeature crossSectionFeature = crossSectionFeatures.First(); foreach (NtsFeature trafficLoadFeature in trafficLoadFeatures) { if (crossSectionFeature.IsIntersecting(trafficLoadFeature)) { intersections++; } } DateTime finish = DateTime.Now; TimeSpan duration = finish - start; Debug.WriteLine("Number of source sections: 1"); Debug.WriteLine("Number of targets: " + trafficLoadFeatures.Count()); Debug.WriteLine("Number of intersections: " + intersections); Debug.WriteLine("Seconds: " + duration.TotalSeconds); Debug.WriteLine("Seconds per intersection: " + duration.TotalSeconds / trafficLoadFeatures.Count()); } } abstract class AbstractFeature { protected AbstractFeature() { this.Attributes = new Dictionary(); } public T Geometry { get; set; } public IDictionary Attributes { get; set; } public abstract bool IsIntersecting(AbstractFeature otherFeature); public abstract bool IsWithin(AbstractFeature otherFeature); public abstract bool IsTouching(AbstractFeature otherFeature); } class NtsFeature : AbstractFeature { public static IEnumerable Read(string fileName) { using (var reader = new ShapefileDataReader(fileName, NetTopologySuite.Geometries.GeometryFactory.Default)) { while (reader.Read()) { // force the reader to read with the US culture var feature = new NtsFeature() { Geometry = reader.Geometry }; for (int i = 0; i < reader.DbaseHeader.NumFields; i++) { string colName = reader.DbaseHeader.Fields[i].Name; object rowValue = reader.GetValue(i); if (!feature.Attributes.ContainsKey(colName)) feature.Attributes.Add(colName, rowValue); } yield return feature; } } } public override bool IsIntersecting(AbstractFeature otherFeature) { return this.Geometry.Intersects(otherFeature.Geometry); } public override bool IsWithin(AbstractFeature otherFeature) { return this.Geometry.Within(otherFeature.Geometry); } public override bool IsTouching(AbstractFeature otherFeature) { return this.Geometry.Touches(otherFeature.Geometry); } } }