// Copyright (C) Stichting Deltares 2017. All rights reserved. // // This file is part of the D-Soil Model application. // // The D-Soil Model application is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; using System.Xml.Serialization; using Deltares.DSoilModel.Data; using Deltares.DSoilModel.Forms.Properties; using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.ConePenetrationTest; using Deltares.Geotechnics.Forms; using Deltares.Geotechnics.GeotechnicalGeometry; using Deltares.Geotechnics.IO; using Deltares.Standard; using Deltares.Standard.Attributes; using Deltares.Standard.EventPublisher; using Deltares.Standard.Forms; using Deltares.Standard.Forms.DExpress; using Deltares.Standard.Language; using Deltares.Standard.Reflection; namespace Deltares.DSoilModel.Forms { /// /// The D-Soil Model Geometry Editor /// public class DSoilModelGeometryEditor : IVisibleEnabled, IDisposable { private readonly List boringLookup1Ds = new List(); private readonly List boringLookup2Ds = new List(); private readonly List cptLookup1Ds = new List(); private readonly List cptLookup2Ds = new List(); private readonly GeometryEditor geometryEditor; private readonly MainForm mainForm; private readonly Panel panel = new Panel(); private readonly List soilprofile1DLookup2Ds = new List(); private readonly SpatialEditor spatialEditor; private readonly List specificMechanismPointLocations = new List(); private CenterCrestLocation localCenterCrestLocation; private bool allowEdit = true; private DSoilModelProject project; private GeometryData selectedGeom; private bool updateForCenterCrestLocation; /// /// Initializes a new instance of the class. /// /// The main form to be able to set the caption of the geometry dock panel. public DSoilModelGeometryEditor(MainForm theMainForm) { mainForm = theMainForm; geometryEditor = theMainForm.GeometryEditor; spatialEditor = geometryEditor.SpatialEditor; // maybe this can move to the Geotechnics plugin later spatialEditor.RegisterShapeType(typeof(ConePenetrationTestData), typeof(DrawingCPT)); spatialEditor.RegisterShapeType(typeof(ConePenetrationTestLookup1D), typeof(DrawingCPT)); spatialEditor.RegisterShapeType(typeof(ConePenetrationTestLookup2D), typeof(DrawingCPT)); //spatialEditor.RegisterShapeType(typeof (Boring), typeof (DrawingBoring)); spatialEditor.RegisterShapeType(typeof(BoringLookup1D), typeof(DrawingBoring)); spatialEditor.RegisterShapeType(typeof(BoringLookup2D), typeof(DrawingBoring)); spatialEditor.RegisterShapeType(typeof(SoilProfile1DLookup2D), typeof(DrawingSoilProfile1D)); spatialEditor.RegisterShapeType(typeof(SpecificMechanismPointLocation), typeof(DrawingSpecificMechanismPointLocation)); spatialEditor.RegisterShapeType(typeof(CenterCrestLocation), typeof(DrawingCenterCrestLocation)); // next was setup by geotechnics plugin but editing should not be allowed spatialEditor.RegisterShapeType(typeof(CharacteristicPoint), typeof(DrawingCharacteristicPoint), null, null, null, false, true); //Next was commented out in Geotechnics plugin because RingToets doesn't need it anymore spatialEditor.RegisterShapeType(typeof(SurfaceLine2), typeof(DrawingSurfaceLine2)); //Next can not be moved to Geotechnics spatialEditor.RegisterShapeType(typeof(SosSoilLayer1D), typeof(DrawingSosSoilLayer1D)); // Make sure SoilLayer1D objects can not be selected so no improper property window will appear. // DSoilModel should only handle SOS-layers, not 1D-layers. But creating 1D-layers for a new project can not (yet) be prevented. var si = spatialEditor.GetShapeInfo(typeof(DrawingLayer)); si.AllowSelect = false; spatialEditor.RegisterShapeType(typeof(BoringLayer), typeof(DrawingBoringLayer)); spatialEditor.MarginBottom = 55; spatialEditor.ShapeRemoved += spatialEditor_ShapeRemoved; DataEventPublisher.OnSelectionChanged += DataEventPublisherOnSelectionChanged; DataEventPublisher.OnAfterChange += DataEventPublisherOnOnAfterChange; DataEventPublisher.OnDataListModified += DataEventPublisher_OnDataListModified; AddUiItems(); } /// /// Gets the spatial editor. /// /// /// The spatial editor. /// public SpatialEditor SpatialEditor { get { return spatialEditor; } } /// /// Gets or sets the project. /// public DSoilModelProject Project { get { return project; } set { if (value != project) { spatialEditor.Clear(); } project = value; } } /// /// Gets or sets a call back method to call when a cpt is added to the geometry editor. /// [XmlIgnore] [Browsable(false)] public Func AddCPTCallback { get; set; } /// /// Creates a Polyline. /// /// /// true if polyline is created; otherwise, false. /// [Label("Create polyline")] public bool CreatePolyline { get { return geometryEditor.SpatialEditor.InsertType != null && geometryEditor.SpatialEditor.InsertType.Equals(BasicGeometryType.GeometryCurve); } set { if (value && selectedGeom != null) { geometryEditor.SpatialEditor.InsertMode = ShapeInsertMode.PolyLine; geometryEditor.SpatialEditor.InsertRepeatMode = ShapeInsertRepeatMode.Connect; geometryEditor.SpatialEditor.InsertIncrease = false; geometryEditor.SpatialEditor.InsertType = BasicGeometryType.GeometryCurve; geometryEditor.SetInsertMode(false); geometryEditor.InsertShapeMethod = selectedGeom.CreateGeometryObject; geometryEditor.StatusString = LocalizationManager.GetTranslatedText(this, "AddGeometryPolylines"); } } } /// /// Creates a point in the line. /// /// /// true if create point in line; otherwise, false. /// [Label("Create point in line")] public bool CreatePointInLine { get { return geometryEditor.SpatialEditor.InsertType != null && geometryEditor.SpatialEditor.InsertType.Equals(BasicGeometryType.GeometryPoint); } set { if (value && selectedGeom != null) { geometryEditor.SpatialEditor.InsertMode = ShapeInsertMode.Point; geometryEditor.SpatialEditor.InsertRepeatMode = ShapeInsertRepeatMode.Repeat; geometryEditor.SpatialEditor.InsertIncrease = false; geometryEditor.SpatialEditor.InsertType = BasicGeometryType.GeometryPoint; geometryEditor.SetInsertMode(false); geometryEditor.InsertShapeMethod = selectedGeom.CreateGeometryObject; geometryEditor.StatusString = LocalizationManager.GetTranslatedText(this, "AddGeometryPointInCurve"); } } } /// /// Gets or sets the is visible callback. /// /// /// The is visible callback. /// [XmlIgnore] [Browsable(false)] public Func IsVisibleCallback { get; set; } /// /// Gets or sets a value indicating whether [allow edit]. /// /// /// true if [allow edit]; otherwise, false. /// public bool AllowEdit { get { return allowEdit; } set { allowEdit = value; } } /// /// Allow the plugin to show the currently selected soil segment which possibly has a stochastic soil /// model. This stochastic soil model can have a possibly currently selected stochastic soil profile. /// If the currently selected stochastic soil profile is undefined, the first profile is selected. /// /// The segment to show, possibly with a stochastic soil model. /// The possible selected soil segment to show. public void ShowSoilSegment(SoilSegment selectedSegment, StochasticSoilProfile selectedSoilProfile) { if (selectedSegment == null) { return; } if (selectedSoilProfile == null) { // Clear also resets Caption, so do that first. Clear(); SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSegment"), selectedSegment.Name)); return; } // Draw the Stochastic Soil Profile and set the appropriate caption var profile1D = selectedSoilProfile.Profile as SoilProfile1D; if (profile1D != null) { ShowSoilProfile1D(profile1D, null); SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSoilProfile1D"), selectedSoilProfile)); } else { var profile2D = selectedSoilProfile.Profile as SoilProfile2D; if (profile2D != null) { ShowSoilProfile2D(profile2D); SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSoilProfile2D"), selectedSoilProfile)); } } } /// /// Inserts mechanism point location. /// [Label("Insert mechanism location")] public void InsertSpecificMechanismPointLocation() { if (project != null) { AddSpecificMechanismPointLocation(); } } /// /// Adds the center crest location to 2d profile. /// public void AddCenterCrestLocationTo2DProfile() { if (project != null) { updateForCenterCrestLocation = true; AddCenterCrestLocation(); } } /// /// Adds the surface line to the existing 2D to create new 2D profile. /// public void AddSurfaceLineToCreateNew2DProfile() { var currentProfile2D = (spatialEditor.EmptySelection.DataObject as SoilProfile2D); // Create a 2D profile from current 2D and selected surfaceline if (project != null) { string item = HandleModalListSelection(project.SurfaceLines.Where(p => p.HasDike()).OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectSurfaceLine"); if (item != null) { SurfaceLine2 surfaceLine2 = project.SurfaceLines.First(p => p.Name == item); CreateNew2DProfileFromSoilProfile2DAndSurfaceLine2(currentProfile2D, surfaceLine2); } } } public void Dispose() { spatialEditor.ShapeRemoved -= spatialEditor_ShapeRemoved; DataEventPublisher.OnDataListModified -= DataEventPublisher_OnDataListModified; DataEventPublisher.OnAfterChange -= DataEventPublisherOnOnAfterChange; DataEventPublisher.OnSelectionChanged -= DataEventPublisherOnSelectionChanged; } public bool IsVisible(string property) { if (IsVisibleCallback != null) { return IsVisibleCallback(property); } bool dataObjectEmptySelectionIsSoilProfile = spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile; bool dataObjectEmptySelectionIsSoilProfile2D = spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile2D; bool dataObjectEmptySelectionIsFilledSoilProfile1D = spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile1D && (spatialEditor.EmptySelection.DataObject as SoilProfile1D).LayerCount > 0; bool dataObjectEmptySelectionIsFilledSurfaceLine2 = spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SurfaceLine2 && (spatialEditor.EmptySelection.DataObject as SurfaceLine2).CharacteristicPoints.Count > 1; bool projectHasSurfaceLinesWithDikes = project != null && project.SurfaceLines != null && project.SurfaceLines.Count > 0 && project.SurfaceLines.Count(p => p.HasDike()) > 0; bool isCenterCrestDefined = dataObjectEmptySelectionIsSoilProfile2D && !double.IsNaN(((SoilProfile2D) spatialEditor.EmptySelection.DataObject).CenterCrestLocation); switch (property) { case "CreatePointInLine": return allowEdit && selectedGeom != null && selectedGeom.Curves.Count > 0; case "CreatePolyline": return allowEdit && selectedGeom != null; case "DeleteLooseLines": return dataObjectEmptySelectionIsSoilProfile2D && selectedGeom != null && selectedGeom.GetLooseCurves().Count > 0; case "InsertCpt": return dataObjectEmptySelectionIsSoilProfile && project.CPTs.Count > 0; case "InsertBoring": return dataObjectEmptySelectionIsSoilProfile && project.Borings.Count > 0; case "InsertSoilProfile1D": return dataObjectEmptySelectionIsSoilProfile2D && project.SoilProfiles1D.Count > 0; case "InsertSpecificMechanismPointLocation": return dataObjectEmptySelectionIsSoilProfile2D; case "AddCenterCrestLocationTo2DProfile": return dataObjectEmptySelectionIsSoilProfile2D && !isCenterCrestDefined; case "AddSurfaceLineToCreateNew2DProfile": return dataObjectEmptySelectionIsSoilProfile2D && projectHasSurfaceLinesWithDikes && isCenterCrestDefined; case "AddSurfaceLineToCreate2DProfile": return dataObjectEmptySelectionIsFilledSoilProfile1D && project.SurfaceLines.Count > 0; case "Add1DProfileToCreate2DProfile": return dataObjectEmptySelectionIsFilledSurfaceLine2 && project.SoilProfiles1D.Count > 0; case "ExecuteClearSoilProfile1DCommand": return spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile1D; case "ExecuteClearSoilProfile2DCommand": return spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile2D; default: return true; } } public bool IsEnabled(string property) { switch (property) { default: return true; } } /// /// Deletes the loose lines. /// private void DeleteLooseLines() { if (selectedGeom != null) { selectedGeom.DeleteLooseCurves(); selectedGeom.DeleteLoosePoints(); } } /// /// Select and inserts a CPT. /// [Label("Insert CPT")] private void InsertCpt() { if (project != null) { string item = HandleModalListSelection(project.CPTs.OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectCPT"); if (item != null) { ConePenetrationTestData conePenetrationTestData = project.CPTs.First(p => p.Name == item); AddCPT(conePenetrationTestData); } } } /// /// Select and insert a boring. /// [Label("Insert Boring")] private void InsertBoring() { if (project != null) { string item = HandleModalListSelection(project.Borings.OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectBoring"); if (item != null) { Boring boring = project.Borings.First(p => p.Name == item); AddBoring(boring); } } } /// /// Select and insert a SoilProfile1D. /// [Label("Insert 1D Soil profile")] private void InsertSoilProfile1D() { if (project != null) { string item = HandleModalListSelection(project.SoilProfiles1D.OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectProfile1D"); if (item != null) { SoilProfile1D profile1D = project.SoilProfiles1D.First(p => p.Name == item); AddSoilProfile1D(profile1D); } } } private void DataEventPublisherOnSelectionChanged(object sender, PublishEventArgs e) { selectedGeom = null; object selectedObj = (spatialEditor.EmptySelection == null) ? null : spatialEditor.EmptySelection.DataObject; if (sender is SoilProfile1D) { ShowSoilProfile1D(sender, selectedObj); } else if (sender is SoilProfile2D) { ShowSoilProfile2D(sender); } else if (sender is SpecificMechanismPointLocation) { ShowSoilProfile2D(((SpecificMechanismPointLocation)sender).SoilProfile2D); } else if (sender is CenterCrestLocation) { ShowSoilProfile2D(((CenterCrestLocation)sender).SoilProfile2D); } else if (sender is ConePenetrationTestData) { ShowCpt(sender, selectedObj); } else if (sender is Boring) { ShowBoring(sender, selectedObj); } else if (sender is SurfaceLine2) { ShowSurfaceLine(sender, selectedObj); } else { return; } DataEventPublisher.AfterChange(this); } private void DataEventPublisherOnOnAfterChange(object sender, PublishEventArgs publishEventArgs) { var ccl = sender as CenterCrestLocation; if (ccl != null) { if (Math.Abs(ccl.SoilProfile2D.CenterCrestLocation - ccl.Location) > GeometryConstants.Accuracy && !(double.IsNaN(ccl.SoilProfile2D.CenterCrestLocation) && double.IsNaN(ccl.Location))) { ccl.SoilProfile2D.CenterCrestLocation = ccl.Location; }; } var soilProfile2D = sender as SoilProfile2D; if (soilProfile2D != null) { if (publishEventArgs.Property == soilProfile2D.GetMemberName(x => x.CenterCrestLocation)) { if (localCenterCrestLocation == null && !double.IsNaN(soilProfile2D.CenterCrestLocation)) { localCenterCrestLocation = new CenterCrestLocation { SoilProfile2D = soilProfile2D }; } if (localCenterCrestLocation != null && Object.ReferenceEquals(localCenterCrestLocation.SoilProfile2D, soilProfile2D) && (Math.Abs(localCenterCrestLocation.Location - soilProfile2D.CenterCrestLocation) > GeometryConstants.Accuracy || double.IsNaN(localCenterCrestLocation.Location) || double.IsNaN(soilProfile2D.CenterCrestLocation))) { localCenterCrestLocation.Location = soilProfile2D.CenterCrestLocation; updateForCenterCrestLocation = true; DataEventPublisherOnSelectionChanged(localCenterCrestLocation, null); } } } if (ReferenceEquals(sender, spatialEditor) && publishEventArgs.Property == spatialEditor.GetMemberName(x => x.InsertType)) { DataEventPublisher.AfterChange(this); } } private void DataEventPublisher_OnDataListModified(object sender, PublishEventArgs e) { // Note: CPT's are already cleaned so they are not in the list below! if (project != null && (sender == Project.Borings || sender == Project.SoilProfiles1D || sender == Project.SoilProfiles2D || sender == Project.SurfaceLines || sender == Project.CurrentSoilSegments)) { if (spatialEditor.EmptySelection != null) { var spatiadEditorSelectedObject = spatialEditor.EmptySelection.DataObject; if (spatiadEditorSelectedObject != null) { // check whether the current displayed object has been removed if (!(sender as IList).Contains(spatiadEditorSelectedObject)) { spatialEditor.Clear(); spatialEditor.Refresh(); } } } } } private void AddUiItems() { // Add buttons to be able to manipulate the geometry of SoilProfiles2D, insert CPT's and Borings and Piping Location BindSupport.Bind(panel, geometryEditor.CreateButton(Resources.CreatePolyline), typeof(DSoilModelGeometryEditor), "CreatePolyline"); BindSupport.Bind(panel, geometryEditor.CreateButton(Resources.CreatePointInLine), typeof(DSoilModelGeometryEditor), "CreatePointInLine"); // Add popup context menu for adding items to a 2D Soilprofile view var deleteLooseLinesMenuItem = new ToolStripMenuItem("Delete Loose Lines"); var insertCptMenuItem = new ToolStripMenuItem("Insert CPT"); var insertBoringMenuItem = new ToolStripMenuItem("Insert Boring"); var insertSoilProfile1DMenuItem = new ToolStripMenuItem("Insert 1D soil profile"); var insertSpecificMechanismPointLocationMenuItem = new ToolStripMenuItem("Insert mechanism location"); var addCenterCrestLocationTo2DProfileMenuItem = new ToolStripMenuItem("Add center of crest"); var addSurfaceLineToCreateNew2DProfileMenuItem = new ToolStripMenuItem("Add surfaceLine to create new 2D profile"); var addSurfaceLineToCreate2DProfileMenuItem = new ToolStripMenuItem("Add surfaceLine to create 2D profile"); var add1DProfileToCreate2DProfileMenuItem = new ToolStripMenuItem("Add 1D profile to create 2D profile"); var clearSoilProfile1DMenuItem = new ToolStripMenuItem(); var clearSoilProfile2DMenuItem = new ToolStripMenuItem(); spatialEditor.ContextMenuStrip.Items.Add(deleteLooseLinesMenuItem); spatialEditor.ContextMenuStrip.Items.Add(insertCptMenuItem); spatialEditor.ContextMenuStrip.Items.Add(insertBoringMenuItem); spatialEditor.ContextMenuStrip.Items.Add(insertSoilProfile1DMenuItem); spatialEditor.ContextMenuStrip.Items.Add(insertSpecificMechanismPointLocationMenuItem); spatialEditor.ContextMenuStrip.Items.Add(addCenterCrestLocationTo2DProfileMenuItem); spatialEditor.ContextMenuStrip.Items.Add(addSurfaceLineToCreateNew2DProfileMenuItem); spatialEditor.ContextMenuStrip.Items.Add(addSurfaceLineToCreate2DProfileMenuItem); spatialEditor.ContextMenuStrip.Items.Add(add1DProfileToCreate2DProfileMenuItem); spatialEditor.ContextMenuStrip.Items.Add(clearSoilProfile1DMenuItem); spatialEditor.ContextMenuStrip.Items.Add(clearSoilProfile2DMenuItem); BindSupport.Bind(panel, deleteLooseLinesMenuItem, ge => ge.DeleteLooseLines()); BindSupport.Bind(panel, insertCptMenuItem, ge => ge.InsertCpt()); BindSupport.Bind(panel, insertBoringMenuItem, ge => ge.InsertBoring()); BindSupport.Bind(panel, insertSoilProfile1DMenuItem, ge => ge.InsertSoilProfile1D()); BindSupport.Bind(panel, insertSpecificMechanismPointLocationMenuItem, ge => ge.InsertSpecificMechanismPointLocation()); BindSupport.Bind(panel, addCenterCrestLocationTo2DProfileMenuItem, ge => ge.AddCenterCrestLocationTo2DProfile()); BindSupport.Bind(panel, addSurfaceLineToCreateNew2DProfileMenuItem, ge => ge.AddSurfaceLineToCreateNew2DProfile()); BindSupport.Bind(panel, addSurfaceLineToCreate2DProfileMenuItem, ge => ge.AddSurfaceLineToCreate2DProfile()); BindSupport.Bind(panel, add1DProfileToCreate2DProfileMenuItem, ge => ge.Add1DProfileToCreate2DProfile()); BindSupport.Bind(panel, clearSoilProfile1DMenuItem, ge => ge.ExecuteClearSoilProfile1DCommand()); BindSupport.Bind(panel, clearSoilProfile2DMenuItem, ge => ge.ExecuteClearSoilProfile2DCommand()); BindSupport.Assign(panel, this); } private bool AskUserWantsToClearSoilProfile1D() { var msg = LocalizationManager.GetTranslatedText(this, "ExecuteClearSoilProfile1DCommandUserConfirm"); var caption = LocalizationManager.GetTranslatedText(this, "ExecuteClearSoilProfile1DCommand"); return MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes; } private bool AskUserWantsToClearSoilProfile2D() { var msg = LocalizationManager.GetTranslatedText(this, "ExecuteClearSoilProfile2DCommandUserConfirm"); var caption = LocalizationManager.GetTranslatedText(this, "ExecuteClearSoilProfile2DCommand"); return MessageBox.Show(msg, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes; } private void ExecuteClearSoilProfile1DCommand() { if (!AskUserWantsToClearSoilProfile1D()) { return; } UndoRedoManager.Instance.BeginAction(); var profile = spatialEditor.EmptySelection.DataObject as SoilProfile1D; ClearGeometryForSoilProfile1D(profile); UndoRedoManager.Instance.EndAction(); DataEventPublisher.DataListModified(profile.Layers); // in order to trigger refresh we select the 1st dummy object and then we reselect the "cleared" one DataEventPublisher.SelectionChanged(new SoilProfile1D()); DataEventPublisher.SelectionChanged(profile); } public void ClearGeometryForSoilProfile1D(SoilProfile1D profile) { foreach (var lookup in Project.BoringLookup1Ds.Where(b => b.SoilProfile1D == profile).ToList()) { Project.BoringLookup1Ds.Remove(lookup); boringLookup1Ds.Remove(lookup); } foreach (var lookup in Project.CptLookup1Ds.Where(p => p.SoilProfile1D == profile).ToList()) { Project.CptLookup1Ds.Remove(lookup); cptLookup1Ds.Remove(lookup); } profile.Layers.Clear(); } private void ExecuteClearSoilProfile2DCommand() { if (!AskUserWantsToClearSoilProfile2D()) { return; } UndoRedoManager.Instance.BeginAction(); var profile = spatialEditor.EmptySelection.DataObject as SoilProfile2D; ClearGeometryForSoilProfile2D(profile); UndoRedoManager.Instance.EndAction(); // publish the changes to the current profile to clear belonging property editors. DataEventPublisher.DataListModified(profile.Geometry.Points); DataEventPublisher.DataListModified(profile.Geometry.Curves); DataEventPublisher.DataListModified(profile.Surfaces); DataEventPublisher.DataListModified(profile.PreconsolidationStresses); // In order to trigger refresh of the picture (to get rid of lookups in picture) first select a dummy object and // then reselect the "cleared" one. DataEventPublisher.SelectionChanged(new SoilProfile2D()); DataEventPublisher.SelectionChanged(profile); } public void ClearGeometryForSoilProfile2D(SoilProfile2D profile) { foreach (var lookup in Project.BoringLookup2Ds.Where(b => b.SoilProfile2D == profile).ToList()) { Project.BoringLookup2Ds.Remove(lookup); boringLookup2Ds.Remove(lookup); } foreach (var lookup in Project.CptLookup2Ds.Where(p => p.SoilProfile2D == profile).ToList()) { Project.CptLookup2Ds.Remove(lookup); cptLookup2Ds.Remove(lookup); } foreach (var location in Project.SpecificMechanismPointLocations.Where(l => l.SoilProfile2D == profile).ToList()) { Project.SpecificMechanismPointLocations.Remove(location); specificMechanismPointLocations.Remove(location); } foreach (var lookup in Project.Soilprofile1DLookup2Ds.Where(c => c.SoilProfile2D == profile).ToList()) { Project.Soilprofile1DLookup2Ds.Remove(lookup); soilprofile1DLookup2Ds.Remove(lookup); } profile.CenterCrestLocation = double.NaN; profile.Geometry.Clear(); profile.PreconsolidationStresses.Clear(); profile.Surfaces.Clear(); localCenterCrestLocation = null; } private void spatialEditor_ShapeRemoved(object sender, ShapeEventArgs e) { // if a CPT/Boring/Soilprofile Lookup is deleted, remove it from the project object dataObject = e.Shape.DataObject; if (dataObject is ConePenetrationTestLookup1D) { project.CptLookup1Ds.Remove((ConePenetrationTestLookup1D)dataObject); } if (dataObject is ConePenetrationTestLookup2D) { project.CptLookup2Ds.Remove((ConePenetrationTestLookup2D)dataObject); } if (dataObject is BoringLookup1D) { project.BoringLookup1Ds.Remove((BoringLookup1D)dataObject); } if (dataObject is BoringLookup2D) { project.BoringLookup2Ds.Remove((BoringLookup2D)dataObject); } if (dataObject is SoilProfile1DLookup2D) { project.Soilprofile1DLookup2Ds.Remove((SoilProfile1DLookup2D)dataObject); } if (dataObject is SpecificMechanismPointLocation) { project.SpecificMechanismPointLocations.Remove((SpecificMechanismPointLocation)dataObject); } if (dataObject is CenterCrestLocation) { ((CenterCrestLocation) dataObject).SoilProfile2D.CenterCrestLocation = double.NaN; localCenterCrestLocation = null; } var surfaceLine2 = dataObject as SurfaceLine2; if (null != surfaceLine2) { project.SurfaceLines.Remove(surfaceLine2); surfaceLine2.Dispose(); } } private void ShowCpt(object sender, object selectedObj) { var cpt = (ConePenetrationTestData)sender; if (spatialEditor.EmptySelection == null || spatialEditor.EmptySelection.DataObject == null || !(spatialEditor.EmptySelection.DataObject is ConePenetrationTestData) || (spatialEditor.EmptySelection.DataObject as ConePenetrationTestData).Name != cpt.Name) { Clear(); AddCPT(cpt); spatialEditor.EmptySelection = new EmptyShape(sender); spatialEditor.Refresh(); if (selectedObj == null || selectedObj is SoilProfile2D) { spatialEditor.ZoomToExtents(true); } else { UpdateExtents(true); } } // Always reset caption SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowCpt"), cpt.Name)); } private void ShowBoring(object sender, object selectedObj) { var boring = (Boring)sender; if (spatialEditor.EmptySelection == null || spatialEditor.EmptySelection.DataObject == null || !(spatialEditor.EmptySelection.DataObject is Boring) || (spatialEditor.EmptySelection.DataObject as Boring).Name != boring.Name) { Clear(); AddBoring(boring); spatialEditor.EmptySelection = new EmptyShape(sender); spatialEditor.Refresh(); Boring selectedBoring = null; if (selectedObj is Boring) { selectedBoring = (Boring)selectedObj; } if (selectedObj == null || selectedBoring == null || (boring.Name != selectedBoring.Name)) { spatialEditor.ZoomToExtents(true); } else { UpdateExtents(true); } } SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowBoring"), boring.Name)); } private void ShowSurfaceLine(object sender, object selectedObj) { var surfaceLine = (SurfaceLine2)sender; if (spatialEditor.EmptySelection == null || spatialEditor.EmptySelection.DataObject == null || !(spatialEditor.EmptySelection.DataObject is SurfaceLine2) || (spatialEditor.EmptySelection.DataObject as SurfaceLine2).Name != surfaceLine.Name) { Clear(); AddSurfaceLine(surfaceLine); spatialEditor.EmptySelection = new EmptyShape(sender); spatialEditor.Refresh(); UpdateExtents(true); } SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSurfaceLine"), surfaceLine.Name)); } private void ShowSoilProfile1D(object sender, object selectedObj) { var soilProfile1D = (SoilProfile1D)sender; if (spatialEditor.EmptySelection == null || spatialEditor.EmptySelection.DataObject == null || !(spatialEditor.EmptySelection.DataObject is SoilProfile1D) || (spatialEditor.EmptySelection.DataObject as SoilProfile1D).Name != soilProfile1D.Name) { Clear(); AddSoilProfile1D(soilProfile1D); spatialEditor.EmptySelection = new EmptyShape(sender); spatialEditor.Refresh(); if (selectedObj == null || selectedObj is SoilProfile2D) { spatialEditor.ZoomToExtents(true); } else { UpdateExtents(true); } } SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSoilProfile1D"), soilProfile1D.Name)); } private void ShowSoilProfile2D(object sender) { var soilProfile2D = (SoilProfile2D)sender; selectedGeom = soilProfile2D.Geometry; geometryEditor.DeleteShapeMethod = selectedGeom.DeleteGeometryObjects; if (spatialEditor.EmptySelection == null || spatialEditor.EmptySelection.DataObject == null || !(spatialEditor.EmptySelection.DataObject is SoilProfile2D) || (spatialEditor.EmptySelection.DataObject as SoilProfile2D).Name != soilProfile2D.Name || updateForCenterCrestLocation) { updateForCenterCrestLocation = false; if (soilProfile2D.Geometry.Points.Count == 0 && Math.Abs(soilProfile2D.Geometry.Bottom - Double.MaxValue) < GeometryConstants.Accuracy) { soilProfile2D.Geometry.Left = GeometryConstants.DefaultLeftLimitGeometry; soilProfile2D.Geometry.Right = GeometryConstants.DefaultRightLimitGeometry; soilProfile2D.Geometry.Bottom = GeometryConstants.DefaultBottomLimitGeometry; } Clear(); AddSoilProfile2D(soilProfile2D); spatialEditor.EmptySelection = new EmptyShape(sender); spatialEditor.Refresh(); spatialEditor.ZoomToExtents(false); } SetCaption(string.Format(LocalizationManager.GetTranslatedText(this, "ShowSoilProfile2D"), soilProfile2D.Name)); } private void AddSoilProfile1D(SoilProfile1D soilProfile) { if (spatialEditor.EmptySelection == null) { spatialEditor.AddObject(soilProfile); spatialEditor.AddList(soilProfile.Layers); // reconnect CPT and Boring lookups ? foreach (var lookup in project.CptLookup1Ds.Where(p => p.SoilProfile1D == soilProfile)) { cptLookup1Ds.Add(lookup); } foreach (var boring in project.BoringLookup1Ds.Where(p => p.SoilProfile1D == soilProfile)) { boringLookup1Ds.Add(boring); } spatialEditor.AddList(cptLookup1Ds); spatialEditor.AddList(boringLookup1Ds); } else if (spatialEditor.EmptySelection.DataObject is SoilProfile2D) { var soilProfile2D = spatialEditor.EmptySelection.DataObject as SoilProfile2D; var lookup = new SoilProfile1DLookup2D { SoilProfile1D = soilProfile, SoilProfile2D = soilProfile2D, Xlocal = (soilProfile2D.Geometry.Right - soilProfile2D.Geometry.Left) * 0.5 }; UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(soilprofile1DLookup2Ds); DataEventPublisher.BeforeChange(project.Soilprofile1DLookup2Ds); soilprofile1DLookup2Ds.Add(lookup); project.Soilprofile1DLookup2Ds.Add(lookup); DataEventPublisher.DataListModified(soilprofile1DLookup2Ds); DataEventPublisher.DataListModified(project.Soilprofile1DLookup2Ds); UndoRedoManager.Instance.EndAction(); spatialEditor.ZoomToExtents(spatialEditor.CurrentMaintainAspectRatio); } } private void AddSoilProfile2D(SoilProfile2D soilProfile) { spatialEditor.AddObject(soilProfile); spatialEditor.AddObject(soilProfile.Geometry); spatialEditor.AddList(soilProfile.Surfaces); spatialEditor.AddList(soilProfile.Geometry.Curves); spatialEditor.AddList(soilProfile.Geometry.Points); if (soilProfile.PreconsolidationStresses != null) { spatialEditor.AddList(soilProfile.PreconsolidationStresses); } // reconnect CPT and Boring lookups ? foreach (var lookup in project.CptLookup2Ds.Where(p => p.SoilProfile2D == soilProfile)) { cptLookup2Ds.Add(lookup); } foreach (var boring in project.BoringLookup2Ds.Where(p => p.SoilProfile2D == soilProfile)) { boringLookup2Ds.Add(boring); } // reconnect linked 1D profiles ? foreach (var lookup in project.Soilprofile1DLookup2Ds.Where(l => l.SoilProfile2D == soilProfile)) { soilprofile1DLookup2Ds.Add(lookup); } // reconnect specific SpecificMechanismPointLocation definitions ? foreach (var location in project.SpecificMechanismPointLocations.Where(l => l.SoilProfile2D == soilProfile)) { specificMechanismPointLocations.Add(location); } // set the proper localCenterCrestLocation if (!double.IsNaN(soilProfile.CenterCrestLocation)) { var selectedCenterCrestLocation = spatialEditor.GetSelectedShapes().ToArray().FirstOrDefault(s => s.DataObject is CenterCrestLocation); if (selectedCenterCrestLocation != null) { localCenterCrestLocation = (CenterCrestLocation)selectedCenterCrestLocation.DataObject; } else { localCenterCrestLocation = new CenterCrestLocation { SoilProfile2D = soilProfile, Location = soilProfile.CenterCrestLocation }; } } spatialEditor.AddObject(localCenterCrestLocation); spatialEditor.AddList(cptLookup2Ds); spatialEditor.AddList(boringLookup2Ds); spatialEditor.AddList(soilprofile1DLookup2Ds); spatialEditor.AddList(specificMechanismPointLocations); selectedGeom = soilProfile.Geometry; } private void AddCPT(ConePenetrationTestData conePenetrationTestData) { if (spatialEditor.EmptySelection == null) { spatialEditor.AddObject(conePenetrationTestData); } else if (AddCPTCallback != null) { AddCPTCallback(conePenetrationTestData); } else if (spatialEditor.EmptySelection.DataObject is SoilProfile2D) { var soilProfile2D = spatialEditor.EmptySelection.DataObject as SoilProfile2D; var lookup = new ConePenetrationTestLookup2D { ConePenetrationTestData = conePenetrationTestData, SoilProfile2D = soilProfile2D, Xlocal = (soilProfile2D.Geometry.Right - soilProfile2D.Geometry.Left) * 0.5, Zlocal = 0.0d, }; DataEventPublisher.BeforeChange(cptLookup2Ds); DataEventPublisher.BeforeChange(project.CptLookup2Ds); cptLookup2Ds.Add(lookup); project.CptLookup2Ds.Add(lookup); DataEventPublisher.DataListModified(cptLookup2Ds); DataEventPublisher.DataListModified(project.CptLookup2Ds); spatialEditor.ZoomToExtents(spatialEditor.CurrentMaintainAspectRatio); } else if (spatialEditor.EmptySelection.DataObject is SoilProfile1D) { var lookup = new ConePenetrationTestLookup1D { ConePenetrationTestData = conePenetrationTestData, SoilProfile1D = spatialEditor.EmptySelection.DataObject as SoilProfile1D, }; DataEventPublisher.BeforeChange(cptLookup1Ds); DataEventPublisher.BeforeChange(project.CptLookup1Ds); cptLookup1Ds.Add(lookup); project.CptLookup1Ds.Add(lookup); DataEventPublisher.DataListModified(cptLookup1Ds); DataEventPublisher.DataListModified(project.CptLookup1Ds); } } private void AddBoring(Boring boring) { if (spatialEditor.EmptySelection == null) { spatialEditor.AddObject(boring); spatialEditor.AddList(boring.BoringLayers); } else if (spatialEditor.EmptySelection.DataObject is SoilProfile2D) { var soilProfile2D = spatialEditor.EmptySelection.DataObject as SoilProfile2D; var lookup = new BoringLookup2D { Boring = boring, SoilProfile2D = soilProfile2D, Xlocal = (soilProfile2D.Geometry.Right - soilProfile2D.Geometry.Left) * 0.5, Zlocal = 0.0d }; UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(boringLookup2Ds); DataEventPublisher.BeforeChange(project.BoringLookup2Ds); boringLookup2Ds.Add(lookup); project.BoringLookup2Ds.Add(lookup); DataEventPublisher.DataListModified(boringLookup2Ds); DataEventPublisher.DataListModified(project.BoringLookup2Ds); UndoRedoManager.Instance.EndAction(); spatialEditor.ZoomToExtents(spatialEditor.CurrentMaintainAspectRatio); } else if (spatialEditor.EmptySelection.DataObject is SoilProfile1D) { var lookup = new BoringLookup1D { Boring = boring, SoilProfile1D = spatialEditor.EmptySelection.DataObject as SoilProfile1D, }; UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(boringLookup1Ds); DataEventPublisher.BeforeChange(project.BoringLookup1Ds); boringLookup1Ds.Add(lookup); project.BoringLookup1Ds.Add(lookup); DataEventPublisher.DataListModified(boringLookup1Ds); DataEventPublisher.DataListModified(project.BoringLookup1Ds); UndoRedoManager.Instance.EndAction(); } } private void AddSurfaceLine(SurfaceLine2 surfaceLine) { if (spatialEditor.EmptySelection == null) { spatialEditor.AddObject(surfaceLine); } List characteristicPoints = surfaceLine.CharacteristicPoints.Where( characteristicPoint => characteristicPoint.CharacteristicPointType != CharacteristicPointType.None).ToList(); spatialEditor.AddList(characteristicPoints); } private void AddSpecificMechanismPointLocation() { if (spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile2D) { var soilProfile2D = spatialEditor.EmptySelection.DataObject as SoilProfile2D; var lookup = new SpecificMechanismPointLocation { SoilProfile2D = soilProfile2D, XCoordinate = (soilProfile2D.Geometry.Right - soilProfile2D.Geometry.Left) * 0.5 }; UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(specificMechanismPointLocations); DataEventPublisher.BeforeChange(project.SpecificMechanismPointLocations); specificMechanismPointLocations.Add(lookup); project.SpecificMechanismPointLocations.Add(lookup); DataEventPublisher.DataListModified(specificMechanismPointLocations); DataEventPublisher.DataListModified(project.SpecificMechanismPointLocations); DataEventPublisher.SelectionChanged(lookup); UndoRedoManager.Instance.EndAction(); } } private void AddCenterCrestLocation() { if (spatialEditor.EmptySelection != null && spatialEditor.EmptySelection.DataObject is SoilProfile2D) { var soilProfile2D = spatialEditor.EmptySelection.DataObject as SoilProfile2D; if (localCenterCrestLocation == null) { localCenterCrestLocation = new CenterCrestLocation(); } UndoRedoManager.Instance.BeginAction(); DataEventPublisher.BeforeChange(soilProfile2D); DataEventPublisher.BeforeChange(project.SoilProfiles2D); DataEventPublisher.InvokeWithoutPublishingEvents(() => { soilProfile2D.CenterCrestLocation = (soilProfile2D.Geometry.Right - soilProfile2D.Geometry.Left) * 0.5; localCenterCrestLocation.SoilProfile2D = soilProfile2D; localCenterCrestLocation.Location = soilProfile2D.CenterCrestLocation; }); DataEventPublisher.DataListModified(project.SoilProfiles2D); DataEventPublisher.SelectionChanged(localCenterCrestLocation); UndoRedoManager.Instance.EndAction(); } } private void UpdateExtents(bool maintainAspectRatio) { Projection cs = spatialEditor.CoordinateSystem; Rectangle bounds = spatialEditor.Bounds; foreach (var shape in spatialEditor.Shapes) { Rectangle? extents = shape.GetExtents(cs); if (extents != null) { if (!bounds.Contains(extents.Value)) { spatialEditor.ZoomToExtents(maintainAspectRatio); return; } } } spatialEditor.CenterExtents(); } private void SetCaption(string caption) { mainForm.GeometryDockPanel.Text = caption; } /// /// Clears up content. /// public void Clear() { geometryEditor.Clear(); cptLookup1Ds.Clear(); cptLookup2Ds.Clear(); boringLookup1Ds.Clear(); boringLookup2Ds.Clear(); soilprofile1DLookup2Ds.Clear(); specificMechanismPointLocations.Clear(); localCenterCrestLocation = null; SetCaption(LocalizationManager.GetTranslatedText(this, "Geometry")); } private void AddSurfaceLineToCreate2DProfile() { var currentProfile1D = (spatialEditor.EmptySelection.DataObject as SoilProfile1D); // Create a 2D profile from current 1D and selected surfaceline if (project != null) { string item = HandleModalListSelection(project.SurfaceLines.OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectSurfaceLine"); if (item != null) { SurfaceLine2 surfaceLine2 = project.SurfaceLines.First(p => p.Name == item); Create2DProfileFromSoilProfile1DAndSurfaceLine2(currentProfile1D, surfaceLine2); } } } private void Add1DProfileToCreate2DProfile() { var currentSurfaceLine2 = (spatialEditor.EmptySelection.DataObject as SurfaceLine2); // Create a 2D profile from current surfaceline and selected 1D if (project != null) { string item = HandleModalListSelection(project.SoilProfiles1D.OrderBy(p => p.Name).Select(p => p.Name).ToList(), "SelectProfile1D"); if (item != null) { SoilProfile1D profile1D = project.SoilProfiles1D.First(p => p.Name == item); Create2DProfileFromSoilProfile1DAndSurfaceLine2(profile1D, currentSurfaceLine2); } } } private void CreateNew2DProfileFromSoilProfile2DAndSurfaceLine2(SoilProfile2D profile2D, SurfaceLine2 surfaceLine2) { // Determine the requested shift of the geometry var dtrx = surfaceLine2.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).X; var dtpx = surfaceLine2.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X; var shift = ((dtrx + dtpx) * 0.5) - profile2D.CenterCrestLocation; var utils = new GeotechnicsUtilities(); try { var soilProfile2D = utils.CombineSurfaceLineWithSoilProfile2D(surfaceLine2.Geometry, profile2D, null, shift); soilProfile2D.Name = profile2D.Name + surfaceLine2.Name; AddSoilProfile2DToProjectAndUpdateUI(soilProfile2D); } catch (GeotechnicsUtilitiesException e) { var title = LocalizationManager.GetTranslatedText(this, "CombinerError"); MessageBox.Show(e.Message, title, MessageBoxButtons.OK); } } private void Create2DProfileFromSoilProfile1DAndSurfaceLine2(SoilProfile1D profile1D, SurfaceLine2 surfaceLine2) { var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile1D, SurfaceLine2 = surfaceLine2, Name = surfaceLine2.Name + "_" + profile1D.Name, CreateSettlementZones = false //See DSB-538: for now do not use zones, old value = true }; // Convert the soilsurfacesoilprofile to a SoilProfile2D to be able to edit it properly. var soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Determine center of crest if possible if (surfaceLine2.HasDike()) { soilProfile2D.CenterCrestLocation = (surfaceLine2.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver).X + surfaceLine2.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X)*0.5; } soilSurfaceProfile.Dispose(); // For some obscure reason, the created soilProfile2D is handled wrong in the UI (see DSB=786). // Its curves do not seem to match the surfaces in the events send on selecting and dragging a curve. // This causes the stange behaviour. To solve this, a Clone is made of the soilProfile2D and that clone is added instead. var newsp2 = (SoilProfile2D)soilProfile2D.Clone(); soilProfile2D.Dispose(); AddSoilProfile2DToProjectAndUpdateUI(newsp2); } private void AddSoilProfile2DToProjectAndUpdateUI(SoilProfile2D soilProfile2D) { DataEventPublisher.BeforeChange(project.SoilProfiles2D); UniqueNameProvider.ProvideUniqueName(project.SoilProfiles2D, soilProfile2D); project.SoilProfiles2D.Add(soilProfile2D); DataEventPublisher.DataListModified(project.SoilProfiles2D); var table = mainForm.DynamicTableControl.TabControl.Controls.Find("2DProfiles", true).FirstOrDefault(); if (table != null) { mainForm.SetAsActiveTable(table); // Make sure the new soilprofile2D is updated in this editor updateForCenterCrestLocation = true; DataEventPublisher.SelectionChanged(soilProfile2D); } } private string HandleModalListSelection(List items, string caption) { var modalList = new ModalListBox { Text = LocalizationManager.GetTranslatedText(this, caption), Items = items }; if (modalList.ShowDialog() == DialogResult.OK) { return modalList.SelectedItem; } return null; } } }