Index: src/Deltares.DSoilModel.Data/DSoilModelProject.cs =================================================================== diff -u -r6 -r87 --- src/Deltares.DSoilModel.Data/DSoilModelProject.cs (.../DSoilModelProject.cs) (revision 6) +++ src/Deltares.DSoilModel.Data/DSoilModelProject.cs (.../DSoilModelProject.cs) (revision 87) @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using Deltares.Geographic; +using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.ConePenetrationTest; using Deltares.Geotechnics.IO; @@ -20,6 +21,7 @@ using Deltares.Standard.IO.Xml; using Deltares.Standard.Language; using Deltares.Standard.Logging; +using Deltares.Standard.Maps; using Deltares.Standard.Project; using Deltares.Standard.Validation; @@ -1042,7 +1044,125 @@ DataEventPublisher.SelectionChanged(selectedSegment, new SelectionEventArgs { Objects = new object[] { selectedSegment, newSegment }}); } } - + + /// + /// Link all selected CPT's and or Borings to the nearest (selected) segment(s) + /// + public void LinkCptsAndBoringsToNearestSegment(object[] selectedObjects) + { + // objects to link + var cpts = selectedObjects.Where(o => o is ConePenetrationTestData).Cast().ToList(); + var borings = selectedObjects.Where(o => o is Boring).Cast().ToList(); + var segments = selectedObjects.Where(o => o is SoilSegment).Cast().ToList(); + if (segments.Count == 0) + { + segments = SoilSegments; + } + foreach (var cpt in cpts) + { + LinkItemToSegments(cpt, segments); + } + foreach (var boring in borings) + { + LinkItemToSegments(boring, segments); + } + } + private void LinkItemToSegments(IGeographic item, List segments) + { + double nearestDistance = double.MaxValue; + IGeographic nearestItem = null; + SoilSegment nearestSegment = null; + foreach (var segment in segments) + { + double distance = DotSpatialGeographicAlgorithms.Distance(item, segment); + if (distance < nearestDistance) + { + nearestDistance = distance; + nearestItem = item; + nearestSegment = segment; + } + } + if (nearestItem != null) + { + // link segment to item + SetSegmentLinkAndLocalCoordinate(nearestSegment, nearestItem); + + // check for other mechanism segment(s) with the same geographic definition and link to these as well + foreach (var segment in segments) + { + double distance = DotSpatialGeographicAlgorithms.Distance(item, segment); + if (Math.Abs(distance - nearestDistance) < GeometryConstants.Accuracy) + { + if (segment.Mechanism != nearestSegment.Mechanism && segment.Points.Count == nearestSegment.Points.Count) + { + if (CompareGeographicStrings(segment, nearestSegment)) + { + SetSegmentLinkAndLocalCoordinate(segment, nearestItem); + } + } + } + } + } + } + + private void SetSegmentLinkAndLocalCoordinate(SoilSegment segment, object item) + { + var itemPoint = item as IGeographicPoint; + if (itemPoint != null) + { + var segmentPoint = DotSpatialGeographicAlgorithms.NearestPointOnGeographicString(segment, itemPoint); + var xSegment = GeographicHelper.Instance.GetOffsetOnGeographicLineString(segmentPoint, segment); + + // link to cpt ? + var cpt = item as ConePenetrationTestData; + if (cpt != null) + { + if (segment.Cpts.All(x => x.ConePenetrationTestData != cpt)) + { + segment.Cpts.Add(new ConePenetrationTestPerSegment + { + ConePenetrationTestData = cpt, + Xlocal = xSegment + }); + } + } + + // link to boring ? + var boring = item as Boring; + if (boring != null) + { + if (segment.Borings.All(x => x.Boring != boring)) + { + segment.Borings.Add(new BoringPerSegment + { + Boring = boring, + Xlocal = xSegment + }); + } + } + } + } + + private bool CompareGeographicStrings(IGeographicString geographicString1, IGeographicString geographicString2) + { + if (geographicString1.Points.Count != geographicString2.Points.Count) + { + return false; + } + for (int i = 0; i < geographicString1.Points.Count; i++) + { + if (Math.Abs(geographicString1.Points[i].X - geographicString2.Points[i].X) > GeometryConstants.Accuracy) + { + return false; + } + if (Math.Abs(geographicString1.Points[i].Y - geographicString2.Points[i].Y) > GeometryConstants.Accuracy) + { + return false; + } + } + return true; + } + private void RearrangeSegmentCpts(SoilSegment selectedSegment, SoilSegment newSegment, double xSplit) { foreach (var cptPerSegment in selectedSegment.Cpts) Index: src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs =================================================================== diff -u -r86 -r87 --- src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs (.../DSoilModelMapEditor.cs) (revision 86) +++ src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs (.../DSoilModelMapEditor.cs) (revision 87) @@ -306,120 +306,10 @@ /// private void LinkToNearestSegment() { - // objects to link - var cpts = mapEditor.SelectedObjects.Where(o => o is ConePenetrationTestData).Cast().ToList(); - var borings = mapEditor.SelectedObjects.Where(o => o is Boring).Cast().ToList(); - var segments = mapEditor.SelectedObjects.Where(o => o is SoilSegment).Cast().ToList(); - if (segments.Count == 0) - { - segments = project.SoilSegments; - } - foreach (var cpt in cpts) - { - LinkItemToSegments(cpt, segments); - } - foreach (var boring in borings) - { - LinkItemToSegments(boring, segments); - } + var selectedObjects = mapEditor.SelectedObjects.Where(o => o is ConePenetrationTestData || o is Boring || o is SoilSegment).ToArray(); + project.LinkCptsAndBoringsToNearestSegment(selectedObjects); } - private void LinkItemToSegments(IGeographic item, List segments) - { - double nearestDistance = double.MaxValue; - IGeographic nearestItem = null; - SoilSegment nearestSegment = null; - foreach (var segment in segments) - { - double distance = DotSpatialGeographicAlgorithms.Distance(item, segment); - if (distance < nearestDistance) - { - nearestDistance = distance; - nearestItem = item; - nearestSegment = segment; - } - } - if (nearestItem != null) - { - // link segment to item - SetSegmentLinkAndLocalCoordinate(nearestSegment, nearestItem); - - // check for other mechanism segment(s) with the same geographic definition and link to these as well - foreach (var segment in segments) - { - double distance = DotSpatialGeographicAlgorithms.Distance(item, segment); - if (Math.Abs(distance - nearestDistance) < GeometryConstants.Accuracy) - { - if (segment.Mechanism != nearestSegment.Mechanism && segment.Points.Count == nearestSegment.Points.Count) - { - if (CompareGeographicStrings(segment, nearestSegment)) - { - SetSegmentLinkAndLocalCoordinate(segment, nearestItem); - } - } - } - } - } - } - - private void SetSegmentLinkAndLocalCoordinate(SoilSegment segment, object item) - { - var itemPoint = item as IGeographicPoint; - if (itemPoint != null) - { - var segmentPoint = DotSpatialGeographicAlgorithms.NearestPointOnGeographicString(segment, itemPoint); - var xSegment = GeographicHelper.Instance.GetOffsetOnGeographicLineString(segmentPoint, segment); - - // link to cpt ? - var cpt = item as ConePenetrationTestData; - if (cpt != null) - { - if (segment.Cpts.All(x => x.ConePenetrationTestData != cpt)) - { - segment.Cpts.Add(new ConePenetrationTestPerSegment - { - ConePenetrationTestData = cpt, - Xlocal = xSegment - }); - } - } - - // link to boring ? - var boring = item as Boring; - if (boring != null) - { - if (segment.Borings.All(x => x.Boring != boring)) - { - segment.Borings.Add(new BoringPerSegment - { - Boring = boring, - Xlocal = xSegment - }); - } - } - } - } - - private bool CompareGeographicStrings(IGeographicString geographicString1, IGeographicString geographicString2) - { - if (geographicString1.Points.Count != geographicString2.Points.Count) - { - return false; - } - for (int i = 0; i < geographicString1.Points.Count; i++) - { - if (Math.Abs(geographicString1.Points[i].X - geographicString2.Points[i].X) > GeometryConstants.Accuracy) - { - return false; - } - if (Math.Abs(geographicString1.Points[i].Y - geographicString2.Points[i].Y) > GeometryConstants.Accuracy) - { - return false; - } - } - return true; - } - /// /// Selection change handler for specific interactions /// Index: src/Deltares.DSoilModel.Tests/DSoilModelProjectTest.cs =================================================================== diff -u -r7 -r87 --- src/Deltares.DSoilModel.Tests/DSoilModelProjectTest.cs (.../DSoilModelProjectTest.cs) (revision 7) +++ src/Deltares.DSoilModel.Tests/DSoilModelProjectTest.cs (.../DSoilModelProjectTest.cs) (revision 87) @@ -20,7 +20,97 @@ [TestFixture] public class DSoilModelProjectTest { + private object geographicHelper; + + [TestFixtureSetUp] + public void FixtureSetup() + { + oldIsDataEventPublishStopped = DataEventPublisher.IsDataEventPublishStopped; + DataEventPublisher.IsDataEventPublishStopped = true; + + geographicHelper = GeographicHelper.Instance; + GeographicHelper.Instance = new DotSpatialGeographicHelper(); + } + + [TestFixtureTearDown] + public void FixtureTearDown() + { + DataEventPublisher.IsDataEventPublishStopped = oldIsDataEventPublishStopped; + GeographicHelper.Instance = geographicHelper as GeographicHelper; + } + [Test] + public void TestLinkCptsAndBoringsToNearestSoilSegment() + { + var project = (DSoilModelProject) DSoilModelIO.OpenSoilDatabase(@"..\..\..\data\TestData\SosDataPlusBorings.soil"); + var selection = new List(); + + // a combination of Cpts, Borings and Segments to link with are selected + selection.AddRange(project.SoilSegments.Where(x => x.Name.StartsWith("36009_"))); + selection.AddRange(project.SoilSegments.Where(x => x.Name.StartsWith("36010_"))); + + // none of the segments are linked + Assert.IsFalse(project.SoilSegments.Any(s => s.Cpts.Count > 0 || s.Borings.Count > 0)); + + // 36009_Piping & 36009_Stability & 36010_Piping & 36010_Stability + Assert.AreEqual(4, selection.Count); + + // CPT's along these segments + selection.Add(project.CPTs.First(x => x.Name == "S45E00003")); + selection.Add(project.CPTs.First(x => x.Name == "S39G00196")); + selection.Add(project.CPTs.First(x => x.Name == "S39G00042")); + selection.Add(project.CPTs.First(x => x.Name == "S45F00115")); + selection.Add(project.CPTs.First(x => x.Name == "S45F00080")); + selection.Add(project.CPTs.First(x => x.Name == "S45F00128")); + + // dummy borings, only 2 in this project + selection.AddRange(project.Borings); + + Assert.AreEqual(12, selection.Count); + + // call + project.LinkCptsAndBoringsToNearestSegment(selection.ToArray()); + + // assert (see the map in D-Soil Model for reference) + Assert.AreEqual(4, project.SoilSegments.Count(s => s.Cpts.Count > 0 || s.Borings.Count > 0)); + Assert.AreEqual(2, project.SoilSegments.Count(s => s.Borings.Count > 0)); + + // the 2 segments on the west side both get the same 3 Cpts, 2 Borings + var segment = project.SoilSegments.First(s => s.Name == "36009_Piping"); + Assert.AreEqual(3, segment.Cpts.Count); + Assert.AreEqual(2, segment.Borings.Count); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45E00003")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S39G00196")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S39G00042")); + Assert.IsTrue(segment.Borings.Any(b => b.Boring.Name == "TestBoring1")); + Assert.IsTrue(segment.Borings.Any(b => b.Boring.Name == "TestBoring2")); + + segment = project.SoilSegments.First(s => s.Name == "36009_Stability"); + Assert.AreEqual(3, segment.Cpts.Count); + Assert.AreEqual(2, segment.Borings.Count); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45E00003")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S39G00196")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S39G00042")); + Assert.IsTrue(segment.Borings.Any(b => b.Boring.Name == "TestBoring1")); + Assert.IsTrue(segment.Borings.Any(b => b.Boring.Name == "TestBoring2")); + + // the 2 segments on the east side both get the same 3 Cpts, no Borings + segment = project.SoilSegments.First(s => s.Name == "36010_Piping"); + Assert.AreEqual(3, segment.Cpts.Count); + Assert.AreEqual(0, segment.Borings.Count); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00115")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00080")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00128")); + + segment = project.SoilSegments.First(s => s.Name == "36010_Stability"); + Assert.AreEqual(3, segment.Cpts.Count); + Assert.AreEqual(0, segment.Borings.Count); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00115")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00080")); + Assert.IsTrue(segment.Cpts.Any(c => c.ConePenetrationTestData.Name == "S45F00128")); + } + + [Test] public void TestSplitSimpleSoilSegment() { var project = new DSoilModelProject(); @@ -589,19 +679,6 @@ private bool oldIsDataEventPublishStopped; - [TestFixtureSetUp] - public void FixtureSetup() - { - oldIsDataEventPublishStopped = DataEventPublisher.IsDataEventPublishStopped; - DataEventPublisher.IsDataEventPublishStopped = true; - } - - [TestFixtureTearDown] - public void FixtureTearDown() - { - DataEventPublisher.IsDataEventPublishStopped = oldIsDataEventPublishStopped; - } - private static Soil CreateTestSoil(bool defineStressTables = true) { Soil.Mechanisms = new[] Index: data/TestData/SosDataPlusBorings.soil =================================================================== diff -u Binary files differ