Index: src/Deltares.DSoilModel.Forms/Translations.xml
===================================================================
diff -u -r67 -r84
--- src/Deltares.DSoilModel.Forms/Translations.xml (.../Translations.xml) (revision 67)
+++ src/Deltares.DSoilModel.Forms/Translations.xml (.../Translations.xml) (revision 84)
@@ -72,13 +72,13 @@
-
+
+
-
Index: src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs
===================================================================
diff -u -r6 -r84
--- src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs (.../DSoilModelMapEditor.cs) (revision 6)
+++ src/Deltares.DSoilModel.Forms/DSoilModelMapEditor.cs (.../DSoilModelMapEditor.cs) (revision 84)
@@ -6,6 +6,7 @@
using Deltares.DSoilModel.Data;
using Deltares.DSoilModel.Forms.Properties;
using Deltares.Geographic;
+using Deltares.Geometry;
using Deltares.Geotechnics;
using Deltares.Geotechnics.ConePenetrationTest;
using Deltares.Standard;
@@ -18,6 +19,7 @@
using Deltares.Standard.Reflection;
using DevExpress.XtraBars;
using DotSpatial.Controls;
+using DotSpatial.Data;
using DotSpatial.Symbology;
using DotSpatial.Topology;
@@ -66,9 +68,7 @@
splitSegmentButton = CreateButton(Resources.SplitSegment);
BindSupport.Bind(panel, splitSegmentButton, me => me.SplitSegmentLocation());
- var splitSegmentMenuItem = new ToolStripMenuItem("Split Segment");
- mapEditor.ContextMenuStrip.Items.Add(splitSegmentMenuItem);
- BindSupport.Bind(panel, splitSegmentMenuItem, ge => ge.SplitSegment());
+ InitializeContextMenu();
BindSupport.Assign(panel, this);
@@ -77,6 +77,17 @@
DataEventPublisher.OnAfterChange += DataEventPublisher_OnAfterChange;
}
+ private void InitializeContextMenu()
+ {
+ var splitSegmentMenuItem = new ToolStripMenuItem("Split segment");
+ mapEditor.ContextMenuStrip.Items.Add(splitSegmentMenuItem);
+ BindSupport.Bind(panel, splitSegmentMenuItem, ge => ge.SplitSegment());
+
+ var assignToSegmentMenuItem = new ToolStripMenuItem("Link to nearest segment");
+ mapEditor.ContextMenuStrip.Items.Add(assignToSegmentMenuItem);
+ BindSupport.Bind(panel, assignToSegmentMenuItem, ge => ge.LinkToNearestSegment());
+ }
+
///
/// Gets or sets the project (setting: Adding Layers from Project to MapEditor).
///
@@ -169,20 +180,6 @@
}
}
- ///
- /// Complete split segment operation (after setting a split location)
- ///
- public void SplitSegment()
- {
- if (splittingSegments.Any() && segmentSplitters.Any()) {}
- {
- var splitter = segmentSplitters[0];
- double x = GeographicHelper.Instance.GetOffsetOnGeographicLineString(splitter, splitter.SoilSegment);
- ClearSegmentSplitter();
- project.SplitSoilSegment(splitter.SoilSegment, x);
- UndoRedoManager.Instance.EndAction();
- }
- }
///
/// Zoom out the map to display all data.
@@ -208,6 +205,18 @@
}
return false;
}
+ if (property == this.GetMemberName(x => x.LinkToNearestSegment()))
+ {
+ // segments present and at least one CPT or boring must be selected
+ if (project != null && project.SoilSegments.Count > 0 && mapEditor.SelectedObjects != null && mapEditor.SelectedObjects.Count > 0)
+ {
+ if (mapEditor.SelectedObjects.Any(o => o is ConePenetrationTestData || o is Boring))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
else
{
return true;
@@ -259,6 +268,132 @@
}
///
+ /// Complete split segment operation (after setting a split location)
+ ///
+ private void SplitSegment()
+ {
+ if (splittingSegments.Any() && segmentSplitters.Any())
+ {
+ var splitter = segmentSplitters[0];
+ double x = GeographicHelper.Instance.GetOffsetOnGeographicLineString(splitter, splitter.SoilSegment);
+ ClearSegmentSplitter();
+ project.SplitSoilSegment(splitter.SoilSegment, x);
+ UndoRedoManager.Instance.EndAction();
+ }
+ }
+
+ ///
+ /// Link all selected CPT's and or Borings to the nearest (selected) segment(s)
+ ///
+ 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);
+ }
+ }
+
+ 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) < Geometry.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
///
/// Selected object