Files
2026-03-25 18:20:24 +08:00

541 lines
26 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CaeModel;
using CaeGlobals;
using System.Windows.Forms;
using CaeMesh;
namespace CPSO.Forms
{
class FrmBC : UserControls.FrmPropertyListView, IFormBase, IFormItemSetDataParent, IFormHighlight
{
// Variables
private string[] _boundaryConditionNames;
private string _boundaryConditionToEditName;
private ViewBoundaryCondition _viewBc;
private Controller _controller;
// Properties
public BoundaryCondition BoundaryCondition
{
get { return _viewBc != null ? _viewBc.GetBase() : null; }
set
{
if (value is FixedBC fix) _viewBc = new ViewFixedBC(fix.DeepClone());
else if (value is DisplacementRotation dr) _viewBc = new ViewDisplacementRotation(dr.DeepClone());
else if (value is SubmodelBC sm) _viewBc = new ViewSubmodelBC(sm.DeepClone());
else if (value is TemperatureBC tmp) _viewBc = new ViewTemperatureBC(tmp.DeepClone());
else throw new NotImplementedException();
}
}
// Constructors
public FrmBC(Controller controller)
{
InitializeComponent();
//
_controller = controller;
_viewBc = null;
}
private void InitializeComponent()
{
this.gbType.SuspendLayout();
this.gbProperties.SuspendLayout();
this.SuspendLayout();
//
// gbProperties
//
this.gbProperties.Size = new System.Drawing.Size(310, 403);
//
// propertyGrid
//
this.propertyGrid.Size = new System.Drawing.Size(298, 375);
//
// btnOK
//
this.btnOK.Location = new System.Drawing.Point(160, 526);
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(241, 526);
//
// btnOkAddNew
//
this.btnOkAddNew.Location = new System.Drawing.Point(79, 526);
//
// FrmBC
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.ClientSize = new System.Drawing.Size(334, 561);
this.Name = "FrmBC";
this.Text = "Edit Boundary Condition";
this.gbType.ResumeLayout(false);
this.gbProperties.ResumeLayout(false);
this.ResumeLayout(false);
}
// Overrides
protected override void OnVisibleChanged(EventArgs e)
{
if (Visible) ShowHideSelectionForm(); // accounts for minimizing/maximizing the main form
//
base.OnVisibleChanged(e);
}
protected override void OnListViewTypeSelectedIndexChanged()
{
// Deactivate selection limits
_controller.Selection.LimitSelectionToFirstGeometryType = false;
//
if (lvTypes.SelectedItems != null && lvTypes.SelectedItems.Count > 0)
{
object itemTag = lvTypes.SelectedItems[0].Tag;
if (itemTag is ViewError) _viewBc = null;
else if (itemTag is ViewFixedBC fix) _viewBc = fix;
else if (itemTag is ViewDisplacementRotation vdr) _viewBc = vdr;
else if (itemTag is ViewSubmodelBC vsm) _viewBc = vsm;
else if (itemTag is ViewTemperatureBC vtmp)
{
// Activate selection limit
_controller.Selection.LimitSelectionToFirstGeometryType = true;
_viewBc = vtmp;
}
else throw new NotImplementedException();
//
ShowHideSelectionForm();
//
propertyGrid.SelectedObject = itemTag;
//
HighlightBoundaryCondition();
}
}
protected override void OnPropertyGridPropertyValueChanged()
{
string property = propertyGrid.SelectedGridItem.PropertyDescriptor.Name;
//
if (property == nameof(_viewBc.RegionType))
{
ShowHideSelectionForm();
//
HighlightBoundaryCondition();
}
else if (property == nameof(_viewBc.CoordinateSystemName))
{
HighlightBoundaryCondition();
}
else if ((_viewBc is ViewFixedBC fix) &&
(property == nameof(fix.NodeSetName) ||
property == nameof(fix.ReferencePointName) ||
property == nameof(fix.SurfaceName)))
{
HighlightBoundaryCondition();
}
else if (_viewBc is ViewDisplacementRotation vdr)
{
if (property == nameof(vdr.NodeSetName) ||
property == nameof(vdr.ReferencePointName) ||
property == nameof(vdr.SurfaceName))
{
HighlightBoundaryCondition();
}
}
else if (_viewBc is ViewSubmodelBC vsm &&
(property == nameof(vsm.NodeSetName) ||
property == nameof(vsm.SurfaceName)))
{
HighlightBoundaryCondition();
}
else if (_viewBc is ViewTemperatureBC vtmp &&
(property == nameof(vtmp.NodeSetName) ||
property == nameof(vtmp.SurfaceName)))
{
HighlightBoundaryCondition();
}
//
base.OnPropertyGridPropertyValueChanged();
}
protected override void OnApply(bool onOkAddNew)
{
if (propertyGrid.SelectedObject is ViewError ve) throw new CaeGlobals.CaeException(ve.Message);
//
_viewBc = (ViewBoundaryCondition)propertyGrid.SelectedObject;
//
if (BoundaryCondition == null) throw new CaeException("No boundary condition was selected.");
// Check if the name exists
CheckName(_boundaryConditionToEditName, BoundaryCondition.Name, _boundaryConditionNames, "boundary condition");
// Check equations
BoundaryCondition.CheckEquations();
//
if (BoundaryCondition.RegionType == RegionTypeEnum.Selection &&
(BoundaryCondition.CreationIds == null || BoundaryCondition.CreationIds.Length == 0))
throw new CaeException("The boundary condition selection must contain at least one item.");
//
if (BoundaryCondition is DisplacementRotation dr)
{
if (!dr.IsProperlyDefined(out string error)) throw new CaeException(error);
}
else if (BoundaryCondition is SubmodelBC sm)
{
if (sm.GetConstrainedDirections().Length == 0)
throw new CaeException("At least one degree of freedom must be defined for the boundary condition.");
}
// Create
if (_boundaryConditionToEditName == null)
{
_controller.AddBoundaryConditionCommand(_stepName, BoundaryCondition);
}
// Replace
else if (_propertyItemChanged || !BoundaryCondition.Valid)
{
_controller.ReplaceBoundaryConditionCommand(_stepName, _boundaryConditionToEditName, BoundaryCondition);
_boundaryConditionToEditName = null; // prevents the execution of toInternal in OnHideOrClose
}
// Convert the boundary condition from internal to show it
else
{
BoundaryConditionInternal(false);
}
// If all is successful close the ItemSetSelectionForm - except for OKAddNew
if (!onOkAddNew) ItemSetDataEditor.SelectionForm.Hide();
}
protected override void OnHideOrClose()
{
// Close the ItemSetSelectionForm
ItemSetDataEditor.SelectionForm.Hide();
// Deactivate selection limits
_controller.Selection.LimitSelectionToFirstGeometryType = false;
// Convert the boundary condition from internal to show it
BoundaryConditionInternal(false);
//
base.OnHideOrClose();
}
protected override bool OnPrepareForm(string stepName, string boundaryConditionToEditName)
{
this.btnOkAddNew.Visible = boundaryConditionToEditName == null;
//
_propertyItemChanged = false;
_stepName = null;
_boundaryConditionNames = null;
_boundaryConditionToEditName = null;
_viewBc = null;
lvTypes.Items.Clear();
propertyGrid.SelectedObject = null;
//
_stepName = stepName;
_boundaryConditionNames = _controller.GetAllBoundaryConditionNames();
_boundaryConditionToEditName = boundaryConditionToEditName;
//
string[] nodeSetNames = _controller.GetUserNodeSetNames();
string[] surfaceNames = _controller.GetUserSurfaceNames();
string[] referencePointNames = _controller.GetModelReferencePointNames();
string[] distributionNames = _controller.GetDistributionNames();
string[] amplitudeNames = _controller.GetAmplitudeNames();
string[] coordinateSystemNames = _controller.GetModelCoordinateSystemNames();
if (nodeSetNames == null) nodeSetNames = new string[0];
if (surfaceNames == null) surfaceNames = new string[0];
if (referencePointNames == null) referencePointNames = new string[0];
if (distributionNames == null) distributionNames = new string[0];
if (amplitudeNames == null) amplitudeNames = new string[0];
if (coordinateSystemNames == null) coordinateSystemNames = new string[0];
//
if (_boundaryConditionNames == null)
throw new CaeException("The boundary condition names must be defined first.");
// Populate list view
PopulateListOfBCs(nodeSetNames, surfaceNames, referencePointNames, distributionNames, amplitudeNames,
coordinateSystemNames);
// Check if this step supports any boundary conditions
if (lvTypes.Items.Count == 0) return false;
// Create new boundary condition
if (_boundaryConditionToEditName == null)
{
// Different steps support different boundary conditions
if (lvTypes.Items.Count == 1) _preselectIndex = 0;
else
{
lvTypes.Enabled = true;
_viewBc = null;
}
//
HighlightBoundaryCondition(); // must be here if called from the menu
}
// Edit existing boundary condition
else
{
// Get and convert a converted boundary condition back to selection
BoundaryCondition = _controller.GetBoundaryCondition(stepName, _boundaryConditionToEditName); // to clone
if (BoundaryCondition.CreationData != null)
{
if (!_controller.Model.IsBoundaryConditionRegionValid(BoundaryCondition) || // do not use BoundaryCondition.Valid
!_controller.Model.RegionValid(BoundaryCondition))
{
// Region invalid
BoundaryCondition.CreationData = null;
BoundaryCondition.CreationIds = null;
_propertyItemChanged = true;
}
BoundaryCondition.RegionType = RegionTypeEnum.Selection;
}
// Convert the boundary condition to internal to hide it
BoundaryConditionInternal(true);
// Check for deleted distributions
if (BoundaryCondition is IDistribution icd)
{
if (icd.DistributionName != null && icd.DistributionName != Distribution.DefaultDistributionName)
CheckMissingValueRef(ref distributionNames, icd.DistributionName, a => { icd.DistributionName = a; });
}
// Check for deleted amplitudes
if (_viewBc.AmplitudeName != Amplitude.DefaultAmplitudeName)
CheckMissingValueRef(ref amplitudeNames, _viewBc.AmplitudeName, s => { _viewBc.AmplitudeName = s; });
// Check for deleted coordinate systems
if (_viewBc.CoordinateSystemName != CoordinateSystem.DefaultCoordinateSystemName)
CheckMissingValueRef(ref coordinateSystemNames, _viewBc.CoordinateSystemName,
s => { _viewBc.CoordinateSystemName = s; });
//
int selectedId;
if (_viewBc is ViewFixedBC fix)
{
selectedId = lvTypes.FindItemWithText("Fixed").Index;
// Check for deleted entities
if (fix.RegionType == RegionTypeEnum.Selection.ToFriendlyString()) { }
else if (fix.RegionType == RegionTypeEnum.NodeSetName.ToFriendlyString())
CheckMissingValueRef(ref nodeSetNames, fix.NodeSetName, s => { fix.NodeSetName = s; });
else if (fix.RegionType == RegionTypeEnum.SurfaceName.ToFriendlyString())
CheckMissingValueRef(ref surfaceNames, fix.SurfaceName, s => { fix.SurfaceName = s; });
else if (fix.RegionType == RegionTypeEnum.ReferencePointName.ToFriendlyString())
CheckMissingValueRef(ref referencePointNames, fix.ReferencePointName, s => { fix.ReferencePointName = s; });
else throw new NotSupportedException();
//
fix.PopulateDropDownLists(nodeSetNames, surfaceNames, referencePointNames);
}
else if (_viewBc is ViewDisplacementRotation vdr)
{
selectedId = lvTypes.FindItemWithText("Displacement/Rotation").Index;
// Check for deleted entities
if (vdr.RegionType == RegionTypeEnum.Selection.ToFriendlyString()) { }
else if (vdr.RegionType == RegionTypeEnum.NodeSetName.ToFriendlyString())
CheckMissingValueRef(ref nodeSetNames, vdr.NodeSetName, s => { vdr.NodeSetName = s; });
else if (vdr.RegionType == RegionTypeEnum.SurfaceName.ToFriendlyString())
CheckMissingValueRef(ref surfaceNames, vdr.SurfaceName, s => { vdr.SurfaceName = s; });
else if (vdr.RegionType == RegionTypeEnum.ReferencePointName.ToFriendlyString())
CheckMissingValueRef(ref referencePointNames, vdr.ReferencePointName, s => { vdr.ReferencePointName = s; });
else throw new NotSupportedException();
//
vdr.PopulateDropDownLists(nodeSetNames, surfaceNames, referencePointNames, amplitudeNames,
coordinateSystemNames);
}
else if (_viewBc is ViewSubmodelBC vsm)
{
selectedId = lvTypes.FindItemWithText("Submodel").Index;
// Check for deleted entities
if (vsm.RegionType == RegionTypeEnum.Selection.ToFriendlyString()) { }
else if (vsm.RegionType == RegionTypeEnum.NodeSetName.ToFriendlyString())
CheckMissingValueRef(ref nodeSetNames, vsm.NodeSetName, s => { vsm.NodeSetName = s; });
else if (vsm.RegionType == RegionTypeEnum.SurfaceName.ToFriendlyString())
CheckMissingValueRef(ref surfaceNames, vsm.SurfaceName, s => { vsm.SurfaceName = s; });
else throw new NotSupportedException();
//
vsm.PopulateDropDownLists(nodeSetNames, surfaceNames);
}
else if (_viewBc is ViewTemperatureBC vtmp)
{
selectedId = lvTypes.FindItemWithText("Temperature").Index;
// Check for deleted entities
if (vtmp.RegionType == RegionTypeEnum.Selection.ToFriendlyString()) { }
else if (vtmp.RegionType == RegionTypeEnum.NodeSetName.ToFriendlyString())
CheckMissingValueRef(ref nodeSetNames, vtmp.NodeSetName, s => { vtmp.NodeSetName = s; });
else if (vtmp.RegionType == RegionTypeEnum.SurfaceName.ToFriendlyString())
CheckMissingValueRef(ref surfaceNames, vtmp.SurfaceName, s => { vtmp.SurfaceName = s; });
else throw new NotSupportedException();
//
vtmp.PopulateDropDownLists(nodeSetNames, surfaceNames, distributionNames, amplitudeNames);
}
else throw new NotSupportedException();
//
lvTypes.Items[selectedId].Tag = _viewBc;
_preselectIndex = selectedId;
}
ShowHideSelectionForm();
//
propertyGrid.BuildAutocompleteMenu(_controller.GetAllParameterNames());
//
return true;
}
// Methods
private void PopulateListOfBCs(string[] nodeSetNames, string[] surfaceNames, string[] referencePointNames,
string[] distributionNames, string[] amplitudeNames, string[] coordinateSystemNames)
{
Step step = _controller.GetStep(_stepName);
System.Drawing.Color color = _controller.Settings.Pre.BoundaryConditionSymbolColor;
bool twoD = _controller.Model.Properties.ModelSpace.IsTwoD();
bool complex = step is SteadyStateDynamicsStep;
// Populate list view
ListViewItem item;
// Fixed
item = new ListViewItem("Fixed");
FixedBC fixedBC = new FixedBC(GetBoundaryConditionName("Fixed"), "", RegionTypeEnum.Selection, twoD);
if (step.IsBoundaryConditionSupported(fixedBC))
{
ViewFixedBC vfix = new ViewFixedBC(fixedBC);
vfix.PopulateDropDownLists(nodeSetNames, surfaceNames, referencePointNames);
vfix.Color = color;
item.Tag = vfix;
lvTypes.Items.Add(item);
}
// Displacement/Rotation
item = new ListViewItem("Displacement/Rotation");
DisplacementRotation displacementRotation = new DisplacementRotation(GetBoundaryConditionName("Displacement_Rotation"),
"", RegionTypeEnum.Selection, twoD, complex, 0);
if (step.IsBoundaryConditionSupported(displacementRotation))
{
ViewDisplacementRotation vdr = new ViewDisplacementRotation(displacementRotation);
vdr.PopulateDropDownLists(nodeSetNames, surfaceNames, referencePointNames, amplitudeNames, coordinateSystemNames);
vdr.Color = color;
item.Tag = vdr;
lvTypes.Items.Add(item);
}
// Submodel
item = new ListViewItem("Submodel");
SubmodelBC submodelBC = new SubmodelBC(GetBoundaryConditionName("Submodel"), "", RegionTypeEnum.Selection, twoD);
if (step.IsBoundaryConditionSupported(submodelBC))
{
ViewSubmodelBC vsm = new ViewSubmodelBC(submodelBC);
vsm.PopulateDropDownLists(nodeSetNames, surfaceNames);
vsm.Color = color;
item.Tag = vsm;
lvTypes.Items.Add(item);
}
// Temperature
item = new ListViewItem("Temperature");
TemperatureBC temperatureBC = new TemperatureBC(GetBoundaryConditionName("Temperature"), "",
RegionTypeEnum.Selection, 0, twoD);
if (step.IsBoundaryConditionSupported(temperatureBC))
{
ViewTemperatureBC vtmp = new ViewTemperatureBC(temperatureBC);
vtmp.PopulateDropDownLists(nodeSetNames, surfaceNames, distributionNames, amplitudeNames);
vtmp.Color = color;
item.Tag = vtmp;
lvTypes.Items.Add(item);
}
}
private string GetBoundaryConditionName(string baseName)
{
return _boundaryConditionNames.GetNextNumberedKey(baseName);
}
private void HighlightBoundaryCondition()
{
try
{
_controller.ClearSelectionHistory();
BoundaryCondition bc = BoundaryCondition;
//
if (_viewBc == null) { }
else if (bc is FixedBC || bc is DisplacementRotation || bc is SubmodelBC || bc is TemperatureBC)
{
if (bc.RegionType == RegionTypeEnum.NodeSetName || bc.RegionType == RegionTypeEnum.ReferencePointName ||
bc.RegionType == RegionTypeEnum.SurfaceName)
{
_controller.Highlight3DObjects(new object[] { bc.RegionName });
}
else if (bc.RegionType == RegionTypeEnum.Selection)
{
SetSelectItem();
//
if (bc.CreationData != null)
{
_controller.Selection = bc.CreationData.DeepClone();
_controller.HighlightSelection();
}
}
else throw new NotImplementedException();
//
if (bc.CoordinateSystemName != null)
_controller.HighlightCoordinateSystem(bc.CoordinateSystemName);
}
else throw new NotSupportedException();
}
catch { }
}
private void ShowHideSelectionForm()
{
if (BoundaryCondition != null && BoundaryCondition.RegionType == RegionTypeEnum.Selection)
ItemSetDataEditor.SelectionForm.ShowIfHidden(this.Owner);
else
ItemSetDataEditor.SelectionForm.Hide();
//
SetSelectItem();
}
private void SetSelectItem()
{
if (BoundaryCondition != null && BoundaryCondition.RegionType == RegionTypeEnum.Selection)
{
if (BoundaryCondition is null) { }
else if (BoundaryCondition is FixedBC) _controller.SetSelectItemToGeometry();
else if (BoundaryCondition is DisplacementRotation) _controller.SetSelectItemToGeometry();
else if (BoundaryCondition is SubmodelBC) _controller.SetSelectItemToGeometry();
else if (BoundaryCondition is TemperatureBC) _controller.SetSelectItemToGeometry();
else throw new NotSupportedException();
}
else _controller.SetSelectByToOff();
}
private void BoundaryConditionInternal(bool toInternal)
{
if (_stepName != null && _boundaryConditionToEditName != null)
{
// Convert the boundary condition from/to internal to hide/show it
_controller.GetBoundaryCondition(_stepName, _boundaryConditionToEditName).Internal = toInternal;
_controller.FeModelUpdate(UpdateType.RedrawSymbols);
}
}
//
public void SelectionChanged(int[] ids)
{
if (BoundaryCondition != null && BoundaryCondition.RegionType == RegionTypeEnum.Selection)
{
if (BoundaryCondition is FixedBC || BoundaryCondition is DisplacementRotation ||
BoundaryCondition is SubmodelBC || BoundaryCondition is TemperatureBC)
{
BoundaryCondition.CreationIds = ids;
BoundaryCondition.CreationData = _controller.Selection.DeepClone();
//
propertyGrid.Refresh();
//
_propertyItemChanged = true;
}
else throw new NotSupportedException();
}
}
// IFormHighlight
public void Highlight()
{
if (!_closing) HighlightBoundaryCondition();
}
// IFormItemSetDataParent
public bool IsSelectionGeometryBased()
{
// Prepare ItemSetDataEditor - prepare Geometry or Mesh based selection
BoundaryCondition boundaryCondition = BoundaryCondition;
//
if (boundaryCondition.CreationData != null) return boundaryCondition.CreationData.IsGeometryBased();
else return true;
}
public bool IsGeometrySelectionIdBased()
{
bool defaultMode = _controller.Settings.Pre.GeometrySelectMode == GeometrySelectModeEnum.SelectId;
// Prepare ItemSetDataEditor - prepare Geometry or Mesh based selection
BoundaryCondition boundaryCondition = BoundaryCondition;
//
if (boundaryCondition.CreationData != null && IsSelectionGeometryBased())
return boundaryCondition.CreationData.IsGeometryIdBased(defaultMode);
else return defaultMode;
}
}
}