From 40b865a7e7861b90e7d7a6b4422d6ac0e5942e69 Mon Sep 17 00:00:00 2001 From: seto Date: Fri, 10 Feb 2023 20:55:09 +0900 Subject: [PATCH] update --- CSManager/CSManager.csproj | 4 +- .../Crystal/AtomControl.cs | 7 +- .../Crystal/CrystalControl.Designer.cs | 210 +- .../Crystal/CrystalControl.cs | 1355 +++-- .../Crystal/CrystalControl.ja.resx | 454 +- .../Crystal/CrystalControl.resx | 4664 ++++++++--------- .../Crystal/FormAnotherSpaceGroup.Designer.cs | 118 + .../Crystal/FormAnotherSpaceGroup.cs | 123 + .../FormAnotherSpaceGroup.resx} | 0 .../Crystal/SymmetryControl.cs | 10 +- .../Crystal/SymmetryControl.ja.resx | 27 +- .../Crystal/SymmetryControl.resx | 2136 ++++---- .../CrystalDatabase/SearchCrystalControl.cs | 444 +- .../Crystallography - Backup.Controls.csproj | 41 + .../Crystallography.Controls.csproj | 15 +- Crystallography.Controls/GraphControl.cs | 2129 ++++---- .../Macro/FormMacroList.Designer.cs | 49 - .../Macro/FormMacroList.cs | 12 - Crystallography.Controls/Macro/Macro.cs | 313 +- .../Numeric/NumericBox.cs | 9 +- .../ScalablePictureBox.cs | 1600 +++--- .../ScalablePictureBoxAdvanced.Designer.cs | 115 +- .../ScalablePictureBoxAdvanced.cs | 1105 ++-- .../ScalablePictureBoxAdvanced.resx | 474 +- Crystallography/Atom/Atoms.cs | 1 - Crystallography/BetheMethod.cs | 2 +- Crystallography/Crystal/ConvertCrystalData.cs | 69 +- Crystallography/Crystal/Crystal.cs | 27 +- Crystallography/Crystal/Plane.cs | 185 +- Crystallography/Crystal/PolyCrystal.cs | 3 + .../Crystallography - Backup (1).csproj | 61 + .../Crystallography - Backup.csproj | 56 + Crystallography/Crystallography.csproj | 15 +- Crystallography/Detector/Ring.cs | 12 +- Crystallography/Images/ImageIO.cs | 70 +- Crystallography/Images/ImageProcessor.cs | 520 +- Crystallography/Images/PseudoBitmap.cs | 4 - Crystallography/Images/Tiff.cs | 28 +- Crystallography/Mathematics/Geometriy.cs | 1871 +++---- Crystallography/Mathematics/Marquardt.cs | 1107 ++-- Crystallography/NativeWrapper.cs | 68 +- Crystallography/PeakSearch.cs | 569 +- Crystallography/PointD.cs | 3 +- 43 files changed, 10665 insertions(+), 9420 deletions(-) create mode 100644 Crystallography.Controls/Crystal/FormAnotherSpaceGroup.Designer.cs create mode 100644 Crystallography.Controls/Crystal/FormAnotherSpaceGroup.cs rename Crystallography.Controls/{Macro/FormMacroList.resx => Crystal/FormAnotherSpaceGroup.resx} (100%) create mode 100644 Crystallography.Controls/Crystallography - Backup.Controls.csproj delete mode 100644 Crystallography.Controls/Macro/FormMacroList.Designer.cs delete mode 100644 Crystallography.Controls/Macro/FormMacroList.cs create mode 100644 Crystallography/Crystallography - Backup (1).csproj create mode 100644 Crystallography/Crystallography - Backup.csproj diff --git a/CSManager/CSManager.csproj b/CSManager/CSManager.csproj index af16c0c..54579e7 100644 --- a/CSManager/CSManager.csproj +++ b/CSManager/CSManager.csproj @@ -4,8 +4,8 @@ WinExe net7.0-windows true - 2022.12.3.0941 - 2022.12.3.0941 + 2023.2.10.1154 + 2023.2.10.1154 App.ico diff --git a/Crystallography.Controls/Crystal/AtomControl.cs b/Crystallography.Controls/Crystal/AtomControl.cs index 4784ec1..0ec8505 100644 --- a/Crystallography.Controls/Crystal/AtomControl.cs +++ b/Crystallography.Controls/Crystal/AtomControl.cs @@ -15,16 +15,19 @@ public partial class AtomControl : UserControl public Crystal Crystal { - get => crystal; set + get => crystal; + set { crystal = value; if (crystal != null) { + SuspendLayout(); table.Clear(); AddRange(Crystal.Atoms); //なぜかEnabledカラムのVisibleが予期せず変わってしまうことがあるので、appearanceTabVisibleを使う. dataGridView.Columns["enabledColumn"].Visible = appearanceTabVisible; + ResumeLayout(); } } } @@ -433,8 +436,10 @@ public void AddRange(IEnumerable atoms) if (atoms != null) { SkipEvent = true; + dataGridView.SuspendLayout(); foreach (var a in atoms) table.Add(a); + dataGridView.ResumeLayout(); SkipEvent = false; ItemsChanged?.Invoke(this, new EventArgs()); bindingSource_PositionChanged(new object(), new EventArgs()); diff --git a/Crystallography.Controls/Crystal/CrystalControl.Designer.cs b/Crystallography.Controls/Crystal/CrystalControl.Designer.cs index 2d08479..ba01e14 100644 --- a/Crystallography.Controls/Crystal/CrystalControl.Designer.cs +++ b/Crystallography.Controls/Crystal/CrystalControl.Designer.cs @@ -63,7 +63,7 @@ private void InitializeComponent() this.tabPageElasticity = new System.Windows.Forms.TabPage(); this.elasticityControl1 = new Crystallography.Controls.ElasticityControl(); this.tabPageStrainStress = new System.Windows.Forms.TabPage(); - this.button1 = new System.Windows.Forms.Button(); + this.buttonStressSet = new System.Windows.Forms.Button(); this.numericBoxStrain33 = new Crystallography.Controls.NumericBox(); this.numericBoxHill = new Crystallography.Controls.NumericBox(); this.label116 = new System.Windows.Forms.Label(); @@ -128,12 +128,12 @@ private void InitializeComponent() this.exportThisCrystalAsCIFToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.sendThisCrystalToOtherSoftwareToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.clearAllDataToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.revertCellConstantsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.strainControlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.convertToP1SymmetryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.convertToSuperstructureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.convertToAnotherSpacegroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.textBoxName = new System.Windows.Forms.TextBox(); this.label22 = new System.Windows.Forms.Label(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); @@ -173,7 +173,6 @@ private void InitializeComponent() // // tabControl // - resources.ApplyResources(this.tabControl, "tabControl"); this.tabControl.AllowDrop = true; this.tabControl.Controls.Add(this.tabPageBasicInfo); this.tabControl.Controls.Add(this.tabPageAtom); @@ -185,40 +184,38 @@ private void InitializeComponent() this.tabControl.Controls.Add(this.tabPagePolycrystalline); this.tabControl.Controls.Add(this.tabPageBounds); this.tabControl.Controls.Add(this.tabPageLatticePlane); + resources.ApplyResources(this.tabControl, "tabControl"); this.tabControl.HotTrack = true; this.tabControl.Name = "tabControl"; this.tabControl.SelectedIndex = 0; - this.toolTip.SetToolTip(this.tabControl, resources.GetString("tabControl.ToolTip")); this.tabControl.DragDrop += new System.Windows.Forms.DragEventHandler(this.FormCrystal_DragDrop); this.tabControl.DragEnter += new System.Windows.Forms.DragEventHandler(this.FormCrystal_DragEnter); // // tabPageBasicInfo // - resources.ApplyResources(this.tabPageBasicInfo, "tabPageBasicInfo"); this.tabPageBasicInfo.BackColor = System.Drawing.SystemColors.Control; this.tabPageBasicInfo.Controls.Add(this.panel5); + resources.ApplyResources(this.tabPageBasicInfo, "tabPageBasicInfo"); this.tabPageBasicInfo.Name = "tabPageBasicInfo"; this.toolTip.SetToolTip(this.tabPageBasicInfo, resources.GetString("tabPageBasicInfo.ToolTip")); // // panel5 // - resources.ApplyResources(this.panel5, "panel5"); this.panel5.Controls.Add(this.flowLayoutPanel4); this.panel5.Controls.Add(this.symmetryControl); + resources.ApplyResources(this.panel5, "panel5"); this.panel5.Name = "panel5"; - this.toolTip.SetToolTip(this.panel5, resources.GetString("panel5.ToolTip")); // // flowLayoutPanel4 // - resources.ApplyResources(this.flowLayoutPanel4, "flowLayoutPanel4"); this.flowLayoutPanel4.Controls.Add(this.numericBoxVolume); this.flowLayoutPanel4.Controls.Add(this.numericBoxCellMass); this.flowLayoutPanel4.Controls.Add(this.numericBoxMolarVolume); this.flowLayoutPanel4.Controls.Add(this.numericBoxMolarMass); this.flowLayoutPanel4.Controls.Add(this.numericBoxDensity); this.flowLayoutPanel4.Controls.Add(this.colorControl); + resources.ApplyResources(this.flowLayoutPanel4, "flowLayoutPanel4"); this.flowLayoutPanel4.Name = "flowLayoutPanel4"; - this.toolTip.SetToolTip(this.flowLayoutPanel4, resources.GetString("flowLayoutPanel4.ToolTip")); // // numericBoxVolume // @@ -305,8 +302,8 @@ private void InitializeComponent() // // colorControl // - resources.ApplyResources(this.colorControl, "colorControl"); this.colorControl.Argb = -986896; + resources.ApplyResources(this.colorControl, "colorControl"); this.colorControl.Blue = 240; this.colorControl.BlueF = 0.9411765F; this.colorControl.BoxSize = new System.Drawing.Size(20, 20); @@ -322,31 +319,29 @@ private void InitializeComponent() // symmetryControl // this.symmetryControl.A = 0D; - resources.ApplyResources(this.symmetryControl, "symmetryControl"); this.symmetryControl.Alpha = 0D; this.symmetryControl.B = 0D; this.symmetryControl.Beta = 0D; this.symmetryControl.C = 0D; + resources.ApplyResources(this.symmetryControl, "symmetryControl"); this.symmetryControl.Gamma = 0D; this.symmetryControl.Name = "symmetryControl"; this.symmetryControl.ShowError = false; this.symmetryControl.SkipEvent = false; this.symmetryControl.SymmetrySeriesNumber = 0; - this.toolTip.SetToolTip(this.symmetryControl, resources.GetString("symmetryControl.ToolTip")); this.symmetryControl.ItemChanged += new System.EventHandler(this.symmetryControl_ItemChanged); // // tabPageAtom // - resources.ApplyResources(this.tabPageAtom, "tabPageAtom"); this.tabPageAtom.BackColor = System.Drawing.SystemColors.Control; this.tabPageAtom.Controls.Add(this.atomControl); this.tabPageAtom.Controls.Add(this.panelAtom); + resources.ApplyResources(this.tabPageAtom, "tabPageAtom"); this.tabPageAtom.Name = "tabPageAtom"; this.toolTip.SetToolTip(this.tabPageAtom, resources.GetString("tabPageAtom.ToolTip")); // // atomControl // - resources.ApplyResources(this.atomControl, "atomControl"); this.atomControl.Alpha = 0F; this.atomControl.Ambient = 0F; this.atomControl.Aniso11 = 0D; @@ -367,6 +362,7 @@ private void InitializeComponent() this.atomControl.AtomNo = 0; this.atomControl.AtomSubNoElectron = -1; this.atomControl.AtomSubNoXray = -1; + resources.ApplyResources(this.atomControl, "atomControl"); this.atomControl.Crystal = null; this.atomControl.DebyeWallerError = false; this.atomControl.DebyeWallerTabVisible = true; @@ -388,7 +384,6 @@ private void InitializeComponent() this.atomControl.ShowLabel = false; this.atomControl.SkipEvent = false; this.atomControl.Specular = 0F; - this.toolTip.SetToolTip(this.atomControl, resources.GetString("atomControl.ToolTip")); this.atomControl.UseIsotropy = false; this.atomControl.UseTypeU = false; this.atomControl.X = 0D; @@ -404,14 +399,12 @@ private void InitializeComponent() resources.ApplyResources(this.panelAtom, "panelAtom"); this.panelAtom.Controls.Add(this.panel3); this.panelAtom.Name = "panelAtom"; - this.toolTip.SetToolTip(this.panelAtom, resources.GetString("panelAtom.ToolTip")); // // panel3 // resources.ApplyResources(this.panel3, "panel3"); this.panel3.ContextMenuStrip = this.contextMenuStrip2; this.panel3.Name = "panel3"; - this.toolTip.SetToolTip(this.panel3, resources.GetString("panel3.ToolTip")); // // contextMenuStrip2 // @@ -420,21 +413,19 @@ private void InitializeComponent() this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.resetToolStripMenuItem}); this.contextMenuStrip2.Name = "contextMenuStrip2"; - this.toolTip.SetToolTip(this.contextMenuStrip2, resources.GetString("contextMenuStrip2.ToolTip")); // // resetToolStripMenuItem // - resources.ApplyResources(this.resetToolStripMenuItem, "resetToolStripMenuItem"); this.resetToolStripMenuItem.Name = "resetToolStripMenuItem"; + resources.ApplyResources(this.resetToolStripMenuItem, "resetToolStripMenuItem"); this.resetToolStripMenuItem.Click += new System.EventHandler(this.resetToolStripMenuItem_Click); // // tabPageBondsPolyhedra // - resources.ApplyResources(this.tabPageBondsPolyhedra, "tabPageBondsPolyhedra"); this.tabPageBondsPolyhedra.BackColor = System.Drawing.SystemColors.Control; this.tabPageBondsPolyhedra.Controls.Add(this.bondControl); + resources.ApplyResources(this.tabPageBondsPolyhedra, "tabPageBondsPolyhedra"); this.tabPageBondsPolyhedra.Name = "tabPageBondsPolyhedra"; - this.toolTip.SetToolTip(this.tabPageBondsPolyhedra, resources.GetString("tabPageBondsPolyhedra.ToolTip")); // // bondControl // @@ -443,101 +434,88 @@ private void InitializeComponent() this.bondControl.ElementList = null; this.bondControl.Name = "bondControl"; this.bondControl.SkipEvent = false; - this.toolTip.SetToolTip(this.bondControl, resources.GetString("bondControl.ToolTip")); // // tabPageReference // - resources.ApplyResources(this.tabPageReference, "tabPageReference"); this.tabPageReference.BackColor = System.Drawing.SystemColors.Control; this.tabPageReference.Controls.Add(this.groupBox8); this.tabPageReference.Controls.Add(this.groupBox6); this.tabPageReference.Controls.Add(this.groupBox7); this.tabPageReference.Controls.Add(this.groupBox5); + resources.ApplyResources(this.tabPageReference, "tabPageReference"); this.tabPageReference.Name = "tabPageReference"; - this.toolTip.SetToolTip(this.tabPageReference, resources.GetString("tabPageReference.ToolTip")); // // groupBox8 // - resources.ApplyResources(this.groupBox8, "groupBox8"); this.groupBox8.Controls.Add(this.textBoxTitle); + resources.ApplyResources(this.groupBox8, "groupBox8"); this.groupBox8.Name = "groupBox8"; this.groupBox8.TabStop = false; - this.toolTip.SetToolTip(this.groupBox8, resources.GetString("groupBox8.ToolTip")); // // textBoxTitle // this.textBoxTitle.AcceptsReturn = true; resources.ApplyResources(this.textBoxTitle, "textBoxTitle"); this.textBoxTitle.Name = "textBoxTitle"; - this.toolTip.SetToolTip(this.textBoxTitle, resources.GetString("textBoxTitle.ToolTip")); // // groupBox6 // - resources.ApplyResources(this.groupBox6, "groupBox6"); this.groupBox6.Controls.Add(this.textBoxAuthor); + resources.ApplyResources(this.groupBox6, "groupBox6"); this.groupBox6.Name = "groupBox6"; this.groupBox6.TabStop = false; - this.toolTip.SetToolTip(this.groupBox6, resources.GetString("groupBox6.ToolTip")); // // textBoxAuthor // this.textBoxAuthor.AcceptsReturn = true; resources.ApplyResources(this.textBoxAuthor, "textBoxAuthor"); this.textBoxAuthor.Name = "textBoxAuthor"; - this.toolTip.SetToolTip(this.textBoxAuthor, resources.GetString("textBoxAuthor.ToolTip")); // // groupBox7 // - resources.ApplyResources(this.groupBox7, "groupBox7"); this.groupBox7.Controls.Add(this.textBoxJournal); + resources.ApplyResources(this.groupBox7, "groupBox7"); this.groupBox7.Name = "groupBox7"; this.groupBox7.TabStop = false; - this.toolTip.SetToolTip(this.groupBox7, resources.GetString("groupBox7.ToolTip")); // // textBoxJournal // this.textBoxJournal.AcceptsReturn = true; resources.ApplyResources(this.textBoxJournal, "textBoxJournal"); this.textBoxJournal.Name = "textBoxJournal"; - this.toolTip.SetToolTip(this.textBoxJournal, resources.GetString("textBoxJournal.ToolTip")); // // groupBox5 // - resources.ApplyResources(this.groupBox5, "groupBox5"); this.groupBox5.Controls.Add(this.textBoxMemo); + resources.ApplyResources(this.groupBox5, "groupBox5"); this.groupBox5.Name = "groupBox5"; this.groupBox5.TabStop = false; - this.toolTip.SetToolTip(this.groupBox5, resources.GetString("groupBox5.ToolTip")); // // textBoxMemo // resources.ApplyResources(this.textBoxMemo, "textBoxMemo"); this.textBoxMemo.Name = "textBoxMemo"; - this.toolTip.SetToolTip(this.textBoxMemo, resources.GetString("textBoxMemo.ToolTip")); // // tabPageEOS // - resources.ApplyResources(this.tabPageEOS, "tabPageEOS"); this.tabPageEOS.BackColor = System.Drawing.SystemColors.Control; this.tabPageEOS.Controls.Add(this.eosControl); + resources.ApplyResources(this.tabPageEOS, "tabPageEOS"); this.tabPageEOS.Name = "tabPageEOS"; - this.toolTip.SetToolTip(this.tabPageEOS, resources.GetString("tabPageEOS.ToolTip")); // // eosControl // - resources.ApplyResources(this.eosControl, "eosControl"); this.eosControl.Crystal = null; + resources.ApplyResources(this.eosControl, "eosControl"); this.eosControl.Name = "eosControl"; this.eosControl.SkipEvent = false; - this.toolTip.SetToolTip(this.eosControl, resources.GetString("eosControl.ToolTip")); // // tabPageElasticity // - resources.ApplyResources(this.tabPageElasticity, "tabPageElasticity"); this.tabPageElasticity.BackColor = System.Drawing.SystemColors.Control; this.tabPageElasticity.Controls.Add(this.elasticityControl1); + resources.ApplyResources(this.tabPageElasticity, "tabPageElasticity"); this.tabPageElasticity.Name = "tabPageElasticity"; - this.toolTip.SetToolTip(this.tabPageElasticity, resources.GetString("tabPageElasticity.ToolTip")); // // elasticityControl1 // @@ -545,14 +523,12 @@ private void InitializeComponent() this.elasticityControl1.Mode = Crystallography.Elasticity.Mode.Stiffness; this.elasticityControl1.Name = "elasticityControl1"; this.elasticityControl1.SymmetrySeriesNumber = 1; - this.toolTip.SetToolTip(this.elasticityControl1, resources.GetString("elasticityControl1.ToolTip")); this.elasticityControl1.ValueChanged += new Crystallography.Controls.ElasticityControl.MyEventHandler(this.elasticityControl1_ValueChanged); // // tabPageStrainStress // - resources.ApplyResources(this.tabPageStrainStress, "tabPageStrainStress"); this.tabPageStrainStress.BackColor = System.Drawing.SystemColors.Control; - this.tabPageStrainStress.Controls.Add(this.button1); + this.tabPageStrainStress.Controls.Add(this.buttonStressSet); this.tabPageStrainStress.Controls.Add(this.numericBoxStrain33); this.tabPageStrainStress.Controls.Add(this.numericBoxHill); this.tabPageStrainStress.Controls.Add(this.label116); @@ -582,16 +558,15 @@ private void InitializeComponent() this.tabPageStrainStress.Controls.Add(this.numericBoxStrain12); this.tabPageStrainStress.Controls.Add(this.numericBoxStrain23); this.tabPageStrainStress.Controls.Add(this.numericBoxStrain13); + resources.ApplyResources(this.tabPageStrainStress, "tabPageStrainStress"); this.tabPageStrainStress.Name = "tabPageStrainStress"; - this.toolTip.SetToolTip(this.tabPageStrainStress, resources.GetString("tabPageStrainStress.ToolTip")); // - // button1 + // buttonStressSet // - resources.ApplyResources(this.button1, "button1"); - this.button1.Name = "button1"; - this.toolTip.SetToolTip(this.button1, resources.GetString("button1.ToolTip")); - this.button1.UseVisualStyleBackColor = true; - this.button1.Click += new System.EventHandler(this.button1_Click); + resources.ApplyResources(this.buttonStressSet, "buttonStressSet"); + this.buttonStressSet.Name = "buttonStressSet"; + this.buttonStressSet.UseVisualStyleBackColor = true; + this.buttonStressSet.Click += new System.EventHandler(this.buttonStressSet_Click); // // numericBoxStrain33 // @@ -605,7 +580,6 @@ private void InitializeComponent() this.numericBoxStrain33.SkipEventDuringInput = false; this.numericBoxStrain33.SmartIncrement = true; this.numericBoxStrain33.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain33, resources.GetString("numericBoxStrain33.ToolTip")); // // numericBoxHill // @@ -620,104 +594,87 @@ private void InitializeComponent() this.numericBoxHill.SkipEventDuringInput = false; this.numericBoxHill.SmartIncrement = true; this.numericBoxHill.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxHill, resources.GetString("numericBoxHill.ToolTip")); this.numericBoxHill.Value = 1D; // // label116 // resources.ApplyResources(this.label116, "label116"); this.label116.Name = "label116"; - this.toolTip.SetToolTip(this.label116, resources.GetString("label116.ToolTip")); // // label117 // resources.ApplyResources(this.label117, "label117"); this.label117.Name = "label117"; - this.toolTip.SetToolTip(this.label117, resources.GetString("label117.ToolTip")); // // label109 // resources.ApplyResources(this.label109, "label109"); this.label109.Name = "label109"; - this.toolTip.SetToolTip(this.label109, resources.GetString("label109.ToolTip")); // // label110 // resources.ApplyResources(this.label110, "label110"); this.label110.Name = "label110"; - this.toolTip.SetToolTip(this.label110, resources.GetString("label110.ToolTip")); // // label111 // resources.ApplyResources(this.label111, "label111"); this.label111.Name = "label111"; - this.toolTip.SetToolTip(this.label111, resources.GetString("label111.ToolTip")); // // label112 // resources.ApplyResources(this.label112, "label112"); this.label112.Name = "label112"; - this.toolTip.SetToolTip(this.label112, resources.GetString("label112.ToolTip")); // // label113 // resources.ApplyResources(this.label113, "label113"); this.label113.Name = "label113"; - this.toolTip.SetToolTip(this.label113, resources.GetString("label113.ToolTip")); // // label114 // resources.ApplyResources(this.label114, "label114"); this.label114.Name = "label114"; - this.toolTip.SetToolTip(this.label114, resources.GetString("label114.ToolTip")); // // label115 // resources.ApplyResources(this.label115, "label115"); this.label115.Name = "label115"; - this.toolTip.SetToolTip(this.label115, resources.GetString("label115.ToolTip")); // // label102 // resources.ApplyResources(this.label102, "label102"); this.label102.Name = "label102"; - this.toolTip.SetToolTip(this.label102, resources.GetString("label102.ToolTip")); // // label103 // resources.ApplyResources(this.label103, "label103"); this.label103.Name = "label103"; - this.toolTip.SetToolTip(this.label103, resources.GetString("label103.ToolTip")); // // label104 // resources.ApplyResources(this.label104, "label104"); this.label104.Name = "label104"; - this.toolTip.SetToolTip(this.label104, resources.GetString("label104.ToolTip")); // // label105 // resources.ApplyResources(this.label105, "label105"); this.label105.Name = "label105"; - this.toolTip.SetToolTip(this.label105, resources.GetString("label105.ToolTip")); // // label106 // resources.ApplyResources(this.label106, "label106"); this.label106.Name = "label106"; - this.toolTip.SetToolTip(this.label106, resources.GetString("label106.ToolTip")); // // label107 // resources.ApplyResources(this.label107, "label107"); this.label107.Name = "label107"; - this.toolTip.SetToolTip(this.label107, resources.GetString("label107.ToolTip")); // // label108 // resources.ApplyResources(this.label108, "label108"); this.label108.Name = "label108"; - this.toolTip.SetToolTip(this.label108, resources.GetString("label108.ToolTip")); // // numericBoxStress33 // @@ -731,7 +688,6 @@ private void InitializeComponent() this.numericBoxStress33.SkipEventDuringInput = false; this.numericBoxStress33.SmartIncrement = true; this.numericBoxStress33.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress33, resources.GetString("numericBoxStress33.ToolTip")); // // numericBoxStress22 // @@ -745,7 +701,6 @@ private void InitializeComponent() this.numericBoxStress22.SkipEventDuringInput = false; this.numericBoxStress22.SmartIncrement = true; this.numericBoxStress22.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress22, resources.GetString("numericBoxStress22.ToolTip")); // // numericBoxStress11 // @@ -759,7 +714,6 @@ private void InitializeComponent() this.numericBoxStress11.SkipEventDuringInput = false; this.numericBoxStress11.SmartIncrement = true; this.numericBoxStress11.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress11, resources.GetString("numericBoxStress11.ToolTip")); // // numericBoxStress23 // @@ -773,7 +727,6 @@ private void InitializeComponent() this.numericBoxStress23.SkipEventDuringInput = false; this.numericBoxStress23.SmartIncrement = true; this.numericBoxStress23.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress23, resources.GetString("numericBoxStress23.ToolTip")); // // numericBoxStress13 // @@ -787,7 +740,6 @@ private void InitializeComponent() this.numericBoxStress13.SkipEventDuringInput = false; this.numericBoxStress13.SmartIncrement = true; this.numericBoxStress13.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress13, resources.GetString("numericBoxStress13.ToolTip")); // // numericBoxStress12 // @@ -801,7 +753,6 @@ private void InitializeComponent() this.numericBoxStress12.SkipEventDuringInput = false; this.numericBoxStress12.SmartIncrement = true; this.numericBoxStress12.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStress12, resources.GetString("numericBoxStress12.ToolTip")); // // numericBoxStrain11 // @@ -815,7 +766,6 @@ private void InitializeComponent() this.numericBoxStrain11.SkipEventDuringInput = false; this.numericBoxStrain11.SmartIncrement = true; this.numericBoxStrain11.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain11, resources.GetString("numericBoxStrain11.ToolTip")); // // numericBoxStrain22 // @@ -829,7 +779,6 @@ private void InitializeComponent() this.numericBoxStrain22.SkipEventDuringInput = false; this.numericBoxStrain22.SmartIncrement = true; this.numericBoxStrain22.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain22, resources.GetString("numericBoxStrain22.ToolTip")); // // numericBoxStrain12 // @@ -843,7 +792,6 @@ private void InitializeComponent() this.numericBoxStrain12.SkipEventDuringInput = false; this.numericBoxStrain12.SmartIncrement = true; this.numericBoxStrain12.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain12, resources.GetString("numericBoxStrain12.ToolTip")); // // numericBoxStrain23 // @@ -857,7 +805,6 @@ private void InitializeComponent() this.numericBoxStrain23.SkipEventDuringInput = false; this.numericBoxStrain23.SmartIncrement = true; this.numericBoxStrain23.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain23, resources.GetString("numericBoxStrain23.ToolTip")); // // numericBoxStrain13 // @@ -871,88 +818,82 @@ private void InitializeComponent() this.numericBoxStrain13.SkipEventDuringInput = false; this.numericBoxStrain13.SmartIncrement = true; this.numericBoxStrain13.TextFont = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.toolTip.SetToolTip(this.numericBoxStrain13, resources.GetString("numericBoxStrain13.ToolTip")); // // tabPagePolycrystalline // - resources.ApplyResources(this.tabPagePolycrystalline, "tabPagePolycrystalline"); this.tabPagePolycrystalline.BackColor = System.Drawing.SystemColors.Control; this.tabPagePolycrystalline.ContextMenuStrip = this.contextMenuStripPoleFigure; this.tabPagePolycrystalline.Controls.Add(this.poleFigureControl); this.tabPagePolycrystalline.Controls.Add(this.flowLayoutPanel3); this.tabPagePolycrystalline.Controls.Add(this.flowLayoutPanel2); + resources.ApplyResources(this.tabPagePolycrystalline, "tabPagePolycrystalline"); this.tabPagePolycrystalline.Name = "tabPagePolycrystalline"; - this.toolTip.SetToolTip(this.tabPagePolycrystalline, resources.GetString("tabPagePolycrystalline.ToolTip")); // // contextMenuStripPoleFigure // - resources.ApplyResources(this.contextMenuStripPoleFigure, "contextMenuStripPoleFigure"); this.contextMenuStripPoleFigure.ImageScalingSize = new System.Drawing.Size(20, 20); this.contextMenuStripPoleFigure.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.readToolStripMenuItem, this.saveToolStripMenuItem, this.exportToolStripMenuItem}); this.contextMenuStripPoleFigure.Name = "contextMenuStripPoleFigure"; - this.toolTip.SetToolTip(this.contextMenuStripPoleFigure, resources.GetString("contextMenuStripPoleFigure.ToolTip")); + resources.ApplyResources(this.contextMenuStripPoleFigure, "contextMenuStripPoleFigure"); // // readToolStripMenuItem // - resources.ApplyResources(this.readToolStripMenuItem, "readToolStripMenuItem"); this.readToolStripMenuItem.Name = "readToolStripMenuItem"; + resources.ApplyResources(this.readToolStripMenuItem, "readToolStripMenuItem"); this.readToolStripMenuItem.Click += new System.EventHandler(this.readToolStripMenuItem_Click); // // saveToolStripMenuItem // - resources.ApplyResources(this.saveToolStripMenuItem, "saveToolStripMenuItem"); this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; + resources.ApplyResources(this.saveToolStripMenuItem, "saveToolStripMenuItem"); this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); // // exportToolStripMenuItem // - resources.ApplyResources(this.exportToolStripMenuItem, "exportToolStripMenuItem"); this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem, this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem, this.asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem}); this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; + resources.ApplyResources(this.exportToolStripMenuItem, "exportToolStripMenuItem"); // // asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem // - resources.ApplyResources(this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem, "asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem"); this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem.Name = "asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem"; + resources.ApplyResources(this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem, "asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem"); this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem.Click += new System.EventHandler(this.asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem_Click); // // asTXTFileAllEulerAngleAndDensityToolStripMenuItem // - resources.ApplyResources(this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem, "asTXTFileAllEulerAngleAndDensityToolStripMenuItem"); this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem.Name = "asTXTFileAllEulerAngleAndDensityToolStripMenuItem"; + resources.ApplyResources(this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem, "asTXTFileAllEulerAngleAndDensityToolStripMenuItem"); this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem.Click += new System.EventHandler(this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem_Click); // // asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem // - resources.ApplyResources(this.asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem, "asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem"); this.asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem.Name = "asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem"; + resources.ApplyResources(this.asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem, "asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem"); this.asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem.Click += new System.EventHandler(this.asTXTFileAllEulerAngleAndDensityToolStripMenuItem_Click); // // poleFigureControl // - resources.ApplyResources(this.poleFigureControl, "poleFigureControl"); this.poleFigureControl.Crystal = null; + resources.ApplyResources(this.poleFigureControl, "poleFigureControl"); this.poleFigureControl.Name = "poleFigureControl"; - this.toolTip.SetToolTip(this.poleFigureControl, resources.GetString("poleFigureControl.ToolTip")); // // flowLayoutPanel3 // resources.ApplyResources(this.flowLayoutPanel3, "flowLayoutPanel3"); this.flowLayoutPanel3.Controls.Add(this.buttonGenerateRandomOrientations); this.flowLayoutPanel3.Name = "flowLayoutPanel3"; - this.toolTip.SetToolTip(this.flowLayoutPanel3, resources.GetString("flowLayoutPanel3.ToolTip")); // // buttonGenerateRandomOrientations // resources.ApplyResources(this.buttonGenerateRandomOrientations, "buttonGenerateRandomOrientations"); this.buttonGenerateRandomOrientations.Name = "buttonGenerateRandomOrientations"; - this.toolTip.SetToolTip(this.buttonGenerateRandomOrientations, resources.GetString("buttonGenerateRandomOrientations.ToolTip")); this.buttonGenerateRandomOrientations.UseVisualStyleBackColor = true; this.buttonGenerateRandomOrientations.Click += new System.EventHandler(this.buttonGenerateRandomOrientations_Click); // @@ -967,18 +908,16 @@ private void InitializeComponent() this.flowLayoutPanel2.Controls.Add(this.numericUpDownCrystallineSize); this.flowLayoutPanel2.Controls.Add(this.label99); this.flowLayoutPanel2.Name = "flowLayoutPanel2"; - this.toolTip.SetToolTip(this.flowLayoutPanel2, resources.GetString("flowLayoutPanel2.ToolTip")); // // label5 // resources.ApplyResources(this.label5, "label5"); this.label5.Name = "label5"; - this.toolTip.SetToolTip(this.label5, resources.GetString("label5.ToolTip")); // // numericUpDownAngleResolution // - resources.ApplyResources(this.numericUpDownAngleResolution, "numericUpDownAngleResolution"); this.numericUpDownAngleResolution.DecimalPlaces = 1; + resources.ApplyResources(this.numericUpDownAngleResolution, "numericUpDownAngleResolution"); this.numericUpDownAngleResolution.Increment = new decimal(new int[] { 5, 0, @@ -995,7 +934,6 @@ private void InitializeComponent() 0, 65536}); this.numericUpDownAngleResolution.Name = "numericUpDownAngleResolution"; - this.toolTip.SetToolTip(this.numericUpDownAngleResolution, resources.GetString("numericUpDownAngleResolution.ToolTip")); this.numericUpDownAngleResolution.Value = new decimal(new int[] { 2, 0, @@ -1007,7 +945,6 @@ private void InitializeComponent() // resources.ApplyResources(this.label29, "label29"); this.label29.Name = "label29"; - this.toolTip.SetToolTip(this.label29, resources.GetString("label29.ToolTip")); // // numericUpDownAngleSubDivision // @@ -1023,7 +960,6 @@ private void InitializeComponent() 0, 0}); this.numericUpDownAngleSubDivision.Name = "numericUpDownAngleSubDivision"; - this.toolTip.SetToolTip(this.numericUpDownAngleSubDivision, resources.GetString("numericUpDownAngleSubDivision.ToolTip")); this.numericUpDownAngleSubDivision.Value = new decimal(new int[] { 4, 0, @@ -1035,7 +971,6 @@ private void InitializeComponent() // resources.ApplyResources(this.label101, "label101"); this.label101.Name = "label101"; - this.toolTip.SetToolTip(this.label101, resources.GetString("label101.ToolTip")); // // numericUpDownCrystallineSize // @@ -1056,7 +991,6 @@ private void InitializeComponent() 0, 0}); this.numericUpDownCrystallineSize.Name = "numericUpDownCrystallineSize"; - this.toolTip.SetToolTip(this.numericUpDownCrystallineSize, resources.GetString("numericUpDownCrystallineSize.ToolTip")); this.numericUpDownCrystallineSize.Value = new decimal(new int[] { 100, 0, @@ -1068,46 +1002,40 @@ private void InitializeComponent() // resources.ApplyResources(this.label99, "label99"); this.label99.Name = "label99"; - this.toolTip.SetToolTip(this.label99, resources.GetString("label99.ToolTip")); // // tabPageBounds // - resources.ApplyResources(this.tabPageBounds, "tabPageBounds"); this.tabPageBounds.Controls.Add(this.boundControl); + resources.ApplyResources(this.tabPageBounds, "tabPageBounds"); this.tabPageBounds.Name = "tabPageBounds"; - this.toolTip.SetToolTip(this.tabPageBounds, resources.GetString("tabPageBounds.ToolTip")); // // boundControl // - resources.ApplyResources(this.boundControl, "boundControl"); this.boundControl.Crystal = null; + resources.ApplyResources(this.boundControl, "boundControl"); this.boundControl.Name = "boundControl"; this.boundControl.SkipEvent = false; - this.toolTip.SetToolTip(this.boundControl, resources.GetString("boundControl.ToolTip")); // // tabPageLatticePlane // - resources.ApplyResources(this.tabPageLatticePlane, "tabPageLatticePlane"); this.tabPageLatticePlane.Controls.Add(this.latticePlaneControl); + resources.ApplyResources(this.tabPageLatticePlane, "tabPageLatticePlane"); this.tabPageLatticePlane.Name = "tabPageLatticePlane"; - this.toolTip.SetToolTip(this.tabPageLatticePlane, resources.GetString("tabPageLatticePlane.ToolTip")); // // latticePlaneControl // - resources.ApplyResources(this.latticePlaneControl, "latticePlaneControl"); this.latticePlaneControl.Crystal = null; + resources.ApplyResources(this.latticePlaneControl, "latticePlaneControl"); this.latticePlaneControl.Name = "latticePlaneControl"; this.latticePlaneControl.SkipEvent = false; - this.toolTip.SetToolTip(this.latticePlaneControl, resources.GetString("latticePlaneControl.ToolTip")); // // panel1 // - resources.ApplyResources(this.panel1, "panel1"); this.panel1.Controls.Add(this.textBoxFormula); this.panel1.Controls.Add(this.numericBoxZnumber); this.panel1.Controls.Add(this.label90); + resources.ApplyResources(this.panel1, "panel1"); this.panel1.Name = "panel1"; - this.toolTip.SetToolTip(this.panel1, resources.GetString("panel1.ToolTip")); // // textBoxFormula // @@ -1138,7 +1066,6 @@ private void InitializeComponent() // // contextMenuStrip // - resources.ApplyResources(this.contextMenuStrip, "contextMenuStrip"); this.contextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20); this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.scatteringFactorToolStripMenuItem, @@ -1148,90 +1075,90 @@ private void InitializeComponent() this.exportThisCrystalAsCIFToolStripMenuItem, this.sendThisCrystalToOtherSoftwareToolStripMenuItem, this.toolStripSeparator1, - this.clearAllDataToolStripMenuItem, this.revertCellConstantsToolStripMenuItem, this.toolStripSeparator3, this.strainControlToolStripMenuItem, this.convertToP1SymmetryToolStripMenuItem, - this.convertToSuperstructureToolStripMenuItem}); + this.convertToSuperstructureToolStripMenuItem, + this.convertToAnotherSpacegroupToolStripMenuItem}); this.contextMenuStrip.Name = "contextMenuStrip1"; - this.toolTip.SetToolTip(this.contextMenuStrip, resources.GetString("contextMenuStrip.ToolTip")); + resources.ApplyResources(this.contextMenuStrip, "contextMenuStrip"); // // scatteringFactorToolStripMenuItem // - resources.ApplyResources(this.scatteringFactorToolStripMenuItem, "scatteringFactorToolStripMenuItem"); this.scatteringFactorToolStripMenuItem.Name = "scatteringFactorToolStripMenuItem"; + resources.ApplyResources(this.scatteringFactorToolStripMenuItem, "scatteringFactorToolStripMenuItem"); this.scatteringFactorToolStripMenuItem.Click += new System.EventHandler(this.scatteringFactorToolStripMenuItem_Click); // // symmetryInformationToolStripMenuItem // - resources.ApplyResources(this.symmetryInformationToolStripMenuItem, "symmetryInformationToolStripMenuItem"); this.symmetryInformationToolStripMenuItem.Name = "symmetryInformationToolStripMenuItem"; + resources.ApplyResources(this.symmetryInformationToolStripMenuItem, "symmetryInformationToolStripMenuItem"); this.symmetryInformationToolStripMenuItem.Click += new System.EventHandler(this.symmetryInformationToolStripMenuItem_Click); // // toolStripSeparator2 // - resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); this.toolStripSeparator2.Name = "toolStripSeparator2"; + resources.ApplyResources(this.toolStripSeparator2, "toolStripSeparator2"); // // importCrystalFromCIFAMCToolStripMenuItem // - resources.ApplyResources(this.importCrystalFromCIFAMCToolStripMenuItem, "importCrystalFromCIFAMCToolStripMenuItem"); this.importCrystalFromCIFAMCToolStripMenuItem.Name = "importCrystalFromCIFAMCToolStripMenuItem"; + resources.ApplyResources(this.importCrystalFromCIFAMCToolStripMenuItem, "importCrystalFromCIFAMCToolStripMenuItem"); this.importCrystalFromCIFAMCToolStripMenuItem.Click += new System.EventHandler(this.importCrystalFromCIFAMCToolStripMenuItem_Click); // // exportThisCrystalAsCIFToolStripMenuItem // - resources.ApplyResources(this.exportThisCrystalAsCIFToolStripMenuItem, "exportThisCrystalAsCIFToolStripMenuItem"); this.exportThisCrystalAsCIFToolStripMenuItem.Name = "exportThisCrystalAsCIFToolStripMenuItem"; + resources.ApplyResources(this.exportThisCrystalAsCIFToolStripMenuItem, "exportThisCrystalAsCIFToolStripMenuItem"); this.exportThisCrystalAsCIFToolStripMenuItem.Click += new System.EventHandler(this.exportThisCrystalAsCIFToolStripMenuItem_Click); // // sendThisCrystalToOtherSoftwareToolStripMenuItem // - resources.ApplyResources(this.sendThisCrystalToOtherSoftwareToolStripMenuItem, "sendThisCrystalToOtherSoftwareToolStripMenuItem"); this.sendThisCrystalToOtherSoftwareToolStripMenuItem.Name = "sendThisCrystalToOtherSoftwareToolStripMenuItem"; + resources.ApplyResources(this.sendThisCrystalToOtherSoftwareToolStripMenuItem, "sendThisCrystalToOtherSoftwareToolStripMenuItem"); this.sendThisCrystalToOtherSoftwareToolStripMenuItem.Click += new System.EventHandler(this.sendThisCrystalToOtherSoftwareToolStripMenuItem_Click); // // toolStripSeparator1 // - resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); this.toolStripSeparator1.Name = "toolStripSeparator1"; - // - // clearAllDataToolStripMenuItem - // - resources.ApplyResources(this.clearAllDataToolStripMenuItem, "clearAllDataToolStripMenuItem"); - this.clearAllDataToolStripMenuItem.Name = "clearAllDataToolStripMenuItem"; - this.clearAllDataToolStripMenuItem.Click += new System.EventHandler(this.clearAllDataToolStripMenuItem_Click); + resources.ApplyResources(this.toolStripSeparator1, "toolStripSeparator1"); // // revertCellConstantsToolStripMenuItem // - resources.ApplyResources(this.revertCellConstantsToolStripMenuItem, "revertCellConstantsToolStripMenuItem"); this.revertCellConstantsToolStripMenuItem.Name = "revertCellConstantsToolStripMenuItem"; + resources.ApplyResources(this.revertCellConstantsToolStripMenuItem, "revertCellConstantsToolStripMenuItem"); this.revertCellConstantsToolStripMenuItem.Click += new System.EventHandler(this.revertCellConstantsToolStripMenuItem_Click); // // toolStripSeparator3 // - resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); this.toolStripSeparator3.Name = "toolStripSeparator3"; + resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); // // strainControlToolStripMenuItem // - resources.ApplyResources(this.strainControlToolStripMenuItem, "strainControlToolStripMenuItem"); this.strainControlToolStripMenuItem.Name = "strainControlToolStripMenuItem"; + resources.ApplyResources(this.strainControlToolStripMenuItem, "strainControlToolStripMenuItem"); this.strainControlToolStripMenuItem.Click += new System.EventHandler(this.strainControlToolStripMenuItem_Click); // // convertToP1SymmetryToolStripMenuItem // - resources.ApplyResources(this.convertToP1SymmetryToolStripMenuItem, "convertToP1SymmetryToolStripMenuItem"); this.convertToP1SymmetryToolStripMenuItem.Name = "convertToP1SymmetryToolStripMenuItem"; + resources.ApplyResources(this.convertToP1SymmetryToolStripMenuItem, "convertToP1SymmetryToolStripMenuItem"); this.convertToP1SymmetryToolStripMenuItem.Click += new System.EventHandler(this.convertToP1ToolStripMenuItem_Click); // // convertToSuperstructureToolStripMenuItem // - resources.ApplyResources(this.convertToSuperstructureToolStripMenuItem, "convertToSuperstructureToolStripMenuItem"); this.convertToSuperstructureToolStripMenuItem.Name = "convertToSuperstructureToolStripMenuItem"; + resources.ApplyResources(this.convertToSuperstructureToolStripMenuItem, "convertToSuperstructureToolStripMenuItem"); this.convertToSuperstructureToolStripMenuItem.Click += new System.EventHandler(this.convertToSuperstructureToolStripMenuItem_Click); // + // convertToAnotherSpacegroupToolStripMenuItem + // + this.convertToAnotherSpacegroupToolStripMenuItem.Name = "convertToAnotherSpacegroupToolStripMenuItem"; + resources.ApplyResources(this.convertToAnotherSpacegroupToolStripMenuItem, "convertToAnotherSpacegroupToolStripMenuItem"); + this.convertToAnotherSpacegroupToolStripMenuItem.Click += new System.EventHandler(this.convertToAnotherSpacegroupToolStripMenuItem_Click); + // // textBoxName // resources.ApplyResources(this.textBoxName, "textBoxName"); @@ -1242,7 +1169,6 @@ private void InitializeComponent() // resources.ApplyResources(this.label22, "label22"); this.label22.Name = "label22"; - this.toolTip.SetToolTip(this.label22, resources.GetString("label22.ToolTip")); // // buttonScatteringFactor // @@ -1268,22 +1194,20 @@ private void InitializeComponent() // resources.ApplyResources(this.flowLayoutPanel1, "flowLayoutPanel1"); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.toolTip.SetToolTip(this.flowLayoutPanel1, resources.GetString("flowLayoutPanel1.ToolTip")); // // panel4 // - resources.ApplyResources(this.panel4, "panel4"); this.panel4.Controls.Add(this.textBoxName); this.panel4.Controls.Add(this.buttonSymmetryInfo); this.panel4.Controls.Add(this.buttonScatteringFactor); this.panel4.Controls.Add(this.label22); + resources.ApplyResources(this.panel4, "panel4"); this.panel4.Name = "panel4"; - this.toolTip.SetToolTip(this.panel4, resources.GetString("panel4.ToolTip")); // // CrystalControl // - resources.ApplyResources(this, "$this"); this.AllowDrop = true; + resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ContextMenuStrip = this.contextMenuStrip; this.Controls.Add(this.tabControl); @@ -1292,7 +1216,6 @@ private void InitializeComponent() this.Controls.Add(this.flowLayoutPanel1); this.DoubleBuffered = true; this.Name = "CrystalControl"; - this.toolTip.SetToolTip(this, resources.GetString("$this.ToolTip")); this.Load += new System.EventHandler(this.CrystalForm_Load); this.DragDrop += new System.Windows.Forms.DragEventHandler(this.FormCrystal_DragDrop); this.DragEnter += new System.Windows.Forms.DragEventHandler(this.FormCrystal_DragEnter); @@ -1455,8 +1378,9 @@ private void InitializeComponent() private System.Windows.Forms.Button buttonSymmetryInfo; private System.Windows.Forms.Button buttonScatteringFactor; private EOSControl eosControl; - private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button buttonStressSet; private System.Windows.Forms.ToolStripMenuItem convertToP1SymmetryToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem convertToSuperstructureToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem convertToAnotherSpacegroupToolStripMenuItem; } } \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/CrystalControl.cs b/Crystallography.Controls/Crystal/CrystalControl.cs index e91dcf7..79ec113 100644 --- a/Crystallography.Controls/Crystal/CrystalControl.cs +++ b/Crystallography.Controls/Crystal/CrystalControl.cs @@ -1,5 +1,6 @@ #region Using using MathNet.Numerics.LinearAlgebra.Double; +using Microsoft.Scripting.Utils; using System; using System.Collections.Generic; using System.ComponentModel; @@ -8,725 +9,977 @@ using System.Linq; using System.Reflection; using System.Windows.Forms; +using static IronPython.Modules._ast; #endregion -namespace Crystallography.Controls +namespace Crystallography.Controls; + +[TypeConverter(typeof(DefinitionOrderTypeConverter))] +public partial class CrystalControl : UserControl { - [TypeConverter(typeof(DefinitionOrderTypeConverter))] - public partial class CrystalControl : UserControl - { - #region プロパティ、フィールド、イベントハンドラ + #region プロパティ、フィールド、イベントハンドラ - public bool SkipEvent { get; set; } = false; + public bool SkipEvent { get; set; } = false; - public bool SymmetryInformationVisible { set => FormSymmetryInformation.Visible = value; get => FormSymmetryInformation.Visible; } + public bool SymmetryInformationVisible { set => FormSymmetryInformation.Visible = value; get => FormSymmetryInformation.Visible; } - public bool ScatteringFactorVisible { set { FormScatteringFactor.Visible = value; } get => FormScatteringFactor.Visible; } + public bool ScatteringFactorVisible { set { FormScatteringFactor.Visible = value; } get => FormScatteringFactor.Visible; } - public bool StrainControlVisible { get => formStrain.Visible; } + public bool StrainControlVisible { get => formStrain.Visible; } - public int SymmetrySeriesNumber { get => symmetryControl.SymmetrySeriesNumber; set => symmetryControl.SymmetrySeriesNumber = value; } + public int SymmetrySeriesNumber { get => symmetryControl.SymmetrySeriesNumber; set => symmetryControl.SymmetrySeriesNumber = value; } - #region Tabページの表示/非表示プロパティ + #region Tabページの表示/非表示プロパティ - public bool VisibleBasicInfoTab { set { visibleBasicInfoTab = value; setTabPages(); } get => visibleBasicInfoTab; } - private bool visibleBasicInfoTab = true; - public bool VisibleAtomTab { set { visibleAtomTab = value; setTabPages(); } get => visibleAtomTab; } - private bool visibleAtomTab = true; - public bool VisibleElasticityTab { set { visibleElasticityTab = value; setTabPages(); } get { return visibleElasticityTab; } } - private bool visibleElasticityTab = true; + public bool VisibleBasicInfoTab { set { visibleBasicInfoTab = value; setTabPages(); } get => visibleBasicInfoTab; } + private bool visibleBasicInfoTab = true; + public bool VisibleAtomTab { set { visibleAtomTab = value; setTabPages(); } get => visibleAtomTab; } + private bool visibleAtomTab = true; + public bool VisibleElasticityTab { set { visibleElasticityTab = value; setTabPages(); } get { return visibleElasticityTab; } } + private bool visibleElasticityTab = true; - public bool VisibleBondsPolyhedraTab { set { visibleBondsPolyhedraTab = value; setTabPages(); } get => visibleBondsPolyhedraTab; } - private bool visibleBondsPolyhedraTab = true; + public bool VisibleBondsPolyhedraTab { set { visibleBondsPolyhedraTab = value; setTabPages(); } get => visibleBondsPolyhedraTab; } + private bool visibleBondsPolyhedraTab = true; - public bool VisibleReferenceTab { set { visibleReferenceTab = value; setTabPages(); } get => visibleReferenceTab; } - private bool visibleReferenceTab = true; + public bool VisibleReferenceTab { set { visibleReferenceTab = value; setTabPages(); } get => visibleReferenceTab; } + private bool visibleReferenceTab = true; - public bool VisibleEOSTab { set { visibleEOSTab = value; setTabPages(); } get => visibleEOSTab; } - private bool visibleEOSTab = true; + public bool VisibleEOSTab { set { visibleEOSTab = value; setTabPages(); } get => visibleEOSTab; } + private bool visibleEOSTab = true; - public bool VisibleStressStrainTab { set { visibleStressStrainTab = value; setTabPages(); } get => visibleStressStrainTab; } - private bool visibleStressStrainTab = false; + public bool VisibleStressStrainTab { set { visibleStressStrainTab = value; setTabPages(); } get => visibleStressStrainTab; } + private bool visibleStressStrainTab = false; - public bool VisiblePolycrystallineTab { set { visiblePolycrystallineTab = value; setTabPages(); } get => visiblePolycrystallineTab; } - private bool visiblePolycrystallineTab = false; - public bool VisibleBoundTab { set { visibleBoundTab = value; setTabPages(); } get => visibleBoundTab; } - private bool visibleBoundTab = false; - public bool VisibleLatticePlaneTab { set { visibleLatticePlaneTab = value; setTabPages(); } get => visibleLatticePlaneTab; } - private bool visibleLatticePlaneTab = false; + public bool VisiblePolycrystallineTab { set { visiblePolycrystallineTab = value; setTabPages(); } get => visiblePolycrystallineTab; } + private bool visiblePolycrystallineTab = false; + public bool VisibleBoundTab { set { visibleBoundTab = value; setTabPages(); } get => visibleBoundTab; } + private bool visibleBoundTab = false; + public bool VisibleLatticePlaneTab { set { visibleLatticePlaneTab = value; setTabPages(); } get => visibleLatticePlaneTab; } + private bool visibleLatticePlaneTab = false; - private void setTabPages() - { - tabControl.TabPages.Clear(); - if (VisibleBasicInfoTab) tabControl.TabPages.Add(tabPageBasicInfo); - if (VisibleAtomTab) tabControl.TabPages.Add(tabPageAtom); - if (visibleBondsPolyhedraTab) tabControl.TabPages.Add(tabPageBondsPolyhedra); - if (VisibleBoundTab) tabControl.TabPages.Add(tabPageBounds); - if (VisibleLatticePlaneTab) tabControl.TabPages.Add(tabPageLatticePlane); - if (VisibleReferenceTab) tabControl.TabPages.Add(tabPageReference); - if (VisibleEOSTab) tabControl.TabPages.Add(tabPageEOS); - if (VisibleElasticityTab) tabControl.TabPages.Add(tabPageElasticity); - if (VisibleStressStrainTab) tabControl.TabPages.Add(tabPageStrainStress); - if (VisiblePolycrystallineTab) tabControl.TabPages.Add(tabPagePolycrystalline); - } + private void setTabPages() + { + tabControl.TabPages.Clear(); + if (VisibleBasicInfoTab) tabControl.TabPages.Add(tabPageBasicInfo); + if (VisibleAtomTab) tabControl.TabPages.Add(tabPageAtom); + if (visibleBondsPolyhedraTab) tabControl.TabPages.Add(tabPageBondsPolyhedra); + if (VisibleBoundTab) tabControl.TabPages.Add(tabPageBounds); + if (VisibleLatticePlaneTab) tabControl.TabPages.Add(tabPageLatticePlane); + if (VisibleReferenceTab) tabControl.TabPages.Add(tabPageReference); + if (VisibleEOSTab) tabControl.TabPages.Add(tabPageEOS); + if (VisibleElasticityTab) tabControl.TabPages.Add(tabPageElasticity); + if (VisibleStressStrainTab) tabControl.TabPages.Add(tabPageStrainStress); + if (VisiblePolycrystallineTab) tabControl.TabPages.Add(tabPagePolycrystalline); + } - #endregion Tabページの表示/非表示プロパティ + #endregion Tabページの表示/非表示プロパティ - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Crystal Crystal + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Crystal Crystal + { + set { - set + crystal = value; + if (crystal != null) { - crystal = value; - if (crystal != null) + Enabled = !crystal.FlexibleMode; + + SetToInterface(); + //原子位置チェック (strain controlで選択した後、原子位置が変になってしまう問題の修正. 2017/05/29) + if (crystal.ChemicalFormulaZ == 1) { - Enabled = !crystal.FlexibleMode; + for (int i = 0; i < crystal.Atoms.Length; i++) + crystal.Atoms[i].ResetSymmetry(SymmetrySeriesNumber); + crystal.GetFormulaAndDensity(); SetToInterface(); - //原子位置チェック (strain controlで選択した後、原子位置が変になってしまう問題の修正. 2017/05/29) - if (crystal.ChemicalFormulaZ == 1) - { - for (int i = 0; i < crystal.Atoms.Length; i++) - crystal.Atoms[i].ResetSymmetry(SymmetrySeriesNumber); - crystal.GetFormulaAndDensity(); - - SetToInterface(); - } - - CrystalChanged?.Invoke(this, new EventArgs()); } + + CrystalChanged?.Invoke(this, new EventArgs()); } - get => crystal; } - private Crystal crystal; + get => crystal; + } + private Crystal crystal; - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public (double A, double B, double C, double Alpha, double Beta, double Gamma) CellConstants - { get => symmetryControl.CellConstants; set => symmetryControl.CellConstants = value; } + public (double A, double B, double C, double Alpha, double Beta, double Gamma) CellConstants + { get => symmetryControl.CellConstants; set => symmetryControl.CellConstants = value; } - public double A { get => symmetryControl.A; set => symmetryControl.A = value; } - public double B { get => symmetryControl.B; set => symmetryControl.B = value; } - public double C { get => symmetryControl.C; set => symmetryControl.C = value; } - public double Alpha { get => symmetryControl.Alpha; set => symmetryControl.Alpha = value; } - public double Beta { get => symmetryControl.Beta; set => symmetryControl.Beta = value; } - public double Gamma { get => symmetryControl.Gamma; set => symmetryControl.Gamma = value; } + public double A { get => symmetryControl.A; set => symmetryControl.A = value; } + public double B { get => symmetryControl.B; set => symmetryControl.B = value; } + public double C { get => symmetryControl.C; set => symmetryControl.C = value; } + public double Alpha { get => symmetryControl.Alpha; set => symmetryControl.Alpha = value; } + public double Beta { get => symmetryControl.Beta; set => symmetryControl.Beta = value; } + public double Gamma { get => symmetryControl.Gamma; set => symmetryControl.Gamma = value; } - public int DefaultTabNumber { set => tabControl.SelectedIndex = value; get => tabControl.SelectedIndex; } + public int DefaultTabNumber { set => tabControl.SelectedIndex = value; get => tabControl.SelectedIndex; } - public event EventHandler CrystalChanged; + public event EventHandler CrystalChanged; - public FormScatteringFactor FormScatteringFactor; - public FormSymmetryInformation FormSymmetryInformation; - //private FormAtomDetailedInfo formAtomDetailedInfo; + public FormScatteringFactor FormScatteringFactor; + public FormSymmetryInformation FormSymmetryInformation; + //private FormAtomDetailedInfo formAtomDetailedInfo; - public FormStrain formStrain; + public FormStrain formStrain; - //候補の数値 - //private readonly double[] rationalNumbers - // = new double[] { 1.0 / 12.0, 1.0 / 8.0, 1.0 / 6.0, 1.0 / 4.0, 1.0 / 3.0, 3.0 / 8.0, 5.0 / 12.0, 1.0 / 2.0, 7.0 / 12.0, 5.0 / 8.0, 2.0 / 3.0, 3.0 / 4.0, 5.0 / 6.0, 7.0 / 8.0, 11.0 / 12.0 }; + //候補の数値 + //private readonly double[] rationalNumbers + // = new double[] { 1.0 / 12.0, 1.0 / 8.0, 1.0 / 6.0, 1.0 / 4.0, 1.0 / 3.0, 3.0 / 8.0, 5.0 / 12.0, 1.0 / 2.0, 7.0 / 12.0, 5.0 / 8.0, 2.0 / 3.0, 3.0 / 4.0, 5.0 / 6.0, 7.0 / 8.0, 11.0 / 12.0 }; - #endregion + #endregion - #region コンストラクタ、Loadイベント - public CrystalControl() - { - InitializeComponent(); + #region コンストラクタ、Loadイベント + public CrystalControl() + { + InitializeComponent(); - FormScatteringFactor = new FormScatteringFactor { CrystalControl = this, Visible = false }; - FormSymmetryInformation = new FormSymmetryInformation { CrystalControl = this, Visible = false }; - formStrain = new FormStrain { CrystalControl = this, Visible = false }; - } + FormScatteringFactor = new FormScatteringFactor { CrystalControl = this, Visible = false }; + FormSymmetryInformation = new FormSymmetryInformation { CrystalControl = this, Visible = false }; + formStrain = new FormStrain { CrystalControl = this, Visible = false }; + } - private void CrystalForm_Load(object sender, System.EventArgs e) - { - textBoxTitle.Size = new Size(tabPageReference.Width - textBoxTitle.Location.X - 2, tabPageReference.Height - textBoxTitle.Location.Y - 2); - FormScatteringFactor.VisibleChanged += new EventHandler(formScatteringFactor_VisibleChanged); - FormSymmetryInformation.VisibleChanged += new EventHandler(formSymmetryInformation_VisibleChanged); + private void CrystalForm_Load(object sender, System.EventArgs e) + { + textBoxTitle.Size = new Size(tabPageReference.Width - textBoxTitle.Location.X - 2, tabPageReference.Height - textBoxTitle.Location.Y - 2); + FormScatteringFactor.VisibleChanged += new EventHandler(formScatteringFactor_VisibleChanged); + FormSymmetryInformation.VisibleChanged += new EventHandler(formSymmetryInformation_VisibleChanged); - typeof(UserControl).GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, true, null); + typeof(UserControl).GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, true, null); - } + } - #endregion + #endregion - #region イベントハンドラ + #region イベントハンドラ - public event EventHandler ScatteringFactor_VisibleChanged; - public event EventHandler SymmetryInformation_VisibleChanged; + public event EventHandler ScatteringFactor_VisibleChanged; + public event EventHandler SymmetryInformation_VisibleChanged; - #endregion + #endregion - #region Crystalクラスを画面下部 から生成/にセット + #region Crystalクラスを画面下部 から生成/にセット + /// + /// Formに入力された内容からからCrystalを生成する + /// + public void GenerateFromInterface() + { + if (SkipEvent) return; + SkipEvent = true; - /// - /// Formに入力された内容からからCrystalを生成する - /// - public void GenerateFromInterface() + var (A, B, C, Alpha, Beta, Gamma) = symmetryControl.CellConstants; + if (A < 0 || B < 0 || C < 0 || Alpha > Math.PI || Beta > Math.PI || Gamma > Math.PI) { - if (SkipEvent) return; - SkipEvent = true; + SkipEvent = false; + MessageBox.Show("Input valid cell constants"); + return; + } - var (A, B, C, Alpha, Beta, Gamma) = symmetryControl.CellConstants; - if (A < 0 || B < 0 || C < 0 || Alpha > Math.PI || Beta > Math.PI || Gamma > Math.PI) - { - SkipEvent = false; - MessageBox.Show("Input valid cell constants"); - return; - } + //対称性が変更されているかもしれないので原子も改めて設定しなおす。 + atomControl.ResetSymmetry(SymmetrySeriesNumber); + + var rot = crystal != null ? crystal.RotationMatrix : new Matrix3D(); - //対称性が変更されているかもしれないので原子も改めて設定しなおす。 - atomControl.ResetSymmetry(SymmetrySeriesNumber); + crystal = new Crystal( + symmetryControl.CellConstants, symmetryControl.CellConstantsErr, + SymmetrySeriesNumber, textBoxName.Text, colorControl.Color, rot, atomControl.GetAll(), + (textBoxMemo.Text, textBoxAuthor.Text, textBoxJournal.Text, textBoxTitle.Text), + bondControl.GetAll(), boundControl.GetAll(), latticePlaneControl.GetAll(), eosControl.EOScondition); - var rot = crystal != null ? crystal.RotationMatrix : new Matrix3D(); + crystal.ElasticStiffness = elasticityControl1.Stiffness.ToArray(); - crystal = new Crystal( - symmetryControl.CellConstants, symmetryControl.CellConstantsErr, - SymmetrySeriesNumber, textBoxName.Text, colorControl.Color, rot, atomControl.GetAll(), - (textBoxMemo.Text, textBoxAuthor.Text, textBoxJournal.Text, textBoxTitle.Text), - bondControl.GetAll(), boundControl.GetAll(), latticePlaneControl.GetAll(), eosControl.EOScondition); + #region PolyCrystallineProperty + crystal.AngleResolution = (double)numericUpDownAngleResolution.Value; + crystal.SubDivision = (int)numericUpDownAngleSubDivision.Value; + crystal.GrainSize = (double)numericUpDownCrystallineSize.Value; + if (poleFigureControl.Crystal != null) + crystal.Crystallites = poleFigureControl.Crystal.Crystallites; - crystal.ElasticStiffness = elasticityControl1.Stiffness.ToArray(); + crystal.Strain = new Matrix3D( + numericBoxStrain11.Value, numericBoxStrain12.Value, numericBoxStrain13.Value, + numericBoxStrain12.Value, numericBoxStrain22.Value, numericBoxStrain23.Value, + numericBoxStrain13.Value, numericBoxStrain23.Value, numericBoxStrain33.Value); + crystal.HillCoefficient = numericBoxHill.Value; - #region PolyCrystallineProperty - crystal.AngleResolution = (double)numericUpDownAngleResolution.Value; - crystal.SubDivision = (int)numericUpDownAngleSubDivision.Value; - crystal.GrainSize = (double)numericUpDownCrystallineSize.Value; - if (poleFigureControl.Crystal != null) - crystal.Crystallites = poleFigureControl.Crystal.Crystallites; + #endregion - crystal.Strain = new Matrix3D( - numericBoxStrain11.Value, numericBoxStrain12.Value, numericBoxStrain13.Value, - numericBoxStrain12.Value, numericBoxStrain22.Value, numericBoxStrain23.Value, - numericBoxStrain13.Value, numericBoxStrain23.Value, numericBoxStrain33.Value); - crystal.HillCoefficient = numericBoxHill.Value; + SkipEvent = false; + SetToInterface(false); - #endregion + CrystalChanged?.Invoke(this, new EventArgs()); + } - SkipEvent = false; - SetToInterface(false); - CrystalChanged?.Invoke(this, new EventArgs()); - } + /// + /// 現在のCrystalによってFormのテキストボックスなどを設定する。 + /// + /// コントロールのCellParaterを変化させた時はFalse + public void SetToInterface(bool ChangeCellParameter = true) + { + if (SkipEvent) return; + SkipEvent = true; + + SuspendLayout(); + colorControl.Color = Color.FromArgb(Crystal.Argb); + textBoxName.Text = Crystal.Name; + textBoxMemo.Text = Crystal.Note; - /// - /// 現在のCrystalによってFormのテキストボックスなどを設定する。 - /// - /// コントロールのCellParaterを変化させた時はFalse - public void SetToInterface(bool ChangeCellParameter = true) + textBoxAuthor.Text = Crystal.PublAuthorName; + textBoxJournal.Text = Crystal.Journal; + textBoxFormula.Text = Crystal.ChemicalFormulaSum; + textBoxTitle.Text = Crystal.PublSectionTitle; + + numericBoxDensity.Value = Crystal.Density; + numericBoxVolume.Value = Crystal.Volume * 1000; + numericBoxMolarVolume.Value = Crystal.Volume * UniversalConstants.A / Crystal.ChemicalFormulaZ * 1E-21; + numericBoxZnumber.Value = Crystal.ChemicalFormulaZ; + + numericBoxMolarMass.Value = numericBoxDensity.Value * numericBoxMolarVolume.Value; + numericBoxCellMass.Value = numericBoxDensity.Value * numericBoxVolume.Value; + + SymmetrySeriesNumber = Crystal.SymmetrySeriesNumber;//SymmetrySeriesNumberをフィールドからプロパティに変更。set{}の所でコンボボックスをセットする。(20170526) + + if (ChangeCellParameter) { - if (SkipEvent) return; - SkipEvent = true; + symmetryControl.CellConstants = (Crystal.A, Crystal.B, Crystal.C, Crystal.Alpha, Crystal.Beta, Crystal.Gamma); + symmetryControl.CellConstantsErr = (Crystal.A_err, Crystal.B_err, Crystal.C_err, Crystal.Alpha_err, Crystal.Beta_err, Crystal.Gamma_err); + } - colorControl.Color = Color.FromArgb(Crystal.Argb); - textBoxName.Text = Crystal.Name; - textBoxMemo.Text = Crystal.Note; + //Atomsコントロール + atomControl.Crystal = crystal; - textBoxAuthor.Text = Crystal.PublAuthorName; - textBoxJournal.Text = Crystal.Journal; - textBoxFormula.Text = Crystal.ChemicalFormulaSum; - textBoxTitle.Text = Crystal.PublSectionTitle; + //Bondコントロール + bondControl.Crystal = crystal; - numericBoxDensity.Value = Crystal.Density; - numericBoxVolume.Value = Crystal.Volume * 1000; - numericBoxMolarVolume.Value = Crystal.Volume * UniversalConstants.A / Crystal.ChemicalFormulaZ * 1E-21; - numericBoxZnumber.Value = Crystal.ChemicalFormulaZ; + //Boundsコントロール + boundControl.Crystal = crystal; - numericBoxMolarMass.Value = numericBoxDensity.Value * numericBoxMolarVolume.Value; - numericBoxCellMass.Value = numericBoxDensity.Value * numericBoxVolume.Value; + //LatticePlaneコントロール + latticePlaneControl.Crystal = crystal; - SymmetrySeriesNumber = Crystal.SymmetrySeriesNumber;//SymmetrySeriesNumberをフィールドからプロパティに変更。set{}の所でコンボボックスをセットする。(20170526) + //EOS関連 + eosControl.Crystal = crystal; - if (ChangeCellParameter) - { - symmetryControl.CellConstants = (Crystal.A, Crystal.B, Crystal.C, Crystal.Alpha, Crystal.Beta, Crystal.Gamma); - symmetryControl.CellConstantsErr = (Crystal.A_err, Crystal.B_err, Crystal.C_err, Crystal.Alpha_err, Crystal.Beta_err, Crystal.Gamma_err); - } - //Atomsコントロール - atomControl.Crystal = crystal; + //弾性定数関連 + elasticityControl1.Stiffness = DenseMatrix.OfArray(crystal.ElasticStiffness); - //Bondコントロール - bondControl.Crystal = crystal; + //PolyCrystallineProperty関連 + numericUpDownAngleResolution.Value = Math.Min((decimal)crystal.AngleResolution, numericUpDownAngleResolution.Maximum); + numericUpDownAngleSubDivision.Value = crystal.SubDivision; + poleFigureControl.Crystal = crystal; - //Boundsコントロール - boundControl.Crystal = crystal; + SkipEvent = false; - //LatticePlaneコントロール - latticePlaneControl.Crystal = crystal; + ResumeLayout(); + } - //EOS関連 - eosControl.Crystal = crystal; + #endregion + public void ReadCrystal(string filename) + { + try { Crystal = ConvertCrystalData.ConvertToCrystal(filename); } + catch (Exception ex) { if (AssemblyState.IsDebug) MessageBox.Show(ex.ToString()); return; } + } - //弾性定数関連 - elasticityControl1.Stiffness = DenseMatrix.OfArray(crystal.ElasticStiffness); + #region ドラッグドロップイベント - //PolyCrystallineProperty関連 - numericUpDownAngleResolution.Value = Math.Min((decimal)crystal.AngleResolution, numericUpDownAngleResolution.Maximum); - numericUpDownAngleSubDivision.Value = (decimal)crystal.SubDivision; - poleFigureControl.Crystal = crystal; + public void FormCrystal_DragDrop(object sender, DragEventArgs e) + { + string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); + if (fileName.Length == 1) + ReadCrystal(fileName[0]); + } - SkipEvent = false; + private void FormCrystal_DragEnter(object sender, DragEventArgs e) + { + e.Effect = (e.Data.GetData(DataFormats.FileDrop) != null) ? DragDropEffects.Copy : DragDropEffects.None; + } - } + #endregion ドラッグドロップイベント - #endregion + #region 右クリックメニュー + private void importCrystalFromCIFAMCToolStripMenuItem_Click(object sender, EventArgs e) + { + var dlg = new OpenFileDialog { Filter = " *.cif; *.amc | *.cif;*.amc" }; + if (dlg.ShowDialog() == DialogResult.OK) + ReadCrystal(dlg.FileName); + } - public void ReadCrystal(string filename) + public void exportThisCrystalAsCIFToolStripMenuItem_Click(object sender, EventArgs e) + { + if (Crystal != null) { - try { Crystal = ConvertCrystalData.ConvertToCrystal(filename); } - catch (Exception ex) { if (AssemblyState.IsDebug) MessageBox.Show(ex.ToString()); return; } + var dlg = new SaveFileDialog { Filter = " *.cif| *.cif" }; + if (dlg.ShowDialog() == DialogResult.OK) + { + var sw = new StreamWriter(dlg.FileName, false); + var str = ConvertCrystalData.ConvertToCIF(Crystal); + sw.Write(str); + sw.Close(); + } } + } - #region ドラッグドロップイベント + private void scatteringFactorToolStripMenuItem_Click(object sender, EventArgs e) + => FormScatteringFactor.Visible = !FormScatteringFactor.Visible; - public void FormCrystal_DragDrop(object sender, DragEventArgs e) - { - string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); - if (fileName.Length == 1) - ReadCrystal(fileName[0]); - } + private void symmetryInformationToolStripMenuItem_Click(object sender, EventArgs e) + => FormSymmetryInformation.Visible = !FormSymmetryInformation.Visible; - private void FormCrystal_DragEnter(object sender, DragEventArgs e) - { - e.Effect = (e.Data.GetData(DataFormats.FileDrop) != null) ? DragDropEffects.Copy : DragDropEffects.None; - } + private void sendThisCrystalToOtherSoftwareToolStripMenuItem_Click(object sender, EventArgs e) + { + GenerateFromInterface(); + if (crystal != null) + Clipboard.SetDataObject(Crystal2.FromCrystal(crystal), true, 3, 10); + } - #endregion ドラッグドロップイベント + private void resetToolStripMenuItem_Click(object sender, EventArgs e) + { + for (int i = 0; i < crystal.Atoms.Length; i++) + crystal.Atoms[i].Dsf = new DiffuseScatteringFactor(DiffuseScatteringFactor.Type.B, true, 0, 0, null, null, Crystal.CellValue); + } + + private void revertCellConstantsToolStripMenuItem_Click(object sender, EventArgs e) + { + crystal.RevertInitialCellConstants(); + Crystal = crystal; + } - #region 右クリックメニュー + private void strainControlToolStripMenuItem_Click(object sender, EventArgs e) + { + if (formStrain.crystal == null) + formStrain.crystal = Crystal; - private void importCrystalFromCIFAMCToolStripMenuItem_Click(object sender, EventArgs e) + formStrain.Visible = !formStrain.Visible; + } + + /// + /// 空間群P1に変換 + /// + /// + /// + private void convertToP1ToolStripMenuItem_Click(object sender, EventArgs e) => toSuperStructure(1, 1, 1); + + //超構造に変換 + private void convertToSuperstructureToolStripMenuItem_Click(object sender, EventArgs e) + { + var dlg = new FormSuperStructure(); + if (dlg.ShowDialog() == DialogResult.OK) + toSuperStructure(dlg.A, dlg.B, dlg.C); + } + private void convertToAnotherSpacegroupToolStripMenuItem_Click(object sender, EventArgs e) + { + var seriesNum = symmetryControl.SymmetrySeriesNumber; + var spNum = SymmetryStatic.NumArray[seriesNum][1]; + + var list = new List<(int SeriesNum, string Notation)>(); + foreach (var n in SymmetryStatic.NumArray) + if (spNum == n[1] && seriesNum != n[0]) + list.Add((n[0], SymmetryStatic.StrArray[n[0]][3]));//自分自身を除く、同じ空間群番号のものを追加 + + if (list.Count == 0 || spNum == 1 || spNum == 2)//候補がゼロかP1かP-1は除く + MessageBox.Show("No candidate for the space group"); + else { - var dlg = new OpenFileDialog { Filter = " *.cif; *.amc | *.cif;*.amc" }; + var dlg = new FormAnotherSpaceGroup() { Candidates = list.ToArray() }; if (dlg.ShowDialog() == DialogResult.OK) - ReadCrystal(dlg.FileName); + toAnotherSpaceGroup(dlg.SeriesNum); } + } + #endregion 右クリックメニュー + + #region 空間群を変換する関数群 + + #region 超構造に変換 + /// + /// 超構造に変換する関数 + /// + /// + /// + /// + private void toSuperStructure(int _u, int _v, int _w) + { + GenerateFromInterface(); + crystal.SymmetrySeriesNumber = 1; - public void exportThisCrystalAsCIFToolStripMenuItem_Click(object sender, EventArgs e) + var temp_atoms = new List(); + foreach (var atoms in Crystal.Atoms) { - if (Crystal != null) + int n = 0; + foreach (var atom in atoms.Atom) { - var dlg = new SaveFileDialog { Filter = " *.cif| *.cif" }; - if (dlg.ShowDialog() == DialogResult.OK) - { - var sw = new StreamWriter(dlg.FileName, false); - var str = ConvertCrystalData.ConvertToCIF(Crystal); - sw.Write(str); - sw.Close(); - } + for (double u = 0; u < _u; u++) + for (double v = 0; v < _v; v++) + for (double w = 0; w < _w; w++) + { + var x = (atom.X + u) / _u; + var y = (atom.Y + v) / _v; + var z = (atom.Z + w) / _w; + + var x_err = atoms.X_err / _u; + var y_err = atoms.Y_err / _v; + var z_err = atoms.Z_err / _w; + + temp_atoms.Add(new Atoms( + atoms.Label.TrimEnd() + "_" + n.ToString(), + atoms.AtomicNumber, atoms.SubNumberXray, atoms.SubNumberElectron, atoms.Isotope, + 1, + new Vector3DBase(x, y, z), new Vector3DBase(x_err, y_err, z_err), + atoms.Occ, atoms.Occ_err, + atoms.Dsf, + atoms.Material, + atoms.Radius, atoms.GLEnabled, atoms.ShowLabel)); + n++; + } } } + crystal.A *= _u; + crystal.B *= _v; + crystal.C *= _w; + crystal.Atoms = temp_atoms.ToArray(); - private void scatteringFactorToolStripMenuItem_Click(object sender, EventArgs e) - => FormScatteringFactor.Visible = !FormScatteringFactor.Visible; - - private void symmetryInformationToolStripMenuItem_Click(object sender, EventArgs e) - => FormSymmetryInformation.Visible = !FormSymmetryInformation.Visible; - - private void sendThisCrystalToOtherSoftwareToolStripMenuItem_Click(object sender, EventArgs e) + SetToInterface(true); + GenerateFromInterface(); + } + #endregion + + #region 別の空間群に変換 + /// + /// 別の空間群に変換する 原子位置や格子定数のエラー、および熱散漫散乱因子の変換は考慮していない + /// + /// + /// + public void toAnotherSpaceGroup(int destNum) + { + var srcNum = symmetryControl.SymmetrySeriesNumber; + var crystalSystem = SymmetryStatic.NumArray[srcNum][5]; + var sgNum = SymmetryStatic.NumArray[srcNum][1]; + var srcExtra = SymmetryStatic.StrArray[srcNum][0]; + var dstExtra = SymmetryStatic.StrArray[destNum][0]; + + #region monoclinicの時。軸の変換のみがあり得る。 + if (crystalSystem == 2) { - GenerateFromInterface(); - if (crystal != null) - Clipboard.SetDataObject(Crystal2.FromCrystal(crystal), true, 3, 10); + if (srcExtra.Length == 1) srcExtra += "1"; + if (dstExtra.Length == 1) dstExtra += "1"; + + var cry = Deep.Copy(Crystal); + cry.SymmetrySeriesNumber = destNum; + cry.SetAxis(); + foreach (var a in cry.Atoms) + { + (a.X, a.Y, a.Z) = exchangeAtomPositionMonoclinic(a.X, a.Y, a.Z, srcExtra, false);//標準セッティングに変換 + (a.X, a.Y, a.Z) = exchangeAtomPositionMonoclinic(a.X, a.Y, a.Z, dstExtra, true);//目的セッティングに変換 + } + var (A, B, C) = convertAxisMonoclinic(cry.A_Axis, cry.B_Axis, cry.C_Axis, srcExtra, false);//標準セッティングに変換 + (A, B, C) = convertAxisMonoclinic(A, B, C, dstExtra, true);//目的セッティングに変換 + cry.A = A.Length; cry.B = B.Length; cry.C = C.Length; + cry.Alpha = Vector3D.AngleBetVectors(B, C); + cry.Beta = Vector3D.AngleBetVectors(C, A); + cry.Gamma = Vector3D.AngleBetVectors(A, B); + crystal = cry; } + #endregion - private void resetToolStripMenuItem_Click(object sender, EventArgs e) + #region Orhorhombicの時. 軸の変換とOrigin Choiceの変換があり得る + if (crystalSystem == 3) { - for (int i = 0; i < crystal.Atoms.Length; i++) - crystal.Atoms[i].Dsf = new DiffuseScatteringFactor(DiffuseScatteringFactor.Type.B, true, 0, 0, null, null, Crystal.CellValue); + var src = convOrtho(srcExtra); + var dst = convOrtho(dstExtra); + + var cry = Deep.Copy(Crystal); + cry.SymmetrySeriesNumber = destNum; + foreach (var a in cry.Atoms) + { + //標準セッティングに変換 + (a.X, a.Y, a.Z) = exchangeOrtho(a.X, a.Y, a.Z, src.Setting); + (a.X_err, a.Y_err, a.Z_err) = exchangeOrtho(a.X_err, a.Y_err, a.Z_err, src.Setting); + //Originの処理 + if (src.Origin != dst.Origin) + (a.X, a.Y, a.Z) = shift(a.X, a.Y, a.Z, sgNum, src.Origin == 1); + //目的セッティングに変換 + (a.X, a.Y, a.Z) = exchangeOrtho(a.X, a.Y, a.Z, dst.Setting, true); + (a.X_err, a.Y_err, a.Z_err) = exchangeOrtho(a.X_err, a.Y_err, a.Z_err, dst.Setting, true); + } + (cry.A, cry.B, cry.C) = exchangeOrtho(cry.A, cry.B, cry.C, src.Setting, false, true);//標準セッティングに変換 + (cry.A, cry.B, cry.C) = exchangeOrtho(cry.A, cry.B, cry.C, dst.Setting, true, true);//目的セッティングに変換 + crystal = cry; } + #endregion - private void revertCellConstantsToolStripMenuItem_Click(object sender, EventArgs e) + #region Tetragonal か Cubicの時。 Origin Choiceの変換があり得る。 + if (crystalSystem == 4 || crystalSystem == 7) { - crystal.RevertInitialCellConstants(); - Crystal = crystal; + var src = convOrtho(srcExtra); + var cry = Deep.Copy(Crystal); + cry.SymmetrySeriesNumber = destNum; + foreach (var a in cry.Atoms) + (a.X, a.Y, a.Z) = shift(a.X, a.Y, a.Z, sgNum, src.Origin == 1); + crystal = cry; } + #endregion - private void strainControlToolStripMenuItem_Click(object sender, EventArgs e) + #region trigonalの時 RhomboとHexaの変換がありうる。 + if (crystalSystem == 5) { - if (formStrain.crystal == null) - formStrain.crystal = Crystal; + var cry = Deep.Copy(Crystal); + cry.SymmetrySeriesNumber = destNum; + cry.SetAxis(); - formStrain.Visible = !formStrain.Visible; + Vector3D srcA = cry.A_Axis, srcB = cry.B_Axis, srcC = cry.C_Axis, dstA, dstB, dstC; + + if (srcExtra == "H") + {//HをRに変換 + foreach (var a in cry.Atoms) + (a.X, a.Y, a.Z) = (a.X + a.Z, -a.X + a.Y + a.Z, a.Y + a.Z);//Rセッティングに変換 + (dstA, dstB, dstC) = ((2 * srcA + srcB + srcC) / 3, (-srcA + srcB + srcC) / 3, (-srcA - srcB + srcC) / 3); + } + else + {//RをHに変換 + foreach (var a in cry.Atoms) + (a.X, a.Y, a.Z) = ((2 * a.X - a.Y - a.Z) / 3, (a.X + a.Y - 2 * a.Z) / 3, (a.X + a.Y + a.Z) / 3);//Hセッティングに変換 + (dstA, dstB, dstC) = (srcA - srcB, srcB - srcC, srcA + srcB + srcC); + } + cry.A = dstA.Length; cry.B = dstB.Length; cry.C = dstC.Length; + cry.Alpha = Vector3D.AngleBetVectors(dstB, dstC); + cry.Beta = Vector3D.AngleBetVectors(dstC, dstA); + cry.Gamma = Vector3D.AngleBetVectors(dstA, dstB); + crystal = cry; } + #endregion - /// - /// 空間群P1に変換 - /// - /// - /// - private void convertToP1ToolStripMenuItem_Click(object sender, EventArgs e) + SetToInterface(true); + GenerateFromInterface(); + } + #endregion + + #region Origin choiceを変更する関数 + static (double X, double Y, double Z) shift(double x, double y, double z, int sgNum, bool to2nd) + => sgNum switch + { + 48 or 86 or 126 or 201 or 222 or 224 => to2nd ? (x + one4th, y + one4th, z + one4th) : (x - one4th, y - one4th, z - one4th), + 50 or 59 or 125 => to2nd ? (x + one4th, y + one4th, z) : (x - one4th, y - one4th, z), + 68 => to2nd ? (x, y + one4th, z + one4th) : (x, y - one4th, z - one4th), + 70 => to2nd ? (x + one8th, y + one8th, z + one8th) : (x - one8th, y - one8th, z - one8th), + 85 => to2nd ? (x + one4th, y - one4th, z) : (x - one4th, y + one4th, z), + 88 => to2nd ? (x, y + one4th, z + one8th) : (x, y - one4th, z - one8th), + 129 or 130 => to2nd ? (x - one4th, y + one4th, z) : (x + one4th, y - one4th, z), + 133 or 137 or 138 => to2nd ? (x - one4th, y + one4th, z - one4th) : (x + one4th, y - one4th, z + one4th), + 134 => to2nd ? (x + one4th, y - one4th, z + one4th) : (x - one4th, y + one4th, z - one4th), + 141 => to2nd ? (x, y - one4th, z + one8th) : (x, y + one4th, z - one8th), + 142 => to2nd ? (x, y + one4th, z + three8th) : (x, y - one4th, z - three8th), + 203 or 227 or 228 => to2nd ? (x + one8th, y + one8th, z + one8th) : (x - one8th, y - one8th, z - one8th), + _ => (x, y, z) + }; + const double one4th = 1.0 / 4.0, one8th = 1.0 / 8.0, three8th = 3.0 / 8.0; + #endregion + + #region Monoclinic用の関数 + /// + /// 原子位置を変換。Monoclinic用。 + /// + /// + /// + /// + /// + /// + /// + static (double X, double Y, double Z) exchangeAtomPositionMonoclinic(double x, double y, double z, string setting, bool forward = true) + => setting switch + { + "b2" => forward ? (-z, y, x - z) : (z - x, y, -x), + "b3" => forward ? (z - x, y, -x) : (-z, y, x - z), + "-b1" => forward ? (-z, y, x) : (z, y, -x), + "-b2" => forward ? (x + z, y, z) : (x - z, y, z), + "-b3" => forward ? (-x, y, -z - x) : (-x, y, x - z), + + "c1" => forward ? (z, x, y) : (y, z, x), + "c2" => forward ? (x - z, -z, y) : (x - y, z, -y), + "c3" => forward ? (-x, z - x, y) : (-x, z, y - x), + "-c1" => forward ? (x, -z, y) : (x, z, -y), + "-c2" => forward ? (z, x + z, y) : (y - x, z, x), + "-c3" => forward ? (-z - x, -x, y) : (-y, z, y - x), + + "a1" => forward ? (y, z, x) : (z, x, y), + "a2" => forward ? (y, x - z, -z) : (y - z, x, -z), + "a3" => forward ? (y, -x, z - x) : (-y, x, z - y), + "-a1" => forward ? (y, x, -z) : (y, x, -z), + "-a2" => forward ? (y, z, x + z) : (z - y, x, y), + "-a3" => forward ? (y, -z - x, -x) : (-z, x, z - y), + _ => (x, y, z), + }; + + static (Vector3D A, Vector3D B, Vector3D C) convertAxisMonoclinic(Vector3D a, Vector3D b, Vector3D c, string setting, bool forward = true) + => setting switch + { + "b2" => forward ? (-c - a, b, a) : (c, b, -c - a), + "b3" => forward ? (c, b, -c - a) : (-c - a, b, a), + "-b1" => forward ? (-c, b, a) : (c, b, -a), + "-b2" => forward ? (a, b, c - a) : (a, b, c + a), + "-b3" => forward ? (c - a, b, -c) : (-c - a, b, -c), + + "c1" => forward ? (c, a, b) : (b, c, a), + "c2" => forward ? (a, -c - a, b) : (a, c, -a - b), + "c3" => forward ? (-c - a, c, b) : (-a - b, c, b), + "-c1" => forward ? (a, -c, b) : (a, c, -b), + "-c2" => forward ? (c - a, a, b) : (b, c, a + b), + "-c3" => forward ? (-c, c - a, b) : (-a - b, c, -a), + + "a1" => forward ? (b, c, a) : (c, a, b), + "a2" => forward ? (b, a, -c - a) : (b, a, -b - c), + "a3" => forward ? (b, -c - a, c) : (-b - c, a, c), + "-a1" => forward ? (b, a, -c) : (b, a, -c), + "-a2" => forward ? (b, c - a, a) : (c, a, b + c), + "-a3" => forward ? (b, -c, c - a) : (-b - c, a, -b), + _ => (a, b, c), + }; + #endregion + + #region Orthorhombic 用の関数 + static (double X, double Y, double Z) exchangeOrtho(double x, double y, double z, int[] setting, bool inverse = false, bool abs = false) + { + double[] src = new[] { x, y, z }, dst = new double[3]; + for (int i = 0; i < 3; i++) { - toSuperStructure(1, 1, 1); + if (!inverse) + dst[Math.Abs(setting[i]) - 1] = setting[i] > 0 ? src[i] : -src[i]; + else + dst[i] = setting[i] > 0 ? src[Math.Abs(setting[i]) - 1] : -src[Math.Abs(setting[i]) - 1]; } - - //超構造に変換 - private void convertToSuperstructureToolStripMenuItem_Click(object sender, EventArgs e) + return abs ? (Math.Abs(dst[0]), Math.Abs(dst[1]), Math.Abs(dst[2])) : (dst[0], dst[1], dst[2]); + } + static (int Origin, int[] Setting) convOrtho(string s) // extra文字列を解析可能な形に変換する。例えば2ba-cを(2, {2, 1, -3}) + { + if (s.Length == 0) return (1, new[] { 1, 2, 3 }); + int origin = 1; + if (s[0] == '1' || s[0] == '2')//OriginChoiceの変換があり得るのは、48, 50, 59, 68, 70, { - var dlg = new FormSuperStructure(); - if (dlg.ShowDialog() == DialogResult.OK) - toSuperStructure(dlg.A, dlg.B, dlg.C); + origin = s[0] == '1' ? 1 : 2; + s = s[1..]; } + if (s.Length == 0) return (origin, new[] { 1, 2, 3 }); - private void toSuperStructure(int _u, int _v, int _w) + int[] setting = new int[3]; + for (int i = 0; i < 3; i++) { - GenerateFromInterface(); - crystal.SymmetrySeriesNumber = 1; + setting[i] = s[0] != '-' ? 1 : -1; + if (s[0] == '-') + s = s[1..]; + setting[i] *= s[0] switch { 'a' => 1, 'b' => 2, _ => 3 }; + s = s[1..]; + } + return (origin, setting); + } + #endregion - var temp_atoms = new List(); - foreach (var atoms in Crystal.Atoms) - { - int n = 0; - foreach (var atom in atoms.Atom) - { - for (double u = 0; u < _u; u++) - for (double v = 0; v < _v; v++) - for (double w = 0; w < _w; w++) - { - var x = (atom.X + u) / _u; - var y = (atom.Y + v) / _v; - var z = (atom.Z + w) / _w; - - var x_err = atoms.X_err / _u; - var y_err = atoms.Y_err / _v; - var z_err = atoms.Z_err / _w; - - temp_atoms.Add(new Atoms( - atoms.Label.TrimEnd() + "_" + n.ToString(), - atoms.AtomicNumber, atoms.SubNumberXray, atoms.SubNumberElectron, atoms.Isotope, - 1, - new Vector3DBase(x, y, z), new Vector3DBase(x_err, y_err, z_err), - atoms.Occ, atoms.Occ_err, - atoms.Dsf, - atoms.Material, - atoms.Radius, atoms.GLEnabled, atoms.ShowLabel)); - n++; - } - } - } - crystal.A *= _u; - crystal.B *= _v; - crystal.C *= _w; - crystal.Atoms = temp_atoms.ToArray(); + #endregion - SetToInterface(true); - GenerateFromInterface(); - } + #region キーボードイベント - #endregion 右クリックメニュー + private void CrystalControl_KeyDown(object sender, KeyEventArgs e) + { + if (e.Control && e.Shift && e.KeyCode == Keys.R) + crystal.Reserved = !crystal.Reserved; + } + #endregion - #region キーボードイベント + #region EOS関連 + /// + /// 外部から呼び出されることを想定. + /// + public void CalculateEOS() => eosControl.CalculatePressure(); - private void CrystalControl_KeyDown(object sender, KeyEventArgs e) - { - if (e.Control && e.Shift && e.KeyCode == Keys.R) - crystal.Reserved = !crystal.Reserved; - } - #endregion + #endregion EOSタブの入力設定 - #region EOS関連 - /// - /// 外部から呼び出されることを想定. - /// - public void CalculateEOS() => eosControl.CalculatePressure(); + #region Polycrystalline関連 - #endregion EOSタブの入力設定 + private void buttonGenerateRandomOrientations_Click(object sender, EventArgs e) + { + if (this.Crystal.Crystallites == null) + this.Crystal.SetCrystallites(); + /* + int[] index=new int[0]; + double[] density=new double[0]; + this.Crystal.Crystallites.GetBiasedDirection(Crystal.Crystallites.GetIndex(0,22,22,5), ref index, ref density, Math.PI / 180.0 * 0.1, 1); + //16040 2015/08ごろに辻野君に対してシミュレーションした番号 + + for (int i = 0; i < Crystal.Crystallites.Density.Length; i++) + crystal.Crystallites.Density[i] = 0; + + for (int i = 0; i < index.Length; i++) + Crystal.Crystallites.Density[index[i]] += density[i]; + */ + poleFigureControl.Crystal = Crystal; + } - #region Polycrystalline関連 + public void DrawPoleFigure() + { + poleFigureControl.Draw(true); + } - private void buttonGenerateRandomOrientations_Click(object sender, EventArgs e) - { - if (this.Crystal.Crystallites == null) - this.Crystal.SetCrystallites(); - /* - int[] index=new int[0]; - double[] density=new double[0]; - this.Crystal.Crystallites.GetBiasedDirection(Crystal.Crystallites.GetIndex(0,22,22,5), ref index, ref density, Math.PI / 180.0 * 0.1, 1); - //16040 2015/08ごろに辻野君に対してシミュレーションした番号 - - for (int i = 0; i < Crystal.Crystallites.Density.Length; i++) - crystal.Crystallites.Density[i] = 0; - - for (int i = 0; i < index.Length; i++) - Crystal.Crystallites.Density[index[i]] += density[i]; - */ - poleFigureControl.Crystal = Crystal; - } + private void numericUpDownAngleResolution_ValueChanged(object sender, EventArgs e) + { + if (SkipEvent) return; + GenerateFromInterface(); + } - public void DrawPoleFigure() - { - poleFigureControl.Draw(true); - } + #endregion Polycrystalline関連 - private void numericUpDownAngleResolution_ValueChanged(object sender, EventArgs e) - { - if (SkipEvent) return; - GenerateFromInterface(); - } + #region poleFigureの右クリックメニュー + /// + /// poleFigureの右クリックメニュー 読み込み + /// + /// + /// + private void readToolStripMenuItem_Click(object sender, EventArgs e) + { + //2022/11/10 BinaryFormatterが使えなくなったので、取りあえずコメントアウト + + //var dlg = new OpenFileDialog { Filter = "Database File[*.cpo]|*.cpo" }; + //try + //{ + // if (dlg.ShowDialog() == DialogResult.OK) + // using (Stream stream = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read)) + // { + // IFormatter formatter = new BinaryFormatter(); + // double version = (double)formatter.Deserialize(stream); + // if (version == 1.0) + // { + // numericUpDownAngleResolution.Value = (decimal)((double)formatter.Deserialize(stream)); + // numericUpDownAngleSubDivision.Value = (decimal)((int)formatter.Deserialize(stream)); + // numericUpDownCrystallineSize.Value = (decimal)((double)formatter.Deserialize(stream)); + // double[] density = (double[])formatter.Deserialize(stream); + // crystal.Crystallites = new Crystallite(Crystal, density); + + // poleFigureControl.Crystal = Crystal; + // } + // } + //} + //catch + //{ + // MessageBox.Show("ファイルが読み込めません"); + //} + } - #endregion Polycrystalline関連 + /// + /// poleFigureの右クリックメニュー 書き込み + /// + /// + /// + private void saveToolStripMenuItem_Click(object sender, EventArgs e) + { - #region poleFigureの右クリックメニュー - /// - /// poleFigureの右クリックメニュー 読み込み - /// - /// - /// - private void readToolStripMenuItem_Click(object sender, EventArgs e) - { - //2022/11/10 BinaryFormatterが使えなくなったので、取りあえずコメントアウト - - //var dlg = new OpenFileDialog { Filter = "Database File[*.cpo]|*.cpo" }; - //try - //{ - // if (dlg.ShowDialog() == DialogResult.OK) - // using (Stream stream = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read)) - // { - // IFormatter formatter = new BinaryFormatter(); - // double version = (double)formatter.Deserialize(stream); - // if (version == 1.0) - // { - // numericUpDownAngleResolution.Value = (decimal)((double)formatter.Deserialize(stream)); - // numericUpDownAngleSubDivision.Value = (decimal)((int)formatter.Deserialize(stream)); - // numericUpDownCrystallineSize.Value = (decimal)((double)formatter.Deserialize(stream)); - // double[] density = (double[])formatter.Deserialize(stream); - // crystal.Crystallites = new Crystallite(Crystal, density); - - // poleFigureControl.Crystal = Crystal; - // } - // } - //} - //catch - //{ - // MessageBox.Show("ファイルが読み込めません"); - //} - } + //2022/11/10 BinaryFormatterが使えなくなったので、取りあえずコメントアウト + + + //var dlg = new SaveFileDialog { Filter = "Database File[*.cpo]|*.cpo" }; + //try + //{ + // if (dlg.ShowDialog() == DialogResult.OK) + // using (Stream stream = new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write)) + // { + // IFormatter formatter = new BinaryFormatter(); + // formatter.Serialize(stream, 1.0); + + // formatter.Serialize(stream, crystal.AngleResolution); + // formatter.Serialize(stream, crystal.SubDivision); + // formatter.Serialize(stream, crystal.GrainSize); + // formatter.Serialize(stream, crystal.Crystallites.Density); + // } + //} + //catch + //{ + // MessageBox.Show("ファイルが書き込みません"); + //} + } - /// - /// poleFigureの右クリックメニュー 書き込み - /// - /// - /// - private void saveToolStripMenuItem_Click(object sender, EventArgs e) - { + /// + /// poleFigureの右クリックメニュー ctfファイルで出力 + /// + /// + /// + private void asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem_Click(object sender, EventArgs e) + { + #region Export CTFボタンをクリックしたときの動作 - //2022/11/10 BinaryFormatterが使えなくなったので、取りあえずコメントアウト - - - //var dlg = new SaveFileDialog { Filter = "Database File[*.cpo]|*.cpo" }; - //try - //{ - // if (dlg.ShowDialog() == DialogResult.OK) - // using (Stream stream = new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write)) - // { - // IFormatter formatter = new BinaryFormatter(); - // formatter.Serialize(stream, 1.0); - - // formatter.Serialize(stream, crystal.AngleResolution); - // formatter.Serialize(stream, crystal.SubDivision); - // formatter.Serialize(stream, crystal.GrainSize); - // formatter.Serialize(stream, crystal.Crystallites.Density); - // } - //} - //catch - //{ - // MessageBox.Show("ファイルが書き込みません"); - //} - } + if (crystal.Crystallites == null) return; + int maxCrystallites = 499900; - /// - /// poleFigureの右クリックメニュー ctfファイルで出力 - /// - /// - /// - private void asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem_Click(object sender, EventArgs e) + var dlg = new SaveFileDialog { Filter = "*.ctf|*.ctf" }; + if (dlg.ShowDialog() == DialogResult.OK) { - #region Export CTFボタンをクリックしたときの動作 + var sw = new StreamWriter(dlg.FileName); + sw.WriteLine("Channel Text File"); + sw.WriteLine("Prj\t OutPut from Recipro"); + sw.WriteLine("Author\t[Unknown]"); + sw.WriteLine("JobMode\tInteractive"); + sw.WriteLine("NoMeas\t" + maxCrystallites.ToString());//+ poleFigureControl1.PolyCrystal.Crysatallites.Length.ToString()); + sw.WriteLine("AcqE1\t0"); + sw.WriteLine("AcqE2\t0"); + sw.WriteLine("AcqE3\t0"); + sw.WriteLine("Euler angles refer to Sample Coordinate system (CS0)!\tMag\t0\tCoverage\t0\tDevice\t0\tKV\t0\tTiltAngle\t0\tTiltAxis\t0"); + sw.WriteLine("Phases\t1"); + sw.WriteLine("0.000;0.000;0.000\t90;90;90\t" + Crystal.Name + "\t3\t0\t3803863129_5.0.6.3\t1060505527\t[" + crystal.Name + "]"); + sw.WriteLine("Phase\tX\tY\tBands\tError\tEuler1\tEuler2\tEuler3\tMAD\tBC\tBS"); + + double sum = 0; + for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) + sum += crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i]; + + double tempSum = 0; + int seed = 0; + for (int i = 0; i < maxCrystallites; i++) + { + double partialSum = (i + 0.5) / (double)maxCrystallites * sum; - if (crystal.Crystallites == null) return; - int maxCrystallites = 499900; + while (tempSum + Crystal.Crystallites.Density[seed] * Crystal.Crystallites.SolidAngle[seed] < partialSum && seed < Crystal.Crystallites.Density.Length) + { + tempSum += Crystal.Crystallites.Density[seed] * Crystal.Crystallites.SolidAngle[seed]; + seed++; + } - var dlg = new SaveFileDialog { Filter = "*.ctf|*.ctf" }; - if (dlg.ShowDialog() == DialogResult.OK) - { - var sw = new StreamWriter(dlg.FileName); - sw.WriteLine("Channel Text File"); - sw.WriteLine("Prj\t OutPut from Recipro"); - sw.WriteLine("Author\t[Unknown]"); - sw.WriteLine("JobMode\tInteractive"); - sw.WriteLine("NoMeas\t" + maxCrystallites.ToString());//+ poleFigureControl1.PolyCrystal.Crysatallites.Length.ToString()); - sw.WriteLine("AcqE1\t0"); - sw.WriteLine("AcqE2\t0"); - sw.WriteLine("AcqE3\t0"); - sw.WriteLine("Euler angles refer to Sample Coordinate system (CS0)!\tMag\t0\tCoverage\t0\tDevice\t0\tKV\t0\tTiltAngle\t0\tTiltAxis\t0"); - sw.WriteLine("Phases\t1"); - sw.WriteLine("0.000;0.000;0.000\t90;90;90\t" + Crystal.Name + "\t3\t0\t3803863129_5.0.6.3\t1060505527\t[" + crystal.Name + "]"); - sw.WriteLine("Phase\tX\tY\tBands\tError\tEuler1\tEuler2\tEuler3\tMAD\tBC\tBS"); - - double sum = 0; - for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) - sum += crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i]; - - double tempSum = 0; - int seed = 0; - for (int i = 0; i < maxCrystallites; i++) + var (Phi, Theta, Psi) = Euler.GetEulerAngle(Crystal.Crystallites.Rotations[seed]); + var euler = new double[] { Phi, Theta, Psi }; + string str = ""; + foreach (double angle in euler) { - double partialSum = (i + 0.5) / (double)maxCrystallites * sum; - - while (tempSum + Crystal.Crystallites.Density[seed] * Crystal.Crystallites.SolidAngle[seed] < partialSum && seed < Crystal.Crystallites.Density.Length) - { - tempSum += Crystal.Crystallites.Density[seed] * Crystal.Crystallites.SolidAngle[seed]; - seed++; - } - - var (Phi, Theta, Psi) = Euler.GetEulerAngle(Crystal.Crystallites.Rotations[seed]); - var euler = new double[] { Phi, Theta, Psi }; - string str = ""; - foreach (double angle in euler) - { - double d = (angle > 0 ? angle : angle + 2 * Math.PI) / Math.PI * 180; - if (d >= 100) - str += $"{d:000.00}\t"; - else if (d >= 10) - str += $"{d:00.000}\t"; - else - str += $"{d:0.0000}\t"; - } - sw.WriteLine($"1\t0\t0\t0\t0\t{str}0\t0\t0"); + double d = (angle > 0 ? angle : angle + 2 * Math.PI) / Math.PI * 180; + if (d >= 100) + str += $"{d:000.00}\t"; + else if (d >= 10) + str += $"{d:00.000}\t"; + else + str += $"{d:0.0000}\t"; } - sw.Close(); + sw.WriteLine($"1\t0\t0\t0\t0\t{str}0\t0\t0"); } - - #endregion Export CTFボタンをクリックしたときの動作 + sw.Close(); } - /// - /// poleFigureの右クリックメニュー txtファイルで出力 - /// - /// - /// - private void asTXTFileAllEulerAngleAndDensityToolStripMenuItem_Click(object sender, EventArgs e) + #endregion Export CTFボタンをクリックしたときの動作 + } + + /// + /// poleFigureの右クリックメニュー txtファイルで出力 + /// + /// + /// + private void asTXTFileAllEulerAngleAndDensityToolStripMenuItem_Click(object sender, EventArgs e) + { + if (crystal.Crystallites == null) return; + + var dlg = new SaveFileDialog { Filter = "*.txt|*.txt" }; + if (dlg.ShowDialog() == DialogResult.OK) { - if (crystal.Crystallites == null) return; + using var sw = new StreamWriter(dlg.FileName); + sw.WriteLine("Sample Name:\t" + Crystal.Name); + sw.WriteLine($"Cell constants:\t{Crystal.A}\t{Crystal.B}\t{Crystal.C}\t{crystal.Alpha / Math.PI * 180}\t{crystal.Beta / Math.PI * 180}\t{crystal.Gamma / Math.PI * 180}"); + sw.WriteLine("Space group:\t" + Crystal.Symmetry.SpaceGroupHMfullStr); + sw.WriteLine(""); + sw.WriteLine("Euler angles refer to Sample Coordinate system"); + sw.WriteLine("No.\tEuler1\tEuler2\tEuler3\tDensity"); + + double sum = 0; + + double[] density = new double[Crystal.Crystallites.TotalCrystalline]; + int[] index = new int[Crystal.Crystallites.TotalCrystalline]; + for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) + { + density[i] = crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i]; + index[i] = i; + sum += density[i]; + } + if (sender == asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem) + { + Array.Sort(density, index); + density = density.Reverse().ToArray(); + index = index.Reverse().ToArray(); + } - var dlg = new SaveFileDialog { Filter = "*.txt|*.txt" }; - if (dlg.ShowDialog() == DialogResult.OK) + for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) { - using var sw = new StreamWriter(dlg.FileName); - sw.WriteLine("Sample Name:\t" + Crystal.Name); - sw.WriteLine($"Cell constants:\t{Crystal.A}\t{Crystal.B}\t{Crystal.C}\t{crystal.Alpha / Math.PI * 180}\t{crystal.Beta / Math.PI * 180}\t{crystal.Gamma / Math.PI * 180}"); - sw.WriteLine("Space group:\t" + Crystal.Symmetry.SpaceGroupHMfullStr); - sw.WriteLine(""); - sw.WriteLine("Euler angles refer to Sample Coordinate system"); - sw.WriteLine("No.\tEuler1\tEuler2\tEuler3\tDensity"); - - double sum = 0; - - double[] density = new double[Crystal.Crystallites.TotalCrystalline]; - int[] index = new int[Crystal.Crystallites.TotalCrystalline]; - for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) - { - density[i] = crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i]; - index[i] = i; - sum += density[i]; - } - if (sender == asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem) - { - Array.Sort(density, index); - density = density.Reverse().ToArray(); - index = index.Reverse().ToArray(); - } + string str = i.ToString() + "\t"; + var (Phi, Theta, Psi) = Euler.GetEulerAngle(Crystal.Crystallites.Rotations[index[i]]); + var euler = new double[] { Phi, Theta, Psi }; - for (int i = 0; i < Crystal.Crystallites.TotalCrystalline; i++) + foreach (double angle in euler) { - string str = i.ToString() + "\t"; - var (Phi, Theta, Psi) = Euler.GetEulerAngle(Crystal.Crystallites.Rotations[index[i]]); - var euler = new double[] { Phi, Theta, Psi }; - - foreach (double angle in euler) - { - double d = (angle > 0 ? angle : angle + 2 * Math.PI) / Math.PI * 180; - str += d.ToString("000.0000") + "\t"; - } - str += (density[i] / sum * crystal.Crystallites.TotalCrystalline).ToString(); - sw.WriteLine(str); + double d = (angle > 0 ? angle : angle + 2 * Math.PI) / Math.PI * 180; + str += d.ToString("000.0000") + "\t"; } + str += (density[i] / sum * crystal.Crystallites.TotalCrystalline).ToString(); + sw.WriteLine(str); } } + } - #endregion - - #region 子コントロールからの変化イベント + #endregion - private void atomControl_AtomsChanged(object sender, EventArgs e) => GenerateFromInterface(); + #region 子コントロールからの変化イベント - private void symmetryControl_ItemChanged(object sender, EventArgs e) => GenerateFromInterface(); + private void atomControl_AtomsChanged(object sender, EventArgs e) => GenerateFromInterface(); - private void bondControl_ItemsChanged(object sender, EventArgs e) - { - //bondControlのItemChangedイベントは、StructureViewerなどに直接登録されている。 - } + private void symmetryControl_ItemChanged(object sender, EventArgs e) => GenerateFromInterface(); - private void elasticityControl1_ValueChanged(object sender, EventArgs e) - { - if (SkipEvent) return; + private void bondControl_ItemsChanged(object sender, EventArgs e) + { + //bondControlのItemChangedイベントは、StructureViewerなどに直接登録されている。 + } - if (elasticityControl1.Mode == Elasticity.Mode.Compliance) - formStrain.Compliance = elasticityControl1.Compliance; - else - formStrain.Stiffness = elasticityControl1.Stiffness; + private void elasticityControl1_ValueChanged(object sender, EventArgs e) + { + if (SkipEvent) return; - formStrain.ElasticityMode = elasticityControl1.Mode; - } - #endregion + if (elasticityControl1.Mode == Elasticity.Mode.Compliance) + formStrain.Compliance = elasticityControl1.Compliance; + else + formStrain.Stiffness = elasticityControl1.Stiffness; - #region Symmetry Information と Scatetring Factorの立ち上げ、イベント + formStrain.ElasticityMode = elasticityControl1.Mode; + } + #endregion - private void buttonSymmetryInfo_Click(object sender, EventArgs e) => FormSymmetryInformation.Visible = !FormSymmetryInformation.Visible; - private void formSymmetryInformation_VisibleChanged(object sender, EventArgs e) => SymmetryInformation_VisibleChanged?.Invoke(sender, e); + #region Symmetry Information と Scatetring Factorの立ち上げ、イベント - private void buttonScatteringFactor_Click(object sender, EventArgs e) => FormScatteringFactor.Visible = !FormScatteringFactor.Visible; + private void buttonSymmetryInfo_Click(object sender, EventArgs e) => FormSymmetryInformation.Visible = !FormSymmetryInformation.Visible; + private void formSymmetryInformation_VisibleChanged(object sender, EventArgs e) => SymmetryInformation_VisibleChanged?.Invoke(sender, e); - private void formScatteringFactor_VisibleChanged(object sender, EventArgs e) => ScatteringFactor_VisibleChanged?.Invoke(sender, e); + private void buttonScatteringFactor_Click(object sender, EventArgs e) => FormScatteringFactor.Visible = !FormScatteringFactor.Visible; - #endregion + private void formScatteringFactor_VisibleChanged(object sender, EventArgs e) => ScatteringFactor_VisibleChanged?.Invoke(sender, e); - #region リサイズイベント中は描画を停止する - bool registResizeEvent = false; - private void CrystalControl_Resize_1(object sender, EventArgs e) - { - if (!this.DesignMode && !registResizeEvent) - { - var parent = this.Parent; - while (parent is not Form && parent != null) - parent = parent.Parent; - if (parent == null) - return; - var form = parent as Form; - form.ResizeBegin += (s, ea) => SuspendLayout(); - form.ResizeEnd += (s, ea) => ResumeLayout(); - registResizeEvent = true; - } - } - #endregion + #endregion - private void button1_Click(object sender, EventArgs e) + #region リサイズイベント中は描画を停止する + bool registResizeEvent = false; + private void CrystalControl_Resize_1(object sender, EventArgs e) + { + if (!this.DesignMode && !registResizeEvent) { - GenerateFromInterface(); + var parent = this.Parent; + while (parent is not Form && parent != null) + parent = parent.Parent; + if (parent == null) + return; + var form = parent as Form; + form.ResizeBegin += (s, ea) => SuspendLayout(); + form.ResizeEnd += (s, ea) => ResumeLayout(); + registResizeEvent = true; } + } + #endregion - private void clearAllDataToolStripMenuItem_Click(object sender, EventArgs e) - { - - } + private void buttonStressSet_Click(object sender, EventArgs e) + { + GenerateFromInterface(); } } \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/CrystalControl.ja.resx b/Crystallography.Controls/Crystal/CrystalControl.ja.resx index 166aff8..8ade4dd 100644 --- a/Crystallography.Controls/Crystal/CrystalControl.ja.resx +++ b/Crystallography.Controls/Crystal/CrystalControl.ja.resx @@ -58,6 +58,139 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 462, 280 + + + 格子/対称性 + + + メイリオ, 9pt + + + + 2, 2, 2, 2 + + + 462, 280 + + + 原子情報 + + + 2, 2, 2, 2 + + + 462, 280 + + + 多面体/結合描画設定 + + + + + + 462, 280 + + + 引用文献 + + + + + + 462, 280 + + + 状態方程式 + + + + + + 462, 280 + + + 弾性定数 + + + + + + 462, 280 + + + + + + + + + 462, 226 + + + + + + 462, 27 + + + + + + 462, 27 + + + + + + 462, 280 + + + + + + 462, 280 + + + + + + 462, 280 + + + + + + メイリオ, 9pt + + + 0, 22 + + + 3, 1 + + + 470, 310 + + + + + + 456, 274 + + + + + + 0, 136 + + + 456, 138 + + + + メイリオ, 9pt @@ -130,23 +263,11 @@ 124, 20 - - 0, 136 - - - 456, 138 - 456, 136 - - 456, 274 - - - 462, 280 - - - 格子/対称性 + + 2, 2 @@ -154,30 +275,29 @@ 458, 276 - - 210, 22 + + - - デバイワラー因子をゼロにする + + 2, 2 + + + 211, 26 - - 2, 2 + + - - メイリオ, 9pt + + - - - 2, 2, 2, 2 - - - 462, 280 + + 210, 22 - - 原子情報 + + デバイワラー因子をゼロにする 2, 2 @@ -185,14 +305,17 @@ 458, 276 - - 2, 2, 2, 2 + + - - 462, 280 + + 350, 162 - - 多面体/結合描画設定 + + タイトル + + + メイリオ, 9pt @@ -200,14 +323,8 @@ 344, 138 - - 350, 162 - - - タイトル - - - 100, 138 + + 106, 162 @@ -215,8 +332,14 @@ 著者 - - 450, 31 + + + + + 100, 138 + + + 456, 55 @@ -224,44 +347,137 @@ 雑誌名 - - 450, 33 + + + + + 450, 31 + + + 456, 57 - - 462, 280 + + - - 引用文献 + + 450, 33 + + + 456, 274 - - 462, 280 - - - 状態方程式 + + - - 462, 280 + + - - 弾性定数 + + 120, 123 - - 462, 280 + + - - 462, 226 + + - - 462, 27 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + メイリオ, 9pt @@ -272,47 +488,53 @@ Division + + + 219, 2 + + + 275, 4 + + + 310, 2 + + + 358, 4 - - 462, 27 - - - 462, 280 + + 456, 274 - - 462, 280 + + 456, 274 - - 462, 280 - - - メイリオ, 9pt + + - - 0, 22 + + 0, 28 - - 3, 1 + + 470, 24 - - 470, 310 + + 61, 0 @@ -344,81 +566,77 @@ 化学組成 - - 0, 28 + + 279, 242 - - 470, 24 + + - 271, 22 + 278, 22 散乱因子 - 271, 22 + 278, 22 対称性詳細 - 268, 6 + 275, 6 - 271, 22 + 278, 22 CIFファイル又はAMCファイルから読み込み - 271, 22 + 278, 22 CIFファイルとして出力 - 271, 22 + 278, 22 - 268, 6 - - - 271, 22 - - - - False + 275, 6 - 271, 22 + 278, 22 アプリ起動時の格子定数に戻す - 268, 6 + 275, 6 - 271, 22 + 278, 22 - Strain control + 格子ひずみ (invisible) - 271, 22 + 278, 22 - 空間群をP1に変換 + P1に変換 - 271, 22 + 278, 22 超構造に変換 - - 272, 242 + + 278, 22 + + + 異なる軸・原点セッティングの空間群に変換 48, 0 @@ -435,6 +653,9 @@ 結晶名 + + + メイリオ, 9pt @@ -462,10 +683,19 @@ 470, 0 + + + 470, 28 + + + 470, 362 + + + \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/CrystalControl.resx b/Crystallography.Controls/Crystal/CrystalControl.resx index d670f3d..980b2d5 100644 --- a/Crystallography.Controls/Crystal/CrystalControl.resx +++ b/Crystallography.Controls/Crystal/CrystalControl.resx @@ -57,3628 +57,3394 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + GrowAndShrink + - - 22, 46 + + Segoe UI Symbol, 9.75pt - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI, 9pt - - - True + + ų - - - Right + + Segoe UI, 9pt - - tabPageReference + + Cell Volume + + + 10, 4 - - 3, 3, 3, 3 + + 10, 0, 0, 0 - - α + + 1000, 25 - - True + + 1, 23 - - 167, 57 + + 0, 0, 1, 0 - - 3, 3, 3, 3 + + 156, 25 - - 209, 46 + + + 90 - - tabControl + + 17, 17 + + + Cell volume in ų - - 4, 0, 4, 0 + + Cell volume in ų - - numericBoxStrain12 + + numericBoxVolume - - 114, 107 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - flowLayoutPanel2 + + flowLayoutPanel4 - - 0, 0, 4, 0 + + 0 - - + + GrowAndShrink - - System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - 0, 0, 1, 0 + + Segoe UI, 9pt - - groupBox6 + + × 10⁻²⁴ g - - 3, 5, 3, 0 + + Segoe UI, 9pt - - 23 + + Cell Mass - - tabPageStrainStress + + 176, 4 - - 7 + + 10, 0, 0, 0 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1000, 25 - - numericBoxVolume + + 1, 23 - - ε11 + + 0, 0, 1, 0 - - GrowAndShrink + + 175, 25 - - saveToolStripMenuItem + + 90 - - True + + Cell mass in 10⁻²⁴ g - - Times New Roman, 9pt + + Cell mass in 10⁻²⁴ g - - 0 + + numericBoxCellMass - - label103 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 0, 0 + + flowLayoutPanel4 - - 199, 25 + + 1 - - 7 + + GrowAndShrink - - 47, 24 + + Segoe UI Symbol, 9.75pt - - ε33 + + Segoe UI Symbol, 9pt - - 239 + + cm³/mol - - 19 + + Segoe UI Symbol, 9pt - - Density in g/cm³ + + Molar Volume - - tabPageStrainStress + + 10, 29 - - Arial, 9pt + + 10, 0, 0, 0 - - + + 1000, 25 - - 459, 298 + + 1, 23 - - 114, 69 + + 0, 0, 1, 0 - - 90 + + 199, 25 - - 94 + + 90 - - 4 + + Molar Volume in cm³/mol - - 0, 0, 1, 0 + + Molar Volume in cm³/mol - - Segoe UI Symbol, 9.75pt + + numericBoxMolarVolume - - 1 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 98 + + flowLayoutPanel4 - - GrowAndShrink + + 2 - + GrowAndShrink - - 6 + + Segoe UI Symbol, 9.75pt - - 3 + + Segoe UI Symbol, 9pt - - 10, 54 + + g/mol - - 1, 25 + + Segoe UI Symbol, 9pt - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Molar Mass - - Segoe UI Symbol, 9.75pt + + 219, 29 - - True + + 10, 0, 0, 0 - - 4, 26 + + 1000, 25 - - 3 + + 1, 23 - + 0, 0, 1, 0 - - Segoe UI, 9pt - - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 171, 25 - - 0 + + 90 - - 1000, 24 + + Molar Mass in g/mol - - 1, 1, 1, 1 + + Molar Mass in g/mol - - Strain Control + + numericBoxMolarMass - - tabPageStrainStress + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 0, 0 + + flowLayoutPanel4 - - 55, 19 + + 3 - - 254 + + GrowAndShrink - + Segoe UI Symbol, 9.75pt - - True + + Segoe UI Symbol, 9pt - - asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem + + g/cm³ - - 0, 0, 1, 0 + + Segoe UI Symbol, 9pt - - flowLayoutPanel2 + + Density - - flowLayoutPanel2 + + 10, 54 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 10, 0, 0, 0 - - as CTF file (comatible to CHANNEL 5 file) + + 1000, 25 - - Crystallography.Controls.EOSControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 1, 23 - - 133 + + 0, 0, 1, 0 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 147, 25 - - Segoe UI Symbol, 9.75pt + + 95 - - groupBox8 + + Density in g/cm³ - - symmetryInformationToolStripMenuItem + + Density in g/cm³ - - 24, 15 + + numericBoxDensity - - GrowAndShrink + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - Microsoft Sans Serif, 9pt + + flowLayoutPanel4 - - 0, 0, 0, 2 + + 4 - - Open another window with the structure factors + + True - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GrowAndShrink - - Molar Mass in g/mol + + Segoe UI Symbol, 9.75pt - - 7 + + Segoe UI Symbol, 9pt - - 6 + + 0, 0, 0, 0 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + - - Top + + Segoe UI Symbol, 9pt - - Segoe UI Symbol, 9.75pt + + 0, 0, 0, 0 - - revertCellConstantsToolStripMenuItem + + Profile color - - 249, 0 + + 167, 57 - - Convert to superstructure + + 10, 3, 3, 3 - - tabControl + + 91, 20 - - tabPageElasticity + + 89 - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + - - 109, 115 + + Profile color + - - 0, 2, 0, 0 + + colorControl - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Crystallography.Controls.ColorControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 3 + + flowLayoutPanel4 - - True + + 5 - - + + Fill - - 353, 0 + + 0, 133 - - 447, 33 + + 4, 4, 4, 4 - - contextMenuStrip2 + + 0, 4, 0, 0 - - 252, 22 + + 453, 159 - - latticePlaneControl + + 94 - - 5 + + flowLayoutPanel4 - - 2 + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + panel5 - - 0, 0, 1, 0 + + 0 - - 114, 25 + + Top - - + + 0, 0 - - TopCenter + + 3, 11, 3, 11 - - 459, 244 + + 453, 133 - - 0 + + 93 - - - - - + + symmetryControl - - scatteringFactorToolStripMenuItem + + Crystallography.Controls.SymmetryControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 114, 30 + + panel5 - - 11 + + 1 - - 0, 27 + + Fill - - GrowAndShrink + + 3, 3 - - 25, 15 + + 2, 2, 2, 2 - - 249, 6 + + 453, 292 - - GrowAndShrink + + 93 - - + + panel5 - - Times New Roman, 9pt + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Atom positions and species + + tabPageBasicInfo - - 206, 25 + + 0 - - contextMenuStripPoleFigure + + 4, 26 - - 120, 121 + + 3, 3, 3, 3 - - buttonSymmetryInfo + + 459, 298 - - tabPageStrainStress + + 4 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + Basic Info. - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Cell constants, symmetry, and other basic informaton - - Times New Roman, 9pt + + Cell constants, symmetry, and other basic informaton - - tabPageStrainStress + + tabPageBasicInfo - - 237 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9pt + + tabControl - - NoControl + + 0 - + True - - 235 - - - 12 + + Fill - - GrowAndShrink + + Microsoft Sans Serif, 9pt - - Import from CIF, AMC... + + 0, 0 - - 71, 84 + + 0, 0, 0, 0 - - Segoe UI, 9pt + + 446, 108 - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 459, 298 - - 1 + + 0 - - Segoe UI Symbol, 9.75pt + + atomControl - - Tahoma, 9pt + + Crystallography.Controls.AtomControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageAtom - + 0 - - panelAtom + + True - - 459, 298 + + GrowAndShrink - - 14 + + True - - Segoe UI Symbol, 9.75pt + + 249, 22 + + + Arial, 9pt - - NoControl + + 217, 22 - - 0 + + Reset Debye-Waller factor - - 1, 23 + + 218, 26 - - 86 + + contextMenuStrip2 - - 1, 22 + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Bottom - - System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 0 - - 453, 57 + + 0, 0 - - ε13 + + 65 - - tabPageBasicInfo + + panel3 - - 0, 0 + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 248 + + panelAtom - - 64, 69 + + 0 - - numericBoxStress33 + + Microsoft Sans Serif, 9pt - - Segoe UI Symbol, 9.75pt + + 0, 0 - - 122, 14 + + 0, 0, 0, 0 - + 0, 0 - - Segoe UI Symbol, 9.75pt + + 65 - - 47, 24 + + panelAtom - - 156, 25 + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 274, 4 + + tabPageAtom - - groupBox6 + + 1 - - panel3 + + Tahoma, 8.25pt - - Segoe UI Symbol, 9.75pt + + 4, 26 - - 0 + + 0, 0, 0, 0 - - 137 + + 459, 298 - - 90 + + 0 - - 4, 0, 0, 0 + + Atom Info. - - 357, 4 + + Atom positions and species - - NoControl + + Atom positions and species - - 4, 26 + + tabPageAtom - - label110 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - numericBoxStrain33 + + tabControl - - + + 1 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + True - - Fill + + GrowAndShrink - - tabPageStrainStress + + Fill - - 1000, 24 + + Segoe UI Symbol, 9pt - - 9 + + 0, 0 - - 91, 20 + + 0, 0, 0, 0 - - 371, 25 + + 459, 298 - - System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 - - 4, 2, 0, 0 + + bondControl - - σ23 + + Crystallography.Controls.BondInputControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageBondsPolyhedra - - label112 + + 0 - - tabPageStrainStress + + 4, 26 - + 459, 298 - - 249, 6 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - numericBoxMolarMass + + 3 - - Segoe UI Symbol, 9pt + + Bonds ( & Polyhedra) - - True + + tabPageBondsPolyhedra - - 47, 24 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Density in g/cm³ + + tabControl - - 467, 328 + + 2 - - 1, 23 + + Fill - + Segoe UI Symbol, 9.75pt - - tabPageEOS + + 3, 21 - - numericBoxStrain11 + + True - - 29 + + Vertical - - Save + + 341, 156 - - label106 + + 0 - - 0, 4, 0, 0 + + textBoxTitle - - Symmetry Information + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + groupBox8 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 0 - - NoControl + + Fill - - tabPageStrainStress + + 109, 115 - - Crystallography.Controls.BondInputControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 347, 180 - - + + 3 - - 120, 46 + + Title - - + + groupBox8 - - 6 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageReference - - True + + 0 - - label114 + + Fill - - 0, 3, 3, 0 + + Segoe UI Symbol, 9.75pt - - NoControl + + 3, 21 - - Molar Mass in g/mol + + True - - 75, 23 + + Vertical - - Molar Volume in cm³/mol + + 100, 156 - - 3 + + 0 - - True + + textBoxAuthor - - tabControl + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1 + + groupBox6 - - Molar Mass + + 0 - - NoControl + + Left - - numericBoxStress22 + + 3, 115 - - 8 + + 106, 180 - + 2 - - + + Authors - - NoControl - - - σ33 - - - panel4 - - - Crystallography.Controls.SymmetryControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + groupBox6 System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True - - - NoControl - - - - - - 0 - - - - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageReference - - 0, 2, 0, 0 + + 1 - + Fill - - System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - 100, 156 + + 3, 21 - - 3, 3 + + True - - numericUpDownAngleResolution + + Vertical - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 447, 31 - + 0 - - - - - - - - 4, 0, 4, 0 - - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + textBoxJournal - - Cell mass in 10⁻²⁴ g + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 90 + + groupBox7 - - flowLayoutPanel1 + + 0 - - 16 + + Top - - 1000, 24 + + 3, 60 - - 0, 0, 1, 0 + + 453, 55 - - 4, 0, 4, 0 + + 1 - - Bottom + + Journal - - NoControl + + groupBox7 - - 459, 298 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI, 9pt + + tabPageReference - - True + + 2 Fill - - numericUpDownCrystallineSize - - + Segoe UI Symbol, 9.75pt - - Z (Number of formula in the unit cell) + + 3, 21 - - Times New Roman, 9pt + + True - - 0 + + 447, 33 - - 65 + + 0 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + textBoxMemo - - 6 + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label101 + + groupBox5 - - 15 + + 0 - - Fill + + Top - - 0 + + 3, 3 - - 306, 159 + + 453, 57 - - + + 0 - - 10, 0, 0, 0 + + Note - - flowLayoutPanel2 + + groupBox5 - - 0, 0 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 453, 55 + + tabPageReference - - 5 + + 3 - - 10, 0, 0, 0 + + 4, 26 - - 110, 2 + + 3, 3, 3, 3 - - 1000, 24 + + 459, 298 - - label5 + + 1 - - Crystallography.Controls.BoundControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + Ref. - - 3, 21 + + tabPageReference - - True + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + tabControl - - + + 3 - + Fill - - 252 - - - 0, 0, 0, 0 + + Segoe UI Symbol, 9pt - - 0, 0, 1, 0 + + 3, 3 - - 2, 2, 2, 2 + + 2, 3, 2, 3 - - 4 + + 453, 292 - - Segoe UI Symbol, 9.75pt + + 0 - - Profile color + + eosControl - - Cell volume in ų + + Crystallography.Controls.EOSControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 139 - - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageEOS - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 - - 1, 1, 1, 1 + + 4, 26 - - Segoe UI Symbol, 9.75pt + + 3, 3, 3, 3 - - panel4 + + 459, 298 - - tabPageAtom + + 5 - - + + EOS - - textBoxTitle + + tabPageEOS - - tabPageBasicInfo + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabControl - - 118, 14 - - - 1, 22 - - - σ12 + + 4 - - 4, 26 + + True - - asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem + + 0, 6 - - NoControl + + 4, 4, 4, 4 - - + + 574, 177 - - 21 + + 0 - - 104, 25 + + elasticityControl1 - - buttonScatteringFactor + + Crystallography.Controls.ElasticityControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 3 + + tabPageElasticity - - Segoe UI Symbol, 9.75pt + + 0 - - 1, 22 + + 4, 26 - - cm³/mol + + 3, 3, 3, 3 - - 252, 22 + + 459, 298 - - 10, 29 + + 6 - - tabPageStrainStress + + Elasticity - - panel5 + + tabPageElasticity - - 0, 0, 1, 0 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabControl - - 0 - - - buttonGenerateRandomOrientations - - - True + + 5 - - 80 + + 282, 196 - - division + + 75, 23 - - Export to CIF + + 263 - - g/mol + + set - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + buttonStressSet - - label22 + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabPageBondsPolyhedra + + tabPageStrainStress - + 0 - - 194, 12 + + GrowAndShrink - - label107 + + Segoe UI Symbol, 9.75pt - - NoControl + + 120, 121 - - 25, 15 + + 1, 1, 1, 1 - - button1 + + 1000, 24 - - Size + + 1, 22 - - 0 + + 0, 0, 1, 0 - - tabControl + + 47, 24 - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 5 - - tabPageLatticePlane + + numericBoxStrain33 - - Right + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 8 + + tabPageStrainStress - - 138 + + 1 - - + + GrowAndShrink - - 87 + + Segoe UI Symbol, 9.75pt - - exportToolStripMenuItem + + 306, 159 - - tabControl + + 1, 1, 1, 1 - - + + 1000, 24 - - 4, 26 + + 1, 22 - - 0, 0 + + 0, 0, 1, 0 - - 4, 0, 4, 0 + + 47, 24 - - 282, 162 + + 13 - - set + + numericBoxHill - - 3 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - + tabPageStrainStress - - 3, 3, 3, 3 - - - 47, 24 + + 2 - - Tahoma, 9pt + + True - - 467, 0 + + Times New Roman, 10pt - - panel5 + + NoControl - - 89 + + 282, 162 - - 9 + + 4, 0, 4, 0 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 14, 16 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 262 - - Profile color - + + α - - 0 + + label116 - - 217, 22 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + tabPageStrainStress - - 17 + + 3 - - 459, 27 + + True - - + + Tahoma, 9pt - + NoControl - - Angle Resolution - - - + + 192, 162 - - groupBox7 + + 4, 0, 4, 0 - - tabPageStrainStress + + 82, 14 - - 1000, 24 + + 12 - - 1 + + Hill coefficient - - tabControl + + label117 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + tabPageStrainStress - - Left + + 4 - - tabPageLatticePlane + + True - - 12 + + Tahoma, 9pt - - True + + NoControl - - Segoe UI Symbol, 9pt + + 194, 12 - - 459, 298 + + 4, 0, 4, 0 - - 4 + + 122, 14 - - readToolStripMenuItem + + 253 - - 1 + + Stress (Reuss model) + - - 0 + + label109 - - System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabPageStrainStress - - Symmetry info. + + 5 - - Segoe UI Symbol, 9.75pt + + True - - 55, 0 + + Times New Roman, 9pt - - 47, 24 + + NoControl - - 0, 0 + + 251, 69 - - + + 4, 0, 4, 0 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 25, 15 - - tabPageBounds + + 249 - - flowLayoutPanel2 + + σ22 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label110 - - + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 206, 28 + + tabPageStrainStress - - 0, 6 + + 6 - - Segoe UI Symbol, 9.75pt + + True - - + + Times New Roman, 9pt - - 0, 0, 0, 0 + + NoControl - - 4 + + 255, 29 - - 76 + + 4, 0, 4, 0 - - 13 + + 25, 15 - - 3 + + 250 - - 1, 22 + + σ12 - - 5 + + label111 - - Top + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabPageStrainStress - - + + 7 - - tabPageStrainStress + + True - - 108, 22 + + Times New Roman, 9pt - - 252, 22 + + NoControl - - True + + 301, 109 - - tabControl + + 4, 0, 4, 0 - - 0, 0, 1, 0 + + 25, 15 - - nm + + 251 - - poleFigureControl + + σ33 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label112 - - Left - - - numericBoxStress13 - - - 459, 298 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + tabPageStrainStress - - 4, 0, 4, 0 + + 8 - - Segoe UI Symbol, 9pt + + True - - 453, 292 + + Times New Roman, 9pt - - 459, 27 + + NoControl - - 13 + + 206, 28 - - 459, 298 + + 4, 0, 4, 0 - - True + + 25, 15 - - 22 + + 254 - - 166, 4 + + σ11 - - GrowAndShrink + + label113 - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0, 2, 0, 0 + + tabPageStrainStress - - Fill + + 9 - - 309, 22 + + True - - + + Times New Roman, 9pt - - Molar Volume in cm³/mol + + NoControl - - 24, 15 + + 301, 69 - - 41, 25 + + 4, 0, 4, 0 - - Basic Info. + + 25, 15 - - Fill + + 252 - - 9 + + σ23 - - 3, 11, 3, 11 + + label114 - - + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 tabPageStrainStress - - Scattering factor - - - textBoxAuthor + + 10 - - groupBox8 + + True - - 252, 22 + + Times New Roman, 9pt - - 2 + + NoControl - - flowLayoutPanel4 + + 304, 29 - - 27 + + 4, 0, 4, 0 - - 8 + + 25, 15 - - Polycrystalline Property + + 248 - - numericBoxCellMass + + σ13 - - 0, 0, 0, 0 + + label115 - - 0 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 87 + + tabPageStrainStress - - Right + + 11 - - 71, 46 + + True - - + + Tahoma, 9pt - - 4, 0, 4, 0 + + NoControl - - True + + 4, 12 - - $this + + 4, 0, 4, 0 - - tabPageStrainStress + + 118, 14 - - numericBoxZnumber + + 240 - - 4 + + Strain (Voigt model) - - Times New Roman, 9pt + + label102 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9.75pt + + tabPageStrainStress - - 44, 25 + + 12 - + True - - panel4 + + Times New Roman, 9pt - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + NoControl - - 0 + + 64, 69 - - Atom Info. + + 4, 0, 4, 0 - - flowLayoutPanel4 + + 24, 15 - - 3, 3 + + 235 - - Tahoma, 9pt + + ε22 - - 25, 15 + + label103 - - Random Rotations + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageStrainStress - - Segoe UI Symbol, 9pt + + 13 - - Crystallography.Controls.AtomControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + True - - TopCenter + + Times New Roman, 9pt - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 0, 0, 0, 0 + + NoControl - - System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 64, 30 - - textBoxName + + 4, 0, 4, 0 - - 0 + + 24, 15 - - 1, 1, 1, 1 + + 236 - - 0, 0, 0, 0 + + ε12 - - 95 + + label104 - - 5 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 47, 24 + + tabPageStrainStress - - GrowAndShrink + + 14 - - Tahoma, 8.25pt + + True - - 574, 177 + + Times New Roman, 9pt - - 47, 24 + + NoControl - - σ13 + + 114, 107 - - 0 + + 4, 0, 4, 0 - - True + + 24, 15 - - 0 + + 237 - - + + ε33 - - groupBox5 + + label105 - - 347, 180 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageStrainStress - - 126, 27 + + 15 - + True - - 1000, 25 + + Times New Roman, 9pt - - label115 + + NoControl - + + 114, 69 + + 4, 0, 4, 0 - - 135 + + 24, 15 - - 341, 156 + + 238 - - 252, 22 + + ε23 - - NoControl + + label106 - - 301, 69 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Z (Number of formula in the unit cell) + + tabPageStrainStress - - 307, 84 + + 16 - - Density + + True - - 453, 292 + + Times New Roman, 9pt - - 2 + + NoControl - - 467, 380 + + 18, 30 - - 4, 26 + + 4, 0, 4, 0 - - GrowAndShrink + + 24, 15 - - ε12 + + 241 - - 1 + + ε11 - - 28 + + label107 - - flowLayoutPanel3 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + tabPageStrainStress - - 447, 31 + + 17 - - 459, 298 + + True - - Strain (Voigt model) + + Times New Roman, 9pt - - 0 + + NoControl - - 1 + + 114, 30 - - panel4 + + 4, 0, 4, 0 - - 0, 0, 1, 0 + + 24, 15 - - 4, 2, 0, 0 + + 239 - - True + + ε13 - - 2 + + label108 - - 0 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Times New Roman, 10pt + + tabPageStrainStress - - 10 + + 18 - - True + + GrowAndShrink - - 3, 21 + + Segoe UI Symbol, 9.75pt - - 5 + + 305, 125 - - 301, 109 + + 1, 1, 1, 1 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 1000, 24 - - 459, 298 + + 1, 22 - - Cell constants, symmetry, and other basic informaton + + 0, 0, 1, 0 - - 238 - - - Vertical + + 47, 24 - - 1, 1, 1, 1 + + 11 - - True + + numericBoxStress33 - - tabControl + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - × 10⁻²⁴ g + + tabPageStrainStress - - 250 + + 19 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + GrowAndShrink - + Segoe UI Symbol, 9.75pt - - 3, 3, 3, 3 + + 257, 84 - - + + 1, 1, 1, 1 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 1000, 24 - - Bounds + + 1, 22 - - Cell volume in ų + + 0, 0, 1, 0 - - Times New Roman, 9pt + + 47, 24 - - σ22 + + 9 - - + + numericBoxStress22 - - 0 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - + tabPageStrainStress - - 219, 29 + + 20 - - numericBoxStrain22 + + GrowAndShrink - - + + Segoe UI Symbol, 9.75pt - - True + + 209, 46 - - 262 + + 1, 1, 1, 1 - - 453, 292 + + 1000, 24 - - 4, 4, 4, 4 + + 1, 22 - - 0 + + 0, 0, 1, 0 - - Top + + 47, 24 - - + + 6 - - 106, 17 + + numericBoxStress11 - - 0, 0, 1, 0 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - tabPageElasticity + + tabPageStrainStress - - + + 21 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + GrowAndShrink - - + + Segoe UI Symbol, 9.75pt - - Authors + + 307, 84 - - panel1 + + 1, 1, 1, 1 - - False + + 1000, 24 - - 305, 125 + + 1, 22 - - $this + + 0, 0, 1, 0 - - Open another window with the detailed symmetry information + + 47, 24 - - False + + 10 - - panelAtom + + numericBoxStress23 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - GrowAndShrink + + tabPageStrainStress - - tabPageAtom + + 22 - + + GrowAndShrink + + Segoe UI Symbol, 9.75pt - - 3, 115 + + 307, 46 - - 0 + + 1, 1, 1, 1 - - Segoe UI Symbol, 9.75pt + + 1000, 24 - - tabPageStrainStress + + 1, 22 - - tabPageReference + + 0, 0, 1, 0 - - 26 + + 47, 24 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 8 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericBoxStress13 - - 65 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - Hill coefficient + + tabPageStrainStress - - 3, 3, 3, 3 + + 23 - - 249, 6 + + GrowAndShrink - - label108 + + Segoe UI Symbol, 9.75pt - - Segoe UI Symbol, 9pt + + 258, 46 - - System.Windows.Forms.UserControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1, 1, 1, 1 - - flowLayoutPanel4 + + 1000, 24 - - 2 + + 1, 22 - + 0, 0, 1, 0 - - Times New Roman, 9pt + + 47, 24 - - Segoe UI Symbol, 9pt + + 7 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericBoxStress12 - - 24, 15 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tabPageStrainStress - - σ11 + + 24 - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GrowAndShrink - - 0, 27 + + Segoe UI Symbol, 9.75pt - + + 22, 46 + + + 1, 1, 1, 1 + + 1000, 24 - - + + 1, 22 - - 1 + + 0, 0, 1, 0 - - + + 47, 24 - - 10, 0, 0, 0 + + 0 - - 136 + + numericBoxStrain11 - - NoControl + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 0, 0, 1, 0 + + tabPageStrainStress - - 11 + + 25 - - 1, 1, 1, 1 + + GrowAndShrink - + Segoe UI Symbol, 9.75pt - - True + + 71, 84 - - elasticityControl1 + + 1, 1, 1, 1 - - 1 + + 1000, 24 - - tabPagePolycrystalline + + 1, 22 - - 1, 1, 1, 1 + + 0, 0, 1, 0 - - 147, 25 + + 47, 24 - - 4, 0, 4, 0 + + 3 - - 1, 1, 1, 1 + + numericBoxStrain22 - - Note + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 85 + + tabPageStrainStress - - panel4 + + 26 - + GrowAndShrink - - tabPageBondsPolyhedra - - - tabPageStrainStress - - - label102 + + Segoe UI Symbol, 9.75pt - - + + 71, 46 - - 120, 84 + + 1, 1, 1, 1 - - 0, 3, 0, 0 + + 1000, 24 - - + + 1, 22 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 0, 1, 0 - - numericBoxStress11 + + 47, 24 - - 1000, 24 + + 1 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericBoxStrain12 - + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - tabPagePolycrystalline + + tabPageStrainStress - - as TXT file (all Euler angle and density) + + 27 - - Atom positions and species + + GrowAndShrink - - True + + Segoe UI Symbol, 9.75pt - - Journal + + 120, 84 - - 3, 3 + + 1, 1, 1, 1 - - numericBoxStrain23 + + 1000, 24 - - NoControl + + 1, 22 - - 93 + + 0, 0, 1, 0 - - 1, 1, 1, 1 + + 47, 24 - - Segoe UI Symbol, 9.75pt + + 4 - - numericBoxMolarVolume + + numericBoxStrain23 - - True + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - NoControl + + tabPageStrainStress - - 253, 242 + + 28 - - + + GrowAndShrink - + Segoe UI Symbol, 9.75pt - - 3, 4, 3, 4 + + 120, 46 - - 109, 70 + + 1, 1, 1, 1 - - flowLayoutPanel4 + + 1000, 24 - - 6 + + 1, 22 - - 3, 21 + + 0, 0, 1, 0 - + + 47, 24 + + 2 - - Cell Mass + + numericBoxStrain13 - - 459, 298 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 1000, 25 + + tabPageStrainStress - + + 29 + + 4, 26 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 3, 3, 3, 3 - - 4 + + 459, 298 - - 1000, 25 + + 7 - - toolTip + + Strain / Stress - - numericBoxStress12 + + tabPageStrainStress - - label90 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - GrowAndShrink + + tabControl - - groupBox7 + + 6 - - 252, 22 + + 414, 22 + + + 108, 22 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + Read - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 108, 22 - - 459, 298 + + Save - - 0, 0, 0, 0 + + 309, 22 - - 0, 133 + + as CTF file (comatible to CHANNEL 5 file) - - Segoe UI Symbol, 9.75pt + + 309, 22 - - textBoxJournal + + as TXT file (all Euler angle and density) - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 309, 22 - - 4, 0, 4, 0 + + as TXT file (all Euler angle and density) sorted - - 3, 3, 3, 3 + + 108, 22 - - 1, 22 + + Export - - 3, 3, 3, 3 + + 109, 70 - - 252, 22 + + contextMenuStripPoleFigure - - Segoe UI Symbol, 9.75pt + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 + + Fill - - 25, 15 + + Segoe UI Symbol, 9.75pt - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 54 - - + + 4, 2, 4, 2 - - Send this crystal to other software + + 459, 244 - - 146 + + 133 - - 43, 19 + + poleFigureControl - - flowLayoutPanel2 + + Crystallography.Controls.PoleFigureControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 0, 0 + + tabPagePolycrystalline - - + + 0 - - 0, 0, 0, 0 + + True - - + + True - - 4, 0, 4, 0 + + GrowAndShrink - - 1000, 24 + + Segoe UI Symbol, 9.75pt - - numericBoxHill + + NoControl - - + + 0, 0 - - 4, 2, 4, 0 + + 0, 0, 0, 0 - - 252, 22 + + 126, 27 - - Name of the crystal + + 146 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Random Rotations - - NoControl + + buttonGenerateRandomOrientations - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 18, 30 + + flowLayoutPanel3 - - textBoxFormula + + 0 - - 4, 0, 4, 0 + + Top - - 4, 0, 4, 0 + + 0, 27 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 459, 27 - - + + 149 - - 48, 25 + + flowLayoutPanel3 - - 108, 22 + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - panel1 + + tabPagePolycrystalline - - Cell constants, symmetry, and other basic informaton + + 1 - - NoControl + + True + + + True Segoe UI Symbol, 9.75pt - - Top + + NoControl - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 4, 4 - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 4, 2, 0, 0 - - + + 106, 17 - - 446, 108 + + 137 - - panel1 + + Angle Resolution - - Fill + + label5 - - convertToSuperstructureToolStripMenuItem + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 108, 22 + + flowLayoutPanel2 - - eosControl + + 0 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - Left + + 110, 2 - - 0, 0, 1, 0 + + 0, 0, 4, 0 - - 4, 0, 4, 0 + + 48, 25 - - 1, 1, 1, 1 + + 136 - - 10, 0, 0, 0 + + True - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericUpDownAngleResolution - - 4, 0, 4, 0 + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9.75pt + + flowLayoutPanel2 - - sendThisCrystalToOtherSoftwareToolStripMenuItem + + 1 - - Segoe UI Symbol, 9.75pt + + True - - tabPagePolycrystalline + + Segoe UI Symbol, 9.75pt - - 90 + + NoControl - - 24, 15 + + 166, 4 - - 0 + + 4, 2, 0, 0 - - contextMenuStrip + + 52, 17 - - Fill + + 138 - - flowLayoutPanel4 + + division - - System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label29 - - 4, 12 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Crystallography.Controls.ColorControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + flowLayoutPanel2 - - True + + 2 - + Segoe UI Symbol, 9.75pt - - label113 + + 218, 2 - - 4, 4, 4, 4 + + 0, 0, 4, 0 - - 10, 0, 0, 0 + + 48, 25 - - 47, 24 + + 136 - - 1, 1, 1, 1 + + True - - atomControl + + numericUpDownAngleSubDivision - - Crystallography.Controls.PoleFigureControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9.75pt + + flowLayoutPanel2 - - 0, 0, 0, 0 + + 3 - - Lattice Plane + + True - - Export + + Segoe UI Symbol, 9.75pt - - 10 + + NoControl - - GrowAndShrink + + 274, 4 - - 1, 22 + + 4, 2, 4, 0 - - NoControl + + 31, 17 - - Microsoft Sans Serif, 9pt + + 138 - - + + Size - - 8 + + label101 - - + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + flowLayoutPanel2 - - Fill + + 4 - - 24, 15 + + Segoe UI Symbol, 9.75pt - - flowLayoutPanel4 + + 309, 2 - - 43, 0 + + 0, 0, 0, 0 - - 1 + + 44, 25 - - Times New Roman, 9pt + + 135 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericUpDownCrystallineSize - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - panel1 + + flowLayoutPanel2 - - Segoe UI Symbol, 9pt + + 5 - - System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - System.Windows.Forms.ToolTip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - tabPageStrainStress + + NoControl - + + 357, 4 + + 4, 2, 4, 0 - - tabPageBounds + + 26, 17 - - 282, 196 + + 139 - - flowLayoutPanel2 + + nm - - Name + + label99 - - 47, 24 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Crystallography.Controls.LatticePlaneControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - - label105 - - - tabPageStrainStress + + flowLayoutPanel2 - - tabPageStrainStress + + 6 - - 10, 4 + + Top - - Chemical formula + + 0, 0 - - 95 + + 0, 2, 0, 0 - - tabPageStrainStress + + 459, 27 - - boundControl + + 148 - - 4, 4 + + False - - GrowAndShrink + + flowLayoutPanel2 - - 1000, 24 + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 47, 24 + + tabPagePolycrystalline - - 467, 25 + + 2 - - 252, 22 + + 4, 26 - - as TXT file (all Euler angle and density) sorted + + 459, 298 - - Formula + + 8 - - 252, 22 + + Polycrystalline Property - - 0 + + tabPagePolycrystalline - - 1000, 24 + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - numericBoxDensity + + tabControl - - textBoxMemo + + 7 - - 309, 22 + + Fill - - Stress (Reuss model) - + + Segoe UI Symbol, 9pt - - 251, 69 + + 3, 3 - + 3, 4, 3, 4 - - - - - Read + + 453, 292 - - + + 0 - - NoControl + + boundControl - - Fill + + Crystallography.Controls.BoundControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 467, 27 + + tabPageBounds - - 253 + + 0 - - 251 + + 4, 26 - - + + 3, 3, 3, 3 - - Vertical + + 459, 298 - - Cell mass in 10⁻²⁴ g + + 9 - - 0, 0, 0, 0 + + Bounds - - 1, 22 + + tabPageBounds - - GrowAndShrink + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + tabControl - - + + 8 - + Fill - - 0 - - - GrowAndShrink + + Segoe UI Symbol, 9pt - - True + + 3, 3 - - label29 + + 3, 4, 3, 4 - - True + + 453, 292 - - + + 0 - - toolStripSeparator2 + + latticePlaneControl - - Times New Roman, 9pt + + Crystallography.Controls.LatticePlaneControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - Fill + + tabPageLatticePlane - - 48, 25 + + 0 - - numericBoxStress23 + + 4, 26 - - 0, 0, 4, 0 + + 3, 3, 3, 3 - - 3, 21 + + 459, 298 - - True + + 10 - - 1, 23 + + Lattice Plane - - 0, 54 + + tabPageLatticePlane - - bondControl + + System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 453, 133 + + tabControl - - NoControl + + 9 - - tabPageReference + + Fill - - numericBoxStrain13 + + Segoe UI Symbol, 9.75pt - - Reset Debye-Waller factor + + 0, 52 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 2, 0, 0 - - NoControl + + True - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 467, 328 - - Segoe UI Symbol, 9.75pt - - - 24, 15 - - - Chemical formula + + 0 - - + + tabControl - - + + System.Windows.Forms.TabControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - importCrystalFromCIFAMCToolStripMenuItem + + 3 - - 2, 3, 2, 3 + + Fill - - 20 + + Segoe UI Symbol, 9.75pt - - Times New Roman, 9pt + + 55, 0 - - strainControlToolStripMenuItem + + 0, 3, 3, 0 - + True - - 0, 52 - - - System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Vertical - - 52, 17 + + 371, 25 - - 1, 22 + + 76 - - 5 + + Chemical formula - - Revert cell constants + + textBoxFormula - - True + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + panel1 - - toolStripSeparator3 + + 0 - - 24 + + GrowAndShrink - - 0 + + Right - - True + + Segoe UI Symbol, 9.75pt - - 1000, 25 + + Z - - 309, 2 + + 426, 0 - - + + 4, 0, 0, 0 - - tabPageStrainStress + + 1000, 25 - - + + 1, 25 - - 1000, 24 + + 0, 0, 1, 0 - - Top + + 41, 25 - - label104 + + 95 - - 0 + + Z (Number of formula in the unit cell) - - Segoe UI Symbol, 9.75pt + + Z (Number of formula in the unit cell) - - Strain / Stress + + numericBoxZnumber - + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 93 + + panel1 - - GrowAndShrink + + 1 - + True - - 249 - - - 426, 0 + + Left - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - True + + 0, 0 - - 1, 22 + + 0, 0, 0, 0 - - + + 0, 2, 0, 0 - - groupBox5 + + 55, 19 - - 453, 159 + + 85 - - + + Formula - - 88 + + Chemical formula - - tabPageStrainStress + + label90 - - Top + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + panel1 - - 26, 17 + + 2 - - 1 + + Top - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0, 27 - - + + 467, 25 - - NoControl + + 98 - - 1, 23 + + panel1 - - 3, 60 + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 10 + + $this - - tabControl + + 4 - - Crystallography.Controls.ElasticityControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 96, 22 + + + 268, 22 - - Times New Roman, 9pt + + Scattering Factor - - 7 + + 268, 22 - - NoControl + + Symmetry Information - - 47, 24 + + 265, 6 - - ε23 + + 268, 22 - - Vertical + + Import from CIF, AMC... - - clearAllDataToolStripMenuItem + + 268, 22 - - - - - 309, 22 + + Export to CIF - - g/cm³ + + 268, 22 - - 96, 96 + + Send this crystal to other software - - panel5 + + False - - 0, 2, 0, 0 + + 265, 6 - - label116 + + 268, 22 - - 1, 1, 1, 1 + + Revert cell constants - - 240 + + 265, 6 - - GrowAndShrink + + 268, 22 - - Fill + + Strain Control - - 1000, 24 + + False - - EOS + + 268, 22 - - Elasticity + + Convert to P1 spacegroup - - Z + + 268, 22 - - 4, 0, 4, 0 + + Convert to a superstructure - - 3, 3 + + 268, 22 - - 2 + + Convert to an equivalent spacegroup - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 269, 242 - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + contextMenuStrip - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + Fill - - Segoe UI Symbol, 9pt + + Segoe UI Symbol, 9.75pt - - + + 43, 0 - - 0, 0, 1, 0 + + 0, 3, 0, 0 - - 1 + + 206, 25 - - Reset all data + + 0 - - Segoe UI Symbol, 9pt + + Name of the crystal - - Segoe UI Symbol, 9.75pt + + textBoxName - - Molar Volume + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1 + + panel4 - - 136 + + 0 - - 1, 22 + + True - - GrowAndShrink + + Left - - 4, 0, 4, 0 + + Segoe UI Symbol, 9.75pt - - 4, 26 + + NoControl - - 0 + + 0, 0 - - tabPageStrainStress + + 3, 5, 3, 0 - - 10, 3, 3, 3 + + 0, 2, 0, 0 - - label111 + + 43, 19 - - + + 80 - - Segoe UI Symbol, 9pt + + Name - - 9 + + label22 - - GrowAndShrink + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1000, 24 + + panel4 - - + + 3 - - 3, 3 + + True - + GrowAndShrink - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Title - - - 1, 23 + + Right - - 175, 25 + + Segoe UI Symbol, 9.75pt - - 192, 162 + + TopCenter - - 149 + + NoControl - - Top + + 353, 0 - - 6 + + 0, 0, 0, 0 - - 25 + + 114, 25 - - + + 87 - - + + Scattering factor - - numericUpDownAngleSubDivision + + Open another window with the structure factors - - 0, 0 + + buttonScatteringFactor - + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Vertical + + panel4 - - 241 + + 2 - - False + + True - - symmetryControl + + GrowAndShrink - - 1000, 25 + + Right - + Segoe UI Symbol, 9.75pt - - True + + TopCenter - - tabPageStrainStress + + NoControl - - Cell Volume + + 249, 0 - - 1, 1, 1, 1 + + 104, 25 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 14, 16 + + 88 - - System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Symmetry info. - - toolStripSeparator1 + + Open another window with the detailed symmetry information - - 307, 46 + + buttonSymmetryInfo - - Ref. + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9.75pt + + panel4 - - 257, 84 + + 1 - - Segoe UI, 9pt + + True - - 148 + + GrowAndShrink - - 0 + + Top - + 0, 0 - - 0, 0, 1, 0 - - - tabPageStrainStress + + 467, 0 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 86 - - + + flowLayoutPanel1 - - 47, 24 + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Times New Roman, 9pt + + $this - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 6 - - 3 + + Top - - 25, 15 + + 0, 0 - - colorControl + + 0, 0, 0, 2 - - Segoe UI Symbol, 9.75pt + + 467, 27 - - 31, 17 + + 87 - - 1, 1, 1, 1 + + panel4 - - 0 + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this - - 0, 0 + + 5 - + True + + + 50 + + + 96, 96 - - 0, 0 - - - label117 - - - tabPageReference - - - 4, 26 + + GrowAndShrink - - + + 0, 0, 0, 0 - - NoControl + + 467, 380 resetToolStripMenuItem - - 459, 298 - - - flowLayoutPanel4 - - - Segoe UI Symbol, 9pt - - - tabPageStrainStress - - - tabPageStrainStress - - - 0, 0, 1, 0 - - - 0 - - - Bonds ( & Polyhedra) - - - ų - - - Convert to P1 symmetry - - - 4, 2, 4, 2 - - - GrowAndShrink - - - flowLayoutPanel3 - - - - - - 218, 2 - - - 0, 0, 1, 0 - - - tabPageReference - - - label99 - - - GrowAndShrink - - - Fill - - - ε22 - - - 1, 22 - - - 1000, 25 - - - 0, 0 - - - 3 - - - GrowAndShrink - - - Segoe UI Symbol, 9.75pt - - - - - - 64, 30 - - - 0, 0, 0, 0 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + readToolStripMenuItem - - 25, 15 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 + + saveToolStripMenuItem - - tabPageEOS + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 218, 26 + + exportToolStripMenuItem - - 4 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 4, 26 + + asCTFFilecomatibleToCHANNEL5FileToolStripMenuItem - - 1, 22 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 236 + + asTXTFileAllEulerAngleAndDensityToolStripMenuItem - - label109 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Segoe UI Symbol, 9.75pt + + asTXTFileallEulerAngleAndDensitySortedToolStripMenuItem - - GrowAndShrink + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 171, 25 + + scatteringFactorToolStripMenuItem - - asTXTFileAllEulerAngleAndDensityToolStripMenuItem + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + symmetryInformationToolStripMenuItem - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0, 0, 1, 0 + + toolStripSeparator2 - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 18 + + importCrystalFromCIFAMCToolStripMenuItem - - Fill + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 exportThisCrystalAsCIFToolStripMenuItem - - tabPagePolycrystalline + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 263 + + sendThisCrystalToOtherSoftwareToolStripMenuItem - - 106, 180 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + toolStripSeparator1 - - Segoe UI Symbol, 9.75pt + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + revertCellConstantsToolStripMenuItem - - 304, 29 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripSeparator3 - - 82, 14 + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - convertToP1SymmetryToolStripMenuItem + + strainControlToolStripMenuItem - - 176, 4 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabPageStrainStress + + convertToP1SymmetryToolStripMenuItem - - 3 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1, 22 + + convertToSuperstructureToolStripMenuItem - - 5 + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - flowLayoutPanel2 + + convertToAnotherSpacegroupToolStripMenuItem - - Top + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 453, 292 + + toolTip - - GrowAndShrink + + System.Windows.Forms.ToolTip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 CrystalControl - - System.Windows.Forms.TabPage, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 258, 46 - - - $this - - - Scattering Factor - - - 255, 29 - - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - - 4, 26 - - - 0, 0, 0, 0 - - - 138 - - - tabPageAtom - - - 47, 24 + + System.Windows.Forms.UserControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 50 - - - True - - - 96, 22 - - - ja - - - 17, 17 - - - 249, 22 - - - 414, 22 - \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.Designer.cs b/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.Designer.cs new file mode 100644 index 0000000..1bf355d --- /dev/null +++ b/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.Designer.cs @@ -0,0 +1,118 @@ +namespace Crystallography.Controls; + +partial class FormAnotherSpaceGroup +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.listBox = new System.Windows.Forms.ListBox(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.buttonOK = new System.Windows.Forms.Button(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.flowLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // listBox + // + this.listBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.listBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; + this.listBox.FormattingEnabled = true; + this.listBox.HorizontalScrollbar = true; + this.listBox.IntegralHeight = false; + this.listBox.ItemHeight = 18; + this.listBox.Location = new System.Drawing.Point(0, 0); + this.listBox.Name = "listBox"; + this.listBox.ScrollAlwaysVisible = true; + this.listBox.Size = new System.Drawing.Size(226, 128); + this.listBox.TabIndex = 0; + this.listBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBoxSpaceGroup_DrawItem); + // + // buttonCancel + // + this.buttonCancel.AutoSize = true; + this.buttonCancel.Location = new System.Drawing.Point(163, 0); + this.buttonCancel.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(60, 25); + this.buttonCancel.TabIndex = 2; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); + // + // buttonOK + // + this.buttonOK.AutoSize = true; + this.buttonOK.Location = new System.Drawing.Point(97, 0); + this.buttonOK.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(60, 25); + this.buttonOK.TabIndex = 3; + this.buttonOK.Text = "OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.AutoSize = true; + this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.flowLayoutPanel1.Controls.Add(this.buttonCancel); + this.flowLayoutPanel1.Controls.Add(this.buttonOK); + this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; + this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 128); + this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(226, 25); + this.flowLayoutPanel1.TabIndex = 5; + // + // FormAnotherSpaceGroup + // + this.AcceptButton = this.buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(226, 153); + this.ControlBox = false; + this.Controls.Add(this.listBox); + this.Controls.Add(this.flowLayoutPanel1); + this.Name = "FormAnotherSpaceGroup"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Convert to another spacegroup"; + this.flowLayoutPanel1.ResumeLayout(false); + this.flowLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListBox listBox; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; +} \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.cs b/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.cs new file mode 100644 index 0000000..a19c2c8 --- /dev/null +++ b/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.cs @@ -0,0 +1,123 @@ +using IronPython.Runtime.Operations; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace Crystallography.Controls; +public partial class FormAnotherSpaceGroup : Form +{ + + private (int SeriesNum, string Notation)[] candidates; + public (int SeriesNum, string Notation)[] Candidates + { + set + { + candidates = value; + listBox.Items.Clear(); + foreach (var c in value) + listBox.Items.Add(c.Notation); + listBox.SelectedIndex = 0; + } + } + public int SeriesNum => candidates[listBox.SelectedIndex].SeriesNum; + + + public FormAnotherSpaceGroup() + { + InitializeComponent(); + } + + private void buttonOK_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void buttonCancel_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + + #region 群の記号を斜体、上付き、下付などに整形する + + //下付き文字用フォント + readonly Font fontSub = new("Times New Roman", 8f, FontStyle.Regular); + //斜体 + readonly Font fontItalic = new("Times New Roman", 11f, FontStyle.Italic); + //普通 + readonly Font fontRegular = new("Times New Roman", 11f, FontStyle.Regular); + //太字 + readonly Font fontBold = new("Times New Roman", 10f, FontStyle.Bold); + + private void listBoxSpaceGroup_DrawItem(object sender, DrawItemEventArgs e) + { + if (e.Index < 0) return; + e.DrawBackground(); + string txt = ((ListBox)sender).Items[e.Index].ToString(); + + float xPos = e.Bounds.Left; + Brush b; + if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) + b = new SolidBrush(Color.Black); + else + b = new SolidBrush(Color.White); + e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + + //「:」が含まれている場合は、空間群番号を表すので、先に「:」までを処理する。 + if (txt.Contains(':')) + { + var i = txt.find(":") + 1; + + e.Graphics.DrawString(txt[0..i].ToString(), fontRegular, b, xPos, e.Bounds.Y); + xPos += e.Graphics.MeasureString(txt[0..i].ToString(), fontRegular).Width - 2; + txt = txt[i..]; + } + + while (txt.Length > 0) + { + if (txt.StartsWith(" ", StringComparison.Ordinal)) + xPos += 0; + else if (txt.StartsWith("sub", StringComparison.Ordinal))//subで始まる時は + { + xPos -= 1; + txt = txt[3..]; + e.Graphics.DrawString(txt[0].ToString(), fontSub, b, xPos, e.Bounds.Y + 3); + xPos += e.Graphics.MeasureString(txt[0].ToString(), fontSub).Width - 2; + } + else if (txt.StartsWith("-", StringComparison.Ordinal))//-で始まる時は + { + float x = e.Graphics.MeasureString(txt[1].ToString(), fontRegular).Width; + e.Graphics.DrawLine(new Pen(b, 1), new PointF(xPos + 2f, e.Bounds.Y + 1), new PointF(x + xPos - 3f, e.Bounds.Y + 1)); + } + else if (txt.StartsWith("Hex", StringComparison.Ordinal) || txt.StartsWith("Rho", StringComparison.Ordinal) || txt.StartsWith("(1)", StringComparison.Ordinal) || txt.StartsWith("(2)", StringComparison.Ordinal)) + { + xPos += 2; + e.Graphics.DrawString(txt[..3], fontSub, b, xPos, e.Bounds.Y + 3); + xPos += e.Graphics.MeasureString(txt[..3], fontSub).Width - 2; + txt = txt[2..]; + } + else if (txt[0] == '/') + { + xPos -= 1; + e.Graphics.DrawString(txt[0].ToString(), fontRegular, b, xPos, e.Bounds.Y); + xPos += e.Graphics.MeasureString(txt[0].ToString(), fontRegular).Width - 5; + } + else if (('0' <= txt[0] && '9' >= txt[0]) || txt[0] == '(' || txt[0] == ')') + { + e.Graphics.DrawString(txt[0].ToString(), fontRegular, b, xPos, e.Bounds.Y); + xPos += e.Graphics.MeasureString(txt[0].ToString(), fontRegular).Width - 2; + } + else + { + e.Graphics.DrawString(txt[0].ToString(), fontItalic, b, xPos, e.Bounds.Y); + xPos += e.Graphics.MeasureString(txt[0].ToString(), fontItalic).Width - 2; + } + txt = txt[1..]; + } + + b.Dispose(); + } + #endregion +} diff --git a/Crystallography.Controls/Macro/FormMacroList.resx b/Crystallography.Controls/Crystal/FormAnotherSpaceGroup.resx similarity index 100% rename from Crystallography.Controls/Macro/FormMacroList.resx rename to Crystallography.Controls/Crystal/FormAnotherSpaceGroup.resx diff --git a/Crystallography.Controls/Crystal/SymmetryControl.cs b/Crystallography.Controls/Crystal/SymmetryControl.cs index 3de6ebf..af3d2fc 100644 --- a/Crystallography.Controls/Crystal/SymmetryControl.cs +++ b/Crystallography.Controls/Crystal/SymmetryControl.cs @@ -28,6 +28,7 @@ public int SymmetrySeriesNumber { (int CrystalSystem, int PointGroup, int SpaceGroup) = SymmetryStatic.GetSytemAndGroupFromSeriesNumber(value); SkipEvent = true; + SuspendLayout(); comboBoxCrystalSystem.SelectedIndex = CrystalSystem; @@ -40,6 +41,7 @@ public int SymmetrySeriesNumber comboBoxSpaceGroup.SelectedIndex = SpaceGroup; SkipEvent = false; + ResumeLayout(); SetCellConstantsBySymmetry(); } @@ -56,6 +58,7 @@ public int SymmetrySeriesNumber get => (numericBoxA.Value / 10, numericBoxB.Value / 10, numericBoxC.Value / 10, numericBoxAlpha.RadianValue, numericBoxBeta.RadianValue, numericBoxGamma.RadianValue); set { + SuspendLayout(); SkipEvent = true; numericBoxA.Value = value.A * 10; numericBoxB.Value = value.B * 10; @@ -64,6 +67,7 @@ public int SymmetrySeriesNumber numericBoxBeta.RadianValue = value.Beta; numericBoxGamma.RadianValue = value.Gamma; SkipEvent = false; + ResumeLayout(); } } @@ -86,12 +90,14 @@ public int SymmetrySeriesNumber numericBoxAlphaErr.RadianValue, numericBoxBetaErr.RadianValue, numericBoxGammaErr.RadianValue); set { + SuspendLayout(); numericBoxAErr.Value = value.AErr * 10; numericBoxBErr.Value = value.BErr * 10; numericBoxCErr.Value = value.CErr * 10; numericBoxAlphaErr.RadianValue = value.AlphaErr; numericBoxBetaErr.RadianValue = value.BetaErr; numericBoxGammaErr.RadianValue = value.GammaErr; + ResumeLayout(); } } @@ -223,6 +229,7 @@ public void SetCellConstantsBySymmetry() { if (SkipEvent) return; SkipEvent = true; + SuspendLayout(); var tempSym = SymmetryStatic.Symmetries[SymmetrySeriesNumber]; //いったんすべてをreadonly=falseにする @@ -333,11 +340,12 @@ public void SetCellConstantsBySymmetry() numericBoxAlphaErr.Enabled = numericBoxAlpha.Enabled; numericBoxBetaErr.Enabled = numericBoxBeta.Enabled; numericBoxGammaErr.Enabled = numericBoxGamma.Enabled; - + ResumeLayout(); SkipEvent = false; ItemChanged?.Invoke(this, new EventArgs()); //GenerateFromInterface(); + } #endregion diff --git a/Crystallography.Controls/Crystal/SymmetryControl.ja.resx b/Crystallography.Controls/Crystal/SymmetryControl.ja.resx index e23bd54..176c214 100644 --- a/Crystallography.Controls/Crystal/SymmetryControl.ja.resx +++ b/Crystallography.Controls/Crystal/SymmetryControl.ja.resx @@ -79,6 +79,9 @@ + + + 128, 54 @@ -88,9 +91,15 @@ + + + + + + 0, 54 @@ -103,6 +112,9 @@ + + + 72, 54 @@ -116,6 +128,9 @@ メイリオ, 9pt + + 300, 132 + 格子定数 @@ -123,19 +138,19 @@ 53, 74 - 141, 26 + 211, 26 53, 45 - 141, 26 + 211, 26 53, 17 - 141, 25 + 211, 25 メイリオ, 9pt @@ -191,7 +206,13 @@ メイリオ, 9pt + + 272, 132 + 対称性 + + 4, 132 + \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/SymmetryControl.resx b/Crystallography.Controls/Crystal/SymmetryControl.resx index 9f5e617..e7adf41 100644 --- a/Crystallography.Controls/Crystal/SymmetryControl.resx +++ b/Crystallography.Controls/Crystal/SymmetryControl.resx @@ -57,1657 +57,1669 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - comboBoxSearchResult - - + NoControl - - - - - - 0, 0, 0, 0 - - - 0, 0, 1, 0 - - - Segoe UI Symbol, 9pt + + 16, 17 - - + + 1000, 25 - - + + α - - Right + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1000, 25 + + tableLayoutPanel1 - - 56, 25 + + + 0, 0, 1, 0 - - + + Disable - - 19 + + tableLayoutPanel1 - - Top, Left, Right + + 10, 50 - - numericBoxB + + tableLayoutPanel1 - - + + 1, 23 - - numericBoxBErr + + Cell constant "c" in angstrom - - - 3 + + Segoe UI Symbol, 9pt - - Fill + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tableLayoutPanel1 + + - - tableLayoutPanel1 + + 0 - - True + + 17 - - Fill + + 128, 27 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 222, 27 - - Unknown + + 1000, 25 - - monoclinic + + 0, 0, 0, 0 - - groupBox4 + + 15, 17 - - Fill + + - - Segoe UI Symbol, 9pt + + 18 - - Fill + + Cell constant "β" in degree - - Right + + Space Group - - 13, 17 + + groupBoxSymmetry - + + label28 + + 56, 25 - + Segoe UI Symbol, 9pt - - Cell constant "α" in degree - - - 6, 0, 0, 0 - - - System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 23 - - tableLayoutPanel1 + + + 3 - + True - - tableLayoutPanel1 + + NoControl - + + comboBoxPointGroup + + - - numericBoxAlphaErr + + 166, 0 - - 18 + + 16, 17 - - 95, 17 + + Show error - + + 1 + + Segoe UI Symbol, 9.75pt - - label17 + + 2 - - Segoe UI Symbol, 9.75pt + + 30 - + 0, 0, 0, 0 - - 1, 23 + + - - 8 + + Fill - - Segoe UI Symbol, 9pt + + 0, 0, 1, 0 - - True + + GrowAndShrink - - 72, 27 + + 1 - - 1000, 25 + + cubic + + + 0, 0, 0, 0 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null 16, 55 - - Cell constant "b" in angstrom + + 1000, 25 - - 14 + + textBoxSearch - - 1 + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="label48" Row="2" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="label46" Row="1" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="numericBoxBeta" Row="1" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="numericBoxAlpha" Row="0" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="label47" Row="0" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="numericBoxGammaErr" Row="2" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="label23" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="numericBoxAlphaErr" Row="0" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="numericBoxBetaErr" Row="1" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="numericBoxA" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label26" Row="0" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="label45" Row="2" RowSpan="1" Column="3" ColumnSpan="1" /><Control Name="numericBoxGamma" Row="2" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="label18" Row="1" RowSpan="1" Column="3" ColumnSpan="1" /><Control Name="numericBoxBErr" Row="1" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="numericBoxB" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label24" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label25" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label28" Row="2" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="label27" Row="1" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="numericBoxC" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="numericBoxCErr" Row="2" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="numericBoxAErr" Row="0" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="label44" Row="0" RowSpan="1" Column="3" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,Percent,25,Percent,25,AutoSize,0,AutoSize,0,Percent,25,Percent,25,AutoSize,0" /><Rows Styles="Percent,33.33333,Percent,33.33334,Percent,33.33334" /></TableLayoutSettings> - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9pt - - 128, 55 + + - - label26 + + Search - - 10, 50 + + 1 - - 150, 0 + + 0, 0, 1, 0 - - 1000, 25 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - label23 + + Segoe UI Symbol, 9.75pt - - Cell constant "β" in degree + + tetragonal - - groupBoxSymmetry + + numericBoxAErr - + + label27 + + 0 - - SymmetryControl + + label20 - + tableLayoutPanel1 - - True + + 1 - - Segoe UI Symbol, 9.75pt + + 7 - - Set space group in HM notation + + Crystal System - - 0 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tableLayoutPanel1 + + 1000, 25 - - 16, 17 + + Segoe UI Symbol, 9pt - - System.Windows.Forms.UserControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 22 - - comboBoxPointGroup + + Segoe UI Symbol, 9pt - - Segoe UI Symbol, 9.75pt + + 1 - - textBoxSearch + + 0 - - label48 + + 0, 0, 0, 0 - - tableLayoutPanel1 + + 576, 132 - - 1, 23 + + Segoe UI Symbol, 9pt - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + - - 272, 132 + + 92, 17 - - Fill + + True - - 3 + + 72, 55 - - tableLayoutPanel1 + + - - Times New Roman, 11.25pt, style=Italic + + 0, 0, 1, 0 - - label44 + + 1, 23 - - 278, 27 + + Right - - + + True - - 0, 27 + + NoControl - - GrowAndShrink + + Set space group in HM notation - - True + + tableLayoutPanel1 - - NoControl + + GrowAndShrink - - Segoe UI Symbol, 9pt + + ° - - 4 + + tableLayoutPanel1 - + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 14, 17 - - - NoControl + + 95, 74 - - 0, 0, 1, 0 + + 304, 0 - + - - 1 - - - comboBoxSpaceGroup + + ± - - 166, 55 + + 0 - - 2 + + label21 - - 84, 17 + + groupBoxSymmetry - + GrowAndShrink - - 0 + + 300, 0 - - + + 0, 0, 1, 0 - - toolTip + + Times New Roman, 11.25pt, style=Italic - - 300, 132 + + NoControl - - 144, 26 + + True - - 1, 23 + + Segoe UI Symbol, 9pt - - 0, 0, 1, 0 + + trigonal - - 13, 17 + + System.Windows.Forms.UserControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0, 0, 0, 0 + + + Times New Roman, 11.25pt, style=Italic + + + ± 56, 25 - - 1, 23 + + 0, 0, 1, 0 - - tableLayoutPanel1 + + 1 - - 278, 0 + + 16, 0 - - 4 + + comboBoxSearchResult - - label28 + + NoControl - - label47 + + label17 - - 1, 23 + + 1000, 25 - - 47, 17 + + Segoe UI Symbol, 9.75pt - - tableLayoutPanel1 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 128, 0 + + Segoe UI Symbol, 9.75pt - - panel1 + + NoControl - - ± + + 6, 0, 0, 0 - - GrowAndShrink + + 0, 0, 0, 0 - - 0, 0, 0, 0 - - - Segoe UI Symbol, 9pt + + label26 - - 0, 0, 0, 0 + + 278, 27 - - 16, 17 + + GrowAndShrink - - 1000, 25 + + 6, 0, 0, 0 - - 0, 0, 0, 0 + + 3, 21 - - 6, 108 + + 3 - - Top, Left, Right + + 78, 17 - + True - - System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tableLayoutPanel1 - - - tableLayoutPanel1 - - - 16, 17 + + System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 3, 21 + + 1000, 25 - - True + + ° - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 47, 17 - - Segoe UI Symbol, 9.75pt + + Right - - label18 + + toolTip - - Fill + + ± - + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 groupBox4 - - Segoe UI Symbol, 9pt + + 16, 17 - - 64, 21 + + groupBoxSymmetry - - γ + + 1 - - ± + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label46 + + 56, 25 - - numericBoxGammaErr + + 56, 25 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 21 - - GrowAndShrink + + 0 - - b + + Fill - - 304, 0 + + Cell constant "a" in angstrom - - Times New Roman, 11.25pt + + 7 - - ° + + tableLayoutPanel1 - - 4 + + Top, Left, Right - - label20 + + Segoe UI Symbol, 9pt - - 0, 0, 0, 0 + + Segoe UI Symbol, 9.75pt - - 0, 0, 0, 0 + + - - + + $this - - 0, 0, 0, 0 + + 96, 96 - - Fill + + 1, 23 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + Segoe UI Symbol, 9.75pt - - 0, 0, 0, 0 + + - - Top, Left, Right + + 6, 79 - - 1000, 25 + + label18 - - 16, 0 + + 13, 17 - - 1, 23 + + ± - - Top, Left, Right + + 0 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 19 - + Segoe UI Symbol, 9pt - - Segoe UI Symbol, 9.75pt - - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - - numericBoxAlpha + + Set crystal system - - tableLayoutPanel1 + + 150, 27 - - hexagonal + + - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1, 23 - - 2 + + Fill - + 0, 0, 0, 0 - - 1 - - - 1 + + 56, 25 - - numericBoxA + + 0, 0, 0, 0 - - 54, 106 + + 1, 23 - - 1 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - Cell constant "a" in angstrom + + - - 0, 0, 1, 0 + + 56, 25 - + Segoe UI Symbol, 9.75pt - + Segoe UI Symbol, 9pt - - Times New Roman, 11.25pt, style=Italic + + 1 - - Segoe UI Symbol, 9.75pt + + 0, 0, 0, 0 - - Segoe UI Symbol, 9.75pt + + - - Cell constant "β" in degree + + 11 - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - NoControl - - - 0, 0, 1, 0 - - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 15 - - - Disable + + Segoe UI Symbol, 9pt - - 11 + + Times New Roman, 9pt - - System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - NoControl + + 3 - - tableLayoutPanel1 + + 169, 26 - - 56, 25 + + - - + + 1, 23 - - + + Segoe UI Symbol, 9pt - - Segoe UI Symbol, 9.75pt + + Cell constants - + Segoe UI Symbol, 9pt - - True + + - - comboBoxCrystalSystem + + Cell constant "c" in angstrom - - Segoe UI Symbol, 9pt + + panel1 - - Search space group + + Disable - - 1000, 25 + + 2 - - Segoe UI Symbol, 9.75pt + + 0, 55 - - 5 + + True - - Set point group in HM notation + + 0, 0, 0, 0 - + 1 - - NoControl + + Segoe UI Symbol, 9pt - + 1 - - 21 - - + Segoe UI Symbol, 9.75pt - - GrowAndShrink + + groupBoxSymmetry - - groupBox4 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1000, 25 + + 0, 0, 0, 0 - - 169, 26 + + - - 5 + + tableLayoutPanel1 - - groupBoxSymmetry + + 0, 0, 0, 0 - - label25 + + Top, Right - - 92, 17 + + Top, Left, Right - - 56, 25 + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 14 + + NoControl - - 56, 25 + + Segoe UI Symbol, 9pt - - ° + + 12 - - 0, 0, 0, 0 + + True - - Top, Right + + 8 - - 2 + + 54, 106 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 64, 21 - - 2 + + 0, 0 - - 1000, 25 + + True - - 0, 0, 0, 0 + + Segoe UI Symbol, 9.75pt - + GrowAndShrink - + - - Segoe UI Symbol, 9.75pt + + 0, 0, 0, 0 - - 16, 17 + + 169, 25 - - 16, 27 + + - - Times New Roman, 11.25pt, style=Italic + + 8 - - $this + + label24 - - NoControl + + 300, 158 - - 0, 55 + + 40 - - 96, 96 + + numericBoxAlphaErr - - 169, 25 + + 294, 84 - - 0, 0, 1, 0 + + Fill - - Segoe UI Symbol, 9.75pt + + - - 72, 55 + + NoControl - - 15, 17 + + comboBoxCrystalSystem - - 7 + + Segoe UI Symbol, 9.75pt - - 120, 103 + + Times New Roman, 11.25pt - - 0, 0, 1, 0 + + - - 4 + + 0, 0, 0, 0 - - GrowAndShrink + + Cell constant "α" in degree + + + label44 + + + 16, 17 56, 25 - - Segoe UI Symbol, 9.75pt + + numericBoxGammaErr - - Set space group in HM notation + + Segoe UI Symbol, 9pt - - 1 + + 0 - - NoControl + + Segoe UI Symbol, 9.75pt - - label19 + + β - - 2 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0, 0, 1, 0 + + groupBoxSymmetry - - 222, 27 + + 3 - - 1 + + 0, 0 - - Segoe UI Symbol, 9pt + + Disable - - 17 + + 3, 21 - - 278, 55 + + 1 - - Times New Roman, 11.25pt + + NoControl - - System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 3 - - numericBoxGamma + + 0, 0, 1, 0 - - 1 + + tableLayoutPanel1 - - 83, 19 + + Times New Roman, 11.25pt - - Cell constant "α" in degree + + 1000, 25 - - label27 + + Segoe UI Symbol, 9.75pt - - 166, 27 + + NoControl + + + Segoe UI Symbol, 9.75pt Symmetry - - Segoe UI Symbol, 9pt + + True - - 22 + + - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 14, 17 - - a + + 56, 25 - - Segoe UI Symbol, 9pt + + 0, 0, 0, 0 - - 0, 0, 1, 0 + + tableLayoutPanel1 - - 6 + + Times New Roman, 11.25pt, style=Italic - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Cell constant "b" in angstrom - - 1 + + groupBox4 - - 1 + + 222, 0 - - tableLayoutPanel1 + + 3 - - 222, 55 + + 0, 0, 1, 0 - - 16, 17 + + 84, 17 - + Fill - - Segoe UI Symbol, 9.75pt - - - Fill + + numericBoxBetaErr - - Segoe UI Symbol, 9.75pt + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - Times New Roman, 11.25pt, style=Italic + + 128, 0 - - ± + + Search space group - - 7 + + 1000, 25 - - 1 + + 2 - + tableLayoutPanel1 - - Times New Roman, 11.25pt, style=Italic - - - - - - $this + + 0, 0, 0, 0 - - 3 + + numericBoxAlpha - - 3 + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Crystal System + + 2 - - + + 0 - - 6, 0, 0, 0 + + Segoe UI Symbol, 9pt - - True + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 1, 23 + + $this - - 72, 0 + + 16, 27 - - Fill + + Cell constant "α" in degree - - groupBoxSymmetry + + Cell constant "β" in degree - - Fill + + 1, 23 - - 0, 0, 1, 0 + + label46 - - NoControl + + 0, 0, 0, 0 - - numericBoxCErr + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tableLayoutPanel1 - - True + + 2 - + tableLayoutPanel1 - - GrowAndShrink + + 0, 0, 1, 0 - - 3 + + ± - - Set crystal system + + 2 - - groupBoxSymmetry + + False - + Fill - - α + + 166, 27 - - 15, 17 + + Fill - - Segoe UI Symbol, 9pt + + 1, 23 9 - - 0, 0, 0, 0 + + System.Windows.Forms.ToolTip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + Search space group - - groupBoxSymmetry + + 144, 26 - - 56, 25 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Set point group in HM notation + + 4 - - 3 + + 20 - - + + 72, 27 - + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - 0, 0, 0, 0 - - - 1, 23 - - - 166, 0 - - - numericBoxC - - - 0 + + 56, 25 - - groupBoxSymmetry + + a - - 169, 26 + + True - + tableLayoutPanel1 - - System.Windows.Forms.TextBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tableLayoutPanel1 - + 1000, 25 - - GrowAndShrink + + tableLayoutPanel1 - - Search space group + + Set space group in HM notation - - c + + - - 0 + + tableLayoutPanel1 - - 1000, 25 + + 95, 45 - - 150, 27 + + Times New Roman, 11.25pt, style=Italic - - Segoe UI Symbol, 9pt + + Show error - - 4 + + groupBox4 - - tableLayoutPanel1 + + - - System.Windows.Forms.ToolTip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 10 Fill - - + + 150, 0 - - 20 + + GrowAndShrink - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GrowAndShrink - - groupBoxSymmetry + + 166, 55 - - tableLayoutPanel1 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9pt - - True + + numericBoxCErr - - 16 + + GrowAndShrink - - 212, 109 + + label19 - - 13 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - GrowAndShrink + + SymmetryControl - + + label48 + + + 0, 0, 0, 0 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 4, 158 + + 56, 25 - - 1, 1, 1, 1 + + Segoe UI Symbol, 9.75pt - - 1 + + orthorhombic - - 0, 0, 0, 0 + + 16, 17 - - True + + 1000, 25 - - NoControl + + Top, Left, Right - - <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="label48" Row="2" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="label46" Row="1" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="numericBoxBeta" Row="1" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="numericBoxAlpha" Row="0" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="label47" Row="0" RowSpan="1" Column="7" ColumnSpan="1" /><Control Name="numericBoxGammaErr" Row="2" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="label23" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="numericBoxAlphaErr" Row="0" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="numericBoxBetaErr" Row="1" RowSpan="1" Column="6" ColumnSpan="1" /><Control Name="numericBoxA" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label26" Row="0" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="label45" Row="2" RowSpan="1" Column="3" ColumnSpan="1" /><Control Name="numericBoxGamma" Row="2" RowSpan="1" Column="5" ColumnSpan="1" /><Control Name="label18" Row="1" RowSpan="1" Column="3" ColumnSpan="1" /><Control Name="numericBoxBErr" Row="1" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="numericBoxB" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="label24" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label25" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="label28" Row="2" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="label27" Row="1" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="numericBoxC" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="numericBoxCErr" Row="2" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="numericBoxAErr" Row="0" RowSpan="1" Column="2" ColumnSpan="1" /><Control Name="label44" Row="0" RowSpan="1" Column="3" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,Percent,25,Percent,25,AutoSize,0,AutoSize,0,Percent,25,Percent,25,AutoSize,0" /><Rows Styles="Percent,33.33333,Percent,33.33334,Percent,33.33334" /></TableLayoutSettings> + + Disable - - 1, 23 + + NoControl - - GrowAndShrink + + 1000, 25 - - 150, 55 + + 5 - - 0, 0, 0, 0 + + Fill - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 272, 158 - - Segoe UI Symbol, 9pt + + Top, Left, Right - - Segoe UI Symbol, 9pt + + 6 - - Show error + + Unknown - - Segoe UI Symbol, 9.75pt + + 1 - - + + 6, 108 - - 1, 23 + + γ - - numericBoxBeta + + tableLayoutPanel1 - - tetragonal + + Set point group in HM notation - - + + True - - checkBoxShowError + + 15 - - trigonal + + 1, 23 - - Segoe UI Symbol, 9.75pt + + Segoe UI Symbol, 9pt - - 56, 25 + + Cell constant "a" in angstrom - - ± + + 0, 0, 1, 0 - + + 1 + + True - - System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 278, 55 - - triclinic + + tableLayoutPanel1 - - 23 + + Cell constant "γ" in degree - - label45 + + 1 - - label24 + + 1, 23 + + + Segoe UI Symbol, 9pt + + + 16 groupBoxSymmetry - - System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + tableLayoutPanel1 - + + Top + + + 1 + + Segoe UI Symbol, 9pt - - + + hexagonal - - 1000, 25 + + 13, 17 - - NoControl + + 0, 0, 1, 0 - - 1, 23 + + Set crystal system + + + 0, 0, 0, 0 - - 0 + + Cell constant "b" in angstrom - - True + + 15, 17 - + Segoe UI Symbol, 9.75pt - - 13, 17 + + GrowAndShrink - - + + NoControl - - 0, 0, 0, 0 + + 13, 17 - - False + + tableLayoutPanel1 - - 222, 0 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 40 + + Segoe UI Symbol, 9pt - - 0, 0, 0, 0 + + label47 - - + + 4 - - 4, 132 + + 6, 0, 0, 0 - - 1 + + c - - 16, 17 + + Fill - - 0, 0, 1, 0 + + 72, 0 - - Segoe UI Symbol, 9pt + + 0, 0, 0, 0 - - NoControl + + System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + 95, 17 - - 0 + + 1, 1, 1, 1 - - Segoe UI Symbol, 9pt + + Segoe UI Symbol, 9.75pt - - 5 + + NoControl - - numericBoxBetaErr + + numericBoxB - - Segoe UI Symbol, 9pt + + Times New Roman, 11.25pt, style=Italic + + + 1, 23 Point Group - - ° + + $this - - tableLayoutPanel1 + + 16, 17 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 3 - - 0 + + 2 - + 1 - - Segoe UI Symbol, 9pt - - - NoControl - - - NoControl - - - groupBoxSymmetry + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Times New Roman, 11.25pt + + label23 Segoe UI Symbol, 9.75pt + + 6 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0, 0 - - + 0, 0, 0, 0 - - Cell constant "γ" in degree - - - Search - - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 56, 25 - - 0, 0, 0, 0 + + 278, 0 - - 1000, 25 + + Segoe UI Symbol, 9.75pt - - tableLayoutPanel1 + + - - 1 + + b - - 1 + + True - - label21 + + Times New Roman, 11.25pt, style=Italic - - + + NoControl - - True + + - - 8 + + comboBoxSpaceGroup - - System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + numericBoxBeta - - Disable + + Fill - - 1, 23 + + Cell constant "γ" in degree - - 128, 27 + + checkBoxShowError - - orthorhombic + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 78, 17 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Segoe UI Symbol, 9pt - - Segoe UI Symbol, 9.75pt + + - + True - - 0, 0, 0, 0 + + 212, 109 - - 2 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + 0 - - Times New Roman, 11.25pt, style=Italic + + 1 - - 0, 0 + + 4 - - Segoe UI Symbol, 9pt + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 576, 132 + + tableLayoutPanel1 - - ± + + 0, 0, 0, 0 - - ± + + 1 - - groupBoxSymmetry + + NoControl - - GrowAndShrink + + Segoe UI Symbol, 9.75pt - - 8 + + Times New Roman, 11.25pt, style=Italic - + 1 - - 294, 84 + + Set point group in HM notation - + True - - Segoe UI Symbol, 9.75pt + + 0, 27 - - 1 + + 169, 26 - - Show error + + 13 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + groupBoxSymmetry - + + 1 + + + ± + + tableLayoutPanel1 - - 0, 0, 0, 0 + + NoControl - - 2 + + 5 - - 95, 74 + + ° - - Times New Roman, 9pt + + groupBoxSymmetry - - Disable + + label45 - - tableLayoutPanel1 + + GrowAndShrink - - β + + 0 - - 95, 45 + + Times New Roman, 11.25pt - - 0, 0, 1, 0 + + 128, 55 - - 1 + + 8 - - NoControl + + 4 - + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 4 + + 5 - + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0, 0, 0, 0 + + Segoe UI Symbol, 9.75pt - - 3 + + tableLayoutPanel1 - - numericBoxAErr + + 150, 55 - - 10 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NoControl + + numericBoxBErr - - 300, 0 + + 1000, 25 - - 6 + + 83, 19 - - + + tableLayoutPanel1 - - Set crystal system + + groupBoxSymmetry - - 30 + + Fill - - Cell constants + + - - Space Group + + 222, 55 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + System.Windows.Forms.GroupBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 6, 79 + + label25 - - 0 + + GrowAndShrink - - cubic + + Segoe UI Symbol, 9.75pt - - Cell constant "c" in angstrom + + 120, 103 - - Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + 56, 25 - + 0, 0, 0, 0 - - Disable + + groupBoxSymmetry - - 1 + + numericBoxGamma - - 56, 25 + + GrowAndShrink - - tableLayoutPanel1 + + Segoe UI Symbol, 9pt - - 6, 0, 0, 0 + + Fill - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - 56, 25 + + numericBoxA - - 0, 0, 0, 0 + + triclinic - - Top + + numericBoxC - + + 1 + + + True + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null - - System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Segoe UI Symbol, 9.75pt - - 3, 21 + + Segoe UI Symbol, 9.75pt - - 12 + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Times New Roman, 11.25pt, style=Italic + + 5 - + 1 - - + + 1, 23 - - $this + + monoclinic - + True - + + + 1 + + + 0, 0, 1, 0 + + + Segoe UI Symbol, 9pt + 17, 17 + + True + ja diff --git a/Crystallography.Controls/CrystalDatabase/SearchCrystalControl.cs b/Crystallography.Controls/CrystalDatabase/SearchCrystalControl.cs index f6dfae0..9be3647 100644 --- a/Crystallography.Controls/CrystalDatabase/SearchCrystalControl.cs +++ b/Crystallography.Controls/CrystalDatabase/SearchCrystalControl.cs @@ -8,302 +8,302 @@ using System.Threading.Tasks; using System.Windows.Forms; -namespace Crystallography.Controls +namespace Crystallography.Controls; +public partial class SearchCrystalControl : UserControl { - public partial class SearchCrystalControl : UserControl - { - #region フィールド、プロパティ、イベント + #region フィールド、プロパティ、イベント - public CrystalDatabaseControl CrystalDatabaseControl; + public CrystalDatabaseControl CrystalDatabaseControl; - public delegate void ProgressChangedEventHandler(object sender, double progress, string message); - public event ProgressChangedEventHandler ProgressChanged; + public delegate void ProgressChangedEventHandler(object sender, double progress, string message); + public event ProgressChangedEventHandler ProgressChanged; - public FormPeriodicTable formPeriodicTable; + public FormPeriodicTable formPeriodicTable; - #endregion + #endregion - #region コンストラクタ - public SearchCrystalControl() - { - InitializeComponent(); - this.Load += SearchCrystalControl_Load; - } + #region コンストラクタ + public SearchCrystalControl() + { + InitializeComponent(); + this.Load += SearchCrystalControl_Load; + } - private void SearchCrystalControl_Load(object sender, EventArgs e) - { - formPeriodicTable = new FormPeriodicTable(); + private void SearchCrystalControl_Load(object sender, EventArgs e) + { + formPeriodicTable = new FormPeriodicTable(); - var parent = this.Parent; - while (parent is not Form && parent != null) - parent = parent.Parent; - if (parent == null) - return; - var form = parent as Form; - formPeriodicTable.Owner = form; + var parent = this.Parent; + while (parent is not Form && parent != null) + parent = parent.Parent; + if (parent == null) + return; + var form = parent as Form; + formPeriodicTable.Owner = form; - } + } - #endregion + #endregion - #region チェックボックス - private void checkBoxSearch_CheckedChanged(object sender, EventArgs e) - { - buttonPeriodicTable.Visible = checkBoxSearchElements.Checked; - if (formPeriodicTable.Visible && !checkBoxSearchElements.Checked) - formPeriodicTable.Visible = false; - - textBoxSearchRefference.Visible = checkBoxSearchRefference.Checked; - textBoxSearchName.Visible = checkBoxSearchName.Checked; - comboBoxSearchCrystalSystem.Visible = checkBoxSearchCrystalSystem.Checked; - groupBoxCellParameter.Visible = checkBoxSearchCellParameter.Checked; - groupBoxDspacing.Visible = checkBoxDspacing.Checked; - groupBoxDensity.Visible = checkBoxDensity.Checked; - } + #region チェックボックス + private void checkBoxSearch_CheckedChanged(object sender, EventArgs e) + { + buttonPeriodicTable.Visible = checkBoxSearchElements.Checked; + if (formPeriodicTable.Visible && !checkBoxSearchElements.Checked) + formPeriodicTable.Visible = false; + + textBoxSearchRefference.Visible = checkBoxSearchRefference.Checked; + textBoxSearchName.Visible = checkBoxSearchName.Checked; + comboBoxSearchCrystalSystem.Visible = checkBoxSearchCrystalSystem.Checked; + groupBoxCellParameter.Visible = checkBoxSearchCellParameter.Checked; + groupBoxDspacing.Visible = checkBoxDspacing.Checked; + groupBoxDensity.Visible = checkBoxDensity.Checked; + } - private void checkBoxD1_CheckedChanged(object sender, EventArgs e) => numericBoxD1.Enabled = numericBoxD1Err.Enabled = checkBoxD1.Checked; + private void checkBoxD1_CheckedChanged(object sender, EventArgs e) => numericBoxD1.Enabled = numericBoxD1Err.Enabled = checkBoxD1.Checked; - private void checkBoxD2_CheckedChanged(object sender, EventArgs e) => numericBoxD2.Enabled = numericBoxD2Err.Enabled = checkBoxD2.Checked; + private void checkBoxD2_CheckedChanged(object sender, EventArgs e) => numericBoxD2.Enabled = numericBoxD2Err.Enabled = checkBoxD2.Checked; - private void checkBoxD3_CheckedChanged(object sender, EventArgs e) => numericBoxD3.Enabled = numericBoxD3Err.Enabled = checkBoxD3.Checked; + private void checkBoxD3_CheckedChanged(object sender, EventArgs e) => numericBoxD3.Enabled = numericBoxD3Err.Enabled = checkBoxD3.Checked; - bool firstTime = true; - private void buttonPeriodicTable_Click(object sender, EventArgs e) + bool firstTime = true; + private void buttonPeriodicTable_Click(object sender, EventArgs e) + { + if (firstTime) { - if (firstTime) - { - formPeriodicTable.Location = formPeriodicTable.Owner.PointToScreen(new System.Drawing.Point(100, 100)); - firstTime = false; - } - formPeriodicTable.Visible = true; - formPeriodicTable.BringToFront(); + formPeriodicTable.Location = formPeriodicTable.Owner.PointToScreen(new System.Drawing.Point(100, 100)); + firstTime = false; } + formPeriodicTable.Visible = true; + formPeriodicTable.BringToFront(); + } - #endregion + #endregion - readonly Stopwatch sw = new(); - bool[] flags = Array.Empty(); - private void buttonSearch_Click(object sender, EventArgs e) - { - if (CrystalDatabaseControl == null || backgroundWorkerSearch.IsBusy || CrystalDatabaseControl.Table.Count == 0) - return; - sw.Restart(); - this.Enabled = false; - flags = new bool[CrystalDatabaseControl.Table.Count]; - CrystalDatabaseControl.Suspend();//バインディングを切る - backgroundWorkerSearch.RunWorkerAsync(); - } + readonly Stopwatch sw = new(); + bool[] flags = Array.Empty(); + private void buttonSearch_Click(object sender, EventArgs e) + { + if (CrystalDatabaseControl == null || backgroundWorkerSearch.IsBusy || CrystalDatabaseControl.Table.Count == 0) + return; + sw.Restart(); + this.Enabled = false; + flags = new bool[CrystalDatabaseControl.Table.Count]; + CrystalDatabaseControl.Suspend();//バインディングを切る + backgroundWorkerSearch.RunWorkerAsync(); + } - private void backgroundWorkerSearch_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) - { - var table = CrystalDatabaseControl.Table; + private void backgroundWorkerSearch_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) + { + var table = CrystalDatabaseControl.Table; - var name = checkBoxSearchName.Checked ? textBoxSearchName.Text.ToLower() : ""; - var reference = checkBoxSearchRefference.Checked ? textBoxSearchRefference.Text.ToLower() : ""; - var system = checkBoxSearchCrystalSystem.Checked ? comboBoxSearchCrystalSystem.SelectedIndex : -1; + var name = checkBoxSearchName.Checked ? textBoxSearchName.Text.ToLower() : ""; + var reference = checkBoxSearchRefference.Checked ? textBoxSearchRefference.Text.ToLower() : ""; + var system = checkBoxSearchCrystalSystem.Checked ? comboBoxSearchCrystalSystem.SelectedIndex : -1; - byte[] includes = formPeriodicTable.Includes, excludes = formPeriodicTable.Excludes; + byte[] includes = formPeriodicTable.Includes, excludes = formPeriodicTable.Excludes; - double lenErr = numericBoxCellLengthErr.Value / 100, angErr = numericBoxCellAngleErr.Value; - double a = numericBoxCellA.Value, b = numericBoxCellB.Value, c = numericBoxCellC.Value; - double alpha = numericBoxCellAlpha.Value, beta = numericBoxCellBeta.Value, gamma = numericBoxCellGamma.Value; + double lenErr = numericBoxCellLengthErr.Value / 100, angErr = numericBoxCellAngleErr.Value; + double a = numericBoxCellA.Value, b = numericBoxCellB.Value, c = numericBoxCellC.Value; + double alpha = numericBoxCellAlpha.Value, beta = numericBoxCellBeta.Value, gamma = numericBoxCellGamma.Value; - double density = checkBoxDensity.Checked ? numericBoxDensity.Value : 0; - double densErr = numericBoxDensityErr.Value / 100; + double density = checkBoxDensity.Checked ? numericBoxDensity.Value : 0; + double densErr = numericBoxDensityErr.Value / 100; - double d1 = checkBoxD1.Checked ? numericBoxD1.Value / 10 : 0; - double d2 = checkBoxD2.Checked ? numericBoxD2.Value / 10 : 0; - double d3 = checkBoxD3.Checked ? numericBoxD3.Value / 10 : 0; - double d1Err = numericBoxD1Err.Value / 100, d2Err = numericBoxD2Err.Value / 100, d3Err = numericBoxD3Err.Value / 100; + double d1 = checkBoxD1.Checked ? numericBoxD1.Value / 10 : 0; + double d2 = checkBoxD2.Checked ? numericBoxD2.Value / 10 : 0; + double d3 = checkBoxD3.Checked ? numericBoxD3.Value / 10 : 0; + double d1Err = numericBoxD1Err.Value / 100, d2Err = numericBoxD2Err.Value / 100, d3Err = numericBoxD3Err.Value / 100; - var dMin = double.MaxValue; - if (d1 != 0) dMin = Math.Min(dMin, d1 * (1 - 2 * d1Err)); - if (d2 != 0) dMin = Math.Min(dMin, d2 * (1 - 2 * d3Err)); - if (d3 != 0) dMin = Math.Min(dMin, d3 * (1 - 2 * d3Err)); + var dMin = double.MaxValue; + if (d1 != 0) dMin = Math.Min(dMin, d1 * (1 - 2 * d1Err)); + if (d2 != 0) dMin = Math.Min(dMin, d2 * (1 - 2 * d3Err)); + if (d3 != 0) dMin = Math.Min(dMin, d3 * (1 - 2 * d3Err)); - long time = 0; + long time = 0; - int count = 0; - Parallel.For(0, table.Count, i => - { - var cry = table.Get(i); + int count = 0; + Parallel.For(0, table.Count, i => + { + var cry = table.Get(i); - var flag = true; + var flag = true; - //名前 - if (name != "" && !cry.name.ToLower().Contains(name)) - flag = false; + //名前 + if (name != "" && !cry.name.ToLower().Contains(name)) + flag = false; - //Reference - if (flag && reference != "" && !(cry.jour.ToLower().Contains(reference) || cry.auth.ToLower().Contains(reference) || cry.sect.ToLower().Contains(reference))) - flag = false; + //Reference + if (flag && reference != "" && !(cry.jour.ToLower().Contains(reference) || cry.auth.ToLower().Contains(reference) || cry.sect.ToLower().Contains(reference))) + flag = false; - //結晶系 - if (flag && system > 0 && system != SymmetryStatic.NumArray[cry.sym][5]) + //結晶系 + if (flag && system > 0 && system != SymmetryStatic.NumArray[cry.sym][5]) + flag = false; + + //元素 + if (flag && checkBoxSearchElements.Checked) + { + var elements = cry.atoms.Select(a => a.AtomNo).Distinct().ToArray(); + if (excludes.Length != 0 && elements.Any(e => excludes.Contains(e))) + flag = false; + if (flag && includes.Length != 0 && !includes.All(e => elements.Contains(e))) + flag = false; + if (flag && cry.atoms.Count == 0) flag = false; + } - //元素 - if (flag && checkBoxSearchElements.Checked) + //格子定数 + if (flag && checkBoxSearchCellParameter.Checked) + { + var Values = cry.CellOnlyValue_nm_radian; + if (!double.IsNaN(Values.A)) { - var elements = cry.atoms.Select(a => a.AtomNo).Distinct().ToArray(); - if (excludes.Length != 0 && elements.Any(e => excludes.Contains(e))) + if (a != 0 && (a * (1 - lenErr) > Values.A || a * (1 + lenErr) < Values.A)) + flag = false; + if (flag && b != 0 && (b * (1 - lenErr) > Values.B || b * (1 + lenErr) < Values.B)) + flag = false; + if (flag && c != 0 && (c * (1 - lenErr) > Values.C || c * (1 + lenErr) < Values.C)) flag = false; - if (flag && includes.Length != 0 && !includes.All(e => elements.Contains(e))) + if (flag && alpha != 0 && (alpha - angErr > Values.Alpha || alpha + angErr < Values.Alpha)) flag = false; - if (flag && cry.atoms.Count == 0) + if (flag && beta != 0 && (beta - angErr > Values.Beta || beta + angErr < Values.Beta)) + flag = false; + if (flag && gamma != 0 && (gamma - angErr > Values.Gamma || gamma + angErr < Values.Gamma)) flag = false; } + } + + //密度のフィルター + if (flag && density != 0 && (density * (1 - densErr) > cry.density || density * (1 + densErr) < cry.density)) + flag = false; - //格子定数 - if (flag && checkBoxSearchCellParameter.Checked) + //d値のフィルター + if (flag && checkBoxDspacing.Checked) + { + var dArray = cry.d; + if (checkBoxIgnoreScatteringFactor.Checked) { var Values = cry.CellOnlyValue_nm_radian; if (!double.IsNaN(Values.A)) - { - if (a != 0 && (a * (1 - lenErr) > Values.A || a * (1 + lenErr) < Values.A)) - flag = false; - if (flag && b != 0 && (b * (1 - lenErr) > Values.B || b * (1 + lenErr) < Values.B)) - flag = false; - if (flag && c != 0 && (c * (1 - lenErr) > Values.C || c * (1 + lenErr) < Values.C)) - flag = false; - if (flag && alpha != 0 && (alpha - angErr > Values.Alpha || alpha + angErr < Values.Alpha)) - flag = false; - if (flag && beta != 0 && (beta - angErr > Values.Beta || beta + angErr < Values.Beta)) - flag = false; - if (flag && gamma != 0 && (gamma - angErr > Values.Gamma || gamma + angErr < Values.Gamma)) - flag = false; - } + dArray = calcDlist(Values.A, Values.B, Values.C, Values.Alpha, Values.Beta, Values.Gamma, dMin); } - //密度のフィルター - if (flag && density != 0 && (density * (1 - densErr) > cry.density || density * (1 + densErr) < cry.density)) + if (flag && d1 != 0 && !dArray.Any(d => d1 * (1 - d1Err) < d && d1 * (1 + d1Err) > d)) flag = false; + if (flag && d2 != 0 && !dArray.Any(d => d2 * (1 - d2Err) < d && d2 * (1 + d2Err) > d)) + flag = false; + if (flag && d3 != 0 && !dArray.Any(d => d3 * (1 - d3Err) < d && d3 * (1 + d3Err) > d)) + flag = false; + } - //d値のフィルター - if (flag && checkBoxDspacing.Checked) - { - var dArray = cry.d; - if (checkBoxIgnoreScatteringFactor.Checked) - { - var Values = cry.CellOnlyValue_nm_radian; - if (!double.IsNaN(Values.A)) - dArray = calcDlist(Values.A, Values.B, Values.C, Values.Alpha, Values.Beta, Values.Gamma, dMin); - } - - if (flag && d1 != 0 && !dArray.Any(d => d1 * (1 - d1Err) < d && d1 * (1 + d1Err) > d)) - flag = false; - if (flag && d2 != 0 && !dArray.Any(d => d2 * (1 - d2Err) < d && d2 * (1 + d2Err) > d)) - flag = false; - if (flag && d3 != 0 && !dArray.Any(d => d3 * (1 - d3Err) < d && d3 * (1 + d3Err) > d)) - flag = false; - } - - flags[i] = flag; + flags[i] = flag; - if (Interlocked.Increment(ref count) % 1000 == 0 && sw.ElapsedMilliseconds - time > 100) - { - time = sw.ElapsedMilliseconds; - backgroundWorkerSearch.ReportProgress(count); - } + if (Interlocked.Increment(ref count) % 1000 == 0 && sw.ElapsedMilliseconds - time > 100) + { + time = sw.ElapsedMilliseconds; + backgroundWorkerSearch.ReportProgress(count); } - ); } + ); + } - static int composeKey(in int h, in int k, in int l) => ((h > 0) || (h == 0 && k > 0) || (h == 0 && k == 0 && l > 0)) ? ((h + 255) << 20) + ((k + 255) << 10) + l + 255 : -1; - static (int h, int k, int l) decomposeKey(in int key) => (((key << 2) >> 22) - 255, ((key << 12) >> 22) - 255, ((key << 22) >> 22) - 255); + static int composeKey(in int h, in int k, in int l) => ((h > 0) || (h == 0 && k > 0) || (h == 0 && k == 0 && l > 0)) ? ((h + 255) << 20) + ((k + 255) << 10) + l + 255 : -1; + static (int h, int k, int l) decomposeKey(in int key) => (((key << 2) >> 22) - 255, ((key << 12) >> 22) - 255, ((key << 22) >> 22) - 255); - static readonly int zeroKey = (255 << 20) + (255 << 10) + 255; - static readonly (int h, int k, int l)[] directions = new[] { (1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1) };//(-1, 0, 0)は除いておく - static float[] calcDlist(double a, double b, double c, double alpha, double beta, double gamma, double dMin) + static readonly int zeroKey = (255 << 20) + (255 << 10) + 255; + static readonly (int h, int k, int l)[] directions = new[] { (1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1) };//(-1, 0, 0)は除いておく + static float[] calcDlist(double a, double b, double c, double alpha, double beta, double gamma, double dMin) + { + double SinAlfa = Math.Sin(alpha), CosAlfa = Math.Cos(alpha), CosBeta = Math.Cos(beta), CosGamma = Math.Cos(gamma); + Vector3DBase cAxis = new(0, 0, c); + Vector3DBase bAxis = new(0, b * SinAlfa, b * CosAlfa); + Vector3DBase aAxis = new( + a * Math.Sqrt(1 - CosBeta * CosBeta - (CosGamma - CosAlfa * CosBeta) * (CosGamma - CosAlfa * CosBeta) / SinAlfa / SinAlfa), + a * (CosGamma - CosAlfa * CosBeta) / SinAlfa, + a * CosBeta); + + var MatrixInverse = new Matrix3D(aAxis, bAxis, cAxis).Inverse(); + double aX = MatrixInverse.E11, aY = MatrixInverse.E12, aZ = MatrixInverse.E13; + double bX = MatrixInverse.E21, bY = MatrixInverse.E22, bZ = MatrixInverse.E23; + double cX = MatrixInverse.E31, cY = MatrixInverse.E32, cZ = MatrixInverse.E33; + + var gMax = 1 / dMin; + var shift = directions.Select(dir => (MatrixInverse * dir).Length).Max(); + var maxGnum = 8000; + var outer = new List<(int key, double len)>() { (zeroKey, 0) }; + var gKeys = new HashSet((int)(maxGnum * 1.5)) { zeroKey }; + var gList = new HashSet((int)(maxGnum * 1.5)); + var minG = 0.0; + + while (gList.Count < maxGnum && (minG = outer.Min(o => o.len)) < gMax) { - double SinAlfa = Math.Sin(alpha), CosAlfa = Math.Cos(alpha), CosBeta = Math.Cos(beta), CosGamma = Math.Cos(gamma); - Vector3DBase cAxis = new(0, 0, c); - Vector3DBase bAxis = new(0, b * SinAlfa, b * CosAlfa); - Vector3DBase aAxis = new( - a * Math.Sqrt(1 - CosBeta * CosBeta - (CosGamma - CosAlfa * CosBeta) * (CosGamma - CosAlfa * CosBeta) / SinAlfa / SinAlfa), - a * (CosGamma - CosAlfa * CosBeta) / SinAlfa, - a * CosBeta); - - var MatrixInverse = new Matrix3D(aAxis, bAxis, cAxis).Inverse(); - double aX = MatrixInverse.E11, aY = MatrixInverse.E12, aZ = MatrixInverse.E13; - double bX = MatrixInverse.E21, bY = MatrixInverse.E22, bZ = MatrixInverse.E23; - double cX = MatrixInverse.E31, cY = MatrixInverse.E32, cZ = MatrixInverse.E33; - - var gMax = 1 / dMin; - var shift = directions.Select(dir => (MatrixInverse * dir).Length).Max(); - var maxGnum = 8000; - var outer = new List<(int key, double len)>() { (zeroKey, 0) }; - var gKeys = new HashSet((int)(maxGnum * 1.5)) { zeroKey }; - var gList = new HashSet((int)(maxGnum * 1.5)); - var minG = 0.0; - - while (gList.Count < maxGnum && (minG = outer.Min(o => o.len)) < gMax) + var end = outer.FindLastIndex(o => o.len - minG < shift * 2); + foreach (var (key1, _) in CollectionsMarshal.AsSpan(outer)[..(end + 1)]) { - var end = outer.FindLastIndex(o => o.len - minG < shift * 2); - foreach (var (key1, _) in CollectionsMarshal.AsSpan(outer)[..(end + 1)]) + var (h1, k1, l1) = decomposeKey(key1); + foreach ((int h2, int k2, int l2) in directions) { - var (h1, k1, l1) = decomposeKey(key1); - foreach ((int h2, int k2, int l2) in directions) + int h = h1 + h2, k = k1 + k2, l = l1 + l2, key2 = composeKey(h, k, l); + if (key2 > 0 && gKeys.Add(key2)) { - int h = h1 + h2, k = k1 + k2, l = l1 + l2, key2 = composeKey(h, k, l); - if (key2 > 0 && gKeys.Add(key2)) - { - double x = h * aX + k * bX + l * cX, y = h * aY + k * bY + l * cY, z = h * aZ + k * bZ + l * cZ; - var len = Math.Sqrt(x * x + y * y + z * z); - gList.Add(len); - outer.Add((key2, len)); - } + double x = h * aX + k * bX + l * cX, y = h * aY + k * bY + l * cY, z = h * aZ + k * bZ + l * cZ; + var len = Math.Sqrt(x * x + y * y + z * z); + gList.Add(len); + outer.Add((key2, len)); } } - outer.RemoveRange(0, end + 1); - outer.Sort((e1, e2) => e1.len.CompareTo(e2.len)); } - return gList.Select(g => (float)(1 / g)).ToArray(); + outer.RemoveRange(0, end + 1); + outer.Sort((e1, e2) => e1.len.CompareTo(e2.len)); } + return gList.Select(g => (float)(1 / g)).ToArray(); + } - bool skipProgressEvent = false; - private void backgroundWorkerSearch_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) + bool skipProgressEvent = false; + private void backgroundWorkerSearch_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) + { + if (skipProgressEvent) return; + try { - if (skipProgressEvent) return; - try - { - skipProgressEvent = true; - ProgressChanged?.Invoke(sender, (double)e.ProgressPercentage / CrystalDatabaseControl.Table.Count, $"Searching... {sw.ElapsedMilliseconds / 1000.0:f2} msec."); - } - catch { } - finally { skipProgressEvent = false; } + skipProgressEvent = true; + ProgressChanged?.Invoke(sender, (double)e.ProgressPercentage / CrystalDatabaseControl.Table.Count, $"Searching... {sw.ElapsedMilliseconds / 1000.0:f2} msec."); } + catch { } + finally { skipProgressEvent = false; } + } - private void backgroundWorkerSearch_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) - { - //最終処理 - var flagCount = flags.Count(f => f); + private void backgroundWorkerSearch_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) + { + //最終処理 + var flagCount = flags.Count(f => f); - if (flagCount == CrystalDatabaseControl.Table.Count) - CrystalDatabaseControl.Filter = ""; - else - { - for (int i = 0; i < CrystalDatabaseControl.Table.Count; i++) - if (CrystalDatabaseControl.Table.GetFlag(i) != flags[i]) - CrystalDatabaseControl.Table.SetFlag(i, flags[i]); + if (flagCount == CrystalDatabaseControl.Table.Count) + CrystalDatabaseControl.Filter = ""; + else + { + for (int i = 0; i < CrystalDatabaseControl.Table.Count; i++) + if (CrystalDatabaseControl.Table.GetFlag(i) != flags[i]) + CrystalDatabaseControl.Table.SetFlag(i, flags[i]); - CrystalDatabaseControl.Filter = "Flag = true"; - } + CrystalDatabaseControl.Filter = "Flag = true"; + } - if (flagCount > 0) - CrystalDatabaseControl.Resume();//バインディングを繋げる + //if (flagCount == 0) + // CrystalDatabaseControl.Suspend(); + //else + CrystalDatabaseControl.Resume();//バインディングを繋げる - this.Enabled = true; + this.Enabled = true; - Thread.Sleep(500); - ProgressChanged?.Invoke(sender, 1.0, $"Completion of search. {sw.ElapsedMilliseconds / 1000.0:f2} msec."); - Application.DoEvents(); + Thread.Sleep(500); + ProgressChanged?.Invoke(sender, 1.0, $"Completion of search. {sw.ElapsedMilliseconds / 1000.0:f2} msec."); + Application.DoEvents(); - } } } diff --git a/Crystallography.Controls/Crystallography - Backup.Controls.csproj b/Crystallography.Controls/Crystallography - Backup.Controls.csproj new file mode 100644 index 0000000..87089b4 --- /dev/null +++ b/Crystallography.Controls/Crystallography - Backup.Controls.csproj @@ -0,0 +1,41 @@ + + + + Library + net7.0-windows + true + 2022.12.16.0206 + 2022.12.16.0206 + PerMonitorV2 + true + true + + + + true + + + + true + + + + + + + + + PreserveNewest + + + + + + + + + + + + + diff --git a/Crystallography.Controls/Crystallography.Controls.csproj b/Crystallography.Controls/Crystallography.Controls.csproj index 49ee07c..cf59f04 100644 --- a/Crystallography.Controls/Crystallography.Controls.csproj +++ b/Crystallography.Controls/Crystallography.Controls.csproj @@ -1,11 +1,11 @@ - + Library net7.0-windows true - 2022.12.3.0941 - 2022.12.3.0941 + 2023.2.10.1154 + 2023.2.10.1154 PerMonitorV2 true true @@ -30,7 +30,8 @@ - + + @@ -38,4 +39,10 @@ + + + + + + diff --git a/Crystallography.Controls/GraphControl.cs b/Crystallography.Controls/GraphControl.cs index b1a1406..5ed2c45 100644 --- a/Crystallography.Controls/GraphControl.cs +++ b/Crystallography.Controls/GraphControl.cs @@ -8,1360 +8,1359 @@ using System.Text; using System.Windows.Forms; -namespace Crystallography.Controls +namespace Crystallography.Controls; + +public partial class GraphControl : UserControl { - public partial class GraphControl : UserControl + public GraphControl() { - public GraphControl() - { - InitializeComponent(); - } + InitializeComponent(); + } - private Bitmap Bmp; - private Graphics G; + private Bitmap Bmp; + private Graphics G; - #region イベント + #region イベント - public delegate void DrawingRangeChangedEventHandler(RectangleD rectangle); + public delegate void DrawingRangeChangedEventHandler(RectangleD rectangle); - public event DrawingRangeChangedEventHandler DrawingRangeChanged; + public event DrawingRangeChangedEventHandler DrawingRangeChanged; - public delegate void LinePositionChengedEventHandler(); + public delegate void LinePositionChengedEventHandler(); - public event LinePositionChengedEventHandler LinePositionChanged; + public event LinePositionChengedEventHandler LinePositionChanged; - public delegate bool MouseEventHandler2(PointD pt); + public delegate bool MouseEventHandler2(PointD pt); - /// - /// マウスが左ダブルクリックされたときのイベント。戻り値がtrueの場合は、その後の動作をスキップ - /// - public event MouseEventHandler2 MouseDoubleClick2; + /// + /// マウスが左ダブルクリックされたときのイベント。戻り値がtrueの場合は、その後の動作をスキップ + /// + public event MouseEventHandler2 MouseDoubleClick2; - #endregion イベント + #endregion イベント - #region プロパティ + #region プロパティ - private double upperX = 1; - public double UpperX { get { return upperX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) upperX = value; } } + private double upperX = 1; + public double UpperX { get { return upperX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) upperX = value; } } - private double lowerX = 0; - public double LowerX { get { return lowerX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) lowerX = value; } } + private double lowerX = 0; + public double LowerX { get { return lowerX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) lowerX = value; } } - private double upperY = 1; - public double UpperY { get { return upperY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) upperY = value; } } + private double upperY = 1; + public double UpperY { get { return upperY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) upperY = value; } } - private double lowerY = 0; - public double LowerY { get { return lowerY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) lowerY = value; } } + private double lowerY = 0; + public double LowerY { get { return lowerY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) lowerY = value; } } - private double maximalX = 1; - public double MaximalX { get { return maximalX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) maximalX = value; } } + private double maximalX = 1; + public double MaximalX { get { return maximalX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) maximalX = value; } } - private double minimalX = 0; - public double MinimalX { get { return minimalX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) minimalX = value; } } + private double minimalX = 0; + public double MinimalX { get { return minimalX; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) minimalX = value; } } - private double maximalY = 1; - public double MaximalY { get { return maximalY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) maximalY = value; } } + private double maximalY = 1; + public double MaximalY { get { return maximalY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) maximalY = value; } } - private double minimalY = 0; - public double MinimalY { get { return minimalY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) minimalY = value; } } + private double minimalY = 0; + public double MinimalY { get { return minimalY; } set { if (!double.IsNaN(value) && !double.IsInfinity(value)) minimalY = value; } } - /// - /// 描画範囲の矩形 - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public RectangleD DrawingRange + /// + /// 描画範囲の矩形 + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public RectangleD DrawingRange + { + set { - set - { - if (!double.IsInfinity(value.X) && !double.IsNaN(value.X) && value.X <= MaximalX && value.X >= MinimalX) - LowerX = value.X; + if (!double.IsInfinity(value.X) && !double.IsNaN(value.X) && value.X <= MaximalX && value.X >= MinimalX) + LowerX = value.X; - if (!double.IsInfinity(value.Y) && !double.IsNaN(value.Y) && value.Y <= MaximalY && value.Y >= MinimalY) - LowerY = value.Y; + if (!double.IsInfinity(value.Y) && !double.IsNaN(value.Y) && value.Y <= MaximalY && value.Y >= MinimalY) + LowerY = value.Y; - if (!double.IsInfinity(value.Width) && !double.IsNaN(value.Width) && value.Width >= 0) - UpperX = Math.Min(LowerX + value.Width, MaximalX); + if (!double.IsInfinity(value.Width) && !double.IsNaN(value.Width) && value.Width >= 0) + UpperX = Math.Min(LowerX + value.Width, MaximalX); - if (!double.IsInfinity(value.Height) && !double.IsNaN(value.Height) && value.Height >= 0) - UpperY = Math.Min(LowerY + value.Height, MaximalY); - } - get - { - if (!double.IsInfinity(LowerX) && !double.IsInfinity(LowerY) && !double.IsInfinity(UpperX) && !double.IsInfinity(UpperY)) - return new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY); - else - return new RectangleD(0, 0, 1, 1); - } + if (!double.IsInfinity(value.Height) && !double.IsNaN(value.Height) && value.Height >= 0) + UpperY = Math.Min(LowerY + value.Height, MaximalY); } - - /// - /// ピクチャーボックスのクライアント領域のサイズ - /// - private Size PictureBoxSize + get { - get { return pictureBox.ClientSize; } + if (!double.IsInfinity(LowerX) && !double.IsInfinity(LowerY) && !double.IsInfinity(UpperX) && !double.IsInfinity(UpperY)) + return new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY); + else + return new RectangleD(0, 0, 1, 1); } + } + + /// + /// ピクチャーボックスのクライアント領域のサイズ + /// + private Size PictureBoxSize + { + get { return pictureBox.ClientSize; } + } - private bool verticalGradiationTextVisivle = true; + private bool verticalGradiationTextVisivle = true; - public bool VerticalGradiationTextVisivle - { - set { verticalGradiationTextVisivle = value; Draw(); } - get { return verticalGradiationTextVisivle; } - } + public bool VerticalGradiationTextVisivle + { + set { verticalGradiationTextVisivle = value; Draw(); } + get { return verticalGradiationTextVisivle; } + } - private bool horizontalGradiationTextVisivle = true; + private bool horizontalGradiationTextVisivle = true; - public bool HorizontalGradiationTextVisivle - { - set { horizontalGradiationTextVisivle = value; Draw(); } - get { return horizontalGradiationTextVisivle; } - } + public bool HorizontalGradiationTextVisivle + { + set { horizontalGradiationTextVisivle = value; Draw(); } + get { return horizontalGradiationTextVisivle; } + } - public Font TextFont { set { flowLayoutPanel.Font = value; } get { return flowLayoutPanel.Font; } } + public Font TextFont { set { flowLayoutPanel.Font = value; } get { return flowLayoutPanel.Font; } } - public string UpperText - { - get { return labelUpperText.Text; } - set { labelUpperText.Text = value; } - } + public string UpperText + { + get { return labelUpperText.Text; } + set { labelUpperText.Text = value; } + } - private bool upperTextVisible = true; + private bool upperTextVisible = true; - /// - /// グラフ上部にマウス位置やラベル情報を示すテキストを表示するかどうか - /// - public bool UpperTextVisible + /// + /// グラフ上部にマウス位置やラベル情報を示すテキストを表示するかどうか + /// + public bool UpperTextVisible + { + set { - set - { - upperTextVisible = value; - flowLayoutPanel.Visible = upperTextVisible; - } - get { return upperTextVisible; } + upperTextVisible = value; + flowLayoutPanel.Visible = upperTextVisible; } + get { return upperTextVisible; } + } - /// - /// X軸の単位 - /// - public string UnitX { get; set; } = ""; + /// + /// X軸の単位 + /// + public string UnitX { get; set; } = ""; - /// - /// Y軸の単位 - /// - public string UnitY { get; set; } = ""; + /// + /// Y軸の単位 + /// + public string UnitY { get; set; } = ""; - private bool mousePositionVisible = true; + private bool mousePositionVisible = true; - /// - /// マウス位置を表示するかどうか - /// - public bool MousePositionVisible + /// + /// マウス位置を表示するかどうか + /// + public bool MousePositionVisible + { + set { - set - { - mousePositionVisible = value; - labelX.Visible = labelXValue.Visible = labelY.Visible = labelYLabel.Visible = mousePositionVisible; - } - get { return mousePositionVisible; } + mousePositionVisible = value; + labelX.Visible = labelXValue.Visible = labelY.Visible = labelYLabel.Visible = mousePositionVisible; } + get { return mousePositionVisible; } + } - private string graphName = ""; + private string graphName = ""; - /// - /// グラフの名前 - /// - public string GraphName + /// + /// グラフの名前 + /// + public string GraphName + { + set { - set - { - graphName = value; - labelUpperText.Text = graphName; - } - get { return graphName; } + graphName = value; + labelUpperText.Text = graphName; } + get { return graphName; } + } - /// - /// マウス操作を受け付けるかどうか - /// - public bool AllowMouseOperation { get; set; } = true; + /// + /// マウス操作を受け付けるかどうか + /// + public bool AllowMouseOperation { get; set; } = true; - private readonly List lineList = new List(); + private readonly List lineList = new List(); - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public PointD[] LineList + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PointD[] LineList + { + set { - set + if (value != null) { - if (value != null) - { - lineList.Clear(); - lineList.AddRange(value); - } + lineList.Clear(); + lineList.AddRange(value); } - get { return lineList.ToArray(); } } + get { return lineList.ToArray(); } + } - private List peaks = new(); + private List peaks = new(); - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public PeakFunction[] Peaks - { - set { peaks.Clear(); peaks.AddRange(value); } - get { return peaks.ToArray(); } - } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PeakFunction[] Peaks + { + set { peaks.Clear(); peaks.AddRange(value); } + get { return peaks.ToArray(); } + } - public Color LineColor { set; get; } = Color.Red; + public Color LineColor { set; get; } = Color.Red; - private int selectedLineIndex = -1; + private int selectedLineIndex = -1; - private List srcProfileList = new(); + private List srcProfileList = new(); - /// - /// 0番目のプロファイルを設定する。複数プロファイルが設定されている場合はひとつだけにする。 - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Profile Profile + /// + /// 0番目のプロファイルを設定する。複数プロファイルが設定されている場合はひとつだけにする。 + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Profile Profile + { + set { - set - { - srcProfileList = new List(); - srcProfileList.Add(value); - InitializeAxis(); - resetDrawRange(); - Draw(); - } - get - { - if (srcProfileList == null || srcProfileList.Count == 0) - return null; - else - return srcProfileList[0]; - } + srcProfileList = new List(); + srcProfileList.Add(value); + InitializeAxis(); + resetDrawRange(); + Draw(); } - - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Profile[] ProfileList + get { - get { return srcProfileList.ToArray(); } + if (srcProfileList == null || srcProfileList.Count == 0) + return null; + else + return srcProfileList[0]; } + } + + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Profile[] ProfileList + { + get { return srcProfileList.ToArray(); } + } - private float lineWidth = 1f; + private float lineWidth = 1f; - /// - /// プロファイル描画線の太さ - /// - public float LineWidth + /// + /// プロファイル描画線の太さ + /// + public float LineWidth + { + set { - set - { - lineWidth = value; - Draw(); - } - get { return lineWidth; } + lineWidth = value; + Draw(); } + get { return lineWidth; } + } - private bool useLineWidth = true; + private bool useLineWidth = true; - /// - /// 共通のプロファイル描画線を使うか (使わない場合は各ProfileのlineWidthを使う) - /// - public bool UseLineWidth { set { useLineWidth = value; Draw(); } get => useLineWidth; } + /// + /// 共通のプロファイル描画線を使うか (使わない場合は各ProfileのlineWidthを使う) + /// + public bool UseLineWidth { set { useLineWidth = value; Draw(); } get => useLineWidth; } - private Color divisionLineColor = Color.Gray; + private Color divisionLineColor = Color.Gray; - /// - /// 目盛線の色 - /// - public Color DivisionLineColor { set { divisionLineColor = value; Draw(); } get => divisionLineColor; } + /// + /// 目盛線の色 + /// + public Color DivisionLineColor { set { divisionLineColor = value; Draw(); } get => divisionLineColor; } - /// - /// 目盛補助線の色 - /// - public Color DivisionSubLineColor { set; get; } = Color.LightGray; + /// + /// 目盛補助線の色 + /// + public Color DivisionSubLineColor { set; get; } = Color.LightGray; - /// - /// 目盛文字の色 - /// - public SolidBrush DivisionTextBrush { set; get; } = new SolidBrush(Color.Black); + /// + /// 目盛文字の色 + /// + public SolidBrush DivisionTextBrush { set; get; } = new SolidBrush(Color.Black); - /// - /// 背景の色 - /// - public Color BackgroundColor { set; get; } = Color.White; + /// + /// 背景の色 + /// + public Color BackgroundColor { set; get; } = Color.White; - private bool xLog = false; + private bool xLog = false; - /// - /// X軸が対数スケールかどうか - /// - public bool XLog + /// + /// X軸が対数スケールかどうか + /// + public bool XLog + { + set { - set + if (XLog != value) { - if (XLog != value) - { - xLog = value; - toolStripMenuItemLogScaleX.Checked = XLog; - InitializeAxis(); - setDrawRangeLimit(); - resetDrawRange(); - Draw(); - } + xLog = value; + toolStripMenuItemLogScaleX.Checked = XLog; + InitializeAxis(); + setDrawRangeLimit(); + resetDrawRange(); + Draw(); } - get => xLog; } + get => xLog; + } - private bool yLog = false; + private bool yLog = false; - /// - /// Y軸が対数スケールかどうか - /// - public bool YLog + /// + /// Y軸が対数スケールかどうか + /// + public bool YLog + { + set { - set + if (YLog != value) { - if (YLog != value) - { - yLog = value; - toolStripMenuItemLogScaleY.Checked = YLog; - InitializeAxis(); setDrawRangeLimit(); - resetDrawRange(); - Draw(); - } + yLog = value; + toolStripMenuItemLogScaleY.Checked = YLog; + InitializeAxis(); setDrawRangeLimit(); + resetDrawRange(); + Draw(); } - get => yLog; } + get => yLog; + } - private bool xScaleLineVisible = true; + private bool xScaleLineVisible = true; - /// - /// X軸の目盛りを表示するかどうか - /// - public bool XScaleLineVisible + /// + /// X軸の目盛りを表示するかどうか + /// + public bool XScaleLineVisible + { + set { - set + if (XScaleLineVisible != value) { - if (XScaleLineVisible != value) - { - xScaleLineVisible = value; - toolStripMenuItemScaleLineX.Checked = value; - Draw(); - } + xScaleLineVisible = value; + toolStripMenuItemScaleLineX.Checked = value; + Draw(); } - get { return xScaleLineVisible; } } + get { return xScaleLineVisible; } + } - private bool yScaleLineVisible = true; + private bool yScaleLineVisible = true; - /// - /// Y軸の目盛りを表示するかどうか - /// - public bool YScaleLineVisible + /// + /// Y軸の目盛りを表示するかどうか + /// + public bool YScaleLineVisible + { + set { - set + if (YScaleLineVisible != value) { - if (YScaleLineVisible != value) - { - yScaleLineVisible = value; - toolStripMenuItemScaleLineY.Checked = value; - Draw(); - } + yScaleLineVisible = value; + toolStripMenuItemScaleLineY.Checked = value; + Draw(); } - get => yScaleLineVisible; } + get => yScaleLineVisible; + } - private bool isIntegerX = false; + private bool isIntegerX = false; - /// - /// Xの値が0以上の整数値かどうか - /// - public bool IsIntegerX - { - set { isIntegerX = value; InitializeAxis(); resetDrawRange(); Draw(); } - get => isIntegerX; - } + /// + /// Xの値が0以上の整数値かどうか + /// + public bool IsIntegerX + { + set { isIntegerX = value; InitializeAxis(); resetDrawRange(); Draw(); } + get => isIntegerX; + } - /// - /// Yの値が0以上の整数値かどうか - /// - public bool IsIntegerY - { - set { isIntegerY = value; InitializeAxis(); resetDrawRange(); Draw(); } - get => isIntegerY; - } + /// + /// Yの値が0以上の整数値かどうか + /// + public bool IsIntegerY + { + set { isIntegerY = value; InitializeAxis(); resetDrawRange(); Draw(); } + get => isIntegerY; + } - private bool isIntegerY = false; + private bool isIntegerY = false; - /// - /// X軸の名称 - /// - public string LabelX { set => labelX.Text = value; get => labelX.Text; } + /// + /// X軸の名称 + /// + public string LabelX { set => labelX.Text = value; get => labelX.Text; } - /// - /// Y軸の名称 - /// - public string LabelY { set => labelY.Text = value; get => labelY.Text; } + /// + /// Y軸の名称 + /// + public string LabelY { set => labelY.Text = value; get => labelY.Text; } - /// - /// 原点の位置(左下からのピクセル単位) - /// - public Point OriginPosition - { - set { originPosition = value; Draw(); } - get => originPosition; - } + /// + /// 原点の位置(左下からのピクセル単位) + /// + public Point OriginPosition + { + set { originPosition = value; Draw(); } + get => originPosition; + } - private Point originPosition = new Point(40, 20); + private Point originPosition = new Point(40, 20); - /// - /// 下側の余白(ピクセル単位) - /// - public double BottomMargin - { - set { bottomMargin = value; Draw(); } - get => bottomMargin; - } + /// + /// 下側の余白(ピクセル単位) + /// + public double BottomMargin + { + set { bottomMargin = value; Draw(); } + get => bottomMargin; + } - private double bottomMargin = 0; + private double bottomMargin = 0; - /// - /// 左側の余白(ピクセル単位) - /// - public float LeftMargin - { - set { leftMargin = value; Draw(); } - get => leftMargin; - } + /// + /// 左側の余白(ピクセル単位) + /// + public float LeftMargin + { + set { leftMargin = value; Draw(); } + get => leftMargin; + } - private float leftMargin = 0f; + private float leftMargin = 0f; - private DrawingMode mode = DrawingMode.Line; + private DrawingMode mode = DrawingMode.Line; - /// - /// trueの場合は棒グラフ状に表示する。falseの場合は線状に表示する - /// - public DrawingMode Mode - { - set { mode = value; Draw(); } - get { return mode; } - } + /// + /// trueの場合は棒グラフ状に表示する。falseの場合は線状に表示する + /// + public DrawingMode Mode + { + set { mode = value; Draw(); } + get { return mode; } + } - private bool interpolation = false; - public bool Interpolation { set { interpolation = value; Draw(); } get { return interpolation; } } + private bool interpolation = false; + public bool Interpolation { set { interpolation = value; Draw(); } get { return interpolation; } } - public bool Smoothing { get; set; } = false; - private int smoothingN = 0; - private int smoothingM = 0; + public bool Smoothing { get; set; } = false; + private int smoothingN = 0; + private int smoothingM = 0; - /// - /// Profileを更新時、横軸を固定する(ただし、上限下限内で) - /// - private bool fixRangeHorizontal = false; + /// + /// Profileを更新時、横軸を固定する(ただし、上限下限内で) + /// + private bool fixRangeHorizontal = false; - public bool FixRangeHorizontal - { - set { fixRangeHorizontal = value; } - get { return fixRangeHorizontal; } - } + public bool FixRangeHorizontal + { + set { fixRangeHorizontal = value; } + get { return fixRangeHorizontal; } + } - /// - /// Profileを更新時、縦を固定する(ただし、上限下限内で) - /// - private bool fixRangeVertical = false; + /// + /// Profileを更新時、縦を固定する(ただし、上限下限内で) + /// + private bool fixRangeVertical = false; - public bool FixRangeVertical - { - set { fixRangeVertical = value; } - get { return fixRangeVertical; } - } + public bool FixRangeVertical + { + set { fixRangeVertical = value; } + get { return fixRangeVertical; } + } - #endregion プロパティ + #endregion プロパティ - /// - /// グラフの描き方の列挙体 - /// - public enum DrawingMode - { - Line, Histogram, Point - } + /// + /// グラフの描き方の列挙体 + /// + public enum DrawingMode + { + Line, Histogram, Point + } - private List destProfileList = new List(); + private List destProfileList = new List(); - public void AddPoint(int profileNumber, PointD pt) - { - srcProfileList[profileNumber].Pt.Add(pt); - InitializeAxis(); - setDrawRangeLimit(); - resetDrawRange(); - Draw(); - } + public void AddPoint(int profileNumber, PointD pt) + { + srcProfileList[profileNumber].Pt.Add(pt); + InitializeAxis(); + setDrawRangeLimit(); + resetDrawRange(); + Draw(); + } - /// - /// プロファイルを加える - /// - /// - public void AddProfile(Profile p) - { - srcProfileList.Add(p); - InitializeAxis(); - setDrawRangeLimit(); - resetDrawRange(); - Draw(); - } + /// + /// プロファイルを加える + /// + /// + public void AddProfile(Profile p) + { + srcProfileList.Add(p); + InitializeAxis(); + setDrawRangeLimit(); + resetDrawRange(); + Draw(); + } - public void AddProfiles(Profile[] p, RectangleD drawingRange = new RectangleD()) - { - srcProfileList.Clear(); - srcProfileList.AddRange(p); - InitializeAxis(); - setDrawRangeLimit(); - if (drawingRange.Width == 0) - resetDrawRange(); - else - DrawingRange = drawingRange; - Draw(); - } + public void AddProfiles(Profile[] p, RectangleD drawingRange = new RectangleD()) + { + srcProfileList.Clear(); + srcProfileList.AddRange(p); + InitializeAxis(); + setDrawRangeLimit(); + if (drawingRange.Width == 0) + resetDrawRange(); + else + DrawingRange = drawingRange; + Draw(); + } - public void ReplaceProfile(int index, Profile p) - { - if (index < srcProfileList.Count) - srcProfileList[index] = p; - InitializeAxis(); - setDrawRangeLimit(); - Draw(); - } + public void ReplaceProfile(int index, Profile p) + { + if (index < srcProfileList.Count) + srcProfileList[index] = p; + InitializeAxis(); + setDrawRangeLimit(); + Draw(); + } - public void SmoothProfiles(int m, int n) - { - smoothingM = m; - smoothingN = n; - InitializeAxis(); - setDrawRangeLimit(); - Draw(); - } + public void SmoothProfiles(int m, int n) + { + smoothingM = m; + smoothingN = n; + InitializeAxis(); + setDrawRangeLimit(); + Draw(); + } - public void ClearProfile() - { - srcProfileList.Clear(); - destProfileList.Clear(); - pictureBox.Image = new Bitmap(PictureBoxSize.Width, PictureBoxSize.Height); - UpperX = UpperY = MaximalX = MaximalY = 1; - LowerX = LowerY = MinimalX = MinimalY = 0; - Draw(); - } + public void ClearProfile() + { + srcProfileList.Clear(); + destProfileList.Clear(); + pictureBox.Image = new Bitmap(PictureBoxSize.Width, PictureBoxSize.Height); + UpperX = UpperY = MaximalX = MaximalY = 1; + LowerX = LowerY = MinimalX = MinimalY = 0; + Draw(); + } - public void InitializeAxis() + public void InitializeAxis() + { + if (srcProfileList == null) return; + destProfileList = new List(); + for (int i = 0; i < srcProfileList.Count; i++) { - if (srcProfileList == null) return; - destProfileList = new List(); - for (int i = 0; i < srcProfileList.Count; i++) - { - var temp = new Profile(); - if (srcProfileList[i] != null && srcProfileList[i].Pt != null && srcProfileList[i].Pt.Any()) - temp = convertAxis(srcProfileList[i]); - destProfileList.Add(temp); - setDrawRangeLimit(); - } + var temp = new Profile(); + if (srcProfileList[i] != null && srcProfileList[i].Pt != null && srcProfileList[i].Pt.Any()) + temp = convertAxis(srcProfileList[i]); + destProfileList.Add(temp); + setDrawRangeLimit(); } + } - /// - /// 軸を変換する - /// - private Profile convertAxis(Profile profile) + /// + /// 軸を変換する + /// + private Profile convertAxis(Profile profile) + { + if (profile == null || profile.Pt == null || profile.Pt.Count == 0) return null; + var p = profile.CopyTo(); + if (Smoothing) + p = p.SmoothingSavitzkyGolay(smoothingM, smoothingN); + + var temp = new Profile(); + double x, y; + for (int i = 0; i < p.Pt.Count; i++) { - if (profile == null || profile.Pt == null || profile.Pt.Count == 0) return null; - var p = profile.CopyTo(); - if (Smoothing) - p = p.SmoothingSavitzkyGolay(smoothingM, smoothingN); + if (!xLog) + x = p.Pt[i].X; + else if (p.Pt[i].X == 0) + if (isIntegerX) + x = 0; + else + x = double.NegativeInfinity; + else + x = Math.Log10(p.Pt[i].X); - var temp = new Profile(); - double x, y; - for (int i = 0; i < p.Pt.Count; i++) + if (!yLog) + y = p.Pt[i].Y; + else { - if (!xLog) - x = p.Pt[i].X; - else if (p.Pt[i].X == 0) - if (isIntegerX) - x = 0; + if (p.Pt[i].Y == 0) + if (IsIntegerY) + y = 0; else - x = double.NegativeInfinity; - else - x = Math.Log10(p.Pt[i].X); - - if (!yLog) - y = p.Pt[i].Y; + y = double.NegativeInfinity; + else if (p.Pt[i].Y > 0) + y = Math.Log10(p.Pt[i].Y); else - { - if (p.Pt[i].Y == 0) - if (IsIntegerY) - y = 0; - else - y = double.NegativeInfinity; - else if (p.Pt[i].Y > 0) - y = Math.Log10(p.Pt[i].Y); - else - y = double.NaN; - } - - if (!double.IsNaN(x) && !double.IsNaN(y)) - temp.Pt.Add(new PointD(x, y)); + y = double.NaN; } - return temp; - } - public void SetInitialParameter(bool xLog, bool yLog) - { - this.xLog = xLog; - this.yLog = yLog; + if (!double.IsNaN(x) && !double.IsNaN(y)) + temp.Pt.Add(new PointD(x, y)); } + return temp; + } - /// - /// 現在のプロファイルから描画範囲の上限、下限値を設定 描画範囲は変更しない - /// - private void setDrawRangeLimit() + public void SetInitialParameter(bool xLog, bool yLog) + { + this.xLog = xLog; + this.yLog = yLog; + } + + /// + /// 現在のプロファイルから描画範囲の上限、下限値を設定 描画範囲は変更しない + /// + private void setDrawRangeLimit() + { + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0] == null || destProfileList[0].Pt == null || destProfileList[0].Pt.Count == 0) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + + try { - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0] == null || destProfileList[0].Pt == null || destProfileList[0].Pt.Count == 0) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + double minX = destProfileList.Where(d => d != null && d.Pt.Count != 0).Min(d => d.Pt.Min(p => p.X)); + double maxX = destProfileList.Where(d => d != null && d.Pt.Count != 0).Max(d => d.Pt.Max(p => p.X)); + double minY = destProfileList.Where(d => d != null && d.Pt.Count != 0).Min(d => d.Pt.Min(p => p.Y)); + double maxY = destProfileList.Where(d => d != null && d.Pt.Count != 0).Max(d => d.Pt.Max(p => p.Y)); - try + if (Miscellaneous.IsFiniteNumber(minX, maxX, minY, maxY)) + { + MinimalX = minX; + MaximalX = maxX; + MinimalY = minY; + MaximalY = maxY; + } + else { - double minX = destProfileList.Where(d => d != null && d.Pt.Count != 0).Min(d => d.Pt.Min(p => p.X)); - double maxX = destProfileList.Where(d => d != null && d.Pt.Count != 0).Max(d => d.Pt.Max(p => p.X)); - double minY = destProfileList.Where(d => d != null && d.Pt.Count != 0).Min(d => d.Pt.Min(p => p.Y)); - double maxY = destProfileList.Where(d => d != null && d.Pt.Count != 0).Max(d => d.Pt.Max(p => p.Y)); + MinimalX = 0; + MaximalX = 1; + MinimalY = 0; + MaximalY = 1; + return; + } - if (Miscellaneous.IsFiniteNumber(minX, maxX, minY, maxY)) - { - MinimalX = minX; - MaximalX = maxX; - MinimalY = minY; - MaximalY = maxY; - } - else + if (!XLog) + { + double space = (MaximalX - MinimalX) * 0.01; + MinimalX -= space; + MaximalX += space; + } + else + { + if (isIntegerX) { + double space = (MaximalX - MinimalX) * 0.01; MinimalX = 0; - MaximalX = 1; - MinimalY = 0; - MaximalY = 1; - return; + MaximalX += space; } - - if (!XLog) + else { double space = (MaximalX - MinimalX) * 0.01; MinimalX -= space; MaximalX += space; } - else - { - if (isIntegerX) - { - double space = (MaximalX - MinimalX) * 0.01; - MinimalX = 0; - MaximalX += space; - } - else - { - double space = (MaximalX - MinimalX) * 0.01; - MinimalX -= space; - MaximalX += space; - } - } + } - if (!YLog) + if (!YLog) + { + if (MinimalY > 0) + MinimalY = 0; + else + MinimalY *= 1.1; + MaximalY *= 1.1; + } + else + { + if (!IsIntegerY) { - if (MinimalY > 0) - MinimalY = 0; - else - MinimalY *= 1.1; - MaximalY *= 1.1; + double space = (MaximalY - MinimalY) * 0.01; + MinimalY = 0; + MaximalY += space; } else { - if (!IsIntegerY) - { - double space = (MaximalY - MinimalY) * 0.01; - MinimalY = 0; - MaximalY += space; - } - else - { - double space = (MaximalY - MinimalY) * 0.01; - MinimalY = 0; - MaximalY += space; - } + double space = (MaximalY - MinimalY) * 0.01; + MinimalY = 0; + MaximalY += space; } } - catch - { - return; - } } - - /// - /// 描画範囲Upper,LowerをMaximal,Minimalに設定する - /// - private void resetDrawRange() + catch { - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0] == null || destProfileList[0].Pt == null) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; - if (!fixRangeHorizontal) - { - LowerX = MinimalX; - UpperX = MaximalX; - } - if (!fixRangeVertical) - { - LowerY = MinimalY; - UpperY = MaximalY; - } - if (LowerX < MinimalX) LowerX = MinimalX; - if (LowerY < MinimalY) LowerY = MinimalY; - if (UpperX > MaximalX) UpperX = MaximalX; - if (UpperY > MaximalY) UpperY = MaximalY; - - DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); + return; } + } - /// - /// 描画範囲を設定する (ただし、上限下限の範囲内で) - /// - /// - public void SetDrawingRange(RectangleD rect) + /// + /// 描画範囲Upper,LowerをMaximal,Minimalに設定する + /// + private void resetDrawRange() + { + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0] == null || destProfileList[0].Pt == null) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + if (!fixRangeHorizontal) { - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; - LowerX = Math.Max(rect.X, MinimalX); - LowerY = Math.Max(rect.Y, MinimalY); - UpperX = Math.Min(rect.Width + rect.X, MaximalX); - UpperY = Math.Min(rect.Height + rect.Y, MaximalY); - Draw(); + LowerX = MinimalX; + UpperX = MaximalX; } - - /// - /// X軸の描画範囲を設定する(Y軸はそのまま) - /// - /// - public void SetDrawingRangeX(RectangleD rect) + if (!fixRangeVertical) { - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; - LowerX = Math.Max(rect.X, MinimalX); - UpperX = Math.Min(rect.Width + rect.X, MaximalX); - Draw(); + LowerY = MinimalY; + UpperY = MaximalY; } + if (LowerX < MinimalX) LowerX = MinimalX; + if (LowerY < MinimalY) LowerY = MinimalY; + if (UpperX > MaximalX) UpperX = MaximalX; + if (UpperY > MaximalY) UpperY = MaximalY; - /// - /// X軸の描画範囲を設定する(Y軸は描画範囲内で拡大する) - /// - /// - public void SetDrawingRangeXandExpandY(RectangleD rect) - { - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; - LowerX = Math.Max(rect.X, MinimalX); - UpperX = Math.Min(rect.Width + rect.X, MaximalX); - - double max = double.MinValue, min = double.MaxValue; - for (int i = 0; i < destProfileList.Count; i++) - for (int j = 0; j < destProfileList[i].Pt.Count; j++) - if (destProfileList[i].Pt[j].X >= LowerX && destProfileList[i].Pt[j].X <= UpperX) - { - max = Math.Max(destProfileList[i].Pt[j].Y, max); - min = Math.Min(destProfileList[i].Pt[j].Y, min); - } - if (max != double.MinValue) - UpperY = max + (max - min) * 0.1;// Math.Abs(max)* 0.1; - if (min != double.MaxValue) - LowerY = min - (max - min) * 0.1;// Math.Abs(min) * 0.1; + DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); + } - Draw(); - } + /// + /// 描画範囲を設定する (ただし、上限下限の範囲内で) + /// + /// + public void SetDrawingRange(RectangleD rect) + { + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + LowerX = Math.Max(rect.X, MinimalX); + LowerY = Math.Max(rect.Y, MinimalY); + UpperX = Math.Min(rect.Width + rect.X, MaximalX); + UpperY = Math.Min(rect.Height + rect.Y, MaximalY); + Draw(); + } + + /// + /// X軸の描画範囲を設定する(Y軸はそのまま) + /// + /// + public void SetDrawingRangeX(RectangleD rect) + { + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + LowerX = Math.Max(rect.X, MinimalX); + UpperX = Math.Min(rect.Width + rect.X, MaximalX); + Draw(); + } - public void Draw() + /// + /// X軸の描画範囲を設定する(Y軸は描画範囲内で拡大する) + /// + /// + public void SetDrawingRangeXandExpandY(RectangleD rect) + { + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + LowerX = Math.Max(rect.X, MinimalX); + UpperX = Math.Min(rect.Width + rect.X, MaximalX); + + double max = double.MinValue, min = double.MaxValue; + for (int i = 0; i < destProfileList.Count; i++) + for (int j = 0; j < destProfileList[i].Pt.Count; j++) + if (destProfileList[i].Pt[j].X >= LowerX && destProfileList[i].Pt[j].X <= UpperX) + { + max = Math.Max(destProfileList[i].Pt[j].Y, max); + min = Math.Min(destProfileList[i].Pt[j].Y, min); + } + if (max != double.MinValue) + UpperY = max + (max - min) * 0.1;// Math.Abs(max)* 0.1; + if (min != double.MaxValue) + LowerY = min - (max - min) * 0.1;// Math.Abs(min) * 0.1; + + Draw(); + } + + public void Draw() + { + Draw(false); + } + + public void Draw(bool initialize) + { + if (initialize) { - Draw(false); + InitializeAxis(); + setDrawRangeLimit(); + resetDrawRange(); } + if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null || destProfileList[0].Pt.Count == 0) return; + if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; - public void Draw(bool initialize) + try { - if (initialize) - { - InitializeAxis(); - setDrawRangeLimit(); - resetDrawRange(); - } - if (destProfileList == null || destProfileList.Count == 0 || destProfileList[0].Pt == null || destProfileList[0].Pt.Count == 0) return; - if (PictureBoxSize.Width <= 0 || PictureBoxSize.Height <= 0) return; + Bmp = new Bitmap(PictureBoxSize.Width, PictureBoxSize.Height); + G = Graphics.FromImage(Bmp); + G.Clear(BackgroundColor); - try { - Bmp = new Bitmap(PictureBoxSize.Width, PictureBoxSize.Height); - G = Graphics.FromImage(Bmp); - G.Clear(BackgroundColor); - - { - G.SmoothingMode = SmoothingMode.AntiAlias; - this.DoubleBuffered = true; - - DrawDivision(); - if (mode == DrawingMode.Histogram) - DrawProfileHistogram(); - else if (mode == DrawingMode.Line) - DrawProfileLine(); - else if (mode == DrawingMode.Point) - DrawProfilePoint(); - - if (lineList.Any()) - DrawLine(); - - if (peaks.Any()) - DrawPeaks(); - } - pictureBox.Image = Bmp; + G.SmoothingMode = SmoothingMode.AntiAlias; + this.DoubleBuffered = true; + + DrawDivision(); + if (mode == DrawingMode.Histogram) + DrawProfileHistogram(); + else if (mode == DrawingMode.Line) + DrawProfileLine(); + else if (mode == DrawingMode.Point) + DrawProfilePoint(); + + if (lineList.Any()) + DrawLine(); + + if (peaks.Any()) + DrawPeaks(); } - catch { } + pictureBox.Image = Bmp; } + catch { } + } - /// - /// グラフ中に線(LineList)で定義されたを描く - /// - private void DrawLine() + /// + /// グラフ中に線(LineList)で定義されたを描く + /// + private void DrawLine() + { + for (int i = 0; i < lineList.Count; i++) { - for (int i = 0; i < lineList.Count; i++) + double x = lineList[i].X; + if (xLog) { - double x = lineList[i].X; - if (xLog) - { - if (x > 0) - x = Math.Log10(x); - else - x = 0; - } - var ptStart = ConvToPicBoxCoord(x, lineList[i].Y); - if (double.IsNaN(lineList[i].Y)) - ptStart.Y = 0; - var ptEnd = new PointF((float)ptStart.X, (float)(pictureBox.Height - originPosition.Y)); - if (!double.IsNaN(ptStart.X) && !double.IsInfinity(ptStart.X)) - G.DrawLine(new Pen(LineColor, selectedLineIndex == i ? 2f : 1f), ptStart, ptEnd); + if (x > 0) + x = Math.Log10(x); + else + x = 0; } + var ptStart = ConvToPicBoxCoord(x, lineList[i].Y); + if (double.IsNaN(lineList[i].Y)) + ptStart.Y = 0; + var ptEnd = new PointF((float)ptStart.X, (float)(pictureBox.Height - originPosition.Y)); + if (!double.IsNaN(ptStart.X) && !double.IsInfinity(ptStart.X)) + G.DrawLine(new Pen(LineColor, selectedLineIndex == i ? 2f : 1f), ptStart, ptEnd); } + } - /// - /// グラフ中にpeaksで定義された釣鐘型曲線を描く - /// - private void DrawPeaks() + /// + /// グラフ中にpeaksで定義された釣鐘型曲線を描く + /// + private void DrawPeaks() + { + for (int i = 0; i < peaks.Count; i++) { - for (int i = 0; i < peaks.Count; i++) + double step = peaks[i].range / 100.0; + for (double x = peaks[i].X - peaks[i].range; x < peaks[i].X + peaks[i].range; x += step) { - double step = peaks[i].range / 100.0; - for (double x = peaks[i].X - peaks[i].range; x < peaks[i].X + peaks[i].range; x += step) - { - G.DrawLine(new Pen(LineColor, 2f), ConvToPicBoxCoord(x, peaks[i].GetValue(x, x == peaks[i].X - peaks[i].range, true)), ConvToPicBoxCoord(x + step, peaks[i].GetValue(x + step, false, true))); - } + G.DrawLine(new Pen(LineColor, 2f), ConvToPicBoxCoord(x, peaks[i].GetValue(x, x == peaks[i].X - peaks[i].range, true)), ConvToPicBoxCoord(x + step, peaks[i].GetValue(x + step, false, true))); } } + } - private void DrawProfilePoint() + private void DrawProfilePoint() + { + //総和が少ないプロファイルを前面に(最後に)書く + float maxX = PictureBoxSize.Width, minX = originPosition.X, maxY = PictureBoxSize.Height - originPosition.Y, minY = 0; + for (int j = 0; j < destProfileList.Count; j++) { - //総和が少ないプロファイルを前面に(最後に)書く - float maxX = PictureBoxSize.Width, minX = originPosition.X, maxY = PictureBoxSize.Height - originPosition.Y, minY = 0; - for (int j = 0; j < destProfileList.Count; j++) + PointD[] pt = destProfileList[j].Pt.ToArray(); + if (pt.Length > 0) { - PointD[] pt = destProfileList[j].Pt.ToArray(); - if (pt.Length > 0) + Brush brush = new SolidBrush(srcProfileList[j].Color); + for (int i = 0; i < pt.Length; i++) { - Brush brush = new SolidBrush(srcProfileList[j].Color); - for (int i = 0; i < pt.Length; i++) - { - PointF p = ConvToPicBoxCoord(pt[i]); - if (p.X > minX - 0.001 && p.X < maxX + 0.001 && p.Y > minY - 0.001 && p.Y < maxY + 0.001)//範囲内であれば - G.FillEllipse(brush, p.X - 1f, p.Y - 1f, 2f, 2f); - } + PointF p = ConvToPicBoxCoord(pt[i]); + if (p.X > minX - 0.001 && p.X < maxX + 0.001 && p.Y > minY - 0.001 && p.Y < maxY + 0.001)//範囲内であれば + G.FillEllipse(brush, p.X - 1f, p.Y - 1f, 2f, 2f); } } } + } - private void DrawProfileHistogram() + private void DrawProfileHistogram() + { + //総和が少ないプロファイルを前面に(最後に)書く + var sort = new List(); + for (int j = 0; j < destProfileList.Count; j++) + { + var pt = destProfileList[j].Pt.ToArray(); + double sum = 0; + for (int i = 0; i < pt.Length; i++) + sum += pt[i].Y; + sort.Add(new PointD(sum, j)); + } + sort.Sort(); + sort.Reverse(); + + float maxX = PictureBoxSize.Width, minX = originPosition.X, maxY = PictureBoxSize.Height - originPosition.Y, minY = 0; + float zeroY = ConvToPicBoxCoord(0, 0).Y; + for (int j = 0; j < sort.Count; j++) { - //総和が少ないプロファイルを前面に(最後に)書く - var sort = new List(); - for (int j = 0; j < destProfileList.Count; j++) + var pt = destProfileList[(int)sort[j].Y].Pt.ToArray(); + if (pt.Length > 0) { - var pt = destProfileList[j].Pt.ToArray(); - double sum = 0; + var brush = new SolidBrush(srcProfileList[(int)sort[j].Y].Color); + //var pointList = new List>(); + var beforePt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); + var presentPt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); + var nextPt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); for (int i = 0; i < pt.Length; i++) - sum += pt[i].Y; - sort.Add(new PointD(sum, j)); - } - sort.Sort(); - sort.Reverse(); - - float maxX = PictureBoxSize.Width, minX = originPosition.X, maxY = PictureBoxSize.Height - originPosition.Y, minY = 0; - float zeroY = ConvToPicBoxCoord(0, 0).Y; - for (int j = 0; j < sort.Count; j++) - { - var pt = destProfileList[(int)sort[j].Y].Pt.ToArray(); - if (pt.Length > 0) { - var brush = new SolidBrush(srcProfileList[(int)sort[j].Y].Color); - //var pointList = new List>(); - var beforePt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); - var presentPt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); - var nextPt = ConvToPicBoxCoord(pt[0].X, pt[0].Y); - for (int i = 0; i < pt.Length; i++) + if (i < pt.Length - 1) + nextPt = ConvToPicBoxCoord(pt[i + 1].X, pt[i + 1].Y); + if (presentPt.X > minY - 0.001 && presentPt.X < maxX + 0.001) { - if (i < pt.Length - 1) - nextPt = ConvToPicBoxCoord(pt[i + 1].X, pt[i + 1].Y); - if (presentPt.X > minY - 0.001 && presentPt.X < maxX + 0.001) - { - float x = Math.Max((beforePt.X + presentPt.X) / 2f - 0.5f, minX); - float y = Math.Max(presentPt.Y, minY); - float width = Math.Min((nextPt.X - beforePt.X) / 2f + 1f, (maxX - beforePt.X) / 2f + 1f); - float height = Math.Min(zeroY - y, maxY - y); - G.FillRectangle(brush, x, y, width, height); - } - beforePt = presentPt; - presentPt = nextPt; + float x = Math.Max((beforePt.X + presentPt.X) / 2f - 0.5f, minX); + float y = Math.Max(presentPt.Y, minY); + float width = Math.Min((nextPt.X - beforePt.X) / 2f + 1f, (maxX - beforePt.X) / 2f + 1f); + float height = Math.Min(zeroY - y, maxY - y); + G.FillRectangle(brush, x, y, width, height); } + beforePt = presentPt; + presentPt = nextPt; } } } + } - /// - /// 線形式のプロファイルを描く //一旦全部書いた後、要らない部分を切った方がいいのでは? - /// - private void DrawProfileLine() + /// + /// 線形式のプロファイルを描く //一旦全部書いた後、要らない部分を切った方がいいのでは? + /// + private void DrawProfileLine() + { + var rect = new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY); + if (rect.Width * rect.Height == 0) + return; + for (int j = 0; j < destProfileList.Count; j++) { - var rect = new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY); - if (rect.Width * rect.Height == 0) - return; - for (int j = 0; j < destProfileList.Count; j++) + if (srcProfileList[j] != null) { - if (srcProfileList[j] != null) - { - //if (!Interpolation)//補間モードではないとき - //{ - var pen = new Pen(srcProfileList[j].Color, UseLineWidth ? LineWidth : srcProfileList[j].LineWidth) { LineJoin = LineJoin.Round }; - var pts = destProfileList[j].GetPointsWithinRectangle(rect); - for (int i = 0; i < pts.Length; i++) - if (pts[i].Length > 1) - G.DrawLines(pen, pts[i].Select(p => ConvToPicBoxCoord(p)).ToArray()); - //} - //else//補間モードの時 - //{ - //} - } + //if (!Interpolation)//補間モードではないとき + //{ + var pen = new Pen(srcProfileList[j].Color, UseLineWidth ? LineWidth : srcProfileList[j].LineWidth) { LineJoin = LineJoin.Round }; + var pts = destProfileList[j].GetPointsWithinRectangle(rect); + for (int i = 0; i < pts.Length; i++) + if (pts[i].Length > 1) + G.DrawLines(pen, pts[i].Select(p => ConvToPicBoxCoord(p)).ToArray()); + //} + //else//補間モードの時 + //{ + //} } } + } - /// - /// 上下限値(max, min)と最大目盛り数(maxDiv)から、目盛りの位置とラベルを生成する - /// - /// - /// - /// - /// - /// - public static SortedList GetDivisions(double min, double max, int maxDiv, bool log) - { - if (double.IsInfinity(min) || double.IsInfinity(max)) return new SortedList(); - var results = new SortedList(); - double d = max - min; - string str = ""; + /// + /// 上下限値(max, min)と最大目盛り数(maxDiv)から、目盛りの位置とラベルを生成する + /// + /// + /// + /// + /// + /// + public static SortedList GetDivisions(double min, double max, int maxDiv, bool log) + { + if (double.IsInfinity(min) || double.IsInfinity(max)) return new SortedList(); + var results = new SortedList(); + double d = max - min; + string str = ""; - if (!log) + if (!log) + { + double step = 1; + double unit = Math.Pow(10, Math.Floor(Math.Log10(d / maxDiv))); + if (d / unit < maxDiv) step = unit; + else if (d / unit / 2 < maxDiv) step = unit * 2; + else if (d / unit / 5 < maxDiv) step = unit * 5; + else if (d / unit / 10 < maxDiv) step = unit * 10; + + for (int i = (int)(min / step) + 1; i < max / step; i++) { - double step = 1; - double unit = Math.Pow(10, Math.Floor(Math.Log10(d / maxDiv))); - if (d / unit < maxDiv) step = unit; - else if (d / unit / 2 < maxDiv) step = unit * 2; - else if (d / unit / 5 < maxDiv) step = unit * 5; - else if (d / unit / 10 < maxDiv) step = unit * 10; - - for (int i = (int)(min / step) + 1; i < max / step; i++) - { - if (max > 1000 || max < 0.001) - // str = ((i * step) / Math.Pow(10, (int)Math.Log10(max) - 1)).ToString("#,#.###############") + "E" + ((int)Math.Log10(max) - 1).ToString(); - str = ((i * step) / Math.Pow(10, (int)Math.Log10(i * step))).ToString("#,#.###############") + "E" + ((int)Math.Log10(i * step)).ToString(); - else - str = Math.Round(i * step, 5).ToString("#,#.###############"); - results.Add(i * step, str); - } + if (max > 1000 || max < 0.001) + // str = ((i * step) / Math.Pow(10, (int)Math.Log10(max) - 1)).ToString("#,#.###############") + "E" + ((int)Math.Log10(max) - 1).ToString(); + str = ((i * step) / Math.Pow(10, (int)Math.Log10(i * step))).ToString("#,#.###############") + "E" + ((int)Math.Log10(i * step)).ToString(); + else + str = Math.Round(i * step, 5).ToString("#,#.###############"); + results.Add(i * step, str); } - else - { - //先ずは無条件で有効数字0桁の目盛りを設定 - for (int i = (int)min; i < max; i++) - if (i > min) - results.Add(i, "1E" + i.ToString()); + } + else + { + //先ずは無条件で有効数字0桁の目盛りを設定 + for (int i = (int)min; i < max; i++) + if (i > min) + results.Add(i, "1E" + i.ToString()); - //有効数字1桁の目盛り(2E1,3E1,4E1など)を設定 - for (int i = (int)Math.Floor(min); i < max + 1; i++) + //有効数字1桁の目盛り(2E1,3E1,4E1など)を設定 + for (int i = (int)Math.Floor(min); i < max + 1; i++) + { + for (int j = 2; j < 10; j++) { - for (int j = 2; j < 10; j++) - { - double a = Math.Log10(j) + i; - if (a >= min && a <= max) - results.Add(a, maxDiv / d < 8 ? "" : j.ToString() + "E" + i.ToString()); - } + double a = Math.Log10(j) + i; + if (a >= min && a <= max) + results.Add(a, maxDiv / d < 8 ? "" : j.ToString() + "E" + i.ToString()); } + } - if (d < 0.5) - { - double max2 = Math.Pow(10, max); - double min2 = Math.Pow(10, min); - double step = 1; - double unit = Math.Pow(10, Math.Floor(Math.Log10((max2 - min2) / maxDiv))); - if ((max2 - min2) / unit < maxDiv) step = unit; - else if ((max2 - min2) / unit / 2 < maxDiv) step = unit * 2; - else if ((max2 - min2) / unit / 5 < maxDiv) step = unit * 5; - else if ((max2 - min2) / unit / 10 < maxDiv) step = unit * 10; - - for (int i = (int)(min2 / step) + 1; i < max2 / step; i++) - if (!results.ContainsKey(Math.Log10(i * step))) - results.Add(Math.Log10(i * step), ((i * step) / Math.Pow(10, (int)Math.Floor(Math.Log10(i * step)))).ToString("#,#.###############") + "E" + ((int)Math.Floor(Math.Log10(i * step))).ToString()); - } + if (d < 0.5) + { + double max2 = Math.Pow(10, max); + double min2 = Math.Pow(10, min); + double step = 1; + double unit = Math.Pow(10, Math.Floor(Math.Log10((max2 - min2) / maxDiv))); + if ((max2 - min2) / unit < maxDiv) step = unit; + else if ((max2 - min2) / unit / 2 < maxDiv) step = unit * 2; + else if ((max2 - min2) / unit / 5 < maxDiv) step = unit * 5; + else if ((max2 - min2) / unit / 10 < maxDiv) step = unit * 10; + + for (int i = (int)(min2 / step) + 1; i < max2 / step; i++) + if (!results.ContainsKey(Math.Log10(i * step))) + results.Add(Math.Log10(i * step), ((i * step) / Math.Pow(10, (int)Math.Floor(Math.Log10(i * step)))).ToString("#,#.###############") + "E" + ((int)Math.Floor(Math.Log10(i * step))).ToString()); } - return results; } + return results; + } - public void DrawDivision() + public void DrawDivision() + { + var strFont = new Font(new FontFamily("tahoma"), 8); + var pen = new Pen(DivisionLineColor, 1); + + //ここよりX目盛りの描画 + G.DrawLine(pen, OriginPosition.X, pictureBox.Height - OriginPosition.Y, PictureBoxSize.Width, pictureBox.Height - OriginPosition.Y); + int maxDivisionNumber = (this.Width - this.originPosition.X) / 60 + 1; + var divisions = GetDivisions(LowerX, UpperX, maxDivisionNumber, XLog); + for (int i = 0; i < divisions.Count; i++) { - var strFont = new Font(new FontFamily("tahoma"), 8); - var pen = new Pen(DivisionLineColor, 1); - - //ここよりX目盛りの描画 - G.DrawLine(pen, OriginPosition.X, pictureBox.Height - OriginPosition.Y, PictureBoxSize.Width, pictureBox.Height - OriginPosition.Y); - int maxDivisionNumber = (this.Width - this.originPosition.X) / 60 + 1; - var divisions = GetDivisions(LowerX, UpperX, maxDivisionNumber, XLog); - for (int i = 0; i < divisions.Count; i++) - { - pen = new Pen(DivisionLineColor, 1); - G.DrawLine(pen, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y + 5); - if (horizontalGradiationTextVisivle) - G.DrawString(divisions.Values[i], strFont, DivisionTextBrush, ConvToPicBoxCoord(divisions.Keys[i], 0).X - 2, PictureBoxSize.Height - OriginPosition.Y + 5); - - pen = new Pen(DivisionSubLineColor, 1); - if (XScaleLineVisible) - G.DrawLine(pen, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y, ConvToPicBoxCoord(divisions.Keys[i], 0).X, 0); - } + pen = new Pen(DivisionLineColor, 1); + G.DrawLine(pen, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y + 5); + if (horizontalGradiationTextVisivle) + G.DrawString(divisions.Values[i], strFont, DivisionTextBrush, ConvToPicBoxCoord(divisions.Keys[i], 0).X - 2, PictureBoxSize.Height - OriginPosition.Y + 5); - //ここよりY目盛りの描画 - G.DrawLine(pen, OriginPosition.X, 0, OriginPosition.X, pictureBox.Height - OriginPosition.Y); - maxDivisionNumber = (this.Height - this.originPosition.Y) / 30 + 1; - divisions = GetDivisions(LowerY, UpperY, maxDivisionNumber, YLog); + pen = new Pen(DivisionSubLineColor, 1); + if (XScaleLineVisible) + G.DrawLine(pen, ConvToPicBoxCoord(divisions.Keys[i], 0).X, PictureBoxSize.Height - OriginPosition.Y, ConvToPicBoxCoord(divisions.Keys[i], 0).X, 0); + } - for (int i = 0; i < divisions.Count; i++) - { - pen = new Pen(DivisionLineColor, 1); - G.DrawLine(pen, OriginPosition.X - 8, ConvToPicBoxCoord(0, divisions.Keys[i]).Y, OriginPosition.X, ConvToPicBoxCoord(0, divisions.Keys[i]).Y); + //ここよりY目盛りの描画 + G.DrawLine(pen, OriginPosition.X, 0, OriginPosition.X, pictureBox.Height - OriginPosition.Y); + maxDivisionNumber = (this.Height - this.originPosition.Y) / 30 + 1; + divisions = GetDivisions(LowerY, UpperY, maxDivisionNumber, YLog); + + for (int i = 0; i < divisions.Count; i++) + { + pen = new Pen(DivisionLineColor, 1); + G.DrawLine(pen, OriginPosition.X - 8, ConvToPicBoxCoord(0, divisions.Keys[i]).Y, OriginPosition.X, ConvToPicBoxCoord(0, divisions.Keys[i]).Y); - if (horizontalGradiationTextVisivle) - G.DrawString(divisions.Values[i], strFont, DivisionTextBrush, 0, ConvToPicBoxCoord(0, divisions.Keys[i]).Y - 6); + if (horizontalGradiationTextVisivle) + G.DrawString(divisions.Values[i], strFont, DivisionTextBrush, 0, ConvToPicBoxCoord(0, divisions.Keys[i]).Y - 6); - pen = new Pen(DivisionSubLineColor, 1); - if (YScaleLineVisible) - G.DrawLine(pen, OriginPosition.X - 8, ConvToPicBoxCoord(0, divisions.Keys[i]).Y, PictureBoxSize.Width, ConvToPicBoxCoord(0, divisions.Keys[i]).Y); - } + pen = new Pen(DivisionSubLineColor, 1); + if (YScaleLineVisible) + G.DrawLine(pen, OriginPosition.X - 8, ConvToPicBoxCoord(0, divisions.Keys[i]).Y, PictureBoxSize.Width, ConvToPicBoxCoord(0, divisions.Keys[i]).Y); } + } - #region 座標変換関係 + #region 座標変換関係 - private PointF ConvToPicBoxCoord(double x, double y) - {//プロファイル座標をピクチャーボックスの座標系に変換 - return new PointF((float)((PictureBoxSize.Width - originPosition.X) / (UpperX - LowerX) * (x - LowerX)) + OriginPosition.X, - (float)(PictureBoxSize.Height - originPosition.Y - BottomMargin - (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) / (UpperY - LowerY) * (y - LowerY))); - } + private PointF ConvToPicBoxCoord(double x, double y) + {//プロファイル座標をピクチャーボックスの座標系に変換 + return new PointF((float)((PictureBoxSize.Width - originPosition.X) / (UpperX - LowerX) * (x - LowerX)) + OriginPosition.X, + (float)(PictureBoxSize.Height - originPosition.Y - BottomMargin - (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) / (UpperY - LowerY) * (y - LowerY))); + } - private PointF ConvToPicBoxCoord(PointD p) - {//ピクチャーボックスの座標系に変換 - return new PointF((float)((PictureBoxSize.Width - OriginPosition.X) / (UpperX - LowerX) * (p.X - LowerX)) + OriginPosition.X, - (float)(PictureBoxSize.Height - OriginPosition.Y - BottomMargin - (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) / (UpperY - LowerY) * (p.Y - LowerY))); - } + private PointF ConvToPicBoxCoord(PointD p) + {//ピクチャーボックスの座標系に変換 + return new PointF((float)((PictureBoxSize.Width - OriginPosition.X) / (UpperX - LowerX) * (p.X - LowerX)) + OriginPosition.X, + (float)(PictureBoxSize.Height - OriginPosition.Y - BottomMargin - (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) / (UpperY - LowerY) * (p.Y - LowerY))); + } - private PointD ConvToRealCoord(int x, int y) - {//マウス座標をオリジナルの座標系に変換 - return new PointD( - (double)(x - OriginPosition.X) / (PictureBoxSize.Width - OriginPosition.X) * (UpperX - LowerX) + LowerX, - (double)(PictureBoxSize.Height - y - OriginPosition.Y - BottomMargin) / (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) * (UpperY - LowerY) + LowerY); - } + private PointD ConvToRealCoord(int x, int y) + {//マウス座標をオリジナルの座標系に変換 + return new PointD( + (double)(x - OriginPosition.X) / (PictureBoxSize.Width - OriginPosition.X) * (UpperX - LowerX) + LowerX, + (double)(PictureBoxSize.Height - y - OriginPosition.Y - BottomMargin) / (PictureBoxSize.Height - OriginPosition.Y - BottomMargin) * (UpperY - LowerY) + LowerY); + } - #endregion 座標変換関係 + #endregion 座標変換関係 - private void GraphControl_Resize(object sender, EventArgs e) - { - Draw(); - } + private void GraphControl_Resize(object sender, EventArgs e) + { + Draw(); + } - /// - /// 近いラインを探す - /// - /// - /// - /// - private int serchLineIndex(double upperX, double lowerX) + /// + /// 近いラインを探す + /// + /// + /// + /// + private int serchLineIndex(double upperX, double lowerX) + { + double dev = double.PositiveInfinity; + int index = -1; + if (xLog) { - double dev = double.PositiveInfinity; - int index = -1; - if (xLog) - { - upperX = Math.Pow(10, upperX); + upperX = Math.Pow(10, upperX); - if (lowerX > 0) lowerX = Math.Pow(10, lowerX); - else lowerX = -Math.Pow(10, lowerX); - } - for (int i = 0; i < lineList.Count; i++) - { - if (upperX > lineList[i].X && lowerX < lineList[i].X) - if (dev > (upperX + lowerX) / 2 - lineList[i].X) - { - dev = (upperX + lowerX) / 2 - lineList[i].X; - index = i; - } - } - return index; + if (lowerX > 0) lowerX = Math.Pow(10, lowerX); + else lowerX = -Math.Pow(10, lowerX); } + for (int i = 0; i < lineList.Count; i++) + { + if (upperX > lineList[i].X && lowerX < lineList[i].X) + if (dev > (upperX + lowerX) / 2 - lineList[i].X) + { + dev = (upperX + lowerX) / 2 - lineList[i].X; + index = i; + } + } + return index; + } - #region マウス操作関連 + #region マウス操作関連 - public Point MouseRangeStart, MouseRangeEnd; - public PointD MouseMovingStartPt; - public bool MouseRangingMode = false; - public bool MouseMovingMode = false; - public bool LineSelectMode = false; + public Point MouseRangeStart, MouseRangeEnd; + public PointD MouseMovingStartPt; + public bool MouseRangingMode = false; + public bool MouseMovingMode = false; + public bool LineSelectMode = false; - private void pictureBox_MouseDoubleClick(object sender, MouseEventArgs e) - { - } + private void pictureBox_MouseDoubleClick(object sender, MouseEventArgs e) + { + } - #region コンテキストメニュー + #region コンテキストメニュー - private void toolStripMenuItemLogScaleY_Click(object sender, EventArgs e) - { - YLog = !YLog; - } + private void toolStripMenuItemLogScaleY_Click(object sender, EventArgs e) + { + YLog = !YLog; + } - private void toolStripMenuItemLogScaleX_Click(object sender, EventArgs e) - { - XLog = !XLog; - } + private void toolStripMenuItemLogScaleX_Click(object sender, EventArgs e) + { + XLog = !XLog; + } + + private void toolStripMenuItemScaleLineX_Click(object sender, EventArgs e) + { + XScaleLineVisible = !XScaleLineVisible; + } + + private void toolStripMenuItemScaleLineY_Click(object sender, EventArgs e) + { + YScaleLineVisible = !YScaleLineVisible; + } - private void toolStripMenuItemScaleLineX_Click(object sender, EventArgs e) + #endregion コンテキストメニュー + + private void pictureBox_MouseDown(object sender, MouseEventArgs e) + { + if (!AllowMouseOperation) return; + + PointD pt = ConvToRealCoord(e.X, e.Y); + if (e.Button == MouseButtons.Middle) { - XScaleLineVisible = !XScaleLineVisible; + MouseMovingMode = true; + MouseMovingStartPt = pt; + pictureBox.Cursor = Cursors.SizeAll; + return; } - private void toolStripMenuItemScaleLineY_Click(object sender, EventArgs e) + if (e.Button == MouseButtons.Right && e.X - OriginPosition.X >= 0 && PictureBoxSize.Height - e.Y - OriginPosition.Y >= 0) { - YScaleLineVisible = !YScaleLineVisible; + MouseRangingMode = true; + MouseRangeStart = new Point(e.X, e.Y); + MouseRangeEnd = new Point(e.X, e.Y); + return; } - - #endregion コンテキストメニュー - - private void pictureBox_MouseDown(object sender, MouseEventArgs e) + if (e.Button == MouseButtons.Left) { - if (!AllowMouseOperation) return; - - PointD pt = ConvToRealCoord(e.X, e.Y); - if (e.Button == MouseButtons.Middle) - { - MouseMovingMode = true; - MouseMovingStartPt = pt; - pictureBox.Cursor = Cursors.SizeAll; - return; - } - - if (e.Button == MouseButtons.Right && e.X - OriginPosition.X >= 0 && PictureBoxSize.Height - e.Y - OriginPosition.Y >= 0) - { - MouseRangingMode = true; - MouseRangeStart = new Point(e.X, e.Y); - MouseRangeEnd = new Point(e.X, e.Y); - return; - } - if (e.Button == MouseButtons.Left) + if (e.Clicks == 1) { - if (e.Clicks == 1) + int i = serchLineIndex(ConvToRealCoord(e.X + 3, e.Y).X, ConvToRealCoord(e.X - 3, e.Y).X); + if (i >= 0) { - int i = serchLineIndex(ConvToRealCoord(e.X + 3, e.Y).X, ConvToRealCoord(e.X - 3, e.Y).X); - if (i >= 0) - { - LineSelectMode = true; - selectedLineIndex = i; - Draw(); - } + LineSelectMode = true; + selectedLineIndex = i; + Draw(); } - else if (e.Clicks == 2) - { - if (MouseDoubleClick2 != null) - if (MouseDoubleClick2(pt)) - return; + } + else if (e.Clicks == 2) + { + if (MouseDoubleClick2 != null) + if (MouseDoubleClick2(pt)) + return; - if (Profile != null && Profile.Pt != null && Profile.Pt.Count != 0) - { - var sb = new StringBuilder(); - for (int i = 0; i < Profile.Pt.Count; i++) - sb.AppendLine(Profile.Pt[i].X.ToString() + "\t" + Profile.Pt[i].Y.ToString()); - Clipboard.SetDataObject(sb.ToString()); - } + if (Profile != null && Profile.Pt != null && Profile.Pt.Count != 0) + { + var sb = new StringBuilder(); + for (int i = 0; i < Profile.Pt.Count; i++) + sb.AppendLine(Profile.Pt[i].X.ToString() + "\t" + Profile.Pt[i].Y.ToString()); + Clipboard.SetDataObject(sb.ToString()); } } } + } - private void pictureBox_MouseMove(object sender, MouseEventArgs e) + private void pictureBox_MouseMove(object sender, MouseEventArgs e) + { + if (!AllowMouseOperation) return; + + //マウスが動いたとき + PointD pt = ConvToRealCoord(e.X, e.Y); + double x = pt.X; + x = XLog ? Math.Pow(10, x) : x; + x = IsIntegerX ? (int)(Math.Round(x)) : x; + + double y = pt.Y; + y = XLog ? Math.Pow(10, y) : y; + y = IsIntegerY ? (int)(Math.Round(y)) : y; + + if (!XLog) + labelXValue.Text = x.ToString("g") + UnitX; + else + labelXValue.Text = x.ToString("E") + UnitX; + if (!YLog) + labelYLabel.Text = y.ToString("g") + UnitY; + else + labelYLabel.Text = y.ToString("E") + UnitY; + + if (MouseMovingMode) { - if (!AllowMouseOperation) return; - - //マウスが動いたとき - PointD pt = ConvToRealCoord(e.X, e.Y); - double x = pt.X; - x = XLog ? Math.Pow(10, x) : x; - x = IsIntegerX ? (int)(Math.Round(x)) : x; - - double y = pt.Y; - y = XLog ? Math.Pow(10, y) : y; - y = IsIntegerY ? (int)(Math.Round(y)) : y; + pictureBox.Cursor = Cursors.SizeAll; + //MouseRangingStartが現在の中心位置に来るように設定を治す + double devX = -pt.X + MouseMovingStartPt.X; + double devY = -pt.Y + MouseMovingStartPt.Y; - if (!XLog) - labelXValue.Text = x.ToString("g") + UnitX; - else - labelXValue.Text = x.ToString("E") + UnitX; - if (!YLog) - labelYLabel.Text = y.ToString("g") + UnitY; - else - labelYLabel.Text = y.ToString("E") + UnitY; - - if (MouseMovingMode) + if (devX + UpperX < MaximalX && devX + LowerX > MinimalX) { - pictureBox.Cursor = Cursors.SizeAll; - //MouseRangingStartが現在の中心位置に来るように設定を治す - double devX = -pt.X + MouseMovingStartPt.X; - double devY = -pt.Y + MouseMovingStartPt.Y; - - if (devX + UpperX < MaximalX && devX + LowerX > MinimalX) - { - UpperX += devX; - LowerX += devX; - } - if (devY + UpperY < MaximalY && devY + LowerY > MinimalY) - { - UpperY += devY; - LowerY += devY; - } - pt = ConvToRealCoord(e.X, e.Y); - MouseMovingStartPt = pt; - Draw(); - return; + UpperX += devX; + LowerX += devX; } - else - pictureBox.Cursor = Cursors.Default; - - if (MouseRangingMode) - {//範囲選択モードのとき - MouseRangeEnd = new Point(e.X, e.Y); - pictureBox.Refresh(); - return; + if (devY + UpperY < MaximalY && devY + LowerY > MinimalY) + { + UpperY += devY; + LowerY += devY; } + pt = ConvToRealCoord(e.X, e.Y); + MouseMovingStartPt = pt; + Draw(); + return; + } + else + pictureBox.Cursor = Cursors.Default; - if (LineSelectMode && e.Button == MouseButtons.Left) + if (MouseRangingMode) + {//範囲選択モードのとき + MouseRangeEnd = new Point(e.X, e.Y); + pictureBox.Refresh(); + return; + } + + if (LineSelectMode && e.Button == MouseButtons.Left) + { + if (e.X > 3 && e.Y > 3 && e.X < PictureBoxSize.Width - 3 && e.Y < PictureBoxSize.Height - 3) { - if (e.X > 3 && e.Y > 3 && e.X < PictureBoxSize.Width - 3 && e.Y < PictureBoxSize.Height - 3) + if (lineList.Count > selectedLineIndex && selectedLineIndex >= 0) { - if (lineList.Count > selectedLineIndex && selectedLineIndex >= 0) - { - //lineList[selectedLineIndex].X = x; - lineList[selectedLineIndex] = new PointD(x, lineList[selectedLineIndex].Y); + //lineList[selectedLineIndex].X = x; + lineList[selectedLineIndex] = new PointD(x, lineList[selectedLineIndex].Y); - Draw(); - LinePositionChanged?.Invoke(); - Refresh(); - } + Draw(); + LinePositionChanged?.Invoke(); + Refresh(); } } } + } - private void pictureBox_MouseUp(object sender, MouseEventArgs e) - { - if (!AllowMouseOperation) return; + private void pictureBox_MouseUp(object sender, MouseEventArgs e) + { + if (!AllowMouseOperation) return; - MouseMovingMode = false; - LineSelectMode = false; + MouseMovingMode = false; + LineSelectMode = false; - var pt = ConvToRealCoord(e.X, e.Y); + var pt = ConvToRealCoord(e.X, e.Y); - if (MouseRangingMode) - { - MouseRangingMode = false; - MouseRangeEnd = new Point(e.X, e.Y); + if (MouseRangingMode) + { + MouseRangingMode = false; + MouseRangeEnd = new Point(e.X, e.Y); - if (Math.Abs(MouseRangeEnd.X - MouseRangeStart.X) < 3 || Math.Abs(MouseRangeEnd.Y - MouseRangeStart.Y) < 3) - {//選択範囲があまりにも小さすぎたら - //縮小 - LowerX = LowerX * 1.5 - UpperX * 0.5; - if (LowerX < MinimalX) LowerX = MinimalX; + if (Math.Abs(MouseRangeEnd.X - MouseRangeStart.X) < 3 || Math.Abs(MouseRangeEnd.Y - MouseRangeStart.Y) < 3) + {//選択範囲があまりにも小さすぎたら + //縮小 + LowerX = LowerX * 1.5 - UpperX * 0.5; + if (LowerX < MinimalX) LowerX = MinimalX; - UpperX = UpperX * 1.5 - LowerX * 0.5; - if (UpperX > MaximalX) UpperX = MaximalX; + UpperX = UpperX * 1.5 - LowerX * 0.5; + if (UpperX > MaximalX) UpperX = MaximalX; - LowerY = LowerY * 1.5 - UpperY * 0.5; - if (LowerY < MinimalY) LowerY = MinimalY; + LowerY = LowerY * 1.5 - UpperY * 0.5; + if (LowerY < MinimalY) LowerY = MinimalY; - UpperY = UpperY * 1.5 - LowerY * 0.5; - if (UpperY > MaximalY) UpperY = MaximalY; + UpperY = UpperY * 1.5 - LowerY * 0.5; + if (UpperY > MaximalY) UpperY = MaximalY; - Draw(); - DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); - } - else if (Math.Abs(MouseRangeEnd.X - MouseRangeStart.X) < 10 || Math.Abs(MouseRangeEnd.Y - MouseRangeStart.Y) < 10) - {//選択範囲が中途半端に小さすぎたら - MouseRangingMode = false; - pictureBox.Refresh(); - } - else - { - double xmax = ConvToRealCoord(Math.Max(MouseRangeStart.X, MouseRangeEnd.X), 1).X; - double xmin = ConvToRealCoord(Math.Min(MouseRangeStart.X, MouseRangeEnd.X), 1).X; - double ymin = ConvToRealCoord(1, Math.Max(MouseRangeStart.Y, MouseRangeEnd.Y)).Y; - double ymax = ConvToRealCoord(1, Math.Min(MouseRangeStart.Y, MouseRangeEnd.Y)).Y; - if (xmax - xmin < 0.000001 || ymax - ymin < 0.00001) return; - if (xmax > UpperX) xmax = UpperX; - if (xmin < LowerX) xmin = LowerX; - if (ymax > UpperY) ymax = UpperY; - if (ymin < LowerY) ymin = LowerY; - - LowerX = xmin; UpperX = xmax; LowerY = ymin; UpperY = ymax; - Draw(); - DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); - } + Draw(); + DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); } - else if (e.Button == MouseButtons.Right && (e.X - OriginPosition.X) * (PictureBoxSize.Height - e.Y - OriginPosition.Y) < 0) - { - toolStripMenuItemLogScaleX.Visible = e.X > OriginPosition.X && PictureBoxSize.Height - e.Y < OriginPosition.Y; - toolStripMenuItemScaleLineX.Visible = e.X > OriginPosition.X && PictureBoxSize.Height - e.Y < OriginPosition.Y; - toolStripMenuItemLogScaleY.Visible = e.X < OriginPosition.X && PictureBoxSize.Height - e.Y > OriginPosition.Y; - toolStripMenuItemScaleLineY.Visible = e.X < OriginPosition.X && PictureBoxSize.Height - e.Y > OriginPosition.Y; + else if (Math.Abs(MouseRangeEnd.X - MouseRangeStart.X) < 10 || Math.Abs(MouseRangeEnd.Y - MouseRangeStart.Y) < 10) + {//選択範囲が中途半端に小さすぎたら MouseRangingMode = false; - contextMenuStripY.Show(this.pictureBox, e.X, e.Y); + pictureBox.Refresh(); } - } - - #endregion マウス操作関連 - - private void pictureBox_Paint(object sender, PaintEventArgs e) - { - if (MouseRangingMode) + else { - Pen pen = new Pen(Brushes.Gray) { DashStyle = DashStyle.Dash }; - e.Graphics.DrawRectangle(pen, Math.Min(MouseRangeStart.X, MouseRangeEnd.X), Math.Min(MouseRangeStart.Y, MouseRangeEnd.Y), - Math.Abs(MouseRangeStart.X - MouseRangeEnd.X), Math.Abs(MouseRangeStart.Y - MouseRangeEnd.Y)); + double xmax = ConvToRealCoord(Math.Max(MouseRangeStart.X, MouseRangeEnd.X), 1).X; + double xmin = ConvToRealCoord(Math.Min(MouseRangeStart.X, MouseRangeEnd.X), 1).X; + double ymin = ConvToRealCoord(1, Math.Max(MouseRangeStart.Y, MouseRangeEnd.Y)).Y; + double ymax = ConvToRealCoord(1, Math.Min(MouseRangeStart.Y, MouseRangeEnd.Y)).Y; + if (xmax - xmin < 0.000001 || ymax - ymin < 0.00001) return; + if (xmax > UpperX) xmax = UpperX; + if (xmin < LowerX) xmin = LowerX; + if (ymax > UpperY) ymax = UpperY; + if (ymin < LowerY) ymin = LowerY; + + LowerX = xmin; UpperX = xmax; LowerY = ymin; UpperY = ymax; + Draw(); + DrawingRangeChanged?.Invoke(new RectangleD(LowerX, LowerY, UpperX - LowerX, UpperY - LowerY)); } } + else if (e.Button == MouseButtons.Right && (e.X - OriginPosition.X) * (PictureBoxSize.Height - e.Y - OriginPosition.Y) < 0) + { + toolStripMenuItemLogScaleX.Visible = e.X > OriginPosition.X && PictureBoxSize.Height - e.Y < OriginPosition.Y; + toolStripMenuItemScaleLineX.Visible = e.X > OriginPosition.X && PictureBoxSize.Height - e.Y < OriginPosition.Y; + toolStripMenuItemLogScaleY.Visible = e.X < OriginPosition.X && PictureBoxSize.Height - e.Y > OriginPosition.Y; + toolStripMenuItemScaleLineY.Visible = e.X < OriginPosition.X && PictureBoxSize.Height - e.Y > OriginPosition.Y; + MouseRangingMode = false; + contextMenuStripY.Show(this.pictureBox, e.X, e.Y); + } + } - private void toolStripMenuItemLogScaleX_CheckedChanged(object sender, EventArgs e) + #endregion マウス操作関連 + + private void pictureBox_Paint(object sender, PaintEventArgs e) + { + if (MouseRangingMode) { - XLog = toolStripMenuItemLogScaleX.Checked; - YLog = toolStripMenuItemLogScaleY.Checked; + Pen pen = new Pen(Brushes.Gray) { DashStyle = DashStyle.Dash }; + e.Graphics.DrawRectangle(pen, Math.Min(MouseRangeStart.X, MouseRangeEnd.X), Math.Min(MouseRangeStart.Y, MouseRangeEnd.Y), + Math.Abs(MouseRangeStart.X - MouseRangeEnd.X), Math.Abs(MouseRangeStart.Y - MouseRangeEnd.Y)); } } + + private void toolStripMenuItemLogScaleX_CheckedChanged(object sender, EventArgs e) + { + XLog = toolStripMenuItemLogScaleX.Checked; + YLog = toolStripMenuItemLogScaleY.Checked; + } } \ No newline at end of file diff --git a/Crystallography.Controls/Macro/FormMacroList.Designer.cs b/Crystallography.Controls/Macro/FormMacroList.Designer.cs deleted file mode 100644 index 6b547ec..0000000 --- a/Crystallography.Controls/Macro/FormMacroList.Designer.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Crystallography.Controls.Macro -{ - partial class FormMacroList - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.SuspendLayout(); - // - // FormMacroList - // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(331, 326); - this.Font = new System.Drawing.Font("Segoe UI Symbol", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.Name = "FormMacroList"; - this.Text = "FormMacroList"; - this.ResumeLayout(false); - - } - - #endregion - - } -} \ No newline at end of file diff --git a/Crystallography.Controls/Macro/FormMacroList.cs b/Crystallography.Controls/Macro/FormMacroList.cs deleted file mode 100644 index 922d8a3..0000000 --- a/Crystallography.Controls/Macro/FormMacroList.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Windows.Forms; - -namespace Crystallography.Controls.Macro -{ - public partial class FormMacroList : Form - { - public FormMacroList() - { - InitializeComponent(); - } - } -} \ No newline at end of file diff --git a/Crystallography.Controls/Macro/Macro.cs b/Crystallography.Controls/Macro/Macro.cs index 7d563f3..21ba42f 100644 --- a/Crystallography.Controls/Macro/Macro.cs +++ b/Crystallography.Controls/Macro/Macro.cs @@ -3,173 +3,166 @@ using System.Linq.Expressions; using System.Windows.Forms; -namespace Crystallography.Controls +namespace Crystallography.Controls; + +[Serializable()] +public class MacroTriger +{ + public bool Debug { set; get; } + public string Target { set; get; } + public string MacroName = ""; + public object[] Obj; + + public MacroTriger(string target, bool debug, object[] obj, string macroName = "") + { + Target = target; + Debug = debug; + Obj = obj; + MacroName = macroName; + } +} + +[Serializable()] +public class MacroBase +{ + public dynamic mainObject; + public string[] Help => help.ToArray(); + public string ScopeName = ""; + public List help = new(); + + public MacroBase(dynamic _main, string scopeName) + { + mainObject = _main; + ScopeName = scopeName; + } + + public void SetMacroToMenu(string[] name) + { + mainObject.SetMacroToMenu(name); + } +} + +[Serializable()] +public class MacroSub { - [Serializable()] - public class MacroTriger + private Control context; + + public MacroSub(Control _context) => context = _context; + + //スレッド間で安全にコントロールを操作する、関数群 + public Type Execute(Expression> expression) => Execute(context, expression.Compile(), null); + + public void Execute(Expression expression) => Execute(context, expression.Compile(), null); + + //public bool Execute(Func func) => Execute(func); + + //public string Execute(Func func) => Execute(func); + + //public string[] Execute(Func func) => Execute(func); + + // public double[] Execute(Func func) => Execute(func); + + //public int[] Execute(Func func) => Execute(func); + + //public int Execute(Func func) => Execute(func); + + //public double Execute(Func func) => Execute(func); + + public static Type Execute(Control _context, Delegate process) => Execute(_context, process, null); + + public Type Execute(Delegate process) => Execute(context, process, null); + + public static void Execute(Control _context, Delegate process) => Execute(_context, process, null); + + public void Execute(Delegate process) => Execute(context, process, null); + + public static Type Execute(Control _context, Delegate process, params object[] args) + { + #region + /*if (context == null) + { + throw new ArgumentNullException("context"); + } + if (process == null) + { + throw new ArgumentNullException("process"); + } + + if (!(context.IsHandleCreated)) + { + return null; + } + */ + #endregion + return _context.InvokeRequired ? (Type)_context.Invoke(process, args) : (Type)process.DynamicInvoke(args); + } + + public static void Execute(Control _context, Delegate process, params object[] args) { - public bool Debug { set; get; } - public string Target { set; get; } - public string MacroName = ""; - public object[] Obj; - - public MacroTriger(string target, bool debug, object[] obj, string macroName = "") - { - Target = target; - Debug = debug; - Obj = obj; - MacroName = macroName; - } + #region + /*if (context == null) + { + throw new ArgumentNullException("context"); + } + if (process == null) + { + throw new ArgumentNullException("process"); + } + + if (!(context.IsHandleCreated)) + { + return null; + } + */ + #endregion + if (_context.InvokeRequired) + _context.Invoke(process, args); + else + process.DynamicInvoke(args); } - [Serializable()] - public class MacroBase + public Type Execute(Delegate process, params object[] args) { - public dynamic mainObject; - public string[] Help { get { return help.ToArray(); } } - public string ScopeName = ""; - public List help = new List(); - - public MacroBase(dynamic _main, string scopeName) - { - mainObject = _main; - ScopeName = scopeName; - } - - public void SetMacroToMenu(string[] name) - { - mainObject.SetMacroToMenu(name); - } + #region + /*if (context == null) + { + throw new ArgumentNullException("context"); + } + if (process == null) + { + throw new ArgumentNullException("process"); + } + + if (!(context.IsHandleCreated)) + { + return null; + } + */ + #endregion + return context.InvokeRequired ? (Type)context.Invoke(process, args) : (Type)process.DynamicInvoke(args); } - [Serializable()] - public class MacroSub + public void Execute(Delegate process, params object[] args) { - private Control context; - - public MacroSub(Control _context) => context = _context; - - //スレッド間で安全にコントロールを操作する、関数群 - public Type Execute(Expression> expression) => Execute(context, expression.Compile(), null); - - public void Execute(Expression expression) => Execute(context, expression.Compile(), null); - - //public bool Execute(Func func) => Execute(func); - - //public string Execute(Func func) => Execute(func); - - //public string[] Execute(Func func) => Execute(func); - - // public double[] Execute(Func func) => Execute(func); - - //public int[] Execute(Func func) => Execute(func); - - //public int Execute(Func func) => Execute(func); - - //public double Execute(Func func) => Execute(func); - - public static Type Execute(Control _context, Delegate process) => Execute(_context, process, null); - - public Type Execute(Delegate process) => Execute(context, process, null); - - public void Execute(Control _context, Delegate process) => Execute(_context, process, null); - - public void Execute(Delegate process) => Execute(context, process, null); - - public static Type Execute(Control _context, Delegate process, params object[] args) - { - #region - /*if (context == null) - { - throw new ArgumentNullException("context"); - } - if (process == null) - { - throw new ArgumentNullException("process"); - } - - if (!(context.IsHandleCreated)) - { - return null; - } - */ - #endregion - if (_context.InvokeRequired) - return (Type)_context.Invoke(process, args); - else - return (Type)process.DynamicInvoke(args); - } - - public void Execute(Control _context, Delegate process, params object[] args) - { - #region - /*if (context == null) - { - throw new ArgumentNullException("context"); - } - if (process == null) - { - throw new ArgumentNullException("process"); - } - - if (!(context.IsHandleCreated)) - { - return null; - } - */ - #endregion - if (_context.InvokeRequired) - _context.Invoke(process, args); - else - process.DynamicInvoke(args); - } - - public Type Execute(Delegate process, params object[] args) - { - #region - /*if (context == null) - { - throw new ArgumentNullException("context"); - } - if (process == null) - { - throw new ArgumentNullException("process"); - } - - if (!(context.IsHandleCreated)) - { - return null; - } - */ - #endregion - if (context.InvokeRequired) - return (Type)context.Invoke(process, args); - else - return (Type)process.DynamicInvoke(args); - } - - public void Execute(Delegate process, params object[] args) - { - #region - /*if (context == null) - { - throw new ArgumentNullException("context"); - } - if (process == null) - { - throw new ArgumentNullException("process"); - } - - if (!(context.IsHandleCreated)) - { - return null; - } - */ - #endregion - if (context.InvokeRequired) - context.Invoke(process, args); - else - process.DynamicInvoke(args); - } + #region + /*if (context == null) + { + throw new ArgumentNullException("context"); + } + if (process == null) + { + throw new ArgumentNullException("process"); + } + + if (!(context.IsHandleCreated)) + { + return null; + } + */ + #endregion + if (context.InvokeRequired) + context.Invoke(process, args); + else + process.DynamicInvoke(args); } } \ No newline at end of file diff --git a/Crystallography.Controls/Numeric/NumericBox.cs b/Crystallography.Controls/Numeric/NumericBox.cs index 5d21f7e..db4a6e8 100644 --- a/Crystallography.Controls/Numeric/NumericBox.cs +++ b/Crystallography.Controls/Numeric/NumericBox.cs @@ -342,7 +342,7 @@ public int DecimalPlaces /// [DefaultValue(false)] [Category("Appearance properties")] - public bool ReadOnly { set => textBox.ReadOnly = value; get => textBox.ReadOnly; } + public bool ReadOnly { set { textBox.ReadOnly = value; numericUpDown.Enabled = !value; } get => textBox.ReadOnly; } /// /// s\邩ǂ @@ -572,7 +572,7 @@ internal string GetString() private static string separateThousands(string valueString) { - char decimalPoint = '.'; + var decimalPoint = '.'; if (valueString.Contains(',')) decimalPoint = ','; @@ -686,8 +686,5 @@ private void textBox_Leave(object sender, EventArgs e) } } - private void textBox_Enter(object sender, EventArgs e) - { - textBox.SelectAll(); - } + private void textBox_Enter(object sender, EventArgs e) => textBox.SelectAll(); } \ No newline at end of file diff --git a/Crystallography.Controls/ScalablePictureBox.cs b/Crystallography.Controls/ScalablePictureBox.cs index da8727f..dc114d1 100644 --- a/Crystallography.Controls/ScalablePictureBox.cs +++ b/Crystallography.Controls/ScalablePictureBox.cs @@ -3,642 +3,642 @@ using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; //using System.Linq; using System.Windows.Forms; -namespace Crystallography.Controls -{ - [Serializable] - public partial class ScalablePictureBox : UserControl - { - public bool SkipEvent = false; - public bool SkipDrawing = false; - public enum SymbolShape { Circle, Cross, Line, CircleAndCross }; - - #region Symbolクラス +namespace Crystallography.Controls; - [Serializable] - public class Symbol - { - public object Tag { get; set; } = null; +[Serializable] +public partial class ScalablePictureBox : UserControl +{ + public bool SkipEvent = false; + public bool SkipDrawing = false; + public enum SymbolShape { Circle, Cross, Line, CircleAndCross }; - public bool LabelVisible { get; set; } = true; - public bool SymbolVisible { get; set; } = true; + #region Symbolクラス - public SymbolShape Shape { get; set; } = SymbolShape.Cross; + [Serializable] + public class Symbol + { + public object Tag { get; set; } = null; - //Circleのオプション - public float CircleRadius { set; get; } + public bool LabelVisible { get; set; } = true; + public bool SymbolVisible { get; set; } = true; - public PointD CircleCenter { set; get; } - public Color CircleColor { get; set; } + public SymbolShape Shape { get; set; } = SymbolShape.Cross; - //Cross(ペケ印)のオプション - public PointD CrossPosition { set; get; } + //Circleのオプション + public float CircleRadius { set; get; } - public Color CrossColor1 { get; set; } = Color.Black; - public Color CrossColor2 { get; set; } = Color.Black; - public float CrossSize { get; set; } + public PointD CircleCenter { set; get; } + public Color CircleColor { get; set; } - //Lineのオプション - public PointD LinePosition1 { set; get; } + //Cross(ペケ印)のオプション + public PointD CrossPosition { set; get; } - public PointD LinePosition2 { set; get; } - public Color LineColor { get; set; } + public Color CrossColor1 { get; set; } = Color.Black; + public Color CrossColor2 { get; set; } = Color.Black; + public float CrossSize { get; set; } - //Labelのオプション - public bool Bold { get; set; } = false; + //Lineのオプション + public PointD LinePosition1 { set; get; } - public bool Italic { get; set; } = false; - public string Label { set; get; } = ""; + public PointD LinePosition2 { set; get; } + public Color LineColor { get; set; } - public Symbol() - { - } + //Labelのオプション + public bool Bold { get; set; } = false; - /// - /// Circleのコンストラクタ - /// - /// - /// - /// - /// - public Symbol(string label, PointD position, double radius, Color color) - { - Shape = SymbolShape.Circle; - Label = label; - CircleCenter = position; - CircleRadius = (float)radius; - CircleColor = color; - } + public bool Italic { get; set; } = false; + public string Label { set; get; } = ""; - public Symbol(string label, PointD position, double circleRadius, Color circleColor, double crossSize, Color crossColor1, Color crossColor2) - { - Shape = SymbolShape.CircleAndCross; - Label = label; - CircleCenter = position; - CircleRadius = (float)circleRadius; - CircleColor = circleColor; - CrossPosition = position; - CrossColor1 = crossColor1; - CrossColor2 = crossColor2; - CrossSize = (float)crossSize; - } - - - /// - /// Crossのコンストラクタ - /// - /// - /// - /// - /// - public Symbol(string label, PointD position, Color color1, Color color2, double size) - { - Shape = SymbolShape.Cross; - Label = label; - CrossPosition = position; - CrossColor1 = color1; - CrossColor2 = color2; - CrossSize = (float)size; - } - - /// - /// Lineのコンストラクタ - /// - /// - /// - /// - /// - public Symbol(string label, PointD position1, PointD position2, Color color) - { - Shape = SymbolShape.Line; - Label = label; - LinePosition1 = position1; - LinePosition2 = position2; - LineColor = color; - } - } - - #endregion Symbolクラス - - public ScalablePictureBox() + public Symbol() { - InitializeComponent(); - this.DoubleBuffered = true; - pictureBox.Location = new Point(0, 0); - pictureBox.ClientSize = this.Size; - pictureBox.MouseWheel += new MouseEventHandler(pictureBox_MouseWheel); - - vScrollBar.Width = 16; - hScrollBar.Height = 16; - pictureBox.Controls.Add(label); - label.BackColor = Color.Transparent; } - #region プロパティ - /// - /// VisualStudioデザイナーの編集の時はTrue + /// Circleのコンストラクタ /// - public new bool DesignMode + /// + /// + /// + /// + public Symbol(string label, PointD position, double radius, Color color) { - get - { - if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) - return true; - Control ctrl = this; - while (ctrl != null) - { - if (ctrl.Site != null && ctrl.Site.DesignMode) - return true; - ctrl = ctrl.Parent; - } - return false; - } + Shape = SymbolShape.Circle; + Label = label; + CircleCenter = position; + CircleRadius = (float)radius; + CircleColor = color; } - /// - /// 上下方向の反転をするかどうか - /// - public bool VerticalFlip + public Symbol(string label, PointD position, double circleRadius, Color circleColor, double crossSize, Color crossColor1, Color crossColor2) { - set { PseudoBitmap.VerticalFlip = value; drawPictureBox(); } - get { return PseudoBitmap.VerticalFlip; } + Shape = SymbolShape.CircleAndCross; + Label = label; + CircleCenter = position; + CircleRadius = (float)circleRadius; + CircleColor = circleColor; + CrossPosition = position; + CrossColor1 = crossColor1; + CrossColor2 = crossColor2; + CrossSize = (float)crossSize; } - private bool horizontalFlip = false; /// - /// 上下方向の反転をするかどうか + /// Crossのコンストラクタ /// - public bool HorizontalFlip + /// + /// + /// + /// + public Symbol(string label, PointD position, Color color1, Color color2, double size) { - set { PseudoBitmap.HorizontalFlip = value; drawPictureBox(); } - get { return PseudoBitmap.HorizontalFlip; } + Shape = SymbolShape.Cross; + Label = label; + CrossPosition = position; + CrossColor1 = color1; + CrossColor2 = color2; + CrossSize = (float)size; } - private double minZoom = 0.1f; - private readonly double maxZoom = 128f; - - private double _Zoom = 1; - /// - /// 表示倍率 + /// Lineのコンストラクタ /// - public double Zoom + /// + /// + /// + /// + public Symbol(string label, PointD position1, PointD position2, Color color) { - set - { - if (_Zoom != value) - { - _Zoom = Math.Min(maxZoom, Math.Max(minZoom, value));//閾値を超えないように - setControlLayout();//ズームに応じたコントロールをセッティングする - skipScrollBarEvent = true; - checkInvalidCenter();//center位置が適切かどうかチェックする - skipScrollBarEvent = false; + Shape = SymbolShape.Line; + Label = label; + LinePosition1 = position1; + LinePosition2 = position2; + LineColor = color; + } + } - drawPictureBox();//イメージを描画する + #endregion Symbolクラス - if (!SkipEvent) - DrawingAreaChanged?.Invoke(this, Zoom, Center); - } + public ScalablePictureBox() + { + InitializeComponent(); + this.DoubleBuffered = true; + pictureBox.Location = new Point(0, 0); + pictureBox.ClientSize = this.Size; + pictureBox.MouseWheel += new MouseEventHandler(pictureBox_MouseWheel); + + vScrollBar.Width = 16; + hScrollBar.Height = 16; + pictureBox.Controls.Add(label); + label.BackColor = Color.Transparent; + } + + #region プロパティ + + /// + /// VisualStudioデザイナーの編集の時はTrue + /// + public new bool DesignMode + { + get + { + if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) + return true; + Control ctrl = this; + while (ctrl != null) + { + if (ctrl.Site != null && ctrl.Site.DesignMode) + return true; + ctrl = ctrl.Parent; } - get { return _Zoom; } + return false; } + } - private PointD _Center = new(double.NaN, double.NaN); + /// + /// 上下方向の反転をするかどうか + /// + public bool VerticalFlip + { + set { PseudoBitmap.VerticalFlip = value; drawPictureBox(); } + get { return PseudoBitmap.VerticalFlip; } + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - /// - /// 中心ピクセル - /// - public PointD Center + private bool horizontalFlip = false; + + /// + /// 上下方向の反転をするかどうか + /// + public bool HorizontalFlip + { + set { PseudoBitmap.HorizontalFlip = value; drawPictureBox(); } + get { return PseudoBitmap.HorizontalFlip; } + } + + private double minZoom = 0.1f; + private readonly double maxZoom = 128f; + + private double _Zoom = 1; + + /// + /// 表示倍率 + /// + public double Zoom + { + set { - set + if (_Zoom != value) { - if (!value.IsNaN) - { - _Center = value; - if (hScrollBar == null || vScrollBar == null || _pseudoBitmap == null) return; - skipScrollBarEvent = true; - checkInvalidCenter();//center位置が適切かどうかチェックする - skipScrollBarEvent = false; - drawPictureBox();//イメージを描画する - if (!SkipEvent) - DrawingAreaChanged?.Invoke(this, Zoom, Center); - } + _Zoom = Math.Min(maxZoom, Math.Max(minZoom, value));//閾値を超えないように + setControlLayout();//ズームに応じたコントロールをセッティングする + skipScrollBarEvent = true; + checkInvalidCenter();//center位置が適切かどうかチェックする + skipScrollBarEvent = false; + + drawPictureBox();//イメージを描画する + + if (!SkipEvent) + DrawingAreaChanged?.Invoke(this, Zoom, Center); } - get => _Center.IsNaN ? new PointD(0, 0) : _Center; } + get { return _Zoom; } + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - private Vector3DBase zoomAndCenter = new(1, 0, 0); + private PointD _Center = new(double.NaN, double.NaN); - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public (double Zoom, PointD Center) ZoomAndCenter + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + /// + /// 中心ピクセル + /// + public PointD Center + { + set { - set + if (!value.IsNaN) { - if (FixZoomAndCenter) return; - skipScrollBarEvent = true; - _Zoom = Math.Min(maxZoom, Math.Max(minZoom, value.Zoom));//閾値を超えないように - _Center = new PointD(value.Center); + _Center = value; if (hScrollBar == null || vScrollBar == null || _pseudoBitmap == null) return; - setControlLayout();//ズームに応じたコントロールをセッティングする + skipScrollBarEvent = true; checkInvalidCenter();//center位置が適切かどうかチェックする skipScrollBarEvent = false; drawPictureBox();//イメージを描画する - - DrawingAreaChanged?.Invoke(this, Zoom, Center); + if (!SkipEvent) + DrawingAreaChanged?.Invoke(this, Zoom, Center); } - get { return (Zoom, new PointD(Center.X, Center.Y)); } } + get => _Center.IsNaN ? new PointD(0, 0) : _Center; + } - /// - /// ZoomやCenter位置を固定するかどうか - /// - public bool FixZoomAndCenter { get; set; } = false; + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + private Vector3DBase zoomAndCenter = new(1, 0, 0); - public Size CanvasSize { get { return pictureBox.ClientSize; } } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public (double Zoom, PointD Center) ZoomAndCenter + { + set + { + if (FixZoomAndCenter) return; + skipScrollBarEvent = true; + _Zoom = Math.Min(maxZoom, Math.Max(minZoom, value.Zoom));//閾値を超えないように + _Center = new PointD(value.Center); + if (hScrollBar == null || vScrollBar == null || _pseudoBitmap == null) return; + setControlLayout();//ズームに応じたコントロールをセッティングする + checkInvalidCenter();//center位置が適切かどうかチェックする + skipScrollBarEvent = false; + drawPictureBox();//イメージを描画する + + DrawingAreaChanged?.Invoke(this, Zoom, Center); + } + get { return (Zoom, new PointD(Center.X, Center.Y)); } + } - /// - /// フォーカスイベント(Enter)を有効にするかどうか - /// - public bool FocusEventEnabled { get; set; } = false; + /// + /// ZoomやCenter位置を固定するかどうか + /// + public bool FixZoomAndCenter { get; set; } = false; - private bool showFocusRectangle = false; + public Size CanvasSize { get { return pictureBox.ClientSize; } } - /// - /// 外枠を表示する - /// - public bool ShowRimRentangle + /// + /// フォーカスイベント(Enter)を有効にするかどうか + /// + public bool FocusEventEnabled { get; set; } = false; + + private bool showFocusRectangle = false; + + /// + /// 外枠を表示する + /// + public bool ShowRimRentangle + { + get => showFocusRectangle; + set { - get => showFocusRectangle; - set + if (showFocusRectangle != value) { - if (showFocusRectangle != value) - { - showFocusRectangle = value; - this.Refresh(); - } + showFocusRectangle = value; + this.Refresh(); } } + } - private bool showAreaRectangle = false; + private bool showAreaRectangle = false; - /// - /// AreaRectangleで指定した矩形を表示するかどうか - /// - public bool ShowAreaRectangle + /// + /// AreaRectangleで指定した矩形を表示するかどうか + /// + public bool ShowAreaRectangle + { + set { - set + if (showAreaRectangle != value) { - if (showAreaRectangle != value) - { - showAreaRectangle = value; - this.Refresh(); - } + showAreaRectangle = value; + this.Refresh(); } - get => showAreaRectangle; } + get => showAreaRectangle; + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - private RectangleD areaRentagle = new RectangleD(); - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public RectangleD AreaRectangle - { - set { areaRentagle = value; this.Refresh(); } - get => areaRentagle; - } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + private RectangleD areaRentagle = new RectangleD(); + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public RectangleD AreaRectangle + { + set { areaRentagle = value; this.Refresh(); } + get => areaRentagle; + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public List Symbols { set; get; } = new List(); + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public List Symbols { set; get; } = new List(); - /// - /// 左上に表示するテキスト - /// - public override string Text { get => label.Text; set => label.Text = value; } + /// + /// 左上に表示するテキスト + /// + public override string Text { get => label.Text; set => label.Text = value; } - /// - /// 左上に表示するテキストの色 - /// - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Color TextColor { get => label.ForeColor; set => label.ForeColor = value; } + /// + /// 左上に表示するテキストの色 + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Color TextColor { get => label.ForeColor; set => label.ForeColor = value; } - private PseudoBitmap _pseudoBitmap = new PseudoBitmap(); + private PseudoBitmap _pseudoBitmap = new PseudoBitmap(); - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public PseudoBitmap PseudoBitmap + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PseudoBitmap PseudoBitmap + { + set { - set + if (value != null) { - if (value != null) + if (value.Width * value.Height == 0) return; + _pseudoBitmap = value; + minZoom = Math.Min((double)(this.ClientSize.Width - 1) / _pseudoBitmap.Width, (double)(this.ClientSize.Height - 1) / _pseudoBitmap.Height); + if (!FixZoomAndCenter) { - if (value.Width * value.Height == 0) return; - _pseudoBitmap = value; - minZoom = Math.Min((double)(this.ClientSize.Width - 1) / _pseudoBitmap.Width, (double)(this.ClientSize.Height - 1) / _pseudoBitmap.Height); - if (!FixZoomAndCenter) - { - Zoom = minZoom; - Center = new PointD(value.Width / 2, value.Height / 2); - } - checkInvalidCenter(); + Zoom = minZoom; + Center = new PointD(value.Width / 2, value.Height / 2); } + checkInvalidCenter(); } - get { return _pseudoBitmap; } } + get { return _pseudoBitmap; } + } - /// - /// マウスによるスケーリングが可能かどうか - /// - public bool MouseScaling { set; get; }//マウスによるスケーリングが可能かどうか + /// + /// マウスによるスケーリングが可能かどうか + /// + public bool MouseScaling { set; get; }//マウスによるスケーリングが可能かどうか - /// - /// マウスによる平行移動が可能かどうか - /// - public bool MouseTranslation { set; get; } + /// + /// マウスによる平行移動が可能かどうか + /// + public bool MouseTranslation { set; get; } - private bool hScrollBarVisible = false; - private bool vScrollBarVisible = false; + private bool hScrollBarVisible = false; + private bool vScrollBarVisible = false; - /// - /// スクロールバーが表示されているかどうかを取得する。読み取り専用. - /// - public bool ScrollBarVisible => hScrollBar.Visible || vScrollBarVisible; + /// + /// クライアント領域の左上にタイトルを表示するか + /// + public bool TitleVisible { get; set; } = false; + public (string Text, Font Font, Color Color1, Color Color2) Title { get; set; } - /// - /// 現在のソース画像中の描画範囲 RectangleD を得る。読み取り専用. - /// - public RectangleD DrawingArea - { get { return PseudoBitmap.GetDrawingArea(Center, Zoom, pictureBox.ClientSize); } } + + #endregion プロパティ - #endregion プロパティ + /// + /// スクロールバーが表示されているかどうかを取得する。読み取り専用. + /// + public bool ScrollBarVisible => hScrollBar.Visible || vScrollBarVisible; - /// - /// centerの位置が適切かどうか(=はみ出していないか)チェックする - /// - /// - private void checkInvalidCenter() + /// + /// 現在のソース画像中の描画範囲 RectangleD を得る。読み取り専用. + /// + public RectangleD DrawingArea => PseudoBitmap.GetDrawingArea(Center, Zoom, pictureBox.ClientSize); + + + + /// + /// centerの位置が適切かどうか(=はみ出していないか)チェックする + /// + /// + private void checkInvalidCenter() + { + if (_Center.IsNaN) return; + if (hScrollBarVisible)//水平スクロールバーが出ているとき { - if (_Center.IsNaN) return; - if (hScrollBarVisible)//水平スクロールバーが出ているとき + if (!horizontalFlip) { - if (!horizontalFlip) - { - if (hScrollBar.Maximum - hScrollBar.LargeChange + 1 < _Center.X) - _Center.X = hScrollBar.Maximum - hScrollBar.LargeChange + 1; - else if (hScrollBar.Minimum > _Center.X) - _Center.X = hScrollBar.Minimum; - hScrollBar.Value = (int)_Center.X; - } - else - { - if (hScrollBar.Maximum - hScrollBar.LargeChange + 1 < hScrollBar.Maximum - hScrollBar.Minimum - _Center.X) - _Center.X = -hScrollBar.Minimum + hScrollBar.LargeChange - 1; - else if (hScrollBar.Minimum > hScrollBar.Maximum - hScrollBar.Minimum - _Center.X) - _Center.X = hScrollBar.Maximum - 2 * hScrollBar.Minimum; - hScrollBar.Value = (int)(hScrollBar.Maximum - hScrollBar.Minimum - _Center.X); - } + if (hScrollBar.Maximum - hScrollBar.LargeChange + 1 < _Center.X) + _Center.X = hScrollBar.Maximum - hScrollBar.LargeChange + 1; + else if (hScrollBar.Minimum > _Center.X) + _Center.X = hScrollBar.Minimum; + hScrollBar.Value = (int)_Center.X; } else - _Center.X = (int)(PseudoBitmap.Width / 2.0 + 0.5); - - if (vScrollBarVisible)//垂直するロールバーが出ているとき { - if (!VerticalFlip) - { - if (vScrollBar.Maximum - vScrollBar.LargeChange + 1 < _Center.Y) - _Center.Y = vScrollBar.Maximum - vScrollBar.LargeChange + 1; - else if (vScrollBar.Minimum > _Center.Y) - _Center.Y = vScrollBar.Minimum; - - vScrollBar.Value = (int)_Center.Y; - } - else - { - if (vScrollBar.Maximum - vScrollBar.LargeChange < vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y) - _Center.Y = -vScrollBar.Minimum + vScrollBar.LargeChange - 1; - else if (vScrollBar.Minimum > vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y) - _Center.Y = vScrollBar.Maximum - 2 * vScrollBar.Minimum; - - vScrollBar.Value = (int)(vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y); - } + if (hScrollBar.Maximum - hScrollBar.LargeChange + 1 < hScrollBar.Maximum - hScrollBar.Minimum - _Center.X) + _Center.X = -hScrollBar.Minimum + hScrollBar.LargeChange - 1; + else if (hScrollBar.Minimum > hScrollBar.Maximum - hScrollBar.Minimum - _Center.X) + _Center.X = hScrollBar.Maximum - 2 * hScrollBar.Minimum; + hScrollBar.Value = (int)(hScrollBar.Maximum - hScrollBar.Minimum - _Center.X); } - else - _Center.Y = (int)(PseudoBitmap.Height / 2.0 + 0.5); } + else + _Center.X = (int)(PseudoBitmap.Width / 2.0 + 0.5); - public void drawPictureBox() + if (vScrollBarVisible)//垂直するロールバーが出ているとき { - if (SkipEvent || SkipDrawing) - return; - - - if (PseudoBitmap != null) + if (!VerticalFlip) { - if (hScrollBarVisible != hScrollBar.Visible) hScrollBar.Visible = hScrollBarVisible; - if (vScrollBarVisible != vScrollBar.Visible) vScrollBar.Visible = vScrollBarVisible; - } + if (vScrollBar.Maximum - vScrollBar.LargeChange + 1 < _Center.Y) + _Center.Y = vScrollBar.Maximum - vScrollBar.LargeChange + 1; + else if (vScrollBar.Minimum > _Center.Y) + _Center.Y = vScrollBar.Minimum; - if (Draw != null)//Drawイベントを発生 このときは自前で描画せず、通知先に任せる。 - { - Draw(); - this.Refresh(); - return; + vScrollBar.Value = (int)_Center.Y; } + else + { + if (vScrollBar.Maximum - vScrollBar.LargeChange < vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y) + _Center.Y = -vScrollBar.Minimum + vScrollBar.LargeChange - 1; + else if (vScrollBar.Minimum > vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y) + _Center.Y = vScrollBar.Maximum - 2 * vScrollBar.Minimum; - if (PseudoBitmap == null || pictureBox.Size.Width == 0 || pictureBox.Size.Height == 0 || Center.IsNaN) - return; - pictureBox.Image = PseudoBitmap.GetImage(Center, Zoom, pictureBox.ClientSize); - //if(pictureBox.Image !=null) - // justBeforeImage = new Bitmap(pictureBox.Image); + vScrollBar.Value = (int)(vScrollBar.Maximum - vScrollBar.Minimum - _Center.Y); + } + } + else + _Center.Y = (int)(PseudoBitmap.Height / 2.0 + 0.5); + } - //if(showAreaRectangle) - // DrawAreaRectangle(); + public void drawPictureBox() + { + if (SkipEvent || SkipDrawing) + return; - this.Refresh(); - } - public static void DrawAreaRectangle() + if (PseudoBitmap != null) { - //if (justBeforeImage == null) - // justBeforeImage = PseudoBitmap.GetImage(Center, Zoom, pictureBox.ClientSize); - //if (showAreaRectangle) - /*{ - Graphics g = Graphics.FromImage(justBeforeImage); - Pen pen = new Pen(Brushes.Yellow); - RectangleF rect = ConvertToClientRect(areaRentagle).ToRectangleF(); - g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); - } - else - pictureBox.Image = justBeforeImage; - */ + if (hScrollBarVisible != hScrollBar.Visible) hScrollBar.Visible = hScrollBarVisible; + if (vScrollBarVisible != vScrollBar.Visible) vScrollBar.Visible = vScrollBarVisible; } - private void pictureBox_MouseWheel(object sender, MouseEventArgs e) + if (Draw != null)//Drawイベントを発生 このときは自前で描画せず、通知先に任せる。 { - if (MouseWheel2 != null && MouseWheel2(this, e, ConvertToSrcPt(e.Location))) - return; - - if (e.Delta > 0 && MouseScaling) - {//縮小モード - _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 - Zoom *= 0.5f; - } - else if (e.Delta < 0 && MouseScaling) - {//拡大モード - _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 - Zoom *= 2f; - } + Draw(); + this.Refresh(); + return; } - private Point justBeforePoint; + if (PseudoBitmap == null || pictureBox.Size.Width == 0 || pictureBox.Size.Height == 0 || Center.IsNaN) + return; + pictureBox.Image = PseudoBitmap.GetImage(Center, Zoom, pictureBox.ClientSize); + //if(pictureBox.Image !=null) + // justBeforeImage = new Bitmap(pictureBox.Image); - private void pictureBox_MouseDown(object sender, MouseEventArgs e) - { - pictureBox.Focus(); + //if(showAreaRectangle) + // DrawAreaRectangle(); - if (MouseDown2 != null && MouseDown2(this, e, ConvertToSrcPt(e.Location))) - return; + this.Refresh(); + } - if (e.Button == MouseButtons.Right && e.Clicks == 1 && MouseScaling) - { - MouseRangeMode = true; - mouseRangeStart = e.Location; - } - else if (e.Button == MouseButtons.Right && e.Clicks == 2 && MouseScaling) - { - _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 - Zoom *= 0.5f; - } - else if (e.Button == MouseButtons.Left && e.Clicks == 1) - { - justBeforePoint = e.Location; - } + #region マウスイベント + private void pictureBox_MouseWheel(object sender, MouseEventArgs e) + { + if (MouseWheel2 != null && MouseWheel2(this, e, ConvertToSrcPt(e.Location))) + return; + + if (e.Delta > 0 && MouseScaling) + {//縮小モード + _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 + Zoom *= 0.5f; } + else if (e.Delta < 0 && MouseScaling) + {//拡大モード + _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 + Zoom *= 2f; + } + } + + private Point justBeforePoint; - private bool manualSpotMode = false; + private void pictureBox_MouseDown(object sender, MouseEventArgs e) + { + pictureBox.Focus(); + + if (MouseDown2 != null && MouseDown2(this, e, ConvertToSrcPt(e.Location))) + return; - public bool ManualSpotMode + if (e.Button == MouseButtons.Right && e.Clicks == 1 && MouseScaling) + { + MouseRangeMode = true; + mouseRangeStart = e.Location; + } + else if (e.Button == MouseButtons.Right && e.Clicks == 2 && MouseScaling) + { + _Center = ConvertToSrcPt(e.Location);//イベントを起こさないように小文字のcenterに代入 + Zoom *= 0.5f; + } + else if (e.Button == MouseButtons.Left && e.Clicks == 1) { - set { manualSpotMode = value; if (manualSpotMode) MouseRangeMode = false; } - get { return manualSpotMode; } + justBeforePoint = e.Location; } + } + - public bool MouseRangeMode = false; - private Point mouseRangeStart, mouseRangeEnd; + private bool manualSpotMode = false; - private void pictureBox_MouseMove(object sender, MouseEventArgs e) - { - if (MouseMove2 != null && MouseMove2(this, e, ConvertToSrcPt(e.Location))) - return; + public bool ManualSpotMode + { + set { manualSpotMode = value; if (manualSpotMode) MouseRangeMode = false; } + get { return manualSpotMode; } + } - if (MouseRangeMode) - { - mouseRangeEnd = e.Location; - pictureBox.Refresh(); - } - else if (e.Button == MouseButtons.Left && MouseTranslation && justBeforePoint != e.Location) - { - Center = new PointD(Center.X + (justBeforePoint.X - e.Location.X) / Zoom, Center.Y + (justBeforePoint.Y - e.Location.Y) / Zoom); - justBeforePoint = e.Location; - } - } + public bool MouseRangeMode = false; + private Point mouseRangeStart, mouseRangeEnd; + + private void pictureBox_MouseMove(object sender, MouseEventArgs e) + { + if (MouseMove2 != null && MouseMove2(this, e, ConvertToSrcPt(e.Location))) + return; - private void pictureBox_MouseUp(object sender, MouseEventArgs e) + if (MouseRangeMode) { - if (MouseUp2 != null && MouseUp2(this, e, ConvertToSrcPt(e.Location))) - return; + mouseRangeEnd = e.Location; + pictureBox.Refresh(); + } + else if (e.Button == MouseButtons.Left && MouseTranslation && justBeforePoint != e.Location) + { + Center = new PointD(Center.X + (justBeforePoint.X - e.Location.X) / Zoom, Center.Y + (justBeforePoint.Y - e.Location.Y) / Zoom); + justBeforePoint = e.Location; + } + } - if (MouseRangeMode && MouseScaling) + private void pictureBox_MouseUp(object sender, MouseEventArgs e) + { + if (MouseUp2 != null && MouseUp2(this, e, ConvertToSrcPt(e.Location))) + return; + + if (MouseRangeMode && MouseScaling) + { + MouseRangeMode = false; + mouseRangeEnd = e.Location; + if ((Control.ModifierKeys & Keys.Control) != Keys.Control)//CTRLキーが押されていない場合 { - MouseRangeMode = false; - mouseRangeEnd = e.Location; - if ((Control.ModifierKeys & Keys.Control) != Keys.Control)//CTRLキーが押されていない場合 - { - if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) < 3 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) < 3) - {//縮小モード - PointD start = ConvertToSrcPt(mouseRangeStart); - PointD end = ConvertToSrcPt(mouseRangeEnd); - _Center = new PointD((start.X + end.X) / 2.0, (start.Y + end.Y) / 2.0);//イベントを起こさないように小文字のcenterに代入 - Zoom *= 0.5f; - } - else if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) > 10 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) > 10) - {//拡大モード - PointD start = ConvertToSrcPt(mouseRangeStart); - PointD end = ConvertToSrcPt(mouseRangeEnd); - _Center = new PointD((start.X + end.X) / 2.0, (start.Y + end.Y) / 2.0 + 0.5);//イベントを起こさないように小文字のcenterに代入 - Zoom = ((float)pictureBox.Width / Math.Abs(start.X - end.X) + (float)pictureBox.Height / Math.Abs(start.Y - end.Y)) / 2.0f; - } - else - pictureBox.Refresh(); - return; + if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) < 3 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) < 3) + {//縮小モード + PointD start = ConvertToSrcPt(mouseRangeStart); + PointD end = ConvertToSrcPt(mouseRangeEnd); + _Center = new PointD((start.X + end.X) / 2.0, (start.Y + end.Y) / 2.0);//イベントを起こさないように小文字のcenterに代入 + Zoom *= 0.5f; } - else//コントロールキーが押されていた場合 - { - ShowAreaRectangle = false; - if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) > 10 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) > 10) - { - ShowAreaRectangle = true; - var start = ConvertToSrcPt(mouseRangeStart); - var end = ConvertToSrcPt(mouseRangeEnd); - AreaRectangle = new RectangleD(start, end); - MouseUp2?.Invoke(this, e, ConvertToSrcPt(e.Location)); - } + else if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) > 10 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) > 10) + {//拡大モード + PointD start = ConvertToSrcPt(mouseRangeStart); + PointD end = ConvertToSrcPt(mouseRangeEnd); + _Center = new PointD((start.X + end.X) / 2.0, (start.Y + end.Y) / 2.0 + 0.5);//イベントを起こさないように小文字のcenterに代入 + Zoom = ((float)pictureBox.Width / Math.Abs(start.X - end.X) + (float)pictureBox.Height / Math.Abs(start.Y - end.Y)) / 2.0f; + } + else pictureBox.Refresh(); - return; + return; + } + else//コントロールキーが押されていた場合 + { + ShowAreaRectangle = false; + if (Math.Abs(mouseRangeStart.X - mouseRangeEnd.X) > 10 && Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y) > 10) + { + ShowAreaRectangle = true; + var start = ConvertToSrcPt(mouseRangeStart); + var end = ConvertToSrcPt(mouseRangeEnd); + AreaRectangle = new RectangleD(start, end); + MouseUp2?.Invoke(this, e, ConvertToSrcPt(e.Location)); } + pictureBox.Refresh(); + return; } } + } - private void pictureBox_MouseLeave(object sender, EventArgs e) - { - //drawPictureBox(); - } + private void pictureBox_MouseLeave(object sender, EventArgs e) + { + //drawPictureBox(); + } - /// - /// PictureBoxのPaintイベント - /// - public event PaintEventHandler Paint2; + #endregion - private void pictureBox_Paint(object sender, PaintEventArgs e) - { - Paint2?.Invoke(this, e); + /// + /// PictureBoxのPaintイベント + /// + public event PaintEventHandler Paint2; + private void pictureBox_Paint(object sender, PaintEventArgs e) + { + Paint2?.Invoke(this, e); + var g = e.Graphics; - e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; + g.SmoothingMode = SmoothingMode.AntiAlias; - if (MouseRangeMode) - { - var pen = new Pen(Brushes.Pink); - if ((ModifierKeys & Keys.Control) == Keys.Control) - pen = new Pen(Brushes.Yellow); - pen.DashStyle = DashStyle.Dash; - e.Graphics.DrawRectangle(pen, Math.Min(mouseRangeStart.X, mouseRangeEnd.X), Math.Min(mouseRangeStart.Y, mouseRangeEnd.Y), - Math.Abs(mouseRangeStart.X - mouseRangeEnd.X), Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y)); - } - if (showFocusRectangle) - { - Brush b = new HatchBrush(HatchStyle.Percent10, Color.Green, Color.Transparent); - e.Graphics.FillRectangle(b, pictureBox.ClientRectangle); - } - if (ShowAreaRectangle) - { - var pen = new Pen(Brushes.Yellow); - var rect = ConvertToClientRect(areaRentagle).ToRectangleF(); - e.Graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); - } + if (MouseRangeMode) + { + var pen = new Pen(Brushes.Pink); + if ((ModifierKeys & Keys.Control) == Keys.Control) + pen = new Pen(Brushes.Yellow); + pen.DashStyle = DashStyle.Dash; + g.DrawRectangle(pen, Math.Min(mouseRangeStart.X, mouseRangeEnd.X), Math.Min(mouseRangeStart.Y, mouseRangeEnd.Y), + Math.Abs(mouseRangeStart.X - mouseRangeEnd.X), Math.Abs(mouseRangeStart.Y - mouseRangeEnd.Y)); + } + if (showFocusRectangle) + { + Brush b = new HatchBrush(HatchStyle.Percent10, Color.Green, Color.Transparent); + g.FillRectangle(b, pictureBox.ClientRectangle); + } + if (ShowAreaRectangle) + { + var pen = new Pen(Brushes.Yellow); + var rect = ConvertToClientRect(areaRentagle).ToRectangleF(); + g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); + } - //drawSymbols(e) - if (!this.DesignMode && Symbols != null) + //drawSymbols(e) + if (!DesignMode) + { + if (Symbols != null) foreach (var s in Symbols) { if (s.SymbolVisible) { - FontFamily ff = new FontFamily("Arial"); + var ff = new FontFamily("Arial"); if (s.Shape == SymbolShape.Cross || s.Shape == SymbolShape.CircleAndCross) { Pen pen1 = new(new SolidBrush(s.CrossColor1)), pen2 = new(new SolidBrush(s.CrossColor2)); @@ -646,13 +646,13 @@ private void pictureBox_Paint(object sender, PaintEventArgs e) var pt = ConvertToClientPt(s.CrossPosition).ToPointF(); if (pt.X > -pictureBox.ClientSize.Width && pt.X < 2 * pictureBox.ClientSize.Width && pt.Y > -pictureBox.ClientSize.Height && pt.Y < 2 * pictureBox.ClientSize.Height) { - e.Graphics.DrawLine(pen2, new PointF(pt.X - s.CrossSize + 1, pt.Y - s.CrossSize - 1), new PointF(pt.X + s.CrossSize + 1, pt.Y + s.CrossSize - 1)); - e.Graphics.DrawLine(pen2, new PointF(pt.X - s.CrossSize - 1, pt.Y - s.CrossSize + 1), new PointF(pt.X + s.CrossSize - 1, pt.Y + s.CrossSize + 1)); - e.Graphics.DrawLine(pen2, new PointF(pt.X + s.CrossSize - 1, pt.Y - s.CrossSize - 1), new PointF(pt.X - s.CrossSize - 1, pt.Y + s.CrossSize - 1)); - e.Graphics.DrawLine(pen2, new PointF(pt.X + s.CrossSize + 1, pt.Y - s.CrossSize + 1), new PointF(pt.X - s.CrossSize + 1, pt.Y + s.CrossSize + 1)); + g.DrawLine(pen2, new PointF(pt.X - s.CrossSize + 1, pt.Y - s.CrossSize - 1), new PointF(pt.X + s.CrossSize + 1, pt.Y + s.CrossSize - 1)); + g.DrawLine(pen2, new PointF(pt.X - s.CrossSize - 1, pt.Y - s.CrossSize + 1), new PointF(pt.X + s.CrossSize - 1, pt.Y + s.CrossSize + 1)); + g.DrawLine(pen2, new PointF(pt.X + s.CrossSize - 1, pt.Y - s.CrossSize - 1), new PointF(pt.X - s.CrossSize - 1, pt.Y + s.CrossSize - 1)); + g.DrawLine(pen2, new PointF(pt.X + s.CrossSize + 1, pt.Y - s.CrossSize + 1), new PointF(pt.X - s.CrossSize + 1, pt.Y + s.CrossSize + 1)); - e.Graphics.DrawLine(pen1, new PointF(pt.X - s.CrossSize, pt.Y - s.CrossSize), new PointF(pt.X + s.CrossSize, pt.Y + s.CrossSize)); - e.Graphics.DrawLine(pen1, new PointF(pt.X + s.CrossSize, pt.Y - s.CrossSize), new PointF(pt.X - s.CrossSize, pt.Y + s.CrossSize)); + g.DrawLine(pen1, new PointF(pt.X - s.CrossSize, pt.Y - s.CrossSize), new PointF(pt.X + s.CrossSize, pt.Y + s.CrossSize)); + g.DrawLine(pen1, new PointF(pt.X + s.CrossSize, pt.Y - s.CrossSize), new PointF(pt.X - s.CrossSize, pt.Y + s.CrossSize)); pen1.Width = pen2.Width = 1f; if (s.LabelVisible) { @@ -661,13 +661,13 @@ private void pictureBox_Paint(object sender, PaintEventArgs e) if (s.Bold) { - e.Graphics.FillPath(new SolidBrush(s.CrossColor2), gp); - e.Graphics.DrawPath(pen1, gp); + g.FillPath(new SolidBrush(s.CrossColor2), gp); + g.DrawPath(pen1, gp); } else { - e.Graphics.FillPath(new SolidBrush(s.CrossColor1), gp); - e.Graphics.DrawPath(pen2, gp); + g.FillPath(new SolidBrush(s.CrossColor1), gp); + g.DrawPath(pen2, gp); } } } @@ -680,7 +680,7 @@ private void pictureBox_Paint(object sender, PaintEventArgs e) if (pt.X > -pictureBox.ClientSize.Width && pt.X < 2 * pictureBox.ClientSize.Width && pt.Y > -pictureBox.ClientSize.Height && pt.Y < 2 * pictureBox.ClientSize.Height) { var rect = ConvertToClientRect(new RectangleD(s.CircleCenter.X - s.CircleRadius, s.CircleCenter.Y - s.CircleRadius, s.CircleRadius * 2, s.CircleRadius * 2)).ToRectangleF(); - e.Graphics.DrawEllipse(pen1, rect); + g.DrawEllipse(pen1, rect); } } if (s.Shape == SymbolShape.Line) @@ -690,332 +690,412 @@ private void pictureBox_Paint(object sender, PaintEventArgs e) var pt2 = ConvertToClientPt(s.LinePosition2).ToPointF(); if (pt1.X > -pictureBox.ClientSize.Width && pt1.X < 2 * pictureBox.ClientSize.Width && pt1.Y > -pictureBox.ClientSize.Height && pt1.Y < 2 * pictureBox.ClientSize.Height) { - e.Graphics.DrawLine(pen1, pt1, pt2); + g.DrawLine(pen1, pt1, pt2); } } } } - /* - if (ShowSpots1) - drawSpots(e, Spots1, Spots1Label,Brushes.Pink, Brushes.DarkRed, ShowSpots1Label, EmphasizeNumberOfSpots1); - if (ShowSpots2) - drawSpots(e, Spots2, Spots2Label, Brushes.LightBlue, Brushes.DarkBlue, ShowSpots2Label, EmphasizeNumberOfSpots2); + if (TitleVisible) + { + var ff = Title.Font.FontFamily; + var gp = new GraphicsPath(); + gp.AddString(Title.Text, ff, (int)FontStyle.Bold, Title.Font.Size, new PointF(0, 0), StringFormat.GenericDefault); + + g.FillPath(new SolidBrush(Title.Color1), gp); + g.DrawPath(new Pen(Title.Color2, 1f), gp); + - if (ShowSpots3) - drawSpots(e, Spots3, Spots3Label, Brushes.LightGreen, Brushes.DarkGreen, ShowSpots3Label, EmphasizeNumberOfSpots3); - */ + //g.DrawString(Title.Text, Title.Font, Title.Brush, new Point(0, 0)); + } } + /* + if (ShowSpots1) + drawSpots(e, Spots1, Spots1Label,Brushes.Pink, Brushes.DarkRed, ShowSpots1Label, EmphasizeNumberOfSpots1); - private void drawSymbols(PaintEventArgs e, List spot, List spotLabel, Brush brush1, Brush brush2, bool showLabel, int? emphasizeNum) - { - var gp = new GraphicsPath(); - FontFamily ff = new FontFamily("Arial"); - Pen pen1 = new(brush1), pen2 = new(brush2); - if (spot != null && spot.Count > 0) - for (int i = 0; i < spot.Count; i++) - { - pen1.Width = pen2.Width = i == emphasizeNum ? 2f : 1f; + if (ShowSpots2) + drawSpots(e, Spots2, Spots2Label, Brushes.LightBlue, Brushes.DarkBlue, ShowSpots2Label, EmphasizeNumberOfSpots2); - PointF pt = ConvertToClientPt(spot[i]).ToPointF(); + if (ShowSpots3) + drawSpots(e, Spots3, Spots3Label, Brushes.LightGreen, Brushes.DarkGreen, ShowSpots3Label, EmphasizeNumberOfSpots3); + */ - e.Graphics.DrawLine(pen2, new PointF(pt.X - 4, pt.Y - 6), new PointF(pt.X + 6, pt.Y + 4)); - e.Graphics.DrawLine(pen2, new PointF(pt.X - 6, pt.Y - 4), new PointF(pt.X + 4, pt.Y + 6)); - e.Graphics.DrawLine(pen2, new PointF(pt.X + 4, pt.Y - 6), new PointF(pt.X - 6, pt.Y + 4)); - e.Graphics.DrawLine(pen2, new PointF(pt.X + 6, pt.Y - 4), new PointF(pt.X - 4, pt.Y + 6)); + } - e.Graphics.DrawLine(pen1, new PointF(pt.X - 5, pt.Y - 5), new PointF(pt.X + 5, pt.Y + 5)); - e.Graphics.DrawLine(pen1, new PointF(pt.X + 5, pt.Y - 5), new PointF(pt.X - 5, pt.Y + 5)); - pen1.Width = pen2.Width = 1f; - if (showLabel) - { - gp = new GraphicsPath(); - string label = spotLabel == null || spotLabel.Count != spot.Count ? i.ToString("000") : spotLabel[i]; - gp.AddString(label, ff, (int)FontStyle.Bold, i == emphasizeNum ? 18f : 16f, new PointF(pt.X + 5, pt.Y + 5), StringFormat.GenericDefault); + private void drawSymbols(PaintEventArgs e, List spot, List spotLabel, Brush brush1, Brush brush2, bool showLabel, int? emphasizeNum) + { + var gp = new GraphicsPath(); + FontFamily ff = new FontFamily("Arial"); + Pen pen1 = new(brush1), pen2 = new(brush2); + if (spot != null && spot.Count > 0) + for (int i = 0; i < spot.Count; i++) + { + pen1.Width = pen2.Width = i == emphasizeNum ? 2f : 1f; - if (i == emphasizeNum) - { - e.Graphics.FillPath(brush2, gp); - e.Graphics.DrawPath(pen1, gp); - } - else - { - e.Graphics.FillPath(brush1, gp); - e.Graphics.DrawPath(pen2, gp); - } + PointF pt = ConvertToClientPt(spot[i]).ToPointF(); + + e.Graphics.DrawLine(pen2, new PointF(pt.X - 4, pt.Y - 6), new PointF(pt.X + 6, pt.Y + 4)); + e.Graphics.DrawLine(pen2, new PointF(pt.X - 6, pt.Y - 4), new PointF(pt.X + 4, pt.Y + 6)); + e.Graphics.DrawLine(pen2, new PointF(pt.X + 4, pt.Y - 6), new PointF(pt.X - 6, pt.Y + 4)); + e.Graphics.DrawLine(pen2, new PointF(pt.X + 6, pt.Y - 4), new PointF(pt.X - 4, pt.Y + 6)); + + e.Graphics.DrawLine(pen1, new PointF(pt.X - 5, pt.Y - 5), new PointF(pt.X + 5, pt.Y + 5)); + e.Graphics.DrawLine(pen1, new PointF(pt.X + 5, pt.Y - 5), new PointF(pt.X - 5, pt.Y + 5)); + pen1.Width = pen2.Width = 1f; + if (showLabel) + { + gp = new GraphicsPath(); + string label = spotLabel == null || spotLabel.Count != spot.Count ? i.ToString("000") : spotLabel[i]; + gp.AddString(label, ff, (int)FontStyle.Bold, i == emphasizeNum ? 18f : 16f, new PointF(pt.X + 5, pt.Y + 5), StringFormat.GenericDefault); + + if (i == emphasizeNum) + { + e.Graphics.FillPath(brush2, gp); + e.Graphics.DrawPath(pen1, gp); + } + else + { + e.Graphics.FillPath(brush1, gp); + e.Graphics.DrawPath(pen2, gp); } } - } + } + } - /// /// - /// コントロール全体のペイントイベント - /// - public event PaintEventHandler PaintControl; + /// /// + /// コントロール全体のペイントイベント + /// + public event PaintEventHandler PaintControl; - private void ScalablePictureBox_Paint(object sender, PaintEventArgs e) - { - PaintControl?.Invoke(sender, e); - } + private void ScalablePictureBox_Paint(object sender, PaintEventArgs e) + { + PaintControl?.Invoke(sender, e); + } - /// - /// コントロール全体がリサイズされたとき - /// - /// - /// - private void ScalablePictureBox_Resize(object sender, EventArgs e) + /// + /// コントロール全体がリサイズされたとき + /// + /// + /// + private void ScalablePictureBox_Resize(object sender, EventArgs e) + { + if (PseudoBitmap != null)//イメージが存在するときは { - if (PseudoBitmap != null)//イメージが存在するときは - { - ResetMinimumZoomValue(); - if (Zoom < minZoom) - Zoom = minZoom; - setControlLayout(); - drawPictureBox(); - } + ResetMinimumZoomValue(); + if (Zoom < minZoom) + Zoom = minZoom; + setControlLayout(); + drawPictureBox(); } + } - public void ResetMinimumZoomValue() - { - minZoom = Math.Min((double)(this.ClientSize.Width - 1) / PseudoBitmap.Width, (double)(this.ClientSize.Height - 1) / PseudoBitmap.Height); - } + public void ResetMinimumZoomValue() + { + minZoom = Math.Min((double)(this.ClientSize.Width - 1) / PseudoBitmap.Width, (double)(this.ClientSize.Height - 1) / PseudoBitmap.Height); + } - #region イベント + #region イベント - /// - /// マウスイベント用のデリゲート - /// - /// sender - /// e - /// ソース画像座標 - /// その後のイベントをキャンセルする場合: true - public delegate bool MouseEvent(object sender, MouseEventArgs e, PointD pt); + /// + /// マウスイベント用のデリゲート + /// + /// sender + /// e + /// ソース画像座標 + /// その後のイベントをキャンセルする場合: true + public delegate bool MouseEvent(object sender, MouseEventArgs e, PointD pt); - public event MouseEvent MouseMove2; + public event MouseEvent MouseMove2; - public event MouseEvent MouseUp2; + public event MouseEvent MouseUp2; - public event MouseEvent MouseDown2; + public event MouseEvent MouseDown2; - public event MouseEvent MouseWheel2; + public event MouseEvent MouseWheel2; - public delegate void DrawEvent(); + public delegate void DrawEvent(); - public event DrawEvent Draw; + public event DrawEvent Draw; - public delegate void DrawingAreaChangedEvent(object sender, double zoom, PointD center); + public delegate void DrawingAreaChangedEvent(object sender, double zoom, PointD center); - public event DrawingAreaChangedEvent DrawingAreaChanged; + public event DrawingAreaChangedEvent DrawingAreaChanged; - #endregion イベント + #endregion イベント - /// - /// 初期化直後、画面リサイズ後、Zoom変更後にPictureBox,ScrollBarコントロールなどを適切に配置するメソッド - /// - private void setControlLayout() - { - hScrollBar.Location = new Point(0, this.ClientSize.Height - hScrollBar.Height); - hScrollBar.Size = new Size(this.ClientSize.Width - vScrollBar.Width, hScrollBar.Height); + /// + /// 初期化直後、画面リサイズ後、Zoom変更後にPictureBox,ScrollBarコントロールなどを適切に配置するメソッド + /// + private void setControlLayout() + { + hScrollBar.Location = new Point(0, this.ClientSize.Height - hScrollBar.Height); + hScrollBar.Size = new Size(this.ClientSize.Width - vScrollBar.Width, hScrollBar.Height); - vScrollBar.Location = new Point(this.ClientSize.Width - vScrollBar.Width, 0); - vScrollBar.Size = new Size(vScrollBar.Width, this.ClientSize.Height - hScrollBar.Height); + vScrollBar.Location = new Point(this.ClientSize.Width - vScrollBar.Width, 0); + vScrollBar.Size = new Size(vScrollBar.Width, this.ClientSize.Height - hScrollBar.Height); - if (this.ClientSize.Width <= 0 || this.ClientSize.Height <= 0) return; - //クライアントサイズ内に収まる時 - if (this.ClientSize.Width >= PseudoBitmap.Width * _Zoom && this.ClientSize.Height >= PseudoBitmap.Height * _Zoom) - { - hScrollBarVisible = vScrollBarVisible = false; - pictureBox.Location = new Point((int)((this.ClientSize.Width - PseudoBitmap.Width * _Zoom) / 2.0), (int)((this.ClientSize.Height - PseudoBitmap.Height * _Zoom) / 2.0)); - pictureBox.Width = (int)(PseudoBitmap.Width * _Zoom); - pictureBox.Height = (int)(PseudoBitmap.Height * _Zoom); - } - //横スクロールだけ出すとき - else if (this.ClientSize.Width <= PseudoBitmap.Width * _Zoom && this.ClientSize.Height - hScrollBar.Height > PseudoBitmap.Height * _Zoom) - { - hScrollBarVisible = true; - vScrollBarVisible = false; + if (this.ClientSize.Width <= 0 || this.ClientSize.Height <= 0) return; + //クライアントサイズ内に収まる時 + if (this.ClientSize.Width >= PseudoBitmap.Width * _Zoom && this.ClientSize.Height >= PseudoBitmap.Height * _Zoom) + { + hScrollBarVisible = vScrollBarVisible = false; + pictureBox.Location = new Point((int)((this.ClientSize.Width - PseudoBitmap.Width * _Zoom) / 2.0), (int)((this.ClientSize.Height - PseudoBitmap.Height * _Zoom) / 2.0)); + pictureBox.Width = (int)(PseudoBitmap.Width * _Zoom); + pictureBox.Height = (int)(PseudoBitmap.Height * _Zoom); + } + //横スクロールだけ出すとき + else if (this.ClientSize.Width <= PseudoBitmap.Width * _Zoom && this.ClientSize.Height - hScrollBar.Height > PseudoBitmap.Height * _Zoom) + { + hScrollBarVisible = true; + vScrollBarVisible = false; - pictureBox.Location = new Point(0, (int)((this.ClientSize.Height - hScrollBar.Height - PseudoBitmap.Height * _Zoom) / 2.0 + 0.5)); - pictureBox.Width = this.ClientSize.Width; - pictureBox.Height = (int)(PseudoBitmap.Height * _Zoom + 0.5); + pictureBox.Location = new Point(0, (int)((this.ClientSize.Height - hScrollBar.Height - PseudoBitmap.Height * _Zoom) / 2.0 + 0.5)); + pictureBox.Width = this.ClientSize.Width; + pictureBox.Height = (int)(PseudoBitmap.Height * _Zoom + 0.5); - hScrollBar.LargeChange = (int)(this.ClientSize.Width / _Zoom + 0.5);//移動量 - hScrollBar.Maximum = (int)(PseudoBitmap.Width - this.ClientSize.Width / 2.0 / _Zoom + 0.5) + hScrollBar.LargeChange;//center.Xの上限値 - hScrollBar.Minimum = (int)(this.ClientSize.Width / 2.0 / _Zoom + 0.5);//center.Xの下限値 - } - //縦スクロールだけ出すとき - else if (this.ClientSize.Width - vScrollBar.Width > PseudoBitmap.Width * _Zoom && this.ClientSize.Height <= PseudoBitmap.Height * _Zoom) - { - hScrollBarVisible = false; - vScrollBarVisible = true; + hScrollBar.LargeChange = (int)(this.ClientSize.Width / _Zoom + 0.5);//移動量 + hScrollBar.Maximum = (int)(PseudoBitmap.Width - this.ClientSize.Width / 2.0 / _Zoom + 0.5) + hScrollBar.LargeChange;//center.Xの上限値 + hScrollBar.Minimum = (int)(this.ClientSize.Width / 2.0 / _Zoom + 0.5);//center.Xの下限値 + } + //縦スクロールだけ出すとき + else if (this.ClientSize.Width - vScrollBar.Width > PseudoBitmap.Width * _Zoom && this.ClientSize.Height <= PseudoBitmap.Height * _Zoom) + { + hScrollBarVisible = false; + vScrollBarVisible = true; - pictureBox.Location = new Point((int)((this.ClientSize.Width - vScrollBar.Width - PseudoBitmap.Width * _Zoom) / 2.0), 0); - pictureBox.Width = (int)(PseudoBitmap.Width * _Zoom); - pictureBox.Height = this.Height; + pictureBox.Location = new Point((int)((this.ClientSize.Width - vScrollBar.Width - PseudoBitmap.Width * _Zoom) / 2.0), 0); + pictureBox.Width = (int)(PseudoBitmap.Width * _Zoom); + pictureBox.Height = this.Height; - vScrollBar.LargeChange = (int)(this.ClientSize.Height / _Zoom + 0.5); - vScrollBar.Maximum = (int)(PseudoBitmap.Height - this.ClientSize.Height / 2.0 / _Zoom + 0.5) + vScrollBar.LargeChange; - vScrollBar.Minimum = (int)(this.Height / 2.0 / _Zoom + 0.5); - } - //両方のスクロールを出さなければいけないとき - else - { - hScrollBarVisible = vScrollBarVisible = true; + vScrollBar.LargeChange = (int)(this.ClientSize.Height / _Zoom + 0.5); + vScrollBar.Maximum = (int)(PseudoBitmap.Height - this.ClientSize.Height / 2.0 / _Zoom + 0.5) + vScrollBar.LargeChange; + vScrollBar.Minimum = (int)(this.Height / 2.0 / _Zoom + 0.5); + } + //両方のスクロールを出さなければいけないとき + else + { + hScrollBarVisible = vScrollBarVisible = true; - pictureBox.Location = new Point(0, 0); - pictureBox.Width = this.ClientSize.Width - vScrollBar.Width; - pictureBox.Height = this.ClientSize.Height - hScrollBar.Height; + pictureBox.Location = new Point(0, 0); + pictureBox.Width = this.ClientSize.Width - vScrollBar.Width; + pictureBox.Height = this.ClientSize.Height - hScrollBar.Height; - int hLargeChange = (int)((this.ClientSize.Width - vScrollBar.Width) / _Zoom + 0.5); + int hLargeChange = (int)((this.ClientSize.Width - vScrollBar.Width) / _Zoom + 0.5); - hScrollBar.Maximum = (int)(PseudoBitmap.Width - (this.ClientSize.Width - vScrollBar.Width) / 2.0 / _Zoom + 0.5) + hLargeChange - 1;//center.Xの上限値 - hScrollBar.Minimum = (int)((this.ClientSize.Width - vScrollBar.Width) / 2.0 / _Zoom);//center.Xの下限値 - if (hLargeChange > 0) - hScrollBar.LargeChange = hLargeChange;//移動量 + hScrollBar.Maximum = (int)(PseudoBitmap.Width - (this.ClientSize.Width - vScrollBar.Width) / 2.0 / _Zoom + 0.5) + hLargeChange - 1;//center.Xの上限値 + hScrollBar.Minimum = (int)((this.ClientSize.Width - vScrollBar.Width) / 2.0 / _Zoom);//center.Xの下限値 + if (hLargeChange > 0) + hScrollBar.LargeChange = hLargeChange;//移動量 - int vLargeChange = (int)((this.ClientSize.Height - hScrollBar.Height) / _Zoom + 0.5); - vScrollBar.Maximum = (int)(PseudoBitmap.Height - (this.ClientSize.Height - hScrollBar.Height) / 2.0 / _Zoom + 0.5) + vLargeChange - 1; - vScrollBar.Minimum = (int)((this.ClientSize.Height - hScrollBar.Height) / 2.0 / _Zoom); - if (vLargeChange > 0) - vScrollBar.LargeChange = vLargeChange; - } + int vLargeChange = (int)((this.ClientSize.Height - hScrollBar.Height) / _Zoom + 0.5); + vScrollBar.Maximum = (int)(PseudoBitmap.Height - (this.ClientSize.Height - hScrollBar.Height) / 2.0 / _Zoom + 0.5) + vLargeChange - 1; + vScrollBar.Minimum = (int)((this.ClientSize.Height - hScrollBar.Height) / 2.0 / _Zoom); + if (vLargeChange > 0) + vScrollBar.LargeChange = vLargeChange; } + } - private bool skipScrollBarEvent = false; + private bool skipScrollBarEvent = false; - private void vScrollBar_ValueChanged(object sender, EventArgs e) + private void vScrollBar_ValueChanged(object sender, EventArgs e) + { + if (skipScrollBarEvent) return; + if (_Center.Y != vScrollBar.Value) { - if (skipScrollBarEvent) return; - if (_Center.Y != vScrollBar.Value) - { - if (!VerticalFlip) - Center = new PointD(_Center.X, vScrollBar.Value); - else - Center = new PointD(_Center.X, vScrollBar.Maximum - vScrollBar.Minimum - vScrollBar.Value); - } + if (!VerticalFlip) + Center = new PointD(_Center.X, vScrollBar.Value); + else + Center = new PointD(_Center.X, vScrollBar.Maximum - vScrollBar.Minimum - vScrollBar.Value); } + } - private void hScrollBar_ValueChanged(object sender, EventArgs e) + private void hScrollBar_ValueChanged(object sender, EventArgs e) + { + if (skipScrollBarEvent) return; + if (_Center.X != hScrollBar.Value) { - if (skipScrollBarEvent) return; - if (_Center.X != hScrollBar.Value) - { - if (!horizontalFlip) - Center = new PointD(hScrollBar.Value, _Center.Y); - else - Center = new PointD(hScrollBar.Maximum - hScrollBar.Minimum - hScrollBar.Value, _Center.Y); - } + if (!horizontalFlip) + Center = new PointD(hScrollBar.Value, _Center.Y); + else + Center = new PointD(hScrollBar.Maximum - hScrollBar.Minimum - hScrollBar.Value, _Center.Y); } + } - private void SpecialPictureBox_MouseDown(object sender, MouseEventArgs e) - { - //範囲外をクリックされると最低倍率に戻す - Zoom = minZoom; - } + private void SpecialPictureBox_MouseDown(object sender, MouseEventArgs e) + { + //範囲外をクリックされると最低倍率に戻す + Zoom = minZoom; + } - #region 座標変換関連 + #region 座標変換関連 + + /// + /// クライアントのPointをソースのPointに変換 + /// + /// + /// + public PointD ConvertToSrcPt(Point clientPt) + { return ConvertToSrcPt(new PointD(clientPt.X, clientPt.Y)); } + + /// + /// クライアントのPointDをソースのPointDに変換 + /// + /// + /// + public PointD ConvertToSrcPt(PointD clientPt) + { + double x, y; + if (!HorizontalFlip) + x = (clientPt.X - pictureBox.ClientSize.Width / 2.0) / _Zoom + _Center.X; + else + x = -(clientPt.X - pictureBox.ClientSize.Width / 2.0) / _Zoom + _Center.X; + + if (!VerticalFlip) + y = (clientPt.Y - pictureBox.ClientSize.Height / 2.0) / _Zoom + _Center.Y; + else + y = -(clientPt.Y - pictureBox.ClientSize.Height / 2.0) / _Zoom + _Center.Y; + + return new PointD(x, y); + } - /// - /// クライアントのPointをソースのPointに変換 - /// - /// - /// - public PointD ConvertToSrcPt(Point clientPt) - { return ConvertToSrcPt(new PointD(clientPt.X, clientPt.Y)); } + /// + /// クライアントのRectangleをSrcのRectangleに変換 + /// + /// + /// + public RectangleD ConvertToSrcRect(Rectangle clientRect) + { return ConvertToSrcRect(new RectangleD(clientRect.X, clientRect.Y, clientRect.Width, clientRect.Height)); } + + /// + /// クライアントのRectangleDをSrcのRectangleDに変換 + /// + /// + /// + public RectangleD ConvertToSrcRect(RectangleD clientRect) + { + PointD ul = ConvertToSrcPt(new PointD(clientRect.X, clientRect.Y)); + PointD lr = ConvertToSrcPt(new PointD(clientRect.X + clientRect.Width, clientRect.Y + clientRect.Height)); + return new RectangleD(ul, new SizeD(lr.X - ul.X, lr.Y - ul.Y)); + } - /// - /// クライアントのPointDをソースのPointDに変換 - /// - /// - /// - public PointD ConvertToSrcPt(PointD clientPt) - { - double x, y; - if (!HorizontalFlip) - x = (clientPt.X - pictureBox.ClientSize.Width / 2.0) / _Zoom + _Center.X; - else - x = -(clientPt.X - pictureBox.ClientSize.Width / 2.0) / _Zoom + _Center.X; + /// + /// ソースのPointDをクライアントのPointDに変換 + /// + /// + /// + public PointD ConvertToClientPt(PointD srcPt) + { + return new PointD(((srcPt.X - _Center.X) * Zoom + pictureBox.ClientSize.Width / 2.0f), ((srcPt.Y - _Center.Y) * Zoom + pictureBox.ClientSize.Height / 2.0f)); + } - if (!VerticalFlip) - y = (clientPt.Y - pictureBox.ClientSize.Height / 2.0) / _Zoom + _Center.Y; - else - y = -(clientPt.Y - pictureBox.ClientSize.Height / 2.0) / _Zoom + _Center.Y; + /// + /// ソースのRectangleDをクライアントのRectangleDに変換 + /// + /// + /// + public RectangleD ConvertToClientRect(RectangleD srcRect) + { + PointD ul = ConvertToClientPt(new PointD(srcRect.X, srcRect.Y)); + PointD lr = ConvertToClientPt(new PointD(srcRect.X + srcRect.Width, srcRect.Y + srcRect.Height)); + return new RectangleD(ul, new SizeD(lr.X - ul.X, lr.Y - ul.Y)); + } - return new PointD(x, y); - } + #endregion 座標変換関連 - /// - /// クライアントのRectangleをSrcのRectangleに変換 - /// - /// - /// - public RectangleD ConvertToSrcRect(Rectangle clientRect) - { return ConvertToSrcRect(new RectangleD(clientRect.X, clientRect.Y, clientRect.Width, clientRect.Height)); } + private void vScrollBar_VisibleChanged(object sender, EventArgs e) + { + } - /// - /// クライアントのRectangleDをSrcのRectangleDに変換 - /// - /// - /// - public RectangleD ConvertToSrcRect(RectangleD clientRect) - { - PointD ul = ConvertToSrcPt(new PointD(clientRect.X, clientRect.Y)); - PointD lr = ConvertToSrcPt(new PointD(clientRect.X + clientRect.Width, clientRect.Y + clientRect.Height)); - return new RectangleD(ul, new SizeD(lr.X - ul.X, lr.Y - ul.Y)); - } + /// + /// 現在表示している画像をBitmapクラスで返す + /// + /// + public Bitmap GetBitmapImage() + { + var bmp = new Bitmap(pictureBox.Image.Width, pictureBox.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + var g = Graphics.FromImage(bmp); + g.DrawImage(pictureBox.Image, new Point(0, 0)); - /// - /// ソースのPointDをクライアントのPointDに変換 - /// - /// - /// - public PointD ConvertToClientPt(PointD srcPt) - { - return new PointD(((srcPt.X - _Center.X) * Zoom + pictureBox.ClientSize.Width / 2.0f), ((srcPt.Y - _Center.Y) * Zoom + pictureBox.ClientSize.Height / 2.0f)); - } + pictureBox_Paint(new object(), new PaintEventArgs(g, pictureBox.ClientRectangle)); + return bmp; + } - /// - /// ソースのRectangleDをクライアントのRectangleDに変換 - /// - /// - /// - public RectangleD ConvertToClientRect(RectangleD srcRect) - { - PointD ul = ConvertToClientPt(new PointD(srcRect.X, srcRect.Y)); - PointD lr = ConvertToClientPt(new PointD(srcRect.X + srcRect.Width, srcRect.Y + srcRect.Height)); - return new RectangleD(ul, new SizeD(lr.X - ul.X, lr.Y - ul.Y)); - } + public void SaveAsPNG() + { + var dlg = new SaveFileDialog() { Filter = "*.png|*.png" }; + if(dlg.ShowDialog()== DialogResult.OK) + GetBitmapImage().Save(dlg.FileName); + } - #endregion 座標変換関連 + public void CopyAsBitmap() + { + Clipboard.SetDataObject(GetBitmapImage(),true); + } - private void vScrollBar_VisibleChanged(object sender, EventArgs e) - { - } + public void SaveAsMetafile() + { + metafile(true); + } - /// - /// 現在表示している画像をBitmapクラスで返す - /// - /// - public Bitmap GetBitmapImage() - { - Bitmap bmp = new Bitmap(pictureBox.Image.Width, pictureBox.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); - Graphics g = Graphics.FromImage(bmp); - g.DrawImage(pictureBox.Image, new Point(0, 0)); - // return PseudoBitmap.GetImage( - return bmp; - } + public void CopyAsMetafile() + { + metafile(false); + } - //このコントロールがフォーカスを浴びた時の処理 - private void ScalablePictureBox_Enter(object sender, EventArgs e) - { - if (FocusEventEnabled) - ShowRimRentangle = true; - } + private void metafile(bool save) + { + using Graphics grfx = CreateGraphics(); + IntPtr ipHdc = grfx.GetHdc(); + MemoryStream ms = new(); + Metafile mf = new(ms, ipHdc, EmfType.EmfPlusDual); + grfx.ReleaseHdc(ipHdc); + grfx.Dispose(); + var g = Graphics.FromImage(mf); - private void ScalablePictureBox_Leave(object sender, EventArgs e) + var destRect = new RectangleF(0, 0, pictureBox.ClientSize.Width, pictureBox.ClientSize.Height); + //var srcRect = PseudoBitmap.GetDrawingArea(Center, Zoom, pictureBox.ClientSize).ToRectangleF(); + //var image = PseudoBitmap.GetImage(); + //g.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel); + + var srcRect = PseudoBitmap.GetDrawingArea(Center, Zoom, pictureBox.ClientSize); + var image = PseudoBitmap.GetImage(srcRect, srcRect.ToSize()); + g.DrawImage(image, destRect); + + pictureBox_Paint(new object(), new PaintEventArgs(g, pictureBox.ClientRectangle)); + + g.Dispose(); + + if (save) { - if (FocusEventEnabled) - ShowRimRentangle = false; + SaveFileDialog dlg = new() { Filter = "*.emf|*.emf" }; + if (dlg.ShowDialog() == DialogResult.OK) + { + FileStream fsm = new(dlg.FileName, FileMode.Create, FileAccess.Write); + fsm.Write(ms.GetBuffer(), 0, (int)ms.Length); + fsm.Close(); + } } + else + ClipboardMetafileHelper.PutEnhMetafileOnClipboard(this.Handle, mf); + } + + + + + + + + //このコントロールがフォーカスを浴びた時の処理 + private void ScalablePictureBox_Enter(object sender, EventArgs e) + { + if (FocusEventEnabled) + ShowRimRentangle = true; + } + + private void ScalablePictureBox_Leave(object sender, EventArgs e) + { + if (FocusEventEnabled) + ShowRimRentangle = false; } } \ No newline at end of file diff --git a/Crystallography.Controls/ScalablePictureBoxAdvanced.Designer.cs b/Crystallography.Controls/ScalablePictureBoxAdvanced.Designer.cs index a5cfb5c..f537f64 100644 --- a/Crystallography.Controls/ScalablePictureBoxAdvanced.Designer.cs +++ b/Crystallography.Controls/ScalablePictureBoxAdvanced.Designer.cs @@ -51,12 +51,22 @@ private void InitializeComponent() this.checkBoxGaussianBlur = new System.Windows.Forms.CheckBox(); this.numericBoxGaussianFWHM = new Crystallography.Controls.NumericBox(); this.panelUpper = new System.Windows.Forms.Panel(); - this.buttonCopyToClipBoard = new System.Windows.Forms.Button(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.scalablePictureBox = new Crystallography.Controls.ScalablePictureBox(); this.graphControl = new Crystallography.Controls.GraphControl(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label14 = new System.Windows.Forms.Label(); + this.labelResolution = new System.Windows.Forms.Label(); + this.buttonMag1 = new System.Windows.Forms.Button(); + this.buttonMag2 = new System.Windows.Forms.Button(); + this.buttonMag4 = new System.Windows.Forms.Button(); + this.buttonMag_2 = new System.Windows.Forms.Button(); + this.buttonMag_4 = new System.Windows.Forms.Button(); + this.buttonMag_8 = new System.Windows.Forms.Button(); + this.buttonMag_16 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); this.panelTrackBar.SuspendLayout(); this.flowLayoutPanelGradient.SuspendLayout(); this.flowLayoutPanelImageFilter.SuspendLayout(); @@ -64,6 +74,7 @@ private void InitializeComponent() this.flowLayoutPanelGaussianBlur2.SuspendLayout(); this.panelUpper.SuspendLayout(); this.statusStrip1.SuspendLayout(); + this.panel1.SuspendLayout(); this.SuspendLayout(); // // panelTrackBar @@ -283,18 +294,10 @@ private void InitializeComponent() // // panelUpper // - this.panelUpper.Controls.Add(this.buttonCopyToClipBoard); this.panelUpper.Controls.Add(this.label); resources.ApplyResources(this.panelUpper, "panelUpper"); this.panelUpper.Name = "panelUpper"; // - // buttonCopyToClipBoard - // - resources.ApplyResources(this.buttonCopyToClipBoard, "buttonCopyToClipBoard"); - this.buttonCopyToClipBoard.Name = "buttonCopyToClipBoard"; - this.buttonCopyToClipBoard.UseVisualStyleBackColor = true; - this.buttonCopyToClipBoard.Click += new System.EventHandler(this.buttonCopyToClipBoard_Click); - // // statusStrip1 // this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -381,11 +384,91 @@ private void InitializeComponent() this.graphControl.YScaleLineVisible = true; this.graphControl.LinePositionChanged += new Crystallography.Controls.GraphControl.LinePositionChengedEventHandler(this.graphControl_LinePositionChanged); // + // panel1 + // + resources.ApplyResources(this.panel1, "panel1"); + this.panel1.Controls.Add(this.label14); + this.panel1.Controls.Add(this.labelResolution); + this.panel1.Controls.Add(this.buttonMag1); + this.panel1.Controls.Add(this.buttonMag2); + this.panel1.Controls.Add(this.buttonMag4); + this.panel1.Controls.Add(this.buttonMag_2); + this.panel1.Controls.Add(this.buttonMag_4); + this.panel1.Controls.Add(this.buttonMag_8); + this.panel1.Controls.Add(this.buttonMag_16); + this.panel1.Controls.Add(this.label1); + this.panel1.Name = "panel1"; + // + // label14 + // + resources.ApplyResources(this.label14, "label14"); + this.label14.Name = "label14"; + // + // labelResolution + // + resources.ApplyResources(this.labelResolution, "labelResolution"); + this.labelResolution.Name = "labelResolution"; + // + // buttonMag1 + // + resources.ApplyResources(this.buttonMag1, "buttonMag1"); + this.buttonMag1.Name = "buttonMag1"; + this.buttonMag1.UseVisualStyleBackColor = true; + this.buttonMag1.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag2 + // + resources.ApplyResources(this.buttonMag2, "buttonMag2"); + this.buttonMag2.Name = "buttonMag2"; + this.buttonMag2.UseVisualStyleBackColor = true; + this.buttonMag2.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag4 + // + resources.ApplyResources(this.buttonMag4, "buttonMag4"); + this.buttonMag4.Name = "buttonMag4"; + this.buttonMag4.UseVisualStyleBackColor = true; + this.buttonMag4.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag_2 + // + resources.ApplyResources(this.buttonMag_2, "buttonMag_2"); + this.buttonMag_2.Name = "buttonMag_2"; + this.buttonMag_2.UseVisualStyleBackColor = true; + this.buttonMag_2.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag_4 + // + resources.ApplyResources(this.buttonMag_4, "buttonMag_4"); + this.buttonMag_4.Name = "buttonMag_4"; + this.buttonMag_4.UseVisualStyleBackColor = true; + this.buttonMag_4.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag_8 + // + resources.ApplyResources(this.buttonMag_8, "buttonMag_8"); + this.buttonMag_8.Name = "buttonMag_8"; + this.buttonMag_8.UseVisualStyleBackColor = true; + this.buttonMag_8.Click += new System.EventHandler(this.buttonMag_Click); + // + // buttonMag_16 + // + resources.ApplyResources(this.buttonMag_16, "buttonMag_16"); + this.buttonMag_16.Name = "buttonMag_16"; + this.buttonMag_16.UseVisualStyleBackColor = true; + this.buttonMag_16.Click += new System.EventHandler(this.buttonMag_Click); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // // ScalablePictureBoxAdvanced // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.Controls.Add(this.scalablePictureBox); + this.Controls.Add(this.panel1); this.Controls.Add(this.panelTrackBar); this.Controls.Add(this.graphControl); this.Controls.Add(this.flowLayoutPanelGradient); @@ -409,6 +492,8 @@ private void InitializeComponent() this.panelUpper.PerformLayout(); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -435,7 +520,6 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox checkBoxGaussianBlur; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelGaussianBlur2; private System.Windows.Forms.Panel panelUpper; - private System.Windows.Forms.Button buttonCopyToClipBoard; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelDustScratches; private System.Windows.Forms.CheckBox checkBoxDustScratches; private NumericBox numericBoxDustScratchesThreshold; @@ -444,5 +528,16 @@ private void InitializeComponent() private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label labelResolution; + private System.Windows.Forms.Button buttonMag1; + private System.Windows.Forms.Button buttonMag2; + private System.Windows.Forms.Button buttonMag4; + private System.Windows.Forms.Button buttonMag_2; + private System.Windows.Forms.Button buttonMag_4; + private System.Windows.Forms.Button buttonMag_8; + private System.Windows.Forms.Button buttonMag_16; + private System.Windows.Forms.Label label1; } } diff --git a/Crystallography.Controls/ScalablePictureBoxAdvanced.cs b/Crystallography.Controls/ScalablePictureBoxAdvanced.cs index 2882cc2..d083ce7 100644 --- a/Crystallography.Controls/ScalablePictureBoxAdvanced.cs +++ b/Crystallography.Controls/ScalablePictureBoxAdvanced.cs @@ -7,657 +7,692 @@ using System.Linq; using System.Windows.Forms; -namespace Crystallography.Controls +namespace Crystallography.Controls; + +[Serializable] +public partial class ScalablePictureBoxAdvanced : UserControl { - [Serializable] - public partial class ScalablePictureBoxAdvanced : UserControl - { - public bool SkipDrawing { get => scalablePictureBox.SkipDrawing; set => scalablePictureBox.SkipDrawing = value; } + public bool SkipDrawing { get => scalablePictureBox.SkipDrawing; set => scalablePictureBox.SkipDrawing = value; } - public ScalablePictureBoxAdvanced() - { + public ScalablePictureBoxAdvanced() + { - InitializeComponent(); + InitializeComponent(); - graphControl.LineList = new[] { new PointD(0, 0), new PointD(0, 0) }; - comboBoxGradient.SelectedIndex = 0; - comboBoxScale1.SelectedIndex = 1; - comboBoxScale2.SelectedIndex = 0; - } + graphControl.LineList = new[] { new PointD(0, 0), new PointD(0, 0) }; + comboBoxGradient.SelectedIndex = 0; + comboBoxScale1.SelectedIndex = 1; + comboBoxScale2.SelectedIndex = 0; + } - #region プロパティ + #region プロパティ - /// - /// VisualStudioデザイナーの編集の時はTrue - /// - public new bool DesignMode + /// + /// VisualStudioデザイナーの編集の時はTrue + /// + public new bool DesignMode + { + get { - get + if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) + return true; + Control ctrl = this; + while (ctrl != null) { - if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) + if (ctrl.Site != null && ctrl.Site.DesignMode) return true; - Control ctrl = this; - while (ctrl != null) - { - if (ctrl.Site != null && ctrl.Site.DesignMode) - return true; - ctrl = ctrl.Parent; - } - return false; - } - } - - /// - /// スクロールバーが表示されているかどうか - /// - public bool ScrollBarVisible { get => scalablePictureBox.ScrollBarVisible; } - - /// - /// スクロールバーをログスケールで動かすかどうか - /// - public bool LogScaleBar { get => trackBarAdvancedMaximum.LogScrollBar; set => trackBarAdvancedMaximum.LogScrollBar = trackBarAdvancedMinimum.LogScrollBar = value; } - - /// - /// 描画しているソース画像の範囲を取得/設定する - /// - public RectangleD DrawingArea { get => scalablePictureBox.DrawingArea; } - - /// - /// マウス位置の情報を表示するかどうか - /// - public bool MousePositionLabelVisible - { - get => label.Visible; - set - { - label.Visible = value; - panelUpper.Visible = MousePositionLabelVisible || CopyButtonVisible; + ctrl = ctrl.Parent; } + return false; } + } - /// - /// コピーボタンを表示するかどうか - /// - public bool CopyButtonVisible + /// + /// スクロールバーが表示されているかどうか + /// + public bool ScrollBarVisible { get => scalablePictureBox.ScrollBarVisible; } + + /// + /// スクロールバーをログスケールで動かすかどうか + /// + public bool LogScaleBar { get => trackBarAdvancedMaximum.LogScrollBar; set => trackBarAdvancedMaximum.LogScrollBar = trackBarAdvancedMinimum.LogScrollBar = value; } + + /// + /// 描画しているソース画像の範囲を取得/設定する + /// + public RectangleD DrawingArea { get => scalablePictureBox.DrawingArea; } + + /// + /// マウス位置の情報を表示するかどうか + /// + public bool MousePositionLabelVisible + { + get => label.Visible; + set { - get => buttonCopyToClipBoard.Visible; - set - { - buttonCopyToClipBoard.Visible = value; - panelUpper.Visible = MousePositionLabelVisible || CopyButtonVisible; - } + label.Visible = value; + panelUpper.Visible = MousePositionLabelVisible;// || CopyButtonVisible; } + } - /// - /// メモリを表示するかどうか - /// - public bool ShowGradiaent { get; set; } = true; - - public bool TrackBarVisible { set => panelTrackBar.Visible = value; get => panelTrackBar.Visible; } - - public bool FrequencyGraphVisible { set => graphControl.Visible = value; get => graphControl.Visible; } - - [Category("Image Filter")] - /// - /// ImageFilterを有効にするかどうか - /// - public bool ImageFilterVisible { set => flowLayoutPanelImageFilter.Visible = value; get => flowLayoutPanelImageFilter.Visible; } - - [Category("Image Filter")] - /// - /// GaussianFilterを有効にするかどうか - /// - public bool ImageFilter_GaussianBlur { set => checkBoxGaussianBlur.Checked = value; get => checkBoxGaussianBlur.Checked; } - - [Category("Image Filter")] - /// - /// GaussianFilterを有効にするかどうか - /// - public bool ImageFilter_GaussianBlurVisible { set => checkBoxGaussianBlur.Visible = value; get => checkBoxGaussianBlur.Visible; } - - [Category("Image Filter")] - /// - /// GaussianFilterの - /// - public double ImageFilter_GaussianBlurRadius { set => numericBoxGaussianFWHM.Value = value; get => numericBoxGaussianFWHM.Value; } - - [Category("Image Filter")] - /// - /// Dust&Scratchesを有効にするかどうか - /// - public bool ImageFilter_DustAndScratches { set => checkBoxDustScratches.Checked = value; get => checkBoxDustScratches.Checked; } - - [Category("Image Filter")] - /// - /// Dust&Scratchesを有効にするかどうか - /// - public bool ImageFilter_DustAndScratchesVisible { set => checkBoxDustScratches.Visible = value; get => checkBoxDustScratches.Visible; } - - [Category("Image Filter")] - public double ImageFilter_DustAndScratchesRadius { set => numericBoxDustScratchesRadius.Value = value; get => numericBoxDustScratchesRadius.Value; } - - [Category("Image Filter")] - public double ImageFilter_DustAndScratchesThreshold { set => numericBoxDustScratchesThreshold.Value = value; get => numericBoxDustScratchesThreshold.Value; } - - public bool VisibleGradient { set => flowLayoutPanelGradient.Visible = value; get => flowLayoutPanelGradient.Visible; } - - public Size PictureSize + /// + /// コピーボタンを表示するかどうか + /// + //public bool CopyButtonVisible + //{ + // get => buttonCopyToClipBoard.Visible; + // set + // { + // buttonCopyToClipBoard.Visible = value; + // panelUpper.Visible = MousePositionLabelVisible || CopyButtonVisible; + // } + //} + + /// + /// メモリを表示するかどうか + /// + public bool ShowGradiaent { get; set; } = true; + + public bool TrackBarVisible { set => panelTrackBar.Visible = value; get => panelTrackBar.Visible; } + + public bool FrequencyGraphVisible { set => graphControl.Visible = value; get => graphControl.Visible; } + + [Category("Image Filter")] + /// + /// ImageFilterを有効にするかどうか + /// + public bool ImageFilterVisible { set => flowLayoutPanelImageFilter.Visible = value; get => flowLayoutPanelImageFilter.Visible; } + + [Category("Image Filter")] + /// + /// GaussianFilterを有効にするかどうか + /// + public bool ImageFilter_GaussianBlur { set => checkBoxGaussianBlur.Checked = value; get => checkBoxGaussianBlur.Checked; } + + [Category("Image Filter")] + /// + /// GaussianFilterを有効にするかどうか + /// + public bool ImageFilter_GaussianBlurVisible { set => checkBoxGaussianBlur.Visible = value; get => checkBoxGaussianBlur.Visible; } + + [Category("Image Filter")] + /// + /// GaussianFilterの + /// + public double ImageFilter_GaussianBlurRadius { set => numericBoxGaussianFWHM.Value = value; get => numericBoxGaussianFWHM.Value; } + + [Category("Image Filter")] + /// + /// Dust&Scratchesを有効にするかどうか + /// + public bool ImageFilter_DustAndScratches { set => checkBoxDustScratches.Checked = value; get => checkBoxDustScratches.Checked; } + + [Category("Image Filter")] + /// + /// Dust&Scratchesを有効にするかどうか + /// + public bool ImageFilter_DustAndScratchesVisible { set => checkBoxDustScratches.Visible = value; get => checkBoxDustScratches.Visible; } + + [Category("Image Filter")] + public double ImageFilter_DustAndScratchesRadius { set => numericBoxDustScratchesRadius.Value = value; get => numericBoxDustScratchesRadius.Value; } + + [Category("Image Filter")] + public double ImageFilter_DustAndScratchesThreshold { set => numericBoxDustScratchesThreshold.Value = value; get => numericBoxDustScratchesThreshold.Value; } + + public bool VisibleGradient { set => flowLayoutPanelGradient.Visible = value; get => flowLayoutPanelGradient.Visible; } + + public Size PictureSize + { + set { - set - { - this.Width = value.Width; - this.Height = (this.Height - scalablePictureBox.Size.Height) + value.Height; - } - get => scalablePictureBox.Size; + this.Width = value.Width; + this.Height = (this.Height - scalablePictureBox.Size.Height) + value.Height; } + get => scalablePictureBox.Size; + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public PseudoBitmap PseudoBitmap + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public PseudoBitmap PseudoBitmap + { + set { - set - { - scalablePictureBox.PseudoBitmap = value; - Initialize(); - } - get => scalablePictureBox.PseudoBitmap; + scalablePictureBox.PseudoBitmap = value; + Initialize(); } + get => scalablePictureBox.PseudoBitmap; + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public (double Zoom, PointD Center) ZoomAndCenter - { - set { scalablePictureBox.ZoomAndCenter = value; } - get { return scalablePictureBox.ZoomAndCenter; } - } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public (double Zoom, PointD Center) ZoomAndCenter + { + set { scalablePictureBox.ZoomAndCenter = value; } + get { return scalablePictureBox.ZoomAndCenter; } + } - /// - /// ZoomやCenter位置を固定するかどうか - /// - public bool FixZoomAndCenter { get => scalablePictureBox.FixZoomAndCenter; set => scalablePictureBox.FixZoomAndCenter = value; } + /// + /// ZoomやCenter位置を固定するかどうか + /// + public bool FixZoomAndCenter { get => scalablePictureBox.FixZoomAndCenter; set => scalablePictureBox.FixZoomAndCenter = value; } - private double upperIntensity = 255; + private double upperIntensity = 255; - public double UpperIntensity + public double UpperIntensity + { + set { - set - { - if (value > MaximumIntensity) - value = MaximumIntensity; - else if (value < LowerIntensity) - value = LowerIntensity; - upperIntensity = value; - trackBarAdvancedMaximum.Value = value; - - int n = graphControl.LineList[0].X > graphControl.LineList[1].X ? 0 : 1; - graphControl.LineList[n].X = value; - graphControl.Draw(); + if (value > MaximumIntensity) + value = MaximumIntensity; + else if (value < LowerIntensity) + value = LowerIntensity; + upperIntensity = value; + trackBarAdvancedMaximum.Value = value; + + int n = graphControl.LineList[0].X > graphControl.LineList[1].X ? 0 : 1; + graphControl.LineList[n].X = value; + graphControl.Draw(); - PseudoBitmap.MaxValue = value; - scalablePictureBox.drawPictureBox(); + PseudoBitmap.MaxValue = value; + scalablePictureBox.drawPictureBox(); - BrightnessAndColorChanged?.Invoke(this, new EventArgs()); - } - get => upperIntensity; + BrightnessAndColorChanged?.Invoke(this, new EventArgs()); } + get => upperIntensity; + } - private double lowerIntensity = 0; + private double lowerIntensity = 0; - public double LowerIntensity + public double LowerIntensity + { + set { - set - { - if (value > UpperIntensity) - value = UpperIntensity; - else if (value < MinimumIntensity) - value = MinimumIntensity; - lowerIntensity = value; - trackBarAdvancedMinimum.Value = value; - - int n = graphControl.LineList[0].X < graphControl.LineList[1].X ? 0 : 1; - graphControl.LineList[n].X = value; - graphControl.Draw(); + if (value > UpperIntensity) + value = UpperIntensity; + else if (value < MinimumIntensity) + value = MinimumIntensity; + lowerIntensity = value; + trackBarAdvancedMinimum.Value = value; + + int n = graphControl.LineList[0].X < graphControl.LineList[1].X ? 0 : 1; + graphControl.LineList[n].X = value; + graphControl.Draw(); - PseudoBitmap.MinValue = value; - scalablePictureBox.drawPictureBox(); + PseudoBitmap.MinValue = value; + scalablePictureBox.drawPictureBox(); - BrightnessAndColorChanged?.Invoke(this, new EventArgs()); - } - get => lowerIntensity; + BrightnessAndColorChanged?.Invoke(this, new EventArgs()); } + get => lowerIntensity; + } - //画像中の最大強度 - private double maximumIntensity = 255; + //画像中の最大強度 + private double maximumIntensity = 255; - public double MaximumIntensity + public double MaximumIntensity + { + get => maximumIntensity; + set { - get => maximumIntensity; - set - { - maximumIntensity = value; - trackBarAdvancedMinimum.Maximum = trackBarAdvancedMaximum.Maximum = maximumIntensity; - } + maximumIntensity = value; + trackBarAdvancedMinimum.Maximum = trackBarAdvancedMaximum.Maximum = maximumIntensity; } + } - //画像中の最小強度 - private double minimumIntensity = 0; + //画像中の最小強度 + private double minimumIntensity = 0; - public double MinimumIntensity + public double MinimumIntensity + { + get => minimumIntensity; + set { - get => minimumIntensity; - set - { - minimumIntensity = value; - trackBarAdvancedMinimum.Minimum = trackBarAdvancedMaximum.Minimum = MinimumIntensity; - } + minimumIntensity = value; + trackBarAdvancedMinimum.Minimum = trackBarAdvancedMaximum.Minimum = MinimumIntensity; } + } - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public ScalablePictureBox ScalablePictureBox => scalablePictureBox; + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public ScalablePictureBox ScalablePictureBox => scalablePictureBox; - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public List Symbols { get => scalablePictureBox.Symbols; set => scalablePictureBox.Symbols = value; } + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public List Symbols { get => scalablePictureBox.Symbols; set => scalablePictureBox.Symbols = value; } - private double progress = 0; + private double progress = 0; - public double StatusProgress + public double StatusProgress + { + set { - set + if (progress != value) { - if (progress != value) - { - progress = value; - toolStripProgressBar1.Value = (int)(toolStripProgressBar1.Maximum * value); - StatusChanged?.Invoke(this, null); - } + progress = value; + toolStripProgressBar1.Value = (int)(toolStripProgressBar1.Maximum * value); + StatusChanged?.Invoke(this, null); } - get => progress; } + get => progress; + } - public string StatusLabel + public string StatusLabel + { + set { - set + if (toolStripStatusLabel1.Text != value) { - if (toolStripStatusLabel1.Text != value) - { - toolStripStatusLabel1.Text = value; - StatusChanged?.Invoke(this, null); - } + toolStripStatusLabel1.Text = value; + StatusChanged?.Invoke(this, null); } - get => toolStripStatusLabel1.Text; } + get => toolStripStatusLabel1.Text; + } - public bool StatusVisible { set => statusStrip1.Visible = value; get => statusStrip1.Visible; } + public bool StatusVisible { set => statusStrip1.Visible = value; get => statusStrip1.Visible; } - #endregion プロパティ - #region イベント + public bool TitleVisible { get=> scalablePictureBox.TitleVisible; set=> scalablePictureBox.TitleVisible=value; } + public (string Text, Font Font, Color Color1, Color Color2) Title { get => scalablePictureBox.Title; set => scalablePictureBox.Title = value; } - /// - /// マウスイベント用のデリゲート - /// - /// sender - /// e - /// ソース画像座標 - /// その後のイベントをキャンセルする場合: true - public delegate bool MouseEvent(object sender, MouseEventArgs e, PointD pt); - public event MouseEvent MouseMove2; + #endregion プロパティ - public event MouseEvent MouseUp2; + #region イベント - public event MouseEvent MouseDown2; + /// + /// マウスイベント用のデリゲート + /// + /// sender + /// e + /// ソース画像座標 + /// その後のイベントをキャンセルする場合: true + public delegate bool MouseEvent(object sender, MouseEventArgs e, PointD pt); - public event MouseEvent MouseWheel2; + public event MouseEvent MouseMove2; - /// - /// マウスが押されたとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue - /// - /// - /// - /// - /// - private bool scalablePictureBox_MouseDown2(object sender, MouseEventArgs e, PointD pt) - { - if (MouseDown2 != null) return MouseDown2(sender, e, pt); - else return false; - } + public event MouseEvent MouseUp2; - /// - /// マウスが上がったとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue - /// - /// - /// - /// - /// - private bool scalablePictureBox_MouseUp2(object sender, MouseEventArgs e, PointD pt) - { - if (MouseUp2 != null) return MouseUp2(sender, e, pt); - else return false; - } + public event MouseEvent MouseDown2; - /// - /// マウスホイールが回ったとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue - /// - /// - /// - /// - /// - private bool scalablePictureBox_MouseWheel2(object sender, MouseEventArgs e, PointD pt) - { - if (MouseWheel2 != null) return MouseWheel2(sender, e, pt); - else return false; - } + public event MouseEvent MouseWheel2; - /// - /// マウスが動いた時に画面上部にマウス位置、強度を示す。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue - /// - /// - /// - /// - /// - private bool scalablePictureBox1_MouseMove2(object sender, MouseEventArgs e, PointD pt) - { - if (PseudoBitmap != null) - { - string text = "X: " + ((int)pt.X).ToString("0000") + ", Y: " + ((int)pt.Y).ToString(); + /// + /// マウスが押されたとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue + /// + /// + /// + /// + /// + private bool scalablePictureBox_MouseDown2(object sender, MouseEventArgs e, PointD pt) + { + if (MouseDown2 != null) return MouseDown2(sender, e, pt); + else return false; + } - if (scalablePictureBox.PseudoBitmap.IsSrcGray) - text += ", Value: " + PseudoBitmap.GetPixelRawValue(pt); - label.Text = text; - } - scalablePictureBox.Refresh(); - if (MouseMove2 != null) - return MouseMove2(sender, e, pt); - else - return false; - } + /// + /// マウスが上がったとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue + /// + /// + /// + /// + /// + private bool scalablePictureBox_MouseUp2(object sender, MouseEventArgs e, PointD pt) + { + if (MouseUp2 != null) return MouseUp2(sender, e, pt); + else return false; + } - /// - /// 輝度が変更された時のイベントハンドラー - /// - public event EventHandler BrightnessAndColorChanged; + /// + /// マウスホイールが回ったとき。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue + /// + /// + /// + /// + /// + private bool scalablePictureBox_MouseWheel2(object sender, MouseEventArgs e, PointD pt) + { + if (MouseWheel2 != null) return MouseWheel2(sender, e, pt); + else return false; + } - public delegate void DrawingAreaChangedEvent(object sender, double zoom, PointD center); + /// + /// マウスが動いた時に画面上部にマウス位置、強度を示す。コントロール本体でのその後のイベントをキャンセルする場合、返り値はtrue + /// + /// + /// + /// + /// + private bool scalablePictureBox1_MouseMove2(object sender, MouseEventArgs e, PointD pt) + { + if (PseudoBitmap != null) + { + string text = "X: " + ((int)pt.X).ToString("0000") + ", Y: " + ((int)pt.Y).ToString(); - public event DrawingAreaChangedEvent DrawingAreaChanged; + if (scalablePictureBox.PseudoBitmap.IsSrcGray) + text += ", Value: " + PseudoBitmap.GetPixelRawValue(pt); + label.Text = text; - private void scalablePictureBox_DrawingAreaChanged(object sender, double zoom, PointD center) - { - DrawingAreaChanged?.Invoke(sender, zoom, center); + labelResolution.Text = scalablePictureBox.Zoom.ToString("g4"); } + scalablePictureBox.Refresh(); + if (MouseMove2 != null) + return MouseMove2(sender, e, pt); + else + return false; + } - /// - /// ステータスラベルやプログレスバーが変更されたとき(現在はフィルター処理のために使用) - /// - public event EventHandler StatusChanged; + /// + /// 輝度が変更された時のイベントハンドラー + /// + public event EventHandler BrightnessAndColorChanged; - /// - /// Filter(Gaussian BlurやDust & Scrach)が変更されたとき - /// - public event EventHandler FilterChanged; + public delegate void DrawingAreaChangedEvent(object sender, double zoom, PointD center); + public event DrawingAreaChangedEvent DrawingAreaChanged; - #endregion イベント + private void scalablePictureBox_DrawingAreaChanged(object sender, double zoom, PointD center) + { + DrawingAreaChanged?.Invoke(sender, zoom, center); + } - //画像が読み込まれた時の初期化作業 - private void Initialize() - { - if (PseudoBitmap.SrcValuesGrayOriginal == null || PseudoBitmap.SrcValuesGrayOriginal.Length == 0) return; - double max = PseudoBitmap.SrcValuesGrayOriginal.Max(); - double min = PseudoBitmap.SrcValuesGrayOriginal.Min(); + /// + /// ステータスラベルやプログレスバーが変更されたとき(現在はフィルター処理のために使用) + /// + public event EventHandler StatusChanged; - //まず、頻度ダイアグラムを作成 - if (FrequencyGraphVisible && PseudoBitmap.FrequencyProfile == null) - { - var temp = Statistics.GetFrequency(PseudoBitmap.SrcValuesGrayOriginal); - if (temp == null) return; - - PseudoBitmap.FrequencyProfile = new Profile(); - for (int i = 0; i < temp.Count; i++) - PseudoBitmap.FrequencyProfile.Pt.Add(new PointD(temp.Keys[i], temp.Values[i])); - //見やすいように上限、下限を広げる - PseudoBitmap.FrequencyProfile.Pt.Insert(0, new PointD(min - (max - min) * 0.05, 0)); - PseudoBitmap.FrequencyProfile.Pt.Add(new PointD(max + (max - min) * 0.05, 0)); - } + /// + /// Filter(Gaussian BlurやDust & Scrach)が変更されたとき + /// + public event EventHandler FilterChanged; - //画像のスケールの判定 - skipEvent = true; - comboBoxGradient.SelectedIndex = PseudoBitmap.IsNegative ? 1 : 0; - comboBoxScale2.SelectedIndex = PseudoBitmap.GrayScale ? 0 : 1; - if (PseudoBitmap.GrayScale) - comboBoxScale1.SelectedIndex = PseudoBitmap.ColorScale == PseudoBitmap.ColorScaleGrayLog ? 0 : 1; - else - comboBoxScale1.SelectedIndex = PseudoBitmap.ColorScale == PseudoBitmap.ColorScaleColdWarmLog ? 0 : 1; - - //Blurの判定 - //checkBoxGaussianBlur.Checked = PseudoBitmap.BlurMode == Crystallography.PseudoBitmap.BlurModeEnum.Gaussian; - //numericUpDownGaussianRadius.Value = (decimal)PseudoBitmap.BlurRadius; - - skipEvent = false; - - graphControl.Profile = PseudoBitmap.FrequencyProfile; - graphControl.UpperX = graphControl.MaximalX; - graphControl.LowerX = graphControl.MinimalX; - - //最大、最小強度などを設定 - double upper = PseudoBitmap.MaxValue; - double lower = PseudoBitmap.MinValue; - - if (upper > max || upper < min || upper < lower) - upper = max; - - if (lower < min || lower < min || lower > upper) - lower = min; - - graphControl.LineList = new[] { new PointD(lower, double.NaN), new PointD(upper, double.NaN) }; - - //書き換えの干渉が起こっているようなので、同じのを繰り返す - MaximumIntensity = max; - MinimumIntensity = min; - MaximumIntensity = max; - UpperIntensity = upper; - LowerIntensity = lower; - UpperIntensity = upper; - if (PseudoBitmap.MaxValue != upper) - PseudoBitmap.MaxValue = upper; - if (PseudoBitmap.MinValue != lower) - PseudoBitmap.MinValue = lower; - this.Refresh(); - graphControl.Draw(); - } - private bool skipEvent = false; + #endregion イベント - private void graphControl_LinePositionChanged() - { - if (skipEvent) return; - if (graphControl.LineList[1].X == graphControl.LineList[0].X) return; - skipEvent = true; - LowerIntensity = Math.Min(graphControl.LineList[0].X, graphControl.LineList[1].X); - UpperIntensity = Math.Max(graphControl.LineList[0].X, graphControl.LineList[1].X); - skipEvent = false; - } + //画像が読み込まれた時の初期化作業 + private void Initialize() + { + if (PseudoBitmap.SrcValuesGrayOriginal == null || PseudoBitmap.SrcValuesGrayOriginal.Length == 0) return; + double max = PseudoBitmap.SrcValuesGrayOriginal.Max(); + double min = PseudoBitmap.SrcValuesGrayOriginal.Min(); - private bool trackBarAdvancedMinimum_ValueChanged(object sender, double value) + //まず、頻度ダイアグラムを作成 + if (FrequencyGraphVisible && PseudoBitmap.FrequencyProfile == null) { - if (skipEvent) return true; - skipEvent = true; - LowerIntensity = trackBarAdvancedMinimum.Value; - skipEvent = false; - return default; + var temp = Statistics.GetFrequency(PseudoBitmap.SrcValuesGrayOriginal); + if (temp == null) return; + + PseudoBitmap.FrequencyProfile = new Profile(); + for (int i = 0; i < temp.Count; i++) + PseudoBitmap.FrequencyProfile.Pt.Add(new PointD(temp.Keys[i], temp.Values[i])); + //見やすいように上限、下限を広げる + PseudoBitmap.FrequencyProfile.Pt.Insert(0, new PointD(min - (max - min) * 0.05, 0)); + PseudoBitmap.FrequencyProfile.Pt.Add(new PointD(max + (max - min) * 0.05, 0)); } - private bool trackBarAdvancedMaximum_ValueChanged(object sender, double value) - { - if (skipEvent) return true; - skipEvent = true; - UpperIntensity = trackBarAdvancedMaximum.Value; - skipEvent = false; - return default; - } + //画像のスケールの判定 + skipEvent = true; + comboBoxGradient.SelectedIndex = PseudoBitmap.IsNegative ? 1 : 0; + comboBoxScale2.SelectedIndex = PseudoBitmap.GrayScale ? 0 : 1; + if (PseudoBitmap.GrayScale) + comboBoxScale1.SelectedIndex = PseudoBitmap.ColorScale == PseudoBitmap.ColorScaleGrayLog ? 0 : 1; + else + comboBoxScale1.SelectedIndex = PseudoBitmap.ColorScale == PseudoBitmap.ColorScaleColdWarmLog ? 0 : 1; + + //Blurの判定 + //checkBoxGaussianBlur.Checked = PseudoBitmap.BlurMode == Crystallography.PseudoBitmap.BlurModeEnum.Gaussian; + //numericUpDownGaussianRadius.Value = (decimal)PseudoBitmap.BlurRadius; + + skipEvent = false; + + graphControl.Profile = PseudoBitmap.FrequencyProfile; + graphControl.UpperX = graphControl.MaximalX; + graphControl.LowerX = graphControl.MinimalX; + + //最大、最小強度などを設定 + double upper = PseudoBitmap.MaxValue; + double lower = PseudoBitmap.MinValue; + + if (upper > max || upper < min || upper < lower) + upper = max; + + if (lower < min || lower < min || lower > upper) + lower = min; + + graphControl.LineList = new[] { new PointD(lower, double.NaN), new PointD(upper, double.NaN) }; + + //書き換えの干渉が起こっているようなので、同じのを繰り返す + MaximumIntensity = max; + MinimumIntensity = min; + MaximumIntensity = max; + UpperIntensity = upper; + LowerIntensity = lower; + UpperIntensity = upper; + if (PseudoBitmap.MaxValue != upper) + PseudoBitmap.MaxValue = upper; + if (PseudoBitmap.MinValue != lower) + PseudoBitmap.MinValue = lower; + this.Refresh(); + graphControl.Draw(); + } - public void DrawPictureBox() - { - if (!SkipDrawing) - scalablePictureBox.drawPictureBox(); - } + private bool skipEvent = false; - private void comboBoxScale_SelectedIndexChanged(object sender, EventArgs e) - { - if (skipEvent) return; - PseudoBitmap.IsNegative = comboBoxGradient.SelectedIndex == 1; + private void graphControl_LinePositionChanged() + { + if (skipEvent) return; + if (graphControl.LineList[1].X == graphControl.LineList[0].X) return; + skipEvent = true; + LowerIntensity = Math.Min(graphControl.LineList[0].X, graphControl.LineList[1].X); + UpperIntensity = Math.Max(graphControl.LineList[0].X, graphControl.LineList[1].X); + skipEvent = false; + } - var linear = comboBoxScale1.SelectedIndex == 1; + private bool trackBarAdvancedMinimum_ValueChanged(object sender, double value) + { + if (skipEvent) return true; + skipEvent = true; + LowerIntensity = trackBarAdvancedMinimum.Value; + skipEvent = false; + return default; + } - if (comboBoxScale2.SelectedIndex == 0)//Gray - PseudoBitmap.SetScaleGray(linear); - else if (comboBoxScale2.SelectedIndex == 1)//Cold-Warm - PseudoBitmap.SetScaleColdWarm(linear); - else if (comboBoxScale2.SelectedIndex == 2)//Spectrum - PseudoBitmap.SetScaleSpectrum(linear); - else if (comboBoxScale2.SelectedIndex == 3)//Fire - PseudoBitmap.SetScaleFire(linear); + private bool trackBarAdvancedMaximum_ValueChanged(object sender, double value) + { + if (skipEvent) return true; + skipEvent = true; + UpperIntensity = trackBarAdvancedMaximum.Value; + skipEvent = false; + return default; + } + public void DrawPictureBox() + { + if (!SkipDrawing) scalablePictureBox.drawPictureBox(); - BrightnessAndColorChanged?.Invoke(sender, e); - } + } - #region ImageFilter関連 + private void comboBoxScale_SelectedIndexChanged(object sender, EventArgs e) + { + if (skipEvent) return; + PseudoBitmap.IsNegative = comboBoxGradient.SelectedIndex == 1; + + var linear = comboBoxScale1.SelectedIndex == 1; + + if (comboBoxScale2.SelectedIndex == 0)//Gray + PseudoBitmap.SetScaleGray(linear); + else if (comboBoxScale2.SelectedIndex == 1)//Cold-Warm + PseudoBitmap.SetScaleColdWarm(linear); + else if (comboBoxScale2.SelectedIndex == 2)//Spectrum + PseudoBitmap.SetScaleSpectrum(linear); + else if (comboBoxScale2.SelectedIndex == 3)//Fire + PseudoBitmap.SetScaleFire(linear); + + scalablePictureBox.drawPictureBox(); + BrightnessAndColorChanged?.Invoke(sender, e); + } - private void imageFilterProperty_Changed(object sender, EventArgs e) - { - if (skipEvent) return; + #region ImageFilter関連 - numericBoxGaussianFWHM.Visible = checkBoxGaussianBlur.Checked; - //PseudoBitmap.BlurRadius = numericBoxGaussianRadius.Value; + private void imageFilterProperty_Changed(object sender, EventArgs e) + { + if (skipEvent) return; - numericBoxDustScratchesRadius.Visible = numericBoxDustScratchesThreshold.Visible = checkBoxDustScratches.Checked; - //PseudoBitmap.BlurMode = flowLayoutPanelGaussianBlur2.Enabled ? Crystallography.PseudoBitmap.BlurModeEnum.Gaussian : Crystallography.PseudoBitmap.BlurModeEnum.None; - ProcessImageFilter(); - FilterChanged?.Invoke(sender, e); - } + numericBoxGaussianFWHM.Visible = checkBoxGaussianBlur.Checked; + //PseudoBitmap.BlurRadius = numericBoxGaussianRadius.Value; - public void ProcessImageFilter() - { - Stopwatch sw = new Stopwatch(); + numericBoxDustScratchesRadius.Visible = numericBoxDustScratchesThreshold.Visible = checkBoxDustScratches.Checked; + //PseudoBitmap.BlurMode = flowLayoutPanelGaussianBlur2.Enabled ? Crystallography.PseudoBitmap.BlurModeEnum.Gaussian : Crystallography.PseudoBitmap.BlurModeEnum.None; + ProcessImageFilter(); + FilterChanged?.Invoke(sender, e); + } - bool originalFlag = true; - StatusLabel = "Elapsed time: "; - sw.Start(); - if (checkBoxDustScratches.Checked) - { - PseudoBitmap.SetDustAndScratches(numericBoxDustScratchesRadius.Value, numericBoxDustScratchesThreshold.Value, originalFlag); - originalFlag = false; - StatusLabel += "Dust && Scratches: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f3") + "msec. "; - } - sw.Restart(); - if (checkBoxGaussianBlur.Checked) - { - PseudoBitmap.SetBlurImage(numericBoxGaussianFWHM.Value / 2, PseudoBitmap.BlurModeEnum.Gaussian, originalFlag); - originalFlag = false; - StatusLabel += "Gaussian Blur: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f3") + "msec. "; - } - if (originalFlag) - { - PseudoBitmap.SetOriginalGray(); - StatusLabel = ""; - } + public void ProcessImageFilter() + { + Stopwatch sw = new Stopwatch(); - scalablePictureBox.drawPictureBox(); + bool originalFlag = true; + StatusLabel = "Elapsed time: "; + sw.Start(); + if (checkBoxDustScratches.Checked) + { + PseudoBitmap.SetDustAndScratches(numericBoxDustScratchesRadius.Value, numericBoxDustScratchesThreshold.Value, originalFlag); + originalFlag = false; + StatusLabel += "Dust && Scratches: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f3") + "msec. "; + } + sw.Restart(); + if (checkBoxGaussianBlur.Checked) + { + PseudoBitmap.SetBlurImage(numericBoxGaussianFWHM.Value / 2, PseudoBitmap.BlurModeEnum.Gaussian, originalFlag); + originalFlag = false; + StatusLabel += "Gaussian Blur: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f3") + "msec. "; + } + if (originalFlag) + { + PseudoBitmap.SetOriginalGray(); + StatusLabel = ""; } - #endregion ImageFilter関連 + scalablePictureBox.drawPictureBox(); + } - public event PaintEventHandler Paint2; + #endregion ImageFilter関連 - private void scalablePictureBox_Paint2(object sender, PaintEventArgs e) - { - if (DesignMode) - return; + public event PaintEventHandler Paint2; - Paint2?.Invoke(sender, e); - } + private void scalablePictureBox_Paint2(object sender, PaintEventArgs e) + { + if (DesignMode) + return; - private void buttonCopyToClipBoard_Click(object sender, EventArgs e) - { - Clipboard.SetDataObject(PseudoBitmap.GetImage(new RectangleD(0, 0, PseudoBitmap.Width, PseudoBitmap.Height), new Size(PseudoBitmap.Width, PseudoBitmap.Height))); - } + Paint2?.Invoke(sender, e); + } - public void ReadImage(string fileName) + private void buttonCopyToClipBoard_Click(object sender, EventArgs e) + { + Clipboard.SetDataObject(PseudoBitmap.GetImage(new RectangleD(0, 0, PseudoBitmap.Width, PseudoBitmap.Height), new Size(PseudoBitmap.Width, PseudoBitmap.Height))); + } + + public void ReadImage(string fileName) + { + if (ImageIO.ReadImage(fileName)) { - if (ImageIO.ReadImage(fileName)) - { - PseudoBitmap = new PseudoBitmap(Ring.Intensity.ToArray(), Ring.SrcImgSize.Width); + PseudoBitmap = new PseudoBitmap(Ring.Intensity.ToArray(), Ring.SrcImgSize.Width); - ProcessImageFilter(); + ProcessImageFilter(); - } } + } - private void ScalablePictureBoxAdvanced_DragDrop(object sender, DragEventArgs e) - { - string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); - Array.Sort(fileName); + private void ScalablePictureBoxAdvanced_DragDrop(object sender, DragEventArgs e) + { + string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); + Array.Sort(fileName); - //まず、フォルダかどうかを判断する - if (fileName.Length == 1 && Directory.Exists(fileName[0])) - {//フォルダの場合 - } - else - {//ファイル群の場合 - ReadImage(fileName[0]); - } + //まず、フォルダかどうかを判断する + if (fileName.Length == 1 && Directory.Exists(fileName[0])) + {//フォルダの場合 } - - private void ScalablePictureBoxAdvanced_DragEnter(object sender, DragEventArgs e) - { - e.Effect = (e.Data.GetData(DataFormats.FileDrop) != null) ? DragDropEffects.Copy : DragDropEffects.None; + else + {//ファイル群の場合 + ReadImage(fileName[0]); } + } + private void ScalablePictureBoxAdvanced_DragEnter(object sender, DragEventArgs e) + { + e.Effect = (e.Data.GetData(DataFormats.FileDrop) != null) ? DragDropEffects.Copy : DragDropEffects.None; + } - - #region 座標変換関連 scalablePictureBoxで定義されているものを呼び出すだけ - /// - /// クライアントのPointをソースのPointに変換 - /// - /// - /// - public PointD ConvertToSrcPt(Point clientPt) => scalablePictureBox.ConvertToSrcPt(clientPt); - - /// - /// クライアントのPointDをソースのPointDに変換 - /// - /// - /// - public PointD ConvertToSrcPt(PointD clientPt) => scalablePictureBox.ConvertToSrcPt(clientPt); - - /// - /// クライアントのRectangleをSrcのRectangleに変換 - /// - /// - /// - public RectangleD ConvertToSrcRect(Rectangle clientRect) => scalablePictureBox.ConvertToSrcRect(clientRect); - - /// - /// クライアントのRectangleDをSrcのRectangleDに変換 - /// - /// - /// - public RectangleD ConvertToSrcRect(RectangleD clientRect) => scalablePictureBox.ConvertToSrcRect(clientRect); - - /// - /// ソースのPointDをクライアントのPointDに変換 - /// - /// - /// - public PointD ConvertToClientPt(PointD srcPt) => scalablePictureBox.ConvertToClientPt(srcPt); - - /// - /// ソースのRectangleDをクライアントのRectangleDに変換 - /// - /// - /// - public RectangleD ConvertToClientRect(RectangleD srcRect) => scalablePictureBox.ConvertToClientRect(srcRect); - #endregion 座標変換関連 + #region 座標変換関連 scalablePictureBoxで定義されているものを呼び出すだけ + /// + /// クライアントのPointをソースのPointに変換 + /// + /// + /// + public PointD ConvertToSrcPt(Point clientPt) => scalablePictureBox.ConvertToSrcPt(clientPt); + + /// + /// クライアントのPointDをソースのPointDに変換 + /// + /// + /// + public PointD ConvertToSrcPt(PointD clientPt) => scalablePictureBox.ConvertToSrcPt(clientPt); + + /// + /// クライアントのRectangleをSrcのRectangleに変換 + /// + /// + /// + public RectangleD ConvertToSrcRect(Rectangle clientRect) => scalablePictureBox.ConvertToSrcRect(clientRect); + + /// + /// クライアントのRectangleDをSrcのRectangleDに変換 + /// + /// + /// + public RectangleD ConvertToSrcRect(RectangleD clientRect) => scalablePictureBox.ConvertToSrcRect(clientRect); + + /// + /// ソースのPointDをクライアントのPointDに変換 + /// + /// + /// + public PointD ConvertToClientPt(PointD srcPt) => scalablePictureBox.ConvertToClientPt(srcPt); + + /// + /// ソースのRectangleDをクライアントのRectangleDに変換 + /// + /// + /// + public RectangleD ConvertToClientRect(RectangleD srcRect) => scalablePictureBox.ConvertToClientRect(srcRect); + #endregion 座標変換関連 + + #region 画像の保存/コピー関連 scalablePictureBoxで定義されているものを呼び出すだけ + public void SaveAsPNG()=> scalablePictureBox.SaveAsPNG(); + + public void CopyAsBitmap()=> scalablePictureBox.CopyAsBitmap(); + + public void SaveAsMetafile() => scalablePictureBox.SaveAsMetafile(); + + public void copyAsMetafile() => scalablePictureBox.CopyAsMetafile(); + + #endregion + + private void buttonMag_Click(object sender, EventArgs e) + { + var name = (sender as Button).Name; + if (name.Contains("Mag1")) + scalablePictureBox.Zoom = 1; + else if (name.Contains("Mag2")) + scalablePictureBox.Zoom = 2; + else if (name.Contains("Mag4")) + scalablePictureBox.Zoom = 4; + else if (name.Contains("Mag_2")) + scalablePictureBox.Zoom = 0.5; + else if (name.Contains("Mag_4")) + scalablePictureBox.Zoom = 0.25; + else if (name.Contains("Mag_8")) + scalablePictureBox.Zoom = 0.125; + else if (name.Contains("Mag_16")) + scalablePictureBox.Zoom = 0.0625; + labelResolution.Text = scalablePictureBox.Zoom.ToString("g4"); } } \ No newline at end of file diff --git a/Crystallography.Controls/ScalablePictureBoxAdvanced.resx b/Crystallography.Controls/ScalablePictureBoxAdvanced.resx index 95ac430..2a988ce 100644 --- a/Crystallography.Controls/ScalablePictureBoxAdvanced.resx +++ b/Crystallography.Controls/ScalablePictureBoxAdvanced.resx @@ -251,7 +251,7 @@ $this - 1 + 2 True @@ -284,7 +284,7 @@ panelUpper - 1 + 0 Gray @@ -515,7 +515,7 @@ $this - 3 + 4 True @@ -821,43 +821,7 @@ $this - 4 - - - True - - - GrowAndShrink - - - Right - - - 282, 2 - - - 2, 2, 2, 2 - - - 115, 22 - - - 10 - - - Copy To ClipBoard - - - buttonCopyToClipBoard - - - System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - panelUpper - - - 0 + 5 Top @@ -872,7 +836,7 @@ 0, 2, 0, 2 - 397, 26 + 397, 30 13 @@ -887,7 +851,7 @@ $this - 5 + 6 17, 17 @@ -926,7 +890,7 @@ $this - 6 + 7 True @@ -935,13 +899,13 @@ Fill - 0, 26 + 0, 59 0, 0, 0, 0 - 397, 328 + 397, 295 0 @@ -986,8 +950,428 @@ $this + 3 + + + True + + + True + + + メイリオ, 9pt + + + NoControl + + + 2, 6 + + + 0, 4, 0, 0 + + + 41, 18 + + + 37 + + + Mag.: + + + MiddleRight + + + label14 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 0 + + + True + + + メイリオ, 9pt + + + NoControl + + + 41, 6 + + + 0, 4, 0, 0 + + + 33, 18 + + + 38 + + + 00.0 + + + MiddleRight + + + labelResolution + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 1 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 95, 2 + + + 0, 0, 0, 0 + + + 34, 25 + + + 30 + + + × 1 + + + buttonMag1 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + 2 + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 129, 2 + + + 0, 0, 0, 0 + + + 34, 25 + + + 31 + + + × 2 + + + buttonMag2 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 3 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 163, 2 + + + 0, 0, 0, 0 + + + 34, 25 + + + 32 + + + × 4 + + + buttonMag4 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 4 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 197, 2 + + + 0, 0, 0, 0 + + + 45, 25 + + + 33 + + + × 1/2 + + + buttonMag_2 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 5 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 242, 2 + + + 0, 0, 0, 0 + + + 45, 25 + + + 34 + + + × 1/4 + + + buttonMag_4 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 6 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 287, 2 + + + 0, 0, 0, 0 + + + 45, 25 + + + 35 + + + × 1/8 + + + buttonMag_8 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 7 + + + True + + + GrowAndShrink + + + Segoe UI Symbol, 9pt + + + NoControl + + + 332, 2 + + + 0, 0, 0, 0 + + + 51, 25 + + + 36 + + + × 1/16 + + + buttonMag_16 + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 8 + + + True + + + Left + + + NoControl + + + 0, 2 + + + 2, 2, 2, 0 + + + 0, 2, 0, 0 + + + 0, 17 + + + 9 + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + 9 + + + Top + + + 0, 30 + + + 2, 2, 2, 2 + + + 0, 2, 0, 2 + + + 397, 29 + + + 15 + + + panel1 + + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + True diff --git a/Crystallography/Atom/Atoms.cs b/Crystallography/Atom/Atoms.cs index 7812d2c..c120166 100644 --- a/Crystallography/Atom/Atoms.cs +++ b/Crystallography/Atom/Atoms.cs @@ -49,7 +49,6 @@ public bool Equals(Atoms obj) public string Label; - [XmlIgnore] public string ElementName; [XmlIgnore] diff --git a/Crystallography/BetheMethod.cs b/Crystallography/BetheMethod.cs index 0ae42d7..8470a7c 100644 --- a/Crystallography/BetheMethod.cs +++ b/Crystallography/BetheMethod.cs @@ -965,7 +965,7 @@ public void stem_DoWork(object sender, DoWorkEventArgs e) bwSTEM.ReportProgress((int)(tempCoef * Interlocked.Increment(ref count)), "Calculating U matrix");//状況を報告 for (int j = 0; j < bLen; j++, k++) U[m][k] = getU(AccVoltage, q + Beams[j] - Beams[i], null, detAngleInner, detAngleOuter).Imag;//局所形式の場合 - //U[m][k] = getU(AccVoltage, q , -Beams[j] + Beams[i], detAngleInner, detAngleOuter).Imag;//非局所形式の場合は、これでいいのか?大塚さんに要確認。 + //U[m][k] = getU(AccVoltage, q , -Beams[j] + Beams[i], detAngleInner, detAngleOuter).Imag;//非局所形式の場合は、これでいいのか?大塚さんに要確認。 //var temp = new DMat(bLen, bLen, U[m]); //U[m] = temp.ToRowMajorArray(); diff --git a/Crystallography/Crystal/ConvertCrystalData.cs b/Crystallography/Crystal/ConvertCrystalData.cs index d1ef4f9..b1e83c5 100644 --- a/Crystallography/Crystal/ConvertCrystalData.cs +++ b/Crystallography/Crystal/ConvertCrystalData.cs @@ -969,13 +969,15 @@ private static Crystal2 ConvertFromCIF(List str) } //܂łCIF_GroupNX̃Xg - string a = "", b = "", c = "", alpha = "", beta = "", gamma = ""; + //iq萔́ACIFt@CɉLڂĂꍇ邽߁AXgɂB + List<(int index, string value)> aList = new(), bList = new(), cList = new(), alphaList = new(), betaList = new(), gammaList = new(); + string name = "", sectionTitle = "", journalNameFull = "", journalCodenASTM = ""; string volume = "", year = "", pageFirst = "", pageLast = "", issue = ""; - StringBuilder journal = new StringBuilder(); + var journal = new StringBuilder(); List spaceGroupNameHM = new(), spaceGroupNameHall = new(); string chemical_formula_sum = "", chemical_formula_structural = ""; - int symmetry_Int_Tables_number = -1; + var symmetry_Int_Tables_number = -1; var author = new List(); var operations = new List(); @@ -988,12 +990,13 @@ private static Crystal2 ConvertFromCIF(List str) if (label.StartsWith("_chemical_name", Ord)) name += data + " "; //iq萔 - if (label == "_cell_length_a") a = data; - else if (label == "_cell_length_b") b = data; - else if (label == "_cell_length_c") c = data; - else if (label == "_cell_angle_alpha") alpha = data; - else if (label == "_cell_angle_beta") beta = data; - else if (label == "_cell_angle_gamma") gamma = data; + if (label == "_cell_length_a") aList.Add((i,data)); + else if (label == "_cell_length_b") bList.Add((i, data)); + else if (label == "_cell_length_c") cList.Add((i, data)); + else if (label == "_cell_angle_alpha") alphaList.Add((i, data)); + else if (label == "_cell_angle_beta" ) betaList.Add((i, data)); + else if (label == "_cell_angle_gamma") gammaList.Add((i, data)); + //W[i else if (label == "_publ_author_name") author.Add(data); else if (label == "_publ_section_title") sectionTitle = data; @@ -1014,11 +1017,42 @@ private static Crystal2 ConvertFromCIF(List str) else if (label == "_symmetry_equiv_pos_as_xyz") operations.Add(data); } - if (a == "" || b == "" || c == "" || alpha == "" || beta == "" || gamma == "") return null; + if (aList.Count == 0 || bList.Count ==0 || cList.Count ==0 || alphaList.Count ==0 || betaList.Count == 0 || gammaList.Count == 0) return null; if (name.Length == 0 || name == "?" || name == "? ?" || name.Trim().Length == 0) name = chemical_formula_sum; + //"_atom_site_label"Ƃx܂CIFԍXgB (ŏ̘Aԍ݂̂g) + //ɁAiq萔List̒ŁAǂꂪlȂ̂𔻕ʂ + string a = "", b = "", c = "", alpha = "", beta = "", gamma = ""; + var atomCIF = new List>(); + bool flag = false; + for (int i = 0; i < CIF.Count; i++) + if (flag || atomCIF.Count == 0) + { + if (CIF[i].Exists(item => item.Label == "_atom_site_label")) + { + atomCIF.Add(CIF[i]); + flag = true; + } + else if(atomCIF.Count != 0) + { + flag = false; + a = aList.Count == 1 ? aList[0].value : aList.Last(e => e.index < i).value; + b = bList.Count == 1 ? bList[0].value : bList.Last(e => e.index < i).value; + c = cList.Count == 1 ? cList[0].value : cList.Last(e => e.index < i).value; + alpha = alphaList.Count == 1 ? alphaList[0].value : alphaList.Last(e => e.index < i).value; + beta = betaList.Count == 1 ? betaList[0].value : betaList.Last(e => e.index < i).value; + gamma = gammaList.Count == 1 ? gammaList[0].value : gammaList.Last(e => e.index < i).value; + } + } + if (a == "") a = aList[0].value; + if (b == "") b = bList[0].value; + if (c == "") c = cList[0].value; + if (alpha == "") alpha = alphaList[0].value; + if (beta == "") beta = betaList[0].value; + if (gamma == "") gamma = gammaList[0].value; + #region ԌQ𒲂ׂ镔 //ԌQ int sgnum = 0; @@ -1098,21 +1132,6 @@ Func func(string sExpr) #endregion - //"_atom_site_label"Ƃx܂CIFԍXgB (ŏ̘Aԍ݂̂g) - var atomCIF = new List>(); - bool flag = false; - for (int i = 0; i < CIF.Count; i++) - if (flag || atomCIF.Count == 0) - { - if (CIF[i].Exists(item => item.Label == "_atom_site_label")) - { - atomCIF.Add(CIF[i]); - flag = true; - } - else - flag = false; - } - var atoms = new List(); foreach (var cif in atomCIF) { diff --git a/Crystallography/Crystal/Crystal.cs b/Crystallography/Crystal/Crystal.cs index e57ffdd..b9bd006 100644 --- a/Crystallography/Crystal/Crystal.cs +++ b/Crystallography/Crystal/Crystal.cs @@ -880,37 +880,37 @@ public void SetPlanes(double dMax, double dMin, bool excludeEquivalentPlane, boo HorizontalAxis horizontalAxis, double horizontalThreshold, double horizontalParameter, int _maxNum = 8000) { if (A_Star == null) SetAxis(); + if (double.IsNaN(MatrixInverse.Column1.X)) return; - double aX = A_Star.X, aY = A_Star.Y, aZ = A_Star.Z; + double aX = A_Star.X, aY = A_Star.Y, aZ = A_Star.Z; double bX = B_Star.X, bY = B_Star.Y, bZ = B_Star.Z; double cX = C_Star.X, cY = C_Star.Y, cZ = C_Star.Z; var gMax = 1 / dMin; - (int h, int k, int l)[] directions = new[] { (1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1) };//(-1, 0, 0)͏Ă + (int h, int k, int l)[] directions = new[] { (1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1) }; var shift = directions.Select(dir => (MatrixInverse * dir).Length).Max(); + var maxNum = _maxNum; - var zeroKey = (255 << 20) + (255 << 10) + 255; - var outer = new List<(int key, double len)>() { (zeroKey, 0) }; - var gHash = new HashSet((int)(maxNum * 1.5)) { zeroKey }; + var outer = new List<(int H, int K, int L, double len)>() { (0, 0, 0, 0) }; + var gHash = new HashSet<(int H, int K, int L)>((int)(maxNum * 1.5)) { (0, 0, 0) }; //SĂhkl邽߁AcomposegȂƂɒ var minG = 0.0; var listPlane = new List((int)(maxNum * 1.5)); while (listPlane.Count < maxNum && (minG = outer.Min(o => o.len)) < gMax) { var end = outer.FindLastIndex(o => o.len - minG < shift * 2); - foreach (var (key1, _) in CollectionsMarshal.AsSpan(outer)[..(end + 1)]) + foreach (var (h1, k1, l1, _) in CollectionsMarshal.AsSpan(outer)[..(end + 1)]) { - var (h1, k1, l1) = decomposeKey(key1); foreach ((int h2, int k2, int l2) in directions) { - int h = h1 + h2, k = k1 + k2, l = l1 + l2, key2 = composeKey(h, k, l); - if (key2 > 0 && gHash.Add(key2)) + int h = h1 + h2, k = k1 + k2, l = l1 + l2; + if (gHash.Add((h, k, l))) { double x = h * aX + k * bX + l * cX, y = h * aY + k * bY + l * cY, z = h * aZ + k * bZ + l * cZ; var len = Math.Sqrt(x * x + y * y + z * z); - outer.Add((key2, len)); + outer.Add((h, k, l, len)); if (len < gMax && len > 1 / dMax) { var root = SymmetryStatic.IsRootIndex((h, k, l), Symmetry, out int multi); @@ -1102,6 +1102,13 @@ public void SetPlanes() #region tiqxNǧvZ + /// + /// h, k, l ̎wIntЂƂ‚ɕϊB(hkl) & h>0 邢 (0kl) & k > 0 邢 (00l) & l > 0 ̎w舵ȂƂɒ + /// + /// + /// + /// + /// static int composeKey(in int h, in int k, in int l) => ((h > 0) || (h == 0 && k > 0) || (h == 0 && k == 0 && l > 0)) ? ((h + 255) << 20) + ((k + 255) << 10) + l + 255 : -1; static (int h, int k, int l) decomposeKey(in int key) => (((key << 2) >> 22) - 255, ((key << 12) >> 22) - 255, ((key << 22) >> 22) - 255); diff --git a/Crystallography/Crystal/Plane.cs b/Crystallography/Crystal/Plane.cs index 2cb3049..4f1b8e5 100644 --- a/Crystallography/Crystal/Plane.cs +++ b/Crystallography/Crystal/Plane.cs @@ -1,105 +1,102 @@ using System; using System.Numerics; -namespace Crystallography +namespace Crystallography; + +/// +/// Plane ̊Tv̐łB +/// +[Serializable()] +public class Plane : IComparable { - /// - /// Plane ̊Tv̐łB - /// - [Serializable()] - public class Plane : System.IComparable + public PeakFunctionForm SerchOption; + + public double SerchRange = 0.10; + public double FWHM = 0.10; + public bool IsCombined;//ق̖ʂƌ()łƂTrue + + //public int multi;//dx + public int[] Multi = new int[1];//dx + + public bool IsRootIndex = false;//̖ʎw‚Ƃ + + public double MillimeterCalc, MillimeterObs; + public double Intensity;//ConbineĂƂ͋x̘a + public double RawIntensity; + + public double[] eachIntensity = new double[1];//CombineĂƂ͗vf2ȏɂȂ + public double observedIntensity; + public PointD simpleParameter; + public PeakFunction peakFunction = new(); + public double[] F2 = new double[1];//CombineĂƂ͗vf2ȏɂȂ + public Complex[] F = new Complex[1]; + public bool IsFittingSelected; + public bool IsFittingChecked; + public int DecompositionGroup; + public int h, k, l; + public int eH, eK, eL; + public double d; + public double dObs; + public double XObs; + public double XCalc; + public double Weight; + public string strHKL, strD; + public string[] strCondition = Array.Empty(); + public string str; + public int num; + + public double CosExpFactor; + public double SinExpFactor; + + public int CompareTo(object obj) { - public PeakFunctionForm SerchOption; - - public double SerchRange = 0.10; - public double FWHM = 0.10; - public bool IsCombined;//ق̖ʂƌ()łƂTrue - - //public int multi;//dx - public int[] Multi = new int[1];//dx - - public bool IsRootIndex = false;//̖ʎw‚Ƃ - - public double MillimeterCalc, MillimeterObs; - public double Intensity;//ConbineĂƂ͋x̘a - public double RawIntensity; - - public double[] eachIntensity = new double[1];//CombineĂƂ͗vf2ȏɂȂ - public double observedIntensity; - public PointD simpleParameter; - public PeakFunction peakFunction = new(); - public double[] F2 = new double[1];//CombineĂƂ͗vf2ȏɂȂ - public Complex[] F = new Complex[1]; - public bool IsFittingSelected; - public bool IsFittingChecked; - public int DecompositionGroup; - public int h, k, l; - public int eH, eK, eL; - public double d; - public double dObs; - public double XObs; - public double XCalc; - public double Weight; - public string strHKL, strD; - public string[] strCondition = Array.Empty(); - public string str; - public int num; - - public double CosExpFactor; - public double SinExpFactor; - - public int CompareTo(object obj) + var _p = obj as Plane; + if (d != _p.d) + return -d.CompareTo(_p.d); + else { - var _p = obj as Plane; - if (d != _p.d) - return -d.CompareTo(_p.d); + var _h = _p.h; + var _k = _p.k; + var _l = _p.l; + + if (h > _h || h == _h && k > _k || h == _h && k == _k && l > _l) + return -1; + else if (h == _h && k == _k && l == _l) + return 0; else - { - var _h = _p.h; - var _k = _p.k; - var _l = _p.l; - - if (h > _h || (h == _h && k > _k) || (h == _h && k == _k && l > _l)) - return -1; - else if (h == _h && k == _k && l == _l) - return 0; - else - return 1; - } - - + return 1; } + } - public override string ToString() - { - //return str.ToString(); - string s = (strHKL + " ").Remove(13);//󔒂}Ă10ڈȍ~Jbg - if (double.IsNaN(XCalc) || XCalc == 0) - s += " " + "##.####"; - else - s += $" {XCalc:00.0000}"; - - if (double.IsNaN(XObs) || XObs == 0) - s += " " + "##.####"; - else - s += $" {XObs:00.0000}"; - - if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(peakFunction.Hk) || peakFunction.Hk == 0 || double.IsInfinity(peakFunction.Hk)) - s += " " + "#.####"; - else - s += $" {peakFunction.Hk:0.0000}"; - - if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(Weight) || Weight == 0 || double.IsInfinity(Weight)) - s += " " + "###.#"; - else - s += $" {Weight:000.0}"; - - if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(observedIntensity) || observedIntensity == 0) - s += " " + "#######"; - else - s += $" {observedIntensity:000000}"; - - return s; - } + public override string ToString() + { + //return str.ToString(); + string s = (strHKL + " ").Remove(13);//󔒂}Ă10ڈȍ~Jbg + if (double.IsNaN(XCalc) || XCalc == 0) + s += " " + "##.####"; + else + s += $" {XCalc:00.0000}"; + + if (double.IsNaN(XObs) || XObs == 0) + s += " " + "##.####"; + else + s += $" {XObs:00.0000}"; + + if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(peakFunction.Hk) || peakFunction.Hk == 0 || double.IsInfinity(peakFunction.Hk)) + s += " " + "#.####"; + else + s += $" {peakFunction.Hk:0.0000}"; + + if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(Weight) || Weight == 0 || double.IsInfinity(Weight)) + s += " " + "###.#"; + else + s += $" {Weight:000.0}"; + + if (double.IsNaN(XObs) || XObs == 0 || double.IsNaN(observedIntensity) || observedIntensity == 0) + s += " " + "#######"; + else + s += $" {observedIntensity:000000}"; + + return s; } } \ No newline at end of file diff --git a/Crystallography/Crystal/PolyCrystal.cs b/Crystallography/Crystal/PolyCrystal.cs index e14db65..77fc91e 100644 --- a/Crystallography/Crystal/PolyCrystal.cs +++ b/Crystallography/Crystal/PolyCrystal.cs @@ -201,6 +201,9 @@ public void SetGVector(Crystal crystal, AreaDetector detector, bool applyTiltMat length = max; } crystal.SetVectorOfG(detector.WaveLength / 2 / Math.Sin(Math.Atan(length / detector.CameraLength) / 2.0), detector.WaveSource); + if (crystal.VectorOfG.Count == 0) + return; + var temp = new List(); foreach (var g in crystal.VectorOfG) if (removeZeroIntensity) diff --git a/Crystallography/Crystallography - Backup (1).csproj b/Crystallography/Crystallography - Backup (1).csproj new file mode 100644 index 0000000..233049a --- /dev/null +++ b/Crystallography/Crystallography - Backup (1).csproj @@ -0,0 +1,61 @@ + + + + Library + net7.0-windows + true + 2023.2.6.0222 + 2023.2.6.0222 + + + + true + False + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Crystallography/Crystallography - Backup.csproj b/Crystallography/Crystallography - Backup.csproj new file mode 100644 index 0000000..7205ff2 --- /dev/null +++ b/Crystallography/Crystallography - Backup.csproj @@ -0,0 +1,56 @@ + + + + Library + net7.0-windows + true + 2022.12.16.0206 + 2022.12.16.0206 + + + + true + False + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Crystallography/Crystallography.csproj b/Crystallography/Crystallography.csproj index 32150fc..37e4409 100644 --- a/Crystallography/Crystallography.csproj +++ b/Crystallography/Crystallography.csproj @@ -1,11 +1,11 @@ - + Library net7.0-windows true - 2022.12.3.0934 - 2022.12.3.0934 + 2023.2.10.1154 + 2023.2.10.1154 @@ -24,9 +24,10 @@ - + - + + @@ -53,4 +54,8 @@ + + + + diff --git a/Crystallography/Detector/Ring.cs b/Crystallography/Detector/Ring.cs index c8ecb86..54d0e71 100644 --- a/Crystallography/Detector/Ring.cs +++ b/Crystallography/Detector/Ring.cs @@ -306,10 +306,14 @@ public enum ImageTypeEnum public static PixelUnitEnum PixelUnit; */ + // DMt@Cׂ̈̃vpeB public static DigitalMicrograph.Property DigitalMicrographProperty; + //MRCt@Cׂ̈̃vpeB public static MRC MRC; + public static double TIA_PixelSize; + /// /// f[^̃sNZ̃rbg /// @@ -2082,7 +2086,7 @@ private static void GetProfileGandlfi(int xMin, int xMax, int yMin, int yMax, re //double tau = IP.tau; double CL = IP.FilmDistance; - Matrix3D m1 = new Matrix3D(CosTau, SinTau * SinPhi, SinTau * CosPhi, 0, CosPhi, -SinPhi, -SinTau, CosTau * SinPhi, CosTau * CosPhi); + var m1 = new Matrix3D(CosTau, SinTau * SinPhi, SinTau * CosPhi, 0, CosPhi, -SinPhi, -SinTau, CosTau * SinPhi, CosTau * CosPhi); //sNZWԍWɕϊFunc Func convPixelToReal; @@ -2144,7 +2148,7 @@ private static void GetProfileGandlfi(int xMin, int xMax, int yMin, int yMax, re { if (IsValid[x + y * width]) { - double intensity = Intensity[x + y * width]; + var intensity = Intensity[x + y * width]; // x, ysNZWԂɕϊ //l2߂ @@ -2154,7 +2158,9 @@ private static void GetProfileGandlfi(int xMin, int xMax, int yMin, int yMax, re twoThetaVertex[x - xMin + 1 + (y - yMin + 1) * (xMax - xMin + 1)], twoThetaVertex[x - xMin + (y - yMin + 1) * (xMax - xMin + 1)] }; - double maxTwoTheta = twoTheta.Max(), minTwoTheta = twoTheta.Min(); + + var (minTwoTheta, maxTwoTheta) = twoTheta.MinMax(); + //double maxTwoTheta = twoTheta.Max(), minTwoTheta = twoTheta.Min(); if (maxTwoTheta > divisions[0] && minTwoTheta < divisions[length - 1])//S؂ɃsNZ(ꕔł)܂ĂꍇiSɔ͈͊O̎͏Oj { diff --git a/Crystallography/Images/ImageIO.cs b/Crystallography/Images/ImageIO.cs index 6a60b87..9f67e92 100644 --- a/Crystallography/Images/ImageIO.cs +++ b/Crystallography/Images/ImageIO.cs @@ -9,7 +9,6 @@ using System.Xml.Serialization; namespace Crystallography; - public static class ImageIO { public static string[] ListOfExtension = @@ -26,7 +25,7 @@ public static class ImageIO "mccd", "his", "h5", - "dm*", + "dm?", "raw", "bmp", "jpg", @@ -52,11 +51,13 @@ public static string FilterString } } - public static bool IsReadable(string ext) + public static bool IsReadable(string _ext) { + var ext = _ext.StartsWith('.') ? _ext[1..] : _ext; return ListOfExtension.Contains(ext.ToLower()) || ext.StartsWith("0") || ext.StartsWith("mar") || ext.StartsWith("dm"); } + #region BinaryReaderから読み込んで整数や実数に変換 public static int convertToInt(BinaryReader br) { var b = new byte[4]; @@ -70,14 +71,16 @@ public static float convertToSingle(BinaryReader br) b[3] = br.ReadByte(); b[2] = br.ReadByte(); b[1] = br.ReadByte(); b[0] = br.ReadByte(); return BitConverter.ToSingle(b, 0); } - + public static void SetBytePosition(string str, ref BinaryReader br, int count) { br.Close(); br = new BinaryReader(new FileStream(str, FileMode.Open, FileAccess.Read)); br.ReadBytes(count); } + #endregion + #region 画像形式を判定する関数群 public static bool IsRAxisImage(string fileName) { var br = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)); @@ -134,6 +137,7 @@ public static bool Check_PF_RAW(string fileName) return str1 == "0236" && str2 == "0052"; } + #endregion /// /// 指定されたfileを読み込み、読み込んだ内容はRing.***に保存される。失敗したときはfalseを返す。flagはノーマライズするかどうか。 @@ -171,20 +175,22 @@ public static bool ReadImage(string str, bool? flag = null) if (strList != null && strList.Any() && strList[0].Contains("BAS_IMAGE_FILE", StringComparison.Ordinal))//BAS2000 result = ImageIO.BAS2000or2500(str, strList.ToArray()); else + { return false; + } } else if (File.Exists(str.Remove(str.Length - 3, 3) + "tem")) - result = ImageIO.FujiFDL(str); - else if (ImageIO.IsRAxisImage(str))//R-Axis5 - result = ImageIO.Raxis4(str); - else if (ImageIO.IsADXVImage(str)) - result = ImageIO.ADXV(str); - else if (ImageIO.IsITEXImage(str)) - result = ImageIO.ITEX(str); - else if (ImageIO.IsADSCImage(str)) - result = ImageIO.ADSC(str); - else if (ImageIO.IsTiffImage(str)) - result = ImageIO.Tiff(str); + result = FujiFDL(str); + else if (IsRAxisImage(str))//R-Axis5 + result = Raxis4(str); + else if (IsADXVImage(str)) + result = ADXV(str); + else if (IsITEXImage(str)) + result = ITEX(str); + else if (IsADSCImage(str)) + result = ADSC(str); + else if (IsTiffImage(str)) + result = Tiff(str); else return false; } @@ -943,8 +949,7 @@ public static bool HIS(string str) Ring.SrcImgSize = new Size(imageWidth, imageHeight); Ring.ImageType = Ring.ImageTypeEnum.HIS; - Ring.Comments = "Num. of Frame: " + numberOfFrame.ToString() + "\r\n" - + "Frame time: " + frameTimeInMilliseconds.ToString() + " ms."; + Ring.Comments = $"Num. of Frame: {numberOfFrame}\r\nFrame time: {frameTimeInMilliseconds} ms."; } catch (Exception e) { @@ -1578,10 +1583,10 @@ public static bool Tiff(string str, bool? normarize = null) Ring.Comments = ""; Ring.SrcImgSize = new Size(t.ImageWidth, t.ImageLength); - Ring.SequentialImageIntensities = new List>(); - Ring.SequentialImageEnergy = new List(); - Ring.SequentialImageNames = new List(); - Ring.SequentialImagePulsePower = new List(); + Ring.SequentialImageIntensities = new List>(t.NumberOfFrames); + Ring.SequentialImageEnergy = new List(t.NumberOfFrames); + Ring.SequentialImageNames = new List(t.NumberOfFrames); + Ring.SequentialImagePulsePower = new List(t.NumberOfFrames); for (int j = 0; j < t.NumberOfFrames; j++) { @@ -1617,6 +1622,10 @@ public static bool Tiff(string str, bool? normarize = null) //Ring.BitsPerPixels = t.BitsPerSampleGray; Ring.ImageType = Ring.ImageTypeEnum.Tiff; + + //TIA経由のTiffファイルだった時 + if (t.Images.Count > 0) + Ring.TIA_PixelSize = t.Images[0].TIA_PixelSizeX; } catch (Exception e) { @@ -1629,27 +1638,8 @@ public static bool Tiff(string str, bool? normarize = null) public static IPAImage IPAImageGenerator(double[] data, int width, int height, PointD center, double resolution, double cameralength, WaveProperty waveProperty) { - //double maxValue = double.NegativeInfinity; - - /*uint[] imageData = new uint[data.Length]; - for (int h = 0; h < height; h++) - for (int w = 0; w < width; w++) - if (!double.IsNaN(data[h * width + w])) - maxValue = Math.Max(data[h * width + w], maxValue); - - for (int h = 0; h < height; h++) - for (int w = 0; w < width; w++) - if (!double.IsNaN(data[h * width + w])) - imageData[h * width + w] = (uint)(data[h * width + w] / maxValue * uint.MaxValue); - else - - imageData[h * width + w] = 0; - */ - IPAImage ipa = new IPAImage { - //ipa.Scale = maxValue / uint.MaxValue; - //ipa.Intensity = imageData; IntensityDouble = data, Width = width, Height = height, diff --git a/Crystallography/Images/ImageProcessor.cs b/Crystallography/Images/ImageProcessor.cs index 405c4ca..83a6777 100644 --- a/Crystallography/Images/ImageProcessor.cs +++ b/Crystallography/Images/ImageProcessor.cs @@ -1,102 +1,102 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; -namespace Crystallography +namespace Crystallography; +public static class ImageProcess { - public static class ImageProcess + /// + /// GaussianBlurを施す。 + /// + /// 画像データの一次元配列 + /// 画像の幅 + /// ピクセル単位でのフィルムにじみ半値幅 + /// + unsafe static public double[] GaussianBlur(double[] pixels, int width, double radius) { - /// - /// GaussianBlurを施す。 - /// - /// 画像データの一次元配列 - /// 画像の幅 - /// ピクセル単位でのフィルムにじみ半値幅 - /// - unsafe static public double[] GaussianBlur(double[] pixels, int width, double radius) + /* var src = Cv.Mat(width, pixels.Length / width, MatrixType.F64C1, pixels); + var dst = src.Clone(); + src.Smooth(dst, SmoothType.Gaussian, (int)(radius * 3) * 2 + 1, 0, radius, radius); + double[] results = new double[pixels.Length]; + Marshal.Copy(dst.DataArrayDouble.Ptr, results, 0, pixels.Length); + + return results; + */ + int limit = (int)(radius * 2) * 2 + 1; + int center = limit / 2; + int height = pixels.Length / width; + if (limit == 1 || width * height != pixels.Length) + return pixels.ToArray(); + + Dictionary tempDic = new Dictionary(); + + for (int h = 0; h < limit; h++) + for (int w = 0; w < limit; w++) + if ((h - center) * (h - center) + (w - center) * (w - center) <= center * center) + tempDic.Add((h - center) * width + w - center, Math.Exp(-((h - center) * (h - center) + (w - center) * (w - center)) / radius / radius * Math.Log(2))); + double sum = tempDic.Values.Sum(); + var pair = tempDic.OrderBy(d => d.Value).ToArray(); + pair = pair.Select(d => new KeyValuePair(d.Key, d.Value / sum)).ToArray(); + + double[] blurredPixels = new double[pixels.Length]; + + int thread = Environment.ProcessorCount; + + ParallelOptions p = new ParallelOptions { MaxDegreeOfParallelism = thread }; + + double[][] blurTemp = new double[thread][]; + Parallel.For(0, thread, p, i => { - /* var src = Cv.Mat(width, pixels.Length / width, MatrixType.F64C1, pixels); - var dst = src.Clone(); - src.Smooth(dst, SmoothType.Gaussian, (int)(radius * 3) * 2 + 1, 0, radius, radius); - double[] results = new double[pixels.Length]; - Marshal.Copy(dst.DataArrayDouble.Ptr, results, 0, pixels.Length); - - return results; - */ - int limit = (int)(radius * 2) * 2 + 1; - int center = limit / 2; - int height = pixels.Length / width; - if (limit == 1 || width * height != pixels.Length) - return pixels.ToArray(); - - Dictionary tempDic = new Dictionary(); - - for (int h = 0; h < limit; h++) - for (int w = 0; w < limit; w++) - if ((h - center) * (h - center) + (w - center) * (w - center) <= center * center) - tempDic.Add((h - center) * width + w - center, Math.Exp(-((h - center) * (h - center) + (w - center) * (w - center)) / radius / radius * Math.Log(2))); - double sum = tempDic.Values.Sum(); - var pair = tempDic.OrderBy(d => d.Value).ToArray(); - pair = pair.Select(d => new KeyValuePair(d.Key, d.Value / sum)).ToArray(); - - double[] blurredPixels = new double[pixels.Length]; - - int thread = Environment.ProcessorCount; - - ParallelOptions p = new ParallelOptions { MaxDegreeOfParallelism = thread }; - - double[][] blurTemp = new double[thread][]; - Parallel.For(0, thread, p, i => + blurTemp[i] = new double[pixels.Length]; + for (int j = pair.Length / thread * i; j < Math.Min(pair.Length / thread * (i + 1), pair.Length); j++) { - blurTemp[i] = new double[pixels.Length]; - for (int j = pair.Length / thread * i; j < Math.Min(pair.Length / thread * (i + 1), pair.Length); j++) + double b = pair[j].Value; + int shift = pair[j].Key; + int start = Math.Max(-shift, 0); + int end = Math.Min(pixels.Length - shift, pixels.Length); + fixed (double* s = &pixels[start], d = &blurTemp[i][start + shift]) { - double b = pair[j].Value; - int shift = pair[j].Key; - int start = Math.Max(-shift, 0); - int end = Math.Min(pixels.Length - shift, pixels.Length); - fixed (double* s = &pixels[start], d = &blurTemp[i][start + shift]) - { - for (int k = 0; k < end - start; k++) - *(d + k) += b * (*(s + k)); - } + for (int k = 0; k < end - start; k++) + *(d + k) += b * (*(s + k)); } } - ); - for (int i = 1; i < thread; i++) - for (int j = 0; j < pixels.Length; j++) - blurTemp[0][j] += blurTemp[i][j]; - - return blurTemp[0]; } + ); + for (int i = 1; i < thread; i++) + for (int j = 0; j < pixels.Length; j++) + blurTemp[0][j] += blurTemp[i][j]; - /// - /// GaussianBlurを施す。横方向と縦方向を分離するため、高速。 - /// - /// 画像データの一次元配列 - /// 画像の幅 - /// ピクセル単位でのフィルムにじみ半値半幅  - /// - unsafe static public double[] GaussianBlurFast(double[] pixels, int width, double hwhm) - { - - int limit = (int)(hwhm * 3) * 2 + 1; - int height = pixels.Length / width; - - int center = limit / 2; + return blurTemp[0]; + } - double[] pixelsFilmBlur1 = new double[width * height]; - double[] pixelsFilmBlur2 = new double[width * height]; + /// + /// GaussianBlurを施す。横方向と縦方向を分離するため、高速。 + /// + /// 画像データの一次元配列 + /// 画像の幅 + /// ピクセル単位でのフィルムにじみ半値半幅  + /// + unsafe static public double[] GaussianBlurFast(double[] pixels, int width, double hwhm) + { - if (limit == 1) - { - for (int i = 0; i < pixels.Length; i++) pixelsFilmBlur2[i] = pixels[i]; - return pixelsFilmBlur2; - } + int limit = (int)(hwhm * 3) * 2 + 1; + int height = pixels.Length / width; + int center = limit / 2; + + var results = new double[width * height]; + if (limit == 1) + { + Array.Copy(pixels, results, pixels.Length); + return results; + } - double[] blur = new double[limit]; + var tmpPixels = ArrayPool.Shared.Rent(width * height); + try + { + var blur = new double[limit]; for (int h = 0; h < limit; h++) blur[h] = Math.Exp(-(h - center) * (h - center) / hwhm / hwhm * Math.Log(2)); blur = Statistics.Normarize(blur); @@ -105,155 +105,140 @@ unsafe static public double[] GaussianBlurFast(double[] pixels, int width, doubl { for (int h = 0; h < height; h++) { - //if (pixels[h * width + w] != 0) - //for (int n = Math.Max(0, center - h); n < Math.Min(blur.Length, height - h + center); n++) - // pixelsFilmBlur1[(h - center + n) * width + w] += blur[n] * pixels[h * width + w]; - + tmpPixels[h * width + w] = 0; for (int n = Math.Max(0, center - h); n < Math.Min(blur.Length, height - h + center); n++) - pixelsFilmBlur1[h * width + w] += blur[n] * pixels[(h - center + n) * width + w]; + tmpPixels[h * width + w] += blur[n] * pixels[(h - center + n) * width + w]; } }); Parallel.For(0, height, h => { for (int w = 0; w < width; w++) - { - //if (pixelsFilmBlur1[h * width + w] != 0) - //for (int n = Math.Max(0, center - w); n < Math.Min(blur.Length, width - w + center); n++) - // pixelsFilmBlur2[h * width + w - center + n] += blur[n] * pixelsFilmBlur1[h * width + w]; for (int n = Math.Max(0, center - w); n < Math.Min(blur.Length, width - w + center); n++) - pixelsFilmBlur2[h * width + w] += blur[n] * pixelsFilmBlur1[h * width + w - center + n]; - } + results[h * width + w] += blur[n] * tmpPixels[h * width + w - center + n]; }); - pixelsFilmBlur1 = null; - - return pixelsFilmBlur2; } + finally { ArrayPool.Shared.Return(tmpPixels); } - /// - /// 周囲のピクセルと比べて、標準偏差 × threshold以上外れたピクセルは、周囲のピクセルの平均強度にする。 - /// - /// - /// - /// - /// - unsafe static public double[] DustAndScratches(double[] pixels, int width, double radius, double threshold) - { - var results = new double[pixels.Length]; - Array.Copy(pixels, results, pixels.Length); - int height = pixels.Length / width; + return results; + } - var index = new List(); - for (int h = -(int)(radius + 1); h < (int)(radius + 1); h++) - for (int w = -(int)(radius + 1); w < (int)(radius + 1); w++) - if (h * h + w * w <= radius * radius && h * h + w * w != 0) - index.Add(h * width + w); + /// + /// 周囲のピクセルと比べて、標準偏差 × threshold以上外れたピクセルは、周囲のピクセルの平均強度にする。 + /// + /// + /// + /// + /// + unsafe static public double[] DustAndScratches(double[] pixels, int width, double radius, double threshold) + { + var results = new double[pixels.Length]; + Array.Copy(pixels, results, pixels.Length); - Parallel.For(1, height - 1, y => - { - double[] list1 = new double[index.Count]; - double[] list2 = new double[index.Count >= 8 ? index.Count / 8 * 6 : index.Count]; - int pos = y * width; - fixed (double* s = &pixels[pos], d = &results[pos]) - { - double* src = s, dst = d; - for (int x = 1; x < width - 1; x++) - { - src++; - dst++; - - for (int i = 0; i < index.Count; i++) - list1[i] = *(src + index[i]); - Array.Sort(list1); - Array.Copy(list1, list1.Length / 8, list2, 0, list2.Length); - if (list2[0] > *src || list2[^1] < *src) - { - double sum = 0, sumSquare = 0; - for (int i = 0; i < list2.Length; i++) - { - sum += list2[i]; - sumSquare += list2[i] * list2[i]; - } - double average = sum / list2.Length; - double valiance = sumSquare / list2.Length - average * average; - - if ((*src - average) * (*src - average) > valiance * threshold * threshold) - *dst = average; - } - } - } - }); + int height = pixels.Length / width; + + var radiusPlusOne = (int)(radius + 1); + + var index = new List(); + for (int h = -radiusPlusOne; h < radiusPlusOne; h++) + for (int w = -radiusPlusOne; w < radiusPlusOne; w++) + if (h * h + w * w <= radius * radius && h * h + w * w != 0) + index.Add(h * width + w); + + if (index.Count == 0) return results; - } - private static readonly object lockObj = new object(); - - /// - /// 画像中から、スポットを検出する。戻り値はList. X, Y: スポットのピクセル上の位置, Int: 強度 - /// - /// - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static public List<(double X, double Y, double Int)> FindSpots(double[] pixels, int width, double distanceOfNearestSpots = 5, int candidateNum = 500, IEnumerable<(double X, double Y)> activeSpots = null) + Parallel.For(radiusPlusOne, height - radiusPlusOne, y => { - if (pixels == null) return null; - var height = pixels.Length / width; - var d = Deviate(pixels, width); - - //隣り合っているピクセルより小さな値を持つ場合はtrue - var mList = new List<(int x, int y, double dev)>(); - Parallel.For(1, height - 1, y => - { - for (int x = 1; x < width - 1; x++) - { - var i = y * width + x; - var v = d[i]; - if (v < 0 && v < d[i + 1] && v < d[i - 1] && v < d[i + width] && v < d[i - width] && v < d[i + 1 + width] && v < d[i - 1 + width] && v < d[i + 1 - width] && v < d[i - 1 - width]) - lock (lockObj) - mList.Add((x, y, v)); - } - }); - mList.Sort((a, b) => (a.dev - b.dev > 0) ? 1 : (a.dev - b.dev < 0) ? -1 : 0); - - //minimumListの中から候補ピクセルを選出 - var list = new List<(int x, int y)>(); - var d2 = distanceOfNearestSpots * distanceOfNearestSpots; - for (int i = 0; i < mList.Count && list.Count < candidateNum; i++) - if (list.All(l => (mList[i].x - l.x) * (mList[i].x - l.x) + (mList[i].y - l.y) * (mList[i].y - l.y) > d2) && - (activeSpots == null || !activeSpots.Any() || - activeSpots.All(s => (mList[i].x - s.X) * (mList[i].x - s.X) + (mList[i].y - s.Y) * (mList[i].y - s.Y) > d2))) - list.Add((mList[i].x, mList[i].y)); - - //最後に自身を含めて周囲9ピクセルの平均強度を格納 - var vec = new List<(double X, double Y, double Int)>(); - for (int i = 0; i < list.Count; i++) + double[] list1 = new double[index.Count]; + int pos = y * width; + fixed (double* s = &pixels[pos + radiusPlusOne], d = &results[pos + radiusPlusOne]) { - var intensity = 0.0; - for (int xx = list[i].x - 1; xx < list[i].x + 2; xx++) - for (int yy = list[i].y - 1; yy < list[i].y + 2; yy++) - intensity += pixels[xx + yy * width] / 9.0; - vec.Add((list[i].x, list[i].y, intensity)); + double* src = s, dst = d; + for (int x = radiusPlusOne; x < width - radiusPlusOne; x++, src++, dst++) + { + for (int i = 0; i < index.Count; i++) + list1[i] = *(src + index[i]); + double average = list1.Average(); + double valiance = list1.Average(e => e * e) - average * average; + + if ((*src - average) * (*src - average) > valiance * threshold * threshold) + *dst = average; + } } - return vec; - } + }); + return results; + } - /// - /// 画像を微分する - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static public double[] Deviate(double[] pixels, int width) + private static readonly object lockObj = new object(); + + /// + /// 画像中から、スポットを検出する。戻り値はList. X, Y: スポットのピクセル上の位置, Int: 強度 + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static public List<(double X, double Y, double Int)> FindSpots(double[] pixels, int width, double distanceOfNearestSpots = 5, int candidateNum = 500, IEnumerable<(double X, double Y)> activeSpots = null) + { + if (pixels == null) return null; + var height = pixels.Length / width; + var d = Deviate(pixels, width); + + //隣り合っているピクセルより小さな値を持つ場合はtrue + var mList = new List<(int x, int y, double dev)>(); + Parallel.For(1, height - 1, y => + { + for (int x = 1; x < width - 1; x++) + { + var i = y * width + x; + var v = d[i]; + if (v < 0 && v < d[i + 1] && v < d[i - 1] && v < d[i + width] && v < d[i - width] && v < d[i + 1 + width] && v < d[i - 1 + width] && v < d[i + 1 - width] && v < d[i - 1 - width]) + lock (lockObj) + mList.Add((x, y, v)); + } + }); + mList.Sort((a, b) => (a.dev - b.dev > 0) ? 1 : (a.dev - b.dev < 0) ? -1 : 0); + + //minimumListの中から候補ピクセルを選出 + var list = new List<(int x, int y)>(); + var d2 = distanceOfNearestSpots * distanceOfNearestSpots; + for (int i = 0; i < mList.Count && list.Count < candidateNum; i++) + if (list.All(l => (mList[i].x - l.x) * (mList[i].x - l.x) + (mList[i].y - l.y) * (mList[i].y - l.y) > d2) && + (activeSpots == null || !activeSpots.Any() || + activeSpots.All(s => (mList[i].x - s.X) * (mList[i].x - s.X) + (mList[i].y - s.Y) * (mList[i].y - s.Y) > d2))) + list.Add((mList[i].x, mList[i].y)); + + //最後に自身を含めて周囲9ピクセルの平均強度を格納 + var vec = new List<(double X, double Y, double Int)>(); + for (int i = 0; i < list.Count; i++) { - //画像を上下左右方向に微分する - var height = pixels.Length / width; + var intensity = 0.0; + for (int xx = list[i].x - 1; xx < list[i].x + 2; xx++) + for (int yy = list[i].y - 1; yy < list[i].y + 2; yy++) + intensity += pixels[xx + yy * width] / 9.0; + vec.Add((list[i].x, list[i].y, intensity)); + } + return vec; + } - var pixelsH1 = new double[pixels.Length]; - var pixelsV1 = new double[pixels.Length]; + /// + /// 画像を微分する + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static public double[] Deviate(double[] pixels, int width) + { + //画像を上下左右方向に微分する + var height = pixels.Length / width; + var pixelsH1 = ArrayPool.Shared.Rent(pixels.Length); + var pixelsV1 = ArrayPool.Shared.Rent(pixels.Length); + try + { Parallel.For(0, height - 1, y => { for (int x = 0; x < width - 1; x++) @@ -275,68 +260,73 @@ static public double[] Deviate(double[] pixels, int width) }); return pixelsResults; } - - /// - /// 画像中からラインプロファイルを取得する - /// - /// なるべくParallelQuery<(double X, double Y, double Z)>の方がよい - /// - /// - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - static public PointD[] GetLineProfile(IEnumerable<(double X, double Y, double Z)> pixels, PointD start, PointD end, double width, double resolution) + finally { - //基本直線の式 a x + b y = c - (double a, double b, double c) line = (end.Y - start.Y, start.X - end.X, (end.Y - start.Y) * start.X + (start.X - end.X) * start.Y); + ArrayPool.Shared.Return(pixelsH1); + ArrayPool.Shared.Return(pixelsV1); + } + } - //候補となるピクセルは、以下の4本の直線(ax+by=c)の内部に存在するはず。 - (double a, double b, double c) parallel1 = (-line.a, -line.b, -line.c - width * Math.Sqrt(line.a * line.a + line.b * line.b)); - (double a, double b, double c) parallel2 = (line.a, line.b, line.c - width * Math.Sqrt(line.a * line.a + line.b * line.b)); + /// + /// 画像中からラインプロファイルを取得する + /// + /// なるべくParallelQuery<(double X, double Y, double Z)>の方がよい + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static public PointD[] GetLineProfile(IEnumerable<(double X, double Y, double Z)> pixels, PointD start, PointD end, double width, double resolution) + { + //基本直線の式 a x + b y = c + (double a, double b, double c) line = (end.Y - start.Y, start.X - end.X, (end.Y - start.Y) * start.X + (start.X - end.X) * start.Y); - //(double a, double b, double c) normal1 = (-line.b, line.a, -line.b * start.X + line.a * start.Y); - //(double a, double b, double c) normal2 = (line.b, -line.a, line.b * end.X - line.a * end.Y); + //候補となるピクセルは、以下の4本の直線(ax+by=c)の内部に存在するはず。 + (double a, double b, double c) parallel1 = (-line.a, -line.b, -line.c - width * Math.Sqrt(line.a * line.a + line.b * line.b)); + (double a, double b, double c) parallel2 = (line.a, line.b, line.c - width * Math.Sqrt(line.a * line.a + line.b * line.b)); - var pixelsP = pixels is ParallelQuery<(double X, double Y, double Z)> query ? query : pixels.AsParallel(); - var targetPixels = pixelsP.Where(pix => - { - (double X, double Y, double Z) = pix; - var pts = new (double X, double Y)[] { (X - .5, Y - .5), (X + .5, Y - .5), (X + .5, Y + .5), (X - .5, Y + .5) }; - return pts.Any(p => p.X * parallel1.a + p.Y * parallel1.b >= parallel1.c) && pts.Any(p => p.X * parallel2.a + p.Y * parallel2.b >= parallel2.c); - }).ToArray(); - - var profile = new List(); - var profileLength = (end - start).Length; - var vec = (end - start) / profileLength; - var center = (start + end) / 2; - - var startX = -(int)(profileLength / 2.0 / resolution + 0.5); - return Enumerable.Range(startX, -startX * 2 + 1).ToList().AsParallel().Select(n => - { - var s = center + resolution * (n - 0.5) * vec; - var e = s + resolution * vec; - (double a, double b, double c) normal1 = (-line.b, line.a, -line.b * s.X + line.a * s.Y); - (double a, double b, double c) normal2 = (line.b, -line.a, line.b * e.X - line.a * e.Y); + //(double a, double b, double c) normal1 = (-line.b, line.a, -line.b * start.X + line.a * start.Y); + //(double a, double b, double c) normal2 = (line.b, -line.a, line.b * end.X - line.a * end.Y); + + var pixelsP = pixels is ParallelQuery<(double X, double Y, double Z)> query ? query : pixels.AsParallel(); + var targetPixels = pixelsP.Where(pix => + { + (double X, double Y, double Z) = pix; + var pts = new (double X, double Y)[] { (X - .5, Y - .5), (X + .5, Y - .5), (X + .5, Y + .5), (X - .5, Y + .5) }; + return pts.Any(p => p.X * parallel1.a + p.Y * parallel1.b >= parallel1.c) && pts.Any(p => p.X * parallel2.a + p.Y * parallel2.b >= parallel2.c); + }).ToArray(); + + var profile = new List(); + var profileLength = (end - start).Length; + var vec = (end - start) / profileLength; + var center = (start + end) / 2; + + var startX = -(int)(profileLength / 2.0 / resolution + 0.5); + return Enumerable.Range(startX, -startX * 2 + 1).ToList().AsParallel().Select(n => + { + var s = center + resolution * (n - 0.5) * vec; + var e = s + resolution * vec; + (double a, double b, double c) normal1 = (-line.b, line.a, -line.b * s.X + line.a * s.Y); + (double a, double b, double c) normal2 = (line.b, -line.a, line.b * e.X - line.a * e.Y); - double intensity = 0, area = 0; - foreach ((double x, double y, double z) in targetPixels) + double intensity = 0, area = 0; + foreach ((double x, double y, double z) in targetPixels) + { + var pts = new[] { (x - .5, y - .5), (x + .5, y - .5), (x + .5, y + .5), (x - .5, y + .5) }; + pts = Geometriy.GetPolygonDividedByLine(pts, normal1.a, normal1.b, normal1.c); + pts = Geometriy.GetPolygonDividedByLine(pts, normal2.a, normal2.b, normal2.c); + pts = Geometriy.GetPolygonDividedByLine(pts, parallel1.a, parallel1.b, parallel1.c); + pts = Geometriy.GetPolygonDividedByLine(pts, parallel2.a, parallel2.b, parallel2.c); + if (pts.Length > 2) { - var pts = new[] { (x - .5, y - .5), (x + .5, y - .5), (x + .5, y + .5), (x - .5, y + .5) }; - pts = Geometriy.GetPolygonDividedByLine(pts, normal1.a, normal1.b, normal1.c); - pts = Geometriy.GetPolygonDividedByLine(pts, normal2.a, normal2.b, normal2.c); - pts = Geometriy.GetPolygonDividedByLine(pts, parallel1.a, parallel1.b, parallel1.c); - pts = Geometriy.GetPolygonDividedByLine(pts, parallel2.a, parallel2.b, parallel2.c); - if (pts.Length > 2) - { - var a = Geometriy.GetPolygonalArea(pts); - area += a; - intensity += z * a; - } + var a = Geometriy.GetPolygonalArea(pts); + area += a; + intensity += z * a; } - return new PointD(n * resolution, area > 0 ? intensity / area : 0); - }).ToArray(); - } + } + return new PointD(n * resolution, area > 0 ? intensity / area : 0); + }).ToArray(); } } \ No newline at end of file diff --git a/Crystallography/Images/PseudoBitmap.cs b/Crystallography/Images/PseudoBitmap.cs index 812dae9..7c67528 100644 --- a/Crystallography/Images/PseudoBitmap.cs +++ b/Crystallography/Images/PseudoBitmap.cs @@ -686,12 +686,8 @@ public Complex[] GetPixelComplex(int x, int y) /// public Bitmap GetImage() { - var bmp = GetImage(new RectangleD(0, 0, Width, Height), new Size(Width, Height)); - - return bmp; - } /// diff --git a/Crystallography/Images/Tiff.cs b/Crystallography/Images/Tiff.cs index 9b190d1..53a816e 100644 --- a/Crystallography/Images/Tiff.cs +++ b/Crystallography/Images/Tiff.cs @@ -340,8 +340,8 @@ public class imageProperty /// public int ImageLength; - public double XResolution; - public double YResolution; + public double ResolutionX; + public double ResolutionY; /// /// 1: 整数, 3:float @@ -382,6 +382,11 @@ public class imageProperty public string Name = ""; public double PulsePower = double.NaN; + + //TIAというソフトからエクスポートされるTEM写真(emiファイル)のピクセルサイズ + public double TIA_PixelSizeX;//65450 + public double TIA_PixelSizeY;//65451 + public int TIA_PixelSizeUnit;//65452 } public static byte[] Read(BinaryReader br, long position, int length, TiffByteOrder byteOrder) @@ -495,19 +500,19 @@ public Loader(string fileName) case 282: if (iFD[i].Data[0] is int n) - image.XResolution = n; + image.ResolutionX = n; else if (iFD[i].Data[0] is float f) - image.XResolution = f; + image.ResolutionX = f; else if (iFD[i].Data[0] is double d) - image.XResolution = d; + image.ResolutionX = d; break; case 283: if (iFD[i].Data[0] is int n2) - image.YResolution = n2; + image.ResolutionY = n2; else if (iFD[i].Data[0] is float f) - image.YResolution = f; + image.ResolutionY = f; else if (iFD[i].Data[0] is double d) - image.YResolution = d; + image.ResolutionY = d; break; case 284: image.ResolutionUnit = (int)iFD[i].Data[0]; break; @@ -551,6 +556,13 @@ public Loader(string fileName) case 60002: image.PulsePower = (double)iFD[i].Data[0]; break; + + case 65450: + image.TIA_PixelSizeX = (double)iFD[i].Data[0]; break; + case 65451: + image.TIA_PixelSizeY = (double)iFD[i].Data[0]; break; + case 65452: + image.TIA_PixelSizeUnit = (int)iFD[i].Data[0]; break; } #endregion diff --git a/Crystallography/Mathematics/Geometriy.cs b/Crystallography/Mathematics/Geometriy.cs index afd1270..ce94ee7 100644 --- a/Crystallography/Mathematics/Geometriy.cs +++ b/Crystallography/Mathematics/Geometriy.cs @@ -1,1076 +1,1127 @@ using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; using System; +using System.Collections; using System.Collections.Generic; +using System.Drawing; using System.Linq; +using System.Runtime.InteropServices; -namespace Crystallography +namespace Crystallography; + +public static class Geometriy { - public static class Geometriy + static Geometriy() + { + MathNet.Numerics.Control.TryUseNativeMKL(); + } + + /// + /// ȉ~Ƃ5_ȏ̓_pt[]^ꂽƂŏ2@璆SʒuԂ֐ + /// + /// + /// + /// + public static PointD GetEllipseCenter(PointD[] pt) { - static Geometriy() + //܂ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1 Ƃ a,b,c,d,e5‚̃p[^ŏQ@狁߂ + if (pt.Length < 8) return new PointD(double.NaN, double.NaN); + var Q = new DenseMatrix(pt.Length, 5); + for (int i = 0; i < pt.Length; i++) { - MathNet.Numerics.Control.TryUseNativeMKL(); + Q[i, 0] = pt[i].X * pt[i].X; + Q[i, 1] = pt[i].X * pt[i].Y; + Q[i, 2] = pt[i].Y * pt[i].Y; + Q[i, 3] = pt[i].X; + Q[i, 4] = pt[i].Y; } + var A = new DenseVector(pt.Length); + for (int i = 0; i < pt.Length; i++) + A[i] = 1000000; + if (!(Q.Transpose() * Q).TryInverse(out Matrix inv)) + return new PointD(double.NaN, double.NaN); + var C = inv * Q.Transpose() * A; + + double a = C[0], b = C[1], c = C[2], d = C[3], e = C[4]; + //̂Ƃ̕sړ(‚܂蒆Sʒu) + //return new PointD(-d / 2 / a, -e / 2 / c); + return new PointD(-(b * e - 2 * c * d) / (b * b - 4 * a * c), -(b * d - 2 * a * e) / (b * b - 4 * a * c)); + } - /// - /// ȉ~Ƃ5_ȏ̓_pt[]^ꂽƂŏ2@璆SʒuԂ֐ - /// - /// - /// - /// - public static PointD GetEllipseCenter(PointD[] pt) + /// + /// ^ꂽPointD[]ɂƂ߂ȉ~̕ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1000000 a,b,c,d,e5‚̃p[^Ԃ + /// + /// + /// + public static double[] GetParameterOfCurveOfSecondaryDegree(PointD[] point) + { + //܂ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1000000 Ƃ a,b,c,d,e5‚̃p[^ŏQ@狁߂ + var pt = new List(); + for (int i = 0; i < point.Length; i++) + if (!double.IsNaN(point[i].X)) + pt.Add(point[i]); + + if (pt.Count < 5) return null; + var Q = new DenseMatrix(pt.Count, 5); + for (int i = 0; i < pt.Count; i++) { - //܂ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1 Ƃ a,b,c,d,e5‚̃p[^ŏQ@狁߂ - if (pt.Length < 8) return new PointD(double.NaN, double.NaN); - var Q = new DenseMatrix(pt.Length, 5); - for (int i = 0; i < pt.Length; i++) - { - Q[i, 0] = pt[i].X * pt[i].X; - Q[i, 1] = pt[i].X * pt[i].Y; - Q[i, 2] = pt[i].Y * pt[i].Y; - Q[i, 3] = pt[i].X; - Q[i, 4] = pt[i].Y; - } - var A = new DenseMatrix(pt.Length, 1); - for (int i = 0; i < pt.Length; i++) - A[i, 0] = 1000000; - if (!(Q.Transpose() * Q).TryInverse(out Matrix inv)) - return new PointD(double.NaN, double.NaN); - var C = inv * Q.Transpose() * A; - - double a = C[0, 0]; - double b = C[1, 0]; - double c = C[2, 0]; - double d = C[3, 0]; - double e = C[4, 0]; - //̂Ƃ̕sړ(‚܂蒆Sʒu) - //return new PointD(-d / 2 / a, -e / 2 / c); - return new PointD(-(b * e - 2 * c * d) / (b * b - 4 * a * c), -(b * d - 2 * a * e) / (b * b - 4 * a * c)); + Q[i, 0] = pt[i].X * pt[i].X; + Q[i, 1] = pt[i].X * pt[i].Y; + Q[i, 2] = pt[i].Y * pt[i].Y; + Q[i, 3] = pt[i].X; + Q[i, 4] = pt[i].Y; } + var A = new DenseVector(pt.Count); + for (int i = 0; i < pt.Count; i++) + A[i] = 1000000; - /// - /// ^ꂽPointD[]ɂƂ߂ȉ~̕ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1000000 a,b,c,d,e5‚̃p[^Ԃ - /// - /// - /// - public static double[] GetParameterOfCurveOfSecondaryDegree(PointD[] point) - { - //܂ a*x^2 + b*x*y + c*y^2 + d*x + e*y = 1000000 Ƃ a,b,c,d,e5‚̃p[^ŏQ@狁߂ - var pt = new List(); - for (int i = 0; i < point.Length; i++) - if (!double.IsNaN(point[i].X)) - pt.Add(point[i]); - - if (pt.Count < 5) return null; - var Q = new DenseMatrix(pt.Count, 5); - for (int i = 0; i < pt.Count; i++) - { - Q[i, 0] = pt[i].X * pt[i].X; - Q[i, 1] = pt[i].X * pt[i].Y; - Q[i, 2] = pt[i].Y * pt[i].Y; - Q[i, 3] = pt[i].X; - Q[i, 4] = pt[i].Y; - } - var A = new DenseVector(pt.Count); - for (int i = 0; i < pt.Count; i++) - A[i] = 1000000; + if (!(Q.Transpose() * Q).TryInverse(out Matrix inv)) + return null; - if (!(Q.Transpose() * Q).TryInverse(out Matrix inv)) - return null; + var C = inv * Q.Transpose() * A; - var C = inv * Q.Transpose() * A; + //catch { return null; } + double a = C[0]; + double b = C[1]; + double c = C[2]; + double d = C[3]; + double e = C[4]; - //catch { return null; } - double a = C[0]; - double b = C[1]; - double c = C[2]; - double d = C[3]; - double e = C[4]; + return new double[] { a, b, c, d, e }; + } - return new double[] { a, b, c, d, e }; + /// + /// aR̉~JFD, Xphi Ɓ@tau@̂Ƃǂ̂悤ȋ`(offset, width, height, cos, sin)ɂȂ邩Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static (PointD OffSet, double Width, double Height, double Cos, double Sin) GetEllipseRectangleAndRot(double R, double FD, double phi, double tau) + { + PointD OffSet; + double Width, Height, Cos, Sin; + //Wn͎(mm)ōl + //a*x^2 + b*x*y + c*y^2 + d*x + e*y = 10000 + double CosPhi = Math.Cos(phi), SinPhi = Math.Sin(phi); + double CosTau = Math.Cos(tau), SinTau = Math.Sin(tau); + double a = 10000 * ((CosPhi * CosPhi + CosTau * CosTau * SinPhi * SinPhi) / R / R - SinPhi * SinPhi * SinTau * SinTau / FD / FD); + double b = 10000 * 2 * (FD * FD + R * R) * SinPhi * CosPhi * SinTau * SinTau / R / R / FD / FD; + double c = 10000 * ((CosPhi * CosPhi * CosTau * CosTau + SinPhi * SinPhi) / R / R - CosPhi * CosPhi * SinTau * SinTau / FD / FD); + double d = 10000 * 2 * SinPhi * SinTau / FD; + double e = -10000 * 2 * CosPhi * SinTau / FD; + + // a*x^2 + b*x*y + c*y^2 + d*x + e*y = 10000 @a * x^2 + b *x*y + c * y^2 = f Ƃ`ɕϊ + //̂Ƃ̕sړ(‚܂蒆Sʒu)X= -d / 2a, Y= -e / 2c + //OffSet = new PointD(-d / 2 / a, -e / 2 / c); + OffSet = new PointD(-(b * e - 2 * c * d) / (b * b - 4 * a * c), -(b * d - 2 * a * e) / (b * b - 4 * a * c)); + //܂f + double f = 10000 + OffSet.X * OffSet.X * a + OffSet.Y * OffSet.Y * c; + + if (Math.Abs(b) < 0.000000001)//b==0̎͌ŗLl肪ƂȂ + { + Cos = 1; + Sin = 0; + Width = Math.Sqrt(f / a); + Height = Math.Sqrt(f / c); } - - /// - /// aR̉~JFD, Xphi Ɓ@tau@̂Ƃǂ̂悤ȋ`(offset, width, height, cos, sin)ɂȂ邩Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static (PointD OffSet, double Width, double Height, double Cos, double Sin) GetEllipseRectangleAndRot(double R, double FD, double phi, double tau) + else { - PointD OffSet; - double Width, Height, Cos, Sin; - //Wn͎(mm)ōl - //a*x^2 + b*x*y + c*y^2 + d*x + e*y = 10000 - double CosPhi = Math.Cos(phi); - double SinPhi = Math.Sin(phi); - double CosTau = Math.Cos(tau); - double SinTau = Math.Sin(tau); - double a = 10000 * ((CosPhi * CosPhi + CosTau * CosTau * SinPhi * SinPhi) / R / R - SinPhi * SinPhi * SinTau * SinTau / FD / FD); - double b = 10000 * 2 * (FD * FD + R * R) * SinPhi * CosPhi * SinTau * SinTau / R / R / FD / FD; - double c = 10000 * ((CosPhi * CosPhi * CosTau * CosTau + SinPhi * SinPhi) / R / R - CosPhi * CosPhi * SinTau * SinTau / FD / FD); - double d = 10000 * 2 * SinPhi * SinTau / FD; - double e = -10000 * 2 * CosPhi * SinTau / FD; - - // a*x^2 + b*x*y + c*y^2 + d*x + e*y = 10000 @a * x^2 + b *x*y + c * y^2 = f Ƃ`ɕϊ - //̂Ƃ̕sړ(‚܂蒆Sʒu)X= -d / 2a, Y= -e / 2c - //OffSet = new PointD(-d / 2 / a, -e / 2 / c); - OffSet = new PointD(-(b * e - 2 * c * d) / (b * b - 4 * a * c), -(b * d - 2 * a * e) / (b * b - 4 * a * c)); - //܂f - double f = 10000 + OffSet.X * OffSet.X * a + OffSet.Y * OffSet.Y * c; - - if (Math.Abs(b) < 0.000000001)//b==0̎͌ŗLl肪ƂȂ - { - Cos = 1; - Sin = 0; - Width = Math.Sqrt(f / a); - Height = Math.Sqrt(f / c); - } - else - { - b *= 0.5; - //{{a,b}{b,c}}̌ŗLl,ŗLxNg߂ - double sqrt = Math.Sqrt(4 * b * b + (a - c) * (a - c)); - //Cos = 0.5 * (1 + (c - a) / sqrt); - Cos = (a - c - sqrt) / Math.Sqrt(2) / Math.Sqrt(4 * b * b - (a - c) * (-a + sqrt + c)); - //if ((a - sqrt - c) / 2 / b < 0) Cos = -Cos; - Sin = (a - c + sqrt) / Math.Sqrt(2) / Math.Sqrt(4 * b * b + (a - c) * (a + sqrt - c)); - if (b < 0) Sin = -Sin; - - double k1 = (a + c - sqrt) / 2.0; - double k2 = (a + c + sqrt) / 2.0; - - //ƌ k1 X^2 + k2 Y^2 = fƂɏƂłB - Width = Math.Sqrt(f / k1); - Height = Math.Sqrt(f / k2); - } - - return (OffSet, Width, Height, Cos, Sin); + b *= 0.5; + //{{a,b}{b,c}}̌ŗLl,ŗLxNg߂ + double sqrt = Math.Sqrt(4 * b * b + (a - c) * (a - c)); + //Cos = 0.5 * (1 + (c - a) / sqrt); + Cos = (a - c - sqrt) / Math.Sqrt(2) / Math.Sqrt(4 * b * b - (a - c) * (-a + sqrt + c)); + //if ((a - sqrt - c) / 2 / b < 0) Cos = -Cos; + Sin = (a - c + sqrt) / Math.Sqrt(2) / Math.Sqrt(4 * b * b + (a - c) * (a + sqrt - c)); + if (b < 0) Sin = -Sin; + + double k1 = (a + c - sqrt) / 2.0; + double k2 = (a + c + sqrt) / 2.0; + + //ƌ k1 X^2 + k2 Y^2 = fƂɏƂłB + Width = Math.Sqrt(f / k1); + Height = Math.Sqrt(f / k2); } - /// - /// ȉ~̒SQƂ̔aA^̒S̃ItZbgʒu(offset)ƌX(tau, phi)Ƃ̌덷Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void GetTiltAndOffset(PointD[] EllipseCenter, double[] Radius, double CameraLength, ref PointD offset, ref PointD offsetDev, - ref double tau, ref double tauDev, ref double phi, ref double phiDev) - { - //Cӂ̓_Ioffset, tau, phivZ - List offsetXList = new(), offsetYList = new(); - List tauList = new(), phiList = new(); + return (OffSet, Width, Height, Cos, Sin); + } - for (int i = 0; i < EllipseCenter.Length; i++) - for (int j = i + 1; j < EllipseCenter.Length; j++) - { - var ellipseCenterTemp = new PointD[] { EllipseCenter[i], EllipseCenter[j] }; - var radiusTemp = new double[] { Radius[i], Radius[j] }; - var offsetTemp = offset; - var tauTemp = tau; - var phiTemp = phi; - - GetTiltAndOffset(ellipseCenterTemp, radiusTemp, CameraLength, ref offsetTemp, ref tauTemp, ref phiTemp); - - offsetXList.Add(offsetTemp.X); - offsetYList.Add(offsetTemp.Y); - tauList.Add(tauTemp); - phiList.Add(phiTemp); - } - offsetDev = new PointD(Statistics.Deviation(offsetXList.ToArray()), Statistics.Deviation(offsetYList.ToArray())); - tauDev = Statistics.Deviation(tauList.ToArray()); + /// + /// ȉ~̒SQƂ̔aA^̒S̃ItZbgʒu(offset)ƌX(tau, phi)Ƃ̌덷Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void GetTiltAndOffset(PointD[] EllipseCenter, double[] Radius, double CameraLength, ref PointD offset, ref PointD offsetDev, + ref double tau, ref double tauDev, ref double phi, ref double phiDev) + { + //Cӂ̓_Ioffset, tau, phivZ + List offsetXList = new(), offsetYList = new(); + List tauList = new(), phiList = new(); + + for (int i = 0; i < EllipseCenter.Length; i++) + for (int j = i + 1; j < EllipseCenter.Length; j++) + { + var ellipseCenterTemp = new PointD[] { EllipseCenter[i], EllipseCenter[j] }; + var radiusTemp = new double[] { Radius[i], Radius[j] }; + var offsetTemp = offset; + var tauTemp = tau; + var phiTemp = phi; + + GetTiltAndOffset(ellipseCenterTemp, radiusTemp, CameraLength, ref offsetTemp, ref tauTemp, ref phiTemp); + + offsetXList.Add(offsetTemp.X); + offsetYList.Add(offsetTemp.Y); + tauList.Add(tauTemp); + phiList.Add(phiTemp); + } + offsetDev = new PointD(Statistics.Deviation(offsetXList.ToArray()), Statistics.Deviation(offsetYList.ToArray())); + tauDev = Statistics.Deviation(tauList.ToArray()); - double phiDev1, phiDev2; + double phiDev1, phiDev2; - phiDev1 = Statistics.Deviation(phiList.ToArray()); - for (int i = 0; i < phiList.Count; i++) - if (phiList[i] < 0) phiList[i] += Math.PI; - phiDev2 = Statistics.Deviation(phiList.ToArray()); + phiDev1 = Statistics.Deviation(phiList.ToArray()); + for (int i = 0; i < phiList.Count; i++) + if (phiList[i] < 0) phiList[i] += Math.PI; + phiDev2 = Statistics.Deviation(phiList.ToArray()); - phiDev = Math.Min(phiDev1, phiDev2); + phiDev = Math.Min(phiDev1, phiDev2); - //SEllipseCenterpāAoffset, tau, phivZ - GetTiltAndOffset(EllipseCenter, Radius, CameraLength, ref offset, ref tau, ref phi); - } + //SEllipseCenterpāAoffset, tau, phivZ + GetTiltAndOffset(EllipseCenter, Radius, CameraLength, ref offset, ref tau, ref phi); + } - /// - /// ȉ~̒SQƂ̔aA^̒S̃ItZbgʒu(offset)ƌX(tau, phi)Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - public static void GetTiltAndOffset(PointD[] EllipseCenter, double[] Radius, double CameraLength, ref PointD offset, - ref double tau, ref double phi) + /// + /// ȉ~̒SQƂ̔aA^̒S̃ItZbgʒu(offset)ƌX(tau, phi)Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + public static void GetTiltAndOffset(PointD[] EllipseCenter, double[] Radius, double CameraLength, ref PointD offset, + ref double tau, ref double phi) + { + //܂CenterPt̉A߂ + double phi1, A; + phi1 = A = 0; + Statistics.LineFitting(EllipseCenter, ref phi1, ref A); + double CosPhi1 = Math.Cos(phi1), SinPhi1 = Math.Sin(phi1); + bool xMode = Math.Abs(CosPhi1) > 1 / Math.Sqrt(2); + + //̒̓_B(x,y)ƁAeCenterPt̋RiƂƂ + //^2= ( Ri - Cameralength * Tan(2)^2 *Sin() / pixelSize )^2@ + //ŏɂȂ悤ȓ_BƃՂ + + //double[] TheoriticalRperSinPsi = new double[EllipseCenter.Length]; + double startTau1 = -Math.PI / 180; + double stepTau1 = Math.PI / 9000; + double endTau1 = Math.PI / 180; + double tau1, bestTau1; + tau1 = 0; + + double startCenter = -5; + double stepCenter = 0.1; + double endCenter = 5; + double Center, BestCenter; + double BestY, BestX, X, Y; + + double residual, bestResidual; + bestResidual = double.PositiveInfinity; + BestX = BestY = bestTau1 = BestCenter = 0; + //double temp; + for (int n = 0; n < 40; n++) { - //܂CenterPt̉A߂ - double phi1, A; - phi1 = A = 0; - Statistics.LineFitting(EllipseCenter, ref phi1, ref A); - double CosPhi1 = Math.Cos(phi1); - double SinPhi1 = Math.Sin(phi1); - bool xMode = Math.Abs(CosPhi1) > 1 / Math.Sqrt(2); - - //̒̓_B(x,y)ƁAeCenterPt̋RiƂƂ - //^2= ( Ri - Cameralength * Tan(2)^2 *Sin() / pixelSize )^2@ - //ŏɂȂ悤ȓ_BƃՂ - - double[] TheoriticalRperSinPsi = new double[EllipseCenter.Length]; - double startTau1 = -Math.PI / 180; - double stepTau1 = Math.PI / 9000; - double endTau1 = Math.PI / 180; - double tau1, bestTau1; - tau1 = 0; - - double startCenter = -5; - double stepCenter = 0.1; - double endCenter = 5; - double Center, BestCenter; - double BestY, BestX, X, Y; - - double residual, bestResidual; - bestResidual = double.PositiveInfinity; - BestX = BestY = bestTau1 = BestCenter = 0; - //double temp; - for (int n = 0; n < 40; n++) + for (Center = startCenter; Center <= endCenter; Center += stepCenter) { - for (Center = startCenter; Center <= endCenter; Center += stepCenter) + if (xMode) { - if (xMode) - { - X = Center; - Y = (X * SinPhi1 - A) / CosPhi1; - } - else - { - Y = Center; - X = (Y * CosPhi1 + A) / SinPhi1; - } - for (tau1 = startTau1; tau1 <= endTau1; tau1 += stepTau1) + X = Center; + Y = (X * SinPhi1 - A) / CosPhi1; + } + else + { + Y = Center; + X = (Y * CosPhi1 + A) / SinPhi1; + } + for (tau1 = startTau1; tau1 <= endTau1; tau1 += stepTau1) + { + residual = 0; + for (int i = 0; i < EllipseCenter.Length; i++) { - residual = 0; - for (int i = 0; i < EllipseCenter.Length; i++) + //݂Tau,X,Y\z锼aR̉~̒Sʒu + double IdealX, IdealY; + double TwoTheta = Math.Atan2(Radius[i], CameraLength); + //RtaûƂÂƂ + //double R = CameraLength * 2 * Math.Sin(TwoTheta) * Math.Sin(TwoTheta) * Math.Sin(tau1) / (Math.Cos(2 * TwoTheta) + Math.Cos(2 * tau1)); + //1/2 CL tan2q { sinj [tan(2q+j) -tan(2q-j)] } + double R = 0.5 * CameraLength * Math.Sin(TwoTheta) * (1 / Math.Cos(TwoTheta + tau1) - 1 / Math.Cos(TwoTheta - tau1)); + if (tau1 > 0) + R = Math.Abs(R); + else + R = -Math.Abs(R); + + IdealX = R * CosPhi1; + IdealY = R * SinPhi1; + + if (xMode && tau1 * IdealX <= 0)//ɍLĂ tau1 > 0 idealX <0 邢 tau1 < 0 idealX > 0 ̂Ƃ { - //݂Tau,X,Y\z锼aR̉~̒Sʒu - double IdealX, IdealY; - double TwoTheta = Math.Atan2(Radius[i], CameraLength); - //RtaûƂÂƂ - //double R = CameraLength * 2 * Math.Sin(TwoTheta) * Math.Sin(TwoTheta) * Math.Sin(tau1) / (Math.Cos(2 * TwoTheta) + Math.Cos(2 * tau1)); - //1/2 CL tan2q { sinj [tan(2q+j) -tan(2q-j)] } - double R = 0.5 * CameraLength * Math.Sin(TwoTheta) * (1 / Math.Cos(TwoTheta + tau1) - 1 / Math.Cos(TwoTheta - tau1)); - if (tau1 > 0) - R = Math.Abs(R); - else - R = -Math.Abs(R); - - IdealX = R * CosPhi1; - IdealY = R * SinPhi1; - - if (xMode && tau1 * IdealX <= 0)//ɍLĂ tau1 > 0 idealX <0 邢 tau1 < 0 idealX > 0 ̂Ƃ - { - IdealX = -IdealX; - IdealY = -IdealY; - } - if (!xMode && tau1 * IdealY <= 0)//cɍLĂ tau1 > 0 idealY <0 邢 tau1 < 0 idealY > 0 ̂Ƃ - { - IdealX = -IdealX; - IdealY = -IdealY; - } - //܂łŁATau Ȃ킿 R̂Ƃ͑ȉ~̒SX,Ŷꂩ̕ɐɐU鎖ɂȂ - residual += (X + IdealX - EllipseCenter[i].X) * (X + IdealX - EllipseCenter[i].X) * 1000 - + (Y + IdealY - EllipseCenter[i].Y) * (Y + IdealY - EllipseCenter[i].Y) * 1000; + IdealX = -IdealX; + IdealY = -IdealY; } - if (residual < bestResidual) + if (!xMode && tau1 * IdealY <= 0)//cɍLĂ tau1 > 0 idealY <0 邢 tau1 < 0 idealY > 0 ̂Ƃ { - bestResidual = residual; - BestX = X; - BestY = Y; - BestCenter = Center; - bestTau1 = tau1; + IdealX = -IdealX; + IdealY = -IdealY; } + //܂łŁATau Ȃ킿 R̂Ƃ͑ȉ~̒SX,Ŷꂩ̕ɐɐU鎖ɂȂ + residual += (X + IdealX - EllipseCenter[i].X) * (X + IdealX - EllipseCenter[i].X) * 1000 + + (Y + IdealY - EllipseCenter[i].Y) * (Y + IdealY - EllipseCenter[i].Y) * 1000; } - } - startCenter = BestCenter - 2.4 * stepCenter; - endCenter = BestCenter + (2.4 * stepCenter); - stepCenter *= 0.8; - - startTau1 = bestTau1 - 2.4 * stepTau1; - endTau1 = bestTau1 + 2.4 * stepTau1; - stepTau1 *= 0.8; - }//œKI - - offset = new PointD(BestX, BestY); - - //270 - phi1 -= 9 * Math.PI / 2; - - //xMode^taûƂ. ̂Ƃ]-135`-45ɂȂׂ - if (xMode && bestTau1 >= 0) - while (phi1 < -Math.PI * 3 / 4 - 0.01)//-135`-45͈̔͂ȂƂ - phi1 += Math.PI; - //xMode^taûƂ. ̂Ƃ]45`135ɂȂׂ - if (xMode && bestTau1 < 0) - while (phi1 < Math.PI / 4 - 0.01)//45ȉ̂Ƃ - phi1 += Math.PI; - //xModeUtaûƂ. ̂Ƃ]-45`45ɂȂׂ - if (!xMode && bestTau1 >= 0) - while (phi1 < -Math.PI / 4 - 0.01)//-45`45͈̔͂ȂƂ - phi1 += Math.PI; - //xModeUtaûƂ.̂Ƃ]135`215ɂȂׂ - if (!xMode && bestTau1 < 0) - while (phi1 < Math.PI * 3 / 4 - 0.01)//135`215͈̔͂ȂƂ - phi1 += Math.PI; - - bestTau1 = Math.Abs(bestTau1); - - double CosPhi = Math.Cos(phi); - double SinPhi = Math.Sin(phi); - double CosTau = Math.Cos(tau); - double SinTau = Math.Sin(tau); - - CosPhi1 = Math.Cos(phi1); - SinPhi1 = Math.Sin(phi1); - double CosTau1 = Math.Cos(bestTau1); - double SinTau1 = Math.Sin(bestTau1); - - var M = new Matrix3D(CosPhi, SinPhi, 0, -SinPhi, CosPhi, 0, 0, 0, 1); - var P = new Matrix3D(1, 0, 0, 0, CosTau, SinTau, 0, -SinTau, CosTau); - - var M1 = new Matrix3D(CosPhi1, SinPhi1, 0, -SinPhi1, CosPhi1, 0, 0, 0, 1); - var P1 = new Matrix3D(1, 0, 0, 0, CosTau1, SinTau1, 0, -SinTau1, CosTau1); - - var Q = M1 * P1 * M1.Transpose() * M * P * M.Transpose(); - - tau = Math.Acos(Q.E33); - if (Math.Sin(tau) == 0) - phi = 0; - else - phi = Math.Atan2(-Q.E31, Q.E32); - - bestResidual = double.PositiveInfinity; - double startPhi = phi - 0.1; - double endPhi = phi + 0.1; - double stepPhi = 0.01; - double startTau = tau - 0.01; - double endTau = tau + 0.01; - double stepTau = 0.001; - double bestPhi = phi; - double bestTau = tau; - double temp; - for (int n = 0; n < 30; n++) - { - for (phi = startPhi; phi <= endPhi; phi += stepPhi) - for (tau = startTau; tau <= endTau; tau += stepTau) + if (residual < bestResidual) { - CosPhi = Math.Cos(phi); - SinPhi = Math.Sin(phi); - CosTau = Math.Cos(tau); - SinTau = Math.Sin(tau); - - residual = 0; - - temp = Q.E11 - (CosPhi * CosPhi + CosTau * SinPhi * SinPhi); - residual += temp * temp; - temp = Q.E12 - (CosPhi * SinPhi - CosTau * CosPhi * SinPhi); - residual += temp * temp; - temp = Q.E13 - (SinPhi * SinTau); - residual += temp * temp; - temp = Q.E21 - (CosPhi * SinPhi - CosPhi * CosTau * SinPhi); - residual += temp * temp; - temp = Q.E22 - (CosPhi * CosPhi * CosTau + SinPhi * SinPhi); - residual += temp * temp; - temp = Q.E23 - (-CosPhi * SinTau); - residual += temp * temp; - temp = Q.E31 - (-SinPhi * SinTau); - residual += temp * temp; - temp = Q.E32 - (CosPhi * SinTau); - residual += temp * temp; - temp = Q.E33 - (CosTau); - residual += temp * temp; - if (bestResidual > residual) - { - bestPhi = phi; - bestTau = tau; - bestResidual = residual; - } + bestResidual = residual; + BestX = X; + BestY = Y; + BestCenter = Center; + bestTau1 = tau1; } - startPhi = bestPhi - stepPhi; - endPhi = bestPhi + stepPhi; - stepPhi *= 0.4; - startTau = bestTau - stepTau; - endTau = bestTau + stepTau; - stepTau *= 0.4; + } } + startCenter = BestCenter - 2.4 * stepCenter; + endCenter = BestCenter + (2.4 * stepCenter); + stepCenter *= 0.8; + + startTau1 = bestTau1 - 2.4 * stepTau1; + endTau1 = bestTau1 + 2.4 * stepTau1; + stepTau1 *= 0.8; + }//œKI + + offset = new PointD(BestX, BestY); + + //270 + phi1 -= 9 * Math.PI / 2; + + //xMode^taûƂ. ̂Ƃ]-135`-45ɂȂׂ + if (xMode && bestTau1 >= 0) + while (phi1 < -Math.PI * 3 / 4 - 0.01)//-135`-45͈̔͂ȂƂ + phi1 += Math.PI; + //xMode^taûƂ. ̂Ƃ]45`135ɂȂׂ + if (xMode && bestTau1 < 0) + while (phi1 < Math.PI / 4 - 0.01)//45ȉ̂Ƃ + phi1 += Math.PI; + //xModeUtaûƂ. ̂Ƃ]-45`45ɂȂׂ + if (!xMode && bestTau1 >= 0) + while (phi1 < -Math.PI / 4 - 0.01)//-45`45͈̔͂ȂƂ + phi1 += Math.PI; + //xModeUtaûƂ.̂Ƃ]135`215ɂȂׂ + if (!xMode && bestTau1 < 0) + while (phi1 < Math.PI * 3 / 4 - 0.01)//135`215͈̔͂ȂƂ + phi1 += Math.PI; + + bestTau1 = Math.Abs(bestTau1); + + double CosPhi = Math.Cos(phi); + double SinPhi = Math.Sin(phi); + double CosTau = Math.Cos(tau); + double SinTau = Math.Sin(tau); + + CosPhi1 = Math.Cos(phi1); + SinPhi1 = Math.Sin(phi1); + double CosTau1 = Math.Cos(bestTau1); + double SinTau1 = Math.Sin(bestTau1); + + var M = new Matrix3D(CosPhi, SinPhi, 0, -SinPhi, CosPhi, 0, 0, 0, 1); + var P = new Matrix3D(1, 0, 0, 0, CosTau, SinTau, 0, -SinTau, CosTau); + + var M1 = new Matrix3D(CosPhi1, SinPhi1, 0, -SinPhi1, CosPhi1, 0, 0, 0, 1); + var P1 = new Matrix3D(1, 0, 0, 0, CosTau1, SinTau1, 0, -SinTau1, CosTau1); + + var Q = M1 * P1 * M1.Transpose() * M * P * M.Transpose(); + + tau = Math.Acos(Q.E33); + if (Math.Sin(tau) == 0) + phi = 0; + else + phi = Math.Atan2(-Q.E31, Q.E32); + + bestResidual = double.PositiveInfinity; + double startPhi = phi - 0.1, endPhi = phi + 0.1, stepPhi = 0.01; + double startTau = tau - 0.01, endTau = tau + 0.01, stepTau = 0.001; + double bestPhi = phi, bestTau = tau; + double temp; + for (int n = 0; n < 30; n++) + { + for (phi = startPhi; phi <= endPhi; phi += stepPhi) + for (tau = startTau; tau <= endTau; tau += stepTau) + { + CosPhi = Math.Cos(phi); + SinPhi = Math.Sin(phi); + CosTau = Math.Cos(tau); + SinTau = Math.Sin(tau); + + residual = 0; + + temp = Q.E11 - (CosPhi * CosPhi + CosTau * SinPhi * SinPhi); + residual += temp * temp; + temp = Q.E12 - (CosPhi * SinPhi - CosTau * CosPhi * SinPhi); + residual += temp * temp; + temp = Q.E13 - (SinPhi * SinTau); + residual += temp * temp; + temp = Q.E21 - (CosPhi * SinPhi - CosPhi * CosTau * SinPhi); + residual += temp * temp; + temp = Q.E22 - (CosPhi * CosPhi * CosTau + SinPhi * SinPhi); + residual += temp * temp; + temp = Q.E23 - (-CosPhi * SinTau); + residual += temp * temp; + temp = Q.E31 - (-SinPhi * SinTau); + residual += temp * temp; + temp = Q.E32 - (CosPhi * SinTau); + residual += temp * temp; + temp = Q.E33 - (CosTau); + residual += temp * temp; + if (bestResidual > residual) + { + bestPhi = phi; + bestTau = tau; + bestResidual = residual; + } + } + startPhi = bestPhi - stepPhi; + endPhi = bestPhi + stepPhi; + stepPhi *= 0.4; + startTau = bestTau - stepTau; + endTau = bestTau + stepTau; + stepTau *= 0.4; + } + + phi = bestPhi; + tau = bestTau; + } - phi = bestPhi; - tau = bestTau; + /// + /// ȉ~̕Ȃȉ~QƂ^~ɋ߂Âp[^(PixX, PixY, Ksi)߂ + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static void GetPixelShape(EllipseParameter[] ellipse, ref double PixX, ref double PixY, ref double Ksi, ref double PixXDev, ref double PixYDev, ref double KsiDev, bool distortion) + { + for (int i = 0; i < ellipse.Length; i++) + { + ellipse[i].SetCoeff(); + //RRɂȂ悤ɒ߂ + ellipse[i].Coeff[0] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; + ellipse[i].Coeff[1] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; + ellipse[i].Coeff[2] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; } - /// - /// ȉ~̕Ȃȉ~QƂ^~ɋ߂Âp[^(PixX, PixY, Ksi)߂ - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static void GetPixelShape(EllipseParameter[] ellipse, ref double PixX, ref double PixY, ref double Ksi, ref double PixXDev, ref double PixYDev, ref double KsiDev, bool distortion) + //aR̉~ X^2 + Y^2 = R^2@AtBϊ { { A, B} , { 0 , C } } Ƃsŕϊ + //ȉ~ a * X^2 + b * X * Y + c * Y^2 = X^2 / A^2 - X * Y * 2B /A^2/C + Y^2 * (A^2+B^2) /(A^2 C^2) = R^2 ɕϊ + //̂Ƃ + //A = 1 / (a) + //B = - b /(a) /(4ac-b^2) + //C = 2(a) /(4ac-b^2) + + var tempPixX = new List(ellipse.Length); + var tempPixY = new List(ellipse.Length); + var tempKsi = new List(ellipse.Length); + double A, B, C; + for (int i = 0; i < ellipse.Length; i++) { - for (int i = 0; i < ellipse.Length; i++) - { - ellipse[i].SetCoeff(); - //RRɂȂ悤ɒ߂ - ellipse[i].Coeff[0] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; - ellipse[i].Coeff[1] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; - ellipse[i].Coeff[2] *= ellipse[i].millimeterCalc * ellipse[i].millimeterCalc / 1000000; - } + A = Math.Sqrt(1.0 / ellipse[i].Coeff[0]); + B = -ellipse[i].Coeff[1] / Math.Sqrt(ellipse[i].Coeff[0] * (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1])); + C = 2 * Math.Sqrt(ellipse[i].Coeff[0] / (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1])); + //{ { A, B} , { 0 , C } } * {x, y} = { { PixX , PixY SinKsi } , { 0 , PixelY } } * {X,Y} // {x,y}͐^̉~̍W, {X,Y}̓sNZW + //@newPixX = PixX /A, newPixY = PixY /C, tan(newKsi) = C (tanKsi-B) /A + tempPixX.Add(PixX / A); + tempPixY.Add(PixY / C); + tempKsi.Add(Math.Atan(C / A * (Math.Tan(Ksi) - B))); + } + + PixX = tempPixX.Average(); + PixXDev = Statistics.Deviation(tempPixX.ToArray()); + PixY = tempPixY.Average(); + PixYDev = Statistics.Deviation(tempPixY.ToArray()); + if (distortion) + { + Ksi = tempKsi.Average(); + KsiDev = Statistics.Deviation(tempKsi.ToArray()); + } + } + - //aR̉~ X^2 + Y^2 = R^2@AtBϊ { { A, B} , { 0 , C } } Ƃsŕϊ - //ȉ~ a * X^2 + b * X * Y + c * Y^2 = X^2 / A^2 - X * Y * 2B /A^2/C + Y^2 * (A^2+B^2) /(A^2 C^2) = R^2 ɕϊ - //̂Ƃ - //A = 1 / (a) - //B = - b /(a) /(4ac-b^2) - //C = 2(a) /(4ac-b^2) - - var tempPixX = new List(); - var tempPixY = new List(); - var tempKsi = new List(); - double A, B, C; - for (int i = 0; i < ellipse.Length; i++) + /// + /// _pA^ꂽ_(E肩)ptsō鑽p`̓ɑ݂邩ǂ𔻒肷B + /// https://www.nttpc.co.jp/technology/number_algorithm.html Winding Number Algorithm̕ό`QlɂB + /// + /// + /// + /// + public static bool InsidePolygonalArea(List pts, in PointD p) => InsidePolygonalArea(CollectionsMarshal.AsSpan(pts), in p); + + /// + /// _pA^ꂽ_(E肩)ptsō鑽p`̓ɑ݂邩ǂ𔻒肷B + /// https://www.nttpc.co.jp/technology/number_algorithm.html Winding Number Algorithm̕ό`QlɂB + /// + /// + /// + /// + public static bool InsidePolygonalArea(Span pts, in PointD p) + { + if (pts.Length < 3) return false; + int wn = 0; + for (int i = 0; i < pts.Length - 1; i++) + { + // ̕ӁA̕ӂɂďB + // ̕ӁB_Pyɂ‚āAn_ƏI_̊ԂɂBAI_͊܂܂ȂB([1) + if ((pts[i].Y <= p.Y) && (pts[i + 1].Y > p.Y)) { - A = Math.Sqrt(1.0 / ellipse[i].Coeff[0]); - B = -ellipse[i].Coeff[1] / Math.Sqrt(ellipse[i].Coeff[0] * (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1])); - C = 2 * Math.Sqrt(ellipse[i].Coeff[0] / (4 * ellipse[i].Coeff[0] * ellipse[i].Coeff[2] - ellipse[i].Coeff[1] * ellipse[i].Coeff[1])); - //{ { A, B} , { 0 , C } } * {x, y} = { { PixX , PixY SinKsi } , { 0 , PixelY } } * {X,Y} // {x,y}͐^̉~̍W, {X,Y}̓sNZW - //@newPixX = PixX /A, newPixY = PixY /C, tan(newKsi) = C (tanKsi-B) /A - tempPixX.Add(PixX / A); - tempPixY.Add(PixY / C); - tempKsi.Add(Math.Atan(C / A * (Math.Tan(Ksi) - B))); + // ӂ͓_pEɂBAdȂȂB([4) + // ӂ_pƓɂȂʒu肵A̎x̒lƓ_px̒lrB + var vt = (p.Y - pts[i].Y) / (pts[i + 1].Y - pts[i].Y); + if (p.X < (pts[i].X + (vt * (pts[i + 1].X - pts[i].X)))) + ++wn; //dvB̕ӂƌꍇ+1 } - - PixX = tempPixX.Average(); - PixXDev = Statistics.Deviation(tempPixX.ToArray()); - PixY = tempPixY.Average(); - PixYDev = Statistics.Deviation(tempPixY.ToArray()); - if (distortion) + // ̕ӁB_Pyɂ‚āAn_ƏI_̊ԂɂBAn_͊܂܂ȂB([2) + else if ((pts[i].Y > p.Y) && (pts[i + 1].Y <= p.Y)) { - Ksi = tempKsi.Average(); - KsiDev = Statistics.Deviation(tempKsi.ToArray()); + // ӂ͓_pEɂBAdȂȂB([4) + // ӂ_pƓɂȂʒu肵A̎x̒lƓ_px̒lrB + var vt = (p.Y - pts[i].Y) / (pts[i + 1].Y - pts[i].Y); + if (p.X < (pts[i].X + (vt * (pts[i + 1].X - pts[i].X)))) + --wn; //dvB̕ӂƌꍇ-1 } + // [1,[2mF邱ƂŁA[3mFłĂB } - public static double GetPolygonalArea(PointD[] pt) - => GetPolygonalArea(pt.Select(p => (p.X, p.Y)).ToArray()); - - /// - /// ^ꂽ_(E肩)ň͂܂ʐςԂ - /// - /// - /// - public static double GetPolygonalArea((double X, double Y)[] pt) + //ŌɁAŌ̓_ƍŏ̓_vZ + if ((pts[^1].Y <= p.Y) && (pts[0].Y > p.Y)) { - if (pt == null || pt.Length < 3) return 0; - - double area = 0; - for (int i = 0; i < pt.Length - 1; i++) - area += (pt[i].X - pt[i + 1].X) * (pt[i].Y + pt[i + 1].Y); - area += (pt[^1].X - pt[0].X) * (pt[^1].Y + pt[0].Y); - return Math.Abs(area * 0.5); + var vt = (p.Y - pts[^1].Y) / (pts[0].Y - pts[^1].Y); + if (p.X < (pts[^1].X + (vt * (pts[0].X - pts[^1].X)))) + ++wn; } - - public static PointD[] GetPolygonDividedByLine(PointD[] pt, double a, double b, double c) + else if ((pts[^1].Y > p.Y) && (pts[0].Y <= p.Y)) { - var results = GetPolygonDividedByLine(pt.Select(p => (p.X, p.Y)).ToArray(), a, b, c); - return results.Select(r => new PointD(r.X, r.Y)).ToArray(); + var vt = (p.Y - pts[^1].Y) / (pts[0].Y - pts[^1].Y); + if (p.X < (pts[^1].X + (vt * (pts[0].X - pts[^1].X)))) + --wn; } + return wn != 0; + } - /// - /// ^ꂽ_pt(E肩)ō\鑽p`ƁA钼(ax+by>c)ň͂܂鑽p`Ԃ (ax+byc)̎͑SĂ̌W̕t] - /// - /// - /// - public static (double X, double Y)[] GetPolygonDividedByLine((double X, double Y)[] pt, double a, double b, double c) - { - //pt2_ȉȂ炻̂܂ܕԂ - if (pt == null || pt.Length < 3) return pt; - //܂^ꂽ̏ (ax+by>c邢ax+by + /// ^ꂽ_(E肩)ň͂܂ʐςԂ + /// + /// + /// + public static double GetPolygonalArea(PointD[] pt) => GetPolygonalArea(pt.Select(p => (p.X, p.Y)).ToArray()); - //ptx,yli[Zɔ͈͓(1)͈͊O(0)L^ꎞIȕϐ - var ptAlpha = new List<(double X, double Y, bool Flag)>(); - bool flag1 = true, flag2 = true; - for (int i = 0; i < pt.Length; i++) - { - (double X, double Y, bool Flag) v = (pt[i].X, pt[i].Y, true); - if (a * pt[i].X + b * pt[i].Y < c)//͈͊Oł - { - v.Flag = false; - flag1 = false;//‚ł͈͊Ô̂flag1falseɂȂ - } - else - flag2 = false;//‚ł͈͓̂̂flag2falseɂȂ + /// + /// ^ꂽ_(E肩)ň͂܂ʐςԂ + /// + /// + /// + public static double GetPolygonalArea((double X, double Y)[] pt) + { + if (pt == null || pt.Length < 3) return 0; - ptAlpha.Add(v); - } + double area = 0; + for (int i = 0; i < pt.Length - 1; i++) + area += (pt[i].X - pt[i + 1].X) * (pt[i].Y + pt[i + 1].Y); + area += (pt[^1].X - pt[0].X) * (pt[^1].Y + pt[0].Y); + return Math.Abs(area * 0.5); + } - //͈͊O_Ȃ΂̂܂ptԂB - if (flag1) - return pt; + public static PointD[] GetPolygonDividedByLine(PointD[] pt, double a, double b, double c) + { + var results = GetPolygonDividedByLine(pt.Select(p => (p.X, p.Y)).ToArray(), a, b, c); + return results.Select(r => new PointD(r.X, r.Y)).ToArray(); + } - //͈͊O_ꍇ + /// + /// ^ꂽ_pt(E肩)ō\鑽p`ƁA钼(ax+by>c)ň͂܂鑽p`Ԃ (ax+byc)̎͑SĂ̌W̕t] + /// + /// + /// + public static (double X, double Y)[] GetPolygonDividedByLine((double X, double Y)[] pt, double a, double b, double c) + { + //pt2_ȉȂ炻̂܂ܕԂ + if (pt == null || pt.Length < 3) return pt; - //ׂĂ͈͊OȂnullԂ - if (flag2) - return Array.Empty<(double X, double Y)>(); + //܂^ꂽ̏ (ax+by>c邢ax+by(); + bool flag1 = true, flag2 = true; + for (int i = 0; i < pt.Length; i++) + { + (double X, double Y, bool Flag) v = (pt[i].X, pt[i].Y, true); + if (a * pt[i].X + b * pt[i].Y < c)//͈͊Oł { - int next = i < ptAlpha.Count - 1 ? i + 1 : 0; - if (ptAlpha[i].Flag != ptAlpha[next].Flag) - { - var (X, Y) = getCrossPoint(ptAlpha[i], ptAlpha[next], a, b, c); - (double X, double Y, bool Flag) v = (X, Y, true); - ptAlpha.Insert(i + 1, v); - i++; - } + v.Flag = false; + flag1 = false;//‚ł͈͊Ô̂flag1falseɂȂ } + else + flag2 = false;//‚ł͈͓̂̂flag2falseɂȂ - var ptBeta = new List<(double X, double Y)>(); - for (int i = 0; i < ptAlpha.Count; i++) - if (ptAlpha[i].Flag) - ptBeta.Add((ptAlpha[i].X, ptAlpha[i].Y)); - - return ptBeta.ToArray(); + ptAlpha.Add(v); } - /// - /// ʂɂāA a x + b y = c@ _pt1pt2Ԓƌ_Ԃ - /// - /// - /// - /// - /// - /// - /// - private static (double X, double Y) getCrossPoint((double X, double Y, bool Flag) p1, (double X, double Y, bool Flag) p2, double a, double b, double c) - { - //2‚̕𖞂x, y߂΂悢 - //a x + b y = c - //(y1 - y2) x - (x1 - x2) y = x1 y2 - x2 y1 + //͈͊O_Ȃ΂̂܂ptԂB + if (flag1) + return pt; - if (a * (p1.X + p2.X) - b * (p1.Y + p2.Y) == 0) - return ((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2); + //͈͊O_ꍇ - return ( - (c * (p1.X - p2.X) + b * (p2.X * p1.Y - p1.X * p2.Y)) / (a * (p1.X - p2.X) + b * (p1.Y - p2.Y)), - (c * (p1.Y - p2.Y) + a * (p1.X * p2.Y - p2.X * p1.Y)) / (a * (p1.X - p2.X) + b * (p1.Y - p2.Y)) - ); - } + //ׂĂ͈͊OȂnullԂ + if (flag2) + return Array.Empty<(double X, double Y)>(); - /// - /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_pt1pt2Ԓƌ_Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - public static Vector3D GetCrossPoint(in double a, in double b, in double c, in double d, Vector3D p1, Vector3D p2) + for (int i = 0; i < ptAlpha.Count; i++) { - return GetCrossPoint(a, b, c, d, new Vector3D(p1.X, p1.Y, p1.Z), new Vector3DBase(p2.X, p2.Y, p2.Z)); + int next = i < ptAlpha.Count - 1 ? i + 1 : 0; + if (ptAlpha[i].Flag != ptAlpha[next].Flag) + { + var (X, Y) = getCrossPoint(ptAlpha[i], ptAlpha[next], a, b, c); + (double X, double Y, bool Flag) v = (X, Y, true); + ptAlpha.Insert(i + 1, v); + i++; + } } - /// - /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_pt1pt2Ԓƌ_Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - public static Vector3D GetCrossPoint(in double a, in double b, in double c, in double d, Vector3DBase p1, Vector3DBase p2) - { - //3‚̕𖞂x, y, z ߂΂悢 (2020/02/04C) - // a x + b y + c z = d - //(y1 - y2) x - (x1 - x2) y = x2 y1 - x1 y2 - //(z1 - z2) y - (y1 - y2) z = y2 z1 - y1 z2 + var ptBeta = new List<(double X, double Y)>(); + for (int i = 0; i < ptAlpha.Count; i++) + if (ptAlpha[i].Flag) + ptBeta.Add((ptAlpha[i].X, ptAlpha[i].Y)); - //double denom = a * (p1.X - p2.X) + b * (p1.Y - p2.Y) + c * (p1.Z - p2.Z); - //double x = (d * (p1.X - p2.X) - b * (p1.X * p2.Y - p1.Y * p2.X) - c * (p1.X * p2.Z - p1.Z * p2.X)) / denom; - //double y = (d * (p1.Y - p2.Y) - c * (p1.Y * p2.Z - p1.Z * p2.Y) - a * (p1.Y * p2.X - p1.X * p2.Y)) / denom; - //double z = (d * (p1.Z - p2.Z) - a * (p1.Z * p2.X - p1.X * p2.Z) - b * (p1.Z * p2.Y - p1.Y * p2.Z)) / denom; + return ptBeta.ToArray(); + } - double dx = p1.X - p2.X, dy = p1.Y - p2.Y, dz = p1.Z - p2.Z; + /// + /// ʂɂāA a x + b y = c@ _pt1pt2Ԓƌ_Ԃ + /// + /// + /// + /// + /// + /// + /// + private static (double X, double Y) getCrossPoint((double X, double Y, bool Flag) p1, (double X, double Y, bool Flag) p2, double a, double b, double c) + { + //2‚̕𖞂x, y߂΂悢 + //a x + b y = c + //(y1 - y2) x - (x1 - x2) y = x1 y2 - x2 y1 - var uz = p1.X * p2.Y - p1.Y * p2.X; - var ux = p1.Y * p2.Z - p1.Z * p2.Y; - var uy = p1.Z * p2.X - p1.X * p2.Z; + if (a * (p1.X + p2.X) - b * (p1.Y + p2.Y) == 0) + return ((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2); - var denom = a * dx + b * dy + c * dz; - var x = (d * dx - b * uz + c * uy) / denom; - var y = (d * dy - c * ux + a * uz) / denom; - var z = (d * dz - a * uy + b * ux) / denom; + return ( + (c * (p1.X - p2.X) + b * (p2.X * p1.Y - p1.X * p2.Y)) / (a * (p1.X - p2.X) + b * (p1.Y - p2.Y)), + (c * (p1.Y - p2.Y) + a * (p1.X * p2.Y - p2.X * p1.Y)) / (a * (p1.X - p2.X) + b * (p1.Y - p2.Y)) + ); + } - return new Vector3D(x, y, z); - } + /// + /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_pt1pt2Ԓƌ_Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3D GetCrossPoint(in double a, in double b, in double c, in double d, Vector3D p1, Vector3D p2) + => GetCrossPoint(a, b, c, d, new Vector3D(p1.X, p1.Y, p1.Z), new Vector3DBase(p2.X, p2.Y, p2.Z)); + + /// + /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_pt1pt2Ԓƌ_Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3D GetCrossPoint(in double a, in double b, in double c, in double d, Vector3DBase p1, Vector3DBase p2) + { + //3‚̕𖞂x, y, z ߂΂悢 (2020/02/04C) + // a x + b y + c z = d + //(y1 - y2) x - (x1 - x2) y = x2 y1 - x1 y2 + //(z1 - z2) y - (y1 - y2) z = y2 z1 - y1 z2 + //double denom = a * (p1.X - p2.X) + b * (p1.Y - p2.Y) + c * (p1.Z - p2.Z); + //double x = (d * (p1.X - p2.X) - b * (p1.X * p2.Y - p1.Y * p2.X) - c * (p1.X * p2.Z - p1.Z * p2.X)) / denom; + //double y = (d * (p1.Y - p2.Y) - c * (p1.Y * p2.Z - p1.Z * p2.Y) - a * (p1.Y * p2.X - p1.X * p2.Y)) / denom; + //double z = (d * (p1.Z - p2.Z) - a * (p1.Z * p2.X - p1.X * p2.Z) - b * (p1.Z * p2.Y - p1.Y * p2.Z)) / denom; - // - /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_(0,0,0)ptԒƌ_Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - public static Vector3DBase GetCrossPoint(in double a, in double b, in double c, in double d, Vector3DBase p) - { - //3‚̕𖞂x, y, z ߂΂悢 (2020/02/04C) - // a x + b y + c z = d - //(y1 - y2) x - (x1 - x2) y = x2 y1 - x1 y2 - //(z1 - z2) y - (y1 - y2) z = y2 z1 - y1 z2 + double dx = p1.X - p2.X, dy = p1.Y - p2.Y, dz = p1.Z - p2.Z; - //double denom = a * (p1.X - p2.X) + b * (p1.Y - p2.Y) + c * (p1.Z - p2.Z); - //double x = (d * (p1.X - p2.X) - b * (p1.X * p2.Y - p1.Y * p2.X) - c * (p1.X * p2.Z - p1.Z * p2.X)) / denom; - //double y = (d * (p1.Y - p2.Y) - c * (p1.Y * p2.Z - p1.Z * p2.Y) - a * (p1.Y * p2.X - p1.X * p2.Y)) / denom; - //double z = (d * (p1.Z - p2.Z) - a * (p1.Z * p2.X - p1.X * p2.Z) - b * (p1.Z * p2.Y - p1.Y * p2.Z)) / denom; + var uz = p1.X * p2.Y - p1.Y * p2.X; + var ux = p1.Y * p2.Z - p1.Z * p2.Y; + var uy = p1.Z * p2.X - p1.X * p2.Z; - return p * d / (a * p.X + b * p.Y + c * p.Z); - } + var denom = a * dx + b * dy + c * dz; + var x = (d * dx - b * uz + c * uy) / denom; + var y = (d * dy - c * ux + a * uz) / denom; + var z = (d * dz - a * uy + b * ux) / denom; + + return new Vector3D(x, y, z); + } + + + // + /// 3ɂāA a x + b y + c z = d (@xNg(a,b,c))ƁA_(0,0,0)ptԒƌ_Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + public static Vector3DBase GetCrossPoint(in double a, in double b, in double c, in double d, Vector3DBase p) + { + //3‚̕𖞂x, y, z ߂΂悢 (2020/02/04C) + // a x + b y + c z = d + //(y1 - y2) x - (x1 - x2) y = x2 y1 - x1 y2 + //(z1 - z2) y - (y1 - y2) z = y2 z1 - y1 z2 + + //double denom = a * (p1.X - p2.X) + b * (p1.Y - p2.Y) + c * (p1.Z - p2.Z); + //double x = (d * (p1.X - p2.X) - b * (p1.X * p2.Y - p1.Y * p2.X) - c * (p1.X * p2.Z - p1.Z * p2.X)) / denom; + //double y = (d * (p1.Y - p2.Y) - c * (p1.Y * p2.Z - p1.Z * p2.Y) - a * (p1.Y * p2.X - p1.X * p2.Y)) / denom; + //double z = (d * (p1.Z - p2.Z) - a * (p1.Z * p2.X - p1.X * p2.Z) - b * (p1.Z * p2.Y - p1.Y * p2.Z)) / denom; + + return p * d / (a * p.X + b * p.Y + c * p.Z); + } - /// - /// sourcePointsŎw肳ꂽCvt@CAareaŎw肳ꂽ͈͓Ő؂B - /// - /// - /// - /// - public static PointD[][] GetPointsWithinRectangle(IEnumerable sourcePoints, RectangleD area) + /// + /// sourcePointsŎw肳ꂽCvt@CAareaŎw肳ꂽ͈͓Ő؂B + /// + /// + /// + /// + public static PointD[][] GetPointsWithinRectangle(IEnumerable sourcePoints, RectangleD area) + { + var pt = sourcePoints.ToList(); + //܂ȀƉg + var first = pt.FindIndex(p => p.X >= area.X) - 1; + if (first > 0) + pt.RemoveRange(0, first); + var last = pt.FindLastIndex(p => p.X <= area.X + area.Width) + 2; + if (last < pt.Count) + pt.RemoveRange(last, pt.Count - last); + + if (pt.Max(p => p.Y) <= area.UpperY && pt.Min(pt => pt.Y) >= area.Y) + return new[] { pt.ToArray() }; + else if (pt.Max(p => p.Y) <= area.Y || pt.Min(pt => pt.Y) >= area.UpperY) + return new[] { Array.Empty() }; + else { - var pt = sourcePoints.ToList(); - //܂ȀƉg - var first = pt.FindIndex(p => p.X >= area.X) - 1; - if (first > 0) - pt.RemoveRange(0, first); - var last = pt.FindLastIndex(p => p.X <= area.X + area.Width) + 2; - if (last < pt.Count) - pt.RemoveRange(last, pt.Count - last); - - if (pt.Max(p => p.Y) <= area.UpperY && pt.Min(pt => pt.Y) >= area.Y) - return new[] { pt.ToArray() }; - else if (pt.Max(p => p.Y) <= area.Y || pt.Min(pt => pt.Y) >= area.UpperY) - return new[] { Array.Empty() }; - else + for (int i = 0; i < pt.Count - 1; i++) { - - for (int i = 0; i < pt.Count - 1; i++) + if (!area.IsInsde(pt[i]) || !area.IsInsde(pt[i + 1])) //ǂ炩͈͊O̎ { - if (!area.IsInsde(pt[i]) || !area.IsInsde(pt[i + 1])) //ǂ炩͈͊O̎ + var pts = getCrossPoint(pt[i], pt[i + 1], area); + if (pts != null) { - var pts = getCrossPoint(pt[i], pt[i + 1], area); - if (pts != null) - { - pt.InsertRange(i + 1, pts); - i += pts.Length; - } + pt.InsertRange(i + 1, pts); + i += pts.Length; } } + } - var results = new List>(); - for (int i = 0; i < pt.Count - 1; i++) + var results = new List>(); + for (int i = 0; i < pt.Count - 1; i++) + { + if (!area.IsInsde(pt[i])) + pt.RemoveAt(i--); + else { - if (!area.IsInsde(pt[i])) - pt.RemoveAt(i--); - else - { - var pts = new List(); - for (; i < pt.Count && area.IsInsde(pt[i]); i++) - pts.Add(new PointD(pt[i])); - i--; - results.Add(pts); - } + var pts = new List(); + for (; i < pt.Count && area.IsInsde(pt[i]); i++) + pts.Add(new PointD(pt[i])); + i--; + results.Add(pts); } - return results.Select(r => r.ToArray()).ToArray(); } + return results.Select(r => r.ToArray()).ToArray(); } + } - /// - /// GetPointsWithinRectangle()Ăяo - /// - /// - /// - /// - /// - private static PointD[] getCrossPoint(PointD p1, PointD p2, RectangleD rect) - { - // y= a x + b - double a = (p2.Y - p1.Y) / (p2.X - p1.X); - double b = p2.Y - a * p2.X; + /// + /// GetPointsWithinRectangle()Ăяo + /// + /// + /// + /// + /// + private static PointD[] getCrossPoint(PointD p1, PointD p2, RectangleD rect) + { + // y= a x + b + var a = (p2.Y - p1.Y) / (p2.X - p1.X); + var b = p2.Y - a * p2.X; - if (rect.IsInsde(p1))//p1͈͓ɂƂ + if (rect.IsInsde(p1))//p1͈͓ɂƂ + { + if (rect.IsInsde(p2))//p1p2͈͓ɂƂ { - if (rect.IsInsde(p2))//p1p2͈͓ɂƂ + return null; + } + else//p1͈͓ɂp2͈͊ÔƂ + { + if (double.IsInfinity(a)) { - return null; + if (p2.Y > rect.UpperY) + return new[] { new PointD(p1.X, rect.UpperY) }; + else + return new[] { new PointD(p1.X, rect.Y) }; } - else//p1͈͓ɂp2͈͊ÔƂ - { - if (double.IsInfinity(a)) - { - if (p2.Y > rect.UpperY) - return new[] { new PointD(p1.X, rect.UpperY) }; - else - return new[] { new PointD(p1.X, rect.Y) }; - } - //x=maxXƂ̌_ - double c = a * rect.UpperX + b; + //x=maxXƂ̌_ + double c = a * rect.UpperX + b; - if (c < rect.Y) - return new[] { new PointD((rect.Y - b) / a, rect.Y) }; - else if (c > rect.UpperY) - return new[] { new PointD((rect.UpperY - b) / a, rect.UpperY) }; + if (c < rect.Y) + return new[] { new PointD((rect.Y - b) / a, rect.Y) }; + else if (c > rect.UpperY) + return new[] { new PointD((rect.UpperY - b) / a, rect.UpperY) }; + else + return new[] { new PointD(rect.UpperX, c) }; + } + } + else//p1͈͊OɂƂ + { + if (rect.IsInsde(p2))//p1͈͊Op2͈͓̂Ƃ + { + // y= a x + b + if (double.IsInfinity(a)) + { + if (p1.Y > rect.UpperY) + return new[] { new PointD(p1.X, rect.UpperY) }; else - return new[] { new PointD(rect.UpperX, c) }; + return new[] { new PointD(p1.X, rect.Y) }; } + //x=minXƂ̌_ + double c = a * rect.X + b; + + if (c < rect.Y) + return new[] { new PointD((rect.Y - b) / a, rect.Y) }; + else if (c > rect.UpperY) + return new[] { new PointD((rect.UpperY - b) / a, rect.UpperY) }; + else + return new[] { new PointD(rect.X, c) }; } - else//p1͈͊OɂƂ + else//p1p2͈͊ÔƂ { - if (rect.IsInsde(p2))//p1͈͊Op2͈͓̂Ƃ + if (double.IsInfinity(a)) //X̎ { - // y= a x + b - if (double.IsInfinity(a)) + if (p1.X >= rect.X && p1.X <= rect.UpperX)//҂X͔͈͓AYꂼƉ𒴂Ăꍇ { - if (p1.Y > rect.UpperY) - return new[] { new PointD(p1.X, rect.UpperY) }; - else - return new[] { new PointD(p1.X, rect.Y) }; + if (p1.Y < rect.Y && rect.UpperY < p2.Y) + return new[] { new PointD(p1.X, rect.Y), new PointD(p1.X, rect.UpperY) }; + else if (p2.Y < rect.Y && rect.UpperY < p1.Y) + return new[] { new PointD(p1.X, rect.UpperY), new PointD(p1.X, rect.Y) }; } - //x=minXƂ̌_ - double c = a * rect.X + b; - - if (c < rect.Y) - return new[] { new PointD((rect.Y - b) / a, rect.Y) }; - else if (c > rect.UpperY) - return new[] { new PointD((rect.UpperY - b) / a, rect.UpperY) }; else - return new[] { new PointD(rect.X, c) }; + return null; } - else//p1p2͈͊ÔƂ - { - if (double.IsInfinity(a)) //X̎ - { - if (p1.X >= rect.X && p1.X <= rect.UpperX)//҂X͔͈͓AYꂼƉ𒴂Ăꍇ - { - if (p1.Y < rect.Y && rect.UpperY < p2.Y) - return new[] { new PointD(p1.X, rect.Y), new PointD(p1.X, rect.UpperY) }; - else if (p2.Y < rect.Y && rect.UpperY < p1.Y) - return new[] { new PointD(p1.X, rect.UpperY), new PointD(p1.X, rect.Y) }; - } - else - return null; - } - //4‚̌_߂ + //4‚̌_߂ - var temp = new List(new[] { - new PointD(rect.X, a * rect.X + b), - new PointD(rect.UpperX, a * rect.UpperX + b), - new PointD((rect.Y - b) / a, rect.Y), - new PointD((rect.UpperY - b) / a, rect.UpperY) }); + var temp = new List(new[] { + new PointD(rect.X, a * rect.X + b), + new PointD(rect.UpperX, a * rect.UpperX + b), + new PointD((rect.Y - b) / a, rect.Y), + new PointD((rect.UpperY - b) / a, rect.UpperY) }); - var pts = temp.Where(p => rect.IsInsde(p) && p.X >= p1.X && p.X <= p2.X && p.Y >= Math.Min(p1.Y, p2.Y) && p.Y <= Math.Max(p1.Y, p2.Y)).OrderBy(p => p.X).ToArray(); - if (pts.Length == 2) - return pts; - else - return null; - } + var pts = temp.Where(p => rect.IsInsde(p) && p.X >= p1.X && p.X <= p2.X && p.Y >= Math.Min(p1.Y, p2.Y) && p.Y <= Math.Max(p1.Y, p2.Y)).OrderBy(p => p.X).ToArray(); + if (pts.Length == 2) + return pts; + else + return null; } } + } - /// - /// 3ɂāA a x + b y + c z + d = 0 (@xNg(a,b,c))ƁA_(x, y, z)Ƃ̋(Βl)Ԃ - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static double GetLengthFromPlane(double a, double b, double c, double d, double x, double y, double z) - { - return Math.Abs(a * x + b * y + c * z + d) / Math.Sqrt(a * a + b * b + c * c); - } - - /// - /// _Wŏ@ɂ镽ʃp[^double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) Ԃ - /// - /// - /// double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) - public static double[] GetPlaneEquationFromPoints(IEnumerable points) - { - //http://sysplan.nams.kyushu-u.ac.jp/gen/edu/Algorithms/PlaneFitting/index.html - //pdfCrystallograpy/tH_ - - var ave = Vector3DBase.Average(points); - var mtx = new DenseMatrix(points.Count(), 3); - int n = 0; - foreach (var p in points.Select(p => p - ave)) - mtx.SetRow(n++, p.ToDoublearray()); + /// + /// 3ɂāA a x + b y + c z + d = 0 (@xNg(a,b,c))ƁA_(x, y, z)Ƃ̋(Βl)Ԃ + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static double GetLengthFromPlane(double a, double b, double c, double d, double x, double y, double z) + { + return Math.Abs(a * x + b * y + c * z + d) / Math.Sqrt(a * a + b * b + c * c); + } - var evd = (mtx.Transpose() * mtx).Evd(Symmetricity.Unknown); - var index = evd.EigenValues.AbsoluteMinimumIndex(); + /// + /// _Wŏ@ɂ镽ʃp[^double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) Ԃ + /// + /// + /// double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) + public static double[] GetPlaneEquationFromPoints(IEnumerable points) + { + //http://sysplan.nams.kyushu-u.ac.jp/gen/edu/Algorithms/PlaneFitting/index.html + //pdfCrystallograpy/tH_ - double a = evd.EigenVectors[0, index], b = evd.EigenVectors[1, index], c = evd.EigenVectors[2, index], d = -(a * ave.X + b * ave.Y + c * ave.Z); - return new double[] { a, b, c, d }; - } + var ave = Vector3DBase.Average(points); + var mtx = new DenseMatrix(points.Count(), 3); + int n = 0; + foreach (var p in points.Select(p => p - ave)) + mtx.SetRow(n++, p.ToDoublearray()); - /// - /// _Wŏ@ɂ镽ʃp[^double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) Ԃ - /// - /// - /// double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) - public static double[] GetPlaneEquationFromPoints(IEnumerable points) - { - //http://sysplan.nams.kyushu-u.ac.jp/gen/edu/Algorithms/PlaneFitting/index.html - //pdfCrystallograpy/tH_ + var evd = (mtx.Transpose() * mtx).Evd(Symmetricity.Unknown); + var index = evd.EigenValues.AbsoluteMinimumIndex(); - var ave = new OpenTK.Vector3d(); - foreach (var p in points) - ave += p; - ave /= points.Count(); + double a = evd.EigenVectors[0, index], b = evd.EigenVectors[1, index], c = evd.EigenVectors[2, index], d = -(a * ave.X + b * ave.Y + c * ave.Z); + return new double[] { a, b, c, d }; + } - var mtx = new DenseMatrix(points.Count(), 3); - int n = 0; - foreach (var p in points.Select(p => p - ave)) - mtx.SetRow(n++, new[] { p.X, p.Y, p.Z }); + /// + /// _Wŏ@ɂ镽ʃp[^double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) Ԃ + /// + /// + /// double[]{a,b,c,d} (AAʕ a x + b y + c z + d = 0) + public static double[] GetPlaneEquationFromPoints(IEnumerable points) + { + //http://sysplan.nams.kyushu-u.ac.jp/gen/edu/Algorithms/PlaneFitting/index.html + //pdfCrystallograpy/tH_ - //var evd = (mtx.Transpose() * mtx).Evd(Symmetricity.Unknown); - var evd = mtx.TransposeThisAndMultiply(mtx).Evd(Symmetricity.Symmetric); - var index = evd.EigenValues.AbsoluteMinimumIndex(); + var ave = new OpenTK.Vector3d(); + foreach (var p in points) + ave += p; + ave /= points.Count(); - double a = evd.EigenVectors[0, index], b = evd.EigenVectors[1, index], c = evd.EigenVectors[2, index], d = -(a * ave.X + b * ave.Y + c * ave.Z); - return new double[] { a, b, c, d }; - } + var mtx = new DenseMatrix(points.Count(), 3); + int n = 0; + foreach (var p in points.Select(p => p - ave)) + mtx.SetRow(n++, new[] { p.X, p.Y, p.Z }); + //var evd = (mtx.Transpose() * mtx).Evd(Symmetricity.Unknown); + var evd = mtx.TransposeThisAndMultiply(mtx).Evd(Symmetricity.Symmetric); + var index = evd.EigenValues.AbsoluteMinimumIndex(); - /// - /// ^ꂽ(double[4], a x + b y + c z + d >= 0 )̏WŁAԂ‚邩ǂ𔻒 - /// - /// - /// - public static bool Enclosed(double[][] bounds) - { - var countList = new List(); + double a = evd.EigenVectors[0, index], b = evd.EigenVectors[1, index], c = evd.EigenVectors[2, index], d = -(a * ave.X + b * ave.Y + c * ave.Z); + return new double[] { a, b, c, d }; + } - for (int i = 0; i < bounds.Length; i++) - { - var n = GetClippedPolygon(i, bounds).Length; - if (n >= 3) - countList.Add(GetClippedPolygon(i, bounds).Length); - } - return countList.Count >= 4; - } + /// + /// ^ꂽ(double[4], a x + b y + c z + d >= 0 )̏WŁAԂ‚邩ǂ𔻒 + /// + /// + /// + public static bool Enclosed(double[][] bounds) + { + var countList = new List(); - /// - /// EʂɂĐ؂ꂽp`̒_W߂. - /// - /// ؂ (double[4], a x + b y + c z + d = 0) - /// E (double[4], a x + b y + c z + d >= 0 ) - /// - public static double[][] GetClippedPolygon(double[] plane, double[][] bounds) + for (int i = 0; i < bounds.Length; i++) { - var pts = new List(); - for (int i = 0; i < bounds.Length; i++) - for (int j = i + 1; j < bounds.Length; j++) - { - var mtx = new Matrix3D(plane[0], bounds[i][0], bounds[j][0], plane[1], bounds[i][1], bounds[j][1], plane[2], bounds[i][2], bounds[j][2]); - if (Math.Abs(mtx.Determinant()) > 0.0000000001) - { - var pt = mtx.Inverse() * new Vector3DBase(-plane[3], -bounds[i][3], -bounds[j][3]); - if (bounds.All(b => b[0] * pt.X + b[1] * pt.Y + b[2] * pt.Z + b[3] > -0.0000000001) && pts.All(p => (p - pt).Length2 > 0.0000000001)) - pts.Add(pt); - } - } - return pts.Select(p => p.ToDoublearray()).ToArray(); + var n = GetClippedPolygon(i, bounds).Length; + if (n >= 3) + countList.Add(GetClippedPolygon(i, bounds).Length); } - /// - /// EʂɂĐ؂ꂽp`̒_W߂. - /// - /// ؂ʂ̃CfbNX - /// E (i͏) (double[4], a x + b y + c z + d >= 0 ) - /// - public static double[][] GetClippedPolygon(int i, double[][] bounds) - { - return GetClippedPolygon(bounds[i], bounds.Where((b, j) => i != j).ToArray()); - } + return countList.Count >= 4; + } - /// - /// xNga1 => xNgb1 xNga2 => xNgb2Ɏʂ悤ȉ]s߂. a1,a2,b1,b2̒1łȂĂ\Ȃi֐ŋKij - /// - /// - /// - /// - /// - /// - public static Matrix3D GetRotation(Vector3DBase a1, Vector3DBase a2, Vector3DBase b1, Vector3DBase b2) - { - //܂Ki - var v1 = new Vector3DBase(a1).Normarize(); - var v2 = new Vector3DBase(a2).Normarize(); - var w1 = new Vector3DBase(b1).Normarize(); - var w2 = new Vector3DBase(b2).Normarize(); + /// + /// EʂɂĐ؂ꂽp`̒_W߂. + /// + /// ؂ (double[4], a x + b y + c z + d = 0) + /// E (double[4], a x + b y + c z + d >= 0 ) + /// + public static double[][] GetClippedPolygon(double[] plane, double[][] bounds) + { + var pts = new List(); + for (int i = 0; i < bounds.Length; i++) + for (int j = i + 1; j < bounds.Length; j++) + { + var mtx = new Matrix3D(plane[0], bounds[i][0], bounds[j][0], plane[1], bounds[i][1], bounds[j][1], plane[2], bounds[i][2], bounds[j][2]); + if (Math.Abs(mtx.Determinant()) > 0.0000000001) + { + var pt = mtx.Inverse() * new Vector3DBase(-plane[3], -bounds[i][3], -bounds[j][3]); + if (bounds.All(b => b[0] * pt.X + b[1] * pt.Y + b[2] * pt.Z + b[3] > -0.0000000001) && pts.All(p => (p - pt).Length2 > 0.0000000001)) + pts.Add(pt); + } + } + return pts.Select(p => p.ToDoublearray()).ToArray(); + } - var v3 = Vector3DBase.VectorProduct(v1, v2); - var w3 = Vector3DBase.VectorProduct(w1, w2); + /// + /// EʂɂĐ؂ꂽp`̒_W߂. + /// + /// ؂ʂ̃CfbNX + /// E (i͏) (double[4], a x + b y + c z + d >= 0 ) + /// + public static double[][] GetClippedPolygon(int i, double[][] bounds) + { + return GetClippedPolygon(bounds[i], bounds.Where((b, j) => i != j).ToArray()); + } - return new Matrix3D(w1, w2, w3) * new Matrix3D(v1, v2, v3).Inverse(); - } + /// + /// xNga1 => xNgb1 xNga2 => xNgb2Ɏʂ悤ȉ]s߂. a1,a2,b1,b2̒1łȂĂ\Ȃi֐ŋKij + /// + /// + /// + /// + /// + /// + public static Matrix3D GetRotation(Vector3DBase a1, Vector3DBase a2, Vector3DBase b1, Vector3DBase b2) + { + //܂Ki + var v1 = new Vector3DBase(a1).Normarize(); + var v2 = new Vector3DBase(a2).Normarize(); + var w1 = new Vector3DBase(b1).Normarize(); + var w2 = new Vector3DBase(b2).Normarize(); + var v3 = Vector3DBase.VectorProduct(v1, v2); + var w3 = Vector3DBase.VectorProduct(w1, w2); + return new Matrix3D(w1, w2, w3) * new Matrix3D(v1, v2, v3).Inverse(); + } - /// - /// ~ƕʂƂ̌_(fʍWn)̏W𓾂B - /// ~͒_(0,0,0), ~p(alpha), ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ`B - /// fʂZ=L𖞂A̓_upperLeft(fʍWn)AE̓_lowerRight(fʍWn)Œ``ʂłB - /// fʍWnƂ́A_(X,Y,L)ɂ‚āA(X,Y)̂̕Ƃł(fʂ̒S(0,0,L)ł))B - /// - /// ~p(alpha) - /// ~S̃p[^. ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ` - /// ~S̃p[^. ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ` - /// fʂ̃p[^. fʂZ=LŒ`. - /// `ʂ̍W - /// `ʂ̉EW - /// - /// - public static List> ConicSection(in double alpha, in double phi, in double tau, in double l, in PointD upperLeft, in PointD lowerRight, bool bothCone = false) - { - double cosPhi = Math.Cos(phi), sinPhi = Math.Sin(phi); - double cosTau = Math.Cos(tau), sinTau = Math.Sin(tau), sinTau2 = sinTau * sinTau; - double cosAlpha = Math.Cos(alpha), cosAlpha2 = cosAlpha * cosAlpha; + /// + /// ~ƕʂƂ̌_(fʍWn)̏W𓾂B + /// ~͒_(0,0,0), ~p(alpha), ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ`B + /// fʂZ=L𖞂A̓_upperLeft(fʍWn)AE̓_lowerRight(fʍWn)Œ``ʂłB + /// fʍWnƂ́A_(X,Y,L)ɂ‚āA(X,Y)̂̕Ƃł(fʂ̒S(0,0,L)ł))B + /// + /// ~p(alpha) + /// ~S̃p[^. ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ` + /// ~S̃p[^. ~S(cosPhi*sinTau, -sinPhi*sinTau, cosTau)Œ` + /// fʂ̃p[^. fʂZ=LŒ`. + /// `ʂ̍W + /// `ʂ̉EW + /// + /// + public static List> ConicSection(in double alpha, in double phi, in double tau, in double l, in PointD upperLeft, in PointD lowerRight, bool bothCone = false) + { + double cosPhi = Math.Cos(phi), sinPhi = Math.Sin(phi); + double cosTau = Math.Cos(tau), sinTau = Math.Sin(tau), sinTau2 = sinTau * sinTau; + double cosAlpha = Math.Cos(alpha), cosAlpha2 = cosAlpha * cosAlpha; - double P = -(sinTau2 - cosAlpha2) / (l * l * (1 - cosAlpha2)), Psqrt = Math.Sqrt(Math.Abs(P)); - double Q = -P * (sinTau2 - cosAlpha2) / cosAlpha2, Qsqrt = Math.Sqrt(Q); + double P = -(sinTau2 - cosAlpha2) / (l * l * (1 - cosAlpha2)), Psqrt = Math.Sqrt(Math.Abs(P)); + double Q = -P * (sinTau2 - cosAlpha2) / cosAlpha2, Qsqrt = Math.Sqrt(Q); - PointD rot(in PointD pt) => new PointD(cosPhi * pt.X - sinPhi * pt.Y, sinPhi * pt.X + cosPhi * pt.Y); + PointD rot(in PointD pt) => new PointD(cosPhi * pt.X - sinPhi * pt.Y, sinPhi * pt.X + cosPhi * pt.Y); - var maxWidth = Math.Max(upperLeft.Length, lowerRight.Length); + var maxWidth = Math.Max(upperLeft.Length, lowerRight.Length); - var tempResult = new List>(); + var tempResult = new List>(); - if (!double.IsNaN(Psqrt) && !double.IsNaN(Qsqrt)) + if (!double.IsNaN(Psqrt) && !double.IsNaN(Qsqrt)) + { + if (Math.Abs(P) < 1E-8)// + { + var pts = new List(); + var shift = new PointD(0, -l / Math.Tan(2 * tau));//sړ + for (double x = -maxWidth; x < maxWidth; x += maxWidth / 2000.0) + pts.Add(rot(new PointD(x, x * x * sinTau / cosTau / l / 2) + shift)); + tempResult.Add(pts); + } + else { - if (Math.Abs(P) < 1E-8)// + var shift = new PointD(0, -l * sinTau * cosTau / (sinTau2 - cosAlpha2));//sړ + if (P > 0)//ȉ~ { var pts = new List(); - var shift = new PointD(0, -l / Math.Tan(2 * tau));//sړ - for (double x = -maxWidth; x < maxWidth; x += maxWidth / 2000.0) - pts.Add(rot(new PointD(x, x * x * sinTau / cosTau / l / 2) + shift)); + for (double omega = 0; omega < Math.PI * 2.0000001; omega += Math.PI / 2000) + pts.Add(rot(new PointD(Math.Sin(omega + Math.PI / 2) / Psqrt, -Math.Cos(omega + Math.PI / 2) / Qsqrt) + shift)); tempResult.Add(pts); } - else + else//oȐ { - var shift = new PointD(0, -l * sinTau * cosTau / (sinTau2 - cosAlpha2));//sړ - if (P > 0)//ȉ~ + var pts1 = new List(); + //var pts2 = new List(); + var omegaMax = Math.Log(maxWidth * Psqrt + Math.Sqrt(maxWidth * Psqrt * maxWidth * Psqrt + 1)) * 2; + var sign = (tau > 0 && alpha < Math.PI / 2) || (tau < 0 && alpha >= Math.PI / 2) ? 1 : -1; + for (double omega = -omegaMax; omega < omegaMax; omega += omegaMax / 1000) { - var pts = new List(); - for (double omega = 0; omega < Math.PI * 2.0000001; omega += Math.PI / 2000) - pts.Add(rot(new PointD(Math.Sin(omega + Math.PI / 2) / Psqrt, -Math.Cos(omega + Math.PI / 2) / Qsqrt) + shift)); - tempResult.Add(pts); - } - else//oȐ - { - var pts1 = new List(); - //var pts2 = new List(); - var omegaMax = Math.Log(maxWidth * Psqrt + Math.Sqrt(maxWidth * Psqrt * maxWidth * Psqrt + 1)) * 2; - var sign = (tau > 0 && alpha < Math.PI / 2) || (tau < 0 && alpha >= Math.PI / 2) ? 1 : -1; - for (double omega = -omegaMax; omega < omegaMax; omega += omegaMax / 1000) - { - double x = Math.Sinh(omega) / Psqrt, y = Math.Cosh(omega) / Qsqrt; - pts1.Add(new PointD(x, sign * y)); - //pts1.Add(rot(new PointD(x, sign * y) + shift)); - //pts2.Add(rot(new PointD(x, -y) + shift)); - } - tempResult.Add(pts1.Select(p => rot(p + shift)).ToList()); - if (bothCone) - tempResult.Add(pts1.Select(p => rot(new PointD(p.X, -p.Y) + shift)).ToList()); + double x = Math.Sinh(omega) / Psqrt, y = Math.Cosh(omega) / Qsqrt; + pts1.Add(new PointD(x, sign * y)); + //pts1.Add(rot(new PointD(x, sign * y) + shift)); + //pts2.Add(rot(new PointD(x, -y) + shift)); } + tempResult.Add(pts1.Select(p => rot(p + shift)).ToList()); + if (bothCone) + tempResult.Add(pts1.Select(p => rot(new PointD(p.X, -p.Y) + shift)).ToList()); } } + } - //E`FbN - var result = new List>(); + //E`FbN + var result = new List>(); - double xMin = upperLeft.X, yMin = upperLeft.Y, xMax = lowerRight.X, yMax = lowerRight.Y; - bool inside(in PointD pt) => xMin <= pt.X && pt.X <= xMax && yMin <= pt.Y && pt.Y <= yMax; + double xMin = upperLeft.X, yMin = upperLeft.Y, xMax = lowerRight.X, yMax = lowerRight.Y; + bool inside(in PointD pt) => xMin <= pt.X && pt.X <= xMax && yMin <= pt.Y && pt.Y <= yMax; - var n = tempResult.Count; - for (int i = 0; i < n; i++) + var n = tempResult.Count; + for (int i = 0; i < n; i++) + { + var pts = tempResult[i]; + var flags = pts.Select(p => inside(p)).ToList(); + for (int j = 0; j < pts.Count - 1; j++) { - var pts = tempResult[i]; - var flags = pts.Select(p => inside(p)).ToList(); - for (int j = 0; j < pts.Count - 1; j++) + if (flags[j] ^ flags[j + 1])//ǂ炩truełfalse̎ { - if (flags[j] ^ flags[j + 1])//ǂ炩truełfalse̎ - { - // (Y2-Y1)x + (X1-X2)y = X1Y2-X2Y1ƂƁA - // x = xMin, x=xMax, y=yMin, y=yMaxƂS{̒̌_vZ - double X1 = pts[j].X, X2 = pts[j + 1].X, Y1 = pts[j].Y, Y2 = pts[j + 1].Y; - var cross = new[]{ - new PointD(xMin, (X1 * Y2 - X2 * Y1 - (Y2 - Y1) * xMin) / (X1 - X2)), - new PointD(xMax, (X1 * Y2 - X2 * Y1 - (Y2 - Y1) * xMax) / (X1 - X2)), - new PointD((X1 * Y2 - X2 * Y1 - (X1 - X2) * yMin) / (Y2 - Y1),yMin), - new PointD((X1 * Y2 - X2 * Y1 - (X1 - X2) * yMax) / (Y2 - Y1),yMax) - }; - var lengthList = cross.Select(c => (c - (pts[j] + pts[j + 1]) / 2).Length2).ToList(); - var index = lengthList.IndexOf(lengthList.Min()); - flags.Insert(j + 1, true); - pts.Insert(j + 1, cross[index]); - if (flags[j]) - j++; - } + // (Y2-Y1)x + (X1-X2)y = X1Y2-X2Y1ƂƁA + // x = xMin, x=xMax, y=yMin, y=yMaxƂS{̒̌_vZ + double X1 = pts[j].X, X2 = pts[j + 1].X, Y1 = pts[j].Y, Y2 = pts[j + 1].Y; + var cross = new[]{ + new PointD(xMin, (X1 * Y2 - X2 * Y1 - (Y2 - Y1) * xMin) / (X1 - X2)), + new PointD(xMax, (X1 * Y2 - X2 * Y1 - (Y2 - Y1) * xMax) / (X1 - X2)), + new PointD((X1 * Y2 - X2 * Y1 - (X1 - X2) * yMin) / (Y2 - Y1),yMin), + new PointD((X1 * Y2 - X2 * Y1 - (X1 - X2) * yMax) / (Y2 - Y1),yMax) + }; + var lengthList = cross.Select(c => (c - (pts[j] + pts[j + 1]) / 2).Length2).ToList(); + var index = lengthList.IndexOf(lengthList.Min()); + flags.Insert(j + 1, true); + pts.Insert(j + 1, cross[index]); + if (flags[j]) + j++; } - for (int j = 0; j < pts.Count; j++) + } + for (int j = 0; j < pts.Count; j++) + { + if (flags[j]) { - if (flags[j]) - { - result.Add(new List()); - for (; j < pts.Count && flags[j]; j++) - result[^1].Add(pts[j]); - } + result.Add(new List()); + for (; j < pts.Count && flags[j]; j++) + result[^1].Add(pts[j]); } } - - - return result; } + + return result; } + } \ No newline at end of file diff --git a/Crystallography/Mathematics/Marquardt.cs b/Crystallography/Mathematics/Marquardt.cs index efb91c7..1765349 100644 --- a/Crystallography/Mathematics/Marquardt.cs +++ b/Crystallography/Mathematics/Marquardt.cs @@ -1,6 +1,5 @@ using MathNet.Numerics.LinearAlgebra.Double; using System; -using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -8,638 +7,630 @@ using DMat = MathNet.Numerics.LinearAlgebra.Double.DenseMatrix; using DVec = MathNet.Numerics.LinearAlgebra.Double.DenseVector; -namespace Crystallography +namespace Crystallography; +public class Marquardt { - public class Marquardt - { - - + public enum Precision { High, Medium, Low } + public enum FuncType + { + #region 組み込み関数 + /// + /// Gaussian 1次元, パラメータは 0: X0, 1: H, 2: A + /// + G1, - public enum Precision { High, Medium, Low } - - public enum FuncType - { - #region 組み込み関数 - - /// - /// Gaussian 1次元, パラメータは 0: X0, 1: H, 2: A - /// - G1, - - /// - /// Gaussian 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: A - /// - G2, - - /// - /// Gaussian 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A - /// - G2E, - - /// - /// Lorenzian 1次元, パラメータは 0: X0, 1: H, 2: A - /// - L1, - - /// - /// Lorenzian 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: A - /// - L2, - - /// - /// Lorenzian 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A - /// - L2E, - - /// - /// PseudoVoigt 1次元, パラメータは 0: X0, 1: H, 2: Eta, 3: A - /// - PV1, - - /// - /// PseudoVoigt 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: Eta, 4: A - /// - PV2, - - /// - /// PseudoVoigt 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: Eta, 6: A - /// - PV2E, - - /// - /// 平面 (B0 + Bx X + By Y), パラメータは 0: B0, 1: Bx, 2: By - /// - Plane - - #endregion 組み込み関数 - } - - public class Function - { - /// - /// 実質的な無限小 infinitesimal - /// - private const double inf = 1E-10; - - #region プロパティ - - /// - /// 関数の表式. Func内の1番目は座標値, 2番目はパラメータ, 3番目は返り値 - /// - public Func Formula { get; set; } - - /// - /// 複数の座標値に対する関数の表式. Func内の1番目は座標値の, 2番目はパラメータ, 3番目は返り値 - /// - public Func FormulaEx { get; set; } - - /// - /// パラメータ配列 - /// - public double[] Prms { get; set; } - - /// - /// パラメータ配列. AddPrmsされたときに、1世代前のパラメータとして保存される - /// - public double[] PrmsPrev { get; set; } - - /// - /// パラメータの数 - /// - public int PrmLength { get; } - - /// - /// 制約条件. double[] をdouble[]に変換する. nullでもよい. - /// - public Func Constraints { get; set; } - - /// - /// 微分値が解析的にわかっている場合のみ設定. nullでもよい. - /// - public Func Derivatives { get; set; } - - public int Length { get => Prms.Length; } - #endregion プロパティ - - private readonly double[] steps; - - /// - /// コンストラクタ - /// - /// - /// - /// - /// - public Function(Func formula, double[] parameters, Func constraints = null, Func derivatives = null) - { - Formula = formula; - Prms = parameters; - PrmsPrev = new double[Prms.Length]; - Constraints = constraints; - Derivatives = derivatives; - steps = Enumerable.Range(-9, 20).Select(n => Pow(10, n)).ToArray(); - PrmLength = Prms.Length; - } + /// + /// Gaussian 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: A + /// + G2, - /// - /// 関数形を指定したコンストラクタ - /// - /// - /// - /// Gaussian1 or Lorenzian1の場合: 0: X0, 1: H, 2: A - /// Gaussian2 or Lorenzian2の場合: 0: X0, 1: Y0, 2: H, 3: A - /// Gaussian2Ellipse or Lorenzian2Ellipseの場合: 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A - /// PseudoVoigt1 の場合; 0: X0, 1: H, 2: Eta, 3: A - /// PseudoVoigt2 の場合; 0: X0, 1: Y0, 2: H, 3: Eta, 4: A - /// PseudoVoigt2Ellipse の場合; 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: Eta, 6: A - /// - public Function(FuncType type, params double[] parameters) - { - Prms = parameters; - PrmsPrev = new double[Prms.Length]; + /// + /// Gaussian 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A + /// + G2E, - switch (type) - { - #region - case FuncType.G1: - Formula = (x, p) => Gaussian(x[0], p[0], p[1], p[2]); - Constraints = p => new[] { p[0], Max(p[1], inf), Max(p[2], inf) }; - break; - - case FuncType.G2: - Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3]); - Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf) }; - break; - - case FuncType.G2E: - Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3], p[4], p[5]); - Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf), p[4], Max(p[5], inf) }; - break; - - case FuncType.L1: - Formula = (x, p) => Lorenzian(x[0], p[0], p[1], p[2]); - Constraints = p => new[] { p[0], Max(p[1], inf), Max(p[2], inf) }; - break; - - case FuncType.L2: - Formula = (x, p) => Lorenzian(x[0], x[1], p[0], p[1], p[2], p[3]); - Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf) }; - break; - - case FuncType.L2E: - Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3], p[4], p[5]); - Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf), p[4], Max(p[5], inf) }; - break; - - case FuncType.PV1: - Formula = (x, p) => PseudoVoigt(x[0], p[0], p[1], p[2], p[3]); - Constraints = p => new[] { p[0], Max(p[1], 0.1), Min(Max(p[2], 0), 1.5), Max(p[3], inf) }; - break; - - case FuncType.PV2: - Formula = (x, p) => PseudoVoigt(x[0], x[1], p[0], p[1], p[2], p[3], p[4]); - Constraints = p => new[] { p[0], p[1], Max(p[2], 0.1), Min(Max(p[3], 0), 1.5), Max(p[4], inf) }; - break; - - case FuncType.PV2E: - Formula = (x, p) => PseudoVoigt(x, p[0], p[1], p[2], p[3], p[4], p[5], p[6]); - Constraints = p => new[] { p[0], p[1], Max(p[2], 0.1), Max(p[3], 0.1), p[4], Min(Max(p[5], 0), 1.5), Max(p[6], inf) }; - Derivatives = (x, p) => PseudoVoigtDiff(x, p[0], p[1], p[2], p[3], p[4], p[5], p[6]); - break; - - case FuncType.Plane: - Formula = (x, p) => p[0] + p[1] * x[0] + p[2] * x[1]; - Derivatives = (x, p) => new[] { 1.0, x[0], x[1] }; - break; - #endregion - } + /// + /// Lorenzian 1次元, パラメータは 0: X0, 1: H, 2: A + /// + L1, - steps = Enumerable.Range(-9, 20).Select(n => Pow(10, n)).ToArray(); - PrmLength = Prms.Length; - } + /// + /// Lorenzian 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: A + /// + L2, - /// - /// 偏微分値を得る - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double[] GetDerivative(double[] x) - { - if (Derivatives != null) - return Derivatives(x, Prms); - - var derivative = new double[Length]; - var f0 = Formula(x, Prms); - for (int j = 0; j < Length; j++) - for (int i = 0; i < steps.Length; i++) - { - var pTemp = Prms.ToArray();//値渡しでコピー - pTemp[j] += steps[i]; - derivative[j] = (Formula(x, pTemp) - f0) / steps[i]; - if (derivative[j] != 0) break; - } - return derivative; - } + /// + /// Lorenzian 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A + /// + L2E, - /// - /// 与えられた座標での値を得る - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double GetValue(params double[] x) => Formula(x, Prms); - - /// - /// 与えられた座標での値を得る - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public double[] GetValues(params double[][] x) - { - return FormulaEx != null ? - FormulaEx(x, Prms) : - x.AsParallel().Select(x1 => Formula(x1, Prms)).ToArray(); - } + /// + /// PseudoVoigt 1次元, パラメータは 0: X0, 1: H, 2: Eta, 3: A + /// + PV1, - /// - /// 全パラメータを指定量だけ変化させる. 制約条件も課す。 - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void AddPrms(double[] delta) - { - for (var i = 0; i < Prms.Length; i++) - { - PrmsPrev[i] = Prms[i]; - Prms[i] += delta[i]; - } - ApplyConstraints(); - } + /// + /// PseudoVoigt 2次元真円, パラメータは 0: X0, 1: Y0, 2: H, 3: Eta, 4: A + /// + PV2, - /// - /// 全パラメータを一世代前のものに戻す - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void RevertPrms() - { - for (int i = 0; i < Prms.Length; i++) - Prms[i] = PrmsPrev[i]; - } + /// + /// PseudoVoigt 2次元楕円, パラメータは 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: Eta, 6: A + /// + PV2E, - /// - /// 全パラメータに制約を課す - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ApplyConstraints() - { - if (Constraints != null) - Prms = Constraints(Prms); - } - } + /// + /// 平面 (B0 + Bx X + By Y), パラメータは 0: B0, 1: Bx, 2: By + /// + Plane - public static double RambdaCoeff1 { get; set; } = 0.1; - public static double RambdaCoeff2 { get; set; } = 8; + #endregion 組み込み関数 + } + public class Function + { /// - /// 静的メソッド. Marquardt法によるフィッティングを実行する. + /// 実質的な無限小 infinitesimal /// - /// 観測値. x は座標, y は強度、 wは重み(分散の逆数) - /// Functinクラスの配列. - /// Prms[i][j]はi番目のFunctionのj番目の最適パラメータ. Errorはまだ未実装. Rは残差 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static (double[][] Prms, double[][] Error, double R) - Solve(IEnumerable<(double[] x, double y, double w)> obsValues, IEnumerable functions, Precision precision = Precision.Medium) - { - #region 計算精度をセット - int countMax = 200; - double rambdaMax = 1E5, threshold = 1E-10; - if (precision == Precision.High) - { - countMax = 400; - rambdaMax = 1E7; - threshold = 1E-15; - } - else if (precision == Precision.Low) - { - countMax = 50; - rambdaMax = 1E3; - threshold = 1E-5; - } - #endregion - - var obs = obsValues.AsParallel(); - var funcs = functions.ToList(); - int valuesLength = obs.Count(), totalPrmsLength = funcs.Sum(f => f.Length), funcLength = funcs.Count; - if (valuesLength == 0) return (null, null, double.PositiveInfinity); - var weight = new DiagonalMatrix(valuesLength, valuesLength, obs.Select(o => o.w).ToArray()); - var rambda = 10.0; - var alpha = new DMat(totalPrmsLength, totalPrmsLength); - var beta = new DVec(totalPrmsLength); - var rCur = new DVec(obs.Select(v => v.y - funcs.Sum(f => f.GetValue(v.x))).ToArray());//現在の残差を計算 - var r2Cur = rCur * weight * rCur;//残差の二乗和を計算 - - var renewAlpha = true; - var exclude = new bool[totalPrmsLength]; - int successCount = -1;//連続成功回数(正)、あるいは連続失敗回数(負)を記録する。 - - for (int count = 0; count < countMax && rambda < rambdaMax; count++) - { - if (renewAlpha) - { - var jacob = DMat.OfRowArrays(obs.Select(o => - { - var d = new double[totalPrmsLength]; - for (int j = 0, n = 0; j < funcLength; n += funcs[j].PrmLength, j++) - Buffer.BlockCopy(funcs[j].GetDerivative(o.x), 0, d, n * 8, funcs[j].PrmLength * 8); - return d; - }).ToArray()); - - var jacobW = (DMat)(weight * jacob); - alpha = (DMat)jacob.TransposeThisAndMultiply(jacobW);//alpha行列を計算 - beta = rCur * jacobW;//betaベクトルを計算 - - //偏微分値がゼロになってしまう時の対策 - exclude = alpha.ToRowArrays().Select(row => row.All(e => e == 0)).ToArray(); - if (exclude.Contains(true)) - { - if (exclude.Count(e => e) == beta.Count) - return (null, null, double.PositiveInfinity); - var betaList = beta.ToList(); - for (int i = exclude.Length - 1; i >= 0; i--) - if (exclude[i]) - { - betaList.RemoveAt(i); - alpha = (DMat)alpha.RemoveColumn(i); - alpha = (DMat)alpha.RemoveRow(i); - } - beta = new DVec(betaList.ToArray()); - } - } + private const double inf = 1E-10; - var alphaTemp = alpha + DMat.OfDiagonalVector(alpha.Diagonal() * rambda);//alphaの対角成分に1+rambdaを掛ける。 - if (alphaTemp.TryInverse(out Matrix alphaInv) == false)//逆行列を計算 - return (null, null, double.PositiveInfinity); //失敗した場合は終了 + #region プロパティ - //deltaベクトルを計算 - var delta = (beta * alphaInv).ToList(); - //偏微分値がゼロになってしまう時の対策 - if (delta.Count != totalPrmsLength) - for (int i = 0; i < exclude.Length; i++) - if (exclude[i]) - delta.Insert(i, 0); + /// + /// 関数の表式. Func内の1番目は座標値, 2番目はパラメータ, 3番目は返り値 + /// + public Func Formula { get; set; } - //パラメータを変化させる - for (int j = 0, n = 0; j < funcLength; n += funcs[j].PrmLength, j++) - funcs[j].AddPrms(delta.Skip(n).Take(funcs[j].PrmLength).ToArray()); + /// + /// 複数の座標値に対する関数の表式. Func内の1番目は座標値の, 2番目はパラメータ, 3番目は返り値 + /// + public Func FormulaEx { get; set; } - var rNew = new DVec(obs.Select(v => v.y - funcs.Sum(f => f.GetValue(v.x))).ToArray());//新しいパラメータで残差を計算 - var r2New = rNew * weight * rNew; //残差の二乗和を計算 + /// + /// パラメータ配列 + /// + public double[] Prms { get; set; } - renewAlpha = r2New < r2Cur; - if (renewAlpha) - { - successCount = successCount < 0 ? 1 : successCount + 1; - if ((r2Cur - r2New) / r2Cur < threshold) - { - r2Cur = r2New; - break;//十分収束が進んだ時は終了 - } - rCur = rNew; - r2Cur = r2New; - rambda = successCount > 2 ? rambda * RambdaCoeff1 : rambda;//2回連続で成功したら、Rambdaを減らす. - } - else - { - successCount = successCount > 0 ? -1 : successCount - 1; - if (successCount < -3)//4回連続で失敗したら、取り合えず現状を採用. - { - successCount = 1; - rCur = rNew; - r2Cur = r2New; - renewAlpha = true; - } - else - { - rambda *= RambdaCoeff2; - funcs.ForEach(f => f.RevertPrms()); - } - } - } - return (functions.Select(f => f.Prms).ToArray(), null, r2Cur / obs.Sum(v => v.w * v.y * v.y)); - } + /// + /// パラメータ配列. AddPrmsされたときに、1世代前のパラメータとして保存される + /// + public double[] PrmsPrev { get; set; } - private const double ln2 = 0.69314718055994530941723212145818; - private const double sqrtln2 = 0.8325546111576977563531646448952; - private const double pi = 3.1415926535897932384626433832795; - private const double piInv = 0.31830988618379067153776752674503; - private const double sqrtpi = 1.7724538509055160272981674833411; - private const double ln2_pi = ln2 / pi; - private const double c = 0.58740105196819947475170563927231;// = 4^(1/3) - 1 + /// + /// パラメータの数 + /// + public int PrmLength { get; } - #region 組み込み関数 + /// + /// 制約条件. double[] をdouble[]に変換する. nullでもよい. + /// + public Func Constraints { get; set; } /// - /// ローレンツ関数 1次元 + /// 微分値が解析的にわかっている場合のみ設定. nullでもよい. /// - /// xの値 - /// xの中心値 - /// 半値半幅 - /// 積分強度 - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Lorenzian(double x, double x0, double h, double a) => a / (pi * h) / (1 + (x - x0) / h * (x - x0) / h); + public Func Derivatives { get; set; } + + public int Length { get => Prms.Length; } + #endregion プロパティ + + private readonly double[] steps; /// - /// ローレンツ関数 2次元 (真円) + /// コンストラクタ /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅 - /// 積分強度 - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Lorenzian(double x, double y, double x0, double y0, double h, double a) - => a / (2 * pi * h * h) / (1 + c * (x - x0) / h * (x - x0) / h + c * (y - y0) / h * (y - y0) / h); + /// + /// + /// + /// + public Function(Func formula, double[] parameters, Func constraints = null, Func derivatives = null) + { + Formula = formula; + Prms = parameters; + PrmsPrev = new double[Prms.Length]; + Constraints = constraints; + Derivatives = derivatives; + steps = Enumerable.Range(-9, 20).Select(n => Pow(10, n)).ToArray(); + PrmLength = Prms.Length; + } /// - /// ローレンツ関数 2次元 (楕円) + /// 関数形を指定したコンストラクタ /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅1 - /// 半値半幅2 - /// h1の方向に回転する角度 - /// 積分強度 - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Lorenzian(double x, double y, double x0, double y0, double h1, double h2, double t, double a) + /// + /// + /// Gaussian1 or Lorenzian1の場合: 0: X0, 1: H, 2: A + /// Gaussian2 or Lorenzian2の場合: 0: X0, 1: Y0, 2: H, 3: A + /// Gaussian2Ellipse or Lorenzian2Ellipseの場合: 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: A + /// PseudoVoigt1 の場合; 0: X0, 1: H, 2: Eta, 3: A + /// PseudoVoigt2 の場合; 0: X0, 1: Y0, 2: H, 3: Eta, 4: A + /// PseudoVoigt2Ellipse の場合; 0: X0, 1: Y0, 2: H1, 3: H2, 4: T, 5: Eta, 6: A + /// + public Function(FuncType type, params double[] parameters) { - double x1 = x - x0, y1 = y - y0; //中心へシフト - double cos = Cos(t), sin = Sin(t); - double X = x1 * cos + y1 * sin, Y = -x1 * sin + y1 * cos; - return a / (2 * pi * h1 * h2) / (1 + c * X / h1 * X / h1 + c * Y / h2 * Y / h2); + Prms = parameters; + PrmsPrev = new double[Prms.Length]; + + switch (type) + { + #region + case FuncType.G1: + Formula = (x, p) => Gaussian(x[0], p[0], p[1], p[2]); + Constraints = p => new[] { p[0], Max(p[1], inf), Max(p[2], inf) }; + break; + + case FuncType.G2: + Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3]); + Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf) }; + break; + + case FuncType.G2E: + Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3], p[4], p[5]); + Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf), p[4], Max(p[5], inf) }; + break; + + case FuncType.L1: + Formula = (x, p) => Lorenzian(x[0], p[0], p[1], p[2]); + Constraints = p => new[] { p[0], Max(p[1], inf), Max(p[2], inf) }; + break; + + case FuncType.L2: + Formula = (x, p) => Lorenzian(x[0], x[1], p[0], p[1], p[2], p[3]); + Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf) }; + break; + + case FuncType.L2E: + Formula = (x, p) => Gaussian(x[0], x[1], p[0], p[1], p[2], p[3], p[4], p[5]); + Constraints = p => new[] { p[0], p[1], Max(p[2], inf), Max(p[3], inf), p[4], Max(p[5], inf) }; + break; + + case FuncType.PV1: + Formula = (x, p) => PseudoVoigt(x[0], p[0], p[1], p[2], p[3]); + Constraints = p => new[] { p[0], Max(p[1], 0.1), Min(Max(p[2], 0), 1.5), Max(p[3], inf) }; + break; + + case FuncType.PV2: + Formula = (x, p) => PseudoVoigt(x[0], x[1], p[0], p[1], p[2], p[3], p[4]); + Constraints = p => new[] { p[0], p[1], Max(p[2], 0.1), Min(Max(p[3], 0), 1.5), Max(p[4], inf) }; + break; + + case FuncType.PV2E: + Formula = (x, p) => PseudoVoigt(x, p[0], p[1], p[2], p[3], p[4], p[5], p[6]); + Constraints = p => new[] { p[0], p[1], Max(p[2], 0.1), Max(p[3], 0.1), p[4], Min(Max(p[5], 0), 1.5), Max(p[6], inf) }; + Derivatives = (x, p) => PseudoVoigtDiff(x, p[0], p[1], p[2], p[3], p[4], p[5], p[6]); + break; + + case FuncType.Plane: + Formula = (x, p) => p[0] + p[1] * x[0] + p[2] * x[1]; + Derivatives = (x, p) => new[] { 1.0, x[0], x[1] }; + break; + #endregion + } + + steps = Enumerable.Range(-9, 20).Select(n => Pow(10, n)).ToArray(); + PrmLength = Prms.Length; } /// - /// ガウス関数 1次元 + /// 偏微分値を得る /// - /// xの値 - /// xの中心値 - /// 半値半幅 - /// 積分強度 + /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Gaussian(double x, double x0, double h, double a) => a * sqrtln2 / sqrtpi / h * Math.Exp(-ln2 * (x - x0) / h * (x - x0) / h); + public double[] GetDerivative(double[] x) + { + if (Derivatives != null) + return Derivatives(x, Prms); + + var derivative = new double[Length]; + var f0 = Formula(x, Prms); + for (int j = 0; j < Length; j++) + for (int i = 0; i < steps.Length; i++) + { + var pTemp = Prms.ToArray();//値渡しでコピー + pTemp[j] += steps[i]; + derivative[j] = (Formula(x, pTemp) - f0) / steps[i]; + if (derivative[j] != 0) break; + } + return derivative; + } /// - /// ガウス関数 2次元 (真円) + /// 与えられた座標での値を得る /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅 - /// 積分強度 + /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Gaussian(double x, double y, double x0, double y0, double h, double a) - => a * ln2 / pi / h / h * Exp(-ln2 * ((x - x0) * (x - x0) + (y - y0) * (y - y0)) / h / h); + public double GetValue(params double[] x) => Formula(x, Prms); /// - /// ガウス関数 2次元 (楕円) + /// 与えられた座標での値を得る /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅1 - /// 半値半幅2 - /// h1の方向に回転する角度 - /// 積分強度 + /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Gaussian(double x, double y, double x0, double y0, double h1, double h2, double t, double a) + public double[] GetValues(params double[][] x) { - double x1 = x - x0, y1 = y - y0; //中心へシフト - double cos = Cos(t), sin = Sin(t); - double X = x1 * cos + y1 * sin, Y = -x1 * sin + y1 * cos; - return a * ln2_pi / h1 / h2 * Exp(-ln2 * (X * X / h1 / h1 + Y * Y / h2 / h2)); + return FormulaEx != null ? + FormulaEx(x, Prms) : + x.AsParallel().Select(x1 => Formula(x1, Prms)).ToArray(); } /// - /// 疑似フォークト関数 1次元 + /// 全パラメータを指定量だけ変化させる. 制約条件も課す。 /// - /// xの値 - /// xの中心値 - /// 半値半幅 - /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) - /// 積分強度 - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double PseudoVoigt(double x, double x0, double h, double eta, double a) - => eta * Lorenzian(x, x0, h, a) + (1 - eta) * Gaussian(x, x0, h, a); + public void AddPrms(double[] delta) + { + for (var i = 0; i < Prms.Length; i++) + { + PrmsPrev[i] = Prms[i]; + Prms[i] += delta[i]; + } + ApplyConstraints(); + } /// - /// 疑似フォークト関数 2次元 (真円) + /// 全パラメータを一世代前のものに戻す /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅1 - /// 半値半幅2 - /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) - /// 積分強度 - /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double PseudoVoigt(double x, double y, double x0, double y0, double h, double eta, double a) - => eta * Lorenzian(x, y, x0, y0, h, a) + (1 - eta) * Gaussian(x, y, x0, y0, h, a); + public void RevertPrms() + { + for (int i = 0; i < Prms.Length; i++) + Prms[i] = PrmsPrev[i]; + } /// - /// 疑似フォークト関数 2次元 (楕円) + /// 全パラメータに制約を課す /// - /// xの値 - /// yの値 - /// xの中心値 - /// yの中心値 - /// 半値半幅1 - /// 半値半幅2 - /// h1の方向に回転する角度 - /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) - /// 積分強度 - /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double PseudoVoigt(double[] x, double x0, double y0, double hx, double hy, double t, double eta, double a) + public void ApplyConstraints() { - double xShift = x[0] - x0, yShift = x[1] - y0; //中心へシフト - double cos = Cos(t), sin = Sin(t); - double xRot = xShift * cos + yShift * sin, yRot = -xShift * sin + yShift * cos; - double hxInv = 1 / hx, hyInv = 1 / hy; - var x2plusY2 = xRot * xRot * hxInv * hxInv + yRot * yRot * hyInv * hyInv; - var g = ln2 * Exp(-ln2 * x2plusY2); - var l = 1 / ((2 + 2 * c * x2plusY2) * Sqrt(1 + c * x2plusY2)); - return a * (eta * l + (1 - eta) * g) * piInv * hxInv * hyInv; - /* - //C++ネイティブで書いてもあまり速くならなかった。 - var results = new double[1]; - _PseudoVoigt(x, x0, y0, hx, hy, t, eta, a, results); - return results[0]; - */ + if (Constraints != null) + Prms = Constraints(Prms); } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double[] PseudoVoigtDiff(double[] x, double x0, double y0, double hx, double hy, double t, double eta, double a) + public static double RambdaCoeff1 { get; set; } = 0.1; + public static double RambdaCoeff2 { get; set; } = 8; + + /// + /// 静的メソッド. Marquardt法によるフィッティングを実行する. + /// + /// 観測値. x は座標, y は強度、 wは重み(分散の逆数) + /// Functinクラスの配列. + /// Prms[i][j]はi番目のFunctionのj番目の最適パラメータ. Errorはまだ未実装. Rは残差 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static (double[][] Prms, double[][] Error, double R) + Solve(in (double[] x, double y, double w)[] obsValues, Function[] functions,in Precision precision = Precision.Medium) + { + #region 計算精度をセット + int countMax = 200; + double rambdaMax = 1E5, threshold = 1E-10; + if (precision == Precision.High) { - double cos = Cos(t), sin = Sin(t); - double hxInv = 1 / hx, hyInv = 1 / hy; - double hx2Inv = hxInv * hxInv, hy2Inv = hyInv * hyInv; + countMax = 400; + rambdaMax = 1E7; + threshold = 1E-15; + } + else if (precision == Precision.Low) + { + countMax = 50; + rambdaMax = 1E3; + threshold = 1E-5; + } + #endregion + + var obs = obsValues.AsParallel(); + int valuesLength = obs.Count(), totalPrmsLength = functions.Sum(f => f.Length), funcLength = functions.Length; + if (valuesLength == 0) return (null, null, double.PositiveInfinity); + var weight = new DiagonalMatrix(valuesLength, valuesLength, obs.Select(o => o.w).ToArray()); + var rambda = 10.0; + var alpha = new DMat(totalPrmsLength, totalPrmsLength); + var beta = new DVec(totalPrmsLength); + var rCur = new DVec(obs.Select(v => v.y - functions.Sum(f => f.GetValue(v.x))).ToArray());//現在の残差を計算 + var r2Cur = rCur * weight * rCur;//残差の二乗和を計算 + + var renewAlpha = true; + var exclude = new bool[totalPrmsLength]; + int successCount = -1;//連続成功回数(正)、あるいは連続失敗回数(負)を記録する。 + + for (int count = 0; count < countMax && rambda < rambdaMax; count++) + { + if (renewAlpha) + { + var jacob = DMat.OfRowArrays(obs.Select(o => + { + var d = new double[totalPrmsLength]; + for (int j = 0, n = 0; j < funcLength; n += functions[j].PrmLength, j++) + Buffer.BlockCopy(functions[j].GetDerivative(o.x), 0, d, n * 8, functions[j].PrmLength * 8); + return d; + }).ToArray()); + + var jacobW = (DMat)(weight * jacob); + alpha = (DMat)jacob.TransposeThisAndMultiply(jacobW);//alpha行列を計算 + beta = rCur * jacobW;//betaベクトルを計算 + + //偏微分値がゼロになってしまう時の対策 + exclude = alpha.ToRowArrays().Select(row => row.All(e => e == 0)).ToArray(); + if (exclude.Contains(true)) + { + if (exclude.Count(e => e) == beta.Count) + return (null, null, double.PositiveInfinity); + var betaList = beta.ToList(); + for (int i = exclude.Length - 1; i >= 0; i--) + if (exclude[i]) + { + betaList.RemoveAt(i); + alpha = (DMat)alpha.RemoveColumn(i); + alpha = (DMat)alpha.RemoveRow(i); + } + beta = new DVec(betaList.ToArray()); + } + } - double xShift = x[0] - x0, yShift = x[1] - y0; //中心へシフト - double xRot = xShift * cos + yShift * sin, yRot = -xShift * sin + yShift * cos; - double xRot2hx2Inv = xRot * xRot * hx2Inv, yRot2hy2Inv = yRot * yRot * hy2Inv; - var x2pY2 = xRot2hx2Inv + yRot2hy2Inv; + var alphaTemp = alpha + DMat.OfDiagonalVector(alpha.Diagonal() * rambda);//alphaの対角成分に1+rambdaを掛ける。 + if (!alphaTemp.TryInverse(out Matrix alphaInv))//逆行列を計算 + return (null, null, double.PositiveInfinity); //失敗した場合は終了 - double lo = 1 + c * x2pY2, sqLo = Sqrt(lo); - var l = 1 / (lo * sqLo * 2); - var g = ln2 * Exp(-ln2 * x2pY2); + //deltaベクトルを計算 + var delta = (beta * alphaInv).ToList(); + //偏微分値がゼロになってしまう時の対策 + if (delta.Count != totalPrmsLength) + for (int i = 0; i < exclude.Length; i++) + if (exclude[i]) + delta.Insert(i, 0); - var d1 = piInv * hxInv * hyInv; - var d2 = d1 * (eta * l + (1 - eta) * g); - var d3 = a * d1 * (3 * eta * l * c / lo + 2 * ln2 * (1 - eta) * g); + //パラメータを変化させる + for (int j = 0, n = 0; j < funcLength; n += functions[j].PrmLength, j++) + functions[j].AddPrms(delta.Skip(n).Take(functions[j].PrmLength).ToArray()); - return new[] + var rNew = new DVec(obs.Select(v => v.y - functions.Sum(f => f.GetValue(v.x))).ToArray());//新しいパラメータで残差を計算 + var r2New = rNew * weight * rNew; //残差の二乗和を計算 + + renewAlpha = r2New < r2Cur; + if (renewAlpha) + { + successCount = successCount < 0 ? 1 : successCount + 1; + if ((r2Cur - r2New) / r2Cur < threshold) + { + r2Cur = r2New; + break;//十分収束が進んだ時は終了 + } + rCur = rNew; + r2Cur = r2New; + rambda = successCount > 2 ? rambda * RambdaCoeff1 : rambda;//2回連続で成功したら、Rambdaを減らす. + } + else { - d3 * (xRot * cos * hx2Inv - yRot * sin * hy2Inv),//x0 - d3 * (xRot * sin * hx2Inv + yRot * cos * hy2Inv),//y0 - (d3 * xRot2hx2Inv - a * d2) * hxInv,//hx - (d3 * yRot2hy2Inv - a * d2) * hyInv,//hy - d3 * ( hy2Inv - hx2Inv) * xRot * yRot,//theta - a * d1 * (l - g) , //eta - d2 //a - }; - - /* - //C++ネイティブで書いてもあまり速くならなかった。呼び出しのオーバヘッドが時間かかってそう。 - var results = new double[7]; - _PseudoVoigtDiff(x, x0, y0, hx, hy, t, eta, a, results); - return results; - */ + successCount = successCount > 0 ? -1 : successCount - 1; + if (successCount < -3)//4回連続で失敗したら、取り合えず現状を採用. + { + successCount = 1; + rCur = rNew; + r2Cur = r2New; + renewAlpha = true; + } + else + { + rambda *= RambdaCoeff2; + foreach (var f in functions) f.RevertPrms(); + } + } } + return (functions.Select(f => f.Prms).ToArray(), null, r2Cur / obs.Sum(v => v.w * v.y * v.y)); + } - [DllImport("Crystallography.Native.dll")] - private static extern void _PseudoVoigtDiff(double[] x, double x0, double y0, double hx, double hy, double t, double eta, double a, double[] results); + private const double ln2 = 0.69314718055994530941723212145818; + private const double sqrtln2 = 0.8325546111576977563531646448952; + private const double pi = 3.1415926535897932384626433832795; + private const double piInv = 0.31830988618379067153776752674503; + private const double sqrtpi = 1.7724538509055160272981674833411; + private const double ln2_pi = ln2 / pi; + private const double c = 0.58740105196819947475170563927231;// = 4^(1/3) - 1 + + #region 組み込み関数 + + /// + /// ローレンツ関数 1次元 + /// + /// xの値 + /// xの中心値 + /// 半値半幅 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Lorenzian(in double x, in double x0, in double h, in double a) => a / (pi * h) / (1 + (x - x0) / h * (x - x0) / h); + + /// + /// ローレンツ関数 2次元 (真円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Lorenzian(in double x, in double y, in double x0, in double y0, in double h, in double a) + => a / (2 * pi * h * h) / (1 + c * (x - x0) / h * (x - x0) / h + c * (y - y0) / h * (y - y0) / h); + + /// + /// ローレンツ関数 2次元 (楕円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅1 + /// 半値半幅2 + /// h1の方向に回転する角度 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Lorenzian(in double x, in double y, in double x0, in double y0, in double h1, in double h2, in double t, in double a) + { + double x1 = x - x0, y1 = y - y0; //中心へシフト + double cos = Cos(t), sin = Sin(t); + double X = x1 * cos + y1 * sin, Y = -x1 * sin + y1 * cos; + return a / (2 * pi * h1 * h2) / (1 + c * X / h1 * X / h1 + c * Y / h2 * Y / h2); + } - [DllImport("Crystallography.Native.dll")] - private static extern void _PseudoVoigt(double[] x, double x0, double y0, double hx, double hy, double t, double eta, double a, double[] results); + /// + /// ガウス関数 1次元 + /// + /// xの値 + /// xの中心値 + /// 半値半幅 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Gaussian(in double x, in double x0, in double h, in double a) => a * sqrtln2 / sqrtpi / h * Math.Exp(-ln2 * (x - x0) / h * (x - x0) / h); + + /// + /// ガウス関数 2次元 (真円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Gaussian(in double x, in double y, in double x0, in double y0, in double h, in double a) + => a * ln2 / pi / h / h * Exp(-ln2 * ((x - x0) * (x - x0) + (y - y0) * (y - y0)) / h / h); + + /// + /// ガウス関数 2次元 (楕円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅1 + /// 半値半幅2 + /// h1の方向に回転する角度 + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Gaussian(in double x, in double y, in double x0, in double y0, in double h1, in double h2, in double t, in double a) + { + double x1 = x - x0, y1 = y - y0; //中心へシフト + double cos = Cos(t), sin = Sin(t); + double X = x1 * cos + y1 * sin, Y = -x1 * sin + y1 * cos; + return a * ln2_pi / h1 / h2 * Exp(-ln2 * (X * X / h1 / h1 + Y * Y / h2 / h2)); + } - #endregion 組み込み関数 + /// + /// 疑似フォークト関数 1次元 + /// + /// xの値 + /// xの中心値 + /// 半値半幅 + /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double PseudoVoigt(in double x, in double x0, in double h, in double eta, in double a) + => eta * Lorenzian(x, x0, h, a) + (1 - eta) * Gaussian(x, x0, h, a); + + /// + /// 疑似フォークト関数 2次元 (真円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅1 + /// 半値半幅2 + /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double PseudoVoigt(in double x, in double y, in double x0, in double y0, in double h, in double eta, in double a) + => eta * Lorenzian(x, y, x0, y0, h, a) + (1 - eta) * Gaussian(x, y, x0, y0, h, a); + + /// + /// 疑似フォークト関数 2次元 (楕円) + /// + /// xの値 + /// yの値 + /// xの中心値 + /// yの中心値 + /// 半値半幅1 + /// 半値半幅2 + /// h1の方向に回転する角度 + /// ガウス関数とローレンツ関数の割合 (r=1のとき、100% Lorentzian) + /// 積分強度 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double PseudoVoigt(in double[] x, in double x0, in double y0, in double hx, in double hy, in double t, in double eta, in double a) + { + double xShift = x[0] - x0, yShift = x[1] - y0; //中心へシフト + double cos = Cos(t), sin = Sin(t); + double xRot = xShift * cos + yShift * sin, yRot = -xShift * sin + yShift * cos; + double hxInv = 1 / hx, hyInv = 1 / hy; + var x2plusY2 = xRot * xRot * hxInv * hxInv + yRot * yRot * hyInv * hyInv; + var g = ln2 * Exp(-ln2 * x2plusY2); + var l = 1 / ((2 + 2 * c * x2plusY2) * Sqrt(1 + c * x2plusY2)); + return a * (eta * l + (1 - eta) * g) * piInv * hxInv * hyInv; + /* + //C++ネイティブで書いてもあまり速くならなかった。 + var results = new double[1]; + _PseudoVoigt(x, x0, y0, hx, hy, t, eta, a, results); + return results[0]; + */ + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double[] PseudoVoigtDiff(in double[] x, in double x0, in double y0, in double hx, in double hy, in double t, in double eta, in double a) + { + double cos = Cos(t), sin = Sin(t); + double hxInv = 1 / hx, hyInv = 1 / hy; + double hx2Inv = hxInv * hxInv, hy2Inv = hyInv * hyInv; + + double xShift = x[0] - x0, yShift = x[1] - y0; //中心へシフト + double xRot = xShift * cos + yShift * sin, yRot = -xShift * sin + yShift * cos; + double xRot2hx2Inv = xRot * xRot * hx2Inv, yRot2hy2Inv = yRot * yRot * hy2Inv; + var x2pY2 = xRot2hx2Inv + yRot2hy2Inv; + + double lo = 1 + c * x2pY2, sqLo = Sqrt(lo); + var l = 1 / (lo * sqLo * 2); + var g = ln2 * Exp(-ln2 * x2pY2); + + var d1 = piInv * hxInv * hyInv; + var d2 = d1 * (eta * l + (1 - eta) * g); + var d3 = a * d1 * (3 * eta * l * c / lo + 2 * ln2 * (1 - eta) * g); + + return new[] + { + d3 * (xRot * cos * hx2Inv - yRot * sin * hy2Inv),//x0 + d3 * (xRot * sin * hx2Inv + yRot * cos * hy2Inv),//y0 + (d3 * xRot2hx2Inv - a * d2) * hxInv,//hx + (d3 * yRot2hy2Inv - a * d2) * hyInv,//hy + d3 * ( hy2Inv - hx2Inv) * xRot * yRot,//theta + a * d1 * (l - g) , //eta + d2 //a + }; + + /* + //C++ネイティブで書いてもあまり速くならなかった。呼び出しのオーバヘッドが時間かかってそう。 + var results = new double[7]; + _PseudoVoigtDiff(x, x0, y0, hx, hy, t, eta, a, results); + return results; + */ } + + [DllImport("Crystallography.Native.dll")] + private static extern void _PseudoVoigtDiff(in double[] x, in double x0, in double y0, in double hx, in double hy, in double t, in double eta, in double a, in double[] results); + + [DllImport("Crystallography.Native.dll")] + private static extern void _PseudoVoigt(in double[] x, double x0, in double y0, in double hx, in double hy, in double t, in double eta, in double a, in double[] results); + + #endregion 組み込み関数 } \ No newline at end of file diff --git a/Crystallography/NativeWrapper.cs b/Crystallography/NativeWrapper.cs index 83166e9..7233f0e 100644 --- a/Crystallography/NativeWrapper.cs +++ b/Crystallography/NativeWrapper.cs @@ -2,6 +2,7 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Data; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; @@ -45,15 +46,18 @@ private static unsafe partial void _AdjointAndMultiply(int dim, double* mat2, double* result); - [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _MultiplyMM(int dim, double* mat1, double* mat2, double* result); + + [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _MultiplyMV(int dim, double* mat, double* vec, double* result); + [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _MultiplySV(int dim, double real, double imag, double* vec, double* result); + [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _DivideVV(int dim, double* vec1, double* vec2, double* result); @@ -64,12 +68,15 @@ private static unsafe partial void _AdjointAndMultiply(int dim, private static unsafe partial void _SubtractVV(int dim, double* vec1, double* vec2, double* result); - [LibraryImport("Crystallography.Native.dll")] - private static unsafe partial void _Inverse(int dim, double[] mat, double[] matInv); + //[LibraryImport("Crystallography.Native.dll")] + //private static unsafe partial void _Inverse(int dim, double[] mat, double[] matInv); [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _Inverse(int dim, double* mat, double* matInv); + [LibraryImport("Crystallography.Native.dll")] + private static unsafe partial void _Inverse_Real(int dim, double* mat, double* matInv); + [LibraryImport("Crystallography.Native.dll")] private static unsafe partial void _EigenSolver(int dim, double[] mat, double[] eigenValues, double[] eigenVectors); @@ -269,6 +276,8 @@ static NativeWrapper() #endregion #region 単純な四則演算 + + #region 行列×行列 /// /// Eigenライブラリーを利用して、非対称複素行列の乗算を求める /// @@ -285,11 +294,13 @@ unsafe static public void MultiplyMxM(int dim, Complex[] matrix1, Complex[] matr } unsafe static public Complex[] MultiplyMxM(int dim, Complex[] matrix1, Complex[] matrix2) { - var result = GC.AllocateUninitializedArray(dim * dim);// new Complex[dim * dim]; + var result = GC.AllocateUninitializedArray(dim * dim); MultiplyMxM(dim, matrix1, matrix2, ref result); return result; } + #endregion + #region 行列×ベクトル unsafe static public void MultiplyMxV(int dim, Complex[] matrix, Complex[] vector, ref Complex[] result) { fixed (Complex* mtx1 = matrix) @@ -300,11 +311,13 @@ unsafe static public void MultiplyMxV(int dim, Complex[] matrix, Complex[] vecto unsafe static public Complex[] MultiplyMxV(int dim, Complex[] matrix, Complex[] vector) { - var result = GC.AllocateUninitializedArray(dim);// new Complex[dim]; + var result = GC.AllocateUninitializedArray(dim); MultiplyMxV(dim, matrix, vector, ref result); return result; } + #endregion + #region 数値×行列 unsafe static public void MultiplySxV(int dim, in Complex s, in Complex[] v, ref Complex[] result) { fixed (Complex* p = v) @@ -312,6 +325,14 @@ unsafe static public void MultiplySxV(int dim, in Complex s, in Complex[] v, ref _MultiplySV(dim, s.Real, s.Imaginary, (double*)p, (double*)res); } + unsafe static public Complex[] MultiplySxV(int dim, in Complex s, in Complex[] v) + { + var result = GC.AllocateUninitializedArray(dim); + MultiplySxV(dim, s, v, ref result); + return result; + } + + #endregion unsafe static public void Add(int dim, in Complex[] v1, in Complex[] v2, ref Complex[] result) { @@ -320,7 +341,6 @@ unsafe static public void Add(int dim, in Complex[] v1, in Complex[] v2, ref Com fixed (Complex* res = result) _AddVV(dim * 2, (double*)p1, (double*)p2, (double*)res); } - unsafe static public void Add(int dim, in double[] v1, in double[] v2, ref double[] result) { fixed (double* p1 = v1) @@ -494,6 +514,42 @@ static unsafe public Complex[] Inverse(int dim, Complex[] mat) return values; } + /// + /// Eigenライブラリーを利用して、非対称複素行列の逆行列を求める + /// + /// + /// + static unsafe public Complex[] Inverse(Complex[] mat) + { + var dim = (int)Math.Sqrt(mat.Length); + return dim * dim == mat.Length ? Inverse(dim, mat) : null; + } + + /// + /// Eigenライブラリーを利用して、実数行列の逆行列を求める + /// + /// + /// + static unsafe public double[] Inverse(int dim, double[] mat) + { + var values = GC.AllocateUninitializedArray(dim * dim);//new Complex[dim* dim]; + fixed (double* _values = values) + fixed (double* _mat = mat) + _Inverse_Real(dim, (double*)_mat, (double*)_values); + return values; + } + + /// + /// Eigenライブラリーを利用して、実数行列の逆行列を求める + /// + /// + /// + static unsafe public double[] Inverse(double[] mat) + { + var dim = (int)Math.Sqrt(mat.Length); + return dim * dim == mat.Length ? Inverse(dim, mat) : null; + } + #endregion 逆行列 #region 固有値 diff --git a/Crystallography/PeakSearch.cs b/Crystallography/PeakSearch.cs index 4dab002..f19dfd4 100644 --- a/Crystallography/PeakSearch.cs +++ b/Crystallography/PeakSearch.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Security.Cryptography.X509Certificates; namespace Crystallography { @@ -34,14 +35,14 @@ public class PeakFunction : IComparable public double m; public double range; public double Residual; - + public bool Success = true; public int GroupIndex; public Color Color; /// /// FittingɁAPeakTop(Xl)TBfalsȅꍇ́AXl̂܂܎g /// - public bool SerchPeakTop = false; + public bool SearchPeakTop { get; set; } = false; public int CompareTo(object o) { @@ -62,38 +63,35 @@ public PeakFunction(double X, double Hk, double range, PeakFunctionForm Option) public PeakFunction Copy() { - PeakFunction p = new PeakFunction(); - p.Option = this.Option; - p.intensity = this.intensity; - p.eta = this.eta; - p.etaH = this.etaH; - p.etaL = this.etaL; - p.Rl = this.Rl; - p.Rh = this.Rh; - p.X = this.X; - p.Hk = this.Hk; - p.Int = this.Int; - p.A = this.A;//Ώ̃p[^ - p.B1 = this.B1; - p.B2 = this.B2; - p.B3 = this.B3; - p.m = this.m; - p.range = this.range; - return p; + return new PeakFunction + { + Option = this.Option, + intensity = this.intensity, + eta = this.eta, + etaH = this.etaH, + etaL = this.etaL, + Rl = this.Rl, + Rh = this.Rh, + X = this.X, + Hk = this.Hk, + Int = this.Int, + A = this.A,//Ώ̃p[^ + B1 = this.B1, + B2 = this.B2, + B3 = this.B3, + m = this.m, + range = this.range + }; } public int GetParamNumber() { - if (Option == PeakFunctionForm.PseudoVoigt) - return 4; - else if (Option == PeakFunctionForm.Peason) - return 4; - else if (Option == PeakFunctionForm.SplitPseudoVoigt) - return 6; - else if (Option == PeakFunctionForm.SplitPearson) - return 6; - else - return int.MinValue; + return Option switch + { + PeakFunctionForm.PseudoVoigt or PeakFunctionForm.Peason => 4, + PeakFunctionForm.SplitPseudoVoigt or PeakFunctionForm.SplitPearson => 6, + _ => int.MinValue + }; } public void RenewParameter() @@ -110,18 +108,14 @@ public double GetValue(double x, bool IsNewParamNeeded, bool withBackground = fa { if (IsNewParamNeeded) RenewParameter(); - double y = 0; - - if (Option == PeakFunctionForm.PseudoVoigt) - y = PseudoVoigt(x); - else if (Option == PeakFunctionForm.Peason) - y = PeasonIV(x); - else if (Option == PeakFunctionForm.SplitPseudoVoigt) - y = SplitPseudoVoigt(x); - else if (Option == PeakFunctionForm.SplitPearson) - y = SplitPearsonIV(x); - else - y = 0; + var y = Option switch + { + PeakFunctionForm.PseudoVoigt => PseudoVoigt(x), + PeakFunctionForm.Peason => PeasonIV(x), + PeakFunctionForm.SplitPseudoVoigt => SplitPseudoVoigt(x), + PeakFunctionForm.SplitPearson => SplitPearsonIV(x), + _ => 0 + }; if (withBackground) y += B1 + B2 * (x - X); @@ -133,16 +127,14 @@ public double[] GetDifferentialValue(double x, bool IsNewParamNeeded) if (IsNewParamNeeded) RenewParameter(); - if (Option == PeakFunctionForm.PseudoVoigt) - return differectialPseudoVoigt(x); - else if (Option == PeakFunctionForm.Peason) - return differectialPeasonIV(x); - else if (Option == PeakFunctionForm.SplitPseudoVoigt) - return differentialSplitPseudoVoigt(x); - else if (Option == PeakFunctionForm.SplitPearson) - return differectialSplitPeasonIV(x); - else - return null; + return Option switch + { + PeakFunctionForm.PseudoVoigt => differentialPseudoVoigt(x), + PeakFunctionForm.Peason => differectialPeasonIV(x), + PeakFunctionForm.SplitPseudoVoigt => differentialSplitPseudoVoigt(x), + PeakFunctionForm.SplitPearson => differentialSplitPearsonIV(x), + _ => null + }; } public double GetIntegral() @@ -167,46 +159,46 @@ public double GetIntegral() return 0; } - private static readonly double SqrtLn2PI = Math.Sqrt(Math.Log(2) * Math.PI); - private static readonly double SqrtLn2PerPI = Math.Sqrt(Math.Log(2) / Math.PI); - private static readonly double Ln2 = Math.Log(2); - private static readonly double Ln2Pow15 = Math.Sqrt(Ln2) * Ln2; - private static readonly double PI = Math.PI; + private const double SqrtLn2PI = 1.4756646266356059;// Math.Sqrt(Math.Log(2) * Math.PI) + private const double SqrtLn2PerPI = 0.46971863934982566;// Math.Sqrt(Math.Log(2) / Math.PI); + private const double Ln2 = 0.69314718055994529;// Math.Log(2); + private const double Ln2Pow15 = 0.57708288138613972;// Math.Sqrt(Ln2) * Ln2; + private const double PI = Math.PI; + private const double SqrtPI = 1.7724538509055159;// Math.Sqrt(PI); - //static double pi = 1 / PI; - private static readonly double SqrtPI = Math.Sqrt(PI); - - private double Z1, Z2, a1, a2, a3, a4, a5, a6, a7, a8, a9, - b, b1, b2, b3, b4, b5, b6, b7; + private double Z1, Z2, a1, a2, a3, a4, a5, a6, a7, a8, a9, b, b1, b2, b3, b4, b5, b6, b7; //Pseudo Voigt private double PseudoVoigt(double x) { - double Fourx2PerHk2 = 4 * (x - X) * (x - X) / Hk / Hk; - return Int * ((eta / Math.PI / (1 + Fourx2PerHk2) + (1 - eta) * SqrtLn2PerPI * Math.Exp(-Ln2 * Fourx2PerHk2)) * 2 / Hk); + var fourx2PerHk2 = 4 * (x - X) * (x - X) / Hk / Hk; + return Int * ((eta / Math.PI / (1 + fourx2PerHk2) + (1 - eta) * SqrtLn2PerPI * Math.Exp(-Ln2 * fourx2PerHk2)) * 2 / Hk); } - private double[] differectialPseudoVoigt(double x) + private double[] differentialPseudoVoigt(double x) { - double tmp3 = (X - x) * (X - x); - double tmp2 = Hk * Hk; - double tmp1 = tmp3 / tmp2; - double ExpMinus4Ln2tmp1 = Math.Exp(-4 * Ln2 * tmp1); - double[] d = new double[4]; - d[0] = 2 / Hk / PI * (eta / (1 + 4 * tmp1) + (1 - eta) * SqrtLn2PI * ExpMinus4Ln2tmp1); - d[1] = Int * (2 / Hk / PI * (1 / (1 + 4 * tmp1) - SqrtLn2PI * ExpMinus4Ln2tmp1)); - d[2] = Int * (-2 * eta * (tmp2 - 4 * tmp3) / PI / (tmp2 + 4 * tmp3) / (tmp2 + 4 * tmp3) + 2 * (eta - 1) * SqrtLn2PerPI * (tmp2 - 8 * tmp3 * Ln2) / (tmp2 * tmp2) * ExpMinus4Ln2tmp1); - d[3] = Int * 16 * (X - x) / (tmp2 * Hk) / PI * (-eta / (1 + 4 * tmp1) / (1 + 4 * tmp1) + (eta - 1) * SqrtLn2PI * Ln2 * ExpMinus4Ln2tmp1); - return d; + var tmp3 = 4 * (X - x) * (X - x); + var tmp2 = Hk * Hk; + var tmp1 = tmp3 / tmp2; + var tmp4 = 1 / (1 + tmp1); + var tmp5 = SqrtLn2PI * Math.Exp(- Ln2 * tmp1); + var tmp6 = 2.0 / Hk / PI; + var _eta = 1 - eta; + return new double[] { + tmp6 * (eta * tmp4 + _eta * tmp5), + Int * tmp6 * (tmp4 - tmp5), + -2 *Int * ( eta * (tmp2 - tmp3) / PI / (tmp2 + tmp3) / (tmp2 + tmp3) + _eta * (tmp2 - 2 * tmp3 * Ln2) / (tmp2 * tmp2) * tmp5), + Int * 8 * tmp6 * (X - x) / tmp2 * (-eta * tmp4 * tmp4 - _eta * Ln2 * tmp5) + }; } - //Pseudo Voigt ܂ //Split Pseudo Voigt private void RenewParamSplitPseudoVoigt() { - Z1 = 1 / Math.Exp(A) + 1; - Z2 = Math.Exp(A) + 1; + var exp = Math.Exp(A); + Z1 = 1 / exp + 1; + Z2 = exp + 1; a1 = etaL - 1; a2 = etaH - 1; a3 = a1 * SqrtLn2PI; @@ -309,8 +301,9 @@ private double[] differectialPeasonIV(double x) //Split Pearson VII private void RenewParamSplitPearsonIV() { - Z1 = 1 / Math.Exp(A) + 1; - Z2 = Math.Exp(A) + 1; + var exp = Math.Exp(A); + Z1 = 1 / exp + 1; + Z2 = exp + 1; a1 = Math.Pow(2, 1 / Rl); a2 = Math.Pow(2, 1 / Rh); a3 = a1 - 1; @@ -331,7 +324,7 @@ private double SplitPearsonIV(double x) return Int * Math.Pow(1 + a7 * b1 * b1 * Z2 * Z2, -Rh); } - private double[] differectialSplitPeasonIV(double x) + private double[] differentialSplitPearsonIV(double x) { b1 = x - X; double[] d = new double[6]; @@ -400,9 +393,9 @@ public static PointD FitPeakAsSimple(double angle, double range, PointD[] pt) } - public static void FitPeakThread(PointD[] pt, bool BackgroundFitting, double RemoveBadSN, ref PeakFunction p) + public static void FitPeakThread(List pt, bool BackgroundFitting, double RemoveBadSN, ref PeakFunction p) { - PeakFunction[] param = new PeakFunction[1]; + var param = new PeakFunction[1]; param[0] = p; FitMultiPeaksThread(pt, BackgroundFitting, RemoveBadSN, ref param); p = param[0]; @@ -412,217 +405,211 @@ public static void FitPeakThread(PointD[] pt, bool BackgroundFitting, double Rem /// /// s[NtBbeBO. ߂ĺARl /// - /// tBbeBOΏۃvt@C̃f[^z + /// tBbeBOΏۃvt@C̃f[^z /// obNOEhtBbeBO邩ǂ /// SN̈s[Nɂ‚ĂNaNԂǂ - /// s[N֐ i[Ă钆SlAlAtBbeBORangeݒ肵Ă - public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, double RemoveBadSN, ref PeakFunction[] p) + /// s[N֐ i[Ă钆SlAlAtBbeBORangeݒ肵Ă + public static double FitMultiPeaksThread(List _pt, bool BackgroundFitting, double RemoveBadSN, ref PeakFunction[] prms) { //}J[̕@PseudoVoigtƂBɂȂ͂ - if (p.Length == 0) - return double.PositiveInfinity; - if (pt == null || pt.Length < 3) + MathNet.Numerics.Control.TryUseNativeMKL(); + + var _prms = prms; + double Failed()//sɌĂяo[J֐. p[^NaNĂ疳ԂB@ + { + foreach(var p in _prms) + { + p.X = double.NaN; + p.intensity = double.NaN; + p.Hk = double.NaN; + } return double.PositiveInfinity; + } + + foreach (var p in prms)//UASSuccessfalseɂBŌ܂ōsTrueɂB + p.Success = false; + + if (prms.Length == 0) + return Failed(); + if (_pt == null || _pt.Count < 3) + return Failed(); //܂vt@CƂ̈⋭xȂȂǂ̏W߂ - var PtX = new List(); - var PtY = new List(); + var pt = new List<(double X, double Y)>(); + //var PtY = new List(); double sum = 0; double temp = double.NegativeInfinity; double tempMin = double.PositiveInfinity; //w肳ꂽ͈͓̃vt@CPtX,PtYɊi[ - for (int i = 0; i < pt.Length; i++) - if (pt[i].X >= Math.Min(p[0].X - p[0].range, p[^1].X - p[^1].range) && pt[i].X <= Math.Max(p[0].X + p[0].range, p[^1].X + p[^1].range)) + for (int i = 0; i < _pt.Count; i++) + if (_pt[i].X >= Math.Min(prms[0].X - prms[0].range, prms[^1].X - prms[^1].range) && _pt[i].X <= Math.Max(prms[0].X + prms[0].range, prms[^1].X + prms[^1].range)) { - PtX.Add(pt[i].X); - PtY.Add(pt[i].Y / 1000); - sum += pt[i].Y / 1000; - if (temp < pt[i].Y / 1000) - temp = pt[i].Y / 1000; + pt.Add((_pt[i].X, _pt[i].Y / 1000)); + //PtY.Add(pt[i].Y / 1000); + sum += _pt[i].Y / 1000; + if (temp < _pt[i].Y / 1000) + temp = _pt[i].Y / 1000; } //p[i].SerchPeakTop - for (int i = 0; i < p.Length; i++) - if (p[i].SerchPeakTop) + for (int i = 0; i < prms.Length; i++) + if (prms[i].SearchPeakTop) { - double max = double.NegativeInfinity; + var max = double.NegativeInfinity; double tempX = 0; - for (int j = 0; j < PtX.Count; j++) - if (PtX[j] >= p[i].X - p[i].range && PtX[j] <= p[0].X + p[0].range) - if (max < PtY[j]) + for (int j = 0; j < pt.Count; j++) + if (pt[j].X >= prms[i].X - prms[i].range && pt[j].X <= prms[0].X + prms[0].range) + if (max < pt[j].Y) { - max = PtY[j]; - tempX = PtX[j]; + max = pt[j].Y; + tempX = pt[j].X; } - p[i].X = tempX; + prms[i].X = tempX; } //łxT - for (int i = 0; i < pt.Length; i++) - if (pt[i].X >= Math.Min(p[0].X - p[0].range, p[^1].X - p[^1].range) && pt[i].X <= Math.Max(p[0].X + p[0].range, p[^1].X + p[^1].range)) + for (int i = 0; i < _pt.Count; i++) + if (_pt[i].X >= Math.Min(prms[0].X - prms[0].range, prms[^1].X - prms[^1].range) && _pt[i].X <= Math.Max(prms[0].X + prms[0].range, prms[^1].X + prms[^1].range)) { - if (tempMin > pt[i].Y / 1000) - tempMin = pt[i].Y / 1000; + if (tempMin > _pt[i].Y / 1000) + tempMin = _pt[i].Y / 1000; } - if (PtY.Count < 3 || /*temp <= 0 ||*/ (PtY[^1] == 0 && PtY[^2] == 0 && PtY[^3] == 0)) + if (pt.Count < 3 || (pt[^1].Y == 0 && pt[^2].Y == 0 && pt[^3].Y == 0)) { - for (int i = 0; i < p.Length; i++) - { - p[i].X = double.NaN; - p[i].Int = double.NaN; - } - return double.PositiveInfinity; + for (int i = 0; i < prms.Length; i++) + prms[i].X = prms[i].Int = double.NaN; + return Failed(); } - - double[] x = PtX.ToArray(); - double[] y = PtY.ToArray(); - int length = x.Length; - //܂łŃvt@C̗̈Ȃǂ + int length = pt.Count; //猈߂Ȃ΂Ȃp[^̐ݒ肷 int ParamNum = 0; - for (int i = 0; i < p.Length; i++) - ParamNum += p[i].GetParamNumber(); + for (int i = 0; i < prms.Length; i++) + ParamNum += prms[i].GetParamNumber(); if (ParamNum < 0) { - for (int i = 0; i < p.Length; i++) + for (int i = 0; i < prms.Length; i++) { - p[i].X = double.NaN; - p[i].Int = double.NaN; + prms[i].X = double.NaN; + prms[i].Int = double.NaN; } - return double.PositiveInfinity; + return Failed(); } var diff = new double[ParamNum + 2, length]; var Alpha = new DenseMatrix(ParamNum + 2, ParamNum + 2); - var Beta = new DenseMatrix(ParamNum + 2, 1); + var Beta = new DenseVector(ParamNum + 2); - var pCurrent = new PeakFunction[p.Length]; - var pNew = new PeakFunction[p.Length]; - for (int i = 0; i < p.Length; i++) + var pCurrent = new PeakFunction[prms.Length]; + var pNew = new PeakFunction[prms.Length]; + for (int i = 0; i < prms.Length; i++) { pCurrent[i] = new PeakFunction(); pNew[i] = new PeakFunction(); - pCurrent[i] = p[i].Copy(); + pCurrent[i] = prms[i].Copy(); } //܂ //Int̒lGcɌ߂ - var peakIntensity = new double[p.Length]; - for (var i = 0; i < p.Length; i++) + var peakIntensity = new double[prms.Length]; + for (var i = 0; i < prms.Length; i++) { var d = double.PositiveInfinity; - for (int j = 0; j < PtX.Count; j++) - if (d > Math.Abs(x[j] - p[i].X)) + for (int j = 0; j < length; j++) + if (d > Math.Abs(pt[j].X - prms[i].X)) { - d = Math.Abs(x[j] - p[i].X); - peakIntensity[i] = y[j]; + d = Math.Abs(pt[j].X - prms[i].X); + peakIntensity[i] = pt[j].Y; } peakIntensity[i] -= tempMin; } //ΒlƂčĔz peakIntensity = Statistics.Normarize(peakIntensity); - double[] ResidualCurrent = new double[length]; - double[] ResidualNew = new double[length]; - double ResidualSquareCurrent; - double ResidualSquareNew = 0; - double residual; - double centerX = (x[0] + x[^1]) / 2; - double B1, B2, B1_New, B2_New; - B1 = B2 = 0; + double[] ResidualCurrent = GC.AllocateUninitializedArray(length); + double[] ResidualNew = GC.AllocateUninitializedArray(length); + double[] IntCurrent = GC.AllocateUninitializedArray(length); + double[] IntNew = GC.AllocateUninitializedArray(length); + double ResidualSquareCurrent, ResidualSquareNew = 0, residual; + double centerX = (pt[0].X + pt[^1].X) / 2; + double B1 = 0, B2 = 0, B1_New, B2_New; double bestResidual = double.PositiveInfinity; - int bestInitial = 0; - int startInitial = 0; - int endInitial = 1;// 2; - int counter = 0; + int bestInitial = 0, startInitial = 0, endInitial = 11;// 2; + int counter; for (int Initial = startInitial; Initial < endInitial; Initial++) { - double[] c = new double[3]; - switch (Initial) + double[] c = Initial switch { - case 00: c = new double[] { 1, 1, 1 }; break; - case 01: c = new double[] { 1, 1, 2 }; break; - case 02: c = new double[] { 1, 1, 0.5 }; break; - case 03: c = new double[] { 0.5, 1, 1 }; break; - case 04: c = new double[] { 0.5, 1, 2 }; break; - case 05: c = new double[] { 0.5, 1, 0.5 }; break; - case 06: c = new double[] { 2, 1, 1 }; break; - case 07: c = new double[] { 2, 1, 0.5 }; break; - case 08: c = new double[] { 2, 1, 2 }; break; - case 09: c = new double[] { 1, 2, 1 }; break; - case 10: c = new double[] { 1, 0.5, 1 }; break; - case 11: c = new double[] { 0.5, 2, 2 }; break; - } + 00 => new double[] { 1, 1, 1 }, + 01 => new double[] { 1, 1, 2 }, + 02 => new double[] { 1, 1, 0.5 }, + 03 => new double[] { 0.5, 1, 1 }, + 04 => new double[] { 0.5, 1, 2 }, + 05 => new double[] { 0.5, 1, 0.5 }, + 06 => new double[] { 2, 1, 1 }, + 07 => new double[] { 2, 1, 0.5 }, + 08 => new double[] { 2, 1, 2 }, + 09 => new double[] { 1, 1.5, 1 }, + 10 => new double[] { 1, 0.5, 1 }, + _ => new double[] { 0.5, 1.5, 2 } + }; //珉l߂ //X͂łɑς //IntȊÔ̏lGcɌ߂ - for (int i = 0; i < p.Length; i++) + for (int i = 0; i < prms.Length; i++) { - pCurrent[i].X = p[i].X; - - if (p[i].Hk > 0) - pCurrent[i].Hk = p[i].Hk * c[0]; - else - pCurrent[i].Hk = p[i].range * 0.5 * c[0]; - - pCurrent[i].eta = 0.5 * c[1]; - pCurrent[i].etaH = 0.5 * c[1]; - pCurrent[i].etaL = 0.5 * c[1]; + pCurrent[i].X = prms[i].X; + pCurrent[i].Hk = prms[i].Hk > 0 ? prms[i].Hk * c[0] : prms[i].range * 0.5 * c[0]; + pCurrent[i].eta = pCurrent[i].etaH = pCurrent[i].etaL = 0.5 * c[1]; pCurrent[i].m = 2 * c[1]; - pCurrent[i].Rl = 2 * c[1]; - pCurrent[i].Rh = 2 * c[1]; + pCurrent[i].Rl = pCurrent[i].Rh = 2 * c[1]; pCurrent[i].A = 0; } B1 = tempMin; B2 = 0; //Int - for (int i = 0; i < p.Length; i++) + for (int i = 0; i < prms.Length; i++) { - pCurrent[i].Int = 1; - pCurrent[i].Int = (sum - tempMin * x.Length) * (x[1] - x[0]) * peakIntensity[i] / pCurrent[i].GetIntegral() * c[2]; + pCurrent[i].Int = 1; //ĂȂƁApCurrent[i].GetIntegral()[ԂĂ܂ + pCurrent[i].Int = (sum - tempMin * length) * (pt[1].X - pt[0].X) * peakIntensity[i] / pCurrent[i].GetIntegral() * c[2]; } //܂ŏl //݂̎cvZ - ResidualSquareCurrent = 0; - double[] IntCurrent = new double[x.Length]; - double[] IntNew = new double[x.Length]; for (int i = 0; i < length; i++) - IntCurrent[i] = B1 + B2 * (x[i] - centerX); - for (int j = 0; j < p.Length; j++) + IntCurrent[i] = B1 + B2 * (pt[i].X - centerX); + for (int j = 0; j < prms.Length; j++) { pCurrent[j].RenewParameter(); for (int i = 0; i < length; i++) - IntCurrent[i] += pCurrent[j].GetValue(x[i], false); + IntCurrent[i] += pCurrent[j].GetValue(pt[i].X, false); } + ResidualSquareCurrent = 0; for (int i = 0; i < length; i++) { - ResidualCurrent[i] = y[i] - IntCurrent[i]; + ResidualCurrent[i] = pt[i].Y - IntCurrent[i]; ResidualSquareCurrent += ResidualCurrent[i] * ResidualCurrent[i]; } - - double ramda = 100; + double ramda = 10; counter = 0; do { counter++; //Δ - int n = 0; - int m = 0; - for (int j = 0; j < p.Length; j++) + int n = 0, m = 0; + for (int j = 0; j < prms.Length; j++) { n = m; pCurrent[j].RenewParameter(); for (int i = 0; i < length; i++) { m = n; - double[] d = pCurrent[j].GetDifferentialValue(x[i], false); + var d = pCurrent[j].GetDifferentialValue(pt[i].X, false); for (int k = 0; k < d.Length; k++) { diff[m, i] = d[k]; @@ -633,7 +620,7 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do for (int i = 0; i < length; i++) {//obNOEhϐ̕Δ diff[ParamNum, i] = 1; - diff[ParamNum + 1, i] = x[i] - centerX; + diff[ParamNum + 1, i] = pt[i].X - centerX; } //Δ ܂ @@ -649,9 +636,9 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do if (i == j) Alpha[i, j] *= (1 + ramda); } - Beta[i, 0] = 0; + Beta[i] = 0; for (int k = 0; k < length; k++) - Beta[i, 0] += ResidualCurrent[k] * diff[i, k]; + Beta[i] += ResidualCurrent[k] * diff[i, k]; } //sAlphaABetaA܂ @@ -659,54 +646,49 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do if (alphaInv == null) { - for (int i = 0; i < p.Length; i++) - { - p[i].X = double.NaN; - p[i].Int = double.NaN; - } - return double.PositiveInfinity; + for (int i = 0; i < prms.Length; i++) + prms[i].X = prms[i].Int = double.NaN; + return Failed(); } - var delta = alphaInv * Beta; + var delta = alphaInv.Multiply(Beta); //Vp[^ZbgēKXC n = 0; bool flag = true; - for (int j = 0; j < p.Length; j++) + for (int j = 0; j < prms.Length; j++) { pNew[j] = pCurrent[j].Copy(); - if (p[j].Option == PeakFunctionForm.PseudoVoigt)//PseudoVoigt: Int, Eta, Hk, X ; + if (prms[j].Option == PeakFunctionForm.PseudoVoigt)//PseudoVoigt: Int, Eta, Hk, X ; { - pNew[j].Int = pCurrent[j].Int + delta[n++, 0]; - pNew[j].eta = pCurrent[j].eta + delta[n++, 0]; - pNew[j].Hk = pCurrent[j].Hk + delta[n++, 0]; - pNew[j].X = pCurrent[j].X + delta[n++, 0]; + pNew[j].Int = pCurrent[j].Int + delta[n++]; + pNew[j].eta = pCurrent[j].eta + delta[n++]; + pNew[j].Hk = pCurrent[j].Hk + delta[n++]; + pNew[j].X = pCurrent[j].X + delta[n++]; - //if (pNew[j].eta < 0 || pNew[j].eta > 1) - // flag = false; if (pNew[j].eta < 0) pNew[j].eta = 0; - if (pNew[j].eta > 1) + else if (pNew[j].eta > 1) pNew[j].eta = 1; } - else if (p[j].Option == PeakFunctionForm.Peason)//PearsonVII: Int, Hk, m, X + else if (prms[j].Option == PeakFunctionForm.Peason)//PearsonVII: Int, Hk, m, X { - pNew[j].Int = pCurrent[j].Int + delta[n++, 0]; - pNew[j].Hk = pCurrent[j].Hk + delta[n++, 0]; - pNew[j].m = pCurrent[j].m + delta[n++, 0]; - pNew[j].X = pCurrent[j].X + delta[n++, 0]; + pNew[j].Int = pCurrent[j].Int + delta[n++]; + pNew[j].Hk = pCurrent[j].Hk + delta[n++]; + pNew[j].m = pCurrent[j].m + delta[n++]; + pNew[j].X = pCurrent[j].X + delta[n++]; if (pNew[j].m <= 0.5 || pNew[j].m >= 10) flag = false; } - else if (p[j].Option == PeakFunctionForm.SplitPseudoVoigt)//SplitPseudoVoigt: Int, Hk, A, etaL , etaH, X + else if (prms[j].Option == PeakFunctionForm.SplitPseudoVoigt)//SplitPseudoVoigt: Int, Hk, A, etaL , etaH, X { - pNew[j].Int = pCurrent[j].Int + delta[n++, 0]; - pNew[j].Hk = pCurrent[j].Hk + delta[n++, 0]; - pNew[j].A = pCurrent[j].A + delta[n++, 0]; - pNew[j].etaL = pCurrent[j].etaL + delta[n++, 0]; - pNew[j].etaH = pCurrent[j].etaH + delta[n++, 0]; - pNew[j].X = pCurrent[j].X + delta[n++, 0]; + pNew[j].Int = pCurrent[j].Int + delta[n++]; + pNew[j].Hk = pCurrent[j].Hk + delta[n++]; + pNew[j].A = pCurrent[j].A + delta[n++]; + pNew[j].etaL = pCurrent[j].etaL + delta[n++]; + pNew[j].etaH = pCurrent[j].etaH + delta[n++]; + pNew[j].X = pCurrent[j].X + delta[n++]; if (pNew[j].etaL < 0 || pNew[j].etaL > 1) flag = false; if (pNew[j].etaH < 0 || pNew[j].etaH > 1) @@ -714,14 +696,14 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do if (pNew[j].A < -2 || pNew[j].A > 2) flag = false; } - else if (p[j].Option == PeakFunctionForm.SplitPearson)//SplitPearsonVII: Int, Hk, A, Rl , Rh, X + else if (prms[j].Option == PeakFunctionForm.SplitPearson)//SplitPearsonVII: Int, Hk, A, Rl , Rh, X { - pNew[j].Int = pCurrent[j].Int + delta[n++, 0]; - pNew[j].Hk = pCurrent[j].Hk + delta[n++, 0]; - pNew[j].A = pCurrent[j].A + delta[n++, 0]; - pNew[j].Rl = pCurrent[j].Rl + delta[n++, 0]; - pNew[j].Rh = pCurrent[j].Rh + delta[n++, 0]; - pNew[j].X = pCurrent[j].X + delta[n++, 0]; + pNew[j].Int = pCurrent[j].Int + delta[n++]; + pNew[j].Hk = pCurrent[j].Hk + delta[n++]; + pNew[j].A = pCurrent[j].A + delta[n++]; + pNew[j].Rl = pCurrent[j].Rl + delta[n++]; + pNew[j].Rh = pCurrent[j].Rh + delta[n++]; + pNew[j].X = pCurrent[j].X + delta[n++]; if (pNew[j].Rl <= 0.5 || pNew[j].Rl >= 10) flag = false; if (pNew[j].Rh <= 0.5 || pNew[j].Rh >= 10) @@ -734,32 +716,30 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do flag = false; //pNew[j].Hk = pCurrent[j].Hk; //2{ȏ̃tBbeBȌꍇAXRange1/8ȏ㓮ǂ - if (p.Length > 1) - if (pNew[j].X - p[j].X > p[j].range / 8 || pNew[j].X - p[j].X < -p[j].range / 8) - { pNew[j].X = pCurrent[j].X; } - // flag = false; //pNew[j].X = p[j].X + p[j].range / 4; + if (prms.Length > 1) + if (pNew[j].X - prms[j].X > prms[j].range / 8 || pNew[j].X - prms[j].X < -prms[j].range / 8) + pNew[j].X = pCurrent[j].X; } - B1_New = B1 + delta[ParamNum, 0]; - B2_New = B2 + delta[ParamNum + 1, 0]; - //if (B1_New + B2_New * (x[0] - centerX) < 0 || B1_New + B2_New * (x[x.Length - 1] - centerX) < 0) - // flag = false; //B1_New = B1;//B2_New = B2; + B1_New = B1 + delta[ParamNum]; + B2_New = B2 + delta[ParamNum + 1]; //炵p[^ł̎cvZ if (flag) { - ResidualSquareNew = 0; for (int i = 0; i < length; i++) - IntNew[i] = B1_New + B2_New * (x[i] - centerX); - for (int j = 0; j < p.Length; j++) + IntNew[i] = B1_New + B2_New * (pt[i].X - centerX); + for (int j = 0; j < prms.Length; j++) { pNew[j].RenewParameter(); for (int i = 0; i < length; i++) - IntNew[i] += pNew[j].GetValue(x[i], false); + IntNew[i] += pNew[j].GetValue(pt[i].X, false); } + ResidualSquareNew = 0; for (int i = 0; i < length; i++) { - ResidualNew[i] = y[i] - IntNew[i]; + ResidualNew[i] = pt[i].Y - IntNew[i]; ResidualSquareNew += ResidualNew[i] * ResidualNew[i]; + } } //cvZ܂ @@ -767,10 +747,9 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do //V̒lr if (flag && ResidualSquareCurrent >= ResidualSquareNew) { - ramda *= 0.8; - for (int i = 0; i < length; i++) - ResidualCurrent[i] = ResidualNew[i]; - for (int j = 0; j < p.Length; j++) + ramda *= 0.5; + Array.Copy(ResidualNew, ResidualCurrent, length); + for (int j = 0; j < prms.Length; j++) pCurrent[j] = pNew[j].Copy(); B1 = B1_New; B2 = B2_New; @@ -779,20 +758,20 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do ResidualSquareCurrent = ResidualSquareNew; } else - ramda *= 2; - } while (ramda < 100000000000 && counter < 1000); + ramda *= 4; + } while (ramda < 1000000000 && counter < 500); for (int i = 0; i < length; i++) - IntNew[i] = B1_New + B2_New * (x[i] - centerX); - for (int j = 0; j < p.Length; j++) + IntNew[i] = B1_New + B2_New * (pt[i].X - centerX); + for (int j = 0; j < prms.Length; j++) { pNew[j].RenewParameter(); for (int i = 0; i < length; i++) - IntNew[i] += pNew[j].GetValue(x[i], false); + IntNew[i] += pNew[j].GetValue(pt[i].X, false); } residual = 0; for (int i = 0; i < length; i++) - residual += (IntNew[i] - y[i]) / IntNew[i] * (IntNew[i] - y[i]) / IntNew[i]; + residual += (IntNew[i] - pt[i].Y) / IntNew[i] * (IntNew[i] - pt[i].Y) / IntNew[i]; residual /= length; if (bestResidual > residual)//łʂ̂悩JEgi[ { @@ -806,12 +785,9 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do //50%𒴂邭炢Ђǂ if (Math.Sqrt(bestResidual) > 0.90) { - for (int i = 0; i < p.Length; i++) - { - p[i].X = double.NaN; - p[i].Int = double.NaN; - } - return double.PositiveInfinity; + for (int i = 0; i < prms.Length; i++) + prms[i].X = prms[i].Int = double.NaN; + return Failed(); } //Ԃ܂ȏlł蒼 startInitial = bestInitial - 1; @@ -832,33 +808,33 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do } counter = 0; //ŌɂꂼƂ܂lB - for (int i = 0; i < p.Length; i++) + for (int i = 0; i < prms.Length; i++) { //p[i] = pCurrent[i].Copy(); - p[i].Option = pCurrent[i].Option; - p[i].intensity = pCurrent[i].intensity; - p[i].eta = pCurrent[i].eta; - p[i].etaH = pCurrent[i].etaH; - p[i].etaL = pCurrent[i].etaL; - p[i].Rl = pCurrent[i].Rl; - p[i].Rh = pCurrent[i].Rh; - p[i].X = pCurrent[i].X; - p[i].Hk = pCurrent[i].Hk; - p[i].Int = pCurrent[i].Int; - p[i].A = pCurrent[i].A; - p[i].B1 = pCurrent[i].B1; - p[i].B2 = pCurrent[i].B2; - p[i].B3 = pCurrent[i].B3; - counter += p[i].GetParamNumber(); - p[i].Xerr = 1 / Math.Sqrt(Alpha[counter - 1, counter - 1]); - p[i].m = pCurrent[i].m; - p[i].range = pCurrent[i].range; - p[i].Residual = bestResidual; - p[i].Int *= 1000; - p[i].B1 = B1 + B2 * (pCurrent[i].X - centerX); - p[i].B2 = B2; - p[i].B1 *= 1000; - p[i].B2 *= 1000; + prms[i].Option = pCurrent[i].Option; + prms[i].intensity = pCurrent[i].intensity; + prms[i].eta = pCurrent[i].eta; + prms[i].etaH = pCurrent[i].etaH; + prms[i].etaL = pCurrent[i].etaL; + prms[i].Rl = pCurrent[i].Rl; + prms[i].Rh = pCurrent[i].Rh; + prms[i].X = pCurrent[i].X; + prms[i].Hk = pCurrent[i].Hk; + prms[i].Int = pCurrent[i].Int; + prms[i].A = pCurrent[i].A; + prms[i].B1 = pCurrent[i].B1; + prms[i].B2 = pCurrent[i].B2; + prms[i].B3 = pCurrent[i].B3; + counter += prms[i].GetParamNumber(); + prms[i].Xerr = 1 / Math.Sqrt(Alpha[counter - 1, counter - 1]); + prms[i].m = pCurrent[i].m; + prms[i].range = pCurrent[i].range; + prms[i].Residual = bestResidual; + prms[i].Int *= 1000; + prms[i].B1 = B1 + B2 * (pCurrent[i].X - centerX); + prms[i].B2 = B2; + prms[i].B1 *= 1000; + prms[i].B2 *= 1000; } //艺͎IPA炾Ă΂镔 @@ -867,25 +843,26 @@ public static double FitMultiPeaksThread(PointD[] pt, bool BackgroundFitting, do //S/N䂪f[^͏ double BackGround = 0; double Signal = 0; - p[0].RenewParameter(); + prms[0].RenewParameter(); for (int i = 0; i < length; i++) { - Signal += p[0].GetValue(x[i], false); - BackGround += p[0].B1 + p[0].B2 * (p[0].X - x[i]); + Signal += prms[0].GetValue(pt[i].X, false); + BackGround += prms[0].B1 + prms[0].B2 * (prms[0].X - pt[i].X); } if (double.IsNaN(Signal / (BackGround + Signal)) || double.IsInfinity(Signal / (BackGround + Signal)) || (Signal / (BackGround + Signal)) < RemoveBadSN) - p[0].X = double.NaN; + prms[0].X = double.NaN; //SʒuOĉ߂Ăi - if (p[0].X < x[0] || x[^1] < p[0].X) - { - p[0].X = double.NaN; - } + if (prms[0].X < pt[0].X || pt[^1].X < prms[0].X) + prms[0].X = double.NaN; } /*if (counter < 1000) return true; else return false;*/ + foreach (var p in prms)//܂ŗꂽASSuccesstrueɂB + p.Success = true; + return bestResidual; } diff --git a/Crystallography/PointD.cs b/Crystallography/PointD.cs index 1d1d0c2..4819ab6 100644 --- a/Crystallography/PointD.cs +++ b/Crystallography/PointD.cs @@ -197,14 +197,13 @@ public int CompareTo(object obj) public override int GetHashCode() => HashCode.Combine(X, Y); - #region Zq̃I[o[[h public static PointD operator +(in PointD p1, in PointD p2) => new(p1.X + p2.X, p1.Y + p2.Y); public static PointD operator -(in PointD p1, in PointD p2) => new(p1.X - p2.X, p1.Y - p2.Y); - public static PointD operator -(in PointD p) => new PointD(-p.X, -p.Y); + public static PointD operator -(in PointD p) => new(-p.X, -p.Y); public static PointD operator *(in double d, in PointD p) => new(d * p.X, d * p.Y);